@hypequery/protocol 0.6.0 → 0.7.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 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,CAgC5B"}
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';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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,12 @@
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
+ }
10
+ export declare function createProtocolSchemaValueParser(input: ProtocolSchema, options?: ProtocolSchemaValueOptions): ProtocolSchemaValueParser;
11
+ export declare function applyProtocolSchemaValue(schema: ProtocolSchema, value: unknown, options?: ProtocolSchemaValueOptions): unknown;
12
+ //# sourceMappingURL=apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/schemas/apply.ts"],"names":[],"mappings":"AAEA,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;CAChC;AAyPD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAQ3B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAET"}
@@ -0,0 +1,282 @@
1
+ import { resolveProtocolSchemaValueLimits } from './value-limits.js';
2
+ import { validateProtocolSchema } from './validate.js';
3
+ export class ProtocolSchemaValueError extends Error {
4
+ path;
5
+ code = 'HQ_SCHEMA_VALUE_INVALID';
6
+ constructor(path) {
7
+ super(`Value does not match the protocol schema at ${path}.`);
8
+ this.path = path;
9
+ this.name = 'ProtocolSchemaValueError';
10
+ }
11
+ }
12
+ const textEncoder = new TextEncoder();
13
+ function fail(path) {
14
+ throw new ProtocolSchemaValueError(path);
15
+ }
16
+ function enter(value, path, depth, state) {
17
+ if (depth > state.limits.maxDepth || state.active.has(value))
18
+ fail(path);
19
+ state.active.add(value);
20
+ }
21
+ function stringValue(value, path, state) {
22
+ if (typeof value !== 'string' || value.length > state.limits.maxStringBytes
23
+ || textEncoder.encode(value).byteLength > state.limits.maxStringBytes)
24
+ fail(path);
25
+ return value;
26
+ }
27
+ function propertyPath(path, key) {
28
+ return /^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(key) ? `${path}.${key}` : `${path}.*`;
29
+ }
30
+ function record(value, path) {
31
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
32
+ fail(path);
33
+ const prototype = Object.getPrototypeOf(value);
34
+ if (prototype !== Object.prototype && prototype !== null
35
+ || Object.getOwnPropertySymbols(value).length > 0)
36
+ fail(path);
37
+ for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(value))) {
38
+ if (!descriptor.enumerable || !('value' in descriptor))
39
+ fail(path);
40
+ }
41
+ return value;
42
+ }
43
+ function array(value, path, state) {
44
+ if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype
45
+ || Object.getOwnPropertySymbols(value).length > 0
46
+ || value.length > state.limits.maxCollectionItems)
47
+ fail(path);
48
+ const descriptors = Object.getOwnPropertyDescriptors(value);
49
+ for (let index = 0; index < value.length; index += 1) {
50
+ const descriptor = descriptors[String(index)];
51
+ if (!descriptor || !descriptor.enumerable || !('value' in descriptor))
52
+ fail(`${path}[${index}]`);
53
+ }
54
+ if (Object.keys(value).length !== value.length)
55
+ fail(path);
56
+ return value;
57
+ }
58
+ function frozenRecord(entries) {
59
+ return Object.freeze(Object.assign(Object.create(null), entries));
60
+ }
61
+ function cloneAny(value, path, depth, state) {
62
+ state.nodes += 1;
63
+ if (state.nodes > state.limits.maxNodes || depth > state.limits.maxDepth)
64
+ fail(path);
65
+ if (value === null || typeof value === 'boolean')
66
+ return value;
67
+ if (typeof value === 'string')
68
+ return stringValue(value, path, state);
69
+ if (typeof value === 'number') {
70
+ if (!Number.isFinite(value) || Object.is(value, -0))
71
+ fail(path);
72
+ return value;
73
+ }
74
+ if (Array.isArray(value)) {
75
+ const values = array(value, path, state);
76
+ enter(value, path, depth, state);
77
+ try {
78
+ return Object.freeze(values.map((item, index) => (cloneAny(item, `${path}[${index}]`, depth + 1, state))));
79
+ }
80
+ finally {
81
+ state.active.delete(value);
82
+ }
83
+ }
84
+ const source = record(value, path);
85
+ if (Object.keys(source).length > state.limits.maxCollectionItems)
86
+ fail(path);
87
+ enter(source, path, depth, state);
88
+ try {
89
+ const result = Object.create(null);
90
+ for (const [key, item] of Object.entries(source)) {
91
+ const itemPath = propertyPath(path, key);
92
+ stringValue(key, itemPath, state);
93
+ result[key] = cloneAny(item, itemPath, depth + 1, state);
94
+ }
95
+ return frozenRecord(result);
96
+ }
97
+ finally {
98
+ state.active.delete(source);
99
+ }
100
+ }
101
+ function canonicalToWire(value) {
102
+ if (typeof value !== 'object' || value === null)
103
+ return value;
104
+ const tag = value.$hypequery;
105
+ if (tag.type === 'array' || tag.type === 'tuple')
106
+ return Object.freeze(tag.values.map(canonicalToWire));
107
+ if (tag.type === 'map' && tag.entries.every(entry => typeof entry[0] === 'string')) {
108
+ const result = Object.create(null);
109
+ for (const [key, item] of tag.entries)
110
+ result[key] = canonicalToWire(item);
111
+ return frozenRecord(result);
112
+ }
113
+ return value;
114
+ }
115
+ function schemaDefault(schema) {
116
+ return 'default' in schema ? schema.default : undefined;
117
+ }
118
+ function sameValue(left, right) {
119
+ if (Object.is(left, right))
120
+ return true;
121
+ if (Array.isArray(left) && Array.isArray(right)) {
122
+ return left.length === right.length && left.every((item, index) => sameValue(item, right[index]));
123
+ }
124
+ if (typeof left !== 'object' || left === null || typeof right !== 'object' || right === null
125
+ || Array.isArray(left) || Array.isArray(right))
126
+ return false;
127
+ const leftEntries = Object.entries(left);
128
+ const rightRecord = right;
129
+ return leftEntries.length === Object.keys(rightRecord).length
130
+ && leftEntries.every(([key, value]) => Object.hasOwn(rightRecord, key)
131
+ && sameValue(value, rightRecord[key]));
132
+ }
133
+ function apply(schema, input, path, depth, state) {
134
+ state.nodes += 1;
135
+ if (state.nodes > state.limits.maxNodes || depth > state.limits.maxDepth)
136
+ fail(path);
137
+ let value = input;
138
+ const defaultValue = schemaDefault(schema);
139
+ if (value === undefined && defaultValue !== undefined)
140
+ value = canonicalToWire(defaultValue);
141
+ switch (schema.kind) {
142
+ case 'void':
143
+ if (value !== undefined)
144
+ fail(path);
145
+ return undefined;
146
+ case 'any':
147
+ if (value === undefined)
148
+ fail(path);
149
+ return cloneAny(value, path, depth, state);
150
+ case 'null':
151
+ if (value !== null)
152
+ fail(path);
153
+ return null;
154
+ case 'boolean':
155
+ if (typeof value !== 'boolean')
156
+ fail(path);
157
+ return value;
158
+ case 'string': {
159
+ const string = stringValue(value, path, state);
160
+ const length = [...string].length;
161
+ if (schema.minLength !== undefined && length < schema.minLength
162
+ || schema.maxLength !== undefined && length > schema.maxLength)
163
+ fail(path);
164
+ return string;
165
+ }
166
+ case 'number':
167
+ case 'integer': {
168
+ if (typeof value !== 'number' || !Number.isFinite(value) || Object.is(value, -0)
169
+ || schema.kind === 'integer' && !Number.isSafeInteger(value)
170
+ || schema.minimum !== undefined && value < schema.minimum
171
+ || schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum
172
+ || schema.maximum !== undefined && value > schema.maximum
173
+ || schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum)
174
+ fail(path);
175
+ return value;
176
+ }
177
+ case 'literal': {
178
+ const result = cloneAny(value, path, depth, state);
179
+ if (!sameValue(result, canonicalToWire(schema.value)))
180
+ fail(path);
181
+ return result;
182
+ }
183
+ case 'enum': {
184
+ const result = cloneAny(value, path, depth, state);
185
+ if (!schema.values.some(candidate => sameValue(result, canonicalToWire(candidate))))
186
+ fail(path);
187
+ return result;
188
+ }
189
+ case 'array': {
190
+ const values = array(value, path, state);
191
+ if (schema.minItems !== undefined && values.length < schema.minItems
192
+ || schema.maxItems !== undefined && values.length > schema.maxItems)
193
+ fail(path);
194
+ enter(value, path, depth, state);
195
+ try {
196
+ return Object.freeze(values.map((item, index) => (apply(schema.items, item, `${path}[${index}]`, depth + 1, state))));
197
+ }
198
+ finally {
199
+ state.active.delete(value);
200
+ }
201
+ }
202
+ case 'object': {
203
+ const source = record(value, path);
204
+ if (Object.keys(source).length > state.limits.maxCollectionItems)
205
+ fail(path);
206
+ enter(source, path, depth, state);
207
+ try {
208
+ const result = Object.create(null);
209
+ for (const [key, item] of Object.entries(source)) {
210
+ const itemPath = propertyPath(path, key);
211
+ stringValue(key, itemPath, state);
212
+ const property = schema.properties[key];
213
+ if (property)
214
+ result[key] = apply(property, item, itemPath, depth + 1, state);
215
+ else if (schema.unknownProperties === 'reject')
216
+ fail(itemPath);
217
+ else if (schema.unknownProperties === 'preserve') {
218
+ result[key] = cloneAny(item, itemPath, depth + 1, state);
219
+ }
220
+ }
221
+ for (const [key, property] of Object.entries(schema.properties)) {
222
+ if (!Object.hasOwn(source, key) && schemaDefault(property) !== undefined) {
223
+ result[key] = apply(property, undefined, `${path}.${key}`, depth + 1, state);
224
+ }
225
+ }
226
+ for (const required of schema.required) {
227
+ if (!Object.hasOwn(result, required))
228
+ fail(`${path}.${required}`);
229
+ }
230
+ return frozenRecord(result);
231
+ }
232
+ finally {
233
+ state.active.delete(source);
234
+ }
235
+ }
236
+ case 'record': {
237
+ const source = record(value, path);
238
+ if (Object.keys(source).length > state.limits.maxCollectionItems)
239
+ fail(path);
240
+ enter(source, path, depth, state);
241
+ try {
242
+ const result = Object.create(null);
243
+ for (const [key, item] of Object.entries(source)) {
244
+ const itemPath = propertyPath(path, key);
245
+ stringValue(key, itemPath, state);
246
+ result[key] = apply(schema.values, item, itemPath, depth + 1, state);
247
+ }
248
+ return frozenRecord(result);
249
+ }
250
+ finally {
251
+ state.active.delete(source);
252
+ }
253
+ }
254
+ case 'union':
255
+ for (const variant of schema.variants) {
256
+ const branch = { active: state.active, limits: state.limits, nodes: state.nodes };
257
+ try {
258
+ const result = apply(variant, value, path, depth, branch);
259
+ state.nodes = branch.nodes;
260
+ return result;
261
+ }
262
+ catch (error) {
263
+ state.nodes = branch.nodes;
264
+ if (!(error instanceof ProtocolSchemaValueError))
265
+ throw error;
266
+ }
267
+ }
268
+ fail(path);
269
+ }
270
+ }
271
+ export function createProtocolSchemaValueParser(input, options = {}) {
272
+ const schema = validateProtocolSchema(input);
273
+ const limits = resolveProtocolSchemaValueLimits(options);
274
+ return Object.freeze({
275
+ parse(value) {
276
+ return apply(schema, value, '$', 1, { active: new WeakSet(), limits, nodes: 0 });
277
+ },
278
+ });
279
+ }
280
+ export function applyProtocolSchemaValue(schema, value, options = {}) {
281
+ return createProtocolSchemaValueParser(schema, options).parse(value);
282
+ }
@@ -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 type { ProtocolSchema, ProtocolSchemaErrorCode, ProtocolSchemaLimits, ProtocolSchemaOptions, } from './types.js';
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,GACtB,MAAM,YAAY,CAAC"}
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"}
@@ -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';
@@ -55,6 +55,16 @@ export interface ProtocolSchemaLimits {
55
55
  export interface ProtocolSchemaOptions {
56
56
  readonly limits?: Partial<ProtocolSchemaLimits>;
57
57
  }
58
+ export interface ProtocolSchemaValueLimits {
59
+ readonly maxDepth: number;
60
+ readonly maxNodes: number;
61
+ readonly maxCollectionItems: number;
62
+ readonly maxStringBytes: number;
63
+ }
64
+ export interface ProtocolSchemaValueOptions {
65
+ /** Product policy may lower, but never raise, the protocol schema-value limits. */
66
+ readonly limits?: Partial<ProtocolSchemaValueLimits>;
67
+ }
58
68
  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
69
  export {};
60
70
  //# 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,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;AA2ZpB,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAMhB"}
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"}
@@ -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
- return entries !== undefined
358
- && entries.every(([key, item]) => typeof key === 'string' && matchesSchema(schema.values, item));
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,CAMjF,CAAC;AAEL,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,0BAA+B,GACvC,QAAQ,CAAC,yBAAyB,CAAC,CAcrC"}
@@ -0,0 +1,20 @@
1
+ export const DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS = Object.freeze({
2
+ maxDepth: 32,
3
+ maxNodes: 10_000,
4
+ maxCollectionItems: 1_000,
5
+ maxStringBytes: 1_048_576,
6
+ });
7
+ export function resolveProtocolSchemaValueLimits(options = {}) {
8
+ const limits = { ...DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS };
9
+ for (const key of Object.keys(options.limits ?? {})) {
10
+ const value = options.limits?.[key];
11
+ if (value === undefined)
12
+ continue;
13
+ if (!Number.isSafeInteger(value) || value < 1
14
+ || value > DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS[key]) {
15
+ throw new RangeError(`${key} must be a positive integer no greater than the protocol schema-value v1 maximum`);
16
+ }
17
+ limits[key] = value;
18
+ }
19
+ return Object.freeze(limits);
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/protocol",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Public contracts and TypeScript reference implementation for portable Hypequery artifacts",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",