tranfi 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/LICENSE +177 -0
  2. package/NOTICE +8 -0
  3. package/README.md +272 -40
  4. package/app/assets/{index-pDFMluyz.js → index-BIAIKnrp.js} +1 -1
  5. package/app/index.html +1 -1
  6. package/binding.gyp +55 -3
  7. package/csrc/arena.c +7 -5
  8. package/csrc/batch.c +818 -71
  9. package/csrc/buffer.c +84 -8
  10. package/csrc/cJSON.c +262 -19
  11. package/csrc/cJSON.h +17 -1
  12. package/csrc/codec_csv.c +1074 -181
  13. package/csrc/codec_jsonl.c +830 -118
  14. package/csrc/codec_table.c +108 -78
  15. package/csrc/codec_text.c +286 -68
  16. package/csrc/compiler.c +31 -3
  17. package/csrc/config.h +21 -0
  18. package/csrc/dsl.c +4722 -485
  19. package/csrc/expr.c +363 -55
  20. package/csrc/expr.h +2 -0
  21. package/csrc/internal.h +316 -27
  22. package/csrc/ir.c +65 -18
  23. package/csrc/ir.h +41 -0
  24. package/csrc/ir_schema.c +20 -5
  25. package/csrc/ir_serialize.c +68 -6
  26. package/csrc/ir_sql.c +796 -185
  27. package/csrc/ir_validate.c +462 -6
  28. package/csrc/json_path.c +210 -0
  29. package/csrc/main.c +879 -30
  30. package/csrc/memory_estimate.c +477 -0
  31. package/csrc/op_acf.c +171 -21
  32. package/csrc/op_across.c +477 -0
  33. package/csrc/op_anomaly.c +167 -32
  34. package/csrc/op_assert.c +761 -0
  35. package/csrc/op_bin.c +168 -29
  36. package/csrc/op_cast.c +383 -55
  37. package/csrc/op_clip.c +30 -19
  38. package/csrc/op_date_trunc.c +208 -34
  39. package/csrc/op_datetime.c +259 -77
  40. package/csrc/op_derive.c +65 -97
  41. package/csrc/op_diff.c +146 -30
  42. package/csrc/op_ewma.c +149 -30
  43. package/csrc/op_explode.c +124 -26
  44. package/csrc/op_fill_down.c +125 -53
  45. package/csrc/op_fill_null.c +176 -31
  46. package/csrc/op_filter.c +89 -40
  47. package/csrc/op_frequency.c +571 -43
  48. package/csrc/op_grep.c +36 -18
  49. package/csrc/op_group_agg.c +1790 -119
  50. package/csrc/op_hash.c +48 -15
  51. package/csrc/op_head.c +21 -86
  52. package/csrc/op_interpolate.c +268 -62
  53. package/csrc/op_join.c +2700 -182
  54. package/csrc/op_json_extract.c +227 -0
  55. package/csrc/op_json_filter.c +384 -0
  56. package/csrc/op_json_flatten.c +293 -0
  57. package/csrc/op_json_schema.c +503 -0
  58. package/csrc/op_label_encode.c +328 -53
  59. package/csrc/op_lag.c +181 -0
  60. package/csrc/op_lead.c +141 -89
  61. package/csrc/op_normalize.c +363 -79
  62. package/csrc/op_onehot.c +345 -73
  63. package/csrc/op_pivot.c +1546 -162
  64. package/csrc/op_quarantine.c +189 -0
  65. package/csrc/op_registry.c +2062 -166
  66. package/csrc/op_rename.c +41 -50
  67. package/csrc/op_replace.c +270 -118
  68. package/csrc/op_rleid.c +297 -0
  69. package/csrc/op_rowid.c +559 -0
  70. package/csrc/op_sample.c +80 -23
  71. package/csrc/op_schema.c +1341 -0
  72. package/csrc/op_schema_infer.c +252 -0
  73. package/csrc/op_select.c +265 -65
  74. package/csrc/op_set.c +3449 -0
  75. package/csrc/op_skip.c +30 -87
  76. package/csrc/op_sort.c +670 -124
  77. package/csrc/op_source_name.c +120 -0
  78. package/csrc/op_split.c +65 -28
  79. package/csrc/op_split_data.c +41 -9
  80. package/csrc/op_stack.c +178 -222
  81. package/csrc/op_stats.c +206 -110
  82. package/csrc/op_step.c +217 -55
  83. package/csrc/op_tail.c +21 -12
  84. package/csrc/op_tee.c +338 -0
  85. package/csrc/op_top.c +260 -53
  86. package/csrc/op_trim.c +48 -19
  87. package/csrc/op_unique.c +1193 -150
  88. package/csrc/op_unpivot.c +100 -66
  89. package/csrc/op_validate.c +601 -24
  90. package/csrc/op_window.c +492 -51
  91. package/csrc/path_policy.c +85 -0
  92. package/csrc/pipeline.c +872 -99
  93. package/csrc/recipes.c +3 -1
  94. package/csrc/report.c +73 -30
  95. package/csrc/selector.c +1097 -0
  96. package/csrc/size_utils.c +348 -0
  97. package/csrc/spill.c +317 -0
  98. package/csrc/spill.h +21 -0
  99. package/csrc/tranfi.h +169 -1
  100. package/csrc/transform.h +209 -0
  101. package/csrc/transform_api.c +2237 -0
  102. package/csrc/transform_categorical.c +923 -0
  103. package/csrc/transform_internal.h +472 -0
  104. package/csrc/transform_json.c +3812 -0
  105. package/csrc/transform_numeric.c +1966 -0
  106. package/csrc/transform_sha256.c +154 -0
  107. package/csrc/transform_wasm.h +162 -0
  108. package/csrc/transform_wasm_api.c +1373 -0
  109. package/csrc/wasm_api.c +70 -9
  110. package/napi_api.c +219 -11
  111. package/napi_transform.c +1648 -0
  112. package/napi_transform.h +8 -0
  113. package/package.json +27 -11
  114. package/scripts/install-native.js +76 -0
  115. package/scripts/prepack.js +64 -0
  116. package/scripts/sync-csrc.js +23 -0
  117. package/src/cli.js +8 -11
  118. package/src/engines/duckdb.js +45 -12
  119. package/src/index.js +661 -42
  120. package/src/memory_policy.js +411 -0
  121. package/src/native.js +1 -5
  122. package/src/pipeline.js +454 -31
  123. package/src/recipe_json.js +80 -0
  124. package/src/server.js +10 -8
  125. package/src/transform.js +403 -0
  126. package/src/transform_error.js +10 -0
  127. package/src/wasm.js +6 -4
  128. package/wasm/index.js +498 -10
  129. package/wasm/tranfi_core.js +0 -0
  130. package/wasm/transform.js +1156 -0
  131. package/wasm/worker.js +786 -0
  132. package/csrc/plan.c +0 -206
