@pulse-compute/wasm-contracts 0.0.0 → 1.0.0-beta.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/README.md +34 -2
- package/package.json +123 -6
- package/src/assets/contracts.js +296 -0
- package/src/config/provider-resolution.js +54 -0
- package/src/config/runtime-provider-kv.js +73 -0
- package/src/config/symbolic-refs.js +192 -0
- package/src/crypto/contracts.js +637 -0
- package/src/definitions/config-schema.js +30 -0
- package/src/definitions/handler-roles.js +66 -0
- package/src/definitions/path-grammar.js +11 -0
- package/src/definitions/router-api.js +146 -0
- package/src/diagnostics/codes.js +42 -0
- package/src/diagnostics/reporter.js +20 -0
- package/src/diagnostics.js +139 -0
- package/src/dispatch-table.js +23 -0
- package/src/entities/catalog.d.ts +7 -0
- package/src/entities/catalog.js +87 -0
- package/src/entities/contracts.d.ts +95 -0
- package/src/entities/contracts.js +122 -0
- package/src/entities/json-rpc.d.ts +27 -0
- package/src/entities/json-rpc.js +69 -0
- package/src/entities/runtime.d.ts +67 -0
- package/src/entities/runtime.js +288 -0
- package/src/events/contracts.js +456 -0
- package/src/execution-plan.js +42 -0
- package/src/grip/contracts.js +106 -0
- package/src/handler/backend-json-request-body.js +58 -0
- package/src/handler/beta-lifecycle-golden.js +97 -0
- package/src/handler/canonical-native-plan.js +143 -0
- package/src/handler/canonical-native-runtime.js +168 -0
- package/src/handler/canonical-runtime.js +13 -0
- package/src/handler/context.js +131 -0
- package/src/handler/ctx-contract.js +71 -0
- package/src/handler/doctor-readiness-aggregator.js +67 -0
- package/src/handler/effects.js +446 -0
- package/src/handler/io-lifecycle.js +134 -0
- package/src/handler/lifecycle-authoring-alignment.js +52 -0
- package/src/handler/lifecycle-readiness-aggregate.js +93 -0
- package/src/handler/reference-node-lifecycle-golden.js +73 -0
- package/src/handler/request-json-body.js +147 -0
- package/src/handler/runtime-api.js +471 -0
- package/src/handler/schema-decode-result.js +135 -0
- package/src/handler/schema-response-codec.js +141 -0
- package/src/handler/surface-contract.js +594 -0
- package/src/handler/types-contract.js +51 -0
- package/src/handler-table.js +28 -0
- package/src/host/backend-capabilities.js +24 -0
- package/src/host/capabilities.js +273 -0
- package/src/host/channel-broadcaster.js +60 -0
- package/src/host/json-body.js +80 -0
- package/src/host/request-result-headers.js +38 -0
- package/src/host/streaming-passthrough.js +90 -0
- package/src/host/wasm-host-abi.js +154 -0
- package/src/index.js +75 -0
- package/src/jwt/contracts.js +427 -0
- package/src/library/api-surface.js +99 -0
- package/src/library/contracts.js +273 -0
- package/src/library/manifest.js +317 -0
- package/src/library/second-package-owned-lowering.js +39 -0
- package/src/library/sidecars.js +147 -0
- package/src/logging.js +89 -0
- package/src/package/package-contract.js +975 -0
- package/src/package/package-contract.schema.json +303 -0
- package/src/package/runtime-pulse-live.js +100 -0
- package/src/path-table.js +12 -0
- package/src/path.js +275 -0
- package/src/project/config-factory.js +48 -0
- package/src/project/config-plan.js +409 -0
- package/src/project/config-runtime.js +46 -0
- package/src/project/javascript-application.js +212 -0
- package/src/project/javascript-core-capabilities.js +44 -0
- package/src/project/native-optimization.js +9 -0
- package/src/project/package-ownership.js +242 -0
- package/src/project/package-product-projection.js +171 -0
- package/src/project/reachable-graph-identity.js +219 -0
- package/src/project/reachable-graph-projections.js +279 -0
- package/src/project/reachable-graph-resolver.js +303 -0
- package/src/project/reachable-graph-v2.js +430 -0
- package/src/project/reachable-graph-v2.schema.json +285 -0
- package/src/project/reachable-graph.js +199 -0
- package/src/project/reachable-graph.schema.json +222 -0
- package/src/project/target-support-evidence.js +559 -0
- package/src/provider/canonical-provider.js +235 -0
- package/src/provider/final-wasm-policy.js +87 -0
- package/src/provider/toolchain.js +771 -0
- package/src/route-plan.js +43 -0
- package/src/schema-json/compile.js +63 -0
- package/src/schema-json/contracts.js +10 -0
- package/src/schema-json/generic-parser.js +62 -0
- package/src/schema-json/registry.js +359 -0
- package/src/schema-json/semantic-trace.js +241 -0
- package/src/schema-json/v1.js +65 -0
- package/src/schema-json/v2.js +110 -0
- package/src/sha256.js +104 -0
- package/src/spine.js +381 -0
- package/src/stable-id.js +142 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ROUTE_PLAN_VERSION = 'pulsewasm.route-plan.v4';
|
|
4
|
+
const ROUTE_STABLE_INPUT_VERSION = 'pulsewasm.route-stable-input.v2';
|
|
5
|
+
|
|
6
|
+
const ROUTE_STABLE_ID_POLICY = Object.freeze({
|
|
7
|
+
algorithm: 'sha256',
|
|
8
|
+
prefix: 'route',
|
|
9
|
+
input: 'method + normalized path + params + handler IDs + inherited middleware/error/lifecycle handler IDs + channel identity',
|
|
10
|
+
version: ROUTE_STABLE_INPUT_VERSION
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const ROUTE_RUNTIME_ID_POLICY = Object.freeze({
|
|
14
|
+
field: 'runtimeId',
|
|
15
|
+
dense: true,
|
|
16
|
+
startsAt: 0,
|
|
17
|
+
assignment: 'deterministic flattened route order'
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const ROUTE_ID_COMPATIBILITY_POLICY = Object.freeze({
|
|
21
|
+
id: 'alias of runtimeId for Phase 1 compatibility'
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const ROUTE_ID_POLICY = Object.freeze({
|
|
25
|
+
stable: ROUTE_STABLE_ID_POLICY,
|
|
26
|
+
runtime: ROUTE_RUNTIME_ID_POLICY,
|
|
27
|
+
compatibility: ROUTE_ID_COMPATIBILITY_POLICY
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const ROUTE_PLAN_POLICY = Object.freeze({
|
|
31
|
+
version: ROUTE_PLAN_VERSION,
|
|
32
|
+
idPolicy: ROUTE_ID_POLICY
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
ROUTE_PLAN_VERSION,
|
|
37
|
+
ROUTE_STABLE_INPUT_VERSION,
|
|
38
|
+
ROUTE_STABLE_ID_POLICY,
|
|
39
|
+
ROUTE_RUNTIME_ID_POLICY,
|
|
40
|
+
ROUTE_ID_COMPATIBILITY_POLICY,
|
|
41
|
+
ROUTE_ID_POLICY,
|
|
42
|
+
ROUTE_PLAN_POLICY
|
|
43
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SCHEMA_JSON_COMPILE_VERSION = 'pulsewasm.schema-json-compile.v1';
|
|
4
|
+
const SCHEMA_JSON_COMPILE_SMOKE_VERSION = 'pulsewasm.schema-json-compile-smoke.v1';
|
|
5
|
+
const SCHEMA_JSON_COMPILE_PHASE = '13';
|
|
6
|
+
const PHASE = SCHEMA_JSON_COMPILE_PHASE;
|
|
7
|
+
|
|
8
|
+
const MARKER_TYPES = new Map([
|
|
9
|
+
['string', 'string'],
|
|
10
|
+
['bool', 'bool'],
|
|
11
|
+
['boolean', 'bool'],
|
|
12
|
+
['i32', 'i32'],
|
|
13
|
+
['u32', 'u32'],
|
|
14
|
+
['Int32', 'i32'],
|
|
15
|
+
['Uint32', 'u32'],
|
|
16
|
+
['f64', 'f64'],
|
|
17
|
+
['number', 'f64']
|
|
18
|
+
]);
|
|
19
|
+
const JSON_MARKER_MODULES = new Set([
|
|
20
|
+
'@pulse-compute/pulse/schema',
|
|
21
|
+
'@pulsewasm/json-types',
|
|
22
|
+
'pulsewasm/json-types'
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
function plainObject(value) {
|
|
26
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function jsonConfig(config) {
|
|
30
|
+
const runtime = plainObject(config && config.runtime);
|
|
31
|
+
const payload = plainObject(runtime.payload);
|
|
32
|
+
return plainObject(payload.json || (config && config.json));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalizeFieldType(type) {
|
|
36
|
+
const raw = String(type || '');
|
|
37
|
+
return MARKER_TYPES.get(raw) || raw;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isJsonMarkerModule(moduleName) {
|
|
41
|
+
return JSON_MARKER_MODULES.has(String(moduleName || ''));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function compileNeeded(config) {
|
|
45
|
+
const json = jsonConfig(config);
|
|
46
|
+
const schemas = Array.isArray(json.schemas) ? json.schemas : [];
|
|
47
|
+
const target = json.target || 'generic';
|
|
48
|
+
const effectiveTarget = target === 'auto' && schemas.length > 0 ? 'schema' : target;
|
|
49
|
+
if (effectiveTarget !== 'schema') return false;
|
|
50
|
+
return schemas.some((schema) => Object.keys(plainObject(schema.fields)).length === 0 && typeof schema.source === 'string' && schema.source && typeof schema.type === 'string' && schema.type);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
SCHEMA_JSON_COMPILE_VERSION,
|
|
55
|
+
SCHEMA_JSON_COMPILE_SMOKE_VERSION,
|
|
56
|
+
SCHEMA_JSON_COMPILE_PHASE,
|
|
57
|
+
PHASE,
|
|
58
|
+
MARKER_TYPES,
|
|
59
|
+
JSON_MARKER_MODULES,
|
|
60
|
+
normalizeFieldType,
|
|
61
|
+
isJsonMarkerModule,
|
|
62
|
+
compileNeeded
|
|
63
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
v1: require('./v1.js'),
|
|
5
|
+
v2: require('./v2.js'),
|
|
6
|
+
compile: require('./compile.js'),
|
|
7
|
+
genericParser: require('./generic-parser.js'),
|
|
8
|
+
registry: require('./registry.js'),
|
|
9
|
+
semanticTrace: require('./semantic-trace.js')
|
|
10
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SCHEMA_JSON_GENERIC_PARSER_VERSION = 'pulsewasm.schema-json-generic-parser.v1';
|
|
4
|
+
const SCHEMA_JSON_GENERIC_PARSER_PLAN_VERSION = 'pulsewasm.schema-json-generic-parser-plan.v1';
|
|
5
|
+
const SCHEMA_JSON_GENERIC_PARSER_ABI_VERSION = 'pulsewasm.schema-json-generic-parser-abi.v1';
|
|
6
|
+
const SCHEMA_JSON_GENERIC_PARSER_SMOKE_VERSION = 'pulsewasm.schema-json-generic-parser-smoke.v1';
|
|
7
|
+
const SCHEMA_JSON_GENERIC_PARSER_PHASE = '34';
|
|
8
|
+
const PHASE = SCHEMA_JSON_GENERIC_PARSER_PHASE;
|
|
9
|
+
|
|
10
|
+
const SCHEMA_JSON_GENERIC_PARSER_ARTIFACT = 'schema-json-generic-parser.json';
|
|
11
|
+
const SCHEMA_JSON_GENERIC_PARSER_PLAN_ARTIFACT = 'schema-json-generic-parser-plan.json';
|
|
12
|
+
const SCHEMA_JSON_GENERIC_PARSER_ABI_ARTIFACT = 'schema-json-generic-parser-abi.json';
|
|
13
|
+
const SCHEMA_JSON_GENERIC_PARSER_SMOKE_ARTIFACT = 'schema-json-generic-parser-smoke.json';
|
|
14
|
+
const SCHEMA_JSON_GENERIC_PARSER_NAME = 'as-json';
|
|
15
|
+
const SCHEMA_JSON_GENERIC_PARSER_ID = SCHEMA_JSON_GENERIC_PARSER_NAME;
|
|
16
|
+
const SCHEMA_JSON_GENERIC_PARSER_MODE = 'generic-as-json-parser';
|
|
17
|
+
const SCHEMA_JSON_GENERIC_PARSER_FILE = 'generated/as/schema-json/generic/as-json-parser.as.ts';
|
|
18
|
+
const SCHEMA_JSON_GENERIC_PARSER_MODULE_FILE = SCHEMA_JSON_GENERIC_PARSER_FILE;
|
|
19
|
+
const SCHEMA_JSON_GENERIC_PARSER_SMOKE_RUNNER_FILE = 'generated/as-smoke/schema-json-generic-parser-smoke-runner.as.ts';
|
|
20
|
+
const SCHEMA_JSON_GENERIC_PARSER_WASM_FILE = 'generated/schema-json-generic-parser/pulsewasm-schema-json-generic-parser.wasm';
|
|
21
|
+
const SCHEMA_JSON_GENERIC_PARSER_WAT_FILE = 'generated/schema-json-generic-parser/pulsewasm-schema-json-generic-parser.wat';
|
|
22
|
+
const SCHEMA_JSON_GENERIC_PARSER_WASM = SCHEMA_JSON_GENERIC_PARSER_WASM_FILE;
|
|
23
|
+
const SCHEMA_JSON_GENERIC_PARSER_WAT = SCHEMA_JSON_GENERIC_PARSER_WAT_FILE;
|
|
24
|
+
const SCHEMA_JSON_GENERIC_PARSER_DOC_FILE = 'generated/host/schema-json-generic-parser.md';
|
|
25
|
+
|
|
26
|
+
const SCHEMA_JSON_TARGETS = Object.freeze(['generic', 'schema', 'auto', 'parser', 'none']);
|
|
27
|
+
const SCHEMA_JSON_GENERIC_PARSER_TARGETS = Object.freeze(['auto', 'parser']);
|
|
28
|
+
const SCHEMA_JSON_PARSER_MODES = Object.freeze([SCHEMA_JSON_GENERIC_PARSER_NAME]);
|
|
29
|
+
const SCHEMA_JSON_GENERIC_VALUE_KINDS = Object.freeze({ null: 0, bool: 1, number: 2, string: 3, array: 4, object: 5, error: -1 });
|
|
30
|
+
const SCHEMA_JSON_GENERIC_PARSER_ACCESSORS = Object.freeze(['parse', 'ok', 'value', 'error', 'errorCode', 'errorMessage', 'errorStatusCode', 'kind', 'isNull', 'asBool', 'asF64', 'asString', 'objectGet', 'objectHas', 'has', 'get', 'getString', 'getI32', 'getU32', 'getF64', 'getBool', 'arrayLen', 'arrayGet', 'length', 'at', 'text']);
|
|
31
|
+
const SCHEMA_JSON_GENERIC_ACCESSOR_SURFACE = SCHEMA_JSON_GENERIC_PARSER_ACCESSORS;
|
|
32
|
+
const SCHEMA_JSON_GENERIC_RESERVED_SURFACE = Object.freeze(['automatic typed schema inference from generic refs', 'arbitrary JavaScript object materialization', 'host JSON.parse fallback', 'binary request body parsing', 'streaming request body parsing', 'mutation APIs for parsed generic refs']);
|
|
33
|
+
const SCHEMA_JSON_GENERIC_PARSER_POLICY = Object.freeze({ phase: SCHEMA_JSON_GENERIC_PARSER_PHASE, parser: SCHEMA_JSON_GENERIC_PARSER_NAME, explicitOptIn: true, schemaDeclarationsPreferred: true, schemaAutoTakesPrecedence: true, directJsObjects: false, hostJsonParse: false, assemblyScriptParser: true, fullJsonTree: true, valueAccess: 'opaque-ref-accessors', bodySource: 'seeded-body-text-only', supportedTargets: SCHEMA_JSON_GENERIC_PARSER_TARGETS, supportedValueKinds: Object.keys(SCHEMA_JSON_GENERIC_VALUE_KINDS).filter((kind) => kind !== 'error'), reservedSurface: SCHEMA_JSON_GENERIC_RESERVED_SURFACE });
|
|
34
|
+
const SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS = Object.freeze({ parserRequired: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_REQUIRED', genericParserRequired: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_REQUIRED', unsupportedParser: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_UNSUPPORTED', genericParserUnsupported: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_UNSUPPORTED', genericParserInactive: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_INACTIVE', schemasTakePrecedence: 'PULSEWASM_SCHEMA_JSON_SCHEMAS_TAKE_PRECEDENCE', schemasIgnored: 'PULSEWASM_SCHEMA_JSON_GENERIC_SCHEMAS_IGNORED', schemaTargetRequiresSchemas: 'PULSEWASM_SCHEMA_JSON_SCHEMAS_REQUIRED', compileFailed: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_COMPILE_FAILED', genericParserCompileFailed: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_COMPILE_FAILED', smokeFailed: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_SMOKE_FAILED', genericParserSmokeFailed: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_SMOKE_FAILED', ascMissing: 'PULSEWASM_SCHEMA_JSON_GENERIC_PARSER_ASC_MISSING' });
|
|
35
|
+
|
|
36
|
+
function plainObject(value) { return value && typeof value === 'object' && !Array.isArray(value) ? value : {}; }
|
|
37
|
+
function configArtifact(config) { return config && typeof config === 'object' && config.artifact ? config.artifact : config; }
|
|
38
|
+
function jsonConfig(config) { const root = plainObject(configArtifact(config)); const runtime = plainObject(root.runtime); const payload = plainObject(runtime.payload); return plainObject(payload.json || root.json); }
|
|
39
|
+
function schemas(config) { const json = jsonConfig(config); return Array.isArray(json.schemas) ? json.schemas : []; }
|
|
40
|
+
function normalizeSchemaJsonTarget(value) { if (typeof value !== 'string' || !value) return 'generic'; if (value === 'fallback') return 'auto'; if (value === 'generic-parser') return 'parser'; return value; }
|
|
41
|
+
function normalizeJsonTarget(config) { return normalizeSchemaJsonTarget(jsonConfig(config).target); }
|
|
42
|
+
function normalizeParserMode(value) { if (typeof value === 'string' && value) return value; if (value && typeof value === 'object' && !Array.isArray(value)) return String(value.id || value.mode || value.kind || value.name || ''); return ''; }
|
|
43
|
+
function normalizeSchemaJsonParser(value) { const normalized = String(normalizeParserMode(value) || '').toLowerCase(); if (!normalized) return undefined; if (normalized === 'assemblyscript-json' || normalized === 'full-as-json' || normalized === 'asjson' || normalized === 'generic-as-json') return SCHEMA_JSON_GENERIC_PARSER_ID; return normalized; }
|
|
44
|
+
function normalizedParserId(config) { return normalizeSchemaJsonParser(jsonConfig(config).parser); }
|
|
45
|
+
function normalizeJsonParserConfig(config = {}) {
|
|
46
|
+
const target = normalizeJsonTarget(config); const parser = normalizedParserId(config); const schemaList = schemas(config); const diagnostics = []; const warnings = []; let effectiveTarget = target; let genericParser = false; let schemaSidecar = false; let mode = 'inactive';
|
|
47
|
+
if (!SCHEMA_JSON_TARGETS.includes(target)) { diagnostics.push('PULSEWASM_SCHEMA_JSON_GENERIC_TARGET_UNSUPPORTED'); mode = 'error'; }
|
|
48
|
+
else if (target === 'schema') { effectiveTarget = 'schema'; schemaSidecar = true; mode = 'schema'; if (schemaList.length === 0) diagnostics.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.schemaTargetRequiresSchemas); }
|
|
49
|
+
else if (target === 'auto') { if (schemaList.length > 0) { effectiveTarget = 'schema'; schemaSidecar = true; mode = 'schema'; if (parser === SCHEMA_JSON_GENERIC_PARSER_ID) warnings.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.schemasTakePrecedence); } else if (parser === SCHEMA_JSON_GENERIC_PARSER_ID) { effectiveTarget = 'parser'; genericParser = true; mode = SCHEMA_JSON_GENERIC_PARSER_MODE; } else if (parser) { effectiveTarget = 'parser'; diagnostics.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.unsupportedParser); mode = 'error'; } else { effectiveTarget = 'parser'; diagnostics.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.parserRequired); mode = 'error'; } }
|
|
50
|
+
else if (target === 'parser') { effectiveTarget = 'parser'; const selectedParser = parser || SCHEMA_JSON_GENERIC_PARSER_ID; if (selectedParser === SCHEMA_JSON_GENERIC_PARSER_ID) { genericParser = true; mode = SCHEMA_JSON_GENERIC_PARSER_MODE; if (schemaList.length > 0) warnings.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.schemasIgnored); } else { diagnostics.push(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.unsupportedParser); mode = 'error'; } }
|
|
51
|
+
return { target, effectiveTarget, parser: target === 'parser' && !parser ? SCHEMA_JSON_GENERIC_PARSER_ID : parser, schemaCount: schemaList.length, schemasPresent: schemaList.length > 0, genericParser, schemaSidecar, mode, diagnostics, warnings, parserUnsupportedDiagnostic: diagnostics.includes(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.unsupportedParser), parserRequiredDiagnostic: diagnostics.includes(SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS.parserRequired), schemaSidecarRequested: schemaSidecar, genericParserRequested: genericParser };
|
|
52
|
+
}
|
|
53
|
+
function normalizeGenericParserConfig(config = {}) { const json = jsonConfig(config); const mode = normalizeJsonParserConfig(config); const schemaList = schemas(config); return { ...mode, schemas: schemaList, schemasSupplied: schemaList.length > 0, contentTypePolicy: typeof json.contentTypePolicy === 'string' && json.contentTypePolicy ? json.contentTypePolicy : 'accept-json-or-missing', defaultNamespace: typeof json.defaultNamespace === 'string' && json.defaultNamespace ? json.defaultNamespace : 'app', maxBytes: Number.isFinite(Number(json.maxBytes)) ? Number(json.maxBytes) : 1048576 }; }
|
|
54
|
+
function normalizeSchemaJsonParserMode(config = {}) { return normalizeJsonParserConfig(config); }
|
|
55
|
+
function normalizeSchemaJsonParserSelection(config = {}) { const mode = normalizeJsonParserConfig(config); return { target: mode.target, effectiveTarget: mode.effectiveTarget, effectiveParser: mode.parser, parserRequested: mode.genericParser, explicitParser: Boolean(mode.parser), schemasSupplied: mode.schemasPresent, schemaCount: mode.schemaCount, schemaSidecarsPreferred: mode.schemaSidecar, mode: mode.mode, diagnostics: mode.diagnostics, warnings: mode.warnings }; }
|
|
56
|
+
function genericParserNeeded(config = {}) { const selection = normalizeJsonParserConfig(config); if (selection.genericParser) return true; if ((selection.target === 'auto' || selection.target === 'parser') && !selection.schemaSidecar && selection.diagnostics.length > 0) return true; return false; }
|
|
57
|
+
function shouldUseGenericSchemaJsonParser(config = {}) { return genericParserNeeded(config); }
|
|
58
|
+
function shouldUseSchemaJsonGenericParser(config = {}, options = {}) { return Boolean(options && options.forceGenericParser) || genericParserNeeded(config); }
|
|
59
|
+
function shouldUseSchemaJsonSchemaMode(config = {}) { return normalizeJsonParserConfig(config).schemaSidecar; }
|
|
60
|
+
function defaultSchemaJsonGenericParserPolicy() { return { ...SCHEMA_JSON_GENERIC_PARSER_POLICY, accessorSurface: SCHEMA_JSON_GENERIC_PARSER_ACCESSORS.slice(), diagnostics: { ...SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS } }; }
|
|
61
|
+
|
|
62
|
+
module.exports = { SCHEMA_JSON_GENERIC_PARSER_VERSION, SCHEMA_JSON_GENERIC_PARSER_PLAN_VERSION, SCHEMA_JSON_GENERIC_PARSER_ABI_VERSION, SCHEMA_JSON_GENERIC_PARSER_SMOKE_VERSION, SCHEMA_JSON_GENERIC_PARSER_PHASE, PHASE, SCHEMA_JSON_GENERIC_PARSER_ARTIFACT, SCHEMA_JSON_GENERIC_PARSER_PLAN_ARTIFACT, SCHEMA_JSON_GENERIC_PARSER_ABI_ARTIFACT, SCHEMA_JSON_GENERIC_PARSER_SMOKE_ARTIFACT, SCHEMA_JSON_GENERIC_PARSER_NAME, SCHEMA_JSON_GENERIC_PARSER_ID, SCHEMA_JSON_GENERIC_PARSER_MODE, SCHEMA_JSON_GENERIC_PARSER_FILE, SCHEMA_JSON_GENERIC_PARSER_MODULE_FILE, SCHEMA_JSON_GENERIC_PARSER_SMOKE_RUNNER_FILE, SCHEMA_JSON_GENERIC_PARSER_WASM_FILE, SCHEMA_JSON_GENERIC_PARSER_WAT_FILE, SCHEMA_JSON_GENERIC_PARSER_WASM, SCHEMA_JSON_GENERIC_PARSER_WAT, SCHEMA_JSON_GENERIC_PARSER_DOC_FILE, SCHEMA_JSON_TARGETS, SCHEMA_JSON_GENERIC_PARSER_TARGETS, SCHEMA_JSON_PARSER_MODES, SCHEMA_JSON_GENERIC_VALUE_KINDS, SCHEMA_JSON_GENERIC_PARSER_ACCESSORS, SCHEMA_JSON_GENERIC_ACCESSOR_SURFACE, SCHEMA_JSON_GENERIC_RESERVED_SURFACE, SCHEMA_JSON_GENERIC_PARSER_POLICY, SCHEMA_JSON_GENERIC_PARSER_DIAGNOSTICS, configArtifact, jsonConfig, schemas, normalizeSchemaJsonTarget, normalizeJsonTarget, normalizeParserMode, normalizeSchemaJsonParser, normalizedParserId, normalizeJsonParserConfig, normalizeGenericParserConfig, normalizeSchemaJsonParserMode, normalizeSchemaJsonParserSelection, genericParserNeeded, shouldUseGenericSchemaJsonParser, shouldUseSchemaJsonGenericParser, shouldUseSchemaJsonSchemaMode, defaultSchemaJsonGenericParserPolicy };
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { sha256Hex, stableStringify } = require('../stable-id.js');
|
|
4
|
+
|
|
5
|
+
const SCHEMA_REGISTRY_IR_VERSION = 'pulse.schema-registry-ir.v1';
|
|
6
|
+
const SCHEMA_CODEC_INPUTS_VERSION = 'pulse.schema-codec-inputs.v1';
|
|
7
|
+
const SCHEMA_AUTHORING_VERSION = 'pulse.schema-authoring.v1';
|
|
8
|
+
const SCHEMA_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z][A-Za-z0-9_-]*)+$/;
|
|
9
|
+
const RESPONSE_CASE_ID_PATTERN = SCHEMA_ID_PATTERN;
|
|
10
|
+
const SCALAR_KINDS = Object.freeze(['string', 'boolean', 'i32', 'u32', 'f64']);
|
|
11
|
+
const NODE_KINDS = Object.freeze([...SCALAR_KINDS, 'object', 'array', 'string-enum', 'nullable']);
|
|
12
|
+
|
|
13
|
+
function schemaContractError(code, message, details = {}) {
|
|
14
|
+
const error = new TypeError(message);
|
|
15
|
+
error.code = code;
|
|
16
|
+
error.details = Object.freeze({ ...details });
|
|
17
|
+
return error;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function plainObject(value) {
|
|
21
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
22
|
+
const proto = Object.getPrototypeOf(value);
|
|
23
|
+
return proto === Object.prototype || proto === null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function deepFreeze(value) {
|
|
27
|
+
if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
|
|
28
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
29
|
+
return Object.freeze(value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function requiredString(value, field) {
|
|
33
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
34
|
+
throw schemaContractError('PULSE_SCHEMA_IR_STRING_REQUIRED', `${field} must be a non-empty string.`, { field, value });
|
|
35
|
+
}
|
|
36
|
+
return value.trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function normalizeSource(input, field) {
|
|
40
|
+
if (!plainObject(input)) {
|
|
41
|
+
throw schemaContractError('PULSE_SCHEMA_IR_SOURCE_REQUIRED', `${field} must identify a source location.`, { field });
|
|
42
|
+
}
|
|
43
|
+
const line = Number(input.line);
|
|
44
|
+
const column = Number(input.column);
|
|
45
|
+
if (!Number.isSafeInteger(line) || line < 1 || !Number.isSafeInteger(column) || column < 1) {
|
|
46
|
+
throw schemaContractError('PULSE_SCHEMA_IR_SOURCE_INVALID', `${field} requires positive line and column values.`, {
|
|
47
|
+
field,
|
|
48
|
+
line,
|
|
49
|
+
column
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return Object.freeze({
|
|
53
|
+
file: requiredString(input.file, `${field}.file`).replace(/\\/g, '/'),
|
|
54
|
+
line,
|
|
55
|
+
column
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function normalizeId(value, field, pattern, code) {
|
|
60
|
+
const id = requiredString(value, field);
|
|
61
|
+
if (!pattern.test(id)) {
|
|
62
|
+
throw schemaContractError(code, `${field} must be a stable dotted identifier.`, { field, id });
|
|
63
|
+
}
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function normalizeSchemaNode(input, field = 'schema.root', stack = []) {
|
|
68
|
+
if (!plainObject(input)) {
|
|
69
|
+
throw schemaContractError('PULSE_SCHEMA_IR_NODE_REQUIRED', `${field} must be a normalized schema node.`, { field });
|
|
70
|
+
}
|
|
71
|
+
const kind = requiredString(input.kind, `${field}.kind`);
|
|
72
|
+
if (!NODE_KINDS.includes(kind)) {
|
|
73
|
+
throw schemaContractError('PULSE_SCHEMA_IR_NODE_KIND_UNSUPPORTED', `${field}.kind is unsupported: ${kind}.`, { field, kind });
|
|
74
|
+
}
|
|
75
|
+
if (SCALAR_KINDS.includes(kind)) return Object.freeze({ kind });
|
|
76
|
+
if (kind === 'array') {
|
|
77
|
+
return Object.freeze({ kind, element: normalizeSchemaNode(input.element, `${field}.element`, stack) });
|
|
78
|
+
}
|
|
79
|
+
if (kind === 'nullable') {
|
|
80
|
+
const value = normalizeSchemaNode(input.value, `${field}.value`, stack);
|
|
81
|
+
if (value.kind === 'nullable') {
|
|
82
|
+
throw schemaContractError('PULSE_SCHEMA_IR_REDUNDANT_NULLABLE', `${field} cannot contain another nullable node.`, { field });
|
|
83
|
+
}
|
|
84
|
+
return Object.freeze({ kind, value });
|
|
85
|
+
}
|
|
86
|
+
if (kind === 'string-enum') {
|
|
87
|
+
if (!Array.isArray(input.values) || input.values.length === 0) {
|
|
88
|
+
throw schemaContractError('PULSE_SCHEMA_IR_ENUM_VALUES_REQUIRED', `${field}.values must contain at least one string literal.`, { field });
|
|
89
|
+
}
|
|
90
|
+
const values = input.values.map((value, index) => requiredString(value, `${field}.values[${index}]`));
|
|
91
|
+
if (new Set(values).size !== values.length) {
|
|
92
|
+
throw schemaContractError('PULSE_SCHEMA_IR_ENUM_VALUE_DUPLICATE', `${field}.values must be unique.`, { field, values });
|
|
93
|
+
}
|
|
94
|
+
return Object.freeze({ kind, values: Object.freeze(values) });
|
|
95
|
+
}
|
|
96
|
+
if (!Array.isArray(input.fields)) {
|
|
97
|
+
throw schemaContractError('PULSE_SCHEMA_IR_OBJECT_FIELDS_REQUIRED', `${field}.fields must be an array.`, { field });
|
|
98
|
+
}
|
|
99
|
+
const names = new Set();
|
|
100
|
+
const fields = input.fields.map((entry, index) => {
|
|
101
|
+
if (!plainObject(entry)) {
|
|
102
|
+
throw schemaContractError('PULSE_SCHEMA_IR_FIELD_REQUIRED', `${field}.fields[${index}] must be an object.`, { field, index });
|
|
103
|
+
}
|
|
104
|
+
const name = requiredString(entry.name, `${field}.fields[${index}].name`);
|
|
105
|
+
if (names.has(name)) {
|
|
106
|
+
throw schemaContractError('PULSE_SCHEMA_IR_FIELD_DUPLICATE', `${field} declares field ${name} more than once.`, { field, name });
|
|
107
|
+
}
|
|
108
|
+
names.add(name);
|
|
109
|
+
if (entry.required !== true) {
|
|
110
|
+
throw schemaContractError('PULSE_SCHEMA_OPTIONAL_FIELD_RESERVED', `${field}.${name} must be required in schema IR v1.`, {
|
|
111
|
+
field,
|
|
112
|
+
name
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return Object.freeze({
|
|
116
|
+
name,
|
|
117
|
+
required: true,
|
|
118
|
+
value: normalizeSchemaNode(entry.value, `${field}.fields[${index}].value`, [...stack, name]),
|
|
119
|
+
source: entry.source ? normalizeSource(entry.source, `${field}.fields[${index}].source`) : undefined
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
return Object.freeze({ kind, fields: Object.freeze(fields) });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function normalizeSchema(input, index) {
|
|
126
|
+
if (!plainObject(input)) {
|
|
127
|
+
throw schemaContractError('PULSE_SCHEMA_IR_SCHEMA_REQUIRED', `schemas[${index}] must be an object.`, { index });
|
|
128
|
+
}
|
|
129
|
+
const id = normalizeId(input.id, `schemas[${index}].id`, SCHEMA_ID_PATTERN, 'PULSE_SCHEMA_ID_INVALID');
|
|
130
|
+
const root = normalizeSchemaNode(input.root, `schemas[${index}].root`);
|
|
131
|
+
if (root.kind !== 'object') {
|
|
132
|
+
throw schemaContractError('PULSE_SCHEMA_ROOT_OBJECT_REQUIRED', `Schema ${id} must have an object root.`, { id, kind: root.kind });
|
|
133
|
+
}
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
id,
|
|
136
|
+
typeName: requiredString(input.typeName, `schemas[${index}].typeName`),
|
|
137
|
+
root,
|
|
138
|
+
source: normalizeSource(input.source, `schemas[${index}].source`)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function normalizeResponseCase(input, index) {
|
|
143
|
+
if (!plainObject(input)) {
|
|
144
|
+
throw schemaContractError('PULSE_RESPONSE_CASE_REQUIRED', `responses[${index}] must be an object.`, { index });
|
|
145
|
+
}
|
|
146
|
+
const status = Number(input.status);
|
|
147
|
+
if (!Number.isSafeInteger(status) || status < 100 || status > 599) {
|
|
148
|
+
throw schemaContractError('PULSE_RESPONSE_STATUS_INVALID', `responses[${index}].status must be an integer from 100 through 599.`, {
|
|
149
|
+
index,
|
|
150
|
+
status
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return Object.freeze({
|
|
154
|
+
id: normalizeId(input.id, `responses[${index}].id`, RESPONSE_CASE_ID_PATTERN, 'PULSE_RESPONSE_CASE_ID_INVALID'),
|
|
155
|
+
status,
|
|
156
|
+
schemaId: normalizeId(input.schemaId, `responses[${index}].schemaId`, SCHEMA_ID_PATTERN, 'PULSE_SCHEMA_ID_INVALID'),
|
|
157
|
+
source: normalizeSource(input.source, `responses[${index}].source`)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function assertUnique(entries, field, code) {
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (seen.has(entry.id)) {
|
|
165
|
+
throw schemaContractError(code, `${field} contains duplicate ID ${entry.id}.`, { field, id: entry.id });
|
|
166
|
+
}
|
|
167
|
+
seen.add(entry.id);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function normalizeSchemaRegistry(input) {
|
|
172
|
+
if (!plainObject(input)) {
|
|
173
|
+
throw schemaContractError('PULSE_SCHEMA_REGISTRY_REQUIRED', 'Schema registry IR must be an object.');
|
|
174
|
+
}
|
|
175
|
+
const schemas = Object.freeze((input.schemas || []).map(normalizeSchema));
|
|
176
|
+
const responses = Object.freeze((input.responses || []).map(normalizeResponseCase));
|
|
177
|
+
assertUnique(schemas, 'schemas', 'PULSE_SCHEMA_ID_DUPLICATE');
|
|
178
|
+
assertUnique(responses, 'responses', 'PULSE_RESPONSE_CASE_ID_DUPLICATE');
|
|
179
|
+
const schemaIds = new Set(schemas.map((entry) => entry.id));
|
|
180
|
+
for (const entry of responses) {
|
|
181
|
+
if (!schemaIds.has(entry.schemaId)) {
|
|
182
|
+
throw schemaContractError(
|
|
183
|
+
'PULSE_RESPONSE_SCHEMA_UNKNOWN',
|
|
184
|
+
`Response case ${entry.id} references unknown schema ${entry.schemaId}.`,
|
|
185
|
+
{ responseCaseId: entry.id, schemaId: entry.schemaId }
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const semantic = {
|
|
190
|
+
version: SCHEMA_REGISTRY_IR_VERSION,
|
|
191
|
+
source: normalizeSource(input.source, 'source'),
|
|
192
|
+
schemas,
|
|
193
|
+
responses,
|
|
194
|
+
policies: deepFreeze({
|
|
195
|
+
objectRoots: true,
|
|
196
|
+
requiredFieldsOnly: true,
|
|
197
|
+
unknownInputFields: 'drop',
|
|
198
|
+
outputFields: 'declared-only',
|
|
199
|
+
outputFieldOrder: 'declaration',
|
|
200
|
+
numericPolicy: 'finite-rfc-json',
|
|
201
|
+
parity: 'semantic',
|
|
202
|
+
dynamicIds: false,
|
|
203
|
+
schemaTrialFallback: false,
|
|
204
|
+
publicDecorators: false
|
|
205
|
+
})
|
|
206
|
+
};
|
|
207
|
+
return deepFreeze({
|
|
208
|
+
...semantic,
|
|
209
|
+
registryHash: sha256Hex(stableStringify(semantic))
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function assemblyScriptType(node, symbols, pathParts) {
|
|
214
|
+
switch (node.kind) {
|
|
215
|
+
case 'string': return 'string';
|
|
216
|
+
case 'boolean': return 'bool';
|
|
217
|
+
case 'i32': return 'i32';
|
|
218
|
+
case 'u32': return 'u32';
|
|
219
|
+
case 'f64': return 'f64';
|
|
220
|
+
case 'string-enum': return 'string';
|
|
221
|
+
case 'array': return `Array<${assemblyScriptType(node.element, symbols, [...pathParts, 'item'])}>`;
|
|
222
|
+
case 'nullable': return `${assemblyScriptType(node.value, symbols, [...pathParts, 'value'])} | null`;
|
|
223
|
+
case 'object': {
|
|
224
|
+
const key = pathParts.join('.');
|
|
225
|
+
return symbols.get(key);
|
|
226
|
+
}
|
|
227
|
+
default: throw schemaContractError('PULSE_SCHEMA_IR_NODE_KIND_UNSUPPORTED', `Unsupported schema node kind ${node.kind}.`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function identifier(value) {
|
|
232
|
+
const normalized = String(value).normalize('NFKC').replace(/[^A-Za-z0-9_$]+/g, '_');
|
|
233
|
+
return /^[A-Za-z_$]/.test(normalized) ? normalized : `_${normalized}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function collectNativeClasses(schema, node, symbols, classes, pathParts = []) {
|
|
237
|
+
if (node.kind === 'nullable') return collectNativeClasses(schema, node.value, symbols, classes, [...pathParts, 'value']);
|
|
238
|
+
if (node.kind === 'array') return collectNativeClasses(schema, node.element, symbols, classes, [...pathParts, 'item']);
|
|
239
|
+
if (node.kind !== 'object') return;
|
|
240
|
+
const key = pathParts.join('.');
|
|
241
|
+
const symbol = `__Pulse_${identifier(schema.id)}${pathParts.length === 0 ? '' : `_${pathParts.map(identifier).join('_')}`}`;
|
|
242
|
+
symbols.set(key, symbol);
|
|
243
|
+
for (const field of node.fields) collectNativeClasses(schema, field.value, symbols, classes, [...pathParts, field.name]);
|
|
244
|
+
classes.push(Object.freeze({
|
|
245
|
+
symbol,
|
|
246
|
+
schemaId: schema.id,
|
|
247
|
+
path: pathParts.length === 0 ? '' : `/${pathParts.map((part) => String(part).replace(/~/g, '~0').replace(/\//g, '~1')).join('/')}`,
|
|
248
|
+
fields: Object.freeze(node.fields.map((field) => Object.freeze({
|
|
249
|
+
name: field.name,
|
|
250
|
+
type: assemblyScriptType(field.value, symbols, [...pathParts, field.name]),
|
|
251
|
+
required: true,
|
|
252
|
+
constraints: field.value.kind === 'string-enum'
|
|
253
|
+
? Object.freeze({ enum: field.value.values })
|
|
254
|
+
: Object.freeze({})
|
|
255
|
+
})))
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function codecInputsForRegistry(registryInput) {
|
|
260
|
+
const registry = normalizeSchemaRegistry(registryInput);
|
|
261
|
+
const nativeSchemas = registry.schemas.map((schema) => {
|
|
262
|
+
const schemaClasses = [];
|
|
263
|
+
const symbols = new Map();
|
|
264
|
+
collectNativeClasses(schema, schema.root, symbols, schemaClasses);
|
|
265
|
+
return Object.freeze({
|
|
266
|
+
id: schema.id,
|
|
267
|
+
rootClass: symbols.get(''),
|
|
268
|
+
classes: Object.freeze(schemaClasses),
|
|
269
|
+
parse: `JSON.parse<${symbols.get('')}>`,
|
|
270
|
+
stringify: `JSON.stringify<${symbols.get('')}>`
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
return deepFreeze({
|
|
274
|
+
version: SCHEMA_CODEC_INPUTS_VERSION,
|
|
275
|
+
registryVersion: registry.version,
|
|
276
|
+
registryHash: registry.registryHash,
|
|
277
|
+
javascript: {
|
|
278
|
+
backend: 'pulse-generated',
|
|
279
|
+
operation: 'direct-parse-or-serialize',
|
|
280
|
+
schemas: registry.schemas,
|
|
281
|
+
policies: registry.policies
|
|
282
|
+
},
|
|
283
|
+
native: {
|
|
284
|
+
backend: 'json-as',
|
|
285
|
+
package: 'json-as',
|
|
286
|
+
packageVersion: '1.5.0',
|
|
287
|
+
transform: 'json-as',
|
|
288
|
+
assemblyScriptVersion: '0.28.18',
|
|
289
|
+
generatedOnly: true,
|
|
290
|
+
publicDecorators: false,
|
|
291
|
+
schemas: Object.freeze(nativeSchemas)
|
|
292
|
+
},
|
|
293
|
+
responses: registry.responses
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function defaultSchemaBoundaryPolicy() {
|
|
298
|
+
return deepFreeze({
|
|
299
|
+
strict: {
|
|
300
|
+
missingSchemaId: 'diagnostic',
|
|
301
|
+
knownSchemaId: 'schema-codec',
|
|
302
|
+
unknownSchemaId: 'diagnostic'
|
|
303
|
+
},
|
|
304
|
+
nonStrict: {
|
|
305
|
+
missingSchemaId: 'generic-json',
|
|
306
|
+
knownSchemaId: 'schema-codec',
|
|
307
|
+
unknownSchemaId: 'diagnostic'
|
|
308
|
+
},
|
|
309
|
+
suppliedIds: 'string-literal-only',
|
|
310
|
+
genericJsonFallbackForUnknownId: false,
|
|
311
|
+
schemaTrialFallback: false,
|
|
312
|
+
jsonBodyOwnership: 'pulse-semantic-encoding',
|
|
313
|
+
bodyOwnership: 'caller-exact-payload',
|
|
314
|
+
bodyAndJsonMutuallyExclusive: true
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function defaultSchemaRegistryContract() {
|
|
319
|
+
return deepFreeze({
|
|
320
|
+
authoringVersion: SCHEMA_AUTHORING_VERSION,
|
|
321
|
+
registryVersion: SCHEMA_REGISTRY_IR_VERSION,
|
|
322
|
+
codecInputsVersion: SCHEMA_CODEC_INPUTS_VERSION,
|
|
323
|
+
schemaIdPattern: SCHEMA_ID_PATTERN.source,
|
|
324
|
+
responseCaseIdPattern: RESPONSE_CASE_ID_PATTERN.source,
|
|
325
|
+
scalarKinds: SCALAR_KINDS,
|
|
326
|
+
nodeKinds: NODE_KINDS,
|
|
327
|
+
helpers: ['defineSchemaRegistry', 'schema', 'response'],
|
|
328
|
+
markerTypes: ['Int32', 'Uint32'],
|
|
329
|
+
policies: {
|
|
330
|
+
canonicalEntrypoint: 'pulse.schema',
|
|
331
|
+
defaultExportRequired: true,
|
|
332
|
+
staticObjectLiteralsOnly: true,
|
|
333
|
+
stableStringIds: true,
|
|
334
|
+
exactLiteralIdsAtBoundaries: true,
|
|
335
|
+
oldSchemasJsonSupported: false,
|
|
336
|
+
optionalPropertiesSupported: false,
|
|
337
|
+
recursiveSchemasSupported: false,
|
|
338
|
+
publicJsonAsImportsSupported: false,
|
|
339
|
+
automaticFallback: false
|
|
340
|
+
},
|
|
341
|
+
boundaryPolicy: defaultSchemaBoundaryPolicy()
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
module.exports = Object.freeze({
|
|
346
|
+
SCHEMA_REGISTRY_IR_VERSION,
|
|
347
|
+
SCHEMA_CODEC_INPUTS_VERSION,
|
|
348
|
+
SCHEMA_AUTHORING_VERSION,
|
|
349
|
+
SCHEMA_ID_PATTERN,
|
|
350
|
+
RESPONSE_CASE_ID_PATTERN,
|
|
351
|
+
SCALAR_KINDS,
|
|
352
|
+
NODE_KINDS,
|
|
353
|
+
schemaContractError,
|
|
354
|
+
normalizeSchemaNode,
|
|
355
|
+
normalizeSchemaRegistry,
|
|
356
|
+
codecInputsForRegistry,
|
|
357
|
+
defaultSchemaBoundaryPolicy,
|
|
358
|
+
defaultSchemaRegistryContract
|
|
359
|
+
});
|