agent-spreadsheet-sdk 0.12.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/README.md +226 -0
- package/package.json +36 -0
- package/src/backend.js +388 -0
- package/src/capabilities.js +79 -0
- package/src/errors.js +103 -0
- package/src/index.js +21 -0
- package/src/mcp-backend.js +497 -0
- package/src/wasm-backend.js +393 -0
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# agent-spreadsheet-sdk
|
|
2
|
+
|
|
3
|
+
**`agent-spreadsheet-sdk` is the JavaScript integration layer for agent-spreadsheet — the tool interaction service for agent-based spreadsheet work.**
|
|
4
|
+
|
|
5
|
+
It lets one application target multiple spreadsheet backends behind a consistent API:
|
|
6
|
+
- **MCP backend** for remote/stateful workflows
|
|
7
|
+
- **WASM/session backend** for embedded or in-process workflows
|
|
8
|
+
|
|
9
|
+
The goal is not “another transport wrapper.”
|
|
10
|
+
The goal is **one app-facing spreadsheet interaction model** for agent systems.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i agent-spreadsheet-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Node: `>=18`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## What this SDK normalizes
|
|
25
|
+
|
|
26
|
+
- shared method names across backends
|
|
27
|
+
- tolerance for common input aliases (`camelCase` / `snake_case`)
|
|
28
|
+
- top-level output normalization
|
|
29
|
+
- capability checks for backend-specific flows
|
|
30
|
+
- typed errors for unsupported features and backend failures
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Backends
|
|
35
|
+
|
|
36
|
+
### `McpBackend`
|
|
37
|
+
Use when your app talks to a running `agent-spreadsheet-mcp` server or MCP client transport.
|
|
38
|
+
|
|
39
|
+
Best for:
|
|
40
|
+
- multi-turn agent workflows
|
|
41
|
+
- remote/stateful spreadsheet execution
|
|
42
|
+
- fork lifecycle and staged changes
|
|
43
|
+
|
|
44
|
+
### `WasmBackend`
|
|
45
|
+
Use when your app embeds a WASM/session runtime.
|
|
46
|
+
|
|
47
|
+
Best for:
|
|
48
|
+
- local/in-process execution
|
|
49
|
+
- browser or embedded app scenarios
|
|
50
|
+
- session-oriented workflows without MCP transport
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const { McpBackend, WasmBackend } = require("agent-spreadsheet-sdk")
|
|
58
|
+
|
|
59
|
+
const mcp = new McpBackend({ transport: myMcpTransport })
|
|
60
|
+
const wasm = new WasmBackend({ bindings: myWasmBindings })
|
|
61
|
+
|
|
62
|
+
async function sharedReadFlow(backend, ctx) {
|
|
63
|
+
const workbook = await backend.describeWorkbook(ctx)
|
|
64
|
+
const sheets = await backend.listSheets(ctx)
|
|
65
|
+
const overview = await backend.sheetOverview({ ...ctx, sheetName: sheets[0] })
|
|
66
|
+
const page = await backend.sheetPage({
|
|
67
|
+
...ctx,
|
|
68
|
+
sheetName: sheets[0],
|
|
69
|
+
startRow: 1,
|
|
70
|
+
pageSize: 50,
|
|
71
|
+
format: "compact"
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
return { workbook, sheets, overview, page }
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Typical context identity:
|
|
79
|
+
- MCP: `{ workbookId: "..." }`
|
|
80
|
+
- WASM/session: `{ sessionId: "..." }`
|
|
81
|
+
- higher-level helper code may use `{ contextId: "..." }`
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Shared methods
|
|
86
|
+
|
|
87
|
+
### Read / inspection
|
|
88
|
+
- `describeWorkbook(input)`
|
|
89
|
+
- `listSheets(input)`
|
|
90
|
+
- `sheetOverview(input)`
|
|
91
|
+
- `namedRanges(input)`
|
|
92
|
+
- `rangeValues(input)`
|
|
93
|
+
- `readTable(input)`
|
|
94
|
+
- `sheetPage(input)`
|
|
95
|
+
- `findValue(input)`
|
|
96
|
+
- `gridExport(input)`
|
|
97
|
+
|
|
98
|
+
### Write
|
|
99
|
+
- `transformBatch(input)`
|
|
100
|
+
|
|
101
|
+
### Verification helpers
|
|
102
|
+
- `verifyWorkbook(input)`
|
|
103
|
+
- `verifyTargets(input)`
|
|
104
|
+
- `verifyErrors(input)`
|
|
105
|
+
|
|
106
|
+
### Backend-specific lifecycle
|
|
107
|
+
- MCP-oriented: `createFork`, `listForks`, `saveFork`, `discardFork`, staged-change methods
|
|
108
|
+
- WASM/session-oriented: `createSession`, `exportWorkbook`, `disposeSession`
|
|
109
|
+
|
|
110
|
+
Always branch on capabilities before using backend-specific methods.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Capability model
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
const caps = backend.getCapabilities()
|
|
118
|
+
|
|
119
|
+
if (caps.supportsForkLifecycle) {
|
|
120
|
+
// MCP path
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (caps.supportsVerification) {
|
|
124
|
+
// verifyWorkbook / verifyTargets / verifyErrors
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (caps.supportsSessionLifecycle) {
|
|
128
|
+
// WASM/session path
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Unsupported backend-specific calls throw `CapabilityError` with code:
|
|
133
|
+
- `UNSUPPORTED_CAPABILITY`
|
|
134
|
+
|
|
135
|
+
This is a feature, not a footgun: **capabilities are the contract for mixed-backend safety**.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Error model
|
|
140
|
+
|
|
141
|
+
SDK exports:
|
|
142
|
+
- `SpreadsheetSdkError`
|
|
143
|
+
- `CapabilityError`
|
|
144
|
+
- `BackendOperationError`
|
|
145
|
+
|
|
146
|
+
Common normalized codes:
|
|
147
|
+
- `INVALID_ARGUMENT`
|
|
148
|
+
- `INVALID_RESPONSE`
|
|
149
|
+
- `UNSUPPORTED_CAPABILITY`
|
|
150
|
+
- backend-provided machine codes when available
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## MCP transport contract
|
|
155
|
+
|
|
156
|
+
`McpBackend` accepts either:
|
|
157
|
+
- a generic `invoke(operation, params)` transport
|
|
158
|
+
- or transport objects with per-operation methods
|
|
159
|
+
|
|
160
|
+
Example:
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
const backend = new McpBackend({
|
|
164
|
+
transport: {
|
|
165
|
+
async invoke(operation, params) {
|
|
166
|
+
return client.callTool(operation, params)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## WASM bindings contract
|
|
175
|
+
|
|
176
|
+
`WasmBackend` expects bindings shaped like:
|
|
177
|
+
- `createSession`
|
|
178
|
+
- `describeWorkbook`
|
|
179
|
+
- `namedRanges`
|
|
180
|
+
- `sheetOverview`
|
|
181
|
+
- `listSheets`
|
|
182
|
+
- `rangeValues`
|
|
183
|
+
- `findValue`
|
|
184
|
+
- `readTable`
|
|
185
|
+
- `sheetPage`
|
|
186
|
+
- `gridExport`
|
|
187
|
+
- `transformBatch`
|
|
188
|
+
- `exportWorkbook`
|
|
189
|
+
- `disposeSession`
|
|
190
|
+
|
|
191
|
+
These map to the in-repo `agent-spreadsheet-wasm` work.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## When to use this SDK
|
|
196
|
+
|
|
197
|
+
Use `agent-spreadsheet-sdk` when you are building:
|
|
198
|
+
- an app that may swap between MCP and embedded execution
|
|
199
|
+
- a higher-level agent workflow system that should not care about transport details
|
|
200
|
+
- a UI or service that needs one normalized spreadsheet interaction model
|
|
201
|
+
|
|
202
|
+
Use the CLI directly when you only need shell/file workflows.
|
|
203
|
+
Use MCP directly when your system already lives entirely inside an MCP runtime.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Release lanes
|
|
208
|
+
|
|
209
|
+
This package is published from `sdk-vX.Y.Z` tags.
|
|
210
|
+
|
|
211
|
+
Dist-tag policy:
|
|
212
|
+
- stable -> `latest`
|
|
213
|
+
- `-rc.N` -> `rc`
|
|
214
|
+
- `-beta.N` -> `beta`
|
|
215
|
+
- `-alpha.N` -> `alpha`
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Related packages
|
|
220
|
+
|
|
221
|
+
- `agent-spreadsheet` — npm CLI wrapper
|
|
222
|
+
- `agent-spreadsheet` — Rust semantic core
|
|
223
|
+
- `agent-spreadsheet-mcp` — MCP server
|
|
224
|
+
- `agent-spreadsheet-wasm` — in-repo WASM-facing crate
|
|
225
|
+
|
|
226
|
+
Repo: <https://github.com/PSU3D0/agent-spreadsheet>
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-spreadsheet-sdk",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Backend-agnostic JavaScript SDK for agent-spreadsheet surfaces (MCP and WASM)",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/PSU3D0/agent-spreadsheet.git",
|
|
9
|
+
"directory": "npm/agent-spreadsheet-sdk"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/PSU3D0/agent-spreadsheet",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/PSU3D0/agent-spreadsheet/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"spreadsheet",
|
|
17
|
+
"xlsx",
|
|
18
|
+
"sdk",
|
|
19
|
+
"mcp",
|
|
20
|
+
"wasm"
|
|
21
|
+
],
|
|
22
|
+
"main": "src/index.js",
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "node --test"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/backend.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
const { CapabilityError, SpreadsheetSdkError } = require("./errors")
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("./capabilities").BackendCapabilities} BackendCapabilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {object} SpreadsheetBackend
|
|
9
|
+
* @property {"mcp"|"wasm"} kind
|
|
10
|
+
* @property {() => Readonly<BackendCapabilities>} getCapabilities
|
|
11
|
+
* @property {(input: Record<string, unknown>) => Promise<string[]>} listSheets
|
|
12
|
+
* @property {(input: Record<string, unknown>) => Promise<{ sheetName: string, values: unknown[] }>} rangeValues
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {{ kind: string, getCapabilities: () => Record<string, boolean> }} backend
|
|
17
|
+
* @param {string} capability
|
|
18
|
+
* @param {string} method
|
|
19
|
+
*/
|
|
20
|
+
function requireCapability(backend, capability, method) {
|
|
21
|
+
const capabilities = backend.getCapabilities()
|
|
22
|
+
if (!capabilities[capability]) {
|
|
23
|
+
throw new CapabilityError({
|
|
24
|
+
backend: backend.kind,
|
|
25
|
+
capability,
|
|
26
|
+
method
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {unknown} value
|
|
33
|
+
* @param {string} name
|
|
34
|
+
*/
|
|
35
|
+
function requiredString(value, name) {
|
|
36
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
37
|
+
throw new SpreadsheetSdkError(`missing required field '${name}'`, {
|
|
38
|
+
code: "INVALID_ARGUMENT"
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {unknown} result
|
|
46
|
+
* @param {string} fallbackSheetName
|
|
47
|
+
*/
|
|
48
|
+
function normalizeSheetPageResult(result, fallbackSheetName) {
|
|
49
|
+
if (!result || typeof result !== "object") {
|
|
50
|
+
throw new SpreadsheetSdkError("invalid sheetPage response", {
|
|
51
|
+
code: "INVALID_RESPONSE"
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
workbookId: typeof result.workbookId === "string"
|
|
57
|
+
? result.workbookId
|
|
58
|
+
: typeof result.workbook_id === "string"
|
|
59
|
+
? result.workbook_id
|
|
60
|
+
: undefined,
|
|
61
|
+
sheetName: typeof result.sheetName === "string"
|
|
62
|
+
? result.sheetName
|
|
63
|
+
: typeof result.sheet_name === "string"
|
|
64
|
+
? result.sheet_name
|
|
65
|
+
: fallbackSheetName,
|
|
66
|
+
rows: Array.isArray(result.rows) ? result.rows : [],
|
|
67
|
+
nextStartRow: typeof result.nextStartRow === "number"
|
|
68
|
+
? result.nextStartRow
|
|
69
|
+
: typeof result.next_start_row === "number"
|
|
70
|
+
? result.next_start_row
|
|
71
|
+
: undefined,
|
|
72
|
+
headerRow: result.headerRow ?? result.header_row,
|
|
73
|
+
compact: result.compact,
|
|
74
|
+
valuesOnly: result.valuesOnly ?? result.values_only,
|
|
75
|
+
format: result.format
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {unknown} result
|
|
81
|
+
*/
|
|
82
|
+
function normalizeGridExportResult(result) {
|
|
83
|
+
if (!result || typeof result !== "object") {
|
|
84
|
+
throw new SpreadsheetSdkError("invalid gridExport response", {
|
|
85
|
+
code: "INVALID_RESPONSE"
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
sheet: result.sheet,
|
|
90
|
+
anchor: result.anchor,
|
|
91
|
+
columns: result.columns,
|
|
92
|
+
merges: result.merges,
|
|
93
|
+
rows: result.rows
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {unknown} result
|
|
99
|
+
*/
|
|
100
|
+
function normalizeTransformBatchResult(result) {
|
|
101
|
+
if (!result || typeof result !== "object") {
|
|
102
|
+
throw new SpreadsheetSdkError("invalid transformBatch response", {
|
|
103
|
+
code: "INVALID_RESPONSE"
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
opsApplied: result.opsApplied ?? result.ops_applied,
|
|
108
|
+
cellsTouched: result.cellsTouched ?? result.cells_touched,
|
|
109
|
+
cellsValueSet: result.cellsValueSet ?? result.cells_value_set,
|
|
110
|
+
cellsFormulaSet: result.cellsFormulaSet ?? result.cells_formula_set,
|
|
111
|
+
cellsFormulaCleared: result.cellsFormulaCleared ?? result.cells_formula_cleared,
|
|
112
|
+
cellsSkippedKeepFormulas: result.cellsSkippedKeepFormulas ?? result.cells_skipped_keep_formulas,
|
|
113
|
+
formulaParseDiagnostics: result.formulaParseDiagnostics ?? result.formula_parse_diagnostics
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {unknown} result
|
|
119
|
+
* @param {string | undefined} fallbackWorkbookId
|
|
120
|
+
*/
|
|
121
|
+
function normalizeDescribeWorkbookResult(result, fallbackWorkbookId) {
|
|
122
|
+
if (!result || typeof result !== "object") {
|
|
123
|
+
throw new SpreadsheetSdkError("invalid describeWorkbook response", {
|
|
124
|
+
code: "INVALID_RESPONSE"
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
workbookId: result.workbookId ?? result.workbook_id ?? fallbackWorkbookId,
|
|
130
|
+
shortId: result.shortId ?? result.short_id,
|
|
131
|
+
slug: result.slug,
|
|
132
|
+
path: result.path,
|
|
133
|
+
clientPath: result.clientPath ?? result.client_path,
|
|
134
|
+
bytes: result.bytes,
|
|
135
|
+
sheetCount: result.sheetCount ?? result.sheet_count,
|
|
136
|
+
definedNames: result.definedNames ?? result.defined_names,
|
|
137
|
+
tables: result.tables,
|
|
138
|
+
macrosPresent: result.macrosPresent ?? result.macros_present,
|
|
139
|
+
lastModified: result.lastModified ?? result.last_modified,
|
|
140
|
+
revisionId: result.revisionId ?? result.revision_id,
|
|
141
|
+
caps: result.caps
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @param {unknown} result
|
|
147
|
+
* @param {string | undefined} fallbackWorkbookId
|
|
148
|
+
*/
|
|
149
|
+
function normalizeNamedRangesResult(result, fallbackWorkbookId) {
|
|
150
|
+
if (!result || typeof result !== "object") {
|
|
151
|
+
throw new SpreadsheetSdkError("invalid namedRanges response", {
|
|
152
|
+
code: "INVALID_RESPONSE"
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
workbookId: result.workbookId ?? result.workbook_id ?? fallbackWorkbookId,
|
|
158
|
+
items: Array.isArray(result.items) ? result.items : []
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {unknown} result
|
|
164
|
+
* @param {string} fallbackSheetName
|
|
165
|
+
* @param {string | undefined} fallbackWorkbookId
|
|
166
|
+
*/
|
|
167
|
+
function normalizeSheetOverviewResult(result, fallbackSheetName, fallbackWorkbookId) {
|
|
168
|
+
if (!result || typeof result !== "object") {
|
|
169
|
+
throw new SpreadsheetSdkError("invalid sheetOverview response", {
|
|
170
|
+
code: "INVALID_RESPONSE"
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
workbookId: result.workbookId ?? result.workbook_id ?? fallbackWorkbookId,
|
|
176
|
+
sheetName: result.sheetName ?? result.sheet_name ?? fallbackSheetName,
|
|
177
|
+
narrative: result.narrative,
|
|
178
|
+
regions: Array.isArray(result.regions) ? result.regions : [],
|
|
179
|
+
detectedRegions: result.detectedRegions ?? result.detected_regions ?? [],
|
|
180
|
+
detectedRegionCount: result.detectedRegionCount ?? result.detected_region_count,
|
|
181
|
+
detectedRegionsTruncated: result.detectedRegionsTruncated ?? result.detected_regions_truncated,
|
|
182
|
+
keyRanges: result.keyRanges ?? result.key_ranges ?? [],
|
|
183
|
+
formulaRatio: result.formulaRatio ?? result.formula_ratio,
|
|
184
|
+
notableFeatures: result.notableFeatures ?? result.notable_features ?? [],
|
|
185
|
+
notes: Array.isArray(result.notes) ? result.notes : []
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @param {unknown} result
|
|
191
|
+
* @param {string | undefined} fallbackWorkbookId
|
|
192
|
+
*/
|
|
193
|
+
function normalizeFindValueResult(result, fallbackWorkbookId) {
|
|
194
|
+
if (!result || typeof result !== "object") {
|
|
195
|
+
throw new SpreadsheetSdkError("invalid findValue response", {
|
|
196
|
+
code: "INVALID_RESPONSE"
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
workbookId: result.workbookId ?? result.workbook_id ?? fallbackWorkbookId,
|
|
202
|
+
matches: Array.isArray(result.matches) ? result.matches : [],
|
|
203
|
+
nextOffset: result.nextOffset ?? result.next_offset
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @param {unknown} result
|
|
209
|
+
* @param {string | undefined} fallbackWorkbookId
|
|
210
|
+
* @param {string | undefined} fallbackSheetName
|
|
211
|
+
*/
|
|
212
|
+
function normalizeReadTableResult(result, fallbackWorkbookId, fallbackSheetName) {
|
|
213
|
+
if (!result || typeof result !== "object") {
|
|
214
|
+
throw new SpreadsheetSdkError("invalid readTable response", {
|
|
215
|
+
code: "INVALID_RESPONSE"
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
workbookId: result.workbookId ?? result.workbook_id ?? fallbackWorkbookId,
|
|
221
|
+
sheetName: result.sheetName ?? result.sheet_name ?? fallbackSheetName,
|
|
222
|
+
tableName: result.tableName ?? result.table_name,
|
|
223
|
+
warnings: Array.isArray(result.warnings) ? result.warnings : [],
|
|
224
|
+
headers: Array.isArray(result.headers) ? result.headers : [],
|
|
225
|
+
rows: Array.isArray(result.rows) ? result.rows : [],
|
|
226
|
+
values: result.values,
|
|
227
|
+
types: result.types,
|
|
228
|
+
csv: result.csv,
|
|
229
|
+
totalRows: result.totalRows ?? result.total_rows ?? 0,
|
|
230
|
+
nextOffset: result.nextOffset ?? result.next_offset
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @param {unknown} result
|
|
236
|
+
*/
|
|
237
|
+
function normalizeStructureBatchResult(result) {
|
|
238
|
+
if (!result || typeof result !== "object") {
|
|
239
|
+
throw new SpreadsheetSdkError("invalid structureBatch response", {
|
|
240
|
+
code: "INVALID_RESPONSE"
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
forkId: result.forkId ?? result.fork_id,
|
|
245
|
+
mode: result.mode,
|
|
246
|
+
changeId: result.changeId ?? result.change_id,
|
|
247
|
+
opsApplied: result.opsApplied ?? result.ops_applied,
|
|
248
|
+
summary: result.summary,
|
|
249
|
+
formulaParseDiagnostics: result.formulaParseDiagnostics ?? result.formula_parse_diagnostics,
|
|
250
|
+
impactReport: result.impactReport ?? result.impact_report,
|
|
251
|
+
formulaDeltaPreview: result.formulaDeltaPreview ?? result.formula_delta_preview
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* @param {unknown} result
|
|
257
|
+
*/
|
|
258
|
+
function normalizeReplaceInFormulasResult(result) {
|
|
259
|
+
if (!result || typeof result !== "object") {
|
|
260
|
+
throw new SpreadsheetSdkError("invalid replaceInFormulas response", {
|
|
261
|
+
code: "INVALID_RESPONSE"
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
forkId: result.forkId ?? result.fork_id,
|
|
266
|
+
mode: result.mode,
|
|
267
|
+
changeId: result.changeId ?? result.change_id,
|
|
268
|
+
formulasChecked: result.formulasChecked ?? result.formulas_checked ?? 0,
|
|
269
|
+
formulasChanged: result.formulasChanged ?? result.formulas_changed ?? 0,
|
|
270
|
+
recalcNeeded: result.recalcNeeded ?? result.recalc_needed ?? false,
|
|
271
|
+
samples: Array.isArray(result.samples) ? result.samples : [],
|
|
272
|
+
warnings: Array.isArray(result.warnings) ? result.warnings : [],
|
|
273
|
+
formulaParseDiagnostics: result.formulaParseDiagnostics ?? result.formula_parse_diagnostics
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @param {unknown} result
|
|
279
|
+
* @param {string | undefined} fallbackBaseline
|
|
280
|
+
* @param {string | undefined} fallbackCurrent
|
|
281
|
+
*/
|
|
282
|
+
function normalizeVerifyWorkbookResult(result, fallbackBaseline, fallbackCurrent) {
|
|
283
|
+
if (!result || typeof result !== "object") {
|
|
284
|
+
throw new SpreadsheetSdkError("invalid verifyWorkbook response", {
|
|
285
|
+
code: "INVALID_RESPONSE"
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const targetClassificationCounts = result.summary?.targetClassificationCounts
|
|
290
|
+
?? result.summary?.target_classification_counts
|
|
291
|
+
?? {}
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
baselineRef: result.baselineRef ?? result.baseline_ref ?? result.baseline ?? fallbackBaseline,
|
|
295
|
+
currentRef: result.currentRef ?? result.current_ref ?? result.current ?? fallbackCurrent,
|
|
296
|
+
targetDeltas: Array.isArray(result.targetDeltas)
|
|
297
|
+
? result.targetDeltas
|
|
298
|
+
: Array.isArray(result.target_deltas)
|
|
299
|
+
? result.target_deltas.map((item) => ({
|
|
300
|
+
address: item.address,
|
|
301
|
+
before: item.before,
|
|
302
|
+
after: item.after,
|
|
303
|
+
beforeFormula: item.beforeFormula ?? item.before_formula,
|
|
304
|
+
afterFormula: item.afterFormula ?? item.after_formula,
|
|
305
|
+
classification: item.classification,
|
|
306
|
+
changed: item.changed
|
|
307
|
+
}))
|
|
308
|
+
: [],
|
|
309
|
+
newErrors: Array.isArray(result.newErrors)
|
|
310
|
+
? result.newErrors
|
|
311
|
+
: Array.isArray(result.new_errors)
|
|
312
|
+
? result.new_errors.map((item) => ({
|
|
313
|
+
address: item.address,
|
|
314
|
+
beforeError: item.beforeError ?? item.before_error,
|
|
315
|
+
afterError: item.afterError ?? item.after_error,
|
|
316
|
+
beforeFormula: item.beforeFormula ?? item.before_formula,
|
|
317
|
+
afterFormula: item.afterFormula ?? item.after_formula
|
|
318
|
+
}))
|
|
319
|
+
: [],
|
|
320
|
+
resolvedErrors: Array.isArray(result.resolvedErrors)
|
|
321
|
+
? result.resolvedErrors
|
|
322
|
+
: Array.isArray(result.resolved_errors)
|
|
323
|
+
? result.resolved_errors.map((item) => ({
|
|
324
|
+
address: item.address,
|
|
325
|
+
beforeError: item.beforeError ?? item.before_error,
|
|
326
|
+
afterError: item.afterError ?? item.after_error,
|
|
327
|
+
beforeFormula: item.beforeFormula ?? item.before_formula,
|
|
328
|
+
afterFormula: item.afterFormula ?? item.after_formula
|
|
329
|
+
}))
|
|
330
|
+
: [],
|
|
331
|
+
preexistingErrors: Array.isArray(result.preexistingErrors)
|
|
332
|
+
? result.preexistingErrors
|
|
333
|
+
: Array.isArray(result.preexisting_errors)
|
|
334
|
+
? result.preexisting_errors.map((item) => ({
|
|
335
|
+
address: item.address,
|
|
336
|
+
beforeError: item.beforeError ?? item.before_error,
|
|
337
|
+
afterError: item.afterError ?? item.after_error,
|
|
338
|
+
beforeFormula: item.beforeFormula ?? item.before_formula,
|
|
339
|
+
afterFormula: item.afterFormula ?? item.after_formula
|
|
340
|
+
}))
|
|
341
|
+
: [],
|
|
342
|
+
namedRangeDeltas: Array.isArray(result.namedRangeDeltas)
|
|
343
|
+
? result.namedRangeDeltas
|
|
344
|
+
: Array.isArray(result.named_range_deltas)
|
|
345
|
+
? result.named_range_deltas.map((item) => ({
|
|
346
|
+
name: item.name,
|
|
347
|
+
scopeKind: item.scopeKind ?? item.scope_kind,
|
|
348
|
+
scopeSheetName: item.scopeSheetName ?? item.scope_sheet_name,
|
|
349
|
+
change: item.change,
|
|
350
|
+
beforeRefersTo: item.beforeRefersTo ?? item.before_refers_to,
|
|
351
|
+
afterRefersTo: item.afterRefersTo ?? item.after_refers_to,
|
|
352
|
+
beforeKind: item.beforeKind ?? item.before_kind,
|
|
353
|
+
afterKind: item.afterKind ?? item.after_kind
|
|
354
|
+
}))
|
|
355
|
+
: [],
|
|
356
|
+
summary: {
|
|
357
|
+
targetCount: result.summary?.targetCount ?? result.summary?.target_count ?? 0,
|
|
358
|
+
changedTargets: result.summary?.changedTargets ?? result.summary?.changed_targets ?? 0,
|
|
359
|
+
newErrorCount: result.summary?.newErrorCount ?? result.summary?.new_error_count ?? 0,
|
|
360
|
+
resolvedErrorCount: result.summary?.resolvedErrorCount ?? result.summary?.resolved_error_count ?? 0,
|
|
361
|
+
preexistingErrorCount: result.summary?.preexistingErrorCount ?? result.summary?.preexisting_error_count ?? 0,
|
|
362
|
+
namedRangeDeltaCount: result.summary?.namedRangeDeltaCount ?? result.summary?.named_range_delta_count ?? 0,
|
|
363
|
+
targetClassificationCounts: {
|
|
364
|
+
unchanged: targetClassificationCounts.unchanged ?? 0,
|
|
365
|
+
directEdit: targetClassificationCounts.directEdit ?? targetClassificationCounts.direct_edit ?? 0,
|
|
366
|
+
recalcResult: targetClassificationCounts.recalcResult ?? targetClassificationCounts.recalc_result ?? 0,
|
|
367
|
+
formulaShift: targetClassificationCounts.formulaShift ?? targetClassificationCounts.formula_shift ?? 0,
|
|
368
|
+
newError: targetClassificationCounts.newError ?? targetClassificationCounts.new_error ?? 0
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
module.exports = {
|
|
375
|
+
requireCapability,
|
|
376
|
+
requiredString,
|
|
377
|
+
normalizeSheetPageResult,
|
|
378
|
+
normalizeGridExportResult,
|
|
379
|
+
normalizeTransformBatchResult,
|
|
380
|
+
normalizeStructureBatchResult,
|
|
381
|
+
normalizeReplaceInFormulasResult,
|
|
382
|
+
normalizeVerifyWorkbookResult,
|
|
383
|
+
normalizeDescribeWorkbookResult,
|
|
384
|
+
normalizeNamedRangesResult,
|
|
385
|
+
normalizeSheetOverviewResult,
|
|
386
|
+
normalizeFindValueResult,
|
|
387
|
+
normalizeReadTableResult
|
|
388
|
+
}
|