@hypequery/datasets 0.13.0 → 0.13.2

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":"query-signature.d.ts","sourceRoot":"","sources":["../../src/cache/query-signature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAGhB,WAAW,EACX,SAAS,EACV,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,CAAC;AA8C3B,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAiBR;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAkBR"}
1
+ {"version":3,"file":"query-signature.d.ts","sourceRoot":"","sources":["../../src/cache/query-signature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAGhB,WAAW,EACX,SAAS,EACV,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,CAAC;AAuE3B,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAiBR;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAkBR"}
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { getMetricGrain, getMetricRef } from '../utils/metric-handle.js';
15
15
  import { getRuntimeTenantPredicate } from '../utils/tenant-runtime.js';
16
+ import { buildRelationshipBuilderContext } from '../utils/relationship-builder-plan.js';
16
17
  import { stableStringify } from '../utils/canonical-json.js';
17
18
  export { stableStringify };
18
19
  const SIGNATURE_VERSION = 1;
@@ -39,15 +40,29 @@ function orderBySignature(orderBy) {
39
40
  }));
40
41
  }
41
42
  /**
42
- * Tenant portion of the key. Only datasets with a `tenantKey` apply the
43
- * runtime tenant predicate, so tenant-less datasets share entries across
44
- * callers while tenant-scoped datasets are strictly partitioned per scope.
43
+ * True when this query joins a tenant-scoped relationship target under an
44
+ * active runtime tenant, so the joined rows are filtered per tenant. Mirrors
45
+ * the executor's join planning (`buildRelationshipBuilderContext`).
45
46
  */
46
- function tenantSignature(ds, context) {
47
+ function activatesTenantScopedJoin(ds, query, context) {
48
+ const joinCtx = buildRelationshipBuilderContext(ds, query, context);
49
+ return !!joinCtx && joinCtx.joins.some((join) => join.tenant);
50
+ }
51
+ /**
52
+ * Tenant portion of the key. A dataset with a `tenantKey` is strictly
53
+ * partitioned per scope. A tenant-less dataset normally shares entries across
54
+ * callers — but if the query joins a tenant-scoped relationship target, those
55
+ * joined rows are still filtered by the runtime tenant, so the key must
56
+ * partition per tenant too or one tenant could be served another's cached rows.
57
+ */
58
+ function tenantSignature(ds, query, context) {
59
+ const predicate = getRuntimeTenantPredicate(context);
47
60
  if (!ds.tenantKey) {
61
+ if (predicate && activatesTenantScopedJoin(ds, query, context)) {
62
+ return { joinScoped: true, operator: predicate.operator, value: predicate.value };
63
+ }
48
64
  return null;
49
65
  }
50
- const predicate = getRuntimeTenantPredicate(context);
51
66
  if (!predicate) {
52
67
  // Trusted cross-tenant scope (`scope: 'all'`) or no runtime tenancy.
53
68
  return { key: ds.tenantKey, scope: 'all' };
@@ -68,7 +83,7 @@ export function buildDatasetQuerySignature(ds, query, context) {
68
83
  by: query.by ?? null,
69
84
  limit: query.limit ?? null,
70
85
  offset: query.offset ?? null,
71
- tenant: tenantSignature(ds, context),
86
+ tenant: tenantSignature(ds, query, context),
72
87
  scope: scopeSignature(context),
73
88
  });
74
89
  }
@@ -87,7 +102,7 @@ export function buildMetricQuerySignature(metric, query, context) {
87
102
  by: grain ?? null,
88
103
  limit: query.limit ?? null,
89
104
  offset: query.offset ?? null,
90
- tenant: tenantSignature(ref.dataset, context),
105
+ tenant: tenantSignature(ref.dataset, query, context),
91
106
  scope: scopeSignature(context),
92
107
  });
93
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAGhB,kBAAkB,EAClB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAEV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAgB7E,OAAO,EAIL,KAAK,4BAA4B,EAClC,MAAM,oBAAoB,CAAC;AAW5B,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AA6JzC,MAAM,WAAW,wBAAwB;IACvC,mDAAmD;IACnD,cAAc,EAAE,wBAAwB,CAAC;CAC1C;AAED,MAAM,WAAW,0BAA0B;IACzC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAC9B;AAWD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;AAE/E,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,cAAc,IACtD,OAAO,SAAS,kBAAkB,GAAG,YAAY,GAAG,WAAW,CAAC;AAElE,MAAM,MAAM,cAAc,CACxB,OAAO,SAAS,cAAc,EAC9B,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5B,OAAO,SAAS,kBAAkB,GAClC,kBAAkB,CAAC,IAAI,CAAC,GACxB,YAAY,CAAC,IAAI,CAAC,CAAC;AAEvB,KAAK,YAAY,CAAC,YAAY,SAAS,MAAM,GAAG,MAAM,IACpD,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC;AAE/C,KAAK,cAAc,CACjB,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,YAAY,CAAC,YAAY,CAAC,IACzC,SAAS,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AAExD,KAAK,qBAAqB,CACxB,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,YAAY,CAAC,YAAY,CAAC,IACzC,gBAAgB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,OAAO,CACL,QAAQ,SAAS,YAAY,EAC7B,KAAK,CAAC,MAAM,SAAS,eAAe,CAAC,QAAQ,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,EAE1E,MAAM,EAAE,QAAQ,EAChB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,OAAO,CACL,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,YAAY,CAAC,YAAY,CAAC,EAC3C,KAAK,CAAC,MAAM,SAAS,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,EAElG,MAAM,EAAE,cAAc,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,EAC3D,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,OAAO,CACL,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,YAAY,CAAC,YAAY,CAAC,EAC3C,KAAK,CAAC,MAAM,SAAS,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,EAElG,MAAM,EAAE,qBAAqB,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,EAClE,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,SAAS,cAAc,GAAG,cAAc,EACrF,MAAM,EAAE,OAAO,EACf,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1C,KAAK,CAAC,OAAO,SAAS,cAAc,EAClC,MAAM,EAAE,OAAO,EACf,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAAC;IACV,QAAQ,CAAC,OAAO,SAAS,cAAc,EACrC,MAAM,EAAE,OAAO,EACf,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAAC;IACpB,+DAA+D;IAC/D,aAAa,IAAI,kBAAkB,CAAC;IACpC;;;OAGG;IACH,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAChC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,cAAc,CAA0B;gBAEpC,OAAO,EAAE,wBAAwB;IAI7C,SAAS,CAAC,iBAAiB,IAAI,uBAAuB;IAItD;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,GAAE,WAAgB,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAW3B;;OAEG;IACH,KAAK,CACH,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,GAAE,WAAgB,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM;IAmBT;;OAEG;IACH,QAAQ,CACN,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB;YA+BL,aAAa;IAgC3B,OAAO,CAAC,cAAc;IAuDtB,OAAO,CAAC,yBAAyB;CA+GlC;AAED,qBAAa,iBAAkB,SAAQ,iBAAkB,YAAW,aAAa;IAC/E,OAAO,CAAC,OAAO,CAAC,CAAkB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAS;gBAEhC,OAAO,EAAE,0BAA0B;IAoB/C,aAAa,IAAI,kBAAkB;IAInC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAI9B;;;;OAIG;IACH,OAAO,CAAC,WAAW;IA0BnB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAUxB,UAAU,CACR,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,GAAE,WAAgB,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,QAAQ;IASX,WAAW,CACT,EAAE,EAAE,kBAAkB,EACtB,KAAK,GAAE,YAAiB,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,QAAQ;IAIX;;OAEG;IACH,OAAO,CACL,QAAQ,SAAS,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACpD,KAAK,CAAC,MAAM,SAAS,eAAe,CAAC,QAAQ,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,EAE1E,MAAM,EAAE,QAAQ,EAChB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,CACL,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,EAC7D,KAAK,CAAC,MAAM,SAAS,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,EAElG,MAAM,EAAE,SAAS,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,EAC3D,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,CACL,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,EAC1B,QAAQ,SAAS,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,EAC7D,KAAK,CAAC,MAAM,SAAS,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,EAElG,MAAM,EAAE,gBAAgB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,EAClE,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAqB1D,KAAK,CAAC,OAAO,SAAS,cAAc,EAClC,MAAM,EAAE,OAAO,EACf,KAAK,GAAE,aAAa,CAAC,OAAO,CAAgC,EAC5D,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM;IAQT,QAAQ,CAAC,OAAO,SAAS,cAAc,EACrC,MAAM,EAAE,OAAO,EACf,KAAK,GAAE,aAAa,CAAC,OAAO,CAAgC,EAC5D,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB;IAQnB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,cAAc;IAiCtB,OAAO,CAAC,YAAY;CAWrB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,aAAa,CAEtF;AAED,YAAY,EAAE,4BAA4B,EAAE,CAAC"}
package/dist/executor.js CHANGED
@@ -18,7 +18,7 @@ import { applyPagination, overfetchLimit } from './utils/pagination.js';
18
18
  import { SemanticQueryCache, } from './cache/semantic-query-cache.js';
19
19
  import { buildDatasetQuerySignature, buildMetricQuerySignature, } from './cache/query-signature.js';
20
20
  import { isQualifiedField, resolveQualifiedField } from './utils/relationship-fields.js';
21
- import { validateQualifiedFilter } from './utils/relationship-validation.js';
21
+ import { validateQualifiedFilter, validateRelationshipTenantRuntime, } from './utils/relationship-validation.js';
22
22
  import { applyRelationshipJoins, buildRelationshipBuilderContext, qualifyBaseColumn, } from './utils/relationship-builder-plan.js';
23
23
  function validateQuery(metric, query, context) {
24
24
  const errors = [];
@@ -38,6 +38,10 @@ function validateQuery(metric, query, context) {
38
38
  if (tenantRuntimeError) {
39
39
  errors.push(tenantRuntimeError);
40
40
  }
41
+ const relationshipTenantError = validateRelationshipTenantRuntime(ds, query, context);
42
+ if (relationshipTenantError) {
43
+ errors.push(relationshipTenantError);
44
+ }
41
45
  if (metric.__type === 'grained_metric_ref' && query.by && query.by !== metric.grain) {
42
46
  errors.push(`Metric "${ref.name}" is already grained by "${metric.grain}" and cannot be queried with by="${query.by}".`);
43
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dataset-query-validation.d.ts","sourceRoot":"","sources":["../../src/utils/dataset-query-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAY9E,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CA0JlB"}
1
+ {"version":3,"file":"dataset-query-validation.d.ts","sourceRoot":"","sources":["../../src/utils/dataset-query-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAe9E,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CA8JlB"}
@@ -2,7 +2,7 @@ import { validateFilterValue } from '../validation.js';
2
2
  import { SUPPORTED_TIME_GRAINS, isSupportedTimeGrain } from '../constants.js';
3
3
  import { getRuntimeTenantPredicate, validateTenantRuntime, } from './tenant-runtime.js';
4
4
  import { isQualifiedField, resolveQualifiedField, } from './relationship-fields.js';
5
- import { validateQualifiedFilter } from './relationship-validation.js';
5
+ import { validateQualifiedFilter, validateRelationshipTenantRuntime, } from './relationship-validation.js';
6
6
  export function validateDatasetQueryInput(ds, query, context) {
7
7
  const errors = [];
8
8
  const dimensionNames = Object.keys(ds.dimensions);
@@ -19,6 +19,10 @@ export function validateDatasetQueryInput(ds, query, context) {
19
19
  if (tenantRuntimeError) {
20
20
  errors.push(tenantRuntimeError);
21
21
  }
22
+ const relationshipTenantError = validateRelationshipTenantRuntime(ds, query, context);
23
+ if (relationshipTenantError) {
24
+ errors.push(relationshipTenantError);
25
+ }
22
26
  if (selectedDimensions.length === 0 && selectedMeasures.length === 0) {
23
27
  errors.push(`Dataset "${ds.name}" query must select at least one dimension or measure.`);
24
28
  }
@@ -2,7 +2,14 @@
2
2
  * Shared validation for relationship-qualified filters, used by both the
3
3
  * dataset-query and metric-query validators.
4
4
  */
5
- import type { AnyDatasetInstance, ExecutionContext, MetricFilter } from '../types.js';
5
+ import type { AnyDatasetInstance, DatasetQuery, ExecutionContext, MetricFilter, MetricQuery } from '../types.js';
6
+ type RelationshipQuery = Pick<DatasetQuery & MetricQuery, 'dimensions' | 'filters' | 'orderBy'>;
7
+ /**
8
+ * Tenant-less base datasets may still reach tenant-scoped data through a
9
+ * relationship. Require either a concrete runtime tenant or the trusted
10
+ * cross-tenant scope whenever a query activates such a join.
11
+ */
12
+ export declare function validateRelationshipTenantRuntime(ds: AnyDatasetInstance, query: RelationshipQuery, context?: ExecutionContext): string | undefined;
6
13
  /**
7
14
  * Validates a relationship-qualified filter (`relationship.field`). Returns an
8
15
  * error message string, or null when the filter is valid.
@@ -12,4 +19,5 @@ import type { AnyDatasetInstance, ExecutionContext, MetricFilter } from '../type
12
19
  * that column is rejected (the planner injects the tenant predicate instead).
13
20
  */
14
21
  export declare function validateQualifiedFilter(ds: AnyDatasetInstance, filter: MetricFilter, context?: ExecutionContext): string | null;
22
+ export {};
15
23
  //# sourceMappingURL=relationship-validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"relationship-validation.d.ts","sourceRoot":"","sources":["../../src/utils/relationship-validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACb,MAAM,aAAa,CAAC;AAKrB;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,IAAI,CAgBf"}
1
+ {"version":3,"file":"relationship-validation.d.ts","sourceRoot":"","sources":["../../src/utils/relationship-validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACZ,MAAM,aAAa,CAAC;AAWrB,KAAK,iBAAiB,GAAG,IAAI,CAC3B,YAAY,GAAG,WAAW,EAC1B,YAAY,GAAG,SAAS,GAAG,SAAS,CACrC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,iBAAiB,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAmBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,IAAI,CAgBf"}
@@ -3,8 +3,30 @@
3
3
  * dataset-query and metric-query validators.
4
4
  */
5
5
  import { validateFilterValue } from '../validation.js';
6
- import { getRuntimeTenantPredicate } from './tenant-runtime.js';
7
- import { resolveQualifiedField } from './relationship-fields.js';
6
+ import { getRuntimeTenantPredicate, hasTenantRuntime, } from './tenant-runtime.js';
7
+ import { isQualifiedField, resolveQualifiedField, } from './relationship-fields.js';
8
+ /**
9
+ * Tenant-less base datasets may still reach tenant-scoped data through a
10
+ * relationship. Require either a concrete runtime tenant or the trusted
11
+ * cross-tenant scope whenever a query activates such a join.
12
+ */
13
+ export function validateRelationshipTenantRuntime(ds, query, context) {
14
+ if (ds.tenantKey || hasTenantRuntime(context)) {
15
+ return undefined;
16
+ }
17
+ const referenced = [
18
+ ...(query.dimensions ?? []),
19
+ ...(query.filters ?? []).map((filter) => filter.field),
20
+ ...(query.orderBy ?? []).map((order) => order.field),
21
+ ].filter(isQualifiedField);
22
+ for (const name of referenced) {
23
+ const resolution = resolveQualifiedField(ds, name);
24
+ if (resolution?.resolved?.target.tenantKey) {
25
+ return `Dataset "${ds.name}" requires runtime tenant scoping because relationship "${resolution.resolved.relationshipName}" targets a tenant-scoped dataset.`;
26
+ }
27
+ }
28
+ return undefined;
29
+ }
8
30
  /**
9
31
  * Validates a relationship-qualified filter (`relationship.field`). Returns an
10
32
  * error message string, or null when the filter is valid.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/datasets",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "Semantic layer for defining datasets, metrics, and semantic queries",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "dist"
30
30
  ],
31
31
  "dependencies": {
32
- "@hypequery/protocol": "^0.9.0",
32
+ "@hypequery/protocol": "^0.10.0",
33
33
  "@noble/hashes": "^1.8.0",
34
34
  "zod": "^3.22.4"
35
35
  },
@@ -37,7 +37,8 @@
37
37
  "@types/node": "^18.19.80",
38
38
  "typescript": "^5.7.3",
39
39
  "@vitest/coverage-v8": "^3.2.6",
40
- "vitest": "^3.2.6"
40
+ "vitest": "^3.2.6",
41
+ "@hypequery/protocol-conformance": "^0.9.1"
41
42
  },
42
43
  "repository": {
43
44
  "type": "git",