@caracal-lynx/sluice 0.1.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 (281) hide show
  1. package/CLAUDE.md +1822 -0
  2. package/LICENCE-FAQ.md +74 -0
  3. package/LICENSE +92 -0
  4. package/README.md +582 -0
  5. package/dist/adapters/source/csv.d.ts +10 -0
  6. package/dist/adapters/source/csv.d.ts.map +1 -0
  7. package/dist/adapters/source/csv.js +110 -0
  8. package/dist/adapters/source/csv.js.map +1 -0
  9. package/dist/adapters/source/index.d.ts +9 -0
  10. package/dist/adapters/source/index.d.ts.map +1 -0
  11. package/dist/adapters/source/index.js +26 -0
  12. package/dist/adapters/source/index.js.map +1 -0
  13. package/dist/adapters/source/mssql.d.ts +11 -0
  14. package/dist/adapters/source/mssql.d.ts.map +1 -0
  15. package/dist/adapters/source/mssql.js +230 -0
  16. package/dist/adapters/source/mssql.js.map +1 -0
  17. package/dist/adapters/source/pg.d.ts +11 -0
  18. package/dist/adapters/source/pg.d.ts.map +1 -0
  19. package/dist/adapters/source/pg.js +88 -0
  20. package/dist/adapters/source/pg.js.map +1 -0
  21. package/dist/adapters/source/registry.d.ts +10 -0
  22. package/dist/adapters/source/registry.d.ts.map +1 -0
  23. package/dist/adapters/source/registry.js +36 -0
  24. package/dist/adapters/source/registry.js.map +1 -0
  25. package/dist/adapters/source/rest.d.ts +16 -0
  26. package/dist/adapters/source/rest.d.ts.map +1 -0
  27. package/dist/adapters/source/rest.js +182 -0
  28. package/dist/adapters/source/rest.js.map +1 -0
  29. package/dist/adapters/source/rest.types.d.ts +15 -0
  30. package/dist/adapters/source/rest.types.d.ts.map +1 -0
  31. package/dist/adapters/source/rest.types.js +6 -0
  32. package/dist/adapters/source/rest.types.js.map +1 -0
  33. package/dist/adapters/source/types.d.ts +23 -0
  34. package/dist/adapters/source/types.d.ts.map +1 -0
  35. package/dist/adapters/source/types.js +4 -0
  36. package/dist/adapters/source/types.js.map +1 -0
  37. package/dist/adapters/source/xlsx.d.ts +10 -0
  38. package/dist/adapters/source/xlsx.d.ts.map +1 -0
  39. package/dist/adapters/source/xlsx.js +71 -0
  40. package/dist/adapters/source/xlsx.js.map +1 -0
  41. package/dist/adapters/target/bc.d.ts +21 -0
  42. package/dist/adapters/target/bc.d.ts.map +1 -0
  43. package/dist/adapters/target/bc.js +188 -0
  44. package/dist/adapters/target/bc.js.map +1 -0
  45. package/dist/adapters/target/bluecherry.d.ts +10 -0
  46. package/dist/adapters/target/bluecherry.d.ts.map +1 -0
  47. package/dist/adapters/target/bluecherry.js +127 -0
  48. package/dist/adapters/target/bluecherry.js.map +1 -0
  49. package/dist/adapters/target/csv.d.ts +10 -0
  50. package/dist/adapters/target/csv.d.ts.map +1 -0
  51. package/dist/adapters/target/csv.js +40 -0
  52. package/dist/adapters/target/csv.js.map +1 -0
  53. package/dist/adapters/target/ifs.d.ts +10 -0
  54. package/dist/adapters/target/ifs.d.ts.map +1 -0
  55. package/dist/adapters/target/ifs.js +55 -0
  56. package/dist/adapters/target/ifs.js.map +1 -0
  57. package/dist/adapters/target/index.d.ts +8 -0
  58. package/dist/adapters/target/index.d.ts.map +1 -0
  59. package/dist/adapters/target/index.js +22 -0
  60. package/dist/adapters/target/index.js.map +1 -0
  61. package/dist/adapters/target/pg.d.ts +11 -0
  62. package/dist/adapters/target/pg.d.ts.map +1 -0
  63. package/dist/adapters/target/pg.js +103 -0
  64. package/dist/adapters/target/pg.js.map +1 -0
  65. package/dist/adapters/target/registry.d.ts +9 -0
  66. package/dist/adapters/target/registry.d.ts.map +1 -0
  67. package/dist/adapters/target/registry.js +29 -0
  68. package/dist/adapters/target/registry.js.map +1 -0
  69. package/dist/adapters/target/types.d.ts +15 -0
  70. package/dist/adapters/target/types.d.ts.map +1 -0
  71. package/dist/adapters/target/types.js +4 -0
  72. package/dist/adapters/target/types.js.map +1 -0
  73. package/dist/cli.d.ts +25 -0
  74. package/dist/cli.d.ts.map +1 -0
  75. package/dist/cli.js +354 -0
  76. package/dist/cli.js.map +1 -0
  77. package/dist/config/index.d.ts +4 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/loader.d.ts +5 -0
  82. package/dist/config/loader.d.ts.map +1 -0
  83. package/dist/config/loader.js +135 -0
  84. package/dist/config/loader.js.map +1 -0
  85. package/dist/config/schema.d.ts +4162 -0
  86. package/dist/config/schema.d.ts.map +1 -0
  87. package/dist/config/schema.js +263 -0
  88. package/dist/config/schema.js.map +1 -0
  89. package/dist/config/types.d.ts +3 -0
  90. package/dist/config/types.d.ts.map +1 -0
  91. package/dist/config/types.js +4 -0
  92. package/dist/config/types.js.map +1 -0
  93. package/dist/dq/engine.d.ts +10 -0
  94. package/dist/dq/engine.d.ts.map +1 -0
  95. package/dist/dq/engine.js +114 -0
  96. package/dist/dq/engine.js.map +1 -0
  97. package/dist/dq/index.d.ts +6 -0
  98. package/dist/dq/index.d.ts.map +1 -0
  99. package/dist/dq/index.js +6 -0
  100. package/dist/dq/index.js.map +1 -0
  101. package/dist/dq/reporter.d.ts +5 -0
  102. package/dist/dq/reporter.d.ts.map +1 -0
  103. package/dist/dq/reporter.js +41 -0
  104. package/dist/dq/reporter.js.map +1 -0
  105. package/dist/dq/rules/allowedValues.d.ts +7 -0
  106. package/dist/dq/rules/allowedValues.d.ts.map +1 -0
  107. package/dist/dq/rules/allowedValues.js +26 -0
  108. package/dist/dq/rules/allowedValues.js.map +1 -0
  109. package/dist/dq/rules/email.d.ts +7 -0
  110. package/dist/dq/rules/email.d.ts.map +1 -0
  111. package/dist/dq/rules/email.js +24 -0
  112. package/dist/dq/rules/email.js.map +1 -0
  113. package/dist/dq/rules/index.d.ts +15 -0
  114. package/dist/dq/rules/index.d.ts.map +1 -0
  115. package/dist/dq/rules/index.js +30 -0
  116. package/dist/dq/rules/index.js.map +1 -0
  117. package/dist/dq/rules/maxLength.d.ts +7 -0
  118. package/dist/dq/rules/maxLength.d.ts.map +1 -0
  119. package/dist/dq/rules/maxLength.js +25 -0
  120. package/dist/dq/rules/maxLength.js.map +1 -0
  121. package/dist/dq/rules/minMax.d.ts +11 -0
  122. package/dist/dq/rules/minMax.d.ts.map +1 -0
  123. package/dist/dq/rules/minMax.js +52 -0
  124. package/dist/dq/rules/minMax.js.map +1 -0
  125. package/dist/dq/rules/notNull.d.ts +7 -0
  126. package/dist/dq/rules/notNull.d.ts.map +1 -0
  127. package/dist/dq/rules/notNull.js +21 -0
  128. package/dist/dq/rules/notNull.js.map +1 -0
  129. package/dist/dq/rules/pattern.d.ts +7 -0
  130. package/dist/dq/rules/pattern.d.ts.map +1 -0
  131. package/dist/dq/rules/pattern.js +31 -0
  132. package/dist/dq/rules/pattern.js.map +1 -0
  133. package/dist/dq/rules/types.d.ts +6 -0
  134. package/dist/dq/rules/types.d.ts.map +1 -0
  135. package/dist/dq/rules/types.js +4 -0
  136. package/dist/dq/rules/types.js.map +1 -0
  137. package/dist/dq/rules/ukPostcode.d.ts +7 -0
  138. package/dist/dq/rules/ukPostcode.d.ts.map +1 -0
  139. package/dist/dq/rules/ukPostcode.js +24 -0
  140. package/dist/dq/rules/ukPostcode.js.map +1 -0
  141. package/dist/dq/rules/unique.d.ts +14 -0
  142. package/dist/dq/rules/unique.d.ts.map +1 -0
  143. package/dist/dq/rules/unique.js +9 -0
  144. package/dist/dq/rules/unique.js.map +1 -0
  145. package/dist/dq/types.d.ts +29 -0
  146. package/dist/dq/types.d.ts.map +1 -0
  147. package/dist/dq/types.js +4 -0
  148. package/dist/dq/types.js.map +1 -0
  149. package/dist/enrich/types.d.ts +87 -0
  150. package/dist/enrich/types.d.ts.map +1 -0
  151. package/dist/enrich/types.js +4 -0
  152. package/dist/enrich/types.js.map +1 -0
  153. package/dist/index.d.ts +17 -0
  154. package/dist/index.d.ts.map +1 -0
  155. package/dist/index.js +17 -0
  156. package/dist/index.js.map +1 -0
  157. package/dist/merge/conflict-log.d.ts +9 -0
  158. package/dist/merge/conflict-log.d.ts.map +1 -0
  159. package/dist/merge/conflict-log.js +28 -0
  160. package/dist/merge/conflict-log.js.map +1 -0
  161. package/dist/merge/engine.d.ts +7 -0
  162. package/dist/merge/engine.d.ts.map +1 -0
  163. package/dist/merge/engine.js +19 -0
  164. package/dist/merge/engine.js.map +1 -0
  165. package/dist/merge/index.d.ts +11 -0
  166. package/dist/merge/index.d.ts.map +1 -0
  167. package/dist/merge/index.js +34 -0
  168. package/dist/merge/index.js.map +1 -0
  169. package/dist/merge/sql-builder.d.ts +19 -0
  170. package/dist/merge/sql-builder.d.ts.map +1 -0
  171. package/dist/merge/sql-builder.js +148 -0
  172. package/dist/merge/sql-builder.js.map +1 -0
  173. package/dist/merge/strategies/coalesce.d.ts +17 -0
  174. package/dist/merge/strategies/coalesce.d.ts.map +1 -0
  175. package/dist/merge/strategies/coalesce.js +77 -0
  176. package/dist/merge/strategies/coalesce.js.map +1 -0
  177. package/dist/merge/strategies/index.d.ts +5 -0
  178. package/dist/merge/strategies/index.d.ts.map +1 -0
  179. package/dist/merge/strategies/index.js +7 -0
  180. package/dist/merge/strategies/index.js.map +1 -0
  181. package/dist/merge/strategies/intersect.d.ts +17 -0
  182. package/dist/merge/strategies/intersect.d.ts.map +1 -0
  183. package/dist/merge/strategies/intersect.js +75 -0
  184. package/dist/merge/strategies/intersect.js.map +1 -0
  185. package/dist/merge/strategies/priority-override.d.ts +16 -0
  186. package/dist/merge/strategies/priority-override.d.ts.map +1 -0
  187. package/dist/merge/strategies/priority-override.js +78 -0
  188. package/dist/merge/strategies/priority-override.js.map +1 -0
  189. package/dist/merge/strategies/registry.d.ts +8 -0
  190. package/dist/merge/strategies/registry.d.ts.map +1 -0
  191. package/dist/merge/strategies/registry.js +19 -0
  192. package/dist/merge/strategies/registry.js.map +1 -0
  193. package/dist/merge/strategies/union.d.ts +15 -0
  194. package/dist/merge/strategies/union.d.ts.map +1 -0
  195. package/dist/merge/strategies/union.js +75 -0
  196. package/dist/merge/strategies/union.js.map +1 -0
  197. package/dist/merge/types.d.ts +24 -0
  198. package/dist/merge/types.d.ts.map +1 -0
  199. package/dist/merge/types.js +4 -0
  200. package/dist/merge/types.js.map +1 -0
  201. package/dist/multi-source-runner.d.ts +22 -0
  202. package/dist/multi-source-runner.d.ts.map +1 -0
  203. package/dist/multi-source-runner.js +398 -0
  204. package/dist/multi-source-runner.js.map +1 -0
  205. package/dist/plugins/index.d.ts +4 -0
  206. package/dist/plugins/index.d.ts.map +1 -0
  207. package/dist/plugins/index.js +5 -0
  208. package/dist/plugins/index.js.map +1 -0
  209. package/dist/plugins/loader.d.ts +22 -0
  210. package/dist/plugins/loader.d.ts.map +1 -0
  211. package/dist/plugins/loader.js +151 -0
  212. package/dist/plugins/loader.js.map +1 -0
  213. package/dist/plugins/registry.d.ts +25 -0
  214. package/dist/plugins/registry.d.ts.map +1 -0
  215. package/dist/plugins/registry.js +42 -0
  216. package/dist/plugins/registry.js.map +1 -0
  217. package/dist/plugins/types.d.ts +61 -0
  218. package/dist/plugins/types.d.ts.map +1 -0
  219. package/dist/plugins/types.js +4 -0
  220. package/dist/plugins/types.js.map +1 -0
  221. package/dist/runner.d.ts +97 -0
  222. package/dist/runner.d.ts.map +1 -0
  223. package/dist/runner.js +520 -0
  224. package/dist/runner.js.map +1 -0
  225. package/dist/staging/index.d.ts +3 -0
  226. package/dist/staging/index.d.ts.map +1 -0
  227. package/dist/staging/index.js +5 -0
  228. package/dist/staging/index.js.map +1 -0
  229. package/dist/staging/schema.d.ts +19 -0
  230. package/dist/staging/schema.d.ts.map +1 -0
  231. package/dist/staging/schema.js +15 -0
  232. package/dist/staging/schema.js.map +1 -0
  233. package/dist/staging/store.d.ts +71 -0
  234. package/dist/staging/store.d.ts.map +1 -0
  235. package/dist/staging/store.js +270 -0
  236. package/dist/staging/store.js.map +1 -0
  237. package/dist/transform/cleanse.d.ts +2 -0
  238. package/dist/transform/cleanse.d.ts.map +1 -0
  239. package/dist/transform/cleanse.js +59 -0
  240. package/dist/transform/cleanse.js.map +1 -0
  241. package/dist/transform/engine.d.ts +10 -0
  242. package/dist/transform/engine.d.ts.map +1 -0
  243. package/dist/transform/engine.js +225 -0
  244. package/dist/transform/engine.js.map +1 -0
  245. package/dist/transform/expression.d.ts +5 -0
  246. package/dist/transform/expression.d.ts.map +1 -0
  247. package/dist/transform/expression.js +52 -0
  248. package/dist/transform/expression.js.map +1 -0
  249. package/dist/transform/index.d.ts +6 -0
  250. package/dist/transform/index.d.ts.map +1 -0
  251. package/dist/transform/index.js +7 -0
  252. package/dist/transform/index.js.map +1 -0
  253. package/dist/transform/lookup.d.ts +10 -0
  254. package/dist/transform/lookup.d.ts.map +1 -0
  255. package/dist/transform/lookup.js +66 -0
  256. package/dist/transform/lookup.js.map +1 -0
  257. package/dist/transform/types.d.ts +10 -0
  258. package/dist/transform/types.d.ts.map +1 -0
  259. package/dist/transform/types.js +4 -0
  260. package/dist/transform/types.js.map +1 -0
  261. package/dist/utils/env.d.ts +3 -0
  262. package/dist/utils/env.d.ts.map +1 -0
  263. package/dist/utils/env.js +26 -0
  264. package/dist/utils/env.js.map +1 -0
  265. package/dist/utils/errors.d.ts +26 -0
  266. package/dist/utils/errors.d.ts.map +1 -0
  267. package/dist/utils/errors.js +39 -0
  268. package/dist/utils/errors.js.map +1 -0
  269. package/dist/utils/index.d.ts +5 -0
  270. package/dist/utils/index.d.ts.map +1 -0
  271. package/dist/utils/index.js +7 -0
  272. package/dist/utils/index.js.map +1 -0
  273. package/dist/utils/logger.d.ts +14 -0
  274. package/dist/utils/logger.d.ts.map +1 -0
  275. package/dist/utils/logger.js +16 -0
  276. package/dist/utils/logger.js.map +1 -0
  277. package/dist/utils/progress.d.ts +66 -0
  278. package/dist/utils/progress.d.ts.map +1 -0
  279. package/dist/utils/progress.js +283 -0
  280. package/dist/utils/progress.js.map +1 -0
  281. package/package.json +92 -0
