semanticdb-v2 2.0.0-alpha.10 → 2.0.0-alpha.12

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 (80) hide show
  1. package/README.md +39 -15
  2. package/dist/cache/types.d.ts +2 -1
  3. package/dist/compiler/compile-computation.d.ts +6 -0
  4. package/dist/compiler/compile-source.d.ts +5 -0
  5. package/dist/executor/component-properties.d.ts +22 -0
  6. package/dist/executor/components.d.ts +7 -3
  7. package/dist/executor/execute-query.d.ts +1 -0
  8. package/dist/executor/execute.d.ts +1 -1
  9. package/dist/executor/federated-execution.d.ts +2 -1
  10. package/dist/executor/fetch-entities.d.ts +2 -2
  11. package/dist/executor/index.d.ts +1 -1
  12. package/dist/executor/merge-by-id.d.ts +3 -0
  13. package/dist/executor/partition.d.ts +18 -0
  14. package/dist/executor/random-data.d.ts +5 -0
  15. package/dist/executor/result-hydrator/entity-fetch-conditions.d.ts +4 -0
  16. package/dist/executor/result-hydrator/index.d.ts +1 -0
  17. package/dist/executor/result-hydrator/types.d.ts +7 -0
  18. package/dist/executor/runtime-execution.d.ts +6 -0
  19. package/dist/executor/sample.d.ts +6 -0
  20. package/dist/executor/types.d.ts +23 -13
  21. package/dist/file-import/index.d.ts +2 -0
  22. package/dist/file-import/read-file.d.ts +2 -0
  23. package/dist/file-import/types.d.ts +31 -0
  24. package/dist/index.d.ts +11 -6
  25. package/dist/logicform/dimensions.d.ts +16 -0
  26. package/dist/logicform/index.d.ts +2 -0
  27. package/dist/logicform-types.d.ts +22 -2
  28. package/dist/normalizer/core.d.ts +8 -1
  29. package/dist/normalizer/index.d.ts +1 -0
  30. package/dist/normalizer/main-time-range.d.ts +9 -0
  31. package/dist/normalizer/public-logicform.d.ts +14 -0
  32. package/dist/normalizer/query.d.ts +3 -2
  33. package/dist/normalizer/random-data.d.ts +2 -0
  34. package/dist/operators/builtins/period-name.d.ts +3 -0
  35. package/dist/operators/builtins/time-range.d.ts +2 -2
  36. package/dist/operators/formula-text.d.ts +10 -0
  37. package/dist/operators/index.d.ts +2 -1
  38. package/dist/operators/registry.d.ts +8 -1
  39. package/dist/operators/types.d.ts +115 -25
  40. package/dist/permissions/index.d.ts +2 -1
  41. package/dist/permissions/metric-permissions.d.ts +9 -0
  42. package/dist/permissions/permissions.d.ts +4 -3
  43. package/dist/permissions/types.d.ts +5 -0
  44. package/dist/physical/connection.d.ts +4 -0
  45. package/dist/physical/db-connector.d.ts +10 -0
  46. package/dist/physical/duckdb-coordinator-provider.d.ts +3 -23
  47. package/dist/physical/duckdb-dataset.d.ts +23 -0
  48. package/dist/physical/duckdb-provider.d.ts +26 -0
  49. package/dist/physical/duckdb-sql.d.ts +33 -0
  50. package/dist/physical/import-types.d.ts +23 -0
  51. package/dist/physical/import-validation.d.ts +14 -0
  52. package/dist/physical/index.d.ts +4 -0
  53. package/dist/physical/postgresql-provider.d.ts +1 -0
  54. package/dist/physical/provider.d.ts +4 -0
  55. package/dist/planner/build-lineage.d.ts +1 -1
  56. package/dist/planner/create-logical-plan.d.ts +15 -2
  57. package/dist/planner/index.d.ts +3 -2
  58. package/dist/planner/mapping-granularity.d.ts +1 -1
  59. package/dist/planner/materialize-computations.d.ts +3 -0
  60. package/dist/planner/select-schema-mapping.d.ts +16 -1
  61. package/dist/planner/types.d.ts +52 -9
  62. package/dist/planner/udf-inputs.d.ts +6 -0
  63. package/dist/plugins/types.d.ts +4 -2
  64. package/dist/schema/index.d.ts +1 -0
  65. package/dist/schema/relation-keys.d.ts +11 -0
  66. package/dist/schema-mappings/computations.d.ts +3 -0
  67. package/dist/schema-mappings/index.d.ts +5 -1
  68. package/dist/schema-mappings/registry.d.ts +1 -0
  69. package/dist/schema-mappings/source.d.ts +11 -0
  70. package/dist/schema-mappings/sql-inputs.d.ts +7 -0
  71. package/dist/schema-mappings/supported-dimensions.d.ts +10 -0
  72. package/dist/schema-mappings/types.d.ts +107 -15
  73. package/dist/schema-mappings/yiask.d.ts +6 -18
  74. package/dist/semantic-types/index.d.ts +1 -1
  75. package/dist/semantic-types/types.d.ts +50 -2
  76. package/dist/semanticdb.esm.js +6 -5
  77. package/dist/semanticdb.js +6 -5
  78. package/dist/utils/format-date.d.ts +3 -0
  79. package/package.json +5 -3
  80. package/dist/executor/evaluate.d.ts +0 -4
