@saptools/sharepoint-excel

v0.1.3

Published

Create, read, and update SharePoint-hosted Excel workbooks through Microsoft Graph with safe local credential profiles

Readme

๐Ÿ“Š @saptools/sharepoint-excel

Safe SharePoint Excel automation for Microsoft Graph app-only integrations.

Create .xlsx files, read workbook content, append records, update cells, and add sheets from a focused CLI or typed TypeScript API without overwriting somebody else's SharePoint file by accident.

npm version node install size types

Install โ€ข Quick Start โ€ข CLI โ€ข Security


โœจ Features

  • ๐Ÿ” Safe local profiles: stores profile metadata under ~/.saptools/sharepoint-excel/ and keeps clientSecret in the OS credential vault by default
  • ๐Ÿงญ Graph app-only flow: uses Azure AD client credentials to resolve SharePoint sites and document libraries
  • ๐Ÿงฑ Local workbook engine: edits .xlsx bytes with exceljs, avoiding delegated-only Microsoft Graph workbook endpoints
  • ๐Ÿ›ก๏ธ No accidental overwrite on create: refuses to create when the target path already exists
  • ๐Ÿ” ETag-protected updates: append/update/add-sheet operations upload with If-Match so concurrent SharePoint edits fail fast instead of being silently overwritten
  • ๐Ÿ“– Workbook reads: inspect all sheets, a single sheet, or an A1 range
  • โž• Content mutation: append JSON objects/rows, update a single cell, and add new sheets with headers
  • ๐Ÿงช Fake-backed e2e tests: package tests do not call real Microsoft Graph or SharePoint
  • ๐Ÿงฐ CLI and typed API: every CLI action is backed by exported TypeScript functions

๐Ÿ“ฆ Install

npm install -g @saptools/sharepoint-excel

Requires Node.js >= 20. The CLI binary is sharepoint-excel.


๐Ÿš€ Quick Start

# 1. Store an app-only SharePoint profile
sharepoint-excel config set \
  --tenant "11111111-1111-1111-1111-111111111111" \
  --client-id "22222222-2222-2222-2222-222222222222" \
  --client-secret "<your-client-secret>" \
  --site "contoso.sharepoint.com/sites/demo" \
  --drive "Documents"

# 2. Prove auth and target resolution
sharepoint-excel test

# 3. Create a workbook without overwriting an existing file
sharepoint-excel create \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --headers "Name,Amount,Status" \
  --rows '[{"Name":"Coffee","Amount":3,"Status":"open"}]'

# 4. Append one object by matching row 1 headers
sharepoint-excel append \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --record '{"Name":"Tea","Amount":8,"Status":"open"}'

# 5. Update one cell
sharepoint-excel update-cell \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --cell "C2" \
  --value '"closed"'

# 6. Read workbook JSON
sharepoint-excel read --path "Reports/orders.xlsx" --json

For CI, every command can also read credentials from environment variables:

export SHAREPOINT_EXCEL_TENANT_ID="11111111-1111-1111-1111-111111111111"
export SHAREPOINT_EXCEL_CLIENT_ID="22222222-2222-2222-2222-222222222222"
export SHAREPOINT_EXCEL_CLIENT_SECRET="<your-client-secret>"
export SHAREPOINT_EXCEL_SITE="contoso.sharepoint.com/sites/demo"
export SHAREPOINT_EXCEL_DRIVE="Documents"

The CLI also accepts the shorter SHAREPOINT_TENANT_ID, SHAREPOINT_CLIENT_ID, SHAREPOINT_CLIENT_SECRET, SHAREPOINT_SITE, and SHAREPOINT_DRIVE fallbacks for consistency with @saptools/sharepoint-check.


๐Ÿงฐ CLI

Common auth flags

| Flag | Env | Description | | --- | --- | --- | | --profile <name> | SHAREPOINT_EXCEL_PROFILE | Stored profile name; default is default | | --tenant <id> | SHAREPOINT_EXCEL_TENANT_ID | Azure AD tenant id | | --client-id <id> | SHAREPOINT_EXCEL_CLIENT_ID | App registration client id | | --client-secret <secret> | SHAREPOINT_EXCEL_CLIENT_SECRET | App registration client secret | | --site <ref> | SHAREPOINT_EXCEL_SITE | SharePoint site, e.g. contoso.sharepoint.com/sites/demo | | --drive <nameOrId> | SHAREPOINT_EXCEL_DRIVE | Document library name or id | | --json | - | Machine-readable output |

