@superdoc/sdk 2.6.0 → 2.8.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.
Files changed (51) hide show
  1. package/dist/agent/actions.cjs +1869 -160
  2. package/dist/agent/actions.d.ts +77 -10
  3. package/dist/agent/actions.js +1870 -161
  4. package/dist/agent/catalog.cjs +102 -9
  5. package/dist/agent/catalog.d.ts +243 -0
  6. package/dist/agent/catalog.js +99 -9
  7. package/dist/agent/doc-snapshot.cjs +200 -2
  8. package/dist/agent/doc-snapshot.d.ts +91 -0
  9. package/dist/agent/doc-snapshot.js +199 -2
  10. package/dist/agent/runtime.cjs +9 -1
  11. package/dist/agent/runtime.d.ts +8 -0
  12. package/dist/agent/runtime.js +9 -1
  13. package/dist/generated/client.cjs +754 -770
  14. package/dist/generated/client.d.ts +10 -9
  15. package/dist/generated/client.js +754 -770
  16. package/dist/generated/contract.cjs +16178 -272
  17. package/dist/generated/contract.d.ts +38 -0
  18. package/dist/generated/contract.js +17419 -1510
  19. package/dist/index.cjs +6 -5
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +6 -5
  22. package/dist/introspection.cjs +59 -0
  23. package/dist/introspection.d.ts +3 -0
  24. package/dist/introspection.js +53 -0
  25. package/dist/runtime/document-rpc.cjs +179 -40
  26. package/dist/runtime/document-rpc.d.ts +13 -4
  27. package/dist/runtime/document-rpc.js +175 -40
  28. package/dist/runtime/embedded-cli.cjs +5 -68
  29. package/dist/runtime/embedded-cli.js +5 -67
  30. package/dist/runtime/embedded-document-host.cjs +28 -0
  31. package/dist/runtime/embedded-document-host.d.ts +1 -0
  32. package/dist/runtime/embedded-document-host.js +23 -0
  33. package/dist/runtime/embedded-platform.cjs +108 -0
  34. package/dist/runtime/embedded-platform.d.ts +5 -0
  35. package/dist/runtime/embedded-platform.js +99 -0
  36. package/dist/runtime/host.cjs +237 -24
  37. package/dist/runtime/host.d.ts +17 -0
  38. package/dist/runtime/host.js +237 -25
  39. package/dist/runtime/process.cjs +30 -9
  40. package/dist/runtime/process.d.ts +9 -0
  41. package/dist/runtime/process.js +29 -9
  42. package/dist/runtime/sdk-version.generated.cjs +8 -0
  43. package/dist/runtime/sdk-version.generated.d.ts +1 -0
  44. package/dist/runtime/sdk-version.generated.js +4 -0
  45. package/dist/runtime/transport-common.cjs +1 -0
  46. package/dist/runtime/transport-common.d.ts +28 -10
  47. package/dist/runtime/transport-common.js +1 -1
  48. package/package.json +7 -7
  49. package/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  50. package/tools/__pycache__/intent_dispatch_generated.cpython-311.pyc +0 -0
  51. package/tools/tools-policy.json +1 -1
@@ -1,17 +1,17 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { SuperDocCliError } from './errors.js';
3
+ import { applyOperationParamAliases, } from './transport-common.js';
3
4
  export const DOCUMENT_RPC_FEATURES = ['document.open', 'document.invoke', 'document.save', 'document.close'];
4
- const DOCUMENT_RPC_V0_OPERATIONS = new Set(['doc.getText', 'doc.insert', 'doc.save', 'doc.close']);
5
+ export const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = 'document.open.defaultChangeMode';
6
+ export const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = 'document.save.source';
7
+ export const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = 'host.request.timeoutMs';
5
8
  const DOCUMENT_RPC_OPEN_FIELDS = new Set(['doc', 'sessionId', 'runtime']);
