@hypequery/datasets 0.18.0 → 0.19.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.
Files changed (98) hide show
  1. package/dist/agent-catalog.d.ts +9 -0
  2. package/dist/agent-catalog.d.ts.map +1 -1
  3. package/dist/aggregations.d.ts +2 -0
  4. package/dist/aggregations.d.ts.map +1 -1
  5. package/dist/aggregations.js +4 -0
  6. package/dist/api.type-test.js +35 -0
  7. package/dist/cache/query-signature.d.ts.map +1 -1
  8. package/dist/cache/query-signature.js +17 -0
  9. package/dist/catalog.d.ts +11 -0
  10. package/dist/catalog.d.ts.map +1 -1
  11. package/dist/catalog.js +12 -2
  12. package/dist/constants.d.ts.map +1 -1
  13. package/dist/constants.js +2 -0
  14. package/dist/contract.d.ts +5 -1
  15. package/dist/contract.d.ts.map +1 -1
  16. package/dist/contract.js +7 -0
  17. package/dist/dataset-query.d.ts.map +1 -1
  18. package/dist/dataset-query.js +6 -1
  19. package/dist/dataset.d.ts +2 -2
  20. package/dist/dataset.d.ts.map +1 -1
  21. package/dist/dataset.js +3 -0
  22. package/dist/executor.d.ts.map +1 -1
  23. package/dist/executor.js +15 -4
  24. package/dist/in-memory-backend.d.ts.map +1 -1
  25. package/dist/in-memory-backend.js +34 -7
  26. package/dist/index.d.ts +8 -6
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +3 -2
  29. package/dist/measure.d.ts +5 -0
  30. package/dist/measure.d.ts.map +1 -1
  31. package/dist/measure.js +5 -0
  32. package/dist/portable-execution-errors.d.ts +4 -0
  33. package/dist/portable-execution-errors.d.ts.map +1 -1
  34. package/dist/portable-execution-errors.js +4 -1
  35. package/dist/portable-executor.d.ts.map +1 -1
  36. package/dist/portable-executor.js +6 -3
  37. package/dist/protocol-adapter.d.ts.map +1 -1
  38. package/dist/protocol-adapter.js +15 -7
  39. package/dist/protocol-rehydrate.d.ts +5 -1
  40. package/dist/protocol-rehydrate.d.ts.map +1 -1
  41. package/dist/protocol-rehydrate.js +20 -10
  42. package/dist/query-builder-protocol.d.ts +7 -3
  43. package/dist/query-builder-protocol.d.ts.map +1 -1
  44. package/dist/query-planner.d.ts.map +1 -1
  45. package/dist/query-planner.js +5 -0
  46. package/dist/relationship-check.d.ts +47 -0
  47. package/dist/relationship-check.d.ts.map +1 -0
  48. package/dist/relationship-check.js +59 -0
  49. package/dist/relationships.d.ts +10 -10
  50. package/dist/relationships.js +10 -10
  51. package/dist/semantic-planner.d.ts.map +1 -1
  52. package/dist/semantic-planner.js +5 -1
  53. package/dist/semantic-query-schema.d.ts.map +1 -1
  54. package/dist/semantic-query-schema.js +5 -0
  55. package/dist/types.d.ts +39 -6
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/utils/agent-catalog-projection.d.ts +6 -0
  58. package/dist/utils/agent-catalog-projection.d.ts.map +1 -1
  59. package/dist/utils/agent-catalog-projection.js +4 -0
  60. package/dist/utils/approximate-measures.d.ts +10 -0
  61. package/dist/utils/approximate-measures.d.ts.map +1 -0
  62. package/dist/utils/approximate-measures.js +15 -0
  63. package/dist/utils/dataset-contract.d.ts.map +1 -1
  64. package/dist/utils/dataset-contract.js +2 -2
  65. package/dist/utils/dataset-metric-ref.d.ts.map +1 -1
  66. package/dist/utils/dataset-metric-ref.js +5 -0
  67. package/dist/utils/dataset-query-validation.d.ts.map +1 -1
  68. package/dist/utils/dataset-query-validation.js +6 -3
  69. package/dist/utils/dataset-time-grains.d.ts +15 -0
  70. package/dist/utils/dataset-time-grains.d.ts.map +1 -0
  71. package/dist/utils/dataset-time-grains.js +17 -0
  72. package/dist/utils/filtered-aggregation-sql.d.ts.map +1 -1
  73. package/dist/utils/filtered-aggregation-sql.js +1 -0
  74. package/dist/utils/portable-aggregations.d.ts +14 -0
  75. package/dist/utils/portable-aggregations.d.ts.map +1 -0
  76. package/dist/utils/portable-aggregations.js +15 -0
  77. package/dist/utils/portable-grains.d.ts +22 -0
  78. package/dist/utils/portable-grains.d.ts.map +1 -0
  79. package/dist/utils/portable-grains.js +35 -0
  80. package/dist/utils/portable-semantic-query.d.ts.map +1 -1
  81. package/dist/utils/portable-semantic-query.js +2 -1
  82. package/dist/utils/protocol-metric-expressions.d.ts.map +1 -1
  83. package/dist/utils/protocol-metric-expressions.js +2 -1
  84. package/dist/utils/relationship-builder-plan.d.ts +6 -3
  85. package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
  86. package/dist/utils/relationship-builder-plan.js +13 -5
  87. package/dist/utils/relationship-key-check.d.ts +43 -0
  88. package/dist/utils/relationship-key-check.d.ts.map +1 -0
  89. package/dist/utils/relationship-key-check.js +72 -0
  90. package/dist/utils/segments.d.ts +31 -0
  91. package/dist/utils/segments.d.ts.map +1 -0
  92. package/dist/utils/segments.js +91 -0
  93. package/dist/utils/semantic-metadata-validation.d.ts.map +1 -1
  94. package/dist/utils/semantic-metadata-validation.js +22 -1
  95. package/dist/utils/unsupported-contract-reasons.d.ts +32 -0
  96. package/dist/utils/unsupported-contract-reasons.d.ts.map +1 -0
  97. package/dist/utils/unsupported-contract-reasons.js +30 -0
  98. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -2,7 +2,9 @@ export { dataset } from './dataset.js';
