data-finder-ts 0.1.3 → 0.1.5

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 (62) hide show
  1. package/README.md +17 -55
  2. package/dist/chunk-BGEX377Q.js +230 -0
  3. package/dist/chunk-BGEX377Q.js.map +1 -0
  4. package/dist/chunk-BKPWV3OF.js +962 -0
  5. package/dist/chunk-BKPWV3OF.js.map +1 -0
  6. package/dist/{chunk-EYXBYV2X.js → chunk-GPHWC533.js} +2 -2
  7. package/dist/chunk-KAK75RVS.js +198 -0
  8. package/dist/chunk-KAK75RVS.js.map +1 -0
  9. package/dist/chunk-MGEL5RWM.js +628 -0
  10. package/dist/chunk-MGEL5RWM.js.map +1 -0
  11. package/dist/chunk-PF6EJZHB.js +1015 -0
  12. package/dist/chunk-PF6EJZHB.js.map +1 -0
  13. package/dist/datafinder/attribute.cjs +595 -18
  14. package/dist/datafinder/attribute.cjs.map +1 -1
  15. package/dist/datafinder/attribute.d.cts +73 -10
  16. package/dist/datafinder/attribute.d.ts +73 -10
  17. package/dist/datafinder/attribute.js +2 -2
  18. package/dist/datafinder/runner.cjs +1589 -288
  19. package/dist/datafinder/runner.cjs.map +1 -1
  20. package/dist/datafinder/runner.d.cts +41 -7
  21. package/dist/datafinder/runner.d.ts +41 -7
  22. package/dist/datafinder/runner.js +12 -6
  23. package/dist/datafinder/sql-generator.cjs +1484 -281
  24. package/dist/datafinder/sql-generator.cjs.map +1 -1
  25. package/dist/datafinder/sql-generator.d.cts +19 -14
  26. package/dist/datafinder/sql-generator.d.ts +19 -14
  27. package/dist/datafinder/sql-generator.js +9 -7
  28. package/dist/datafinder/typed-attributes.cjs +856 -93
  29. package/dist/datafinder/typed-attributes.cjs.map +1 -1
  30. package/dist/datafinder/typed-attributes.d.cts +3 -135
  31. package/dist/datafinder/typed-attributes.d.ts +3 -135
  32. package/dist/datafinder/typed-attributes.js +3 -3
  33. package/dist/dialect-CogGPm_y.d.cts +38 -0
  34. package/dist/dialect-aaG1bDi5.d.ts +38 -0
  35. package/dist/index.cjs +2080 -480
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +119 -14
  38. package/dist/index.d.ts +119 -14
  39. package/dist/index.js +362 -12
  40. package/dist/index.js.map +1 -1
  41. package/dist/model/milestoning.cjs +529 -0
  42. package/dist/model/milestoning.cjs.map +1 -1
  43. package/dist/model/milestoning.js +2 -2
  44. package/dist/model/relational.cjs +608 -12
  45. package/dist/model/relational.cjs.map +1 -1
  46. package/dist/model/relational.d.cts +456 -47
  47. package/dist/model/relational.d.ts +456 -47
  48. package/dist/model/relational.js +61 -3
  49. package/dist/typed-attributes-CUTf_6Ru.d.ts +328 -0
  50. package/dist/typed-attributes-CdWXq_78.d.cts +328 -0
  51. package/package.json +5 -2
  52. package/dist/chunk-3SSWFES4.js +0 -448
  53. package/dist/chunk-3SSWFES4.js.map +0 -1
  54. package/dist/chunk-5K2Z3YDY.js +0 -393
  55. package/dist/chunk-5K2Z3YDY.js.map +0 -1
  56. package/dist/chunk-6QTCGJWX.js +0 -98
  57. package/dist/chunk-6QTCGJWX.js.map +0 -1
  58. package/dist/chunk-DFYZVBII.js +0 -652
  59. package/dist/chunk-DFYZVBII.js.map +0 -1
  60. package/dist/chunk-V647VNMY.js +0 -135
  61. package/dist/chunk-V647VNMY.js.map +0 -1
  62. /package/dist/{chunk-EYXBYV2X.js.map → chunk-GPHWC533.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,21 +1,25 @@
1
1
  import {
2
+ DEFAULT_TIMEOUT_MS,
2
3
  FinderResult,
4
+ QueryTimeoutError,
3
5
  clearRunner,
4
6
  convertInputsAndSelect,
7
+ convertInputsAndSelectForDateRange,
5
8
  getRunner,
6
9
  registerRunner
7
- } from "./chunk-6QTCGJWX.js";
10
+ } from "./chunk-KAK75RVS.js";
8
11
  import {
9
12
  getRelatedFinderClass,
10
13
  registerRelatedFinderClass
11
14
  } from "./chunk-FLEIUDZZ.js";
