@neocompose/cli 0.10.2 → 0.10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.4] - 2026-07-26
4
+
5
+ ### Fixed
6
+
7
+ - Materialize the required keys a bare `new()` omits. A constructor body was
8
+ built from constructor projections and explicit assignments only, so
9
+ `Birthday = new()` lowered to `{}` and the commit was rejected with
10
+ `missing required schema key "Day"` -- naming a key whose default the source
11
+ declares one line away. Each omitted required key now lowers the member's own
12
+ declared initializer, so a nested `new()` recurses and a row-backed default
13
+ is copied rather than shared. Optional keys stay absent, and a required key
14
+ whose member declares no default is unchanged.
15
+
16
+ - Stop rejecting the transaction status response over a field the server no
17
+ longer sends. `resultCursor` was removed from the status payload as dead --
18
+ it was hardcoded null and read only as the starting result-page cursor,
19
+ where an empty cursor means the same thing -- but push still required it to
20
+ be present, so every push large enough to go durable failed with
21
+ `resultCursor must be a string or null` after the write had already
22
+ committed.
23
+
24
+ ## [0.10.3] - 2026-07-25
25
+
26
+ ### Fixed
27
+
28
+ - Stop writing `isReadOnly: false` onto members that never carried the field.
29
+ Absent is how false is spelled, but document normalization materialized the
30
+ full-member default, so any member record that changed for another reason
31
+ pushed an explicit `isReadOnly: false` with it. The explicit value is kept
32
+ only where it has something to overwrite -- a record that already carries
33
+ the field, which is how dropping `readonly` from a declaration reaches the
34
+ server.
35
+
3
36
  ## [0.10.2] - 2026-07-25
4
37
 
5
38
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -1356,6 +1356,9 @@ function composeDocumentRecord(recordKind, recordId, authoredFields, baseRecord)
1356
1356
  const base = partitionDocumentFields(recordKind, baseRecord.data);
1357
1357
  Object.assign(data, base.derived, base.volatile);
1358
1358
  }
1359
+ if (recordKind === "member" && data.isReadOnly === false && !Object.prototype.hasOwnProperty.call(baseRecord?.data ?? {}, "isReadOnly")) {
1360
+ delete data.isReadOnly;
1361
+ }
1359
1362
  return { recordKind, recordId, data };
1360
1363
  }
1361
1364
  function assertOnlyAuthoredFields(recordKind, fields) {
@@ -42414,6 +42417,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
42414
42417
  mainLocale: projectMainLocaleFromState(state),
42415
42418
  valuePlacements: indexValuePlacements(state),
42416
42419
  parsedInitializers,
42420
+ declaredInitializers: indexDeclaredInitializers(options.analysis),
42417
42421
  reconstructed: /* @__PURE__ */ new Map(),
42418
42422
  pendingValues: /* @__PURE__ */ new Map(),
42419
42423
  pendingLocalizedTexts: /* @__PURE__ */ new Map(),
@@ -42421,6 +42425,27 @@ function buildValueLowerContext(state, manifest, options = {}) {
42421
42425
  pendingBindingMembersByClassId: /* @__PURE__ */ new Map()
42422
42426
  };
42423
42427
  }
42428
+ function indexDeclaredInitializers(analysis) {
42429
+ const initializers = /* @__PURE__ */ new Map();
42430
+ if (analysis === void 0) return initializers;
42431
+ for (const sourceClass of analysis.schema.classes) {
42432
+ for (const declaration of sourceClass.members) {
42433
+ if (declaration.kind !== "field" || declaration.initializer === null) {
42434
+ continue;
42435
+ }
42436
+ if (declaration.modifiers.includes("static")) continue;
42437
+ initializers.set(
42438
+ sourceIdentityId(
42439
+ declaration,
42440
+ "member",
42441
+ `${sourceClass.name}.${declaration.name}`
42442
+ ),
42443
+ declaration.initializer
42444
+ );
42445
+ }
42446
+ }
42447
+ return initializers;
42448
+ }
42424
42449
  function lowerStoredValueBindingsV4(state, manifest, bindings, options = {}) {
42425
42450
  const context = buildValueLowerContext(state, manifest, options);
42426
42451
  const memberValueIds = /* @__PURE__ */ new Map();
@@ -42886,6 +42911,17 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
42886
42911
  environment
42887
42912
  );
42888
42913
  }
