@hypequery/protocol 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/deployments/validate.d.ts.map +1 -1
- package/dist/deployments/validate.js +8 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas/apply.d.ts +13 -0
- package/dist/schemas/apply.d.ts.map +1 -0
- package/dist/schemas/apply.js +294 -0
- package/dist/schemas/index.d.ts +4 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/types.d.ts +11 -0
- package/dist/schemas/types.d.ts.map +1 -1
- package/dist/schemas/validate.d.ts.map +1 -1
- package/dist/schemas/validate.js +11 -3
- package/dist/schemas/value-limits.d.ts +4 -0
- package/dist/schemas/value-limits.d.ts.map +1 -0
- package/dist/schemas/value-limits.js +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,9 @@ against a dataset contract before execution.
|
|
|
62
62
|
The proposed schema surface exports strict types and validation for portable
|
|
63
63
|
query input/output schemas. It covers the current declarative Serve/Zod schema
|
|
64
64
|
features without depending on Zod or embedding executable transforms and
|
|
65
|
-
refinements.
|
|
65
|
+
refinements. The reusable schema-value parser applies defaults and unknown
|
|
66
|
+
property policy to bounded plain wire values and returns detached immutable
|
|
67
|
+
values for execution adapters.
|
|
66
68
|
|
|
67
69
|
The proposed query-implementation surface keeps trusted implementation details
|
|
68
70
|
separate from public query intent. It covers Dataset SQL expressions, fixed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/deployments/validate.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAEV,uBAAuB,EASvB,0BAA0B,EAE1B,yBAAyB,EAK1B,MAAM,YAAY,CAAC;AAsfpB,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,yBAA8B,GACtC,uBAAuB,CAEzB;AAoKD,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,yBAA8B,GACtC,0BAA0B,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/deployments/validate.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAEV,uBAAuB,EASvB,0BAA0B,EAE1B,yBAAyB,EAK1B,MAAM,YAAY,CAAC;AAsfpB,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,yBAA8B,GACtC,uBAAuB,CAEzB;AAoKD,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,yBAA8B,GACtC,0BAA0B,CA2C5B"}
|
|
@@ -532,6 +532,14 @@ export function validateProtocolDeploymentContract(input, options = {}) {
|
|
|
532
532
|
queries,
|
|
533
533
|
artifacts,
|
|
534
534
|
});
|
|
535
|
+
const routes = new Set();
|
|
536
|
+
for (const [queryIndex, query] of queries.entries()) {
|
|
537
|
+
const route = `${query.endpoint.method}\0${query.endpoint.path}`;
|
|
538
|
+
if (routes.has(route)) {
|
|
539
|
+
deploymentError('HQ_DEPLOYMENT_INVALID_VALUE', `$.queries[${queryIndex}].endpoint`);
|
|
540
|
+
}
|
|
541
|
+
routes.add(route);
|
|
542
|
+
}
|
|
535
543
|
validateReferences(result);
|
|
536
544
|
return result;
|
|
537
545
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { DEFAULT_CANONICAL_VALUE_LIMITS, ProtocolValueError, decodeCanonicalValu
|
|
|
2
2
|
export type { ArrayTaggedValue, BytesTaggedValue, CanonicalValue, CanonicalValueLimits, CanonicalValueOptions, DateTaggedValue, DatetimeTaggedValue, DecimalTaggedValue, EnumTaggedValue, IntegerTaggedValue, MapTaggedValue, ProtocolValueErrorCode, TaggedValue, TupleTaggedValue, UuidTaggedValue, } from './values/index.js';
|
|
3
3
|
export { PROTOCOL_IDENTIFIER_LIMITS, ProtocolIdentifierError, isProtocolIdentifier, isProtocolQualifiedIdentifier, joinProtocolQualifiedIdentifier, parseProtocolIdentifier, parseProtocolQualifiedIdentifier, splitProtocolQualifiedIdentifier, } from './identifiers/index.js';
|
|
4
4
|
export { DEFAULT_PROTOCOL_EXPRESSION_LIMITS, ProtocolExpressionError, validateProtocolExpression, validateProtocolSemanticQuery, } from './expressions/index.js';
|
|
5
|
-
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, ProtocolSchemaError, validateProtocolSchema, } from './schemas/index.js';
|
|
6
|
-
export type { ProtocolSchema, ProtocolSchemaErrorCode, ProtocolSchemaLimits, ProtocolSchemaOptions, } from './schemas/index.js';
|
|
5
|
+
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, ProtocolSchemaError, ProtocolSchemaValueError, applyProtocolSchemaValue, createProtocolSchemaValueParser, resolveProtocolSchemaValueLimits, validateProtocolSchema, } from './schemas/index.js';
|
|
6
|
+
export type { ProtocolSchema, ProtocolSchemaErrorCode, ProtocolSchemaLimits, ProtocolSchemaOptions, ProtocolSchemaValueLimits, ProtocolSchemaValueOptions, ProtocolSchemaValueParser, } from './schemas/index.js';
|
|
7
7
|
export type { ProtocolAggregation, ProtocolBinaryOperator, ProtocolComparisonOperator, ProtocolDatasetQuery, ProtocolExpression, ProtocolExpressionErrorCode, ProtocolExpressionLimits, ProtocolExpressionOptions, ProtocolFunctionName, ProtocolMetricQuery, ProtocolOrderBy, ProtocolSemanticQuery, ProtocolTimeGrain, } from './expressions/index.js';
|
|
8
8
|
export type { ProtocolIdentifier, ProtocolIdentifierErrorCode, ProtocolQualifiedIdentifier, } from './identifiers/index.js';
|
|
9
9
|
export { DEFAULT_PROTOCOL_QUERY_IMPLEMENTATION_LIMITS, ProtocolQueryImplementationError, validateProtocolQueryImplementation, validateProtocolSqlExpression, } from './query-implementations/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,oBAAoB,EACpB,6BAA6B,EAC7B,+BAA+B,EAC/B,uBAAuB,EACvB,gCAAgC,EAChC,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,kCAAkC,EAClC,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,8BAA8B,EAC9B,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { DEFAULT_CANONICAL_VALUE_LIMITS, ProtocolValueError, decodeCanonicalValue, encodeCanonicalValue, encodeCanonicalValueToString, hashCanonicalValue, validateCanonicalValue, } from './values/index.js';
|
|
2
2
|
export { PROTOCOL_IDENTIFIER_LIMITS, ProtocolIdentifierError, isProtocolIdentifier, isProtocolQualifiedIdentifier, joinProtocolQualifiedIdentifier, parseProtocolIdentifier, parseProtocolQualifiedIdentifier, splitProtocolQualifiedIdentifier, } from './identifiers/index.js';
|
|
3
3
|
export { DEFAULT_PROTOCOL_EXPRESSION_LIMITS, ProtocolExpressionError, validateProtocolExpression, validateProtocolSemanticQuery, } from './expressions/index.js';
|
|
4
|
-
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, ProtocolSchemaError, validateProtocolSchema, } from './schemas/index.js';
|
|
4
|
+
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, ProtocolSchemaError, ProtocolSchemaValueError, applyProtocolSchemaValue, createProtocolSchemaValueParser, resolveProtocolSchemaValueLimits, validateProtocolSchema, } from './schemas/index.js';
|
|
5
5
|
export { DEFAULT_PROTOCOL_QUERY_IMPLEMENTATION_LIMITS, ProtocolQueryImplementationError, validateProtocolQueryImplementation, validateProtocolSqlExpression, } from './query-implementations/index.js';
|
|
6
6
|
export { DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS, PROTOCOL_DEPLOYMENT_BUNDLE_IDENTITY_DOMAIN, ProtocolDeploymentBundleError, encodeProtocolDeploymentBundleManifest, encodeProtocolDeploymentBundleManifestToString, hashProtocolDeploymentBundleManifest, prepareProtocolDeploymentBundleManifest, validateProtocolDeploymentBundleManifest, } from './bundles/index.js';
|
|
7
7
|
export { DEFAULT_PROTOCOL_DEPLOYMENT_RELEASE_LIMITS, PROTOCOL_DEPLOYMENT_RELEASE_IDENTITY_DOMAIN, ProtocolDeploymentReleaseError, encodeProtocolDeploymentReleaseEnvelope, encodeProtocolDeploymentReleaseEnvelopeToString, hashProtocolDeploymentReleaseEnvelope, prepareProtocolDeploymentReleaseEnvelope, validateProtocolDeploymentReleaseEnvelope, validateProtocolDeploymentReleaseTarget, } from './releases/index.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ProtocolSchema, ProtocolSchemaValueOptions } from './types.js';
|
|
2
|
+
export declare class ProtocolSchemaValueError extends Error {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly code: "HQ_SCHEMA_VALUE_INVALID";
|
|
5
|
+
constructor(path: string);
|
|
6
|
+
}
|
|
7
|
+
export interface ProtocolSchemaValueParser {
|
|
8
|
+
parse(input: unknown): unknown;
|
|
9
|
+
parseJson?(input: string | Uint8Array): unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function createProtocolSchemaValueParser(input: ProtocolSchema, options?: ProtocolSchemaValueOptions): ProtocolSchemaValueParser;
|
|
12
|
+
export declare function applyProtocolSchemaValue(schema: ProtocolSchema, value: unknown, options?: ProtocolSchemaValueOptions): unknown;
|
|
13
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/schemas/apply.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EAEd,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAKpB,qBAAa,wBAAyB,SAAQ,KAAK;IAGrC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFjC,QAAQ,CAAC,IAAI,EAAG,yBAAyB,CAAU;gBAE9B,IAAI,EAAE,MAAM;CAIlC;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B,SAAS,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;CACjD;AAyPD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAoB3B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAET"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { DEFAULT_CANONICAL_VALUE_LIMITS } from '../values/limits.js';
|
|
2
|
+
import { parseDuplicateAwareJson } from '../values/parser.js';
|
|
3
|
+
import { resolveProtocolSchemaValueLimits } from './value-limits.js';
|
|
4
|
+
import { validateProtocolSchema } from './validate.js';
|
|
5
|
+
export class ProtocolSchemaValueError extends Error {
|
|
6
|
+
path;
|
|
7
|
+
code = 'HQ_SCHEMA_VALUE_INVALID';
|
|
8
|
+
constructor(path) {
|
|
9
|
+
super(`Value does not match the protocol schema at ${path}.`);
|
|
10
|
+
this.path = path;
|
|
11
|
+
this.name = 'ProtocolSchemaValueError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const textEncoder = new TextEncoder();
|
|
15
|
+
function fail(path) {
|
|
16
|
+
throw new ProtocolSchemaValueError(path);
|
|
17
|
+
}
|
|
18
|
+
function enter(value, path, depth, state) {
|
|
19
|
+
if (depth > state.limits.maxDepth || state.active.has(value))
|
|
20
|
+
fail(path);
|
|
21
|
+
state.active.add(value);
|
|
22
|
+
}
|
|
23
|
+
function stringValue(value, path, state) {
|
|
24
|
+
if (typeof value !== 'string' || value.length > state.limits.maxStringBytes
|
|
25
|
+
|| textEncoder.encode(value).byteLength > state.limits.maxStringBytes)
|
|
26
|
+
fail(path);
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function propertyPath(path, key) {
|
|
30
|
+
return /^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(key) ? `${path}.${key}` : `${path}.*`;
|
|
31
|
+
}
|
|
32
|
+
function record(value, path) {
|
|
33
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
34
|
+
fail(path);
|
|
35
|
+
const prototype = Object.getPrototypeOf(value);
|
|
36
|
+
if (prototype !== Object.prototype && prototype !== null
|
|
37
|
+
|| Object.getOwnPropertySymbols(value).length > 0)
|
|
38
|
+
fail(path);
|
|
39
|
+
for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(value))) {
|
|
40
|
+
if (!descriptor.enumerable || !('value' in descriptor))
|
|
41
|
+
fail(path);
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
function array(value, path, state) {
|
|
46
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype
|
|
47
|
+
|| Object.getOwnPropertySymbols(value).length > 0
|
|
48
|
+
|| value.length > state.limits.maxCollectionItems)
|
|
49
|
+
fail(path);
|
|
50
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
51
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
52
|
+
const descriptor = descriptors[String(index)];
|
|
53
|
+
if (!descriptor || !descriptor.enumerable || !('value' in descriptor))
|
|
54
|
+
fail(`${path}[${index}]`);
|
|
55
|
+
}
|
|
56
|
+
if (Object.keys(value).length !== value.length)
|
|
57
|
+
fail(path);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function frozenRecord(entries) {
|
|
61
|
+
return Object.freeze(Object.assign(Object.create(null), entries));
|
|
62
|
+
}
|
|
63
|
+
function cloneAny(value, path, depth, state) {
|
|
64
|
+
state.nodes += 1;
|
|
65
|
+
if (state.nodes > state.limits.maxNodes || depth > state.limits.maxDepth)
|
|
66
|
+
fail(path);
|
|
67
|
+
if (value === null || typeof value === 'boolean')
|
|
68
|
+
return value;
|
|
69
|
+
if (typeof value === 'string')
|
|
70
|
+
return stringValue(value, path, state);
|
|
71
|
+
if (typeof value === 'number') {
|
|
72
|
+
if (!Number.isFinite(value) || Object.is(value, -0))
|
|
73
|
+
fail(path);
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
const values = array(value, path, state);
|
|
78
|
+
enter(value, path, depth, state);
|
|
79
|
+
try {
|
|
80
|
+
return Object.freeze(values.map((item, index) => (cloneAny(item, `${path}[${index}]`, depth + 1, state))));
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
state.active.delete(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const source = record(value, path);
|
|
87
|
+
if (Object.keys(source).length > state.limits.maxCollectionItems)
|
|
88
|
+
fail(path);
|
|
89
|
+
enter(source, path, depth, state);
|
|
90
|
+
try {
|
|
91
|
+
const result = Object.create(null);
|
|
92
|
+
for (const [key, item] of Object.entries(source)) {
|
|
93
|
+
const itemPath = propertyPath(path, key);
|
|
94
|
+
stringValue(key, itemPath, state);
|
|
95
|
+
result[key] = cloneAny(item, itemPath, depth + 1, state);
|
|
96
|
+
}
|
|
97
|
+
return frozenRecord(result);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
state.active.delete(source);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function canonicalToWire(value) {
|
|
104
|
+
if (typeof value !== 'object' || value === null)
|
|
105
|
+
return value;
|
|
106
|
+
const tag = value.$hypequery;
|
|
107
|
+
if (tag.type === 'array' || tag.type === 'tuple')
|
|
108
|
+
return Object.freeze(tag.values.map(canonicalToWire));
|
|
109
|
+
if (tag.type === 'map' && tag.entries.every(entry => typeof entry[0] === 'string')) {
|
|
110
|
+
const result = Object.create(null);
|
|
111
|
+
for (const [key, item] of tag.entries)
|
|
112
|
+
result[key] = canonicalToWire(item);
|
|
113
|
+
return frozenRecord(result);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function schemaDefault(schema) {
|
|
118
|
+
return 'default' in schema ? schema.default : undefined;
|
|
119
|
+
}
|
|
120
|
+
function sameValue(left, right) {
|
|
121
|
+
if (Object.is(left, right))
|
|
122
|
+
return true;
|
|
123
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
124
|
+
return left.length === right.length && left.every((item, index) => sameValue(item, right[index]));
|
|
125
|
+
}
|
|
126
|
+
if (typeof left !== 'object' || left === null || typeof right !== 'object' || right === null
|
|
127
|
+
|| Array.isArray(left) || Array.isArray(right))
|
|
128
|
+
return false;
|
|
129
|
+
const leftEntries = Object.entries(left);
|
|
130
|
+
const rightRecord = right;
|
|
131
|
+
return leftEntries.length === Object.keys(rightRecord).length
|
|
132
|
+
&& leftEntries.every(([key, value]) => Object.hasOwn(rightRecord, key)
|
|
133
|
+
&& sameValue(value, rightRecord[key]));
|
|
134
|
+
}
|
|
135
|
+
function apply(schema, input, path, depth, state) {
|
|
136
|
+
state.nodes += 1;
|
|
137
|
+
if (state.nodes > state.limits.maxNodes || depth > state.limits.maxDepth)
|
|
138
|
+
fail(path);
|
|
139
|
+
let value = input;
|
|
140
|
+
const defaultValue = schemaDefault(schema);
|
|
141
|
+
if (value === undefined && defaultValue !== undefined)
|
|
142
|
+
value = canonicalToWire(defaultValue);
|
|
143
|
+
switch (schema.kind) {
|
|
144
|
+
case 'void':
|
|
145
|
+
if (value !== undefined)
|
|
146
|
+
fail(path);
|
|
147
|
+
return undefined;
|
|
148
|
+
case 'any':
|
|
149
|
+
if (value === undefined)
|
|
150
|
+
fail(path);
|
|
151
|
+
return cloneAny(value, path, depth, state);
|
|
152
|
+
case 'null':
|
|
153
|
+
if (value !== null)
|
|
154
|
+
fail(path);
|
|
155
|
+
return null;
|
|
156
|
+
case 'boolean':
|
|
157
|
+
if (typeof value !== 'boolean')
|
|
158
|
+
fail(path);
|
|
159
|
+
return value;
|
|
160
|
+
case 'string': {
|
|
161
|
+
const string = stringValue(value, path, state);
|
|
162
|
+
const length = [...string].length;
|
|
163
|
+
if (schema.minLength !== undefined && length < schema.minLength
|
|
164
|
+
|| schema.maxLength !== undefined && length > schema.maxLength)
|
|
165
|
+
fail(path);
|
|
166
|
+
return string;
|
|
167
|
+
}
|
|
168
|
+
case 'number':
|
|
169
|
+
case 'integer': {
|
|
170
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || Object.is(value, -0)
|
|
171
|
+
|| schema.kind === 'integer' && !Number.isSafeInteger(value)
|
|
172
|
+
|| schema.minimum !== undefined && value < schema.minimum
|
|
173
|
+
|| schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum
|
|
174
|
+
|| schema.maximum !== undefined && value > schema.maximum
|
|
175
|
+
|| schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum)
|
|
176
|
+
fail(path);
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
case 'literal': {
|
|
180
|
+
const result = cloneAny(value, path, depth, state);
|
|
181
|
+
if (!sameValue(result, canonicalToWire(schema.value)))
|
|
182
|
+
fail(path);
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
case 'enum': {
|
|
186
|
+
const result = cloneAny(value, path, depth, state);
|
|
187
|
+
if (!schema.values.some(candidate => sameValue(result, canonicalToWire(candidate))))
|
|
188
|
+
fail(path);
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
case 'array': {
|
|
192
|
+
const values = array(value, path, state);
|
|
193
|
+
if (schema.minItems !== undefined && values.length < schema.minItems
|
|
194
|
+
|| schema.maxItems !== undefined && values.length > schema.maxItems)
|
|
195
|
+
fail(path);
|
|
196
|
+
enter(value, path, depth, state);
|
|
197
|
+
try {
|
|
198
|
+
return Object.freeze(values.map((item, index) => (apply(schema.items, item, `${path}[${index}]`, depth + 1, state))));
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
state.active.delete(value);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
case 'object': {
|
|
205
|
+
const source = record(value, path);
|
|
206
|
+
if (Object.keys(source).length > state.limits.maxCollectionItems)
|
|
207
|
+
fail(path);
|
|
208
|
+
enter(source, path, depth, state);
|
|
209
|
+
try {
|
|
210
|
+
const result = Object.create(null);
|
|
211
|
+
for (const [key, item] of Object.entries(source)) {
|
|
212
|
+
const itemPath = propertyPath(path, key);
|
|
213
|
+
stringValue(key, itemPath, state);
|
|
214
|
+
const property = schema.properties[key];
|
|
215
|
+
if (property)
|
|
216
|
+
result[key] = apply(property, item, itemPath, depth + 1, state);
|
|
217
|
+
else if (schema.unknownProperties === 'reject')
|
|
218
|
+
fail(itemPath);
|
|
219
|
+
else if (schema.unknownProperties === 'preserve') {
|
|
220
|
+
result[key] = cloneAny(item, itemPath, depth + 1, state);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const [key, property] of Object.entries(schema.properties)) {
|
|
224
|
+
if (!Object.hasOwn(source, key) && schemaDefault(property) !== undefined) {
|
|
225
|
+
result[key] = apply(property, undefined, `${path}.${key}`, depth + 1, state);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
for (const required of schema.required) {
|
|
229
|
+
if (!Object.hasOwn(result, required))
|
|
230
|
+
fail(`${path}.${required}`);
|
|
231
|
+
}
|
|
232
|
+
return frozenRecord(result);
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
state.active.delete(source);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
case 'record': {
|
|
239
|
+
const source = record(value, path);
|
|
240
|
+
if (Object.keys(source).length > state.limits.maxCollectionItems)
|
|
241
|
+
fail(path);
|
|
242
|
+
enter(source, path, depth, state);
|
|
243
|
+
try {
|
|
244
|
+
const result = Object.create(null);
|
|
245
|
+
for (const [key, item] of Object.entries(source)) {
|
|
246
|
+
const itemPath = propertyPath(path, key);
|
|
247
|
+
stringValue(key, itemPath, state);
|
|
248
|
+
result[key] = apply(schema.values, item, itemPath, depth + 1, state);
|
|
249
|
+
}
|
|
250
|
+
return frozenRecord(result);
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
state.active.delete(source);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
case 'union':
|
|
257
|
+
for (const variant of schema.variants) {
|
|
258
|
+
const branch = { active: state.active, limits: state.limits, nodes: state.nodes };
|
|
259
|
+
try {
|
|
260
|
+
const result = apply(variant, value, path, depth, branch);
|
|
261
|
+
state.nodes = branch.nodes;
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
state.nodes = branch.nodes;
|
|
266
|
+
if (!(error instanceof ProtocolSchemaValueError))
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
fail(path);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
export function createProtocolSchemaValueParser(input, options = {}) {
|
|
274
|
+
const schema = validateProtocolSchema(input);
|
|
275
|
+
const limits = resolveProtocolSchemaValueLimits(options);
|
|
276
|
+
const jsonLimits = Object.freeze({
|
|
277
|
+
...DEFAULT_CANONICAL_VALUE_LIMITS,
|
|
278
|
+
maxInputBytes: limits.maxInputBytes,
|
|
279
|
+
maxDepth: limits.maxDepth,
|
|
280
|
+
maxNodes: limits.maxNodes,
|
|
281
|
+
maxCollectionItems: limits.maxCollectionItems,
|
|
282
|
+
maxStringBytes: limits.maxStringBytes,
|
|
283
|
+
});
|
|
284
|
+
const parse = (value) => (apply(schema, value, '$', 1, { active: new WeakSet(), limits, nodes: 0 }));
|
|
285
|
+
return Object.freeze({
|
|
286
|
+
parse,
|
|
287
|
+
parseJson(value) {
|
|
288
|
+
return parse(parseDuplicateAwareJson(value, jsonLimits));
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
export function applyProtocolSchemaValue(schema, value, options = {}) {
|
|
293
|
+
return createProtocolSchemaValueParser(schema, options).parse(value);
|
|
294
|
+
}
|
package/dist/schemas/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { ProtocolSchemaError } from './errors.js';
|
|
2
2
|
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS } from './limits.js';
|
|
3
3
|
export { validateProtocolSchema } from './validate.js';
|
|
4
|
-
export
|
|
4
|
+
export { applyProtocolSchemaValue, createProtocolSchemaValueParser, ProtocolSchemaValueError, } from './apply.js';
|
|
5
|
+
export { DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, resolveProtocolSchemaValueLimits, } from './value-limits.js';
|
|
6
|
+
export type { ProtocolSchema, ProtocolSchemaErrorCode, ProtocolSchemaLimits, ProtocolSchemaOptions, ProtocolSchemaValueLimits, ProtocolSchemaValueOptions, } from './types.js';
|
|
7
|
+
export type { ProtocolSchemaValueParser } from './apply.js';
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oCAAoC,EACpC,gCAAgC,GACjC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/schemas/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { ProtocolSchemaError } from './errors.js';
|
|
2
2
|
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS } from './limits.js';
|
|
3
3
|
export { validateProtocolSchema } from './validate.js';
|
|
4
|
+
export { applyProtocolSchemaValue, createProtocolSchemaValueParser, ProtocolSchemaValueError, } from './apply.js';
|
|
5
|
+
export { DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, resolveProtocolSchemaValueLimits, } from './value-limits.js';
|
package/dist/schemas/types.d.ts
CHANGED
|
@@ -55,6 +55,17 @@ export interface ProtocolSchemaLimits {
|
|
|
55
55
|
export interface ProtocolSchemaOptions {
|
|
56
56
|
readonly limits?: Partial<ProtocolSchemaLimits>;
|
|
57
57
|
}
|
|
58
|
+
export interface ProtocolSchemaValueLimits {
|
|
59
|
+
readonly maxInputBytes: number;
|
|
60
|
+
readonly maxDepth: number;
|
|
61
|
+
readonly maxNodes: number;
|
|
62
|
+
readonly maxCollectionItems: number;
|
|
63
|
+
readonly maxStringBytes: number;
|
|
64
|
+
}
|
|
65
|
+
export interface ProtocolSchemaValueOptions {
|
|
66
|
+
/** Product policy may lower, but never raise, the protocol schema-value limits. */
|
|
67
|
+
readonly limits?: Partial<ProtocolSchemaValueLimits>;
|
|
68
|
+
}
|
|
58
69
|
export type ProtocolSchemaErrorCode = 'HQ_SCHEMA_TYPE' | 'HQ_SCHEMA_UNKNOWN_FIELD' | 'HQ_SCHEMA_UNKNOWN_KIND' | 'HQ_SCHEMA_INVALID_IDENTIFIER' | 'HQ_SCHEMA_INVALID_VALUE' | 'HQ_SCHEMA_INVALID_CONSTRAINT' | 'HQ_SCHEMA_INVALID_REQUIRED' | 'HQ_SCHEMA_DUPLICATE_VALUE' | 'HQ_SCHEMA_TOO_DEEP' | 'HQ_SCHEMA_TOO_MANY_NODES' | 'HQ_SCHEMA_TOO_MANY_ITEMS' | 'HQ_SCHEMA_TOO_LARGE' | 'HQ_SCHEMA_UNSAFE_OBJECT';
|
|
59
70
|
export {};
|
|
60
71
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schemas/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schemas/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,UAAU,yBAAyB;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;CACnC;AAED,MAAM,MAAM,cAAc,GACtB,CAAC,yBAAyB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,CAAC,yBAAyB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,CAAC,yBAAyB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,GAC1D,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC;IAC1E,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,QAAQ,CAAC,iBAAiB,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;CAC7D,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;CACjC,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAC9C,CAAC,CAAC;AAEP,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACtD;AAED,MAAM,MAAM,uBAAuB,GAC/B,gBAAgB,GAChB,yBAAyB,GACzB,wBAAwB,GACxB,8BAA8B,GAC9B,yBAAyB,GACzB,8BAA8B,GAC9B,4BAA4B,GAC5B,2BAA2B,GAC3B,oBAAoB,GACpB,0BAA0B,GAC1B,0BAA0B,GAC1B,qBAAqB,GACrB,yBAAyB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/schemas/validate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,cAAc,EAEd,qBAAqB,EACtB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/schemas/validate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,cAAc,EAEd,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAkapB,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAMhB"}
|
package/dist/schemas/validate.js
CHANGED
|
@@ -338,7 +338,7 @@ function matchesSchema(schema, value) {
|
|
|
338
338
|
return false;
|
|
339
339
|
const found = new Set();
|
|
340
340
|
for (const [key, item] of entries) {
|
|
341
|
-
if (typeof key !== 'string')
|
|
341
|
+
if (typeof key !== 'string' || found.has(key))
|
|
342
342
|
return false;
|
|
343
343
|
const property = schema.properties[key];
|
|
344
344
|
if (property) {
|
|
@@ -354,8 +354,16 @@ function matchesSchema(schema, value) {
|
|
|
354
354
|
}
|
|
355
355
|
case 'record': {
|
|
356
356
|
const entries = taggedEntries(value);
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
if (entries === undefined)
|
|
358
|
+
return false;
|
|
359
|
+
const found = new Set();
|
|
360
|
+
return entries.every(([key, item]) => {
|
|
361
|
+
if (typeof key !== 'string' || found.has(key) || !matchesSchema(schema.values, item)) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
found.add(key);
|
|
365
|
+
return true;
|
|
366
|
+
});
|
|
359
367
|
}
|
|
360
368
|
case 'union':
|
|
361
369
|
return schema.variants.some(variant => matchesSchema(variant, value));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProtocolSchemaValueLimits, ProtocolSchemaValueOptions } from './types.js';
|
|
2
|
+
export declare const DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS: Readonly<ProtocolSchemaValueLimits>;
|
|
3
|
+
export declare function resolveProtocolSchemaValueLimits(options?: ProtocolSchemaValueOptions): Readonly<ProtocolSchemaValueLimits>;
|
|
4
|
+
//# sourceMappingURL=value-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-limits.d.ts","sourceRoot":"","sources":["../../src/schemas/value-limits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAExF,eAAO,MAAM,oCAAoC,EAAE,QAAQ,CAAC,yBAAyB,CAOjF,CAAC;AAEL,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,0BAA+B,GACvC,QAAQ,CAAC,yBAAyB,CAAC,CAcrC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS = Object.freeze({
|
|
2
|
+
maxInputBytes: 1_048_576,
|
|
3
|
+
maxDepth: 32,
|
|
4
|
+
maxNodes: 10_000,
|
|
5
|
+
maxCollectionItems: 1_000,
|
|
6
|
+
maxStringBytes: 1_048_576,
|
|
7
|
+
});
|
|
8
|
+
export function resolveProtocolSchemaValueLimits(options = {}) {
|
|
9
|
+
const limits = { ...DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS };
|
|
10
|
+
for (const key of Object.keys(options.limits ?? {})) {
|
|
11
|
+
const value = options.limits?.[key];
|
|
12
|
+
if (value === undefined)
|
|
13
|
+
continue;
|
|
14
|
+
if (!Number.isSafeInteger(value) || value < 1
|
|
15
|
+
|| value > DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS[key]) {
|
|
16
|
+
throw new RangeError(`${key} must be a positive integer no greater than the protocol schema-value v1 maximum`);
|
|
17
|
+
}
|
|
18
|
+
limits[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return Object.freeze(limits);
|
|
21
|
+
}
|