@neocompose/cli 0.36.8 → 0.36.9

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.36.9] - 2026-08-20
4
+
5
+ ### Fixed
6
+
7
+ - Preserve shared aggregate constructor arguments as value references during
8
+ canonical pull emission, preventing web-created placements from duplicating
9
+ catalog rows or reporting false value-containment cycles.
10
+
3
11
  ## [0.36.8] - 2026-08-20
4
12
 
5
13
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -45228,6 +45228,21 @@ function findSchemaPlacement(memberId, classes) {
45228
45228
  }
45229
45229
  return null;
45230
45230
  }
45231
+ function findNearestAncestorSchemaPlacement(ownerClass, schemaKey, classesById) {
45232
+ const visited = /* @__PURE__ */ new Set([ownerClass.id]);
45233
+ let ancestorId = ownerClass.extendsClassId;
45234
+ while (typeof ancestorId === "string") {
45235
+ if (visited.has(ancestorId)) return null;
45236
+ visited.add(ancestorId);
45237
+ const ancestor = classesById.get(ancestorId);
45238
+ if (ancestor === void 0) return null;
45239
+ if (typeof ancestor.schema[schemaKey] === "string") {
45240
+ return { ownerClass: ancestor, schemaKey };
45241
+ }
45242
+ ancestorId = ancestor.extendsClassId;
45243
+ }
45244
+ return null;
45245
+ }
45231
45246
  function walkExtendsMemberChain(startId, members, pick, options) {
45232
45247
  const requireKind = options?.requireKind;
45233
45248
  const maxHops = options?.maxHops ?? 16;
@@ -57224,6 +57239,104 @@ var init_dialogue_sources = __esm({
57224
57239
  }
57225
57240
  });
57226
57241
 
57242
+ // ../src/models/variants/variants.ts
57243
+ function isNonEmptyString2(value) {
57244
+ if (typeof value !== "string") return false;
57245
+ return value.length > 0;
57246
+ }
57247
+ function isNeoClassVariant(value) {
57248
+ if (typeof value !== "object" || value === null) return false;
57249
+ if (Array.isArray(value)) return false;
57250
+ const v = value;
57251
+ if (!isNonEmptyString2(v.id)) return false;
57252
+ if (!isNonEmptyString2(v.classId)) return false;
57253
+ if (!isNonEmptyString2(v.name)) return false;
57254
+ if (!isNonEmptyString2(v.valueId)) return false;
57255
+ if (v.folderId !== null && !isNonEmptyString2(v.folderId)) return false;
57256
+ return true;
57257
+ }
57258
+ function isNeoClassVariantFolder(value) {
57259
+ if (typeof value !== "object" || value === null) return false;
57260
+ if (Array.isArray(value)) return false;
57261
+ const v = value;
57262
+ if (!isNonEmptyString2(v.id)) return false;
57263
+ if (!isNonEmptyString2(v.classId)) return false;
57264
+ if (typeof v.path !== "string") return false;
57265
+ if (v.binding === void 0 || v.binding === null) return v.path.length > 0;
57266
+ if (typeof v.binding !== "object" || Array.isArray(v.binding)) return false;
57267
+ const binding = v.binding;
57268
+ if (!isNonEmptyString2(binding.collectionMemberId)) return false;
57269
+ if (!isNonEmptyString2(binding.collectionValueId)) return false;
57270
+ return true;
57271
+ }
57272
+ var NEO_VARIANT_INITIALIZE_SCHEMA_KEY, NEO_VARIANT_APPLY_SCHEMA_KEY, NEO_VARIANT_OVERRIDES_SCHEMA_KEY, NEO_VARIANT_CHILD_OVERRIDES_SCHEMA_KEY;
57273
+ var init_variants = __esm({
57274
+ "../src/models/variants/variants.ts"() {
57275
+ "use strict";
57276
+ NEO_VARIANT_INITIALIZE_SCHEMA_KEY = "Initialize";
57277
+ NEO_VARIANT_APPLY_SCHEMA_KEY = "Apply";
57278
+ NEO_VARIANT_OVERRIDES_SCHEMA_KEY = "Overrides";
57279
+ NEO_VARIANT_CHILD_OVERRIDES_SCHEMA_KEY = "ChildOverrides";
57280
+ }
57281
+ });
57282
+
57283
+ // ../src/models/variants/variant-member.ts
57284
+ function neoVariantSystemClass(classes, lookup = false) {
57285
+ const declared = classes.find(
57286
+ (item) => item.system?.worldKind === (lookup ? NeoWorldSystemClassKind.LookupVariant : NeoWorldSystemClassKind.Variant)
57287
+ );
57288
+ if (declared === void 0) return null;
57289
+ const targetParamId = declared.genericParams?.[0]?.id;
57290
+ if (targetParamId === void 0) return null;
57291
+ const valueParamId = declared.genericParams?.[1]?.id;
57292
+ return {
57293
+ classId: declared.id,
57294
+ targetParamId,
57295
+ ...valueParamId === void 0 ? {} : { valueParamId }
57296
+ };
57297
+ }
57298
+ var init_variant_member = __esm({
57299
+ "../src/models/variants/variant-member.ts"() {
57300
+ "use strict";
57301
+ init_core();
57302
+ init_member_kind_enum();
57303
+ }
57304
+ });
57305
+
57306
+ // ../src/models/variants/variant-naming.ts
57307
+ var init_variant_naming = __esm({
57308
+ "../src/models/variants/variant-naming.ts"() {
57309
+ "use strict";
57310
+ }
57311
+ });
57312
+
57313
+ // ../src/models/variants/variant-write.ts
57314
+ var init_variant_write = __esm({
57315
+ "../src/models/variants/variant-write.ts"() {
57316
+ "use strict";
57317
+ }
57318
+ });
57319
+
57320
+ // ../src/models/variants/variant-initialize-source.ts
57321
+ var init_variant_initialize_source = __esm({
57322
+ "../src/models/variants/variant-initialize-source.ts"() {
57323
+ "use strict";
57324
+ init_member_kind_enum();
57325
+ }
57326
+ });
57327
+
57328
+ // ../src/models/variants/index.ts
57329
+ var init_variants2 = __esm({
57330
+ "../src/models/variants/index.ts"() {
57331
+ "use strict";
57332
+ init_variants();
57333
+ init_variant_member();
57334
+ init_variant_naming();
57335
+ init_variant_write();
57336
+ init_variant_initialize_source();
57337
+ }
57338
+ });
57339
+
57227
57340
  // src/project-source/lower-support.ts