42914
+ materializeRequiredDefaults(
42915
+ context,
42916
+ resolvedMember,
42917
+ effectiveClass,
42918
+ body,
42919
+ source,
42920
+ path,
42921
+ rows,
42922
+ localizedTexts,
42923
+ environment
42924
+ );
42889
42925
  value = body;
42890
42926
  } else if (resolvedMember.kind === "list") {
42891
42927
  if (expression.kind === "litNull") {
@@ -42981,6 +43017,51 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
42981
43017
  context.pendingValues.set(valueId, row);
42982
43018
  return row;
42983
43019
  }
43020
+ function materializeRequiredDefaults(context, member, effectiveClass, body, source, path, rows, localizedTexts, environment) {
43021
+ if (member.partial === true) return;
43022
+ for (const [schemaKey, childMember] of storedSchemaEntries(
43023
+ context,
43024
+ effectiveClass
43025
+ )) {
43026
+ if (body[schemaKey] !== void 0) continue;
43027
+ if (!childMember.required) continue;
43028
+ if (childMember.kind === "class" && childMember.partial === true) continue;
43029
+ const initializer = context.declaredInitializers.get(childMember.id);
43030
+ if (initializer === void 0) continue;
43031
+ body[schemaKey] = lowerSeedChild(
43032
+ context,
43033
+ recursivePartialMember(member, childMember),
43034
+ parseCachedInitializer(context.parsedInitializers, initializer),
43035
+ source,
43036
+ `${path}.${schemaKey}`,
43037
+ rows,
43038
+ localizedTexts,
43039
+ void 0,
43040
+ environment
43041
+ );
43042
+ }
43043
+ }
43044
+ function storedSchemaEntries(context, schemaClass2) {
43045
+ const entries = /* @__PURE__ */ new Map();
43046
+ const visited = /* @__PURE__ */ new Set();
43047
+ let current = schemaClass2;
43048
+ while (current !== void 0 && !visited.has(current.id)) {
43049
+ visited.add(current.id);
43050
+ for (const [schemaKey, memberId] of Object.entries(current.schema)) {
43051
+ if (entries.has(schemaKey)) continue;
43052
+ const child = context.members.get(memberId);
43053
+ if (child === void 0) continue;
43054
+ if (!ownsValueRow(child)) continue;
43055
+ entries.set(schemaKey, child);
43056
+ }
43057
+ current = current.extendsClassId === null ? void 0 : context.classes.get(current.extendsClassId);
43058
+ }
43059
+ return [...entries];
43060
+ }
43061
+ function ownsValueRow(member) {
43062
+ if (member.isReadOnly) return false;
43063
+ return member.kind !== "computed" && member.kind !== "function" && member.kind !== "scriptFunction";
43064
+ }
42984
43065
  function lowerSeedChild(context, member, expression, source, path, rows, localizedTexts, containerId, environment) {
42985
43066
  const symbolId = sourceValueSymbol(context, expression);
42986
43067
  if (symbolId !== null) return symbolId;
@@ -66665,10 +66746,6 @@ function readProjectVersionTransactionStatus(value, transactionId) {
66665
66746
  value.errorMessage,
66666
66747
  `Project transaction "${transactionId}" errorMessage`
66667
66748
  );
66668
- const resultCursor = readNullableString(
66669
- value.resultCursor,
66670
- `Project transaction "${transactionId}" resultCursor`
66671
- );
66672
66749
  return {
66673
66750
  transactionId,
66674
66751
  commitStatus: value.commitStatus,
@@ -66689,8 +66766,7 @@ function readProjectVersionTransactionStatus(value, transactionId) {
66689
66766
  `Project transaction "${transactionId}" appliedChunkCount`
66690
66767
  ),
66691
66768
  errorCode,
66692
- errorMessage: errorMessage3,
66693
- resultCursor
66769
+ errorMessage: errorMessage3
66694
66770
  };
66695
66771
  }
66696
66772
  function readProjectVersionTransactionResultPage(value, transactionId) {
@@ -66898,7 +66974,7 @@ async function downloadProjectVersionTransactionResult(args) {
66898
66974
  const assignments = {};
66899
66975
  const changedRecords = [];
66900
66976
  const seenCursors = /* @__PURE__ */ new Set();
66901
- let cursor = args.status.resultCursor ?? "";
66977
+ let cursor = "";
66902
66978
  for (; ; ) {
66903
66979
  if (seenCursors.has(cursor)) {
66904
66980
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",