@hypequery/datasets 0.25.0 → 0.26.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.
@@ -1 +1 @@
1
- {"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AAGA,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;AAmFD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,mCAAwC,GAChD,uBAAuB,CAqIzB"}
1
+ {"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AAGA,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;AAmFD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,mCAAwC,GAChD,uBAAuB,CAsIzB"}
@@ -5,7 +5,7 @@ import { parseProtocolIdentifier, parseProtocolQualifiedIdentifier, validateProt
5
5
  import { SEMANTIC_FILTER_OPERATORS } from './constants.js';
6
6
  import { toProtocolSemanticMetadata } from './utils/protocol-semantic-metadata.js';
7
7
  import { assertPublishableTimeGrains, isPortableTimeGrain, requirePortableTimeGrain } from './utils/portable-grains.js';
8
- import { requirePortableAggregation } from './utils/portable-aggregations.js';
8
+ import { requirePublishableMeasureAggregation } from './utils/portable-aggregations.js';
9
9
  import { assertNoPublishedSegments } from './utils/segments.js';
10
10
  function fieldSchema(type) {
11
11
  switch (type) {
@@ -131,8 +131,9 @@ export function buildProtocolDatasetContract(dataset, options = {}) {
131
131
  })).sort(byName),
132
132
  measures: Object.entries(baseMeasures).map(([name, measure]) => ({
133
133
  name,
134
- aggregation: requirePortableAggregation(measure.aggregation, `Measure "${dataset.name}.${name}"`),
134
+ aggregation: requirePublishableMeasureAggregation(measure.aggregation, `Measure "${dataset.name}.${name}"`),
135
135
  field: measure.field,
136
+ ...(measure.stateFunction !== undefined ? { stateFunction: measure.stateFunction } : {}),
136
137
  ...(measure.argField !== undefined ? { argField: measure.argField } : {}),
137
138
  ...(measure.level !== undefined ? { level: measure.level } : {}),
138
139
  ...(measure.sql !== undefined
@@ -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;AAOpB,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;AA8QD;;;;;;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,CAyF7C;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;AAOpB,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;AA+QD;;;;;;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,CAyF7C;AAED,gFAAgF;AAChF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAG7C"}
@@ -70,6 +70,7 @@ function rehydrateMeasure(datasetName, measure) {
70
70
  ...snapshotSemanticMetadata(measure),
71
71
  aggregation: measure.aggregation,
72
72
  field: String(measure.field),
73
+ ...(measure.stateFunction !== undefined ? { stateFunction: measure.stateFunction } : {}),
73
74
  ...(measure.argField !== undefined ? { argField: String(measure.argField) } : {}),
74
75
  ...(measure.level !== undefined ? { level: measure.level } : {}),
75
76
  ...(measure.sql !== undefined
@@ -11,9 +11,10 @@
11
11
  * cannot read back from the column type. The name is interpolated into SQL, so
12
12
  * it must come from this list.
13
13
  */
14
+ import { type ProtocolAggregateStateFunction } from '@hypequery/protocol';
14
15
  import type { MeasureDefinition } from '../types.js';
15
16
  export declare const AGGREGATE_STATE_FUNCTIONS: readonly ["uniq", "uniqExact", "uniqCombined", "uniqCombined64", "uniqHLL12", "uniqTheta", "count", "sum", "avg", "min", "max", "any", "anyLast", "groupBitmap"];
16
- export type AggregateStateFunction = (typeof AGGREGATE_STATE_FUNCTIONS)[number];
17
+ export type AggregateStateFunction = ProtocolAggregateStateFunction;
17
18
  export declare function isAggregateStateFunction(value: unknown): value is AggregateStateFunction;
18
19
  /** Throws unless `value` is a supported state function; `owner` names the measure. */
19
20
  export declare function assertAggregateStateFunction(value: unknown, owner: string): asserts value is AggregateStateFunction;
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-state-functions.d.ts","sourceRoot":"","sources":["../../src/utils/aggregate-state-functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,yBAAyB,kKAe5B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAchF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED,sFAAsF;AACtF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,sBAAsB,CAOnH;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElG;AAED,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAErF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,eAAe,CAAC,GAAG,OAAO,CAI/G"}
1
+ {"version":3,"file":"aggregate-state-functions.d.ts","sourceRoot":"","sources":["../../src/utils/aggregate-state-functions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAGL,KAAK,8BAA8B,EACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,eAAO,MAAM,yBAAyB,kKAAqC,CAAC;AAE5E,MAAM,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AAYpE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED,sFAAsF;AACtF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,sBAAsB,CAOnH;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElG;AAED,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAErF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,eAAe,CAAC,GAAG,OAAO,CAI/G"}
@@ -11,27 +11,13 @@
11
11
  * cannot read back from the column type. The name is interpolated into SQL, so
12
12
  * it must come from this list.
13
13
  */
14
- export const AGGREGATE_STATE_FUNCTIONS = [
15
- 'uniq',
16
- 'uniqExact',
17
- 'uniqCombined',
18
- 'uniqCombined64',
19
- 'uniqHLL12',
20
- 'uniqTheta',
21
- 'count',
22
- 'sum',
23
- 'avg',
24
- 'min',
25
- 'max',
26
- 'any',
27
- 'anyLast',
28
- 'groupBitmap',
29
- ];
14
+ import { PROTOCOL_AGGREGATE_STATE_FUNCTIONS, PROTOCOL_APPROXIMATE_STATE_FUNCTIONS, } from '@hypequery/protocol';
15
+ // One list, shared with the deployment contract (RFC 0022), so what can be
16
+ // authored is exactly what can be published.
17
+ export const AGGREGATE_STATE_FUNCTIONS = PROTOCOL_AGGREGATE_STATE_FUNCTIONS;
30
18
  const STATE_FUNCTIONS = new Set(AGGREGATE_STATE_FUNCTIONS);
31
19
  /** States whose merged value is an estimate. */
32
- const APPROXIMATE_STATE_FUNCTIONS = new Set([
33
- 'uniq', 'uniqCombined', 'uniqCombined64', 'uniqHLL12', 'uniqTheta',
34
- ]);
20
+ const APPROXIMATE_STATE_FUNCTIONS = new Set(PROTOCOL_APPROXIMATE_STATE_FUNCTIONS);
35
21
  /** States whose merged value is a count: 0, not NULL, over an empty population. */
36
22
  const COUNT_STATE_FUNCTIONS = new Set([
37
23
  'uniq', 'uniqExact', 'uniqCombined', 'uniqCombined64', 'uniqHLL12', 'uniqTheta', 'count', 'groupBitmap',
@@ -4,12 +4,15 @@
4
4
  * `approxCountDistinct` runs locally, but it is an expression extension 2 and
5
5
  * deployment contract 3 feature (RFC 0015). Publishing emits contract 2 until
6
6
  * it can emit contract 3, so it refuses the measure with an error naming it.
7
- * `merge` reads ClickHouse aggregate-state columns and has no contract form.
7
+ * `merge` is a deployment measure with its state function (RFC 0022), but the
8
+ * expression grammar has no merge aggregate, so a metric over one is refused.
8
9
  */
9
- import type { ProtocolAggregation } from '@hypequery/protocol';
10
+ import type { ProtocolAggregation, ProtocolDatasetMeasure } from '@hypequery/protocol';
10
11
  import type { AggregationType } from '../types.js';
11
12
  type PortableAggregation = Exclude<ProtocolAggregation, 'approxCountDistinct'>;
12
- /** Returns `aggregation` when publishing can carry it; otherwise throws naming `owner`. */
13
+ /** A dataset measure's aggregation as the contract carries it; otherwise throws naming `owner`. */
14
+ export declare function requirePublishableMeasureAggregation(aggregation: AggregationType, owner: string): ProtocolDatasetMeasure['aggregation'];
15
+ /** Returns `aggregation` when an expression can carry it; otherwise throws naming `owner`. */
13
16
  export declare function requirePortableAggregation(aggregation: AggregationType, owner: string): PortableAggregation;
14
17
  export {};
15
18
  //# sourceMappingURL=portable-aggregations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"portable-aggregations.d.ts","sourceRoot":"","sources":["../../src/utils/portable-aggregations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC;AAE/E,2FAA2F;AAC3F,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,eAAe,EAC5B,KAAK,EAAE,MAAM,GACZ,mBAAmB,CAcrB"}
1
+ {"version":3,"file":"portable-aggregations.d.ts","sourceRoot":"","sources":["../../src/utils/portable-aggregations.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC;AAc/E,mGAAmG;AACnG,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,eAAe,EAC5B,KAAK,EAAE,MAAM,GACZ,sBAAsB,CAAC,aAAa,CAAC,CAGvC;AAED,8FAA8F;AAC9F,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,eAAe,EAC5B,KAAK,EAAE,MAAM,GACZ,mBAAmB,CASrB"}
@@ -4,17 +4,26 @@
4
4
  * `approxCountDistinct` runs locally, but it is an expression extension 2 and
5
5
  * deployment contract 3 feature (RFC 0015). Publishing emits contract 2 until
6
6
  * it can emit contract 3, so it refuses the measure with an error naming it.
7
- * `merge` reads ClickHouse aggregate-state columns and has no contract form.
7
+ * `merge` is a deployment measure with its state function (RFC 0022), but the
8
+ * expression grammar has no merge aggregate, so a metric over one is refused.
8
9
  */
9
- /** Returns `aggregation` when publishing can carry it; otherwise throws naming `owner`. */
10
- export function requirePortableAggregation(aggregation, owner) {
11
- if (aggregation === 'merge') {
12
- throw new Error(`${owner} uses merge, which cannot be published: the deployment contract has no aggregate-state ` +
13
- 'measures. Use it for local queries only.');
14
- }
10
+ function refuseApproximate(aggregation, owner) {
15
11
  if (aggregation === 'approxCountDistinct') {
16
12
  throw new Error(`${owner} uses approxCountDistinct, which cannot be published yet: approximate aggregations ` +
17
13
  'need deployment contract 3 (RFC 0015). Use it for local queries, or publish countDistinct instead.');
18
14
  }
15
+ }
16
+ /** A dataset measure's aggregation as the contract carries it; otherwise throws naming `owner`. */
17
+ export function requirePublishableMeasureAggregation(aggregation, owner) {
18
+ refuseApproximate(aggregation, owner);
19
+ return aggregation;
20
+ }
21
+ /** Returns `aggregation` when an expression can carry it; otherwise throws naming `owner`. */
22
+ export function requirePortableAggregation(aggregation, owner) {
23
+ if (aggregation === 'merge') {
24
+ throw new Error(`${owner} uses merge, which a published metric cannot express: the expression grammar has no ` +
25
+ 'aggregate-state merge. Publish the merge measure itself and query it, or use it for local queries only.');
26
+ }
27
+ refuseApproximate(aggregation, owner);
19
28
  return aggregation;
20
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/datasets",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Code-first TypeScript semantic layer for ClickHouse datasets, metrics, multi-tenancy, and AI agents",
5
5
  "keywords": [
6
6
  "semantic-layer",
@@ -55,7 +55,7 @@
55
55
  "!dist/**/type-tests/**"
56
56
  ],
57
57
  "dependencies": {
58
- "@hypequery/protocol": "^0.22.0",
58
+ "@hypequery/protocol": "^0.23.0",
59
59
  "@noble/hashes": "^2.4.0",
60
60
  "zod": "^4.6.6",
61
61
  "zod-to-json-schema": "^3.25.2"
@@ -73,7 +73,7 @@
73
73
  "typescript": "^6.0.3",
74
74
  "@vitest/coverage-v8": "^5.0.5",
75
75
  "vitest": "^5.0.5",
76
- "@hypequery/protocol-conformance": "^0.16.1"
76
+ "@hypequery/protocol-conformance": "^0.16.2"
77
77
  },
78
78
  "repository": {
79
79
  "type": "git",