@hypequery/protocol 0.10.2 → 0.11.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/dist/cache-keys/cache-keys.d.ts +19 -0
- package/dist/cache-keys/cache-keys.d.ts.map +1 -0
- package/dist/cache-keys/cache-keys.js +141 -0
- package/dist/cache-keys/index.d.ts +4 -0
- package/dist/cache-keys/index.d.ts.map +1 -0
- package/dist/cache-keys/index.js +2 -0
- package/dist/cache-keys/types.d.ts +26 -0
- package/dist/cache-keys/types.d.ts.map +1 -0
- package/dist/cache-keys/types.js +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/values/validate.d.ts.map +1 -1
- package/dist/values/validate.js +10 -2
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type DeriveProtocolCacheKeyOptions, type ProtocolCacheKeyErrorCode } from './types.js';
|
|
2
|
+
export declare class ProtocolCacheKeyError extends Error {
|
|
3
|
+
readonly code: ProtocolCacheKeyErrorCode;
|
|
4
|
+
constructor(code: ProtocolCacheKeyErrorCode);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Derives the opaque namespace prefix. Truncated to 16 bytes because it is a
|
|
8
|
+
* grouping label for prefix operations, not an authentication tag.
|
|
9
|
+
*/
|
|
10
|
+
export declare function deriveProtocolCacheNamespaceToken(secret: Uint8Array, project: string, environment: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Derives the opaque store key for one canonical preimage (RFC 0013).
|
|
13
|
+
*
|
|
14
|
+
* The preimage never appears in the result. An unkeyed digest would be
|
|
15
|
+
* offline-guessable — the schema is public and identifier value spaces are
|
|
16
|
+
* small — so the derivation is an HMAC under a per-namespace secret.
|
|
17
|
+
*/
|
|
18
|
+
export declare function deriveProtocolCacheKey(options: DeriveProtocolCacheKeyOptions): string;
|
|
19
|
+
//# sourceMappingURL=cache-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-keys.d.ts","sourceRoot":"","sources":["../../src/cache-keys/cache-keys.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC/B,MAAM,YAAY,CAAC;AAUpB,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;gBAE7B,IAAI,EAAE,yBAAyB;CAO5C;AA8FD;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,CAUR;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,CA8BrF"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
3
|
+
import { validateProtocolDeploymentReleaseTarget } from '../releases/validate.js';
|
|
4
|
+
import { PROTOCOL_CACHE_KEY_LIMITS, } from './types.js';
|
|
5
|
+
const SCHEME = 'hq1';
|
|
6
|
+
const NAMESPACE_DOMAIN = 'hypequery.cache.namespace.v1';
|
|
7
|
+
const ENTRY_DOMAIN = 'hypequery.cache.entry.v1';
|
|
8
|
+
const textEncoder = new TextEncoder();
|
|
9
|
+
const BASE64URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
10
|
+
export class ProtocolCacheKeyError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(code) {
|
|
13
|
+
// The message is the code and nothing else: an error here has the secret
|
|
14
|
+
// and the preimage in scope, and neither may reach a log.
|
|
15
|
+
super(code);
|
|
16
|
+
this.name = 'ProtocolCacheKeyError';
|
|
17
|
+
this.code = code;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function cacheKeyError(code) {
|
|
21
|
+
throw new ProtocolCacheKeyError(code);
|
|
22
|
+
}
|
|
23
|
+
/** RFC 4648 base64url without padding. */
|
|
24
|
+
function base64url(bytes) {
|
|
25
|
+
let out = '';
|
|
26
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
27
|
+
const b0 = bytes[index];
|
|
28
|
+
const b1 = bytes[index + 1];
|
|
29
|
+
const b2 = bytes[index + 2];
|
|
30
|
+
out += BASE64URL[b0 >> 2];
|
|
31
|
+
out += BASE64URL[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)];
|
|
32
|
+
if (b1 === undefined)
|
|
33
|
+
break;
|
|
34
|
+
out += BASE64URL[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)];
|
|
35
|
+
if (b2 === undefined)
|
|
36
|
+
break;
|
|
37
|
+
out += BASE64URL[b2 & 0x3f];
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Joins parts with a single 0x00 byte. RFC 0008 restricts deployment target
|
|
43
|
+
* tokens to an ASCII grammar that excludes 0x00, so the concatenation is
|
|
44
|
+
* injective — which is why the namespace must be validated before this runs.
|
|
45
|
+
*/
|
|
46
|
+
function joinNulSeparated(parts) {
|
|
47
|
+
const total = parts.reduce((sum, part) => sum + part.byteLength, 0) + parts.length - 1;
|
|
48
|
+
const out = new Uint8Array(total);
|
|
49
|
+
let offset = 0;
|
|
50
|
+
parts.forEach((part, index) => {
|
|
51
|
+
if (index > 0) {
|
|
52
|
+
out[offset] = 0x00;
|
|
53
|
+
offset += 1;
|
|
54
|
+
}
|
|
55
|
+
out.set(part, offset);
|
|
56
|
+
offset += part.byteLength;
|
|
57
|
+
});
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
function requireSecret(secret) {
|
|
61
|
+
if (!secret || secret.byteLength === 0)
|
|
62
|
+
cacheKeyError('HQ_CACHE_KEY_SECRET_MISSING');
|
|
63
|
+
if (secret.byteLength < PROTOCOL_CACHE_KEY_LIMITS.minSecretBytes) {
|
|
64
|
+
cacheKeyError('HQ_CACHE_KEY_SECRET_TOO_SHORT');
|
|
65
|
+
}
|
|
66
|
+
return secret;
|
|
67
|
+
}
|
|
68
|
+
function requireNamespace(namespace) {
|
|
69
|
+
try {
|
|
70
|
+
const target = validateProtocolDeploymentReleaseTarget(namespace);
|
|
71
|
+
return {
|
|
72
|
+
project: textEncoder.encode(target.project),
|
|
73
|
+
environment: textEncoder.encode(target.environment),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Deliberately does not forward release-target validation details: a
|
|
78
|
+
// single code keeps callers from branching on namespace internals.
|
|
79
|
+
cacheKeyError('HQ_CACHE_KEY_INVALID_NAMESPACE');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function requireKeyVersion(keyVersion) {
|
|
83
|
+
if (typeof keyVersion !== 'number'
|
|
84
|
+
|| !Number.isSafeInteger(keyVersion)
|
|
85
|
+
|| keyVersion < PROTOCOL_CACHE_KEY_LIMITS.minKeyVersion
|
|
86
|
+
|| keyVersion > PROTOCOL_CACHE_KEY_LIMITS.maxKeyVersion) {
|
|
87
|
+
cacheKeyError('HQ_CACHE_KEY_INVALID_VERSION');
|
|
88
|
+
}
|
|
89
|
+
return keyVersion;
|
|
90
|
+
}
|
|
91
|
+
function requirePreimage(preimage) {
|
|
92
|
+
if (typeof preimage === 'string'
|
|
93
|
+
&& preimage.length > PROTOCOL_CACHE_KEY_LIMITS.maxPreimageBytes) {
|
|
94
|
+
cacheKeyError('HQ_CACHE_KEY_PREIMAGE_TOO_LARGE');
|
|
95
|
+
}
|
|
96
|
+
const bytes = typeof preimage === 'string' ? textEncoder.encode(preimage) : preimage;
|
|
97
|
+
if (bytes.byteLength > PROTOCOL_CACHE_KEY_LIMITS.maxPreimageBytes) {
|
|
98
|
+
cacheKeyError('HQ_CACHE_KEY_PREIMAGE_TOO_LARGE');
|
|
99
|
+
}
|
|
100
|
+
return bytes;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Derives the opaque namespace prefix. Truncated to 16 bytes because it is a
|
|
104
|
+
* grouping label for prefix operations, not an authentication tag.
|
|
105
|
+
*/
|
|
106
|
+
export function deriveProtocolCacheNamespaceToken(secret, project, environment) {
|
|
107
|
+
const key = requireSecret(secret);
|
|
108
|
+
const namespace = requireNamespace({ project, environment });
|
|
109
|
+
const input = joinNulSeparated([
|
|
110
|
+
textEncoder.encode(NAMESPACE_DOMAIN),
|
|
111
|
+
namespace.project,
|
|
112
|
+
namespace.environment,
|
|
113
|
+
]);
|
|
114
|
+
const mac = hmac(sha256, key, input);
|
|
115
|
+
return base64url(mac.slice(0, PROTOCOL_CACHE_KEY_LIMITS.namespaceTokenBytes));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Derives the opaque store key for one canonical preimage (RFC 0013).
|
|
119
|
+
*
|
|
120
|
+
* The preimage never appears in the result. An unkeyed digest would be
|
|
121
|
+
* offline-guessable — the schema is public and identifier value spaces are
|
|
122
|
+
* small — so the derivation is an HMAC under a per-namespace secret.
|
|
123
|
+
*/
|
|
124
|
+
export function deriveProtocolCacheKey(options) {
|
|
125
|
+
const secret = requireSecret(options.secret);
|
|
126
|
+
const { project, environment } = requireNamespace(options.namespace);
|
|
127
|
+
const keyVersion = requireKeyVersion(options.keyVersion);
|
|
128
|
+
const preimage = requirePreimage(options.preimage);
|
|
129
|
+
const namespaceToken = base64url(hmac(sha256, secret, joinNulSeparated([textEncoder.encode(NAMESPACE_DOMAIN), project, environment])).slice(0, PROTOCOL_CACHE_KEY_LIMITS.namespaceTokenBytes));
|
|
130
|
+
// The namespace participates in the entry MAC directly, not only through the
|
|
131
|
+
// prefix, so two namespaces cannot collide even in a store that ignores
|
|
132
|
+
// prefixes.
|
|
133
|
+
const entryMac = hmac(sha256, secret, joinNulSeparated([textEncoder.encode(ENTRY_DOMAIN), project, environment, preimage]));
|
|
134
|
+
const key = `${SCHEME}.${keyVersion}.${namespaceToken}.${base64url(entryMac)}`;
|
|
135
|
+
/* c8 ignore next 3 -- unreachable with version-1 limits; a guard against a
|
|
136
|
+
future format change silently exceeding what stores accept. */
|
|
137
|
+
if (textEncoder.encode(key).byteLength > PROTOCOL_CACHE_KEY_LIMITS.maxStoreKeyBytes) {
|
|
138
|
+
cacheKeyError('HQ_CACHE_KEY_INVALID_VERSION');
|
|
139
|
+
}
|
|
140
|
+
return key;
|
|
141
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ProtocolCacheKeyError, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, } from './cache-keys.js';
|
|
2
|
+
export { PROTOCOL_CACHE_KEY_LIMITS } from './types.js';
|
|
3
|
+
export type { DeriveProtocolCacheKeyOptions, ProtocolCacheKeyErrorCode, ProtocolCacheKeyNamespace, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache-keys/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EACV,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Absolute limits for cache key version 1 (RFC 0013). */
|
|
2
|
+
export declare const PROTOCOL_CACHE_KEY_LIMITS: {
|
|
3
|
+
readonly minSecretBytes: 32;
|
|
4
|
+
readonly maxPreimageBytes: 1048576;
|
|
5
|
+
readonly namespaceTokenBytes: 16;
|
|
6
|
+
readonly entryMacBytes: 32;
|
|
7
|
+
readonly maxStoreKeyBytes: 128;
|
|
8
|
+
readonly minKeyVersion: 1;
|
|
9
|
+
readonly maxKeyVersion: 2147483647;
|
|
10
|
+
};
|
|
11
|
+
export type ProtocolCacheKeyErrorCode = 'HQ_CACHE_KEY_SECRET_MISSING' | 'HQ_CACHE_KEY_SECRET_TOO_SHORT' | 'HQ_CACHE_KEY_INVALID_NAMESPACE' | 'HQ_CACHE_KEY_INVALID_VERSION' | 'HQ_CACHE_KEY_PREIMAGE_TOO_LARGE';
|
|
12
|
+
/** The RFC 0008 deployment target a cache entry belongs to. */
|
|
13
|
+
export interface ProtocolCacheKeyNamespace {
|
|
14
|
+
readonly project: string;
|
|
15
|
+
readonly environment: string;
|
|
16
|
+
}
|
|
17
|
+
export interface DeriveProtocolCacheKeyOptions {
|
|
18
|
+
/** At least 32 bytes, distinct per namespace, never derived from a name. */
|
|
19
|
+
readonly secret: Uint8Array;
|
|
20
|
+
readonly namespace: ProtocolCacheKeyNamespace;
|
|
21
|
+
/** Increments whenever the namespace secret is rotated. */
|
|
22
|
+
readonly keyVersion: number;
|
|
23
|
+
/** Canonical bytes identifying the query. Stays in memory. */
|
|
24
|
+
readonly preimage: Uint8Array | string;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cache-keys/types.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB;;;;;;;;CAQ5B,CAAC;AAEX,MAAM,MAAM,yBAAyB,GACjC,6BAA6B,GAC7B,+BAA+B,GAC/B,gCAAgC,GAChC,8BAA8B,GAC9B,iCAAiC,CAAC;AAEtC,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,6BAA6B;IAC5C,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;IAC9C,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAAC;CACxC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Absolute limits for cache key version 1 (RFC 0013). */
|
|
2
|
+
export const PROTOCOL_CACHE_KEY_LIMITS = {
|
|
3
|
+
minSecretBytes: 32,
|
|
4
|
+
maxPreimageBytes: 1_048_576,
|
|
5
|
+
namespaceTokenBytes: 16,
|
|
6
|
+
entryMacBytes: 32,
|
|
7
|
+
maxStoreKeyBytes: 128,
|
|
8
|
+
minKeyVersion: 1,
|
|
9
|
+
maxKeyVersion: 2_147_483_647,
|
|
10
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export { DEFAULT_CANONICAL_VALUE_LIMITS, ProtocolValueError, decodeCanonicalValue, encodeCanonicalValue, encodeCanonicalValueToString, hashCanonicalValue, validateCanonicalValue, } from './values/index.js';
|
|
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
|
+
export { PROTOCOL_CACHE_KEY_LIMITS, ProtocolCacheKeyError, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, } from './cache-keys/index.js';
|
|
4
5
|
export { DEFAULT_PROTOCOL_EXPRESSION_LIMITS, ProtocolExpressionError, validateProtocolExpression, validateProtocolSemanticQuery, } from './expressions/index.js';
|
|
5
6
|
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, ProtocolSchemaError, ProtocolSchemaValueError, applyProtocolSchemaValue, createProtocolSchemaValueParser, resolveProtocolSchemaValueLimits, validateProtocolSchema, } from './schemas/index.js';
|
|
6
7
|
export type { ProtocolSchema, ProtocolSchemaErrorCode, ProtocolSchemaLimits, ProtocolSchemaOptions, ProtocolSchemaValueLimits, ProtocolSchemaValueOptions, ProtocolSchemaValueParser, } from './schemas/index.js';
|
|
7
8
|
export type { ProtocolAggregation, ProtocolBinaryOperator, ProtocolComparisonOperator, ProtocolDatasetQuery, ProtocolExpression, ProtocolExpressionErrorCode, ProtocolExpressionLimits, ProtocolExpressionOptions, ProtocolFunctionName, ProtocolMetricQuery, ProtocolOrderBy, ProtocolSemanticQuery, ProtocolTimeGrain, } from './expressions/index.js';
|
|
9
|
+
export type { DeriveProtocolCacheKeyOptions, ProtocolCacheKeyErrorCode, ProtocolCacheKeyNamespace, } from './cache-keys/index.js';
|
|
8
10
|
export type { ProtocolIdentifier, ProtocolIdentifierErrorCode, ProtocolQualifiedIdentifier, } from './identifiers/index.js';
|
|
9
11
|
export { DEFAULT_PROTOCOL_QUERY_IMPLEMENTATION_LIMITS, ProtocolQueryImplementationError, validateProtocolQueryImplementation, validateProtocolSqlExpression, } from './query-implementations/index.js';
|
|
10
12
|
export { DEFAULT_PROTOCOL_QUERY_EVENT_LIMITS, ProtocolQueryDiagnosticsError, ProtocolQueryEventError, validateProtocolQueryDiagnostics, validateProtocolQueryEvent, } from './events/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":"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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,5 +1,6 @@
|
|
|
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
|
+
export { PROTOCOL_CACHE_KEY_LIMITS, ProtocolCacheKeyError, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, } from './cache-keys/index.js';
|
|
3
4
|
export { DEFAULT_PROTOCOL_EXPRESSION_LIMITS, ProtocolExpressionError, validateProtocolExpression, validateProtocolSemanticQuery, } from './expressions/index.js';
|
|
4
5
|
export { DEFAULT_PROTOCOL_SCHEMA_LIMITS, DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, ProtocolSchemaError, ProtocolSchemaValueError, applyProtocolSchemaValue, createProtocolSchemaValueParser, resolveProtocolSchemaValueLimits, validateProtocolSchema, } from './schemas/index.js';
|
|
5
6
|
export { DEFAULT_PROTOCOL_QUERY_IMPLEMENTATION_LIMITS, ProtocolQueryImplementationError, validateProtocolQueryImplementation, validateProtocolSqlExpression, } from './query-implementations/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/values/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/values/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAqWpB,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAOhB;AAYD,kFAAkF;AAClF,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACtC,sBAAsB,CAAC,EAAE,MAAM,GAC9B,cAAc,CAGhB;AAED,6EAA6E;AAC7E,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACtC,sBAAsB,CAAC,EAAE,MAAM,GAC9B,cAAc,CAEhB"}
|
package/dist/values/validate.js
CHANGED
|
@@ -40,10 +40,15 @@ function requireMetadataInteger(value, path) {
|
|
|
40
40
|
}
|
|
41
41
|
return value;
|
|
42
42
|
}
|
|
43
|
+
// Tab, line feed, and carriage return are permitted so authored prose can
|
|
44
|
+
// span lines; JCS escapes them deterministically. Every other C0 control, DEL,
|
|
45
|
+
// and the C1 range stay forbidden.
|
|
46
|
+
const ALLOWED_CONTROL_CHARACTERS = new Set([0x09, 0x0a, 0x0d]);
|
|
43
47
|
function validateUnicode(value, path, maxBytes) {
|
|
44
48
|
for (let index = 0; index < value.length; index += 1) {
|
|
45
49
|
const code = value.charCodeAt(index);
|
|
46
|
-
if (code <= 0x1f
|
|
50
|
+
if ((code <= 0x1f && !ALLOWED_CONTROL_CHARACTERS.has(code))
|
|
51
|
+
|| (code >= 0x7f && code <= 0x9f)) {
|
|
47
52
|
valueError('HQ_VALUE_CONTROL_CHARACTER', path);
|
|
48
53
|
}
|
|
49
54
|
if (code >= 0xd800 && code <= 0xdbff) {
|
|
@@ -139,7 +144,10 @@ function validateDatetimeTag(tag, path) {
|
|
|
139
144
|
}
|
|
140
145
|
const timezone = requireString(tag.timezone, `${path}.timezone`);
|
|
141
146
|
validateUnicode(timezone, `${path}.timezone`, 64);
|
|
142
|
-
|
|
147
|
+
// Single-component identifiers are valid: UTC, EST, GMT, CET, and MST7MDT
|
|
148
|
+
// are all real tzdb entries. Existence is checked at deployment time
|
|
149
|
+
// against the server's system.time_zones, not here.
|
|
150
|
+
if (!/^[A-Za-z][A-Za-z0-9_+-]*(?:\/[A-Za-z0-9_+-]+)*$/.test(timezone)) {
|
|
143
151
|
valueError('HQ_VALUE_INVALID_FORMAT', `${path}.timezone`);
|
|
144
152
|
}
|
|
145
153
|
const value = requireString(tag.value, `${path}.value`);
|