@neocompose/cli 0.7.2 → 0.7.4

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/neo.mjs +312 -35
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@
7
7
  - Document the final relation-only world layer-link contract and keep the
8
8
  format-4 Hello World corpus free of the retired value-side binding field.
9
9
 
10
+ ## [0.7.4] - 2026-07-22
11
+
12
+ ### Fixed
13
+
14
+ - Emit Generic member slots without nullable syntax while preserving their
15
+ binding-owned nullability in the manifest.
16
+ - Project stored Generic values through their concrete class bindings during
17
+ pull and source lowering.
18
+
19
+ ## [0.7.3] - 2026-07-22
20
+
21
+ ### Fixed
22
+
23
+ - Keep sparse member fields sparse during push-time NeoScript recompilation so
24
+ `isReadOnly: false` does not create phantom changes rejected by trusted lowering.
25
+
10
26
  ## [0.7.2] - 2026-07-22
11
27
 
12
28
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -16613,6 +16613,15 @@ function validateAllTypeApplications(documents, environment, diagnostics) {
16613
16613
  member.name,
16614
16614
  diagnostics
16615
16615
  );
16616
+ if (member.kind === "field" && generics.has(member.type.name) && member.type.typeArguments.length === 0 && member.type.nullable) {
16617
+ diagnose(
16618
+ diagnostics,
16619
+ uri,
16620
+ member.type.range,
16621
+ "nullable-generic-member-slot",
16622
+ `Generic member slot '${member.name}' cannot declare '${member.type.name}?' because nullability comes from the concrete '${member.type.name}' binding. Use '${member.type.name}'.`
16623
+ );
16624
+ }
16616
16625
  if (member.kind !== "function") continue;
16617
16626
  for (const parameter3 of member.parameters) {
16618
16627
  validateTypeApplication(
@@ -28431,7 +28440,16 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
28431
28440
  };
28432
28441
  }
28433
28442
  const genericParamId = context.genericParametersByClass.get(materializedId(ownerClass, "class", ownerClass.name))?.get(name);
28434
- if (genericParamId) return { ...common, kind: "generic", genericParamId };
28443
+ if (genericParamId) {
28444
+ return {
28445
+ ...common,
28446
+ // Generic slots never own nullability. The concrete binding member
28447
+ // supplies `required` and the default for every use of this parameter.
28448
+ required: false,
28449
+ kind: "generic",
28450
+ genericParamId
28451
+ };
28452
+ }
28435
28453
  const classId = context.classIdsByName.get(name);
