# ๐Ÿ“Š `@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](https://img.shields.io/npm/v/@saptools/sharepoint-excel.svg?style=flat&color=CB3837&logo=npm)](https://www.npmjs.com/package/@saptools/sharepoint-excel) [![node](https://img.shields.io/node/v/@saptools/sharepoint-excel.svg?style=flat&color=339933&logo=node.js&logoColor=white)](https://nodejs.org) [![install size](https://packagephobia.com/badge?p=@saptools/sharepoint-excel)](https://packagephobia.com/result?p=@saptools/sharepoint-excel) [![types](https://img.shields.io/npm/types/@saptools/sharepoint-excel.svg?style=flat&color=3178C6&logo=typescript&logoColor=white)](https://www.typescriptlang.org) [Install](#-install) โ€ข [Quick Start](#-quick-start) โ€ข [CLI](#-cli) โ€ข [Security](#-credential-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 ```bash npm install -g @saptools/sharepoint-excel ``` Requires **Node.js >= 20**. The CLI binary is `sharepoint-excel`. --- ## ๐Ÿš€ Quick Start ```bash # 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 "" \ --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: ```bash 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="" 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 ` | `SHAREPOINT_EXCEL_PROFILE` | Stored profile name; default is `default` | | `--tenant ` | `SHAREPOINT_EXCEL_TENANT_ID` | Azure AD tenant id | | `--client-id ` | `SHAREPOINT_EXCEL_CLIENT_ID` | App registration client id | | `--client-secret ` | `SHAREPOINT_EXCEL_CLIENT_SECRET` | App registration client secret | | `--site ` | `SHAREPOINT_EXCEL_SITE` | SharePoint site, e.g. `contoso.sharepoint.com/sites/demo` | | `--drive ` | `SHAREPOINT_EXCEL_DRIVE` | Document library name or id | | `--json` | - | Machine-readable output | ### ๐Ÿ” `config set` Store a reusable local profile. ```bash 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: ```bash 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` ```bash sharepoint-excel config get --profile finance sharepoint-excel config get --profile finance --json ``` Secrets are never printed. ### ๐Ÿงน `config remove` ```bash sharepoint-excel config remove --profile finance ``` Removes both profile metadata and the stored secret. ### โœ… `test` Authenticate, resolve the site, and list document libraries. ```bash sharepoint-excel test sharepoint-excel test --json ``` ### ๐Ÿ—‚๏ธ `drives` ```bash 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` ```bash 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` ```bash sharepoint-excel read --path "Reports/orders.xlsx" sharepoint-excel read --path "Reports/orders.xlsx" --sheet "Orders" --range "A1:C10" --json ``` ### โž• `append` ```bash 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` ```bash 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` ```bash 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: ```bash 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 - ๐Ÿ”Ž [`@saptools/sharepoint-check`](https://www.npmjs.com/package/@saptools/sharepoint-check) โ€” pre-flight Graph and SharePoint diagnostics - ๐Ÿ—‚๏ธ [saptools monorepo](https://github.com/dongitran/saptools) โ€” the full toolbox --- ## ๐Ÿ‘จโ€๐Ÿ’ป Author **dongtran** โœจ ## ๐Ÿ“„ License MIT --- Made with โค๏ธ to make your work life easier!