@superdoc-dev/cli 0.2.0-next.52 → 0.2.0-next.54
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/index.js +263 -27
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -8292,6 +8292,16 @@ function normalizeSessionType(value) {
|
|
|
8292
8292
|
return "collab";
|
|
8293
8293
|
return "local";
|
|
8294
8294
|
}
|
|
8295
|
+
function normalizeUser(value) {
|
|
8296
|
+
const record = asRecord(value);
|
|
8297
|
+
if (!record)
|
|
8298
|
+
return;
|
|
8299
|
+
if (typeof record.name !== "string" || record.name.length === 0)
|
|
8300
|
+
return;
|
|
8301
|
+
if (typeof record.email !== "string")
|
|
8302
|
+
return;
|
|
8303
|
+
return { name: record.name, email: record.email };
|
|
8304
|
+
}
|
|
8295
8305
|
function normalizeCollaborationProfile(value) {
|
|
8296
8306
|
const record = asRecord(value);
|
|
8297
8307
|
if (!record)
|
|
@@ -8301,6 +8311,8 @@ function normalizeCollaborationProfile(value) {
|
|
|
8301
8311
|
const documentId = record.documentId;
|
|
8302
8312
|
const tokenEnv = record.tokenEnv;
|
|
8303
8313
|
const syncTimeoutMs = record.syncTimeoutMs;
|
|
8314
|
+
const onMissing = record.onMissing;
|
|
8315
|
+
const bootstrapSettlingMs = record.bootstrapSettlingMs;
|
|
8304
8316
|
if (providerType !== "hocuspocus" && providerType !== "y-websocket")
|
|
8305
8317
|
return;
|
|
8306
8318
|
if (typeof url !== "string" || url.length === 0)
|
|
@@ -8312,28 +8324,39 @@ function normalizeCollaborationProfile(value) {
|
|
|
8312
8324
|
if (syncTimeoutMs != null && (typeof syncTimeoutMs !== "number" || !Number.isFinite(syncTimeoutMs) || syncTimeoutMs <= 0)) {
|
|
8313
8325
|
return;
|
|
8314
8326
|
}
|
|
8327
|
+
if (onMissing != null && onMissing !== "seedFromDoc" && onMissing !== "blank" && onMissing !== "error") {
|
|
8328
|
+
return;
|
|
8329
|
+
}
|
|
8330
|
+
if (bootstrapSettlingMs != null && (typeof bootstrapSettlingMs !== "number" || !Number.isFinite(bootstrapSettlingMs) || bootstrapSettlingMs <= 0)) {
|
|
8331
|
+
return;
|
|
8332
|
+
}
|
|
8315
8333
|
return {
|
|
8316
8334
|
providerType,
|
|
8317
8335
|
url,
|
|
8318
8336
|
documentId,
|
|
8319
8337
|
tokenEnv: typeof tokenEnv === "string" ? tokenEnv : undefined,
|
|
8320
|
-
syncTimeoutMs: typeof syncTimeoutMs === "number" ? syncTimeoutMs : undefined
|
|
8338
|
+
syncTimeoutMs: typeof syncTimeoutMs === "number" ? syncTimeoutMs : undefined,
|
|
8339
|
+
onMissing,
|
|
8340
|
+
bootstrapSettlingMs: typeof bootstrapSettlingMs === "number" ? bootstrapSettlingMs : undefined
|
|
8321
8341
|
};
|
|
8322
8342
|
}
|
|
8323
8343
|
function normalizeContextMetadata(metadata) {
|
|
8324
8344
|
const sessionType = normalizeSessionType(metadata.sessionType);
|
|
8325
8345
|
const collaboration = normalizeCollaborationProfile(metadata.collaboration);
|
|
8346
|
+
const user = normalizeUser(metadata.user);
|
|
8326
8347
|
if (sessionType === "collab" && collaboration) {
|
|
8327
8348
|
return {
|
|
8328
8349
|
...metadata,
|
|
8329
8350
|
sessionType,
|
|
8330
|
-
collaboration
|
|
8351
|
+
collaboration,
|
|
8352
|
+
user
|
|
8331
8353
|
};
|
|
8332
8354
|
}
|
|
8333
8355
|
return {
|
|
8334
8356
|
...metadata,
|
|
8335
8357
|
sessionType: "local",
|
|
8336
|
-
collaboration: undefined
|
|
8358
|
+
collaboration: undefined,
|
|
8359
|
+
user
|
|
8337
8360
|
};
|
|
8338
8361
|
}
|
|
8339
8362
|
function sleep(ms) {
|
|
@@ -8747,6 +8770,7 @@ function createInitialContextMetadata(io, paths, contextId, input) {
|
|
|
8747
8770
|
revision: 0,
|
|
8748
8771
|
sessionType,
|
|
8749
8772
|
collaboration: sessionType === "collab" ? input.collaboration : undefined,
|
|
8773
|
+
user: input.user,
|
|
8750
8774
|
openedAt: timestamp,
|
|
8751
8775
|
updatedAt: timestamp,
|
|
8752
8776
|
sourceSnapshot: input.sourceSnapshot
|
|
@@ -9196,6 +9220,14 @@ var init_cli_only_operation_definitions = __esm(() => {
|
|
|
9196
9220
|
documentId: { type: "string" },
|
|
9197
9221
|
url: { type: "string" }
|
|
9198
9222
|
}
|
|
9223
|
+
},
|
|
9224
|
+
bootstrap: {
|
|
9225
|
+
type: "object",
|
|
9226
|
+
properties: {
|
|
9227
|
+
roomState: { type: "string" },
|
|
9228
|
+
bootstrapApplied: { type: "boolean" },
|
|
9229
|
+
bootstrapSource: { type: "string" }
|
|
9230
|
+
}
|
|
9199
9231
|
}
|
|
9200
9232
|
},
|
|
9201
9233
|
required: ["contextId", "sessionType"]
|
|
@@ -83665,18 +83697,35 @@ function parseCollaborationInput(value) {
|
|
|
83665
83697
|
if ("params" in value) {
|
|
83666
83698
|
throw new CliError("VALIDATION_ERROR", "collaboration.params is not supported in v1.");
|
|
83667
83699
|
}
|
|
83668
|
-
const allowedKeys = new Set([
|
|
83700
|
+
const allowedKeys = new Set([
|
|
83701
|
+
"providerType",
|
|
83702
|
+
"url",
|
|
83703
|
+
"documentId",
|
|
83704
|
+
"tokenEnv",
|
|
83705
|
+
"syncTimeoutMs",
|
|
83706
|
+
"onMissing",
|
|
83707
|
+
"bootstrapSettlingMs"
|
|
83708
|
+
]);
|
|
83669
83709
|
for (const key of Object.keys(value)) {
|
|
83670
83710
|
if (!allowedKeys.has(key)) {
|
|
83671
83711
|
throw new CliError("VALIDATION_ERROR", `collaboration.${key} is not supported.`);
|
|
83672
83712
|
}
|
|
83673
83713
|
}
|
|
83714
|
+
let onMissing;
|
|
83715
|
+
if (value.onMissing != null) {
|
|
83716
|
+
if (value.onMissing !== "seedFromDoc" && value.onMissing !== "blank" && value.onMissing !== "error") {
|
|
83717
|
+
throw new CliError("VALIDATION_ERROR", 'collaboration.onMissing must be "seedFromDoc", "blank", or "error".');
|
|
83718
|
+
}
|
|
83719
|
+
onMissing = value.onMissing;
|
|
83720
|
+
}
|
|
83674
83721
|
return {
|
|
83675
83722
|
providerType: normalizeProviderType(value.providerType, "collaboration.providerType"),
|
|
83676
83723
|
url: expectNonEmptyString(value.url, "collaboration.url").trim(),
|
|
83677
83724
|
documentId: value.documentId != null ? expectNonEmptyString(value.documentId, "collaboration.documentId") : undefined,
|
|
83678
83725
|
tokenEnv: expectOptionalEnvVarName(value.tokenEnv, "collaboration.tokenEnv"),
|
|
83679
|
-
syncTimeoutMs: expectOptionalPositiveNumber(value.syncTimeoutMs, "collaboration.syncTimeoutMs")
|
|
83726
|
+
syncTimeoutMs: expectOptionalPositiveNumber(value.syncTimeoutMs, "collaboration.syncTimeoutMs"),
|
|
83727
|
+
onMissing,
|
|
83728
|
+
bootstrapSettlingMs: expectOptionalPositiveNumber(value.bootstrapSettlingMs, "collaboration.bootstrapSettlingMs")
|
|
83680
83729
|
};
|
|
83681
83730
|
}
|
|
83682
83731
|
function resolveCollaborationProfile(input, sessionId) {
|
|
@@ -83686,7 +83735,9 @@ function resolveCollaborationProfile(input, sessionId) {
|
|
|
83686
83735
|
url: input.url,
|
|
83687
83736
|
documentId,
|
|
83688
83737
|
tokenEnv: input.tokenEnv,
|
|
83689
|
-
syncTimeoutMs: input.syncTimeoutMs
|
|
83738
|
+
syncTimeoutMs: input.syncTimeoutMs,
|
|
83739
|
+
onMissing: input.onMissing,
|
|
83740
|
+
bootstrapSettlingMs: input.bootstrapSettlingMs
|
|
83690
83741
|
};
|
|
83691
83742
|
}
|
|
83692
83743
|
function resolveCollaborationToken(profile) {
|
|
@@ -83786,6 +83837,119 @@ var init_collaboration = __esm(() => {
|
|
|
83786
83837
|
ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
83787
83838
|
});
|
|
83788
83839
|
|
|
83840
|
+
// src/lib/bootstrap.ts
|
|
83841
|
+
function detectRoomState(ydoc) {
|
|
83842
|
+
const fragment = ydoc.getXmlFragment("supereditor");
|
|
83843
|
+
if (fragment.length > 0)
|
|
83844
|
+
return "populated";
|
|
83845
|
+
const metaMap = ydoc.getMap("meta");
|
|
83846
|
+
for (const [key, value] of metaMap.entries()) {
|
|
83847
|
+
if (key === "bootstrap") {
|
|
83848
|
+
const marker = value;
|
|
83849
|
+
if (marker && marker.source !== "pending")
|
|
83850
|
+
return "populated";
|
|
83851
|
+
continue;
|
|
83852
|
+
}
|
|
83853
|
+
return "populated";
|
|
83854
|
+
}
|
|
83855
|
+
return "empty";
|
|
83856
|
+
}
|
|
83857
|
+
function resolveBootstrapDecision(roomState, onMissing, hasDoc) {
|
|
83858
|
+
if (roomState === "populated")
|
|
83859
|
+
return { action: "join" };
|
|
83860
|
+
switch (onMissing) {
|
|
83861
|
+
case "seedFromDoc":
|
|
83862
|
+
return { action: "seed", source: hasDoc ? "doc" : "blank" };
|
|
83863
|
+
case "blank":
|
|
83864
|
+
return { action: "seed", source: "blank" };
|
|
83865
|
+
case "error":
|
|
83866
|
+
return { action: "error", reason: 'Collaboration room is empty and onMissing is set to "error".' };
|
|
83867
|
+
}
|
|
83868
|
+
}
|
|
83869
|
+
function writeBootstrapMarker(ydoc, source) {
|
|
83870
|
+
const metaMap = ydoc.getMap("meta");
|
|
83871
|
+
const marker = {
|
|
83872
|
+
version: 1,
|
|
83873
|
+
clientId: ydoc.clientID,
|
|
83874
|
+
seededAt: new Date().toISOString(),
|
|
83875
|
+
source
|
|
83876
|
+
};
|
|
83877
|
+
metaMap.set("bootstrap", marker);
|
|
83878
|
+
}
|
|
83879
|
+
function readBootstrapMarker(ydoc) {
|
|
83880
|
+
return ydoc.getMap("meta").get("bootstrap");
|
|
83881
|
+
}
|
|
83882
|
+
function snapshotCompetitor(marker) {
|
|
83883
|
+
return {
|
|
83884
|
+
observedOtherClientId: marker.clientId,
|
|
83885
|
+
observedSource: marker.source,
|
|
83886
|
+
observedAt: new Date().toISOString()
|
|
83887
|
+
};
|
|
83888
|
+
}
|
|
83889
|
+
function observeCompetitor(ydoc) {
|
|
83890
|
+
const myClientId = ydoc.clientID;
|
|
83891
|
+
const metaMap = ydoc.getMap("meta");
|
|
83892
|
+
let competitor = null;
|
|
83893
|
+
const handler2 = (event) => {
|
|
83894
|
+
if (!event.keysChanged.has("bootstrap"))
|
|
83895
|
+
return;
|
|
83896
|
+
const marker = metaMap.get("bootstrap");
|
|
83897
|
+
if (marker && marker.clientId !== myClientId && !competitor) {
|
|
83898
|
+
competitor = snapshotCompetitor(marker);
|
|
83899
|
+
}
|
|
83900
|
+
};
|
|
83901
|
+
metaMap.observe(handler2);
|
|
83902
|
+
return {
|
|
83903
|
+
getCompetitor: () => competitor,
|
|
83904
|
+
dispose: () => metaMap.unobserve(handler2)
|
|
83905
|
+
};
|
|
83906
|
+
}
|
|
83907
|
+
function sleep2(ms) {
|
|
83908
|
+
if (ms <= 0)
|
|
83909
|
+
return Promise.resolve();
|
|
83910
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
83911
|
+
}
|
|
83912
|
+
async function claimBootstrap(ydoc, settlingMs, jitterMs = DEFAULT_BOOTSTRAP_JITTER_MS) {
|
|
83913
|
+
await sleep2(Math.floor(Math.random() * jitterMs));
|
|
83914
|
+
const metaMap = ydoc.getMap("meta");
|
|
83915
|
+
metaMap.set("bootstrap", {
|
|
83916
|
+
version: 1,
|
|
83917
|
+
clientId: ydoc.clientID,
|
|
83918
|
+
seededAt: new Date().toISOString(),
|
|
83919
|
+
source: "pending"
|
|
83920
|
+
});
|
|
83921
|
+
const observer = observeCompetitor(ydoc);
|
|
83922
|
+
try {
|
|
83923
|
+
await sleep2(settlingMs);
|
|
83924
|
+
const competitor = observer.getCompetitor();
|
|
83925
|
+
if (competitor)
|
|
83926
|
+
return { granted: false, competitor };
|
|
83927
|
+
const marker = readBootstrapMarker(ydoc);
|
|
83928
|
+
if (marker?.clientId === ydoc.clientID) {
|
|
83929
|
+
return { granted: true };
|
|
83930
|
+
}
|
|
83931
|
+
return {
|
|
83932
|
+
granted: false,
|
|
83933
|
+
competitor: marker ? snapshotCompetitor(marker) : { observedOtherClientId: 0, observedSource: "unknown", observedAt: new Date().toISOString() }
|
|
83934
|
+
};
|
|
83935
|
+
} finally {
|
|
83936
|
+
observer.dispose();
|
|
83937
|
+
}
|
|
83938
|
+
}
|
|
83939
|
+
async function detectBootstrapRace(ydoc, observeMs = POST_SEED_OBSERVE_MS) {
|
|
83940
|
+
const observer = observeCompetitor(ydoc);
|
|
83941
|
+
try {
|
|
83942
|
+
await sleep2(observeMs);
|
|
83943
|
+
const competitor = observer.getCompetitor();
|
|
83944
|
+
if (competitor)
|
|
83945
|
+
return { raceSuspected: true, competitor };
|
|
83946
|
+
return { raceSuspected: false };
|
|
83947
|
+
} finally {
|
|
83948
|
+
observer.dispose();
|
|
83949
|
+
}
|
|
83950
|
+
}
|
|
83951
|
+
var DEFAULT_BOOTSTRAP_SETTLING_MS = 1500, DEFAULT_BOOTSTRAP_JITTER_MS = 150, POST_SEED_OBSERVE_MS = 200;
|
|
83952
|
+
|
|
83789
83953
|
// src/lib/document.ts
|
|
83790
83954
|
import { readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
83791
83955
|
import { createHash as createHash2 } from "node:crypto";
|
|
@@ -83879,10 +84043,11 @@ async function openDocument(doc, io, options = {}) {
|
|
|
83879
84043
|
const isTest = false;
|
|
83880
84044
|
editor = await EditorRuntime.open(Buffer.from(source), {
|
|
83881
84045
|
documentId: options.documentId ?? meta.path ?? "blank.docx",
|
|
83882
|
-
user: { id: "cli", name: "CLI" },
|
|
84046
|
+
user: options.user ? { name: options.user.name, email: options.user.email, image: null } : { id: "cli", name: "CLI" },
|
|
83883
84047
|
...isTest ? { telemetry: { enabled: false } } : {},
|
|
83884
84048
|
ydoc: options.ydoc,
|
|
83885
84049
|
...options.collaborationProvider != null ? { collaborationProvider: options.collaborationProvider } : {},
|
|
84050
|
+
...options.isNewFile != null ? { isNewFile: options.isNewFile } : {},
|
|
83886
84051
|
...passThroughEditorOpts
|
|
83887
84052
|
});
|
|
83888
84053
|
} catch (error) {
|
|
@@ -83939,18 +84104,48 @@ async function openDocument(doc, io, options = {}) {
|
|
|
83939
84104
|
}
|
|
83940
84105
|
};
|
|
83941
84106
|
}
|
|
83942
|
-
async function openCollaborativeDocument(doc, io, profile) {
|
|
84107
|
+
async function openCollaborativeDocument(doc, io, profile, options = {}) {
|
|
83943
84108
|
const runtime = createCollaborationRuntime(profile);
|
|
83944
84109
|
try {
|
|
83945
84110
|
await runtime.waitForSync();
|
|
83946
|
-
const
|
|
84111
|
+
const onMissing = profile.onMissing ?? "seedFromDoc";
|
|
84112
|
+
let finalRoomState = detectRoomState(runtime.ydoc);
|
|
84113
|
+
let decision = resolveBootstrapDecision(finalRoomState, onMissing, doc != null);
|
|
84114
|
+
if (decision.action === "seed") {
|
|
84115
|
+
const claim = await claimBootstrap(runtime.ydoc, profile.bootstrapSettlingMs ?? DEFAULT_BOOTSTRAP_SETTLING_MS);
|
|
84116
|
+
if (!claim.granted) {
|
|
84117
|
+
finalRoomState = detectRoomState(runtime.ydoc);
|
|
84118
|
+
decision = { action: "join" };
|
|
84119
|
+
}
|
|
84120
|
+
}
|
|
84121
|
+
if (decision.action === "error") {
|
|
84122
|
+
throw new CliError("COLLABORATION_ROOM_EMPTY", decision.reason);
|
|
84123
|
+
}
|
|
84124
|
+
const shouldSeed = decision.action === "seed";
|
|
84125
|
+
const docForEditor = shouldSeed ? doc : undefined;
|
|
84126
|
+
const opened = await openDocument(docForEditor, io, {
|
|
83947
84127
|
documentId: profile.documentId,
|
|
83948
84128
|
ydoc: runtime.ydoc,
|
|
83949
|
-
collaborationProvider: runtime.provider
|
|
84129
|
+
collaborationProvider: runtime.provider,
|
|
84130
|
+
isNewFile: shouldSeed,
|
|
84131
|
+
user: options.user
|
|
83950
84132
|
});
|
|
84133
|
+
let raceDetection;
|
|
84134
|
+
if (shouldSeed) {
|
|
84135
|
+
writeBootstrapMarker(runtime.ydoc, decision.source);
|
|
84136
|
+
raceDetection = await detectBootstrapRace(runtime.ydoc);
|
|
84137
|
+
}
|
|
84138
|
+
const bootstrap = {
|
|
84139
|
+
roomState: finalRoomState,
|
|
84140
|
+
bootstrapApplied: shouldSeed,
|
|
84141
|
+
bootstrapSource: shouldSeed ? decision.source : undefined,
|
|
84142
|
+
raceSuspected: raceDetection?.raceSuspected,
|
|
84143
|
+
raceCompetitor: raceDetection?.raceSuspected ? raceDetection.competitor : undefined
|
|
84144
|
+
};
|
|
83951
84145
|
return {
|
|
83952
84146
|
editor: opened.editor,
|
|
83953
84147
|
meta: opened.meta,
|
|
84148
|
+
bootstrap,
|
|
83954
84149
|
dispose() {
|
|
83955
84150
|
try {
|
|
83956
84151
|
opened.dispose();
|
|
@@ -83966,7 +84161,7 @@ async function openCollaborativeDocument(doc, io, profile) {
|
|
|
83966
84161
|
}
|
|
83967
84162
|
async function openSessionDocument(doc, io, metadata, options = {}) {
|
|
83968
84163
|
if (metadata.sessionType !== "collab") {
|
|
83969
|
-
return openDocument(doc, io);
|
|
84164
|
+
return openDocument(doc, io, { user: metadata.user });
|
|
83970
84165
|
}
|
|
83971
84166
|
if (!metadata.collaboration) {
|
|
83972
84167
|
throw new CliError("COMMAND_FAILED", "Session is marked as collaborative but has no collaboration profile.");
|
|
@@ -83981,11 +84176,12 @@ async function openSessionDocument(doc, io, metadata, options = {}) {
|
|
|
83981
84176
|
sessionType: metadata.sessionType,
|
|
83982
84177
|
collaboration: metadata.collaboration,
|
|
83983
84178
|
sourcePath: metadata.sourcePath,
|
|
83984
|
-
workingDocPath: metadata.workingDocPath
|
|
84179
|
+
workingDocPath: metadata.workingDocPath,
|
|
84180
|
+
user: metadata.user
|
|
83985
84181
|
};
|
|
83986
84182
|
return options.collabSessionPool.acquire(sessionId, doc, metadataForPool, io);
|
|
83987
84183
|
}
|
|
83988
|
-
return openCollaborativeDocument(doc, io, metadata.collaboration);
|
|
84184
|
+
return openCollaborativeDocument(doc, io, metadata.collaboration, { user: metadata.user });
|
|
83989
84185
|
}
|
|
83990
84186
|
async function getFileChecksum(path2) {
|
|
83991
84187
|
let bytes;
|
|
@@ -85445,7 +85641,7 @@ async function executeReadOperation(request) {
|
|
|
85445
85641
|
opened2.dispose();
|
|
85446
85642
|
}
|
|
85447
85643
|
}
|
|
85448
|
-
const opened = await openDocument(paths.workingDocPath, context.io);
|
|
85644
|
+
const opened = await openDocument(paths.workingDocPath, context.io, { user: metadata.user });
|
|
85449
85645
|
try {
|
|
85450
85646
|
const result = invokeOperation(opened.editor, operationId, input);
|
|
85451
85647
|
const document4 = {
|
|
@@ -85635,7 +85831,7 @@ async function executeMutationOperation(request) {
|
|
|
85635
85831
|
opened2.dispose();
|
|
85636
85832
|
}
|
|
85637
85833
|
}
|
|
85638
|
-
const opened = await openDocument(paths.workingDocPath, context.io);
|
|
85834
|
+
const opened = await openDocument(paths.workingDocPath, context.io, { user: metadata.user });
|
|
85639
85835
|
try {
|
|
85640
85836
|
const result = invokeOperation2(opened.editor, operationId, input, invokeOptions);
|
|
85641
85837
|
const document4 = {
|
|
@@ -86344,7 +86540,7 @@ function deriveOptionSpecs(params3) {
|
|
|
86344
86540
|
}
|
|
86345
86541
|
return specs;
|
|
86346
86542
|
}
|
|
86347
|
-
var DOC_PARAM, SESSION_PARAM, OUT_PARAM, FORCE_PARAM, DRY_RUN_PARAM, CHANGE_MODE_PARAM, EXPECTED_REVISION_PARAM, AGENT_HIDDEN_PARAM_NAMES, OPERATION_CONSTRAINTS, PARAM_FLAG_OVERRIDES, PARAM_SCHEMA_OVERRIDES, PARAM_EXCLUSIONS, TEXT_TARGET_FLAT_PARAMS, INSERT_FLAT_PARAMS, LIST_TARGET_FLAT_PARAMS, FORMAT_OPERATION_IDS, EXTRA_CLI_PARAMS, CLI_ONLY_METADATA, CLI_OPERATION_METADATA, CLI_OPERATION_OPTION_SPECS;
|
|
86543
|
+
var DOC_PARAM, SESSION_PARAM, OUT_PARAM, FORCE_PARAM, DRY_RUN_PARAM, CHANGE_MODE_PARAM, EXPECTED_REVISION_PARAM, USER_NAME_PARAM, USER_EMAIL_PARAM, AGENT_HIDDEN_PARAM_NAMES, OPERATION_CONSTRAINTS, PARAM_FLAG_OVERRIDES, PARAM_SCHEMA_OVERRIDES, PARAM_EXCLUSIONS, TEXT_TARGET_FLAT_PARAMS, INSERT_FLAT_PARAMS, LIST_TARGET_FLAT_PARAMS, FORMAT_OPERATION_IDS, EXTRA_CLI_PARAMS, CLI_ONLY_METADATA, CLI_OPERATION_METADATA, CLI_OPERATION_OPTION_SPECS;
|
|
86348
86544
|
var init_operation_params = __esm(() => {
|
|
86349
86545
|
init_src();
|
|
86350
86546
|
init_operation_set();
|
|
@@ -86375,6 +86571,18 @@ var init_operation_params = __esm(() => {
|
|
|
86375
86571
|
type: "number",
|
|
86376
86572
|
agentVisible: false
|
|
86377
86573
|
};
|
|
86574
|
+
USER_NAME_PARAM = {
|
|
86575
|
+
name: "userName",
|
|
86576
|
+
kind: "flag",
|
|
86577
|
+
flag: "user-name",
|
|
86578
|
+
type: "string"
|
|
86579
|
+
};
|
|
86580
|
+
USER_EMAIL_PARAM = {
|
|
86581
|
+
name: "userEmail",
|
|
86582
|
+
kind: "flag",
|
|
86583
|
+
flag: "user-email",
|
|
86584
|
+
type: "string"
|
|
86585
|
+
};
|
|
86378
86586
|
AGENT_HIDDEN_PARAM_NAMES = new Set(["out", "expectedRevision", "changeMode", "dryRun"]);
|
|
86379
86587
|
OPERATION_CONSTRAINTS = {
|
|
86380
86588
|
"doc.find": {
|
|
@@ -86501,7 +86709,11 @@ var init_operation_params = __esm(() => {
|
|
|
86501
86709
|
{ name: "collabDocumentId", kind: "flag", flag: "collab-document-id", type: "string" },
|
|
86502
86710
|
{ name: "collabUrl", kind: "flag", flag: "collab-url", type: "string" },
|
|
86503
86711
|
{ name: "contentOverride", kind: "flag", flag: "content-override", type: "string" },
|
|
86504
|
-
{ name: "overrideType", kind: "flag", flag: "override-type", type: "string" }
|
|
86712
|
+
{ name: "overrideType", kind: "flag", flag: "override-type", type: "string" },
|
|
86713
|
+
{ name: "onMissing", kind: "flag", flag: "on-missing", type: "string" },
|
|
86714
|
+
{ name: "bootstrapSettlingMs", kind: "flag", flag: "bootstrap-settling-ms", type: "number" },
|
|
86715
|
+
USER_NAME_PARAM,
|
|
86716
|
+
USER_EMAIL_PARAM
|
|
86505
86717
|
],
|
|
86506
86718
|
constraints: null
|
|
86507
86719
|
},
|
|
@@ -87800,6 +88012,10 @@ async function runOpen(tokens, context) {
|
|
|
87800
88012
|
const collabDocumentId = getStringOption(parsed, "collab-document-id");
|
|
87801
88013
|
const contentOverride = getStringOption(parsed, "content-override");
|
|
87802
88014
|
const overrideType = getStringOption(parsed, "override-type");
|
|
88015
|
+
const onMissing = getStringOption(parsed, "on-missing");
|
|
88016
|
+
const bootstrapSettlingMs = getNumberOption(parsed, "bootstrap-settling-ms");
|
|
88017
|
+
const userName = getStringOption(parsed, "user-name");
|
|
88018
|
+
const userEmail = getStringOption(parsed, "user-email");
|
|
87803
88019
|
if (contentOverride != null && !overrideType) {
|
|
87804
88020
|
throw new CliError("INVALID_ARGUMENT", "open: --content-override requires --override-type.");
|
|
87805
88021
|
}
|
|
@@ -87809,6 +88025,9 @@ async function runOpen(tokens, context) {
|
|
|
87809
88025
|
if (overrideType && !VALID_OVERRIDE_TYPES.has(overrideType)) {
|
|
87810
88026
|
throw new CliError("INVALID_ARGUMENT", `open: --override-type must be one of: markdown, html, text. Got "${overrideType}".`);
|
|
87811
88027
|
}
|
|
88028
|
+
if (onMissing != null && !VALID_ON_MISSING.has(onMissing)) {
|
|
88029
|
+
throw new CliError("INVALID_ARGUMENT", `open: --on-missing must be one of: seedFromDoc, blank, error. Got "${onMissing}".`);
|
|
88030
|
+
}
|
|
87812
88031
|
if (collaborationPayload != null && (collabUrl || collabDocumentId)) {
|
|
87813
88032
|
throw new CliError("INVALID_ARGUMENT", "open: do not combine --collaboration-json with --collab-url / --collab-document-id.");
|
|
87814
88033
|
}
|
|
@@ -87817,18 +88036,32 @@ async function runOpen(tokens, context) {
|
|
|
87817
88036
|
}
|
|
87818
88037
|
let collaborationInput;
|
|
87819
88038
|
if (collaborationPayload != null) {
|
|
87820
|
-
|
|
88039
|
+
if (typeof collaborationPayload !== "object" || Array.isArray(collaborationPayload)) {
|
|
88040
|
+
throw new CliError("VALIDATION_ERROR", "open: --collaboration-json must be a JSON object.");
|
|
88041
|
+
}
|
|
88042
|
+
const payload = collaborationPayload;
|
|
88043
|
+
if (onMissing != null && !("onMissing" in payload))
|
|
88044
|
+
payload.onMissing = onMissing;
|
|
88045
|
+
if (bootstrapSettlingMs != null && !("bootstrapSettlingMs" in payload))
|
|
88046
|
+
payload.bootstrapSettlingMs = bootstrapSettlingMs;
|
|
88047
|
+
collaborationInput = parseCollaborationInput(payload);
|
|
87821
88048
|
} else if (collabUrl) {
|
|
87822
88049
|
collaborationInput = parseCollaborationInput({
|
|
87823
88050
|
providerType: "hocuspocus",
|
|
87824
88051
|
url: collabUrl,
|
|
87825
|
-
documentId: collabDocumentId
|
|
88052
|
+
documentId: collabDocumentId,
|
|
88053
|
+
...onMissing != null ? { onMissing } : {},
|
|
88054
|
+
...bootstrapSettlingMs != null ? { bootstrapSettlingMs } : {}
|
|
87826
88055
|
});
|
|
87827
88056
|
} else if (collabDocumentId) {
|
|
87828
88057
|
throw new CliError("MISSING_REQUIRED", "open: --collab-document-id requires --collab-url.");
|
|
87829
88058
|
}
|
|
87830
88059
|
const collaboration = collaborationInput ? resolveCollaborationProfile(collaborationInput, sessionId) : undefined;
|
|
87831
88060
|
const sessionType = collaboration ? "collab" : "local";
|
|
88061
|
+
if (!collaboration && (onMissing != null || bootstrapSettlingMs != null)) {
|
|
88062
|
+
throw new CliError("INVALID_ARGUMENT", "open: --on-missing and --bootstrap-settling-ms require collaboration mode (--collaboration-json or --collab-url).");
|
|
88063
|
+
}
|
|
88064
|
+
const user = userName != null || userEmail != null ? { name: userName ?? "CLI", email: userEmail ?? "" } : undefined;
|
|
87832
88065
|
const editorOpenOptions = {};
|
|
87833
88066
|
if (contentOverride != null && overrideType) {
|
|
87834
88067
|
if (overrideType === "markdown") {
|
|
@@ -87854,10 +88087,8 @@ async function runOpen(tokens, context) {
|
|
|
87854
88087
|
revision: existing.revision
|
|
87855
88088
|
});
|
|
87856
88089
|
}
|
|
87857
|
-
|
|
87858
|
-
|
|
87859
|
-
}
|
|
87860
|
-
const opened = collaboration ? await openCollaborativeDocument(doc, context.io, collaboration) : await openDocument(doc, context.io, { editorOpenOptions });
|
|
88090
|
+
const opened = collaboration ? await openCollaborativeDocument(doc, context.io, collaboration, { user }) : await openDocument(doc, context.io, { editorOpenOptions, user });
|
|
88091
|
+
const bootstrap = "bootstrap" in opened ? opened.bootstrap : undefined;
|
|
87861
88092
|
let adoptedToHostPool = false;
|
|
87862
88093
|
try {
|
|
87863
88094
|
const output = await exportToPath(opened.editor, paths.workingDocPath, true);
|
|
@@ -87868,7 +88099,8 @@ async function runOpen(tokens, context) {
|
|
|
87868
88099
|
sourcePath,
|
|
87869
88100
|
sourceSnapshot,
|
|
87870
88101
|
sessionType,
|
|
87871
|
-
collaboration
|
|
88102
|
+
collaboration,
|
|
88103
|
+
user
|
|
87872
88104
|
});
|
|
87873
88105
|
await writeContextMetadata(paths, metadata);
|
|
87874
88106
|
await setActiveSessionId(metadata.contextId);
|
|
@@ -87890,6 +88122,7 @@ async function runOpen(tokens, context) {
|
|
|
87890
88122
|
dirty: metadata.dirty,
|
|
87891
88123
|
sessionType: metadata.sessionType,
|
|
87892
88124
|
collaboration: metadata.collaboration,
|
|
88125
|
+
bootstrap,
|
|
87893
88126
|
openedAt: metadata.openedAt,
|
|
87894
88127
|
updatedAt: metadata.updatedAt
|
|
87895
88128
|
},
|
|
@@ -87902,7 +88135,7 @@ async function runOpen(tokens, context) {
|
|
|
87902
88135
|
}
|
|
87903
88136
|
}, undefined, sessionId);
|
|
87904
88137
|
}
|
|
87905
|
-
var VALID_OVERRIDE_TYPES;
|
|
88138
|
+
var VALID_OVERRIDE_TYPES, VALID_ON_MISSING;
|
|
87906
88139
|
var init_open = __esm(() => {
|
|
87907
88140
|
init_args();
|
|
87908
88141
|
init_collaboration();
|
|
@@ -87912,6 +88145,7 @@ var init_open = __esm(() => {
|
|
|
87912
88145
|
init_operation_args();
|
|
87913
88146
|
init_session();
|
|
87914
88147
|
VALID_OVERRIDE_TYPES = new Set(["markdown", "html", "text"]);
|
|
88148
|
+
VALID_ON_MISSING = new Set(["seedFromDoc", "blank", "error"]);
|
|
87915
88149
|
});
|
|
87916
88150
|
|
|
87917
88151
|
// src/commands/save.ts
|
|
@@ -94374,7 +94608,9 @@ function profileToKey(profile) {
|
|
|
94374
94608
|
url: profile.url,
|
|
94375
94609
|
documentId: profile.documentId,
|
|
94376
94610
|
tokenEnv: profile.tokenEnv ?? null,
|
|
94377
|
-
syncTimeoutMs: profile.syncTimeoutMs ?? null
|
|
94611
|
+
syncTimeoutMs: profile.syncTimeoutMs ?? null,
|
|
94612
|
+
onMissing: profile.onMissing ?? null,
|
|
94613
|
+
bootstrapSettlingMs: profile.bootstrapSettlingMs ?? null
|
|
94378
94614
|
});
|
|
94379
94615
|
}
|
|
94380
94616
|
function buildFingerprint(metadata) {
|
|
@@ -94417,7 +94653,7 @@ class InMemoryCollaborationSessionPool {
|
|
|
94417
94653
|
await this.disposeSession(sessionId);
|
|
94418
94654
|
}
|
|
94419
94655
|
const profile = metadata.collaboration;
|
|
94420
|
-
const opened = await this.openCollaborative(docPath, io, profile);
|
|
94656
|
+
const opened = await this.openCollaborative(docPath, io, profile, { user: metadata.user });
|
|
94421
94657
|
const created = {
|
|
94422
94658
|
opened,
|
|
94423
94659
|
fingerprint,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc-dev/cli",
|
|
3
|
-
"version": "0.2.0-next.
|
|
3
|
+
"version": "0.2.0-next.54",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"superdoc": "./dist/index.js"
|
|
@@ -20,20 +20,20 @@
|
|
|
20
20
|
"@types/node": "22.19.2",
|
|
21
21
|
"typescript": "^5.9.2",
|
|
22
22
|
"@superdoc/document-api": "0.0.1",
|
|
23
|
-
"superdoc": "1.16.0",
|
|
24
23
|
"@superdoc/super-editor": "0.0.1",
|
|
25
|
-
"@superdoc/pm-adapter": "0.0.0"
|
|
24
|
+
"@superdoc/pm-adapter": "0.0.0",
|
|
25
|
+
"superdoc": "1.16.0"
|
|
26
26
|
},
|
|
27
27
|
"module": "src/index.ts",
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"optionalDependencies": {
|
|
32
|
-
"@superdoc-dev/cli-darwin-arm64": "0.2.0-next.
|
|
33
|
-
"@superdoc-dev/cli-darwin-x64": "0.2.0-next.
|
|
34
|
-
"@superdoc-dev/cli-linux-
|
|
35
|
-
"@superdoc-dev/cli-windows-x64": "0.2.0-next.
|
|
36
|
-
"@superdoc-dev/cli-linux-
|
|
32
|
+
"@superdoc-dev/cli-darwin-arm64": "0.2.0-next.54",
|
|
33
|
+
"@superdoc-dev/cli-darwin-x64": "0.2.0-next.54",
|
|
34
|
+
"@superdoc-dev/cli-linux-x64": "0.2.0-next.54",
|
|
35
|
+
"@superdoc-dev/cli-windows-x64": "0.2.0-next.54",
|
|
36
|
+
"@superdoc-dev/cli-linux-arm64": "0.2.0-next.54"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"dev": "bun run src/index.ts",
|