@metaobjectsdev/metadata 0.24.0-rc.1 → 0.24.0
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/dist/attr-schema-validate.d.ts.map +1 -1
- package/dist/attr-schema-validate.js +17 -2
- package/dist/attr-schema-validate.js.map +1 -1
- package/dist/core/field/field-constants.d.ts +18 -5
- package/dist/core/field/field-constants.d.ts.map +1 -1
- package/dist/core/field/field-constants.js +21 -5
- package/dist/core/field/field-constants.js.map +1 -1
- package/dist/core/field/field-definition.embedded.d.ts.map +1 -1
- package/dist/core/field/field-definition.embedded.js +8 -3
- package/dist/core/field/field-definition.embedded.js.map +1 -1
- package/dist/core/field/validate-field-mutability.d.ts +22 -0
- package/dist/core/field/validate-field-mutability.d.ts.map +1 -0
- package/dist/core/field/validate-field-mutability.js +208 -0
- package/dist/core/field/validate-field-mutability.js.map +1 -0
- package/dist/core/identity/identity-constants.d.ts +12 -0
- package/dist/core/identity/identity-constants.d.ts.map +1 -1
- package/dist/core/identity/identity-constants.js +15 -0
- package/dist/core/identity/identity-constants.js.map +1 -1
- package/dist/core/object/object-definition.embedded.js +2 -2
- package/dist/core/object/object-definition.embedded.js.map +1 -1
- package/dist/core/requirement/meta-requirement.d.ts +1 -2
- package/dist/core/requirement/meta-requirement.d.ts.map +1 -1
- package/dist/core/requirement/meta-requirement.js +2 -6
- package/dist/core/requirement/meta-requirement.js.map +1 -1
- package/dist/core/requirement/requirement-constants.d.ts +3 -8
- package/dist/core/requirement/requirement-constants.d.ts.map +1 -1
- package/dist/core/requirement/requirement-constants.js +2 -9
- package/dist/core/requirement/requirement-constants.js.map +1 -1
- package/dist/core/requirement/requirement-definition.embedded.d.ts.map +1 -1
- package/dist/core/requirement/requirement-definition.embedded.js +8 -46
- package/dist/core/requirement/requirement-definition.embedded.js.map +1 -1
- package/dist/core/requirement/resolve-claim.d.ts +37 -0
- package/dist/core/requirement/resolve-claim.d.ts.map +1 -0
- package/dist/core/requirement/resolve-claim.js +83 -0
- package/dist/core/requirement/resolve-claim.js.map +1 -0
- package/dist/core-types.d.ts.map +1 -1
- package/dist/core-types.js +10 -10
- package/dist/core-types.js.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +16 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/library/library-sources.d.ts +11 -0
- package/dist/library/library-sources.d.ts.map +1 -1
- package/dist/library/library-sources.js +13 -0
- package/dist/library/library-sources.js.map +1 -1
- package/dist/loader/meta-data-loader.d.ts.map +1 -1
- package/dist/loader/meta-data-loader.js +10 -9
- package/dist/loader/meta-data-loader.js.map +1 -1
- package/dist/loader/validation-passes.js +2 -2
- package/dist/loader/validation-passes.js.map +1 -1
- package/dist/naming-refs.d.ts.map +1 -1
- package/dist/naming-refs.js +2 -3
- package/dist/naming-refs.js.map +1 -1
- package/dist/parser-core.d.ts.map +1 -1
- package/dist/parser-core.js +22 -5
- package/dist/parser-core.js.map +1 -1
- package/dist/persistence/origin/meta-origin.d.ts +0 -10
- package/dist/persistence/origin/meta-origin.d.ts.map +1 -1
- package/dist/persistence/origin/meta-origin.js +1 -15
- package/dist/persistence/origin/meta-origin.js.map +1 -1
- package/dist/persistence/origin/origin-constants.d.ts +2 -4
- package/dist/persistence/origin/origin-constants.d.ts.map +1 -1
- package/dist/persistence/origin/origin-constants.js +9 -7
- package/dist/persistence/origin/origin-constants.js.map +1 -1
- package/dist/persistence/origin/origin-definition.embedded.d.ts.map +1 -1
- package/dist/persistence/origin/origin-definition.embedded.js +0 -16
- package/dist/persistence/origin/origin-definition.embedded.js.map +1 -1
- package/dist/registry-manifest.d.ts +9 -4
- package/dist/registry-manifest.d.ts.map +1 -1
- package/dist/registry-manifest.js +9 -4
- package/dist/registry-manifest.js.map +1 -1
- package/dist/retired-vocabulary.d.ts +92 -0
- package/dist/retired-vocabulary.d.ts.map +1 -0
- package/dist/retired-vocabulary.js +204 -0
- package/dist/retired-vocabulary.js.map +1 -0
- package/dist/super-resolve.d.ts +33 -0
- package/dist/super-resolve.d.ts.map +1 -1
- package/dist/super-resolve.js +56 -1
- package/dist/super-resolve.js.map +1 -1
- package/dist/template/prompt-definition.embedded.js +1 -1
- package/dist/template/prompt-definition.embedded.js.map +1 -1
- package/dist/template/template-constants.d.ts +6 -0
- package/dist/template/template-constants.d.ts.map +1 -1
- package/dist/template/template-constants.js +24 -1
- package/dist/template/template-constants.js.map +1 -1
- package/dist/template/template-definition.embedded.d.ts.map +1 -1
- package/dist/template/template-definition.embedded.js +34 -21
- package/dist/template/template-definition.embedded.js.map +1 -1
- package/dist/vocabulary-rewrite.d.ts +33 -0
- package/dist/vocabulary-rewrite.d.ts.map +1 -0
- package/dist/vocabulary-rewrite.js +310 -0
- package/dist/vocabulary-rewrite.js.map +1 -0
- package/package.json +6 -1
- package/src/attr-schema-validate.ts +17 -2
- package/src/core/field/field-constants.ts +24 -5
- package/src/core/field/field-definition.embedded.ts +8 -3
- package/src/core/field/validate-field-mutability.ts +259 -0
- package/src/core/identity/identity-constants.ts +16 -0
- package/src/core/object/object-definition.embedded.ts +2 -2
- package/src/core/requirement/meta-requirement.ts +1 -7
- package/src/core/requirement/requirement-constants.ts +2 -9
- package/src/core/requirement/requirement-definition.embedded.ts +8 -46
- package/src/core/requirement/resolve-claim.ts +98 -0
- package/src/core-types.ts +9 -10
- package/src/errors.ts +16 -2
- package/src/index.ts +29 -1
- package/src/library/library-sources.ts +14 -0
- package/src/loader/meta-data-loader.ts +10 -9
- package/src/loader/validation-passes.ts +3 -3
- package/src/naming-refs.ts +1 -3
- package/src/parser-core.ts +27 -5
- package/src/persistence/origin/meta-origin.ts +0 -16
- package/src/persistence/origin/origin-constants.ts +9 -8
- package/src/persistence/origin/origin-definition.embedded.ts +0 -16
- package/src/registry-manifest.ts +9 -4
- package/src/retired-vocabulary.ts +280 -0
- package/src/super-resolve.ts +59 -1
- package/src/template/prompt-definition.embedded.ts +1 -1
- package/src/template/template-constants.ts +27 -1
- package/src/template/template-definition.embedded.ts +34 -21
- package/src/vocabulary-rewrite.ts +346 -0
- package/dist/core/field/validate-field-readonly.d.ts +0 -9
- package/dist/core/field/validate-field-readonly.d.ts.map +0 -1
- package/dist/core/field/validate-field-readonly.js +0 -128
- package/dist/core/field/validate-field-readonly.js.map +0 -1
- package/src/core/field/validate-field-readonly.ts +0 -154
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// server/typescript/packages/metadata/src/vocabulary-rewrite.ts
|
|
2
|
+
//
|
|
3
|
+
// The raw-document rewriter behind `meta upgrade`.
|
|
4
|
+
//
|
|
5
|
+
// WHY IT CANNOT USE THE LOADER — the constraint that shapes everything here. Once an
|
|
6
|
+
// attribute is deregistered, metadata carrying it FAILS THE LOAD; that is the point of a
|
|
7
|
+
// retirement. So load → transform → canonical-serialize is impossible: the input does not
|
|
8
|
+
// load, and the canonical serializer needs a loaded model. This operates on RAW TEXT.
|
|
9
|
+
//
|
|
10
|
+
// That is also what makes the upgrade path exist at all. An adopter installs the new CLI and
|
|
11
|
+
// runs this against metadata the new CLI REFUSES. A fixer that needed a successful load
|
|
12
|
+
// would be a chicken-and-egg with no exit.
|
|
13
|
+
//
|
|
14
|
+
// SURGICAL, NOT PARSE-AND-REPRINT. Adopters author JSONC with comments and meaningful key
|
|
15
|
+
// order — `meta gen`'s output order, review conventions, "do not reorder" notes. A
|
|
16
|
+
// round-trip through JSON.parse/stringify destroys all of it while reporting success. So
|
|
17
|
+
// every edit here is a span replacement on the original text, and any region we did not
|
|
18
|
+
// deliberately change comes back byte-identical.
|
|
19
|
+
//
|
|
20
|
+
// IT SCOPES EVERY OCCURRENCE, NOT EVERY FILE. Retirements are type-scoped — `@unique` is
|
|
21
|
+
// retired on `identity.secondary` and perfectly live on a field — so the governing type is
|
|
22
|
+
// a property of WHERE the attribute sits, not of the document it sits in. A file-level
|
|
23
|
+
// scope was the original shape and it was wrong in both directions: a caller that ran one
|
|
24
|
+
// pass per type key present in the file let the `identity.secondary` scope reach a
|
|
25
|
+
// `field.string`'s `@unique` (branding live vocabulary retired, and with a `dropAttr` entry
|
|
26
|
+
// DELETING it), and reported every wildcard-scoped refusal once per subtype key in the file.
|
|
27
|
+
// `scopeRanges` below recovers the enclosing `"<type>.<subType>"` for each occurrence, so
|
|
28
|
+
// one pass over the document answers both correctly.
|
|
29
|
+
//
|
|
30
|
+
// CANONICAL JSON ONLY. YAML authoring is real (ADR-0006) but is not rewritable here: a
|
|
31
|
+
// correct YAML editor needs the `yaml` package's CST, and this module is reachable from
|
|
32
|
+
// `src/index.ts`, which the browser-safety test forbids from importing it. A hand-rolled
|
|
33
|
+
// YAML mode was tried and shipped a file-corrupting bug — a multi-item block sequence lost
|
|
34
|
+
// every item but the first, because the value scanner stops at a newline — while the
|
|
35
|
+
// dominant in-repo authoring style (flow mappings, `{ name: x, readOnly: true }`) was not
|
|
36
|
+
// matched at all, so the rename silently did nothing. `meta upgrade` refuses YAML by name
|
|
37
|
+
// instead; a refusal an adopter can act on beats a success they cannot trust.
|
|
38
|
+
//
|
|
39
|
+
// IT REFUSES WHAT IT CANNOT KNOW. A retirement with no `rewrite` (`@status: abandoned`) is
|
|
40
|
+
// reported, never guessed at. Deleting the node, retyping it, and fixing the residue it
|
|
41
|
+
// describes are all defensible, and a wrong guess emits metadata that LOADS and means
|
|
42
|
+
// something different — strictly worse than leaving it alone, because the adopter would
|
|
43
|
+
// believe the migration finished.
|
|
44
|
+
import { RETIRED_VOCABULARY, note, scopeMatches, } from "./retired-vocabulary.js";
|
|
45
|
+
/** `0.24.0` → `[0,24,0]`, for an ordered comparison rather than a string one. */
|
|
46
|
+
function parts(v) {
|
|
47
|
+
return v.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
48
|
+
}
|
|
49
|
+
function atOrBefore(a, b) {
|
|
50
|
+
const [x, y] = [parts(a), parts(b)];
|
|
51
|
+
for (let i = 0; i < Math.max(x.length, y.length); i++) {
|
|
52
|
+
const d = (x[i] ?? 0) - (y[i] ?? 0);
|
|
53
|
+
if (d !== 0)
|
|
54
|
+
return d < 0;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/** 1-indexed line of `index` in `text`. */
|
|
59
|
+
function lineAt(text, index) {
|
|
60
|
+
let line = 1;
|
|
61
|
+
for (let i = 0; i < index && i < text.length; i++)
|
|
62
|
+
if (text[i] === "\n")
|
|
63
|
+
line++;
|
|
64
|
+
return line;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Offset just past the bracket closing the one at `open`, or undefined if unbalanced.
|
|
68
|
+
* String-aware, so a brace inside a JSON string literal cannot unbalance the scan.
|
|
69
|
+
*/
|
|
70
|
+
function closingBracket(text, open) {
|
|
71
|
+
const close = text[open] === "[" ? "]" : "}";
|
|
72
|
+
const openCh = text[open];
|
|
73
|
+
let depth = 0;
|
|
74
|
+
let inStr = false;
|
|
75
|
+
for (let j = open; j < text.length; j++) {
|
|
76
|
+
const c = text[j];
|
|
77
|
+
if (inStr) {
|
|
78
|
+
if (c === "\\")
|
|
79
|
+
j++;
|
|
80
|
+
else if (c === '"')
|
|
81
|
+
inStr = false;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (c === '"')
|
|
85
|
+
inStr = true;
|
|
86
|
+
else if (c === openCh)
|
|
87
|
+
depth++;
|
|
88
|
+
else if (c === close) {
|
|
89
|
+
depth--;
|
|
90
|
+
if (depth === 0)
|
|
91
|
+
return j + 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Every node body in the document, in source order.
|
|
98
|
+
*
|
|
99
|
+
* A canonical-JSON node is `{ "<type>.<subType>": { …body… } }`, so an attribute belongs to
|
|
100
|
+
* the INNERMOST body containing it — which is what makes per-occurrence scoping possible
|
|
101
|
+
* without a parser we deliberately do not have.
|
|
102
|
+
*/
|
|
103
|
+
function scopeRanges(source) {
|
|
104
|
+
const ranges = [];
|
|
105
|
+
const re = /"([a-z][A-Za-z0-9]*)\.([A-Za-z0-9_*]+)"\s*:\s*\{/g;
|
|
106
|
+
let m;
|
|
107
|
+
while ((m = re.exec(source)) !== null) {
|
|
108
|
+
const bodyStart = m.index + m[0].length - 1;
|
|
109
|
+
const bodyEnd = closingBracket(source, bodyStart);
|
|
110
|
+
if (bodyEnd === undefined)
|
|
111
|
+
continue;
|
|
112
|
+
ranges.push({ typeKey: `${m[1]}.${m[2]}`, keyIndex: m.index, bodyStart, bodyEnd });
|
|
113
|
+
}
|
|
114
|
+
return ranges;
|
|
115
|
+
}
|
|
116
|
+
/** The type key governing `offset` — the innermost body containing it. */
|
|
117
|
+
function scopeAt(ranges, offset) {
|
|
118
|
+
let best;
|
|
119
|
+
for (const r of ranges) {
|
|
120
|
+
if (offset <= r.bodyStart || offset >= r.bodyEnd)
|
|
121
|
+
continue;
|
|
122
|
+
// Properly nested ranges: the innermost containing one starts last.
|
|
123
|
+
if (best === undefined || r.bodyStart > best.bodyStart)
|
|
124
|
+
best = r;
|
|
125
|
+
}
|
|
126
|
+
return best?.typeKey;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Matches `"@name"` at a key position, plus the separator that follows, capturing the key
|
|
130
|
+
* separately so a replacement can keep the original spacing.
|
|
131
|
+
*
|
|
132
|
+
* Deliberately NOT a full parser. A parser would have to reproduce the document to emit it,
|
|
133
|
+
* which is the thing this exists to avoid; matching a key occurrence lets every untouched
|
|
134
|
+
* byte survive by construction.
|
|
135
|
+
*/
|
|
136
|
+
function keyPattern(attr) {
|
|
137
|
+
return new RegExp(`("@?${attr}")(\\s*:\\s*)`, "g");
|
|
138
|
+
}
|
|
139
|
+
/** The JSON value token starting at `from` — a scalar, or a bracketed array/object. */
|
|
140
|
+
function valueSpan(text, from) {
|
|
141
|
+
let i = from;
|
|
142
|
+
while (i < text.length && /\s/.test(text[i] ?? ""))
|
|
143
|
+
i++;
|
|
144
|
+
const open = text[i];
|
|
145
|
+
if (open === "[" || open === "{") {
|
|
146
|
+
const end = closingBracket(text, i);
|
|
147
|
+
return end === undefined ? undefined : { start: i, end, raw: text.slice(i, end) };
|
|
148
|
+
}
|
|
149
|
+
// Scalar: to the next comma, closing brace, or newline, whichever comes first.
|
|
150
|
+
let j = i;
|
|
151
|
+
let inStr = false;
|
|
152
|
+
for (; j < text.length; j++) {
|
|
153
|
+
const c = text[j];
|
|
154
|
+
if (inStr) {
|
|
155
|
+
if (c === "\\")
|
|
156
|
+
j++;
|
|
157
|
+
else if (c === '"')
|
|
158
|
+
inStr = false;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (c === '"')
|
|
162
|
+
inStr = true;
|
|
163
|
+
else if (c === "," || c === "}" || c === "\n")
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
return { start: i, end: j, raw: text.slice(i, j).trim() };
|
|
167
|
+
}
|
|
168
|
+
/** Does the raw token equal this literal? Compares JSON-decoded where possible so
|
|
169
|
+
* `"readOnly"` and `readOnly` both match a string literal. */
|
|
170
|
+
function rawEquals(raw, want) {
|
|
171
|
+
try {
|
|
172
|
+
return JSON.parse(raw) === want;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return raw === String(want);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The span to delete so that removing a key leaves loadable JSON.
|
|
180
|
+
*
|
|
181
|
+
* The arithmetic is fiddly and every branch is load-bearing, so it lives here with its
|
|
182
|
+
* steps named rather than inline in the dispatch below.
|
|
183
|
+
*/
|
|
184
|
+
function dropSpan(source, keyStart, valueEnd) {
|
|
185
|
+
// 1. Absorb the value's trailing spaces, then its trailing comma if it has one.
|
|
186
|
+
let end = valueEnd;
|
|
187
|
+
while (end < source.length && /[ \t]/.test(source[end] ?? ""))
|
|
188
|
+
end++;
|
|
189
|
+
const hadTrailingComma = source[end] === ",";
|
|
190
|
+
if (hadTrailingComma)
|
|
191
|
+
end++;
|
|
192
|
+
// 2. Absorb the key's own indentation, so the removal does not leave a ragged line.
|
|
193
|
+
let start = keyStart;
|
|
194
|
+
while (start > 0 && /[ \t]/.test(source[start - 1] ?? ""))
|
|
195
|
+
start--;
|
|
196
|
+
// 3. THE LAST-KEY CASE, found by dogfooding rather than by a unit test: when the retired
|
|
197
|
+
// attr is last in its object there IS no trailing comma — the comma belongs to the
|
|
198
|
+
// PRECEDING key. Dropping without taking it leaves `"...",\n}`, which does not parse.
|
|
199
|
+
// A tool whose whole job is producing loadable metadata cannot emit invalid JSON.
|
|
200
|
+
if (!hadTrailingComma) {
|
|
201
|
+
let back = start;
|
|
202
|
+
while (back > 0 && /\s/.test(source[back - 1] ?? ""))
|
|
203
|
+
back--;
|
|
204
|
+
if (source[back - 1] === ",")
|
|
205
|
+
start = back - 1;
|
|
206
|
+
}
|
|
207
|
+
// 4. If the key owned its whole line, take the line terminator too rather than leaving a
|
|
208
|
+
// blank line. Otherwise the key shares a line with other content, so undo step 2's
|
|
209
|
+
// indentation trim — it would eat the separating space after the preceding key's comma.
|
|
210
|
+
if (source[start - 1] === "\n" && source[end] === "\n")
|
|
211
|
+
end++;
|
|
212
|
+
else if (start > 0 && source[start - 1] !== "\n" && hadTrailingComma)
|
|
213
|
+
start = keyStart;
|
|
214
|
+
return { start, end };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Rewrite retired vocabulary in one raw canonical-JSON metadata document.
|
|
218
|
+
*
|
|
219
|
+
* Pure: no filesystem, no loader, no registry. Returns the new text plus every change and
|
|
220
|
+
* every refusal, so a caller can print a diff and exit non-zero when work remains.
|
|
221
|
+
*/
|
|
222
|
+
export function rewriteDocument(source, opts = {}) {
|
|
223
|
+
const changes = [];
|
|
224
|
+
const refusals = [];
|
|
225
|
+
// Edits are collected as spans against the ORIGINAL text and applied in one pass at the
|
|
226
|
+
// end, right-to-left. Rewriting incrementally would invalidate every later offset.
|
|
227
|
+
const edits = [];
|
|
228
|
+
const inWindow = (e) => opts.maxVersion === undefined || atOrBefore(e.since, opts.maxVersion);
|
|
229
|
+
const ranges = scopeRanges(source);
|
|
230
|
+
// A retired SUBTYPE has no attribute to rewrite — the node itself has to be re-modelled
|
|
231
|
+
// (`origin.collection` becomes `origin.aggregate @agg: collect`), which is a judgment the
|
|
232
|
+
// adopter makes. Reporting it is what keeps `meta upgrade` from exiting 0 on a document
|
|
233
|
+
// that still will not load; it used to be filtered out entirely and was invisible.
|
|
234
|
+
for (const r of ranges) {
|
|
235
|
+
for (const entry of RETIRED_VOCABULARY) {
|
|
236
|
+
if (entry.isSubTypeRetirement !== true || !inWindow(entry))
|
|
237
|
+
continue;
|
|
238
|
+
if (`${entry.type}.${entry.subType}` !== r.typeKey)
|
|
239
|
+
continue;
|
|
240
|
+
refusals.push({ ...note(entry), subject: r.typeKey, line: lineAt(source, r.keyIndex) });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
for (const entry of RETIRED_VOCABULARY.filter((e) => e.attr !== undefined && inWindow(e))) {
|
|
244
|
+
const attr = entry.attr;
|
|
245
|
+
const re = keyPattern(attr);
|
|
246
|
+
let m;
|
|
247
|
+
while ((m = re.exec(source)) !== null) {
|
|
248
|
+
const keyStart = m.index;
|
|
249
|
+
const keyEnd = keyStart + (m[1]?.length ?? 0);
|
|
250
|
+
const afterKey = m.index + m[0].length;
|
|
251
|
+
// Scope is decided HERE, per occurrence, from the enclosing node.
|
|
252
|
+
const scope = scopeAt(ranges, keyStart);
|
|
253
|
+
if (scope === undefined || !scopeMatches(entry, scope))
|
|
254
|
+
continue;
|
|
255
|
+
const line = lineAt(source, keyStart);
|
|
256
|
+
const span = valueSpan(source, afterKey);
|
|
257
|
+
// A VALUE-scoped retirement only fires on the retired values. `@dbColumnType: jsonb`
|
|
258
|
+
// is live vocabulary on the same attribute; touching it would silently change the
|
|
259
|
+
// column type.
|
|
260
|
+
if (entry.attrValues !== undefined) {
|
|
261
|
+
if (!entry.attrValues.some((v) => rawEquals(span?.raw ?? "", v)))
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const refuse = () => {
|
|
265
|
+
refusals.push({
|
|
266
|
+
...note(entry),
|
|
267
|
+
subject: `@${attr}`,
|
|
268
|
+
...(span?.raw !== undefined ? { value: span.raw } : {}),
|
|
269
|
+
line,
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
const drop = () => {
|
|
273
|
+
if (span === undefined)
|
|
274
|
+
return;
|
|
275
|
+
const { start, end } = dropSpan(source, keyStart, span.end);
|
|
276
|
+
edits.push({ start, end, text: "" });
|
|
277
|
+
changes.push({ attr, from: attr, to: "(removed)", line });
|
|
278
|
+
};
|
|
279
|
+
const rw = entry.rewrite;
|
|
280
|
+
if (rw === undefined)
|
|
281
|
+
refuse();
|
|
282
|
+
else if (rw.kind === "renameAttr") {
|
|
283
|
+
edits.push({ start: keyStart, end: keyEnd, text: `"@${rw.to}"` });
|
|
284
|
+
changes.push({ attr, from: attr, to: rw.to, line });
|
|
285
|
+
}
|
|
286
|
+
else if (rw.kind === "dropAttr")
|
|
287
|
+
drop();
|
|
288
|
+
else if (span === undefined)
|
|
289
|
+
continue;
|
|
290
|
+
else if (rawEquals(span.raw, rw.fromValue)) {
|
|
291
|
+
const valText = JSON.stringify(rw.toValue);
|
|
292
|
+
edits.push({ start: keyStart, end: keyEnd, text: `"@${rw.toAttr}"` });
|
|
293
|
+
edits.push({ start: span.start, end: span.end, text: valText });
|
|
294
|
+
changes.push({ attr, from: `${attr}: ${span.raw}`, to: `${rw.toAttr}: ${valText}`, line });
|
|
295
|
+
}
|
|
296
|
+
// Every other value of a retired attribute still has to go somewhere — the entry says
|
|
297
|
+
// which, and the type makes saying it mandatory.
|
|
298
|
+
else if (rw.otherwise === "drop")
|
|
299
|
+
drop();
|
|
300
|
+
else
|
|
301
|
+
refuse();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
edits.sort((a, b) => b.start - a.start);
|
|
305
|
+
let text = source;
|
|
306
|
+
for (const e of edits)
|
|
307
|
+
text = text.slice(0, e.start) + e.text + text.slice(e.end);
|
|
308
|
+
return { text, changes, refusals };
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=vocabulary-rewrite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary-rewrite.js","sourceRoot":"","sources":["../src/vocabulary-rewrite.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/metadata",
|
|
3
|
-
"version": "0.24.0
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Metamodel loader, types, and constants for the MetaObjects standard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
"types": "./dist/core/index.d.ts",
|
|
17
17
|
"default": "./dist/core/index.js"
|
|
18
18
|
},
|
|
19
|
+
"./library": {
|
|
20
|
+
"bun": "./src/library/library-sources.ts",
|
|
21
|
+
"types": "./dist/library/library-sources.d.ts",
|
|
22
|
+
"default": "./dist/library/library-sources.js"
|
|
23
|
+
},
|
|
19
24
|
"./constants": {
|
|
20
25
|
"bun": "./src/constants.ts",
|
|
21
26
|
"types": "./dist/constants.d.ts",
|
|
@@ -47,6 +47,9 @@ import type { AttrSchema, TypeRegistry } from "./registry.js";
|
|
|
47
47
|
import { childRuleMatches } from "./registry.js";
|
|
48
48
|
import { TYPE_FIELD, TYPE_METADATA } from "./shared/base-types.js";
|
|
49
49
|
import { ATTR_SUBTYPE_PROPERTIES } from "./core/attr/attr-constants.js";
|
|
50
|
+
// #337: turns "unknown X" into "retired in V — here is the migration". Changes no load
|
|
51
|
+
// outcome; retired vocabulary still fails with the same code.
|
|
52
|
+
import { retiredAttr, retiredAttrValue, retirementHint } from "./retired-vocabulary.js";
|
|
50
53
|
import {
|
|
51
54
|
FIELD_SUBTYPE_ENUM,
|
|
52
55
|
FIELD_ATTR_VALUES,
|
|
@@ -164,10 +167,17 @@ function validateNode(
|
|
|
164
167
|
// @-attr still fails — only the `properties` subtype is exempt.)
|
|
165
168
|
if (inst.subType === ATTR_SUBTYPE_PROPERTIES) continue;
|
|
166
169
|
if (!byName.has(inst.name)) {
|
|
170
|
+
// #337: if we RETIRED this name, say so. "Not declared by any registered
|
|
171
|
+
// provider" is true and reads as "your metadata is malformed", which sent one
|
|
172
|
+
// adopter to file a registration bug against a deliberate, documented breaking
|
|
173
|
+
// change. Unrecognised names still report generically — a typo is a typo.
|
|
174
|
+
const retired = retiredAttr(typeKey, inst.name);
|
|
167
175
|
errors.push(
|
|
168
176
|
new ParseError(
|
|
169
177
|
`Unknown attribute '@${inst.name}' on ${nodeLabel(node)} — ` +
|
|
170
|
-
|
|
178
|
+
(retired !== undefined
|
|
179
|
+
? retirementHint(retired)
|
|
180
|
+
: `not declared by any registered provider for ${typeKey}`),
|
|
171
181
|
{ code: "ERR_UNKNOWN_ATTR", source: node.source },
|
|
172
182
|
),
|
|
173
183
|
);
|
|
@@ -290,11 +300,16 @@ function validateNode(
|
|
|
290
300
|
? []
|
|
291
301
|
: [value];
|
|
292
302
|
for (const bad of offenders) {
|
|
303
|
+
// #337: a member we REMOVED reads very differently from a member that never
|
|
304
|
+
// existed. `@status: abandoned` was valid one release ago, so "not one of the
|
|
305
|
+
// allowed values" invites the reader to conclude the enum is broken.
|
|
306
|
+
const retiredValue = retiredAttrValue(typeKey, inst.name, bad);
|
|
293
307
|
errors.push(
|
|
294
308
|
new ParseError(
|
|
295
309
|
`${nodeLabel(node)} attribute '@${inst.name}' has value ` +
|
|
296
310
|
`'${String(bad)}' which is not one of the allowed values: ` +
|
|
297
|
-
`${allowed.map((v) => String(v)).join(", ")}
|
|
311
|
+
`${allowed.map((v) => String(v)).join(", ")}` +
|
|
312
|
+
(retiredValue !== undefined ? ` — ${retirementHint(retiredValue)}` : ""),
|
|
298
313
|
{ code: "ERR_BAD_ATTR_VALUE", source: node.source },
|
|
299
314
|
),
|
|
300
315
|
);
|
|
@@ -64,11 +64,30 @@ export type FieldSubType = (typeof FIELD_SUBTYPES)[number];
|
|
|
64
64
|
export const FIELD_ATTR_REQUIRED = "required";
|
|
65
65
|
export const FIELD_ATTR_UNIQUE = "unique";
|
|
66
66
|
|
|
67
|
-
/** FR-
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* layer split — this is logical (no DB-introspection round-trip). */
|
|
71
|
-
export const
|
|
67
|
+
/** FR-037 R1: who may write this field, and when. One axis, three mutually
|
|
68
|
+
* exclusive modes, so the illegal pair (`readOnly` + `writeOnce`) is
|
|
69
|
+
* unrepresentable and inheritance has a total order. Absent ⇒ `readWrite`.
|
|
70
|
+
* See ADR-0013 layer split — this is logical (no DB-introspection round-trip). */
|
|
71
|
+
export const FIELD_ATTR_MUTABILITY = "mutability";
|
|
72
|
+
|
|
73
|
+
/** `readWrite` — the caller may set it on create and change it on update. */
|
|
74
|
+
export const MUTABILITY_READ_WRITE = "readWrite";
|
|
75
|
+
/** `writeOnce` — set on create, then excluded from the update shape. A value
|
|
76
|
+
* presented on PATCH is IGNORED, not rejected (the uniform behaviour of every
|
|
77
|
+
* excluded-settable-set key, and the generated edit form submits every field). */
|
|
78
|
+
export const MUTABILITY_WRITE_ONCE = "writeOnce";
|
|
79
|
+
/** `readOnly` — nobody writes it: no setter, skipped on INSERT/UPDATE, omitted
|
|
80
|
+
* from every input variant. Populated by the DB, replication, or another owner. */
|
|
81
|
+
export const MUTABILITY_READ_ONLY = "readOnly";
|
|
82
|
+
|
|
83
|
+
/** Declaration order IS the tightening order — index in this array is the mode's
|
|
84
|
+
* rank, so "may only tighten" is an index comparison rather than a lookup table. */
|
|
85
|
+
export const MUTABILITY_MODES = [
|
|
86
|
+
MUTABILITY_READ_WRITE,
|
|
87
|
+
MUTABILITY_WRITE_ONCE,
|
|
88
|
+
MUTABILITY_READ_ONLY,
|
|
89
|
+
] as const;
|
|
90
|
+
export type MutabilityMode = (typeof MUTABILITY_MODES)[number];
|
|
72
91
|
export const FIELD_ATTR_DEFAULT = "default";
|
|
73
92
|
export const FIELD_ATTR_MAX_LENGTH = "maxLength";
|
|
74
93
|
|
|
@@ -46,11 +46,16 @@ export const FIELD_DEFINITION: ProviderDefinition = {
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"type": "attr",
|
|
49
|
-
"subType": "
|
|
50
|
-
"name": "
|
|
49
|
+
"subType": "string",
|
|
50
|
+
"name": "mutability",
|
|
51
51
|
"min": 0,
|
|
52
52
|
"max": 1,
|
|
53
|
-
"
|
|
53
|
+
"allowedValues": [
|
|
54
|
+
"readWrite",
|
|
55
|
+
"writeOnce",
|
|
56
|
+
"readOnly"
|
|
57
|
+
],
|
|
58
|
+
"description": "FR-037 R1: who may write this field, and when. 'readWrite' (the default when absent) — the caller may set it on create and change it on update. 'writeOnce' — the caller sets it on create; it is excluded from the update shape thereafter, so a value presented on PATCH is ignored rather than rejected. 'readOnly' — nobody writes it: codegen emits no setter / writable property, the persistence layer skips the column on INSERT/UPDATE, and Zod/Pydantic/class-validator schemas omit it from input variants; the value is populated by the database (computed column, default expression, trigger), by replication, or by another external owner. The three are mutually exclusive modes of ONE axis — who may write, and when — so the illegal pair is unrepresentable and inheritance has a total order: a subtype may TIGHTEN an inherited mode (readWrite < writeOnce < readOnly) and never loosen it (ERR_MUTABILITY_DOWNGRADE). Pairing a non-readWrite mode with @autoSet is ERR_MUTABILITY_AUTOSET_CONFLICT: @autoSet already says the SERVER supplies the value, which is a different axis from who may write it."
|
|
54
59
|
},
|
|
55
60
|
{
|
|
56
61
|
"type": "attr",
|