package/src/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * tranfi — Streaming ETL language + runtime.
3
3
  *
4
4
  * Usage:
5
- * import { pipeline, codec, ops, expr } from 'tranfi'
5
+ * const { pipeline, codec, ops, expr } = require('tranfi')
6
6
  *
7
7
  * const p = pipeline([
8
8
  * codec.csv({ delimiter: ',' }),
@@ -19,31 +19,52 @@
19
19
  * const result2 = await p2.run({ inputFile: './data.csv' })
20
20
  */
21
21
 
22
- import { Pipeline, PipelineResult, compileDsl, compileToSql, loadRecipe, saveRecipe, recipes } from './pipeline.js'
22
+ const { Pipeline, PipelineResult, compileDsl, compileToSql, loadRecipe, saveRecipe, recipes } = require('./pipeline.js')
23
23
 
24
- export { Pipeline, PipelineResult, compileDsl, compileToSql, loadRecipe, saveRecipe, recipes }
25
-
26
- export function pipeline(steps, { engine } = {}) {
24
+ function pipeline(steps, { engine } = {}) {
27
25
  return new Pipeline(steps, { engine })
28
26
  }
29
27
 
30
- export function param(name, defaultValue) {
28
+ function param(name, defaultValue) {
31
29
  const result = { param: name }
32
30
  if (defaultValue !== undefined) result.default = defaultValue
33
31
  return result
34
32
  }
35
33
 
36
- export function expr(text) {
34
+ function expr(text) {
37
35
  return text
38
36
  }
39
37
 
40
- export const codec = {
41
- csv({ delimiter = ',', header = true, batchSize = 1024, repair = false } = {}) {
38
+ const codec = {
39
+ csv({ delimiter = ',', header = true, batchSize = 1024, repair = false, mode, strict = false, maxErrorBytes = 4096, maxRecordBytes = 64 * 1024 * 1024, maxColumns = 8192, audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes, nulls, na, quotedNulls = true, comment, trimWs = true, skipEmptyRows = false, skipRepeatedHeader = false, skip = 0, nMax, maxRows } = {}) {
42
40
  const args = {}
43
41
  if (delimiter !== ',') args.delimiter = delimiter
44
42
  if (!header) args.header = false
45
43
  if (batchSize !== 1024) args.batch_size = batchSize
46
44
  if (repair) args.repair = true
45
+ if (mode !== undefined) args.mode = mode
46
+ if (strict) args.strict = true
47
+ if (maxErrorBytes !== 4096) args.max_error_bytes = Number(maxErrorBytes)
48
+ if (maxRecordBytes !== 64 * 1024 * 1024) args.max_record_bytes = Number(maxRecordBytes)
49
+ if (maxColumns !== 8192) args.max_columns = Number(maxColumns)
50
+ if (audit) args.audit = true
51
+ if (auditLimit !== undefined) args.audit_limit = Number(auditLimit)
52
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
53
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
54
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
55
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
56
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
57
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
58
+ if (nulls !== undefined) args.nulls = nulls
59
+ else if (na !== undefined) args.na = na
60
+ if (quotedNulls !== true) args.quoted_nulls = Boolean(quotedNulls)
61
+ if (comment) args.comment = String(comment)
62
+ if (trimWs !== true) args.trim_ws = Boolean(trimWs)
63
+ if (skipEmptyRows) args.skip_empty_rows = true
64
+ if (skipRepeatedHeader) args.skip_repeated_header = true
65
+ if (skip) args.skip = Number(skip)
66
+ if (nMax !== undefined) args.n_max = Number(nMax)
67
+ else if (maxRows !== undefined) args.max_rows = Number(maxRows)
47
68
  return { op: 'codec.csv.decode', args }
48
69
  },
49
70
 
@@ -57,9 +78,12 @@ export const codec = {
57
78
  return { op: 'codec.csv.encode', args }
58
79
  },
59
80
 
60
- jsonl({ batchSize = 1024 } = {}) {
81
+ jsonl({ batchSize = 1024, onError = 'skip', maxErrorBytes = 4096, maxRecordBytes = 64 * 1024 * 1024 } = {}) {
61
82
  const args = {}
62
83
  if (batchSize !== 1024) args.batch_size = batchSize
84
+ if (onError !== 'skip') args.on_error = onError
85
+ if (maxErrorBytes !== 4096) args.max_error_bytes = Number(maxErrorBytes)
86
+ if (maxRecordBytes !== 64 * 1024 * 1024) args.max_record_bytes = Number(maxRecordBytes)
63
87
  return { op: 'codec.jsonl.decode', args }
64
88
  },
65
89
 
@@ -71,9 +95,11 @@ export const codec = {
71
95
  return { op: 'codec.jsonl.encode', args: {} }
72
96
  },
73
97
 
74
- text({ batchSize = 1024 } = {}) {
98
+ text({ batchSize = 1024, maxErrorBytes = 4096, maxRecordBytes = 64 * 1024 * 1024 } = {}) {
75
99
  const args = {}
76
100
  if (batchSize !== 1024) args.batch_size = batchSize
101
+ if (maxErrorBytes !== 4096) args.max_error_bytes = Number(maxErrorBytes)
102
+ if (maxRecordBytes !== 64 * 1024 * 1024) args.max_record_bytes = Number(maxRecordBytes)
77
103
  return { op: 'codec.text.decode', args }
78
104
  },
79
105
 
@@ -93,15 +119,31 @@ export const codec = {
93
119
  }
94
120
  }
95
121
 
96
- export const ops = {
97
- filter(expression) {
98
- return { op: 'filter', args: { expr: expression } }
122
+ const ops = {
123
+ filter(expression, { audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
124
+ const args = { expr: expression }
125
+ if (audit) args.audit = true
126
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
127
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
128
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
129
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
130
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
131
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
132
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
133
+ return { op: 'filter', args }
99
134
  },
100
135
 
101
136
  select(columns) {
102
137
  return { op: 'select', args: { columns } }
103
138
  },
104
139
 
140
+ relocate(columns, { before, after } = {}) {
141
+ const args = { columns }
142
+ if (before !== undefined) args.before = before
143
+ if (after !== undefined) args.after = after
144
+ return { op: 'relocate', args }
145
+ },
146
+
105
147
  rename(mapping) {
106
148
  return { op: 'rename', args: { mapping } }
107
149
  },
@@ -122,15 +164,46 @@ export const ops = {
122
164
  return { op: 'derive', args: { columns: cols } }
123
165
  },
124
166
 
167
+ sourceName({ result = '_source', defaultValue = '' } = {}) {
168
+ const args = {}
169
+ if (result !== '_source') args.result = result
170
+ if (defaultValue !== '') args.default = defaultValue
171
+ return { op: 'source-name', args }
172
+ },
173
+
174
+
175
+ across(columns, { functions, fn, names, replace } = {}) {
176
+ const args = { columns }
177
+ if (functions !== undefined) args.functions = Array.isArray(functions) ? functions : [functions]
178
+ else if (fn !== undefined) args.fn = fn
179
+ else throw new Error('across requires functions or fn')
180
+ if (names !== undefined) args.names = names
181
+ if (replace !== undefined) args.replace = !!replace
182
+ return { op: 'across', args }
183
+ },
184
+
125
185
  stats(statsList) {
126
186
  const args = {}
127
187
  if (statsList) args.stats = statsList
128
188
  return { op: 'stats', args }
129
189
  },
130
190
 
131
- unique(columns) {
191
+ scan(statsList) {
192
+ const args = {}
193
+ if (statsList) args.stats = statsList
194
+ return { op: 'scan', args }
195
+ },
196
+
197
+ unique(columns, { maxKeys, maxStateBytes, sorted = false, mode, approx = false, bloomBytes, bloomHashes } = {}) {
132
198
  const args = {}
133
199
  if (columns) args.columns = columns
200
+ if (mode !== undefined) args.mode = mode
201
+ if (approx) args.approx = true
202
+ if (bloomBytes !== undefined) args.bloom_bytes = bloomBytes
203
+ if (bloomHashes !== undefined) args.bloom_hashes = bloomHashes
204
+ if (maxKeys !== undefined) args.max_keys = maxKeys
205
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
206
+ if (sorted) args.sorted = true
134
207
  return { op: 'unique', args }
135
208
  },
136
209
 
@@ -150,8 +223,123 @@ export const ops = {
150
223
  return { op: 'tail', args: { n } }
151
224
  },
152
225
 
153
- validate(expression) {
154
- return { op: 'validate', args: { expr: expression } }
226
+ validate(expression, { audit = false, auditLimit, maxFailures, maxFailureRate, warnFailureRate, name, message, rules, rulesFile, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
227
+ const args = {}
228
+ const isBuffer = typeof Buffer !== 'undefined' && Buffer.isBuffer(expression)
229
+ const firstArgIsRules = rules === undefined && expression && typeof expression === 'object' && !isBuffer
230
+ if (rulesFile !== undefined) args.rules_file = rulesFile
231
+ if (rules !== undefined) args.rules = rules
232
+ else if (firstArgIsRules) args.rules = expression
233
+ else if (expression !== undefined && expression !== null) args.expr = expression
234
+ if (args.expr === undefined && args.rules === undefined && args.rules_file === undefined) {
235
+ throw new Error('validate requires expression, rules, or rulesFile')
236
+ }
237
+ if (audit) args.audit = true
238
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
239
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
240
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
241
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
242
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
243
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
244
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
245
+ if (maxFailures !== undefined) args.max_failures = maxFailures
246
+ if (maxFailureRate !== undefined) args.max_failure_rate = maxFailureRate
247
+ if (warnFailureRate !== undefined) args.warn_failure_rate = warnFailureRate
248
+ if (name !== undefined && name !== null) args.name = name
249
+ if (message) args.message = message
250
+ return { op: 'validate', args }
251
+ },
252
+
253
+ assert(expression, { action = 'fail', name = 'assert', message = '', result = '_assert', audit = false, auditLimit, aggregate, op, value, column, tolerance, rel, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
254
+ const args = { action }
255
+ if (aggregate !== undefined && aggregate !== null) {
256
+ if (expression !== undefined && expression !== null) throw new Error('assert accepts either expression or aggregate, not both')
257
+ if (op === undefined || value === undefined) throw new Error('aggregate assert requires op and value')
258
+ args.aggregate = aggregate
259
+ args.op = op
260
+ args.value = Number(value)
261
+ if (column !== undefined && column !== null) args.column = column
262
+ if (tolerance !== undefined) args.tolerance = Number(tolerance)
263
+ if (rel !== undefined) args.rel = !!rel
264
+ } else if (expression !== undefined && expression !== null) {
265
+ if (tolerance !== undefined || rel !== undefined) throw new Error('assert tolerance and rel require aggregate')
266
+ args.expr = expression
267
+ } else {
268
+ throw new Error('assert requires expression or aggregate')
269
+ }
270
+ if (name !== undefined && name !== null) args.name = name
271
+ if (message) args.message = message
272
+ if (result !== undefined && result !== null) args.result = result
273
+ if (audit) args.audit = true
274
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
275
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
276
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
277
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
278
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
279
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
280
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
281
+ return { op: 'assert', args }
282
+ },
283
+
284
+ quarantine(expression, { name, message, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
285
+ const args = { expr: expression }
286
+ if (name !== undefined && name !== null) args.name = name
287
+ if (message) args.message = message
288
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
289
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
290
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
291
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
292
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
293
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
294
+ return { op: 'quarantine', args }
295
+ },
296
+
297
+ schema({ baseline, columns, required, nonNull, nullable, values, min, max, regex, mode = 'fail', name = 'schema', message = '', result = '_schema', audit = false, auditLimit, maxRegexPatternBytes, maxRegexCellBytes, allowExtraColumns, requireValuesSeen, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
298
+ const args = { mode, action: mode }
299
+ if (baseline !== undefined) args.baseline = baseline
300
+ if (columns !== undefined) args.columns = columns
301
+ if (required !== undefined) args.required = required
302
+ if (nonNull !== undefined) args.non_null = nonNull
303
+ if (nullable !== undefined) args.nullable = nullable
304
+ if (values !== undefined) args.values = values
305
+ if (min !== undefined) args.min = min
306
+ if (max !== undefined) args.max = max
307
+ if (regex !== undefined) args.regex = regex
308
+ if (name !== undefined && name !== null) args.name = name
309
+ if (message) args.message = message
310
+ if (result !== undefined && result !== null) args.result = result
311
+ if (audit) args.audit = true
312
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
313
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
314
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
315
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
316
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
317
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
318
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
319
+ if (maxRegexPatternBytes !== undefined) args.max_regex_pattern_bytes = maxRegexPatternBytes
320
+ if (maxRegexCellBytes !== undefined) args.max_regex_cell_bytes = maxRegexCellBytes
321
+ if (allowExtraColumns !== undefined) args.allow_extra_columns = !!allowExtraColumns
322
+ if (requireValuesSeen !== undefined) args.require_values_seen = !!requireValuesSeen
323
+ return { op: 'schema', args }
324
+ },
325
+
326
+ schemaInfer({ rows } = {}) {
327
+ const args = {}
328
+ if (rows !== undefined) args.rows = rows
329
+ return { op: 'schema-infer', args }
330
+ },
331
+
332
+ tee({ expr, channel = 'samples', columns, limit = 1000, every = 1, name = 'tee', includeRow = true, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
333
+ const args = { channel, limit, every, name, include_row: includeRow }
334
+ if (expr !== undefined && expr !== null) args.expr = expr
335
+ if (columns !== undefined && columns !== null) args.columns = columns
336
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
337
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
338
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
339
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
340
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
341
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
342
+ return { op: 'tee', args }
155
343
  },
156
344
 
157
345
  trim(columns) {
@@ -160,12 +348,31 @@ export const ops = {
160
348
  return { op: 'trim', args }
161
349
  },
162
350
 
163
- fillNull(mapping) {
164
- return { op: 'fill-null', args: { mapping } }
165
- },
166
-
167
- cast(mapping) {
168
- return { op: 'cast', args: { mapping } }
351
+ fillNull(mapping, { audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
352
+ const args = { mapping }
353
+ if (audit) args.audit = true
354
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
355
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
356
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
357
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
358
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
359
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
360
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
361
+ return { op: 'fill-null', args }
362
+ },
363
+
364
+ cast(mapping, { onError, audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
365
+ const args = { mapping }
366
+ if (onError !== undefined) args.on_error = onError
367
+ if (audit) args.audit = true
368
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
369
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
370
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
371
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
372
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
373
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
374
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
375
+ return { op: 'cast', args }
169
376
  },
170
377
 
171
378
  clip(column, { min, max } = {}) {
@@ -175,9 +382,17 @@ export const ops = {
175
382
  return { op: 'clip', args }
176
383
  },
177
384
 
178
- replace(column, pattern, replacement, { regex = false } = {}) {
385
+ replace(column, pattern, replacement, { regex = false, audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
179
386
  const args = { column, pattern, replacement }
180
387
  if (regex) args.regex = true
388
+ if (audit) args.audit = true
389
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
390
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
391
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
392
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
393
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
394
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
395
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
181
396
  return { op: 'replace', args }
182
397
  },
183
398
 
@@ -187,8 +402,28 @@ export const ops = {
187
402
  return { op: 'hash', args }
188
403
  },
189
404
 
190
- bin(column, boundaries) {
191
- return { op: 'bin', args: { column, boundaries } }
405
+ bin(column, boundaries, { missing, onTypeError } = {}) {
406
+ const args = { column, boundaries }
407
+ if (missing !== undefined) args.missing = missing
408
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
409
+ return { op: 'bin', args }
410
+ },
411
+
412
+ ewma(column, alpha, { result, missing, onTypeError } = {}) {
413
+ const args = { column, alpha }
414
+ if (result !== undefined) args.result = result
415
+ if (missing !== undefined) args.missing = missing
416
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
417
+ return { op: 'ewma', args }
418
+ },
419
+
420
+ anomaly(column, { threshold = 3.0, result, missing, onTypeError } = {}) {
421
+ const args = { column }
422
+ if (threshold !== undefined) args.threshold = threshold
423
+ if (result !== undefined) args.result = result
424
+ if (missing !== undefined) args.missing = missing
425
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
426
+ return { op: 'anomaly', args }
192
427
  },
193
428
 
194
429
  fillDown(columns) {
@@ -197,21 +432,84 @@ export const ops = {
197
432
  return { op: 'fill-down', args }
198
433
  },
199
434
 
200
- step(column, func, result) {
435
+ step(column, func, resultOrOptions) {
201
436
  const args = { column, func }
437
+ const options = resultOrOptions && typeof resultOrOptions === 'object' ? resultOrOptions : { result: resultOrOptions }
438
+ const { result, missing, onTypeError } = options || {}
202
439
  if (result) args.result = result
440
+ if (missing) args.missing = missing
441
+ if (onTypeError) args.on_type_error = onTypeError
203
442
  return { op: 'step', args }
204
443
  },
205
444
 
206
- window(column, size, func, result) {
445
+ window(column, size, func, resultOrOptions) {
207
446
  const args = { column, size, func }
208
- if (result) args.result = result
447
+ const options = resultOrOptions && typeof resultOrOptions === 'object' ? resultOrOptions : { result: resultOrOptions }
448
+ const { result, missing, onTypeError } = options || {}
449
+ if (result !== undefined) args.result = result
450
+ if (missing !== undefined) args.missing = missing
451
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
209
452
  return { op: 'window', args }
210
453
  },
211
454
 
212
- explode(column, delimiter) {
455
+ rollingSum(column, size, { result, missing, onTypeError } = {}) {
456
+ const args = { column, size }
457
+ if (result !== undefined) args.result = result
458
+ if (missing !== undefined) args.missing = missing
459
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
460
+ return { op: 'rolling-sum', args }
461
+ },
462
+
463
+ rollingMean(column, size, { result, missing, onTypeError } = {}) {
464
+ const args = { column, size }
465
+ if (result !== undefined) args.result = result
466
+ if (missing !== undefined) args.missing = missing
467
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
468
+ return { op: 'rolling-mean', args }
469
+ },
470
+
471
+ rollingMin(column, size, { result, missing, onTypeError } = {}) {
472
+ const args = { column, size }
473
+ if (result !== undefined) args.result = result
474
+ if (missing !== undefined) args.missing = missing
475
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
476
+ return { op: 'rolling-min', args }
477
+ },
478
+
479
+ rollingMax(column, size, { result, missing, onTypeError } = {}) {
480
+ const args = { column, size }
481
+ if (result !== undefined) args.result = result
482
+ if (missing !== undefined) args.missing = missing
483
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
484
+ return { op: 'rolling-max', args }
485
+ },
486
+
487
+ rollingAny(column, size, { result, nulls = 'ignore' } = {}) {
488
+ const args = { column, size }
489
+ if (result) args.result = result
490
+ if (nulls !== 'ignore') args.nulls = nulls
491
+ return { op: 'rolling-any', args }
492
+ },
493
+
494
+ rollingAll(column, size, { result, nulls = 'ignore' } = {}) {
495
+ const args = { column, size }
496
+ if (result) args.result = result
497
+ if (nulls !== 'ignore') args.nulls = nulls
498
+ return { op: 'rolling-all', args }
499
+ },
500
+
501
+ explode(column, delimiter, options = {}) {
502
+ if (delimiter && typeof delimiter === 'object') {
503
+ options = delimiter
504
+ delimiter = undefined
505
+ }
213
506
  const args = { column }
214
507
  if (delimiter && delimiter !== ',') args.delimiter = delimiter
508
+ const { maxTokensPerRow, maxOutputRowsPerInputRow, maxOutputRowsPerBatch, maxTokenBytes } = options || {}
509
+ if (maxTokensPerRow !== undefined) args.max_tokens_per_row = maxTokensPerRow
510
+ if (maxOutputRowsPerInputRow !== undefined) args.max_output_rows_per_input_row = maxOutputRowsPerInputRow
511
+ if (maxOutputRowsPerBatch !== undefined) args.max_output_rows_per_batch = maxOutputRowsPerBatch
512
+ if (maxTokenBytes !== undefined) args.max_token_bytes = maxTokenBytes
215
513
  return { op: 'explode', args }
216
514
  },
217
515
 
@@ -221,31 +519,154 @@ export const ops = {
221
519
  return { op: 'split', args }
222
520
  },
223
521
 
224
- unpivot(columns) {
225
- return { op: 'unpivot', args: { columns } }
522
+ unpivot(columns, { maxOutputRowsPerInputRow, maxOutputRowsPerBatch } = {}) {
523
+ const args = { columns }
524
+ if (maxOutputRowsPerInputRow !== undefined) args.max_output_rows_per_input_row = maxOutputRowsPerInputRow
525
+ if (maxOutputRowsPerBatch !== undefined) args.max_output_rows_per_batch = maxOutputRowsPerBatch
526
+ return { op: 'unpivot', args }
527
+ },
528
+
529
+ pivot(nameColumn, valueColumn, { agg, categories, maxCategories, sorted = false } = {}) {
530
+ const args = { name_column: nameColumn, value_column: valueColumn }
531
+ if (agg !== undefined) args.agg = agg
532
+ if (categories !== undefined) args.categories = categories
533
+ if (maxCategories !== undefined) args.max_categories = maxCategories
534
+ if (sorted) args.sorted = true
535
+ return { op: 'pivot', args }
536
+ },
537
+
538
+ interpolate(column, { method = 'linear', missing, onTypeError } = {}) {
539
+ const args = { column, method }
540
+ if (missing !== undefined) args.missing = missing
541
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
542
+ return { op: 'interpolate', args }
543
+ },
544
+
545
+ normalize(columns, { method = 'minmax', audit = false, auditLimit, missing, onTypeError, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
546
+ const cols = Array.isArray(columns)
547
+ ? columns
548
+ : String(columns).split(',').map(c => c.trim()).filter(Boolean)
549
+ const args = { columns: cols, method }
550
+ if (audit) args.audit = true
551
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
552
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
553
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
554
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
555
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
556
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
557
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
558
+ if (missing !== undefined) args.missing = missing
559
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
560
+ return { op: 'normalize', args }
561
+ },
562
+
563
+ acf(column, { lags = 20, missing, onTypeError } = {}) {
564
+ const args = { column, lags }
565
+ if (missing !== undefined) args.missing = missing
566
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
567
+ return { op: 'acf', args }
226
568
  },
227
569
 
228
570
  top(n, column, desc = true) {
229
571
  return { op: 'top', args: { n, column, desc } }
230
572
  },
231
573
 
232
- sample(n) {
233
- return { op: 'sample', args: { n } }
574
+ topK(n, column) {
575
+ return { op: 'top-k', args: { n, column, desc: true } }
576
+ },
577
+
578
+ bottomK(n, column) {
579
+ return { op: 'bottom-k', args: { n, column, desc: false } }
580
+ },
581
+
582
+ sliceHead(n) {
583
+ return { op: 'slice-head', args: { n } }
584
+ },
585
+
586
+ sliceTail(n) {
587
+ return { op: 'slice-tail', args: { n } }
588
+ },
589
+
590
+ sliceMin(column, n = 1, options = {}) {
591
+ const withTies = options && Object.prototype.hasOwnProperty.call(options, 'withTies') ? options.withTies : false
592
+ if (withTies) throw new Error('sliceMin withTies=true is not supported by bounded exact-N execution')
593
+ return { op: 'slice-min', args: { n, column, desc: false, with_ties: false } }
594
+ },
595
+
596
+ sliceMax(column, n = 1, options = {}) {
597
+ const withTies = options && Object.prototype.hasOwnProperty.call(options, 'withTies') ? options.withTies : false
598
+ if (withTies) throw new Error('sliceMax withTies=true is not supported by bounded exact-N execution')
599
+ return { op: 'slice-max', args: { n, column, desc: true, with_ties: false } }
234
600
  },
235
601
 
236
- groupAgg(groupBy, aggs) {
237
- return { op: 'group-agg', args: { group_by: groupBy, aggs } }
602
+ sample(n, { seed = 0 } = {}) {
603
+ const args = { n }
604
+ if (seed !== 0) args.seed = seed
605
+ return { op: 'sample', args }
238
606
  },
239
607
 
240
- frequency(columns) {
608
+ groupAgg(groupBy, aggs, { maxGroups, maxStateBytes, sorted = false } = {}) {
609
+ const args = { group_by: groupBy, aggs }
610
+ if (maxGroups !== undefined) args.max_groups = maxGroups
611
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
612
+ if (sorted) args.sorted = true
613
+ return { op: 'group-agg', args }
614
+ },
615
+
616
+ frequency(columns, { maxValues, maxStateBytes, mode, approx, overflow, other, audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
241
617
  const args = {}
242
618
  if (columns) args.columns = columns
619
+ if (maxValues !== undefined) args.max_values = maxValues
620
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
621
+ if (mode !== undefined) args.mode = mode
622
+ if (approx !== undefined) args.approx = !!approx
623
+ if (overflow !== undefined) args.overflow = overflow
624
+ if (other !== undefined) args.other = other
625
+ if (audit) args.audit = true
626
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
627
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
628
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
629
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
630
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
631
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
632
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
243
633
  return { op: 'frequency', args }
244
634
  },
245
635
 
246
- datetime(column, extract) {
636
+ onehot(column, { drop = false, categories, maxCategories, unknown, maxStateBytes } = {}) {
637
+ const args = { column }
638
+ if (drop) args.drop = true
639
+ if (categories !== undefined) args.categories = categories
640
+ if (maxCategories !== undefined) args.max_categories = maxCategories
641
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
642
+ if (unknown !== undefined) args.unknown = unknown
643
+ return { op: 'onehot', args }
644
+ },
645
+
646
+ labelEncode(column, { result, categories, maxCategories, unknown, maxStateBytes } = {}) {
647
+ const args = { column }
648
+ if (result) args.result = result
649
+ if (categories !== undefined) args.categories = categories
650
+ if (maxCategories !== undefined) args.max_categories = maxCategories
651
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
652
+ if (unknown !== undefined) args.unknown = unknown
653
+ return { op: 'label-encode', args }
654
+ },
655
+
656
+ datetime(column, extractOrOptions, options = {}) {
247
657
  const args = { column }
248
- if (extract) args.extract = extract
658
+ let opts = options || {}
659
+ if (Array.isArray(extractOrOptions) || typeof extractOrOptions === 'string') {
660
+ args.extract = extractOrOptions
661
+ } else if (extractOrOptions && typeof extractOrOptions === 'object') {
662
+ opts = extractOrOptions
663
+ } else if (extractOrOptions !== undefined && extractOrOptions !== null) {
664
+ args.extract = extractOrOptions
665
+ }
666
+ if (opts.extract !== undefined) args.extract = opts.extract
667
+ if (opts.missing !== undefined) args.missing = opts.missing
668
+ if (opts.onTypeError !== undefined) args.on_type_error = opts.onTypeError
669
+ if (opts.on_type_error !== undefined) args.on_type_error = opts.on_type_error
249
670
  return { op: 'datetime', args }
250
671
  },
251
672
 
@@ -253,9 +674,16 @@ export const ops = {
253
674
  return { op: 'reorder', args: { columns } }
254
675
  },
255
676
 
256
- dedup(columns) {
677
+ dedup(columns, { maxKeys, maxStateBytes, sorted = false, mode, approx = false, bloomBytes, bloomHashes } = {}) {
257
678
  const args = {}
258
679
  if (columns) args.columns = columns
680
+ if (mode !== undefined) args.mode = mode
681
+ if (approx) args.approx = true
682
+ if (bloomBytes !== undefined) args.bloom_bytes = bloomBytes
683
+ if (bloomHashes !== undefined) args.bloom_hashes = bloomHashes
684
+ if (maxKeys !== undefined) args.max_keys = maxKeys
685
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
686
+ if (sorted) args.sorted = true
259
687
  return { op: 'dedup', args }
260
688
  },
261
689
 
@@ -271,6 +699,132 @@ export const ops = {
271
699
  return { op: 'flatten', args: {} }
272
700
  },
273
701
 
702
+ jsonExtract(path, result, { column = '_line', type = 'string' } = {}) {
703
+ return { op: 'json-extract', args: { column, path, result, type } }
704
+ },
705
+
706
+ jsonFilter(path, { op = 'exists', value, column = '_line', type = 'auto' } = {}) {
707
+ const args = { column, path, op, type }
708
+ if (value !== undefined) args.value = value
709
+ return { op: 'json-filter', args }
710
+ },
711
+
712
+ jsonSchema(schema, { column = '_line', mode = 'annotate', result = '_valid', audit = false, auditLimit, auditIncludeRow, auditColumns, auditRedact, auditHashColumns, auditMaxBytes, auditMaxCellBytes } = {}) {
713
+ const args = { column, schema, mode, result }
714
+ if (audit) args.audit = true
715
+ if (auditLimit !== undefined) args.audit_limit = auditLimit
716
+ if (auditIncludeRow !== undefined) args.audit_include_row = !!auditIncludeRow
717
+ if (auditColumns !== undefined) args.audit_columns = auditColumns
718
+ if (auditRedact !== undefined) args.audit_redact = auditRedact
719
+ if (auditHashColumns !== undefined) args.audit_hash_columns = auditHashColumns
720
+ if (auditMaxBytes !== undefined) args.audit_max_bytes = Number(auditMaxBytes)
721
+ if (auditMaxCellBytes !== undefined) args.audit_max_cell_bytes = Number(auditMaxCellBytes)
722
+ return { op: 'json-schema', args }
723
+ },
724
+
725
+ jsonFlatten(fields, { column = '_line' } = {}) {
726
+ return { op: 'json-flatten', args: { column, fields } }
727
+ },
728
+
729
+ join(file, on, { how = 'inner', maxLookupRows, maxLookupKeys, maxLookupBytes, maxStateBytes, maxMatchesPerRow, maxOutputRows, sorted = false } = {}) {
730
+ const args = { file, on }
731
+ if (how !== 'inner') args.how = how
732
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
733
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
734
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
735
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
736
+ if (maxMatchesPerRow !== undefined) args.max_matches_per_row = maxMatchesPerRow
737
+ if (maxOutputRows !== undefined) args.max_output_rows = maxOutputRows
738
+ if (sorted) args.sorted = true
739
+ return { op: 'join', args }
740
+ },
741
+
742
+ semiJoin(file, on, { maxLookupRows, maxLookupKeys, maxLookupBytes, maxStateBytes, maxOutputRows, sorted = false } = {}) {
743
+ const args = { file, on }
744
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
745
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
746
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
747
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
748
+ if (maxOutputRows !== undefined) args.max_output_rows = maxOutputRows
749
+ if (sorted) args.sorted = true
750
+ return { op: 'semi-join', args }
751
+ },
752
+
753
+ antiJoin(file, on, { maxLookupRows, maxLookupKeys, maxLookupBytes, maxStateBytes, maxOutputRows, sorted = false } = {}) {
754
+ const args = { file, on }
755
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
756
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
757
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
758
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
759
+ if (maxOutputRows !== undefined) args.max_output_rows = maxOutputRows
760
+ if (sorted) args.sorted = true
761
+ return { op: 'anti-join', args }
762
+ },
763
+
764
+ intersect(file, { columns, maxLookupRows, maxLookupKeys, maxLookupBytes, maxOutputKeys, maxStateBytes, sorted = false } = {}) {
765
+ const args = { file }
766
+ if (columns !== undefined) args.columns = columns
767
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
768
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
769
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
770
+ if (maxOutputKeys !== undefined) args.max_output_keys = maxOutputKeys
771
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
772
+ if (sorted) args.sorted = true
773
+ return { op: 'intersect', args }
774
+ },
775
+
776
+ setdiff(file, { columns, maxLookupRows, maxLookupKeys, maxLookupBytes, maxOutputKeys, maxStateBytes, sorted = false } = {}) {
777
+ const args = { file }
778
+ if (columns !== undefined) args.columns = columns
779
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
780
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
781
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
782
+ if (maxOutputKeys !== undefined) args.max_output_keys = maxOutputKeys
783
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
784
+ if (sorted) args.sorted = true
785
+ return { op: 'setdiff', args }
786
+ },
787
+
788
+ intersectAll(file, { columns, maxLookupRows, maxLookupKeys, maxLookupBytes, maxStateBytes, sorted = false } = {}) {
789
+ const args = { file }
790
+ if (columns !== undefined) args.columns = columns
791
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
792
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
793
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
794
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
795
+ if (sorted) args.sorted = true
796
+ return { op: 'intersect-all', args }
797
+ },
798
+
799
+ setdiffAll(file, { columns, maxLookupRows, maxLookupKeys, maxLookupBytes, maxStateBytes, sorted = false } = {}) {
800
+ const args = { file }
801
+ if (columns !== undefined) args.columns = columns
802
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
803
+ if (maxLookupKeys !== undefined) args.max_lookup_keys = maxLookupKeys
804
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
805
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
806
+ if (sorted) args.sorted = true
807
+ return { op: 'setdiff-all', args }
808
+ },
809
+
810
+ union(file, { columns, maxLookupRows, maxLookupBytes, maxOutputKeys, maxStateBytes, sorted = false } = {}) {
811
+ const args = { file }
812
+ if (columns !== undefined) args.columns = columns
813
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
814
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
815
+ if (maxOutputKeys !== undefined) args.max_output_keys = maxOutputKeys
816
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
817
+ if (sorted) args.sorted = true
818
+ return { op: 'union', args }
819
+ },
820
+
821
+ unionAll(file, { maxLookupRows, maxLookupBytes } = {}) {
822
+ const args = { file }
823
+ if (maxLookupRows !== undefined) args.max_lookup_rows = maxLookupRows
824
+ if (maxLookupBytes !== undefined) args.max_lookup_bytes = maxLookupBytes
825
+ return { op: 'union-all', args }
826
+ },
827
+
274
828
  stack(file, { tag, tagValue } = {}) {
275
829
  const args = { file }
276
830
  if (tag) args.tag = tag
@@ -285,14 +839,48 @@ export const ops = {
285
839
  return { op: 'lead', args }
286
840
  },
287
841
 
288
- dateTrunc(column, trunc, { result } = {}) {
842
+ lag(column, { offset = 1, result } = {}) {
843
+ const args = { column }
844
+ if (offset !== 1) args.offset = offset
845
+ if (result) args.result = result
846
+ return { op: 'lag', args }
847
+ },
848
+
849
+ shift(column, { offset = 1, result, type = 'lag' } = {}) {
850
+ const args = { column }
851
+ if (offset !== 1) args.offset = offset
852
+ if (result) args.result = result
853
+ if (type !== 'lag') args.type = type
854
+ return { op: 'shift', args }
855
+ },
856
+
857
+ rowid(columns, { result, sorted = false, maxKeys, maxStateBytes } = {}) {
858
+ const args = {}
859
+ if (columns !== undefined && columns !== null) args.columns = Array.isArray(columns) ? columns : [columns]
860
+ if (result) args.result = result
861
+ if (sorted) args.sorted = true
862
+ if (maxKeys !== undefined) args.max_keys = maxKeys
863
+ if (maxStateBytes !== undefined) args.max_state_bytes = maxStateBytes
864
+ return { op: 'rowid', args }
865
+ },
866
+
867
+ rleid(columns, { result } = {}) {
868
+ const args = { columns: Array.isArray(columns) ? columns : [columns] }
869
+ if (result) args.result = result
870
+ return { op: 'rleid', args }
871
+ },
872
+
873
+ dateTrunc(column, trunc, { result, missing, onTypeError, on_type_error } = {}) {
289
874
  const args = { column, trunc }
290
875
  if (result) args.result = result
876
+ if (missing !== undefined) args.missing = missing
877
+ if (onTypeError !== undefined) args.on_type_error = onTypeError
878
+ if (on_type_error !== undefined) args.on_type_error = on_type_error
291
879
  return { op: 'date-trunc', args }
292
880
  }
293
881
  }
294
882
 
295
- export const io = {
883
+ const io = {
296
884
  read: {
297
885
  file(path) {
298
886
  return { op: 'io.read.file', args: { path } }
@@ -304,3 +892,34 @@ export const io = {
304
892
  }
305
893
  }
306
894
  }
895
+
896
+ const {
897
+ TranfiTransformError,
898
+ TransformRecipe,
899
+ TransformAnalyzer,
900
+ TransformPlan,
901
+ TransformApply,
902
+ safeTransformLimits
903
+ } = require('./transform.js')
904
+
905
+ module.exports = {
906
+ Pipeline,
907
+ PipelineResult,
908
+ compileDsl,
909
+ compileToSql,
910
+ loadRecipe,
911
+ saveRecipe,
912
+ recipes,
913
+ pipeline,
914
+ param,
915
+ expr,
916
+ codec,
917
+ ops,
918
+ io,
919
+ TranfiTransformError,
920
+ TransformRecipe,
921
+ TransformAnalyzer,
922
+ TransformPlan,
923
+ TransformApply,
924
+ safeTransformLimits
925
+ }