28436
28454
  if (classId) {
28437
28455
  return {
@@ -30283,6 +30301,7 @@ function renderMemberType(context, member) {
30283
30301
  value = renderReturnType(context, member.returnType);
30284
30302
  break;
30285
30303
  }
30304
+ if (member.kind === "generic") return value;
30286
30305
  return nullable && value !== "null" ? `${value}?` : value;
30287
30306
  }
30288
30307
  function renderType(context, type) {
@@ -40362,13 +40381,13 @@ var init_dialogue_sources = __esm({
40362
40381
  });
40363
40382
 
40364
40383
  // src/project-source/value-sources.ts
40365
- function emitStaticValueSourcesV4(records2) {
40384
+ function emitStaticValueSourcesV4(records2, manifest) {
40366
40385
  const memberIds = [...records2.values()].flatMap(
40367
40386
  (record3) => record3.recordKind === "member" && !record3.deleted && isObjectRecord2(record3.data) && record3.data.isStatic === true && typeof record3.data.valueId === "string" ? [record3.recordId] : []
40368
40387
  );
40369
- return emitStoredValueBindingSourcesV4(records2, memberIds);
40388
+ return emitStoredValueBindingSourcesV4(records2, memberIds, { manifest });
40370
40389
  }
40371
- function buildValueEmitContext(records2) {
40390
+ function buildValueEmitContext(records2, manifest) {
40372
40391
  const members = dataById(records2, "member");
40373
40392
  const classes = dataById(records2, "class");
40374
40393
  const values = dataById(records2, "value");
@@ -40379,6 +40398,12 @@ function buildValueEmitContext(records2) {
40379
40398
  return {
40380
40399
  members,
40381
40400
  classes,
40401
+ manifestMembers: new Map(
40402
+ manifest.members.map((member) => [member.id, member])
40403
+ ),
40404
+ manifestClasses: new Map(
40405
+ manifest.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
40406
+ ),
40382
40407
  values,
40383
40408
  enums,
40384
40409
  localizedTexts,
@@ -40394,8 +40419,8 @@ function buildValueEmitContext(records2) {
40394
40419
  localizedTextIds: /* @__PURE__ */ new Set()
40395
40420
  };
40396
40421
  }
40397
- function emitStoredValueBindingSourcesV4(records2, memberIds, options = {}) {
40398
- const context = buildValueEmitContext(records2);
40422
+ function emitStoredValueBindingSourcesV4(records2, memberIds, options) {
40423
+ const context = buildValueEmitContext(records2, options.manifest);
40399
40424
  const members = context.members;
40400
40425
  const initializers = /* @__PURE__ */ new Map();
40401
40426
  const recordKeysByMember = /* @__PURE__ */ new Map();
@@ -40464,8 +40489,8 @@ function rowBackedDefaultMemberIdsV4(state) {
40464
40489
  }
40465
40490
  return result;
40466
40491
  }
40467
- function emitMemberDefaultSourcesV4(records2) {
40468
- const context = buildValueEmitContext(records2);
40492
+ function emitMemberDefaultSourcesV4(records2, manifest) {
40493
+ const context = buildValueEmitContext(records2, manifest);
40469
40494
  const initializers = /* @__PURE__ */ new Map();
40470
40495
  const recordKeysByMember = /* @__PURE__ */ new Map();
40471
40496
  for (const record3 of records2.values()) {
@@ -40489,7 +40514,12 @@ function emitMemberDefaultSourcesV4(records2) {
40489
40514
  } else if (backed.kind === "list") {
40490
40515
  expression = listValue(context, member, { value: backed.body }, visited);
40491
40516
  } else {
40492
- expression = dictionaryValue(context, member, backed.body, visited);
40517
+ expression = dictionaryValue(
40518
+ context,
40519
+ member,
40520
+ { value: backed.body },
40521
+ visited
40522
+ );
40493
40523
  }
40494
40524
  initializers.set(record3.recordId, expression);
40495
40525
  recordKeysByMember.set(
@@ -40961,7 +40991,7 @@ function lowerSeedChild(context, member, expression, source, path, rows, localiz
40961
40991
  );
40962
40992
  return valueId;
40963
40993
  }
40964
- function lowerValueRow(context, member, sourceExpression, expectedValueId, source) {
40994
+ function lowerValueRow(context, member, sourceExpression, expectedValueId, source, environment) {
40965
40995
  const { expression, id: id2 } = annotatedValue(sourceExpression);
40966
40996
  if (id2 !== null && id2 !== expectedValueId) {
40967
40997
  throw new Error(
@@ -40969,11 +40999,23 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
40969
40999
  );
40970
41000
  }
40971
41001
  const base = valueBase(context, expectedValueId);
40972
- const value = lowerValueBody(context, member, expression, base, source);
41002
+ const resolvedMember = resolveGenericSchemaMember(
41003
+ context,
41004
+ member,
41005
+ environment
41006
+ );
41007
+ const value = lowerValueBody(
41008
+ context,
41009
+ resolvedMember,
41010
+ expression,
41011
+ base,
41012
+ source,
41013
+ environment
41014
+ );
40973
41015
  addReconstructed(context, "value", expectedValueId, value, source.source);
40974
41016
  return expectedValueId;
40975
41017
  }
40976
- function lowerValueBody(context, member, expression, base, source) {
41018
+ function lowerValueBody(context, member, expression, base, source, environment) {
40977
41019
  const next = valueFileFields(base);
40978
41020
  if (expression.kind === "litNull") return { ...next, value: null };
40979
41021
  switch (member.kind) {
@@ -41019,18 +41061,39 @@ function lowerValueBody(context, member, expression, base, source) {
41019
41061
  case "audio":
41020
41062
  return { ...next, value: lowerFileValue(context, member, expression) };
41021
41063
  case "class":
41022
- return lowerClassValue(context, member, expression, base, source);
41064
+ return lowerClassValue(
41065
+ context,
41066
+ member,
41067
+ expression,
41068
+ base,
41069
+ source,
41070
+ environment
41071
+ );
41023
41072
  case "list":
41024
- return lowerListValue(context, member, expression, base, source);
41073
+ return lowerListValue(
41074
+ context,
41075
+ member,
41076
+ expression,
41077
+ base,
41078
+ source,
41079
+ environment
41080
+ );
41025
41081
  case "dictionary":
41026
- return lowerDictionaryValue(context, member, expression, base, source);
41082
+ return lowerDictionaryValue(
41083
+ context,
41084
+ member,
41085
+ expression,
41086
+ base,
41087
+ source,
41088
+ environment
41089
+ );
41027
41090
  default:
41028
41091
  throw new Error(
41029
41092
  `Stored static value lowering does not support member kind ${member.kind}.`
41030
41093
  );
41031
41094
  }
41032
41095
  }
41033
- function lowerClassValue(context, member, expression, base, source) {
41096
+ function lowerClassValue(context, member, expression, base, source, outerEnvironment) {
41034
41097
  if (expression.kind !== "new")
41035
41098
  throw new Error("Class values require new(...).");
41036
41099
  const currentClassId = stringOrNull(base.classId) ?? member.classId;
@@ -41043,6 +41106,12 @@ function lowerClassValue(context, member, expression, base, source) {
41043
41106
  `Cannot instantiate abstract class ${schemaClass2.name} for value ${String(base.id)}. Use a concrete descendant instead.`
41044
41107
  );
41045
41108
  }
41109
+ const environment = lowerInstanceGenericEnvironment(
41110
+ context,
41111
+ classId,
41112
+ member,
41113
+ outerEnvironment
41114
+ );
41046
41115
  const baseBody = isObjectRecord2(base.value) ? base.value : {};
41047
41116
  const body = { ...baseBody };
41048
41117
  for (const assignment of expression.initializer ?? []) {
@@ -41068,7 +41137,8 @@ function lowerClassValue(context, member, expression, base, source) {
41068
41137
  childMember,
41069
41138
  assignment.value,
41070
41139
  childId,
41071
- source
41140
+ source,
41141
+ environment
41072
41142
  );
41073
41143
  }
41074
41144
  return {
@@ -41077,12 +41147,13 @@ function lowerClassValue(context, member, expression, base, source) {
41077
41147
  ...classId === currentClassId ? {} : { classId }
41078
41148
  };
41079
41149
  }
41080
- function lowerListValue(context, member, expression, base, source) {
41150
+ function lowerListValue(context, member, expression, base, source, inheritedEnvironment) {
41081
41151
  if (expression.kind === "litNull")
41082
41152
  return { ...valueFileFields(base), value: null };
41083
41153
  if (expression.kind !== "litList")
41084
41154
  throw new Error("List values require [...].");
41085
41155
  const entryMember = requiredMember(context, member.entryMemberId);
41156
+ const environment = valueGenericEnvironment(base, inheritedEnvironment);
41086
41157
  const existingIds = existingListItemIds(context, member, base);
41087
41158
  const ids = [];
41088
41159
  for (const element of expression.elements) {
@@ -41108,7 +41179,9 @@ function lowerListValue(context, member, expression, base, source) {
41108
41179
  `Unordered list item ${itemId} belongs to a different container.`
41109
41180
  );
41110
41181
  }
41111
- ids.push(lowerValueRow(context, entryMember, element, itemId, source));
41182
+ ids.push(
41183
+ lowerValueRow(context, entryMember, element, itemId, source, environment)
41184
+ );
41112
41185
  }
41113
41186
  return {
41114
41187
  ...valueFileFields(base),
@@ -41125,7 +41198,7 @@ function existingListItemIds(context, member, base) {
41125
41198
  Array.isArray(base.value) ? base.value.filter((entry) => typeof entry === "string") : []
41126
41199
  );
41127
41200
  }
41128
- function lowerDictionaryValue(context, member, expression, base, source) {
41201
+ function lowerDictionaryValue(context, member, expression, base, source, inheritedEnvironment) {
41129
41202
  if (expression.kind === "litNull")
41130
41203
  return { ...valueFileFields(base), value: null };
41131
41204
  if (expression.kind !== "litDict") {
@@ -41133,6 +41206,7 @@ function lowerDictionaryValue(context, member, expression, base, source) {
41133
41206
  }
41134
41207
  const baseBody = isObjectRecord2(base.value) ? base.value : {};
41135
41208
  const entryMember = requiredMember(context, member.entryMemberId);
41209
+ const environment = valueGenericEnvironment(base, inheritedEnvironment);
41136
41210
  const body = {};
41137
41211
  for (const entry of expression.entries) {
41138
41212
  if (entry.key.kind !== "litString") {
@@ -41161,7 +41235,8 @@ function lowerDictionaryValue(context, member, expression, base, source) {
41161
41235
  entryMember,
41162
41236
  entry.value,
41163
41237
  valueId,
41164
- source
41238
+ source,
41239
+ environment
41165
41240
  );
41166
41241
  }
41167
41242
  return { ...valueFileFields(base), value: body };
@@ -41839,18 +41914,24 @@ function emitValue(context, member, valueId, options) {
41839
41914
  throw new Error(`Stored member value ${valueId} was not pulled.`);
41840
41915
  }
41841
41916
  options.visited.add(valueId);
41842
- const expression = emitValueBody(
41917
+ const resolvedMember = resolveGenericValueMember(
41843
41918
  context,
41844
41919
  member,
41920
+ options.environment
41921
+ );
41922
+ const expression = emitValueBody(
41923
+ context,
41924
+ resolvedMember,
41845
41925
  value,
41846
41926
  options.visited,
41847
- options.targetTyped ?? false
41927
+ options.targetTyped ?? false,
41928
+ options.environment
41848
41929
  );
41849
41930
  const prefix = options.exposeIdentity ? `@id(${quote4(valueId)})
41850
41931
  ` : "";
41851
41932
  return `${prefix}${expression}`;
41852
41933
  }
41853
- function emitValueBody(context, member, value, visited, targetTyped) {
41934
+ function emitValueBody(context, member, value, visited, targetTyped, environment) {
41854
41935
  const kind = numberField(member, "kind");
41855
41936
  const body = value.value;
41856
41937
  if (kind === 0) return "null";
@@ -41865,19 +41946,34 @@ function emitValueBody(context, member, value, visited, targetTyped) {
41865
41946
  if (kind === 9) return referenceValue(context, member, body, false);
41866
41947
  if (kind === 18) return referenceValue(context, member, body, true);
41867
41948
  if (kind === 11 || kind === 12) return fileValue(context, kind, body);
41868
- if (kind === 5) return dictionaryValue(context, member, body, visited);
41869
- if (kind === 6) return listValue(context, member, value, visited);
41949
+ if (kind === 5)
41950
+ return dictionaryValue(context, member, value, visited, environment);
41951
+ if (kind === 6)
41952
+ return listValue(context, member, value, visited, environment);
41870
41953
  if (kind === 7)
41871
- return classValue(context, member, value, visited, targetTyped);
41954
+ return classValue(
41955
+ context,
41956
+ member,
41957
+ value,
41958
+ visited,
41959
+ targetTyped,
41960
+ environment
41961
+ );
41872
41962
  throw new Error(
41873
41963
  `Stored member ${String(member.name ?? member.id)} has unsupported value kind ${kind}.`
41874
41964
  );
41875
41965
  }
41876
- function classValue(context, member, value, visited, targetTyped) {
41966
+ function classValue(context, member, value, visited, targetTyped, outerEnvironment) {
41877
41967
  const classId = stringOrNull(value.classId) ?? stringField2(member, "classId");
41878
41968
  const schemaClass2 = context.classes.get(classId);
41879
41969
  if (schemaClass2 === void 0)
41880
41970
  throw new Error(`Unknown value class ${classId}.`);
41971
+ const environment = instanceGenericEnvironment(
41972
+ context,
41973
+ classId,
41974
+ member,
41975
+ outerEnvironment
41976
+ );
41881
41977
  const name = stringField2(schemaClass2, "name");
41882
41978
  if (!isObjectRecord2(value.value))
41883
41979
  return targetTyped ? "new()" : `new ${name}()`;
@@ -41899,6 +41995,7 @@ function classValue(context, member, value, visited, targetTyped) {
41899
41995
  throw new Error(`Class ${name}.${key} has no member record.`);
41900
41996
  fields.push(
41901
41997
  `${key} = ${emitValue(context, childMember, childId, {
41998
+ environment,
41902
41999
  exposeIdentity: !context.symbolsByValueId.has(childId) && context.referencedValueIds.has(childId),
41903
42000
  visited
41904
42001
  })}`
@@ -41908,6 +42005,153 @@ function classValue(context, member, value, visited, targetTyped) {
41908
42005
  ${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
41909
42006
  }`;
41910
42007
  }
42008
+ function resolveGenericValueMember(context, member, environment) {
42009
+ if (numberField(member, "kind") !== 21) return member;
42010
+ const genericParamId = stringField2(member, "genericParamId");
42011
+ const bindingMemberId = environment?.get(genericParamId);
42012
+ if (bindingMemberId === void 0) {
42013
+ throw new Error(
42014
+ `Stored Generic member ${String(member.name ?? member.id)} cannot be emitted because generic parameter ${genericParamId} is unbound in the value's concrete class.`
42015
+ );
42016
+ }
42017
+ const bindingMember = context.members.get(bindingMemberId);
42018
+ if (bindingMember === void 0) {
42019
+ throw new Error(
42020
+ `Stored Generic member ${String(member.name ?? member.id)} resolves to missing binding member ${bindingMemberId}.`
42021
+ );
42022
+ }
42023
+ return bindingMember;
42024
+ }
42025
+ function instanceGenericEnvironment(context, classId, member, outerEnvironment) {
42026
+ const bindings = classGenericBindings(context.manifestClasses, classId);
42027
+ const memberId = stringField2(member, "id");
42028
+ const manifestMember = context.manifestMembers.get(memberId);
42029
+ if (manifestMember?.kind === "class") {
42030
+ for (const [genericParamId, argument2] of Object.entries(
42031
+ manifestMember.classArguments
42032
+ )) {
42033
+ if (bindings.get(genericParamId)?.kind === "member") continue;
42034
+ if (argument2.kind === "member") {
42035
+ bindings.set(genericParamId, argument2);
42036
+ continue;
42037
+ }
42038
+ const outerMemberId = outerEnvironment?.get(argument2.genericParamId);
42039
+ if (outerMemberId !== void 0) {
42040
+ bindings.set(genericParamId, {
42041
+ kind: "member",
42042
+ memberId: outerMemberId
42043
+ });
42044
+ }
42045
+ }
42046
+ }
42047
+ const environment = /* @__PURE__ */ new Map();
42048
+ for (const genericParamId of bindings.keys()) {
42049
+ const memberIdValue = terminalGenericBindingMemberId(
42050
+ genericParamId,
42051
+ bindings
42052
+ );
42053
+ if (memberIdValue !== void 0) {
42054
+ environment.set(genericParamId, memberIdValue);
42055
+ }
42056
+ }
42057
+ return environment;
42058
+ }
42059
+ function classGenericBindings(classes, classId) {
42060
+ const chain = [];
42061
+ const visited = /* @__PURE__ */ new Set();
42062
+ let current = classes.get(classId);
42063
+ while (current !== void 0 && !visited.has(current.id)) {
42064
+ visited.add(current.id);
42065
+ chain.push(current);
42066
+ current = current.extendsClassId ? classes.get(current.extendsClassId) : void 0;
42067
+ }
42068
+ const bindings = /* @__PURE__ */ new Map();
42069
+ for (let declarerIndex = 0; declarerIndex < chain.length; declarerIndex++) {
42070
+ const declarer = chain[declarerIndex];
42071
+ for (const parameter3 of declarer.genericParameters) {
42072
+ let cursor = parameter3.id;
42073
+ let terminal = {
42074
+ kind: "generic",
42075
+ genericParamId: cursor
42076
+ };
42077
+ for (let level = declarerIndex; level > 0; level--) {
42078
+ const child = chain[level - 1];
42079
+ const binding = child.extendsGenericBindings[cursor];
42080
+ if (binding === void 0) break;
42081
+ terminal = binding;
42082
+ if (binding.kind === "member") break;
42083
+ cursor = binding.genericParamId;
42084
+ }
42085
+ bindings.set(parameter3.id, terminal);
42086
+ }
42087
+ }
42088
+ return bindings;
42089
+ }
42090
+ function terminalGenericBindingMemberId(genericParamId, bindings) {
42091
+ const visited = /* @__PURE__ */ new Set();
42092
+ let cursor = genericParamId;
42093
+ while (!visited.has(cursor)) {
42094
+ visited.add(cursor);
42095
+ const binding = bindings.get(cursor);
42096
+ if (binding === void 0) return void 0;
42097
+ if (binding.kind === "member") return binding.memberId;
42098
+ cursor = binding.genericParamId;
42099
+ }
42100
+ return void 0;
42101
+ }
42102
+ function resolveGenericSchemaMember(context, member, environment) {
42103
+ if (member.kind !== "generic") return member;
42104
+ const bindingMemberId = environment?.get(member.genericParamId);
42105
+ if (bindingMemberId === void 0) {
42106
+ throw new Error(
42107
+ `Stored Generic member ${member.name} cannot be lowered because generic parameter ${member.genericParamId} is unbound in the value's concrete class.`
42108
+ );
42109
+ }
42110
+ const bindingMember = context.members.get(bindingMemberId);
42111
+ if (bindingMember === void 0) {
42112
+ throw new Error(
42113
+ `Stored Generic member ${member.name} resolves to missing binding member ${bindingMemberId}.`
42114
+ );
42115
+ }
42116
+ return bindingMember;
42117
+ }
42118
+ function lowerInstanceGenericEnvironment(context, classId, member, outerEnvironment) {
42119
+ const bindings = classGenericBindings(context.classes, classId);
42120
+ for (const [genericParamId, argument2] of Object.entries(
42121
+ member.classArguments
42122
+ )) {
42123
+ if (bindings.get(genericParamId)?.kind === "member") continue;
42124
+ if (argument2.kind === "member") {
42125
+ bindings.set(genericParamId, argument2);
42126
+ continue;
42127
+ }
42128
+ const outerMemberId = outerEnvironment?.get(argument2.genericParamId);
42129
+ if (outerMemberId !== void 0) {
42130
+ bindings.set(genericParamId, {
42131
+ kind: "member",
42132
+ memberId: outerMemberId
42133
+ });
42134
+ }
42135
+ }
42136
+ const environment = /* @__PURE__ */ new Map();
42137
+ for (const genericParamId of bindings.keys()) {
42138
+ const memberId = terminalGenericBindingMemberId(genericParamId, bindings);
42139
+ if (memberId !== void 0) environment.set(genericParamId, memberId);
42140
+ }
42141
+ return environment;
42142
+ }
42143
+ function valueGenericEnvironment(value, inherited) {
42144
+ const environment = new Map(inherited ?? []);
42145
+ if (!isObjectRecord2(value.genericBindings)) return environment;
42146
+ for (const [genericParamId, memberId] of Object.entries(
42147
+ value.genericBindings
42148
+ )) {
42149
+ if (typeof memberId === "string") {
42150
+ environment.set(genericParamId, memberId);
42151
+ }
42152
+ }
42153
+ return environment;
42154
+ }
41911
42155
  function inheritedSchemaMemberId(context, schemaClass2, key) {
41912
42156
  const visited = /* @__PURE__ */ new Set();
41913
42157
  let current = typeof schemaClass2.extendsClassId === "string" ? schemaClass2.extendsClassId : void 0;
@@ -41922,11 +42166,12 @@ function inheritedSchemaMemberId(context, schemaClass2, key) {
41922
42166
  }
41923
42167
  return void 0;
41924
42168
  }
41925
- function listValue(context, member, value, visited) {
42169
+ function listValue(context, member, value, visited, inheritedEnvironment) {
41926
42170
  if (value.value === null) return "null";
41927
42171
  const entryMember = context.members.get(stringField2(member, "entryMemberId"));
41928
42172
  if (entryMember === void 0)
41929
42173
  throw new Error(`List entry member was not pulled.`);
42174
+ const environment = valueGenericEnvironment(value, inheritedEnvironment);
41930
42175
  const ids = member.listKind === "unordered" ? [...context.values].filter(([, candidate]) => candidate.containerId === value.id).map(([id2]) => id2).sort(compareCodePoints) : Array.isArray(value.value) ? value.value.filter(
41931
42176
  (entry) => typeof entry === "string"
41932
42177
  ) : [];
@@ -41935,6 +42180,7 @@ function listValue(context, member, value, visited) {
41935
42180
  ${ids.map(
41936
42181
  (id2) => indentNeoSourceNonEmptyLines(
41937
42182
  emitValue(context, entryMember, id2, {
42183
+ environment,
41938
42184
  exposeIdentity: context.symbolsByValueId.get(id2) === void 0,
41939
42185
  visited
41940
42186
  }),
@@ -41943,12 +42189,14 @@ ${ids.map(
41943
42189
  ).join(",\n\n")}
41944
42190
  ]`;
41945
42191
  }
41946
- function dictionaryValue(context, member, body, visited) {
42192
+ function dictionaryValue(context, member, value, visited, inheritedEnvironment) {
42193
+ const body = value.value;
41947
42194
  if (body === null) return "null";
41948
42195
  if (!isObjectRecord2(body)) return "{}";
41949
42196
  const entryMember = context.members.get(stringField2(member, "entryMemberId"));
41950
42197
  if (entryMember === void 0)
41951
42198
  throw new Error(`Dictionary entry member was not pulled.`);
42199
+ const environment = valueGenericEnvironment(value, inheritedEnvironment);
41952
42200
  const entries = Object.entries(body).sort(
41953
42201
  ([left], [right]) => compareCodePoints(left, right)
41954
42202
  );
@@ -41958,6 +42206,7 @@ ${entries.flatMap(
41958
42206
  ([key, id2]) => typeof id2 === "string" ? [
41959
42207
  indentNeoSourceNonEmptyLines(
41960
42208
  `${quote4(key)}: ${emitValue(context, entryMember, id2, {
42209
+ environment,
41961
42210
  exposeIdentity: !context.symbolsByValueId.has(id2) && context.referencedValueIds.has(id2),
41962
42211
  visited
41963
42212
  })}`,
@@ -42175,6 +42424,7 @@ function emitProjectRootSourceV4(records2, manifest) {
42175
42424
  );
42176
42425
  const classes = new Map(manifest.classes.map((entry) => [entry.id, entry]));
42177
42426
  const values = emitStoredValueBindingSourcesV4(records2, memberIds, {
42427
+ manifest,
42178
42428
  targetTypedRoot: true
42179
42429
  });
42180
42430
  const declarations = PROJECT_ROOT_SOURCE_SLOTS.map((slot, index) => {
@@ -42340,8 +42590,8 @@ function emitProjectDocumentFilesV4(records2) {
42340
42590
  });
42341
42591
  }
42342
42592
  const manifest = documentsToProjectSchemaManifest(schemaRecords);
42343
- const staticValues = emitStaticValueSourcesV4(records2);
42344
- const memberDefaults = emitMemberDefaultSourcesV4(records2);
42593
+ const staticValues = emitStaticValueSourcesV4(records2, manifest);
42594
+ const memberDefaults = emitMemberDefaultSourcesV4(records2, manifest);
42345
42595
  const baseSource = emitProjectSourcesV4(manifest, {
42346
42596
  staticInitializers: staticValues.initializers,
42347
42597
  defaultInitializers: memberDefaults.initializers,
@@ -64311,13 +64561,28 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
64311
64561
  if (typeof compiled.id !== "string") continue;
64312
64562
  const explicit = changesById.get(compiled.id);
64313
64563
  if (explicit !== void 0) {
64314
- explicit.nextData = compiled;
64564
+ if (explicit.nextData === void 0) {
64565
+ throw new Error(
64566
+ `Cannot attach compiled NeoScript for deleted member "${compiled.id}".`
64567
+ );
64568
+ }
64569
+ explicit.nextData = mergeCompiledNeoScriptBody(
64570
+ explicit.nextData,
64571
+ compiled
64572
+ );
64315
64573
  continue;
64316
64574
  }
64317
64575
  if (!completeSweep) continue;
64318
64576
  const key = recordStateKey("member", compiled.id);
64319
64577
  const base = workspace.state.records[key];
64320
- if (base === void 0 || canonicallyEqual(base.data, compiled)) continue;
64578
+ if (base === void 0) continue;
64579
+ if (!isObjectRecord2(base.data)) {
64580
+ throw new Error(
64581
+ `Cannot attach compiled NeoScript for member "${compiled.id}": its base record is not an object.`
64582
+ );
64583
+ }
64584
+ const nextData = mergeCompiledNeoScriptBody(base.data, compiled);
64585
+ if (canonicallyEqual(base.data, nextData)) continue;
64321
64586
  const reconstructed3 = status.reconstructed.get(key);
64322
64587
  if (reconstructed3 === void 0) {
64323
64588
  throw new Error(
@@ -64329,7 +64594,7 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
64329
64594
  recordKind: "member",
64330
64595
  recordId: compiled.id,
64331
64596
  file: reconstructed3.file,
64332
- nextData: compiled,
64597
+ nextData,
64333
64598
  baseData: base.data,
64334
64599
  baseContentHash: base.contentHash,
64335
64600
  casBaseHash: base.conflictServerHash ?? base.contentHash
@@ -64338,6 +64603,18 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
64338
64603
  changesById.set(compiled.id, cascadeChange);
64339
64604
  }
64340
64605
  }
64606
+ function mergeCompiledNeoScriptBody(persisted, compiled) {
64607
+ const next = { ...persisted };
64608
+ const fields = compiled.kind === 10 ? ["getter", "setter"] : ["action"];
64609
+ for (const field of fields) {
64610
+ if (compiled[field] === void 0) {
64611
+ delete next[field];
64612
+ } else {
64613
+ next[field] = compiled[field];
64614
+ }
64615
+ }
64616
+ return next;
64617
+ }
64341
64618
  function workspaceChangesRequireCompleteBodySweep(changes) {
64342
64619
  for (const change of changes) {
64343
64620
  if (change.recordKind === "class" || change.recordKind === "enum" || change.recordKind === "interface") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",