@neocompose/cli 0.61.1 → 0.61.3
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 +10 -0
- package/dist/neo.mjs +612 -210
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/commands-and-sync.md +6 -0
- package/skills/neocompose-cli/references/declarations-and-construction.md +4 -0
- package/skills/neocompose-cli/references/values-identities-and-references.md +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.61.3] - 2026-10-01
|
|
4
|
+
|
|
5
|
+
- Resolve `collectionValue: Reference(root.Assets.Quests.Daily)` through construction defaults, including classes and empty collections declared in the same push. Preparation creates the required rows and associations together; no preliminary push or manually assigned value IDs are needed.
|
|
6
|
+
- Preserve generated collection identities through source verification and subsequent pulls. Report one source diagnostic when a collection path cannot resolve.
|
|
7
|
+
- Capture root-path reads through construction defaults as executable initializers, including nested object fields. Preserve sparse receiver identities during read-only construction replay so local and web preparation can resolve those reads.
|
|
8
|
+
|
|
9
|
+
## [0.61.2] - 2026-09-30
|
|
10
|
+
|
|
11
|
+
- Delete hidden collection entry members when their owning class or collection declaration is removed or changed to a scalar, while preserving entries still used by surviving declarations.
|
|
12
|
+
|
|
3
13
|
## [0.61.1] - 2026-09-30
|
|
4
14
|
|
|
5
15
|
- Resolve and emit lookup dialogue group collections as `Class.Member` and `Reference(root.Assets.Member)`, including lists created in the same push. Existing raw-ID references remain readable.
|
package/dist/neo.mjs
CHANGED
|
@@ -49838,6 +49838,40 @@ function descendantClassIdsInChildIndex(classId, childrenByClassId) {
|
|
|
49838
49838
|
}
|
|
49839
49839
|
return result;
|
|
49840
49840
|
}
|
|
49841
|
+
function addDependentMemberIds(memberIds, members) {
|
|
49842
|
+
const childIdsByParentId = /* @__PURE__ */ new Map();
|
|
49843
|
+
const entryIdByOwnerId = /* @__PURE__ */ new Map();
|
|
49844
|
+
const remainingOwnersByEntryId = /* @__PURE__ */ new Map();
|
|
49845
|
+
for (const member of members) {
|
|
49846
|
+
if (member.extendsMemberId) {
|
|
49847
|
+
const children = childIdsByParentId.get(member.extendsMemberId);
|
|
49848
|
+
if (children === void 0) {
|
|
49849
|
+
childIdsByParentId.set(member.extendsMemberId, [member.id]);
|
|
49850
|
+
} else children.push(member.id);
|
|
49851
|
+
}
|
|
49852
|
+
if (member.entryMemberId) {
|
|
49853
|
+
entryIdByOwnerId.set(member.id, member.entryMemberId);
|
|
49854
|
+
remainingOwnersByEntryId.set(
|
|
49855
|
+
member.entryMemberId,
|
|
49856
|
+
(remainingOwnersByEntryId.get(member.entryMemberId) ?? 0) + 1
|
|
49857
|
+
);
|
|
49858
|
+
}
|
|
49859
|
+
}
|
|
49860
|
+
const pending = [...memberIds];
|
|
49861
|
+
function include(memberId) {
|
|
49862
|
+
if (memberIds.has(memberId)) return;
|
|
49863
|
+
memberIds.add(memberId);
|
|
49864
|
+
pending.push(memberId);
|
|
49865
|
+
}
|
|
49866
|
+
for (let id2 = pending.pop(); id2 !== void 0; id2 = pending.pop()) {
|
|
49867
|
+
for (const childId of childIdsByParentId.get(id2) ?? []) include(childId);
|
|
49868
|
+
const entryId = entryIdByOwnerId.get(id2);
|
|
49869
|
+
if (entryId === void 0) continue;
|
|
49870
|
+
const remainingOwners = remainingOwnersByEntryId.get(entryId) - 1;
|
|
49871
|
+
remainingOwnersByEntryId.set(entryId, remainingOwners);
|
|
49872
|
+
if (remainingOwners === 0) include(entryId);
|
|
49873
|
+
}
|
|
49874
|
+
}
|
|
49841
49875
|
var UnresolvedMemberInheritanceError, NO_CLASSES, NO_MEMBERS, instanceSurfaceMemo, storedInstanceMemo, readOnlyMemberMemo, staticMemberMemo;
|
|
49842
49876
|
var init_inheritance = __esm({
|
|
49843
49877
|
"../src/models/classes/inheritance.ts"() {
|
|
@@ -63050,6 +63084,7 @@ function isSourceMemberValueRead(context, expression, ownerClass) {
|
|
|
63050
63084
|
while (current.kind === "annotated") current = current.expression;
|
|
63051
63085
|
const path = expressionMemberPath(current);
|
|
63052
63086
|
if (path === null) return false;
|
|
63087
|
+
if (path.startsWith("root.")) return true;
|
|
63053
63088
|
const parts = path.split(".");
|
|
63054
63089
|
let classId;
|
|
63055
63090
|
let memberName;
|
|
@@ -75726,7 +75761,7 @@ function withEvaluationRuntime(ctx, writes) {
|
|
|
75726
75761
|
ctx.__runtimeSessionValues
|
|
75727
75762
|
);
|
|
75728
75763
|
const referencesAlreadyRemapped = ctx.__valueOverlay !== void 0 && ctx.__runtimeReferenceRemap !== void 0;
|
|
75729
|
-
const remap = (value) => referencesAlreadyRemapped ? value : remapRuntimeReferences(
|
|
75764
|
+
const remap = (value) => referencesAlreadyRemapped || ctx.storedConstructionReplay === true ? value : remapRuntimeReferences(
|
|
75730
75765
|
value,
|
|
75731
75766
|
overlay,
|
|
75732
75767
|
referenceRemap,
|
|
@@ -85719,14 +85754,15 @@ function claimVirtualIdentity(args) {
|
|
|
85719
85754
|
virtualId: args.fixedVirtualId
|
|
85720
85755
|
};
|
|
85721
85756
|
}
|
|
85722
|
-
const
|
|
85757
|
+
const valueId = (sourceIdentity4) => args.instanceRootId.startsWith("__pending__:") || hasPendingVirtualSourceIdentity(sourceIdentity4) ? pendingVirtualValueId(args.instanceRootId, sourceIdentity4) : virtualValueId(args.instanceRootId, sourceIdentity4);
|
|
85758
|
+
const derivedId = valueId(args.rawSourceIdentity);
|
|
85723
85759
|
const claimedPath = args.claimedVirtualIds.get(derivedId);
|
|
85724
85760
|
if (claimedPath === void 0 || claimedPath === args.pathKey) {
|
|
85725
85761
|
args.claimedVirtualIds.set(derivedId, args.pathKey);
|
|
85726
85762
|
return { sourceIdentity: args.rawSourceIdentity, virtualId: derivedId };
|
|
85727
85763
|
}
|
|
85728
85764
|
const sourceIdentity3 = `${args.rawSourceIdentity}:${args.pathKey}`;
|
|
85729
|
-
const virtualId =
|
|
85765
|
+
const virtualId = valueId(sourceIdentity3);
|
|
85730
85766
|
args.claimedVirtualIds.set(virtualId, args.pathKey);
|
|
85731
85767
|
return { sourceIdentity: sourceIdentity3, virtualId };
|
|
85732
85768
|
}
|
|
@@ -88107,6 +88143,8 @@ function createHeadlessVirtualInstanceResolver(args) {
|
|
|
88107
88143
|
const remember = (graph, rows) => {
|
|
88108
88144
|
graphRowsByRootId.set(graph.instanceRootId, rows);
|
|
88109
88145
|
for (const [id2, row] of graph.rowsById) {
|
|
88146
|
+
if (id2 !== graph.instanceRootId && graphByValueId.get(id2)?.instanceRootId === id2)
|
|
88147
|
+
continue;
|
|
88110
88148
|
expandedRowById.set(id2, row);
|
|
88111
88149
|
graphByValueId.set(id2, graph);
|
|
88112
88150
|
if (typeof row.value === "object" && row.value !== null) {
|
|
@@ -88114,6 +88152,8 @@ function createHeadlessVirtualInstanceResolver(args) {
|
|
|
88114
88152
|
}
|
|
88115
88153
|
}
|
|
88116
88154
|
for (const id2 of graph.locationsById.keys()) {
|
|
88155
|
+
if (id2 !== graph.instanceRootId && graphByValueId.get(id2)?.instanceRootId === id2)
|
|
88156
|
+
continue;
|
|
88117
88157
|
graphByValueId.set(id2, graph);
|
|
88118
88158
|
}
|
|
88119
88159
|
graphByValueId.set(graph.instanceRootId, graph);
|
|
@@ -88232,7 +88272,10 @@ function createHeadlessVirtualInstanceResolver(args) {
|
|
|
88232
88272
|
rowForValueReference: (value) => expandedRowByRecord.get(value) ?? null,
|
|
88233
88273
|
virtualInstanceGraphForValue: (valueId) => {
|
|
88234
88274
|
const known = graphByValueId.get(valueId);
|
|
88235
|
-
if (known
|
|
88275
|
+
if (known?.instanceRootId === valueId) return known;
|
|
88276
|
+
const stored = rawById.get(valueId);
|
|
88277
|
+
if (known !== void 0 && (stored === void 0 || !isStoredClassResolutionRoot(stored)))
|
|
88278
|
+
return known;
|
|
88236
88279
|
virtualInstanceRowsForValue(valueId);
|
|
88237
88280
|
return graphByValueId.get(valueId) ?? null;
|
|
88238
88281
|
},
|
|
@@ -98302,6 +98345,389 @@ var init_project_commit_preparation_scoped_loader = __esm({
|
|
|
98302
98345
|
}
|
|
98303
98346
|
});
|
|
98304
98347
|
|
|
98348
|
+
// ../src/runtime/neoscript/index.ts
|
|
98349
|
+
var init_neoscript2 = __esm({
|
|
98350
|
+
"../src/runtime/neoscript/index.ts"() {
|
|
98351
|
+
"use strict";
|
|
98352
|
+
init_NSGetterRuntimeError();
|
|
98353
|
+
init_evaluateNSGetter();
|
|
98354
|
+
init_evaluateInitializer();
|
|
98355
|
+
init_initializer_context();
|
|
98356
|
+
}
|
|
98357
|
+
});
|
|
98358
|
+
|
|
98359
|
+
// ../src/database/headless-virtual-instance-lookups.ts
|
|
98360
|
+
function headlessVirtualInstanceLookups(document, options = {}) {
|
|
98361
|
+
const members = document.members;
|
|
98362
|
+
const expandedDocument = expandPackedDocumentValues(document);
|
|
98363
|
+
const values = expandedDocument.values;
|
|
98364
|
+
const indexed = makeEvaluatorLookups(
|
|
98365
|
+
members,
|
|
98366
|
+
values,
|
|
98367
|
+
options.includeValueGraphIndexes === true ? {
|
|
98368
|
+
includeValueGraphIndexes: true,
|
|
98369
|
+
constructorInitializerDocument: {
|
|
98370
|
+
classes: document.classes,
|
|
98371
|
+
members,
|
|
98372
|
+
values
|
|
98373
|
+
}
|
|
98374
|
+
} : {}
|
|
98375
|
+
);
|
|
98376
|
+
const virtual = createHeadlessVirtualInstanceResolver2({
|
|
98377
|
+
document: {
|
|
98378
|
+
...expandedDocument,
|
|
98379
|
+
...options.initializerCompiler === void 0 ? {} : { initializerCompiler: options.initializerCompiler }
|
|
98380
|
+
},
|
|
98381
|
+
// A thunk: the resolver resolves nested reads through the lookups being
|
|
98382
|
+
// built around it.
|
|
98383
|
+
resolverLookups: () => lookups
|
|
98384
|
+
});
|
|
98385
|
+
const lookups = {
|
|
98386
|
+
...indexed,
|
|
98387
|
+
// Raw first, then virtual: a materialized row always wins over the
|
|
98388
|
+
// expansion that would otherwise answer for it.
|
|
98389
|
+
valueById: (id2) => indexed.valueById(id2) ?? virtual.valueById(id2),
|
|
98390
|
+
rowForValueReference: (value) => indexed.rowForValueReference(value) ?? virtual.rowForValueReference(value),
|
|
98391
|
+
virtualInstanceRowsForValue: (receiverValueId) => virtual.virtualInstanceRowsForValue(receiverValueId),
|
|
98392
|
+
// Stored-construction replay evaluates `ToVariant`, and production's
|
|
98393
|
+
// variant-constructed placements collapse through exactly this path.
|
|
98394
|
+
resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument2({
|
|
98395
|
+
document,
|
|
98396
|
+
resolverLookups: lookups,
|
|
98397
|
+
...args
|
|
98398
|
+
}),
|
|
98399
|
+
// A write to a virtual key must MATERIALIZE it (a pin row at the
|
|
98400
|
+
// deterministic virtual id plus the sparse spine); the planner needs the
|
|
98401
|
+
// owning graph, not just its rows.
|
|
98402
|
+
virtualInstanceGraphForValue: (valueId) => virtual.virtualInstanceGraphForValue(valueId)
|
|
98403
|
+
};
|
|
98404
|
+
return lookups;
|
|
98405
|
+
}
|
|
98406
|
+
var init_headless_virtual_instance_lookups = __esm({
|
|
98407
|
+
"../src/database/headless-virtual-instance-lookups.ts"() {
|
|
98408
|
+
"use strict";
|
|
98409
|
+
init_virtual_instance_values();
|
|
98410
|
+
init_packed_value_encoding();
|
|
98411
|
+
init_neoscript2();
|
|
98412
|
+
}
|
|
98413
|
+
});
|
|
98414
|
+
|
|
98415
|
+
// ../src/database/collection-binding-materialization.ts
|
|
98416
|
+
function mergeBodies(left, right) {
|
|
98417
|
+
if (right === void 0) return left;
|
|
98418
|
+
if (typeof left === "object" && left !== null && !Array.isArray(left) && typeof right === "object" && right !== null && !Array.isArray(right)) {
|
|
98419
|
+
return { ...left, ...right };
|
|
98420
|
+
}
|
|
98421
|
+
return right;
|
|
98422
|
+
}
|
|
98423
|
+
var CollectionBindingMaterializer;
|
|
98424
|
+
var init_collection_binding_materialization = __esm({
|
|
98425
|
+
"../src/database/collection-binding-materialization.ts"() {
|
|
98426
|
+
"use strict";
|
|
98427
|
+
init_members();
|
|
98428
|
+
init_virtual_instance_values();
|
|
98429
|
+
init_headless_virtual_instance_lookups();
|
|
98430
|
+
init_document_initializer_compiler();
|
|
98431
|
+
CollectionBindingMaterializer = class {
|
|
98432
|
+
constructor(document) {
|
|
98433
|
+
this.document = document;
|
|
98434
|
+
this.stored = new Map(document.values.map((row) => [row.id, row]));
|
|
98435
|
+
this.lookups = headlessVirtualInstanceLookups(document, {
|
|
98436
|
+
initializerCompiler: documentInitializerCompiler(document)
|
|
98437
|
+
});
|
|
98438
|
+
}
|
|
98439
|
+
document;
|
|
98440
|
+
rows = /* @__PURE__ */ new Map();
|
|
98441
|
+
pathRowsByRootId = /* @__PURE__ */ new Map();
|
|
98442
|
+
stored;
|
|
98443
|
+
lookups;
|
|
98444
|
+
resolvePath(rootId, segments) {
|
|
98445
|
+
let id2 = rootId;
|
|
98446
|
+
const pathRows = this.pathRowsByRootId.get(rootId) ?? /* @__PURE__ */ new Set();
|
|
98447
|
+
this.pathRowsByRootId.set(rootId, pathRows);
|
|
98448
|
+
for (const segment of segments) {
|
|
98449
|
+
const graph = this.lookups.virtualInstanceGraphForValue(id2);
|
|
98450
|
+
const row = graph?.rowsById.get(id2) ?? this.stored.get(id2);
|
|
98451
|
+
if (row === void 0 || !isLiteralValueContent(row)) return null;
|
|
98452
|
+
const body = row.value;
|
|
98453
|
+
if (typeof body !== "object" || body === null || Array.isArray(body))
|
|
98454
|
+
return null;
|
|
98455
|
+
const next = Reflect.get(body, segment);
|
|
98456
|
+
if (typeof next !== "string") return null;
|
|
98457
|
+
id2 = next;
|
|
98458
|
+
pathRows.add(id2);
|
|
98459
|
+
}
|
|
98460
|
+
return this.materialize(id2, pathRows) ? id2 : null;
|
|
98461
|
+
}
|
|
98462
|
+
/** Discover opaque virtual IDs from web selections against this candidate's roots. */
|
|
98463
|
+
materializeTargets(ids) {
|
|
98464
|
+
const missing = new Set([...ids].filter((id2) => !this.stored.has(id2)));
|
|
98465
|
+
if (missing.size === 0) return;
|
|
98466
|
+
const visited = /* @__PURE__ */ new Set();
|
|
98467
|
+
for (const row of this.document.values) {
|
|
98468
|
+
if (typeof row.classId !== "string") continue;
|
|
98469
|
+
const graph = this.lookups.virtualInstanceGraphForValue(row.id);
|
|
98470
|
+
if (graph === null || visited.has(graph.instanceRootId)) continue;
|
|
98471
|
+
visited.add(graph.instanceRootId);
|
|
98472
|
+
for (const id2 of graph.rowsById.keys()) {
|
|
98473
|
+
if (!missing.has(id2)) continue;
|
|
98474
|
+
if (this.materialize(id2)) missing.delete(id2);
|
|
98475
|
+
}
|
|
98476
|
+
if (missing.size === 0) return;
|
|
98477
|
+
}
|
|
98478
|
+
if (missing.size > 0) {
|
|
98479
|
+
throw new Error(
|
|
98480
|
+
`Collection binding targets missing values: ${[...missing].join(", ")}.`
|
|
98481
|
+
);
|
|
98482
|
+
}
|
|
98483
|
+
}
|
|
98484
|
+
locationForValue(id2) {
|
|
98485
|
+
return this.lookups.virtualInstanceGraphForValue(id2)?.locationsById.get(id2);
|
|
98486
|
+
}
|
|
98487
|
+
rowForValue(id2) {
|
|
98488
|
+
return this.rows.get(id2) ?? this.stored.get(id2);
|
|
98489
|
+
}
|
|
98490
|
+
materialize(id2, pathRows) {
|
|
98491
|
+
if (this.stored.has(id2) || this.rows.has(id2)) return true;
|
|
98492
|
+
const graph = this.lookups.virtualInstanceGraphForValue(id2);
|
|
98493
|
+
const row = graph?.rowsById.get(id2);
|
|
98494
|
+
if (graph === null || row === void 0 || !isLiteralValueContent(row))
|
|
98495
|
+
return false;
|
|
98496
|
+
const plan = planVirtualOverrideWrite({
|
|
98497
|
+
graph,
|
|
98498
|
+
valueId: id2,
|
|
98499
|
+
value: row.value
|
|
98500
|
+
});
|
|
98501
|
+
for (const create of plan.creates) {
|
|
98502
|
+
pathRows?.add(create.id);
|
|
98503
|
+
const { valuePlacement: _placement, ...fields } = create;
|
|
98504
|
+
const previous = this.rows.get(create.id);
|
|
98505
|
+
this.rows.set(create.id, {
|
|
98506
|
+
...fields,
|
|
98507
|
+
value: mergeBodies(fields.value, previous?.value),
|
|
98508
|
+
projectId: this.document.project.id,
|
|
98509
|
+
createdAt: 0,
|
|
98510
|
+
updatedAt: 0
|
|
98511
|
+
});
|
|
98512
|
+
}
|
|
98513
|
+
for (const update of plan.updates) {
|
|
98514
|
+
pathRows?.add(update.valueId);
|
|
98515
|
+
const previous = this.rows.get(update.valueId) ?? this.stored.get(update.valueId);
|
|
98516
|
+
if (previous === void 0)
|
|
98517
|
+
throw new Error(
|
|
98518
|
+
`Collection binding has no ancestor ${update.valueId}.`
|
|
98519
|
+
);
|
|
98520
|
+
this.rows.set(update.valueId, {
|
|
98521
|
+
...previous,
|
|
98522
|
+
value: mergeBodies(previous.value, update.value)
|
|
98523
|
+
});
|
|
98524
|
+
}
|
|
98525
|
+
return true;
|
|
98526
|
+
}
|
|
98527
|
+
};
|
|
98528
|
+
}
|
|
98529
|
+
});
|
|
98530
|
+
|
|
98531
|
+
// ../src/database/project-version-write-changes.ts
|
|
98532
|
+
function applyProjectVersionWriteChanges(document, changes) {
|
|
98533
|
+
return projectVersionDocumentWithChanges(document, changes, false);
|
|
98534
|
+
}
|
|
98535
|
+
function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
|
|
98536
|
+
const projectRows = (rows, kind) => {
|
|
98537
|
+
const relevant = changes.filter((change) => change.recordKind === kind);
|
|
98538
|
+
if (reuseUnchangedBuckets && relevant.length === 0) return rows;
|
|
98539
|
+
return applyArrayChanges(rows, relevant);
|
|
98540
|
+
};
|
|
98541
|
+
const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
|
|
98542
|
+
const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
|
|
98543
|
+
const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
|
|
98544
|
+
const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
|
|
98545
|
+
const projected = {
|
|
98546
|
+
localizedTexts: projectRows(
|
|
98547
|
+
document.localizedTexts ?? [],
|
|
98548
|
+
"localized-text"
|
|
98549
|
+
),
|
|
98550
|
+
localizationConfig: applySingletonChange(
|
|
98551
|
+
document.localizationConfig,
|
|
98552
|
+
changes,
|
|
98553
|
+
"localization-config"
|
|
98554
|
+
),
|
|
98555
|
+
project: applySingletonChange(document.project, changes, "project"),
|
|
98556
|
+
members: projectRows(document.members, "member"),
|
|
98557
|
+
classes: projectRows(document.classes, "class"),
|
|
98558
|
+
// P43 §6. Declared constructors participate in the post-transaction
|
|
98559
|
+
// document so the whole-graph validator and every body compile see the
|
|
98560
|
+
// same constructor surface the transaction is about to persist.
|
|
98561
|
+
constructors: projectRows(document.constructors ?? [], "constructor"),
|
|
98562
|
+
// P67 §2.1. Same reason as constructors: without these buckets the
|
|
98563
|
+
// whole-graph validator, the variant ownership roots, and every body
|
|
98564
|
+
// compile would grade the transaction against the pre-transaction
|
|
98565
|
+
// variant set — so a newly pushed variant's closures would compile
|
|
98566
|
+
// against a document that does not contain it.
|
|
98567
|
+
variants: projectRows(document.variants ?? [], "variant"),
|
|
98568
|
+
variantFolders: projectRows(
|
|
98569
|
+
document.variantFolders ?? [],
|
|
98570
|
+
"variant-folder"
|
|
98571
|
+
),
|
|
98572
|
+
values: projectRows(document.values ?? [], "value"),
|
|
98573
|
+
// Project-file staging finalizes pending uploads before schema
|
|
98574
|
+
// preparation. Defaults and authored instance graphs may reference a file
|
|
98575
|
+
// created by the same source transaction, so every construction pass must
|
|
98576
|
+
// see that finalized row in its post-write document.
|
|
98577
|
+
projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
|
|
98578
|
+
// Import-setting templates are part of the same file graph. A new file
|
|
98579
|
+
// may select a new template in one source transaction, and default-value
|
|
98580
|
+
// materialization validates that relationship immediately against this
|
|
98581
|
+
// post-write document.
|
|
98582
|
+
textureTemplates: projectRows(
|
|
98583
|
+
document.textureTemplates ?? [],
|
|
98584
|
+
"unity-texture-template"
|
|
98585
|
+
),
|
|
98586
|
+
audioClipTemplates: projectRows(
|
|
98587
|
+
document.audioClipTemplates ?? [],
|
|
98588
|
+
"unity-audio-clip-template"
|
|
98589
|
+
),
|
|
98590
|
+
internalRecordRelations: projectRows(
|
|
98591
|
+
document.internalRecordRelations ?? [],
|
|
98592
|
+
"internal-record-relation"
|
|
98593
|
+
),
|
|
98594
|
+
enums: projectRows(document.enums, "enum"),
|
|
98595
|
+
interfaces: projectRows(document.interfaces, "interface"),
|
|
98596
|
+
dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
|
|
98597
|
+
dialogueRecords,
|
|
98598
|
+
dialogueNodes
|
|
98599
|
+
),
|
|
98600
|
+
dialogueGroups: projectRows(
|
|
98601
|
+
document.dialogueGroups ?? [],
|
|
98602
|
+
"dialogue-group"
|
|
98603
|
+
),
|
|
98604
|
+
migrations: projectRows(document.migrations ?? [], "migration")
|
|
98605
|
+
};
|
|
98606
|
+
return {
|
|
98607
|
+
...document,
|
|
98608
|
+
...projected,
|
|
98609
|
+
...dialogueRecords === void 0 ? {} : { dialogueRecords },
|
|
98610
|
+
...dialogueNodes === void 0 ? {} : { dialogueNodes }
|
|
98611
|
+
// The document spread above carries every bucket the caller's view declares
|
|
98612
|
+
// beyond the projected ones, so the result is the same view; TypeScript
|
|
98613
|
+
// cannot prove that of an object literal built over a type parameter.
|
|
98614
|
+
};
|
|
98615
|
+
}
|
|
98616
|
+
function applySingletonChange(current, changes, recordKind) {
|
|
98617
|
+
const change = changes.find(
|
|
98618
|
+
(candidate) => candidate.recordKind === recordKind
|
|
98619
|
+
);
|
|
98620
|
+
if (change === void 0) return current;
|
|
98621
|
+
if (change.operation === "delete" || change.nextData === void 0) {
|
|
98622
|
+
throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
|
|
98623
|
+
}
|
|
98624
|
+
return change.nextData;
|
|
98625
|
+
}
|
|
98626
|
+
function applyArrayChanges(current, changes) {
|
|
98627
|
+
const byId = new Map(current.map((record6) => [record6.id, record6]));
|
|
98628
|
+
for (const change of changes) {
|
|
98629
|
+
if (change.operation === "delete") {
|
|
98630
|
+
byId.delete(change.recordId);
|
|
98631
|
+
continue;
|
|
98632
|
+
}
|
|
98633
|
+
if (change.nextData !== void 0) {
|
|
98634
|
+
byId.set(change.recordId, change.nextData);
|
|
98635
|
+
}
|
|
98636
|
+
}
|
|
98637
|
+
return [...byId.values()];
|
|
98638
|
+
}
|
|
98639
|
+
var init_project_version_write_changes = __esm({
|
|
98640
|
+
"../src/database/project-version-write-changes.ts"() {
|
|
98641
|
+
"use strict";
|
|
98642
|
+
init_projectDocumentDialogueMaterialization();
|
|
98643
|
+
}
|
|
98644
|
+
});
|
|
98645
|
+
|
|
98646
|
+
// ../src/database/prepared-collection-bindings.ts
|
|
98647
|
+
function materializePreparedCollectionBindings(args) {
|
|
98648
|
+
const targets = /* @__PURE__ */ new Set();
|
|
98649
|
+
for (const change of args.prepared) {
|
|
98650
|
+
if (change.operation === "delete") continue;
|
|
98651
|
+
if (change.recordKind !== "member" && change.recordKind !== "variant-folder" && change.recordKind !== "dialogue-group")
|
|
98652
|
+
continue;
|
|
98653
|
+
const data = change.nextData;
|
|
98654
|
+
if (typeof data !== "object" || data === null) continue;
|
|
98655
|
+
const binding = change.recordKind === "variant-folder" ? Reflect.get(data, "binding") : data;
|
|
98656
|
+
if (typeof binding !== "object" || binding === null) continue;
|
|
98657
|
+
const id2 = Reflect.get(binding, "collectionValueId");
|
|
98658
|
+
if (typeof id2 === "string") targets.add(id2);
|
|
98659
|
+
}
|
|
98660
|
+
if (targets.size === 0) return;
|
|
98661
|
+
const deletedTargets = /* @__PURE__ */ new Set();
|
|
98662
|
+
for (const change of args.prepared) {
|
|
98663
|
+
if (change.recordKind !== "value" || !targets.has(change.recordId))
|
|
98664
|
+
continue;
|
|
98665
|
+
if (change.operation === "delete") deletedTargets.add(change.recordId);
|
|
98666
|
+
else targets.delete(change.recordId);
|
|
98667
|
+
}
|
|
98668
|
+
if (targets.size === 0) return;
|
|
98669
|
+
for (const row of args.document.values) {
|
|
98670
|
+
if (!deletedTargets.has(row.id)) targets.delete(row.id);
|
|
98671
|
+
if (targets.size === 0) return;
|
|
98672
|
+
}
|
|
98673
|
+
const document = projectVersionDocumentWithChanges(
|
|
98674
|
+
args.document,
|
|
98675
|
+
args.prepared,
|
|
98676
|
+
true
|
|
98677
|
+
);
|
|
98678
|
+
const existingIds = new Set(document.values.map((row) => row.id));
|
|
98679
|
+
const materializer = new CollectionBindingMaterializer(document);
|
|
98680
|
+
materializer.materializeTargets(targets);
|
|
98681
|
+
const indexes2 = /* @__PURE__ */ new Map();
|
|
98682
|
+
args.prepared.forEach((change, index) => {
|
|
98683
|
+
if (change.recordKind === "value") indexes2.set(change.recordId, index);
|
|
98684
|
+
});
|
|
98685
|
+
const hashes = new Map(
|
|
98686
|
+
args.contentHashHeads.filter((head) => head.recordKind === "value").map((head) => [head.recordId, head.contentHash])
|
|
98687
|
+
);
|
|
98688
|
+
for (const row of materializer.rows.values()) {
|
|
98689
|
+
const index = indexes2.get(row.id);
|
|
98690
|
+
if (index !== void 0) {
|
|
98691
|
+
const previous = args.prepared[index];
|
|
98692
|
+
args.prepared[index] = {
|
|
98693
|
+
...previous,
|
|
98694
|
+
operation: previous.operation === "delete" ? "update" : previous.operation,
|
|
98695
|
+
deleted: false,
|
|
98696
|
+
nextData: row,
|
|
98697
|
+
intent: previous.operation === "delete" ? createProjectVersionIntent("value.update", {
|
|
98698
|
+
source: "collection-binding-materialization"
|
|
98699
|
+
}) : previous.intent
|
|
98700
|
+
};
|
|
98701
|
+
continue;
|
|
98702
|
+
}
|
|
98703
|
+
const contentHash = hashes.get(row.id);
|
|
98704
|
+
if (existingIds.has(row.id) && contentHash === void 0) {
|
|
98705
|
+
throw new Error(
|
|
98706
|
+
`Collection binding ancestor "${row.id}" has no content hash.`
|
|
98707
|
+
);
|
|
98708
|
+
}
|
|
98709
|
+
args.prepared.push({
|
|
98710
|
+
recordKind: "value",
|
|
98711
|
+
recordId: row.id,
|
|
98712
|
+
operation: existingIds.has(row.id) ? "update" : "create",
|
|
98713
|
+
nextData: row,
|
|
98714
|
+
expectedBaseContentHash: contentHash ?? null,
|
|
98715
|
+
intent: createProjectVersionIntent(
|
|
98716
|
+
existingIds.has(row.id) ? "value.update" : "value.create",
|
|
98717
|
+
{ source: "collection-binding-materialization" }
|
|
98718
|
+
)
|
|
98719
|
+
});
|
|
98720
|
+
}
|
|
98721
|
+
}
|
|
98722
|
+
var init_prepared_collection_bindings = __esm({
|
|
98723
|
+
"../src/database/prepared-collection-bindings.ts"() {
|
|
98724
|
+
"use strict";
|
|
98725
|
+
init_project_version_intents();
|
|
98726
|
+
init_collection_binding_materialization();
|
|
98727
|
+
init_project_version_write_changes();
|
|
98728
|
+
}
|
|
98729
|
+
});
|
|
98730
|
+
|
|
98305
98731
|
// ../src/models/project/world-content-sidecar-validation.ts
|
|
98306
98732
|
function cachedWorldLayerTarget(context, args) {
|
|
98307
98733
|
let target = context.linkTargetsByClassId.get(args.sourceClassId);
|
|
@@ -98957,17 +99383,6 @@ var init_world_content_sidecar_validation = __esm({
|
|
|
98957
99383
|
}
|
|
98958
99384
|
});
|
|
98959
99385
|
|
|
98960
|
-
// ../src/runtime/neoscript/index.ts
|
|
98961
|
-
var init_neoscript2 = __esm({
|
|
98962
|
-
"../src/runtime/neoscript/index.ts"() {
|
|
98963
|
-
"use strict";
|
|
98964
|
-
init_NSGetterRuntimeError();
|
|
98965
|
-
init_evaluateNSGetter();
|
|
98966
|
-
init_evaluateInitializer();
|
|
98967
|
-
init_initializer_context();
|
|
98968
|
-
}
|
|
98969
|
-
});
|
|
98970
|
-
|
|
98971
99386
|
// ../src/database/dialogue-node-index.ts
|
|
98972
99387
|
function indexDialogueNodesByDialogue(nodes, dialogueId) {
|
|
98973
99388
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -100266,62 +100681,6 @@ var init_general_function_call_ir_source_recompile = __esm({
|
|
|
100266
100681
|
}
|
|
100267
100682
|
});
|
|
100268
100683
|
|
|
100269
|
-
// ../src/database/headless-virtual-instance-lookups.ts
|
|
100270
|
-
function headlessVirtualInstanceLookups(document, options = {}) {
|
|
100271
|
-
const members = document.members;
|
|
100272
|
-
const expandedDocument = expandPackedDocumentValues(document);
|
|
100273
|
-
const values = expandedDocument.values;
|
|
100274
|
-
const indexed = makeEvaluatorLookups(
|
|
100275
|
-
members,
|
|
100276
|
-
values,
|
|
100277
|
-
options.includeValueGraphIndexes === true ? {
|
|
100278
|
-
includeValueGraphIndexes: true,
|
|
100279
|
-
constructorInitializerDocument: {
|
|
100280
|
-
classes: document.classes,
|
|
100281
|
-
members,
|
|
100282
|
-
values
|
|
100283
|
-
}
|
|
100284
|
-
} : {}
|
|
100285
|
-
);
|
|
100286
|
-
const virtual = createHeadlessVirtualInstanceResolver2({
|
|
100287
|
-
document: {
|
|
100288
|
-
...expandedDocument,
|
|
100289
|
-
...options.initializerCompiler === void 0 ? {} : { initializerCompiler: options.initializerCompiler }
|
|
100290
|
-
},
|
|
100291
|
-
// A thunk: the resolver resolves nested reads through the lookups being
|
|
100292
|
-
// built around it.
|
|
100293
|
-
resolverLookups: () => lookups
|
|
100294
|
-
});
|
|
100295
|
-
const lookups = {
|
|
100296
|
-
...indexed,
|
|
100297
|
-
// Raw first, then virtual: a materialized row always wins over the
|
|
100298
|
-
// expansion that would otherwise answer for it.
|
|
100299
|
-
valueById: (id2) => indexed.valueById(id2) ?? virtual.valueById(id2),
|
|
100300
|
-
rowForValueReference: (value) => indexed.rowForValueReference(value) ?? virtual.rowForValueReference(value),
|
|
100301
|
-
virtualInstanceRowsForValue: (receiverValueId) => virtual.virtualInstanceRowsForValue(receiverValueId),
|
|
100302
|
-
// Stored-construction replay evaluates `ToVariant`, and production's
|
|
100303
|
-
// variant-constructed placements collapse through exactly this path.
|
|
100304
|
-
resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument2({
|
|
100305
|
-
document,
|
|
100306
|
-
resolverLookups: lookups,
|
|
100307
|
-
...args
|
|
100308
|
-
}),
|
|
100309
|
-
// A write to a virtual key must MATERIALIZE it (a pin row at the
|
|
100310
|
-
// deterministic virtual id plus the sparse spine); the planner needs the
|
|
100311
|
-
// owning graph, not just its rows.
|
|
100312
|
-
virtualInstanceGraphForValue: (valueId) => virtual.virtualInstanceGraphForValue(valueId)
|
|
100313
|
-
};
|
|
100314
|
-
return lookups;
|
|
100315
|
-
}
|
|
100316
|
-
var init_headless_virtual_instance_lookups = __esm({
|
|
100317
|
-
"../src/database/headless-virtual-instance-lookups.ts"() {
|
|
100318
|
-
"use strict";
|
|
100319
|
-
init_virtual_instance_values();
|
|
100320
|
-
init_packed_value_encoding();
|
|
100321
|
-
init_neoscript2();
|
|
100322
|
-
}
|
|
100323
|
-
});
|
|
100324
|
-
|
|
100325
100684
|
// ../src/database/localized-instance-override-writes.ts
|
|
100326
100685
|
function collapseEditedLocalizedInstanceOverrides(args) {
|
|
100327
100686
|
const edits = args.changes.filter(
|
|
@@ -100753,121 +101112,6 @@ var init_member_access_modifier_validation = __esm({
|
|
|
100753
101112
|
}
|
|
100754
101113
|
});
|
|
100755
101114
|
|
|
100756
|
-
// ../src/database/project-version-write-changes.ts
|
|
100757
|
-
function applyProjectVersionWriteChanges(document, changes) {
|
|
100758
|
-
return projectVersionDocumentWithChanges(document, changes, false);
|
|
100759
|
-
}
|
|
100760
|
-
function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
|
|
100761
|
-
const projectRows = (rows, kind) => {
|
|
100762
|
-
const relevant = changes.filter((change) => change.recordKind === kind);
|
|
100763
|
-
if (reuseUnchangedBuckets && relevant.length === 0) return rows;
|
|
100764
|
-
return applyArrayChanges(rows, relevant);
|
|
100765
|
-
};
|
|
100766
|
-
const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
|
|
100767
|
-
const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
|
|
100768
|
-
const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
|
|
100769
|
-
const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
|
|
100770
|
-
const projected = {
|
|
100771
|
-
localizedTexts: projectRows(
|
|
100772
|
-
document.localizedTexts ?? [],
|
|
100773
|
-
"localized-text"
|
|
100774
|
-
),
|
|
100775
|
-
localizationConfig: applySingletonChange(
|
|
100776
|
-
document.localizationConfig,
|
|
100777
|
-
changes,
|
|
100778
|
-
"localization-config"
|
|
100779
|
-
),
|
|
100780
|
-
project: applySingletonChange(document.project, changes, "project"),
|
|
100781
|
-
members: projectRows(document.members, "member"),
|
|
100782
|
-
classes: projectRows(document.classes, "class"),
|
|
100783
|
-
// P43 §6. Declared constructors participate in the post-transaction
|
|
100784
|
-
// document so the whole-graph validator and every body compile see the
|
|
100785
|
-
// same constructor surface the transaction is about to persist.
|
|
100786
|
-
constructors: projectRows(document.constructors ?? [], "constructor"),
|
|
100787
|
-
// P67 §2.1. Same reason as constructors: without these buckets the
|
|
100788
|
-
// whole-graph validator, the variant ownership roots, and every body
|
|
100789
|
-
// compile would grade the transaction against the pre-transaction
|
|
100790
|
-
// variant set — so a newly pushed variant's closures would compile
|
|
100791
|
-
// against a document that does not contain it.
|
|
100792
|
-
variants: projectRows(document.variants ?? [], "variant"),
|
|
100793
|
-
variantFolders: projectRows(
|
|
100794
|
-
document.variantFolders ?? [],
|
|
100795
|
-
"variant-folder"
|
|
100796
|
-
),
|
|
100797
|
-
values: projectRows(document.values ?? [], "value"),
|
|
100798
|
-
// Project-file staging finalizes pending uploads before schema
|
|
100799
|
-
// preparation. Defaults and authored instance graphs may reference a file
|
|
100800
|
-
// created by the same source transaction, so every construction pass must
|
|
100801
|
-
// see that finalized row in its post-write document.
|
|
100802
|
-
projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
|
|
100803
|
-
// Import-setting templates are part of the same file graph. A new file
|
|
100804
|
-
// may select a new template in one source transaction, and default-value
|
|
100805
|
-
// materialization validates that relationship immediately against this
|
|
100806
|
-
// post-write document.
|
|
100807
|
-
textureTemplates: projectRows(
|
|
100808
|
-
document.textureTemplates ?? [],
|
|
100809
|
-
"unity-texture-template"
|
|
100810
|
-
),
|
|
100811
|
-
audioClipTemplates: projectRows(
|
|
100812
|
-
document.audioClipTemplates ?? [],
|
|
100813
|
-
"unity-audio-clip-template"
|
|
100814
|
-
),
|
|
100815
|
-
internalRecordRelations: projectRows(
|
|
100816
|
-
document.internalRecordRelations ?? [],
|
|
100817
|
-
"internal-record-relation"
|
|
100818
|
-
),
|
|
100819
|
-
enums: projectRows(document.enums, "enum"),
|
|
100820
|
-
interfaces: projectRows(document.interfaces, "interface"),
|
|
100821
|
-
dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
|
|
100822
|
-
dialogueRecords,
|
|
100823
|
-
dialogueNodes
|
|
100824
|
-
),
|
|
100825
|
-
dialogueGroups: projectRows(
|
|
100826
|
-
document.dialogueGroups ?? [],
|
|
100827
|
-
"dialogue-group"
|
|
100828
|
-
),
|
|
100829
|
-
migrations: projectRows(document.migrations ?? [], "migration")
|
|
100830
|
-
};
|
|
100831
|
-
return {
|
|
100832
|
-
...document,
|
|
100833
|
-
...projected,
|
|
100834
|
-
...dialogueRecords === void 0 ? {} : { dialogueRecords },
|
|
100835
|
-
...dialogueNodes === void 0 ? {} : { dialogueNodes }
|
|
100836
|
-
// The document spread above carries every bucket the caller's view declares
|
|
100837
|
-
// beyond the projected ones, so the result is the same view; TypeScript
|
|
100838
|
-
// cannot prove that of an object literal built over a type parameter.
|
|
100839
|
-
};
|
|
100840
|
-
}
|
|
100841
|
-
function applySingletonChange(current, changes, recordKind) {
|
|
100842
|
-
const change = changes.find(
|
|
100843
|
-
(candidate) => candidate.recordKind === recordKind
|
|
100844
|
-
);
|
|
100845
|
-
if (change === void 0) return current;
|
|
100846
|
-
if (change.operation === "delete" || change.nextData === void 0) {
|
|
100847
|
-
throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
|
|
100848
|
-
}
|
|
100849
|
-
return change.nextData;
|
|
100850
|
-
}
|
|
100851
|
-
function applyArrayChanges(current, changes) {
|
|
100852
|
-
const byId = new Map(current.map((record6) => [record6.id, record6]));
|
|
100853
|
-
for (const change of changes) {
|
|
100854
|
-
if (change.operation === "delete") {
|
|
100855
|
-
byId.delete(change.recordId);
|
|
100856
|
-
continue;
|
|
100857
|
-
}
|
|
100858
|
-
if (change.nextData !== void 0) {
|
|
100859
|
-
byId.set(change.recordId, change.nextData);
|
|
100860
|
-
}
|
|
100861
|
-
}
|
|
100862
|
-
return [...byId.values()];
|
|
100863
|
-
}
|
|
100864
|
-
var init_project_version_write_changes = __esm({
|
|
100865
|
-
"../src/database/project-version-write-changes.ts"() {
|
|
100866
|
-
"use strict";
|
|
100867
|
-
init_projectDocumentDialogueMaterialization();
|
|
100868
|
-
}
|
|
100869
|
-
});
|
|
100870
|
-
|
|
100871
101115
|
// ../src/database/member-localization-normalization.ts
|
|
100872
101116
|
function planMemberLocalizationNormalization(input, now = 0) {
|
|
100873
101117
|
const before = expandPackedDocumentValues(input);
|
|
@@ -103316,6 +103560,11 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
|
|
|
103316
103560
|
prepared,
|
|
103317
103561
|
contentHashHeads: args.contentHashHeads
|
|
103318
103562
|
});
|
|
103563
|
+
materializePreparedCollectionBindings({
|
|
103564
|
+
document: args.document,
|
|
103565
|
+
prepared,
|
|
103566
|
+
contentHashHeads: args.contentHashHeads
|
|
103567
|
+
});
|
|
103319
103568
|
drainConstructedGraphValidations({
|
|
103320
103569
|
document: args.document,
|
|
103321
103570
|
prepared,
|
|
@@ -106806,6 +107055,7 @@ var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_
|
|
|
106806
107055
|
var init_project_version_schema_commit = __esm({
|
|
106807
107056
|
"../src/database/project-version-schema-commit.ts"() {
|
|
106808
107057
|
"use strict";
|
|
107058
|
+
init_prepared_collection_bindings();
|
|
106809
107059
|
init_document_initializer_compiler();
|
|
106810
107060
|
init_effective_value_comparison();
|
|
106811
107061
|
init_classes();
|
|
@@ -120773,7 +121023,8 @@ function resolveRootPathCollectionValuesV4(args) {
|
|
|
120773
121023
|
args.registry,
|
|
120774
121024
|
placements,
|
|
120775
121025
|
rootValues,
|
|
120776
|
-
fail2
|
|
121026
|
+
fail2,
|
|
121027
|
+
args.resolveVirtualPath
|
|
120777
121028
|
);
|
|
120778
121029
|
if (target !== null) resolved.set(member.id, target);
|
|
120779
121030
|
}
|
|
@@ -120811,7 +121062,8 @@ function resolveRootPathVariantFolderCollectionValuesV4(args) {
|
|
|
120811
121062
|
args.registry,
|
|
120812
121063
|
placements,
|
|
120813
121064
|
rootValues,
|
|
120814
|
-
fail2
|
|
121065
|
+
fail2,
|
|
121066
|
+
args.resolveVirtualPath
|
|
120815
121067
|
);
|
|
120816
121068
|
if (target !== null) resolved.set(folder.id, target);
|
|
120817
121069
|
}
|
|
@@ -120848,7 +121100,8 @@ function resolveRootPathDialogueGroupCollectionValuesV4(args) {
|
|
|
120848
121100
|
expression: null,
|
|
120849
121101
|
label: String(record6.fileFields.name)
|
|
120850
121102
|
}
|
|
120851
|
-
})
|
|
121103
|
+
}),
|
|
121104
|
+
args.resolveVirtualPath
|
|
120852
121105
|
);
|
|
120853
121106
|
if (target !== null) record6.fileFields.collectionValueId = target;
|
|
120854
121107
|
}
|
|
@@ -120868,7 +121121,7 @@ function rootSlotValueIds(state) {
|
|
|
120868
121121
|
});
|
|
120869
121122
|
return values;
|
|
120870
121123
|
}
|
|
120871
|
-
function walkRootValuePath(path, state, registry, placements, rootValues, fail2) {
|
|
121124
|
+
function walkRootValuePath(path, state, registry, placements, rootValues, fail2, resolveVirtualPath) {
|
|
120872
121125
|
const segments = path.split(".");
|
|
120873
121126
|
const slotName = segments[1];
|
|
120874
121127
|
if (segments[0] !== "root" || slotName === void 0) {
|
|
@@ -120911,10 +121164,17 @@ function walkRootValuePath(path, state, registry, placements, rootValues, fail2)
|
|
|
120911
121164
|
}
|
|
120912
121165
|
const next = placements.childrenByParentValueId.get(cursor)?.get(segment)?.childValueId;
|
|
120913
121166
|
if (typeof next !== "string") {
|
|
120914
|
-
|
|
120915
|
-
|
|
121167
|
+
try {
|
|
121168
|
+
const resolved = resolveVirtualPath?.(slotValueId, segments.slice(2));
|
|
121169
|
+
if (resolved != null) return resolved;
|
|
121170
|
+
} catch (error) {
|
|
121171
|
+
fail2(
|
|
121172
|
+
`collectionValue path ${path} could not resolve its construction: ${error instanceof Error ? error.message : String(error)}`
|
|
121173
|
+
);
|
|
121174
|
+
return null;
|
|
121175
|
+
}
|
|
120916
121176
|
fail2(
|
|
120917
|
-
|
|
121177
|
+
`collectionValue path ${path} has no value at segment ${segment} after this push.`
|
|
120918
121178
|
);
|
|
120919
121179
|
return null;
|
|
120920
121180
|
}
|
|
@@ -120984,7 +121244,6 @@ var init_root_source = __esm({
|
|
|
120984
121244
|
"use strict";
|
|
120985
121245
|
init_src();
|
|
120986
121246
|
init_src2();
|
|
120987
|
-
init_instance_provenance();
|
|
120988
121247
|
init_value_sources();
|
|
120989
121248
|
init_source_format();
|
|
120990
121249
|
init_stored_value_placements();
|
|
@@ -122263,6 +122522,61 @@ function recordUpsertChange(args) {
|
|
|
122263
122522
|
casBaseHash: inConflictState ? args.base.conflictServerHash : args.base.contentHash
|
|
122264
122523
|
};
|
|
122265
122524
|
}
|
|
122525
|
+
function recordDeleteChange(base, file) {
|
|
122526
|
+
return {
|
|
122527
|
+
kind: "delete",
|
|
122528
|
+
recordKind: base.recordKind,
|
|
122529
|
+
recordId: base.recordId,
|
|
122530
|
+
file,
|
|
122531
|
+
baseData: base.data,
|
|
122532
|
+
baseContentHash: base.contentHash,
|
|
122533
|
+
casBaseHash: base.conflictServerHash ?? base.contentHash
|
|
122534
|
+
};
|
|
122535
|
+
}
|
|
122536
|
+
function appendCollectionEntryDeletes(workspace, reconstructed3, changes) {
|
|
122537
|
+
const releasedOwnerIds = /* @__PURE__ */ new Set();
|
|
122538
|
+
for (const change of changes) {
|
|
122539
|
+
if (change.recordKind !== "member") continue;
|
|
122540
|
+
if (change.kind === "delete") {
|
|
122541
|
+
releasedOwnerIds.add(change.recordId);
|
|
122542
|
+
continue;
|
|
122543
|
+
}
|
|
122544
|
+
const base = workspace.state.records[recordStateKey("member", change.recordId)];
|
|
122545
|
+
if (base === void 0) continue;
|
|
122546
|
+
const data = effectiveRecordData(base);
|
|
122547
|
+
if (isObjectRecord2(data) && typeof data.entryMemberId === "string" && data.entryMemberId !== change.nextData?.entryMemberId)
|
|
122548
|
+
releasedOwnerIds.add(change.recordId);
|
|
122549
|
+
}
|
|
122550
|
+
if (releasedOwnerIds.size === 0) return;
|
|
122551
|
+
const members = /* @__PURE__ */ new Map();
|
|
122552
|
+
function setOwnership(id2, data) {
|
|
122553
|
+
if (!isObjectRecord2(data)) return;
|
|
122554
|
+
const entryMemberId = data.entryMemberId;
|
|
122555
|
+
members.set(id2, {
|
|
122556
|
+
id: id2,
|
|
122557
|
+
// Reconstructed entries survive, including entries moved to a new owner.
|
|
122558
|
+
...typeof entryMemberId === "string" && !reconstructed3.has(recordStateKey("member", entryMemberId)) ? { entryMemberId } : {}
|
|
122559
|
+
});
|
|
122560
|
+
}
|
|
122561
|
+
for (const record6 of Object.values(workspace.state.records)) {
|
|
122562
|
+
if (record6.recordKind === "member" && record6.conflictServerHash !== null)
|
|
122563
|
+
setOwnership(record6.recordId, effectiveRecordData(record6));
|
|
122564
|
+
}
|
|
122565
|
+
for (const record6 of reconstructed3.values()) {
|
|
122566
|
+
if (record6.recordKind === "member" && !releasedOwnerIds.has(record6.recordId))
|
|
122567
|
+
setOwnership(record6.recordId, record6.fullData);
|
|
122568
|
+
}
|
|
122569
|
+
const dependentIds = new Set(releasedOwnerIds);
|
|
122570
|
+
addDependentMemberIds(dependentIds, members.values());
|
|
122571
|
+
for (const id2 of dependentIds) {
|
|
122572
|
+
if (releasedOwnerIds.has(id2)) continue;
|
|
122573
|
+
const key = recordStateKey("member", id2);
|
|
122574
|
+
if (reconstructed3.has(key)) continue;
|
|
122575
|
+
const base = workspace.state.records[key];
|
|
122576
|
+
if (base === void 0 || base.conflictServerHash === null) continue;
|
|
122577
|
+
changes.push(recordDeleteChange(base, base.file ?? null));
|
|
122578
|
+
}
|
|
122579
|
+
}
|
|
122266
122580
|
function listVirtualProjectSourceFilesV4(files) {
|
|
122267
122581
|
const selected = files.filter((file) => {
|
|
122268
122582
|
const kind = neoProjectSourceKind(file.path);
|
|
@@ -122547,9 +122861,35 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
122547
122861
|
[...staticValues.records, ...memberDefaults.records, ...rootValues.records],
|
|
122548
122862
|
staticMemberValueIds
|
|
122549
122863
|
);
|
|
122864
|
+
let collectionBindings;
|
|
122865
|
+
const resolveVirtualPath = (rootId, segments) => {
|
|
122866
|
+
if (collectionBindings === void 0) {
|
|
122867
|
+
const candidate = /* @__PURE__ */ new Map();
|
|
122868
|
+
for (const [key, record6] of Object.entries(rootPathResolutionState)) {
|
|
122869
|
+
if (record6.file !== void 0 && isSchemaRecordKindV4(record6.recordKind) && !documentsByKey.has(key))
|
|
122870
|
+
continue;
|
|
122871
|
+
candidate.set(key, { ...record6, deleted: false });
|
|
122872
|
+
}
|
|
122873
|
+
for (const row of valueLowerRegistry.pendingValues.values()) {
|
|
122874
|
+
candidate.set(`value:${row.id}`, {
|
|
122875
|
+
recordKind: "value",
|
|
122876
|
+
recordId: row.id,
|
|
122877
|
+
contentHash: "",
|
|
122878
|
+
deleted: false,
|
|
122879
|
+
data: { id: row.id, ...encodeStoredValueRowFields(row) }
|
|
122880
|
+
});
|
|
122881
|
+
}
|
|
122882
|
+
const document = readPulledProjectDocumentV4(candidate);
|
|
122883
|
+
compilePulledProjectDocumentForEvaluationV4(document);
|
|
122884
|
+
collectionBindings = new CollectionBindingMaterializer(document);
|
|
122885
|
+
}
|
|
122886
|
+
const resolved = collectionBindings.resolvePath(rootId, segments);
|
|
122887
|
+
return resolved;
|
|
122888
|
+
};
|
|
122550
122889
|
const resolvedCollectionPaths = resolveRootPathCollectionValuesV4({
|
|
122551
122890
|
manifest,
|
|
122552
122891
|
state: rootPathResolutionState,
|
|
122892
|
+
resolveVirtualPath,
|
|
122553
122893
|
registry: valueLowerRegistry,
|
|
122554
122894
|
siteForMember: (memberId) => {
|
|
122555
122895
|
const span2 = sourceByKey.get(recordStateKey("member", memberId))?.span;
|
|
@@ -122578,6 +122918,7 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
122578
122918
|
const resolvedVariantFolderPaths = resolveRootPathVariantFolderCollectionValuesV4({
|
|
122579
122919
|
manifest,
|
|
122580
122920
|
state: rootPathResolutionState,
|
|
122921
|
+
resolveVirtualPath,
|
|
122581
122922
|
registry: valueLowerRegistry,
|
|
122582
122923
|
siteForFolder: (folderId) => {
|
|
122583
122924
|
const span2 = sourceByKey.get(
|
|
@@ -122664,7 +123005,7 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
122664
123005
|
}
|
|
122665
123006
|
}
|
|
122666
123007
|
}
|
|
122667
|
-
const rootRecords = rootValues.records;
|
|
123008
|
+
const rootRecords = [...rootValues.records];
|
|
122668
123009
|
const variantValues = lowerVariantValueSourcesV4(
|
|
122669
123010
|
loweringRecords,
|
|
122670
123011
|
manifest,
|
|
@@ -122680,8 +123021,71 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
122680
123021
|
records: supplementalRecords,
|
|
122681
123022
|
manifest,
|
|
122682
123023
|
state: rootPathResolutionState,
|
|
123024
|
+
resolveVirtualPath,
|
|
122683
123025
|
registry: valueLowerRegistry
|
|
122684
123026
|
});
|
|
123027
|
+
if (collectionBindings !== void 0) {
|
|
123028
|
+
const bindingSeeds = new Map(authoredValueSeeds);
|
|
123029
|
+
const rootRecordsById = new Map(
|
|
123030
|
+
rootRecords.filter((record6) => record6.recordKind === "value").map((record6) => [record6.recordId, record6])
|
|
123031
|
+
);
|
|
123032
|
+
const rootMembers = /* @__PURE__ */ new Map();
|
|
123033
|
+
for (const record6 of Object.values(rootPathResolutionState)) {
|
|
123034
|
+
if (record6.recordKind === "member" && isObjectRecord2(record6.data) && typeof record6.data.valueId === "string")
|
|
123035
|
+
rootMembers.set(record6.data.valueId, record6.recordId);
|
|
123036
|
+
}
|
|
123037
|
+
for (const row of collectionBindings.rows.values()) {
|
|
123038
|
+
if (rootPathResolutionState[`value:${row.id}`] === void 0) continue;
|
|
123039
|
+
const existing = rootRecordsById.get(row.id);
|
|
123040
|
+
if (existing !== void 0) Object.assign(existing.fileFields, row);
|
|
123041
|
+
else
|
|
123042
|
+
rootRecords.push({
|
|
123043
|
+
recordKind: "value",
|
|
123044
|
+
recordId: row.id,
|
|
123045
|
+
file: "Root.neo",
|
|
123046
|
+
line: 1,
|
|
123047
|
+
fileFields: { ...row }
|
|
123048
|
+
});
|
|
123049
|
+
}
|
|
123050
|
+
for (const [rootId, rowIds] of collectionBindings.pathRowsByRootId) {
|
|
123051
|
+
const memberId = rootMembers.get(rootId);
|
|
123052
|
+
const root = collectionBindings.rowForValue(rootId);
|
|
123053
|
+
if (memberId === void 0 || root === void 0) continue;
|
|
123054
|
+
const seed = authoredValueSeeds.get(memberId);
|
|
123055
|
+
const rows = new Map((seed?.values ?? []).map((row) => [row.id, row]));
|
|
123056
|
+
for (const id2 of rowIds) {
|
|
123057
|
+
if (id2 === rootId) continue;
|
|
123058
|
+
const row = collectionBindings.rowForValue(id2);
|
|
123059
|
+
const location3 = collectionBindings.locationForValue(id2);
|
|
123060
|
+
if (row === void 0 || !isLiteralValueContent(row) || location3 === void 0)
|
|
123061
|
+
throw new Error(`Collection binding row ${id2} has no member.`);
|
|
123062
|
+
const isNew = rootPathResolutionState[`value:${id2}`] === void 0;
|
|
123063
|
+
const classId = row.classId ?? (isMemberClassBase(location3.member) ? location3.member.classId : null);
|
|
123064
|
+
const authored = staticValueSeedRow(
|
|
123065
|
+
{
|
|
123066
|
+
...row,
|
|
123067
|
+
classId,
|
|
123068
|
+
...isNew && classId !== null ? {
|
|
123069
|
+
constructorArgs: row.constructorArgs ?? {},
|
|
123070
|
+
instanceConstructorId: row.instanceConstructorId ?? null
|
|
123071
|
+
} : {}
|
|
123072
|
+
},
|
|
123073
|
+
location3.memberId
|
|
123074
|
+
);
|
|
123075
|
+
rows.set(id2, authored);
|
|
123076
|
+
if (isNew) valueLowerRegistry.pendingValues.set(id2, authored);
|
|
123077
|
+
}
|
|
123078
|
+
bindingSeeds.set(memberId, {
|
|
123079
|
+
...seed,
|
|
123080
|
+
nodeType: "literal",
|
|
123081
|
+
valueId: rootId,
|
|
123082
|
+
value: root.value,
|
|
123083
|
+
classId: root.classId ?? null,
|
|
123084
|
+
values: [...rows.values()]
|
|
123085
|
+
});
|
|
123086
|
+
}
|
|
123087
|
+
authoredValueSeeds = bindingSeeds;
|
|
123088
|
+
}
|
|
122685
123089
|
const prospectiveState = overlayProspectiveSourceRecords(
|
|
122686
123090
|
loweringRecords,
|
|
122687
123091
|
documents,
|
|
@@ -122790,16 +123194,9 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
122790
123194
|
if (recordState.recordKind === "value") {
|
|
122791
123195
|
deletedValueIds.add(recordState.recordId);
|
|
122792
123196
|
}
|
|
122793
|
-
changes.push(
|
|
122794
|
-
kind: "delete",
|
|
122795
|
-
recordKind: recordState.recordKind,
|
|
122796
|
-
recordId: recordState.recordId,
|
|
122797
|
-
file: recordFile,
|
|
122798
|
-
baseData: recordState.data,
|
|
122799
|
-
baseContentHash: recordState.contentHash,
|
|
122800
|
-
casBaseHash: recordState.conflictServerHash !== void 0 ? recordState.conflictServerHash : recordState.contentHash
|
|
122801
|
-
});
|
|
123197
|
+
changes.push(recordDeleteChange(recordState, recordFile));
|
|
122802
123198
|
}
|
|
123199
|
+
appendCollectionEntryDeletes(workspace, reconstructed3, changes);
|
|
122803
123200
|
const sourceTextByUri = new Map(
|
|
122804
123201
|
sourceEntries.map((entry) => [entry.relPath, entry.source])
|
|
122805
123202
|
);
|
|
@@ -124071,6 +124468,8 @@ var ANIMATION_DOCUMENT_RECORD_KINDS, ANIMATION_REPLAY_RECORD_KINDS, PROSPECTIVE_
|
|
|
124071
124468
|
var init_workspace_status_core = __esm({
|
|
124072
124469
|
"src/project-source/workspace-status-core.ts"() {
|
|
124073
124470
|
"use strict";
|
|
124471
|
+
init_members();
|
|
124472
|
+
init_collection_binding_materialization();
|
|
124074
124473
|
init_localizable_member_value_writes();
|
|
124075
124474
|
init_localized_instance_override_writes();
|
|
124076
124475
|
init_localization2();
|
|
@@ -124115,6 +124514,7 @@ var init_workspace_status_core = __esm({
|
|
|
124115
124514
|
init_materialized_construction_cache();
|
|
124116
124515
|
init_project_version_whole_graph_validation();
|
|
124117
124516
|
init_value_base_desync();
|
|
124517
|
+
init_inheritance();
|
|
124118
124518
|
ANIMATION_DOCUMENT_RECORD_KINDS = [
|
|
124119
124519
|
ProjectRecordKind.Project,
|
|
124120
124520
|
ProjectRecordKind.Class,
|
|
@@ -126741,6 +127141,7 @@ function collectionValueObligations(manifest) {
|
|
|
126741
127141
|
for (const member of manifest.members) {
|
|
126742
127142
|
if (member.kind !== "lookup") continue;
|
|
126743
127143
|
if (typeof member.collectionValueId !== "string") continue;
|
|
127144
|
+
if (member.collectionValueId.startsWith("__pending__:root-path:")) continue;
|
|
126744
127145
|
obligations.push({
|
|
126745
127146
|
kind: "collectionValue",
|
|
126746
127147
|
site: {
|
|
@@ -127125,6 +127526,7 @@ function memberInitializerRequiresEvaluation(context, member, expression, source
|
|
|
127125
127526
|
function isSchemaMemberValueRead(context, expression, source) {
|
|
127126
127527
|
const path = memberPath2(annotatedValue(expression).expression);
|
|
127127
127528
|
if (path === null) return false;
|
|
127529
|
+
if (path.startsWith("root.")) return true;
|
|
127128
127530
|
const parts = path.split(".");
|
|
127129
127531
|
const name = parts.at(-1);
|
|
127130
127532
|
if (name === void 0) return false;
|
|
@@ -131369,10 +131771,9 @@ function classValueBody(context, member, value, visited, targetTyped, outerEnvir
|
|
|
131369
131771
|
`${key} = ${emitValue(context, emittedChildMember, childId, {
|
|
131370
131772
|
environment,
|
|
131371
131773
|
definitionSite: !context.symbolsByValueId.has(childId),
|
|
131372
|
-
//
|
|
131373
|
-
//
|
|
131374
|
-
|
|
131375
|
-
writeIdentity: false,
|
|
131774
|
+
// Existing slots recover identity from storage. A newly pinned virtual
|
|
131775
|
+
// slot must keep its derived pending identity through repeat lowering.
|
|
131776
|
+
writeIdentity: pendingVirtualValueIdentity(childId) !== null,
|
|
131376
131777
|
visited
|
|
131377
131778
|
})}`
|
|
131378
131779
|
);
|
|
@@ -133038,6 +133439,7 @@ var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, M
|
|
|
133038
133439
|
var init_value_sources = __esm({
|
|
133039
133440
|
"src/project-source/value-sources.ts"() {
|
|
133040
133441
|
"use strict";
|
|
133442
|
+
init_member_value_id();
|
|
133041
133443
|
init_effective_value_comparison();
|
|
133042
133444
|
init_member_declared_type_info();
|
|
133043
133445
|
init_constructor_argument_ownership();
|
|
@@ -145620,7 +146022,7 @@ var init_registry2 = __esm({
|
|
|
145620
146022
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
145621
146023
|
"use strict";
|
|
145622
146024
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
145623
|
-
cliVersion: "0.61.
|
|
146025
|
+
cliVersion: "0.61.3",
|
|
145624
146026
|
projectFileUploadBatchSize: 32,
|
|
145625
146027
|
documentRecords: {
|
|
145626
146028
|
member: {
|
|
@@ -154300,7 +154702,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
154300
154702
|
async function main() {
|
|
154301
154703
|
const args = parseArgs(process.argv.slice(2));
|
|
154302
154704
|
if (args.command === "--version") {
|
|
154303
|
-
console.log("0.61.
|
|
154705
|
+
console.log("0.61.3");
|
|
154304
154706
|
return;
|
|
154305
154707
|
}
|
|
154306
154708
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.61.
|
|
113
|
+
<!-- reviewed-through-cli: 0.61.3 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -78,6 +78,12 @@ compilation, schema-commit materialization, seeded structural rows, and
|
|
|
78
78
|
whole-graph validation — so a rejection reports before anything is sent. It
|
|
79
79
|
does not prompt, upload, commit, or rewrite source.
|
|
80
80
|
|
|
81
|
+
Removing a class or collection declaration also deletes its hidden collection
|
|
82
|
+
entry members, including nested lists and dictionaries. Replacing a collection
|
|
83
|
+
with a scalar deletes its abandoned entries too. Entries used by surviving
|
|
84
|
+
declarations are retained. Review these derived deletions in `neo status` or
|
|
85
|
+
`neo diff` before pushing.
|
|
86
|
+
|
|
81
87
|
Dry-run also compares the CLI's derived-edge extractor with the server version
|
|
82
88
|
saved by the last pull. Run `neo pull` after upgrading the CLI or when an older
|
|
83
89
|
workspace lacks that metadata. A newer server extractor requires a CLI
|
|
@@ -219,6 +219,10 @@ qualified static, or reached through a stable root path. For example,
|
|
|
219
219
|
`protected int Slots = FeatureFlags.StartInventorySize;` evaluates the current
|
|
220
220
|
static field or getter whenever a new instance is constructed; it is not baked
|
|
221
221
|
into a persisted literal during push.
|
|
222
|
+
Root paths such as `root.Save.World.Time.Year` remain executable even when
|
|
223
|
+
`World` and `Time` exist only through construction defaults. This also applies
|
|
224
|
+
inside `new() { Year = root.Save.World.Time.Year }`: the child field retains
|
|
225
|
+
its initializer and reads the root when the instance is constructed.
|
|
222
226
|
|
|
223
227
|
Declare overloadable constructors as members when each constructor body owns
|
|
224
228
|
its parameter scope:
|
|
@@ -130,7 +130,11 @@ the edit is not a target, and lookup/dialogue references must still satisfy
|
|
|
130
130
|
assignability, collection membership, multiplicity, and group constraints.
|
|
131
131
|
|
|
132
132
|
`collectionValue` references follow the same post-push resolution and
|
|
133
|
-
membership rules as member defaults.
|
|
133
|
+
membership rules as member defaults. Name the collection itself, for example
|
|
134
|
+
`Reference(root.Assets.Quests.Daily)`. A path may traverse construction defaults
|
|
135
|
+
and declarations created in the same push. Preparation materializes the target
|
|
136
|
+
collection and its required ancestor rows together, preserving the virtual
|
|
137
|
+
identities. No preliminary push or manual value ID is needed.
|
|
134
138
|
|
|
135
139
|
## Defaults and localization
|
|
136
140
|
|