@narrative.io/jsonforms-provider-protocols 3.0.0-beta.19 → 3.0.0-beta.20
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/core/initFormData.d.ts.map +1 -1
- package/dist/core/initFormData.js +0 -2
- package/dist/core/initFormData.js.map +1 -1
- package/dist/core/projection.d.ts.map +1 -1
- package/dist/core/projection.js +3 -12
- package/dist/core/projection.js.map +1 -1
- package/dist/core/resolveScope.d.ts.map +1 -1
- package/dist/core/resolveScope.js +5 -21
- package/dist/core/resolveScope.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/no-eval-ajv.d.ts +70 -0
- package/dist/no-eval-ajv.d.ts.map +1 -0
- package/dist/no-eval-ajv.js +247 -0
- package/dist/no-eval-ajv.js.map +1 -0
- package/dist/vue/composables/useProjection.d.ts.map +1 -1
- package/dist/vue/composables/useProjection.js +13 -9
- package/dist/vue/composables/useProjection.js.map +1 -1
- package/package.json +8 -2
- package/src/core/initFormData.ts +0 -2
- package/src/core/projection.ts +4 -16
- package/src/core/resolveScope.ts +5 -21
- package/src/index.ts +13 -2
- package/src/no-eval-ajv.ts +381 -0
- package/src/vue/composables/useProjection.ts +27 -12
- package/dist/debug/overlay.d.ts +0 -18
- package/dist/debug/overlay.d.ts.map +0 -1
- package/dist/debug/overlay.js +0 -308
- package/dist/debug/overlay.js.map +0 -1
- package/src/debug/overlay.ts +0 -358
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Validator,
|
|
3
|
+
type OutputUnit,
|
|
4
|
+
type Schema,
|
|
5
|
+
type SchemaDraft,
|
|
6
|
+
} from "@cfworker/json-schema";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CSP-safe JSON Schema validation backed by `@cfworker/json-schema`.
|
|
10
|
+
*
|
|
11
|
+
* Cloudflare Pages and similar strict-CSP environments forbid `new Function`,
|
|
12
|
+
* which is how AJV compiles validators. This factory returns an
|
|
13
|
+
* AJV-shaped facade whose `compile()` produces a synchronous validator
|
|
14
|
+
* function `(data) => boolean` with a mutable `errors` property — enough
|
|
15
|
+
* for `<JsonForms :ajv="..." />` to drop in without any other changes.
|
|
16
|
+
*
|
|
17
|
+
* Only `compile()` is functional; the rest of the surface (`addSchema`,
|
|
18
|
+
* `getSchema`, `removeSchema`, `addFormat`, `addKeyword`, `opts`) exists
|
|
19
|
+
* as no-ops for forward compatibility with plugins that probe the AJV
|
|
20
|
+
* interface but never reach those methods at runtime.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// AJV's ErrorObject shape. We don't import `ajv` here to keep the lib's
|
|
24
|
+
// zero-runtime-deps philosophy intact; the consumer's transitive AJV types
|
|
25
|
+
// are structurally compatible.
|
|
26
|
+
export interface NoEvalErrorObject {
|
|
27
|
+
instancePath: string;
|
|
28
|
+
schemaPath: string;
|
|
29
|
+
keyword: string;
|
|
30
|
+
params: Record<string, unknown>;
|
|
31
|
+
message?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface NoEvalValidateFunction {
|
|
35
|
+
(data: unknown): boolean;
|
|
36
|
+
errors: NoEvalErrorObject[] | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Minimal subset of AJV's surface that JsonForms touches. The factory
|
|
40
|
+
// returns this as `unknown as Ajv` at the call site; consumers cast on
|
|
41
|
+
// import or pass directly to `<JsonForms :ajv="..." />`.
|
|
42
|
+
export interface NoEvalAjv {
|
|
43
|
+
compile: (schema: unknown) => NoEvalValidateFunction;
|
|
44
|
+
addSchema: (schema: unknown, key?: string) => NoEvalAjv;
|
|
45
|
+
getSchema: (key: string) => NoEvalValidateFunction | undefined;
|
|
46
|
+
removeSchema: (schemaKeyRef?: unknown) => NoEvalAjv;
|
|
47
|
+
addFormat: (name: string, format: unknown) => NoEvalAjv;
|
|
48
|
+
addKeyword: (definition: unknown) => NoEvalAjv;
|
|
49
|
+
opts: Readonly<Record<string, unknown>>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface CreateNoEvalAjvOptions {
|
|
53
|
+
/**
|
|
54
|
+
* JSON Schema draft to validate against. Defaults to `'2020-12'` to match
|
|
55
|
+
* the spec; schemas authored against draft-07 should pass `'7'`.
|
|
56
|
+
*/
|
|
57
|
+
draft?: SchemaDraft;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const KEYWORD_WRAPPERS = new Set([
|
|
61
|
+
"properties",
|
|
62
|
+
"items",
|
|
63
|
+
"prefixItems",
|
|
64
|
+
"$ref",
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
const QUOTED_RE = /(['"])((?:\\.|(?!\1).)*?)\1/g;
|
|
68
|
+
|
|
69
|
+
function findQuoted(s: string): string[] {
|
|
70
|
+
const out: string[] = [];
|
|
71
|
+
let m: RegExpExecArray | null;
|
|
72
|
+
QUOTED_RE.lastIndex = 0;
|
|
73
|
+
while ((m = QUOTED_RE.exec(s)) !== null) {
|
|
74
|
+
out.push(m[2]!);
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function firstQuoted(s: string): string | undefined {
|
|
80
|
+
const all = findQuoted(s);
|
|
81
|
+
return all[0];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function allQuoted(s: string): string[] {
|
|
85
|
+
return findQuoted(s);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const NUMBER_RE = /-?\d+(?:\.\d+)?/g;
|
|
89
|
+
|
|
90
|
+
function extractNumbers(s: string): number[] {
|
|
91
|
+
const out: number[] = [];
|
|
92
|
+
let m: RegExpExecArray | null;
|
|
93
|
+
NUMBER_RE.lastIndex = 0;
|
|
94
|
+
while ((m = NUMBER_RE.exec(s)) !== null) {
|
|
95
|
+
out.push(Number(m[0]));
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function firstNumber(s: string): number | undefined {
|
|
101
|
+
const nums = extractNumbers(s);
|
|
102
|
+
return nums[0];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function stripPointerPrefix(p: string): string {
|
|
106
|
+
return p.startsWith("#") ? p.slice(1) : p;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface KeywordTransform {
|
|
110
|
+
params: Record<string, unknown>;
|
|
111
|
+
message: string | undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function transformByKeyword(unit: OutputUnit): KeywordTransform {
|
|
115
|
+
const { keyword, error } = unit;
|
|
116
|
+
|
|
117
|
+
switch (keyword) {
|
|
118
|
+
case "required": {
|
|
119
|
+
const prop = firstQuoted(error);
|
|
120
|
+
return {
|
|
121
|
+
params: { missingProperty: prop ?? "" },
|
|
122
|
+
message: prop
|
|
123
|
+
? `must have required property '${prop}'`
|
|
124
|
+
: "must have required property",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case "type": {
|
|
129
|
+
const quoted = allQuoted(error);
|
|
130
|
+
// cfworker emits `Instance type "X" is invalid. Expected "Y".` (single)
|
|
131
|
+
// or `... Expected "Y" or "Z".` (union). Per AJV: `params.type` is the
|
|
132
|
+
// expected type as a string; for unions it's comma-separated.
|
|
133
|
+
const expected = quoted.slice(1).join(",") || quoted[0];
|
|
134
|
+
const message = expected ? `must be ${expected}` : "must be of expected type";
|
|
135
|
+
return {
|
|
136
|
+
params: expected ? { type: expected } : {},
|
|
137
|
+
message,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
case "enum": {
|
|
142
|
+
// cfworker error: `Instance does not match any of [...].`
|
|
143
|
+
const match = error.match(/\[.*\]/);
|
|
144
|
+
let allowedValues: unknown[] = [];
|
|
145
|
+
if (match) {
|
|
146
|
+
try {
|
|
147
|
+
allowedValues = JSON.parse(match[0]);
|
|
148
|
+
} catch {
|
|
149
|
+
allowedValues = [];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
params: { allowedValues },
|
|
154
|
+
message: "must be equal to one of the allowed values",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case "const":
|
|
159
|
+
return {
|
|
160
|
+
params: {},
|
|
161
|
+
message: "must be equal to constant",
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
case "minimum": {
|
|
165
|
+
const limit = extractNumbers(error)[1];
|
|
166
|
+
return {
|
|
167
|
+
params: { comparison: ">=", limit: limit ?? 0 },
|
|
168
|
+
message: `must be >= ${limit ?? 0}`,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case "exclusiveMinimum": {
|
|
173
|
+
const limit = extractNumbers(error)[1];
|
|
174
|
+
return {
|
|
175
|
+
params: { comparison: ">", limit: limit ?? 0 },
|
|
176
|
+
message: `must be > ${limit ?? 0}`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
case "maximum": {
|
|
181
|
+
const limit = extractNumbers(error)[1];
|
|
182
|
+
return {
|
|
183
|
+
params: { comparison: "<=", limit: limit ?? 0 },
|
|
184
|
+
message: `must be <= ${limit ?? 0}`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
case "exclusiveMaximum": {
|
|
189
|
+
const limit = extractNumbers(error)[1];
|
|
190
|
+
return {
|
|
191
|
+
params: { comparison: "<", limit: limit ?? 0 },
|
|
192
|
+
message: `must be < ${limit ?? 0}`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
case "minLength": {
|
|
197
|
+
const limit = firstNumber(error) ?? 0;
|
|
198
|
+
return {
|
|
199
|
+
params: { limit },
|
|
200
|
+
message: `must NOT have fewer than ${limit} characters`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
case "maxLength": {
|
|
205
|
+
const limit = firstNumber(error) ?? 0;
|
|
206
|
+
return {
|
|
207
|
+
params: { limit },
|
|
208
|
+
message: `must NOT have more than ${limit} characters`,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
case "minItems": {
|
|
213
|
+
const limit = firstNumber(error) ?? 0;
|
|
214
|
+
return {
|
|
215
|
+
params: { limit },
|
|
216
|
+
message: `must NOT have fewer than ${limit} items`,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
case "maxItems": {
|
|
221
|
+
const limit = firstNumber(error) ?? 0;
|
|
222
|
+
return {
|
|
223
|
+
params: { limit },
|
|
224
|
+
message: `must NOT have more than ${limit} items`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
case "pattern": {
|
|
229
|
+
const pattern = firstQuoted(error) ?? "";
|
|
230
|
+
return {
|
|
231
|
+
params: { pattern },
|
|
232
|
+
message: `must match pattern "${pattern}"`,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
case "format": {
|
|
237
|
+
const format = firstQuoted(error) ?? "";
|
|
238
|
+
return {
|
|
239
|
+
params: { format },
|
|
240
|
+
message: `must match format "${format}"`,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
case "multipleOf": {
|
|
245
|
+
// cfworker emits two numbers: the value and the divisor.
|
|
246
|
+
const nums = extractNumbers(error);
|
|
247
|
+
const multipleOf = nums[1] ?? nums[0] ?? 1;
|
|
248
|
+
return {
|
|
249
|
+
params: { multipleOf },
|
|
250
|
+
message: `must be multiple of ${multipleOf}`,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
case "uniqueItems":
|
|
255
|
+
return {
|
|
256
|
+
params: {},
|
|
257
|
+
message: "must NOT have duplicate items",
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
case "additionalProperties": {
|
|
261
|
+
const additionalProperty = firstQuoted(error) ?? "";
|
|
262
|
+
return {
|
|
263
|
+
params: { additionalProperty },
|
|
264
|
+
message: `must NOT have additional property '${additionalProperty}'`,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
case "anyOf":
|
|
269
|
+
return { params: {}, message: "must match a schema in anyOf" };
|
|
270
|
+
|
|
271
|
+
case "oneOf":
|
|
272
|
+
return {
|
|
273
|
+
params: { passingSchemas: null },
|
|
274
|
+
message: "must match exactly one schema in oneOf",
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
case "allOf":
|
|
278
|
+
return { params: {}, message: "must match all schemas in allOf" };
|
|
279
|
+
|
|
280
|
+
case "not":
|
|
281
|
+
return { params: {}, message: "must NOT be valid against schema" };
|
|
282
|
+
|
|
283
|
+
default:
|
|
284
|
+
return { params: {}, message: undefined };
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Transform a single cfworker `OutputUnit` into an AJV-compatible
|
|
290
|
+
* `ErrorObject`, or `null` if the unit is a structural wrapper that should
|
|
291
|
+
* be filtered out (`properties` / `items` / `prefixItems` / `$ref`).
|
|
292
|
+
*
|
|
293
|
+
* Exported for unit testing.
|
|
294
|
+
*/
|
|
295
|
+
export function transformUnit(unit: OutputUnit): NoEvalErrorObject | null {
|
|
296
|
+
if (KEYWORD_WRAPPERS.has(unit.keyword)) return null;
|
|
297
|
+
|
|
298
|
+
const { params, message } = transformByKeyword(unit);
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
instancePath: stripPointerPrefix(unit.instanceLocation),
|
|
302
|
+
schemaPath: unit.keywordLocation,
|
|
303
|
+
keyword: unit.keyword,
|
|
304
|
+
params,
|
|
305
|
+
message: message ?? unit.error,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Transform a cfworker `OutputUnit[]` into an AJV-compatible
|
|
311
|
+
* `ErrorObject[]`, with structural wrappers filtered out.
|
|
312
|
+
*
|
|
313
|
+
* Exported for unit testing.
|
|
314
|
+
*/
|
|
315
|
+
export function transformErrors(units: OutputUnit[]): NoEvalErrorObject[] {
|
|
316
|
+
const out: NoEvalErrorObject[] = [];
|
|
317
|
+
for (const unit of units) {
|
|
318
|
+
const transformed = transformUnit(unit);
|
|
319
|
+
if (transformed !== null) out.push(transformed);
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const FROZEN_OPTS: Readonly<Record<string, unknown>> = Object.freeze({
|
|
325
|
+
allErrors: true,
|
|
326
|
+
verbose: true,
|
|
327
|
+
errorDataPath: "",
|
|
328
|
+
strict: false,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Build a CSP-safe AJV-shaped validator backed by `@cfworker/json-schema`.
|
|
333
|
+
*
|
|
334
|
+
* Each `compile(schema)` call constructs a `Validator` and returns a
|
|
335
|
+
* synchronous validator function. The validator function's `errors`
|
|
336
|
+
* property is reassigned on every call, matching AJV's contract.
|
|
337
|
+
*
|
|
338
|
+
* Validators are memoized per-schema via a `WeakMap`, so JsonForms's
|
|
339
|
+
* repeated `compile()` calls on prop changes don't re-parse the schema
|
|
340
|
+
* graph each time.
|
|
341
|
+
*/
|
|
342
|
+
export function createNoEvalAjv(
|
|
343
|
+
options: CreateNoEvalAjvOptions = {},
|
|
344
|
+
): NoEvalAjv {
|
|
345
|
+
const draft: SchemaDraft = options.draft ?? "2020-12";
|
|
346
|
+
const cache = new WeakMap<object, NoEvalValidateFunction>();
|
|
347
|
+
|
|
348
|
+
const compile = (schema: unknown): NoEvalValidateFunction => {
|
|
349
|
+
if (schema && typeof schema === "object") {
|
|
350
|
+
const cached = cache.get(schema as object);
|
|
351
|
+
if (cached) return cached;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const validator = new Validator(schema as Schema | boolean, draft, false);
|
|
355
|
+
|
|
356
|
+
const fn: NoEvalValidateFunction = ((data: unknown) => {
|
|
357
|
+
const result = validator.validate(data);
|
|
358
|
+
fn.errors = result.valid ? null : transformErrors(result.errors);
|
|
359
|
+
return result.valid;
|
|
360
|
+
}) as NoEvalValidateFunction;
|
|
361
|
+
|
|
362
|
+
fn.errors = null;
|
|
363
|
+
|
|
364
|
+
if (schema && typeof schema === "object") {
|
|
365
|
+
cache.set(schema as object, fn);
|
|
366
|
+
}
|
|
367
|
+
return fn;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const facade: NoEvalAjv = {
|
|
371
|
+
compile,
|
|
372
|
+
addSchema: () => facade,
|
|
373
|
+
getSchema: () => undefined,
|
|
374
|
+
removeSchema: () => facade,
|
|
375
|
+
addFormat: () => facade,
|
|
376
|
+
addKeyword: () => facade,
|
|
377
|
+
opts: FROZEN_OPTS,
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
return facade;
|
|
381
|
+
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getProjectedSchema,
|
|
6
6
|
parseProjectionPath,
|
|
7
7
|
} from "../../core/projection";
|
|
8
|
+
import { deref } from "../../core/refs";
|
|
8
9
|
|
|
9
10
|
interface ProjectionControl {
|
|
10
11
|
data: unknown;
|
|
@@ -48,27 +49,34 @@ function resolveLabel(
|
|
|
48
49
|
* Determine whether the leaf of a projection path is listed in its parent
|
|
49
50
|
* schema's `required` array. Numeric leaf segments (array indices) are not
|
|
50
51
|
* considered "required properties".
|
|
52
|
+
*
|
|
53
|
+
* Dereferences `$ref` at every step against `root` (defaulting to `schema`)
|
|
54
|
+
* so that schemas like `items: { $ref: '#/$defs/Foo' }` resolve correctly.
|
|
51
55
|
*/
|
|
52
56
|
function isProjectedFieldRequired(
|
|
53
57
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
58
|
schema: Record<string, any>,
|
|
55
59
|
path: string,
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
root?: Record<string, any>,
|
|
56
62
|
): boolean {
|
|
57
63
|
const segments = parseProjectionPath(path);
|
|
58
64
|
if (segments.length === 0) return false;
|
|
65
|
+
const rootSchema = root ?? schema;
|
|
59
66
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
-
let current: Record<string, any> = schema;
|
|
67
|
+
let current: Record<string, any> | undefined = deref(schema, rootSchema);
|
|
61
68
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
62
69
|
const seg = segments[i]!;
|
|
63
70
|
if (typeof seg === "number") {
|
|
64
|
-
current = current?.items;
|
|
71
|
+
current = deref(current?.items, rootSchema);
|
|
65
72
|
} else {
|
|
66
|
-
current = current?.properties?.[seg];
|
|
73
|
+
current = deref(current?.properties?.[seg], rootSchema);
|
|
67
74
|
}
|
|
68
75
|
if (!current) return false;
|
|
69
76
|
}
|
|
70
77
|
const last = segments[segments.length - 1];
|
|
71
78
|
if (typeof last !== "string") return false;
|
|
79
|
+
current = deref(current, rootSchema);
|
|
72
80
|
return Array.isArray(current?.required) && current.required.includes(last);
|
|
73
81
|
}
|
|
74
82
|
|
|
@@ -162,13 +170,16 @@ export function useProjection(
|
|
|
162
170
|
};
|
|
163
171
|
}
|
|
164
172
|
|
|
165
|
-
// Inject JSONForms state to access raw AJV errors for projected sub-paths
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
const jsonforms = inject<{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
// Inject JSONForms state to access raw AJV errors for projected sub-paths,
|
|
174
|
+
// and the root schema so that `$ref` resolution inside the projected slice
|
|
175
|
+
// can find `$defs` (which live at the root, not on the control's schema).
|
|
176
|
+
const jsonforms = inject<{
|
|
177
|
+
core?: {
|
|
178
|
+
errors?: ErrorLike[];
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
180
|
+
schema?: Record<string, any>;
|
|
181
|
+
};
|
|
182
|
+
} | null>("jsonforms", null);
|
|
172
183
|
|
|
173
184
|
const fullProjectedPath = control.value.path + "." + projection;
|
|
174
185
|
|
|
@@ -181,7 +192,11 @@ export function useProjection(
|
|
|
181
192
|
);
|
|
182
193
|
|
|
183
194
|
const projectedRequired = computed(() =>
|
|
184
|
-
isProjectedFieldRequired(
|
|
195
|
+
isProjectedFieldRequired(
|
|
196
|
+
control.value.schema,
|
|
197
|
+
projection,
|
|
198
|
+
jsonforms?.core?.schema ?? control.value.schema,
|
|
199
|
+
),
|
|
185
200
|
);
|
|
186
201
|
|
|
187
202
|
const label = computed(() =>
|
|
@@ -195,7 +210,7 @@ export function useProjection(
|
|
|
195
210
|
const projectedErrors = computed(() => {
|
|
196
211
|
const baseErrors = normalizeErrors(control.value.errors || "");
|
|
197
212
|
|
|
198
|
-
const rawErrors = jsonforms?.core?.errors ?? [];
|
|
213
|
+
const rawErrors = jsonforms?.core?.errors ?? ([] as ErrorLike[]);
|
|
199
214
|
const matching = rawErrors.filter(
|
|
200
215
|
(err) => getErrorPath(err) === fullProjectedPath,
|
|
201
216
|
);
|
package/dist/debug/overlay.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-DOM debug overlay for `@narrative.io/jsonforms-provider-protocols`.
|
|
3
|
-
*
|
|
4
|
-
* Renders a fixed-position panel with a scrollable list of structured log
|
|
5
|
-
* entries. Used in place of `console.*` because some host apps strip console
|
|
6
|
-
* output in production. No-op unless explicitly enabled at runtime via
|
|
7
|
-
* either `window.__PP_DEBUG__ = true` or `localStorage.PP_DEBUG = "1"`.
|
|
8
|
-
*
|
|
9
|
-
* Internal API. Not part of the package's public surface.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Append a structured debug entry to the in-DOM overlay. No-op unless the
|
|
13
|
-
* runtime gate is on (`window.__PP_DEBUG__ === true` or
|
|
14
|
-
* `localStorage.PP_DEBUG === "1"`). Stringification is lazy: the payload is
|
|
15
|
-
* not serialized when the gate is off, so this is safe to leave in hot paths.
|
|
16
|
-
*/
|
|
17
|
-
export declare function debugLog(label: string, payload: unknown): void;
|
|
18
|
-
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/debug/overlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA0TH;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CA4B9D"}
|