2
2
  export { dimension } from './field.js';
3
3
  export { measure } from './measure.js';
4
4
  export { belongsTo, hasMany, hasOne } from './relationships.js';
5
- export { sum, count, countDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance } from './aggregations.js';
5
+ export { checkRelationships } from './relationship-check.js';
6
+ export type { CheckRelationshipsOptions, CheckRelationshipsResult, RelationshipKeyIssue, } from './relationship-check.js';
7
+ export { sum, count, countDistinct, approxCountDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance, } from './aggregations.js';
6
8
  export { divide, multiply, subtract, add, nullIfZero, coalesce, round, floor, ceil, } from './formulas.js';
7
9
  export { eq, neq, gt, gte, lt, lte, inList, notInList, between, like, asc, desc, filter, order, } from './query-helpers.js';
8
10
  export { createDatasetRegistry } from './registry.js';
@@ -11,12 +13,12 @@ export type { DatasetPublisher } from './publishing/publisher.js';
11
13
  export type { PublishableMetric, PublishedMetricHandle, PublishedMetricMap, PublishedMetrics, PublishedDataset, PublishedDatasetRegistry, PublishDatasetOptions, } from './publishing/types.js';
12
14
  export { getDatasetCatalog, getDatasetCatalogs, getQueryableRelationshipFields } from './catalog.js';
13
15
  export { listQueryableRelationshipFields } from './utils/relationship-fields.js';
14
- export type { DatasetCatalog, DatasetCatalogMap, DatasetCatalogSource, DimensionCatalogEntry, MeasureCatalogEntry, MetricCatalogEntry, FilterCatalogEntry, RelationshipCatalogEntry, } from './catalog.js';
16
+ export type { DatasetCatalog, DatasetCatalogMap, DatasetCatalogSource, DimensionCatalogEntry, MeasureCatalogEntry, SegmentCatalogEntry, MetricCatalogEntry, FilterCatalogEntry, RelationshipCatalogEntry, } from './catalog.js';
15
17
  export { DEFAULT_AGENT_CATALOG_MAX_BYTES, assertAgentSafeCatalogBudget, projectAgentSafeCatalog, projectTrustedDebugCatalog, } from './agent-catalog.js';
16
- export type { AgentCatalogDataset, AgentCatalogDatasetRegistry, AgentCatalogProjectionOptions, AgentCatalogDimension, AgentCatalogFilter, AgentCatalogMeasure, AgentCatalogMetric, AgentCatalogRelationship, AgentCatalogSource, AgentSafeCatalog, TrustedDebugCatalog, TrustedDebugCatalogAuthorization, } from './agent-catalog.js';
18
+ export type { AgentCatalogDataset, AgentCatalogDatasetRegistry, AgentCatalogProjectionOptions, AgentCatalogDimension, AgentCatalogFilter, AgentCatalogMeasure, AgentCatalogSegment, AgentCatalogMetric, AgentCatalogRelationship, AgentCatalogSource, AgentSafeCatalog, TrustedDebugCatalog, TrustedDebugCatalogAuthorization, } from './agent-catalog.js';
17
19
  export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
