@neocompose/cli 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/neo.mjs +1184 -193
- package/package.json +1 -1
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) => {
|
|
@@ -36051,6 +36062,14 @@ var init_world_system_classes_generated = __esm({
|
|
|
36051
36062
|
defaultValue: { x: 1, y: 1, z: 0 },
|
|
36052
36063
|
required: true,
|
|
36053
36064
|
schemaKey: "Size"
|
|
36065
|
+
},
|
|
36066
|
+
{
|
|
36067
|
+
memberId: "system_4858148e-1c42-449d-8a03-c1601da529bd",
|
|
36068
|
+
memberKind: "bool",
|
|
36069
|
+
defaultValue: true,
|
|
36070
|
+
docsText: "When false, this object and its children are neither rendered nor collided with. The value stays live: member writes still apply and a running animation clip keeps playing. Disabling an object hides its whole subtree regardless of each child's own value, and re-enabling it restores exactly what was there.",
|
|
36071
|
+
required: true,
|
|
36072
|
+
schemaKey: "Enabled"
|
|
36054
36073
|
}
|
|
36055
36074
|
],
|
|
36056
36075
|
worldKind: "objectBase"
|
|
@@ -47688,6 +47707,24 @@ function assertAnimationClipDocumentValid(document) {
|
|
|
47688
47707
|
context.validateClipMember(member);
|
|
47689
47708
|
}
|
|
47690
47709
|
}
|
|
47710
|
+
function collectAnimationClipNestedOwnerWarnings(document) {
|
|
47711
|
+
try {
|
|
47712
|
+
return new AnimationValidationContext(
|
|
47713
|
+
document
|
|
47714
|
+
).collectNestedOwnerWarnings();
|
|
47715
|
+
} catch {
|
|
47716
|
+
return [];
|
|
47717
|
+
}
|
|
47718
|
+
}
|
|
47719
|
+
function compareNestedChildrenRowUseSites(left, right) {
|
|
47720
|
+
if (left.ownerClassName !== right.ownerClassName) {
|
|
47721
|
+
return left.ownerClassName < right.ownerClassName ? -1 : 1;
|
|
47722
|
+
}
|
|
47723
|
+
if (left.rowValueId !== right.rowValueId) {
|
|
47724
|
+
return left.rowValueId < right.rowValueId ? -1 : 1;
|
|
47725
|
+
}
|
|
47726
|
+
return 0;
|
|
47727
|
+
}
|
|
47691
47728
|
function isRecord3(value) {
|
|
47692
47729
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47693
47730
|
}
|
|
@@ -48257,13 +48294,19 @@ var init_animation_clips = __esm({
|
|
|
48257
48294
|
return typeof member.valueId === "string" ? this.valueById.get(member.valueId) ?? null : null;
|
|
48258
48295
|
}
|
|
48259
48296
|
memberRootNode(member) {
|
|
48260
|
-
const
|
|
48297
|
+
const node = this.optionalMemberRootNode(member);
|
|
48298
|
+
if (node === null) {
|
|
48299
|
+
throw new Error(
|
|
48300
|
+
`Animation clip "${member.name}" must have a composite default-value graph.`
|
|
48301
|
+
);
|
|
48302
|
+
}
|
|
48303
|
+
return node;
|
|
48304
|
+
}
|
|
48305
|
+
/** {@link memberRootNode} without the throw, for diagnostics-only readers. */
|
|
48306
|
+
optionalMemberRootNode(member) {
|
|
48261
48307
|
if (member.defaultValue !== void 0) {
|
|
48262
|
-
|
|
48263
|
-
|
|
48264
|
-
`Animation clip "${member.name}" must have a composite default-value graph.`
|
|
48265
|
-
);
|
|
48266
|
-
}
|
|
48308
|
+
const value = member.defaultValue.value;
|
|
48309
|
+
if (!isRecord3(value)) return null;
|
|
48267
48310
|
return {
|
|
48268
48311
|
id: `member-default:${member.id}`,
|
|
48269
48312
|
projectId: member.projectId,
|
|
@@ -48274,13 +48317,8 @@ var init_animation_clips = __esm({
|
|
|
48274
48317
|
};
|
|
48275
48318
|
}
|
|
48276
48319
|
const valueId = member.valueId;
|
|
48277
|
-
if (typeof valueId
|
|
48278
|
-
|
|
48279
|
-
if (stored !== void 0) return stored;
|
|
48280
|
-
}
|
|
48281
|
-
throw new Error(
|
|
48282
|
-
`Animation clip "${member.name}" must have a composite default-value graph.`
|
|
48283
|
-
);
|
|
48320
|
+
if (typeof valueId !== "string") return null;
|
|
48321
|
+
return this.valueById.get(valueId) ?? null;
|
|
48284
48322
|
}
|
|
48285
48323
|
optionalFieldNode(parent, classId, memberId) {
|
|
48286
48324
|
const field = this.field(classId, memberId);
|
|
@@ -48304,35 +48342,45 @@ var init_animation_clips = __esm({
|
|
|
48304
48342
|
}
|
|
48305
48343
|
requireListField(parent, classId, memberId, label) {
|
|
48306
48344
|
const field = this.requireField(classId, memberId, label);
|
|
48345
|
+
const ids = this.listFieldIds(parent, field);
|
|
48346
|
+
if (!Array.isArray(ids)) {
|
|
48347
|
+
throw new Error(`${label} must be an ordered list.`);
|
|
48348
|
+
}
|
|
48349
|
+
const inferredClassId = this.listEntryClassId(field.member);
|
|
48350
|
+
return ids.map((id2) => {
|
|
48351
|
+
if (typeof id2 !== "string" || !this.valueById.has(id2)) {
|
|
48352
|
+
throw new Error(`${label} references missing entry "${String(id2)}".`);
|
|
48353
|
+
}
|
|
48354
|
+
const entry = this.valueById.get(id2);
|
|
48355
|
+
return typeof entry.classId === "string" || inferredClassId === void 0 ? entry : { ...entry, classId: inferredClassId };
|
|
48356
|
+
});
|
|
48357
|
+
}
|
|
48358
|
+
/**
|
|
48359
|
+
* The raw list payload behind a field: an explicit instance edge wins even
|
|
48360
|
+
* when it is dangling, then the member default, then the legacy value row.
|
|
48361
|
+
*/
|
|
48362
|
+
listFieldIds(parent, field) {
|
|
48307
48363
|
const mapped = isRecord3(parent.value) ? parent.value[field.schemaKey] : null;
|
|
48308
|
-
let ids;
|
|
48309
48364
|
if (typeof mapped === "string") {
|
|
48310
|
-
|
|
48311
|
-
} else if (field.member.defaultValue !== void 0) {
|
|
48312
|
-
ids = field.member.defaultValue.value;
|
|
48313
|
-
} else {
|
|
48314
|
-
ids = typeof field.member.valueId === "string" ? this.valueById.get(field.member.valueId)?.value : void 0;
|
|
48365
|
+
return this.valueById.get(mapped)?.value;
|
|
48315
48366
|
}
|
|
48316
|
-
if (
|
|
48317
|
-
|
|
48367
|
+
if (field.member.defaultValue !== void 0) {
|
|
48368
|
+
return field.member.defaultValue.value;
|
|
48318
48369
|
}
|
|
48370
|
+
return typeof field.member.valueId === "string" ? this.valueById.get(field.member.valueId)?.value : void 0;
|
|
48371
|
+
}
|
|
48372
|
+
/** Class a list's rows carry when a row omits its own `classId`. */
|
|
48373
|
+
listEntryClassId(member) {
|
|
48319
48374
|
const listMember = {
|
|
48320
|
-
...
|
|
48321
|
-
...resolveMember2(
|
|
48375
|
+
...member,
|
|
48376
|
+
...resolveMember2(member, this.document.members)
|
|
48322
48377
|
};
|
|
48323
48378
|
const entryMember = isMemberList(listMember) ? this.memberById.get(listMember.entryMemberId) : void 0;
|
|
48324
48379
|
const resolvedEntryMember = entryMember === void 0 ? void 0 : {
|
|
48325
48380
|
...entryMember,
|
|
48326
48381
|
...resolveMember2(entryMember, this.document.members)
|
|
48327
48382
|
};
|
|
48328
|
-
|
|
48329
|
-
return ids.map((id2) => {
|
|
48330
|
-
if (typeof id2 !== "string" || !this.valueById.has(id2)) {
|
|
48331
|
-
throw new Error(`${label} references missing entry "${String(id2)}".`);
|
|
48332
|
-
}
|
|
48333
|
-
const entry = this.valueById.get(id2);
|
|
48334
|
-
return typeof entry.classId === "string" || inferredClassId === void 0 ? entry : { ...entry, classId: inferredClassId };
|
|
48335
|
-
});
|
|
48383
|
+
return isMemberClass(resolvedEntryMember) ? resolvedEntryMember.classId : void 0;
|
|
48336
48384
|
}
|
|
48337
48385
|
requireSingleLookupField(parent, classId, memberId, label) {
|
|
48338
48386
|
const value = this.scalarField(parent, classId, memberId);
|
|
@@ -48377,18 +48425,23 @@ var init_animation_clips = __esm({
|
|
|
48377
48425
|
return node.classId;
|
|
48378
48426
|
}
|
|
48379
48427
|
requireClassBinding(member, paramId, label) {
|
|
48428
|
+
const classId = this.optionalClassBinding(member, paramId);
|
|
48429
|
+
if (classId === null) {
|
|
48430
|
+
throw new Error(
|
|
48431
|
+
`${label} must bind its target generic to a Class member.`
|
|
48432
|
+
);
|
|
48433
|
+
}
|
|
48434
|
+
return classId;
|
|
48435
|
+
}
|
|
48436
|
+
/** {@link requireClassBinding} without the throw, for diagnostics-only readers. */
|
|
48437
|
+
optionalClassBinding(member, paramId) {
|
|
48380
48438
|
const binding = resolveInstanceEnv(
|
|
48381
48439
|
member.classId,
|
|
48382
48440
|
member.classArguments,
|
|
48383
48441
|
this.document.classes
|
|
48384
48442
|
).get(paramId);
|
|
48385
48443
|
const bindingMember = binding?.kind === "member" ? this.memberById.get(binding.memberId) : void 0;
|
|
48386
|
-
|
|
48387
|
-
throw new Error(
|
|
48388
|
-
`${label} must bind its target generic to a Class member.`
|
|
48389
|
-
);
|
|
48390
|
-
}
|
|
48391
|
-
return bindingMember.classId;
|
|
48444
|
+
return isMemberClass(bindingMember) ? bindingMember.classId : null;
|
|
48392
48445
|
}
|
|
48393
48446
|
requireClassMember(value) {
|
|
48394
48447
|
if (!isMemberClass(value)) throw new Error("Expected Class member.");
|
|
@@ -48425,6 +48478,188 @@ var init_animation_clips = __esm({
|
|
|
48425
48478
|
}
|
|
48426
48479
|
return false;
|
|
48427
48480
|
}
|
|
48481
|
+
// ---------------------------------------------------------------------------
|
|
48482
|
+
// P41 §2.3 SCAFFOLDING — DELETE EVERYTHING BELOW THIS BANNER WHEN P44 LANDS,
|
|
48483
|
+
// together with `collectAnimationClipNestedOwnerWarnings` and its tests. See
|
|
48484
|
+
// that function's doc block for why the check exists and why P44 retires it.
|
|
48485
|
+
// ---------------------------------------------------------------------------
|
|
48486
|
+
collectNestedOwnerWarnings() {
|
|
48487
|
+
const useSiteByClassId = this.nestedChildrenRowUseSites();
|
|
48488
|
+
if (useSiteByClassId.size === 0) return [];
|
|
48489
|
+
const warnings = [];
|
|
48490
|
+
for (const member of this.document.members) {
|
|
48491
|
+
if (!isMemberClass(member)) continue;
|
|
48492
|
+
if (!this.classHasWorldKind(member.classId, "animationClip")) continue;
|
|
48493
|
+
const ownerClassId2 = this.optionalClassBinding(
|
|
48494
|
+
member,
|
|
48495
|
+
WORLD_ANIMATION_CLIP_TARGET_PARAM_ID
|
|
48496
|
+
);
|
|
48497
|
+
if (ownerClassId2 === null) continue;
|
|
48498
|
+
const useSite = useSiteByClassId.get(ownerClassId2);
|
|
48499
|
+
if (useSite === void 0) continue;
|
|
48500
|
+
if (!this.clipDeclaresChildReferences(member)) continue;
|
|
48501
|
+
const ownerClassName = this.classById.get(ownerClassId2)?.name ?? ownerClassId2;
|
|
48502
|
+
const nestedRowClassName = this.classById.get(useSite.rowClassId)?.name ?? useSite.rowClassId;
|
|
48503
|
+
const nesting = useSite.rowClassId === ownerClassId2 ? "which is also used as a nested Children row" : `whose subclass "${nestedRowClassName}" is used as a nested Children row`;
|
|
48504
|
+
warnings.push({
|
|
48505
|
+
clipName: member.name,
|
|
48506
|
+
ownerClassName,
|
|
48507
|
+
nestedOwnerClassName: useSite.ownerClassName,
|
|
48508
|
+
nestedRowClassName,
|
|
48509
|
+
nestedRowValueId: useSite.rowValueId,
|
|
48510
|
+
message: `Animation clip "${member.name}" overrides or tracks children of "${ownerClassName}", ${nesting} (value "${useSite.rowValueId}" in class "${useSite.ownerClassName}"). A nested instance carries re-lowered copies of those rows, so the clip resolves none of them there. Give nested Children rows authored provenance (P44), or declare the child rows through a constructor (P43).`
|
|
48511
|
+
});
|
|
48512
|
+
}
|
|
48513
|
+
return warnings;
|
|
48514
|
+
}
|
|
48515
|
+
/**
|
|
48516
|
+
* Every class an authored `Children` list instantiates as a row, keyed by
|
|
48517
|
+
* that class and each of its ancestors — a nested row of a subclass inherits
|
|
48518
|
+
* the base class's clips, so the base is affected too.
|
|
48519
|
+
*
|
|
48520
|
+
* Both authoring shapes count. A class-default `Children` is one; a
|
|
48521
|
+
* `Children` list authored on a row inside one is the other, and it is the
|
|
48522
|
+
* shape P41 §3 itself writes — `CharacterBody.Children` holds a `HeadPart`
|
|
48523
|
+
* row whose own `Children` holds the hat. Scanning only class defaults would
|
|
48524
|
+
* miss every slot below the first level.
|
|
48525
|
+
*
|
|
48526
|
+
* A layer's directly placed objects hang off `NeoObjectLayerLink.Objects`, a
|
|
48527
|
+
* different member, so a directly placed class is never collected here.
|
|
48528
|
+
*/
|
|
48529
|
+
nestedChildrenRowUseSites() {
|
|
48530
|
+
const declaringClasses = /* @__PURE__ */ new Map();
|
|
48531
|
+
for (const schemaClass2 of this.document.classes) {
|
|
48532
|
+
for (const [schemaKey, memberId] of Object.entries(schemaClass2.schema)) {
|
|
48533
|
+
if (typeof memberId !== "string") continue;
|
|
48534
|
+
if (declaringClasses.has(memberId)) continue;
|
|
48535
|
+
declaringClasses.set(memberId, { schemaClass: schemaClass2, schemaKey });
|
|
48536
|
+
}
|
|
48537
|
+
}
|
|
48538
|
+
const sites = [];
|
|
48539
|
+
const pending = [];
|
|
48540
|
+
for (const member of this.document.members) {
|
|
48541
|
+
if (!this.memberDescendsFrom(member.id, WORLD_OBJECT_CHILDREN_MEMBER_ID)) {
|
|
48542
|
+
continue;
|
|
48543
|
+
}
|
|
48544
|
+
const declaration = declaringClasses.get(member.id);
|
|
48545
|
+
if (declaration === void 0) continue;
|
|
48546
|
+
const node = this.resolveDefinitionChild(
|
|
48547
|
+
null,
|
|
48548
|
+
declaration.schemaKey,
|
|
48549
|
+
member
|
|
48550
|
+
);
|
|
48551
|
+
pending.push(
|
|
48552
|
+
...this.childrenRowUseSites(node, member, declaration.schemaClass.name)
|
|
48553
|
+
);
|
|
48554
|
+
}
|
|
48555
|
+
const visited = /* @__PURE__ */ new Set();
|
|
48556
|
+
for (let index = 0; index < pending.length; index += 1) {
|
|
48557
|
+
const site = pending[index];
|
|
48558
|
+
if (site === void 0) continue;
|
|
48559
|
+
if (visited.has(site.rowValueId)) continue;
|
|
48560
|
+
visited.add(site.rowValueId);
|
|
48561
|
+
sites.push(site);
|
|
48562
|
+
const row = this.valueById.get(site.rowValueId);
|
|
48563
|
+
if (row === void 0) continue;
|
|
48564
|
+
const field = this.field(
|
|
48565
|
+
site.rowClassId,
|
|
48566
|
+
WORLD_OBJECT_CHILDREN_MEMBER_ID
|
|
48567
|
+
);
|
|
48568
|
+
if (field === null) continue;
|
|
48569
|
+
const rowClassName = this.classById.get(site.rowClassId)?.name ?? site.rowClassId;
|
|
48570
|
+
pending.push(
|
|
48571
|
+
...this.childrenRowUseSites(
|
|
48572
|
+
{ ...row, value: this.listFieldIds(row, field) },
|
|
48573
|
+
field.member,
|
|
48574
|
+
rowClassName
|
|
48575
|
+
)
|
|
48576
|
+
);
|
|
48577
|
+
}
|
|
48578
|
+
sites.sort(compareNestedChildrenRowUseSites);
|
|
48579
|
+
const useSiteByClassId = /* @__PURE__ */ new Map();
|
|
48580
|
+
for (const site of sites) {
|
|
48581
|
+
if (useSiteByClassId.has(site.rowClassId)) continue;
|
|
48582
|
+
useSiteByClassId.set(site.rowClassId, site);
|
|
48583
|
+
}
|
|
48584
|
+
for (const site of sites) {
|
|
48585
|
+
for (const classId of this.classAndAncestorIds(site.rowClassId)) {
|
|
48586
|
+
if (useSiteByClassId.has(classId)) continue;
|
|
48587
|
+
useSiteByClassId.set(classId, site);
|
|
48588
|
+
}
|
|
48589
|
+
}
|
|
48590
|
+
return useSiteByClassId;
|
|
48591
|
+
}
|
|
48592
|
+
/** The rows an authored `Children` list holds, as use sites of `ownerClassName`. */
|
|
48593
|
+
childrenRowUseSites(node, listMember, ownerClassName) {
|
|
48594
|
+
if (!Array.isArray(node?.value)) return [];
|
|
48595
|
+
const entryClassId = this.listEntryClassId(listMember);
|
|
48596
|
+
const sites = [];
|
|
48597
|
+
for (const rowValueId of node.value) {
|
|
48598
|
+
if (typeof rowValueId !== "string") continue;
|
|
48599
|
+
const row = this.valueById.get(rowValueId);
|
|
48600
|
+
const rowClassId = typeof row?.classId === "string" ? row.classId : entryClassId;
|
|
48601
|
+
if (rowClassId === void 0) continue;
|
|
48602
|
+
sites.push({ ownerClassName, rowValueId, rowClassId });
|
|
48603
|
+
}
|
|
48604
|
+
return sites;
|
|
48605
|
+
}
|
|
48606
|
+
/** True when the clip names at least one child through a track or override. */
|
|
48607
|
+
clipDeclaresChildReferences(clipMember) {
|
|
48608
|
+
const clipNode = this.optionalMemberRootNode(clipMember);
|
|
48609
|
+
if (clipNode === null) return false;
|
|
48610
|
+
const tracks = this.optionalListRows(
|
|
48611
|
+
clipNode,
|
|
48612
|
+
clipMember.classId,
|
|
48613
|
+
WORLD_ANIMATION_CLIP_TRACKS_MEMBER_ID
|
|
48614
|
+
);
|
|
48615
|
+
if (tracks !== null && tracks.length > 0) return true;
|
|
48616
|
+
const frames = this.optionalListRows(
|
|
48617
|
+
clipNode,
|
|
48618
|
+
clipMember.classId,
|
|
48619
|
+
WORLD_ANIMATION_CLIP_FRAMES_MEMBER_ID
|
|
48620
|
+
) ?? [];
|
|
48621
|
+
for (const frame of frames) {
|
|
48622
|
+
if (typeof frame.classId !== "string") continue;
|
|
48623
|
+
const childOverrides = this.optionalListRows(
|
|
48624
|
+
frame,
|
|
48625
|
+
frame.classId,
|
|
48626
|
+
WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_MEMBER_ID
|
|
48627
|
+
);
|
|
48628
|
+
if (childOverrides !== null && childOverrides.length > 0) return true;
|
|
48629
|
+
}
|
|
48630
|
+
return false;
|
|
48631
|
+
}
|
|
48632
|
+
/** {@link requireListField} without the throws, for diagnostics-only readers. */
|
|
48633
|
+
optionalListRows(parent, classId, memberId) {
|
|
48634
|
+
const field = this.field(classId, memberId);
|
|
48635
|
+
if (field === null) return null;
|
|
48636
|
+
const ids = this.listFieldIds(parent, field);
|
|
48637
|
+
if (!Array.isArray(ids)) return null;
|
|
48638
|
+
const inferredClassId = this.listEntryClassId(field.member);
|
|
48639
|
+
const rows = [];
|
|
48640
|
+
for (const id2 of ids) {
|
|
48641
|
+
if (typeof id2 !== "string") return null;
|
|
48642
|
+
const entry = this.valueById.get(id2);
|
|
48643
|
+
if (entry === void 0) return null;
|
|
48644
|
+
rows.push(
|
|
48645
|
+
typeof entry.classId === "string" || inferredClassId === void 0 ? entry : { ...entry, classId: inferredClassId }
|
|
48646
|
+
);
|
|
48647
|
+
}
|
|
48648
|
+
return rows;
|
|
48649
|
+
}
|
|
48650
|
+
/** The class itself followed by every ancestor it extends. */
|
|
48651
|
+
classAndAncestorIds(classId) {
|
|
48652
|
+
const ids = [];
|
|
48653
|
+
const visited = /* @__PURE__ */ new Set();
|
|
48654
|
+
let current = this.classById.get(classId);
|
|
48655
|
+
if (current === void 0) return [classId];
|
|
48656
|
+
while (current !== void 0 && !visited.has(current.id)) {
|
|
48657
|
+
visited.add(current.id);
|
|
48658
|
+
ids.push(current.id);
|
|
48659
|
+
current = current.extendsClassId ? this.classById.get(current.extendsClassId) : void 0;
|
|
48660
|
+
}
|
|
48661
|
+
return ids;
|
|
48662
|
+
}
|
|
48428
48663
|
};
|
|
48429
48664
|
}
|
|
48430
48665
|
});
|
|
@@ -48703,6 +48938,7 @@ function compareWorkspacePaths(left, right) {
|
|
|
48703
48938
|
function computeWorkspaceStatus(workspace, options = {}) {
|
|
48704
48939
|
const conflictedFiles = [];
|
|
48705
48940
|
const parseErrors = [];
|
|
48941
|
+
const warnings = [];
|
|
48706
48942
|
const migrationSources = [];
|
|
48707
48943
|
const projectSources = [];
|
|
48708
48944
|
const sourceEntries = options.virtualSourceFiles === void 0 ? listProjectSourceFilesV4(workspace.root).map((filePath) => ({
|
|
@@ -48732,6 +48968,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
48732
48968
|
changes: [],
|
|
48733
48969
|
conflictedFiles,
|
|
48734
48970
|
parseErrors,
|
|
48971
|
+
warnings,
|
|
48735
48972
|
reconstructed: /* @__PURE__ */ new Map(),
|
|
48736
48973
|
staticValueSeeds: /* @__PURE__ */ new Map(),
|
|
48737
48974
|
binaryChanges: [],
|
|
@@ -48780,6 +49017,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
48780
49017
|
changes: [],
|
|
48781
49018
|
conflictedFiles,
|
|
48782
49019
|
parseErrors,
|
|
49020
|
+
warnings,
|
|
48783
49021
|
reconstructed: /* @__PURE__ */ new Map(),
|
|
48784
49022
|
staticValueSeeds,
|
|
48785
49023
|
binaryChanges: [],
|
|
@@ -48804,6 +49042,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
48804
49042
|
changes: [],
|
|
48805
49043
|
conflictedFiles,
|
|
48806
49044
|
parseErrors,
|
|
49045
|
+
warnings,
|
|
48807
49046
|
reconstructed: /* @__PURE__ */ new Map(),
|
|
48808
49047
|
staticValueSeeds,
|
|
48809
49048
|
binaryChanges: [],
|
|
@@ -48851,6 +49090,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
48851
49090
|
changes: [],
|
|
48852
49091
|
conflictedFiles,
|
|
48853
49092
|
parseErrors,
|
|
49093
|
+
warnings,
|
|
48854
49094
|
reconstructed: /* @__PURE__ */ new Map(),
|
|
48855
49095
|
staticValueSeeds: /* @__PURE__ */ new Map(),
|
|
48856
49096
|
binaryChanges: [],
|
|
@@ -49067,15 +49307,16 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
49067
49307
|
)) {
|
|
49068
49308
|
parseErrors.push(new SchemaSourceError(message, "<project-files>", 1, 1));
|
|
49069
49309
|
}
|
|
49310
|
+
let validatedAnimationRecords = null;
|
|
49070
49311
|
try {
|
|
49071
|
-
|
|
49072
|
-
|
|
49073
|
-
|
|
49074
|
-
|
|
49075
|
-
|
|
49076
|
-
staticValueSeeds
|
|
49077
|
-
)
|
|
49312
|
+
const animationRecords = prospectiveAnimationRecords(
|
|
49313
|
+
workspace.state.records,
|
|
49314
|
+
reconstructed3,
|
|
49315
|
+
changes,
|
|
49316
|
+
staticValueSeeds
|
|
49078
49317
|
);
|
|
49318
|
+
validateProspectiveAnimationRecordsV4(animationRecords);
|
|
49319
|
+
validatedAnimationRecords = animationRecords;
|
|
49079
49320
|
} catch (error) {
|
|
49080
49321
|
parseErrors.push(
|
|
49081
49322
|
new SchemaSourceError(
|
|
@@ -49086,6 +49327,11 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
49086
49327
|
)
|
|
49087
49328
|
);
|
|
49088
49329
|
}
|
|
49330
|
+
if (validatedAnimationRecords !== null) {
|
|
49331
|
+
warnings.push(
|
|
49332
|
+
...collectProspectiveAnimationWarningsV4(validatedAnimationRecords)
|
|
49333
|
+
);
|
|
49334
|
+
}
|
|
49089
49335
|
for (const binary of binaryChanges) {
|
|
49090
49336
|
if (binary.action !== "missing-local") continue;
|
|
49091
49337
|
parseErrors.push(
|
|
@@ -49101,6 +49347,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
49101
49347
|
changes,
|
|
49102
49348
|
conflictedFiles,
|
|
49103
49349
|
parseErrors,
|
|
49350
|
+
warnings,
|
|
49104
49351
|
reconstructed: reconstructed3,
|
|
49105
49352
|
staticValueSeeds,
|
|
49106
49353
|
binaryChanges,
|
|
@@ -49108,11 +49355,27 @@ function computeWorkspaceStatus(workspace, options = {}) {
|
|
|
49108
49355
|
};
|
|
49109
49356
|
}
|
|
49110
49357
|
function validateProspectiveAnimationRecordsV4(records2) {
|
|
49358
|
+
const document = prospectiveAnimationDocumentV4(records2);
|
|
49359
|
+
if (document === null) return;
|
|
49360
|
+
assertAnimationClipDocumentValid(document);
|
|
49361
|
+
}
|
|
49362
|
+
function collectProspectiveAnimationWarningsV4(records2) {
|
|
49363
|
+
try {
|
|
49364
|
+
const document = prospectiveAnimationDocumentV4(records2);
|
|
49365
|
+
if (document === null) return [];
|
|
49366
|
+
return collectAnimationClipNestedOwnerWarnings(document).map(
|
|
49367
|
+
(warning) => warning.message
|
|
49368
|
+
);
|
|
49369
|
+
} catch {
|
|
49370
|
+
return [];
|
|
49371
|
+
}
|
|
49372
|
+
}
|
|
49373
|
+
function prospectiveAnimationDocumentV4(records2) {
|
|
49111
49374
|
const candidates = [...records2];
|
|
49112
49375
|
const hasAnimationSchema = candidates.some(
|
|
49113
49376
|
(record3) => record3.recordKind === "class" && (Array.isArray(record3.data.constructorProjections) || isObjectRecord2(record3.data.system) && typeof record3.data.system.worldKind === "string" && record3.data.system.worldKind.startsWith("animation"))
|
|
49114
49377
|
);
|
|
49115
|
-
if (!hasAnimationSchema) return;
|
|
49378
|
+
if (!hasAnimationSchema) return null;
|
|
49116
49379
|
let project;
|
|
49117
49380
|
const classes = [];
|
|
49118
49381
|
const members = [];
|
|
@@ -49148,8 +49411,8 @@ function validateProspectiveAnimationRecordsV4(records2) {
|
|
|
49148
49411
|
values.push(record3.data);
|
|
49149
49412
|
}
|
|
49150
49413
|
}
|
|
49151
|
-
if (project === void 0) return;
|
|
49152
|
-
|
|
49414
|
+
if (project === void 0) return null;
|
|
49415
|
+
return { project, classes, members, values };
|
|
49153
49416
|
}
|
|
49154
49417
|
function serverEnvelope(stored) {
|
|
49155
49418
|
if (!isObjectRecord2(stored)) return {};
|
|
@@ -51477,7 +51740,7 @@ var init_http = __esm({
|
|
|
51477
51740
|
}
|
|
51478
51741
|
return new _NeoApiClient(apiBaseUrl, token);
|
|
51479
51742
|
}
|
|
51480
|
-
async post(path, body, headers) {
|
|
51743
|
+
async post(path, body, headers, options = {}) {
|
|
51481
51744
|
const url = new URL(path, this.apiBaseUrl).toString();
|
|
51482
51745
|
const response = await fetch(url, {
|
|
51483
51746
|
method: "POST",
|
|
@@ -51486,7 +51749,8 @@ var init_http = __esm({
|
|
|
51486
51749
|
"Content-Type": "application/json",
|
|
51487
51750
|
...headers
|
|
51488
51751
|
},
|
|
51489
|
-
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
51752
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
51753
|
+
signal: options.signal
|
|
51490
51754
|
});
|
|
51491
51755
|
const text = await response.text();
|
|
51492
51756
|
let parsed = null;
|
|
@@ -59572,13 +59836,13 @@ function ownedObjectChildMember(row, sourceMember, key, ctx) {
|
|
|
59572
59836
|
return memberForCustomSchemaValue(classId, key, ctx);
|
|
59573
59837
|
}
|
|
59574
59838
|
function freshCloneValueId() {
|
|
59575
|
-
const
|
|
59576
|
-
if (
|
|
59839
|
+
const randomUUID7 = globalThis.crypto?.randomUUID;
|
|
59840
|
+
if (randomUUID7 === void 0) {
|
|
59577
59841
|
throw new NSGetterRuntimeError(
|
|
59578
59842
|
"Class.Clone cannot mint a value id because crypto.randomUUID is unavailable."
|
|
59579
59843
|
);
|
|
59580
59844
|
}
|
|
59581
|
-
return
|
|
59845
|
+
return randomUUID7.call(globalThis.crypto);
|
|
59582
59846
|
}
|
|
59583
59847
|
function parseDialogueMemoryPointer(pointer) {
|
|
59584
59848
|
if (typeof pointer !== "string") return null;
|
|
@@ -66504,80 +66768,154 @@ function ensureProjectFileBinaryChangesV4(args) {
|
|
|
66504
66768
|
});
|
|
66505
66769
|
}
|
|
66506
66770
|
}
|
|
66771
|
+
function prepareProjectFilePushesV4(args) {
|
|
66772
|
+
const prepared = [];
|
|
66773
|
+
for (const binary of args.binaryChanges) {
|
|
66774
|
+
if (binary.action !== "create" && binary.action !== "upload") continue;
|
|
66775
|
+
const recordId = args.assignedIds.get(binary.fileId) ?? binary.fileId;
|
|
66776
|
+
const change = args.changes.find(
|
|
66777
|
+
(candidate) => candidate.recordKind === "project-file" && candidate.recordId === recordId
|
|
66778
|
+
);
|
|
66779
|
+
if (change === void 0) {
|
|
66780
|
+
throw new Error(
|
|
66781
|
+
`Project file ${recordId} has upload bytes but no source change.`
|
|
66782
|
+
);
|
|
66783
|
+
}
|
|
66784
|
+
if (!isObjectRecord2(change.nextData)) {
|
|
66785
|
+
throw new Error(
|
|
66786
|
+
`Project file ${recordId} has upload bytes but its source change has no record data.`
|
|
66787
|
+
);
|
|
66788
|
+
}
|
|
66789
|
+
const absolute = join14(args.workspace.root, binary.path);
|
|
66790
|
+
const bytes = new Uint8Array(readFileSync12(absolute));
|
|
66791
|
+
const digest = sha256Bytes(bytes);
|
|
66792
|
+
if (binary.localSha256 !== null && digest !== binary.localSha256) {
|
|
66793
|
+
throw new Error(
|
|
66794
|
+
`Project file ${binary.path} changed after status was computed; run push again.`
|
|
66795
|
+
);
|
|
66796
|
+
}
|
|
66797
|
+
const mimeType = binary.mimeType;
|
|
66798
|
+
if (mimeType === null) {
|
|
66799
|
+
throw new Error(`Project file ${binary.path} has no MIME type.`);
|
|
66800
|
+
}
|
|
66801
|
+
prepared.push({
|
|
66802
|
+
uploadToken: `${recordId}-${prepared.length}`,
|
|
66803
|
+
recordId,
|
|
66804
|
+
replaceFileId: binary.action === "upload" ? recordId : null,
|
|
66805
|
+
name: basename2(binary.path),
|
|
66806
|
+
fileType: binary.kind,
|
|
66807
|
+
mimeType,
|
|
66808
|
+
byteLength: bytes.byteLength,
|
|
66809
|
+
contentSha256: digest,
|
|
66810
|
+
audioDurationSeconds: binary.kind === "audio" && typeof change.nextData.audioDurationSeconds === "number" ? change.nextData.audioDurationSeconds : null,
|
|
66811
|
+
bytes
|
|
66812
|
+
});
|
|
66813
|
+
}
|
|
66814
|
+
return prepared;
|
|
66815
|
+
}
|
|
66507
66816
|
async function stageProjectFilePushesV4(args) {
|
|
66817
|
+
const prepared = args.prepared ?? prepareProjectFilePushesV4({
|
|
66818
|
+
workspace: args.workspace,
|
|
66819
|
+
changes: args.changes,
|
|
66820
|
+
binaryChanges: args.binaryChanges,
|
|
66821
|
+
assignedIds: args.assignedIds
|
|
66822
|
+
});
|
|
66508
66823
|
const staged = [];
|
|
66509
66824
|
const cleanupKeys = [];
|
|
66510
66825
|
const put = args.put ?? fetch;
|
|
66826
|
+
const interruptController = new AbortController();
|
|
66827
|
+
const interrupt = () => interruptController.abort(new ProjectFilePushCancelledError());
|
|
66828
|
+
process.once("SIGINT", interrupt);
|
|
66829
|
+
const signal = combineSignals(args.signal, interruptController.signal);
|
|
66830
|
+
const totalBytes = prepared.reduce((sum, file) => sum + file.byteLength, 0);
|
|
66831
|
+
let completedBytes = 0;
|
|
66832
|
+
let completedFiles = 0;
|
|
66833
|
+
const report = () => args.onProgress?.({
|
|
66834
|
+
completedFiles,
|
|
66835
|
+
totalFiles: prepared.length,
|
|
66836
|
+
completedBytes,
|
|
66837
|
+
totalBytes
|
|
66838
|
+
});
|
|
66839
|
+
report();
|
|
66511
66840
|
try {
|
|
66512
|
-
for (
|
|
66513
|
-
|
|
66514
|
-
|
|
66515
|
-
|
|
66516
|
-
(candidate) => candidate.recordKind === "project-file" && candidate.recordId === recordId
|
|
66841
|
+
for (let offset = 0; offset < prepared.length; offset += PROJECT_FILE_UPLOAD_BATCH_SIZE) {
|
|
66842
|
+
const batch = prepared.slice(
|
|
66843
|
+
offset,
|
|
66844
|
+
offset + PROJECT_FILE_UPLOAD_BATCH_SIZE
|
|
66517
66845
|
);
|
|
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(
|
|
66846
|
+
const presign = await postWithTimeout(
|
|
66847
|
+
args.client,
|
|
66538
66848
|
versionPath2(args.workspace, "upload"),
|
|
66539
66849
|
{
|
|
66540
66850
|
route: "projectFile",
|
|
66541
66851
|
metadata: {
|
|
66542
|
-
|
|
66543
|
-
|
|
66544
|
-
|
|
66545
|
-
|
|
66852
|
+
deferredSourceCommit: true,
|
|
66853
|
+
uploads: batch.map((file) => ({
|
|
66854
|
+
uploadToken: file.uploadToken,
|
|
66855
|
+
projectFileId: file.recordId,
|
|
66856
|
+
replaceFileId: file.replaceFileId,
|
|
66857
|
+
name: file.name,
|
|
66858
|
+
contentSha256: file.contentSha256
|
|
66859
|
+
}))
|
|
66546
66860
|
},
|
|
66547
|
-
files:
|
|
66548
|
-
|
|
66861
|
+
files: batch.map((file) => ({
|
|
66862
|
+
name: file.uploadToken,
|
|
66863
|
+
size: file.byteLength,
|
|
66864
|
+
type: file.mimeType
|
|
66865
|
+
}))
|
|
66866
|
+
},
|
|
66867
|
+
signal
|
|
66549
66868
|
);
|
|
66550
|
-
const
|
|
66551
|
-
const
|
|
66552
|
-
const
|
|
66553
|
-
|
|
66554
|
-
|
|
66869
|
+
const entries = readPresignEntries(presign, batch);
|
|
66870
|
+
for (const entry of entries) cleanupKeys.push(entry.storageKey);
|
|
66871
|
+
const batchController = new AbortController();
|
|
66872
|
+
try {
|
|
66873
|
+
await mapWithConcurrency(entries, UPLOAD_CONCURRENCY, async (entry) => {
|
|
66874
|
+
try {
|
|
66875
|
+
await putWithRetry(
|
|
66876
|
+
put,
|
|
66877
|
+
entry,
|
|
66878
|
+
combineSignals(signal, batchController.signal)
|
|
66879
|
+
);
|
|
66880
|
+
} catch (error) {
|
|
66881
|
+
batchController.abort(error);
|
|
66882
|
+
throw error;
|
|
66883
|
+
}
|
|
66884
|
+
staged.push({
|
|
66885
|
+
uploadToken: entry.file.uploadToken,
|
|
66886
|
+
file: {
|
|
66887
|
+
recordId: entry.file.recordId,
|
|
66888
|
+
replaceFileId: entry.file.replaceFileId,
|
|
66889
|
+
name: entry.file.name,
|
|
66890
|
+
fileType: entry.file.fileType,
|
|
66891
|
+
mimeType: entry.file.mimeType,
|
|
66892
|
+
byteLength: entry.file.byteLength,
|
|
66893
|
+
storageKey: entry.storageKey,
|
|
66894
|
+
contentSha256: entry.file.contentSha256,
|
|
66895
|
+
audioDurationSeconds: entry.file.audioDurationSeconds
|
|
66896
|
+
}
|
|
66897
|
+
});
|
|
66898
|
+
completedFiles += 1;
|
|
66899
|
+
completedBytes += entry.file.byteLength;
|
|
66900
|
+
report();
|
|
66901
|
+
});
|
|
66902
|
+
} catch (error) {
|
|
66903
|
+
batchController.abort(error);
|
|
66904
|
+
throw error;
|
|
66555
66905
|
}
|
|
66556
|
-
|
|
66557
|
-
|
|
66558
|
-
|
|
66559
|
-
|
|
66560
|
-
|
|
66561
|
-
|
|
66562
|
-
|
|
66563
|
-
if (!response.ok) {
|
|
66906
|
+
}
|
|
66907
|
+
const byUploadToken = new Map(
|
|
66908
|
+
staged.map((entry) => [entry.uploadToken, entry.file])
|
|
66909
|
+
);
|
|
66910
|
+
return prepared.map((file) => {
|
|
66911
|
+
const result = byUploadToken.get(file.uploadToken);
|
|
66912
|
+
if (result === void 0) {
|
|
66564
66913
|
throw new Error(
|
|
66565
|
-
`
|
|
66914
|
+
`Uploaded project file ${file.name} (${file.uploadToken}) is missing from the staged result.`
|
|
66566
66915
|
);
|
|
66567
66916
|
}
|
|
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;
|
|
66917
|
+
return result;
|
|
66918
|
+
});
|
|
66581
66919
|
} catch (error) {
|
|
66582
66920
|
if (cleanupKeys.length > 0) {
|
|
66583
66921
|
try {
|
|
@@ -66588,8 +66926,145 @@ async function stageProjectFilePushesV4(args) {
|
|
|
66588
66926
|
} catch {
|
|
66589
66927
|
}
|
|
66590
66928
|
}
|
|
66929
|
+
if (interruptController.signal.aborted || args.signal?.aborted === true) {
|
|
66930
|
+
throw new ProjectFilePushCancelledError();
|
|
66931
|
+
}
|
|
66591
66932
|
throw error;
|
|
66933
|
+
} finally {
|
|
66934
|
+
process.removeListener("SIGINT", interrupt);
|
|
66935
|
+
}
|
|
66936
|
+
}
|
|
66937
|
+
function readPresignEntries(presign, batch) {
|
|
66938
|
+
const entries = Array.isArray(presign.files) ? presign.files.filter(isObjectRecord2) : [];
|
|
66939
|
+
return batch.map((file) => {
|
|
66940
|
+
const entry = entries.find((candidate) => {
|
|
66941
|
+
const info = isObjectRecord2(candidate.file) ? candidate.file : {};
|
|
66942
|
+
return info.name === file.uploadToken;
|
|
66943
|
+
});
|
|
66944
|
+
const fileInfo = isObjectRecord2(entry?.file) ? entry.file : {};
|
|
66945
|
+
const objectInfo = isObjectRecord2(fileInfo.objectInfo) ? fileInfo.objectInfo : {};
|
|
66946
|
+
if (typeof entry?.signedUrl !== "string") {
|
|
66947
|
+
throw new Error(
|
|
66948
|
+
`Upload presign response is missing signedUrl for ${file.name}.`
|
|
66949
|
+
);
|
|
66950
|
+
}
|
|
66951
|
+
if (typeof objectInfo.key !== "string") {
|
|
66952
|
+
throw new Error(
|
|
66953
|
+
`Upload presign response is missing a storage key for ${file.name}.`
|
|
66954
|
+
);
|
|
66955
|
+
}
|
|
66956
|
+
return {
|
|
66957
|
+
file,
|
|
66958
|
+
signedUrl: entry.signedUrl,
|
|
66959
|
+
storageKey: objectInfo.key,
|
|
66960
|
+
headers: uploadHeaders(entry, objectInfo, file.mimeType)
|
|
66961
|
+
};
|
|
66962
|
+
});
|
|
66963
|
+
}
|
|
66964
|
+
async function postWithTimeout(client, path, body, signal) {
|
|
66965
|
+
for (let attempt = 1; attempt <= PRESIGN_ATTEMPTS; attempt += 1) {
|
|
66966
|
+
try {
|
|
66967
|
+
return await client.post(path, body, void 0, {
|
|
66968
|
+
signal: combineSignals(signal, AbortSignal.timeout(PRESIGN_TIMEOUT_MS))
|
|
66969
|
+
});
|
|
66970
|
+
} catch (error) {
|
|
66971
|
+
if (signal.aborted || !isRetryableRequestError(error) || attempt === PRESIGN_ATTEMPTS) {
|
|
66972
|
+
throw error;
|
|
66973
|
+
}
|
|
66974
|
+
await waitForRetry(attempt, signal);
|
|
66975
|
+
}
|
|
66976
|
+
}
|
|
66977
|
+
throw new Error("Upload presign failed after all retry attempts.");
|
|
66978
|
+
}
|
|
66979
|
+
async function putWithRetry(put, entry, signal) {
|
|
66980
|
+
let lastError;
|
|
66981
|
+
for (let attempt = 1; attempt <= STORAGE_PUT_ATTEMPTS; attempt += 1) {
|
|
66982
|
+
let response;
|
|
66983
|
+
try {
|
|
66984
|
+
response = await put(entry.signedUrl, {
|
|
66985
|
+
method: "PUT",
|
|
66986
|
+
headers: entry.headers,
|
|
66987
|
+
body: Buffer.from(entry.file.bytes),
|
|
66988
|
+
signal: combineSignals(
|
|
66989
|
+
signal,
|
|
66990
|
+
AbortSignal.timeout(STORAGE_PUT_TIMEOUT_MS)
|
|
66991
|
+
)
|
|
66992
|
+
});
|
|
66993
|
+
} catch (error) {
|
|
66994
|
+
if (signal.aborted || attempt === STORAGE_PUT_ATTEMPTS) throw error;
|
|
66995
|
+
lastError = error;
|
|
66996
|
+
await waitForRetry(attempt, signal);
|
|
66997
|
+
continue;
|
|
66998
|
+
}
|
|
66999
|
+
if (response.ok) return;
|
|
67000
|
+
if (isRetryableStatus(response.status) && attempt < STORAGE_PUT_ATTEMPTS) {
|
|
67001
|
+
lastError = new Error(`Storage PUT failed (${response.status}).`);
|
|
67002
|
+
await waitForRetry(attempt, signal);
|
|
67003
|
+
continue;
|
|
67004
|
+
}
|
|
67005
|
+
throw new Error(
|
|
67006
|
+
`Storage PUT failed (${response.status}): ${await response.text()}`
|
|
67007
|
+
);
|
|
67008
|
+
}
|
|
67009
|
+
throw lastError instanceof Error ? lastError : new Error(`Storage PUT failed for ${entry.file.name}.`);
|
|
67010
|
+
}
|
|
67011
|
+
function isRetryableStatus(status) {
|
|
67012
|
+
return status === 408 || status === 429 || status >= 500;
|
|
67013
|
+
}
|
|
67014
|
+
function isRetryableRequestError(error) {
|
|
67015
|
+
if (isObjectRecord2(error) && typeof error.status === "number") {
|
|
67016
|
+
return isRetryableStatus(error.status);
|
|
67017
|
+
}
|
|
67018
|
+
if (isObjectRecord2(error) && error.name === "TimeoutError") return true;
|
|
67019
|
+
if (!(error instanceof TypeError) || error.message !== "fetch failed") {
|
|
67020
|
+
return false;
|
|
67021
|
+
}
|
|
67022
|
+
if (!isObjectRecord2(error.cause) || typeof error.cause.code !== "string") {
|
|
67023
|
+
return false;
|
|
66592
67024
|
}
|
|
67025
|
+
return RETRYABLE_NETWORK_ERROR_CODES.has(error.cause.code);
|
|
67026
|
+
}
|
|
67027
|
+
async function waitForRetry(attempt, signal) {
|
|
67028
|
+
await new Promise((resolve4, reject) => {
|
|
67029
|
+
const abort = () => {
|
|
67030
|
+
clearTimeout(timeout);
|
|
67031
|
+
reject(signal.reason);
|
|
67032
|
+
};
|
|
67033
|
+
const timeout = setTimeout(
|
|
67034
|
+
() => {
|
|
67035
|
+
signal.removeEventListener("abort", abort);
|
|
67036
|
+
resolve4();
|
|
67037
|
+
},
|
|
67038
|
+
200 * 2 ** (attempt - 1)
|
|
67039
|
+
);
|
|
67040
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
67041
|
+
});
|
|
67042
|
+
}
|
|
67043
|
+
async function mapWithConcurrency(values, concurrency, run) {
|
|
67044
|
+
let nextIndex = 0;
|
|
67045
|
+
let firstError;
|
|
67046
|
+
const worker = async () => {
|
|
67047
|
+
while (firstError === void 0) {
|
|
67048
|
+
const index = nextIndex;
|
|
67049
|
+
nextIndex += 1;
|
|
67050
|
+
if (index >= values.length) return;
|
|
67051
|
+
try {
|
|
67052
|
+
await run(values[index]);
|
|
67053
|
+
} catch (error) {
|
|
67054
|
+
firstError ??= error;
|
|
67055
|
+
}
|
|
67056
|
+
}
|
|
67057
|
+
};
|
|
67058
|
+
await Promise.all(
|
|
67059
|
+
Array.from({ length: Math.min(concurrency, values.length) }, worker)
|
|
67060
|
+
);
|
|
67061
|
+
if (firstError !== void 0) throw firstError;
|
|
67062
|
+
}
|
|
67063
|
+
function combineSignals(...signals) {
|
|
67064
|
+
const defined = signals.filter(
|
|
67065
|
+
(signal) => signal !== void 0
|
|
67066
|
+
);
|
|
67067
|
+
return defined.length === 1 ? defined[0] : AbortSignal.any(defined);
|
|
66593
67068
|
}
|
|
66594
67069
|
function uploadHeaders(entry, objectInfo, mimeType) {
|
|
66595
67070
|
const headers = { "Content-Type": mimeType };
|
|
@@ -66611,11 +67086,431 @@ function uploadHeaders(entry, objectInfo, mimeType) {
|
|
|
66611
67086
|
function versionPath2(workspace, suffix) {
|
|
66612
67087
|
return `/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/${suffix}`;
|
|
66613
67088
|
}
|
|
67089
|
+
var UPLOAD_CONCURRENCY, PRESIGN_TIMEOUT_MS, PRESIGN_ATTEMPTS, STORAGE_PUT_TIMEOUT_MS, STORAGE_PUT_ATTEMPTS, ProjectFilePushCancelledError, RETRYABLE_NETWORK_ERROR_CODES;
|
|
66614
67090
|
var init_project_file_push = __esm({
|
|
66615
67091
|
"src/project-source/project-file-push.ts"() {
|
|
66616
67092
|
"use strict";
|
|
66617
67093
|
init_project_files();
|
|
66618
67094
|
init_projection();
|
|
67095
|
+
init_src();
|
|
67096
|
+
UPLOAD_CONCURRENCY = 6;
|
|
67097
|
+
PRESIGN_TIMEOUT_MS = 3e4;
|
|
67098
|
+
PRESIGN_ATTEMPTS = 3;
|
|
67099
|
+
STORAGE_PUT_TIMEOUT_MS = 12e4;
|
|
67100
|
+
STORAGE_PUT_ATTEMPTS = 3;
|
|
67101
|
+
ProjectFilePushCancelledError = class extends Error {
|
|
67102
|
+
constructor() {
|
|
67103
|
+
super("Project file upload was cancelled.");
|
|
67104
|
+
this.name = "ProjectFilePushCancelledError";
|
|
67105
|
+
}
|
|
67106
|
+
};
|
|
67107
|
+
RETRYABLE_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
67108
|
+
"ECONNRESET",
|
|
67109
|
+
"ECONNREFUSED",
|
|
67110
|
+
"EHOSTUNREACH",
|
|
67111
|
+
"ENETUNREACH",
|
|
67112
|
+
"ENOTFOUND",
|
|
67113
|
+
"EPIPE",
|
|
67114
|
+
"ETIMEDOUT"
|
|
67115
|
+
]);
|
|
67116
|
+
}
|
|
67117
|
+
});
|
|
67118
|
+
|
|
67119
|
+
// src/project-source/trusted-commit-verification.ts
|
|
67120
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
67121
|
+
import { tmpdir } from "node:os";
|
|
67122
|
+
import { join as join15 } from "node:path";
|
|
67123
|
+
function verifyProjectSourceCommitAgainstStateV4(args) {
|
|
67124
|
+
const root = join15(tmpdir(), `neo-source-verify-virtual-${randomUUID5()}`);
|
|
67125
|
+
const workspace = {
|
|
67126
|
+
root,
|
|
67127
|
+
config: {
|
|
67128
|
+
formatVersion: 4,
|
|
67129
|
+
apiBaseUrl: "https://trusted-server.invalid",
|
|
67130
|
+
projectId: args.projectId,
|
|
67131
|
+
versionId: args.versionId,
|
|
67132
|
+
profile: "editor"
|
|
67133
|
+
},
|
|
67134
|
+
state: { records: { ...args.stateRecords } }
|
|
67135
|
+
};
|
|
67136
|
+
const assignments = validateAssignments(args.pendingIdAssignments);
|
|
67137
|
+
const pendingIdByAssignedId = new Map(
|
|
67138
|
+
[...assignments].map(([pendingId2, assignedId]) => [assignedId, pendingId2])
|
|
67139
|
+
);
|
|
67140
|
+
const trustedPendingProjectFiles = /* @__PURE__ */ new Map();
|
|
67141
|
+
const stagedRecordIds = /* @__PURE__ */ new Set();
|
|
67142
|
+
for (const file of args.stagedFiles) {
|
|
67143
|
+
if (stagedRecordIds.has(file.recordId)) {
|
|
67144
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67145
|
+
"Source commit contains duplicate verified staged project files."
|
|
67146
|
+
);
|
|
67147
|
+
}
|
|
67148
|
+
stagedRecordIds.add(file.recordId);
|
|
67149
|
+
const metadata = {
|
|
67150
|
+
mimeType: file.mimeType,
|
|
67151
|
+
byteLength: file.byteLength,
|
|
67152
|
+
sha256: file.contentSha256
|
|
67153
|
+
};
|
|
67154
|
+
trustedPendingProjectFiles.set(file.recordId, metadata);
|
|
67155
|
+
const pendingId2 = pendingIdByAssignedId.get(file.recordId);
|
|
67156
|
+
if (pendingId2 !== void 0) {
|
|
67157
|
+
trustedPendingProjectFiles.set(pendingId2, metadata);
|
|
67158
|
+
}
|
|
67159
|
+
}
|
|
67160
|
+
const status = computeWorkspaceStatus(workspace, {
|
|
67161
|
+
skipProjectBinaryInspection: true,
|
|
67162
|
+
writeProjectAnalysisCache: () => void 0,
|
|
67163
|
+
trustedPendingProjectFiles,
|
|
67164
|
+
virtualSourceFiles: args.files
|
|
67165
|
+
});
|
|
67166
|
+
const blockingErrors = status.parseErrors.filter(isBlockingSchemaSourceError);
|
|
67167
|
+
if (status.conflictedFiles.length > 0 || blockingErrors.length > 0) {
|
|
67168
|
+
const first = blockingErrors[0];
|
|
67169
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67170
|
+
first ? `Trusted source lowering failed: ${first.file}:${first.line}:${first.column} ${first.message}` : `Trusted source lowering found conflict markers in ${status.conflictedFiles[0]}.`
|
|
67171
|
+
);
|
|
67172
|
+
}
|
|
67173
|
+
const usedAssignments = /* @__PURE__ */ new Set();
|
|
67174
|
+
const expectedChanges = status.changes.map((change) => {
|
|
67175
|
+
const rewrittenData = change.nextData === void 0 ? void 0 : rewritePending(change.nextData, assignments, usedAssignments);
|
|
67176
|
+
return {
|
|
67177
|
+
recordKind: change.recordKind,
|
|
67178
|
+
recordId: rewritePending(change.recordId, assignments, usedAssignments),
|
|
67179
|
+
operation: change.kind,
|
|
67180
|
+
// Source syntax does not author project ownership. The CLI stamps the
|
|
67181
|
+
// authenticated project id on creates immediately before transport;
|
|
67182
|
+
// reproduce that server-known field instead of comparing the
|
|
67183
|
+
// lowerer's empty construction placeholder.
|
|
67184
|
+
nextData: change.kind === "create" && isObjectRecord2(rewrittenData) ? { ...rewrittenData, projectId: args.projectId } : rewrittenData,
|
|
67185
|
+
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
67186
|
+
};
|
|
67187
|
+
});
|
|
67188
|
+
const expectedSeeds = [...status.staticValueSeeds].map(
|
|
67189
|
+
([memberId, seed]) => ({
|
|
67190
|
+
memberId: rewritePending(memberId, assignments, usedAssignments),
|
|
67191
|
+
value: rewritePending(seed.value, assignments, usedAssignments),
|
|
67192
|
+
classId: seed.classId === null ? null : rewritePending(seed.classId, assignments, usedAssignments),
|
|
67193
|
+
...seed.valueId === void 0 ? {} : {
|
|
67194
|
+
valueId: rewritePending(seed.valueId, assignments, usedAssignments)
|
|
67195
|
+
},
|
|
67196
|
+
...seed.values === void 0 ? {} : {
|
|
67197
|
+
values: rewritePending(seed.values, assignments, usedAssignments)
|
|
67198
|
+
},
|
|
67199
|
+
...seed.bindingMembers === void 0 ? {} : {
|
|
67200
|
+
bindingMembers: rewritePending(
|
|
67201
|
+
seed.bindingMembers,
|
|
67202
|
+
assignments,
|
|
67203
|
+
usedAssignments
|
|
67204
|
+
)
|
|
67205
|
+
},
|
|
67206
|
+
...seed.localizedTexts === void 0 ? {} : {
|
|
67207
|
+
localizedTexts: rewritePending(
|
|
67208
|
+
seed.localizedTexts,
|
|
67209
|
+
assignments,
|
|
67210
|
+
usedAssignments
|
|
67211
|
+
)
|
|
67212
|
+
}
|
|
67213
|
+
})
|
|
67214
|
+
);
|
|
67215
|
+
for (const pendingId2 of assignments.keys()) {
|
|
67216
|
+
if (!usedAssignments.has(pendingId2)) {
|
|
67217
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67218
|
+
`Pending id assignment ${pendingId2} is not present in the verified source manifest.`
|
|
67219
|
+
);
|
|
67220
|
+
}
|
|
67221
|
+
}
|
|
67222
|
+
compareChanges(expectedChanges, args.changes);
|
|
67223
|
+
compareSeeds(expectedSeeds, args.staticValueSeeds);
|
|
67224
|
+
}
|
|
67225
|
+
function validateAssignments(value) {
|
|
67226
|
+
const assignments = /* @__PURE__ */ new Map();
|
|
67227
|
+
const assignedIds = /* @__PURE__ */ new Set();
|
|
67228
|
+
for (const [pendingId2, assignedId] of Object.entries(value)) {
|
|
67229
|
+
if (!pendingId2.startsWith("__pending__:")) {
|
|
67230
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67231
|
+
`Pending id assignment key ${pendingId2} is not a pending identity.`
|
|
67232
|
+
);
|
|
67233
|
+
}
|
|
67234
|
+
if (pendingMemberValueMemberId(pendingId2) === null) {
|
|
67235
|
+
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(
|
|
67236
|
+
assignedId
|
|
67237
|
+
)) {
|
|
67238
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67239
|
+
`Pending id assignment for ${pendingId2} is not a UUID v4.`
|
|
67240
|
+
);
|
|
67241
|
+
}
|
|
67242
|
+
}
|
|
67243
|
+
if (assignedIds.has(assignedId)) {
|
|
67244
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67245
|
+
`Pending id assignments reuse durable id ${assignedId}.`
|
|
67246
|
+
);
|
|
67247
|
+
}
|
|
67248
|
+
assignments.set(pendingId2, assignedId);
|
|
67249
|
+
assignedIds.add(assignedId);
|
|
67250
|
+
}
|
|
67251
|
+
assertMemberValueAssignmentsAreDerived(assignments);
|
|
67252
|
+
return assignments;
|
|
67253
|
+
}
|
|
67254
|
+
function assertMemberValueAssignmentsAreDerived(assignments) {
|
|
67255
|
+
for (const [pendingId2, assignedId] of assignments) {
|
|
67256
|
+
const memberLocator = pendingMemberValueMemberId(pendingId2);
|
|
67257
|
+
if (memberLocator === null) continue;
|
|
67258
|
+
const memberId = memberLocator.startsWith("__pending__:") ? assignments.get(memberLocator) : memberLocator;
|
|
67259
|
+
if (memberId === void 0) {
|
|
67260
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67261
|
+
`Member value assignment ${pendingId2} names member ${memberLocator}, which has no pending id assignment.`
|
|
67262
|
+
);
|
|
67263
|
+
}
|
|
67264
|
+
const derived = derivedMemberValueId(memberId);
|
|
67265
|
+
if (assignedId !== derived) {
|
|
67266
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67267
|
+
`Member value assignment ${pendingId2} is ${assignedId}, but member ${memberId} owns value ${derived}.`
|
|
67268
|
+
);
|
|
67269
|
+
}
|
|
67270
|
+
}
|
|
67271
|
+
}
|
|
67272
|
+
function positionIndependentPendingKey(pendingId2) {
|
|
67273
|
+
const parts = pendingId2.split(":");
|
|
67274
|
+
if (parts.length !== 6) return null;
|
|
67275
|
+
const [prefix, kind, uri, line, character, label] = parts;
|
|
67276
|
+
if (prefix !== "__pending__") return null;
|
|
67277
|
+
if (!/^\d+$/u.test(line) || !/^\d+$/u.test(character)) return null;
|
|
67278
|
+
return `${prefix}:${kind}:${uri}:${label}`;
|
|
67279
|
+
}
|
|
67280
|
+
function positionIndependentAssignments(assignments) {
|
|
67281
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
67282
|
+
for (const pendingId2 of assignments.keys()) {
|
|
67283
|
+
const key = positionIndependentPendingKey(pendingId2);
|
|
67284
|
+
if (key === null) continue;
|
|
67285
|
+
candidates.set(key, [...candidates.get(key) ?? [], pendingId2]);
|
|
67286
|
+
}
|
|
67287
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
67288
|
+
for (const [key, pendingIds] of candidates) {
|
|
67289
|
+
if (pendingIds.length !== 1) continue;
|
|
67290
|
+
resolved.set(key, pendingIds[0]);
|
|
67291
|
+
}
|
|
67292
|
+
return resolved;
|
|
67293
|
+
}
|
|
67294
|
+
function rewritePending(value, assignments, used, byPosition) {
|
|
67295
|
+
const positionless = byPosition ?? positionIndependentAssignments(assignments);
|
|
67296
|
+
if (typeof value === "string") {
|
|
67297
|
+
const exact = assignments.get(value);
|
|
67298
|
+
if (exact !== void 0) {
|
|
67299
|
+
used.add(value);
|
|
67300
|
+
return exact;
|
|
67301
|
+
}
|
|
67302
|
+
if (value.startsWith("__pending__:")) {
|
|
67303
|
+
const key = positionIndependentPendingKey(value);
|
|
67304
|
+
const relocated = key === null ? void 0 : positionless.get(key);
|
|
67305
|
+
if (relocated !== void 0) {
|
|
67306
|
+
used.add(relocated);
|
|
67307
|
+
return assignments.get(relocated);
|
|
67308
|
+
}
|
|
67309
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67310
|
+
`Verified source identity ${value} has no pending id assignment.`
|
|
67311
|
+
);
|
|
67312
|
+
}
|
|
67313
|
+
let rewritten = value;
|
|
67314
|
+
for (const [pendingId2, assignedId] of assignments) {
|
|
67315
|
+
if (!rewritten.includes(pendingId2)) continue;
|
|
67316
|
+
rewritten = rewritten.replaceAll(pendingId2, assignedId);
|
|
67317
|
+
used.add(pendingId2);
|
|
67318
|
+
}
|
|
67319
|
+
return rewritten;
|
|
67320
|
+
}
|
|
67321
|
+
if (Array.isArray(value)) {
|
|
67322
|
+
return value.map(
|
|
67323
|
+
(entry) => rewritePending(entry, assignments, used, positionless)
|
|
67324
|
+
);
|
|
67325
|
+
}
|
|
67326
|
+
if (isObjectRecord2(value)) {
|
|
67327
|
+
const result = {};
|
|
67328
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
67329
|
+
const rewrittenKey = key.startsWith("__pending__:") ? rewritePending(key, assignments, used, positionless) : key;
|
|
67330
|
+
result[rewrittenKey] = rewritePending(
|
|
67331
|
+
entry,
|
|
67332
|
+
assignments,
|
|
67333
|
+
used,
|
|
67334
|
+
positionless
|
|
67335
|
+
);
|
|
67336
|
+
}
|
|
67337
|
+
return result;
|
|
67338
|
+
}
|
|
67339
|
+
return value;
|
|
67340
|
+
}
|
|
67341
|
+
function compareChanges(expected, received) {
|
|
67342
|
+
const expectedByKey = new Map(
|
|
67343
|
+
expected.map((change) => [
|
|
67344
|
+
`${change.recordKind}:${change.recordId}`,
|
|
67345
|
+
change
|
|
67346
|
+
])
|
|
67347
|
+
);
|
|
67348
|
+
const receivedByKey = new Map(
|
|
67349
|
+
received.map((change) => [
|
|
67350
|
+
`${change.recordKind}:${change.recordId}`,
|
|
67351
|
+
change
|
|
67352
|
+
])
|
|
67353
|
+
);
|
|
67354
|
+
if (expectedByKey.size !== expected.length || receivedByKey.size !== received.length) {
|
|
67355
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67356
|
+
"Source commit contains duplicate semantic record changes."
|
|
67357
|
+
);
|
|
67358
|
+
}
|
|
67359
|
+
for (const [key, expectedChange] of expectedByKey) {
|
|
67360
|
+
const actual = receivedByKey.get(key);
|
|
67361
|
+
if (actual === void 0) {
|
|
67362
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67363
|
+
`Source commit omitted semantic change ${key}.`
|
|
67364
|
+
);
|
|
67365
|
+
}
|
|
67366
|
+
if (actual.operation !== expectedChange.operation || (actual.expectedBaseContentHash ?? null) !== expectedChange.expectedBaseContentHash) {
|
|
67367
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67368
|
+
`Source commit changed operation or CAS base for ${key}.`
|
|
67369
|
+
);
|
|
67370
|
+
}
|
|
67371
|
+
const expectedData = comparisonData(
|
|
67372
|
+
expectedChange.recordKind,
|
|
67373
|
+
expectedChange.nextData
|
|
67374
|
+
);
|
|
67375
|
+
const actualData = comparisonData(actual.recordKind, actual.nextData);
|
|
67376
|
+
if (canonicalStringify(expectedData) !== canonicalStringify(actualData)) {
|
|
67377
|
+
const difference = firstDifference(expectedData, actualData);
|
|
67378
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67379
|
+
`Source commit nextData for ${key} does not match trusted lowering${difference === null ? "." : ` at ${difference.path}: trusted ${formatDifferenceValue(difference.trusted)}, submitted ${formatDifferenceValue(difference.submitted)}.`}`
|
|
67380
|
+
);
|
|
67381
|
+
}
|
|
67382
|
+
if (!isObjectRecord2(actual.intent) || actual.intent.type !== `${actual.recordKind}.${actual.operation}`) {
|
|
67383
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67384
|
+
`Source commit intent for ${key} does not match its semantic operation.`
|
|
67385
|
+
);
|
|
67386
|
+
}
|
|
67387
|
+
receivedByKey.delete(key);
|
|
67388
|
+
}
|
|
67389
|
+
const extra = receivedByKey.keys().next().value;
|
|
67390
|
+
if (extra !== void 0) {
|
|
67391
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67392
|
+
`Source commit added semantic change ${extra} absent from trusted lowering.`
|
|
67393
|
+
);
|
|
67394
|
+
}
|
|
67395
|
+
}
|
|
67396
|
+
function firstDifference(trusted, submitted, path = "$") {
|
|
67397
|
+
if (Object.is(trusted, submitted)) return null;
|
|
67398
|
+
if (Array.isArray(trusted) && Array.isArray(submitted)) {
|
|
67399
|
+
const count = Math.max(trusted.length, submitted.length);
|
|
67400
|
+
for (let index = 0; index < count; index += 1) {
|
|
67401
|
+
if (index >= trusted.length) {
|
|
67402
|
+
return {
|
|
67403
|
+
path: `${path}[${index}]`,
|
|
67404
|
+
trusted: ABSENT_DIFFERENCE_VALUE,
|
|
67405
|
+
submitted: submitted[index]
|
|
67406
|
+
};
|
|
67407
|
+
}
|
|
67408
|
+
if (index >= submitted.length) {
|
|
67409
|
+
return {
|
|
67410
|
+
path: `${path}[${index}]`,
|
|
67411
|
+
trusted: trusted[index],
|
|
67412
|
+
submitted: ABSENT_DIFFERENCE_VALUE
|
|
67413
|
+
};
|
|
67414
|
+
}
|
|
67415
|
+
const difference = firstDifference(
|
|
67416
|
+
trusted[index],
|
|
67417
|
+
submitted[index],
|
|
67418
|
+
`${path}[${index}]`
|
|
67419
|
+
);
|
|
67420
|
+
if (difference !== null) return difference;
|
|
67421
|
+
}
|
|
67422
|
+
}
|
|
67423
|
+
if (isObjectRecord2(trusted) && isObjectRecord2(submitted)) {
|
|
67424
|
+
const keys = [
|
|
67425
|
+
.../* @__PURE__ */ new Set([...Object.keys(trusted), ...Object.keys(submitted)])
|
|
67426
|
+
].sort();
|
|
67427
|
+
for (const key of keys) {
|
|
67428
|
+
const trustedHasKey = Object.hasOwn(trusted, key);
|
|
67429
|
+
const submittedHasKey = Object.hasOwn(submitted, key);
|
|
67430
|
+
const childPath = `${path}.${key}`;
|
|
67431
|
+
if (!trustedHasKey || !submittedHasKey) {
|
|
67432
|
+
return {
|
|
67433
|
+
path: childPath,
|
|
67434
|
+
trusted: trustedHasKey ? trusted[key] : ABSENT_DIFFERENCE_VALUE,
|
|
67435
|
+
submitted: submittedHasKey ? submitted[key] : ABSENT_DIFFERENCE_VALUE
|
|
67436
|
+
};
|
|
67437
|
+
}
|
|
67438
|
+
const difference = firstDifference(
|
|
67439
|
+
trusted[key],
|
|
67440
|
+
submitted[key],
|
|
67441
|
+
childPath
|
|
67442
|
+
);
|
|
67443
|
+
if (difference !== null) return difference;
|
|
67444
|
+
}
|
|
67445
|
+
}
|
|
67446
|
+
return { path, trusted, submitted };
|
|
67447
|
+
}
|
|
67448
|
+
function formatDifferenceValue(value) {
|
|
67449
|
+
if (value === ABSENT_DIFFERENCE_VALUE) return "<absent>";
|
|
67450
|
+
const serialized = JSON.stringify(value);
|
|
67451
|
+
const rendered = serialized === void 0 ? String(value) : serialized;
|
|
67452
|
+
return rendered.length <= 160 ? rendered : `${rendered.slice(0, 157)}...`;
|
|
67453
|
+
}
|
|
67454
|
+
function comparisonData(recordKind, value) {
|
|
67455
|
+
if (!isObjectRecord2(value)) return value;
|
|
67456
|
+
const result = { ...value };
|
|
67457
|
+
delete result.createdAt;
|
|
67458
|
+
delete result.updatedAt;
|
|
67459
|
+
if (recordKind === "member") {
|
|
67460
|
+
delete result.getter;
|
|
67461
|
+
delete result.setter;
|
|
67462
|
+
if (result.kind === 23) delete result.action;
|
|
67463
|
+
}
|
|
67464
|
+
if (recordKind === "migration") delete result.action;
|
|
67465
|
+
return result;
|
|
67466
|
+
}
|
|
67467
|
+
function compareSeeds(expected, received) {
|
|
67468
|
+
const normalize = (values) => values.map(normalizeSeedForComparison).sort((left, right) => {
|
|
67469
|
+
if (left.memberId < right.memberId) return -1;
|
|
67470
|
+
if (left.memberId > right.memberId) return 1;
|
|
67471
|
+
return 0;
|
|
67472
|
+
});
|
|
67473
|
+
if (canonicalStringify(normalize(expected)) !== canonicalStringify(normalize(received))) {
|
|
67474
|
+
throw new ProjectSourceCommitVerificationError(
|
|
67475
|
+
"Source commit static value seeds do not match trusted lowering."
|
|
67476
|
+
);
|
|
67477
|
+
}
|
|
67478
|
+
}
|
|
67479
|
+
function normalizeSeedForComparison(seed) {
|
|
67480
|
+
const normalized = { ...seed };
|
|
67481
|
+
if (seed.values !== void 0) {
|
|
67482
|
+
normalized.values = sortSeedRows(seed.values);
|
|
67483
|
+
}
|
|
67484
|
+
if (seed.bindingMembers !== void 0) {
|
|
67485
|
+
normalized.bindingMembers = sortSeedRows(seed.bindingMembers);
|
|
67486
|
+
}
|
|
67487
|
+
if (seed.localizedTexts !== void 0) {
|
|
67488
|
+
normalized.localizedTexts = sortSeedRows(seed.localizedTexts);
|
|
67489
|
+
}
|
|
67490
|
+
return normalized;
|
|
67491
|
+
}
|
|
67492
|
+
function sortSeedRows(values) {
|
|
67493
|
+
return [...values].sort((left, right) => {
|
|
67494
|
+
if (left.id < right.id) return -1;
|
|
67495
|
+
if (left.id > right.id) return 1;
|
|
67496
|
+
return 0;
|
|
67497
|
+
});
|
|
67498
|
+
}
|
|
67499
|
+
var ProjectSourceCommitVerificationError, ABSENT_DIFFERENCE_VALUE;
|
|
67500
|
+
var init_trusted_commit_verification = __esm({
|
|
67501
|
+
"src/project-source/trusted-commit-verification.ts"() {
|
|
67502
|
+
"use strict";
|
|
67503
|
+
init_workspace_status();
|
|
67504
|
+
init_source_diagnostics();
|
|
67505
|
+
init_projection();
|
|
67506
|
+
init_member_value_id();
|
|
67507
|
+
ProjectSourceCommitVerificationError = class extends Error {
|
|
67508
|
+
constructor(message) {
|
|
67509
|
+
super(message);
|
|
67510
|
+
this.name = "ProjectSourceCommitVerificationError";
|
|
67511
|
+
}
|
|
67512
|
+
};
|
|
67513
|
+
ABSENT_DIFFERENCE_VALUE = /* @__PURE__ */ Symbol("absent-difference-value");
|
|
66619
67514
|
}
|
|
66620
67515
|
});
|
|
66621
67516
|
|
|
@@ -66660,7 +67555,7 @@ __export(push_exports, {
|
|
|
66660
67555
|
stripServerDerivedNeoScript: () => stripServerDerivedNeoScript,
|
|
66661
67556
|
workspaceChangesRequireCompleteBodySweep: () => workspaceChangesRequireCompleteBodySweep
|
|
66662
67557
|
});
|
|
66663
|
-
import { randomUUID as
|
|
67558
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
66664
67559
|
import {
|
|
66665
67560
|
mkdirSync as mkdirSync11,
|
|
66666
67561
|
writeFileSync as writeFileSync11,
|
|
@@ -66668,7 +67563,7 @@ import {
|
|
|
66668
67563
|
existsSync as existsSync12,
|
|
66669
67564
|
readFileSync as readFileSync13
|
|
66670
67565
|
} from "node:fs";
|
|
66671
|
-
import { dirname as dirname7, join as
|
|
67566
|
+
import { dirname as dirname7, join as join16, relative as relative5, sep as sep5 } from "node:path";
|
|
66672
67567
|
function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
|
|
66673
67568
|
const assigned = /* @__PURE__ */ new Map();
|
|
66674
67569
|
const assign = (pendingId2) => {
|
|
@@ -66681,7 +67576,7 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
|
|
|
66681
67576
|
assigned.set(pendingId2, derived);
|
|
66682
67577
|
return derived;
|
|
66683
67578
|
}
|
|
66684
|
-
const fresh =
|
|
67579
|
+
const fresh = randomUUID6();
|
|
66685
67580
|
assigned.set(pendingId2, fresh);
|
|
66686
67581
|
return fresh;
|
|
66687
67582
|
};
|
|
@@ -66992,6 +67887,10 @@ function createPushProgressReporter(json) {
|
|
|
66992
67887
|
};
|
|
66993
67888
|
}
|
|
66994
67889
|
function projectTransactionProgressLabel(event) {
|
|
67890
|
+
if (event.type === "push-progress") {
|
|
67891
|
+
if (event.phase === "preparing") return "Preparing push\u2026";
|
|
67892
|
+
return `Uploading files\u2026 ${event.completedFiles.toLocaleString("en-US")}/${event.totalFiles.toLocaleString("en-US")} (${formatByteProgress(event.completedBytes)}/${formatByteProgress(event.totalBytes)})`;
|
|
67893
|
+
}
|
|
66995
67894
|
if (event.phase === "submitting") return "Pushing\u2026";
|
|
66996
67895
|
if (event.phase === "preparing") return "Preparing push\u2026";
|
|
66997
67896
|
if (event.phase === "waiting") return "Waiting to apply project transaction\u2026";
|
|
@@ -67009,6 +67908,11 @@ function projectTransactionProgressLabel(event) {
|
|
|
67009
67908
|
}
|
|
67010
67909
|
return "Finalizing project transaction\u2026";
|
|
67011
67910
|
}
|
|
67911
|
+
function formatByteProgress(bytes) {
|
|
67912
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
67913
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
67914
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
67915
|
+
}
|
|
67012
67916
|
function progressEventFromAccepted(accepted) {
|
|
67013
67917
|
return {
|
|
67014
67918
|
type: "project-transaction-progress",
|
|
@@ -67177,6 +68081,9 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67177
68081
|
changes: status.changes,
|
|
67178
68082
|
binaryChanges: status.binaryChanges ?? []
|
|
67179
68083
|
});
|
|
68084
|
+
if (options.json !== true) {
|
|
68085
|
+
for (const message of status.warnings) warn(message);
|
|
68086
|
+
}
|
|
67180
68087
|
if (status.changes.length === 0) {
|
|
67181
68088
|
if (options.json === true) {
|
|
67182
68089
|
console.log(
|
|
@@ -67185,7 +68092,8 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67185
68092
|
dryRun: options.dryRun,
|
|
67186
68093
|
changeCount: 0,
|
|
67187
68094
|
staticValueSeedCount: 0,
|
|
67188
|
-
changes: []
|
|
68095
|
+
changes: [],
|
|
68096
|
+
warnings: status.warnings
|
|
67189
68097
|
})
|
|
67190
68098
|
);
|
|
67191
68099
|
} else {
|
|
@@ -67247,7 +68155,8 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67247
68155
|
kind: change.kind,
|
|
67248
68156
|
recordKind: change.recordKind,
|
|
67249
68157
|
recordId: change.recordId
|
|
67250
|
-
}))
|
|
68158
|
+
})),
|
|
68159
|
+
warnings: status.warnings
|
|
67251
68160
|
})
|
|
67252
68161
|
);
|
|
67253
68162
|
} else {
|
|
@@ -67281,46 +68190,111 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67281
68190
|
console.log("Push cancelled.");
|
|
67282
68191
|
return;
|
|
67283
68192
|
}
|
|
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
|
|
68193
|
+
let progress = createPushProgressReporter(options.json === true);
|
|
68194
|
+
progress.report({
|
|
68195
|
+
type: "push-progress",
|
|
68196
|
+
phase: "preparing",
|
|
68197
|
+
completedFiles: 0,
|
|
68198
|
+
totalFiles: status.binaryChanges?.length ?? 0,
|
|
68199
|
+
completedBytes: 0,
|
|
68200
|
+
totalBytes: 0
|
|
67303
68201
|
});
|
|
68202
|
+
const prepareAndStage = async () => {
|
|
68203
|
+
const source2 = await createPendingProjectSourceBundleV4(
|
|
68204
|
+
workspace,
|
|
68205
|
+
status,
|
|
68206
|
+
status.staticValueSeeds
|
|
68207
|
+
);
|
|
68208
|
+
const pendingAssignment2 = assignPendingIds(
|
|
68209
|
+
status.changes,
|
|
68210
|
+
status.staticValueSeeds,
|
|
68211
|
+
status.reconstructed
|
|
68212
|
+
);
|
|
68213
|
+
const operations = new Set(status.changes.map((change) => change.kind));
|
|
68214
|
+
const transactionOperation2 = operations.size === 1 ? status.changes[0].kind : "update";
|
|
68215
|
+
const client2 = NeoApiClient.forBaseUrl(workspace.config.apiBaseUrl);
|
|
68216
|
+
const transportChanges2 = status.changes.map((change) => ({
|
|
68217
|
+
recordKind: change.recordKind,
|
|
68218
|
+
recordId: change.recordId,
|
|
68219
|
+
operation: change.kind,
|
|
68220
|
+
nextData: change.kind === "delete" ? void 0 : stripServerDerivedNeoScript(change.nextData),
|
|
68221
|
+
deleted: change.kind === "delete" ? true : void 0,
|
|
68222
|
+
intent: createNeoCliPushIntent(change),
|
|
68223
|
+
expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
|
|
68224
|
+
}));
|
|
68225
|
+
const transportSeeds2 = [...pendingAssignment2.staticValueSeeds].map(
|
|
68226
|
+
([memberId, seed]) => ({ memberId, ...seed })
|
|
68227
|
+
);
|
|
68228
|
+
const files = prepareProjectFilePushesV4({
|
|
68229
|
+
workspace,
|
|
68230
|
+
changes: status.changes,
|
|
68231
|
+
binaryChanges: status.binaryChanges ?? [],
|
|
68232
|
+
assignedIds: pendingAssignment2.assigned
|
|
68233
|
+
});
|
|
68234
|
+
verifyProjectSourceCommitAgainstStateV4({
|
|
68235
|
+
projectId: workspace.config.projectId,
|
|
68236
|
+
versionId: workspace.config.versionId,
|
|
68237
|
+
stateRecords: workspace.state.records,
|
|
68238
|
+
files: source2.files,
|
|
68239
|
+
changes: transportChanges2,
|
|
68240
|
+
staticValueSeeds: transportSeeds2,
|
|
68241
|
+
pendingIdAssignments: Object.fromEntries(pendingAssignment2.assigned),
|
|
68242
|
+
stagedFiles: files
|
|
68243
|
+
});
|
|
68244
|
+
const stagedFiles2 = await stageProjectFilePushesV4({
|
|
68245
|
+
workspace,
|
|
68246
|
+
changes: status.changes,
|
|
68247
|
+
binaryChanges: status.binaryChanges ?? [],
|
|
68248
|
+
assignedIds: pendingAssignment2.assigned,
|
|
68249
|
+
client: client2,
|
|
68250
|
+
prepared: files,
|
|
68251
|
+
onProgress: (upload) => progress.report({
|
|
68252
|
+
type: "push-progress",
|
|
68253
|
+
phase: "uploading",
|
|
68254
|
+
...upload
|
|
68255
|
+
})
|
|
68256
|
+
});
|
|
68257
|
+
return {
|
|
68258
|
+
source: source2,
|
|
68259
|
+
pendingAssignment: pendingAssignment2,
|
|
68260
|
+
transactionOperation: transactionOperation2,
|
|
68261
|
+
client: client2,
|
|
68262
|
+
transportChanges: transportChanges2,
|
|
68263
|
+
transportSeeds: transportSeeds2,
|
|
68264
|
+
preparedFiles: files,
|
|
68265
|
+
stagedFiles: stagedFiles2
|
|
68266
|
+
};
|
|
68267
|
+
};
|
|
68268
|
+
let preparedPush;
|
|
68269
|
+
try {
|
|
68270
|
+
preparedPush = await prepareAndStage();
|
|
68271
|
+
} catch (error) {
|
|
68272
|
+
progress.stop();
|
|
68273
|
+
if (error instanceof ProjectFilePushCancelledError) {
|
|
68274
|
+
if (options.json !== true) console.error("Push cancelled.");
|
|
68275
|
+
process.exitCode = 130;
|
|
68276
|
+
return;
|
|
68277
|
+
}
|
|
68278
|
+
throw error;
|
|
68279
|
+
}
|
|
68280
|
+
const {
|
|
68281
|
+
source,
|
|
68282
|
+
pendingAssignment,
|
|
68283
|
+
transactionOperation,
|
|
68284
|
+
client,
|
|
68285
|
+
transportChanges,
|
|
68286
|
+
transportSeeds,
|
|
68287
|
+
preparedFiles
|
|
68288
|
+
} = preparedPush;
|
|
68289
|
+
let { stagedFiles } = preparedPush;
|
|
67304
68290
|
const commit = async (force) => await client.post(
|
|
67305
68291
|
`/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/schema/commit`,
|
|
67306
68292
|
{
|
|
67307
68293
|
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
|
-
),
|
|
68294
|
+
changes: transportChanges,
|
|
68295
|
+
staticValueSeeds: transportSeeds,
|
|
67322
68296
|
stagedFiles,
|
|
67323
|
-
sourceBundle,
|
|
68297
|
+
sourceBundle: source.bundle,
|
|
67324
68298
|
pendingIdAssignments: Object.fromEntries(pendingAssignment.assigned),
|
|
67325
68299
|
summary: options.summary ?? "neo push"
|
|
67326
68300
|
},
|
|
@@ -67434,7 +68408,6 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67434
68408
|
if (options.json !== true) success("Push complete.");
|
|
67435
68409
|
return true;
|
|
67436
68410
|
};
|
|
67437
|
-
let progress = createPushProgressReporter(options.json === true);
|
|
67438
68411
|
progress.report({
|
|
67439
68412
|
type: "project-transaction-progress",
|
|
67440
68413
|
transactionId: null,
|
|
@@ -67467,28 +68440,39 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
67467
68440
|
fallback: false
|
|
67468
68441
|
})) {
|
|
67469
68442
|
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
68443
|
try {
|
|
67482
68444
|
stagedFiles = await stageProjectFilePushesV4({
|
|
67483
68445
|
workspace,
|
|
67484
68446
|
changes: status.changes,
|
|
67485
68447
|
binaryChanges: status.binaryChanges ?? [],
|
|
67486
68448
|
assignedIds: pendingAssignment.assigned,
|
|
67487
|
-
client
|
|
68449
|
+
client,
|
|
68450
|
+
prepared: preparedFiles,
|
|
68451
|
+
onProgress: (upload) => progress.report({
|
|
68452
|
+
type: "push-progress",
|
|
68453
|
+
phase: "uploading",
|
|
68454
|
+
...upload
|
|
68455
|
+
})
|
|
68456
|
+
});
|
|
68457
|
+
progress.report({
|
|
68458
|
+
type: "project-transaction-progress",
|
|
68459
|
+
transactionId: null,
|
|
68460
|
+
phase: "submitting",
|
|
68461
|
+
totalChangeCount: status.changes.length,
|
|
68462
|
+
appliedChangeCount: 0,
|
|
68463
|
+
totalChunkCount: null,
|
|
68464
|
+
appliedChunkCount: 0,
|
|
68465
|
+
errorCode: null,
|
|
68466
|
+
errorMessage: null
|
|
67488
68467
|
});
|
|
67489
68468
|
result = await commit(true);
|
|
67490
68469
|
} catch (retryError) {
|
|
67491
68470
|
progress.stop();
|
|
68471
|
+
if (retryError instanceof ProjectFilePushCancelledError) {
|
|
68472
|
+
if (options.json !== true) console.error("Push cancelled.");
|
|
68473
|
+
process.exitCode = 130;
|
|
68474
|
+
return;
|
|
68475
|
+
}
|
|
67492
68476
|
if (retryError instanceof NeoApiError) {
|
|
67493
68477
|
reportPushRejection(retryError.status, retryError.body);
|
|
67494
68478
|
process.exitCode = 1;
|
|
@@ -67617,17 +68601,19 @@ async function createPendingProjectSourceBundleV4(workspace, status, staticValue
|
|
|
67617
68601
|
}
|
|
67618
68602
|
}
|
|
67619
68603
|
const emission = emitProjectDocumentFilesV4(records2);
|
|
67620
|
-
|
|
67621
|
-
|
|
67622
|
-
|
|
67623
|
-
|
|
67624
|
-
|
|
67625
|
-
|
|
67626
|
-
|
|
67627
|
-
|
|
67628
|
-
|
|
67629
|
-
|
|
67630
|
-
|
|
68604
|
+
const files = emission.files.map((file) => {
|
|
68605
|
+
const kind = neoProjectSourceKind(file.path);
|
|
68606
|
+
if (kind === null) {
|
|
68607
|
+
throw new Error(
|
|
68608
|
+
`Emitted project source bundle file ${JSON.stringify(file.path)} is not a recognized Neo source path.`
|
|
68609
|
+
);
|
|
68610
|
+
}
|
|
68611
|
+
return { path: file.path, kind, content: file.content };
|
|
68612
|
+
});
|
|
68613
|
+
return {
|
|
68614
|
+
files,
|
|
68615
|
+
bundle: await createProjectSourceBundle(files)
|
|
68616
|
+
};
|
|
67631
68617
|
}
|
|
67632
68618
|
function staticSeedBindingMemberRecord(projectId, bindingMember, timestamp) {
|
|
67633
68619
|
return {
|
|
@@ -68018,11 +69004,11 @@ ${finalErrors.map(
|
|
|
68018
69004
|
for (const recordState of Object.values(workspace.state.records)) {
|
|
68019
69005
|
const previousPath = recordState.file;
|
|
68020
69006
|
if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
|
|
68021
|
-
const absolute =
|
|
69007
|
+
const absolute = join16(workspace.root, previousPath);
|
|
68022
69008
|
if (existsSync12(absolute)) rmSync6(absolute);
|
|
68023
69009
|
}
|
|
68024
69010
|
for (const file of files) {
|
|
68025
|
-
const absolute =
|
|
69011
|
+
const absolute = join16(workspace.root, file.path);
|
|
68026
69012
|
mkdirSync11(dirname7(absolute), { recursive: true });
|
|
68027
69013
|
const existing = existsSync12(absolute) ? readFileSync13(absolute, "utf8") : null;
|
|
68028
69014
|
if (existing !== file.content)
|
|
@@ -68702,6 +69688,7 @@ var init_push = __esm({
|
|
|
68702
69688
|
init_source_diagnostics();
|
|
68703
69689
|
init_projection();
|
|
68704
69690
|
init_project_file_push();
|
|
69691
|
+
init_trusted_commit_verification();
|
|
68705
69692
|
init_world_system_classes();
|
|
68706
69693
|
init_project_manifest();
|
|
68707
69694
|
init_merge();
|
|
@@ -68744,7 +69731,7 @@ __export(dev_exports, {
|
|
|
68744
69731
|
runDev: () => runDev
|
|
68745
69732
|
});
|
|
68746
69733
|
import { watch } from "node:fs";
|
|
68747
|
-
import { join as
|
|
69734
|
+
import { join as join17 } from "node:path";
|
|
68748
69735
|
import { emitKeypressEvents } from "node:readline";
|
|
68749
69736
|
import { ConvexClient } from "convex/browser";
|
|
68750
69737
|
function isSchemaSignal(value) {
|
|
@@ -68851,7 +69838,7 @@ async function runDev(workspace, options) {
|
|
|
68851
69838
|
};
|
|
68852
69839
|
for (const dir of ["Classes", "Enums"]) {
|
|
68853
69840
|
try {
|
|
68854
|
-
watch(
|
|
69841
|
+
watch(join17(workspace.root, dir), { persistent: true }, onFileChange);
|
|
68855
69842
|
} catch {
|
|
68856
69843
|
}
|
|
68857
69844
|
}
|
|
@@ -68907,7 +69894,7 @@ __export(resolve_exports, {
|
|
|
68907
69894
|
workspaceFilePath: () => workspaceFilePath
|
|
68908
69895
|
});
|
|
68909
69896
|
import { readFileSync as readFileSync14, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "node:fs";
|
|
68910
|
-
import { join as
|
|
69897
|
+
import { join as join18 } from "node:path";
|
|
68911
69898
|
function runResolve(workspace, side) {
|
|
68912
69899
|
let resolvedFiles = 0;
|
|
68913
69900
|
for (const filePath of listProjectSourceFilesV4(workspace.root)) {
|
|
@@ -68922,12 +69909,12 @@ function runResolve(workspace, side) {
|
|
|
68922
69909
|
const binary = state.projectBinary;
|
|
68923
69910
|
const conflict2 = binary?.conflict;
|
|
68924
69911
|
if (binary === void 0 || conflict2 === void 0) continue;
|
|
68925
|
-
const destination =
|
|
69912
|
+
const destination = join18(workspace.root, binary.path);
|
|
68926
69913
|
if (side === "theirs") {
|
|
68927
69914
|
if (conflict2.remoteSha256 !== null && conflict2.artifactPath !== void 0) {
|
|
68928
69915
|
writeVerifiedBinaryDownloadV4(
|
|
68929
69916
|
destination,
|
|
68930
|
-
readFileSync14(
|
|
69917
|
+
readFileSync14(join18(workspace.root, conflict2.artifactPath)),
|
|
68931
69918
|
conflict2.remoteSha256
|
|
68932
69919
|
);
|
|
68933
69920
|
binary.sha256 = conflict2.remoteSha256;
|
|
@@ -68937,7 +69924,7 @@ function runResolve(workspace, side) {
|
|
|
68937
69924
|
}
|
|
68938
69925
|
}
|
|
68939
69926
|
if (conflict2.artifactPath !== void 0) {
|
|
68940
|
-
rmSync7(
|
|
69927
|
+
rmSync7(join18(workspace.root, conflict2.artifactPath), { force: true });
|
|
68941
69928
|
}
|
|
68942
69929
|
delete binary.conflict;
|
|
68943
69930
|
resolvedBinaries += 1;
|
|
@@ -68990,7 +69977,7 @@ function resolveMarkers(source, side) {
|
|
|
68990
69977
|
return output.join("\n");
|
|
68991
69978
|
}
|
|
68992
69979
|
function workspaceFilePath(workspace, file) {
|
|
68993
|
-
return
|
|
69980
|
+
return join18(workspace.root, file);
|
|
68994
69981
|
}
|
|
68995
69982
|
var init_resolve = __esm({
|
|
68996
69983
|
"src/commands/resolve.ts"() {
|
|
@@ -69373,6 +70360,7 @@ function projectStatusJsonV4(status, options) {
|
|
|
69373
70360
|
blocking: isBlockingSchemaSourceError(error),
|
|
69374
70361
|
message: error.message
|
|
69375
70362
|
})),
|
|
70363
|
+
warnings: status.warnings,
|
|
69376
70364
|
records: status.changes.map(
|
|
69377
70365
|
(change) => recordChangeJsonV4(change, status, options)
|
|
69378
70366
|
),
|
|
@@ -70051,6 +71039,9 @@ async function main() {
|
|
|
70051
71039
|
for (const error of status.parseErrors) {
|
|
70052
71040
|
console.log(`${sym.warn} ${error.message}`);
|
|
70053
71041
|
}
|
|
71042
|
+
for (const message of status.warnings) {
|
|
71043
|
+
console.log(`${sym.warn} ${message}`);
|
|
71044
|
+
}
|
|
70054
71045
|
for (const group of groupProjectStatusChangesV4(status)) {
|
|
70055
71046
|
console.log(color.bold(group.source));
|
|
70056
71047
|
for (const change of group.changes) {
|