@neocompose/cli 0.10.3 → 0.10.5
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 +40 -0
- package/dist/neo.mjs +136 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.5] - 2026-07-26
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Stop writing a second `@id` above every static and project-root initializer.
|
|
8
|
+
A member owns exactly one value row, so that row's identity is a function of
|
|
9
|
+
the declaration the annotation sat under and never needed to be authored.
|
|
10
|
+
`neo pull` now emits the binding without it, and lowering resolves the row
|
|
11
|
+
itself. An `@id` left in a file is accepted while it agrees with the row the
|
|
12
|
+
member already owns, so existing workspaces keep working until their next
|
|
13
|
+
pull; one that disagrees is rejected rather than pushing a create for a
|
|
14
|
+
second row.
|
|
15
|
+
- Derive the row id for a binding that does not have one yet, instead of
|
|
16
|
+
minting it. A member declared for the first time has no durable id to derive
|
|
17
|
+
from, so it carries a `__pending__:member-value:` token that resolves to the
|
|
18
|
+
derivation once the push assigns the member; the server re-derives it rather
|
|
19
|
+
than accepting the client's answer. Rows that already exist keep the ids
|
|
20
|
+
they were minted with -- P39 moves those onto the derivation.
|
|
21
|
+
|
|
22
|
+
## [0.10.4] - 2026-07-26
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Materialize the required keys a bare `new()` omits. A constructor body was
|
|
27
|
+
built from constructor projections and explicit assignments only, so
|
|
28
|
+
`Birthday = new()` lowered to `{}` and the commit was rejected with
|
|
29
|
+
`missing required schema key "Day"` -- naming a key whose default the source
|
|
30
|
+
declares one line away. Each omitted required key now lowers the member's own
|
|
31
|
+
declared initializer, so a nested `new()` recurses and a row-backed default
|
|
32
|
+
is copied rather than shared. Optional keys stay absent, and a required key
|
|
33
|
+
whose member declares no default is unchanged.
|
|
34
|
+
|
|
35
|
+
- Stop rejecting the transaction status response over a field the server no
|
|
36
|
+
longer sends. `resultCursor` was removed from the status payload as dead --
|
|
37
|
+
it was hardcoded null and read only as the starting result-page cursor,
|
|
38
|
+
where an empty cursor means the same thing -- but push still required it to
|
|
39
|
+
be present, so every push large enough to go durable failed with
|
|
40
|
+
`resultCursor must be a string or null` after the write had already
|
|
41
|
+
committed.
|
|
42
|
+
|
|
3
43
|
## [0.10.3] - 2026-07-25
|
|
4
44
|
|
|
5
45
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -42179,6 +42179,27 @@ var init_dialogue_sources = __esm({
|
|
|
42179
42179
|
}
|
|
42180
42180
|
});
|
|
42181
42181
|
|
|
42182
|
+
// ../src/models/members/member-value-id.ts
|
|
42183
|
+
function derivedMemberValueId(memberId) {
|
|
42184
|
+
return v5_default(memberId, NEO_MEMBER_VALUE_NAMESPACE);
|
|
42185
|
+
}
|
|
42186
|
+
function pendingMemberValueId(pendingMemberId) {
|
|
42187
|
+
return `${PENDING_MEMBER_VALUE_PREFIX}${encodeURIComponent(pendingMemberId)}`;
|
|
42188
|
+
}
|
|
42189
|
+
function pendingMemberValueMemberId(token) {
|
|
42190
|
+
if (!token.startsWith(PENDING_MEMBER_VALUE_PREFIX)) return null;
|
|
42191
|
+
return decodeURIComponent(token.slice(PENDING_MEMBER_VALUE_PREFIX.length));
|
|
42192
|
+
}
|
|
42193
|
+
var NEO_MEMBER_VALUE_NAMESPACE, PENDING_MEMBER_VALUE_PREFIX;
|
|
42194
|
+
var init_member_value_id = __esm({
|
|
42195
|
+
"../src/models/members/member-value-id.ts"() {
|
|
42196
|
+
"use strict";
|
|
42197
|
+
init_dist_node();
|
|
42198
|
+
NEO_MEMBER_VALUE_NAMESPACE = "7f2b9c14-58d6-5a07-b3e1-4c9d0a6f8b25";
|
|
42199
|
+
PENDING_MEMBER_VALUE_PREFIX = "__pending__:member-value:";
|
|
42200
|
+
}
|
|
42201
|
+
});
|
|
42202
|
+
|
|
42182
42203
|
// src/project-source/value-sources.ts
|
|
42183
42204
|
function inferredGenericClassBinding(classId) {
|
|
42184
42205
|
return `${INFERRED_GENERIC_CLASS_PREFIX}${classId}`;
|
|
@@ -42240,7 +42261,10 @@ function emitStoredValueBindingSourcesV4(records2, memberIds, options) {
|
|
|
42240
42261
|
initializers.set(
|
|
42241
42262
|
memberId,
|
|
42242
42263
|
emitValue(context, member, member.valueId, {
|
|
42243
|
-
|
|
42264
|
+
definitionSite: true,
|
|
42265
|
+
// The row is `derivedMemberValueId(memberId)` and the declaration
|
|
42266
|
+
// above it already carries `@id(memberId)`.
|
|
42267
|
+
writeIdentity: false,
|
|
42244
42268
|
targetTyped: options.targetTypedRoot === true,
|
|
42245
42269
|
visited
|
|
42246
42270
|
})
|
|
@@ -42417,6 +42441,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
|
|
|
42417
42441
|
mainLocale: projectMainLocaleFromState(state),
|
|
42418
42442
|
valuePlacements: indexValuePlacements(state),
|
|
42419
42443
|
parsedInitializers,
|
|
42444
|
+
declaredInitializers: indexDeclaredInitializers(options.analysis),
|
|
42420
42445
|
reconstructed: /* @__PURE__ */ new Map(),
|
|
42421
42446
|
pendingValues: /* @__PURE__ */ new Map(),
|
|
42422
42447
|
pendingLocalizedTexts: /* @__PURE__ */ new Map(),
|
|
@@ -42424,6 +42449,27 @@ function buildValueLowerContext(state, manifest, options = {}) {
|
|
|
42424
42449
|
pendingBindingMembersByClassId: /* @__PURE__ */ new Map()
|
|
42425
42450
|
};
|
|
42426
42451
|
}
|
|
42452
|
+
function indexDeclaredInitializers(analysis) {
|
|
42453
|
+
const initializers = /* @__PURE__ */ new Map();
|
|
42454
|
+
if (analysis === void 0) return initializers;
|
|
42455
|
+
for (const sourceClass of analysis.schema.classes) {
|
|
42456
|
+
for (const declaration of sourceClass.members) {
|
|
42457
|
+
if (declaration.kind !== "field" || declaration.initializer === null) {
|
|
42458
|
+
continue;
|
|
42459
|
+
}
|
|
42460
|
+
if (declaration.modifiers.includes("static")) continue;
|
|
42461
|
+
initializers.set(
|
|
42462
|
+
sourceIdentityId(
|
|
42463
|
+
declaration,
|
|
42464
|
+
"member",
|
|
42465
|
+
`${sourceClass.name}.${declaration.name}`
|
|
42466
|
+
),
|
|
42467
|
+
declaration.initializer
|
|
42468
|
+
);
|
|
42469
|
+
}
|
|
42470
|
+
}
|
|
42471
|
+
return initializers;
|
|
42472
|
+
}
|
|
42427
42473
|
function lowerStoredValueBindingsV4(state, manifest, bindings, options = {}) {
|
|
42428
42474
|
const context = buildValueLowerContext(state, manifest, options);
|
|
42429
42475
|
const memberValueIds = /* @__PURE__ */ new Map();
|
|
@@ -42667,8 +42713,8 @@ function lowerStoredBinding(context, binding, memberValueIds, seeds) {
|
|
|
42667
42713
|
preserveReboundValue(context, currentValueId, referenced, binding);
|
|
42668
42714
|
return;
|
|
42669
42715
|
}
|
|
42670
|
-
const
|
|
42671
|
-
|
|
42716
|
+
const valueId = currentValueId ?? memberValueId(binding.memberId);
|
|
42717
|
+
assertAuthoredBindingIdMatches(expression, binding, valueId);
|
|
42672
42718
|
memberValueIds.set(binding.memberId, valueId);
|
|
42673
42719
|
if (currentValueId === valueId) {
|
|
42674
42720
|
const existingReconstructedKeys = new Set(context.reconstructed.keys());
|
|
@@ -42716,6 +42762,16 @@ function lowerStoredBinding(context, binding, memberValueIds, seeds) {
|
|
|
42716
42762
|
const seed = lowerStaticSeed(context, member, expression, binding, valueId);
|
|
42717
42763
|
seeds.set(binding.memberId, { ...seed, valueId });
|
|
42718
42764
|
}
|
|
42765
|
+
function assertAuthoredBindingIdMatches(expression, binding, valueId) {
|
|
42766
|
+
const authoredId = annotatedValue(expression).id;
|
|
42767
|
+
if (authoredId === null || authoredId === valueId) return;
|
|
42768
|
+
throw new Error(
|
|
42769
|
+
`Binding ${binding.label} is annotated with value id ${authoredId}, but the member owns value ${valueId}. Remove the @id \u2014 \`neo pull\` rewrites this file without it.`
|
|
42770
|
+
);
|
|
42771
|
+
}
|
|
42772
|
+
function memberValueId(memberId) {
|
|
42773
|
+
return isPendingId(memberId) ? pendingMemberValueId(memberId) : derivedMemberValueId(memberId);
|
|
42774
|
+
}
|
|
42719
42775
|
function reconstructedOrStateValue(context, valueId) {
|
|
42720
42776
|
return context.reconstructed.get(`value:${valueId}`)?.fileFields ?? valueBase(context, valueId);
|
|
42721
42777
|
}
|
|
@@ -42889,6 +42945,17 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
|
|
|
42889
42945
|
environment
|
|
42890
42946
|
);
|
|
42891
42947
|
}
|
|
42948
|
+
materializeRequiredDefaults(
|
|
42949
|
+
context,
|
|
42950
|
+
resolvedMember,
|
|
42951
|
+
effectiveClass,
|
|
42952
|
+
body,
|
|
42953
|
+
source,
|
|
42954
|
+
path,
|
|
42955
|
+
rows,
|
|
42956
|
+
localizedTexts,
|
|
42957
|
+
environment
|
|
42958
|
+
);
|
|
42892
42959
|
value = body;
|
|
42893
42960
|
} else if (resolvedMember.kind === "list") {
|
|
42894
42961
|
if (expression.kind === "litNull") {
|
|
@@ -42984,6 +43051,51 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
|
|
|
42984
43051
|
context.pendingValues.set(valueId, row);
|
|
42985
43052
|
return row;
|
|
42986
43053
|
}
|
|
43054
|
+
function materializeRequiredDefaults(context, member, effectiveClass, body, source, path, rows, localizedTexts, environment) {
|
|
43055
|
+
if (member.partial === true) return;
|
|
43056
|
+
for (const [schemaKey, childMember] of storedSchemaEntries(
|
|
43057
|
+
context,
|
|
43058
|
+
effectiveClass
|
|
43059
|
+
)) {
|
|
43060
|
+
if (body[schemaKey] !== void 0) continue;
|
|
43061
|
+
if (!childMember.required) continue;
|
|
43062
|
+
if (childMember.kind === "class" && childMember.partial === true) continue;
|
|
43063
|
+
const initializer = context.declaredInitializers.get(childMember.id);
|
|
43064
|
+
if (initializer === void 0) continue;
|
|
43065
|
+
body[schemaKey] = lowerSeedChild(
|
|
43066
|
+
context,
|
|
43067
|
+
recursivePartialMember(member, childMember),
|
|
43068
|
+
parseCachedInitializer(context.parsedInitializers, initializer),
|
|
43069
|
+
source,
|
|
43070
|
+
`${path}.${schemaKey}`,
|
|
43071
|
+
rows,
|
|
43072
|
+
localizedTexts,
|
|
43073
|
+
void 0,
|
|
43074
|
+
environment
|
|
43075
|
+
);
|
|
43076
|
+
}
|
|
43077
|
+
}
|
|
43078
|
+
function storedSchemaEntries(context, schemaClass2) {
|
|
43079
|
+
const entries = /* @__PURE__ */ new Map();
|
|
43080
|
+
const visited = /* @__PURE__ */ new Set();
|
|
43081
|
+
let current = schemaClass2;
|
|
43082
|
+
while (current !== void 0 && !visited.has(current.id)) {
|
|
43083
|
+
visited.add(current.id);
|
|
43084
|
+
for (const [schemaKey, memberId] of Object.entries(current.schema)) {
|
|
43085
|
+
if (entries.has(schemaKey)) continue;
|
|
43086
|
+
const child = context.members.get(memberId);
|
|
43087
|
+
if (child === void 0) continue;
|
|
43088
|
+
if (!ownsValueRow(child)) continue;
|
|
43089
|
+
entries.set(schemaKey, child);
|
|
43090
|
+
}
|
|
43091
|
+
current = current.extendsClassId === null ? void 0 : context.classes.get(current.extendsClassId);
|
|
43092
|
+
}
|
|
43093
|
+
return [...entries];
|
|
43094
|
+
}
|
|
43095
|
+
function ownsValueRow(member) {
|
|
43096
|
+
if (member.isReadOnly) return false;
|
|
43097
|
+
return member.kind !== "computed" && member.kind !== "function" && member.kind !== "scriptFunction";
|
|
43098
|
+
}
|
|
42987
43099
|
function lowerSeedChild(context, member, expression, source, path, rows, localizedTexts, containerId, environment) {
|
|
42988
43100
|
const symbolId = sourceValueSymbol(context, expression);
|
|
42989
43101
|
if (symbolId !== null) return symbolId;
|
|
@@ -44351,7 +44463,7 @@ function projectMainLocaleFromState(state) {
|
|
|
44351
44463
|
}
|
|
44352
44464
|
function emitValue(context, member, valueId, options) {
|
|
44353
44465
|
const externalSymbol = context.symbolsByValueId.get(valueId);
|
|
44354
|
-
if (!options.
|
|
44466
|
+
if (!options.definitionSite && externalSymbol !== void 0) {
|
|
44355
44467
|
return externalSymbol;
|
|
44356
44468
|
}
|
|
44357
44469
|
if (options.visited.has(valueId)) {
|
|
@@ -44375,7 +44487,7 @@ function emitValue(context, member, valueId, options) {
|
|
|
44375
44487
|
options.targetTyped ?? false,
|
|
44376
44488
|
options.environment
|
|
44377
44489
|
);
|
|
44378
|
-
const prefix = options.
|
|
44490
|
+
const prefix = options.writeIdentity ? `@id(${quote4(valueId)})
|
|
44379
44491
|
` : "";
|
|
44380
44492
|
return `${prefix}${expression}`;
|
|
44381
44493
|
}
|
|
@@ -44459,7 +44571,8 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
|
|
|
44459
44571
|
fields.push(
|
|
44460
44572
|
`${key} = ${emitValue(context, emittedChildMember, childId, {
|
|
44461
44573
|
environment,
|
|
44462
|
-
|
|
44574
|
+
definitionSite: !context.symbolsByValueId.has(childId),
|
|
44575
|
+
writeIdentity: !context.symbolsByValueId.has(childId) && context.referencedValueIds.has(childId),
|
|
44463
44576
|
visited
|
|
44464
44577
|
})}`
|
|
44465
44578
|
);
|
|
@@ -44767,7 +44880,8 @@ ${ids.map(
|
|
|
44767
44880
|
(id2) => indentNeoSourceNonEmptyLines(
|
|
44768
44881
|
emitValue(context, entryMember, id2, {
|
|
44769
44882
|
environment,
|
|
44770
|
-
|
|
44883
|
+
definitionSite: context.symbolsByValueId.get(id2) === void 0,
|
|
44884
|
+
writeIdentity: context.symbolsByValueId.get(id2) === void 0,
|
|
44771
44885
|
visited
|
|
44772
44886
|
}),
|
|
44773
44887
|
2
|
|
@@ -44793,7 +44907,8 @@ ${entries.flatMap(
|
|
|
44793
44907
|
indentNeoSourceNonEmptyLines(
|
|
44794
44908
|
`${quote4(key)}: ${emitValue(context, entryMember, id2, {
|
|
44795
44909
|
environment,
|
|
44796
|
-
|
|
44910
|
+
definitionSite: !context.symbolsByValueId.has(id2),
|
|
44911
|
+
writeIdentity: !context.symbolsByValueId.has(id2) && context.referencedValueIds.has(id2),
|
|
44797
44912
|
visited
|
|
44798
44913
|
})}`,
|
|
44799
44914
|
2
|
|
@@ -45010,6 +45125,7 @@ var init_value_sources = __esm({
|
|
|
45010
45125
|
init_lower_members();
|
|
45011
45126
|
init_source_format();
|
|
45012
45127
|
init_world_system_classes();
|
|
45128
|
+
init_member_value_id();
|
|
45013
45129
|
INFERRED_GENERIC_CLASS_PREFIX = "__inferred_class__:";
|
|
45014
45130
|
MEMBER_KIND_DICTIONARY = 5;
|
|
45015
45131
|
MEMBER_KIND_LIST = 6;
|
|
@@ -45139,7 +45255,8 @@ function validateProjectRootEnvelopeV4(state, analysis) {
|
|
|
45139
45255
|
const expression = parseExpression(slot.initializer);
|
|
45140
45256
|
const annotation2 = expression.kind === "annotated" ? expression.annotations.find((entry) => entry.name === "id") : void 0;
|
|
45141
45257
|
const authoredValueId = annotation2?.args[0];
|
|
45142
|
-
if (authoredValueId
|
|
45258
|
+
if (authoredValueId === void 0) return;
|
|
45259
|
+
if (authoredValueId.kind !== "litString" || authoredValueId.value !== memberData.valueId) {
|
|
45143
45260
|
throw new Error(
|
|
45144
45261
|
`Root value root.${expected.name} must retain stable value id ${memberData.valueId}.`
|
|
45145
45262
|
);
|
|
@@ -66474,6 +66591,13 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
|
|
|
66474
66591
|
const assign = (pendingId2) => {
|
|
66475
66592
|
const existing = assigned.get(pendingId2);
|
|
66476
66593
|
if (existing !== void 0) return existing;
|
|
66594
|
+
const memberLocator = pendingMemberValueMemberId(pendingId2);
|
|
66595
|
+
if (memberLocator !== null) {
|
|
66596
|
+
const memberId = isPendingId(memberLocator) ? assign(memberLocator) : memberLocator;
|
|
66597
|
+
const derived = derivedMemberValueId(memberId);
|
|
66598
|
+
assigned.set(pendingId2, derived);
|
|
66599
|
+
return derived;
|
|
66600
|
+
}
|
|
66477
66601
|
const fresh = randomUUID5();
|
|
66478
66602
|
assigned.set(pendingId2, fresh);
|
|
66479
66603
|
return fresh;
|
|
@@ -66668,10 +66792,6 @@ function readProjectVersionTransactionStatus(value, transactionId) {
|
|
|
66668
66792
|
value.errorMessage,
|
|
66669
66793
|
`Project transaction "${transactionId}" errorMessage`
|
|
66670
66794
|
);
|
|
66671
|
-
const resultCursor = readNullableString(
|
|
66672
|
-
value.resultCursor,
|
|
66673
|
-
`Project transaction "${transactionId}" resultCursor`
|
|
66674
|
-
);
|
|
66675
66795
|
return {
|
|
66676
66796
|
transactionId,
|
|
66677
66797
|
commitStatus: value.commitStatus,
|
|
@@ -66692,8 +66812,7 @@ function readProjectVersionTransactionStatus(value, transactionId) {
|
|
|
66692
66812
|
`Project transaction "${transactionId}" appliedChunkCount`
|
|
66693
66813
|
),
|
|
66694
66814
|
errorCode,
|
|
66695
|
-
errorMessage: errorMessage3
|
|
66696
|
-
resultCursor
|
|
66815
|
+
errorMessage: errorMessage3
|
|
66697
66816
|
};
|
|
66698
66817
|
}
|
|
66699
66818
|
function readProjectVersionTransactionResultPage(value, transactionId) {
|
|
@@ -66901,7 +67020,7 @@ async function downloadProjectVersionTransactionResult(args) {
|
|
|
66901
67020
|
const assignments = {};
|
|
66902
67021
|
const changedRecords = [];
|
|
66903
67022
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
66904
|
-
let cursor =
|
|
67023
|
+
let cursor = "";
|
|
66905
67024
|
for (; ; ) {
|
|
66906
67025
|
if (seenCursors.has(cursor)) {
|
|
66907
67026
|
throw new Error(
|
|
@@ -68496,6 +68615,7 @@ var init_push = __esm({
|
|
|
68496
68615
|
init_project_documents();
|
|
68497
68616
|
init_workspace_status();
|
|
68498
68617
|
init_lower_support();
|
|
68618
|
+
init_member_value_id();
|
|
68499
68619
|
init_source_diagnostics();
|
|
68500
68620
|
init_projection();
|
|
68501
68621
|
init_project_file_push();
|