@neocompose/cli 0.10.1 → 0.10.2

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,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.2] - 2026-07-25
4
+
5
+ ### Fixed
6
+
7
+ - Read `required` and an override's `extendsMemberId` from source instead of
8
+ carrying the pulled value forward. A member whose stored `required`
9
+ contradicted its own return type, and an override pointing past the member
10
+ it directly overrides, are corrected on the next push.
11
+ - Persist a class's `schemaKeyOrder` only where the declaration order differs
12
+ from the one its schema map already implies. An equivalent order is stored
13
+ as absent rather than spelled out, and the answer no longer depends on
14
+ having pulled the class.
15
+ - Restore the server-owned envelope on reconstructed records before
16
+ prospective animation validation, so a workspace with animation schema no
17
+ longer reports every class as malformed. Validation failures now name the
18
+ offending record.
19
+
3
20
  ## [0.10.1] - 2026-07-25
4
21
 
5
22
  ### Changed
package/dist/neo.mjs CHANGED
@@ -28915,11 +28915,7 @@ function lowerClass(context, declaration) {
28915
28915
  selectionSpan: span(parameter3.identity)
28916
28916
  };
28917
28917
  });
28918
- const baseEffectiveOrder = base?.schemaKeyOrder ?? (base ? Object.keys(base.schema) : []);
28919
- const baseOwnOrder = baseEffectiveOrder.filter(
28920
- (name) => Object.hasOwn(base?.schema ?? {}, name)
28921
- );
28922
- const persistedSchemaOrder = base && JSON.stringify(baseOwnOrder) === JSON.stringify(schemaKeyOrder) ? base.schemaKeyOrder : schemaKeyOrder;
28918
+ const persistedSchemaOrder = isImpliedSchemaKeyOrder(schemaKeyOrder) ? null : schemaKeyOrder;
28923
28919
  return {
28924
28920
  id: id2,
28925
28921
  source: sourceIdentity2(declaration, "class", declaration.name),
@@ -29120,7 +29116,7 @@ function projectSchemaJsonValue(value) {
29120
29116
  }
29121
29117
  function memberCommon(context, ownerClass, declaration, id2, owner, base) {
29122
29118
  const storage = annotation(declaration.annotations, "storage");
29123
- const inheritedId = declaration.modifiers.includes("override") || declaration.modifiers.includes("sealed") ? base?.overrideOf ?? inheritedMemberId(context, ownerClass, declaration.name) : null;
29119
+ const inheritedId = declaration.modifiers.includes("override") || declaration.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, declaration.name) : null;
29124
29120
  return {
29125
29121
  id: id2,
29126
29122
  source: sourceIdentity2(declaration, "member", declaration.name),
@@ -29135,7 +29131,10 @@ function memberCommon(context, ownerClass, declaration, id2, owner, base) {
29135
29131
  accessModifier: owner.kind === "classMember" ? effectiveSourceAccessModifier(declaration.modifiers, "class") : "public",
29136
29132
  modifier: memberModifier2(declaration.modifiers, base?.modifier),
29137
29133
  locked: hasAnnotation(declaration.annotations, "locked"),
29138
- required: declaration.kind === "field" ? !declaration.type.nullable : base?.required ?? false,
29134
+ // Every declaration kind carries a type, and its nullability is the whole
29135
+ // of what `required` means. Properties and getters used to fall back to
29136
+ // the pulled value, which left a fresh workspace calling them optional.
29137
+ required: !declaration.type.nullable,
29139
29138
  defaultValue: null,
29140
29139
  overrideOf: inheritedId,
29141
29140
  system: systemMetadata(declaration.annotations),
@@ -30161,6 +30160,9 @@ function referenceId(raw) {
30161
30160
  return null;
30162
30161
  }
30163
30162
  }
30163
+ function isImpliedSchemaKeyOrder(order) {
30164
+ return order.every((key, index) => index === 0 || order[index - 1] <= key);
30165
+ }
30164
30166
  function memberModifier2(modifiers, baseModifier) {
30165
30167
  if (modifiers.includes("override")) {
30166
30168
  if (modifiers.includes("abstract")) return "abstractOverride";
@@ -48915,28 +48917,28 @@ function validateProspectiveAnimationRecordsV4(records2) {
48915
48917
  if (record3.recordKind === "project") {
48916
48918
  if (!isProject(record3.data)) {
48917
48919
  throw new Error(
48918
- "Prospective animation validation received an invalid project record."
48920
+ `Prospective animation validation received an invalid project record ${recordLabel(record3.data)}.`
48919
48921
  );
48920
48922
  }
48921
48923
  project = record3.data;
48922
48924
  } else if (record3.recordKind === "class") {
48923
48925
  if (!isNeoSchemaClass(record3.data)) {
48924
48926
  throw new Error(
48925
- "Prospective animation validation received an invalid class record."
48927
+ `Prospective animation validation received an invalid class record ${recordLabel(record3.data)}.`
48926
48928
  );
48927
48929
  }
48928
48930
  classes.push(record3.data);
48929
48931
  } else if (record3.recordKind === "member") {
48930
48932
  if (!isMember(record3.data)) {
48931
48933
  throw new Error(
48932
- "Prospective animation validation received an invalid member record."
48934
+ `Prospective animation validation received an invalid member record ${recordLabel(record3.data)}.`
48933
48935
  );
48934
48936
  }
48935
48937
  members.push(record3.data);
48936
48938
  } else if (record3.recordKind === "value") {
48937
48939
  if (!isMemberValue(record3.data)) {
48938
48940
  throw new Error(
48939
- "Prospective animation validation received an invalid value record."
48941
+ `Prospective animation validation received an invalid value record ${recordLabel(record3.data)}.`
48940
48942
  );
48941
48943
  }
48942
48944
  values.push(record3.data);
@@ -48945,6 +48947,18 @@ function validateProspectiveAnimationRecordsV4(records2) {
48945
48947
  if (project === void 0) return;
48946
48948
  assertAnimationClipDocumentValid({ project, classes, members, values });
48947
48949
  }
48950
+ function serverEnvelope(stored) {
48951
+ if (!isObjectRecord2(stored)) return {};
48952
+ const envelope = {};
48953
+ for (const field of ["projectId", "createdAt", "updatedAt"]) {
48954
+ if (stored[field] !== void 0) envelope[field] = stored[field];
48955
+ }
48956
+ return envelope;
48957
+ }
48958
+ function recordLabel(data) {
48959
+ const id2 = typeof data.id === "string" ? data.id : "<no id>";
48960
+ return typeof data.name === "string" ? `${id2} ("${data.name}")` : id2;
48961
+ }
48948
48962
  function prospectiveAnimationRecords(base, reconstructed3, changes, seeds) {
48949
48963
  const prospective = /* @__PURE__ */ new Map();
48950
48964
  for (const [key, state] of Object.entries(base)) {
@@ -48957,16 +48971,25 @@ function prospectiveAnimationRecords(base, reconstructed3, changes, seeds) {
48957
48971
  const key = recordStateKey(change.recordKind, change.recordId);
48958
48972
  if (change.kind === "delete") prospective.delete(key);
48959
48973
  }
48960
- for (const [key, record3] of reconstructed3) {
48961
- prospective.set(key, {
48962
- recordKind: record3.recordKind,
48963
- data: record3.fullData
48964
- });
48965
- }
48966
- const projectId = [...prospective.values()].find(
48974
+ const projectRecord = [...prospective.values()].find(
48967
48975
  (record3) => record3.recordKind === "project"
48968
- )?.data.id;
48976
+ ) ?? [...reconstructed3.values()].filter((record3) => record3.recordKind === "project").map((record3) => ({
48977
+ recordKind: record3.recordKind,
48978
+ data: record3.fullData
48979
+ }))[0];
48980
+ const projectId = projectRecord?.data.id;
48969
48981
  const seedEnvelope = typeof projectId === "string" ? { projectId, createdAt: 0, updatedAt: 0 } : {};
48982
+ for (const [key, record3] of reconstructed3) {
48983
+ const envelope = {
48984
+ ...seedEnvelope,
48985
+ ...serverEnvelope(prospective.get(key)?.data)
48986
+ };
48987
+ const data = { ...record3.fullData };
48988
+ for (const [field, value] of Object.entries(envelope)) {
48989
+ if (data[field] === void 0) data[field] = value;
48990
+ }
48991
+ prospective.set(key, { recordKind: record3.recordKind, data });
48992
+ }
48970
48993
  for (const [memberId, seed] of seeds) {
48971
48994
  for (const bindingMember of seed.bindingMembers ?? []) {
48972
48995
  prospective.set(recordStateKey("member", bindingMember.id), {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",