๐Ÿ” config set

Store a reusable local profile.

sharepoint-excel config set \
  --profile finance \
  --tenant "$SHAREPOINT_EXCEL_TENANT_ID" \
  --client-id "$SHAREPOINT_EXCEL_CLIENT_ID" \
  --client-secret "$SHAREPOINT_EXCEL_CLIENT_SECRET" \
  --site "contoso.sharepoint.com/sites/finance" \
  --drive "Documents"

By default, the secret goes to the OS credential vault:

  • macOS: Keychain
  • Windows: Credential Manager
  • Linux: Secret Service-compatible keyring

For headless CI containers where an OS keyring is unavailable, an explicit plaintext fallback exists:

SAPTOOLS_SHAREPOINT_EXCEL_ALLOW_PLAINTEXT=1 \
sharepoint-excel config set --store file --allow-plaintext-secret ...

Use that only in controlled CI environments. The file is written with 0600 permissions under ~/.saptools/sharepoint-excel/secrets.json.

๐Ÿ‘€ config get

sharepoint-excel config get --profile finance
sharepoint-excel config get --profile finance --json

Secrets are never printed.

๐Ÿงน config remove

sharepoint-excel config remove --profile finance

Removes both profile metadata and the stored secret.

โœ… test

Authenticate, resolve the site, and list document libraries.

sharepoint-excel test
sharepoint-excel test --json

๐Ÿ—‚๏ธ drives

sharepoint-excel drives
sharepoint-excel drives --json

Use this when you are unsure whether the document library is named Documents, Shared Documents, or something custom.

๐Ÿ†• create

sharepoint-excel create \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --headers "Name,Amount,Status" \
  --rows '[{"Name":"Coffee","Amount":3,"Status":"open"}]' \
  --table "OrdersTable"

create fails if Reports/orders.xlsx already exists.

๐Ÿ“– read

sharepoint-excel read --path "Reports/orders.xlsx"
sharepoint-excel read --path "Reports/orders.xlsx" --sheet "Orders" --range "A1:C10" --json

โž• append

sharepoint-excel append \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --record '{"Name":"Tea","Amount":8,"Status":"open"}'

Objects are mapped by the first row's headers by default. Use --no-match-header to append object values by their JSON key order instead.

๐ŸŽฏ update-cell

sharepoint-excel update-cell \
  --path "Reports/orders.xlsx" \
  --sheet "Orders" \
  --cell "B2" \
  --value "42"

--value accepts a JSON scalar (42, true, null, "text") or a raw string.

๐Ÿ“„ add-sheet

sharepoint-excel add-sheet \
  --path "Reports/orders.xlsx" \
  --sheet "Audit" \
  --headers "At,Action,Actor"

Fails if the sheet already exists.


๐Ÿ” Credential Security

@saptools/sharepoint-excel handles Microsoft Graph app secrets. Treat them like production credentials.

  • The CLI never prints clientSecret.
  • Default secret storage uses OS-provided credential storage via @napi-rs/keyring.
  • Local profile metadata lives under ~/.saptools/sharepoint-excel/profiles.json with 0600 permissions.
  • Plaintext secret files require explicit opt-in and should only be used in controlled automation.
  • Mutating workbook commands use SharePoint ETags so a stale local download cannot silently replace a newer SharePoint edit.

Required Graph application permissions depend on your tenant model. Typical setups use Sites.Selected with site-specific grant plus file read/write access, or a broader Files.ReadWrite.All/Sites.ReadWrite.All policy where your organization permits it.


๐Ÿ› ๏ธ Development

From the monorepo root:

pnpm install
pnpm --filter @saptools/sharepoint-excel lint
pnpm --filter @saptools/sharepoint-excel typecheck
pnpm --filter @saptools/sharepoint-excel build
pnpm --filter @saptools/sharepoint-excel test:unit
pnpm --filter @saptools/sharepoint-excel test:e2e:fake

The e2e suite uses a fake Microsoft Graph server and does not call real SharePoint.


๐ŸŒ Related


๐Ÿ‘จโ€๐Ÿ’ป Author

dongtran โœจ

๐Ÿ“„ License

MIT


Made with โค๏ธ to make your work life easier!