@@ -0,0 +1,14 @@
1
+ import type { LogicformType } from '../logicform-types';
2
+ import type { ResolvedSemanticSchema } from '../semantic-types/index';
3
+ /**
4
+ * The planner uses canonical relation paths (for example `customer_name`),
5
+ * while a LogicForm exposed to an application keeps the relation structure
6
+ * that the caller wrote. This is the public view of a normalized form.
7
+ *
8
+ * This conversion deliberately only changes relation paths. Scalar values,
9
+ * temporal bounds, generated predicates and operator arguments remain the
10
+ * values produced by the normalizer.
11
+ */
12
+ type SchemaResolver = (schemaId: string) => ResolvedSemanticSchema;
13
+ export declare const expandPublicLogicform: (logicform: LogicformType, schema: ResolvedSemanticSchema, resolveSchema?: SchemaResolver, source?: LogicformType) => LogicformType;
14
+ export {};
@@ -1,5 +1,6 @@
1
1
  import type { ResolvedSemanticSchema } from '../semantic-types/index';
2
2
  import type { LogicformType } from '../logicform-types';
3
3
  import type { NormalizeLogicformOptions } from './core';
4
- export declare const normalizeQueryObject: (query: Readonly<Record<string, unknown>>, schema: ResolvedSemanticSchema, options: NormalizeLogicformOptions) => Promise<Readonly<Record<string, unknown>>>;
5
- export declare const normalizeQuery: (query: LogicformType["query"], schema: ResolvedSemanticSchema, options: NormalizeLogicformOptions) => Promise<LogicformType["query"]>;
4
+ import type { MainTimeRangeCollector } from './main-time-range';
5
+ export declare const normalizeQueryObject: (query: Readonly<Record<string, unknown>>, schema: ResolvedSemanticSchema, options: NormalizeLogicformOptions, timeRange?: MainTimeRangeCollector, queryPath?: readonly (string | number)[]) => Promise<Readonly<Record<string, unknown>>>;
6
+ export declare const normalizeQuery: (query: LogicformType["query"], schema: ResolvedSemanticSchema, options: NormalizeLogicformOptions, timeRange?: MainTimeRangeCollector) => Promise<LogicformType["query"]>;
@@ -0,0 +1,2 @@
1
+ import type { LogicformRandomDataType } from '../logicform-types';
2
+ export declare const normalizeRandomData: (value: unknown, allowed?: boolean) => LogicformRandomDataType | undefined;
@@ -1,2 +1,5 @@
1
1
  import type { LocaleTranslate } from '../../i18n/index';
2
+ import type { OperatorFormulaTextContext } from '../types';
3
+ /** Describe the target period, rather than serializing the period-shift wire protocol. */
4
+ export declare const periodShiftFormulaText: ({ input, args }: OperatorFormulaTextContext) => string;
2
5
  export declare const periodComparisonName: (args: Readonly<Record<string, unknown>>, locale: string, t?: LocaleTranslate) => string;
@@ -8,6 +8,6 @@ export interface ResolvedTimeRange {
8
8
  readonly queryWithoutTime?: QueryType;
9
9
  }
10
10
  export declare const requireTimestampProperty: (schema: ResolvedSemanticSchema, operator: string) => ResolvedSemanticProperty;
11
- export declare const resolveTimeRange: (query: QueryType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string) => ResolvedTimeRange;
12
- export declare const resolvePredTimeRange: (logicformQuery: QueryType | undefined, pred: PredItemType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string) => ResolvedTimeRange;
11
+ export declare const resolveTimeRange: (query: QueryType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string, defaultBoundary?: string | number | Date) => ResolvedTimeRange;
12
+ export declare const resolvePredTimeRange: (logicformQuery: QueryType | undefined, pred: PredItemType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string, defaultBoundary?: string | number | Date) => ResolvedTimeRange;
13
13
  export declare const withTimeCondition: (query: QueryType | undefined, propertyName: string, condition: unknown) => QueryType;
@@ -0,0 +1,10 @@
1
+ import type { OperatorDefinition, OperatorFormulaTextContext } from './types';
2
+ /** Keep arbitrary custom/SQL expressions grouped when another operator consumes them. */
3
+ export declare function groupFormulaText(formula: string): string;
4
+ export declare function groupFormulaText(formula: string | null): string | null;
5
+ export declare const functionFormulaText: (name: string) => (context: OperatorFormulaTextContext) => string;
6
+ /** Missing formulas stay null, including when consumed by another expression. */
7
+ export declare const operatorFormulaText: (operator: OperatorDefinition, context: Omit<OperatorFormulaTextContext, "input" | "inputs"> & {
8
+ readonly input?: string | null;
9
+ readonly inputs: readonly (string | null)[];
10
+ }) => string | null;
@@ -3,6 +3,7 @@ import { OperatorRegistry } from './registry';
3
3
  export { OperatorRegistry } from './registry';
4
4
  export { resolveOperator } from './resolve';
5
5
  export { bindTrustedSqlExpression } from './sql-expression';
6
- export type { OperatorDefinition, OperatorDefaultNameContext, OperatorExecutionContext, OperatorComponentContext, OperatorComponentCalculation, OperatorComponentQuery, OperatorExecutionComponent, OperatorGroupKeyShift, OperatorJavaScriptCalculation, OperatorQueryComponent, OperatorEvaluateContext, OperatorOutputPropertyContext, OperatorPeriodBoundaryPolicy, OperatorPeriodBoundaryPolicyContext, OperatorNormalizePredContext, OperatorPlanExpressionContext, OperatorPeriodEvaluationContext, OperatorPlanInputContext, OperatorPlannedInput, OperatorRewriteLogicformContext, OperatorValidatePlanContext, OperatorSqlCapabilities, OperatorSqlContext, ResultProperty, ResultPropertyTemporalMetadata, ResultPropertyTemporalMetadataExtensions, } from './types';
6
+ export { groupFormulaText, operatorFormulaText } from './formula-text';
7
+ export type { OperatorDefinition, OperatorDefaultNameContext, OperatorFormulaTextContext, OperatorExecutionContext, ResolvedTimeRange, OperatorComponentContext, OperatorComponentCalculation, OperatorComponentQuery, OperatorComponentLiteral, OperatorComponentInput, OperatorExecutionComponent, OperatorGroupKeyShift, OperatorJavaScriptCalculation, OperatorQueryComponent, OperatorOutputPropertyContext, OperatorPeriodBoundaryPolicy, OperatorPeriodBoundaryPolicyContext, OperatorNormalizePredContext, OperatorPlanExpressionContext, OperatorPeriodEvaluationContext, OperatorRuntimeHelpers, OperatorRuntimeConfig, OperatorRuntimeExecute, OperatorRuntimeRun, OperatorRuntimeValue, OperatorPlanInputContext, OperatorPlannedInput, OperatorRewriteLogicformContext, OperatorValidatePlanContext, OperatorSqlCapabilities, OperatorSqlContext, ResultProperty, ResultPropertyTemporalMetadata, ResultPropertyTemporalMetadataExtensions, } from './types';
7
8
  export declare const builtinOperators: readonly import("./types").OperatorDefinition[];
