@neocompose/cli 0.11.0 → 0.11.1
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/CHANGELOG.md +12 -0
- package/dist/neo.mjs +874 -144
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.1] - 2026-07-27
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Show push preparation and file-upload progress immediately after confirmation,
|
|
8
|
+
validate trusted lowering before uploading bytes, and batch presigning with
|
|
9
|
+
bounded concurrent transfers, request deadlines, retries, and cancellation.
|
|
10
|
+
- Preserve inherited numeric settings when lowering newly authored member
|
|
11
|
+
overrides, preventing trusted-lowering rejection after file staging.
|
|
12
|
+
- Report the first divergent trusted-lowering field when a source commit is
|
|
13
|
+
rejected instead of only identifying the affected record.
|
|
14
|
+
|
|
3
15
|
## [0.11.0] - 2026-07-27
|
|
4
16
|
|
|
5
17
|
### Added
|
package/dist/neo.mjs
CHANGED
|
@@ -11837,12 +11837,13 @@ var init_project_source_parser = __esm({
|
|
|
11837
11837
|
});
|
|
11838
11838
|
|
|
11839
11839
|
// ../packages/neoscript-language/src/project-schema-contract.generated.ts
|
|
11840
|
-
var PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION, PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION, NEO_PROJECT_SOURCE_RECORD_CONTRACT;
|
|
11840
|
+
var PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION, PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION, PROJECT_FILE_UPLOAD_BATCH_SIZE, NEO_PROJECT_SOURCE_RECORD_CONTRACT;
|
|
11841
11841
|
var init_project_schema_contract_generated = __esm({
|
|
11842
11842
|
"../packages/neoscript-language/src/project-schema-contract.generated.ts"() {
|
|
11843
11843
|
"use strict";
|
|
11844
11844
|
PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION = 3;
|
|
11845
11845
|
PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "3.5";
|
|
11846
|
+
PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
|
|
11846
11847
|
NEO_PROJECT_SOURCE_RECORD_CONTRACT = {
|
|
11847
11848
|
"recordFields": {
|
|
11848
11849
|
"member": [
|
|
@@ -19507,8 +19508,8 @@ function memberSymbol(member, schemaKey, environment, field) {
|
|
|
19507
19508
|
`${field}.source`
|
|
19508
19509
|
);
|
|
19509
19510
|
const overrideOf = nullableString(member.overrideOf, `${field}.overrideOf`);
|
|
19510
|
-
const
|
|
19511
|
-
const inheritedOwner =
|
|
19511
|
+
const inheritedMember2 = overrideOf ? environment.members.get(overrideOf) : void 0;
|
|
19512
|
+
const inheritedOwner = inheritedMember2 ? optionalRecord(inheritedMember2.owner) : void 0;
|
|
19512
19513
|
const inheritedTypeId = inheritedOwner?.kind === "classMember" && typeof inheritedOwner.classId === "string" ? inheritedOwner.classId : void 0;
|
|
19513
19514
|
const inheritedType = inheritedTypeId ? environment.classes.get(inheritedTypeId) : void 0;
|
|
19514
19515
|
const common = {
|
|
@@ -29260,6 +29261,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
29260
29261
|
const fieldType = partial ? requiredTypeArgument(declaration.type, 0) : declaration.type;
|
|
29261
29262
|
const storedStatic = declaration.modifiers.includes("static") && !declaration.modifiers.includes("readonly");
|
|
29262
29263
|
const settings = annotation(declaration.annotations, "settings");
|
|
29264
|
+
const inherited = inheritedMember(context, commonInput.overrideOf);
|
|
29263
29265
|
const storesSelectionArray = context.enumIdsByName.has(fieldType.name) || fieldType.name === "Dialogue" || Boolean(settings && argument(settings, "collection"));
|
|
29264
29266
|
const common = {
|
|
29265
29267
|
...commonInput,
|
|
@@ -29291,11 +29293,12 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
29291
29293
|
return { ...common, kind: name };
|
|
29292
29294
|
}
|
|
29293
29295
|
if (name === "int") {
|
|
29296
|
+
const inheritedInt = inherited?.kind === "int" ? inherited : void 0;
|
|
29294
29297
|
return {
|
|
29295
29298
|
...common,
|
|
29296
29299
|
kind: "int",
|
|
29297
|
-
min: numberArgument(settings, "min"),
|
|
29298
|
-
max: numberArgument(settings, "max")
|
|
29300
|
+
min: numberArgument(settings, "min") ?? inheritedInt?.min ?? null,
|
|
29301
|
+
max: numberArgument(settings, "max") ?? inheritedInt?.max ?? null
|
|
29299
29302
|
};
|
|
29300
29303
|
}
|
|
29301
29304
|
if (name === "string") {
|
|
@@ -29310,20 +29313,24 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
29310
29313
|
const min = numberTextArgument(settings, "min");
|
|
29311
29314
|
const max = numberTextArgument(settings, "max");
|
|
29312
29315
|
if (name === "decimal") {
|
|
29316
|
+
const inheritedDecimal = inherited?.kind === "decimal" ? inherited : void 0;
|
|
29313
29317
|
return {
|
|
29314
29318
|
...common,
|
|
29315
29319
|
kind: "decimal",
|
|
29316
|
-
min,
|
|
29317
|
-
max,
|
|
29318
|
-
decimalPoints: numberArgument(settings, "decimalPoints")
|
|
29320
|
+
min: min ?? inheritedDecimal?.min ?? null,
|
|
29321
|
+
max: max ?? inheritedDecimal?.max ?? null,
|
|
29322
|
+
decimalPoints: numberArgument(settings, "decimalPoints") ?? inheritedDecimal?.decimalPoints ?? null
|
|
29319
29323
|
};
|
|
29320
29324
|
}
|
|
29325
|
+
const inheritedFloat = inherited?.kind === "float" ? inherited : void 0;
|
|
29326
|
+
const numericMin = min === null ? null : Number(min);
|
|
29327
|
+
const numericMax = max === null ? null : Number(max);
|
|
29321
29328
|
return {
|
|
29322
29329
|
...common,
|
|
29323
29330
|
kind: "float",
|
|
29324
|
-
min:
|
|
29325
|
-
max:
|
|
29326
|
-
decimalPoints: numberArgument(settings, "decimalPoints")
|
|
29331
|
+
min: numericMin ?? inheritedFloat?.min ?? null,
|
|
29332
|
+
max: numericMax ?? inheritedFloat?.max ?? null,
|
|
29333
|
+
decimalPoints: numberArgument(settings, "decimalPoints") ?? inheritedFloat?.decimalPoints ?? null
|
|
29327
29334
|
};
|
|
29328
29335
|
}
|
|
29329
29336
|
const primitive3 = primitiveMemberKind(name);
|
|
@@ -29443,6 +29450,10 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
29443
29450
|
`Unsupported field type ${JSON.stringify(name)} on ${ownerClass.name}.${declaration.name}.`
|
|
29444
29451
|
);
|
|
29445
29452
|
}
|
|
29453
|
+
function inheritedMember(context, memberId) {
|
|
29454
|
+
if (memberId === null) return void 0;
|
|
29455
|
+
return context.loweredMembers.get(memberId) ?? context.baseMembers.get(memberId);
|
|
29456
|
+
}
|
|
29446
29457
|
function lowerListIndexes(ownerClass, declaration) {
|
|
29447
29458
|
const declared = /* @__PURE__ */ new Set();
|
|
29448
29459
|
return declaration.annotations.filter((entry) => entry.name === "index").map((entry) => {
|
|
@@ -51477,7 +51488,7 @@ var init_http = __esm({
|
|
|
51477
51488
|
}
|
|
51478
51489
|
return new _NeoApiClient(apiBaseUrl, token);
|
|
51479
51490
|
}
|
|
51480
|
-
async post(path, body, headers) {
|
|
51491
|
+
async post(path, body, headers, options = {}) {
|
|
51481
51492
|
const url = new URL(path, this.apiBaseUrl).toString();
|
|
51482
51493
|
const response = await fetch(url, {
|
|
51483
51494
|
method: "POST",
|
|
@@ -51486,7 +51497,8 @@ var init_http = __esm({
|
|
|
51486
51497
|
"Content-Type": "application/json",
|
|
51487
51498
|
...headers
|
|
51488
51499
|
},
|
|
51489
|
-
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
51500
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
51501
|
+
signal: options.signal
|
|
51490
51502
|
});
|
|
51491
51503
|
const text = await response.text();
|
|
51492
51504
|
let parsed = null;
|
|
@@ -59572,13 +59584,13 @@ function ownedObjectChildMember(row, sourceMember, key, ctx) {
|
|
|
59572
59584
|
return memberForCustomSchemaValue(classId, key, ctx);
|
|
59573
59585
|
}
|
|
59574
59586
|
function freshCloneValueId() {
|
|
59575
|
-
const
|
|
59576
|
-
if (
|
|
59587
|
+
const randomUUID7 = globalThis.crypto?.randomUUID;
|
|
59588
|
+
if (randomUUID7 === void 0) {
|
|
59577
59589
|
throw new NSGetterRuntimeError(
|
|
59578
59590
|
"Class.Clone cannot mint a value id because crypto.randomUUID is unavailable."
|
|
59579
59591
|
);
|
|
59580
59592
|
}
|
|
59581
|
-
return
|
|
59593
|
+
return randomUUID7.call(globalThis.crypto);
|
|
59582
59594
|
}
|
|
59583
59595
|
function parseDialogueMemoryPointer(pointer) {
|
|
59584
59596
|
if (typeof pointer !== "string") return null;
|
|
@@ -66504,80 +66516,154 @@ function ensureProjectFileBinaryChangesV4(args) {
|
|
|
66504
66516
|
});
|
|
66505
66517
|
}
|
|
66506
66518
|
}
|
|
66519
|
+
function prepareProjectFilePushesV4(args) {
|
|
66520
|
+
const prepared = [];
|
|
66521
|
+
for (const binary of args.binaryChanges) {
|
|
66522
|
+
if (binary.action !== "create" && binary.action !== "upload") continue;
|
|
66523
|
+
const recordId = args.assignedIds.get(binary.fileId) ?? binary.fileId;
|
|
66524
|
+
const change = args.changes.find(
|
|
66525
|
+
(candidate) => candidate.recordKind === "project-file" && candidate.recordId === recordId
|
|
66526
|
+
);
|
|
66527
|
+
if (change === void 0) {
|
|
66528
|
+
throw new Error(
|
|
66529
|
+
`Project file ${recordId} has upload bytes but no source change.`
|
|
66530
|
+
);
|
|
66531
|
+
}
|
|
66532
|
+
if (!isObjectRecord2(change.nextData)) {
|
|
66533
|
+
throw new Error(
|
|
66534
|
+
`Project file ${recordId} has upload bytes but its source change has no record data.`
|
|
66535
|
+
);
|
|
66536
|
+
}
|
|
66537
|
+
const absolute = join14(args.workspace.root, binary.path);
|
|
66538
|
+
const bytes = new Uint8Array(readFileSync12(absolute));
|
|
66539
|
+
const digest = sha256Bytes(bytes);
|
|
66540
|
+
if (binary.localSha256 !== null && digest !== binary.localSha256) {
|
|
66541
|
+
throw new Error(
|
|
66542
|
+
`Project file ${binary.path} changed after status was computed; run push again.`
|
|
66543
|
+
);
|
|
66544
|
+
}
|
|
66545
|
+
const mimeType = binary.mimeType;
|
|
66546
|
+
if (mimeType === null) {
|
|
66547
|
+
throw new Error(`Project file ${binary.path} has no MIME type.`);
|
|
66548
|
+
}
|
|
66549
|
+
prepared.push({
|
|
66550
|
+
uploadToken: `${recordId}-${prepared.length}`,
|
|
66551
|
+
recordId,
|
|
66552
|
+
replaceFileId: binary.action === "upload" ? recordId : null,
|
|
66553
|
+
name: basename2(binary.path),
|
|
66554
|
+
fileType: binary.kind,
|
|
66555
|
+
mimeType,
|
|
66556
|
+
byteLength: bytes.byteLength,
|
|
66557
|
+
contentSha256: digest,
|
|
66558
|
+
audioDurationSeconds: binary.kind === "audio" && typeof change.nextData.audioDurationSeconds === "number" ? change.nextData.audioDurationSeconds : null,
|
|
66559
|
+
bytes
|
|
66560
|
+
});
|
|
66561
|
+
}
|
|
66562
|
+
return prepared;
|
|
66563
|
+
}
|
|
66507
66564
|
async function stageProjectFilePushesV4(args) {
|
|
66565
|
+
const prepared = args.prepared ?? prepareProjectFilePushesV4({
|
|
66566
|
+
workspace: args.workspace,
|
|
66567
|
+
changes: args.changes,
|
|
66568
|
+
binaryChanges: args.binaryChanges,
|
|
66569
|
+
assignedIds: args.assignedIds
|
|
66570
|
+
});
|
|
66508
66571
|
const staged = [];
|
|
66509
66572
|
const cleanupKeys = [];
|
|
66510
66573
|
const put = args.put ?? fetch;
|
|
66574
|
+
const interruptController = new AbortController();
|
|
66575
|
+
const interrupt = () => interruptController.abort(new ProjectFilePushCancelledError());
|
|
66576
|
+
process.once("SIGINT", interrupt);
|
|
66577
|
+
const signal = combineSignals(args.signal, interruptController.signal);
|
|
66578
|
+
const totalBytes = prepared.reduce((sum, file) => sum + file.byteLength, 0);
|
|
66579
|
+
let completedBytes = 0;
|
|
66580
|
+
let completedFiles = 0;
|
|
66581
|
+
const report = () => args.onProgress?.({
|
|
66582
|
+
completedFiles,
|
|
66583
|
+
totalFiles: prepared.length,
|
|
66584
|
+
completedBytes,
|
|
66585
|
+
totalBytes
|
|
66586
|
+
});
|
|
66587
|
+
report();
|
|
66511
66588
|
try {
|
|
66512
|
-
for (
|
|
66513
|
-
|
|
66514
|
-
|
|
66515
|
-
|
|
66516
|
-
(candidate) => candidate.recordKind === "project-file" && candidate.recordId === recordId
|
|
66589
|
+
for (let offset = 0; offset < prepared.length; offset += PROJECT_FILE_UPLOAD_BATCH_SIZE) {
|
|
66590
|
+
const batch = prepared.slice(
|
|
66591
|
+
offset,
|
|
66592
|
+
offset + PROJECT_FILE_UPLOAD_BATCH_SIZE
|
|
66517
66593
|
);
|
|
66518
|
-
|
|
66519
|
-
|
|
66520
|
-
`Project file ${recordId} has upload bytes but no source change.`
|
|
66521
|
-
);
|
|
66522
|
-
}
|
|
66523
|
-
const absolute = join14(args.workspace.root, binary.path);
|
|
66524
|
-
const bytes = new Uint8Array(readFileSync12(absolute));
|
|
66525
|
-
const digest = sha256Bytes(bytes);
|
|
66526
|
-
if (binary.localSha256 !== null && digest !== binary.localSha256) {
|
|
66527
|
-
throw new Error(
|
|
66528
|
-
`Project file ${binary.path} changed after status was computed; run push again.`
|
|
66529
|
-
);
|
|
66530
|
-
}
|
|
66531
|
-
const mimeType = binary.mimeType;
|
|
66532
|
-
if (mimeType === null) {
|
|
66533
|
-
throw new Error(`Project file ${binary.path} has no MIME type.`);
|
|
66534
|
-
}
|
|
66535
|
-
const name = basename2(binary.path);
|
|
66536
|
-
const replaceFileId = binary.action === "upload" ? recordId : null;
|
|
66537
|
-
const presign = await args.client.post(
|
|
66594
|
+
const presign = await postWithTimeout(
|
|
66595
|
+
args.client,
|
|
66538
66596
|
versionPath2(args.workspace, "upload"),
|
|
66539
66597
|
{
|
|
66540
66598
|
route: "projectFile",
|
|
66541
66599
|
metadata: {
|
|
66542
|
-
|
|
66543
|
-
|
|
66544
|
-
|
|
66545
|
-
|
|
66600
|
+
deferredSourceCommit: true,
|
|
66601
|
+
uploads: batch.map((file) => ({
|
|
66602
|
+
uploadToken: file.uploadToken,
|
|
66603
|
+
projectFileId: file.recordId,
|
|
66604
|
+
replaceFileId: file.replaceFileId,
|
|
66605
|
+
name: file.name,
|
|
66606
|
+
contentSha256: file.contentSha256
|
|
66607
|
+
}))
|
|
66546
66608
|
},
|
|
66547
|
-
files:
|
|
66548
|
-
|
|
66609
|
+
files: batch.map((file) => ({
|
|
66610
|
+
name: file.uploadToken,
|
|
66611
|
+
size: file.byteLength,
|
|
66612
|
+
type: file.mimeType
|
|
66613
|
+
}))
|
|
66614
|
+
},
|
|
66615
|
+
signal
|
|
66549
66616
|
);
|
|
66550
|
-
const
|
|
66551
|
-
const
|
|
66552
|
-
const
|
|
66553
|
-
|
|
66554
|
-
|
|
66617
|
+
const entries = readPresignEntries(presign, batch);
|
|
66618
|
+
for (const entry of entries) cleanupKeys.push(entry.storageKey);
|
|
66619
|
+
const batchController = new AbortController();
|
|
66620
|
+
try {
|
|
66621
|
+
await mapWithConcurrency(entries, UPLOAD_CONCURRENCY, async (entry) => {
|
|
66622
|
+
try {
|
|
66623
|
+
await putWithRetry(
|
|
66624
|
+
put,
|
|
66625
|
+
entry,
|
|
66626
|
+
combineSignals(signal, batchController.signal)
|
|
66627
|
+
);
|
|
66628
|
+
} catch (error) {
|
|
66629
|
+
batchController.abort(error);
|
|
66630
|
+
throw error;
|
|
66631
|
+
}
|
|
66632
|
+
staged.push({
|
|
66633
|
+
uploadToken: entry.file.uploadToken,
|
|
66634
|
+
file: {
|
|
66635
|
+
recordId: entry.file.recordId,
|
|
66636
|
+
replaceFileId: entry.file.replaceFileId,
|
|
66637
|
+
name: entry.file.name,
|
|
66638
|
+
fileType: entry.file.fileType,
|
|
66639
|
+
mimeType: entry.file.mimeType,
|
|
66640
|
+
byteLength: entry.file.byteLength,
|
|
66641
|
+
storageKey: entry.storageKey,
|
|
66642
|
+
contentSha256: entry.file.contentSha256,
|
|
66643
|
+
audioDurationSeconds: entry.file.audioDurationSeconds
|
|
66644
|
+
}
|
|
66645
|
+
});
|
|
66646
|
+
completedFiles += 1;
|
|
66647
|
+
completedBytes += entry.file.byteLength;
|
|
66648
|
+
report();
|
|
66649
|
+
});
|
|
66650
|
+
} catch (error) {
|
|
66651
|
+
batchController.abort(error);
|
|
66652
|
+
throw error;
|
|
66555
66653
|
}
|
|
66556
|
-
|
|
66557
|
-
|
|
66558
|
-
|
|
66559
|
-
|
|
66560
|
-
|
|
66561
|
-
|
|
66562
|
-
|
|
66563
|
-
if (!response.ok) {
|
|
66654
|
+
}
|
|
66655
|
+
const byUploadToken = new Map(
|
|
66656
|
+
staged.map((entry) => [entry.uploadToken, entry.file])
|
|
66657
|
+
);
|
|
66658
|
+
return prepared.map((file) => {
|
|
66659
|
+
const result = byUploadToken.get(file.uploadToken);
|
|
66660
|
+
if (result === void 0) {
|
|
66564
66661
|
throw new Error(
|
|
66565
|
-
`
|
|
66662
|
+
`Uploaded project file ${file.name} (${file.uploadToken}) is missing from the staged result.`
|
|
66566
66663
|
);
|
|
66567
66664
|
}
|
|
66568
|
-
|
|
66569
|
-
|
|
66570
|
-
replaceFileId,
|
|
66571
|
-
name,
|
|
66572
|
-
fileType: binary.kind,
|
|
66573
|
-
mimeType,
|
|
66574
|
-
byteLength: bytes.byteLength,
|
|
66575
|
-
storageKey: objectInfo.key,
|
|
66576
|
-
contentSha256: digest,
|
|
66577
|
-
audioDurationSeconds: binary.kind === "audio" && typeof change.nextData.audioDurationSeconds === "number" ? change.nextData.audioDurationSeconds : null
|
|
66578
|
-
});
|
|
66579
|
-
}
|
|
66580
|
-
return staged;
|
|
66665
|
+
return result;
|
|
66666
|
+
});
|
|
66581
66667
|
} catch (error) {
|
|
66582
66668
|
if (cleanupKeys.length > 0) {
|
|
66583
66669
|
try {
|
|
@@ -66588,9 +66674,146 @@ async function stageProjectFilePushesV4(args) {
|
|
|
66588
66674
|
} catch {
|
|
66589
66675
|
}
|
|
66590
66676
|
}
|
|
66677
|
+
if (interruptController.signal.aborted || args.signal?.aborted === true) {
|
|
66678
|
+
throw new ProjectFilePushCancelledError();
|
|
66679
|
+
}
|
|
66591
66680
|
throw error;
|
|
66681
|
+
} finally {
|
|
66682
|
+
process.removeListener("SIGINT", interrupt);
|
|
66592
66683
|
}
|
|
66593
66684
|
}
|
|
66685
|
+
function readPresignEntries(presign, batch) {
|
|
66686
|
+
const entries = Array.isArray(presign.files) ? presign.files.filter(isObjectRecord2) : [];
|
|
66687
|
+
return batch.map((file) => {
|
|
66688
|
+
const entry = entries.find((candidate) => {
|
|
66689
|
+
const info = isObjectRecord2(candidate.file) ? candidate.file : {};
|
|
66690
|
+
return info.name === file.uploadToken;
|
|
66691
|
+
});
|
|
66692
|
+
const fileInfo = isObjectRecord2(entry?.file) ? entry.file : {};
|
|
66693
|
+
const objectInfo = isObjectRecord2(fileInfo.objectInfo) ? fileInfo.objectInfo : {};
|
|
66694
|
+
if (typeof entry?.signedUrl !== "string") {
|
|
66695
|
+
throw new Error(
|
|
66696
|
+
`Upload presign response is missing signedUrl for ${file.name}.`
|
|
66697
|
+
);
|
|
66698
|
+
}
|
|
66699
|
+
if (typeof objectInfo.key !== "string") {
|
|
66700
|
+
throw new Error(
|
|
66701
|
+
`Upload presign response is missing a storage key for ${file.name}.`
|
|
66702
|
+
);
|
|
66703
|
+
}
|
|
66704
|
+
return {
|
|
66705
|
+
file,
|
|
66706
|
+
signedUrl: entry.signedUrl,
|
|
66707
|
+
storageKey: objectInfo.key,
|
|
66708
|
+
headers: uploadHeaders(entry, objectInfo, file.mimeType)
|
|
66709
|
+
};
|
|
66710
|
+
});
|
|
66711
|
+
}
|
|
66712
|
+
async function postWithTimeout(client, path, body, signal) {
|
|
66713
|
+
for (let attempt = 1; attempt <= PRESIGN_ATTEMPTS; attempt += 1) {
|
|
66714
|
+
try {
|
|
66715
|
+
return await client.post(path, body, void 0, {
|
|
66716
|
+
signal: combineSignals(signal, AbortSignal.timeout(PRESIGN_TIMEOUT_MS))
|
|
66717
|
+
});
|
|
66718
|
+
} catch (error) {
|
|
66719
|
+
if (signal.aborted || !isRetryableRequestError(error) || attempt === PRESIGN_ATTEMPTS) {
|
|
66720
|
+
throw error;
|
|
66721
|
+
}
|
|
66722
|
+
await waitForRetry(attempt, signal);
|
|
66723
|
+
}
|
|
66724
|
+
}
|
|
66725
|
+
throw new Error("Upload presign failed after all retry attempts.");
|
|
66726
|
+
}
|
|
66727
|
+
async function putWithRetry(put, entry, signal) {
|
|
66728
|
+
let lastError;
|
|
66729
|
+
for (let attempt = 1; attempt <= STORAGE_PUT_ATTEMPTS; attempt += 1) {
|
|
66730
|
+
let response;
|
|
66731
|
+
try {
|
|
66732
|
+
response = await put(entry.signedUrl, {
|
|
66733
|
+
method: "PUT",
|
|
66734
|
+
headers: entry.headers,
|
|
66735
|
+
body: Buffer.from(entry.file.bytes),
|
|
66736
|
+
signal: combineSignals(
|
|
66737
|
+
signal,
|
|
66738
|
+
AbortSignal.timeout(STORAGE_PUT_TIMEOUT_MS)
|
|
66739
|
+
)
|
|
66740
|
+
});
|
|
66741
|
+
} catch (error) {
|
|
66742
|
+
if (signal.aborted || attempt === STORAGE_PUT_ATTEMPTS) throw error;
|
|
66743
|
+
lastError = error;
|
|
66744
|
+
await waitForRetry(attempt, signal);
|
|
66745
|
+
continue;
|
|
66746
|
+
}
|
|
66747
|
+
if (response.ok) return;
|
|
66748
|
+
if (isRetryableStatus(response.status) && attempt < STORAGE_PUT_ATTEMPTS) {
|
|
66749
|
+
lastError = new Error(`Storage PUT failed (${response.status}).`);
|
|
66750
|
+
await waitForRetry(attempt, signal);
|
|
66751
|
+
continue;
|
|
66752
|
+
}
|
|
66753
|
+
throw new Error(
|
|
66754
|
+
`Storage PUT failed (${response.status}): ${await response.text()}`
|
|
66755
|
+
);
|
|
66756
|
+
}
|
|
66757
|
+
throw lastError instanceof Error ? lastError : new Error(`Storage PUT failed for ${entry.file.name}.`);
|
|
66758
|
+
}
|
|
66759
|
+
function isRetryableStatus(status) {
|
|
66760
|
+
return status === 408 || status === 429 || status >= 500;
|
|
66761
|
+
}
|
|
66762
|
+
function isRetryableRequestError(error) {
|
|
66763
|
+
if (isObjectRecord2(error) && typeof error.status === "number") {
|
|
66764
|
+
return isRetryableStatus(error.status);
|
|
66765
|
+
}
|
|
66766
|
+
if (isObjectRecord2(error) && error.name === "TimeoutError") return true;
|
|
66767
|
+
if (!(error instanceof TypeError) || error.message !== "fetch failed") {
|
|
66768
|
+
return false;
|
|
66769
|
+
}
|
|
66770
|
+
if (!isObjectRecord2(error.cause) || typeof error.cause.code !== "string") {
|
|
66771
|
+
return false;
|
|
66772
|
+
}
|
|
66773
|
+
return RETRYABLE_NETWORK_ERROR_CODES.has(error.cause.code);
|
|
66774
|
+
}
|
|
66775
|
+
async function waitForRetry(attempt, signal) {
|
|
66776
|
+
await new Promise((resolve4, reject) => {
|
|
66777
|
+
const abort = () => {
|
|
66778
|
+
clearTimeout(timeout);
|
|
66779
|
+
reject(signal.reason);
|
|
66780
|
+
};
|
|
66781
|
+
const timeout = setTimeout(
|
|
66782
|
+
() => {
|
|
66783
|
+
signal.removeEventListener("abort", abort);
|
|
66784
|
+
resolve4();
|
|
66785
|
+
},
|
|
66786
|
+
200 * 2 ** (attempt - 1)
|
|
66787
|
+
);
|
|
66788
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
66789
|
+
});
|
|
66790
|
+
}
|
|
66791
|
+
async function mapWithConcurrency(values, concurrency, run) {
|
|
66792
|
+
let nextIndex = 0;
|
|
66793
|
+
let firstError;
|
|
66794
|
+
const worker = async () => {
|
|
66795
|
+
while (firstError === void 0) {
|
|
66796
|
+
const index = nextIndex;
|
|
66797
|
+
nextIndex += 1;
|
|
66798
|
+
if (index >= values.length) return;
|
|
66799
|
+
try {
|
|
66800
|
+
await run(values[index]);
|
|
66801
|
+
} catch (error) {
|
|
66802
|
+
firstError ??= error;
|
|
66803
|
+
}
|
|
66804
|
+
}
|
|
66805
|
+
};
|
|
66806
|
+
await Promise.all(
|
|
66807
|
+
Array.from({ length: Math.min(concurrency, values.length) }, worker)
|
|
66808
|
+
);
|
|
66809
|
+
if (firstError !== void 0) throw firstError;
|
|
66810
|
+
}
|
|
66811
|
+
function combineSignals(...signals) {
|
|
66812
|
+
const defined = signals.filter(
|
|
66813
|
+
(signal) => signal !== void 0
|
|
66814
|
+
);
|
|
66815
|
+
return defined.length === 1 ? defined[0] : AbortSignal.any(defined);
|
|
66816
|
+
}
|
|
66594
66817
|
function uploadHeaders(entry, objectInfo, mimeType) {
|
|
66595
66818
|
const headers = { "Content-Type": mimeType };
|
|
66596
66819
|
if (typeof objectInfo.cacheControl === "string") {
|
|
@@ -66611,11 +66834,431 @@ function uploadHeaders(entry, objectInfo, mimeType) {
|
|
|
66611
66834
|
function versionPath2(workspace, suffix) {
|
|
66612
66835
|
return `/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/${suffix}`;
|
|
66613
66836
|
}
|
|
66837
|
+
var UPLOAD_CONCURRENCY, PRESIGN_TIMEOUT_MS, PRESIGN_ATTEMPTS, STORAGE_PUT_TIMEOUT_MS, STORAGE_PUT_ATTEMPTS, ProjectFilePushCancelledError, RETRYABLE_NETWORK_ERROR_CODES;
|
|
66614
66838
|
var init_project_file_push = __esm({
|
|
66615
66839
|
"src/project-source/project-file-push.ts"() {
|
|
66616
66840
|
"use strict";
|
|
66617
66841
|
init_project_files();
|
|
66618
66842
|
init_projection();
|
|
66843
|
+
init_src();
|
|
66844
|
+
UPLOAD_CONCURRENCY = 6;
|
|
66845
|
+
PRESIGN_TIMEOUT_MS = 3e4;
|
|
66846
|
+
PRESIGN_ATTEMPTS = 3;
|
|
66847
|
+
STORAGE_PUT_TIMEOUT_MS = 12e4;
|
|
66848
|
+
STORAGE_PUT_ATTEMPTS = 3;
|
|
66849
|
+
ProjectFilePushCancelledError = class extends Error {
|
|
66850
|
+
constructor() {
|
|
66851
|
+
super("Project file upload was cancelled.");
|
|
66852
|
+
this.name = "ProjectFilePushCancelledError";
|
|
66853
|
+
}
|
|
66854
|
+
};
|
|
66855
|
+
RETRYABLE_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
66856
|
+
"ECONNRESET",
|
|
66857
|
+
"ECONNREFUSED",
|
|
66858
|
+
"EHOSTUNREACH",
|
|
66859
|
+
"ENETUNREACH",
|
|
66860
|
+
"ENOTFOUND",
|
|
66861
|
+
"EPIPE",
|
|
66862
|
+
"ETIMEDOUT"
|
|
66863
|
+
]);
|
|
66864
|
+
}
|
|
66865
|
+
});
|
|
66866
|
+
|
|
66867
|
+
// src/project-source/trusted-commit-verification.ts
|
|
66868
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
66869
|
+
import { tmpdir } from "node:os";
|
|
66870
|
+
import { join as join15 } from "node:path";
|
|
66871
|
+
function verifyProjectSourceCommitAgainstStateV4(args) {
|
|
66872
|
+
const root = join15(tmpdir(), `neo-source-verify-virtual-${randomUUID5()}`);
|
|
66873
|
+
const workspace = {
|
|
66874
|
+
root,
|
|
66875
|
+
config: {
|
|
66876
|
+
formatVersion: 4,
|
|
66877
|
+
apiBaseUrl: "https://trusted-server.invalid",
|
|
66878
|
+
projectId: args.projectId,
|
|
66879
|
+
versionId: args.versionId,
|
|
66880
|
+
profile: "editor"
|
|
66881
|
+
},
|
|
66882
|
+
state: { records: { ...args.stateRecords } }
|
|
66883
|
+
};
|
|
66884
|
+
const assignments = validateAssignments(args.pendingIdAssignments);
|
|
66885
|
+
const pendingIdByAssignedId = new Map(
|
|
66886
|
+
[...assignments].map(([pendingId2, assignedId]) => [assignedId, pendingId2])
|
|
66887
|
+
);
|
|
66888
|
+
const trustedPendingProjectFiles = /* @__PURE__ */ new Map();
|
|
66889
|
+
const stagedRecordIds = /* @__PURE__ */ new Set();
|
|
66890
|
+
for (const file of args.stagedFiles) {
|
|
66891
|
+
if (stagedRecordIds.has(file.recordId)) {
|
|
66892
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66893
|
+
"Source commit contains duplicate verified staged project files."
|
|
66894
|
+
);
|
|
66895
|
+
}
|
|
66896
|
+
stagedRecordIds.add(file.recordId);
|
|
66897
|
+
const metadata = {
|
|
66898
|
+
mimeType: file.mimeType,
|
|
66899
|
+
byteLength: file.byteLength,
|
|
66900
|
+
sha256: file.contentSha256
|
|
66901
|
+
};
|
|
66902
|
+
trustedPendingProjectFiles.set(file.recordId, metadata);
|
|
66903
|
+
const pendingId2 = pendingIdByAssignedId.get(file.recordId);
|
|
66904
|
+
if (pendingId2 !== void 0) {
|
|
66905
|
+
trustedPendingProjectFiles.set(pendingId2, metadata);
|
|
66906
|
+
}
|
|
66907
|
+
}
|
|
66908
|
+
const status = computeWorkspaceStatus(workspace, {
|
|
66909
|
+
skipProjectBinaryInspection: true,
|
|
66910
|
+
writeProjectAnalysisCache: () => void 0,
|
|
66911
|
+
trustedPendingProjectFiles,
|
|
66912
|
+
virtualSourceFiles: args.files
|
|
66913
|
+
});
|
|
66914
|
+
const blockingErrors = status.parseErrors.filter(isBlockingSchemaSourceError);
|
|
66915
|
+
if (status.conflictedFiles.length > 0 || blockingErrors.length > 0) {
|
|
66916
|
+
const first = blockingErrors[0];
|
|
66917
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66918
|
+
first ? `Trusted source lowering failed: ${first.file}:${first.line}:${first.column} ${first.message}` : `Trusted source lowering found conflict markers in ${status.conflictedFiles[0]}.`
|
|
66919
|
+
);
|
|
66920
|
+
}
|
|
66921
|
+
const usedAssignments = /* @__PURE__ */ new Set();
|
|
66922
|
+
const expectedChanges = status.changes.map((change) => {
|
|
66923
|
+
const rewrittenData = change.nextData === void 0 ? void 0 : rewritePending(change.nextData, assignments, usedAssignments);
|
|
66924
|
+
return {
|
|
66925
|
+
recordKind: change.recordKind,
|
|
66926
|
+
recordId: rewritePending(change.recordId, assignments, usedAssignments),
|
|
66927
|
+
operation: change.kind,
|
|
66928
|
+
// Source syntax does not author project ownership. The CLI stamps the
|
|
66929
|
+
// authenticated project id on creates immediately before transport;
|
|
66930
|
+
// reproduce that server-known field instead of comparing the
|
|
66931
|
+
// lowerer's empty construction placeholder.
|
|
66932
|
+
nextData: change.kind === "create" && isObjectRecord2(rewrittenData) ? { ...rewrittenData, projectId: args.projectId } : rewrittenData,
|
|
66933
|
+
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
66934
|
+
};
|
|
66935
|
+
});
|
|
66936
|
+
const expectedSeeds = [...status.staticValueSeeds].map(
|
|
66937
|
+
([memberId, seed]) => ({
|
|
66938
|
+
memberId: rewritePending(memberId, assignments, usedAssignments),
|
|
66939
|
+
value: rewritePending(seed.value, assignments, usedAssignments),
|
|
66940
|
+
classId: seed.classId === null ? null : rewritePending(seed.classId, assignments, usedAssignments),
|
|
66941
|
+
...seed.valueId === void 0 ? {} : {
|
|
66942
|
+
valueId: rewritePending(seed.valueId, assignments, usedAssignments)
|
|
66943
|
+
},
|
|
66944
|
+
...seed.values === void 0 ? {} : {
|
|
66945
|
+
values: rewritePending(seed.values, assignments, usedAssignments)
|
|
66946
|
+
},
|
|
66947
|
+
...seed.bindingMembers === void 0 ? {} : {
|
|
66948
|
+
bindingMembers: rewritePending(
|
|
66949
|
+
seed.bindingMembers,
|
|
66950
|
+
assignments,
|
|
66951
|
+
usedAssignments
|
|
66952
|
+
)
|
|
66953
|
+
},
|
|
66954
|
+
...seed.localizedTexts === void 0 ? {} : {
|
|
66955
|
+
localizedTexts: rewritePending(
|
|
66956
|
+
seed.localizedTexts,
|
|
66957
|
+
assignments,
|
|
66958
|
+
usedAssignments
|
|
66959
|
+
)
|
|
66960
|
+
}
|
|
66961
|
+
})
|
|
66962
|
+
);
|
|
66963
|
+
for (const pendingId2 of assignments.keys()) {
|
|
66964
|
+
if (!usedAssignments.has(pendingId2)) {
|
|
66965
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66966
|
+
`Pending id assignment ${pendingId2} is not present in the verified source manifest.`
|
|
66967
|
+
);
|
|
66968
|
+
}
|
|
66969
|
+
}
|
|
66970
|
+
compareChanges(expectedChanges, args.changes);
|
|
66971
|
+
compareSeeds(expectedSeeds, args.staticValueSeeds);
|
|
66972
|
+
}
|
|
66973
|
+
function validateAssignments(value) {
|
|
66974
|
+
const assignments = /* @__PURE__ */ new Map();
|
|
66975
|
+
const assignedIds = /* @__PURE__ */ new Set();
|
|
66976
|
+
for (const [pendingId2, assignedId] of Object.entries(value)) {
|
|
66977
|
+
if (!pendingId2.startsWith("__pending__:")) {
|
|
66978
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66979
|
+
`Pending id assignment key ${pendingId2} is not a pending identity.`
|
|
66980
|
+
);
|
|
66981
|
+
}
|
|
66982
|
+
if (pendingMemberValueMemberId(pendingId2) === null) {
|
|
66983
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(
|
|
66984
|
+
assignedId
|
|
66985
|
+
)) {
|
|
66986
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66987
|
+
`Pending id assignment for ${pendingId2} is not a UUID v4.`
|
|
66988
|
+
);
|
|
66989
|
+
}
|
|
66990
|
+
}
|
|
66991
|
+
if (assignedIds.has(assignedId)) {
|
|
66992
|
+
throw new ProjectSourceCommitVerificationError(
|
|
66993
|
+
`Pending id assignments reuse durable id ${assignedId}.`
|
|
66994
|
+
);
|
|
66995
|
+
}
|
|
66996
|
+
assignments.set(pendingId2, assignedId);
|
|
66997
|
+
assignedIds.add(assignedId);
|
|
66998
|
+
}
|
|
66999
|
+
assertMemberValueAssignmentsAreDerived(assignments);
|
|
67000
|
+
return assignments;
|
|
67001
|
+
}
|
|
67002
|
+
function assertMemberValueAssignmentsAreDerived(assignments) {
|
|
67003
|
+
for (const [pendingId2, assignedId] of assignments) {
|
|
67004
|
+
const memberLocator = pendingMemberValueMemberId(pendingId2);
|
|
67005
|
+
if (memberLocator === null) continue;
|
|
67006
|
+
const memberId = memberLocator.startsWith("__pending__:") ? assignments.get(memberLocator) : memberLocator;
|
|
67007
|
+
if (memberId === void 0) {
|
|
67008
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67009
|
+
`Member value assignment ${pendingId2} names member ${memberLocator}, which has no pending id assignment.`
|
|
67010
|
+
);
|
|
67011
|
+
}
|
|
67012
|
+
const derived = derivedMemberValueId(memberId);
|
|
67013
|
+
if (assignedId !== derived) {
|
|
67014
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67015
|
+
`Member value assignment ${pendingId2} is ${assignedId}, but member ${memberId} owns value ${derived}.`
|
|
67016
|
+
);
|
|
67017
|
+
}
|
|
67018
|
+
}
|
|
67019
|
+
}
|
|
67020
|
+
function positionIndependentPendingKey(pendingId2) {
|
|
67021
|
+
const parts = pendingId2.split(":");
|
|
67022
|
+
if (parts.length !== 6) return null;
|
|
67023
|
+
const [prefix, kind, uri, line, character, label] = parts;
|
|
67024
|
+
if (prefix !== "__pending__") return null;
|
|
67025
|
+
if (!/^\d+$/u.test(line) || !/^\d+$/u.test(character)) return null;
|
|
67026
|
+
return `${prefix}:${kind}:${uri}:${label}`;
|
|
67027
|
+
}
|
|
67028
|
+
function positionIndependentAssignments(assignments) {
|
|
67029
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
67030
|
+
for (const pendingId2 of assignments.keys()) {
|
|
67031
|
+
const key = positionIndependentPendingKey(pendingId2);
|
|
67032
|
+
if (key === null) continue;
|
|
67033
|
+
candidates.set(key, [...candidates.get(key) ?? [], pendingId2]);
|
|
67034
|
+
}
|
|
67035
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
67036
|
+
for (const [key, pendingIds] of candidates) {
|
|
67037
|
+
if (pendingIds.length !== 1) continue;
|
|
67038
|
+
resolved.set(key, pendingIds[0]);
|
|
67039
|
+
}
|
|
67040
|
+
return resolved;
|
|
67041
|
+
}
|
|
67042
|
+
function rewritePending(value, assignments, used, byPosition) {
|
|
67043
|
+
const positionless = byPosition ?? positionIndependentAssignments(assignments);
|
|
67044
|
+
if (typeof value === "string") {
|
|
67045
|
+
const exact = assignments.get(value);
|
|
67046
|
+
if (exact !== void 0) {
|
|
67047
|
+
used.add(value);
|
|
67048
|
+
return exact;
|
|
67049
|
+
}
|
|
67050
|
+
if (value.startsWith("__pending__:")) {
|
|
67051
|
+
const key = positionIndependentPendingKey(value);
|
|
67052
|
+
const relocated = key === null ? void 0 : positionless.get(key);
|
|
67053
|
+
if (relocated !== void 0) {
|
|
67054
|
+
used.add(relocated);
|
|
67055
|
+
return assignments.get(relocated);
|
|
67056
|
+
}
|
|
67057
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67058
|
+
`Verified source identity ${value} has no pending id assignment.`
|
|
67059
|
+
);
|
|
67060
|
+
}
|
|
67061
|
+
let rewritten = value;
|
|
67062
|
+
for (const [pendingId2, assignedId] of assignments) {
|
|
67063
|
+
if (!rewritten.includes(pendingId2)) continue;
|
|
67064
|
+
rewritten = rewritten.replaceAll(pendingId2, assignedId);
|
|
67065
|
+
used.add(pendingId2);
|
|
67066
|
+
}
|
|
67067
|
+
return rewritten;
|
|
67068
|
+
}
|
|
67069
|
+
if (Array.isArray(value)) {
|
|
67070
|
+
return value.map(
|
|
67071
|
+
(entry) => rewritePending(entry, assignments, used, positionless)
|
|
67072
|
+
);
|
|
67073
|
+
}
|
|
67074
|
+
if (isObjectRecord2(value)) {
|
|
67075
|
+
const result = {};
|
|
67076
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
67077
|
+
const rewrittenKey = key.startsWith("__pending__:") ? rewritePending(key, assignments, used, positionless) : key;
|
|
67078
|
+
result[rewrittenKey] = rewritePending(
|
|
67079
|
+
entry,
|
|
67080
|
+
assignments,
|
|
67081
|
+
used,
|
|
67082
|
+
positionless
|
|
67083
|
+
);
|
|
67084
|
+
}
|
|
67085
|
+
return result;
|
|
67086
|
+
}
|
|
67087
|
+
return value;
|
|
67088
|
+
}
|
|
67089
|
+
function compareChanges(expected, received) {
|
|
67090
|
+
const expectedByKey = new Map(
|
|
67091
|
+
expected.map((change) => [
|
|
67092
|
+
`${change.recordKind}:${change.recordId}`,
|
|
67093
|
+
change
|
|
67094
|
+
])
|
|
67095
|
+
);
|
|
67096
|
+
const receivedByKey = new Map(
|
|
67097
|
+
received.map((change) => [
|
|
67098
|
+
`${change.recordKind}:${change.recordId}`,
|
|
67099
|
+
change
|
|
67100
|
+
])
|
|
67101
|
+
);
|
|
67102
|
+
if (expectedByKey.size !== expected.length || receivedByKey.size !== received.length) {
|
|
67103
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67104
|
+
"Source commit contains duplicate semantic record changes."
|
|
67105
|
+
);
|
|
67106
|
+
}
|
|
67107
|
+
for (const [key, expectedChange] of expectedByKey) {
|
|
67108
|
+
const actual = receivedByKey.get(key);
|
|
67109
|
+
if (actual === void 0) {
|
|
67110
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67111
|
+
`Source commit omitted semantic change ${key}.`
|
|
67112
|
+
);
|
|
67113
|
+
}
|
|
67114
|
+
if (actual.operation !== expectedChange.operation || (actual.expectedBaseContentHash ?? null) !== expectedChange.expectedBaseContentHash) {
|
|
67115
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67116
|
+
`Source commit changed operation or CAS base for ${key}.`
|
|
67117
|
+
);
|
|
67118
|
+
}
|
|
67119
|
+
const expectedData = comparisonData(
|
|
67120
|
+
expectedChange.recordKind,
|
|
67121
|
+
expectedChange.nextData
|
|
67122
|
+
);
|
|
67123
|
+
const actualData = comparisonData(actual.recordKind, actual.nextData);
|
|
67124
|
+
if (canonicalStringify(expectedData) !== canonicalStringify(actualData)) {
|
|
67125
|
+
const difference = firstDifference(expectedData, actualData);
|
|
67126
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67127
|
+
`Source commit nextData for ${key} does not match trusted lowering${difference === null ? "." : ` at ${difference.path}: trusted ${formatDifferenceValue(difference.trusted)}, submitted ${formatDifferenceValue(difference.submitted)}.`}`
|
|
67128
|
+
);
|
|
67129
|
+
}
|
|
67130
|
+
if (!isObjectRecord2(actual.intent) || actual.intent.type !== `${actual.recordKind}.${actual.operation}`) {
|
|
67131
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67132
|
+
`Source commit intent for ${key} does not match its semantic operation.`
|
|
67133
|
+
);
|
|
67134
|
+
}
|
|
67135
|
+
receivedByKey.delete(key);
|
|
67136
|
+
}
|
|
67137
|
+
const extra = receivedByKey.keys().next().value;
|
|
67138
|
+
if (extra !== void 0) {
|
|
67139
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67140
|
+
`Source commit added semantic change ${extra} absent from trusted lowering.`
|
|
67141
|
+
);
|
|
67142
|
+
}
|
|
67143
|
+
}
|
|
67144
|
+
function firstDifference(trusted, submitted, path = "$") {
|
|
67145
|
+
if (Object.is(trusted, submitted)) return null;
|
|
67146
|
+
if (Array.isArray(trusted) && Array.isArray(submitted)) {
|
|
67147
|
+
const count = Math.max(trusted.length, submitted.length);
|
|
67148
|
+
for (let index = 0; index < count; index += 1) {
|
|
67149
|
+
if (index >= trusted.length) {
|
|
67150
|
+
return {
|
|
67151
|
+
path: `${path}[${index}]`,
|
|
67152
|
+
trusted: ABSENT_DIFFERENCE_VALUE,
|
|
67153
|
+
submitted: submitted[index]
|
|
67154
|
+
};
|
|
67155
|
+
}
|
|
67156
|
+
if (index >= submitted.length) {
|
|
67157
|
+
return {
|
|
67158
|
+
path: `${path}[${index}]`,
|
|
67159
|
+
trusted: trusted[index],
|
|
67160
|
+
submitted: ABSENT_DIFFERENCE_VALUE
|
|
67161
|
+
};
|
|
67162
|
+
}
|
|
67163
|
+
const difference = firstDifference(
|
|
67164
|
+
trusted[index],
|
|
67165
|
+
submitted[index],
|
|
67166
|
+
`${path}[${index}]`
|
|
67167
|
+
);
|
|
67168
|
+
if (difference !== null) return difference;
|
|
67169
|
+
}
|
|
67170
|
+
}
|
|
67171
|
+
if (isObjectRecord2(trusted) && isObjectRecord2(submitted)) {
|
|
67172
|
+
const keys = [
|
|
67173
|
+
.../* @__PURE__ */ new Set([...Object.keys(trusted), ...Object.keys(submitted)])
|
|
67174
|
+
].sort();
|
|
67175
|
+
for (const key of keys) {
|
|
67176
|
+
const trustedHasKey = Object.hasOwn(trusted, key);
|
|
67177
|
+
const submittedHasKey = Object.hasOwn(submitted, key);
|
|
67178
|
+
const childPath = `${path}.${key}`;
|
|
67179
|
+
if (!trustedHasKey || !submittedHasKey) {
|
|
67180
|
+
return {
|
|
67181
|
+
path: childPath,
|
|
67182
|
+
trusted: trustedHasKey ? trusted[key] : ABSENT_DIFFERENCE_VALUE,
|
|
67183
|
+
submitted: submittedHasKey ? submitted[key] : ABSENT_DIFFERENCE_VALUE
|
|
67184
|
+
};
|
|
67185
|
+
}
|
|
67186
|
+
const difference = firstDifference(
|
|
67187
|
+
trusted[key],
|
|
67188
|
+
submitted[key],
|
|
67189
|
+
childPath
|
|
67190
|
+
);
|
|
67191
|
+
if (difference !== null) return difference;
|
|
67192
|
+
}
|
|
67193
|
+
}
|
|
67194
|
+
return { path, trusted, submitted };
|
|
67195
|
+
}
|
|
67196
|
+
function formatDifferenceValue(value) {
|
|
67197
|
+
if (value === ABSENT_DIFFERENCE_VALUE) return "<absent>";
|
|
67198
|
+
const serialized = JSON.stringify(value);
|
|
67199
|
+
const rendered = serialized === void 0 ? String(value) : serialized;
|
|
67200
|
+
return rendered.length <= 160 ? rendered : `${rendered.slice(0, 157)}...`;
|
|
67201
|
+
}
|
|
67202
|
+
function comparisonData(recordKind, value) {
|
|
67203
|
+
if (!isObjectRecord2(value)) return value;
|
|
67204
|
+
const result = { ...value };
|
|
67205
|
+
delete result.createdAt;
|
|
67206
|
+
delete result.updatedAt;
|
|
67207
|
+
if (recordKind === "member") {
|
|
67208
|
+
delete result.getter;
|
|
67209
|
+
delete result.setter;
|
|
67210
|
+
if (result.kind === 23) delete result.action;
|
|
67211
|
+
}
|
|
67212
|
+
if (recordKind === "migration") delete result.action;
|
|
67213
|
+
return result;
|
|
67214
|
+
}
|
|
67215
|
+
function compareSeeds(expected, received) {
|
|
67216
|
+
const normalize = (values) => values.map(normalizeSeedForComparison).sort((left, right) => {
|
|
67217
|
+
if (left.memberId < right.memberId) return -1;
|
|
67218
|
+
if (left.memberId > right.memberId) return 1;
|
|
67219
|
+
return 0;
|
|
67220
|
+
});
|
|
67221
|
+
if (canonicalStringify(normalize(expected)) !== canonicalStringify(normalize(received))) {
|
|
67222
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67223
|
+
"Source commit static value seeds do not match trusted lowering."
|
|
67224
|
+
);
|
|
67225
|
+
}
|
|
67226
|
+
}
|
|
67227
|
+
function normalizeSeedForComparison(seed) {
|
|
67228
|
+
const normalized = { ...seed };
|
|
67229
|
+
if (seed.values !== void 0) {
|
|
67230
|
+
normalized.values = sortSeedRows(seed.values);
|
|
67231
|
+
}
|
|
67232
|
+
if (seed.bindingMembers !== void 0) {
|
|
67233
|
+
normalized.bindingMembers = sortSeedRows(seed.bindingMembers);
|
|
67234
|
+
}
|
|
67235
|
+
if (seed.localizedTexts !== void 0) {
|
|
67236
|
+
normalized.localizedTexts = sortSeedRows(seed.localizedTexts);
|
|
67237
|
+
}
|
|
67238
|
+
return normalized;
|
|
67239
|
+
}
|
|
67240
|
+
function sortSeedRows(values) {
|
|
67241
|
+
return [...values].sort((left, right) => {
|
|
67242
|
+
if (left.id < right.id) return -1;
|
|
67243
|
+
if (left.id > right.id) return 1;
|
|
67244
|
+
return 0;
|
|
67245
|
+
});
|
|
67246
|
+
}
|
|
67247
|
+
var ProjectSourceCommitVerificationError, ABSENT_DIFFERENCE_VALUE;
|
|
67248
|
+
var init_trusted_commit_verification = __esm({
|
|
67249
|
+
"src/project-source/trusted-commit-verification.ts"() {
|
|
67250
|
+
"use strict";
|
|
67251
|
+
init_workspace_status();
|
|
67252
|
+
init_source_diagnostics();
|
|
67253
|
+
init_projection();
|
|
67254
|
+
init_member_value_id();
|
|
67255
|
+
ProjectSourceCommitVerificationError = class extends Error {
|
|
67256
|
+
constructor(message) {
|
|
67257
|
+
super(message);
|
|
67258
|
+
this.name = "ProjectSourceCommitVerificationError";
|
|
67259
|
+
}
|
|
67260
|
+
};
|
|
67261
|
+
ABSENT_DIFFERENCE_VALUE = /* @__PURE__ */ Symbol("absent-difference-value");
|
|
66619
67262
|
}
|
|
66620
67263
|
});
|
|
66621
67264
|
|
|
@@ -66660,7 +67303,7 @@ __export(push_exports, {
|
|
|
66660
67303
|
stripServerDerivedNeoScript: () => stripServerDerivedNeoScript,
|
|
66661
67304
|
workspaceChangesRequireCompleteBodySweep: () => workspaceChangesRequireCompleteBodySweep
|
|
66662
67305
|
});
|
|
66663
|
-
import { randomUUID as
|
|
67306
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
66664
67307
|
import {
|
|
66665
67308
|
mkdirSync as mkdirSync11,
|
|
66666
67309
|
writeFileSync as writeFileSync11,
|
|
@@ -66668,7 +67311,7 @@ import {
|
|
|
66668
67311
|
existsSync as existsSync12,
|
|
66669
67312
|
readFileSync as readFileSync13
|
|
66670
67313
|
} from "node:fs";
|
|
66671
|
-
import { dirname as dirname7, join as
|
|
67314
|
+
import { dirname as dirname7, join as join16, relative as relative5, sep as sep5 } from "node:path";
|
|
66672
67315
|
function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
|
|
66673
67316
|
const assigned = /* @__PURE__ */ new Map();
|
|
66674
67317
|
const assign = (pendingId2) => {
|
|
@@ -66681,7 +67324,7 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
|
|
|
66681
67324
|
assigned.set(pendingId2, derived);
|
|
66682
67325
|
return derived;
|
|
66683
67326
|
}
|
|
66684
|
-
const fresh =
|
|
67327
|
+
const fresh = randomUUID6();
|
|
66685
67328
|
assigned.set(pendingId2, fresh);
|
|
66686
67329
|
return fresh;
|
|
66687
67330
|
};
|
|
@@ -66992,6 +67635,10 @@ function createPushProgressReporter(json) {
|
|
|
66992
67635
|
};
|
|
66993
67636
|
}
|
|
66994
67637
|
function projectTransactionProgressLabel(event) {
|
|
67638
|
+
if (event.type === "push-progress") {
|
|
67639
|
+
if (event.phase === "preparing") return "Preparing push\u2026";
|
|
67640
|
+
return `Uploading files\u2026 ${event.completedFiles.toLocaleString("en-US")}/${event.totalFiles.toLocaleString("en-US")} (${formatByteProgress(event.completedBytes)}/${formatByteProgress(event.totalBytes)})`;
|
|
67641
|
+
}
|
|
66995
67642
|
if (event.phase === "submitting") return "Pushing\u2026";
|
|
66996
67643
|
if (event.phase === "preparing") return "Preparing push\u2026";
|
|
66997
67644
|
if (event.phase === "waiting") return "Waiting to apply project transaction\u2026";
|
|
@@ -67009,6 +67656,11 @@ function projectTransactionProgressLabel(event) {
|
|
|
67009
67656
|
}
|
|
67010
67657
|
return "Finalizing project transaction\u2026";
|
|
67011
67658
|
}
|
|
67659
|
+
function formatByteProgress(bytes) {
|
|
67660
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
67661
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
67662
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
67663
|
+
}
|
|
67012
67664
|
function progressEventFromAccepted(accepted) {
|
|
67013
67665
|
return {
|
|
67014
67666
|
type: "project-transaction-progress",
|
|
@@ -67281,46 +67933,111 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67281
67933
|
console.log("Push cancelled.");
|
|
67282
67934
|
return;
|
|
67283
67935
|
}
|
|
67284
|
-
|
|
67285
|
-
|
|
67286
|
-
|
|
67287
|
-
|
|
67288
|
-
|
|
67289
|
-
|
|
67290
|
-
|
|
67291
|
-
|
|
67292
|
-
status.reconstructed
|
|
67293
|
-
);
|
|
67294
|
-
const operations = new Set(status.changes.map((change) => change.kind));
|
|
67295
|
-
const transactionOperation = operations.size === 1 ? status.changes[0].kind : "update";
|
|
67296
|
-
const client = NeoApiClient.forBaseUrl(workspace.config.apiBaseUrl);
|
|
67297
|
-
let stagedFiles = await stageProjectFilePushesV4({
|
|
67298
|
-
workspace,
|
|
67299
|
-
changes: status.changes,
|
|
67300
|
-
binaryChanges: status.binaryChanges ?? [],
|
|
67301
|
-
assignedIds: pendingAssignment.assigned,
|
|
67302
|
-
client
|
|
67936
|
+
let progress = createPushProgressReporter(options.json === true);
|
|
67937
|
+
progress.report({
|
|
67938
|
+
type: "push-progress",
|
|
67939
|
+
phase: "preparing",
|
|
67940
|
+
completedFiles: 0,
|
|
67941
|
+
totalFiles: status.binaryChanges?.length ?? 0,
|
|
67942
|
+
completedBytes: 0,
|
|
67943
|
+
totalBytes: 0
|
|
67303
67944
|
});
|
|
67945
|
+
const prepareAndStage = async () => {
|
|
67946
|
+
const source2 = await createPendingProjectSourceBundleV4(
|
|
67947
|
+
workspace,
|
|
67948
|
+
status,
|
|
67949
|
+
status.staticValueSeeds
|
|
67950
|
+
);
|
|
67951
|
+
const pendingAssignment2 = assignPendingIds(
|
|
67952
|
+
status.changes,
|
|
67953
|
+
status.staticValueSeeds,
|
|
67954
|
+
status.reconstructed
|
|
67955
|
+
);
|
|
67956
|
+
const operations = new Set(status.changes.map((change) => change.kind));
|
|
67957
|
+
const transactionOperation2 = operations.size === 1 ? status.changes[0].kind : "update";
|
|
67958
|
+
const client2 = NeoApiClient.forBaseUrl(workspace.config.apiBaseUrl);
|
|
67959
|
+
const transportChanges2 = status.changes.map((change) => ({
|
|
67960
|
+
recordKind: change.recordKind,
|
|
67961
|
+
recordId: change.recordId,
|
|
67962
|
+
operation: change.kind,
|
|
67963
|
+
nextData: change.kind === "delete" ? void 0 : stripServerDerivedNeoScript(change.nextData),
|
|
67964
|
+
deleted: change.kind === "delete" ? true : void 0,
|
|
67965
|
+
intent: createNeoCliPushIntent(change),
|
|
67966
|
+
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
67967
|
+
}));
|
|
67968
|
+
const transportSeeds2 = [...pendingAssignment2.staticValueSeeds].map(
|
|
67969
|
+
([memberId, seed]) => ({ memberId, ...seed })
|
|
67970
|
+
);
|
|
67971
|
+
const files = prepareProjectFilePushesV4({
|
|
67972
|
+
workspace,
|
|
67973
|
+
changes: status.changes,
|
|
67974
|
+
binaryChanges: status.binaryChanges ?? [],
|
|
67975
|
+
assignedIds: pendingAssignment2.assigned
|
|
67976
|
+
});
|
|
67977
|
+
verifyProjectSourceCommitAgainstStateV4({
|
|
67978
|
+
projectId: workspace.config.projectId,
|
|
67979
|
+
versionId: workspace.config.versionId,
|
|
67980
|
+
stateRecords: workspace.state.records,
|
|
67981
|
+
files: source2.files,
|
|
67982
|
+
changes: transportChanges2,
|
|
67983
|
+
staticValueSeeds: transportSeeds2,
|
|
67984
|
+
pendingIdAssignments: Object.fromEntries(pendingAssignment2.assigned),
|
|
67985
|
+
stagedFiles: files
|
|
67986
|
+
});
|
|
67987
|
+
const stagedFiles2 = await stageProjectFilePushesV4({
|
|
67988
|
+
workspace,
|
|
67989
|
+
changes: status.changes,
|
|
67990
|
+
binaryChanges: status.binaryChanges ?? [],
|
|
67991
|
+
assignedIds: pendingAssignment2.assigned,
|
|
67992
|
+
client: client2,
|
|
67993
|
+
prepared: files,
|
|
67994
|
+
onProgress: (upload) => progress.report({
|
|
67995
|
+
type: "push-progress",
|
|
67996
|
+
phase: "uploading",
|
|
67997
|
+
...upload
|
|
67998
|
+
})
|
|
67999
|
+
});
|
|
68000
|
+
return {
|
|
68001
|
+
source: source2,
|
|
68002
|
+
pendingAssignment: pendingAssignment2,
|
|
68003
|
+
transactionOperation: transactionOperation2,
|
|
68004
|
+
client: client2,
|
|
68005
|
+
transportChanges: transportChanges2,
|
|
68006
|
+
transportSeeds: transportSeeds2,
|
|
68007
|
+
preparedFiles: files,
|
|
68008
|
+
stagedFiles: stagedFiles2
|
|
68009
|
+
};
|
|
68010
|
+
};
|
|
68011
|
+
let preparedPush;
|
|
68012
|
+
try {
|
|
68013
|
+
preparedPush = await prepareAndStage();
|
|
68014
|
+
} catch (error) {
|
|
68015
|
+
progress.stop();
|
|
68016
|
+
if (error instanceof ProjectFilePushCancelledError) {
|
|
68017
|
+
if (options.json !== true) console.error("Push cancelled.");
|
|
68018
|
+
process.exitCode = 130;
|
|
68019
|
+
return;
|
|
68020
|
+
}
|
|
68021
|
+
throw error;
|
|
68022
|
+
}
|
|
68023
|
+
const {
|
|
68024
|
+
source,
|
|
68025
|
+
pendingAssignment,
|
|
68026
|
+
transactionOperation,
|
|
68027
|
+
client,
|
|
68028
|
+
transportChanges,
|
|
68029
|
+
transportSeeds,
|
|
68030
|
+
preparedFiles
|
|
68031
|
+
} = preparedPush;
|
|
68032
|
+
let { stagedFiles } = preparedPush;
|
|
67304
68033
|
const commit = async (force) => await client.post(
|
|
67305
68034
|
`/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/schema/commit`,
|
|
67306
68035
|
{
|
|
67307
68036
|
operation: transactionOperation,
|
|
67308
|
-
changes:
|
|
67309
|
-
|
|
67310
|
-
recordKind: change.recordKind,
|
|
67311
|
-
recordId: change.recordId,
|
|
67312
|
-
operation: change.kind,
|
|
67313
|
-
nextData: change.kind === "delete" ? void 0 : stripServerDerivedNeoScript(change.nextData),
|
|
67314
|
-
deleted: change.kind === "delete" ? true : void 0,
|
|
67315
|
-
intent: createNeoCliPushIntent(change),
|
|
67316
|
-
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
67317
|
-
};
|
|
67318
|
-
}),
|
|
67319
|
-
staticValueSeeds: [...pendingAssignment.staticValueSeeds].map(
|
|
67320
|
-
([memberId, seed]) => ({ memberId, ...seed })
|
|
67321
|
-
),
|
|
68037
|
+
changes: transportChanges,
|
|
68038
|
+
staticValueSeeds: transportSeeds,
|
|
67322
68039
|
stagedFiles,
|
|
67323
|
-
sourceBundle,
|
|
68040
|
+
sourceBundle: source.bundle,
|
|
67324
68041
|
pendingIdAssignments: Object.fromEntries(pendingAssignment.assigned),
|
|
67325
68042
|
summary: options.summary ?? "neo push"
|
|
67326
68043
|
},
|
|
@@ -67434,7 +68151,6 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67434
68151
|
if (options.json !== true) success("Push complete.");
|
|
67435
68152
|
return true;
|
|
67436
68153
|
};
|
|
67437
|
-
let progress = createPushProgressReporter(options.json === true);
|
|
67438
68154
|
progress.report({
|
|
67439
68155
|
type: "project-transaction-progress",
|
|
67440
68156
|
transactionId: null,
|
|
@@ -67467,28 +68183,39 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67467
68183
|
fallback: false
|
|
67468
68184
|
})) {
|
|
67469
68185
|
progress = createPushProgressReporter(options.json === true);
|
|
67470
|
-
progress.report({
|
|
67471
|
-
type: "project-transaction-progress",
|
|
67472
|
-
transactionId: null,
|
|
67473
|
-
phase: "submitting",
|
|
67474
|
-
totalChangeCount: status.changes.length,
|
|
67475
|
-
appliedChangeCount: 0,
|
|
67476
|
-
totalChunkCount: null,
|
|
67477
|
-
appliedChunkCount: 0,
|
|
67478
|
-
errorCode: null,
|
|
67479
|
-
errorMessage: null
|
|
67480
|
-
});
|
|
67481
68186
|
try {
|
|
67482
68187
|
stagedFiles = await stageProjectFilePushesV4({
|
|
67483
68188
|
workspace,
|
|
67484
68189
|
changes: status.changes,
|
|
67485
68190
|
binaryChanges: status.binaryChanges ?? [],
|
|
67486
68191
|
assignedIds: pendingAssignment.assigned,
|
|
67487
|
-
client
|
|
68192
|
+
client,
|
|
68193
|
+
prepared: preparedFiles,
|
|
68194
|
+
onProgress: (upload) => progress.report({
|
|
68195
|
+
type: "push-progress",
|
|
68196
|
+
phase: "uploading",
|
|
68197
|
+
...upload
|
|
68198
|
+
})
|
|
68199
|
+
});
|
|
68200
|
+
progress.report({
|
|
68201
|
+
type: "project-transaction-progress",
|
|
68202
|
+
transactionId: null,
|
|
68203
|
+
phase: "submitting",
|
|
68204
|
+
totalChangeCount: status.changes.length,
|
|
68205
|
+
appliedChangeCount: 0,
|
|
68206
|
+
totalChunkCount: null,
|
|
68207
|
+
appliedChunkCount: 0,
|
|
68208
|
+
errorCode: null,
|
|
68209
|
+
errorMessage: null
|
|
67488
68210
|
});
|
|
67489
68211
|
result = await commit(true);
|
|
67490
68212
|
} catch (retryError) {
|
|
67491
68213
|
progress.stop();
|
|
68214
|
+
if (retryError instanceof ProjectFilePushCancelledError) {
|
|
68215
|
+
if (options.json !== true) console.error("Push cancelled.");
|
|
68216
|
+
process.exitCode = 130;
|
|
68217
|
+
return;
|
|
68218
|
+
}
|
|
67492
68219
|
if (retryError instanceof NeoApiError) {
|
|
67493
68220
|
reportPushRejection(retryError.status, retryError.body);
|
|
67494
68221
|
process.exitCode = 1;
|
|
@@ -67617,17 +68344,19 @@ async function createPendingProjectSourceBundleV4(workspace, status, staticValue
|
|
|
67617
68344
|
}
|
|
67618
68345
|
}
|
|
67619
68346
|
const emission = emitProjectDocumentFilesV4(records2);
|
|
67620
|
-
|
|
67621
|
-
|
|
67622
|
-
|
|
67623
|
-
|
|
67624
|
-
|
|
67625
|
-
|
|
67626
|
-
|
|
67627
|
-
|
|
67628
|
-
|
|
67629
|
-
|
|
67630
|
-
|
|
68347
|
+
const files = emission.files.map((file) => {
|
|
68348
|
+
const kind = neoProjectSourceKind(file.path);
|
|
68349
|
+
if (kind === null) {
|
|
68350
|
+
throw new Error(
|
|
68351
|
+
`Emitted project source bundle file ${JSON.stringify(file.path)} is not a recognized Neo source path.`
|
|
68352
|
+
);
|
|
68353
|
+
}
|
|
68354
|
+
return { path: file.path, kind, content: file.content };
|
|
68355
|
+
});
|
|
68356
|
+
return {
|
|
68357
|
+
files,
|
|
68358
|
+
bundle: await createProjectSourceBundle(files)
|
|
68359
|
+
};
|
|
67631
68360
|
}
|
|
67632
68361
|
function staticSeedBindingMemberRecord(projectId, bindingMember, timestamp) {
|
|
67633
68362
|
return {
|
|
@@ -68018,11 +68747,11 @@ ${finalErrors.map(
|
|
|
68018
68747
|
for (const recordState of Object.values(workspace.state.records)) {
|
|
68019
68748
|
const previousPath = recordState.file;
|
|
68020
68749
|
if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
|
|
68021
|
-
const absolute =
|
|
68750
|
+
const absolute = join16(workspace.root, previousPath);
|
|
68022
68751
|
if (existsSync12(absolute)) rmSync6(absolute);
|
|
68023
68752
|
}
|
|
68024
68753
|
for (const file of files) {
|
|
68025
|
-
const absolute =
|
|
68754
|
+
const absolute = join16(workspace.root, file.path);
|
|
68026
68755
|
mkdirSync11(dirname7(absolute), { recursive: true });
|
|
68027
68756
|
const existing = existsSync12(absolute) ? readFileSync13(absolute, "utf8") : null;
|
|
68028
68757
|
if (existing !== file.content)
|
|
@@ -68702,6 +69431,7 @@ var init_push = __esm({
|
|
|
68702
69431
|
init_source_diagnostics();
|
|
68703
69432
|
init_projection();
|
|
68704
69433
|
init_project_file_push();
|
|
69434
|
+
init_trusted_commit_verification();
|
|
68705
69435
|
init_world_system_classes();
|
|
68706
69436
|
init_project_manifest();
|
|
68707
69437
|
init_merge();
|
|
@@ -68744,7 +69474,7 @@ __export(dev_exports, {
|
|
|
68744
69474
|
runDev: () => runDev
|
|
68745
69475
|
});
|
|
68746
69476
|
import { watch } from "node:fs";
|
|
68747
|
-
import { join as
|
|
69477
|
+
import { join as join17 } from "node:path";
|
|
68748
69478
|
import { emitKeypressEvents } from "node:readline";
|
|
68749
69479
|
import { ConvexClient } from "convex/browser";
|
|
68750
69480
|
function isSchemaSignal(value) {
|
|
@@ -68851,7 +69581,7 @@ async function runDev(workspace, options) {
|
|
|
68851
69581
|
};
|
|
68852
69582
|
for (const dir of ["Classes", "Enums"]) {
|
|
68853
69583
|
try {
|
|
68854
|
-
watch(
|
|
69584
|
+
watch(join17(workspace.root, dir), { persistent: true }, onFileChange);
|
|
68855
69585
|
} catch {
|
|
68856
69586
|
}
|
|
68857
69587
|
}
|
|
@@ -68907,7 +69637,7 @@ __export(resolve_exports, {
|
|
|
68907
69637
|
workspaceFilePath: () => workspaceFilePath
|
|
68908
69638
|
});
|
|
68909
69639
|
import { readFileSync as readFileSync14, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "node:fs";
|
|
68910
|
-
import { join as
|
|
69640
|
+
import { join as join18 } from "node:path";
|
|
68911
69641
|
function runResolve(workspace, side) {
|
|
68912
69642
|
let resolvedFiles = 0;
|
|
68913
69643
|
for (const filePath of listProjectSourceFilesV4(workspace.root)) {
|
|
@@ -68922,12 +69652,12 @@ function runResolve(workspace, side) {
|
|
|
68922
69652
|
const binary = state.projectBinary;
|
|
68923
69653
|
const conflict2 = binary?.conflict;
|
|
68924
69654
|
if (binary === void 0 || conflict2 === void 0) continue;
|
|
68925
|
-
const destination =
|
|
69655
|
+
const destination = join18(workspace.root, binary.path);
|
|
68926
69656
|
if (side === "theirs") {
|
|
68927
69657
|
if (conflict2.remoteSha256 !== null && conflict2.artifactPath !== void 0) {
|
|
68928
69658
|
writeVerifiedBinaryDownloadV4(
|
|
68929
69659
|
destination,
|
|
68930
|
-
readFileSync14(
|
|
69660
|
+
readFileSync14(join18(workspace.root, conflict2.artifactPath)),
|
|
68931
69661
|
conflict2.remoteSha256
|
|
68932
69662
|
);
|
|
68933
69663
|
binary.sha256 = conflict2.remoteSha256;
|
|
@@ -68937,7 +69667,7 @@ function runResolve(workspace, side) {
|
|
|
68937
69667
|
}
|
|
68938
69668
|
}
|
|
68939
69669
|
if (conflict2.artifactPath !== void 0) {
|
|
68940
|
-
rmSync7(
|
|
69670
|
+
rmSync7(join18(workspace.root, conflict2.artifactPath), { force: true });
|
|
68941
69671
|
}
|
|
68942
69672
|
delete binary.conflict;
|
|
68943
69673
|
resolvedBinaries += 1;
|
|
@@ -68990,7 +69720,7 @@ function resolveMarkers(source, side) {
|
|
|
68990
69720
|
return output.join("\n");
|
|
68991
69721
|
}
|
|
68992
69722
|
function workspaceFilePath(workspace, file) {
|
|
68993
|
-
return
|
|
69723
|
+
return join18(workspace.root, file);
|
|
68994
69724
|
}
|
|
68995
69725
|
var init_resolve = __esm({
|
|
68996
69726
|
"src/commands/resolve.ts"() {
|