6
- const DOCUMENT_RPC_INSERT_FIELDS = new Set([
7
- 'value',
8
- 'type',
9
- 'target',
10
- 'ref',
11
- 'in',
12
- 'placement',
13
- 'content',
14
- 'nestingPolicy',
9
+ const DOCUMENT_RPC_SAVE_FIELDS = new Set(['sessionId', 'out', 'force', 'mode', 'inPlace']);
10
+ const DOCUMENT_API_OPTION_FIELDS = new Set(['expectedRevision', 'changeMode', 'dryRun', 'supportCheck']);
11
+ const DOCUMENT_API_REVISION_PREFLIGHT_OPERATIONS = new Set([
12
+ 'doc.history.redo',
13
+ 'doc.history.undo',
14
+ 'doc.plan.execute',
15
15
  ]);
16
16
  function unsupported(message, operationId) {
17
17
  return new SuperDocCliError(message, {
@@ -19,21 +19,42 @@ function unsupported(message, operationId) {
19
19
  ...(operationId === undefined ? {} : { details: { operationId } }),
20
20
  });
21
21
  }
22
+ function buildDocumentAuthor(user) {
23
+ if (user === undefined)
24
+ return undefined;
25
+ if (typeof user !== 'object' || user === null || Array.isArray(user)) {
26
+ throw new SuperDocCliError('user must be an object with a non-empty name.', {
27
+ code: 'INVALID_ARGUMENT',
28
+ });
29
+ }
30
+ const record = user;
31
+ if (typeof record.name !== 'string' || record.name.trim().length === 0) {
32
+ throw new SuperDocCliError('user.name must be a non-empty string.', {
33
+ code: 'INVALID_ARGUMENT',
34
+ });
35
+ }
36
+ if (record.email !== undefined && typeof record.email !== 'string') {
37
+ throw new SuperDocCliError('user.email must be a string.', {
38
+ code: 'INVALID_ARGUMENT',
39
+ });
40
+ }
41
+ return {
42
+ name: record.name,
43
+ ...(record.email === undefined ? {} : { email: record.email }),
44
+ };
45
+ }
22
46
  export function documentRpcEnabled(env) {
23
47
  return (env?.SUPERDOC_SDK_DOCUMENT_RPC ?? process.env.SUPERDOC_SDK_DOCUMENT_RPC) === '1';
24
48
  }
25
49
  export function supportsDocumentRpc(features) {
26
50
  return DOCUMENT_RPC_FEATURES.every((feature) => features.has(feature));
27
51
  }
28
- function hasUnsupportedInvokeOptions(options) {
29
- return (options.stdinBytes !== undefined ||
30
- options.dryRun !== undefined ||
31
- options.expectedRevision !== undefined ||
32
- options.changeMode !== undefined);
33
- }
34
52
  export function canOpenWithDocumentRpc(params, options) {
35
- if (hasUnsupportedInvokeOptions(options))
53
+ if (options.stdinBytes !== undefined)
54
+ return false;
55
+ if (options.dryRun !== undefined || options.expectedRevision !== undefined || options.changeMode !== undefined) {
36
56
  return false;
57
+ }
37
58
  if (typeof params.doc !== 'string' || params.doc.trim().length === 0 || params.doc === '-')
38
59
  return false;
39
60
  if (params.runtime !== undefined && params.runtime !== 'v2')
@@ -43,11 +64,17 @@ export function canOpenWithDocumentRpc(params, options) {
43
64
  }
44
65
  return Object.entries(params).every(([key, value]) => value === undefined || DOCUMENT_RPC_OPEN_FIELDS.has(key));
45
66
  }
46
- export function buildDocumentOpenParams(params) {
67
+ export function buildDocumentOpenParams(params, user, defaultChangeMode) {
47
68
  const sessionId = typeof params.sessionId === 'string' && params.sessionId.length > 0 ? params.sessionId : randomUUID();
69
+ const author = buildDocumentAuthor(user);
48
70
  return {
49
71
  sessionId,
50
- params: { sessionId, path: params.doc },
72
+ params: {
73
+ sessionId,
74
+ path: params.doc,
75
+ ...(author === undefined ? {} : { author }),
76
+ ...(defaultChangeMode == null ? {} : { defaultChangeMode }),
77
+ },
51
78
  };
52
79
  }
53
80
  export function mapDocumentOpenResult(response, sessionId, path) {
@@ -73,37 +100,120 @@ export function mapDocumentOpenResult(response, sessionId, path) {
73
100
  dirty: false,
74
101
  };
75
102
  }
76
- function documentInvokeInput(operationId, params) {
77
- const allowedFields = operationId === 'doc.getText' ? new Set(['in']) : DOCUMENT_RPC_INSERT_FIELDS;
78
- const input = Object.fromEntries(Object.entries(params).filter(([key, value]) => value !== undefined && key !== 'doc' && key !== 'sessionId'));
79
- const unsupportedField = Object.keys(input).find((key) => !allowedFields.has(key));
80
- if (unsupportedField) {
81
- throw unsupported(`Structured document RPC v0 does not support ${operationId} field ${unsupportedField}.`, operationId);
82
- }
83
- return input;
103
+ function supportsTrackedMode(operation) {
104
+ return operation.supportsTrackedMode === true || operation.supportsConditionalTrackedMode === true;
84
105
  }
85
- export function buildDocumentInvokeParams(sessionId, operation, params, options) {
86
- if (!DOCUMENT_RPC_V0_OPERATIONS.has(operation.operationId)) {
87
- throw unsupported(`Structured document RPC does not support ${operation.operationId} in v0.`, operation.operationId);
106
+ function documentInvokePayload(operation, params, invokeOptions) {
107
+ const normalizedParams = applyOperationParamAliases(operation, params);
108
+ if (invokeOptions.stdinBytes !== undefined) {
109
+ throw unsupported('Structured document RPC does not support stdinBytes.', operation.operationId);
110
+ }
111
+ if (typeof normalizedParams.out === 'string' && normalizedParams.out.length > 0) {
112
+ throw unsupported('Structured document RPC does not support per-operation output paths.', operation.operationId);
113
+ }
114
+ if (normalizedParams.force === true) {
115
+ throw unsupported('Structured document RPC does not support per-operation force.', operation.operationId);
116
+ }
117
+ const input = {};
118
+ const options = {};
119
+ const paramsByName = new Map(operation.params.map((param) => [param.name, param]));
120
+ for (const [name, value] of Object.entries(normalizedParams)) {
121
+ if (value === undefined || name === 'doc' || name === 'sessionId' || name === 'out' || name === 'force')
122
+ continue;
123
+ const param = paramsByName.get(name);
124
+ if (!param) {
125
+ throw unsupported(`Structured document RPC does not support ${operation.operationId} field ${name}.`, operation.operationId);
126
+ }
127
+ if (typeof param.documentApiInputName === 'string' && param.documentApiInputName.length > 0) {
128
+ input[param.documentApiInputName] = value;
129
+ continue;
130
+ }
131
+ if (DOCUMENT_API_OPTION_FIELDS.has(name)) {
132
+ options[name] = value;
133
+ continue;
134
+ }
135
+ throw unsupported(`Structured document RPC does not support ${operation.operationId} field ${name}.`, operation.operationId);
88
136
  }
89
- if (hasUnsupportedInvokeOptions(options)) {
90
- throw unsupported('Structured document RPC v0 does not support document mutation options.', operation.operationId);
137
+ for (const name of ['expectedRevision', 'changeMode', 'dryRun']) {
138
+ const value = invokeOptions[name];
139
+ if (value === undefined || normalizedParams[name] !== undefined)
140
+ continue;
141
+ const projectedValue = name === 'expectedRevision' ? String(value) : value;
142
+ const param = paramsByName.get(name);
143
+ if (typeof param?.documentApiInputName === 'string' && param.documentApiInputName.length > 0) {
144
+ input[param.documentApiInputName] = projectedValue;
145
+ }
146
+ else {
147
+ options[name] = projectedValue;
148
+ }
149
+ }
150
+ if (options.changeMode !== undefined && !supportsTrackedMode(operation)) {
151
+ if (options.changeMode === 'tracked') {
152
+ throw unsupported(`Structured document RPC does not support tracked mode for ${operation.operationId}.`, operation.operationId);
153
+ }
154
+ if (options.changeMode !== 'direct') {
155
+ throw unsupported(`Structured document RPC received an invalid change mode for ${operation.operationId}.`, operation.operationId);
156
+ }
157
+ delete options.changeMode;
91
158
  }
159
+ if (options.dryRun !== undefined && operation.supportsDryRun !== true) {
160
+ if (options.dryRun === true) {
161
+ throw unsupported(`Structured document RPC does not support dry run for ${operation.operationId}.`, operation.operationId);
162
+ }
163
+ delete options.dryRun;
164
+ }
165
+ if (options.expectedRevision !== undefined && DOCUMENT_API_REVISION_PREFLIGHT_OPERATIONS.has(operation.operationId)) {
166
+ throw unsupported(`Structured document RPC does not yet support expectedRevision for ${operation.operationId}.`, operation.operationId);
167
+ }
168
+ if (options.expectedRevision !== undefined && operation.mutates !== true) {
169
+ throw unsupported(`Structured document RPC does not support expectedRevision for ${operation.operationId}.`, operation.operationId);
170
+ }
171
+ return {
172
+ input,
173
+ ...(Object.keys(options).length === 0 ? {} : { options }),
174
+ };
175
+ }
176
+ export function buildDocumentInvokeParams(sessionId, operation, params, options, hostFeatures) {
92
177
  if (operation.operationId === 'doc.save') {
93
- if (params.inPlace === true || typeof params.out !== 'string' || params.out.length === 0) {
94
- throw unsupported('Structured document RPC v0 requires doc.save({ out }) and does not support inPlace.', operation.operationId);
178
+ if (options.stdinBytes !== undefined ||
179
+ options.dryRun !== undefined ||
180
+ options.expectedRevision !== undefined ||
181
+ options.changeMode !== undefined) {
182
+ throw unsupported('Structured document RPC does not support document.save invoke options.', operation.operationId);
183
+ }
184
+ const unknownField = Object.entries(params).find(([name, value]) => value !== undefined && !DOCUMENT_RPC_SAVE_FIELDS.has(name))?.[0];
185
+ if (unknownField !== undefined) {
186
+ throw unsupported(`Structured document RPC does not support doc.save field ${unknownField}.`, operation.operationId);
187
+ }
188
+ if (params.inPlace !== undefined && typeof params.inPlace !== 'boolean') {
189
+ throw unsupported('Structured document RPC requires inPlace to be a boolean.', operation.operationId);
190
+ }
191
+ if (params.inPlace === true && params.out !== undefined) {
192
+ throw unsupported('Structured document RPC requires either inPlace or out, not both.', operation.operationId);
193
+ }
194
+ if (params.out !== undefined && (typeof params.out !== 'string' || params.out.length === 0)) {
195
+ throw unsupported('Structured document RPC requires out to be a non-empty path.', operation.operationId);
196
+ }
197
+ if (params.out === undefined && hostFeatures?.has(DOCUMENT_RPC_SOURCE_SAVE_FEATURE) !== true) {
198
+ throw unsupported('Structured document RPC host does not support source saves.', operation.operationId);
95
199
  }
96
200
  return {
97
201
  method: 'document.save',
98
202
  params: {
99
203
  sessionId,
100
- path: params.out,
101
- overwrite: params.force === true,
204
+ ...(params.out === undefined ? {} : { path: params.out }),
205
+ ...(params.force === true ? { overwrite: true } : {}),
102
206
  ...(params.mode === undefined ? {} : { mode: params.mode }),
103
207
  },
104
208
  };
105
209
  }
106
210
  if (operation.operationId === 'doc.close') {
211
+ if (options.stdinBytes !== undefined ||
212
+ options.dryRun !== undefined ||
213
+ options.expectedRevision !== undefined ||
214
+ options.changeMode !== undefined) {
215
+ throw unsupported('Structured document RPC does not support document.close invoke options.', operation.operationId);
216
+ }
107
217
  return {
108
218
  method: 'document.close',
109
219
  params: {
@@ -112,16 +222,40 @@ export function buildDocumentInvokeParams(sessionId, operation, params, options)
112
222
  },
113
223
  };
114
224
  }
225
+ const documentOperation = operation;
226
+ if (typeof documentOperation.documentApiOperationId !== 'string' ||
227
+ documentOperation.documentApiOperationId.length === 0) {
228
+ throw unsupported(`Structured document RPC does not support ${operation.operationId}.`, operation.operationId);
229
+ }
230
+ const payload = documentInvokePayload(documentOperation, params, options);
115
231
  return {
116
232
  method: 'document.invoke',
117
233
  params: {
118
234
  sessionId,
119
- operationId: operation.operationId.slice('doc.'.length),
120
- input: documentInvokeInput(operation.operationId, params),
235
+ operationId: documentOperation.documentApiOperationId,
236
+ input: payload.input,
237
+ ...(payload.options === undefined ? {} : { options: payload.options }),
121
238
  },
122
239
  };
123
240
  }
124
- export function mapDocumentLifecycleResult(operationId, response, sessionId) {
241
+ export function documentRpcRequestSupportsResponseTimeout(operation, request) {
242
+ if (request.method === 'document.save')
243
+ return false;
244
+ if (request.method !== 'document.invoke')
245
+ return true;
246
+ const documentOperation = operation;
247
+ const requestOptions = typeof request.params.options === 'object' &&
248
+ request.params.options !== null &&
249
+ !Array.isArray(request.params.options)
250
+ ? request.params.options
251
+ : undefined;
252
+ if (requestOptions?.dryRun === true)
253
+ return true;
254
+ if (documentOperation.mutates === false)
255
+ return true;
256
+ return documentOperation.idempotency === 'idempotent';
257
+ }
258
+ export function mapDocumentLifecycleResult(operationId, response, sessionId, expectedInPlace) {
125
259
  if (operationId !== 'doc.save' && operationId !== 'doc.close')
126
260
  return response;
127
261
  if (typeof response !== 'object' || response == null || Array.isArray(response)) {
@@ -155,6 +289,7 @@ export function mapDocumentLifecycleResult(operationId, response, sessionId) {
155
289
  }
156
290
  const output = record.output;
157
291
  if (record.saved !== true ||
292
+ (typeof record.inPlace !== 'boolean' && !(record.inPlace === undefined && expectedInPlace === false)) ||
158
293
  typeof output !== 'object' ||
159
294
  output == null ||
160
295
  Array.isArray(output) ||
@@ -169,7 +304,7 @@ export function mapDocumentLifecycleResult(operationId, response, sessionId) {
169
304
  contextId: sessionId,
170
305
  runtime: 'v2',
171
306
  saved: true,
172
- inPlace: false,
307
+ inPlace: record.inPlace ?? false,
173
308
  mode: record.mode,
174
309
  output,
175
310
  report: record.report,
@@ -1,78 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var node_fs = require('node:fs');
4
- var node_module = require('node:module');
5
- var path = require('node:path');
6
- var node_url = require('node:url');
7
3
  var errors = require('./errors.cjs');
4
+ var embeddedPlatform = require('./embedded-platform.cjs');
8
5
 
9
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runtime/embedded-cli.cjs', document.baseURI).href)));
11
- const TARGET_TO_PACKAGE = {
12
- 'darwin-arm64': '@superdoc/sdk-darwin-arm64',
13
- 'darwin-x64': '@superdoc/sdk-darwin-x64',
14
- 'linux-x64': '@superdoc/sdk-linux-x64',
15
- 'linux-arm64': '@superdoc/sdk-linux-arm64',
16
- 'windows-x64': '@superdoc/sdk-windows-x64',
17
- };
18
- const TARGET_TO_DIR = {
19
- 'darwin-arm64': 'sdk-darwin-arm64',
20
- 'darwin-x64': 'sdk-darwin-x64',
21
- 'linux-x64': 'sdk-linux-x64',
22
- 'linux-arm64': 'sdk-linux-arm64',
23
- 'windows-x64': 'sdk-windows-x64',
24
- };
25
- function resolveTarget() {
26
- const platform = process.platform;
27
- const arch = process.arch;
28
- if (platform === 'darwin' && arch === 'arm64')
29
- return 'darwin-arm64';
30
- if (platform === 'darwin' && arch === 'x64')
31
- return 'darwin-x64';
32
- if (platform === 'linux' && arch === 'x64')
33
- return 'linux-x64';
34
- if (platform === 'linux' && arch === 'arm64')
35
- return 'linux-arm64';
36
- if (platform === 'win32' && arch === 'x64')
37
- return 'windows-x64';
38
- return null;
39
- }
40
6
  function binaryNameForTarget(target) {
41
7
  return target === 'windows-x64' ? 'superdoc.exe' : 'superdoc';
42
8
  }
43
- function ensureExecutable(binaryPath) {
44
- if (process.platform === 'win32')
45
- return;
46
- try {
47
- node_fs.chmodSync(binaryPath, 0o755);
48
- }
49
- catch {
50
- // Non-fatal: if chmod fails, spawn() will surface the real execution error.
51
- }
52
- }
53
- function resolveFromPlatformPackage(target) {
54
- const pkg = TARGET_TO_PACKAGE[target];
55
- const binaryName = binaryNameForTarget(target);
56
- try {
57
- return require$1.resolve(`${pkg}/bin/${binaryName}`);
58
- }
59
- catch {
60
- return null;
61
- }
62
- }
63
- function resolveFromWorkspaceFallback(target) {
64
- const binaryName = binaryNameForTarget(target);
65
- const dirName = TARGET_TO_DIR[target];
66
- const filePath = path.resolve(node_url.fileURLToPath(new URL('../../platforms', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runtime/embedded-cli.cjs', document.baseURI).href)))), dirName, 'bin', binaryName);
67
- if (!node_fs.existsSync(filePath))
68
- return null;
69
- return filePath;
70
- }
71
9
  /**
72
10
  * Resolve the path to the embedded SuperDoc CLI binary for the current platform.
73
11
  */
74
12
  function resolveEmbeddedCliBinary() {
75
- const target = resolveTarget();
13
+ const target = embeddedPlatform.resolveEmbeddedTarget();
76
14
  if (!target) {
77
15
  throw new errors.SuperDocCliError('No embedded SuperDoc CLI binary is available for this platform.', {
78
16
  code: 'UNSUPPORTED_PLATFORM',
@@ -82,18 +20,17 @@ function resolveEmbeddedCliBinary() {
82
20
  },
83
21
  });
84
22
  }
85
- const platformPackagePath = resolveFromPlatformPackage(target);
86
- const resolvedPath = platformPackagePath ?? resolveFromWorkspaceFallback(target);
23
+ const resolvedPath = embeddedPlatform.resolveEmbeddedPlatformBinary(target, binaryNameForTarget(target));
87
24
  if (!resolvedPath) {
88
25
  throw new errors.SuperDocCliError('Embedded SuperDoc CLI binary is missing for this platform.', {
89
26
  code: 'CLI_BINARY_MISSING',
90
27
  details: {
91
28
  target,
92
- packageName: TARGET_TO_PACKAGE[target],
29
+ packageName: embeddedPlatform.embeddedPlatformPackage(target),
93
30
  },
94
31
  });
95
32
  }
96
- ensureExecutable(resolvedPath);
33
+ embeddedPlatform.ensureEmbeddedExecutable(resolvedPath);
97
34
  return resolvedPath;
98
35
  }
99
36
 
@@ -1,74 +1,13 @@
1
- import { chmodSync, existsSync } from 'node:fs';
2
- import { createRequire } from 'node:module';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
1
  import { SuperDocCliError } from './errors.js';
6
- const require = createRequire(import.meta.url);
7
- const TARGET_TO_PACKAGE = {
8
- 'darwin-arm64': '@superdoc/sdk-darwin-arm64',
9
- 'darwin-x64': '@superdoc/sdk-darwin-x64',
10
- 'linux-x64': '@superdoc/sdk-linux-x64',
11
- 'linux-arm64': '@superdoc/sdk-linux-arm64',
12
- 'windows-x64': '@superdoc/sdk-windows-x64',
13
- };
14
- const TARGET_TO_DIR = {
15
- 'darwin-arm64': 'sdk-darwin-arm64',
16
- 'darwin-x64': 'sdk-darwin-x64',
17
- 'linux-x64': 'sdk-linux-x64',
18
- 'linux-arm64': 'sdk-linux-arm64',
19
- 'windows-x64': 'sdk-windows-x64',
20
- };
21
- function resolveTarget() {
22
- const platform = process.platform;
23
- const arch = process.arch;
24
- if (platform === 'darwin' && arch === 'arm64')
25
- return 'darwin-arm64';
26
- if (platform === 'darwin' && arch === 'x64')
27
- return 'darwin-x64';
28
- if (platform === 'linux' && arch === 'x64')
29
- return 'linux-x64';
30
- if (platform === 'linux' && arch === 'arm64')
31
- return 'linux-arm64';
32
- if (platform === 'win32' && arch === 'x64')
33
- return 'windows-x64';
34
- return null;
35
- }
2
+ import { embeddedPlatformPackage, ensureEmbeddedExecutable, resolveEmbeddedPlatformBinary, resolveEmbeddedTarget, } from './embedded-platform.js';
36
3
  function binaryNameForTarget(target) {
37
4
  return target === 'windows-x64' ? 'superdoc.exe' : 'superdoc';
38
5
  }
39
- function ensureExecutable(binaryPath) {
40
- if (process.platform === 'win32')
41
- return;
42
- try {
43
- chmodSync(binaryPath, 0o755);
44
- }
45
- catch {
46
- // Non-fatal: if chmod fails, spawn() will surface the real execution error.
47
- }
48
- }
49
- function resolveFromPlatformPackage(target) {
50
- const pkg = TARGET_TO_PACKAGE[target];
51
- const binaryName = binaryNameForTarget(target);
52
- try {
53
- return require.resolve(`${pkg}/bin/${binaryName}`);
54
- }
55
- catch {
56
- return null;
57
- }
58
- }
59
- function resolveFromWorkspaceFallback(target) {
60
- const binaryName = binaryNameForTarget(target);
61
- const dirName = TARGET_TO_DIR[target];
62
- const filePath = path.resolve(fileURLToPath(new URL('../../platforms', import.meta.url)), dirName, 'bin', binaryName);
63
- if (!existsSync(filePath))
64
- return null;
65
- return filePath;
66
- }
67
6
  /**
68
7
  * Resolve the path to the embedded SuperDoc CLI binary for the current platform.
69
8
  */
70
9
  export function resolveEmbeddedCliBinary() {
71
- const target = resolveTarget();
10
+ const target = resolveEmbeddedTarget();
72
11
  if (!target) {
73
12
  throw new SuperDocCliError('No embedded SuperDoc CLI binary is available for this platform.', {
74
13
  code: 'UNSUPPORTED_PLATFORM',
@@ -78,17 +17,16 @@ export function resolveEmbeddedCliBinary() {
78
17
  },
79
18
  });
80
19
  }
81
- const platformPackagePath = resolveFromPlatformPackage(target);
82
- const resolvedPath = platformPackagePath ?? resolveFromWorkspaceFallback(target);
20
+ const resolvedPath = resolveEmbeddedPlatformBinary(target, binaryNameForTarget(target));
83
21
  if (!resolvedPath) {
84
22
  throw new SuperDocCliError('Embedded SuperDoc CLI binary is missing for this platform.', {
85
23
  code: 'CLI_BINARY_MISSING',
86
24
  details: {
87
25
  target,
88
- packageName: TARGET_TO_PACKAGE[target],
26
+ packageName: embeddedPlatformPackage(target),
89
27
  },
90
28
  });
91
29
  }
92
- ensureExecutable(resolvedPath);
30
+ ensureEmbeddedExecutable(resolvedPath);
93
31
  return resolvedPath;
94
32
  }
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ var embeddedPlatform = require('./embedded-platform.cjs');
4
+ var errors = require('./errors.cjs');
5
+
6
+ function binaryNameForTarget(target) {
7
+ return target === 'windows-x64' ? 'superdoc-document-host.exe' : 'superdoc-document-host';
8
+ }
9
+ function resolveEmbeddedDocumentHostBinary() {
10
+ const target = embeddedPlatform.resolveEmbeddedTarget();
11
+ if (!target) {
12
+ throw new errors.SuperDocCliError('No embedded SuperDoc document host is available for this platform.', {
13
+ code: 'UNSUPPORTED_PLATFORM',
14
+ details: { platform: process.platform, arch: process.arch },
15
+ });
16
+ }
17
+ const resolvedPath = embeddedPlatform.resolveEmbeddedPlatformBinary(target, binaryNameForTarget(target));
18
+ if (!resolvedPath) {
19
+ throw new errors.SuperDocCliError('Embedded SuperDoc document host is missing for this platform.', {
20
+ code: 'DOCUMENT_HOST_BINARY_MISSING',
21
+ details: { target, packageName: embeddedPlatform.embeddedPlatformPackage(target) },
22
+ });
23
+ }
24
+ embeddedPlatform.ensureEmbeddedExecutable(resolvedPath);
25
+ return resolvedPath;
26
+ }
27
+
28
+ exports.resolveEmbeddedDocumentHostBinary = resolveEmbeddedDocumentHostBinary;
@@ -0,0 +1 @@
1
+ export declare function resolveEmbeddedDocumentHostBinary(): string;
@@ -0,0 +1,23 @@
1
+ import { embeddedPlatformPackage, ensureEmbeddedExecutable, resolveEmbeddedPlatformBinary, resolveEmbeddedTarget, } from './embedded-platform.js';
2
+ import { SuperDocCliError } from './errors.js';
3
+ function binaryNameForTarget(target) {
4
+ return target === 'windows-x64' ? 'superdoc-document-host.exe' : 'superdoc-document-host';
5
+ }
6
+ export function resolveEmbeddedDocumentHostBinary() {
7
+ const target = resolveEmbeddedTarget();
8
+ if (!target) {
9
+ throw new SuperDocCliError('No embedded SuperDoc document host is available for this platform.', {
10
+ code: 'UNSUPPORTED_PLATFORM',
11
+ details: { platform: process.platform, arch: process.arch },
12
+ });
13
+ }
14
+ const resolvedPath = resolveEmbeddedPlatformBinary(target, binaryNameForTarget(target));
15
+ if (!resolvedPath) {
16
+ throw new SuperDocCliError('Embedded SuperDoc document host is missing for this platform.', {
17
+ code: 'DOCUMENT_HOST_BINARY_MISSING',
18
+ details: { target, packageName: embeddedPlatformPackage(target) },
19
+ });
20
+ }
21
+ ensureEmbeddedExecutable(resolvedPath);
22
+ return resolvedPath;
23
+ }
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ var node_fs = require('node:fs');
4
+ var node_module = require('node:module');
5
+ var path = require('node:path');
6
+ var node_url = require('node:url');
7
+ var sdkVersion_generated = require('./sdk-version.generated.cjs');
8
+
9
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runtime/embedded-platform.cjs', document.baseURI).href)));
11
+ const TARGET_TO_PACKAGE = {
12
+ 'darwin-arm64': '@superdoc/sdk-darwin-arm64',
13
+ 'darwin-x64': '@superdoc/sdk-darwin-x64',
14
+ 'linux-x64': '@superdoc/sdk-linux-x64',
15
+ 'linux-arm64': '@superdoc/sdk-linux-arm64',
16
+ 'windows-x64': '@superdoc/sdk-windows-x64',
17
+ };
18
+ const TARGET_TO_DIR = {
19
+ 'darwin-arm64': 'sdk-darwin-arm64',
20
+ 'darwin-x64': 'sdk-darwin-x64',
21
+ 'linux-x64': 'sdk-linux-x64',
22
+ 'linux-arm64': 'sdk-linux-arm64',
23
+ 'windows-x64': 'sdk-windows-x64',
24
+ };
25
+ function resolveEmbeddedTarget(platform = process.platform, arch = process.arch) {
26
+ if (platform === 'darwin' && arch === 'arm64')
27
+ return 'darwin-arm64';
28
+ if (platform === 'darwin' && arch === 'x64')
29
+ return 'darwin-x64';
30
+ if (platform === 'linux' && arch === 'x64')
31
+ return 'linux-x64';
32
+ if (platform === 'linux' && arch === 'arm64')
33
+ return 'linux-arm64';
34
+ if (platform === 'win32' && arch === 'x64')
35
+ return 'windows-x64';
36
+ return null;
37
+ }
38
+ function embeddedPlatformPackage(target) {
39
+ return TARGET_TO_PACKAGE[target];
40
+ }
41
+ /**
42
+ * The binary shipped inside this package (`platforms/<target>/bin/`). A build
43
+ * that carries its own host is authoritative — it is the only copy guaranteed
44
+ * to match this SDK's code — so it is tried before any resolver lookup.
45
+ */
46
+ function resolveFromPackageLocal(target, binaryName) {
47
+ const workspacePath = path.resolve(node_url.fileURLToPath(new URL('../../platforms', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runtime/embedded-platform.cjs', document.baseURI).href)))), TARGET_TO_DIR[target], 'bin', binaryName);
48
+ return node_fs.existsSync(workspacePath) ? workspacePath : null;
49
+ }
50
+ /**
51
+ * Resolve the platform package through Node, and reject a version that is not
52
+ * this SDK's own.
53
+ *
54
+ * Resolution starts from the installed SDK so pnpm's isolated optional
55
+ * dependency remains visible after the SDK itself is bundled. `require.resolve`
56
+ * can also fall back to NODE_PATH, so the version check prevents a host binary
57
+ * from an unrelated SDK version in a flat store from satisfying this lookup.
58
+ * optionalDependencies pin the platform package to an exact version, so a
59
+ * mismatch here is never legitimate.
60
+ */
61
+ function resolveFromPlatformPackage(target, binaryName) {
62
+ const pkg = TARGET_TO_PACKAGE[target];
63
+ let sdkRequire;
64
+ try {
65
+ sdkRequire = node_module.createRequire(require$1.resolve('@superdoc/sdk'));
66
+ }
67
+ catch {
68
+ sdkRequire = require$1;
69
+ }
70
+ let binaryPath;
71
+ try {
72
+ binaryPath = sdkRequire.resolve(`${pkg}/bin/${binaryName}`);
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ try {
78
+ const platformVersion = sdkRequire(sdkRequire.resolve(`${pkg}/package.json`)).version;
79
+ if (platformVersion !== sdkVersion_generated.SDK_VERSION)
80
+ return null;
81
+ }
82
+ catch {
83
+ // An unreadable platform manifest is itself disqualifying: an unverifiable
84
+ // host is exactly the case this guard exists to reject.
85
+ return null;
86
+ }
87
+ return binaryPath;
88
+ }
89
+ function resolveEmbeddedPlatformBinary(target, binaryName) {
90
+ // Package-local first: a self-contained build must never be overridden by
91
+ // whatever the module resolver happens to find on NODE_PATH.
92
+ return resolveFromPackageLocal(target, binaryName) ?? resolveFromPlatformPackage(target, binaryName);
93
+ }
94
+ function ensureEmbeddedExecutable(binaryPath) {
95
+ if (process.platform === 'win32')
96
+ return;
97
+ try {
98
+ node_fs.chmodSync(binaryPath, 0o755);
99
+ }
100
+ catch {
101
+ // Non-fatal: spawn() reports the actionable execution error.
102
+ }
103
+ }
104
+
105
+ exports.embeddedPlatformPackage = embeddedPlatformPackage;
106
+ exports.ensureEmbeddedExecutable = ensureEmbeddedExecutable;
107
+ exports.resolveEmbeddedPlatformBinary = resolveEmbeddedPlatformBinary;
108
+ exports.resolveEmbeddedTarget = resolveEmbeddedTarget;
@@ -0,0 +1,5 @@
1
+ export type SupportedEmbeddedTarget = 'darwin-arm64' | 'darwin-x64' | 'linux-x64' | 'linux-arm64' | 'windows-x64';
2
+ export declare function resolveEmbeddedTarget(platform?: NodeJS.Platform, arch?: NodeJS.Architecture): SupportedEmbeddedTarget | null;
3
+ export declare function embeddedPlatformPackage(target: SupportedEmbeddedTarget): string;
4
+ export declare function resolveEmbeddedPlatformBinary(target: SupportedEmbeddedTarget, binaryName: string): string | null;
5
+ export declare function ensureEmbeddedExecutable(binaryPath: string): void;