@@ -0,0 +1,225 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * TransformEngine — reads rows from `sourceTable`, applies field mappings
5
+ * (cleanse ops, type coercion, lookups, expressions, constants, concat, custom
6
+ * plugins), and writes to `targetTable`. Both tables default to
7
+ * `stg_raw` / `stg_transformed` so callers can reuse the engine for both the
8
+ * single-source path and the post-merge multi-source path.
9
+ *
10
+ * Every output column is stored as VARCHAR in the staging store. Target
11
+ * adapters re-emit as needed; DuckDB serialises values losslessly through
12
+ * the string representation.
13
+ */
14
+ import dayjs from 'dayjs';
15
+ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
16
+ import { TransformRegistry } from '../plugins/registry.js';
17
+ import { quoteIdent } from '../staging/index.js';
18
+ import { TransformError } from '../utils/errors.js';
19
+ import { logger } from '../utils/logger.js';
20
+ import { applyCleanse } from './cleanse.js';
21
+ import { ExpressionEvaluator } from './expression.js';
22
+ import { LookupResolver } from './lookup.js';
23
+ dayjs.extend(customParseFormat);
24
+ export class TransformEngine {
25
+ transforms;
26
+ constructor(transforms = new TransformRegistry()) {
27
+ this.transforms = transforms;
28
+ }
29
+ async run(config, store, sourceTable = 'stg_raw', targetTable = 'stg_transformed', onProgress) {
30
+ const lookups = new LookupResolver();
31
+ await lookups.loadAll(config, config.run);
32
+ const expressionEval = new ExpressionEvaluator();
33
+ const outputColumns = config.transform.fields.map((f) => ({
34
+ name: f.to,
35
+ duckDbType: 'VARCHAR',
36
+ }));
37
+ await store.dropTable(targetTable);
38
+ await store.createTable(targetTable, outputColumns);
39
+ const rows = await store.query(`SELECT * FROM ${quoteIdent(sourceTable)}`);
40
+ const outputBatch = [];
41
+ const outputDateFormat = config.target.dateFormat;
42
+ let rowsFailed = 0;
43
+ for (let i = 0; i < rows.length; i++) {
44
+ const row = rows[i];
45
+ try {
46
+ const outRow = {};
47
+ for (const field of config.transform.fields) {
48
+ outRow[field.to] = applyFieldMapping(field, row, lookups, expressionEval, this.transforms, outputDateFormat);
49
+ }
50
+ outputBatch.push(outRow);
51
+ if (outputBatch.length >= config.run.batchSize) {
52
+ await store.insertBatch(targetTable, outputBatch);
53
+ outputBatch.length = 0;
54
+ if (onProgress)
55
+ onProgress(i + 1);
56
+ }
57
+ }
58
+ catch (err) {
59
+ rowsFailed++;
60
+ if (config.run.onError === 'stop') {
61
+ throw err instanceof TransformError
62
+ ? err
63
+ : new TransformError(`transform failed at row ${i}: ${String(err)}`, err);
64
+ }
65
+ logger.warn({ rowIndex: i, err: err instanceof Error ? err.message : String(err) }, 'transform: row failed (onError: continue)');
66
+ }
67
+ }
68
+ if (outputBatch.length > 0) {
69
+ await store.insertBatch(targetTable, outputBatch);
70
+ }
71
+ if (onProgress)
72
+ onProgress(rows.length);
73
+ const rowsOut = await store.rowCount(targetTable);
74
+ return { rowsIn: rows.length, rowsOut, rowsFailed };
75
+ }
76
+ }
77
+ function applyFieldMapping(field, row, lookups, expr, transforms, outputDateFormat) {
78
+ // ── Types that do not read `from` directly ──────────────────────────────
79
+ if (field.type === 'constant') {
80
+ return field.value ?? null;
81
+ }
82
+ if (field.type === 'expression') {
83
+ if (typeof field.value !== 'string') {
84
+ throw new TransformError(`expression field "${field.to}" requires string 'value'`);
85
+ }
86
+ return expr.evaluate(field.value, row);
87
+ }
88
+ if (field.type === 'custom') {
89
+ if (!field.customOp) {
90
+ throw new TransformError(`custom field "${field.to}" requires 'customOp'`);
91
+ }
92
+ const plugin = transforms.get(field.customOp);
93
+ if (!plugin) {
94
+ throw new TransformError(`No custom transform plugin registered for "${field.customOp}"`);
95
+ }
96
+ const value = typeof field.from === 'string' ? row[field.from] : undefined;
97
+ // Apply default/optional logic before calling plugin
98
+ if (value === null || value === undefined || value === '') {
99
+ if (field.default !== undefined && field.default !== null) {
100
+ return field.default;
101
+ }
102
+ else if (field.optional) {
103
+ return null;
104
+ }
105
+ }
106
+ // FieldMapping is schema-validated but not modeled as a discriminated union,
107
+ // so we narrow to the custom mapping shape at this call site.
108
+ const result = plugin.apply(value, row, field);
109
+ // Apply default/optional logic after plugin returns
110
+ if (result === null || result === undefined) {
111
+ if (field.default !== undefined && field.default !== null) {
112
+ return field.default;
113
+ }
114
+ else if (field.optional) {
115
+ return null;
116
+ }
117
+ }
118
+ return result;
119
+ }
120
+ // ── concat: join from[] with separator, then cleanse ────────────────────
121
+ if (field.type === 'concat') {
122
+ if (!Array.isArray(field.from)) {
123
+ throw new TransformError(`concat field "${field.to}" requires array 'from'`);
124
+ }
125
+ const sep = field.separator ?? ' ';
126
+ const parts = field.from.map((f) => {
127
+ const v = row[f];
128
+ return v === null || v === undefined ? '' : String(v);
129
+ });
130
+ let value = parts.join(sep);
131
+ if (field.cleanse)
132
+ value = applyCleanse(value, field.cleanse);
133
+ if (value === null || value === undefined || value === '') {
134
+ return applyDefaultOrOptional(field, value);
135
+ }
136
+ return String(value);
137
+ }
138
+ // ── lookup: resolve via LookupResolver ──────────────────────────────────
139
+ if (field.type === 'lookup') {
140
+ if (typeof field.from !== 'string') {
141
+ throw new TransformError(`lookup field "${field.to}" requires string 'from'`);
142
+ }
143
+ if (!field.lookup) {
144
+ throw new TransformError(`lookup field "${field.to}" requires 'lookup'`);
145
+ }
146
+ const sourceValue = row[field.from];
147
+ const resolved = lookups.resolve(field.lookup, sourceValue);
148
+ if (resolved !== undefined)
149
+ return resolved;
150
+ if (field.default !== undefined && field.default !== null)
151
+ return field.default;
152
+ if (field.optional)
153
+ return null;
154
+ throw new TransformError(`lookup "${field.lookup}" missed value "${String(sourceValue)}" for field "${field.to}"`);
155
+ }
156
+ // ── Scalar types: string, number, decimal, boolean, date ─────────────────
157
+ if (typeof field.from !== 'string') {
158
+ throw new TransformError(`field "${field.to}" of type ${field.type} requires string 'from'`);
159
+ }
160
+ let value = row[field.from];
161
+ // Default + optional: null/empty handling
162
+ if (value === null || value === undefined || value === '') {
163
+ if (field.default !== undefined && field.default !== null) {
164
+ value = field.default;
165
+ }
166
+ else if (field.optional) {
167
+ return null;
168
+ }
169
+ else if (field.type === 'string') {
170
+ // Empty strings pass through as-is for strings unless optional/default
171
+ value = value === null || value === undefined ? null : '';
172
+ }
173
+ }
174
+ if (field.cleanse && value !== null && value !== undefined) {
175
+ value = applyCleanse(value, field.cleanse);
176
+ }
177
+ if (value === null || value === undefined)
178
+ return null;
179
+ switch (field.type) {
180
+ case 'string': {
181
+ let s = String(value);
182
+ if (typeof field.max === 'number')
183
+ s = s.slice(0, field.max);
184
+ return s;
185
+ }
186
+ case 'number': {
187
+ const n = Number(value);
188
+ if (!Number.isFinite(n)) {
189
+ throw new TransformError(`field "${field.to}" value "${String(value)}" is not a number`);
190
+ }
191
+ return Math.round(n);
192
+ }
193
+ case 'decimal': {
194
+ const n = parseFloat(String(value));
195
+ if (!Number.isFinite(n)) {
196
+ throw new TransformError(`field "${field.to}" value "${String(value)}" is not a decimal`);
197
+ }
198
+ return n.toFixed(field.precision ?? 2);
199
+ }
200
+ case 'boolean': {
201
+ return ['1', 'true', 'yes', 'y', 't'].includes(String(value).toLowerCase())
202
+ ? 'true'
203
+ : 'false';
204
+ }
205
+ case 'date': {
206
+ const parsed = field.format
207
+ ? dayjs(String(value), field.format, true)
208
+ : dayjs(String(value));
209
+ if (!parsed.isValid()) {
210
+ throw new TransformError(`field "${field.to}" value "${String(value)}" is not a valid date (format: ${field.format ?? 'ISO'})`);
211
+ }
212
+ return outputDateFormat ? parsed.format(outputDateFormat) : parsed.toISOString();
213
+ }
214
+ }
215
+ // Unreachable — all cases covered above
216
+ return value;
217
+ }
218
+ function applyDefaultOrOptional(field, value) {
219
+ if (field.default !== undefined && field.default !== null)
220
+ return field.default;
221
+ if (field.optional)
222
+ return null;
223
+ return value;
224
+ }
225
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/transform/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare class ExpressionEvaluator {
2
+ private readonly warnedExpressions;
3
+ evaluate(expression: string, row: Record<string, unknown>): unknown;
4
+ }
5
+ //# sourceMappingURL=expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../src/transform/expression.ts"],"names":[],"mappings":"AAsBA,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IAEvD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;CAwCpE"}
@@ -0,0 +1,52 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * Expression evaluator.
5
+ *
6
+ * Two dispatch paths per CLAUDE.md:
7
+ * - No `js:` prefix → expr-eval Parser (safe, limited to arithmetic + member access).
8
+ * - `js:` prefix → vm.runInNewContext with a restricted global set.
9
+ *
10
+ * Neither path uses `eval()` or `new Function()`.
11
+ */
12
+ import { runInNewContext } from 'node:vm';
13
+ import { Parser } from 'expr-eval';
14
+ import { ExpressionError } from '../utils/errors.js';
15
+ import { logger } from '../utils/logger.js';
16
+ const parser = new Parser();
17
+ export class ExpressionEvaluator {
18
+ warnedExpressions = new Set();
19
+ evaluate(expression, row) {
20
+ if (expression.startsWith('js:')) {
21
+ const code = expression.slice(3).trim();
22
+ if (!this.warnedExpressions.has(code)) {
23
+ this.warnedExpressions.add(code);
24
+ logger.warn({ expression: code }, 'expression: using js: path (vm.runInNewContext)');
25
+ }
26
+ try {
27
+ return runInNewContext(code, {
28
+ row,
29
+ Date,
30
+ Math,
31
+ JSON,
32
+ String,
33
+ Number,
34
+ Boolean,
35
+ }, { timeout: 1000 });
36
+ }
37
+ catch (err) {
38
+ throw new ExpressionError(`js expression failed: ${err instanceof Error ? err.message : String(err)}`, err);
39
+ }
40
+ }
41
+ try {
42
+ // expr-eval's Value type is narrower than Record<string, unknown>, but
43
+ // at runtime it only traverses property access — non-primitive leaves
44
+ // are fine as long as the expression doesn't operate on them.
45
+ return parser.parse(expression).evaluate({ row });
46
+ }
47
+ catch (err) {
48
+ throw new ExpressionError(`expr-eval expression failed: ${err instanceof Error ? err.message : String(err)}`, err);
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.js","sourceRoot":"","sources":["../../src/transform/expression.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAc,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;AAE5B,MAAM,OAAO,mBAAmB;IACb,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvD,QAAQ,CAAC,UAAkB,EAAE,GAA4B;QACvD,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,iDAAiD,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,eAAe,CACpB,IAAI,EACJ;oBACE,GAAG;oBACH,IAAI;oBACJ,IAAI;oBACJ,IAAI;oBACJ,MAAM;oBACN,MAAM;oBACN,OAAO;iBACR,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,eAAe,CACvB,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC3E,GAAG,CACJ,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,uEAAuE;YACvE,sEAAsE;YACtE,8DAA8D;YAC9D,OAAO,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAsB,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,eAAe,CACvB,gCAAgC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAClF,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export { applyCleanse } from './cleanse.js';
2
+ export { TransformEngine } from './engine.js';
3
+ export { ExpressionEvaluator } from './expression.js';
4
+ export { LookupResolver } from './lookup.js';
5
+ export type { TransformResult } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transform/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ export { applyCleanse } from './cleanse.js';
4
+ export { TransformEngine } from './engine.js';
5
+ export { ExpressionEvaluator } from './expression.js';
6
+ export { LookupResolver } from './lookup.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transform/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Pipeline, RunConfig } from '../config/types.js';
2
+ export declare class LookupResolver {
3
+ private readonly tables;
4
+ loadAll(config: Pipeline, runConfig: RunConfig): Promise<void>;
5
+ /** Returns the resolved value, or undefined on miss. */
6
+ resolve(lookupName: string, key: unknown): string | undefined;
7
+ /** Primarily for tests. */
8
+ getTable(name: string): ReadonlyMap<string, string> | undefined;
9
+ }
10
+ //# sourceMappingURL=lookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../../src/transform/lookup.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAK9D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IAE3D,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCpE,wDAAwD;IACxD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAS7D,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;CAGhE"}
@@ -0,0 +1,66 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * LookupResolver — preloads every `transform.lookups[]` entry into an
5
+ * in-memory Map<string, string> keyed by name. Values stringified.
6
+ *
7
+ * Each lookup entry has its own `source` config (any source adapter works),
8
+ * so this resolver re-uses the global SourceAdapterRegistry to extract the
9
+ * lookup table into a temporary `:memory:` staging store, then copies the
10
+ * key/value pairs into the cache.
11
+ */
12
+ import { SourceAdapterRegistry } from '../adapters/source/index.js';
13
+ import { StagingStore, quoteIdent } from '../staging/index.js';
14
+ import { TransformError } from '../utils/errors.js';
15
+ import { logger } from '../utils/logger.js';
16
+ export class LookupResolver {
17
+ tables = new Map();
18
+ async loadAll(config, runConfig) {
19
+ for (const lookup of config.transform.lookups) {
20
+ if (this.tables.has(lookup.name)) {
21
+ throw new TransformError(`Duplicate lookup name: "${lookup.name}"`);
22
+ }
23
+ const adapter = SourceAdapterRegistry.get(lookup.source.adapter);
24
+ const tempStore = new StagingStore(':memory:');
25
+ await tempStore.open();
26
+ try {
27
+ await adapter.connect(lookup.source);
28
+ try {
29
+ await adapter.extract(lookup.source, tempStore, runConfig, () => { }, 'stg_lookup');
30
+ }
31
+ finally {
32
+ await adapter.disconnect();
33
+ }
34
+ const rows = await tempStore.query(`SELECT ${quoteIdent(lookup.key)} AS k, ${quoteIdent(lookup.value)} AS v FROM stg_lookup`);
35
+ const map = new Map();
36
+ for (const row of rows) {
37
+ const k = row['k'];
38
+ const v = row['v'];
39
+ if (k === null || k === undefined)
40
+ continue;
41
+ map.set(String(k), v === null || v === undefined ? '' : String(v));
42
+ }
43
+ this.tables.set(lookup.name, map);
44
+ logger.debug({ lookup: lookup.name, entries: map.size }, 'lookup: loaded');
45
+ }
46
+ finally {
47
+ await tempStore.close();
48
+ }
49
+ }
50
+ }
51
+ /** Returns the resolved value, or undefined on miss. */
52
+ resolve(lookupName, key) {
53
+ const table = this.tables.get(lookupName);
54
+ if (!table) {
55
+ throw new TransformError(`Unknown lookup: "${lookupName}"`);
56
+ }
57
+ if (key === null || key === undefined || key === '')
58
+ return undefined;
59
+ return table.get(String(key));
60
+ }
61
+ /** Primarily for tests. */
62
+ getTable(name) {
63
+ return this.tables.get(name);
64
+ }
65
+ }
66
+ //# sourceMappingURL=lookup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup.js","sourceRoot":"","sources":["../../src/transform/lookup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Transform engine result. Phase 4 runner emits a trivial pass-through count;
3
+ * Phase 6 introduces the full engine with cleanse/expression/lookup.
4
+ */
5
+ export interface TransformResult {
6
+ rowsIn: number;
7
+ rowsOut: number;
8
+ rowsFailed: number;
9
+ }
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transform/types.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transform/types.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC"}
@@ -0,0 +1,3 @@
1
+ export declare function loadEnv(envFile?: string): void;
2
+ export declare function requireEnv(name: string): string;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAQA,wBAAgB,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ9C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C"}
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ import { config as dotenvConfig } from 'dotenv';
4
+ import { ConfigError } from './errors.js';
5
+ let envLoaded = false;
6
+ export function loadEnv(envFile) {
7
+ if (envLoaded)
8
+ return;
9
+ if (envFile !== undefined) {
10
+ dotenvConfig({ path: envFile });
11
+ }
12
+ else {
13
+ dotenvConfig();
14
+ }
15
+ envLoaded = true;
16
+ }
17
+ export function requireEnv(name) {
18
+ // Treat an explicitly-set empty string as set. "Not set" means the
19
+ // variable is absent from the environment, not that it is empty.
20
+ const value = process.env[name];
21
+ if (value === undefined) {
22
+ throw new ConfigError(`Required environment variable not set: ${name}`);
23
+ }
24
+ return value;
25
+ }
26
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,UAAU,OAAO,CAAC,OAAgB;IACtC,IAAI,SAAS;QAAE,OAAO;IACtB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,YAAY,EAAE,CAAC;IACjB,CAAC;IACD,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,mEAAmE;IACnE,iEAAiE;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,WAAW,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,26 @@
1
+ export declare class PipelineError extends Error {
2
+ readonly cause?: unknown | undefined;
3
+ constructor(message: string, cause?: unknown | undefined);
4
+ }
5
+ export declare class ConfigError extends PipelineError {
6
+ }
7
+ export declare class SourceError extends PipelineError {
8
+ }
9
+ export declare class StagingError extends PipelineError {
10
+ }
11
+ export declare class DQError extends PipelineError {
12
+ }
13
+ export declare class PipelineDQError extends DQError {
14
+ readonly criticalCount: number;
15
+ readonly reportPath: string;
16
+ constructor(criticalCount: number, reportPath: string);
17
+ }
18
+ export declare class TransformError extends PipelineError {
19
+ }
20
+ export declare class ExpressionError extends TransformError {
21
+ }
22
+ export declare class LoadError extends PipelineError {
23
+ }
24
+ export declare class EnrichError extends PipelineError {
25
+ }
26
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAGA,qBAAa,aAAc,SAAQ,KAAK;aACO,KAAK,CAAC,EAAE,OAAO;gBAAhD,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,OAAO,YAAA;CAO7D;AACD,qBAAa,WAAY,SAAQ,aAAa;CAAG;AACjD,qBAAa,WAAY,SAAQ,aAAa;CAAG;AACjD,qBAAa,YAAa,SAAQ,aAAa;CAAG;AAClD,qBAAa,OAAQ,SAAQ,aAAa;CAAG;AAC7C,qBAAa,eAAgB,SAAQ,OAAO;aAExB,aAAa,EAAE,MAAM;aACrB,UAAU,EAAE,MAAM;gBADlB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM;CAIrC;AACD,qBAAa,cAAe,SAAQ,aAAa;CAAG;AACpD,qBAAa,eAAgB,SAAQ,cAAc;CAAG;AACtD,qBAAa,SAAU,SAAQ,aAAa;CAAG;AAC/C,qBAAa,WAAY,SAAQ,aAAa;CAAG"}
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ export class PipelineError extends Error {
4
+ cause;
5
+ constructor(message, cause) {
6
+ super(message);
7
+ this.cause = cause;
8
+ this.name = this.constructor.name;
9
+ if (Error.captureStackTrace) {
10
+ Error.captureStackTrace(this, this.constructor);
11
+ }
12
+ }
13
+ }
14
+ export class ConfigError extends PipelineError {
15
+ }
16
+ export class SourceError extends PipelineError {
17
+ }
18
+ export class StagingError extends PipelineError {
19
+ }
20
+ export class DQError extends PipelineError {
21
+ }
22
+ export class PipelineDQError extends DQError {
23
+ criticalCount;
24
+ reportPath;
25
+ constructor(criticalCount, reportPath) {
26
+ super(`Pipeline halted: ${criticalCount} critical DQ violations. See ${reportPath}`);
27
+ this.criticalCount = criticalCount;
28
+ this.reportPath = reportPath;
29
+ }
30
+ }
31
+ export class TransformError extends PipelineError {
32
+ }
33
+ export class ExpressionError extends TransformError {
34
+ }
35
+ export class LoadError extends PipelineError {
36
+ }
37
+ export class EnrichError extends PipelineError {
38
+ }
39
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC,MAAM,OAAO,aAAc,SAAQ,KAAK;IACO;IAA7C,YAAY,OAAe,EAAkB,KAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAU;QAE1D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;CACF;AACD,MAAM,OAAO,WAAY,SAAQ,aAAa;CAAG;AACjD,MAAM,OAAO,WAAY,SAAQ,aAAa;CAAG;AACjD,MAAM,OAAO,YAAa,SAAQ,aAAa;CAAG;AAClD,MAAM,OAAO,OAAQ,SAAQ,aAAa;CAAG;AAC7C,MAAM,OAAO,eAAgB,SAAQ,OAAO;IAExB;IACA;IAFlB,YACkB,aAAqB,EACrB,UAAkB;QAElC,KAAK,CAAC,oBAAoB,aAAa,gCAAgC,UAAU,EAAE,CAAC,CAAC;QAHrE,kBAAa,GAAb,aAAa,CAAQ;QACrB,eAAU,GAAV,UAAU,CAAQ;IAGpC,CAAC;CACF;AACD,MAAM,OAAO,cAAe,SAAQ,aAAa;CAAG;AACpD,MAAM,OAAO,eAAgB,SAAQ,cAAc;CAAG;AACtD,MAAM,OAAO,SAAU,SAAQ,aAAa;CAAG;AAC/C,MAAM,OAAO,WAAY,SAAQ,aAAa;CAAG"}
@@ -0,0 +1,5 @@
1
+ export { logger } from './logger.js';
2
+ export { loadEnv, requireEnv } from './env.js';
3
+ export { ProgressReporter, createSilentProgress, type PhaseKind, type PhaseEndState, type ProgressLogLevel, type ProgressReporterOptions, type StartPhaseOpts, type EndPhaseOpts, type SummaryOpts, } from './progress.js';
4
+ export { PipelineError, ConfigError, SourceError, StagingError, DQError, PipelineDQError, TransformError, ExpressionError, LoadError, } from './errors.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACZ,OAAO,EACP,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,GACV,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ export { logger } from './logger.js';
4
+ export { loadEnv, requireEnv } from './env.js';
5
+ export { ProgressReporter, createSilentProgress, } from './progress.js';
6
+ export { PipelineError, ConfigError, SourceError, StagingError, DQError, PipelineDQError, TransformError, ExpressionError, LoadError, } from './errors.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GAQrB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACZ,OAAO,EACP,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,GACV,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ import pino from 'pino';
2
+ /**
3
+ * Route all pino output to stderr so stdout stays dedicated to the progress
4
+ * bar rendered by `ProgressReporter`. This matches how tools like git, cargo,
5
+ * and npm separate streams:
6
+ *
7
+ * stdout → progress feedback and final summary (from ProgressReporter)
8
+ * stderr → all structured log records (info, warn, error, fatal)
9
+ *
10
+ * Operators who want just the logs in a file can use `2>run.log`; the bar
11
+ * stays visible on the terminal.
12
+ */
13
+ export declare const logger: pino.Logger<never, boolean>;
14
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,6BAGlB,CAAC"}
@@ -0,0 +1,16 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ import pino from 'pino';
4
+ /**
5
+ * Route all pino output to stderr so stdout stays dedicated to the progress
6
+ * bar rendered by `ProgressReporter`. This matches how tools like git, cargo,
7
+ * and npm separate streams:
8
+ *
9
+ * stdout → progress feedback and final summary (from ProgressReporter)
10
+ * stderr → all structured log records (info, warn, error, fatal)
11
+ *
12
+ * Operators who want just the logs in a file can use `2>run.log`; the bar
13
+ * stays visible on the terminal.
14
+ */
15
+ export const logger = pino({ level: process.env['LOG_LEVEL'] ?? 'info' }, pino.destination({ fd: 2, sync: false }));
16
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CACxB,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,MAAM,EAAE,EAC7C,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CACzC,CAAC"}