@metaobjectsdev/metadata 0.24.0-rc.1 → 0.24.1
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/identity/identity-definition.embedded.js +2 -2
- package/dist/core/identity/identity-definition.embedded.js.map +1 -1
- package/dist/core/index/index-definition.embedded.js +2 -2
- package/dist/core/index/index-definition.embedded.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/vocabulary-rewrite-yaml.d.ts +21 -0
- package/dist/core/vocabulary-rewrite-yaml.d.ts.map +1 -0
- package/dist/core/vocabulary-rewrite-yaml.js +245 -0
- package/dist/core/vocabulary-rewrite-yaml.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 +37 -4
- 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 +14 -10
- package/dist/loader/meta-data-loader.js.map +1 -1
- package/dist/loader/validation-passes.d.ts +1 -0
- package/dist/loader/validation-passes.d.ts.map +1 -1
- package/dist/loader/validation-passes.js +263 -45
- 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 +5 -21
- 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 +314 -0
- package/dist/vocabulary-rewrite.js.map +1 -0
- package/package.json +11 -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/identity/identity-definition.embedded.ts +2 -2
- package/src/core/index/index-definition.embedded.ts +2 -2
- 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/vocabulary-rewrite-yaml.ts +267 -0
- package/src/core-types.ts +9 -10
- package/src/errors.ts +37 -4
- package/src/index.ts +29 -1
- package/src/library/library-sources.ts +14 -0
- package/src/loader/meta-data-loader.ts +15 -10
- package/src/loader/validation-passes.ts +323 -50
- 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 +5 -21
- 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 +350 -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
|
@@ -18,9 +18,9 @@ export const TEMPLATE_DEFINITION: ProviderDefinition = {
|
|
|
18
18
|
{
|
|
19
19
|
"type": "template",
|
|
20
20
|
"subType": "prompt",
|
|
21
|
-
"description": "An LLM-targeted renderable prompt template (FR-004). Carries the generic reference + governance attrs plus the LLM overlay (@maxTokens / @requiredSlots / @model / @responseRef). Its renderable body is required via @textRef.",
|
|
22
|
-
"whenToUse": "You are sending text to an LLM. Declare a prompt template with a typed payload so the prompt is versioned, drift-checked against its fields, and cache-stable — instead of string-building it in code.",
|
|
23
|
-
"rules": "prompt requires @payloadRef (the typed payload it renders against) AND @textRef (the body text, provider-resolved at render time — enforced in the loader's validateTemplatePayloadRefs pass, not at the attr layer where @textRef is relaxed to optional so template.output email can omit it). @format is a closed enum keyed by the render engine's escaper. @responseRef (optional) names the response value-object the prompt expects
|
|
21
|
+
"description": "An LLM-targeted renderable prompt template (FR-004). Carries the generic reference + governance attrs plus the LLM overlay (@maxTokens / @requiredSlots / @model / @responseRef). Its renderable body is required via @textRef. A prompt declaring @responseRef also owns the INBOUND half (ADR-0052): the parser-on-receipt, the FR-010 response-format fragment (@promptStyle), and the reply syntax (@responseFormat).",
|
|
22
|
+
"whenToUse": "You are sending text to an LLM. Declare a prompt template with a typed payload so the prompt is versioned, drift-checked against its fields, and cache-stable — instead of string-building it in code. Add @responseRef when you also want the reply parsed into a typed shape.",
|
|
23
|
+
"rules": "prompt requires @payloadRef (the typed payload it renders against) AND @textRef (the body text, provider-resolved at render time — enforced in the loader's validateTemplatePayloadRefs pass, not at the attr layer where @textRef is relaxed to optional so template.output email can omit it). @format is the syntax of the rendered PROMPT body, a closed enum keyed by the render engine's escaper; @responseFormat (ADR-0053) is the syntax of the model's REPLY. @responseRef (optional) names the response value-object the prompt expects, drives typed LLM-call trace derivation, and is the sole gate on the inbound codegen tier — which keys on its presence, never on a format value.",
|
|
24
24
|
"children": [
|
|
25
25
|
{
|
|
26
26
|
"type": "attr",
|
|
@@ -120,16 +120,43 @@ export const TEMPLATE_DEFINITION: ProviderDefinition = {
|
|
|
120
120
|
"name": "responseRef",
|
|
121
121
|
"min": 0,
|
|
122
122
|
"max": 1,
|
|
123
|
-
"description": "Optional ref to the response value-object this prompt expects (peer of @payloadRef; drives typed LLM-call trace derivation)."
|
|
123
|
+
"description": "Optional ref to the response value-object this prompt expects (peer of @payloadRef; drives typed LLM-call trace derivation). Its presence is the sole gate on the inbound codegen tier (ADR-0052): parser-on-receipt, tolerant extract, and the FR-010 response-format fragment."
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"type": "attr",
|
|
127
|
+
"subType": "string",
|
|
128
|
+
"name": "promptStyle",
|
|
129
|
+
"min": 0,
|
|
130
|
+
"max": 1,
|
|
131
|
+
"default": "guide",
|
|
132
|
+
"allowedValues": [
|
|
133
|
+
"guide",
|
|
134
|
+
"inline",
|
|
135
|
+
"exampleOnly"
|
|
136
|
+
],
|
|
137
|
+
"description": "FR-010 response-format fragment presentation: 'guide' (prose list + example), 'inline' (inline placeholders / enum choices), or 'exampleOnly' (filled skeleton). Guidance is never emitted as comments."
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"type": "attr",
|
|
141
|
+
"subType": "string",
|
|
142
|
+
"name": "responseFormat",
|
|
143
|
+
"min": 0,
|
|
144
|
+
"max": 1,
|
|
145
|
+
"default": "json",
|
|
146
|
+
"allowedValues": [
|
|
147
|
+
"json",
|
|
148
|
+
"xml"
|
|
149
|
+
],
|
|
150
|
+
"description": "ADR-0053: the syntax of the model's REPLY, read by the parser-on-receipt and the FR-010 response-format fragment. Distinct from @format, which is the syntax of the rendered PROMPT body. Two members because two is what every shipping consumer dispatches on; the other @format members are reserved-not-registered."
|
|
124
151
|
}
|
|
125
152
|
]
|
|
126
153
|
},
|
|
127
154
|
{
|
|
128
155
|
"type": "template",
|
|
129
156
|
"subType": "output",
|
|
130
|
-
"description": "An output / serialization template (FR-004): every rendered artifact other than an LLM prompt — a document (email, export, docs, config) or an email. Carries the generic reference + governance attrs
|
|
131
|
-
"whenToUse": "You render a document/email/serialized output from typed data. Declare an output template so the {{fields}} are drift-checked against the payload VO at build time.",
|
|
132
|
-
"rules": "output is either a document (@kind=\"document\" or absent → renders @textRef in @format to one string) or an email (@kind=\"email\" → renders subject + html + optional text to a structured EmailDocument). The cross-field presence rule is enforced in the loader's validateTemplatePayloadRefs pass: document requires @textRef; email requires @subjectRef AND @htmlBodyRef (with @textBodyRef optional) and carries NO @textRef. @format is a closed enum keyed by the render engine's escaper
|
|
157
|
+
"description": "An output / serialization template (FR-004): every rendered artifact other than an LLM prompt — a document (email, export, docs, config) or an email. Carries the generic reference + governance attrs and the @kind + email part-refs. OUTBOUND ONLY (ADR-0052) — it renders, and generates no parser.",
|
|
158
|
+
"whenToUse": "You render a document/email/serialized output from typed data. Declare an output template so the {{fields}} are drift-checked against the payload VO at build time. To parse a model's reply instead, declare @responseRef on the template.prompt that elicits it — never a template.output.",
|
|
159
|
+
"rules": "output is either a document (@kind=\"document\" or absent → renders @textRef in @format to one string) or an email (@kind=\"email\" → renders subject + html + optional text to a structured EmailDocument). The cross-field presence rule is enforced in the loader's validateTemplatePayloadRefs pass: document requires @textRef; email requires @subjectRef AND @htmlBodyRef (with @textBodyRef optional) and carries NO @textRef. @format is a closed enum keyed by the render engine's escaper. template.output is OUTBOUND ONLY (ADR-0052): it emits a render helper and nothing that reads a model's reply — the parser-on-receipt, the tolerant extract and the FR-010 response-format fragment all belong to template.prompt @responseRef.",
|
|
133
160
|
"children": [
|
|
134
161
|
{
|
|
135
162
|
"type": "attr",
|
|
@@ -198,20 +225,6 @@ export const TEMPLATE_DEFINITION: ProviderDefinition = {
|
|
|
198
225
|
"max": 1,
|
|
199
226
|
"description": "Output tags the rendered text must contain (drives the verify output-tag check)."
|
|
200
227
|
},
|
|
201
|
-
{
|
|
202
|
-
"type": "attr",
|
|
203
|
-
"subType": "string",
|
|
204
|
-
"name": "promptStyle",
|
|
205
|
-
"min": 0,
|
|
206
|
-
"max": 1,
|
|
207
|
-
"default": "guide",
|
|
208
|
-
"allowedValues": [
|
|
209
|
-
"guide",
|
|
210
|
-
"inline",
|
|
211
|
-
"exampleOnly"
|
|
212
|
-
],
|
|
213
|
-
"description": "FR-010 output-format prompt presentation: 'guide' (prose list + example), 'inline' (inline placeholders / enum choices), or 'exampleOnly' (filled skeleton). Guidance is never emitted as comments."
|
|
214
|
-
},
|
|
215
228
|
{
|
|
216
229
|
"type": "attr",
|
|
217
230
|
"subType": "string",
|
|
@@ -0,0 +1,350 @@
|
|
|
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 lives in `core/vocabulary-rewrite-yaml.ts`, not here. This
|
|
31
|
+
// module is reachable from `src/index.ts`, which may not import the Node-only `yaml`
|
|
32
|
+
// package, so the YAML arm sits behind its own package subpath and `meta upgrade`
|
|
33
|
+
// dynamic-imports it. The split is a bundling constraint, not a difference in contract: both
|
|
34
|
+
// arms return the same result shape, scope every occurrence the same way, and refuse the
|
|
35
|
+
// same retirements.
|
|
36
|
+
//
|
|
37
|
+
// The reason YAML gets a parser and this arm does not: a hand-rolled YAML mode was tried
|
|
38
|
+
// here first and shipped a file-corrupting bug — a multi-item block sequence lost every item
|
|
39
|
+
// but the first, because a scanner stops at a newline — while the dominant authoring style
|
|
40
|
+
// (flow mappings, `{ name: x, readOnly: true }`) was not matched at all. YAML's value extent
|
|
41
|
+
// is not derivable by scanning; JSON's is.
|
|
42
|
+
//
|
|
43
|
+
// IT REFUSES WHAT IT CANNOT KNOW. A retirement with no `rewrite` (`@status: abandoned`) is
|
|
44
|
+
// reported, never guessed at. Deleting the node, retyping it, and fixing the residue it
|
|
45
|
+
// describes are all defensible, and a wrong guess emits metadata that LOADS and means
|
|
46
|
+
// something different — strictly worse than leaving it alone, because the adopter would
|
|
47
|
+
// believe the migration finished.
|
|
48
|
+
|
|
49
|
+
import {
|
|
50
|
+
RETIRED_VOCABULARY,
|
|
51
|
+
note,
|
|
52
|
+
scopeMatches,
|
|
53
|
+
type RetiredEntry,
|
|
54
|
+
type RetirementNote,
|
|
55
|
+
} from "./retired-vocabulary.js";
|
|
56
|
+
|
|
57
|
+
export interface RewriteChange {
|
|
58
|
+
/** Attribute name, without the sigil. */
|
|
59
|
+
readonly attr: string;
|
|
60
|
+
readonly from: string;
|
|
61
|
+
readonly to: string;
|
|
62
|
+
/** 1-indexed line in the ORIGINAL document. */
|
|
63
|
+
readonly line: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface RewriteRefusal extends RetirementNote {
|
|
67
|
+
/** What was refused, ready to print: `@status` for an attribute, `origin.collection` for
|
|
68
|
+
* a retired subtype. Carries its own sigil so a caller never has to guess which. */
|
|
69
|
+
readonly subject: string;
|
|
70
|
+
readonly value?: string;
|
|
71
|
+
readonly line: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface RewriteResult {
|
|
75
|
+
readonly text: string;
|
|
76
|
+
readonly changes: readonly RewriteChange[];
|
|
77
|
+
readonly refusals: readonly RewriteRefusal[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface RewriteOpts {
|
|
81
|
+
/** Only apply retirements at or before this version. */
|
|
82
|
+
readonly maxVersion?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** `0.24.0` → `[0,24,0]`, for an ordered comparison rather than a string one. */
|
|
86
|
+
function parts(v: string): number[] {
|
|
87
|
+
return v.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function atOrBefore(a: string, b: string): boolean {
|
|
91
|
+
const [x, y] = [parts(a), parts(b)];
|
|
92
|
+
for (let i = 0; i < Math.max(x.length, y.length); i++) {
|
|
93
|
+
const d = (x[i] ?? 0) - (y[i] ?? 0);
|
|
94
|
+
if (d !== 0) return d < 0;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** 1-indexed line of `index` in `text`. */
|
|
100
|
+
function lineAt(text: string, index: number): number {
|
|
101
|
+
let line = 1;
|
|
102
|
+
for (let i = 0; i < index && i < text.length; i++) if (text[i] === "\n") line++;
|
|
103
|
+
return line;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Offset just past the bracket closing the one at `open`, or undefined if unbalanced.
|
|
108
|
+
* String-aware, so a brace inside a JSON string literal cannot unbalance the scan.
|
|
109
|
+
*/
|
|
110
|
+
function closingBracket(text: string, open: number): number | undefined {
|
|
111
|
+
const close = text[open] === "[" ? "]" : "}";
|
|
112
|
+
const openCh = text[open];
|
|
113
|
+
let depth = 0;
|
|
114
|
+
let inStr = false;
|
|
115
|
+
for (let j = open; j < text.length; j++) {
|
|
116
|
+
const c = text[j];
|
|
117
|
+
if (inStr) {
|
|
118
|
+
if (c === "\\") j++;
|
|
119
|
+
else if (c === '"') inStr = false;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (c === '"') inStr = true;
|
|
123
|
+
else if (c === openCh) depth++;
|
|
124
|
+
else if (c === close) {
|
|
125
|
+
depth--;
|
|
126
|
+
if (depth === 0) return j + 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** One `{ "<type>.<subType>": { … } }` node body, and where it sits in the text. */
|
|
133
|
+
interface ScopeRange {
|
|
134
|
+
readonly typeKey: string;
|
|
135
|
+
/** Offset of the opening quote of the type key — where a reader would point. */
|
|
136
|
+
readonly keyIndex: number;
|
|
137
|
+
readonly bodyStart: number;
|
|
138
|
+
readonly bodyEnd: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Every node body in the document, in source order.
|
|
143
|
+
*
|
|
144
|
+
* A canonical-JSON node is `{ "<type>.<subType>": { …body… } }`, so an attribute belongs to
|
|
145
|
+
* the INNERMOST body containing it — which is what makes per-occurrence scoping possible
|
|
146
|
+
* without a parser we deliberately do not have.
|
|
147
|
+
*/
|
|
148
|
+
function scopeRanges(source: string): ScopeRange[] {
|
|
149
|
+
const ranges: ScopeRange[] = [];
|
|
150
|
+
const re = /"([a-z][A-Za-z0-9]*)\.([A-Za-z0-9_*]+)"\s*:\s*\{/g;
|
|
151
|
+
let m: RegExpExecArray | null;
|
|
152
|
+
while ((m = re.exec(source)) !== null) {
|
|
153
|
+
const bodyStart = m.index + m[0].length - 1;
|
|
154
|
+
const bodyEnd = closingBracket(source, bodyStart);
|
|
155
|
+
if (bodyEnd === undefined) continue;
|
|
156
|
+
ranges.push({ typeKey: `${m[1]}.${m[2]}`, keyIndex: m.index, bodyStart, bodyEnd });
|
|
157
|
+
}
|
|
158
|
+
return ranges;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The type key governing `offset` — the innermost body containing it. */
|
|
162
|
+
function scopeAt(ranges: readonly ScopeRange[], offset: number): string | undefined {
|
|
163
|
+
let best: ScopeRange | undefined;
|
|
164
|
+
for (const r of ranges) {
|
|
165
|
+
if (offset <= r.bodyStart || offset >= r.bodyEnd) continue;
|
|
166
|
+
// Properly nested ranges: the innermost containing one starts last.
|
|
167
|
+
if (best === undefined || r.bodyStart > best.bodyStart) best = r;
|
|
168
|
+
}
|
|
169
|
+
return best?.typeKey;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Matches `"@name"` at a key position, plus the separator that follows, capturing the key
|
|
174
|
+
* separately so a replacement can keep the original spacing.
|
|
175
|
+
*
|
|
176
|
+
* Deliberately NOT a full parser. A parser would have to reproduce the document to emit it,
|
|
177
|
+
* which is the thing this exists to avoid; matching a key occurrence lets every untouched
|
|
178
|
+
* byte survive by construction.
|
|
179
|
+
*/
|
|
180
|
+
function keyPattern(attr: string): RegExp {
|
|
181
|
+
return new RegExp(`("@?${attr}")(\\s*:\\s*)`, "g");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** The JSON value token starting at `from` — a scalar, or a bracketed array/object. */
|
|
185
|
+
function valueSpan(text: string, from: number): { start: number; end: number; raw: string } | undefined {
|
|
186
|
+
let i = from;
|
|
187
|
+
while (i < text.length && /\s/.test(text[i] ?? "")) i++;
|
|
188
|
+
const open = text[i];
|
|
189
|
+
if (open === "[" || open === "{") {
|
|
190
|
+
const end = closingBracket(text, i);
|
|
191
|
+
return end === undefined ? undefined : { start: i, end, raw: text.slice(i, end) };
|
|
192
|
+
}
|
|
193
|
+
// Scalar: to the next comma, closing brace, or newline, whichever comes first.
|
|
194
|
+
let j = i;
|
|
195
|
+
let inStr = false;
|
|
196
|
+
for (; j < text.length; j++) {
|
|
197
|
+
const c = text[j];
|
|
198
|
+
if (inStr) {
|
|
199
|
+
if (c === "\\") j++;
|
|
200
|
+
else if (c === '"') inStr = false;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (c === '"') inStr = true;
|
|
204
|
+
else if (c === "," || c === "}" || c === "\n") break;
|
|
205
|
+
}
|
|
206
|
+
return { start: i, end: j, raw: text.slice(i, j).trim() };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Does the raw token equal this literal? Compares JSON-decoded where possible so
|
|
210
|
+
* `"readOnly"` and `readOnly` both match a string literal. */
|
|
211
|
+
function rawEquals(raw: string, want: unknown): boolean {
|
|
212
|
+
try {
|
|
213
|
+
return JSON.parse(raw) === want;
|
|
214
|
+
} catch {
|
|
215
|
+
return raw === String(want);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* The span to delete so that removing a key leaves loadable JSON.
|
|
221
|
+
*
|
|
222
|
+
* The arithmetic is fiddly and every branch is load-bearing, so it lives here with its
|
|
223
|
+
* steps named rather than inline in the dispatch below.
|
|
224
|
+
*/
|
|
225
|
+
function dropSpan(source: string, keyStart: number, valueEnd: number): { start: number; end: number } {
|
|
226
|
+
// 1. Absorb the value's trailing spaces, then its trailing comma if it has one.
|
|
227
|
+
let end = valueEnd;
|
|
228
|
+
while (end < source.length && /[ \t]/.test(source[end] ?? "")) end++;
|
|
229
|
+
const hadTrailingComma = source[end] === ",";
|
|
230
|
+
if (hadTrailingComma) end++;
|
|
231
|
+
|
|
232
|
+
// 2. Absorb the key's own indentation, so the removal does not leave a ragged line.
|
|
233
|
+
let start = keyStart;
|
|
234
|
+
while (start > 0 && /[ \t]/.test(source[start - 1] ?? "")) start--;
|
|
235
|
+
|
|
236
|
+
// 3. THE LAST-KEY CASE, found by dogfooding rather than by a unit test: when the retired
|
|
237
|
+
// attr is last in its object there IS no trailing comma — the comma belongs to the
|
|
238
|
+
// PRECEDING key. Dropping without taking it leaves `"...",\n}`, which does not parse.
|
|
239
|
+
// A tool whose whole job is producing loadable metadata cannot emit invalid JSON.
|
|
240
|
+
if (!hadTrailingComma) {
|
|
241
|
+
let back = start;
|
|
242
|
+
while (back > 0 && /\s/.test(source[back - 1] ?? "")) back--;
|
|
243
|
+
if (source[back - 1] === ",") start = back - 1;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 4. If the key owned its whole line, take the line terminator too rather than leaving a
|
|
247
|
+
// blank line. Otherwise the key shares a line with other content, so undo step 2's
|
|
248
|
+
// indentation trim — it would eat the separating space after the preceding key's comma.
|
|
249
|
+
if (source[start - 1] === "\n" && source[end] === "\n") end++;
|
|
250
|
+
else if (start > 0 && source[start - 1] !== "\n" && hadTrailingComma) start = keyStart;
|
|
251
|
+
|
|
252
|
+
return { start, end };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Rewrite retired vocabulary in one raw canonical-JSON metadata document.
|
|
257
|
+
*
|
|
258
|
+
* Pure: no filesystem, no loader, no registry. Returns the new text plus every change and
|
|
259
|
+
* every refusal, so a caller can print a diff and exit non-zero when work remains.
|
|
260
|
+
*/
|
|
261
|
+
export function rewriteDocument(source: string, opts: RewriteOpts = {}): RewriteResult {
|
|
262
|
+
const changes: RewriteChange[] = [];
|
|
263
|
+
const refusals: RewriteRefusal[] = [];
|
|
264
|
+
|
|
265
|
+
// Edits are collected as spans against the ORIGINAL text and applied in one pass at the
|
|
266
|
+
// end, right-to-left. Rewriting incrementally would invalidate every later offset.
|
|
267
|
+
const edits: { start: number; end: number; text: string }[] = [];
|
|
268
|
+
|
|
269
|
+
const inWindow = (e: RetiredEntry): boolean =>
|
|
270
|
+
opts.maxVersion === undefined || atOrBefore(e.since, opts.maxVersion);
|
|
271
|
+
const ranges = scopeRanges(source);
|
|
272
|
+
|
|
273
|
+
// A retired SUBTYPE has no attribute to rewrite — the node itself has to be re-modelled
|
|
274
|
+
// (`origin.collection` becomes `origin.aggregate @agg: collect`), which is a judgment the
|
|
275
|
+
// adopter makes. Reporting it is what keeps `meta upgrade` from exiting 0 on a document
|
|
276
|
+
// that still will not load; it used to be filtered out entirely and was invisible.
|
|
277
|
+
for (const r of ranges) {
|
|
278
|
+
for (const entry of RETIRED_VOCABULARY) {
|
|
279
|
+
if (entry.isSubTypeRetirement !== true || !inWindow(entry)) continue;
|
|
280
|
+
if (`${entry.type}.${entry.subType}` !== r.typeKey) continue;
|
|
281
|
+
refusals.push({ ...note(entry), subject: r.typeKey, line: lineAt(source, r.keyIndex) });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
for (const entry of RETIRED_VOCABULARY.filter((e) => e.attr !== undefined && inWindow(e))) {
|
|
286
|
+
const attr = entry.attr as string;
|
|
287
|
+
const re = keyPattern(attr);
|
|
288
|
+
let m: RegExpExecArray | null;
|
|
289
|
+
|
|
290
|
+
while ((m = re.exec(source)) !== null) {
|
|
291
|
+
const keyStart = m.index;
|
|
292
|
+
const keyEnd = keyStart + (m[1]?.length ?? 0);
|
|
293
|
+
const afterKey = m.index + m[0].length;
|
|
294
|
+
|
|
295
|
+
// Scope is decided HERE, per occurrence, from the enclosing node.
|
|
296
|
+
const scope = scopeAt(ranges, keyStart);
|
|
297
|
+
if (scope === undefined || !scopeMatches(entry, scope)) continue;
|
|
298
|
+
|
|
299
|
+
const line = lineAt(source, keyStart);
|
|
300
|
+
const span = valueSpan(source, afterKey);
|
|
301
|
+
|
|
302
|
+
// A VALUE-scoped retirement only fires on the retired values. `@dbColumnType: jsonb`
|
|
303
|
+
// is live vocabulary on the same attribute; touching it would silently change the
|
|
304
|
+
// column type.
|
|
305
|
+
if (entry.attrValues !== undefined) {
|
|
306
|
+
if (!entry.attrValues.some((v) => rawEquals(span?.raw ?? "", v))) continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const refuse = (): void => {
|
|
310
|
+
refusals.push({
|
|
311
|
+
...note(entry),
|
|
312
|
+
subject: `@${attr}`,
|
|
313
|
+
...(span?.raw !== undefined ? { value: span.raw } : {}),
|
|
314
|
+
line,
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const drop = (): void => {
|
|
319
|
+
if (span === undefined) return;
|
|
320
|
+
const { start, end } = dropSpan(source, keyStart, span.end);
|
|
321
|
+
edits.push({ start, end, text: "" });
|
|
322
|
+
changes.push({ attr, from: attr, to: "(removed)", line });
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const rw = entry.rewrite;
|
|
326
|
+
if (rw === undefined) refuse();
|
|
327
|
+
else if (rw.kind === "renameAttr") {
|
|
328
|
+
edits.push({ start: keyStart, end: keyEnd, text: `"@${rw.to}"` });
|
|
329
|
+
changes.push({ attr, from: attr, to: rw.to, line });
|
|
330
|
+
} else if (rw.kind === "dropAttr") drop();
|
|
331
|
+
else if (span === undefined) continue;
|
|
332
|
+
else if (rawEquals(span.raw, rw.fromValue)) {
|
|
333
|
+
const valText = JSON.stringify(rw.toValue);
|
|
334
|
+
edits.push({ start: keyStart, end: keyEnd, text: `"@${rw.toAttr}"` });
|
|
335
|
+
edits.push({ start: span.start, end: span.end, text: valText });
|
|
336
|
+
changes.push({ attr, from: `${attr}: ${span.raw}`, to: `${rw.toAttr}: ${valText}`, line });
|
|
337
|
+
}
|
|
338
|
+
// Every other value of a retired attribute still has to go somewhere — the entry says
|
|
339
|
+
// which, and the type makes saying it mandatory.
|
|
340
|
+
else if (rw.otherwise === "drop") drop();
|
|
341
|
+
else refuse();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
edits.sort((a, b) => b.start - a.start);
|
|
346
|
+
let text = source;
|
|
347
|
+
for (const e of edits) text = text.slice(0, e.start) + e.text + text.slice(e.end);
|
|
348
|
+
|
|
349
|
+
return { text, changes, refusals };
|
|
350
|
+
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { MetaData } from "../../shared/meta-data.js";
|
|
2
|
-
import { ParseError } from "../../errors.js";
|
|
3
|
-
import type { LoaderWarning } from "../../source.js";
|
|
4
|
-
export interface FieldReadOnlyValidationResult {
|
|
5
|
-
errors: ParseError[];
|
|
6
|
-
warnings: LoaderWarning[];
|
|
7
|
-
}
|
|
8
|
-
export declare function validateFieldReadOnly(root: MetaData): FieldReadOnlyValidationResult;
|
|
9
|
-
//# sourceMappingURL=validate-field-readonly.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-field-readonly.d.ts","sourceRoot":"","sources":["../../../src/core/field/validate-field-readonly.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAerD,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,6BAA6B,CAsEnF"}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// Validation pass: field-level @readOnly cross-attribute rules (FR-013).
|
|
2
|
-
//
|
|
3
|
-
// Codes:
|
|
4
|
-
// ERR_READONLY_ASSIGNED_PRIMARY — @readOnly: true on a field that is the
|
|
5
|
-
// target of an identity.primary with @generation: "assigned". The application
|
|
6
|
-
// has no path to populate the identity value (no setter; not generated; not
|
|
7
|
-
// defaulted).
|
|
8
|
-
// ERR_READONLY_DOWNGRADE — a concrete subtype declares @readOnly: false on a
|
|
9
|
-
// field whose extends-chain parent declares @readOnly: true. Read-only-ness
|
|
10
|
-
// can only be upgraded, never downgraded.
|
|
11
|
-
// WARN_READONLY_VALUE_OBJECT — @readOnly: true on a field child of object.value.
|
|
12
|
-
// The persistence implication does not apply; the attr is retained for
|
|
13
|
-
// language-specific record/struct treatment.
|
|
14
|
-
import { ParseError } from "../../errors.js";
|
|
15
|
-
import { TYPE_OBJECT, TYPE_FIELD, TYPE_IDENTITY, } from "../../shared/base-types.js";
|
|
16
|
-
import { OBJECT_SUBTYPE_VALUE } from "../object/object-constants.js";
|
|
17
|
-
import { IDENTITY_SUBTYPE_PRIMARY, IDENTITY_ATTR_GENERATION, IDENTITY_ATTR_FIELDS, GENERATION_ASSIGNED, } from "../identity/identity-constants.js";
|
|
18
|
-
import { FIELD_ATTR_READ_ONLY } from "./field-constants.js";
|
|
19
|
-
export function validateFieldReadOnly(root) {
|
|
20
|
-
const errors = [];
|
|
21
|
-
const warnings = [];
|
|
22
|
-
// ADR-0039: root has no super; children()==ownChildren() but resolving is the default.
|
|
23
|
-
for (const obj of root.children().filter((c) => c.type === TYPE_OBJECT)) {
|
|
24
|
-
const isValueObject = obj.subType === OBJECT_SUBTYPE_VALUE;
|
|
25
|
-
// 1) WARN_READONLY_VALUE_OBJECT — any @readOnly field child of an object.value.
|
|
26
|
-
if (isValueObject) {
|
|
27
|
-
// ADR-0039: own — warns on @readOnly DECLARED on this value's own fields
|
|
28
|
-
// (readOnlyFlag reads the explicit own flag; the FR-013 read-only checks
|
|
29
|
-
// are own-vs-super comparisons by design).
|
|
30
|
-
for (const child of obj.ownChildren()) {
|
|
31
|
-
if (child.type === TYPE_FIELD && readOnlyFlag(child) === true) {
|
|
32
|
-
warnings.push({
|
|
33
|
-
code: "WARN_READONLY_VALUE_OBJECT",
|
|
34
|
-
message: `field "${child.name}" on object.value "${obj.name}" declares ` +
|
|
35
|
-
`@readOnly: true; value-objects have no persistence semantics so ` +
|
|
36
|
-
`the read-only contract is advisory (codegen may use it for record/` +
|
|
37
|
-
`struct treatment).`,
|
|
38
|
-
source: child.source,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// 2) ERR_READONLY_DOWNGRADE — read-only-ness can only be upgraded across
|
|
44
|
-
// extends. Compare own field vs. inherited field's effective @readOnly.
|
|
45
|
-
// ADR-0039: own — the downgrade check compares this object's OWN explicit
|
|
46
|
-
// @readOnly:false against the inherited effective value (own-vs-super by design).
|
|
47
|
-
for (const ownField of obj.ownChildren().filter((c) => c.type === TYPE_FIELD)) {
|
|
48
|
-
const ownVal = readOnlyFlag(ownField);
|
|
49
|
-
if (ownVal !== false)
|
|
50
|
-
continue; // only the explicit downgrade case matters
|
|
51
|
-
const inherited = inheritedField(obj, ownField.name);
|
|
52
|
-
if (inherited !== undefined && readOnlyFlag(inherited) === true) {
|
|
53
|
-
errors.push(new ParseError(`field "${ownField.name}" on "${obj.name}" sets @readOnly: false, but the ` +
|
|
54
|
-
`extends-chain parent declares @readOnly: true. Read-only-ness can only be ` +
|
|
55
|
-
`upgraded, not downgraded (FR-013).`, { code: "ERR_READONLY_DOWNGRADE", source: ownField.source }));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// 3) ERR_READONLY_ASSIGNED_PRIMARY — @readOnly: true on a field used in an
|
|
59
|
-
// identity.primary whose @generation is "assigned" (effective tree).
|
|
60
|
-
if (!isValueObject) {
|
|
61
|
-
const primaryAssignedFields = primaryAssignedFieldNames(obj);
|
|
62
|
-
if (primaryAssignedFields.size > 0) {
|
|
63
|
-
for (const field of obj.children().filter((c) => c.type === TYPE_FIELD)) {
|
|
64
|
-
if (!primaryAssignedFields.has(field.name))
|
|
65
|
-
continue;
|
|
66
|
-
if (readOnlyFlag(field) !== true)
|
|
67
|
-
continue;
|
|
68
|
-
errors.push(new ParseError(`field "${field.name}" on "${obj.name}" is @readOnly: true AND the target ` +
|
|
69
|
-
`of identity.primary with @generation: "assigned"; the application has no ` +
|
|
70
|
-
`path to populate the identity value (FR-013).`, { code: "ERR_READONLY_ASSIGNED_PRIMARY", source: field.source }));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return { errors, warnings };
|
|
76
|
-
}
|
|
77
|
-
/** Read the explicit @readOnly value from a field's own attrs. Returns
|
|
78
|
-
* true / false when explicitly set, undefined when absent. */
|
|
79
|
-
function readOnlyFlag(field) {
|
|
80
|
-
// ADR-0039: own — the FR-013 downgrade rule needs the EXPLICIT own @readOnly on
|
|
81
|
-
// THIS node (detecting an own :false against an inherited :true); resolving would
|
|
82
|
-
// mask the downgrade. Deliberate own-vs-super comparison.
|
|
83
|
-
const v = field.ownAttr(FIELD_ATTR_READ_ONLY);
|
|
84
|
-
if (typeof v === "boolean")
|
|
85
|
-
return v;
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
/** Walk the extends chain looking for a field with the same name; return its
|
|
89
|
-
* declaring node (own attrs preserved) if found. */
|
|
90
|
-
function inheritedField(obj, name) {
|
|
91
|
-
let cursor = obj.superResolved;
|
|
92
|
-
while (cursor !== undefined) {
|
|
93
|
-
// ADR-0039: own — super-chain walk reading each level's OWN fields to find the
|
|
94
|
-
// declaring node (the FR-013 comparison needs the declaring node's own flag).
|
|
95
|
-
const f = cursor.ownChildren().find((c) => c.type === TYPE_FIELD && c.name === name);
|
|
96
|
-
if (f !== undefined)
|
|
97
|
-
return f;
|
|
98
|
-
cursor = cursor.superResolved;
|
|
99
|
-
}
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
/** Names of fields participating in any identity.primary with @generation:
|
|
103
|
-
* "assigned" on `obj` or its extends chain. */
|
|
104
|
-
function primaryAssignedFieldNames(obj) {
|
|
105
|
-
const out = new Set();
|
|
106
|
-
for (const id of obj.children()) {
|
|
107
|
-
if (id.type !== TYPE_IDENTITY)
|
|
108
|
-
continue;
|
|
109
|
-
if (id.subType !== IDENTITY_SUBTYPE_PRIMARY)
|
|
110
|
-
continue;
|
|
111
|
-
// ADR-0039: resolving — an identity may inherit @generation / @fields via extends.
|
|
112
|
-
const gen = id.attr(IDENTITY_ATTR_GENERATION);
|
|
113
|
-
if (gen !== GENERATION_ASSIGNED)
|
|
114
|
-
continue;
|
|
115
|
-
const fields = id.attr(IDENTITY_ATTR_FIELDS);
|
|
116
|
-
if (Array.isArray(fields)) {
|
|
117
|
-
for (const fName of fields) {
|
|
118
|
-
if (typeof fName === "string")
|
|
119
|
-
out.add(fName);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else if (typeof fields === "string") {
|
|
123
|
-
out.add(fields);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return out;
|
|
127
|
-
}
|
|
128
|
-
//# sourceMappingURL=validate-field-readonly.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-field-readonly.js","sourceRoot":"","sources":["../../../src/core/field/validate-field-readonly.ts"],"names":[],"mappings":"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"}
|