@hypequery/protocol-conformance 0.11.1 → 0.12.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/adapters/generators.d.ts +0 -1
- package/dist/adapters/generators.d.ts.map +1 -1
- package/dist/adapters/generators.js +0 -112
- package/dist/adapters/reference.d.ts +1 -1
- package/dist/adapters/reference.d.ts.map +1 -1
- package/dist/adapters/reference.js +6 -6
- package/fixtures/deployments-v2/README.md +15 -0
- package/fixtures/deployments-v2/identity.json +7 -0
- package/fixtures/deployments-v2/rejections.json +874 -0
- package/fixtures/deployments-v2/success.json +67 -0
- package/fixtures/fuzz-seeds-v1/structured-values.json +3 -3
- package/fixtures/manifest.json +4 -4
- package/fixtures/query-implementations-v1/rejections.json +445 -6
- package/fixtures/query-implementations-v1/success.json +88 -12
- package/fixtures/query-schemas-v1/README.md +2 -0
- package/fixtures/query-schemas-v1/rejections.json +224 -13
- package/fixtures/sql-portability-v1/README.md +2 -0
- package/fixtures/sql-portability-v1/non-portable.json +121 -0
- package/fixtures/tagged-values-v1/rejections.json +18 -0
- package/package.json +2 -2
- package/fixtures/deployments-v1/README.md +0 -11
- package/fixtures/deployments-v1/identity.json +0 -12
- package/fixtures/deployments-v1/rejections.json +0 -18
- package/fixtures/deployments-v1/success.json +0 -139
|
@@ -7,7 +7,6 @@ export declare function materializeImplementation(spec: Spec): unknown;
|
|
|
7
7
|
export declare function materializeSemanticInvocation(spec: Spec): unknown;
|
|
8
8
|
export declare function materializeEvent(spec: Spec): unknown;
|
|
9
9
|
export declare function materializeDiagnostics(spec: Spec): unknown;
|
|
10
|
-
export declare function materializeDeployment(spec: Spec): unknown;
|
|
11
10
|
export declare function materializeBundle(spec: Spec): unknown;
|
|
12
11
|
export declare function materializeRelease(spec: Spec): unknown;
|
|
13
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/adapters/generators.ts"],"names":[],"mappings":"AAIA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAkBpC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuC1D;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAMxD;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoCzD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CA2BrD;AAgBD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuB7D;AA4CD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAsFjE;AAkBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAyBpD;AAeD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoB1D;
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/adapters/generators.ts"],"names":[],"mappings":"AAIA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAkBpC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuC1D;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAMxD;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoCzD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CA2BrD;AAgBD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuB7D;AA4CD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAsFjE;AAkBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAyBpD;AAeD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoB1D;AAmBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAmBrD;AAaD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAgBtD"}
|
|
@@ -368,118 +368,6 @@ export function materializeDiagnostics(spec) {
|
|
|
368
368
|
default: throw new Error(`Unknown diagnostics generator: ${String(spec.type)}`);
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
|
-
// --- deployments-v1 ---
|
|
372
|
-
function minimalDataset(name = 'orders') {
|
|
373
|
-
return {
|
|
374
|
-
name,
|
|
375
|
-
source: 'orders',
|
|
376
|
-
tenant: { kind: 'not-required' },
|
|
377
|
-
dimensions: [],
|
|
378
|
-
measures: [],
|
|
379
|
-
filters: [],
|
|
380
|
-
metrics: [],
|
|
381
|
-
relationships: [],
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
function baseDeployment() {
|
|
385
|
-
return {
|
|
386
|
-
kind: 'hypequery-deployment',
|
|
387
|
-
version: 1,
|
|
388
|
-
datasets: [minimalDataset()],
|
|
389
|
-
queries: [],
|
|
390
|
-
artifacts: [],
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
export function materializeDeployment(spec) {
|
|
394
|
-
const value = baseDeployment();
|
|
395
|
-
switch (spec.type) {
|
|
396
|
-
case 'wrong-root-type': return [];
|
|
397
|
-
case 'unknown-root-field': return { ...value, extra: true };
|
|
398
|
-
case 'unsupported-version': return { ...value, version: 2 };
|
|
399
|
-
case 'invalid-dataset-identifier': return { ...value, datasets: [minimalDataset('bad-name')] };
|
|
400
|
-
case 'invalid-relationship-queryability':
|
|
401
|
-
return {
|
|
402
|
-
...value,
|
|
403
|
-
datasets: [{
|
|
404
|
-
...minimalDataset(),
|
|
405
|
-
relationships: [{
|
|
406
|
-
name: 'items', kind: 'hasMany', target: 'orders', from: 'id', to: 'order_id', queryable: true,
|
|
407
|
-
}],
|
|
408
|
-
}],
|
|
409
|
-
};
|
|
410
|
-
case 'missing-runtime-artifact':
|
|
411
|
-
return {
|
|
412
|
-
...value,
|
|
413
|
-
queries: [{
|
|
414
|
-
name: 'health',
|
|
415
|
-
input: { kind: 'any' },
|
|
416
|
-
output: { kind: 'any' },
|
|
417
|
-
implementation: {
|
|
418
|
-
kind: 'runtime-reference', runtime: 'node', artifactSha256: '0'.repeat(64), entrypoint: 'queries.health',
|
|
419
|
-
},
|
|
420
|
-
endpoint: { access: { kind: 'public' }, tenant: { kind: 'not-required' }, method: 'GET', path: '/health' },
|
|
421
|
-
tags: [],
|
|
422
|
-
}],
|
|
423
|
-
};
|
|
424
|
-
case 'ambiguous-query-route': {
|
|
425
|
-
const namedQuery = (name) => ({
|
|
426
|
-
name,
|
|
427
|
-
input: { kind: 'void' },
|
|
428
|
-
output: { kind: 'void' },
|
|
429
|
-
implementation: {
|
|
430
|
-
kind: 'semantic-plan',
|
|
431
|
-
query: { kind: 'dataset', dataset: 'orders', dimensions: [], measures: [], filters: [], orderBy: [] },
|
|
432
|
-
},
|
|
433
|
-
endpoint: { access: { kind: 'public' }, tenant: { kind: 'not-required' }, method: 'GET', path: '/same' },
|
|
434
|
-
tags: [],
|
|
435
|
-
});
|
|
436
|
-
return { ...value, queries: [namedQuery('first'), namedQuery('second')] };
|
|
437
|
-
}
|
|
438
|
-
case 'invalid-sensitivity':
|
|
439
|
-
return { ...value, datasets: [{ ...minimalDataset(), sensitivity: 'secret' }] };
|
|
440
|
-
case 'invalid-currency':
|
|
441
|
-
return { ...value, datasets: [{ ...minimalDataset(), currency: 'usd' }] };
|
|
442
|
-
case 'empty-defaults':
|
|
443
|
-
return { ...value, datasets: [{ ...minimalDataset(), defaults: {} }] };
|
|
444
|
-
case 'default-dimension-not-groupable':
|
|
445
|
-
return {
|
|
446
|
-
...value,
|
|
447
|
-
datasets: [{
|
|
448
|
-
...minimalDataset(),
|
|
449
|
-
dimensions: [{
|
|
450
|
-
name: 'status',
|
|
451
|
-
type: 'string',
|
|
452
|
-
source: { kind: 'column', column: 'status' },
|
|
453
|
-
filterable: true,
|
|
454
|
-
groupable: false,
|
|
455
|
-
}],
|
|
456
|
-
defaults: { dimensions: ['status'] },
|
|
457
|
-
}],
|
|
458
|
-
};
|
|
459
|
-
case 'default-grain-without-time-field':
|
|
460
|
-
// `timeGrain` has nothing to apply to unless the dataset declares
|
|
461
|
-
// `timeField`, so the reference reports it as a broken reference.
|
|
462
|
-
return { ...value, datasets: [{ ...minimalDataset(), defaults: { timeGrain: 'day' } }] };
|
|
463
|
-
case 'too-many-datasets':
|
|
464
|
-
return { ...value, datasets: Array.from({ length: 101 }, (_, i) => minimalDataset(`dataset_${i}`)) };
|
|
465
|
-
case 'too-many-synonyms':
|
|
466
|
-
return {
|
|
467
|
-
...value,
|
|
468
|
-
datasets: [{
|
|
469
|
-
...minimalDataset(),
|
|
470
|
-
synonyms: Array.from({ length: 101 }, (_, i) => `synonym_${i}`),
|
|
471
|
-
}],
|
|
472
|
-
};
|
|
473
|
-
case 'source-too-large':
|
|
474
|
-
return { ...value, datasets: [{ ...minimalDataset(), source: repeat('a', 1_025) }] };
|
|
475
|
-
case 'unsafe-accessor': {
|
|
476
|
-
const unsafe = baseDeployment();
|
|
477
|
-
Object.defineProperty(unsafe, 'kind', { enumerable: true, get: () => 'hypequery-deployment' });
|
|
478
|
-
return unsafe;
|
|
479
|
-
}
|
|
480
|
-
default: throw new Error(`Unknown deployment generator: ${String(spec.type)}`);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
371
|
// --- deployment-bundles-v1 ---
|
|
484
372
|
function bundleArtifact(index = 0) {
|
|
485
373
|
const sha256 = index.toString(16).padStart(64, '0');
|
|
@@ -9,7 +9,7 @@ export declare const REFERENCE_HOSTILE_OBJECT_SUITE: {
|
|
|
9
9
|
readonly count: 7;
|
|
10
10
|
readonly mechanisms: readonly ["getter", "toJSON", "proxy", "custom-prototype", "symbol-key", "sparse-array", "cycle"];
|
|
11
11
|
};
|
|
12
|
-
export declare const REFERENCE_FAMILIES: readonly ["cache-keys-v1", "tagged-values-v1", "identifiers-v1", "expressions-v1", "query-schemas-v1", "query-implementations-v1", "query-events-v1", "query-diagnostics-v1", "deployments-
|
|
12
|
+
export declare const REFERENCE_FAMILIES: readonly ["cache-keys-v1", "tagged-values-v1", "identifiers-v1", "expressions-v1", "query-schemas-v1", "query-implementations-v1", "query-events-v1", "query-diagnostics-v1", "deployments-v2", "deployment-bundles-v1", "deployment-releases-v1", "semantic-invocations-v1"];
|
|
13
13
|
export declare function referenceHandle(family: string, role: FixtureRole, c: Case, section?: string): HandlerResult;
|
|
14
14
|
export {};
|
|
15
15
|
//# sourceMappingURL=reference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/adapters/reference.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/adapters/reference.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAc9D,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA0BpC;;;;GAIG;AACH,eAAO,MAAM,8BAA8B;;;CAWjC,CAAC;AAEX,eAAO,MAAM,kBAAkB,+QAarB,CAAC;AAEX,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,EACjB,CAAC,EAAE,IAAI,EACP,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,CAsCf"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// goes through the package's supported surface — this is exactly what a second
|
|
4
4
|
// implementation must reproduce.
|
|
5
5
|
import { decodeCanonicalValue, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, encodeCanonicalValue, hashCanonicalValue, parseProtocolIdentifier, parseProtocolQualifiedIdentifier, prepareProtocolDeploymentBundleManifest, prepareProtocolDeploymentContract, prepareProtocolDeploymentReleaseEnvelope, splitProtocolQualifiedIdentifier, validateCanonicalValue, validateProtocolDeploymentBundleManifest, validateProtocolDeploymentContract, validateProtocolDeploymentReleaseEnvelope, validateProtocolExpression, validateProtocolQueryDiagnostics, validateProtocolQueryEvent, validateProtocolQueryImplementation, validateProtocolSchema, validateProtocolSemanticInvocation, validateProtocolSemanticInvocationFailure, validateProtocolSemanticInvocationResult, validateProtocolSemanticQuery, validateProtocolSqlExpression, } from '@hypequery/protocol';
|
|
6
|
-
import { materializeBundle,
|
|
6
|
+
import { materializeBundle, materializeDiagnostics, materializeEvent, materializeSemanticInvocation, materializeExpression, materializeIdentifier, materializeImplementation, materializeRelease, materializeSchema, materializeTaggedValue, } from './generators.js';
|
|
7
7
|
const STABLE_CODE = /^HQ_[A-Z0-9_]+$/;
|
|
8
8
|
/** Turns a thrown protocol error into a wire rejection; rethrows anything else. */
|
|
9
9
|
function mapError(error) {
|
|
@@ -51,7 +51,7 @@ export const REFERENCE_FAMILIES = [
|
|
|
51
51
|
'query-implementations-v1',
|
|
52
52
|
'query-events-v1',
|
|
53
53
|
'query-diagnostics-v1',
|
|
54
|
-
'deployments-
|
|
54
|
+
'deployments-v2',
|
|
55
55
|
'deployment-bundles-v1',
|
|
56
56
|
'deployment-releases-v1',
|
|
57
57
|
'semantic-invocations-v1',
|
|
@@ -81,8 +81,8 @@ export function referenceHandle(family, role, c, section) {
|
|
|
81
81
|
validateProtocolQueryDiagnostics(validationInput(c, materializeDiagnostics));
|
|
82
82
|
return ACCEPT;
|
|
83
83
|
});
|
|
84
|
-
case 'deployments-
|
|
85
|
-
return
|
|
84
|
+
case 'deployments-v2':
|
|
85
|
+
return handleDeploymentV2(role, c);
|
|
86
86
|
case 'deployment-bundles-v1':
|
|
87
87
|
return handleBundle(role, c);
|
|
88
88
|
case 'deployment-releases-v1':
|
|
@@ -208,7 +208,7 @@ function handleImplementation(c) {
|
|
|
208
208
|
return ACCEPT;
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
-
function
|
|
211
|
+
function handleDeploymentV2(role, c) {
|
|
212
212
|
if (role === 'identity') {
|
|
213
213
|
return attempt(() => {
|
|
214
214
|
const prepared = prepareProtocolDeploymentContract(c.value);
|
|
@@ -216,7 +216,7 @@ function handleDeployment(role, c) {
|
|
|
216
216
|
});
|
|
217
217
|
}
|
|
218
218
|
return attempt(() => {
|
|
219
|
-
validateProtocolDeploymentContract(
|
|
219
|
+
validateProtocolDeploymentContract(c.value);
|
|
220
220
|
return ACCEPT;
|
|
221
221
|
});
|
|
222
222
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Deployment contract v2 fixtures
|
|
2
|
+
|
|
3
|
+
`success.json` holds contracts every implementation must accept, `identity.json`
|
|
4
|
+
pins the canonical bytes and SHA-256 of the success case sharing its id, and
|
|
5
|
+
`rejections.json` pins a stable failure code for each rule the contract states.
|
|
6
|
+
|
|
7
|
+
Acceptance of RFC 0006 added the rejection corpus. Before it, the family had one
|
|
8
|
+
success and one identity case, which cannot tell a faithful validator from one
|
|
9
|
+
that accepts contracts another implementation rejects — the corpus now covers
|
|
10
|
+
the envelope's forbidden fields, the null-versus-absent distinction, relationship
|
|
11
|
+
and tenant agreement, measure shape, semantic metadata, defaults, endpoint
|
|
12
|
+
policy, and derived-measure rules.
|
|
13
|
+
|
|
14
|
+
Every case was checked against both the TypeScript and Python implementations
|
|
15
|
+
before being recorded; none of them changed either implementation's behaviour.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "derived-measures",
|
|
4
|
+
"canonical": "{\"datasets\":[{\"dimensions\":[],\"filters\":[],\"measures\":[{\"aggregation\":\"sum\",\"field\":\"amount\",\"filters\":[],\"name\":\"revenue\"},{\"aggregation\":\"count\",\"field\":\"id\",\"filters\":[],\"name\":\"orders\"},{\"expression\":{\"kind\":\"binary\",\"left\":{\"kind\":\"reference\",\"name\":\"revenue\"},\"operator\":\"divide\",\"right\":{\"args\":[{\"kind\":\"reference\",\"name\":\"orders\"}],\"function\":\"nullIfZero\",\"kind\":\"call\"}},\"kind\":\"derived\",\"name\":\"averageOrderValue\",\"uses\":[{\"alias\":\"revenue\",\"measure\":\"revenue\"},{\"alias\":\"orders\",\"measure\":\"orders\"}]}],\"name\":\"orders\",\"relationships\":[],\"source\":\"orders\",\"tenant\":{\"kind\":\"not-required\"}}],\"kind\":\"hypequery-deployment\",\"version\":2}",
|
|
5
|
+
"sha256": "bd7b6818e8028e609923324455c3842425dcaa447dfd7d792b50de288769f379"
|
|
6
|
+
}
|
|
7
|
+
]
|