@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,110 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * CSV source adapter.
5
+ *
6
+ * - All columns inferred as VARCHAR.
7
+ * - UTF-8 BOM stripped automatically (`bom: true`).
8
+ * - Supports simple filename globs (`./data/export-*.csv`) — wildcard must
9
+ * be in the filename, not the directory.
10
+ * - Glob-matched files are concatenated into a single staging table; the
11
+ * first file's columns define the schema.
12
+ * - Rows are streamed through csv-parse and flushed to the staging store
13
+ * in batches of `runConfig.batchSize`.
14
+ *
15
+ * `targetTable` defaults to 'stg_raw' here so single-source callers don't
16
+ * have to pass it; `MultiSourcePipelineRunner` overrides per source.
17
+ */
18
+ import { createReadStream, readdirSync } from 'node:fs';
19
+ import * as path from 'node:path';
20
+ import { parse } from 'csv-parse';
21
+ import { SourceError } from '../../utils/errors.js';
22
+ import { logger } from '../../utils/logger.js';
23
+ function resolveGlob(pattern) {
24
+ if (!pattern.includes('*'))
25
+ return [pattern];
26
+ const parsed = path.parse(pattern);
27
+ if (parsed.dir.includes('*')) {
28
+ throw new SourceError(`glob wildcards are only supported in the filename: "${pattern}"`);
29
+ }
30
+ const re = new RegExp('^' + parsed.base.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') + '$');
31
+ const searchDir = parsed.dir === '' ? '.' : parsed.dir;
32
+ let entries;
33
+ try {
34
+ entries = readdirSync(searchDir);
35
+ }
36
+ catch (err) {
37
+ throw new SourceError(`could not read directory "${searchDir}" for glob "${pattern}"`, err);
38
+ }
39
+ const matches = entries
40
+ .filter((f) => re.test(f))
41
+ .map((f) => path.join(searchDir, f))
42
+ .sort();
43
+ if (matches.length === 0) {
44
+ throw new SourceError(`glob "${pattern}" matched no files`);
45
+ }
46
+ return matches;
47
+ }
48
+ export class CsvSourceAdapter {
49
+ id = 'csv';
50
+ async connect(_config) {
51
+ // CSV is file-based; no persistent connection to establish.
52
+ }
53
+ async disconnect() {
54
+ // Nothing to release.
55
+ }
56
+ async extract(config, store, runConfig, onProgress, targetTable = 'stg_raw') {
57
+ if (!config.file) {
58
+ throw new SourceError('csv source requires `file`');
59
+ }
60
+ const files = resolveGlob(config.file);
61
+ logger.debug({ files, targetTable }, 'csv: resolved input files');
62
+ let columns = null;
63
+ let totalRows = 0;
64
+ const batchSize = runConfig.batchSize;
65
+ for (const file of files) {
66
+ const parser = createReadStream(file).pipe(parse({
67
+ columns: true,
68
+ skip_empty_lines: true,
69
+ bom: true,
70
+ delimiter: config.delimiter,
71
+ }));
72
+ const batch = [];
73
+ try {
74
+ for await (const record of parser) {
75
+ const row = record;
76
+ if (!columns) {
77
+ const names = Object.keys(row);
78
+ if (names.length === 0) {
79
+ throw new SourceError(`csv file "${file}" has no columns`);
80
+ }
81
+ columns = names.map((n) => ({ name: n, duckDbType: 'VARCHAR' }));
82
+ await store.createTable(targetTable, columns);
83
+ }
84
+ batch.push(row);
85
+ if (batch.length >= batchSize) {
86
+ await store.insertBatch(targetTable, batch);
87
+ totalRows += batch.length;
88
+ batch.length = 0;
89
+ onProgress(totalRows);
90
+ }
91
+ }
92
+ if (batch.length > 0) {
93
+ await store.insertBatch(targetTable, batch);
94
+ totalRows += batch.length;
95
+ onProgress(totalRows);
96
+ }
97
+ }
98
+ catch (err) {
99
+ if (err instanceof SourceError)
100
+ throw err;
101
+ throw new SourceError(`csv extract failed for "${file}": ${err instanceof Error ? err.message : String(err)}`, err);
102
+ }
103
+ }
104
+ if (!columns) {
105
+ throw new SourceError(`csv extract produced no data for "${config.file}"`);
106
+ }
107
+ return { rowsExtracted: totalRows, tableName: targetTable, columns };
108
+ }
109
+ }
110
+ //# sourceMappingURL=csv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv.js","sourceRoot":"","sources":["../../../src/adapters/source/csv.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { CsvSourceAdapter } from './csv.js';
2
+ export { MssqlSourceAdapter } from './mssql.js';
3
+ export { PgSourceAdapter } from './pg.js';
4
+ export { RestSourceAdapter } from './rest.js';
5
+ export { SourceAdapterRegistry } from './registry.js';
6
+ export { XlsxSourceAdapter } from './xlsx.js';
7
+ export type { ExtractResult, SourceAdapter } from './types.js';
8
+ export type { ColumnMeta } from '../../staging/index.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/source/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * Barrel for source adapters. Built-in adapters self-register on first import.
5
+ */
6
+ import { CsvSourceAdapter } from './csv.js';
7
+ import { MssqlSourceAdapter } from './mssql.js';
8
+ import { PgSourceAdapter } from './pg.js';
9
+ import { RestSourceAdapter } from './rest.js';
10
+ import { SourceAdapterRegistry } from './registry.js';
11
+ import { XlsxSourceAdapter } from './xlsx.js';
12
+ // Register built-in source adapters exactly once (ES modules are single-eval).
13
+ if (!SourceAdapterRegistry.has('csv')) {
14
+ SourceAdapterRegistry.register(new CsvSourceAdapter());
15
+ SourceAdapterRegistry.register(new MssqlSourceAdapter());
16
+ SourceAdapterRegistry.register(new PgSourceAdapter());
17
+ SourceAdapterRegistry.register(new XlsxSourceAdapter());
18
+ SourceAdapterRegistry.register(new RestSourceAdapter());
19
+ }
20
+ export { CsvSourceAdapter } from './csv.js';
21
+ export { MssqlSourceAdapter } from './mssql.js';
22
+ export { PgSourceAdapter } from './pg.js';
23
+ export { RestSourceAdapter } from './rest.js';
24
+ export { SourceAdapterRegistry } from './registry.js';
25
+ export { XlsxSourceAdapter } from './xlsx.js';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/source/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,+EAA+E;AAC/E,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACtC,qBAAqB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;IACvD,qBAAqB,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;IACzD,qBAAqB,CAAC,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;IACtD,qBAAqB,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IACxD,qBAAqB,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { RunConfig, SourceConfig } from '../../config/types.js';
2
+ import type { StagingStore } from '../../staging/index.js';
3
+ import type { ExtractResult, SourceAdapter } from './types.js';
4
+ export declare class MssqlSourceAdapter implements SourceAdapter {
5
+ readonly id = "mssql";
6
+ private pool;
7
+ connect(config: SourceConfig): Promise<void>;
8
+ disconnect(): Promise<void>;
9
+ extract(config: SourceConfig, store: StagingStore, runConfig: RunConfig, onProgress: (rows: number) => void, targetTable?: string): Promise<ExtractResult>;
10
+ }
11
+ //# sourceMappingURL=mssql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mssql.d.ts","sourceRoot":"","sources":["../../../src/adapters/source/mssql.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkG/D,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,EAAE,WAAW;IACtB,OAAO,CAAC,IAAI,CAA+B;IAErC,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB5C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,CACX,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAClC,WAAW,SAAY,GACtB,OAAO,CAAC,aAAa,CAAC;CAmG1B"}
@@ -0,0 +1,230 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * SQL Server source adapter.
5
+ *
6
+ * Accepts either a URL connection string (`mssql://user:pass@host/db`) or a
7
+ * JSON-encoded config object — the latter supports Windows trusted connections
8
+ * via `{"trustedConnection": true, ...}`.
9
+ *
10
+ * Uses the streaming `request.stream = true` + `recordset` / `row` / `done`
11
+ * event flow so extremely large result sets don't blow the heap.
12
+ * `targetTable` defaults to 'stg_raw'.
13
+ */
14
+ import sql from 'mssql';
15
+ import { SourceError } from '../../utils/errors.js';
16
+ import { logger } from '../../utils/logger.js';
17
+ // Column metadata from mssql carries the type constructor function; its `.name`
18
+ // yields the SQL Server type name (e.g. "VarChar", "Int").
19
+ const MSSQL_TO_DUCKDB = {
20
+ varchar: 'VARCHAR',
21
+ nvarchar: 'VARCHAR',
22
+ char: 'VARCHAR',
23
+ nchar: 'VARCHAR',
24
+ text: 'VARCHAR',
25
+ ntext: 'VARCHAR',
26
+ xml: 'VARCHAR',
27
+ uniqueidentifier: 'VARCHAR',
28
+ int: 'BIGINT',
29
+ bigint: 'BIGINT',
30
+ smallint: 'BIGINT',
31
+ tinyint: 'BIGINT',
32
+ decimal: 'DOUBLE',
33
+ numeric: 'DOUBLE',
34
+ money: 'DOUBLE',
35
+ smallmoney: 'DOUBLE',
36
+ float: 'DOUBLE',
37
+ real: 'DOUBLE',
38
+ bit: 'BOOLEAN',
39
+ datetime: 'TIMESTAMP',
40
+ datetime2: 'TIMESTAMP',
41
+ smalldatetime: 'TIMESTAMP',
42
+ datetimeoffset: 'TIMESTAMP',
43
+ date: 'TIMESTAMP',
44
+ time: 'VARCHAR',
45
+ };
46
+ function mapMssqlType(t) {
47
+ if (t === null || t === undefined)
48
+ return 'VARCHAR';
49
+ const name = typeof t === 'function'
50
+ ? (t.name ?? '')
51
+ : typeof t === 'object'
52
+ ? (t.name ?? '')
53
+ : String(t);
54
+ return MSSQL_TO_DUCKDB[name.toLowerCase()] ?? 'VARCHAR';
55
+ }
56
+ function parseBooleanParam(value) {
57
+ if (value === null)
58
+ return undefined;
59
+ const normalized = value.trim().toLowerCase();
60
+ if (normalized === 'true' || normalized === '1')
61
+ return true;
62
+ if (normalized === 'false' || normalized === '0')
63
+ return false;
64
+ return undefined;
65
+ }
66
+ function parseMssqlUrl(connection) {
67
+ const parsed = new URL(connection);
68
+ const database = parsed.pathname.replace(/^\//, '');
69
+ const encrypt = parseBooleanParam(parsed.searchParams.get('encrypt'));
70
+ const trustServerCertificate = parseBooleanParam(parsed.searchParams.get('trustServerCertificate'));
71
+ const config = {
72
+ server: parsed.hostname,
73
+ ...(parsed.port ? { port: Number(parsed.port) } : {}),
74
+ ...(database ? { database } : {}),
75
+ ...(parsed.username ? { user: decodeURIComponent(parsed.username) } : {}),
76
+ ...(parsed.password ? { password: decodeURIComponent(parsed.password) } : {}),
77
+ options: {
78
+ ...(encrypt !== undefined ? { encrypt } : {}),
79
+ ...(trustServerCertificate !== undefined ? { trustServerCertificate } : {}),
80
+ },
81
+ };
82
+ if (Object.keys(config.options ?? {}).length === 0) {
83
+ delete config.options;
84
+ }
85
+ return config;
86
+ }
87
+ function parseConnection(connection) {
88
+ const trimmed = connection.trimStart();
89
+ if (trimmed.startsWith('{')) {
90
+ try {
91
+ return JSON.parse(connection);
92
+ }
93
+ catch (err) {
94
+ throw new SourceError(`mssql: invalid JSON in connection config: ${String(err)}`, err);
95
+ }
96
+ }
97
+ if (trimmed.startsWith('mssql://')) {
98
+ try {
99
+ return parseMssqlUrl(connection);
100
+ }
101
+ catch (err) {
102
+ throw new SourceError(`mssql: invalid URL in connection config: ${String(err)}`, err);
103
+ }
104
+ }
105
+ return connection;
106
+ }
107
+ export class MssqlSourceAdapter {
108
+ id = 'mssql';
109
+ pool = null;
110
+ async connect(config) {
111
+ if (!config.connection) {
112
+ throw new SourceError('mssql source requires `connection`');
113
+ }
114
+ const poolConfig = parseConnection(config.connection);
115
+ this.pool = new sql.ConnectionPool(poolConfig);
116
+ try {
117
+ await this.pool.connect();
118
+ }
119
+ catch (err) {
120
+ this.pool = null;
121
+ throw new SourceError(`mssql: connection failed: ${err instanceof Error ? err.message : String(err)}`, err);
122
+ }
123
+ }
124
+ async disconnect() {
125
+ if (this.pool) {
126
+ const p = this.pool;
127
+ this.pool = null;
128
+ await p.close();
129
+ }
130
+ }
131
+ async extract(config, store, runConfig, onProgress, targetTable = 'stg_raw') {
132
+ if (!config.query) {
133
+ throw new SourceError('mssql source requires `query`');
134
+ }
135
+ if (!this.pool) {
136
+ throw new SourceError('mssql: not connected (call connect() first)');
137
+ }
138
+ const query = config.query;
139
+ const request = this.pool.request();
140
+ request.stream = true;
141
+ let columns = null;
142
+ let pendingBatch = [];
143
+ let totalRows = 0;
144
+ return new Promise((resolve, reject) => {
145
+ let settled = false;
146
+ const fail = (err) => {
147
+ if (settled)
148
+ return;
149
+ settled = true;
150
+ reject(err instanceof SourceError ? err : new SourceError(`mssql query failed: ${String(err)}`, err));
151
+ };
152
+ request.on('recordset', (meta) => {
153
+ (async () => {
154
+ try {
155
+ columns = Object.entries(meta).map(([name, info]) => ({
156
+ name,
157
+ duckDbType: mapMssqlType(info?.type),
158
+ }));
159
+ if (columns.length === 0) {
160
+ throw new SourceError('mssql query produced no columns');
161
+ }
162
+ await store.createTable(targetTable, columns);
163
+ }
164
+ catch (err) {
165
+ fail(err);
166
+ }
167
+ })();
168
+ });
169
+ request.on('row', (row) => {
170
+ pendingBatch.push(row);
171
+ if (pendingBatch.length >= runConfig.batchSize) {
172
+ const toInsert = pendingBatch;
173
+ pendingBatch = [];
174
+ try {
175
+ request.pause();
176
+ }
177
+ catch {
178
+ /* older mssql may not support pause */
179
+ }
180
+ store
181
+ .insertBatch(targetTable, toInsert)
182
+ .then(() => {
183
+ totalRows += toInsert.length;
184
+ onProgress(totalRows);
185
+ try {
186
+ request.resume();
187
+ }
188
+ catch {
189
+ /* noop */
190
+ }
191
+ })
192
+ .catch((err) => {
193
+ fail(err);
194
+ });
195
+ }
196
+ });
197
+ request.on('error', fail);
198
+ request.on('done', () => {
199
+ (async () => {
200
+ try {
201
+ if (pendingBatch.length > 0) {
202
+ await store.insertBatch(targetTable, pendingBatch);
203
+ totalRows += pendingBatch.length;
204
+ onProgress(totalRows);
205
+ pendingBatch = [];
206
+ }
207
+ if (!columns) {
208
+ throw new SourceError('mssql query completed without any columns');
209
+ }
210
+ if (settled)
211
+ return;
212
+ settled = true;
213
+ logger.debug({ totalRows, targetTable }, 'mssql: extract complete');
214
+ resolve({ rowsExtracted: totalRows, tableName: targetTable, columns });
215
+ }
216
+ catch (err) {
217
+ fail(err);
218
+ }
219
+ })();
220
+ });
221
+ try {
222
+ request.query(query);
223
+ }
224
+ catch (err) {
225
+ fail(err);
226
+ }
227
+ });
228
+ }
229
+ }
230
+ //# sourceMappingURL=mssql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mssql.js","sourceRoot":"","sources":["../../../src/adapters/source/mssql.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { RunConfig, SourceConfig } from '../../config/types.js';
2
+ import type { StagingStore } from '../../staging/index.js';
3
+ import type { ExtractResult, SourceAdapter } from './types.js';
4
+ export declare class PgSourceAdapter implements SourceAdapter {
5
+ readonly id = "pg";
6
+ private pool;
7
+ connect(config: SourceConfig): Promise<void>;
8
+ disconnect(): Promise<void>;
9
+ extract(config: SourceConfig, store: StagingStore, runConfig: RunConfig, onProgress: (rows: number) => void, targetTable?: string): Promise<ExtractResult>;
10
+ }
11
+ //# sourceMappingURL=pg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../../src/adapters/source/pg.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuB/D,qBAAa,eAAgB,YAAW,aAAa;IACnD,QAAQ,CAAC,EAAE,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAwB;IAE9B,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,CACX,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAClC,WAAW,SAAY,GACtB,OAAO,CAAC,aAAa,CAAC;CAoC1B"}
@@ -0,0 +1,88 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * PostgreSQL source adapter.
5
+ *
6
+ * Executes `config.query` against `config.connection` via pg.Pool. The entire
7
+ * result set is held in memory; streaming via cursors is a future optimization
8
+ * for very large extracts. `targetTable` defaults to 'stg_raw'.
9
+ */
10
+ import pg from 'pg';
11
+ import { SourceError } from '../../utils/errors.js';
12
+ // OIDs from pg's built-in types — full list at node_modules/pg-types/lib/textParsers.js
13
+ // We only map the commonest ones; unknown OIDs default to VARCHAR.
14
+ const PG_OID_TO_DUCKDB = {
15
+ 16: 'BOOLEAN', // bool
16
+ 20: 'BIGINT', // int8
17
+ 21: 'BIGINT', // int2
18
+ 23: 'BIGINT', // int4
19
+ 25: 'VARCHAR', // text
20
+ 700: 'DOUBLE', // float4
21
+ 701: 'DOUBLE', // float8
22
+ 1043: 'VARCHAR', // varchar
23
+ 1042: 'VARCHAR', // bpchar (char)
24
+ 1082: 'TIMESTAMP', // date
25
+ 1114: 'TIMESTAMP', // timestamp
26
+ 1184: 'TIMESTAMP', // timestamptz
27
+ 1700: 'DOUBLE', // numeric
28
+ 114: 'VARCHAR', // json
29
+ 3802: 'VARCHAR', // jsonb
30
+ 2950: 'VARCHAR', // uuid
31
+ };
32
+ export class PgSourceAdapter {
33
+ id = 'pg';
34
+ pool = null;
35
+ async connect(config) {
36
+ if (!config.connection) {
37
+ throw new SourceError('pg source requires `connection`');
38
+ }
39
+ this.pool = new pg.Pool({ connectionString: config.connection });
40
+ // pg.Pool doesn't connect eagerly; trigger a check via a trivial query so
41
+ // connection errors surface before extract() is called.
42
+ try {
43
+ const client = await this.pool.connect();
44
+ client.release();
45
+ }
46
+ catch (err) {
47
+ this.pool = null;
48
+ throw new SourceError(`pg: connection failed: ${err instanceof Error ? err.message : String(err)}`, err);
49
+ }
50
+ }
51
+ async disconnect() {
52
+ if (this.pool) {
53
+ const p = this.pool;
54
+ this.pool = null;
55
+ await p.end();
56
+ }
57
+ }
58
+ async extract(config, store, runConfig, onProgress, targetTable = 'stg_raw') {
59
+ if (!config.query) {
60
+ throw new SourceError('pg source requires `query`');
61
+ }
62
+ if (!this.pool) {
63
+ throw new SourceError('pg: not connected');
64
+ }
65
+ let result;
66
+ try {
67
+ result = await this.pool.query(config.query);
68
+ }
69
+ catch (err) {
70
+ throw new SourceError(`pg query failed: ${err instanceof Error ? err.message : String(err)}`, err);
71
+ }
72
+ if (result.fields.length === 0) {
73
+ throw new SourceError('pg query produced no columns');
74
+ }
75
+ const columns = result.fields.map((f) => ({
76
+ name: f.name,
77
+ duckDbType: PG_OID_TO_DUCKDB[f.dataTypeID] ?? 'VARCHAR',
78
+ }));
79
+ await store.createTable(targetTable, columns);
80
+ for (let i = 0; i < result.rows.length; i += runConfig.batchSize) {
81
+ const batch = result.rows.slice(i, i + runConfig.batchSize);
82
+ await store.insertBatch(targetTable, batch);
83
+ onProgress(Math.min(i + batch.length, result.rows.length));
84
+ }
85
+ return { rowsExtracted: result.rows.length, tableName: targetTable, columns };
86
+ }
87
+ }
88
+ //# sourceMappingURL=pg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.js","sourceRoot":"","sources":["../../../src/adapters/source/pg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { SourceAdapter } from './types.js';
2
+ export declare class SourceAdapterRegistry {
3
+ static register(adapter: SourceAdapter): void;
4
+ static get(id: string): SourceAdapter;
5
+ static has(id: string): boolean;
6
+ static list(): string[];
7
+ /** Remove an adapter by id. Primarily for test isolation. */
8
+ static unregister(id: string): void;
9
+ }
10
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/adapters/source/registry.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,qBAAa,qBAAqB;IAChC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAO7C,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa;IAUrC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,MAAM,CAAC,IAAI,IAAI,MAAM,EAAE;IAIvB,6DAA6D;IAC7D,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAGpC"}
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: Elastic-2.0
2
+ // Copyright (c) 2026 Caracal Lynx Ltd.
3
+ /**
4
+ * Global registry of source adapters, keyed by adapter id ('csv', 'mssql', ...).
5
+ *
6
+ * Built-in adapters self-register when the `adapters/source` barrel is
7
+ * imported. Tests that need a clean registry can call `unregister()`.
8
+ */
9
+ import { ConfigError } from '../../utils/errors.js';
10
+ const adapters = new Map();
11
+ export class SourceAdapterRegistry {
12
+ static register(adapter) {
13
+ if (adapters.has(adapter.id)) {
14
+ throw new ConfigError(`Duplicate source adapter id "${adapter.id}"`);
15
+ }
16
+ adapters.set(adapter.id, adapter);
17
+ }
18
+ static get(id) {
19
+ const adapter = adapters.get(id);
20
+ if (!adapter) {
21
+ throw new ConfigError(`No source adapter registered for "${id}". Known adapters: ${[...adapters.keys()].join(', ') || '(none)'}`);
22
+ }
23
+ return adapter;
24
+ }
25
+ static has(id) {
26
+ return adapters.has(id);
27
+ }
28
+ static list() {
29
+ return [...adapters.keys()];
30
+ }
31
+ /** Remove an adapter by id. Primarily for test isolation. */
32
+ static unregister(id) {
33
+ adapters.delete(id);
34
+ }
35
+ }
36
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/adapters/source/registry.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,uCAAuC;AAEvC;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAElD,MAAM,OAAO,qBAAqB;IAChC,MAAM,CAAC,QAAQ,CAAC,OAAsB;QACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,WAAW,CAAC,gCAAgC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,EAAU;QACnB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,WAAW,CACnB,qCAAqC,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAC3G,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,EAAU;QACnB,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,IAAI;QACT,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,UAAU,CAAC,EAAU;QAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { RunConfig, SourceConfig } from '../../config/types.js';
2
+ import type { StagingStore } from '../../staging/index.js';
3
+ import type { ExtractResult, SourceAdapter } from './types.js';
4
+ type Source = SourceConfig;
5
+ export declare class RestSourceAdapter implements SourceAdapter {
6
+ readonly id = "rest";
7
+ private client;
8
+ connect(config: Source): Promise<void>;
9
+ disconnect(): Promise<void>;
10
+ extract(config: Source, store: StagingStore, runConfig: RunConfig, onProgress: (rows: number) => void, targetTable?: string): Promise<ExtractResult>;
11
+ private fetchOne;
12
+ private fetchPaged;
13
+ private get;
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=rest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../../src/adapters/source/rest.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,KAAK,MAAM,GAAG,YAAY,CAAC;AA4B3B,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,EAAE,UAAU;IACrB,OAAO,CAAC,MAAM,CAA8B;IAEtC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBtC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,CACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAClC,WAAW,SAAY,GACtB,OAAO,CAAC,aAAa,CAAC;YA8BX,QAAQ;YAgBR,UAAU;YAmEV,GAAG;CAclB"}