57228
57341
  function identityMap(declarations, kind) {
57229
57342
  return new Map(
@@ -61184,99 +61297,6 @@ var init_member_value_id = __esm({
61184
61297
  }
61185
61298
  });
61186
61299
 
61187
- // ../src/models/variants/variants.ts
61188
- function isNonEmptyString2(value) {
61189
- if (typeof value !== "string") return false;
61190
- return value.length > 0;
61191
- }
61192
- function isNeoClassVariant(value) {
61193
- if (typeof value !== "object" || value === null) return false;
61194
- if (Array.isArray(value)) return false;
61195
- const v = value;
61196
- if (!isNonEmptyString2(v.id)) return false;
61197
- if (!isNonEmptyString2(v.classId)) return false;
61198
- if (!isNonEmptyString2(v.name)) return false;
61199
- if (!isNonEmptyString2(v.valueId)) return false;
61200
- if (v.folderId !== null && !isNonEmptyString2(v.folderId)) return false;
61201
- return true;
61202
- }
61203
- function isNeoClassVariantFolder(value) {
61204
- if (typeof value !== "object" || value === null) return false;
61205
- if (Array.isArray(value)) return false;
61206
- const v = value;
61207
- if (!isNonEmptyString2(v.id)) return false;
61208
- if (!isNonEmptyString2(v.classId)) return false;
61209
- if (typeof v.path !== "string") return false;
61210
- if (v.binding === void 0 || v.binding === null) return v.path.length > 0;
61211
- if (typeof v.binding !== "object" || Array.isArray(v.binding)) return false;
61212
- const binding = v.binding;
61213
- if (!isNonEmptyString2(binding.collectionMemberId)) return false;
61214
- if (!isNonEmptyString2(binding.collectionValueId)) return false;
61215
- return true;
61216
- }
61217
- var init_variants = __esm({
61218
- "../src/models/variants/variants.ts"() {
61219
- "use strict";
61220
- }
61221
- });
61222
-
61223
- // ../src/models/variants/variant-member.ts
61224
- function neoVariantSystemClass(classes, lookup = false) {
61225
- const declared = classes.find(
61226
- (item) => item.system?.worldKind === (lookup ? NeoWorldSystemClassKind.LookupVariant : NeoWorldSystemClassKind.Variant)
61227
- );
61228
- if (declared === void 0) return null;
61229
- const targetParamId = declared.genericParams?.[0]?.id;
61230
- if (targetParamId === void 0) return null;
61231
- const valueParamId = declared.genericParams?.[1]?.id;
61232
- return {
61233
- classId: declared.id,
61234
- targetParamId,
61235
- ...valueParamId === void 0 ? {} : { valueParamId }
61236
- };
61237
- }
61238
- var init_variant_member = __esm({
61239
- "../src/models/variants/variant-member.ts"() {
61240
- "use strict";
61241
- init_core();
61242
- init_member_kind_enum();
61243
- }
61244
- });
61245
-
61246
- // ../src/models/variants/variant-naming.ts
61247
- var init_variant_naming = __esm({
61248
- "../src/models/variants/variant-naming.ts"() {
61249
- "use strict";
61250
- }
61251
- });
61252
-
61253
- // ../src/models/variants/variant-write.ts
61254
- var init_variant_write = __esm({
61255
- "../src/models/variants/variant-write.ts"() {
61256
- "use strict";
61257
- }
61258
- });
61259
-
61260
- // ../src/models/variants/variant-initialize-source.ts
61261
- var init_variant_initialize_source = __esm({
61262
- "../src/models/variants/variant-initialize-source.ts"() {
61263
- "use strict";
61264
- init_member_kind_enum();
61265
- }
61266
- });
61267
-
61268
- // ../src/models/variants/index.ts
61269
- var init_variants2 = __esm({
61270
- "../src/models/variants/index.ts"() {
61271
- "use strict";
61272
- init_variants();
61273
- init_variant_member();
61274
- init_variant_naming();
61275
- init_variant_write();
61276
- init_variant_initialize_source();
61277
- }
61278
- });
61279
-
61280
61300
  // ../src/models/project/project-root-members.ts
61281
61301
  function buildRootStorageMap(project) {
61282
61302
  const map = /* @__PURE__ */ new Map();
@@ -89764,6 +89784,97 @@ var init_localizable_member_value_writes = __esm({
89764
89784
  });
89765
89785
 
89766
89786
  // ../src/database/project-version-schema-commit.ts
89787
+ function indexRecordsById(records2) {
89788
+ const recordsById2 = /* @__PURE__ */ new Map();
89789
+ for (const record3 of records2) recordsById2.set(record3.id, record3);
89790
+ return recordsById2;
89791
+ }
89792
+ function indexLiveContentHashesByRecordId(heads, recordKind) {
89793
+ const hashes = /* @__PURE__ */ new Map();
89794
+ for (const head of heads) {
89795
+ if (head.recordKind !== recordKind || head.deleted) continue;
89796
+ hashes.set(head.recordId, head.contentHash);
89797
+ }
89798
+ return hashes;
89799
+ }
89800
+ function indexLiveContentHashesByRecordKey(heads) {
89801
+ const hashes = /* @__PURE__ */ new Map();
89802
+ for (const head of heads) {
89803
+ if (head.deleted) continue;
89804
+ hashes.set(`${head.recordKind}:${head.recordId}`, head.contentHash);
89805
+ }
89806
+ return hashes;
89807
+ }
89808
+ function indexChangesByRecordId(changes, recordKind) {
89809
+ const indexes = /* @__PURE__ */ new Map();
89810
+ for (let index = 0; index < changes.length; index += 1) {
89811
+ const change = changes[index];
89812
+ if (change?.recordKind === recordKind) indexes.set(change.recordId, index);
89813
+ }
89814
+ return indexes;
89815
+ }
89816
+ function reconcileDirectOverrideChains(args) {
89817
+ if (!args.changes.some(
89818
+ (change) => change.recordKind === "class" || change.recordKind === "member"
89819
+ )) {
89820
+ return;
89821
+ }
89822
+ const postDocument = applyProjectVersionWriteChanges(
89823
+ args.document,
89824
+ args.changes
89825
+ );
89826
+ const postClassesById = indexRecordsById(postDocument.classes);
89827
+ const postMembersById = indexRecordsById(postDocument.members);
89828
+ const changeIndexByMemberId = indexChangesByRecordId(args.changes, "member");
89829
+ let baseHashByMemberId = null;
89830
+ for (const schemaClass2 of postDocument.classes) {
89831
+ for (const [schemaKey, memberId] of Object.entries(schemaClass2.schema)) {
89832
+ const member = postMembersById.get(memberId);
89833
+ if (member === void 0 || typeof member.extendsMemberId !== "string") {
89834
+ continue;
89835
+ }
89836
+ const expectedPlacement = findNearestAncestorSchemaPlacement(
89837
+ schemaClass2,
89838
+ schemaKey,
89839
+ postClassesById
89840
+ );
89841
+ const expected = expectedPlacement?.ownerClass.schema[expectedPlacement.schemaKey];
89842
+ if (expected === member.extendsMemberId) continue;
89843
+ if (typeof expected !== "string") continue;
89844
+ const nextMember = { ...member, extendsMemberId: expected };
89845
+ postMembersById.set(member.id, nextMember);
89846
+ const existingIndex = changeIndexByMemberId.get(member.id);
89847
+ if (existingIndex !== void 0) {
89848
+ const existing = args.changes[existingIndex];
89849
+ if (existing !== void 0) {
89850
+ args.changes[existingIndex] = { ...existing, nextData: nextMember };
89851
+ }
89852
+ continue;
89853
+ }
89854
+ baseHashByMemberId ??= indexLiveContentHashesByRecordId(
89855
+ args.contentHashHeads,
89856
+ "member"
89857
+ );
89858
+ const expectedBaseContentHash = baseHashByMemberId.get(member.id);
89859
+ if (expectedBaseContentHash === void 0) {
89860
+ throw new Error(
89861
+ `Cannot safely repair override chain for member "${member.name}" (${member.id}): its current content hash is unavailable.`
89862
+ );
89863
+ }
89864
+ changeIndexByMemberId.set(member.id, args.changes.length);
89865
+ args.changes.push({
89866
+ recordKind: "member",
89867
+ recordId: member.id,
89868
+ operation: "update",
89869
+ nextData: nextMember,
89870
+ expectedBaseContentHash,
89871
+ intent: createProjectVersionIntent("member.update", {
89872
+ source: "server-direct-override-chain-reconcile"
89873
+ })
89874
+ });
89875
+ }
89876
+ }
89877
+ }
89767
89878
  function prepareServerOwnedSchemaCommit(args) {
89768
89879
  if (args.forceRecompile === true) clearNeoScriptBodyCompileCache();
89769
89880
  assertUniqueChanges(args.changes);
@@ -89784,6 +89895,18 @@ function prepareServerOwnedSchemaCommit(args) {
89784
89895
  ),
89785
89896
  changes: authoredChanges
89786
89897
  });
89898
+ const explicitlyChangedMemberIds = /* @__PURE__ */ new Set();
89899
+ for (const change of authoredChanges) {
89900
+ if (change.recordKind !== "member" || change.operation === "delete") {
89901
+ continue;
89902
+ }
89903
+ explicitlyChangedMemberIds.add(change.recordId);
89904
+ }
89905
+ reconcileDirectOverrideChains({
89906
+ document: args.document,
89907
+ changes: authoredChanges,
89908
+ contentHashHeads: args.contentHashHeads
89909
+ });
89787
89910
  assertNoLegacyWorldLayerBindingFields(authoredChanges);
89788
89911
  const hasSchemaChange = authoredChanges.some(
89789
89912
  (change) => SCHEMA_RECORD_KINDS.has(change.recordKind)
@@ -89812,11 +89935,6 @@ function prepareServerOwnedSchemaCommit(args) {
89812
89935
  additionalImpactedIds: args.additionalImpactedIds,
89813
89936
  forceRecompile: args.forceRecompile
89814
89937
  });
89815
- const explicitlyChangedMemberIds = new Set(
89816
- authoredChanges.filter(
89817
- (change) => change.recordKind === "member" && change.operation !== "delete"
89818
- ).map((change) => change.recordId)
89819
- );
89820
89938
  const currentById = new Map(
89821
89939
  args.document.members.map((member) => [member.id, member])
89822
89940
  );
@@ -89875,9 +89993,12 @@ function prepareServerOwnedSchemaCommit(args) {
89875
89993
  const compiledById = new Map(
89876
89994
  sourceMembers.map((member) => [member.id, member])
89877
89995
  );
89878
- const explicitMemberIds = new Set(
89879
- authoredChanges.filter((change) => change.recordKind === "member").map((change) => change.recordId)
89880
- );
89996
+ const explicitMemberIds = /* @__PURE__ */ new Set();
89997
+ for (const change of authoredChanges) {
89998
+ if (change.recordKind === "member") {
89999
+ explicitMemberIds.add(change.recordId);
90000
+ }
90001
+ }
89881
90002
  const prepared = authoredChanges.map((change) => {
89882
90003
  if (change.recordKind !== "member" || change.operation === "delete") {
89883
90004
  return change;
@@ -89890,9 +90011,7 @@ function prepareServerOwnedSchemaCommit(args) {
89890
90011
  }
89891
90012
  return { ...change, nextData: compiled };
89892
90013
  });
89893
- const hashByKey = new Map(
89894
- args.contentHashHeads.filter((head) => !head.deleted).map((head) => [`${head.recordKind}:${head.recordId}`, head.contentHash])
89895
- );
90014
+ const hashByKey = indexLiveContentHashesByRecordKey(args.contentHashHeads);
89896
90015
  for (const compiled of sourceMembers) {
89897
90016
  if (!recompileTargets.memberIds.has(compiled.id)) continue;
89898
90017
  if (explicitMemberIds.has(compiled.id)) continue;
@@ -93209,32 +93328,17 @@ function reconcileVariantConstructorArgs(args) {
93209
93328
  );
93210
93329
  const variants = postDocument.variants ?? [];
93211
93330
  if (variants.length === 0) return;
93212
- const valueById = new Map(
93213
- postDocument.values.map((value) => [value.id, value])
93214
- );
93215
- const classById = new Map(
93216
- postDocument.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
93217
- );
93218
- const memberById = new Map(
93219
- postDocument.members.map((member) => [member.id, member])
93220
- );
93221
- const constructorById = new Map(
93222
- (postDocument.constructors ?? []).map((record3) => [record3.id, record3])
93223
- );
93224
- const changeIndexByValueId = /* @__PURE__ */ new Map();
93225
- args.prepared.forEach((change, index) => {
93226
- if (change.recordKind !== "value") return;
93227
- changeIndexByValueId.set(change.recordId, index);
93228
- });
93229
- const baseHashByValueId = new Map(
93230
- args.contentHashHeads.filter((head) => head.recordKind === "value" && !head.deleted).map((head) => [head.recordId, head.contentHash])
93231
- );
93331
+ const valueById = indexRecordsById(postDocument.values);
93332
+ const classById = indexRecordsById(postDocument.classes);
93333
+ const memberById = indexRecordsById(postDocument.members);
93334
+ const constructorById = indexRecordsById(postDocument.constructors ?? []);
93335
+ const changeIndexByValueId = indexChangesByRecordId(args.prepared, "value");
93336
+ let baseHashByValueId = null;
93232
93337
  for (const variant of variants) {
93233
93338
  const root = valueById.get(variant.valueId);
93234
93339
  if (root === void 0) continue;
93235
93340
  if (!isLiteralValueContent(root)) continue;
93236
- const existingArgs = root.constructorArgs;
93237
- if (existingArgs === void 0 || existingArgs === null) continue;
93341
+ const existingArgs = root.constructorArgs ?? {};
93238
93342
  const rootClassId = root.classId;
93239
93343
  if (typeof rootClassId !== "string") continue;
93240
93344
  const schemaClass2 = classById.get(rootClassId);
@@ -93245,37 +93349,46 @@ function reconcileVariantConstructorArgs(args) {
93245
93349
  if (constructorRecord === void 0) continue;
93246
93350
  if (typeof root.value !== "object" || root.value === null) continue;
93247
93351
  if (Array.isArray(root.value)) continue;
93248
- const nextArgs = { ...existingArgs };
93249
- let changed = false;
93250
- constructorRecord.argumentTypes.forEach((argument2, index) => {
93352
+ const nextArgs = {};
93353
+ for (let index = 0; index < constructorRecord.argumentTypes.length; index += 1) {
93354
+ const argument2 = constructorRecord.argumentTypes[index];
93355
+ if (argument2 === void 0) continue;
93251
93356
  const parameterId = constructorActionParameterId(
93252
93357
  constructorRecord,
93253
93358
  index
93254
93359
  );
93255
- if (!(parameterId in nextArgs)) return;
93256
- const schemaKey = Object.keys(schemaClass2.schema).find(
93257
- (key) => key.toLowerCase() === argument2.name.toLowerCase()
93360
+ const schemaKey = NEO_VARIANT_SCHEMA_KEY_BY_ARGUMENT_NAME.get(
93361
+ argument2.name.toLowerCase()
93258
93362
  );
93259
- if (schemaKey === void 0) return;
93363
+ if (schemaKey === void 0) continue;
93260
93364
  const memberId = schemaClass2.schema[schemaKey];
93261
93365
  const member = memberId === void 0 ? void 0 : memberById.get(memberId);
93262
- if (member?.kind !== 25 /* NSDelegate */) return;
93366
+ if (member === void 0) continue;
93263
93367
  const childId = root.value[schemaKey];
93264
- if (typeof childId !== "string") return;
93368
+ if (typeof childId !== "string") continue;
93265
93369
  const childRow = valueById.get(childId);
93266
- if (childRow === void 0 || !isLiteralValueContent(childRow)) return;
93370
+ if (childRow === void 0 || !isLiteralValueContent(childRow)) continue;
93267
93371
  const rowValue = childRow.value;
93268
- if (typeof rowValue !== "object" || rowValue === null) return;
93269
- if (Array.isArray(rowValue)) return;
93270
- const rowCode = rowValue.code;
93271
- if (typeof rowCode !== "string") return;
93272
- const derived = { code: rowCode };
93273
- if (canonicalJsonStringify(nextArgs[parameterId]) === canonicalJsonStringify(derived)) {
93274
- return;
93372
+ if (variantConstructorArgumentIsRestValue(schemaKey, rowValue)) {
93373
+ continue;
93275
93374
  }
93276
- nextArgs[parameterId] = derived;
93277
- changed = true;
93278
- });
93375
+ if (member.kind === 25 /* NSDelegate */) {
93376
+ if (typeof rowValue !== "object" || rowValue === null) continue;
93377
+ if (Array.isArray(rowValue)) continue;
93378
+ const rowCode = rowValue.code;
93379
+ if (typeof rowCode !== "string") continue;
93380
+ nextArgs[parameterId] = { code: rowCode };
93381
+ continue;
93382
+ }
93383
+ if (member.kind === 7 /* Class */ || member.kind === 22 /* Interface */ || member.kind === 21 /* Generic */ || member.kind === 6 /* List */ || member.kind === 5 /* Dictionary */) {
93384
+ nextArgs[parameterId] = childId;
93385
+ continue;
93386
+ }
93387
+ const defaultValue = argument2.defaultValue?.value;
93388
+ if (canonicallyEqual2(rowValue, defaultValue)) continue;
93389
+ nextArgs[parameterId] = rowValue;
93390
+ }
93391
+ const changed = !canonicallyEqual2(existingArgs, nextArgs);
93279
93392
  if (!changed) continue;
93280
93393
  const nextRoot = { ...root, constructorArgs: nextArgs };
93281
93394
  const existingIndex = changeIndexByValueId.get(root.id);
@@ -93286,8 +93399,13 @@ function reconcileVariantConstructorArgs(args) {
93286
93399
  }
93287
93400
  continue;
93288
93401
  }
93402
+ baseHashByValueId ??= indexLiveContentHashesByRecordId(
93403
+ args.contentHashHeads,
93404
+ "value"
93405
+ );
93289
93406
  const baseContentHash = baseHashByValueId.get(root.id);
93290
93407
  if (baseContentHash === void 0) continue;
93408
+ changeIndexByValueId.set(root.id, args.prepared.length);
93291
93409
  args.prepared.push({
93292
93410
  recordKind: "value",
93293
93411
  recordId: root.id,
@@ -93300,6 +93418,13 @@ function reconcileVariantConstructorArgs(args) {
93300
93418
  });
93301
93419
  }
93302
93420
  }
93421
+ function variantConstructorArgumentIsRestValue(schemaKey, value) {
93422
+ if (value === null) return true;
93423
+ if (schemaKey === NEO_VARIANT_OVERRIDES_SCHEMA_KEY) {
93424
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;
93425
+ }
93426
+ return schemaKey === NEO_VARIANT_CHILD_OVERRIDES_SCHEMA_KEY && Array.isArray(value) && value.length === 0;
93427
+ }
93303
93428
  function appendVariantGraphCascadeDeletes(args) {
93304
93429
  const deletedVariantIds = /* @__PURE__ */ new Set();
93305
93430
  for (const change of args.prepared) {
@@ -93313,11 +93438,13 @@ function appendVariantGraphCascadeDeletes(args) {
93313
93438
  variants: args.document.variants ?? [],
93314
93439
  variantIds: deletedVariantIds
93315
93440
  });
93316
- const alreadyChanged = new Set(
93317
- args.prepared.filter((change) => change.recordKind === "value").map((change) => change.recordId)
93318
- );
93319
- const baseHashByValueId = new Map(
93320
- args.contentHashHeads.filter((head) => head.recordKind === "value").map((head) => [head.recordId, head.contentHash])
93441
+ const alreadyChanged = /* @__PURE__ */ new Set();
93442
+ for (const change of args.prepared) {
93443
+ if (change.recordKind === "value") alreadyChanged.add(change.recordId);
93444
+ }
93445
+ const baseHashByValueId = indexLiveContentHashesByRecordId(
93446
+ args.contentHashHeads,
93447
+ "value"
93321
93448
  );
93322
93449
  for (const valueId of valueIds) {
93323
93450
  if (alreadyChanged.has(valueId)) continue;
@@ -93339,7 +93466,7 @@ function appendVariantGraphCascadeDeletes(args) {
93339
93466
  });
93340
93467
  }
93341
93468
  }
93342
- var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_ONLY_SOURCE_CONVERSION_INTENT_SOURCE, SCHEMA_RECORD_KINDS, DIALOGUE_SOURCE_RECORD_KINDS;
93469
+ var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_ONLY_SOURCE_CONVERSION_INTENT_SOURCE, SCHEMA_RECORD_KINDS, DIALOGUE_SOURCE_RECORD_KINDS, NEO_VARIANT_SCHEMA_KEY_BY_ARGUMENT_NAME;
93343
93470
  var init_project_version_schema_commit = __esm({
93344
93471
  "../src/database/project-version-schema-commit.ts"() {
93345
93472
  "use strict";
@@ -93352,6 +93479,7 @@ var init_project_version_schema_commit = __esm({
93352
93479
  init_project2();
93353
93480
  init_member_access_modifier_validation();
93354
93481
  init_variant_value_graph();
93482
+ init_variants2();
93355
93483
  init_localization2();
93356
93484
  init_internal_record_relations();
93357
93485
  init_project_content_hash();
@@ -93393,6 +93521,12 @@ var init_project_version_schema_commit = __esm({
93393
93521
  "dialogue-node",
93394
93522
  "dialogue-group"
93395
93523
  ]);
93524
+ NEO_VARIANT_SCHEMA_KEY_BY_ARGUMENT_NAME = /* @__PURE__ */ new Map([
93525
+ ["initialize", NEO_VARIANT_INITIALIZE_SCHEMA_KEY],
93526
+ ["apply", NEO_VARIANT_APPLY_SCHEMA_KEY],
93527
+ ["overrides", NEO_VARIANT_OVERRIDES_SCHEMA_KEY],
93528
+ ["childoverrides", NEO_VARIANT_CHILD_OVERRIDES_SCHEMA_KEY]
93529
+ ]);
93396
93530
  }
93397
93531
  });
93398
93532
 
@@ -97826,15 +97960,15 @@ function emitVariantValueSourcesV4(records2, manifest) {
97826
97960
  visited
97827
97961
  });
97828
97962
  };
97829
- const initialize = argument2("Initialize");
97963
+ const initialize = argument2(NEO_VARIANT_INITIALIZE_SCHEMA_KEY);
97830
97964
  if (initialize === null) {
97831
97965
  throw new Error(
97832
97966
  `Variant "${variant.id}" has no Initialize row; every variant constructs a fresh instance.`
97833
97967
  );
97834
97968
  }
97835
- const apply = argument2("Apply");
97836
- const overrides = argument2("Overrides");
97837
- const childOverrides = argument2("ChildOverrides");
97969
+ const apply = argument2(NEO_VARIANT_APPLY_SCHEMA_KEY);
97970
+ const overrides = argument2(NEO_VARIANT_OVERRIDES_SCHEMA_KEY);
97971
+ const childOverrides = argument2(NEO_VARIANT_CHILD_OVERRIDES_SCHEMA_KEY);
97838
97972
  const authored = [["initialize", initialize]];
97839
97973
  if (apply !== null && apply !== "null") authored.push(["apply", apply]);
97840
97974
  if (overrides !== null && overrides !== "new {}") {
@@ -102887,6 +103021,12 @@ function storedConstructorCallSource(context, schemaClass2, value, className, en
102887
103021
  `Stored construction for ${className} is missing evaluated argument ${key}.`
102888
103022
  );
102889
103023
  }
103024
+ const settledMember = settledMemberForConstructorArgument(
103025
+ context,
103026
+ schemaClass2,
103027
+ value,
103028
+ constructorArgs[key]
103029
+ );
102890
103030
  return `${argument2.name}: ${storedConstructorArgumentSource(
102891
103031
  context,
102892
103032
  argument2.type,
@@ -102894,24 +103034,23 @@ function storedConstructorCallSource(context, schemaClass2, value, className, en
102894
103034
  environment,
102895
103035
  visited,
102896
103036
  cloneAggregateArguments,
102897
- settledMemberIsPartial(context, schemaClass2, value, constructorArgs[key])
103037
+ settledMember?.partial === true,
103038
+ settledMember !== void 0
102898
103039
  )}`;
102899
103040
  });
102900
103041
  return argumentsValue.length === 0 && targetTyped ? "new()" : constructorCallSource(`new ${className}`, argumentsValue);
102901
103042
  }
102902
- function settledMemberIsPartial(context, schemaClass2, value, argument2) {
102903
- if (typeof argument2 !== "string") return false;
103043
+ function settledMemberForConstructorArgument(context, schemaClass2, value, argument2) {
103044
+ if (typeof argument2 !== "string") return void 0;
102904
103045
  const body = value.value;
102905
- if (!isObjectRecord2(body)) return false;
103046
+ if (!isObjectRecord2(body)) return void 0;
102906
103047
  const schemaKey = Object.entries(body).find(
102907
103048
  ([, rowId]) => rowId === argument2
102908
103049
  )?.[0];
102909
- if (schemaKey === void 0) return false;
103050
+ if (schemaKey === void 0) return void 0;
102910
103051
  const schema = isObjectRecord2(schemaClass2.schema) ? schemaClass2.schema : {};
102911
103052
  const memberId = schema[schemaKey];
102912
- if (typeof memberId !== "string") return false;
102913
- const member = context.members.get(memberId);
102914
- return member?.partial === true;
103053
+ return typeof memberId === "string" ? context.members.get(memberId) : void 0;
102915
103054
  }
102916
103055
  function constructorCallSource(callee, argumentsValue) {
102917
103056
  const inline = `${callee}(${argumentsValue.join(", ")})`;
@@ -102950,7 +103089,7 @@ function storedValueConstructor(context, schemaClass2, constructorArgs) {
102950
103089
  }
102951
103090
  return selected;
102952
103091
  }
102953
- function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false, partial = false) {
103092
+ function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false, partial = false, constructorOwnsGraph = false) {
102954
103093
  if (value === null) {
102955
103094
  if (!type.nullable) {
102956
103095
  throw new Error("Required constructor argument stores null.");
@@ -103033,7 +103172,8 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
103033
103172
  environment,
103034
103173
  visited,
103035
103174
  false,
103036
- partial
103175
+ partial,
103176
+ constructorOwnsGraph
103037
103177
  );
103038
103178
  }
103039
103179
  case "generic": {
@@ -103057,7 +103197,8 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
103057
103197
  environment,
103058
103198
  visited,
103059
103199
  cloneAggregateArguments,
103060
- partial
103200
+ partial,
103201
+ constructorOwnsGraph
103061
103202
  );
103062
103203
  }
103063
103204
  case "interface":
@@ -103077,7 +103218,9 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
103077
103218
  value,
103078
103219
  environment,
103079
103220
  visited,
103080
- false
103221
+ false,
103222
+ false,
103223
+ constructorOwnsGraph
103081
103224
  );
103082
103225
  case "lookup":
103083
103226
  return referenceValue(
@@ -103351,7 +103494,7 @@ function storedSchemaTypeName(context, type, environment, valueId) {
103351
103494
  return "null";
103352
103495
  }
103353
103496
  }
103354
- function storedTypedRowSource(context, type, valueId, environment, visited, writeIdentity, partial = false) {
103497
+ function storedTypedRowSource(context, type, valueId, environment, visited, writeIdentity, partial = false, constructorOwnsGraph = false) {
103355
103498
  const symbol = context.symbolsByValueId.get(valueId);
103356
103499
  if (symbol !== void 0) return symbol;
103357
103500
  const row = context.values.get(valueId);
@@ -103360,6 +103503,9 @@ function storedTypedRowSource(context, type, valueId, environment, visited, writ
103360
103503
  `Stored ${type.kind} constructor argument references missing value row ${valueId}.`
103361
103504
  );
103362
103505
  }
103506
+ if (!constructorOwnsGraph && context.readMaterializedGraph().independentlyOwnedValueIds.has(valueId)) {
103507
+ return `Reference<${storedSchemaTypeName(context, type, environment, valueId)}>(id: ${quote5(valueId)})`;
103508
+ }
103363
103509
  if (visited.has(valueId)) {
103364
103510
  throw new Error(
103365
103511
  `Stored constructor argument containment cycle reaches ${valueId}.`
@@ -103410,7 +103556,9 @@ ${ids.map(
103410
103556
  id2,
103411
103557
  environment,
103412
103558
  visited,
103413
- true
103559
+ true,
103560
+ false,
103561
+ constructorOwnsGraph
103414
103562
  ),
103415
103563
  2
103416
103564
  )
@@ -103438,7 +103586,9 @@ ${entries.flatMap(
103438
103586
  id2,
103439
103587
  environment,
103440
103588
  visited,
103441
- false
103589
+ false,
103590
+ false,
103591
+ constructorOwnsGraph
103442
103592
  )}`,
103443
103593
  2
103444
103594
  )
@@ -104201,6 +104351,7 @@ var init_value_sources = __esm({
104201
104351
  "use strict";
104202
104352
  init_src();
104203
104353
  init_projection();
104354
+ init_variants2();
104204
104355
  init_project_file_source();
104205
104356
  init_lower_members();
104206
104357
  init_lower_variants();
@@ -114185,7 +114336,7 @@ var init_registry2 = __esm({
114185
114336
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
114186
114337
  formatVersion: 3,
114187
114338
  contractVersion: "3.14",
114188
- cliVersion: "0.36.8",
114339
+ cliVersion: "0.36.9",
114189
114340
  projectFileUploadBatchSize: 32,
114190
114341
  documentRecords: {
114191
114342
  member: {
@@ -120789,7 +120940,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
120789
120940
  async function main() {
120790
120941
  const args = parseArgs(process.argv.slice(2));
120791
120942
  if (args.command === "--version") {
120792
- console.log("0.36.8");
120943
+ console.log("0.36.9");
120793
120944
  return;
120794
120945
  }
120795
120946
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.36.8",
3
+ "version": "0.36.9",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.36.8 -->
12
+ <!-- reviewed-through-cli: 0.36.9 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -83,7 +83,7 @@ wrappers.
83
83
  The marker near the top of `SKILL.md` must exactly match the package version:
84
84
 
85
85
  ```html
86
- <!-- reviewed-through-cli: 0.36.8 -->
86
+ <!-- reviewed-through-cli: 0.36.9 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale