@objectstack/service-analytics 10.0.0 → 10.3.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.cjs +24 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +24 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -221,6 +221,14 @@ interface AnalyticsServiceConfig {
|
|
|
221
221
|
* `StrategyContext.coerceTemporalFilterValue` for the full rationale.
|
|
222
222
|
*/
|
|
223
223
|
coerceTemporalFilterValue?: (objectName: string, fieldName: string, value: unknown) => unknown;
|
|
224
|
+
/**
|
|
225
|
+
* ADR-0062 D6 — report whether an object is federated (external datasource).
|
|
226
|
+
* Threaded into the StrategyContext so `NativeSQLStrategy` declines external
|
|
227
|
+
* objects (which it would otherwise query against the wrong physical table),
|
|
228
|
+
* routing them to the driver-correct ObjectQL aggregate path instead. See
|
|
229
|
+
* `StrategyContext.isExternalObject`.
|
|
230
|
+
*/
|
|
231
|
+
isExternalObject?: (objectName: string) => boolean;
|
|
224
232
|
/**
|
|
225
233
|
* ADR-0021 — optional object-graph resolver used when compiling datasets:
|
|
226
234
|
* `(baseObject, relationshipName) => relatedObjectName | undefined`. When
|
package/dist/index.d.ts
CHANGED
|
@@ -221,6 +221,14 @@ interface AnalyticsServiceConfig {
|
|
|
221
221
|
* `StrategyContext.coerceTemporalFilterValue` for the full rationale.
|
|
222
222
|
*/
|
|
223
223
|
coerceTemporalFilterValue?: (objectName: string, fieldName: string, value: unknown) => unknown;
|
|
224
|
+
/**
|
|
225
|
+
* ADR-0062 D6 — report whether an object is federated (external datasource).
|
|
226
|
+
* Threaded into the StrategyContext so `NativeSQLStrategy` declines external
|
|
227
|
+
* objects (which it would otherwise query against the wrong physical table),
|
|
228
|
+
* routing them to the driver-correct ObjectQL aggregate path instead. See
|
|
229
|
+
* `StrategyContext.isExternalObject`.
|
|
230
|
+
*/
|
|
231
|
+
isExternalObject?: (objectName: string) => boolean;
|
|
224
232
|
/**
|
|
225
233
|
* ADR-0021 — optional object-graph resolver used when compiling datasets:
|
|
226
234
|
* `(baseObject, relationshipName) => relatedObjectName | undefined`. When
|
package/dist/index.js
CHANGED
|
@@ -320,6 +320,17 @@ var NativeSQLStrategy = class {
|
|
|
320
320
|
canHandle(query, ctx) {
|
|
321
321
|
if (!query.cube) return false;
|
|
322
322
|
if (query.timeDimensions?.some((td) => !!td.granularity)) return false;
|
|
323
|
+
if (typeof ctx.isExternalObject === "function") {
|
|
324
|
+
const cube = ctx.getCube(query.cube);
|
|
325
|
+
if (cube) {
|
|
326
|
+
if (ctx.isExternalObject(this.extractObjectName(cube))) return false;
|
|
327
|
+
const joinTargets = cube.joins ? Object.values(cube.joins) : [];
|
|
328
|
+
for (const j of joinTargets) {
|
|
329
|
+
const joinedObject = j?.name;
|
|
330
|
+
if (joinedObject && ctx.isExternalObject(joinedObject)) return false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
323
334
|
const caps = ctx.queryCapabilities(query.cube);
|
|
324
335
|
return caps.nativeSql && typeof ctx.executeRawSql === "function";
|
|
325
336
|
}
|
|
@@ -1477,7 +1488,8 @@ var AnalyticsService = class {
|
|
|
1477
1488
|
// Prefer a compiled dataset's declared relationships (D-C join allowlist);
|
|
1478
1489
|
// fall back to any explicitly-configured provider for legacy cubes.
|
|
1479
1490
|
getAllowedRelationships: (cubeName) => this.datasetRegistry.get(cubeName)?.allowedRelationships ?? config.getAllowedRelationships?.(cubeName),
|
|
1480
|
-
coerceTemporalFilterValue: config.coerceTemporalFilterValue
|
|
1491
|
+
coerceTemporalFilterValue: config.coerceTemporalFilterValue,
|
|
1492
|
+
isExternalObject: config.isExternalObject
|
|
1481
1493
|
};
|
|
1482
1494
|
const builtIn = [
|
|
1483
1495
|
new NativeSQLStrategy(),
|
|
@@ -1745,9 +1757,10 @@ var AnalyticsService = class {
|
|
|
1745
1757
|
if (!cube) {
|
|
1746
1758
|
cube = this.inferCubeFromQuery(query);
|
|
1747
1759
|
this.cubeRegistry.register(cube);
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
);
|
|
1760
|
+
const isScalarMetric = (query.dimensions?.length ?? 0) === 0 && (query.timeDimensions?.length ?? 0) === 0;
|
|
1761
|
+
const message = `[Analytics] No cube registered for "${name}"; auto-inferred a minimal cube (sql="${name}", measures=${Object.keys(cube.measures).join(",") || "(none)"}, dimensions=${Object.keys(cube.dimensions).join(",") || "(none)"}). Define an explicit Cube in your stack for full control.`;
|
|
1762
|
+
if (isScalarMetric) this.logger.debug(message);
|
|
1763
|
+
else this.logger.warn(message);
|
|
1751
1764
|
return;
|
|
1752
1765
|
}
|
|
1753
1766
|
const stripPrefix = (m) => m.includes(".") ? m.split(".").slice(1).join(".") : m;
|
|
@@ -2082,6 +2095,13 @@ var AnalyticsServicePlugin = class {
|
|
|
2082
2095
|
const f = dataEngine()?.getObject?.(object)?.fields?.[field];
|
|
2083
2096
|
return f ? { type: f.type, defaultCurrency: f.currencyConfig?.defaultCurrency } : void 0;
|
|
2084
2097
|
},
|
|
2098
|
+
// ADR-0062 D6 — a federated object carries an `external` block (ADR-0015).
|
|
2099
|
+
// Reported so NativeSQLStrategy declines it (its hand-compiled FROM would
|
|
2100
|
+
// hit the wrong physical table) and the driver-correct ObjectQL path runs.
|
|
2101
|
+
isExternalObject: (objectName) => {
|
|
2102
|
+
const obj = dataEngine()?.getObject?.(objectName);
|
|
2103
|
+
return !!(obj && obj.external != null);
|
|
2104
|
+
},
|
|
2085
2105
|
draftRowsResolver
|
|
2086
2106
|
};
|
|
2087
2107
|
if (autoBridgedReadScope) {
|