8
9
  export declare const createOperatorRegistry: (plugins?: readonly SemanticDBPlugin[]) => OperatorRegistry;
@@ -2,11 +2,18 @@ import type { OperatorDefinition, OperatorExecutionContext, OperatorPeriodEvalua
2
2
  export declare class OperatorRegistry {
3
3
  #private;
4
4
  readonly executionContext: OperatorExecutionContext;
5
- constructor(definitions?: readonly OperatorDefinition[], executionContext?: OperatorExecutionContext);
5
+ constructor(definitions?: readonly OperatorDefinition[], executionContext?: OperatorExecutionContext, builtinDefinitions?: readonly OperatorDefinition[]);
6
6
  withExecutionContext(executionContext: OperatorExecutionContext): OperatorRegistry;
7
7
  register(input: OperatorDefinition): this;
8
+ /** Built-in status comes from registry construction, never an operator's spelling. */
9
+ isBuiltin(name: string): boolean;
8
10
  get(name: string): OperatorDefinition;
9
11
  requiresPerPeriodEvaluation(name: string, context: OperatorPeriodEvaluationContext): boolean;
12
+ /** Whether this predicate needs an executor query component. */
13
+ isComponent(pred: {
14
+ readonly operator?: string;
15
+ readonly query?: Readonly<Record<string, unknown>>;
16
+ }): boolean;
10
17
  has(name: string): boolean;
11
18
  definitions(): readonly OperatorDefinition[];
12
19
  }
@@ -1,12 +1,33 @@
1
- import type { PrimalType, ResolvedSemanticProperty, ResolvedSemanticSchema, TimeGranularity, ComparableCategoryDefinition } from '../semantic-types/index';
2
- import type { LogicformType, PredItemType } from '../logicform-types';
1
+ import type { PrimalType, ResolvedSemanticProperty, ResolvedSemanticSchema, TimeGranularity, ComparableCategoryDefinition, SemanticTypeRegistry } from '../semantic-types/index';
2
+ import type { LogicformType, PredItemType, QueryType } from '../logicform-types';
3
3
  import type { DataRow } from '../physical/index';
4
4
  import type { Expression, LogicalPlan } from '../planner/index';
5
5
  import type { LocaleTranslate } from '../i18n/index';
6
+ import type dayjs from 'dayjs';
7
+ /** One unambiguous, inclusive date interval in the main query. */
8
+ export interface ResolvedTimeRange {
9
+ readonly schemaId: string;
10
+ readonly propertyId: string;
11
+ readonly queryPath: readonly (string | number)[];
12
+ /** Expanded question interval, before applying the time watermark. */
13
+ readonly requestedRange: {
14
+ readonly start: string;
15
+ readonly end: string;
16
+ };
17
+ /** Interval used by the normalized data query. */
18
+ readonly effectiveRange: {
19
+ readonly start: string;
20
+ readonly end: string;
21
+ };
22
+ /** Resolved watermark, not necessarily the raw database maximum. */
23
+ readonly timeWatermark?: string;
24
+ }
6
25
  /** Immutable data shared by all Operator hooks during one LogicForm execution. */
7
26
  export interface OperatorExecutionContext {
8
27
  /** Complete rows from the unique Schema marked with `is_calendar`. */
9
28
  readonly calendar?: readonly Readonly<DataRow>[];
29
+ /** Available after main-query normalization; child queries do not replace it. */
30
+ readonly timeRange?: ResolvedTimeRange;
10
31
  }
11
32
  interface OperatorHookContext {
12
33
  /** Always supplied by the executor; optional for direct unit-level hook invocation. */
@@ -44,16 +65,13 @@ export interface OperatorSqlContext extends OperatorHookContext {
44
65
  /** Operator-specific LogicForm arguments. */
45
66
  readonly args: Readonly<Record<string, unknown>>;
46
67
  }
47
- /** Context passed to an operator evaluated after the provider returns rows. */
48
- export interface OperatorEvaluateContext extends OperatorHookContext {
49
- /** Value produced by the nested expression, or undefined for a propertyless operator. */
50
- readonly input: unknown;
51
- /** Operator-specific LogicForm arguments. */
52
- readonly args: Readonly<Record<string, unknown>>;
53
- }
54
68
  /** A logical output column produced by one LogicForm projection. */
55
69
  export interface ResultProperty {
56
70
  readonly name: string;
71
+ /** Ordered child metric properties; names match the exposed component value keys. */
72
+ readonly componentProperties?: readonly ResultProperty[];
73
+ /** Readable calculation using logical property names; excludes query/groupby context. */
74
+ readonly formulaText?: string | null;
57
75
  readonly type: string;
58
76
  readonly primal_type: PrimalType;
59
77
  readonly isArray: boolean;
@@ -92,6 +110,8 @@ export type ResultPropertyTemporalMetadata = {
92
110
  }[];
93
111
  } | ResultPropertyTemporalMetadataExtensions[keyof ResultPropertyTemporalMetadataExtensions];
94
112
  export interface OperatorOutputPropertyContext extends OperatorHookContext {
113
+ /** Registry for resolving output semantic types, including application-defined types. */
114
+ readonly semanticTypes?: SemanticTypeRegistry;
95
115
  /** Final alias assigned to this operator's single output column. */
96
116
  readonly name: string;
97
117
  /** Original Schema property when the operator starts from a physical property. */
@@ -110,6 +130,49 @@ export interface OperatorPeriodEvaluationContext extends OperatorHookContext {
110
130
  readonly schema: ResolvedSemanticSchema;
111
131
  readonly inputProperty?: ResolvedSemanticProperty;
112
132
  }
133
+ /** Helpers supplied to a runtime metric during one execution. */
134
+ export interface OperatorRuntimeConfig {
135
+ readonly result_only: true;
136
+ /** The current metric projection. */
137
+ readonly pred: PredItemType;
138
+ readonly name?: string;
139
+ readonly args?: Readonly<Record<string, unknown>>;
140
+ readonly locale: string;
141
+ readonly signal?: AbortSignal;
142
+ readonly [key: string]: unknown;
143
+ }
144
+ export interface OperatorRuntimeExecute {
145
+ (logicform: LogicformType, config: {
146
+ readonly result_only: true;
147
+ }): Promise<DataRow[]>;
148
+ (logicform: LogicformType, config?: {
149
+ readonly result_only?: false;
150
+ }): Promise<{
151
+ readonly result: readonly Readonly<DataRow>[];
152
+ readonly total?: number;
153
+ }>;
154
+ }
155
+ export interface OperatorRuntimeHelpers {
156
+ readonly execute: OperatorRuntimeExecute;
157
+ /** Merge arrays by `_id`, preserving first-seen order; later columns win. */
158
+ readonly mergeByID: (results: readonly (readonly Readonly<DataRow>[])[]) => DataRow[];
159
+ readonly config: OperatorRuntimeConfig;
160
+ readonly schemas: Readonly<Record<string, ResolvedSemanticSchema>>;
161
+ readonly getSchema: (schemaId: string) => ResolvedSemanticSchema;
162
+ readonly getProperty: (schemaId: string, property: string) => ResolvedSemanticProperty;
163
+ readonly signal?: AbortSignal;
164
+ readonly locale: string;
165
+ readonly now: Date;
166
+ readonly log: (...values: unknown[]) => void;
167
+ readonly md5: (value: string) => string;
168
+ readonly fetch: typeof globalThis.fetch;
169
+ readonly dayjs: typeof dayjs;
170
+ /** Compatibility alias; this is dayjs, not the Moment.js package. */
171
+ readonly moment: typeof dayjs;
172
+ readonly [key: string]: unknown;
173
+ }
174
+ export type OperatorRuntimeValue = unknown;
175
+ export type OperatorRuntimeRun = (logicform: LogicformType, schema: ResolvedSemanticSchema, config: OperatorRuntimeConfig, helpers: OperatorRuntimeHelpers) => OperatorRuntimeValue;
113
176
  export interface OperatorDefaultNameContext extends OperatorHookContext {
114
177
  /** Name produced by the direct pred inputs or localized row label. */
115
178
  readonly operandName: string;
@@ -174,6 +237,9 @@ export interface OperatorRewriteLogicformContext extends OperatorHookContext {
174
237
  readonly getOperator?: (name: string) => OperatorDefinition;
175
238
  }
176
239
  export interface OperatorComponentContext extends OperatorHookContext {
240
+ readonly dayjs: typeof dayjs;
241
+ /** Compatibility alias; this is dayjs, not the Moment.js package. */
242
+ readonly moment: typeof dayjs;
177
243
  /** Normalized input LogicForm; having, sort, limit, limitBy, and page stay on the merged result. */
178
244
  readonly logicform: LogicformType;
179
245
  /** Caller-authored normalized input before executor row policies, with result operations removed. */
@@ -199,42 +265,67 @@ export interface OperatorQueryComponent {
199
265
  readonly kind: 'query';
200
266
  /** Internal LogicForm executed by the normal planner/compiler/provider pipeline. */
201
267
  readonly logicform: LogicformType;
268
+ /** Original projections whose semantic policies apply to the generated metric expressions. */
269
+ readonly semanticPreds?: readonly PredItemType[];
202
270
  /** Apply permissions and normalize this dynamically generated LogicForm before planning. */
203
271
  readonly prepare?: boolean;
204
272
  /** Optional result-key mapping used before component rows are merged. */
205
273
  readonly mapResult?: (rows: readonly DataRow[]) => DataRow[];
206
274
  /** SQL-side transformations that align this component's group keys with the base component. */
207
275
  readonly groupKeyShifts?: readonly OperatorGroupKeyShift[];
276
+ /** Shift an already partitioned current query into this comparison period. */
277
+ readonly partitionQuery?: (currentShardQuery: QueryType) => QueryType;
278
+ /** Unshifted metric used to choose the same Mapping for a standalone comparison. */
279
+ readonly partitionCurrentLogicform?: LogicformType;
208
280
  }
209
281
  export interface OperatorComponentQuery {
210
282
  /** Final result-column name for this child component. */
211
283
  readonly name: string;
212
284
  readonly logicform: LogicformType;
285
+ readonly literal?: never;
213
286
  readonly prepare?: boolean;
214
287
  readonly mapResult?: (rows: readonly DataRow[]) => DataRow[];
215
288
  readonly groupKeyShifts?: readonly OperatorGroupKeyShift[];
289
+ /** Name of the current-period component whose selected Mapping this query inherits. */
290
+ readonly comparisonOf?: string;
291
+ readonly partitionQuery?: (currentShardQuery: QueryType) => QueryType;
216
292
  /**
217
293
  * Group output names used to join this component back to the first component.
218
294
  * When omitted, the compiler joins on the groupby outputs shared by both components.
219
295
  */
220
296
  readonly joinKeys?: readonly string[];
221
297
  }
298
+ /** A precomputed finite numeric value, broadcast to every result group. */
299
+ export interface OperatorComponentLiteral {
300
+ readonly name: string;
301
+ readonly literal: number;
302
+ readonly logicform?: never;
303
+ }
304
+ export type OperatorComponentInput = OperatorComponentQuery | OperatorComponentLiteral;
222
305
  export interface OperatorComponentCalculation {
223
- readonly components: readonly OperatorComponentQuery[];
224
- /** Provider-independent formula referring to component names. */
306
+ readonly components: readonly OperatorComponentInput[];
307
+ /** Provider-independent formula referring to component names; also exposed verbatim as result formulaText. */
225
308
  readonly expression: string;
226
309
  }
227
310
  export interface OperatorJavaScriptCalculation {
228
311
  readonly kind: 'js';
229
- readonly components: readonly OperatorComponentQuery[];
312
+ readonly components: readonly OperatorComponentInput[];
230
313
  readonly mergeRow: (values: DataRow) => unknown;
231
314
  }
232
315
  export type OperatorExecutionComponent = OperatorQueryComponent | OperatorComponentCalculation | OperatorJavaScriptCalculation;
316
+ export interface OperatorFormulaTextContext extends OperatorHookContext {
317
+ readonly schema: ResolvedSemanticSchema;
318
+ /** Recursively expanded single-input formula, independent of its output alias. */
319
+ readonly input?: string;
320
+ /** Recursively expanded multi-input formulas, in operand order. */
321
+ readonly inputs: readonly string[];
322
+ readonly args: Readonly<Record<string, unknown>>;
323
+ }
233
324
  /**
234
325
  * Extension contract for one LogicForm operator.
235
326
  *
236
327
  * `kind` is the semantic category used by planning and execution. Its variant
237
- * requires the corresponding SQL, JavaScript, window, or component contract.
328
+ * requires the corresponding SQL, window, or component contract.
238
329
  * The planner recursively connects nested `pred` expressions and uses
239
330
  * `getOutputProperty` to describe the resulting one-column logical schema.
240
331
  */
@@ -245,6 +336,8 @@ interface OperatorDefinitionBase {
245
336
  readonly description?: string;
246
337
  /** Produce the normalized output name when the PredItem does not declare one. */
247
338
  readonly defaultName: (context: OperatorDefaultNameContext) => string;
339
+ /** Describe the calculation independently of the generated or authored output name. */
340
+ readonly getFormulaText?: (context: OperatorFormulaTextContext) => string;
248
341
  /** Translation key for the generated name. Defaults to `operator.${name}`. */
249
342
  readonly defaultNameKey?: string | ((context: OperatorDefaultNameContext) => string);
250
343
  /** defaultName already used the translator and must not be translated a second time. */
@@ -288,43 +381,40 @@ interface OperatorDefinitionBase {
288
381
  export type OperatorWindowFunction = 'rank' | 'rowNumber';
289
382
  export type OperatorDefinition = OperatorDefinitionBase & ({
290
383
  readonly kind: 'scalar';
384
+ /** Isolate a non-empty pred.query before computing this expression. */
385
+ readonly createQueryComponent?: (context: OperatorComponentContext) => OperatorQueryComponent;
291
386
  /** Convert the operator and its input expression into SQL. */
292
387
  readonly toSQL: (context: OperatorSqlContext) => string;
293
- readonly evaluate?: (context: OperatorEvaluateContext) => unknown;
294
- readonly createComponent?: never;
295
- readonly windowFunction?: never;
296
- } | {
297
- readonly kind: 'scalar';
298
- readonly toSQL?: (context: OperatorSqlContext) => string;
299
- /** JavaScript evaluator for this operator. */
300
- readonly evaluate: (context: OperatorEvaluateContext) => unknown;
301
388
  readonly createComponent?: never;
302
389
  readonly windowFunction?: never;
303
390
  } | {
304
391
  readonly kind: 'aggregate';
305
392
  readonly toSQL: (context: OperatorSqlContext) => string;
306
- readonly evaluate?: (context: OperatorEvaluateContext) => unknown;
307
393
  readonly createComponent?: never;
308
394
  readonly windowFunction?: never;
309
395
  } | {
310
396
  readonly kind: 'component';
311
397
  readonly toSQL?: never;
312
- readonly evaluate?: never;
313
398
  readonly createComponent: (context: OperatorComponentContext) => OperatorExecutionComponent;
314
399
  readonly windowFunction?: never;
315
400
  } | {
316
401
  readonly kind: 'window';
317
402
  readonly toSQL?: never;
318
- readonly evaluate?: never;
319
403
  readonly createComponent?: never;
320
404
  /** Plan this operator as a SQL window expression. */
321
405
  readonly windowFunction: OperatorWindowFunction;
322
406
  } | {
323
407
  readonly kind: 'logical';
324
408
  readonly toSQL?: never;
325
- readonly evaluate?: never;
326
409
  readonly createComponent?: never;
327
410
  readonly windowFunction?: never;
328
411
  readonly planExpression: (context: OperatorPlanExpressionContext) => Expression;
412
+ } | {
413
+ readonly kind: 'runtime';
414
+ readonly toSQL?: never;
415
+ readonly createComponent?: never;
416
+ readonly windowFunction?: never;
417
+ /** Evaluate a metric using application services and return a scalar or result rows. */
418
+ readonly run: OperatorRuntimeRun;
329
419
  });
330
420
  export {};
@@ -1,3 +1,4 @@
1
1
  export { applyPermissions, assertLogicformAllowed, getSchemaPermissions, isColumnAllowed, validatePermissions, } from './permissions';
2
2
  export type { PermissionSchemaResolver, } from './permissions';
3
- export type { ColumnPermissions, Permissions, SchemaPermissions, } from './types';
3
+ export type { ColumnPermissions, MetricPermissions, Permissions, SchemaPermissions, } from './types';
4
+ export { assertMetricCallsAllowed, validateSchemaMetricPermissions } from './metric-permissions';
@@ -0,0 +1,9 @@
1
+ import { type LogicformType } from '../logicform-types';
2
+ import type { OperatorRegistry } from '../operators/index';
3
+ import type { ResolvedSemanticSchema } from '../semantic-types/index';
4
+ import type { PermissionSchemaResolver } from './permissions';
5
+ import type { Permissions } from './types';
6
+ /** Validate only a Schema reached by this execution; registry membership alone is insufficient. */
7
+ export declare const validateSchemaMetricPermissions: (schema: ResolvedSemanticSchema, permissions: Permissions | undefined, operators: OperatorRegistry) => void;
8
+ /** Check caller expressions before rewrites, and generated expressions before compilation. */
9
+ export declare const assertMetricCallsAllowed: (form: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, operators: OperatorRegistry) => void;
@@ -1,10 +1,11 @@
1
1
  import type { LogicformType } from '../logicform-types';
2
2
  import type { ResolvedSemanticProperty, ResolvedSemanticSchema } from '../semantic-types/index';
3
+ import type { OperatorRegistry } from '../operators/index';
3
4
  import type { Permissions, SchemaPermissions } from './types';
4
5
  import type { SemanticDBPlugin } from '../plugins/index';
5
6
  export type PermissionSchemaResolver = (schemaId: string) => ResolvedSemanticSchema;
6
7
  export declare const getSchemaPermissions: (permissions: Permissions | undefined, schemaId: string) => SchemaPermissions | undefined;
7
8
  export declare const isColumnAllowed: (permissions: Permissions | undefined, schemaId: string, property: Pick<ResolvedSemanticProperty, "id" | "name">) => boolean;
8
- export declare const assertLogicformAllowed: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, plugins?: readonly SemanticDBPlugin[]) => void;
9
- export declare const applyPermissions: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, authorize?: boolean, appliedSchemas?: ReadonlySet<string>, plugins?: readonly SemanticDBPlugin[]) => LogicformType;
10
- export declare const validatePermissions: (permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver) => void;
9
+ export declare const assertLogicformAllowed: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, plugins?: readonly SemanticDBPlugin[], trustedQueries?: ReadonlyMap<string, ReadonlySet<string>>) => void;
10
+ export declare const applyPermissions: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, authorize?: boolean, appliedSchemas?: ReadonlySet<string>, plugins?: readonly SemanticDBPlugin[], operators?: OperatorRegistry) => LogicformType;
11
+ export declare const validatePermissions: (permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, schemaIds?: Iterable<string>) => void;
@@ -2,7 +2,12 @@ import type { QueryType } from '../logicform-types';
2
2
  export interface ColumnPermissions {
3
3
  readonly whitelist: readonly string[];
4
4
  }
5
+ /** Omitted: unrestricted for compatibility. []: deny all. '*': all Schema metrics. */
6
+ export interface MetricPermissions {
7
+ readonly whitelist: readonly string[] | '*';
8
+ }
5
9
  export interface SchemaPermissions {
10
+ readonly metricPermissions?: MetricPermissions;
6
11
  readonly rowPermissions?: QueryType;
7
12
  readonly columnPermissions?: ColumnPermissions;
8
13
  }
@@ -1,3 +1,4 @@
1
+ import type { DuckDBConnectionOptions } from './duckdb-provider';
1
2
  import type { CoreComputeProvider } from './provider';
2
3
  import type { ClickHouseProviderOptions } from './clickhouse-provider';
3
4
  import type { DatabricksConnectionOptions } from './databricks-provider';
@@ -19,6 +20,9 @@ export interface DatabaseConnectionBase {
19
20
  export interface DatabaseConnectionExtensions {
20
21
  }
21
22
  export type BuiltinDatabaseConnection = ({
23
+ readonly id: string;
24
+ readonly kind: 'duckdb';
25
+ } & DuckDBConnectionOptions) | ({
22
26
  readonly id: string;
23
27
  readonly kind: 'mysql';
24
28
  } & MySQLConnectionOptions) | ({
@@ -1,3 +1,5 @@
1
+ import type { ReadImportFileOptions, ReadImportFileResult } from '../file-import/index';
2
+ import type { ImportRowsRequest, ImportRowsResult } from './import-types';
1
3
  import type { DatabaseConnection, ProviderRegistry } from './connection';
2
4
  import type { DatabaseTable, SQLResult, SqlParameters, TableListRequest, DescribeTableRequest, TableDescription } from './provider';
3
5
  export interface DBConnectorOptions {
@@ -14,10 +16,18 @@ export interface GetTableListOptions extends DBConnectorOptions, TableListReques
14
16
  }
15
17
  export interface DescribeTableOptions extends DBConnectorOptions, DescribeTableRequest {
16
18
  }
19
+ export interface ImportFileOptions extends DBConnectorOptions, ReadImportFileOptions, Omit<ImportRowsRequest, 'rows'> {
20
+ }
21
+ export interface ImportFileResult extends ImportRowsResult {
22
+ readonly format: ReadImportFileResult['format'];
23
+ readonly encoding?: ReadImportFileResult['encoding'];
24
+ readonly sheet?: string;
25
+ }
17
26
  /** Trusted physical operations; no LogicForm permissions, rewriting, or caching. */
18
27
  export declare const DBConnector: Readonly<{
19
28
  runSQL: (options: RunSQLOptions) => Promise<SQLResult>;
20
29
  getTableList: (options: GetTableListOptions) => Promise<DatabaseTable[]>;
21
30
  describeTable: (options: DescribeTableOptions) => Promise<TableDescription>;
31
+ importFile: (options: ImportFileOptions) => Promise<ImportFileResult>;
22
32
  close: () => Promise<void>;
23
33
  }>;
@@ -1,36 +1,16 @@
1
- import type { CoreComputeProvider, DataRow, DatePart, ProviderExecutionRequest } from './provider';
1
+ import { DuckDBSql } from './duckdb-sql';
2
+ import type { CoreComputeProvider, DataRow, ProviderExecutionRequest } from './provider';
2
3
  export type DuckDBCoordinatorColumnKind = 'boolean' | 'date' | 'number' | 'string';
3
4
  export interface DuckDBCoordinatorColumn {
4
5
  readonly name: string;
5
6
  readonly kind: DuckDBCoordinatorColumnKind;
6
7
  }
7
8
  /** In-process SQL engine used only to combine results from separate physical connections. */
8
- export declare class DuckDBCoordinatorProvider implements CoreComputeProvider {
9
+ export declare class DuckDBCoordinatorProvider extends DuckDBSql implements CoreComputeProvider {
9
10
  private readonly instance;
10
11
  private readonly connection;
11
- readonly kind: "duckdb";
12
- readonly supportsHavingAlias = true;
13
- readonly supportsRecursiveCte = true;
14
12
  static create(): Promise<DuckDBCoordinatorProvider>;
15
13
  private constructor();
16
- quoteIdentifier(identifier: string): string;
17
- tableAlias(expression: string, alias: string): string;
18
- paginate(sql: string, pageSize: number, offset: number): string;
19
- parameter(index: number, value: unknown): string;
20
- displayQuery(sql: string, parameters: readonly unknown[]): string;
21
- dateBucket(expression: string, level: string): string;
22
- datePart(expression: string, part: DatePart): string;
23
- dateShift(expression: string, granularity: string, offset: number): string;
24
- datePeriodBoundary(expression: string, granularity: string, boundary: 'start' | 'end'): string;
25
- castValue(expression: string, type: string): string;
26
- scalarExtremum(operator: 'least' | 'greatest', expressions: readonly string[]): string;
27
- aggregateFunction(name: string, expression?: string): string;
28
- stringify(expression: string): string;
29
- concat(expressions: readonly string[]): string;
30
- substring(expression: string, start: number, length: number): string;
31
- stringLength(expression: string): string;
32
- regex(expression: string, pattern: string, options?: string): string;
33
- arrayContains(arrayExpression: string, valueExpression: string): string;
34
14
  materialize(tableName: string, inputColumns: readonly DuckDBCoordinatorColumn[], rows: readonly DataRow[]): Promise<void>;
35
15
  execute(request: ProviderExecutionRequest): Promise<DataRow[]>;
36
16
  close(): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import type { DuckDBConnection } from '@duckdb/node-api';
2
+ import type { ImportColumn, ImportRowsRequest, ImportRowsResult } from './import-types';
3
+ interface DatasetBatch {
4
+ readonly id: string;
5
+ readonly file: string;
6
+ readonly hash: string;
7
+ readonly rowCount: number;
8
+ }
9
+ interface DatasetTable {
10
+ readonly name: string;
11
+ readonly columns: readonly ImportColumn[];
12
+ readonly batches: readonly DatasetBatch[];
13
+ }
14
+ export interface DatasetManifest {
15
+ readonly format: 1;
16
+ readonly version: string;
17
+ readonly tables: readonly DatasetTable[];
18
+ }
19
+ /** Readers load one atomically published manifest; old batch files stay readable. */
20
+ export declare const readDatasetManifest: (directory: string) => Promise<DatasetManifest>;
21
+ export declare const registerDatasetViews: (connection: DuckDBConnection, directory: string, manifest: DatasetManifest) => Promise<void>;
22
+ export declare const importDatasetRows: (directory: string, request: ImportRowsRequest, lockTimeoutMs: number) => Promise<ImportRowsResult>;
23
+ export {};
@@ -0,0 +1,26 @@
1
+ import { DuckDBSql } from './duckdb-sql';
2
+ import type { ImportRowsRequest, ImportRowsResult } from './import-types';
3
+ import type { CoreComputeProvider, DataRow, DatabaseTable, DescribeTableRequest, ProviderExecutionRequest, SQLResult, TableDescription, TableListRequest } from './provider';
4
+ export type DuckDBConnectionOptions = {
5
+ readonly path: string;
6
+ readonly readOnly?: boolean;
7
+ readonly directory?: never;
8
+ readonly lockTimeoutMs?: never;
9
+ } | {
10
+ readonly directory: string;
11
+ readonly lockTimeoutMs?: number;
12
+ readonly path?: never;
13
+ readonly readOnly?: never;
14
+ };
15
+ /** A customer-owned DuckDB file or a managed directory of published Parquet datasets. */
16
+ export declare class DuckDBProvider extends DuckDBSql implements CoreComputeProvider {
17
+ #private;
18
+ constructor(options: DuckDBConnectionOptions);
19
+ getDataVersion(): Promise<string | undefined>;
20
+ importRows(request: ImportRowsRequest): Promise<ImportRowsResult>;
21
+ execute(request: ProviderExecutionRequest): Promise<DataRow[]>;
22
+ runSQL(request: ProviderExecutionRequest): Promise<SQLResult>;
23
+ getTableList(request: TableListRequest): Promise<DatabaseTable[]>;
24
+ describeTable(request: DescribeTableRequest): Promise<TableDescription>;
25
+ close(): Promise<void>;
26
+ }
@@ -0,0 +1,33 @@
1
+ import type { DuckDBValue } from '@duckdb/node-api';
2
+ import type { DatePart } from './provider';
3
+ export declare const duckdbParameter: (value: unknown, label?: string) => DuckDBValue;
4
+ export declare const duckdbLiteral: (value: string) => string;
5
+ /** Shared dialect for physical DuckDB connections and the federated coordinator. */
6
+ export declare class DuckDBSql {
7
+ readonly kind: "duckdb";
8
+ readonly supportsHavingAlias = true;
9
+ readonly supportsRecursiveCte = true;
10
+ quoteIdentifier(identifier: string): string;
11
+ tableAlias(expression: string, alias: string): string;
12
+ paginate(sql: string, pageSize: number, offset: number): string;
13
+ parameter(index: number, value: unknown): string;
14
+ displayQuery(sql: string, parameters: readonly unknown[]): string;
15
+ dateBucket(expression: string, level: string): string;
16
+ datePart(expression: string, part: DatePart): string;
17
+ dateShift(expression: string, granularity: string, offset: number): string;
18
+ datePeriodBoundary(expression: string, granularity: string, boundary: 'start' | 'end'): string;
19
+ castValue(expression: string, type: string): string;
20
+ scalarExtremum(operator: 'least' | 'greatest', expressions: readonly string[]): string;
21
+ aggregateFunction(name: string, expression?: string): string;
22
+ stringify(expression: string): string;
23
+ concat(expressions: readonly string[]): string;
24
+ substring(expression: string, start: number, length: number): string;
25
+ stringLength(expression: string): string;
26
+ regex(expression: string, pattern: string, options?: string): string;
27
+ arrayContains(arrayExpression: string, valueExpression: string): string;
28
+ normalizeStringArray(expression: string): string;
29
+ expandArray(arrayExpression: string, alias: string, column: string): {
30
+ joinSql: string;
31
+ valueExpression: string;
32
+ };
33
+ }
@@ -0,0 +1,23 @@
1
+ import type { DataRow } from './provider';
2
+ export interface ImportColumn {
3
+ readonly name: string;
4
+ readonly type: 'string' | 'number' | 'boolean' | 'date' | 'timestamp';
5
+ readonly nullable?: boolean;
6
+ }
7
+ /** Database-neutral write capability. Files are parsed before reaching a provider. */
8
+ export interface ImportRowsRequest {
9
+ readonly table: string;
10
+ readonly columns: readonly ImportColumn[];
11
+ readonly rows: readonly DataRow[];
12
+ /** Stable caller-supplied identity, e.g. a business date. */
13
+ readonly batchId: string;
14
+ readonly mode?: 'append' | 'replace-batch' | 'replace';
15
+ readonly signal?: AbortSignal;
16
+ }
17
+ export interface ImportRowsResult {
18
+ readonly table: string;
19
+ readonly batchId: string;
20
+ readonly rowCount: number;
21
+ readonly version: string;
22
+ readonly status: 'imported' | 'unchanged';
23
+ }
@@ -0,0 +1,14 @@
1
+ import type { ImportColumn, ImportRowsRequest } from './import-types';
2
+ import type { DataRow } from './provider';
3
+ export declare const importSqlType: (type: ImportColumn["type"]) => string;
4
+ export declare const validateImportColumns: (columns: unknown) => asserts columns is readonly ImportColumn[];
5
+ export declare const normalizeImport: (request: ImportRowsRequest) => {
6
+ columns: {
7
+ name: string;
8
+ type: "string" | "number" | "boolean" | "date" | "timestamp";
9
+ nullable: boolean;
10
+ }[];
11
+ rows: DataRow[];
12
+ mode: "replace" | "append" | "replace-batch";
13
+ hash: string;
14
+ };
@@ -2,6 +2,10 @@
2
2
  export type { CoreComputeProvider, DatePart, DataRow, DatabaseTable, SQLResult, TableListRequest, DescribeTableRequest, DatabaseColumn, TableDescription, ProviderExecutionRequest, ProviderKind, ProviderKindExtensions, SqlRenderCapabilities, SqlParameters, } from './provider';
3
3
  export { ConnectionRegistry, getConnectionProvider, closeConnections } from './connection-registry';
4
4
  export { DBConnector } from './db-connector';
5
+ export { DuckDBProvider } from './duckdb-provider';
6
+ export type { DuckDBConnectionOptions } from './duckdb-provider';
7
+ export type { ImportColumn, ImportRowsRequest, ImportRowsResult } from './import-types';
8
+ export type { ImportFileOptions, ImportFileResult } from './db-connector';
5
9
  export type { DBConnectorOptions, RunSQLOptions, GetTableListOptions, DescribeTableOptions } from './db-connector';
6
10
  export { builtinProviderDefinitions, createProvider, defaultProviderRegistry, ProviderRegistry, } from './connection';
7
11
  export type { BuiltinDatabaseConnection, DatabaseConnection, DatabaseConnectionBase, DatabaseConnectionExtensions, ProviderDefinition, } from './connection';
@@ -38,6 +38,7 @@ export declare class PostgreSQLProvider implements CoreComputeProvider {
38
38
  dateBucket(expression: string, level: string): string;
39
39
  datePart(expression: string, part: DatePart): string;
40
40
  dateShift(expression: string, granularity: string, offset: number): string;
41
+ castValue(expression: string, type: string): string;
41
42
  aggregateFunction(name: string, expression?: string): string;
42
43
  stringify(expression: string): string;
43
44
  concat(expressions: readonly string[]): string;