document-operations 0.0.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joseph Mearman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # document-operations
2
+
3
+ [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/documents.js/tree/main/packages/document-operations) [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/document-operations) [![npm version](https://img.shields.io/npm/v/document-operations)](https://www.npmjs.com/package/document-operations) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/documents.js/ci.yml?branch=main)](https://github.com/ExaDev/documents.js/actions)
4
+
5
+ > The canonical set of document-conversion, editing, inspection, and `.odb` operations [`documents.js`](https://github.com/ExaDev/documents.js) exposes — one Zod input/output schema and one transport-agnostic `run()` function per operation, so [`document-mcp`](../document-mcp/README.md), a REST API server, and [`document-cli`](../document-cli/README.md) can each expose the identical operation without redefining its shape or its behaviour a second time.
6
+
7
+ Before this package existed, `document-mcp` defined each MCP tool's Zod schema and dispatch logic directly in its own `src/tools/*.ts`, and `document-cli` described the same underlying operations again as hand-written `commander` flags — two independent definitions of "what does `convert_document` take" that could silently drift, with no shared source of truth a third surface (a REST server) could build against either. `document-operations` is that source of truth: every operation from `document-mcp`'s own tool set moved here unchanged in behaviour, decoupled from any one transport's own result-shaping.
8
+
9
+ ```mermaid
10
+ graph TD
11
+ schema("document-schema.js")
12
+ documents("documents.js")
13
+ outline("document-outline.js")
14
+ compute("document-compute.js")
15
+ operations("document-operations")
16
+ mcp("document-mcp")
17
+
18
+ schema --> documents
19
+ schema --> outline
20
+ schema --> compute
21
+ documents --> operations
22
+ outline --> operations
23
+ compute --> operations
24
+ operations --> mcp
25
+
26
+ click schema "https://github.com/ExaDev/documents.js/tree/main/packages/document-schema.js" "document-schema.js"
27
+ click documents "https://github.com/ExaDev/documents.js" "documents.js"
28
+ click outline "https://github.com/ExaDev/documents.js/tree/main/packages/document-outline.js" "document-outline.js"
29
+ click compute "https://github.com/ExaDev/documents.js/tree/main/packages/document-compute.js" "document-compute.js"
30
+ click operations "https://github.com/ExaDev/documents.js/tree/main/packages/document-operations" "document-operations"
31
+ click mcp "https://github.com/ExaDev/documents.js/tree/main/packages/document-mcp" "document-mcp"
32
+
33
+ style operations fill:#f9a825,stroke:#333,stroke-width:3px
34
+ ```
35
+
36
+ ## The `DocumentOperation` contract
37
+
38
+ Every operation this package exports has the same shape (`src/operation.ts`):
39
+
40
+ ```ts
41
+ interface DocumentOperation<In, Out> {
42
+ readonly name: string;
43
+ readonly title: string;
44
+ readonly description: string;
45
+ readonly inputSchema: z.ZodType<In>;
46
+ readonly outputSchema?: z.ZodType<Out>;
47
+ run(input: In, context?: { readonly signal?: AbortSignal }): Promise<Out>;
48
+ }
49
+ ```
50
+
51
+ `inputSchema`/`outputSchema` are the single source of truth for validation and description text; `run()` is the transport-agnostic implementation. A failure is always a thrown Error (a plain one, or one of `documents.js`'s own typed errors, e.g. `OdbReportNotSpecifiedError`, `OdmUnresolvedSectionError`) — `run()` never shapes a transport-specific result. Each transport decides for itself how to present a thrown error: `document-mcp` wraps it as an `isError` tool result (with an optional `mapError` hook for the two operations whose errors carry data worth surfacing structurally), a REST route would map it to a 4xx JSON body, and a CLI command would print it to stderr with a non-zero exit code.
52
+
53
+ `defineOperation()`/`defineOperationWithoutOutputSchema()` build one of these from a plain object, inferring `In`/`Out` from the Zod schemas so a call site never repeats `z.infer<typeof Schema>` itself. Use the `WithoutOutputSchema` variant for the handful of operations whose original MCP tool registration declared no `outputSchema` at all (`metadata_read`'s return shape varies per format; the `.odb`-reading operations return `documents.js`'s own reader types directly) — adding a guessed schema there would risk introducing output validation that did not previously exist and could reject a genuine value the guess did not anticipate.
54
+
55
+ `DOCUMENT_OPERATIONS` (`src/registry.ts`) is every operation in one array — "the same registry as the MCP" a caller that wants to enumerate every operation, rather than import one by name, reaches for: an MCP server registers each entry as a tool, a REST server would add one route per entry, and a CLI would validate its own parsed flags against an entry's `inputSchema` before dispatching to `run()`.
56
+
57
+ ## Operations
58
+
59
+ Every operation below was ported unchanged in behaviour from `document-mcp`'s own `src/tools/*.ts` — see that package's README for the full description of what each one does; this table is the index.
60
+
61
+ | Export | Name |
62
+ | ----------------------------------- | ---------------------------- |
63
+ | `convertDocumentOperation` | `convert_document` |
64
+ | `listDocumentConversionsOperation` | `list_document_conversions` |
65
+ | `metadataReadOperation` | `metadata_read` |
66
+ | `metadataWriteOperation` | `metadata_write` |
67
+ | `documentCreateOperation` | `document_create` |
68
+ | `documentAppendParagraphsOperation` | `document_append_paragraphs` |
69
+ | `fontsOperation` | `fonts` |
70
+ | `describeFontFileOperation` | `describe_font_file` |
71
+ | `docxExtrasOperation` | `docx_extras` |
72
+ | `fromPackageOperation` | `from_package` |
73
+ | `outlineDocumentOperation` | `outline_document` |
74
+ | `pdfInspectOperation` | `pdf_inspect` |
75
+ | `computeFormulaOperation` | `compute_formula` |
76
+ | `odmToPdfOperation` | `odm_to_pdf` |
77
+ | `odbTablesOperation` | `odb_tables` |
78
+ | `odbFormsOperation` | `odb_forms` |
79
+ | `odbReportsOperation` | `odb_reports` |
80
+ | `odbQueryOperation` | `odb_query` |
81
+ | `odbToCsvOperation` | `odb_to_csv` |
82
+ | `odbToXlsxOperation` | `odb_to_xlsx` |
83
+ | `odbRenderReportOperation` | `odb_render_report` |
84
+
85
+ ## Getting started
86
+
87
+ ```sh
88
+ pnpm install
89
+ pnpm build # turbo -> tsdown -> dist/ (ESM + CJS + .d.ts)
90
+ pnpm typecheck # turbo -> tsc --noEmit, plus attw --pack
91
+ pnpm lint # turbo -> eslint . --fix --cache --max-warnings 0
92
+ pnpm test # turbo -> vitest run
93
+ pnpm test:workers # turbo -> vitest under the real Cloudflare Workers runtime (workerd) via @cloudflare/vitest-pool-workers, exercising every operation's bytesBase64 input path
94
+ ```
95
+
96
+ ## Gotchas
97
+
98
+ - **Not held to Worker isomorphism, unlike the foundation packages it depends on.** `resolveDocumentInput`'s `path` branch (`src/io/document-input.ts`) reads a file from disk via `node:fs/promises`, and `odm_to_pdf`'s chapter-directory resolution (`src/operations/odm.ts`) uses `node:fs`'s synchronous API — the same reason `document-mcp` and `document-cli` are excluded from the isomorphic-package list in the [monorepo root README](../../README.md#conventions). `pnpm test:workers` still proves every operation's `bytesBase64` input path runs correctly under workerd (no `path`/`chaptersDir` involved), matching `document-mcp`'s own workers-test scope.
99
+ - **`document-mcp`'s own tests were left untouched, not moved here.** They keep testing the full MCP registration (`createServer()` + a real client/server JSON-RPC round trip), which still exercises this package's own `run()` functions underneath — moving them would have meant re-verifying ~3000 lines of existing, passing test behaviour for no functional gain. This package's own tests are a separate, more direct unit-level check on each `run()` function in isolation.
100
+ - **`odb_render_report`'s `OdbReportNotSpecifiedError` and `odm_to_pdf`'s `OdmUnresolvedSectionError` are not caught here.** Both are thrown by the underlying `documents.js` functions and left to propagate — the MCP-specific enrichment (a remediation hint, `structuredContent.availableReports`/`.hrefs`) lives in `document-mcp`'s own `mapError` hooks (`src/tools/odb-render-report.ts`, `src/tools/odm.ts`), since that shaping is presentation, not operation logic.
101
+
102
+ ## Contributing
103
+
104
+ Release, CI, and commit-message conventions are all workspace-wide, not package-local — see the [monorepo root README](../../README.md#releases) for the release mechanism and [CONTRIBUTING.md](../../CONTRIBUTING.md) for the shared git hooks and history conventions. Work inside `packages/document-operations/`.
105
+
106
+ ## License
107
+
108
+ MIT