@hypequery/datasets 0.14.0 → 0.16.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/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/portable-execution-errors.d.ts +49 -0
- package/dist/portable-execution-errors.d.ts.map +1 -0
- package/dist/portable-execution-errors.js +52 -0
- package/dist/portable-executor.d.ts +61 -0
- package/dist/portable-executor.d.ts.map +1 -0
- package/dist/portable-executor.js +90 -0
- package/dist/protocol-adapter.d.ts.map +1 -1
- package/dist/protocol-adapter.js +5 -97
- package/dist/protocol-rehydrate.d.ts +10 -0
- package/dist/protocol-rehydrate.d.ts.map +1 -1
- package/dist/protocol-rehydrate.js +62 -16
- package/dist/protocol-schema-adapter.d.ts +9 -0
- package/dist/protocol-schema-adapter.d.ts.map +1 -0
- package/dist/protocol-schema-adapter.js +249 -0
- package/dist/relationships.d.ts +25 -4
- package/dist/relationships.d.ts.map +1 -1
- package/dist/relationships.js +25 -4
- package/dist/semantic-query-schema.d.ts +31 -0
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +29 -1
- package/dist/utils/portable-execution-deadline.d.ts +4 -0
- package/dist/utils/portable-execution-deadline.d.ts.map +1 -0
- package/dist/utils/portable-execution-deadline.js +27 -0
- package/dist/utils/portable-result-budget.d.ts +12 -0
- package/dist/utils/portable-result-budget.d.ts.map +1 -0
- package/dist/utils/portable-result-budget.js +21 -0
- package/dist/utils/portable-semantic-query.d.ts +5 -0
- package/dist/utils/portable-semantic-query.d.ts.map +1 -0
- package/dist/utils/portable-semantic-query.js +36 -0
- package/dist/utils/protocol-metric-expressions.d.ts +17 -0
- package/dist/utils/protocol-metric-expressions.d.ts.map +1 -0
- package/dist/utils/protocol-metric-expressions.js +118 -0
- package/dist/utils/protocol-rehydrate-derivation.d.ts +27 -0
- package/dist/utils/protocol-rehydrate-derivation.d.ts.map +1 -0
- package/dist/utils/protocol-rehydrate-derivation.js +104 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -19,11 +19,13 @@ export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './p
|
|
|
19
19
|
export type { RehydratedDataset, RehydrateProtocolDatasetsOptions, } from './protocol-rehydrate.js';
|
|
20
20
|
export { buildProtocolDatasetContract } from './protocol-adapter.js';
|
|
21
21
|
export type { BuildProtocolDatasetContractOptions } from './protocol-adapter.js';
|
|
22
|
+
export { createPortableSemanticExecutor, PortableExecutionBudgetError, PortableExecutionTenantError, PortableExecutionUnsupportedError, } from './portable-executor.js';
|
|
23
|
+
export type { PortableSemanticBudget, PortableSemanticExecutionInput, PortableSemanticExecutorOptions, } from './portable-executor.js';
|
|
22
24
|
export { compilePortableSqlExpression, DEFAULT_SQL_PORTABILITY_LIMITS, } from './sql-portability.js';
|
|
23
25
|
export type { SqlPortabilityIssue, SqlPortabilityIssueCode, SqlPortabilityLimits, SqlPortabilityOptions, SqlPortabilityResult, } from './sql-portability.js';
|
|
24
26
|
export type { SemanticContract, SerializeSemanticContractOptions, ContractDataset, ContractDimension, ContractMeasure, ContractMetric, ContractFilter, ContractRelationship, } from './contract.js';
|
|
25
27
|
export { generateDatasetTools, toOpenAITools, toAISDKTools, toMcpTools, } from './tools.js';
|
|
26
|
-
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, } from './semantic-query-schema.js';
|
|
28
|
+
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, buildDatasetInputProtocolSchema, buildMetricInputProtocolSchema, } from './semantic-query-schema.js';
|
|
27
29
|
export type { CanonicalSemanticQuerySchemas, SemanticMetricQueryContract, SemanticQuerySchemaLimits, SemanticQuerySchemaOptions, SemanticQuerySchemaSource, } from './semantic-query-schema.js';
|
|
28
30
|
export type { AISDKToolDefinition, DatasetToolAnalytics, DatasetToolMode, GenerateDatasetToolsOptions, JsonSchema, McpToolDefinition, OpenAIToolDefinition, SemanticToolDefinition, } from './tools.js';
|
|
29
31
|
export { createDatasetClient } from './executor.js';
|
|
@@ -41,4 +43,5 @@ export { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
|
41
43
|
export { validateSQLIdentifier, isSafeSQLIdentifier, quoteSQLIdentifier } from './sql-utils.js';
|
|
42
44
|
export { GRAIN_FUNCTIONS, SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
|
|
43
45
|
export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, InferDimensionType, RelationshipKind, RelationshipDefinition, AggregationType, MeasureAggregation, AggregationSpec, FormulaExpr, DerivedMetricSpec, TimeGrain, MetricRef, BaseMetricRef, DerivedMetricRef, GrainedMetricRef, MetricContract, MetricFilter, MetricOrderBy, MetricQuery, DatasetQuery, MetricResultMeta, MetricResult, DatasetQueryResult, MetricHandle, ExecutionContext, SemanticExecutionRuntime, SemanticTenantRuntime, SemanticFilterDefinition, SemanticFiltersDefinition, DatasetConfig, DatasetDefaults, DatasetFreshness, DatasetLimits, DatasetCachePolicy, SemanticMetadata, SemanticSensitivity, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetQueryableDimensions, DatasetMeasureNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
|
|
46
|
+
export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
|
|
44
47
|
//# sourceMappingURL=index.d.ts.map
|
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
|
@@ -26,12 +26,14 @@ export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC
|
|
|
26
26
|
// Portable deployment contract adapter
|
|
27
27
|
export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
28
28
|
export { buildProtocolDatasetContract } from './protocol-adapter.js';
|
|
29
|
+
// Portable native execution of a semantic invocation (decision 0005).
|
|
30
|
+
export { createPortableSemanticExecutor, PortableExecutionBudgetError, PortableExecutionTenantError, PortableExecutionUnsupportedError, } from './portable-executor.js';
|
|
29
31
|
// SQL portability compiler (R1A-07)
|
|
30
32
|
export { compilePortableSqlExpression, DEFAULT_SQL_PORTABILITY_LIMITS, } from './sql-portability.js';
|
|
31
33
|
// Agent/tool metadata
|
|
32
34
|
export { generateDatasetTools, toOpenAITools, toAISDKTools, toMcpTools, } from './tools.js';
|
|
33
35
|
// Canonical semantic query schemas shared by Serve, MCP, and agent adapters.
|
|
34
|
-
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, } from './semantic-query-schema.js';
|
|
36
|
+
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, buildDatasetInputProtocolSchema, buildMetricInputProtocolSchema, } from './semantic-query-schema.js';
|
|
35
37
|
// Dataset client
|
|
36
38
|
export { createDatasetClient } from './executor.js';
|
|
37
39
|
// Semantic query result cache
|
|
@@ -47,3 +49,4 @@ export { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
|
47
49
|
export { validateSQLIdentifier, isSafeSQLIdentifier, quoteSQLIdentifier } from './sql-utils.js';
|
|
48
50
|
// Constants
|
|
49
51
|
export { GRAIN_FUNCTIONS, SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
|
|
52
|
+
export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error that deliberately claims a portable failure category.
|
|
3
|
+
*
|
|
4
|
+
* A data plane forwards the category and message of an error carrying this
|
|
5
|
+
* marker instead of reporting a generic executor failure, so the marker — not
|
|
6
|
+
* the shape of the error — is what grants that. A provider exception cannot
|
|
7
|
+
* acquire one by accident, which is the point: the two packages are siblings
|
|
8
|
+
* and cannot share a class, but a raw driver error must never be able to pass
|
|
9
|
+
* itself off as a deliberate claim and put its own message in front of a
|
|
10
|
+
* caller.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately not exported. The three errors below are, because this package's
|
|
13
|
+
* own executor throws them; this base is only how they share the marker. A
|
|
14
|
+
* supported way for someone else's executor to claim a category belongs beside
|
|
15
|
+
* the data plane that honours it, not beside one implementation of the slot it
|
|
16
|
+
* fills.
|
|
17
|
+
*/
|
|
18
|
+
declare abstract class PortableExecutionError extends Error {
|
|
19
|
+
/** The opt-in a data plane checks before trusting anything below it. */
|
|
20
|
+
readonly hypequerySemanticFailure: true;
|
|
21
|
+
abstract readonly code: string;
|
|
22
|
+
abstract readonly category: string;
|
|
23
|
+
}
|
|
24
|
+
/** Signalled when portable execution cannot faithfully serve a target. */
|
|
25
|
+
export declare class PortableExecutionUnsupportedError extends PortableExecutionError {
|
|
26
|
+
readonly code = "HQ_SEMANTIC_UNSUPPORTED_CAPABILITY";
|
|
27
|
+
readonly category = "unsupported-capability";
|
|
28
|
+
constructor(message: string, options?: {
|
|
29
|
+
cause?: unknown;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export declare class PortableExecutionBudgetError extends PortableExecutionError {
|
|
33
|
+
readonly code = "HQ_SEMANTIC_BUDGET_EXCEEDED";
|
|
34
|
+
readonly category = "budget-exceeded";
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Signalled when tenancy cannot be enforced for a call that resolved a tenant.
|
|
39
|
+
*
|
|
40
|
+
* `configuration-invalid` rather than a caller-facing category: nothing the
|
|
41
|
+
* caller sent is wrong, and nothing it can send would make the call succeed.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PortableExecutionTenantError extends PortableExecutionError {
|
|
44
|
+
readonly code = "HQ_SEMANTIC_TENANT_UNENFORCEABLE";
|
|
45
|
+
readonly category = "configuration-invalid";
|
|
46
|
+
constructor(message: string);
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=portable-execution-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-execution-errors.d.ts","sourceRoot":"","sources":["../src/portable-execution-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,uBAAe,sBAAuB,SAAQ,KAAK;IACjD,wEAAwE;IACxE,QAAQ,CAAC,wBAAwB,EAAG,IAAI,CAAU;IAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CACpC;AAED,0EAA0E;AAC1E,qBAAa,iCAAkC,SAAQ,sBAAsB;IAC3E,QAAQ,CAAC,IAAI,wCAAwC;IACrD,QAAQ,CAAC,QAAQ,4BAA4B;gBAEjC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAI/D;AAED,qBAAa,4BAA6B,SAAQ,sBAAsB;IACtE,QAAQ,CAAC,IAAI,iCAAiC;IAC9C,QAAQ,CAAC,QAAQ,qBAAqB;gBAE1B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,sBAAsB;IACtE,QAAQ,CAAC,IAAI,sCAAsC;IACnD,QAAQ,CAAC,QAAQ,2BAA2B;gBAEhC,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error that deliberately claims a portable failure category.
|
|
3
|
+
*
|
|
4
|
+
* A data plane forwards the category and message of an error carrying this
|
|
5
|
+
* marker instead of reporting a generic executor failure, so the marker — not
|
|
6
|
+
* the shape of the error — is what grants that. A provider exception cannot
|
|
7
|
+
* acquire one by accident, which is the point: the two packages are siblings
|
|
8
|
+
* and cannot share a class, but a raw driver error must never be able to pass
|
|
9
|
+
* itself off as a deliberate claim and put its own message in front of a
|
|
10
|
+
* caller.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately not exported. The three errors below are, because this package's
|
|
13
|
+
* own executor throws them; this base is only how they share the marker. A
|
|
14
|
+
* supported way for someone else's executor to claim a category belongs beside
|
|
15
|
+
* the data plane that honours it, not beside one implementation of the slot it
|
|
16
|
+
* fills.
|
|
17
|
+
*/
|
|
18
|
+
class PortableExecutionError extends Error {
|
|
19
|
+
/** The opt-in a data plane checks before trusting anything below it. */
|
|
20
|
+
hypequerySemanticFailure = true;
|
|
21
|
+
}
|
|
22
|
+
/** Signalled when portable execution cannot faithfully serve a target. */
|
|
23
|
+
export class PortableExecutionUnsupportedError extends PortableExecutionError {
|
|
24
|
+
code = 'HQ_SEMANTIC_UNSUPPORTED_CAPABILITY';
|
|
25
|
+
category = 'unsupported-capability';
|
|
26
|
+
constructor(message, options = {}) {
|
|
27
|
+
super(message, options);
|
|
28
|
+
this.name = 'PortableExecutionUnsupportedError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class PortableExecutionBudgetError extends PortableExecutionError {
|
|
32
|
+
code = 'HQ_SEMANTIC_BUDGET_EXCEEDED';
|
|
33
|
+
category = 'budget-exceeded';
|
|
34
|
+
constructor(message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'PortableExecutionBudgetError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Signalled when tenancy cannot be enforced for a call that resolved a tenant.
|
|
41
|
+
*
|
|
42
|
+
* `configuration-invalid` rather than a caller-facing category: nothing the
|
|
43
|
+
* caller sent is wrong, and nothing it can send would make the call succeed.
|
|
44
|
+
*/
|
|
45
|
+
export class PortableExecutionTenantError extends PortableExecutionError {
|
|
46
|
+
code = 'HQ_SEMANTIC_TENANT_UNENFORCEABLE';
|
|
47
|
+
category = 'configuration-invalid';
|
|
48
|
+
constructor(message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = 'PortableExecutionTenantError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export { PortableExecutionUnsupportedError, PortableExecutionBudgetError, PortableExecutionTenantError } from './portable-execution-errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Portable native execution of a semantic invocation.
|
|
4
|
+
*
|
|
5
|
+
* Decision 0005 chose this over a supervised runtime binding: resolve the
|
|
6
|
+
* dataset or metric from the validated active contract, rebuild its catalog
|
|
7
|
+
* with `rehydrateProtocolDatasets`, and plan the query with the existing
|
|
8
|
+
* semantic planner. No customer module is loaded and no isolated runtime is
|
|
9
|
+
* required, so customer code only ever runs on the author's machine at deploy
|
|
10
|
+
* time.
|
|
11
|
+
*
|
|
12
|
+
* The input is typed structurally rather than against
|
|
13
|
+
* `@hypequery/deployment`'s execution input, so this package stays a sibling of
|
|
14
|
+
* that one. A caller wires the returned function into the data plane's injected
|
|
15
|
+
* `execute` slot.
|
|
16
|
+
*/
|
|
17
|
+
import type { ProtocolDatasetContract, ProtocolDatasetMetric, ProtocolSemanticInvocationResult, ProtocolSemanticQuery } from '@hypequery/protocol';
|
|
18
|
+
import type { QueryBuilderFactoryInput } from './query-builder-protocol.js';
|
|
19
|
+
/** Ceilings the data plane already reduced to the most restrictive value. */
|
|
20
|
+
export interface PortableSemanticBudget {
|
|
21
|
+
readonly maxRows: number;
|
|
22
|
+
readonly deadlineMs?: number;
|
|
23
|
+
readonly maxResponseBytes?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Structurally compatible with the deployment data plane's execution input.
|
|
27
|
+
* Only the fields portable execution reads are declared, so the two packages
|
|
28
|
+
* stay independent.
|
|
29
|
+
*/
|
|
30
|
+
export interface PortableSemanticExecutionInput {
|
|
31
|
+
readonly deployment: {
|
|
32
|
+
readonly datasets: readonly ProtocolDatasetContract[];
|
|
33
|
+
};
|
|
34
|
+
readonly dataset: ProtocolDatasetContract;
|
|
35
|
+
readonly metric?: ProtocolDatasetMetric;
|
|
36
|
+
readonly operation: ProtocolSemanticQuery;
|
|
37
|
+
/** Resolved by the provider callback; never caller-supplied. */
|
|
38
|
+
readonly tenant: unknown;
|
|
39
|
+
readonly budget: PortableSemanticBudget;
|
|
40
|
+
/** Identifies the immutable generation, and keys the rebuilt catalog. */
|
|
41
|
+
readonly activationRevision: string;
|
|
42
|
+
readonly signal?: AbortSignal;
|
|
43
|
+
}
|
|
44
|
+
export interface PortableSemanticExecutorOptions {
|
|
45
|
+
readonly queryBuilder: QueryBuilderFactoryInput;
|
|
46
|
+
/**
|
|
47
|
+
* Rebuilt catalogs are memoized by activation revision. A release is
|
|
48
|
+
* immutable and content-addressed, so the revision is an exact key with no
|
|
49
|
+
* invalidation problem. Only the most recent generation is kept here;
|
|
50
|
+
* `CLOUD-09` owns the bounded multi-release cache.
|
|
51
|
+
*/
|
|
52
|
+
readonly cacheRebuiltCatalogs?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the executor the deployment data plane injects.
|
|
56
|
+
*
|
|
57
|
+
* Returns the portable result record; the data plane validates it before it
|
|
58
|
+
* reaches a caller.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createPortableSemanticExecutor(options: PortableSemanticExecutorOptions): (input: PortableSemanticExecutionInput) => Promise<ProtocolSemanticInvocationResult>;
|
|
61
|
+
//# sourceMappingURL=portable-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-executor.d.ts","sourceRoot":"","sources":["../src/portable-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAK/I;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,gCAAgC,EAChC,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAA;KAAE,CAAC;IAC/E,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC;IACxC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,YAAY,EAAE,wBAAwB,CAAC;IAChD;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAID;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,CAAC,KAAK,EAAE,8BAA8B,KAAK,OAAO,CAAC,gCAAgC,CAAC,CAgGtF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { PortableExecutionUnsupportedError, PortableExecutionTenantError } from './portable-execution-errors.js';
|
|
2
|
+
export { PortableExecutionUnsupportedError, PortableExecutionBudgetError, PortableExecutionTenantError } from './portable-execution-errors.js';
|
|
3
|
+
import { tenantRuntime, semanticQuery } from './utils/portable-semantic-query.js';
|
|
4
|
+
import { bounded } from './utils/portable-result-budget.js';
|
|
5
|
+
import { withDeadline } from './utils/portable-execution-deadline.js';
|
|
6
|
+
import { createDatasetClient } from './executor.js';
|
|
7
|
+
import { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
8
|
+
/**
|
|
9
|
+
* Build the executor the deployment data plane injects.
|
|
10
|
+
*
|
|
11
|
+
* Returns the portable result record; the data plane validates it before it
|
|
12
|
+
* reaches a caller.
|
|
13
|
+
*/
|
|
14
|
+
export function createPortableSemanticExecutor(options) {
|
|
15
|
+
const client = createDatasetClient({ queryBuilder: options.queryBuilder });
|
|
16
|
+
let memo;
|
|
17
|
+
function registryFor(input) {
|
|
18
|
+
if (options.cacheRebuiltCatalogs !== false && memo?.revision === input.activationRevision) {
|
|
19
|
+
return memo.registry;
|
|
20
|
+
}
|
|
21
|
+
let registry;
|
|
22
|
+
try {
|
|
23
|
+
// Skip rather than throw: a single derived metric anywhere in the
|
|
24
|
+
// contract must not make every other dataset unexecutable. The requested
|
|
25
|
+
// target is still refused below when it is one of the skipped ones.
|
|
26
|
+
registry = rehydrateProtocolDatasets(input.deployment.datasets, {
|
|
27
|
+
onUnsupportedMetric: 'skip',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof UnsupportedContractFeatureError) {
|
|
32
|
+
// Decision 0005: a surface portable execution cannot reproduce is
|
|
33
|
+
// excluded from it, never approximated.
|
|
34
|
+
throw new PortableExecutionUnsupportedError(error.message, { cause: error });
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
memo = { revision: input.activationRevision, registry };
|
|
39
|
+
return registry;
|
|
40
|
+
}
|
|
41
|
+
return async function execute(input) {
|
|
42
|
+
if (input.metric?.kind === 'derived-metric' && input.metric.derivation === undefined) {
|
|
43
|
+
// A derived metric is executable once the contract carries the formula in
|
|
44
|
+
// the shape it was authored in. One written before that field existed
|
|
45
|
+
// still states only what the metric means, not the aliases its SQL is
|
|
46
|
+
// written in terms of, so it stays excluded rather than approximated.
|
|
47
|
+
throw new PortableExecutionUnsupportedError(`Metric "${String(input.metric.name)}" is derived, and this deployment contract does not `
|
|
48
|
+
+ 'carry the authored formula portable execution needs to plan it.');
|
|
49
|
+
}
|
|
50
|
+
const registry = registryFor(input);
|
|
51
|
+
const rebuilt = registry[String(input.dataset.name)];
|
|
52
|
+
if (rebuilt === undefined) {
|
|
53
|
+
throw new PortableExecutionUnsupportedError(`Dataset "${String(input.dataset.name)}" is not part of the activated contract.`);
|
|
54
|
+
}
|
|
55
|
+
const target = input.metric === undefined
|
|
56
|
+
? rebuilt
|
|
57
|
+
: rebuilt.metrics[String(input.metric.name)];
|
|
58
|
+
if (target === undefined) {
|
|
59
|
+
throw new PortableExecutionUnsupportedError(`Metric "${String(input.metric?.name)}" could not be rebuilt from the contract.`);
|
|
60
|
+
}
|
|
61
|
+
const tenant = tenantRuntime(input.tenant);
|
|
62
|
+
// A tenant with nothing to scope by is the one failure that is silent
|
|
63
|
+
// everywhere else: the runtime accepts it, the planner emits no predicate,
|
|
64
|
+
// and the query reads every tenant while each layer believes tenancy was
|
|
65
|
+
// enforced. Contract validation refuses that shape, but this executor is
|
|
66
|
+
// exported on its own and typed structurally, so it must refuse it too
|
|
67
|
+
// rather than trusting the caller to have validated the contract.
|
|
68
|
+
if (tenant !== undefined && rebuilt.tenantKey === undefined) {
|
|
69
|
+
throw new PortableExecutionTenantError(`Dataset "${String(input.dataset.name)}" declares no tenant field, so a resolved tenant `
|
|
70
|
+
+ 'cannot be applied to it.');
|
|
71
|
+
}
|
|
72
|
+
const query = semanticQuery(input.operation, input.budget.maxRows);
|
|
73
|
+
const output = await withDeadline(input.budget, input.signal, async (signal) => (await client.execute(target, query, {
|
|
74
|
+
abortSignal: signal,
|
|
75
|
+
...(tenant === undefined ? {} : { runtime: { tenant } }),
|
|
76
|
+
})));
|
|
77
|
+
const rows = output.data ?? [];
|
|
78
|
+
const pagination = output.meta?.pagination;
|
|
79
|
+
return bounded(Object.freeze({
|
|
80
|
+
kind: 'hypequery-semantic-invocation-result',
|
|
81
|
+
version: 1,
|
|
82
|
+
activationRevision: input.activationRevision,
|
|
83
|
+
data: rows,
|
|
84
|
+
meta: {
|
|
85
|
+
rowCount: rows.length,
|
|
86
|
+
...(pagination === undefined ? {} : { pagination }),
|
|
87
|
+
},
|
|
88
|
+
}), input.budget);
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,uBAAuB,EAE5B,KAAK,sBAAsB,EAG5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,kBAAkB,EAElB,YAAY,EAEb,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;CAC7E;AAsFD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,mCAAwC,GAChD,uBAAuB,CAiHzB"}
|
package/dist/protocol-adapter.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { filterExpression, metricExpression, metricDerivation } from './utils/protocol-metric-expressions.js';
|
|
2
|
+
import { parseProtocolIdentifier, parseProtocolQualifiedIdentifier, validateProtocolDatasetContract, } from '@hypequery/protocol';
|
|
2
3
|
import { SEMANTIC_FILTER_OPERATORS } from './constants.js';
|
|
3
4
|
import { toProtocolSemanticMetadata } from './utils/protocol-semantic-metadata.js';
|
|
4
5
|
function byName(left, right) {
|
|
@@ -17,107 +18,11 @@ function fieldSchema(type) {
|
|
|
17
18
|
return { kind: 'any' };
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
function canonicalValue(input) {
|
|
21
|
-
if (Array.isArray(input)) {
|
|
22
|
-
return validateCanonicalValue({
|
|
23
|
-
$hypequery: {
|
|
24
|
-
type: 'array',
|
|
25
|
-
version: 1,
|
|
26
|
-
values: input.map(canonicalValue),
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
if (typeof input === 'object' && input !== null) {
|
|
31
|
-
if ('$hypequery' in input)
|
|
32
|
-
return validateCanonicalValue(input);
|
|
33
|
-
const prototype = Object.getPrototypeOf(input);
|
|
34
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
35
|
-
throw new TypeError('Dataset protocol adapter only accepts plain filter values.');
|
|
36
|
-
}
|
|
37
|
-
return validateCanonicalValue({
|
|
38
|
-
$hypequery: {
|
|
39
|
-
type: 'map',
|
|
40
|
-
version: 1,
|
|
41
|
-
entries: Object.entries(input)
|
|
42
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
43
|
-
.map(([key, value]) => [key, canonicalValue(value)]),
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return validateCanonicalValue(input);
|
|
48
|
-
}
|
|
49
|
-
function filterExpression(filter) {
|
|
50
|
-
const left = {
|
|
51
|
-
kind: 'reference',
|
|
52
|
-
name: parseProtocolQualifiedIdentifier(filter.field),
|
|
53
|
-
};
|
|
54
|
-
const right = {
|
|
55
|
-
kind: 'literal',
|
|
56
|
-
value: canonicalValue(filter.value),
|
|
57
|
-
};
|
|
58
|
-
const result = {
|
|
59
|
-
kind: 'comparison',
|
|
60
|
-
operator: filter.operator,
|
|
61
|
-
left,
|
|
62
|
-
right,
|
|
63
|
-
};
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
function aggregationExpression(spec) {
|
|
67
|
-
const result = {
|
|
68
|
-
kind: 'aggregate',
|
|
69
|
-
aggregation: spec.aggregation,
|
|
70
|
-
field: parseProtocolQualifiedIdentifier(spec.field),
|
|
71
|
-
...(spec.argField !== undefined
|
|
72
|
-
? { argField: parseProtocolQualifiedIdentifier(spec.argField) }
|
|
73
|
-
: {}),
|
|
74
|
-
...(spec.level !== undefined ? { level: spec.level } : {}),
|
|
75
|
-
...(spec.filters?.length
|
|
76
|
-
? { filters: spec.filters.map(filterExpression) }
|
|
77
|
-
: {}),
|
|
78
|
-
};
|
|
79
|
-
return result;
|
|
80
|
-
}
|
|
81
|
-
function semanticExpression(expression, references = {}) {
|
|
82
|
-
switch (expression.kind) {
|
|
83
|
-
case 'ref':
|
|
84
|
-
return references[expression.name]
|
|
85
|
-
?? {
|
|
86
|
-
kind: 'reference',
|
|
87
|
-
name: parseProtocolQualifiedIdentifier(expression.name),
|
|
88
|
-
};
|
|
89
|
-
case 'literal':
|
|
90
|
-
return { kind: 'literal', value: canonicalValue(expression.value) };
|
|
91
|
-
case 'binary':
|
|
92
|
-
return {
|
|
93
|
-
kind: 'binary',
|
|
94
|
-
operator: expression.operator,
|
|
95
|
-
left: semanticExpression(expression.left, references),
|
|
96
|
-
right: semanticExpression(expression.right, references),
|
|
97
|
-
};
|
|
98
|
-
case 'function':
|
|
99
|
-
return {
|
|
100
|
-
kind: 'call',
|
|
101
|
-
function: expression.name,
|
|
102
|
-
args: expression.args.map(argument => semanticExpression(argument, references)),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
21
|
function unwrapMetric(metric) {
|
|
107
22
|
return metric.__type === 'grained_metric_ref'
|
|
108
23
|
? { ref: metric.metric, grain: metric.grain }
|
|
109
24
|
: { ref: metric };
|
|
110
25
|
}
|
|
111
|
-
function metricExpression(spec) {
|
|
112
|
-
if (spec.__type === 'aggregation_spec')
|
|
113
|
-
return aggregationExpression(spec);
|
|
114
|
-
const aliases = Object.fromEntries(Object.keys(spec.uses).map(alias => [alias, alias]));
|
|
115
|
-
const references = Object.fromEntries(Object.entries(spec.uses).map(([alias, metric]) => [
|
|
116
|
-
alias,
|
|
117
|
-
aggregationExpression(metric.spec),
|
|
118
|
-
]));
|
|
119
|
-
return semanticExpression(spec.formula(aliases).expression, references);
|
|
120
|
-
}
|
|
121
26
|
function metricContract(exposedName, metric, endpoint) {
|
|
122
27
|
const { ref, grain } = unwrapMetric(metric);
|
|
123
28
|
const contract = metric.contract();
|
|
@@ -129,6 +34,9 @@ function metricContract(exposedName, metric, endpoint) {
|
|
|
129
34
|
? 'derived-metric'
|
|
130
35
|
: 'metric',
|
|
131
36
|
expression: metricExpression(ref.spec),
|
|
37
|
+
...(ref.spec.__type === 'derived_metric_spec'
|
|
38
|
+
? { derivation: metricDerivation(ref.spec) }
|
|
39
|
+
: {}),
|
|
132
40
|
dimensions: [...contract.dimensions].sort().map(parseProtocolQualifiedIdentifier),
|
|
133
41
|
filters: [...contract.filters].sort().map(parseProtocolIdentifier),
|
|
134
42
|
grains: [...contract.grains].sort(),
|
|
@@ -23,6 +23,16 @@ export interface RehydrateProtocolDatasetsOptions {
|
|
|
23
23
|
* an operational concern of whoever runs the query, not of the deployment.
|
|
24
24
|
*/
|
|
25
25
|
readonly cache?: DatasetCachePolicy;
|
|
26
|
+
/**
|
|
27
|
+
* What to do with a metric portable execution cannot rebuild.
|
|
28
|
+
*
|
|
29
|
+
* `throw` (the default) refuses the whole contract, which is right when a
|
|
30
|
+
* caller is checking whether a deployment is fully portable. `skip` omits
|
|
31
|
+
* just that metric, which is what a runtime wants: one derived metric must
|
|
32
|
+
* not make every other dataset in the deployment unexecutable. A caller that
|
|
33
|
+
* skips is responsible for refusing the skipped target at the point of use.
|
|
34
|
+
*/
|
|
35
|
+
readonly onUnsupportedMetric?: 'throw' | 'skip';
|
|
26
36
|
}
|
|
27
37
|
/**
|
|
28
38
|
* Thrown when a contract describes something portable execution cannot rebuild.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-rehydrate.d.ts","sourceRoot":"","sources":["../src/protocol-rehydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,uBAAuB,
|
|
1
|
+
{"version":3,"file":"protocol-rehydrate.d.ts","sourceRoot":"","sources":["../src/protocol-rehydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,uBAAuB,EAKxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAKlB,YAAY,EAIb,MAAM,YAAY,CAAC;AAMpB,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACjD;AAED;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAMjE;AAwOD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,uBAAuB,EAAE,EAC7C,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAqE7C"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { dataset } from './dataset.js';
|
|
15
15
|
import { snapshotSemanticMetadata } from './utils/semantic-metadata.js';
|
|
16
16
|
import { withContractCapabilities } from './utils/protocol-metric-capabilities.js';
|
|
17
|
+
import { rehydrateDerivedFormula } from './utils/protocol-rehydrate-derivation.js';
|
|
17
18
|
import { rehydrateMeasureFilter } from './utils/protocol-rehydrate-filters.js';
|
|
18
19
|
/**
|
|
19
20
|
* Thrown when a contract describes something portable execution cannot rebuild.
|
|
@@ -119,38 +120,75 @@ function aggregationKey(value) {
|
|
|
119
120
|
value.filters ?? [],
|
|
120
121
|
]);
|
|
121
122
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const expression = metric.expression;
|
|
123
|
+
/**
|
|
124
|
+
* The declared measure an aggregate expression was built from.
|
|
125
|
+
*
|
|
126
|
+
* A metric's expression names an aggregation and a field, not the measure that
|
|
127
|
+
* produced it, so the measure is recovered by matching aggregation identity.
|
|
128
|
+
*/
|
|
129
|
+
function measureForAggregate(instance, contract, subject, expression) {
|
|
130
130
|
if (expression.kind !== 'aggregate') {
|
|
131
|
-
throw new UnsupportedContractFeatureError(instance.name,
|
|
131
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, `expected an aggregate expression, received "${expression.kind}"`);
|
|
132
132
|
}
|
|
133
133
|
const field = String(expression.field);
|
|
134
134
|
const candidates = contract.measures.filter(measure => (aggregationKey(measure) === aggregationKey(expression)));
|
|
135
135
|
if (candidates.length === 0) {
|
|
136
|
-
throw new UnsupportedContractFeatureError(instance.name,
|
|
136
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, `no declared measure matches ${expression.aggregation}(${field})`);
|
|
137
137
|
}
|
|
138
138
|
// A metric expression carries no raw SQL, so two measures that share an
|
|
139
139
|
// aggregation identity but override SQL differently are indistinguishable in
|
|
140
140
|
// contract v1. Binding to either would be a guess at which SQL to emit.
|
|
141
141
|
const distinctSql = new Set(candidates.map(measure => measure.sql?.sql ?? null));
|
|
142
142
|
if (distinctSql.size > 1) {
|
|
143
|
-
throw new UnsupportedContractFeatureError(instance.name,
|
|
143
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, `${candidates.map(measure => `"${String(measure.name)}"`).join(' and ')} share `
|
|
144
144
|
+ `${expression.aggregation}(${field}) but emit different SQL, so the contract cannot `
|
|
145
145
|
+ 'say which one this metric was built from');
|
|
146
146
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
return String(candidates[0].name);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Rebuilds the `uses` map and formula of a derived metric.
|
|
151
|
+
*
|
|
152
|
+
* Each input becomes a base metric named by its alias, because that alias is
|
|
153
|
+
* what both plan builders emit as the column of the intermediate aggregate.
|
|
154
|
+
*/
|
|
155
|
+
function derivedMetricConfig(instance, contract, subject, derivation) {
|
|
156
|
+
const unsupported = (reason) => new UnsupportedContractFeatureError(instance.name, subject, reason);
|
|
157
|
+
const uses = Object.fromEntries(derivation.inputs.map(input => {
|
|
158
|
+
const alias = String(input.alias);
|
|
159
|
+
return [
|
|
160
|
+
alias,
|
|
161
|
+
instance.metric(alias, {
|
|
162
|
+
measure: measureForAggregate(instance, contract, `${subject} input "${alias}"`, input.expression),
|
|
163
|
+
}),
|
|
164
|
+
];
|
|
165
|
+
}));
|
|
166
|
+
return { uses, formula: rehydrateDerivedFormula(derivation, unsupported) };
|
|
167
|
+
}
|
|
168
|
+
function rehydrateMetric(instance, contract, metric) {
|
|
169
|
+
const name = String(metric.name);
|
|
170
|
+
const subject = `metric "${name}"`;
|
|
171
|
+
const derived = metric.expression.kind !== 'aggregate';
|
|
172
|
+
if (derived && metric.derivation === undefined) {
|
|
173
|
+
// The inlined expression states what a derived metric means but drops the
|
|
174
|
+
// aliases its SQL is written in terms of. Without them a rebuild computes
|
|
175
|
+
// the same number through different SQL, which decision 0005 excludes.
|
|
176
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, 'a derived metric requires its authored formula, which this contract does not carry');
|
|
177
|
+
}
|
|
178
|
+
const metadata = {
|
|
150
179
|
...snapshotSemanticMetadata(metric),
|
|
151
180
|
...(metric.label !== undefined ? { label: metric.label } : {}),
|
|
152
181
|
...(metric.description !== undefined ? { description: metric.description } : {}),
|
|
153
|
-
}
|
|
182
|
+
};
|
|
183
|
+
const base = (metric.derivation === undefined
|
|
184
|
+
? instance.metric(name, {
|
|
185
|
+
measure: measureForAggregate(instance, contract, subject, metric.expression),
|
|
186
|
+
...metadata,
|
|
187
|
+
})
|
|
188
|
+
: instance.metric(name, {
|
|
189
|
+
...derivedMetricConfig(instance, contract, subject, metric.derivation),
|
|
190
|
+
...metadata,
|
|
191
|
+
}));
|
|
154
192
|
const handle = metric.grain === undefined
|
|
155
193
|
? base
|
|
156
194
|
: base.by(metric.grain);
|
|
@@ -210,7 +248,15 @@ export function rehydrateProtocolDatasets(contracts, options = {}) {
|
|
|
210
248
|
const instance = instances.get(name);
|
|
211
249
|
const metrics = {};
|
|
212
250
|
for (const metric of contract.metrics) {
|
|
213
|
-
|
|
251
|
+
try {
|
|
252
|
+
metrics[String(metric.name)] = rehydrateMetric(instance, contract, metric);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
if (options.onUnsupportedMetric !== 'skip'
|
|
256
|
+
|| !(error instanceof UnsupportedContractFeatureError)) {
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
214
260
|
}
|
|
215
261
|
registry[name] = Object.assign(Object.create(Object.getPrototypeOf(instance)), instance, { metrics });
|
|
216
262
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ZodTypeAny } from 'zod';
|
|
2
|
+
import { type ProtocolSchema } from '@hypequery/protocol';
|
|
3
|
+
export declare class ProtocolSchemaAdapterError extends TypeError {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
constructor(message: string, path?: string);
|
|
6
|
+
}
|
|
7
|
+
/** Converts the portable subset of a Zod v3 schema into RFC 0004. */
|
|
8
|
+
export declare function zodToProtocolSchema(schema: ZodTypeAny | undefined, path?: string): ProtocolSchema;
|
|
9
|
+
//# sourceMappingURL=protocol-schema-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-schema-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-schema-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,0BAA2B,SAAQ,SAAS;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,IAAI,SAAM;CAKxC;AAoPD,qEAAqE;AACrE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,IAAI,SAAM,GACT,cAAc,CAGhB"}
|