12
15
  import {
13
- ExistsOperation,
14
- NotExistsOperation,
15
- RelatedFinder,
16
+ DATABRICKS,
17
+ DUCKDB,
18
+ POSTGRES,
19
+ dialectOf,
16
20
  selectSqlToString,
17
21
  toSql
18
- } from "./chunk-DFYZVBII.js";
22
+ } from "./chunk-BKPWV3OF.js";
19
23
  import {
20
24
  BiTemporalColumns,
21
25
  BusinessDateAndProcessingTemporalColumns,
@@ -23,7 +27,7 @@ import {
23
27
  MilestoningColumns,
24
28
  ProcessingTemporalColumns,
25
29
  SingleBusinessDateColumn
26
- } from "./chunk-EYXBYV2X.js";
30
+ } from "./chunk-GPHWC533.js";
27
31
  import {
28
32
  BooleanAttribute,
29
33
  DateAttribute,
@@ -33,22 +37,34 @@ import {
33
37
  FloatAttribute,
34
38
  IntegerAttribute,
35
39
  NumericAttribute,
36
- StringAttribute
37
- } from "./chunk-5K2Z3YDY.js";
40
+ NumericFunctionOperation,
41
+ StringAttribute,
42
+ StringFunctionOperation
43
+ } from "./chunk-MGEL5RWM.js";
38
44
  import {
39
45
  Attribute
40
- } from "./chunk-V647VNMY.js";
46
+ } from "./chunk-BGEX377Q.js";
41
47
  import {
42
48
  AggregateOperation,
43
49
  AggregateOperator,
50
+ Aggregates,
51
+ Alias,
52
+ Arithmetic,
53
+ ArithmeticOperation,
54
+ ArithmeticOperator,
44
55
  BinaryOperation,
56
+ BooleanAggregates,
45
57
  BooleanConstantOperation,
58
+ CaseOperation,
46
59
  Column,
47
60
  ColumnWithJoin,
61
+ Comparable,
48
62
  ComparisonOperation,
49
63
  ComparisonOperator,
64
+ ConcatOperation,
50
65
  ConstantOperation,
51
66
  CountAllOperation,
67
+ DATE_ONLY_PATTERN,
52
68
  DataCatalog,
53
69
  DataStore,
54
70
  Database,
@@ -56,59 +72,367 @@ import {
56
72
  DateConstantOperation,
57
73
  DateDiffOperation,
58
74
  DateExtractOperation,
75
+ DateOnly,
59
76
  DatePart,
60
77
  DateTimeConstantOperation,
78
+ DateTruncOperation,
61
79
  DecimalConstantOperation,
80
+ ExistsOperation,
62
81
  FloatConstantOperation,
63
82
  ForeignKey,
83
+ InOperation,
64
84
  IntegerConstantOperation,
65
85
  IsNotNullOperation,
66
86
  IsNullOperation,
67
87
  JoinOperation,
68
88
  JoinTreeNodeOperation,
89
+ LIKE_ESCAPE,
69
90
  LogicalOperation,
70
91
  LogicalOperator,
92
+ NUMERIC_FUNCTIONS,
71
93
  NoOperation,
94
+ NotExistsOperation,
95
+ NotInOperation,
96
+ NumericConstantOperation,
72
97
  Operation,
73
98
  RelationalOperationElement,
74
99
  ScalarFunction,
75
100
  ScalarFunctionOperation,
76
101
  Schema,
102
+ SelectOperation,
77
103
  SortDirection,
78
104
  SortOperation,
79
105
  StringConstantOperation,
106
+ StringPredicates,
80
107
  Table,
81
108
  UnaryOperation,
82
109
  WindowFunction,
83
110
  WindowFunctionOperation,
84
- WindowSpecification
85
- } from "./chunk-3SSWFES4.js";
111
+ WindowSpecification,
112
+ applyMixins,
113
+ concat,
114
+ containsAggregate,
115
+ containsAggregateOrWindow,
116
+ escapeLike,
117
+ operandOf,
118
+ sample,
119
+ valueOperand
120
+ } from "./chunk-PF6EJZHB.js";
121
+
122
+ // src/datafinder/expressions.ts
123
+ function constant(value2) {
124
+ if (typeof value2 === "boolean") return new BooleanConstantOperation(value2);
125
+ if (typeof value2 === "number" && Number.isFinite(value2)) {
126
+ return Number.isInteger(value2) ? new IntegerConstantOperation(value2) : new FloatConstantOperation(value2);
127
+ }
128
+ if (typeof value2 === "string") return new StringConstantOperation(value2);
129
+ if (value2 instanceof DateOnly) return new DateConstantOperation(value2);
130
+ if (value2 instanceof Date) return new DateTimeConstantOperation(value2);
131
+ throw new TypeError(`A constant column holds a boolean, a finite number, a string or a date, not ${value2 === null ? "null" : typeof value2}`);
132
+ }
133
+ function countAll() {
134
+ return new CountAllOperation("");
135
+ }
136
+
137
+ // src/datafinder/conditional.ts
138
+ var CONDITIONS = [
139
+ ComparisonOperation,
140
+ LogicalOperation,
141
+ IsNullOperation,
142
+ IsNotNullOperation,
143
+ InOperation,
144
+ NotInOperation,
145
+ ExistsOperation,
146
+ NotExistsOperation
147
+ ];
148
+ function value(branch) {
149
+ if (branch instanceof Attribute) return branch.cwj();
150
+ if (branch instanceof RelationalOperationElement) return branch;
151
+ try {
152
+ return constant(branch);
153
+ } catch {
154
+ throw new TypeError(`A branch is a column, an expression or a value, not ${branch === null ? "null" : typeof branch}`);
155
+ }
156
+ }
157
+ function checked(condition) {
158
+ if (!CONDITIONS.some((c) => condition instanceof c)) {
159
+ throw new TypeError("The condition is a comparison, a null check, a membership test, exists, or and/or of those");
160
+ }
161
+ return condition;
162
+ }
163
+ function chain(cases, fallback) {
164
+ const [[condition, then], ...rest] = cases;
165
+ return new CaseOperation(condition, then, rest.length > 0 ? chain(rest, fallback) : fallback);
166
+ }
167
+ var Then = class extends CaseOperation {
168
+ constructor(cases) {
169
+ const first = chain(cases);
170
+ super(first.condition, first.then, first.fallback);
171
+ this.cases = cases;
172
+ }
173
+ cases;
174
+ /** Another case, tried when the ones before it do not hold. */
175
+ when(condition) {
176
+ return new When(checked(condition), this.cases);
177
+ }
178
+ /** The value when none of the cases hold. */
179
+ otherwise(branch) {
180
+ return chain(this.cases, value(branch));
181
+ }
182
+ };
183
+ var When = class {
184
+ constructor(condition, earlier = []) {
185
+ this.condition = condition;
186
+ this.earlier = earlier;
187
+ }
188
+ condition;
189
+ earlier;
190
+ /** The value where the condition holds. A value is a column, an expression or a plain value. */
191
+ then(branch) {
192
+ return new Then([...this.earlier, [this.condition, value(branch)]]);
193
+ }
194
+ };
195
+ function when(condition) {
196
+ return new When(checked(condition));
197
+ }
198
+
199
+ // src/datafinder/naming.ts
200
+ function titleCase(value2) {
201
+ return value2.replace(/[A-Za-z]+/g, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase());
202
+ }
203
+
204
+ // src/datafinder/embedded.ts
205
+ function embeddedUnder(embedded, prefix) {
206
+ if (!embedded) return void 0;
207
+ const result = {};
208
+ for (const [key, attr] of Object.entries(embedded)) {
209
+ if (key.startsWith(prefix)) result[key.slice(prefix.length)] = attr;
210
+ }
211
+ return Object.keys(result).length > 0 ? result : void 0;
212
+ }
213
+
214
+ // src/datafinder/finder.ts
215
+ var RelatedFinder = class {
216
+ constructor(_node) {
217
+ this._node = _node;
218
+ }
219
+ _node;
220
+ exists() {
221
+ return new ExistsOperation(this._node);
222
+ }
223
+ notExists() {
224
+ return new NotExistsOperation(this._node);
225
+ }
226
+ };
227
+
228
+ // src/datafinder/databricks-runner.ts
229
+ var DatabricksQueryError = class extends Error {
230
+ constructor(message, code, statementId) {
231
+ super(message);
232
+ this.code = code;
233
+ this.statementId = statementId;
234
+ this.name = "DatabricksQueryError";
235
+ }
236
+ code;
237
+ statementId;
238
+ };
239
+ var API = "/api/2.0/sql/statements";
240
+ var MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
241
+ function convertValue(text, typeName) {
242
+ if (text === null || text === void 0) return null;
243
+ switch ((typeName ?? "").toUpperCase()) {
244
+ case "BYTE":
245
+ case "SHORT":
246
+ case "INT":
247
+ return Number(text);
248
+ case "LONG": {
249
+ const value2 = BigInt(text);
250
+ return value2 >= -MAX_SAFE && value2 <= MAX_SAFE ? Number(value2) : value2;
251
+ }
252
+ case "FLOAT":
253
+ case "DOUBLE":
254
+ case "DECIMAL":
255
+ return Number(text);
256
+ case "BOOLEAN":
257
+ return text.toLowerCase() === "true";
258
+ case "DATE":
259
+ return new DateOnly(text + "T00:00:00Z");
260
+ case "TIMESTAMP":
261
+ case "TIMESTAMP_NTZ": {
262
+ const zoned = /(Z|[+-]\d{2}:?\d{2})$/.test(text);
263
+ return new Date(zoned ? text : text.replace(" ", "T") + "Z");
264
+ }
265
+ default:
266
+ return text;
267
+ }
268
+ }
269
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
270
+ var DatabricksConnect = class {
271
+ constructor(config) {
272
+ this.config = config;
273
+ if (!config.host) throw new Error("DatabricksConnect needs the host of a workspace, or of a server in front of it");
274
+ if (!config.warehouseId) throw new Error("DatabricksConnect needs the id of a SQL warehouse");
275
+ }
276
+ config;
277
+ dialect = "databricks";
278
+ /** Names of the columns of the last query that returned. */
279
+ lastColumns = [];
280
+ async select(businessDate, processingDatetime, columns, table, op, orderBy, groupBy, limit, timeoutMs = DEFAULT_TIMEOUT_MS, businessDateTo = null, distinct = false, offset, having) {
281
+ const statement = toSql(
282
+ businessDate,
283
+ processingDatetime,
284
+ columns,
285
+ table,
286
+ op,
287
+ orderBy,
288
+ groupBy,
289
+ limit,
290
+ businessDateTo,
291
+ distinct,
292
+ offset,
293
+ having,
294
+ this.dialect
295
+ );
296
+ const deadline = Date.now() + timeoutMs;
297
+ const controller = new AbortController();
298
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
299
+ let statementId;
300
+ try {
301
+ let response = await this.call("POST", `${API}/`, controller.signal, {
302
+ warehouse_id: this.config.warehouseId,
303
+ statement,
304
+ // the API holds the request for up to 50 s and answers at once if the statement is quicker; a shorter
305
+ // wait than 5 s is not allowed except 0, so poll
306
+ wait_timeout: timeoutMs >= 5e3 ? `${Math.min(50, Math.floor(timeoutMs / 1e3))}s` : "0s",
307
+ on_wait_timeout: "CONTINUE",
308
+ disposition: "INLINE",
309
+ format: "JSON_ARRAY",
310
+ ...this.config.catalog ? { catalog: this.config.catalog } : {},
311
+ ...this.config.schema ? { schema: this.config.schema } : {}
312
+ });
313
+ statementId = response.statement_id;
314
+ let delay = this.config.pollIntervalMs ?? 250;
315
+ while (response.status.state === "PENDING" || response.status.state === "RUNNING") {
316
+ if (Date.now() >= deadline) throw new QueryTimeoutError(timeoutMs);
317
+ await sleep(Math.min(delay, Math.max(0, deadline - Date.now())));
318
+ delay = Math.min(delay * 2, 2e3);
319
+ response = await this.call("GET", `${API}/${statementId}`, controller.signal);
320
+ }
321
+ if (response.status.state !== "SUCCEEDED") {
322
+ const error = response.status.error;
323
+ throw new DatabricksQueryError(
324
+ error?.message ?? `The statement ${response.status.state.toLowerCase()}`,
325
+ error?.error_code,
326
+ statementId
327
+ );
328
+ }
329
+ return await this.rows(response, controller.signal);
330
+ } catch (e) {
331
+ const timedOut = controller.signal.aborted || e instanceof QueryTimeoutError;
332
+ if (timedOut && statementId !== void 0) await this.cancel(statementId);
333
+ if (controller.signal.aborted) throw new QueryTimeoutError(timeoutMs);
334
+ throw e;
335
+ } finally {
336
+ clearTimeout(timer);
337
+ }
338
+ }
339
+ /** The rows of a finished statement, following its chunks. */
340
+ async rows(first, signal) {
341
+ const info = first.manifest?.schema?.columns ?? [];
342
+ this.lastColumns = info.map((c) => c.name);
343
+ const rows = [];
344
+ const take = (data) => {
345
+ for (const row of data ?? []) rows.push(row.map((text, i) => convertValue(text, info[i]?.type_name)));
346
+ };
347
+ take(first.result?.data_array);
348
+ let next = first.result?.next_chunk_index;
349
+ while (next !== void 0 && next !== null) {
350
+ const chunk = await this.call("GET", `${API}/${first.statement_id}/result/chunks/${next}`, signal);
351
+ take(chunk.data_array);
352
+ next = chunk.next_chunk_index;
353
+ }
354
+ return rows;
355
+ }
356
+ /** Ask Databricks to stop a statement. Best effort: the query is already given up on. */
357
+ async cancel(statementId) {
358
+ try {
359
+ await this.call("POST", `${API}/${statementId}/cancel`, void 0, {});
360
+ } catch {
361
+ }
362
+ }
363
+ async call(method, path, signal, body) {
364
+ const { host, token, headers, fetch: custom } = this.config;
365
+ const bearer = typeof token === "function" ? await token() : token;
366
+ const response = await (custom ?? fetch)(host.replace(/\/+$/, "") + path, {
367
+ method,
368
+ headers: {
369
+ "Content-Type": "application/json",
370
+ ...bearer ? { Authorization: `Bearer ${bearer}` } : {},
371
+ ...headers
372
+ },
373
+ body: body === void 0 ? void 0 : JSON.stringify(body),
374
+ signal
375
+ });
376
+ const text = await response.text();
377
+ let parsed;
378
+ try {
379
+ parsed = text ? JSON.parse(text) : {};
380
+ } catch {
381
+ parsed = void 0;
382
+ }
383
+ if (!response.ok) {
384
+ const detail = parsed;
385
+ throw new DatabricksQueryError(
386
+ detail?.message ?? `Databricks request failed: ${response.status} ${response.statusText}`,
387
+ detail?.error_code
388
+ );
389
+ }
390
+ return parsed;
391
+ }
392
+ };
86
393
  export {
87
394
  AggregateOperation,
88
395
  AggregateOperator,
396
+ Aggregates,
397
+ Alias,
398
+ Arithmetic,
399
+ ArithmeticOperation,
400
+ ArithmeticOperator,
89
401
  Attribute,
90
402
  BiTemporalColumns,
91
403
  BinaryOperation,
404
+ BooleanAggregates,
92
405
  BooleanAttribute,
93
406
  BooleanConstantOperation,
94
407
  BusinessDateAndProcessingTemporalColumns,
408
+ CaseOperation,
95
409
  Column,
96
410
  ColumnWithJoin,
411
+ Comparable,
97
412
  ComparisonOperation,
98
413
  ComparisonOperator,
414
+ ConcatOperation,
99
415
  ConstantOperation,
100
416
  CountAllOperation,
417
+ DATABRICKS,
418
+ DATE_ONLY_PATTERN,
419
+ DEFAULT_TIMEOUT_MS,
420
+ DUCKDB,
101
421
  DataCatalog,
102
422
  DataStore,
103
423
  Database,
424
+ DatabricksConnect,
425
+ DatabricksQueryError,
104
426
  DateArithmeticOperation,
105
427
  DateAttribute,
106
428
  DateConstantOperation,
107
429
  DateDiffOperation,
108
430
  DateExtractOperation,
431
+ DateOnly,
109
432
  DatePart,
110
433
  DateTimeAttribute,
111
434
  DateTimeConstantOperation,
435
+ DateTruncOperation,
112
436
  DecimalAttribute,
113
437
  DecimalConstantOperation,
114
438
  DoubleAttribute,
@@ -117,43 +441,69 @@ export {
117
441
  FloatAttribute,
118
442
  FloatConstantOperation,
119
443
  ForeignKey,
444
+ InOperation,
120
445
  IntegerAttribute,
121
446
  IntegerConstantOperation,
122
447
  IsNotNullOperation,
123
448
  IsNullOperation,
124
449
  JoinOperation,
125
450
  JoinTreeNodeOperation,
451
+ LIKE_ESCAPE,
126
452
  LogicalOperation,
127
453
  LogicalOperator,
128
454
  MilestonedTable,
129
455
  MilestoningColumns,
456
+ NUMERIC_FUNCTIONS,
130
457
  NoOperation,
131
458
  NotExistsOperation,
459
+ NotInOperation,
132
460
  NumericAttribute,
461
+ NumericConstantOperation,
462
+ NumericFunctionOperation,
133
463
  Operation,
464
+ POSTGRES,
134
465
  ProcessingTemporalColumns,
466
+ QueryTimeoutError,
135
467
  RelatedFinder,
136
468
  RelationalOperationElement,
137
469
  ScalarFunction,
138
470
  ScalarFunctionOperation,
139
471
  Schema,
472
+ SelectOperation,
140
473
  SingleBusinessDateColumn,
141
474
  SortDirection,
142
475
  SortOperation,
143
476
  StringAttribute,
144
477
  StringConstantOperation,
478
+ StringFunctionOperation,
479
+ StringPredicates,
145
480
  Table,
146
481
  UnaryOperation,
147
482
  WindowFunction,
148
483
  WindowFunctionOperation,
149
484
  WindowSpecification,
485
+ applyMixins,
150
486
  clearRunner,
487
+ concat,
488
+ constant,
489
+ containsAggregate,
490
+ containsAggregateOrWindow,
151
491
  convertInputsAndSelect,
492
+ convertInputsAndSelectForDateRange,
493
+ countAll,
494
+ dialectOf,
495
+ embeddedUnder,
496
+ escapeLike,
152
497
  getRelatedFinderClass,
153
498
  getRunner,
499
+ operandOf,
154
500
  registerRelatedFinderClass,
155
501
  registerRunner,
502
+ sample,
156
503
  selectSqlToString,
157
- toSql
504
+ titleCase,
505
+ toSql,
506
+ valueOperand,
507
+ when
158
508
  };
159
509
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/datafinder/expressions.ts","../src/datafinder/conditional.ts","../src/datafinder/naming.ts","../src/datafinder/embedded.ts","../src/datafinder/finder.ts","../src/datafinder/databricks-runner.ts"],"sourcesContent":["/** Expressions that are not a column of a finder: values to select next to the columns. */\nimport {\n BooleanConstantOperation,\n CountAllOperation,\n ConstantOperation,\n DateConstantOperation,\n DateOnly,\n DateTimeConstantOperation,\n FloatConstantOperation,\n IntegerConstantOperation,\n NumericConstantOperation,\n StringConstantOperation,\n} from '../model/relational';\n\n/**\n * A fixed value as a column: `f.findAll(null, null, [f.name(), constant('EU').alias('Region')])`.\n * A number is a `NumericConstantOperation`, which takes part in arithmetic: `constant(100).minus(f.price())`.\n * A `DateOnly` is a date and any other `Date` a timestamp. It is named \"Constant\" unless `alias` gives it a name.\n */\nexport function constant(value: number): NumericConstantOperation;\nexport function constant(value: boolean | string | Date): ConstantOperation;\nexport function constant(value: boolean | number | string | Date): ConstantOperation;\nexport function constant(value: boolean | number | string | Date): ConstantOperation {\n if (typeof value === 'boolean') return new BooleanConstantOperation(value);\n if (typeof value === 'number' && Number.isFinite(value)) {\n return Number.isInteger(value) ? new IntegerConstantOperation(value) : new FloatConstantOperation(value);\n }\n if (typeof value === 'string') return new StringConstantOperation(value);\n if (value instanceof DateOnly) return new DateConstantOperation(value); // before Date: DateOnly is a Date\n if (value instanceof Date) return new DateTimeConstantOperation(value);\n throw new TypeError(`A constant column holds a boolean, a finite number, a string or a date, not ${value === null ? 'null' : typeof value}`);\n}\n\n/**\n * The number of rows in the group, `COUNT(*)`: `f.findAll(null, null, [f.category(), countAll()]).groupBy(f.category())`.\n * Unlike `count()` of a column it also counts rows where that column is missing.\n */\nexport function countAll(): CountAllOperation {\n return new CountAllOperation('');\n}\n","/**\n * A value that depends on a condition, written as in polars:\n * `when(f.age().gt(30)).then('senior').otherwise('junior')`.\n */\nimport { Attribute } from './attribute';\nimport { constant } from './expressions';\nimport {\n CaseOperation,\n ComparisonOperation,\n ExistsOperation,\n InOperation,\n IsNotNullOperation,\n IsNullOperation,\n LogicalOperation,\n NotExistsOperation,\n NotInOperation,\n Operation,\n RelationalOperationElement,\n} from '../model/relational';\n\nconst CONDITIONS = [\n ComparisonOperation, LogicalOperation, IsNullOperation, IsNotNullOperation,\n InOperation, NotInOperation, ExistsOperation, NotExistsOperation,\n];\n\n/** What a branch can be: a column or expression as it is, a plain value as a constant. */\nexport type Branch = Attribute | RelationalOperationElement | boolean | number | string | Date;\n\n/**\n * Something that is true or false for a row, which a `when` can test: a comparison, a null check, a membership\n * test, `exists`, or `and` / `or` of those. Checked when `when` is called.\n */\nexport type Condition = Operation | ExistsOperation | NotExistsOperation;\n\ntype Case = [Condition, RelationalOperationElement];\n\nfunction value(branch: Branch): RelationalOperationElement {\n if (branch instanceof Attribute) return branch.cwj();\n if (branch instanceof RelationalOperationElement) return branch;\n try {\n return constant(branch);\n } catch {\n throw new TypeError(`A branch is a column, an expression or a value, not ${branch === null ? 'null' : typeof branch}`);\n }\n}\n\nfunction checked(condition: unknown): Condition {\n if (!CONDITIONS.some(c => condition instanceof c)) {\n throw new TypeError('The condition is a comparison, a null check, a membership test, exists, or and/or of those');\n }\n return condition as Condition;\n}\n\n/** The cases in order as a conditional: each later case is what the one before falls back to. */\nfunction chain(cases: Case[], fallback?: RelationalOperationElement): CaseOperation {\n const [[condition, then], ...rest] = cases;\n return new CaseOperation(condition, then, rest.length > 0 ? chain(rest, fallback) : fallback);\n}\n\n/**\n * `when(condition).then(value)`: a column on its own (missing where the condition does not hold), or continued\n * with another `when` or closed with `otherwise`.\n */\nexport class Then extends CaseOperation {\n constructor(private readonly cases: Case[]) {\n const first = chain(cases);\n super(first.condition, first.then, first.fallback);\n }\n\n /** Another case, tried when the ones before it do not hold. */\n when(condition: Condition): When {\n return new When(checked(condition), this.cases);\n }\n\n /** The value when none of the cases hold. */\n otherwise(branch: Branch): CaseOperation {\n return chain(this.cases, value(branch));\n }\n}\n\nexport class When {\n constructor(private readonly condition: Condition, private readonly earlier: Case[] = []) {}\n\n /** The value where the condition holds. A value is a column, an expression or a plain value. */\n then(branch: Branch): Then {\n return new Then([...this.earlier, [this.condition, value(branch)]]);\n }\n}\n\n/**\n * Start a conditional: `when(f.category().eq('Technology')).then('tech').otherwise('other')`.\n *\n * Further cases follow with `.when(...).then(...)`; with no `otherwise` the value is missing (NULL). A condition\n * that is NULL for a row (a comparison with a missing value) is not true, so that row takes the next case.\n */\nexport function when(condition: Condition): When {\n return new When(checked(condition));\n}\n","/** Python's `str.title()`: uppercase the first letter of each alphabetic run and lowercase the rest. */\nexport function titleCase(value: string): string {\n return value.replace(/[A-Za-z]+/g, w => w[0].toUpperCase() + w.slice(1).toLowerCase());\n}\n","import type { Attribute } from './attribute';\n\n/**\n * Join-less alternates for a related class's properties, keyed by dotted property path relative to\n * that class (e.g. `name`, `branch.city`). The attributes point at flat columns on the owning table.\n */\nexport type EmbeddedAttributes = Record<string, Attribute>;\n\n/** The alternates under `prefix` (e.g. `branch.`), re-keyed relative to it; undefined when there are none. */\nexport function embeddedUnder(embedded: EmbeddedAttributes | undefined, prefix: string): EmbeddedAttributes | undefined {\n if (!embedded) return undefined;\n const result: EmbeddedAttributes = {};\n for (const [key, attr] of Object.entries(embedded)) {\n if (key.startsWith(prefix)) result[key.slice(prefix.length)] = attr;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","import { ExistsOperation, NotExistsOperation, JoinTreeNodeOperation } from '../model/relational';\nimport { titleCase } from './naming';\n\n/**\n * The display-name prefix for a column reached through a join: the relation names from the root, so\n * `account().branch().city()` is \"Account Branch City\" and not just \"Branch City\".\n */\nexport function displayPrefix(relationName: string, parentJoin?: JoinTreeNodeOperation): string {\n const names = [relationName];\n for (let node = parentJoin; node !== undefined; node = node.parent) names.push(node.join.name);\n return names.reverse().map(titleCase).join(' ');\n}\n\nexport class RelatedFinder {\n constructor(private readonly _node: JoinTreeNodeOperation) {}\n\n exists(): ExistsOperation {\n return new ExistsOperation(this._node);\n }\n\n notExists(): NotExistsOperation {\n return new NotExistsOperation(this._node);\n }\n}\n","/**\n * Runs a query on a Databricks SQL warehouse through the SQL Statement Execution REST API\n * (`/api/2.0/sql/statements`), which is plain HTTPS and so works from a browser as well as Node.\n *\n * A browser cannot call a Databricks workspace directly, as the workspace does not send CORS headers, so\n * `host` is usually a server of your own that forwards `/api/2.0/sql/…` to the workspace (and may add the\n * credentials, in which case no `token` is needed here).\n */\nimport { Attribute } from './attribute';\nimport { DEFAULT_TIMEOUT_MS, QueryRunner, QueryTarget, QueryTimeoutError, Row } from './runner';\nimport { toSql } from './sql-generator';\nimport {\n DateOnly,\n Operation,\n RelationalOperationElement,\n SortOperation,\n Table,\n} from '../model/relational';\n\nexport interface DatabricksConfig {\n /** The workspace URL, or a server that forwards the Statement Execution API to it. No trailing path. */\n host: string;\n /** The SQL warehouse that runs the statements. */\n warehouseId: string;\n /** Sent as the bearer token. A function is called for every request, so a token can be refreshed. */\n token?: string | (() => string | Promise<string>);\n /** The catalog and schema unqualified table names resolve in. */\n catalog?: string;\n schema?: string;\n /** Extra request headers, for a gateway in front of the workspace. */\n headers?: Record<string, string>;\n /** `fetch`, if not the global one. */\n fetch?: typeof fetch;\n /** How long to wait before first asking again whether a statement has finished (it backs off from there). */\n pollIntervalMs?: number;\n}\n\n/** A statement Databricks ran and failed, or the API refused. */\nexport class DatabricksQueryError extends Error {\n constructor(message: string, readonly code?: string, readonly statementId?: string) {\n super(message);\n this.name = 'DatabricksQueryError';\n }\n}\n\ninterface ColumnInfo { name: string; type_name?: string; type_text?: string }\n\n/** A chunk of rows, as the statement itself carries the first and the chunks endpoint the rest. */\ninterface ResultData { data_array?: (string | null)[][]; next_chunk_index?: number }\n\ninterface StatementResponse {\n statement_id: string;\n status: { state: string; error?: { error_code?: string; message?: string } };\n manifest?: { schema?: { columns?: ColumnInfo[] } };\n result?: ResultData;\n}\n\nconst API = '/api/2.0/sql/statements';\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\n\n/** A value as Databricks sends it (text, or null) as the JavaScript value for its column type. */\nexport function convertValue(text: string | null, typeName: string | undefined): unknown {\n if (text === null || text === undefined) return null;\n switch ((typeName ?? '').toUpperCase()) {\n case 'BYTE': case 'SHORT': case 'INT': return Number(text);\n case 'LONG': {\n const value = BigInt(text);\n return value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value; // exact when it cannot be a number\n }\n case 'FLOAT': case 'DOUBLE': case 'DECIMAL': return Number(text);\n case 'BOOLEAN': return text.toLowerCase() === 'true';\n case 'DATE': return new DateOnly(text + 'T00:00:00Z');\n case 'TIMESTAMP': case 'TIMESTAMP_NTZ': {\n const zoned = /(Z|[+-]\\d{2}:?\\d{2})$/.test(text);\n return new Date(zoned ? text : text.replace(' ', 'T') + 'Z');\n }\n default: return text; // STRING, and anything structured (ARRAY, MAP, STRUCT, BINARY, INTERVAL) as the text sent\n }\n}\n\nconst sleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms));\n\nexport class DatabricksConnect implements QueryRunner {\n readonly dialect = 'databricks' as const;\n\n /** Names of the columns of the last query that returned. */\n lastColumns: string[] = [];\n\n constructor(private readonly config: DatabricksConfig) {\n if (!config.host) throw new Error('DatabricksConnect needs the host of a workspace, or of a server in front of it');\n if (!config.warehouseId) throw new Error('DatabricksConnect needs the id of a SQL warehouse');\n }\n\n async select(\n businessDate: Date | null,\n processingDatetime: Date | null,\n columns: (Attribute | RelationalOperationElement)[],\n table: QueryTarget,\n op: RelationalOperationElement,\n orderBy?: SortOperation[],\n groupBy?: Attribute[],\n limit?: number,\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n businessDateTo: Date | null = null,\n distinct: boolean = false,\n offset?: number,\n having?: Operation,\n ): Promise<Row[]> {\n const statement = toSql(\n businessDate, processingDatetime, columns, table as Table, op, orderBy, groupBy, limit,\n businessDateTo, distinct, offset, having, this.dialect,\n );\n const deadline = Date.now() + timeoutMs;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n let statementId: string | undefined;\n try {\n let response = await this.call('POST', `${API}/`, controller.signal, {\n warehouse_id: this.config.warehouseId,\n statement,\n // the API holds the request for up to 50 s and answers at once if the statement is quicker; a shorter\n // wait than 5 s is not allowed except 0, so poll\n wait_timeout: timeoutMs >= 5000 ? `${Math.min(50, Math.floor(timeoutMs / 1000))}s` : '0s',\n on_wait_timeout: 'CONTINUE',\n disposition: 'INLINE',\n format: 'JSON_ARRAY',\n ...(this.config.catalog ? { catalog: this.config.catalog } : {}),\n ...(this.config.schema ? { schema: this.config.schema } : {}),\n });\n statementId = response.statement_id;\n\n let delay = this.config.pollIntervalMs ?? 250;\n while (response.status.state === 'PENDING' || response.status.state === 'RUNNING') {\n if (Date.now() >= deadline) throw new QueryTimeoutError(timeoutMs);\n await sleep(Math.min(delay, Math.max(0, deadline - Date.now())));\n delay = Math.min(delay * 2, 2000);\n response = await this.call('GET', `${API}/${statementId}`, controller.signal);\n }\n\n if (response.status.state !== 'SUCCEEDED') {\n const error = response.status.error;\n throw new DatabricksQueryError(\n error?.message ?? `The statement ${response.status.state.toLowerCase()}`, error?.error_code, statementId);\n }\n return await this.rows(response, controller.signal);\n } catch (e) {\n const timedOut = controller.signal.aborted || e instanceof QueryTimeoutError;\n if (timedOut && statementId !== undefined) await this.cancel(statementId);\n if (controller.signal.aborted) throw new QueryTimeoutError(timeoutMs);\n throw e;\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** The rows of a finished statement, following its chunks. */\n private async rows(first: StatementResponse, signal: AbortSignal): Promise<Row[]> {\n const info = first.manifest?.schema?.columns ?? [];\n this.lastColumns = info.map(c => c.name);\n const rows: Row[] = [];\n const take = (data: (string | null)[][] | undefined) => {\n for (const row of data ?? []) rows.push(row.map((text, i) => convertValue(text, info[i]?.type_name)));\n };\n take(first.result?.data_array);\n let next = first.result?.next_chunk_index;\n while (next !== undefined && next !== null) {\n const chunk = await this.call<ResultData>('GET', `${API}/${first.statement_id}/result/chunks/${next}`, signal);\n take(chunk.data_array);\n next = chunk.next_chunk_index;\n }\n return rows;\n }\n\n /** Ask Databricks to stop a statement. Best effort: the query is already given up on. */\n private async cancel(statementId: string): Promise<void> {\n try {\n await this.call('POST', `${API}/${statementId}/cancel`, undefined, {});\n } catch {\n // nothing more can be done about it\n }\n }\n\n private async call<T = StatementResponse>(method: 'GET' | 'POST', path: string, signal: AbortSignal | undefined, body?: object): Promise<T> {\n const { host, token, headers, fetch: custom } = this.config;\n const bearer = typeof token === 'function' ? await token() : token;\n const response = await (custom ?? fetch)(host.replace(/\\/+$/, '') + path, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),\n ...headers,\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n const text = await response.text();\n let parsed: unknown;\n try { parsed = text ? JSON.parse(text) : {}; } catch { parsed = undefined; }\n if (!response.ok) {\n const detail = parsed as { error_code?: string; message?: string } | undefined;\n throw new DatabricksQueryError(\n detail?.message ?? `Databricks request failed: ${response.status} ${response.statusText}`, detail?.error_code);\n }\n return parsed as T;\n }\n}\n"],"mappings":"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","names":["value","value","value"]}