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