@neocompose/cli 0.48.2 → 0.48.3
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,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.48.3] - 2026-09-10
|
|
4
|
+
|
|
5
|
+
- Show inherited generic binding defaults in implicit constructions, so sparse
|
|
6
|
+
instances expose their effective values and no longer warn about unsettled
|
|
7
|
+
required members. Matching defaults remain virtual through pull/status and
|
|
8
|
+
edits create ordinary sparse overrides. Recorded constructors keep their
|
|
9
|
+
own settlement behavior.
|
|
10
|
+
- Preserve hidden collection argument defaults and ordering when lowering
|
|
11
|
+
unchanged generic types.
|
|
12
|
+
|
|
3
13
|
## [0.48.2] - 2026-09-10
|
|
4
14
|
|
|
5
15
|
- Emit class member defaults with contextual `new()` when they construct the declared type, while keeping an explicit concrete type for subclass defaults.
|
package/dist/neo.mjs
CHANGED
|
@@ -64603,6 +64603,22 @@ function manifestTypeForMember(context, member) {
|
|
|
64603
64603
|
}
|
|
64604
64604
|
return primitive3;
|
|
64605
64605
|
}
|
|
64606
|
+
if (member.kind === "list" || member.kind === "dictionary") {
|
|
64607
|
+
const entry = context.baseMembers.get(member.entryMemberId);
|
|
64608
|
+
if (entry === void 0)
|
|
64609
|
+
throw new Error(
|
|
64610
|
+
`Collection ${member.name} has no entry member ${member.entryMemberId}.`
|
|
64611
|
+
);
|
|
64612
|
+
const entryType = manifestTypeForMember(context, entry);
|
|
64613
|
+
if (member.kind === "list")
|
|
64614
|
+
return { name: "List", nullable: nullable2, arguments: [entryType] };
|
|
64615
|
+
const keyType = {
|
|
64616
|
+
name: member.key.kind === "string" ? "string" : context.baseEnums.get(member.key.enumId)?.name ?? "object",
|
|
64617
|
+
nullable: false,
|
|
64618
|
+
arguments: []
|
|
64619
|
+
};
|
|
64620
|
+
return { name: "Dictionary", nullable: nullable2, arguments: [keyType, entryType] };
|
|
64621
|
+
}
|
|
64606
64622
|
if (member.kind === "class") {
|
|
64607
64623
|
const schemaClass2 = context.baseClasses.get(member.classId);
|
|
64608
64624
|
const classType = {
|
|
@@ -64848,6 +64864,16 @@ function lowerGenericArgument(context, ownerClass, type, memberId, genericParamI
|
|
|
64848
64864
|
const base = context.baseMembers.get(memberId);
|
|
64849
64865
|
if (base && JSON.stringify(manifestTypeForMember(context, base)) === JSON.stringify(type)) {
|
|
64850
64866
|
context.loweredMembers.set(memberId, { ...base, owner });
|
|
64867
|
+
if (base.kind === "list" || base.kind === "dictionary") {
|
|
64868
|
+
lowerCollectionEntry(
|
|
64869
|
+
context,
|
|
64870
|
+
ownerClass,
|
|
64871
|
+
requiredTypeArgument(type, base.kind === "list" ? 0 : 1),
|
|
64872
|
+
base.entryMemberId,
|
|
64873
|
+
memberId,
|
|
64874
|
+
memberId
|
|
64875
|
+
);
|
|
64876
|
+
}
|
|
64851
64877
|
return;
|
|
64852
64878
|
}
|
|
64853
64879
|
const declaration = {
|
|
@@ -113263,6 +113289,7 @@ function buildValueEmitContext(records2, manifest) {
|
|
|
113263
113289
|
},
|
|
113264
113290
|
members,
|
|
113265
113291
|
classes,
|
|
113292
|
+
implicitGenericMembersByClassId: /* @__PURE__ */ new Map(),
|
|
113266
113293
|
manifestMembers,
|
|
113267
113294
|
manifestClasses: new Map(
|
|
113268
113295
|
manifest.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
|
|
@@ -116497,18 +116524,32 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
|
|
|
116497
116524
|
`Class value ${String(base.id)}.${assignment.name} cannot place existing value ${symbolId2} into a new structural slot. Create the nested value inline so the atomic construction transaction can own it.`
|
|
116498
116525
|
);
|
|
116499
116526
|
}
|
|
116500
|
-
|
|
116527
|
+
const rows = /* @__PURE__ */ new Map();
|
|
116528
|
+
const localizedTexts = /* @__PURE__ */ new Map();
|
|
116529
|
+
const seededId = lowerSeedChild(
|
|
116501
116530
|
context,
|
|
116502
116531
|
recursivePartialMember(member, childMember),
|
|
116503
116532
|
assignment.value,
|
|
116504
116533
|
source,
|
|
116505
116534
|
`${String(base.id)}.${assignment.name}`,
|
|
116506
|
-
|
|
116507
|
-
|
|
116535
|
+
rows,
|
|
116536
|
+
localizedTexts,
|
|
116508
116537
|
void 0,
|
|
116509
116538
|
environment,
|
|
116510
116539
|
assignmentSlices.get(assignment.name)
|
|
116511
116540
|
);
|
|
116541
|
+
if (!partial && freshChildReplaysDeclaredDefault({
|
|
116542
|
+
context,
|
|
116543
|
+
childMember,
|
|
116544
|
+
childId: seededId,
|
|
116545
|
+
rows,
|
|
116546
|
+
localizedTexts,
|
|
116547
|
+
environment
|
|
116548
|
+
})) {
|
|
116549
|
+
deleteSeedRow(context, rows, seededId);
|
|
116550
|
+
continue;
|
|
116551
|
+
}
|
|
116552
|
+
body[assignment.name] = seededId;
|
|
116512
116553
|
continue;
|
|
116513
116554
|
}
|
|
116514
116555
|
const symbolId = sourceValueSymbol(context, assignment.value);
|
|
@@ -118309,23 +118350,33 @@ function freshChildReplaysDeclaredDefault(args) {
|
|
|
118309
118350
|
if (child.instanceVariantId != null) return false;
|
|
118310
118351
|
if (child.instanceVariantRowValueId != null) return false;
|
|
118311
118352
|
if (context.collectionBindingMemberIds.has(childMember.id)) return false;
|
|
118312
|
-
const defaultValue = childMember.defaultValue;
|
|
118313
|
-
if (defaultValue === null || defaultValue === void 0) return false;
|
|
118314
|
-
if (!("value" in defaultValue)) return false;
|
|
118315
118353
|
const resolved = resolveGenericSchemaMember(
|
|
118316
118354
|
context,
|
|
118317
118355
|
childMember,
|
|
118318
118356
|
environment
|
|
118319
118357
|
);
|
|
118358
|
+
let defaultValue = null;
|
|
118359
|
+
if (resolved.defaultValue && "value" in resolved.defaultValue) {
|
|
118360
|
+
defaultValue = resolved.defaultValue;
|
|
118361
|
+
} else if (resolved.defaultValue && "serverValueId" in resolved.defaultValue) {
|
|
118362
|
+
const storedMember = context.state[`member:${resolved.id}`]?.data;
|
|
118363
|
+
const storedDefault = isObjectRecord2(storedMember) ? storedMember.defaultValue : null;
|
|
118364
|
+
if (isObjectRecord2(storedDefault) && "value" in storedDefault) {
|
|
118365
|
+
defaultValue = {
|
|
118366
|
+
value: storedDefault.value,
|
|
118367
|
+
classId: storedDefault.classId
|
|
118368
|
+
};
|
|
118369
|
+
}
|
|
118370
|
+
}
|
|
118371
|
+
if (defaultValue === null) return false;
|
|
118320
118372
|
if (resolved.kind === "lookup" || resolved.kind === "dialogueLookup") {
|
|
118321
118373
|
return false;
|
|
118322
118374
|
}
|
|
118323
118375
|
if (resolved.kind === "class") {
|
|
118324
|
-
return freshConstructionReplaysDeclaredDefault(
|
|
118325
|
-
|
|
118326
|
-
|
|
118327
|
-
|
|
118328
|
-
);
|
|
118376
|
+
return freshConstructionReplaysDeclaredDefault(resolved, child, {
|
|
118377
|
+
value: defaultValue.value,
|
|
118378
|
+
classId: defaultValue.classId
|
|
118379
|
+
});
|
|
118329
118380
|
}
|
|
118330
118381
|
if (resolved.kind === "list") {
|
|
118331
118382
|
return Array.isArray(child.value) && child.value.length === 0 && !context.pendingContainerChildCounts.has(childId) && Array.isArray(defaultValue.value) && defaultValue.value.length === 0 && child.classId == null && (child.constructorArgs == null || Object.keys(child.constructorArgs).length === 0) && child.instanceConstructorId == null;
|
|
@@ -118903,6 +118954,41 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
|
|
|
118903
118954
|
);
|
|
118904
118955
|
overrideKeys.add(key);
|
|
118905
118956
|
}
|
|
118957
|
+
if (!partial && value.instanceVariantId == null && value.instanceVariantRowValueId == null) {
|
|
118958
|
+
for (const [key, genericMember] of implicitGenericMembers(
|
|
118959
|
+
context,
|
|
118960
|
+
classId
|
|
118961
|
+
)) {
|
|
118962
|
+
if (key in value.value) continue;
|
|
118963
|
+
const parameterId = stringField3(genericMember, "genericParamId");
|
|
118964
|
+
if (!environment.has(parameterId)) continue;
|
|
118965
|
+
const binding = resolveGenericValueMember(
|
|
118966
|
+
context,
|
|
118967
|
+
genericMember,
|
|
118968
|
+
environment
|
|
118969
|
+
);
|
|
118970
|
+
const kind = numberField(binding, "kind");
|
|
118971
|
+
if (!IMPLICIT_GENERIC_DEFAULT_KINDS.has(kind)) continue;
|
|
118972
|
+
if (kind === 3 /* String */ && isLocalizedStringMember(binding))
|
|
118973
|
+
continue;
|
|
118974
|
+
if (binding.payload === 1 /* Partial */) continue;
|
|
118975
|
+
const defaultValue = binding.defaultValue;
|
|
118976
|
+
if (!isObjectRecord2(defaultValue) || !("value" in defaultValue)) continue;
|
|
118977
|
+
const body = defaultValue.value;
|
|
118978
|
+
if (body === null) continue;
|
|
118979
|
+
if (Array.isArray(body) && body.length > 0) continue;
|
|
118980
|
+
if (isObjectRecord2(body) && Object.keys(body).length > 0) continue;
|
|
118981
|
+
const expression = emitValueBody(
|
|
118982
|
+
context,
|
|
118983
|
+
binding,
|
|
118984
|
+
defaultValue,
|
|
118985
|
+
/* @__PURE__ */ new Set(),
|
|
118986
|
+
(defaultValue.classId ?? binding.classId) === binding.classId,
|
|
118987
|
+
environment
|
|
118988
|
+
);
|
|
118989
|
+
fields.push(`${key} = ${expression}`);
|
|
118990
|
+
}
|
|
118991
|
+
}
|
|
118906
118992
|
if (partial) {
|
|
118907
118993
|
return fields.length === 0 ? "new { }" : `new {
|
|
118908
118994
|
${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
|
|
@@ -118921,6 +119007,33 @@ ${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
|
|
|
118921
119007
|
${fields.map((field) => indentNeoSourceNonEmptyLines(field, 2)).join(",\n")}
|
|
118922
119008
|
}`;
|
|
118923
119009
|
}
|
|
119010
|
+
function implicitGenericMembers(context, classId) {
|
|
119011
|
+
const cached = context.implicitGenericMembersByClassId.get(classId);
|
|
119012
|
+
if (cached !== void 0) return cached;
|
|
119013
|
+
const result = /* @__PURE__ */ new Map();
|
|
119014
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
119015
|
+
const seenClasses = /* @__PURE__ */ new Set();
|
|
119016
|
+
let current = context.manifestClasses.get(classId);
|
|
119017
|
+
while (current !== void 0 && !seenClasses.has(current.id)) {
|
|
119018
|
+
seenClasses.add(current.id);
|
|
119019
|
+
if (current.requiredConstructorId || current.constructorIds?.length) {
|
|
119020
|
+
result.clear();
|
|
119021
|
+
context.implicitGenericMembersByClassId.set(classId, result);
|
|
119022
|
+
return result;
|
|
119023
|
+
}
|
|
119024
|
+
for (const [key, memberId] of Object.entries(current.schema)) {
|
|
119025
|
+
if (seenKeys.has(key)) continue;
|
|
119026
|
+
seenKeys.add(key);
|
|
119027
|
+
const member = context.members.get(memberId);
|
|
119028
|
+
if (member?.kind === 21 /* Generic */ && !isObjectRecord2(member.init)) {
|
|
119029
|
+
result.set(key, member);
|
|
119030
|
+
}
|
|
119031
|
+
}
|
|
119032
|
+
current = current.extendsClassId === null ? void 0 : context.manifestClasses.get(current.extendsClassId);
|
|
119033
|
+
}
|
|
119034
|
+
context.implicitGenericMembersByClassId.set(classId, result);
|
|
119035
|
+
return result;
|
|
119036
|
+
}
|
|
118924
119037
|
function emitsAsMemberDefaultDerivedAbsence(context, member, valueId) {
|
|
118925
119038
|
const value = context.values.get(valueId);
|
|
118926
119039
|
if (value === void 0) return false;
|
|
@@ -120456,7 +120569,7 @@ function memberDefaultBody(member) {
|
|
|
120456
120569
|
if (!("value" in defaultValue)) return null;
|
|
120457
120570
|
return defaultValue.value;
|
|
120458
120571
|
}
|
|
120459
|
-
var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, MEMBER_KIND_CLASS2, LEADING_AUTHORED_ROW_ID, CANONICAL_CONSTRUCTOR_INLINE_WIDTH;
|
|
120572
|
+
var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, MEMBER_KIND_CLASS2, IMPLICIT_GENERIC_DEFAULT_KINDS, LEADING_AUTHORED_ROW_ID, CANONICAL_CONSTRUCTOR_INLINE_WIDTH;
|
|
120460
120573
|
var init_value_sources = __esm({
|
|
120461
120574
|
"src/project-source/value-sources.ts"() {
|
|
120462
120575
|
"use strict";
|
|
@@ -120496,6 +120609,16 @@ var init_value_sources = __esm({
|
|
|
120496
120609
|
MEMBER_KIND_DICTIONARY2 = 5;
|
|
120497
120610
|
MEMBER_KIND_LIST2 = 6;
|
|
120498
120611
|
MEMBER_KIND_CLASS2 = 7;
|
|
120612
|
+
IMPLICIT_GENERIC_DEFAULT_KINDS = /* @__PURE__ */ new Set([
|
|
120613
|
+
1 /* Bool */,
|
|
120614
|
+
2 /* Int */,
|
|
120615
|
+
4 /* Float */,
|
|
120616
|
+
20 /* Decimal */,
|
|
120617
|
+
3 /* String */,
|
|
120618
|
+
7 /* Class */,
|
|
120619
|
+
6 /* List */,
|
|
120620
|
+
5 /* Dictionary */
|
|
120621
|
+
]);
|
|
120499
120622
|
LEADING_AUTHORED_ROW_ID = /^@id\(\s*"((?:[^"\\]|\\.)*)"\s*\)/;
|
|
120500
120623
|
CANONICAL_CONSTRUCTOR_INLINE_WIDTH = 88;
|
|
120501
120624
|
}
|
|
@@ -131454,7 +131577,7 @@ var init_registry2 = __esm({
|
|
|
131454
131577
|
"schema-contract/registry.mjs"() {
|
|
131455
131578
|
"use strict";
|
|
131456
131579
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
131457
|
-
cliVersion: "0.48.
|
|
131580
|
+
cliVersion: "0.48.3",
|
|
131458
131581
|
projectFileUploadBatchSize: 32,
|
|
131459
131582
|
documentRecords: {
|
|
131460
131583
|
member: {
|
|
@@ -138504,7 +138627,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
138504
138627
|
async function main() {
|
|
138505
138628
|
const args = parseArgs(process.argv.slice(2));
|
|
138506
138629
|
if (args.command === "--version") {
|
|
138507
|
-
console.log("0.48.
|
|
138630
|
+
console.log("0.48.3");
|
|
138508
138631
|
return;
|
|
138509
138632
|
}
|
|
138510
138633
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -88,7 +88,7 @@ wrappers.
|
|
|
88
88
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
89
89
|
|
|
90
90
|
```html
|
|
91
|
-
<!-- reviewed-through-cli: 0.48.
|
|
91
|
+
<!-- reviewed-through-cli: 0.48.3 -->
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -136,6 +136,12 @@ member creates a sparse override with its deterministic projected ID; removing
|
|
|
136
136
|
that member from an existing initializer resets the override and resumes source
|
|
137
137
|
tracking. Require either transition to appear in `neo diff`.
|
|
138
138
|
|
|
139
|
+
A concrete generic argument can carry a default that its type spelling does
|
|
140
|
+
not show. Pull writes nonlocalized scalar and empty aggregate binding defaults at implicit
|
|
141
|
+
construction sites, for example `DefaultData = new()`. Keeping that expression
|
|
142
|
+
unchanged or omitting it retains the virtual default; editing it creates an
|
|
143
|
+
override. A default that selects a subtype keeps the explicit subtype name.
|
|
144
|
+
|
|
139
145
|
Editing an initializer updates sparse override rows in place: projected member
|
|
140
146
|
IDs remain stable, and omitted virtual rows are never emitted as authored seed
|
|
141
147
|
records. Spelling a declared default verbatim in a new initializer lowers to
|