@kumwe/studio-core 0.1.0-alpha.7 → 0.1.0-beta.2
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/README.md +87 -4
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/dist/authentication-lifetime.d.ts +16 -0
- package/dist/authentication-lifetime.d.ts.map +1 -0
- package/dist/authentication-lifetime.js +1 -0
- package/dist/binding-projection.d.ts +47 -0
- package/dist/binding-projection.d.ts.map +1 -0
- package/dist/binding-projection.js +1 -0
- package/dist/canonical.js +1 -100
- package/dist/clone.js +1 -4
- package/dist/commands.d.ts +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +1 -799
- package/dist/contextual-session.d.ts +112 -0
- package/dist/contextual-session.d.ts.map +1 -0
- package/dist/contextual-session.js +1 -0
- package/dist/contributions.d.ts +63 -2
- package/dist/contributions.d.ts.map +1 -1
- package/dist/contributions.js +1 -302
- package/dist/deployment-validation.d.ts +10 -0
- package/dist/deployment-validation.d.ts.map +1 -0
- package/dist/deployment-validation.js +1 -0
- package/dist/entry-commands.js +1 -36
- package/dist/extension-sdk.d.ts +12 -6
- package/dist/extension-sdk.d.ts.map +1 -1
- package/dist/extension-sdk.js +1 -188
- package/dist/history.d.ts +12 -2
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +1 -63
- package/dist/host-session.d.ts +93 -0
- package/dist/host-session.d.ts.map +1 -0
- package/dist/host-session.js +1 -0
- package/dist/http-authoring-contract.d.ts +29 -0
- package/dist/http-authoring-contract.d.ts.map +1 -0
- package/dist/http-authoring-contract.js +1 -0
- package/dist/http-host-adapter.d.ts +173 -0
- package/dist/http-host-adapter.d.ts.map +1 -0
- package/dist/http-host-adapter.js +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -18
- package/dist/layout.d.ts +66 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +1 -0
- package/dist/migrations.js +1 -83
- package/dist/model-commands.js +1 -21
- package/dist/modes.js +1 -280
- package/dist/negotiation.js +1 -65
- package/dist/production-values.d.ts +12 -0
- package/dist/production-values.d.ts.map +1 -0
- package/dist/production-values.js +1 -0
- package/dist/production.d.ts +86 -0
- package/dist/production.d.ts.map +1 -0
- package/dist/production.js +1 -0
- package/dist/profile-validator.d.ts +2 -2
- package/dist/profile-validator.d.ts.map +1 -1
- package/dist/profile-validator.js +1 -783
- package/dist/recipes.js +1 -34
- package/dist/registry.js +1 -56
- package/dist/schema-profile.d.ts +23 -5
- package/dist/schema-profile.d.ts.map +1 -1
- package/dist/schema-profile.js +1 -390
- package/dist/semver.js +1 -128
- package/dist/session-policy.d.ts +23 -0
- package/dist/session-policy.d.ts.map +1 -0
- package/dist/session-policy.js +1 -0
- package/dist/session.d.ts +14 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +1 -178
- package/dist/strict-json.d.ts +7 -0
- package/dist/strict-json.d.ts.map +1 -0
- package/dist/strict-json.js +2 -0
- package/dist/url-policy.js +1 -248
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -398
- package/package.json +5 -3
- package/dist/canonical.js.map +0 -1
- package/dist/clone.js.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/contributions.js.map +0 -1
- package/dist/entry-commands.js.map +0 -1
- package/dist/extension-sdk.js.map +0 -1
- package/dist/history.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migrations.js.map +0 -1
- package/dist/model-commands.js.map +0 -1
- package/dist/modes.js.map +0 -1
- package/dist/negotiation.js.map +0 -1
- package/dist/profile-validator.js.map +0 -1
- package/dist/recipes.js.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/schema-profile.js.map +0 -1
- package/dist/semver.js.map +0 -1
- package/dist/session.js.map +0 -1
- package/dist/url-policy.js.map +0 -1
- package/dist/validation.js.map +0 -1
package/dist/recipes.js
CHANGED
|
@@ -1,34 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
/**
|
|
3
|
-
* The reserved node property that records which theme recipe an author
|
|
4
|
-
* selected. Recipe selection is canonically an atomic batch of set-property
|
|
5
|
-
* operations, so it inherits batch atomicity and verified inverses from the
|
|
6
|
-
* command contract instead of introducing a new command type.
|
|
7
|
-
*/
|
|
8
|
-
export const RECIPE_MARKER_PROPERTY = 'studio.recipe';
|
|
9
|
-
/**
|
|
10
|
-
* Expand a theme recipe selection into the deterministic batch operations
|
|
11
|
-
* that apply it to one node: every design value of the recipe, in sorted
|
|
12
|
-
* member order, followed by the reserved recipe marker property.
|
|
13
|
-
*/
|
|
14
|
-
export function recipeSelectionOperations(node, theme, recipeId) {
|
|
15
|
-
const recipe = theme.recipes.find((candidate) => candidate.id === recipeId);
|
|
16
|
-
if (recipe === undefined) {
|
|
17
|
-
throw new Error(`Theme ${theme.id} does not declare a recipe ${recipeId}.`);
|
|
18
|
-
}
|
|
19
|
-
if (recipe.blockType !== node.type) {
|
|
20
|
-
throw new Error(`Recipe ${recipeId} targets ${recipe.blockType} blocks, not ${node.type} node ${node.id}.`);
|
|
21
|
-
}
|
|
22
|
-
const operations = Object.entries(recipe.designValues)
|
|
23
|
-
.sort(([left], [right]) => (left < right ? -1 : 1))
|
|
24
|
-
.map(([property, value]) => ({
|
|
25
|
-
payload: { nodeId: node.id, property, value: cloneContractValue(value) },
|
|
26
|
-
type: 'studio.command/set-property',
|
|
27
|
-
}));
|
|
28
|
-
operations.push({
|
|
29
|
-
payload: { nodeId: node.id, property: RECIPE_MARKER_PROPERTY, value: recipeId },
|
|
30
|
-
type: 'studio.command/set-property',
|
|
31
|
-
});
|
|
32
|
-
return operations;
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=recipes.js.map
|
|
1
|
+
import{cloneContractValue as e}from"./clone.js";export const RECIPE_MARKER_PROPERTY=`studio.recipe`;export function recipeSelectionOperations(t,n,r){let i=n.recipes.find(e=>e.id===r);if(i===void 0)throw Error(`Theme ${n.id} does not declare a recipe ${r}.`);if(i.blockType!==t.type)throw Error(`Recipe ${r} targets ${i.blockType} blocks, not ${t.type} node ${t.id}.`);let a=Object.entries(i.designValues).sort(([e],[t])=>e<t?-1:1).map(([n,r])=>({payload:{nodeId:t.id,property:n,value:e(r)},type:`studio.command/set-property`}));return a.push({payload:{nodeId:t.id,property:`studio.recipe`,value:r},type:`studio.command/set-property`}),a}
|
package/dist/registry.js
CHANGED
|
@@ -1,56 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { assertStudioPropertySchema } from './schema-profile.js';
|
|
3
|
-
export class BlockRegistry {
|
|
4
|
-
#definitions = new Map();
|
|
5
|
-
constructor(definitions = []) {
|
|
6
|
-
for (const definition of definitions) {
|
|
7
|
-
this.register(definition);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
register(definition, options = {}) {
|
|
11
|
-
assertStudioPropertySchema(definition.propertySchema);
|
|
12
|
-
if (options.verifiedIntegrity !== undefined && !isIntegrity(options.verifiedIntegrity)) {
|
|
13
|
-
throw new TypeError('Host-verified block integrity must be a canonical SRI sha256/384/512 value.');
|
|
14
|
-
}
|
|
15
|
-
let versions = this.#definitions.get(definition.type);
|
|
16
|
-
if (versions === undefined) {
|
|
17
|
-
versions = new Map();
|
|
18
|
-
this.#definitions.set(definition.type, versions);
|
|
19
|
-
}
|
|
20
|
-
if (versions.has(definition.version)) {
|
|
21
|
-
throw new Error(`Block ${definition.type}@${definition.version} is already registered.`);
|
|
22
|
-
}
|
|
23
|
-
const registration = {
|
|
24
|
-
definition: cloneContractValue(definition),
|
|
25
|
-
};
|
|
26
|
-
if (options.verifiedIntegrity !== undefined) {
|
|
27
|
-
registration.verifiedIntegrity = options.verifiedIntegrity;
|
|
28
|
-
}
|
|
29
|
-
versions.set(definition.version, registration);
|
|
30
|
-
}
|
|
31
|
-
resolve(type, version) {
|
|
32
|
-
return this.resolveRegistration(type, version)?.definition;
|
|
33
|
-
}
|
|
34
|
-
resolveRegistration(type, version) {
|
|
35
|
-
const registration = this.#definitions.get(type)?.get(version);
|
|
36
|
-
if (registration === undefined) {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
const resolved = {
|
|
40
|
-
definition: cloneContractValue(registration.definition),
|
|
41
|
-
};
|
|
42
|
-
if (registration.verifiedIntegrity !== undefined) {
|
|
43
|
-
resolved.verifiedIntegrity = registration.verifiedIntegrity;
|
|
44
|
-
}
|
|
45
|
-
return resolved;
|
|
46
|
-
}
|
|
47
|
-
definitions() {
|
|
48
|
-
return [...this.#definitions.values()]
|
|
49
|
-
.flatMap((versions) => [...versions.values()])
|
|
50
|
-
.map((registration) => cloneContractValue(registration.definition));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
function isIntegrity(value) {
|
|
54
|
-
return /^(?:sha256-[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=|sha384-[A-Za-z0-9+/]{64}|sha512-[A-Za-z0-9+/]{85}[AQgw]==)(?![\s\S])/u.test(value);
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=registry.js.map
|
|
1
|
+
import{cloneContractValue as e}from"./clone.js";import{assertStudioPropertySchema as t}from"./schema-profile.js";export class BlockRegistry{#definitions=new Map;constructor(e=[]){for(let t of e)this.register(t)}register(n,i={}){if(t(n.propertySchema),i.verifiedIntegrity!==void 0&&!r(i.verifiedIntegrity))throw TypeError(`Host-verified block integrity must be a canonical SRI sha256/384/512 value.`);let a=this.#definitions.get(n.type);if(a===void 0&&(a=new Map,this.#definitions.set(n.type,a)),a.has(n.version))throw Error(`Block ${n.type}@${n.version} is already registered.`);let o={definition:e(n)};i.verifiedIntegrity!==void 0&&(o.verifiedIntegrity=i.verifiedIntegrity),a.set(n.version,o)}resolve(e,t){return this.resolveRegistration(e,t)?.definition}resolveRegistration(t,n){let r=this.#definitions.get(t)?.get(n);if(r===void 0)return;let i={definition:e(r.definition)};return r.verifiedIntegrity!==void 0&&(i.verifiedIntegrity=r.verifiedIntegrity),i}definitions(){return[...this.#definitions.values()].flatMap(e=>[...e.values()]).map(t=>e(t.definition))}}function r(e){return/^(?:sha256-[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=|sha384-[A-Za-z0-9+/]{64}|sha512-[A-Za-z0-9+/]{85}[AQgw]==)(?![\s\S])/u.test(e)}
|
package/dist/schema-profile.d.ts
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import type { JsonSchema } from '@kumwe/studio-protocol';
|
|
2
|
+
import { type SchemaValidationError } from './profile-validator.js';
|
|
3
|
+
/** Published complexity limits, pinned to `$defs/limits` in the meta-schema. */
|
|
4
|
+
export declare const STUDIO_SCHEMA_PROFILE_LIMITS: Readonly<Record<string, number>>;
|
|
5
|
+
export type StudioSchemaProfileErrorCode = 'invalid-root' | 'unsupported-keyword' | 'invalid-keyword-value' | 'unsafe-member' | 'limit-exceeded' | 'invalid-reference' | 'recursive-schema';
|
|
6
|
+
export declare const STUDIO_SCHEMA_PROFILE_ERROR_CODES: readonly StudioSchemaProfileErrorCode[];
|
|
7
|
+
/** A deterministic admission failure suitable for cross-runtime corpus comparison. */
|
|
8
|
+
export declare class StudioSchemaProfileError extends TypeError {
|
|
9
|
+
readonly code: StudioSchemaProfileErrorCode;
|
|
10
|
+
/** JSON Pointer to the rejected schema location; the empty string is the root. */
|
|
11
|
+
readonly schemaPath: string;
|
|
12
|
+
constructor(code: StudioSchemaProfileErrorCode, schemaPath: string, message: string, options?: ErrorOptions);
|
|
13
|
+
}
|
|
14
|
+
/** Public, implementation-neutral shape returned by a compiled property schema. */
|
|
15
|
+
export interface StudioPropertySchemaValidator {
|
|
16
|
+
readonly errors: SchemaValidationError[] | null;
|
|
17
|
+
validate(instance: unknown): boolean;
|
|
18
|
+
}
|
|
2
19
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
20
|
+
* Admit and compile one contributed block property schema. The alpha profile
|
|
21
|
+
* is deliberately object-rooted, closed, local-reference-only, non-recursive,
|
|
22
|
+
* and format-free. The returned interpreter performs no code generation.
|
|
6
23
|
*/
|
|
7
|
-
export declare
|
|
8
|
-
|
|
24
|
+
export declare function compileStudioPropertySchema(schema: unknown): StudioPropertySchemaValidator;
|
|
25
|
+
/** Assert that a value is an admitted Studio property schema. */
|
|
26
|
+
export declare function assertStudioPropertySchema(schema: unknown): asserts schema is JsonSchema;
|
|
9
27
|
//# sourceMappingURL=schema-profile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-profile.d.ts","sourceRoot":"","sources":["../src/schema-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema-profile.d.ts","sourceRoot":"","sources":["../src/schema-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAoB1F,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBxE,CAAC;AAEH,MAAM,MAAM,4BAA4B,GACpC,cAAc,GACd,qBAAqB,GACrB,uBAAuB,GACvB,eAAe,GACf,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,CAAC;AAEvB,eAAO,MAAM,iCAAiC,EAAE,SAAS,4BAA4B,EASjF,CAAC;AAEL,sFAAsF;AACtF,qBAAa,wBAAyB,SAAQ,SAAS;IACrD,SAAgB,IAAI,EAAE,4BAA4B,CAAC;IACnD,kFAAkF;IAClF,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAGjC,IAAI,EAAE,4BAA4B,EAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAOzB;AAED,mFAAmF;AACnF,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC;AAsDD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,OAAO,GAAG,6BAA6B,CA4D1F;AAED,iEAAiE;AACjE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,UAAU,CAExF"}
|
package/dist/schema-profile.js
CHANGED
|
@@ -1,390 +1 @@
|
|
|
1
|
-
import { compileProfileSchema } from './profile-validator.js';
|
|
2
|
-
const DRAFT_2020_12 = 'https://json-schema.org/draft/2020-12/schema';
|
|
3
|
-
const MAX_ALTERNATIVES = 64;
|
|
4
|
-
const MAX_ENUM_MEMBERS = 1_024;
|
|
5
|
-
const MAX_JSON_DEPTH = 64;
|
|
6
|
-
const MAX_JSON_ITEMS = 10_000;
|
|
7
|
-
const MAX_JSON_PROPERTIES = 1_000;
|
|
8
|
-
const MAX_REFERENCES = 128;
|
|
9
|
-
const MAX_SCHEMA_BYTES = 262_144;
|
|
10
|
-
const MAX_SCHEMA_DEPTH = 32;
|
|
11
|
-
const MAX_SCHEMA_MAP_PROPERTIES = 512;
|
|
12
|
-
const MAX_SCHEMA_NODES = 1_024;
|
|
13
|
-
const MAX_OBJECT_KEY_LENGTH = 200;
|
|
14
|
-
/**
|
|
15
|
-
* The published complexity limits of the Studio Schema Profile. The
|
|
16
|
-
* machine-readable meta-schema (`schema-profile.schema.json`) carries the
|
|
17
|
-
* same values; a parity test keeps the two from drifting.
|
|
18
|
-
*/
|
|
19
|
-
export const STUDIO_SCHEMA_PROFILE_LIMITS = Object.freeze({
|
|
20
|
-
maxAlternatives: MAX_ALTERNATIVES,
|
|
21
|
-
maxEnumMembers: MAX_ENUM_MEMBERS,
|
|
22
|
-
maxJsonDepth: MAX_JSON_DEPTH,
|
|
23
|
-
maxJsonItems: MAX_JSON_ITEMS,
|
|
24
|
-
maxJsonProperties: MAX_JSON_PROPERTIES,
|
|
25
|
-
maxObjectKeyLength: MAX_OBJECT_KEY_LENGTH,
|
|
26
|
-
maxReferences: MAX_REFERENCES,
|
|
27
|
-
maxSchemaBytes: MAX_SCHEMA_BYTES,
|
|
28
|
-
maxSchemaDepth: MAX_SCHEMA_DEPTH,
|
|
29
|
-
maxSchemaMapProperties: MAX_SCHEMA_MAP_PROPERTIES,
|
|
30
|
-
maxSchemaNodes: MAX_SCHEMA_NODES,
|
|
31
|
-
});
|
|
32
|
-
const allowedKeywords = new Set([
|
|
33
|
-
'$defs',
|
|
34
|
-
'$ref',
|
|
35
|
-
'$schema',
|
|
36
|
-
'additionalProperties',
|
|
37
|
-
'allOf',
|
|
38
|
-
'anyOf',
|
|
39
|
-
'const',
|
|
40
|
-
'default',
|
|
41
|
-
'dependentRequired',
|
|
42
|
-
'description',
|
|
43
|
-
'else',
|
|
44
|
-
'enum',
|
|
45
|
-
'examples',
|
|
46
|
-
'exclusiveMaximum',
|
|
47
|
-
'exclusiveMinimum',
|
|
48
|
-
'if',
|
|
49
|
-
'items',
|
|
50
|
-
'maxItems',
|
|
51
|
-
'maxLength',
|
|
52
|
-
'maxProperties',
|
|
53
|
-
'maximum',
|
|
54
|
-
'minItems',
|
|
55
|
-
'minLength',
|
|
56
|
-
'minProperties',
|
|
57
|
-
'minimum',
|
|
58
|
-
'multipleOf',
|
|
59
|
-
'not',
|
|
60
|
-
'oneOf',
|
|
61
|
-
'prefixItems',
|
|
62
|
-
'properties',
|
|
63
|
-
'propertyNames',
|
|
64
|
-
'readOnly',
|
|
65
|
-
'required',
|
|
66
|
-
'then',
|
|
67
|
-
'title',
|
|
68
|
-
'type',
|
|
69
|
-
'uniqueItems',
|
|
70
|
-
'writeOnly',
|
|
71
|
-
]);
|
|
72
|
-
export function assertStudioPropertySchema(schema) {
|
|
73
|
-
const state = { references: 0, schemaNodes: 0, seen: new WeakSet() };
|
|
74
|
-
visitSchema(schema, '$', 1, state);
|
|
75
|
-
assertNonRecursiveSchema(schema);
|
|
76
|
-
let serialized;
|
|
77
|
-
try {
|
|
78
|
-
serialized = JSON.stringify(schema);
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
throw new TypeError('Studio property schema must be an acyclic JSON document.', {
|
|
82
|
-
cause: error,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
if (utf8ByteLength(serialized) > MAX_SCHEMA_BYTES) {
|
|
86
|
-
throw new RangeError(`Studio property schema exceeds ${MAX_SCHEMA_BYTES} bytes.`);
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
// The eval-free interpreter is the reference implementation: it validates
|
|
90
|
-
// keyword operands, compiles bounded lexical patterns, and resolves local
|
|
91
|
-
// references, so a schema that fails to compile is rejected atomically.
|
|
92
|
-
compileProfileSchema(schema);
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
throw new TypeError('Studio property schema does not compile under the strict profile.', {
|
|
96
|
-
cause: error,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function visitSchema(value, path, depth, state) {
|
|
101
|
-
if (!isRecord(value)) {
|
|
102
|
-
throw new TypeError(`${path} must be a JSON Schema object.`);
|
|
103
|
-
}
|
|
104
|
-
trackObject(value, path, state);
|
|
105
|
-
if (depth > MAX_SCHEMA_DEPTH) {
|
|
106
|
-
throw new RangeError(`${path} exceeds the Studio Schema Profile depth limit.`);
|
|
107
|
-
}
|
|
108
|
-
state.schemaNodes += 1;
|
|
109
|
-
if (state.schemaNodes > MAX_SCHEMA_NODES) {
|
|
110
|
-
throw new RangeError(`Studio property schema exceeds ${MAX_SCHEMA_NODES} schema nodes.`);
|
|
111
|
-
}
|
|
112
|
-
for (const [keyword, keywordValue] of Object.entries(value)) {
|
|
113
|
-
assertSafeObjectKey(keyword, path);
|
|
114
|
-
if (!allowedKeywords.has(keyword)) {
|
|
115
|
-
throw new TypeError(`${path}.${keyword} is not allowed by the Studio Schema Profile.`);
|
|
116
|
-
}
|
|
117
|
-
switch (keyword) {
|
|
118
|
-
case '$defs':
|
|
119
|
-
case 'properties':
|
|
120
|
-
visitSchemaMap(keywordValue, `${path}.${keyword}`, depth + 1, state);
|
|
121
|
-
break;
|
|
122
|
-
case 'additionalProperties':
|
|
123
|
-
case 'else':
|
|
124
|
-
case 'if':
|
|
125
|
-
case 'items':
|
|
126
|
-
case 'not':
|
|
127
|
-
case 'propertyNames':
|
|
128
|
-
case 'then':
|
|
129
|
-
visitSubschema(keywordValue, `${path}.${keyword}`, depth + 1, state);
|
|
130
|
-
break;
|
|
131
|
-
case 'allOf':
|
|
132
|
-
case 'anyOf':
|
|
133
|
-
case 'oneOf':
|
|
134
|
-
case 'prefixItems':
|
|
135
|
-
visitSchemaArray(keywordValue, `${path}.${keyword}`, depth + 1, state);
|
|
136
|
-
break;
|
|
137
|
-
case '$ref':
|
|
138
|
-
visitReference(keywordValue, `${path}.${keyword}`, state);
|
|
139
|
-
break;
|
|
140
|
-
case '$schema':
|
|
141
|
-
if (keywordValue !== DRAFT_2020_12) {
|
|
142
|
-
throw new TypeError(`${path} must declare JSON Schema Draft 2020-12.`);
|
|
143
|
-
}
|
|
144
|
-
break;
|
|
145
|
-
case 'enum':
|
|
146
|
-
if (!Array.isArray(keywordValue) || keywordValue.length > MAX_ENUM_MEMBERS) {
|
|
147
|
-
throw new RangeError(`${path}.enum exceeds ${MAX_ENUM_MEMBERS} members.`);
|
|
148
|
-
}
|
|
149
|
-
visitJsonValue(keywordValue, `${path}.enum`, depth + 1, state);
|
|
150
|
-
break;
|
|
151
|
-
default:
|
|
152
|
-
visitJsonValue(keywordValue, `${path}.${keyword}`, depth + 1, state);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
function visitSchemaMap(value, path, depth, state) {
|
|
157
|
-
if (!isRecord(value)) {
|
|
158
|
-
throw new TypeError(`${path} must be an object of schemas.`);
|
|
159
|
-
}
|
|
160
|
-
trackObject(value, path, state);
|
|
161
|
-
const entries = Object.entries(value);
|
|
162
|
-
if (entries.length > MAX_SCHEMA_MAP_PROPERTIES) {
|
|
163
|
-
throw new RangeError(`${path} exceeds ${MAX_SCHEMA_MAP_PROPERTIES} schema entries.`);
|
|
164
|
-
}
|
|
165
|
-
for (const [name, schema] of entries) {
|
|
166
|
-
assertSafeObjectKey(name, path);
|
|
167
|
-
visitSchema(schema, `${path}.${name}`, depth, state);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function visitSchemaArray(value, path, depth, state) {
|
|
171
|
-
if (!Array.isArray(value) || value.length > MAX_ALTERNATIVES) {
|
|
172
|
-
throw new RangeError(`${path} must contain at most ${MAX_ALTERNATIVES} schemas.`);
|
|
173
|
-
}
|
|
174
|
-
trackObject(value, path, state);
|
|
175
|
-
assertDenseArray(value, path);
|
|
176
|
-
for (const [index, schema] of value.entries()) {
|
|
177
|
-
visitSubschema(schema, `${path}[${index}]`, depth, state);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
function visitSubschema(value, path, depth, state) {
|
|
181
|
-
if (typeof value === 'boolean') {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
visitSchema(value, path, depth, state);
|
|
185
|
-
}
|
|
186
|
-
function visitReference(value, path, state) {
|
|
187
|
-
if (typeof value !== 'string' ||
|
|
188
|
-
(value !== '#' && !value.startsWith('#/')) ||
|
|
189
|
-
value.length > 500) {
|
|
190
|
-
throw new TypeError(`${path} must be a bounded local JSON Pointer reference.`);
|
|
191
|
-
}
|
|
192
|
-
state.references += 1;
|
|
193
|
-
if (state.references > MAX_REFERENCES) {
|
|
194
|
-
throw new RangeError(`Studio property schema exceeds ${MAX_REFERENCES} references.`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
function visitJsonValue(value, path, depth, state) {
|
|
198
|
-
if (value === null ||
|
|
199
|
-
typeof value === 'boolean' ||
|
|
200
|
-
typeof value === 'string' ||
|
|
201
|
-
(typeof value === 'number' && Number.isFinite(value))) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
if (depth > MAX_JSON_DEPTH) {
|
|
205
|
-
throw new RangeError(`${path} exceeds the Studio Schema Profile JSON depth limit.`);
|
|
206
|
-
}
|
|
207
|
-
if (Array.isArray(value)) {
|
|
208
|
-
trackObject(value, path, state);
|
|
209
|
-
assertDenseArray(value, path);
|
|
210
|
-
if (value.length > MAX_JSON_ITEMS) {
|
|
211
|
-
throw new RangeError(`${path} exceeds ${MAX_JSON_ITEMS} JSON items.`);
|
|
212
|
-
}
|
|
213
|
-
for (const [index, entry] of value.entries()) {
|
|
214
|
-
visitJsonValue(entry, `${path}[${index}]`, depth + 1, state);
|
|
215
|
-
}
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
if (isRecord(value)) {
|
|
219
|
-
trackObject(value, path, state);
|
|
220
|
-
const entries = Object.entries(value);
|
|
221
|
-
if (entries.length > MAX_JSON_PROPERTIES) {
|
|
222
|
-
throw new RangeError(`${path} exceeds ${MAX_JSON_PROPERTIES} JSON properties.`);
|
|
223
|
-
}
|
|
224
|
-
for (const [key, entry] of entries) {
|
|
225
|
-
assertSafeObjectKey(key, path);
|
|
226
|
-
visitJsonValue(entry, `${path}.${key}`, depth + 1, state);
|
|
227
|
-
}
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
throw new TypeError(`${path} is not JSON-compatible.`);
|
|
231
|
-
}
|
|
232
|
-
function assertSafeObjectKey(key, path) {
|
|
233
|
-
if (key.length === 0 ||
|
|
234
|
-
key.length > MAX_OBJECT_KEY_LENGTH ||
|
|
235
|
-
key === '__proto__' ||
|
|
236
|
-
key === 'constructor' ||
|
|
237
|
-
key === 'prototype' ||
|
|
238
|
-
containsControlCharacter(key)) {
|
|
239
|
-
throw new TypeError(`${path} contains forbidden object member name ${JSON.stringify(key)}.`);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
function assertNonRecursiveSchema(root) {
|
|
243
|
-
const active = new WeakSet();
|
|
244
|
-
const finished = new WeakSet();
|
|
245
|
-
const stack = [{ entered: false, node: root }];
|
|
246
|
-
while (stack.length > 0) {
|
|
247
|
-
const frame = stack.pop();
|
|
248
|
-
if (frame === undefined || finished.has(frame.node)) {
|
|
249
|
-
continue;
|
|
250
|
-
}
|
|
251
|
-
if (frame.entered) {
|
|
252
|
-
active.delete(frame.node);
|
|
253
|
-
finished.add(frame.node);
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
if (active.has(frame.node)) {
|
|
257
|
-
throw new TypeError('Recursive contributed schemas are not admitted by the alpha profile.');
|
|
258
|
-
}
|
|
259
|
-
active.add(frame.node);
|
|
260
|
-
stack.push({ entered: true, node: frame.node });
|
|
261
|
-
const dependencies = schemaDependencies(frame.node, root);
|
|
262
|
-
for (let index = dependencies.length - 1; index >= 0; index -= 1) {
|
|
263
|
-
const dependency = dependencies[index];
|
|
264
|
-
if (dependency === undefined || finished.has(dependency)) {
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
if (active.has(dependency)) {
|
|
268
|
-
throw new TypeError('Recursive contributed schemas are not admitted by the alpha profile.');
|
|
269
|
-
}
|
|
270
|
-
stack.push({ entered: false, node: dependency });
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function schemaDependencies(schema, root) {
|
|
275
|
-
const dependencies = [];
|
|
276
|
-
for (const keyword of [
|
|
277
|
-
'additionalProperties',
|
|
278
|
-
'else',
|
|
279
|
-
'if',
|
|
280
|
-
'items',
|
|
281
|
-
'not',
|
|
282
|
-
'propertyNames',
|
|
283
|
-
'then',
|
|
284
|
-
]) {
|
|
285
|
-
appendSchemaDependency(dependencies, schema[keyword]);
|
|
286
|
-
}
|
|
287
|
-
for (const keyword of ['allOf', 'anyOf', 'oneOf', 'prefixItems']) {
|
|
288
|
-
const candidates = schema[keyword];
|
|
289
|
-
if (Array.isArray(candidates)) {
|
|
290
|
-
for (const candidate of candidates) {
|
|
291
|
-
appendSchemaDependency(dependencies, candidate);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
for (const keyword of ['$defs', 'properties']) {
|
|
296
|
-
const schemaMap = schema[keyword];
|
|
297
|
-
if (isRecord(schemaMap)) {
|
|
298
|
-
for (const candidate of Object.values(schemaMap)) {
|
|
299
|
-
appendSchemaDependency(dependencies, candidate);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
if (typeof schema.$ref === 'string') {
|
|
304
|
-
appendSchemaDependency(dependencies, resolveLocalReference(root, schema.$ref));
|
|
305
|
-
}
|
|
306
|
-
return dependencies;
|
|
307
|
-
}
|
|
308
|
-
function appendSchemaDependency(dependencies, value) {
|
|
309
|
-
if (isRecord(value)) {
|
|
310
|
-
dependencies.push(value);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
function resolveLocalReference(root, reference) {
|
|
314
|
-
if (reference === '#') {
|
|
315
|
-
return root;
|
|
316
|
-
}
|
|
317
|
-
let current = root;
|
|
318
|
-
for (const encodedToken of reference.slice(2).split('/')) {
|
|
319
|
-
if (/(?:~[^01]|~$)/u.test(encodedToken)) {
|
|
320
|
-
throw new TypeError(`Local schema reference ${reference} is not a valid JSON Pointer.`);
|
|
321
|
-
}
|
|
322
|
-
const token = encodedToken.replaceAll('~1', '/').replaceAll('~0', '~');
|
|
323
|
-
if (!isRecord(current) && !Array.isArray(current)) {
|
|
324
|
-
throw new TypeError(`Local schema reference ${reference} does not resolve to a schema.`);
|
|
325
|
-
}
|
|
326
|
-
if (!Object.hasOwn(current, token)) {
|
|
327
|
-
throw new TypeError(`Local schema reference ${reference} does not resolve to a schema.`);
|
|
328
|
-
}
|
|
329
|
-
current = current[token];
|
|
330
|
-
}
|
|
331
|
-
if (typeof current !== 'boolean' && !isRecord(current)) {
|
|
332
|
-
throw new TypeError(`Local schema reference ${reference} does not resolve to a schema.`);
|
|
333
|
-
}
|
|
334
|
-
return current;
|
|
335
|
-
}
|
|
336
|
-
function containsControlCharacter(value) {
|
|
337
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
338
|
-
const code = value.charCodeAt(index);
|
|
339
|
-
if (code <= 0x1f || code === 0x7f) {
|
|
340
|
-
return true;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
function assertDenseArray(value, path) {
|
|
346
|
-
const keys = Object.keys(value);
|
|
347
|
-
if (keys.length !== value.length || keys.some((key, index) => key !== String(index))) {
|
|
348
|
-
throw new TypeError(`${path} must be a dense JSON array without extra properties.`);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
function trackObject(value, path, state) {
|
|
352
|
-
if (state.seen.has(value)) {
|
|
353
|
-
throw new TypeError(`${path} reuses or cycles a JSON object.`);
|
|
354
|
-
}
|
|
355
|
-
state.seen.add(value);
|
|
356
|
-
}
|
|
357
|
-
function isRecord(value) {
|
|
358
|
-
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
const prototype = Object.getPrototypeOf(value);
|
|
362
|
-
return prototype === Object.prototype || prototype === null;
|
|
363
|
-
}
|
|
364
|
-
function utf8ByteLength(value) {
|
|
365
|
-
let bytes = 0;
|
|
366
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
367
|
-
const code = value.charCodeAt(index);
|
|
368
|
-
if (code <= 0x7f) {
|
|
369
|
-
bytes += 1;
|
|
370
|
-
}
|
|
371
|
-
else if (code <= 0x7ff) {
|
|
372
|
-
bytes += 2;
|
|
373
|
-
}
|
|
374
|
-
else if (code >= 0xd800 && code <= 0xdbff) {
|
|
375
|
-
const next = value.charCodeAt(index + 1);
|
|
376
|
-
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
377
|
-
bytes += 4;
|
|
378
|
-
index += 1;
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
bytes += 3;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
else {
|
|
385
|
-
bytes += 3;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return bytes;
|
|
389
|
-
}
|
|
390
|
-
//# sourceMappingURL=schema-profile.js.map
|
|
1
|
+
import{canonicalStringify as e}from"./canonical.js";import{compileProfileSchema as t}from"./profile-validator.js";const n=1e4,r=1024,i=1e4,a=1e3,o=262144,s=1024,c=1e3;export const STUDIO_SCHEMA_PROFILE_LIMITS=Object.freeze({maxAlternatives:64,maxDescriptionLength:n,maxEnumMembers:r,maxExamples:100,maxJsonDepth:64,maxJsonItems:i,maxJsonProperties:a,maxObjectKeyLength:200,maxPropertyNames:512,maxReferenceLength:500,maxReferences:128,maxSchemaBytes:o,maxSchemaDepth:32,maxSchemaMapProperties:512,maxSchemaNodes:s,maxTitleLength:c});export const STUDIO_SCHEMA_PROFILE_ERROR_CODES=Object.freeze([`invalid-root`,`unsupported-keyword`,`invalid-keyword-value`,`unsafe-member`,`limit-exceeded`,`invalid-reference`,`recursive-schema`]);export class StudioSchemaProfileError extends TypeError{code;schemaPath;constructor(e,t,n,r){super(n,r),this.name=`StudioSchemaProfileError`,this.code=e,this.schemaPath=t}}const d=new Set(`$defs.$ref.$schema.additionalProperties.allOf.anyOf.const.default.dependentRequired.description.else.enum.examples.exclusiveMaximum.exclusiveMinimum.if.items.maxItems.maxLength.maxProperties.maximum.minItems.minLength.minProperties.minimum.multipleOf.not.oneOf.prefixItems.properties.propertyNames.readOnly.required.then.title.type.uniqueItems.writeOnly`.split(`.`)),f=new Set([`array`,`boolean`,`integer`,`null`,`number`,`object`,`string`]);class p extends RangeError{}class m extends TypeError{}export function compileStudioPropertySchema(e){Z(e)||z(`invalid-root`,``,`Studio property schema root must be a JSON Schema object.`);try{G(e)}catch(e){e instanceof p&&z(`limit-exceeded`,``,`Studio property schema exceeds ${o} canonical UTF-8 bytes.`),e instanceof m||z(`invalid-root`,``,`Studio property schema must be a bounded canonical JSON document.`,e)}let n={references:0,schemaNodes:0,seen:new WeakSet},r=[];j(()=>h(e,``,1,n),r),j(()=>I(e),r),j(()=>A(e),r);let i=M(e,r);if(i!==void 0)throw i;try{return t(e)}catch(e){z(`invalid-keyword-value`,``,`Studio property schema does not compile under the strict profile.`,e)}}export function assertStudioPropertySchema(e){compileStudioPropertySchema(e)}function h(e,t,r,i){Z(e)||z(`invalid-keyword-value`,t,`${V(t)} must be a JSON Schema object.`),X(e,t,i),y(t,r,i);for(let[a,o]of q(e)){let e=B(t,a);switch(F(a,t),d.has(a)||z(`unsupported-keyword`,e,`${V(e)} uses keyword ${JSON.stringify(a)}, which is not allowed by the Studio Schema Profile.`),a){case`$defs`:case`properties`:g(o,e,r+1,i);break;case`additionalProperties`:case`else`:case`if`:case`items`:case`not`:case`propertyNames`:case`then`:v(o,e,r+1,i);break;case`allOf`:case`anyOf`:case`oneOf`:case`prefixItems`:_(o,e,r+1,i);break;case`$ref`:b(o,e,i);break;case`$schema`:o!==`https://json-schema.org/draft/2020-12/schema`&&z(`invalid-keyword-value`,e,`${V(e)} must declare JSON Schema Draft 2020-12.`);break;case`enum`:x(o,e,1,i);break;case`examples`:S(o,e,1,i);break;case`dependentRequired`:C(o,e,i);break;case`required`:w(o,e,512,i);break;case`type`:T(o,e,i);break;case`description`:E(o,e,n);break;case`title`:E(o,e,c);break;case`maxItems`:case`maxLength`:case`maxProperties`:case`minItems`:case`minLength`:case`minProperties`:D(o,e);break;case`exclusiveMaximum`:case`exclusiveMinimum`:case`maximum`:case`minimum`:O(o,e);break;case`multipleOf`:O(o,e),o<=0&&z(`invalid-keyword-value`,e,`${V(e)} must be greater than zero.`);break;case`readOnly`:case`uniqueItems`:case`writeOnly`:typeof o!=`boolean`&&z(`invalid-keyword-value`,e,`${V(e)} must be a boolean.`);break;case`const`:case`default`:k(o,e,1,i)}}}function g(e,t,n,r){Z(e)||z(`invalid-keyword-value`,t,`${V(t)} must be an object of schemas.`),X(e,t,r);let i=Object.keys(e);i.length>512&&z(`limit-exceeded`,t,`${V(t)} exceeds 512 schema entries.`);for(let a of i.sort(Y))F(a,t),h(e[a],B(t,a),n,r)}function _(e,t,n,r){(!Array.isArray(e)||!J(e))&&z(`invalid-keyword-value`,t,`${V(t)} must be a dense JSON array of schemas.`),e.length===0&&z(`invalid-keyword-value`,t,`${V(t)} must contain at least one schema.`),e.length>64&&z(`limit-exceeded`,t,`${V(t)} must contain at most 64 schemas.`),X(e,t,r);for(let[i,a]of e.entries())v(a,B(t,String(i)),n,r)}function v(e,t,n,r){if(typeof e==`boolean`){y(t,n,r);return}h(e,t,n,r)}function y(e,t,n){t>32&&z(`limit-exceeded`,e,`${V(e)} exceeds the Studio Schema Profile depth limit.`),n.schemaNodes+=1,n.schemaNodes>s&&z(`limit-exceeded`,e,`Studio property schema exceeds ${s} schema nodes.`)}function b(e,t,n){U(e)||z(`invalid-reference`,t,`${V(t)} must be a bounded local JSON Pointer reference.`),n.references+=1,n.references>128&&z(`limit-exceeded`,t,`Studio property schema exceeds 128 references.`)}function x(t,n,i,a){(!Array.isArray(t)||!J(t))&&z(`invalid-keyword-value`,n,`${V(n)} must be a dense JSON array.`),t.length===0&&z(`invalid-keyword-value`,n,`${V(n)} must contain at least one value.`),t.length>r&&z(`limit-exceeded`,n,`${V(n)} exceeds ${r} members.`),X(t,n,a);let o=new Set;for(let[r,s]of t.entries()){k(s,B(n,String(r)),i,a);let t=e(s,{maximumDepth:65});o.has(t)&&z(`invalid-keyword-value`,B(n,String(r)),`${V(n)} must contain unique JSON values.`),o.add(t)}}function S(e,t,n,r){(!Array.isArray(e)||!J(e))&&z(`invalid-keyword-value`,t,`${V(t)} must be a dense JSON array.`),e.length>100&&z(`limit-exceeded`,t,`${V(t)} exceeds 100 examples.`),X(e,t,r);for(let[i,a]of e.entries())k(a,B(t,String(i)),n,r)}function C(e,t,n){Z(e)||z(`invalid-keyword-value`,t,`${V(t)} must be an object of property-name arrays.`),X(e,t,n);let r=Object.keys(e);r.length>512&&z(`limit-exceeded`,t,`${V(t)} exceeds 512 dependency entries.`);for(let i of r.sort(Y))F(i,t),w(e[i],B(t,i),512,n)}function w(e,t,n,r){(!Array.isArray(e)||!J(e))&&z(`invalid-keyword-value`,t,`${V(t)} must be a dense array of property names.`),e.length>n&&z(`limit-exceeded`,t,`${V(t)} exceeds ${n} property names.`),X(e,t,r);let i=new Set;for(let[n,r]of e.entries())typeof r!=`string`&&z(`invalid-keyword-value`,B(t,String(n)),`${V(t)} must contain only property-name strings.`),F(r,t,B(t,String(n))),i.has(r)&&z(`invalid-keyword-value`,B(t,String(n)),`${V(t)} must list unique property names.`),i.add(r)}function T(e,t,n){if(typeof e==`string`){f.has(e)||z(`invalid-keyword-value`,t,`${V(t)} names an unknown JSON Schema type.`);return}(!Array.isArray(e)||!J(e)||e.length===0||e.length>7)&&z(`invalid-keyword-value`,t,`${V(t)} must be a type name or a non-empty array of at most seven names.`),X(e,t,n);let r=new Set;for(let[n,i]of e.entries())(typeof i!=`string`||!f.has(i)||r.has(i))&&z(`invalid-keyword-value`,B(t,String(n)),`${V(t)} must list unique, known JSON Schema type names.`),r.add(i)}function E(e,t,n){typeof e!=`string`&&z(`invalid-keyword-value`,t,`${V(t)} must be a string.`),W(e)>n&&z(`limit-exceeded`,t,`${V(t)} exceeds ${n} characters.`)}function D(e,t){(typeof e!=`number`||!Number.isInteger(e)||e<0)&&z(`invalid-keyword-value`,t,`${V(t)} must be a non-negative integer.`)}function O(e,t){(typeof e!=`number`||!Number.isFinite(e))&&z(`invalid-keyword-value`,t,`${V(t)} must be a finite number.`)}function k(e,t,n,r){if(!(e===null||typeof e==`boolean`||typeof e==`string`||typeof e==`number`&&Number.isFinite(e))){if(n>64&&z(`limit-exceeded`,t,`${V(t)} exceeds the Studio Schema Profile JSON depth limit.`),Array.isArray(e)){J(e)||z(`invalid-keyword-value`,t,`${V(t)} must be a dense JSON array.`),X(e,t,r),e.length>i&&z(`limit-exceeded`,t,`${V(t)} exceeds ${i} JSON items.`);for(let[i,a]of e.entries())k(a,B(t,String(i)),n+1,r);return}if(Z(e)){X(e,t,r);let i=Object.keys(e);i.length>a&&z(`limit-exceeded`,t,`${V(t)} exceeds ${a} JSON properties.`);for(let a of i.sort(Y))F(a,t),k(e[a],B(t,a),n+1,r);return}z(`invalid-keyword-value`,t,`${V(t)} is not JSON-compatible.`)}}function A(e){e.additionalProperties!==!1&&z(`invalid-root`,`/additionalProperties`,`Studio property schema root must declare additionalProperties: false.`),e.type!==`object`&&z(`invalid-root`,`/type`,`Studio property schema root must declare exactly type "object".`)}function j(e,t){try{e()}catch(e){if(e instanceof StudioSchemaProfileError){t.push(e);return}throw e}}function M(e,t){let n;for(let r of t)(n===void 0||N(e,r.schemaPath,n.schemaPath)<0)&&(n=r);return n}function N(e,t,n){let r=P(t),i=P(n),a=e,o=Math.min(r.length,i.length);for(let e=0;e<o;e+=1){let t=r[e],n=i[e];if(t===void 0||n===void 0)break;if(t!==n){if(Array.isArray(a)){let e=Number(t),r=Number(n);if(Number.isSafeInteger(e)&&Number.isSafeInteger(r))return e-r}return Y(t,n)}a=(Z(a)||Array.isArray(a))&&Object.hasOwn(a,t)?a[t]:void 0}return r.length-i.length}function P(e){return e===``?[]:e.slice(1).split(`/`).map(e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`))}function F(e,t,n=B(t,e)){W(e)>200&&z(`limit-exceeded`,n,`${V(t)} contains an object member name longer than 200 characters.`),(e.length===0||e===`__proto__`||e===`constructor`||e===`prototype`||H(e))&&z(`unsafe-member`,n,`${V(t)} contains forbidden object member name ${JSON.stringify(e)}.`)}function I(e){let t=[],n=new Map,r=[],i=[],a=[],o=new WeakSet,s=0,c=(e,t)=>({parent:e,token:t}),l=e=>{let t=[],n=e;for(;n!==void 0;)t.push(n.token),n=n.parent;let r=``;for(let e=t.length-1;e>=0;--e){let n=t[e];n!==void 0&&(r=B(r,n))}return r},u=e=>{let t=n.get(e);if(t!==void 0)return t;let a=r.length;return n.set(e,a),r.push([]),i.push([]),a},d=(e,t)=>{r[e]?.push(t),i[t]?.push(e)};u(e);let f=[{depth:1,diagnosticsEligible:!0,node:e,path:void 0}];for(;f.length>0;){let n=f.pop();if(n===void 0||o.has(n.node))continue;o.add(n.node);let r=u(n.node),i=[],p=(e,t,a=n.diagnosticsEligible)=>{if(!Z(e))return;let o=u(e);d(r,o);let s=n.depth+1;i.push({depth:s,diagnosticsEligible:a&&s<=32,node:e,path:t})};for(let[i,o]of q(n.node)){let f=c(n.path,i);switch(i){case`$defs`:case`properties`:if(Z(o)){let e=Object.keys(o),t=e.length<=512;t&&e.sort(Y);for(let r of e)p(o[r],c(f,r),n.diagnosticsEligible&&t)}break;case`$ref`:if(U(o)){let i=n.diagnosticsEligible&&(s+=1)<=128,c=i?l(f):``;try{let n=R(e,o,c);if(!n.schemaPosition)i&&t.push(new StudioSchemaProfileError(`invalid-reference`,c,`Local schema reference ${o} does not resolve to a schema position.`));else if(Z(n.value)){let e=u(n.value);d(r,e),i&&a.push({path:c,source:r,target:e})}}catch(e){if(e instanceof StudioSchemaProfileError)i&&t.push(e);else throw e}}break;case`additionalProperties`:case`else`:case`if`:case`items`:case`not`:case`propertyNames`:case`then`:p(o,f);break;case`allOf`:case`anyOf`:case`oneOf`:case`prefixItems`:if(Array.isArray(o)){let e=o.length>0&&o.length<=64&&J(o);for(let t=0;t<o.length;t+=1)Object.hasOwn(o,t)&&p(o[t],c(f,String(t)),n.diagnosticsEligible&&e)}}}for(let e=i.length-1;e>=0;--e){let t=i[e];t!==void 0&&f.push(t)}}let p=L(r,i);for(let e of a)p[e.source]===p[e.target]&&t.push(new StudioSchemaProfileError(`recursive-schema`,e.path,`Recursive contributed schemas are not admitted by the alpha profile.`));let m=M(e,t);if(m!==void 0)throw m}function L(e,t){let n=new Uint8Array(e.length),r=[];for(let t=0;t<e.length;t+=1){if(n[t]!==0)continue;n[t]=1;let i=[{edge:0,node:t}];for(;i.length>0;){let t=i[i.length-1];if(t===void 0)break;let a=(e[t.node]??[])[t.edge];a===void 0?(r.push(t.node),i.pop()):(t.edge+=1,n[a]===0&&(n[a]=1,i.push({edge:0,node:a})))}}let i=new Int32Array(e.length);i.fill(-1);let a=0;for(let e=r.length-1;e>=0;--e){let n=r[e];if(n===void 0||i[n]!==-1)continue;i[n]=a;let o=[n];for(;o.length>0;){let e=o.pop();if(e!==void 0)for(let n of t[e]??[])i[n]===-1&&(i[n]=a,o.push(n))}a+=1}return i}function R(e,t,n){if(t===`#`)return{schemaPosition:!0,value:e};let r=e,i=`schema`;for(let e of t.slice(2).split(`/`)){let a=e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),o=`other`;if(i===`schema`&&Z(r))switch(a){case`$defs`:case`properties`:o=`schema-map`;break;case`additionalProperties`:case`else`:case`if`:case`items`:case`not`:case`propertyNames`:case`then`:o=`schema`;break;case`allOf`:case`anyOf`:case`oneOf`:case`prefixItems`:o=`schema-array`}else(i===`schema-map`&&Z(r)||i===`schema-array`&&Array.isArray(r))&&(o=`schema`);!Z(r)&&!Array.isArray(r)&&z(`invalid-reference`,n,`Local schema reference ${t} does not resolve to a schema.`),Object.hasOwn(r,a)||z(`invalid-reference`,n,`Local schema reference ${t} does not resolve to a schema.`),r=r[a],i=o}return typeof r!=`boolean`&&!Z(r)&&z(`invalid-reference`,n,`Local schema reference ${t} does not resolve to a schema.`),{schemaPosition:i===`schema`,value:r}}function z(e,t,n,r){throw new StudioSchemaProfileError(e,t,n,r===void 0?void 0:{cause:r})}function B(e,t){return`${e}/${t.replaceAll(`~`,`~0`).replaceAll(`/`,`~1`)}`}function V(e){return e===``?`schema root`:e}function H(e){for(let t=0;t<e.length;t+=1){let n=e.charCodeAt(t);if(n<=31||n===127)return!0}return!1}function U(e){return typeof e==`string`&&W(e)<=500&&!H(e)&&/^#(?:\/(?:[A-Za-z0-9._!$&'()*+,;=:@-]|~[01])*)*$/u.test(e)}function W(e){let t=0;for(let n=0;n<e.length;n+=1){t+=1;let r=e.charCodeAt(n);r>=55296&&r<=56319&&n+1<e.length&&(e.charCodeAt(n+1)&64512)==56320&&(n+=1)}return t}function G(e){let t=[e],n=new WeakSet,r=0,i=e=>{if(r+=e,r>o)throw new p};for(;t.length>0;){let e=t.pop();if(e===null){i(4);continue}switch(typeof e){case`boolean`:i(e?4:5);continue;case`number`:if(!Number.isFinite(e))throw new m;i(JSON.stringify(Object.is(e,-0)?0:e).length);continue;case`string`:K(e,i);continue;case`object`:break;default:throw new m}if(n.has(e))throw new m;if(n.add(e),Array.isArray(e)){let n=e;if(i(2+Math.max(0,n.length-1)),!J(n))throw new m;for(let e=n.length-1;e>=0;--e){let r=n[e];if(r===void 0)throw new m;t.push(r)}continue}if(!Z(e))throw new m;let r=Object.keys(e);i(2+Math.max(0,r.length-1));for(let n=r.length-1;n>=0;--n){let a=r[n];if(a===void 0)continue;let o=e[a];if(o===void 0)throw new m;K(a,i),i(1),t.push(o)}}}function K(e,t){t(2);for(let n=0;n<e.length;n+=1){let r=e.charCodeAt(n);if(r===34||r===92||r===8||r===9||r===10||r===12||r===13)t(2);else if(r<=31)t(6);else if(r<=127)t(1);else if(r<=2047)t(2);else if(r>=55296&&r<=56319){let r=e.charCodeAt(n+1);n+1<e.length&&(r&64512)==56320?(t(4),n+=1):t(6)}else t(r>=56320&&r<=57343?6:3)}}function q(e){let t=Object.keys(e);if(t.length<=d.size)return t.sort(Y).map(t=>[t,e[t]]);let n=[],r;for(let e of t)d.has(e)?n.push(e):(r===void 0||Y(e,r)<0)&&(r=e);return r!==void 0&&n.push(r),n.sort(Y).map(t=>[t,e[t]])}function J(e){let t=Object.keys(e);return t.length===e.length&&t.every((e,t)=>e===String(t))}function Y(e,t){return e<t?-1:+(e>t)}function X(e,t,n){n.seen.has(e)&&z(`invalid-root`,t,`${V(t)} reuses or cycles a JSON object.`),n.seen.add(e)}function Z(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}
|