data-finder-ts 0.1.4 → 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.
- package/dist/{chunk-4JVW4TAB.js → chunk-BGEX377Q.js} +58 -8
- package/dist/chunk-BGEX377Q.js.map +1 -0
- package/dist/chunk-BKPWV3OF.js +962 -0
- package/dist/chunk-BKPWV3OF.js.map +1 -0
- package/dist/{chunk-PMPLCEWQ.js → chunk-GPHWC533.js} +2 -2
- package/dist/{chunk-FJYA2ASS.js → chunk-KAK75RVS.js} +74 -12
- package/dist/chunk-KAK75RVS.js.map +1 -0
- package/dist/{chunk-4LNZV6EN.js → chunk-MGEL5RWM.js} +206 -78
- package/dist/chunk-MGEL5RWM.js.map +1 -0
- package/dist/chunk-PF6EJZHB.js +1015 -0
- package/dist/chunk-PF6EJZHB.js.map +1 -0
- package/dist/datafinder/attribute.cjs +537 -11
- package/dist/datafinder/attribute.cjs.map +1 -1
- package/dist/datafinder/attribute.d.cts +29 -7
- package/dist/datafinder/attribute.d.ts +29 -7
- package/dist/datafinder/attribute.js +2 -2
- package/dist/datafinder/runner.cjs +1267 -215
- package/dist/datafinder/runner.cjs.map +1 -1
- package/dist/datafinder/runner.d.cts +28 -5
- package/dist/datafinder/runner.d.ts +28 -5
- package/dist/datafinder/runner.js +6 -6
- package/dist/datafinder/sql-generator.cjs +1203 -206
- package/dist/datafinder/sql-generator.cjs.map +1 -1
- package/dist/datafinder/sql-generator.d.cts +19 -5
- package/dist/datafinder/sql-generator.d.ts +19 -5
- package/dist/datafinder/sql-generator.js +9 -5
- package/dist/datafinder/typed-attributes.cjs +693 -88
- package/dist/datafinder/typed-attributes.cjs.map +1 -1
- package/dist/datafinder/typed-attributes.d.cts +3 -242
- package/dist/datafinder/typed-attributes.d.ts +3 -242
- package/dist/datafinder/typed-attributes.js +3 -3
- package/dist/dialect-CogGPm_y.d.cts +38 -0
- package/dist/dialect-aaG1bDi5.d.ts +38 -0
- package/dist/index.cjs +1677 -408
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -5
- package/dist/index.d.ts +109 -5
- package/dist/index.js +321 -11
- package/dist/index.js.map +1 -1
- package/dist/model/milestoning.cjs +529 -0
- package/dist/model/milestoning.cjs.map +1 -1
- package/dist/model/milestoning.js +2 -2
- package/dist/model/relational.cjs +547 -16
- package/dist/model/relational.cjs.map +1 -1
- package/dist/model/relational.d.cts +421 -57
- package/dist/model/relational.d.ts +421 -57
- package/dist/model/relational.js +53 -3
- package/dist/typed-attributes-CUTf_6Ru.d.ts +328 -0
- package/dist/typed-attributes-CdWXq_78.d.cts +328 -0
- package/package.json +3 -2
- package/dist/chunk-4JVW4TAB.js.map +0 -1
- package/dist/chunk-4LNZV6EN.js.map +0 -1
- package/dist/chunk-FJYA2ASS.js.map +0 -1
- package/dist/chunk-MH4XMYVB.js +0 -696
- package/dist/chunk-MH4XMYVB.js.map +0 -1
- package/dist/chunk-UYMOE6YU.js +0 -509
- package/dist/chunk-UYMOE6YU.js.map +0 -1
- /package/dist/{chunk-PMPLCEWQ.js.map → chunk-GPHWC533.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -7,15 +7,19 @@ import {
|
|
|
7
7
|
convertInputsAndSelectForDateRange,
|
|
8
8
|
getRunner,
|
|
9
9
|
registerRunner
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KAK75RVS.js";
|
|
11
11
|
import {
|
|
12
12
|
getRelatedFinderClass,
|
|
13
13
|
registerRelatedFinderClass
|
|
14
14
|
} from "./chunk-FLEIUDZZ.js";
|
|
15
15
|
import {
|
|
16
|
+
DATABRICKS,
|
|
17
|
+
DUCKDB,
|
|
18
|
+
POSTGRES,
|
|
19
|
+
dialectOf,
|
|
16
20
|
selectSqlToString,
|
|
17
21
|
toSql
|
|
18
|
-
} from "./chunk-
|
|
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-
|
|
30
|
+
} from "./chunk-GPHWC533.js";
|
|
27
31
|
import {
|
|
28
32
|
BooleanAttribute,
|
|
29
33
|
DateAttribute,
|
|
@@ -33,23 +37,34 @@ import {
|
|
|
33
37
|
FloatAttribute,
|
|
34
38
|
IntegerAttribute,
|
|
35
39
|
NumericAttribute,
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
NumericFunctionOperation,
|
|
41
|
+
StringAttribute,
|
|
42
|
+
StringFunctionOperation
|
|
43
|
+
} from "./chunk-MGEL5RWM.js";
|
|
38
44
|
import {
|
|
39
45
|
Attribute
|
|
40
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-BGEX377Q.js";
|
|
41
47
|
import {
|
|
42
48
|
AggregateOperation,
|
|
43
49
|
AggregateOperator,
|
|
50
|
+
Aggregates,
|
|
44
51
|
Alias,
|
|
52
|
+
Arithmetic,
|
|
53
|
+
ArithmeticOperation,
|
|
54
|
+
ArithmeticOperator,
|
|
45
55
|
BinaryOperation,
|
|
56
|
+
BooleanAggregates,
|
|
46
57
|
BooleanConstantOperation,
|
|
58
|
+
CaseOperation,
|
|
47
59
|
Column,
|
|
48
60
|
ColumnWithJoin,
|
|
61
|
+
Comparable,
|
|
49
62
|
ComparisonOperation,
|
|
50
63
|
ComparisonOperator,
|
|
64
|
+
ConcatOperation,
|
|
51
65
|
ConstantOperation,
|
|
52
66
|
CountAllOperation,
|
|
67
|
+
DATE_ONLY_PATTERN,
|
|
53
68
|
DataCatalog,
|
|
54
69
|
DataStore,
|
|
55
70
|
Database,
|
|
@@ -57,21 +72,28 @@ import {
|
|
|
57
72
|
DateConstantOperation,
|
|
58
73
|
DateDiffOperation,
|
|
59
74
|
DateExtractOperation,
|
|
75
|
+
DateOnly,
|
|
60
76
|
DatePart,
|
|
61
77
|
DateTimeConstantOperation,
|
|
78
|
+
DateTruncOperation,
|
|
62
79
|
DecimalConstantOperation,
|
|
63
80
|
ExistsOperation,
|
|
64
81
|
FloatConstantOperation,
|
|
65
82
|
ForeignKey,
|
|
83
|
+
InOperation,
|
|
66
84
|
IntegerConstantOperation,
|
|
67
85
|
IsNotNullOperation,
|
|
68
86
|
IsNullOperation,
|
|
69
87
|
JoinOperation,
|
|
70
88
|
JoinTreeNodeOperation,
|
|
89
|
+
LIKE_ESCAPE,
|
|
71
90
|
LogicalOperation,
|
|
72
91
|
LogicalOperator,
|
|
92
|
+
NUMERIC_FUNCTIONS,
|
|
73
93
|
NoOperation,
|
|
74
94
|
NotExistsOperation,
|
|
95
|
+
NotInOperation,
|
|
96
|
+
NumericConstantOperation,
|
|
75
97
|
Operation,
|
|
76
98
|
RelationalOperationElement,
|
|
77
99
|
ScalarFunction,
|
|
@@ -81,16 +103,102 @@ import {
|
|
|
81
103
|
SortDirection,
|
|
82
104
|
SortOperation,
|
|
83
105
|
StringConstantOperation,
|
|
106
|
+
StringPredicates,
|
|
84
107
|
Table,
|
|
85
108
|
UnaryOperation,
|
|
86
109
|
WindowFunction,
|
|
87
110
|
WindowFunctionOperation,
|
|
88
|
-
WindowSpecification
|
|
89
|
-
|
|
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
|
+
}
|
|
90
198
|
|
|
91
199
|
// src/datafinder/naming.ts
|
|
92
|
-
function titleCase(
|
|
93
|
-
return
|
|
200
|
+
function titleCase(value2) {
|
|
201
|
+
return value2.replace(/[A-Za-z]+/g, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase());
|
|
94
202
|
}
|
|
95
203
|
|
|
96
204
|
// src/datafinder/embedded.ts
|
|
@@ -116,34 +224,215 @@ var RelatedFinder = class {
|
|
|
116
224
|
return new NotExistsOperation(this._node);
|
|
117
225
|
}
|
|
118
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
|
+
};
|
|
119
393
|
export {
|
|
120
394
|
AggregateOperation,
|
|
121
395
|
AggregateOperator,
|
|
396
|
+
Aggregates,
|
|
122
397
|
Alias,
|
|
398
|
+
Arithmetic,
|
|
399
|
+
ArithmeticOperation,
|
|
400
|
+
ArithmeticOperator,
|
|
123
401
|
Attribute,
|
|
124
402
|
BiTemporalColumns,
|
|
125
403
|
BinaryOperation,
|
|
404
|
+
BooleanAggregates,
|
|
126
405
|
BooleanAttribute,
|
|
127
406
|
BooleanConstantOperation,
|
|
128
407
|
BusinessDateAndProcessingTemporalColumns,
|
|
408
|
+
CaseOperation,
|
|
129
409
|
Column,
|
|
130
410
|
ColumnWithJoin,
|
|
411
|
+
Comparable,
|
|
131
412
|
ComparisonOperation,
|
|
132
413
|
ComparisonOperator,
|
|
414
|
+
ConcatOperation,
|
|
133
415
|
ConstantOperation,
|
|
134
416
|
CountAllOperation,
|
|
417
|
+
DATABRICKS,
|
|
418
|
+
DATE_ONLY_PATTERN,
|
|
135
419
|
DEFAULT_TIMEOUT_MS,
|
|
420
|
+
DUCKDB,
|
|
136
421
|
DataCatalog,
|
|
137
422
|
DataStore,
|
|
138
423
|
Database,
|
|
424
|
+
DatabricksConnect,
|
|
425
|
+
DatabricksQueryError,
|
|
139
426
|
DateArithmeticOperation,
|
|
140
427
|
DateAttribute,
|
|
141
428
|
DateConstantOperation,
|
|
142
429
|
DateDiffOperation,
|
|
143
430
|
DateExtractOperation,
|
|
431
|
+
DateOnly,
|
|
144
432
|
DatePart,
|
|
145
433
|
DateTimeAttribute,
|
|
146
434
|
DateTimeConstantOperation,
|
|
435
|
+
DateTruncOperation,
|
|
147
436
|
DecimalAttribute,
|
|
148
437
|
DecimalConstantOperation,
|
|
149
438
|
DoubleAttribute,
|
|
@@ -152,20 +441,27 @@ export {
|
|
|
152
441
|
FloatAttribute,
|
|
153
442
|
FloatConstantOperation,
|
|
154
443
|
ForeignKey,
|
|
444
|
+
InOperation,
|
|
155
445
|
IntegerAttribute,
|
|
156
446
|
IntegerConstantOperation,
|
|
157
447
|
IsNotNullOperation,
|
|
158
448
|
IsNullOperation,
|
|
159
449
|
JoinOperation,
|
|
160
450
|
JoinTreeNodeOperation,
|
|
451
|
+
LIKE_ESCAPE,
|
|
161
452
|
LogicalOperation,
|
|
162
453
|
LogicalOperator,
|
|
163
454
|
MilestonedTable,
|
|
164
455
|
MilestoningColumns,
|
|
456
|
+
NUMERIC_FUNCTIONS,
|
|
165
457
|
NoOperation,
|
|
166
458
|
NotExistsOperation,
|
|
459
|
+
NotInOperation,
|
|
167
460
|
NumericAttribute,
|
|
461
|
+
NumericConstantOperation,
|
|
462
|
+
NumericFunctionOperation,
|
|
168
463
|
Operation,
|
|
464
|
+
POSTGRES,
|
|
169
465
|
ProcessingTemporalColumns,
|
|
170
466
|
QueryTimeoutError,
|
|
171
467
|
RelatedFinder,
|
|
@@ -179,21 +475,35 @@ export {
|
|
|
179
475
|
SortOperation,
|
|
180
476
|
StringAttribute,
|
|
181
477
|
StringConstantOperation,
|
|
478
|
+
StringFunctionOperation,
|
|
479
|
+
StringPredicates,
|
|
182
480
|
Table,
|
|
183
481
|
UnaryOperation,
|
|
184
482
|
WindowFunction,
|
|
185
483
|
WindowFunctionOperation,
|
|
186
484
|
WindowSpecification,
|
|
485
|
+
applyMixins,
|
|
187
486
|
clearRunner,
|
|
487
|
+
concat,
|
|
488
|
+
constant,
|
|
489
|
+
containsAggregate,
|
|
490
|
+
containsAggregateOrWindow,
|
|
188
491
|
convertInputsAndSelect,
|
|
189
492
|
convertInputsAndSelectForDateRange,
|
|
493
|
+
countAll,
|
|
494
|
+
dialectOf,
|
|
190
495
|
embeddedUnder,
|
|
496
|
+
escapeLike,
|
|
191
497
|
getRelatedFinderClass,
|
|
192
498
|
getRunner,
|
|
499
|
+
operandOf,
|
|
193
500
|
registerRelatedFinderClass,
|
|
194
501
|
registerRunner,
|
|
502
|
+
sample,
|
|
195
503
|
selectSqlToString,
|
|
196
504
|
titleCase,
|
|
197
|
-
toSql
|
|
505
|
+
toSql,
|
|
506
|
+
valueOperand,
|
|
507
|
+
when
|
|
198
508
|
};
|
|
199
509
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/datafinder/naming.ts","../src/datafinder/embedded.ts","../src/datafinder/finder.ts"],"sourcesContent":["/** 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACO,SAAS,UAAU,OAAuB;AAC/C,SAAO,MAAM,QAAQ,cAAc,OAAK,EAAE,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC;AACvF;;;ACMO,SAAS,cAAc,UAA0C,QAAgD;AACtH,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAA6B,CAAC;AACpC,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAClD,QAAI,IAAI,WAAW,MAAM,EAAG,QAAO,IAAI,MAAM,OAAO,MAAM,CAAC,IAAI;AAAA,EACjE;AACA,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AACnD;;;ACHO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,OAA8B;AAA9B;AAAA,EAA+B;AAAA,EAA/B;AAAA,EAE7B,SAA0B;AACxB,WAAO,IAAI,gBAAgB,KAAK,KAAK;AAAA,EACvC;AAAA,EAEA,YAAgC;AAC9B,WAAO,IAAI,mBAAmB,KAAK,KAAK;AAAA,EAC1C;AACF;","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBO,SAAS,SAASA,QAA4D;AACnF,MAAI,OAAOA,WAAU,UAAW,QAAO,IAAI,yBAAyBA,MAAK;AACzE,MAAI,OAAOA,WAAU,YAAY,OAAO,SAASA,MAAK,GAAG;AACvD,WAAO,OAAO,UAAUA,MAAK,IAAI,IAAI,yBAAyBA,MAAK,IAAI,IAAI,uBAAuBA,MAAK;AAAA,EACzG;AACA,MAAI,OAAOA,WAAU,SAAU,QAAO,IAAI,wBAAwBA,MAAK;AACvE,MAAIA,kBAAiB,SAAU,QAAO,IAAI,sBAAsBA,MAAK;AACrE,MAAIA,kBAAiB,KAAM,QAAO,IAAI,0BAA0BA,MAAK;AACrE,QAAM,IAAI,UAAU,+EAA+EA,WAAU,OAAO,SAAS,OAAOA,MAAK,EAAE;AAC7I;AAMO,SAAS,WAA8B;AAC5C,SAAO,IAAI,kBAAkB,EAAE;AACjC;;;ACnBA,IAAM,aAAa;AAAA,EACjB;AAAA,EAAqB;AAAA,EAAkB;AAAA,EAAiB;AAAA,EACxD;AAAA,EAAa;AAAA,EAAgB;AAAA,EAAiB;AAChD;AAaA,SAAS,MAAM,QAA4C;AACzD,MAAI,kBAAkB,UAAW,QAAO,OAAO,IAAI;AACnD,MAAI,kBAAkB,2BAA4B,QAAO;AACzD,MAAI;AACF,WAAO,SAAS,MAAM;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,UAAU,uDAAuD,WAAW,OAAO,SAAS,OAAO,MAAM,EAAE;AAAA,EACvH;AACF;AAEA,SAAS,QAAQ,WAA+B;AAC9C,MAAI,CAAC,WAAW,KAAK,OAAK,qBAAqB,CAAC,GAAG;AACjD,UAAM,IAAI,UAAU,4FAA4F;AAAA,EAClH;AACA,SAAO;AACT;AAGA,SAAS,MAAM,OAAe,UAAsD;AAClF,QAAM,CAAC,CAAC,WAAW,IAAI,GAAG,GAAG,IAAI,IAAI;AACrC,SAAO,IAAI,cAAc,WAAW,MAAM,KAAK,SAAS,IAAI,MAAM,MAAM,QAAQ,IAAI,QAAQ;AAC9F;AAMO,IAAM,OAAN,cAAmB,cAAc;AAAA,EACtC,YAA6B,OAAe;AAC1C,UAAM,QAAQ,MAAM,KAAK;AACzB,UAAM,MAAM,WAAW,MAAM,MAAM,MAAM,QAAQ;AAFtB;AAAA,EAG7B;AAAA,EAH6B;AAAA;AAAA,EAM7B,KAAK,WAA4B;AAC/B,WAAO,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,KAAK;AAAA,EAChD;AAAA;AAAA,EAGA,UAAU,QAA+B;AACvC,WAAO,MAAM,KAAK,OAAO,MAAM,MAAM,CAAC;AAAA,EACxC;AACF;AAEO,IAAM,OAAN,MAAW;AAAA,EAChB,YAA6B,WAAuC,UAAkB,CAAC,GAAG;AAA7D;AAAuC;AAAA,EAAuB;AAAA,EAA9D;AAAA,EAAuC;AAAA;AAAA,EAGpE,KAAK,QAAsB;AACzB,WAAO,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,KAAK,WAAW,MAAM,MAAM,CAAC,CAAC,CAAC;AAAA,EACpE;AACF;AAQO,SAAS,KAAK,WAA4B;AAC/C,SAAO,IAAI,KAAK,QAAQ,SAAS,CAAC;AACpC;;;AChGO,SAAS,UAAUC,QAAuB;AAC/C,SAAOA,OAAM,QAAQ,cAAc,OAAK,EAAE,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC;AACvF;;;ACMO,SAAS,cAAc,UAA0C,QAAgD;AACtH,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAA6B,CAAC;AACpC,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAClD,QAAI,IAAI,WAAW,MAAM,EAAG,QAAO,IAAI,MAAM,OAAO,MAAM,CAAC,IAAI;AAAA,EACjE;AACA,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AACnD;;;ACHO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,OAA8B;AAA9B;AAAA,EAA+B;AAAA,EAA/B;AAAA,EAE7B,SAA0B;AACxB,WAAO,IAAI,gBAAgB,KAAK,KAAK;AAAA,EACvC;AAAA,EAEA,YAAgC;AAC9B,WAAO,IAAI,mBAAmB,KAAK,KAAK;AAAA,EAC1C;AACF;;;ACeO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,SAA0B,MAAwB,aAAsB;AAClF,UAAM,OAAO;AADuB;AAAwB;AAE5D,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAAA,EAAwB;AAIhE;AAcA,IAAM,MAAM;AACZ,IAAM,WAAW,OAAO,OAAO,gBAAgB;AAGxC,SAAS,aAAa,MAAqB,UAAuC;AACvF,MAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,WAAS,YAAY,IAAI,YAAY,GAAG;AAAA,IACtC,KAAK;AAAA,IAAQ,KAAK;AAAA,IAAS,KAAK;AAAO,aAAO,OAAO,IAAI;AAAA,IACzD,KAAK,QAAQ;AACX,YAAMC,SAAQ,OAAO,IAAI;AACzB,aAAOA,UAAS,CAAC,YAAYA,UAAS,WAAW,OAAOA,MAAK,IAAIA;AAAA,IACnE;AAAA,IACA,KAAK;AAAA,IAAS,KAAK;AAAA,IAAU,KAAK;AAAW,aAAO,OAAO,IAAI;AAAA,IAC/D,KAAK;AAAW,aAAO,KAAK,YAAY,MAAM;AAAA,IAC9C,KAAK;AAAQ,aAAO,IAAI,SAAS,OAAO,YAAY;AAAA,IACpD,KAAK;AAAA,IAAa,KAAK,iBAAiB;AACtC,YAAM,QAAQ,wBAAwB,KAAK,IAAI;AAC/C,aAAO,IAAI,KAAK,QAAQ,OAAO,KAAK,QAAQ,KAAK,GAAG,IAAI,GAAG;AAAA,IAC7D;AAAA,IACA;AAAS,aAAO;AAAA,EAClB;AACF;AAEA,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAc,aAAW,WAAW,SAAS,EAAE,CAAC;AAE3E,IAAM,oBAAN,MAA+C;AAAA,EAMpD,YAA6B,QAA0B;AAA1B;AAC3B,QAAI,CAAC,OAAO,KAAM,OAAM,IAAI,MAAM,gFAAgF;AAClH,QAAI,CAAC,OAAO,YAAa,OAAM,IAAI,MAAM,mDAAmD;AAAA,EAC9F;AAAA,EAH6B;AAAA,EALpB,UAAU;AAAA;AAAA,EAGnB,cAAwB,CAAC;AAAA,EAOzB,MAAM,OACJ,cACA,oBACA,SACA,OACA,IACA,SACA,SACA,OACA,YAAoB,oBACpB,iBAA8B,MAC9B,WAAoB,OACpB,QACA,QACgB;AAChB,UAAM,YAAY;AAAA,MAChB;AAAA,MAAc;AAAA,MAAoB;AAAA,MAAS;AAAA,MAAgB;AAAA,MAAI;AAAA,MAAS;AAAA,MAAS;AAAA,MACjF;AAAA,MAAgB;AAAA,MAAU;AAAA,MAAQ;AAAA,MAAQ,KAAK;AAAA,IACjD;AACA,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAC5D,QAAI;AACJ,QAAI;AACF,UAAI,WAAW,MAAM,KAAK,KAAK,QAAQ,GAAG,GAAG,KAAK,WAAW,QAAQ;AAAA,QACnE,cAAc,KAAK,OAAO;AAAA,QAC1B;AAAA;AAAA;AAAA,QAGA,cAAc,aAAa,MAAO,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,YAAY,GAAI,CAAC,CAAC,MAAM;AAAA,QACrF,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,GAAI,KAAK,OAAO,UAAU,EAAE,SAAS,KAAK,OAAO,QAAQ,IAAI,CAAC;AAAA,QAC9D,GAAI,KAAK,OAAO,SAAS,EAAE,QAAQ,KAAK,OAAO,OAAO,IAAI,CAAC;AAAA,MAC7D,CAAC;AACD,oBAAc,SAAS;AAEvB,UAAI,QAAQ,KAAK,OAAO,kBAAkB;AAC1C,aAAO,SAAS,OAAO,UAAU,aAAa,SAAS,OAAO,UAAU,WAAW;AACjF,YAAI,KAAK,IAAI,KAAK,SAAU,OAAM,IAAI,kBAAkB,SAAS;AACjE,cAAM,MAAM,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;AAC/D,gBAAQ,KAAK,IAAI,QAAQ,GAAG,GAAI;AAChC,mBAAW,MAAM,KAAK,KAAK,OAAO,GAAG,GAAG,IAAI,WAAW,IAAI,WAAW,MAAM;AAAA,MAC9E;AAEA,UAAI,SAAS,OAAO,UAAU,aAAa;AACzC,cAAM,QAAQ,SAAS,OAAO;AAC9B,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,iBAAiB,SAAS,OAAO,MAAM,YAAY,CAAC;AAAA,UAAI,OAAO;AAAA,UAAY;AAAA,QAAW;AAAA,MAC5G;AACA,aAAO,MAAM,KAAK,KAAK,UAAU,WAAW,MAAM;AAAA,IACpD,SAAS,GAAG;AACV,YAAM,WAAW,WAAW,OAAO,WAAW,aAAa;AAC3D,UAAI,YAAY,gBAAgB,OAAW,OAAM,KAAK,OAAO,WAAW;AACxE,UAAI,WAAW,OAAO,QAAS,OAAM,IAAI,kBAAkB,SAAS;AACpE,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,KAAK,OAA0B,QAAqC;AAChF,UAAM,OAAO,MAAM,UAAU,QAAQ,WAAW,CAAC;AACjD,SAAK,cAAc,KAAK,IAAI,OAAK,EAAE,IAAI;AACvC,UAAM,OAAc,CAAC;AACrB,UAAM,OAAO,CAAC,SAA0C;AACtD,iBAAW,OAAO,QAAQ,CAAC,EAAG,MAAK,KAAK,IAAI,IAAI,CAAC,MAAM,MAAM,aAAa,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,IACtG;AACA,SAAK,MAAM,QAAQ,UAAU;AAC7B,QAAI,OAAO,MAAM,QAAQ;AACzB,WAAO,SAAS,UAAa,SAAS,MAAM;AAC1C,YAAM,QAAQ,MAAM,KAAK,KAAiB,OAAO,GAAG,GAAG,IAAI,MAAM,YAAY,kBAAkB,IAAI,IAAI,MAAM;AAC7G,WAAK,MAAM,UAAU;AACrB,aAAO,MAAM;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,OAAO,aAAoC;AACvD,QAAI;AACF,YAAM,KAAK,KAAK,QAAQ,GAAG,GAAG,IAAI,WAAW,WAAW,QAAW,CAAC,CAAC;AAAA,IACvE,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAc,KAA4B,QAAwB,MAAc,QAAiC,MAA2B;AAC1I,UAAM,EAAE,MAAM,OAAO,SAAS,OAAO,OAAO,IAAI,KAAK;AACrD,UAAM,SAAS,OAAO,UAAU,aAAa,MAAM,MAAM,IAAI;AAC7D,UAAM,WAAW,OAAO,UAAU,OAAO,KAAK,QAAQ,QAAQ,EAAE,IAAI,MAAM;AAAA,MACxE;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG,IAAI,CAAC;AAAA,QACtD,GAAG;AAAA,MACL;AAAA,MACA,MAAM,SAAS,SAAY,SAAY,KAAK,UAAU,IAAI;AAAA,MAC1D;AAAA,IACF,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI;AACJ,QAAI;AAAE,eAAS,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC;AAAA,IAAG,QAAQ;AAAE,eAAS;AAAA,IAAW;AAC3E,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,SAAS;AACf,YAAM,IAAI;AAAA,QACR,QAAQ,WAAW,8BAA8B,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QAAI,QAAQ;AAAA,MAAU;AAAA,IACjH;AACA,WAAO;AAAA,EACT;AACF;","names":["value","value","value"]}
|