18
- export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
19
- export type { RehydratedDataset, RehydrateProtocolDatasetsOptions, } from './protocol-rehydrate.js';
20
+ export { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
21
+ export type { RehydratedDataset, RehydrateProtocolDatasetsOptions, UnsupportedContractReason, } from './protocol-rehydrate.js';
20
22
  export { buildProtocolDatasetContract } from './protocol-adapter.js';
21
23
  export { buildProtocolDeploymentContract } from './protocol-deployment-adapter.js';
22
24
  export type { BuildProtocolDeploymentContractOptions } from './protocol-deployment-adapter.js';
@@ -47,6 +49,6 @@ export type { QueryBuilderLike, QueryBuilderFactoryLike, QueryBuilderFactoryComp
47
49
  export { toQueryBuilderFactory } from './query-builder-protocol.js';
48
50
  export { validateSQLIdentifier, isSafeSQLIdentifier, quoteSQLIdentifier } from './sql-utils.js';
49
51
  export { GRAIN_FUNCTIONS, SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
50
- export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, DatasetMeasureDefinition, DerivedMeasureDefinition, DerivedMeasureOptions, DerivedMeasureUses, 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';
52
+ export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, DatasetMeasureDefinition, DerivedMeasureDefinition, DerivedMeasureOptions, DerivedMeasureUses, 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, SegmentDefinition, SemanticFiltersDefinition, DatasetConfig, DatasetDefaults, DatasetFreshness, DatasetLimits, DatasetCachePolicy, SemanticMetadata, SemanticSensitivity, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetQueryableDimensions, DatasetMeasureNames, DatasetSegmentNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
51
53
  export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
52
54
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -6,8 +6,9 @@ export { dimension } from './field.js';
6
6
  export { measure } from './measure.js';
7
7
  // Relationship helpers
8
8
  export { belongsTo, hasMany, hasOne } from './relationships.js';
9
+ export { checkRelationships } from './relationship-check.js';
9
10
  // Aggregation helpers
10
- export { sum, count, countDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance } from './aggregations.js';
11
+ export { sum, count, countDistinct, approxCountDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance, } from './aggregations.js';
11
12
  // Formula helpers
12
13
  export { divide, multiply, subtract, add, nullIfZero, coalesce, round, floor, ceil, } from './formulas.js';
13
14
  // Semantic query helpers
@@ -24,7 +25,7 @@ export { DEFAULT_AGENT_CATALOG_MAX_BYTES, assertAgentSafeCatalogBudget, projectA
24
25
  // Semantic contract (stable, hashable export for snapshots/diffs/validation)
25
26
  export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
26
27
  // Portable deployment contract adapter
27
- export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
28
+ export { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
28
29
  export { buildProtocolDatasetContract } from './protocol-adapter.js';
29
30
  export { buildProtocolDeploymentContract } from './protocol-deployment-adapter.js';
30
31
  export { rehydrateProtocolDeploymentContract } from './protocol-rehydrate.js';
package/dist/measure.d.ts CHANGED
@@ -6,6 +6,11 @@ export declare const measure: {
6
6
  readonly sum: (field: string, opts?: MeasureOptions) => MeasureDefinition;
7
7
  readonly count: (field: string, opts?: MeasureOptions) => MeasureDefinition;
8
8
  readonly countDistinct: (field: string, opts?: MeasureOptions) => MeasureDefinition;
9
+ /**
10
+ * Estimated number of distinct values (ClickHouse `uniq`). Uses bounded
11
+ * memory on high-cardinality columns; catalogs mark it `approximate`.
12
+ */
13
+ readonly approxCountDistinct: (field: string, opts?: MeasureOptions) => MeasureDefinition;
9
14
  readonly avg: (field: string, opts?: MeasureOptions) => MeasureDefinition;
10
15
  readonly min: (field: string, opts?: MeasureOptions) => MeasureDefinition;
11
16
  readonly max: (field: string, opts?: MeasureOptions) => MeasureDefinition;
@@ -1 +1 @@
1
- {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EAEf,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAqBD,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,iBAAiB,CAcvG;AAED,iBAAS,oBAAoB,CAAC,KAAK,CAAC,KAAK,SAAS,kBAAkB,EAClE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GACpC,wBAAwB,CAAC,KAAK,CAAC,CASjC;AAED,eAAO,MAAM,OAAO;0BAnEH,MAAM,SAAS,cAAc,KAAG,iBAAiB;4BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;oCAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA0EhE,gFAAgF;;IAEhF,mDAAmD;6BACnC,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAEjE;;;;;OAKG;6BAhEY,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAkE7F,gFAAgF;6BAlEjE,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAoE7F,2DAA2D;6BAxF5C,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA0FhE,8CAA8C;+BA1F/B,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA4FhE,0DAA0D;;CAElD,CAAC"}
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EAEf,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAqBD,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,iBAAiB,CAcvG;AAED,iBAAS,oBAAoB,CAAC,KAAK,CAAC,KAAK,SAAS,kBAAkB,EAClE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GACpC,wBAAwB,CAAC,KAAK,CAAC,CASjC;AAED,eAAO,MAAM,OAAO;0BAnEH,MAAM,SAAS,cAAc,KAAG,iBAAiB;4BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;oCAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAuEhE;;;OAGG;0CA1EY,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA+EhE,gFAAgF;;IAEhF,mDAAmD;6BACnC,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAEjE;;;;;OAKG;6BArEY,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAuE7F,gFAAgF;6BAvEjE,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAyE7F,2DAA2D;6BA7F5C,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA+FhE,8CAA8C;+BA/F/B,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAiGhE,0DAA0D;;CAElD,CAAC"}
package/dist/measure.js CHANGED
@@ -64,6 +64,11 @@ export const measure = {
64
64
  sum: createMeasureHelper('sum'),
65
65
  count: createMeasureHelper('count'),
66
66
  countDistinct: createMeasureHelper('countDistinct'),
67
+ /**
68
+ * Estimated number of distinct values (ClickHouse `uniq`). Uses bounded
69
+ * memory on high-cardinality columns; catalogs mark it `approximate`.
70
+ */
71
+ approxCountDistinct: createMeasureHelper('approxCountDistinct'),
67
72
  avg: createMeasureHelper('avg'),
68
73
  min: createMeasureHelper('min'),
69
74
  max: createMeasureHelper('max'),
@@ -1,3 +1,4 @@
1
+ import type { UnsupportedContractReason } from './utils/unsupported-contract-reasons.js';
1
2
  /**
2
3
  * An error that deliberately claims a portable failure category.
3
4
  *
@@ -25,8 +26,11 @@ declare abstract class PortableExecutionError extends Error {
25
26
  export declare class PortableExecutionUnsupportedError extends PortableExecutionError {
26
27
  readonly code = "HQ_SEMANTIC_UNSUPPORTED_CAPABILITY";
27
28
  readonly category = "unsupported-capability";
29
+ /** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
30
+ readonly reason: UnsupportedContractReason | undefined;
28
31
  constructor(message: string, options?: {
29
32
  cause?: unknown;
33
+ reason?: UnsupportedContractReason;
30
34
  });
31
35
  }
32
36
  export declare class PortableExecutionBudgetError extends PortableExecutionError {
@@ -1 +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"}
1
+ {"version":3,"file":"portable-execution-errors.d.ts","sourceRoot":"","sources":["../src/portable-execution-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAEzF;;;;;;;;;;;;;;;;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;IAC7C,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;gBAGrD,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,yBAAyB,CAAA;KAAO;CAMxE;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"}
@@ -23,9 +23,12 @@ class PortableExecutionError extends Error {
23
23
  export class PortableExecutionUnsupportedError extends PortableExecutionError {
24
24
  code = 'HQ_SEMANTIC_UNSUPPORTED_CAPABILITY';
25
25
  category = 'unsupported-capability';
26
+ /** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
27
+ reason;
26
28
  constructor(message, options = {}) {
27
- super(message, options);
29
+ super(message, options.cause === undefined ? {} : { cause: options.cause });
28
30
  this.name = 'PortableExecutionUnsupportedError';
31
+ this.reason = options.reason;
29
32
  }
30
33
  }
31
34
  export class PortableExecutionBudgetError extends PortableExecutionError {
@@ -1 +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,yBAAyB,EACzB,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,yBAAyB,EAAE,CAAA;KAAE,CAAC;IACjF,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,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,CAwEtF"}
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,yBAAyB,EACzB,gCAAgC,EAChC,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAQ7B,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,yBAAyB,EAAE,CAAA;KAAE,CAAC;IACjF,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,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,CA4EtF"}
@@ -4,7 +4,7 @@ import { tenantRuntime, semanticQuery } from './utils/portable-semantic-query.js
4
4
  import { bounded } from './utils/portable-result-budget.js';
5
5
  import { withDeadline } from './utils/portable-execution-deadline.js';
6
6
  import { createDatasetClient } from './executor.js';
7
- import { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
7
+ import { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
8
8
  /**
9
9
  * Build the executor the deployment data plane injects.
10
10
  *
@@ -26,7 +26,10 @@ export function createPortableSemanticExecutor(options) {
26
26
  if (error instanceof UnsupportedContractFeatureError) {
27
27
  // Decision 0005: a surface portable execution cannot reproduce is
28
28
  // excluded from it, never approximated.
29
- throw new PortableExecutionUnsupportedError(error.message, { cause: error });
29
+ throw new PortableExecutionUnsupportedError(error.message, {
30
+ cause: error,
31
+ ...(error.reason === undefined ? {} : { reason: error.reason }),
32
+ });
30
33
  }
31
34
  throw error;
32
35
  }
@@ -37,7 +40,7 @@ export function createPortableSemanticExecutor(options) {
37
40
  const registry = registryFor(input);
38
41
  const rebuilt = registry[String(input.dataset.name)];
39
42
  if (rebuilt === undefined) {
40
- throw new PortableExecutionUnsupportedError(`Dataset "${String(input.dataset.name)}" is not part of the activated contract.`);
43
+ throw new PortableExecutionUnsupportedError(`Dataset "${String(input.dataset.name)}" is not part of the activated contract.`, { reason: UNSUPPORTED_CONTRACT_REASONS.datasetNotActivated });
41
44
  }
42
45
  const target = rebuilt;
43
46
  const tenant = tenantRuntime(input.tenant);
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,uBAAuB,EAE5B,KAAK,sBAAsB,EAI5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,kBAAkB,EAElB,YAAY,EAEb,MAAM,YAAY,CAAC;AAMpB,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;AAuFD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,mCAAwC,GAChD,uBAAuB,CA0HzB"}
@@ -2,6 +2,9 @@ import { filterExpression, metricExpression, metricDerivation } from './utils/pr
2
2
  import { parseProtocolIdentifier, parseProtocolQualifiedIdentifier, validateProtocolDatasetContract, } from '@hypequery/protocol';
3
3
  import { SEMANTIC_FILTER_OPERATORS } from './constants.js';
4
4
  import { toProtocolSemanticMetadata } from './utils/protocol-semantic-metadata.js';
5
+ import { assertPublishableTimeGrains, isPortableTimeGrain, requirePortableTimeGrain } from './utils/portable-grains.js';
6
+ import { requirePortableAggregation } from './utils/portable-aggregations.js';
7
+ import { assertNoPublishedSegments } from './utils/segments.js';
5
8
  function byName(left, right) {
6
9
  return left.name.localeCompare(right.name);
7
10
  }
@@ -18,13 +21,13 @@ function fieldSchema(type) {
18
21
  return { kind: 'any' };
19
22
  }
20
23
  }
21
- function unwrapMetric(metric) {
24
+ function unwrapMetric(metric, exposedName) {
22
25
  return metric.__type === 'grained_metric_ref'
23
- ? { ref: metric.metric, grain: metric.grain }
26
+ ? { ref: metric.metric, grain: requirePortableTimeGrain(metric.grain, `Metric "${exposedName}"`) }
24
27
  : { ref: metric };
25
28
  }
26
29
  function metricContract(exposedName, metric, endpoint) {
27
- const { ref, grain } = unwrapMetric(metric);
30
+ const { ref, grain } = unwrapMetric(metric, exposedName);
28
31
  const contract = metric.contract();
29
32
  const result = {
30
33
  name: parseProtocolIdentifier(exposedName),
@@ -39,7 +42,8 @@ function metricContract(exposedName, metric, endpoint) {
39
42
  : {}),
40
43
  dimensions: [...contract.dimensions].sort().map(parseProtocolQualifiedIdentifier),
41
44
  filters: [...contract.filters].sort().map(parseProtocolIdentifier),
42
- grains: [...contract.grains].sort(),
45
+ // Only grains the published contract can carry are advertised there.
46
+ grains: contract.grains.filter(isPortableTimeGrain).sort(),
43
47
  ...(grain !== undefined ? { grain } : {}),
44
48
  ...(ref.label !== undefined ? { label: ref.label } : {}),
45
49
  ...(ref.description !== undefined ? { description: ref.description } : {}),
@@ -68,8 +72,10 @@ function requiredSqlDependencies(kind, name, dependencies) {
68
72
  * Deployment assembly selects the fields supported by the deployment contract.
69
73
  */
70
74
  export function buildProtocolDatasetContract(dataset, options = {}) {
75
+ assertNoPublishedSegments(dataset);
76
+ assertPublishableTimeGrains(dataset);
71
77
  const metrics = Object.entries(options.metrics ?? {})
72
- .filter(([, metric]) => unwrapMetric(metric).ref.datasetName === dataset.name)
78
+ .filter(([, metric]) => (metric.__type === 'grained_metric_ref' ? metric.metric : metric).datasetName === dataset.name)
73
79
  .map(([name, metric]) => {
74
80
  const endpoint = options.metricEndpoints?.[name];
75
81
  if (!endpoint) {
@@ -92,7 +98,9 @@ export function buildProtocolDatasetContract(dataset, options = {}) {
92
98
  ? { dimensions: [...dataset.defaults.dimensions].map(parseProtocolIdentifier) }
93
99
  : {}),
94
100
  ...(dataset.defaults.timeGrain !== undefined
95
- ? { timeGrain: dataset.defaults.timeGrain }
101
+ ? {
102
+ timeGrain: requirePortableTimeGrain(dataset.defaults.timeGrain, `Dataset "${dataset.name}" defaults.timeGrain`),
103
+ }
96
104
  : {}),
97
105
  },
98
106
  }
@@ -115,7 +123,7 @@ export function buildProtocolDatasetContract(dataset, options = {}) {
115
123
  })).sort(byName),
116
124
  measures: Object.entries(dataset.measures).map(([name, measure]) => ({
117
125
  name,
118
- aggregation: measure.aggregation,
126
+ aggregation: requirePortableAggregation(measure.aggregation, `Measure "${dataset.name}.${name}"`),
119
127
  field: measure.field,
120
128
  ...(measure.argField !== undefined ? { argField: measure.argField } : {}),
121
129
  ...(measure.level !== undefined ? { level: measure.level } : {}),
@@ -13,6 +13,8 @@
13
13
  */
14
14
  import type { ProtocolDatasetContract, ProtocolDeploymentDataset } from '@hypequery/protocol';
15
15
  import type { AnyDatasetInstance, DatasetCachePolicy, MetricHandle } from './types.js';
16
+ import { type UnsupportedContractReason } from './utils/unsupported-contract-reasons.js';
17
+ export { UNSUPPORTED_CONTRACT_REASONS, type UnsupportedContractReason, } from './utils/unsupported-contract-reasons.js';
16
18
  /** A rebuilt dataset in the registry shape Serve, MCP, and the planner accept. */
17
19
  export type RehydratedDataset = AnyDatasetInstance & {
18
20
  readonly metrics: Readonly<Record<string, MetricHandle>>;
@@ -43,7 +45,9 @@ export interface RehydrateProtocolDatasetsOptions {
43
45
  export declare class UnsupportedContractFeatureError extends Error {
44
46
  readonly dataset: string;
45
47
  readonly feature: string;
46
- constructor(datasetName: string, feature: string, detail: string);
48
+ /** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
49
+ readonly reason: UnsupportedContractReason | undefined;
50
+ constructor(datasetName: string, feature: string, detail: string, reason?: UnsupportedContractReason);
47
51
  }
48
52
  /**
49
53
  * Rebuild every dataset in a validated deployment contract.
@@ -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,EAEvB,yBAAyB,EAM1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAMlB,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;AAyPD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,CAAC,uBAAuB,GAAG,yBAAyB,CAAC,EAAE,EAC3E,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAmF7C;AAED,gFAAgF;AAChF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAG7C"}
1
+ {"version":3,"file":"protocol-rehydrate.d.ts","sourceRoot":"","sources":["../src/protocol-rehydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,uBAAuB,EAEvB,yBAAyB,EAM1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAMlB,YAAY,EAIb,MAAM,YAAY,CAAC;AAMpB,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EACL,4BAA4B,EAC5B,KAAK,yBAAyB,GAC/B,MAAM,yCAAyC,CAAC;AAEjD,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;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;gBAGrD,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,yBAAyB;CAQrC;AAoQD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,CAAC,uBAAuB,GAAG,yBAAyB,CAAC,EAAE,EAC3E,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAwF7C;AAED,gFAAgF;AAChF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAG7C"}
@@ -17,6 +17,9 @@ import { snapshotSemanticMetadata } from './utils/semantic-metadata.js';
17
17
  import { withContractCapabilities } from './utils/protocol-metric-capabilities.js';
18
18
  import { rehydrateDerivedFormula } from './utils/protocol-rehydrate-derivation.js';
19
19
  import { rehydrateMeasureFilter } from './utils/protocol-rehydrate-filters.js';
20
+ import { PORTABLE_TIME_GRAINS } from './utils/portable-grains.js';
21
+ import { UNSUPPORTED_CONTRACT_REASONS, } from './utils/unsupported-contract-reasons.js';
22
+ export { UNSUPPORTED_CONTRACT_REASONS, } from './utils/unsupported-contract-reasons.js';
20
23
  /**
21
24
  * Thrown when a contract describes something portable execution cannot rebuild.
22
25
  *
@@ -26,11 +29,14 @@ import { rehydrateMeasureFilter } from './utils/protocol-rehydrate-filters.js';
26
29
  export class UnsupportedContractFeatureError extends Error {
27
30
  dataset;
28
31
  feature;
29
- constructor(datasetName, feature, detail) {
32
+ /** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
33
+ reason;
34
+ constructor(datasetName, feature, detail, reason) {
30
35
  super(`Cannot rebuild ${feature} on dataset "${datasetName}": ${detail}`);
31
36
  this.name = 'UnsupportedContractFeatureError';
32
37
  this.dataset = datasetName;
33
38
  this.feature = feature;
39
+ this.reason = reason;
34
40
  }
35
41
  }
36
42
  function rehydrateDimensions(contract) {
@@ -57,7 +63,7 @@ function rehydrateDimensions(contract) {
57
63
  return dimensions;
58
64
  }
59
65
  function rehydrateMeasure(datasetName, measure) {
60
- const filters = measure.filters.map((expression, index) => rehydrateMeasureFilter(expression, () => new UnsupportedContractFeatureError(datasetName, `measure "${String(measure.name)}"`, `fixed filter ${index} is not a field/operator/value comparison`)));
66
+ const filters = measure.filters.map((expression, index) => rehydrateMeasureFilter(expression, () => new UnsupportedContractFeatureError(datasetName, `measure "${String(measure.name)}"`, `fixed filter ${index} is not a field/operator/value comparison`, UNSUPPORTED_CONTRACT_REASONS.measureFilterNotComparison)));
61
67
  return {
62
68
  __type: 'measure_definition',
63
69
  ...snapshotSemanticMetadata(measure),
@@ -78,7 +84,7 @@ function rehydrateDerivedMeasure(datasetName, measure) {
78
84
  __type: 'derived_measure_definition',
79
85
  ...snapshotSemanticMetadata(measure),
80
86
  uses: Object.fromEntries(measure.uses.map(input => [String(input.alias), String(input.measure)])),
81
- formula: rehydrateDerivedFormula({ inputs: [], expression: measure.expression }, reason => new UnsupportedContractFeatureError(datasetName, `measure "${measure.name}"`, reason)),
87
+ formula: rehydrateDerivedFormula({ inputs: [], expression: measure.expression }, reason => new UnsupportedContractFeatureError(datasetName, `measure "${measure.name}"`, reason, UNSUPPORTED_CONTRACT_REASONS.unsupportedFormula)),
82
88
  ...(measure.label !== undefined ? { label: measure.label } : {}),
83
89
  ...(measure.description !== undefined ? { description: measure.description } : {}),
84
90
  };
@@ -139,12 +145,12 @@ function aggregationKey(value) {
139
145
  */
140
146
  function measureForAggregate(instance, contract, subject, expression) {
141
147
  if (expression.kind !== 'aggregate') {
142
- throw new UnsupportedContractFeatureError(instance.name, subject, `expected an aggregate expression, received "${expression.kind}"`);
148
+ throw new UnsupportedContractFeatureError(instance.name, subject, `expected an aggregate expression, received "${expression.kind}"`, UNSUPPORTED_CONTRACT_REASONS.expressionNotAggregate);
143
149
  }
144
150
  const field = String(expression.field);
145
151
  const candidates = contract.measures.filter(measure => (aggregationKey(measure) === aggregationKey(expression)));
146
152
  if (candidates.length === 0) {
147
- throw new UnsupportedContractFeatureError(instance.name, subject, `no declared measure matches ${expression.aggregation}(${field})`);
153
+ throw new UnsupportedContractFeatureError(instance.name, subject, `no declared measure matches ${expression.aggregation}(${field})`, UNSUPPORTED_CONTRACT_REASONS.noMatchingMeasure);
148
154
  }
149
155
  // A metric expression carries no raw SQL, so two measures that share an
150
156
  // aggregation identity but override SQL differently are indistinguishable in
@@ -153,7 +159,7 @@ function measureForAggregate(instance, contract, subject, expression) {
153
159
  if (distinctSql.size > 1) {
154
160
  throw new UnsupportedContractFeatureError(instance.name, subject, `${candidates.map(measure => `"${String(measure.name)}"`).join(' and ')} share `
155
161
  + `${expression.aggregation}(${field}) but emit different SQL, so the contract cannot `
156
- + 'say which one this metric was built from');
162
+ + 'say which one this metric was built from', UNSUPPORTED_CONTRACT_REASONS.ambiguousMeasureSql);
157
163
  }
158
164
  return String(candidates[0].name);
159
165
  }
@@ -164,7 +170,7 @@ function measureForAggregate(instance, contract, subject, expression) {
164
170
  * what both plan builders emit as the column of the intermediate aggregate.
165
171
  */
166
172
  function derivedMetricConfig(instance, contract, subject, derivation) {
167
- const unsupported = (reason) => new UnsupportedContractFeatureError(instance.name, subject, reason);
173
+ const unsupported = (reason) => new UnsupportedContractFeatureError(instance.name, subject, reason, UNSUPPORTED_CONTRACT_REASONS.unsupportedFormula);
168
174
  const uses = Object.fromEntries(derivation.inputs.map(input => {
169
175
  const alias = String(input.alias);
170
176
  return [
@@ -184,7 +190,7 @@ function rehydrateMetric(instance, contract, metric) {
184
190
  // The inlined expression states what a derived metric means but drops the
185
191
  // aliases its SQL is written in terms of. Without them a rebuild computes
186
192
  // the same number through different SQL, which decision 0005 excludes.
187
- throw new UnsupportedContractFeatureError(instance.name, subject, 'a derived metric requires its authored formula, which this contract does not carry');
193
+ throw new UnsupportedContractFeatureError(instance.name, subject, 'a derived metric requires its authored formula, which this contract does not carry', UNSUPPORTED_CONTRACT_REASONS.derivedMetricWithoutFormula);
188
194
  }
189
195
  const metadata = {
190
196
  ...snapshotSemanticMetadata(metric),
@@ -234,7 +240,7 @@ export function rehydrateProtocolDatasets(contracts, options = {}) {
234
240
  if (!instance) {
235
241
  // The deployment validator already rejects a dangling relationship, so
236
242
  // reaching this means the caller passed a partial contract.
237
- throw new UnsupportedContractFeatureError(target, 'relationship target', `dataset "${target}" is not part of the supplied contract`);
243
+ throw new UnsupportedContractFeatureError(target, 'relationship target', `dataset "${target}" is not part of the supplied contract`, UNSUPPORTED_CONTRACT_REASONS.relationshipTargetMissing);
238
244
  }
239
245
  return instance;
240
246
  };
@@ -251,7 +257,11 @@ export function rehydrateProtocolDatasets(contracts, options = {}) {
251
257
  ...(contract.defaults.dimensions !== undefined ? { dimensions: [...contract.defaults.dimensions] } : {}),
252
258
  } } : {}),
253
259
  ...(contract.tenant.kind === 'required' ? { tenantKey: contract.tenant.field } : {}),
254
- ...(contract.timeField !== undefined ? { timeKey: String(contract.timeField) } : {}),
260
+ // A published dataset supports only the grains its contract can carry,
261
+ // so its catalog never advertises a grain the portable path would refuse.
262
+ ...(contract.timeField !== undefined
263
+ ? { timeKey: String(contract.timeField), timeGrains: PORTABLE_TIME_GRAINS }
264
+ : {}),
255
265
  dimensions: rehydrateDimensions(contract),
256
266
  measures: Object.fromEntries([
257
267
  ...contract.measures.map(measure => [
@@ -27,12 +27,16 @@ export interface QueryBuilderLike {
27
27
  stddev?(column: string, alias?: string): QueryBuilderLike;
28
28
  /** Sample variance of `column`. */
29
29
  variance?(column: string, alias?: string): QueryBuilderLike;
30
+ /** Estimated number of distinct non-NULL values of `column`. */
31
+ approxCountDistinct?(column: string, alias?: string): QueryBuilderLike;
30
32
  where(column: string, operator: string, value: unknown): QueryBuilderLike;
31
33
  leftJoin(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
32
34
  /**
33
- * Optional single-match LEFT JOIN (ClickHouse `LEFT ANY JOIN`). When a
34
- * builder provides it, relationship joins use it so duplicate target join
35
- * keys cannot fan out aggregates; otherwise `leftJoin` is used.
35
+ * Single-match LEFT JOIN (ClickHouse `LEFT ANY JOIN`). Required to query
36
+ * relationship-qualified fields: duplicate target join keys cannot fan out
37
+ * aggregates. A builder without it can still run every query that does not
38
+ * traverse a relationship; one that does is rejected with a clear error
39
+ * instead of falling back to `leftJoin`.
36
40
  */
37
41
  leftAnyJoin?(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
38
42
  groupBy(columns: string | string[]): QueryBuilderLike;
@@ -1 +1 @@
1
- {"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAC;AAI9C,KAAK,YAAY,GAAG,kBAAkB,CAAC;AA6BvC,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCnD;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAgElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,iBAAiB,EAC7B,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,OAAO,EAAE,aAAa,EAAE,GAAG,SAAS,EACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAoBlB;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,YAAY,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAMpB"}
1
+ {"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAC;AAI9C,KAAK,YAAY,GAAG,kBAAkB,CAAC;AA6BvC,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCnD;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAqElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,iBAAiB,EAC7B,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,OAAO,EAAE,aAAa,EAAE,GAAG,SAAS,EACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAoBlB;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,YAAY,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAMpB"}
@@ -120,6 +120,11 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx) {
120
120
  }
121
121
  return qb.quantile(fieldOrExpr, spec.level, alias);
122
122
  }
123
+ case "approxCountDistinct":
124
+ if (!qb.approxCountDistinct) {
125
+ throw new Error('Query builder does not support approxCountDistinct aggregations.');
126
+ }
127
+ return qb.approxCountDistinct(fieldOrExpr, alias);
123
128
  case "stddev":
124
129
  if (!qb.stddev) {
125
130
  throw new Error('Query builder does not support stddev aggregations.');
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Verifies declared to-one relationships against the data.
3
+ *
4
+ * `belongsTo` and `hasOne` are declarations: nothing at query time proves the
5
+ * target join column is unique. Relationship joins are single-match, so a
6
+ * duplicate key cannot inflate an aggregate, but the join then takes an
7
+ * arbitrary one of the matching rows and grouped values drift without any
8
+ * error. `checkRelationships` counts rows and distinct keys on each target so a
9
+ * mis-declaration is caught in CI or at deploy time rather than in a report.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const result = await checkRelationships(Orders, { queryBuilder: db });
14
+ * if (!result.ok) {
15
+ * throw new Error(result.issues.map((issue) => issue.message).join('\n'));
16
+ * }
17
+ * ```
18
+ */
19
+ import type { AnyDatasetInstance, ExecutionContext } from './types.js';
20
+ import { type QueryBuilderFactoryInput } from './query-builder-protocol.js';
21
+ import { type RelationshipKeyIssue } from './utils/relationship-key-check.js';
22
+ export type { RelationshipKeyIssue } from './utils/relationship-key-check.js';
23
+ export interface CheckRelationshipsOptions {
24
+ /** Query builder factory used to count target keys. */
25
+ queryBuilder: QueryBuilderFactoryInput;
26
+ /**
27
+ * Runtime context. A tenant-scoped target is checked within the runtime
28
+ * tenant, the same scope its join uses, so it requires tenant runtime.
29
+ */
30
+ context?: ExecutionContext;
31
+ /** Restrict the check to these to-one relationship names. */
32
+ relationships?: readonly string[];
33
+ }
34
+ export interface CheckRelationshipsResult {
35
+ /** True when every checked relationship has a unique target key. */
36
+ ok: boolean;
37
+ /** Relationship names that were checked. */
38
+ checked: string[];
39
+ issues: RelationshipKeyIssue[];
40
+ }
41
+ /**
42
+ * Checks that the target join column of each `belongsTo` and `hasOne`
43
+ * relationship on `ds` is unique. NULL keys are ignored because they never
44
+ * match a join. `hasMany` relationships are skipped.
45
+ */
46
+ export declare function checkRelationships(ds: AnyDatasetInstance, options: CheckRelationshipsOptions): Promise<CheckRelationshipsResult>;
47
+ //# sourceMappingURL=relationship-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationship-check.d.ts","sourceRoot":"","sources":["../src/relationship-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAyB,KAAK,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEnG,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAE9E,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,YAAY,EAAE,wBAAwB,CAAC;IACvC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,6DAA6D;IAC7D,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,EAAE,EAAE,OAAO,CAAC;IACZ,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAKD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAkCnC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Verifies declared to-one relationships against the data.
3
+ *
4
+ * `belongsTo` and `hasOne` are declarations: nothing at query time proves the
5
+ * target join column is unique. Relationship joins are single-match, so a
6
+ * duplicate key cannot inflate an aggregate, but the join then takes an
7
+ * arbitrary one of the matching rows and grouped values drift without any
8
+ * error. `checkRelationships` counts rows and distinct keys on each target so a
9
+ * mis-declaration is caught in CI or at deploy time rather than in a report.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const result = await checkRelationships(Orders, { queryBuilder: db });
14
+ * if (!result.ok) {
15
+ * throw new Error(result.issues.map((issue) => issue.message).join('\n'));
16
+ * }
17
+ * ```
18
+ */
19
+ import { toQueryBuilderFactory } from './query-builder-protocol.js';
20
+ import { getRuntimeTenantPredicate, validateTenantRuntime } from './utils/tenant-runtime.js';
21
+ import { listToOneRelationships, readCount, relationshipKeyIssue, } from './utils/relationship-key-check.js';
22
+ const ROWS_ALIAS = '__hq_rows';
23
+ const KEYS_ALIAS = '__hq_keys';
24
+ /**
25
+ * Checks that the target join column of each `belongsTo` and `hasOne`
26
+ * relationship on `ds` is unique. NULL keys are ignored because they never
27
+ * match a join. `hasMany` relationships are skipped.
28
+ */
29
+ export async function checkRelationships(ds, options) {
30
+ const factory = toQueryBuilderFactory(options.queryBuilder);
31
+ const tenantPredicate = getRuntimeTenantPredicate(options.context);
32
+ const entries = listToOneRelationships(ds, options.relationships);
33
+ const issues = [];
34
+ for (const entry of entries) {
35
+ const tenantError = validateTenantRuntime(entry.target, options.context);
36
+ if (tenantError) {
37
+ throw new Error(`Cannot check relationship "${entry.relationship}": ${tenantError}`);
38
+ }
39
+ let qb = factory
40
+ .table(entry.target.source)
41
+ .count(entry.column, ROWS_ALIAS)
42
+ .countDistinct(entry.column, KEYS_ALIAS);
43
+ if (entry.target.tenantKey && tenantPredicate) {
44
+ qb = qb.where(entry.target.tenantKey, tenantPredicate.operator, tenantPredicate.value);
45
+ }
46
+ const [row] = await qb.execute({
47
+ abortSignal: options.context?.abortSignal,
48
+ });
49
+ const issue = relationshipKeyIssue(entry, readCount(row?.[ROWS_ALIAS]), readCount(row?.[KEYS_ALIAS]));
50
+ if (issue) {
51
+ issues.push(issue);
52
+ }
53
+ }
54
+ return {
55
+ ok: issues.length === 0,
56
+ checked: entries.map((entry) => entry.relationship),
57
+ issues,
58
+ };
59
+ }