@superdoc/sdk 2.10.0-next.3 → 2.10.0-next.5
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/dist/generated/contract.cjs +1 -0
- package/dist/generated/contract.js +2 -0
- package/dist/index.cjs +12 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +12 -0
- package/dist/runtime/document-rpc.cjs +27 -0
- package/dist/runtime/document-rpc.d.ts +2 -0
- package/dist/runtime/document-rpc.js +25 -0
- package/dist/runtime/host.cjs +35 -2
- package/dist/runtime/host.d.ts +1 -0
- package/dist/runtime/host.js +36 -3
- package/dist/runtime/process.cjs +32 -0
- package/dist/runtime/process.d.ts +14 -0
- package/dist/runtime/process.js +32 -0
- package/dist/runtime/sdk-version.generated.cjs +1 -1
- package/dist/runtime/sdk-version.generated.d.ts +1 -1
- package/dist/runtime/sdk-version.generated.js +1 -1
- package/package.json +7 -7
|
@@ -2905,6 +2905,7 @@ export const CONTRACT = {
|
|
|
2905
2905
|
"document.open",
|
|
2906
2906
|
"document.open.defaultChangeMode",
|
|
2907
2907
|
"document.currentRevision",
|
|
2908
|
+
"document.replaceFile",
|
|
2908
2909
|
"document.invoke",
|
|
2909
2910
|
"document.save",
|
|
2910
2911
|
"document.save.source",
|
|
@@ -2936,6 +2937,7 @@ export const CONTRACT = {
|
|
|
2936
2937
|
"document.open",
|
|
2937
2938
|
"document.open.defaultChangeMode",
|
|
2938
2939
|
"document.currentRevision",
|
|
2940
|
+
"document.replaceFile",
|
|
2939
2941
|
"document.invoke",
|
|
2940
2942
|
"document.save",
|
|
2941
2943
|
"document.save.source",
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,15 @@ class BoundRuntime {
|
|
|
37
37
|
}
|
|
38
38
|
return this.runtime.invoke(operation, { ...params, sessionId: this.sessionId }, options);
|
|
39
39
|
}
|
|
40
|
+
async replaceFile(source, options = {}) {
|
|
41
|
+
if (this.closed) {
|
|
42
|
+
throw new errors.SuperDocCliError('Document handle is closed; cannot replace its file.', {
|
|
43
|
+
code: 'DOCUMENT_CLOSED',
|
|
44
|
+
details: { sessionId: this.sessionId },
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return this.runtime.replaceFile(this.sessionId, source, options);
|
|
48
|
+
}
|
|
40
49
|
markClosed() {
|
|
41
50
|
this.closed = true;
|
|
42
51
|
}
|
|
@@ -72,6 +81,9 @@ class SuperDocDocumentCore {
|
|
|
72
81
|
async save(params = {}, options = {}) {
|
|
73
82
|
return this.boundRuntime.invoke(contract.CONTRACT.operations['doc.save'], params, options);
|
|
74
83
|
}
|
|
84
|
+
async replaceFile(source, options = {}) {
|
|
85
|
+
return this.boundRuntime.replaceFile(source, options);
|
|
86
|
+
}
|
|
75
87
|
async close(params = {}, options = {}) {
|
|
76
88
|
const result = await this.boundRuntime.invoke(contract.CONTRACT.operations['doc.close'], params, options);
|
|
77
89
|
this.boundRuntime.markClosed();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BoundDocApi, type DocCloseBoundParams, type DocCloseResult, type DocFormatApplyBoundParams, type DocFormatApplyResult, type DocOpenParams as GeneratedDocOpenParams, type DocOpenResult, type DocSaveBoundParams, type DocSaveResult } from './generated/client.js';
|
|
2
|
-
import { SuperDocRuntime, type SuperDocClientOptions, type DocOpenOptions, type InvokeOptions, type OperationSpec, type RuntimeInvoker } from './runtime/process.js';
|
|
2
|
+
import { SuperDocRuntime, type SuperDocClientOptions, type DocOpenOptions, type InvokeOptions, type OperationSpec, type ReplaceFileOptions, type ReplaceFileResult, type ReplaceFileSource, type RuntimeInvoker } from './runtime/process.js';
|
|
3
3
|
/**
|
|
4
4
|
* Wraps a raw runtime and injects a fixed sessionId into every invoke call.
|
|
5
5
|
* Implements RuntimeInvoker so generated code can use it directly.
|
|
@@ -12,6 +12,7 @@ declare class BoundRuntime implements RuntimeInvoker {
|
|
|
12
12
|
private closed;
|
|
13
13
|
constructor(runtime: SuperDocRuntime, sessionId: string);
|
|
14
14
|
invoke<TData = unknown>(operation: OperationSpec, params?: Record<string, unknown>, options?: InvokeOptions): Promise<TData>;
|
|
15
|
+
replaceFile(source: ReplaceFileSource, options?: ReplaceFileOptions): Promise<ReplaceFileResult>;
|
|
15
16
|
markClosed(): void;
|
|
16
17
|
}
|
|
17
18
|
export interface DocFormatRangeBoundParams extends Omit<DocFormatApplyBoundParams, 'inline'> {
|
|
@@ -33,6 +34,7 @@ declare class SuperDocDocumentCore {
|
|
|
33
34
|
/** Read-only snapshot of the initial doc.open response metadata. */
|
|
34
35
|
get openResult(): DocOpenResult;
|
|
35
36
|
save(params?: DocSaveBoundParams, options?: InvokeOptions): Promise<DocSaveResult>;
|
|
37
|
+
replaceFile(source: ReplaceFileSource, options?: ReplaceFileOptions): Promise<ReplaceFileResult>;
|
|
36
38
|
close(params?: DocCloseBoundParams, options?: InvokeOptions): Promise<DocCloseResult>;
|
|
37
39
|
/** @internal */
|
|
38
40
|
markClosed(): void;
|
|
@@ -42,6 +44,7 @@ type SuperDocDocumentInstance = SuperDocDocumentCore & BoundDocApi;
|
|
|
42
44
|
export declare const SuperDocDocument: new (boundRuntime: BoundRuntime, sessionId: string, openResult: DocOpenResult, client: SuperDocClient) => SuperDocDocumentInstance;
|
|
43
45
|
export type SuperDocDocument = SuperDocDocumentInstance;
|
|
44
46
|
export type DocOpenParams = GeneratedDocOpenParams;
|
|
47
|
+
export type { ReplaceFileOptions, ReplaceFileResult, ReplaceFileSource };
|
|
45
48
|
export interface DocDescribeCommandParams {
|
|
46
49
|
operationId: string;
|
|
47
50
|
[key: string]: unknown;
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,15 @@ class BoundRuntime {
|
|
|
29
29
|
}
|
|
30
30
|
return this.runtime.invoke(operation, { ...params, sessionId: this.sessionId }, options);
|
|
31
31
|
}
|
|
32
|
+
async replaceFile(source, options = {}) {
|
|
33
|
+
if (this.closed) {
|
|
34
|
+
throw new SuperDocCliError('Document handle is closed; cannot replace its file.', {
|
|
35
|
+
code: 'DOCUMENT_CLOSED',
|
|
36
|
+
details: { sessionId: this.sessionId },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return this.runtime.replaceFile(this.sessionId, source, options);
|
|
40
|
+
}
|
|
32
41
|
markClosed() {
|
|
33
42
|
this.closed = true;
|
|
34
43
|
}
|
|
@@ -64,6 +73,9 @@ class SuperDocDocumentCore {
|
|
|
64
73
|
async save(params = {}, options = {}) {
|
|
65
74
|
return this.boundRuntime.invoke(CONTRACT.operations['doc.save'], params, options);
|
|
66
75
|
}
|
|
76
|
+
async replaceFile(source, options = {}) {
|
|
77
|
+
return this.boundRuntime.replaceFile(source, options);
|
|
78
|
+
}
|
|
67
79
|
async close(params = {}, options = {}) {
|
|
68
80
|
const result = await this.boundRuntime.invoke(CONTRACT.operations['doc.close'], params, options);
|
|
69
81
|
this.boundRuntime.markClosed();
|
|
@@ -5,6 +5,7 @@ var errors = require('./errors.cjs');
|
|
|
5
5
|
var transportCommon = require('./transport-common.cjs');
|
|
6
6
|
|
|
7
7
|
const DOCUMENT_RPC_FEATURES = ['document.open', 'document.invoke', 'document.save', 'document.close'];
|
|
8
|
+
const DOCUMENT_RPC_REPLACE_FILE_FEATURE = 'document.replaceFile';
|
|
8
9
|
const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = 'document.open.defaultChangeMode';
|
|
9
10
|
const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = 'document.save.source';
|
|
10
11
|
const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = 'host.request.timeoutMs';
|
|
@@ -103,6 +104,30 @@ function mapDocumentOpenResult(response, sessionId, path) {
|
|
|
103
104
|
dirty: false,
|
|
104
105
|
};
|
|
105
106
|
}
|
|
107
|
+
function mapDocumentReplaceFileResult(response, sessionId) {
|
|
108
|
+
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
109
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile result.', {
|
|
110
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
111
|
+
details: { result: response },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const record = response;
|
|
115
|
+
if (record.sessionId !== sessionId ||
|
|
116
|
+
record.replaced !== true ||
|
|
117
|
+
typeof record.byteLength !== 'number' ||
|
|
118
|
+
typeof record.revision !== 'string') {
|
|
119
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
|
|
120
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
121
|
+
details: { expectedSessionId: sessionId, result: response },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
contextId: sessionId,
|
|
126
|
+
runtime: 'v2',
|
|
127
|
+
replaced: true,
|
|
128
|
+
document: { byteLength: record.byteLength, revision: record.revision },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
106
131
|
function supportsTrackedMode(operation) {
|
|
107
132
|
return operation.supportsTrackedMode === true || operation.supportsConditionalTrackedMode === true;
|
|
108
133
|
}
|
|
@@ -316,6 +341,7 @@ function mapDocumentLifecycleResult(operationId, response, sessionId, expectedIn
|
|
|
316
341
|
|
|
317
342
|
exports.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE;
|
|
318
343
|
exports.DOCUMENT_RPC_FEATURES = DOCUMENT_RPC_FEATURES;
|
|
344
|
+
exports.DOCUMENT_RPC_REPLACE_FILE_FEATURE = DOCUMENT_RPC_REPLACE_FILE_FEATURE;
|
|
319
345
|
exports.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE;
|
|
320
346
|
exports.DOCUMENT_RPC_SOURCE_SAVE_FEATURE = DOCUMENT_RPC_SOURCE_SAVE_FEATURE;
|
|
321
347
|
exports.buildDocumentInvokeParams = buildDocumentInvokeParams;
|
|
@@ -325,4 +351,5 @@ exports.documentRpcEnabled = documentRpcEnabled;
|
|
|
325
351
|
exports.documentRpcRequestSupportsResponseTimeout = documentRpcRequestSupportsResponseTimeout;
|
|
326
352
|
exports.mapDocumentLifecycleResult = mapDocumentLifecycleResult;
|
|
327
353
|
exports.mapDocumentOpenResult = mapDocumentOpenResult;
|
|
354
|
+
exports.mapDocumentReplaceFileResult = mapDocumentReplaceFileResult;
|
|
328
355
|
exports.supportsDocumentRpc = supportsDocumentRpc;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ChangeMode, type InvokeOptions, type OperationSpec, type UserIdentity } from './transport-common.js';
|
|
2
2
|
export declare const DOCUMENT_RPC_FEATURES: readonly ["document.open", "document.invoke", "document.save", "document.close"];
|
|
3
|
+
export declare const DOCUMENT_RPC_REPLACE_FILE_FEATURE = "document.replaceFile";
|
|
3
4
|
export declare const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = "document.open.defaultChangeMode";
|
|
4
5
|
export declare const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = "document.save.source";
|
|
5
6
|
export declare const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = "host.request.timeoutMs";
|
|
@@ -15,6 +16,7 @@ export declare function buildDocumentOpenParams(params: Record<string, unknown>,
|
|
|
15
16
|
readonly params: Record<string, unknown>;
|
|
16
17
|
};
|
|
17
18
|
export declare function mapDocumentOpenResult(response: unknown, sessionId: string, path: string): Record<string, unknown>;
|
|
19
|
+
export declare function mapDocumentReplaceFileResult(response: unknown, sessionId: string): Record<string, unknown>;
|
|
18
20
|
export declare function buildDocumentInvokeParams(sessionId: string, operation: OperationSpec, params: Record<string, unknown>, options: InvokeOptions, hostFeatures?: ReadonlySet<string>): {
|
|
19
21
|
readonly method: string;
|
|
20
22
|
readonly params: Record<string, unknown>;
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { SuperDocCliError } from './errors.js';
|
|
3
3
|
import { applyOperationParamAliases, } from './transport-common.js';
|
|
4
4
|
export const DOCUMENT_RPC_FEATURES = ['document.open', 'document.invoke', 'document.save', 'document.close'];
|
|
5
|
+
export const DOCUMENT_RPC_REPLACE_FILE_FEATURE = 'document.replaceFile';
|
|
5
6
|
export const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = 'document.open.defaultChangeMode';
|
|
6
7
|
export const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = 'document.save.source';
|
|
7
8
|
export const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = 'host.request.timeoutMs';
|
|
@@ -100,6 +101,30 @@ export function mapDocumentOpenResult(response, sessionId, path) {
|
|
|
100
101
|
dirty: false,
|
|
101
102
|
};
|
|
102
103
|
}
|
|
104
|
+
export function mapDocumentReplaceFileResult(response, sessionId) {
|
|
105
|
+
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
106
|
+
throw new SuperDocCliError('Host returned invalid document.replaceFile result.', {
|
|
107
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
108
|
+
details: { result: response },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const record = response;
|
|
112
|
+
if (record.sessionId !== sessionId ||
|
|
113
|
+
record.replaced !== true ||
|
|
114
|
+
typeof record.byteLength !== 'number' ||
|
|
115
|
+
typeof record.revision !== 'string') {
|
|
116
|
+
throw new SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
|
|
117
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
118
|
+
details: { expectedSessionId: sessionId, result: response },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
contextId: sessionId,
|
|
123
|
+
runtime: 'v2',
|
|
124
|
+
replaced: true,
|
|
125
|
+
document: { byteLength: record.byteLength, revision: record.revision },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
103
128
|
function supportsTrackedMode(operation) {
|
|
104
129
|
return operation.supportsTrackedMode === true || operation.supportsConditionalTrackedMode === true;
|
|
105
130
|
}
|
package/dist/runtime/host.cjs
CHANGED
|
@@ -187,6 +187,34 @@ class HostTransport {
|
|
|
187
187
|
async invoke(operation, params = {}, options = {}) {
|
|
188
188
|
return this.runWhileActive(() => this.invokeWhileActive(operation, params, options));
|
|
189
189
|
}
|
|
190
|
+
async replaceFile(sessionId, path, options = {}) {
|
|
191
|
+
return this.runWhileActive(async () => {
|
|
192
|
+
await this.ensureConnected();
|
|
193
|
+
if (!this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE)) {
|
|
194
|
+
throw new errors.SuperDocCliError('The connected host does not support document replacement.', {
|
|
195
|
+
code: 'CAPABILITY_UNSUPPORTED',
|
|
196
|
+
details: { feature: documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const tracksDirectSession = this.documentRpcSessions.has(sessionId);
|
|
200
|
+
if (tracksDirectSession)
|
|
201
|
+
this.beginDocumentRpcMutation(sessionId);
|
|
202
|
+
try {
|
|
203
|
+
const response = await this.sendJsonRpcRequest(documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
204
|
+
const result = documentRpc.mapDocumentReplaceFileResult(response, sessionId);
|
|
205
|
+
if (tracksDirectSession)
|
|
206
|
+
this.settleDocumentRpcMutation(sessionId, 'applied');
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
if (tracksDirectSession) {
|
|
211
|
+
const indeterminate = error instanceof errors.SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
212
|
+
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
213
|
+
}
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
190
218
|
async invokeWhileActive(operation, params, options) {
|
|
191
219
|
const collaborationAuth = options.collaborationAuth === undefined ? undefined : transportCommon.normalizeCollaborationAuth(options.collaborationAuth);
|
|
192
220
|
if (collaborationAuth !== undefined) {
|
|
@@ -285,8 +313,11 @@ class HostTransport {
|
|
|
285
313
|
details: { operationId: operation.operationId },
|
|
286
314
|
});
|
|
287
315
|
}
|
|
316
|
+
const supportsRequestTimeoutMetadata = this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
|
|
288
317
|
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
289
|
-
if (
|
|
318
|
+
if (!supportsRequestTimeoutMetadata &&
|
|
319
|
+
options.timeoutMs !== undefined &&
|
|
320
|
+
options.timeoutMs > cliHostRequestTimeoutMs) {
|
|
290
321
|
throw new errors.SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
291
322
|
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
292
323
|
details: {
|
|
@@ -304,7 +335,9 @@ class HostTransport {
|
|
|
304
335
|
argv,
|
|
305
336
|
stdinBase64,
|
|
306
337
|
...(collaborationAuth === undefined ? {} : { collaborationAuth }),
|
|
307
|
-
}, watchdogTimeout
|
|
338
|
+
}, watchdogTimeout, {
|
|
339
|
+
requestTimeoutMs: supportsRequestTimeoutMetadata ? options.timeoutMs : undefined,
|
|
340
|
+
});
|
|
308
341
|
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
309
342
|
throw new errors.SuperDocCliError('Host returned invalid cli.invoke result.', {
|
|
310
343
|
code: 'HOST_PROTOCOL_ERROR',
|
package/dist/runtime/host.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export declare class HostTransport {
|
|
|
64
64
|
dispose(): Promise<void>;
|
|
65
65
|
private disposeAfterActiveCalls;
|
|
66
66
|
invoke<TData = unknown>(operation: OperationSpec, params?: Record<string, unknown>, options?: TransportInvokeOptions): Promise<TData>;
|
|
67
|
+
replaceFile(sessionId: string, path: string, options?: TransportInvokeOptions): Promise<Record<string, unknown>>;
|
|
67
68
|
private invokeWhileActive;
|
|
68
69
|
private runWhileActive;
|
|
69
70
|
private ensureConnected;
|
package/dist/runtime/host.js
CHANGED
|
@@ -2,7 +2,7 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { createInterface } from 'node:readline';
|
|
3
3
|
import { buildOperationArgv, normalizeCollaborationAuth, resolveInvocation, } from './transport-common.js';
|
|
4
4
|
import { SuperDocCliError } from './errors.js';
|
|
5
|
-
import { DOCUMENT_RPC_FEATURES, DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE, DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE, DOCUMENT_RPC_SOURCE_SAVE_FEATURE, buildDocumentInvokeParams, buildDocumentOpenParams, canOpenWithDocumentRpc, documentRpcRequestSupportsResponseTimeout, documentRpcEnabled, mapDocumentLifecycleResult, mapDocumentOpenResult, supportsDocumentRpc, } from './document-rpc.js';
|
|
5
|
+
import { DOCUMENT_RPC_FEATURES, DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE, DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE, DOCUMENT_RPC_REPLACE_FILE_FEATURE, DOCUMENT_RPC_SOURCE_SAVE_FEATURE, buildDocumentInvokeParams, buildDocumentOpenParams, canOpenWithDocumentRpc, documentRpcRequestSupportsResponseTimeout, documentRpcEnabled, mapDocumentLifecycleResult, mapDocumentOpenResult, mapDocumentReplaceFileResult, supportsDocumentRpc, } from './document-rpc.js';
|
|
6
6
|
const HOST_PROTOCOL_VERSION = '1.0';
|
|
7
7
|
const CLI_HOST_REQUIRED_FEATURES = ['cli.invoke', 'host.shutdown'];
|
|
8
8
|
export const COLLABORATION_AUTH_PER_OPEN_FEATURE = 'collaboration.auth.perOpen';
|
|
@@ -184,6 +184,34 @@ export class HostTransport {
|
|
|
184
184
|
async invoke(operation, params = {}, options = {}) {
|
|
185
185
|
return this.runWhileActive(() => this.invokeWhileActive(operation, params, options));
|
|
186
186
|
}
|
|
187
|
+
async replaceFile(sessionId, path, options = {}) {
|
|
188
|
+
return this.runWhileActive(async () => {
|
|
189
|
+
await this.ensureConnected();
|
|
190
|
+
if (!this.hostFeatures.has(DOCUMENT_RPC_REPLACE_FILE_FEATURE)) {
|
|
191
|
+
throw new SuperDocCliError('The connected host does not support document replacement.', {
|
|
192
|
+
code: 'CAPABILITY_UNSUPPORTED',
|
|
193
|
+
details: { feature: DOCUMENT_RPC_REPLACE_FILE_FEATURE },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const tracksDirectSession = this.documentRpcSessions.has(sessionId);
|
|
197
|
+
if (tracksDirectSession)
|
|
198
|
+
this.beginDocumentRpcMutation(sessionId);
|
|
199
|
+
try {
|
|
200
|
+
const response = await this.sendJsonRpcRequest(DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
201
|
+
const result = mapDocumentReplaceFileResult(response, sessionId);
|
|
202
|
+
if (tracksDirectSession)
|
|
203
|
+
this.settleDocumentRpcMutation(sessionId, 'applied');
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
if (tracksDirectSession) {
|
|
208
|
+
const indeterminate = error instanceof SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
209
|
+
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
210
|
+
}
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
187
215
|
async invokeWhileActive(operation, params, options) {
|
|
188
216
|
const collaborationAuth = options.collaborationAuth === undefined ? undefined : normalizeCollaborationAuth(options.collaborationAuth);
|
|
189
217
|
if (collaborationAuth !== undefined) {
|
|
@@ -282,8 +310,11 @@ export class HostTransport {
|
|
|
282
310
|
details: { operationId: operation.operationId },
|
|
283
311
|
});
|
|
284
312
|
}
|
|
313
|
+
const supportsRequestTimeoutMetadata = this.hostFeatures.has(DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
|
|
285
314
|
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
286
|
-
if (
|
|
315
|
+
if (!supportsRequestTimeoutMetadata &&
|
|
316
|
+
options.timeoutMs !== undefined &&
|
|
317
|
+
options.timeoutMs > cliHostRequestTimeoutMs) {
|
|
287
318
|
throw new SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
288
319
|
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
289
320
|
details: {
|
|
@@ -301,7 +332,9 @@ export class HostTransport {
|
|
|
301
332
|
argv,
|
|
302
333
|
stdinBase64,
|
|
303
334
|
...(collaborationAuth === undefined ? {} : { collaborationAuth }),
|
|
304
|
-
}, watchdogTimeout
|
|
335
|
+
}, watchdogTimeout, {
|
|
336
|
+
requestTimeoutMs: supportsRequestTimeoutMetadata ? options.timeoutMs : undefined,
|
|
337
|
+
});
|
|
305
338
|
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
306
339
|
throw new SuperDocCliError('Host returned invalid cli.invoke result.', {
|
|
307
340
|
code: 'HOST_PROTOCOL_ERROR',
|
package/dist/runtime/process.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var os = require('node:os');
|
|
5
|
+
var path = require('node:path');
|
|
3
6
|
var host = require('./host.cjs');
|
|
4
7
|
var embeddedCli = require('./embedded-cli.cjs');
|
|
5
8
|
var embeddedDocumentHost = require('./embedded-document-host.cjs');
|
|
@@ -88,6 +91,35 @@ class SuperDocRuntime {
|
|
|
88
91
|
throw error;
|
|
89
92
|
}
|
|
90
93
|
}
|
|
94
|
+
async replaceFile(sessionId, source, options = {}) {
|
|
95
|
+
if (typeof source === 'string') {
|
|
96
|
+
if (source.trim().length === 0) {
|
|
97
|
+
throw new errors.SuperDocCliError('replaceFile source path must be non-empty.', { code: 'INVALID_ARGUMENT' });
|
|
98
|
+
}
|
|
99
|
+
return (await this.transport.replaceFile(sessionId, source, options));
|
|
100
|
+
}
|
|
101
|
+
let bytes;
|
|
102
|
+
if (source instanceof Uint8Array) {
|
|
103
|
+
bytes = new Uint8Array(source);
|
|
104
|
+
}
|
|
105
|
+
else if (source instanceof ArrayBuffer) {
|
|
106
|
+
bytes = new Uint8Array(source.slice(0));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
throw new errors.SuperDocCliError('replaceFile source must be a path, Uint8Array, or ArrayBuffer.', {
|
|
110
|
+
code: 'INVALID_ARGUMENT',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const stagingDirectory = await promises.mkdtemp(path.join(os.tmpdir(), 'superdoc-sdk-replace-'));
|
|
114
|
+
const stagedPath = path.join(stagingDirectory, 'replacement.docx');
|
|
115
|
+
try {
|
|
116
|
+
await promises.writeFile(stagedPath, bytes, { mode: 0o600 });
|
|
117
|
+
return (await this.transport.replaceFile(sessionId, stagedPath, options));
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
await promises.rm(stagingDirectory, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
91
123
|
}
|
|
92
124
|
|
|
93
125
|
exports.SuperDocRuntime = SuperDocRuntime;
|
|
@@ -7,6 +7,19 @@ type EmbeddedRuntimeResolvers = {
|
|
|
7
7
|
cli: () => string;
|
|
8
8
|
documentHost: () => string;
|
|
9
9
|
};
|
|
10
|
+
export type ReplaceFileSource = string | Uint8Array | ArrayBuffer;
|
|
11
|
+
export interface ReplaceFileOptions {
|
|
12
|
+
readonly timeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ReplaceFileResult {
|
|
15
|
+
readonly contextId: string;
|
|
16
|
+
readonly runtime: 'v2';
|
|
17
|
+
readonly replaced: true;
|
|
18
|
+
readonly document: {
|
|
19
|
+
readonly byteLength: number;
|
|
20
|
+
readonly revision: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
10
23
|
export declare function resolveRuntimeProcess(options?: SuperDocClientOptions, embedded?: EmbeddedRuntimeResolvers): RuntimeProcessResolution;
|
|
11
24
|
export declare function toSafeInvokeTraceOptions(options: TransportInvokeOptions): InvokeOptions;
|
|
12
25
|
/**
|
|
@@ -21,5 +34,6 @@ export declare class SuperDocRuntime {
|
|
|
21
34
|
connect(): Promise<void>;
|
|
22
35
|
dispose(): Promise<void>;
|
|
23
36
|
invoke<TData = unknown>(operation: OperationSpec, params?: Record<string, unknown>, options?: TransportInvokeOptions): Promise<TData>;
|
|
37
|
+
replaceFile(sessionId: string, source: ReplaceFileSource, options?: ReplaceFileOptions): Promise<ReplaceFileResult>;
|
|
24
38
|
}
|
|
25
39
|
export type { CollaborationAuth, DocumentRuntimeKind, DocOpenOptions, InvokeOptions, OperationParamSpec, OperationSpec, RuntimeInvoker, SuperDocClientOptions, };
|
package/dist/runtime/process.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
1
4
|
import { HostTransport } from './host.js';
|
|
2
5
|
import { resolveEmbeddedCliBinary } from './embedded-cli.js';
|
|
3
6
|
import { resolveEmbeddedDocumentHostBinary } from './embedded-document-host.js';
|
|
@@ -85,4 +88,33 @@ export class SuperDocRuntime {
|
|
|
85
88
|
throw error;
|
|
86
89
|
}
|
|
87
90
|
}
|
|
91
|
+
async replaceFile(sessionId, source, options = {}) {
|
|
92
|
+
if (typeof source === 'string') {
|
|
93
|
+
if (source.trim().length === 0) {
|
|
94
|
+
throw new SuperDocCliError('replaceFile source path must be non-empty.', { code: 'INVALID_ARGUMENT' });
|
|
95
|
+
}
|
|
96
|
+
return (await this.transport.replaceFile(sessionId, source, options));
|
|
97
|
+
}
|
|
98
|
+
let bytes;
|
|
99
|
+
if (source instanceof Uint8Array) {
|
|
100
|
+
bytes = new Uint8Array(source);
|
|
101
|
+
}
|
|
102
|
+
else if (source instanceof ArrayBuffer) {
|
|
103
|
+
bytes = new Uint8Array(source.slice(0));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw new SuperDocCliError('replaceFile source must be a path, Uint8Array, or ArrayBuffer.', {
|
|
107
|
+
code: 'INVALID_ARGUMENT',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const stagingDirectory = await mkdtemp(join(tmpdir(), 'superdoc-sdk-replace-'));
|
|
111
|
+
const stagedPath = join(stagingDirectory, 'replacement.docx');
|
|
112
|
+
try {
|
|
113
|
+
await writeFile(stagedPath, bytes, { mode: 0o600 });
|
|
114
|
+
return (await this.transport.replaceFile(sessionId, stagedPath, options));
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
await rm(stagingDirectory, { recursive: true, force: true });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
88
120
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
// AUTO-GENERATED by scripts/embed-version.mjs — DO NOT EDIT.
|
|
4
4
|
// Source of truth: package.json. Regenerated on every SDK build so the
|
|
5
5
|
// SDK retains its own version identity when bundled into another package.
|
|
6
|
-
const SDK_VERSION = '2.10.0-next.
|
|
6
|
+
const SDK_VERSION = '2.10.0-next.5';
|
|
7
7
|
|
|
8
8
|
exports.SDK_VERSION = SDK_VERSION;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.10.0-next.
|
|
1
|
+
export declare const SDK_VERSION = "2.10.0-next.5";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/embed-version.mjs — DO NOT EDIT.
|
|
2
2
|
// Source of truth: package.json. Regenerated on every SDK build so the
|
|
3
3
|
// SDK retains its own version identity when bundled into another package.
|
|
4
|
-
export const SDK_VERSION = '2.10.0-next.
|
|
4
|
+
export const SDK_VERSION = '2.10.0-next.5';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/sdk",
|
|
3
|
-
"version": "2.10.0-next.
|
|
3
|
+
"version": "2.10.0-next.5",
|
|
4
4
|
"description": "Node SDK for SuperDoc, wrapping the SuperDoc CLI to read and edit .docx files from JavaScript and TypeScript.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"typescript": "^5.9.2"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"@superdoc/sdk-darwin-arm64": "2.10.0-next.
|
|
41
|
-
"@superdoc/sdk-darwin-x64": "2.10.0-next.
|
|
42
|
-
"@superdoc/sdk-linux-x64": "2.10.0-next.
|
|
43
|
-
"@superdoc/sdk-linux-arm64": "2.10.0-next.
|
|
44
|
-
"@superdoc/sdk-windows-x64": "2.10.0-next.
|
|
40
|
+
"@superdoc/sdk-darwin-arm64": "2.10.0-next.5",
|
|
41
|
+
"@superdoc/sdk-darwin-x64": "2.10.0-next.5",
|
|
42
|
+
"@superdoc/sdk-linux-x64": "2.10.0-next.5",
|
|
43
|
+
"@superdoc/sdk-linux-arm64": "2.10.0-next.5",
|
|
44
|
+
"@superdoc/sdk-windows-x64": "2.10.0-next.5"
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"build": "rm -rf dist && node scripts/embed-version.mjs && node scripts/embed-prompts.mjs && node scripts/embed-tools.mjs && tsc && pnpm run typecheck:consumer && rollup -c rollup.cjs.config.mjs && rm -rf dist/prompts && mkdir -p dist/prompts && cp src/prompts/*.md dist/prompts/ && pnpm run audit:publish",
|
|
51
51
|
"audit:publish": "node ../../../../scripts/audit-publish-artifact.mjs dist --label sdk-node-dist",
|
|
52
52
|
"typecheck": "tsc --noEmit",
|
|
53
|
-
"typecheck:consumer": "tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext ../../../../tests/consumer-typecheck/src/sdk-per-open-collaboration-auth.mts",
|
|
53
|
+
"typecheck:consumer": "tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext ../../../../tests/consumer-typecheck/src/sdk-per-open-collaboration-auth.mts ../../../../tests/consumer-typecheck/src/sdk-replace-file.mts",
|
|
54
54
|
"test:document-host": "bun test src/runtime/__tests__/host-spawn-args.test.ts src/runtime/__tests__/document-rpc.test.ts src/__tests__/structured-document-rpc.e2e.test.ts src/__tests__/request-timeout-ms.e2e.test.ts",
|
|
55
55
|
"smoke:product-action": "node scripts/product-action-smoke.mjs"
|
|
56
56
|
}
|