@c9up/eon 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 (123) hide show
  1. package/README.md +69 -0
  2. package/dist/EonProvider.d.ts +51 -0
  3. package/dist/EonProvider.d.ts.map +1 -0
  4. package/dist/EonProvider.js +154 -0
  5. package/dist/EonProvider.js.map +1 -0
  6. package/dist/connection/EonConnection.d.ts +116 -0
  7. package/dist/connection/EonConnection.d.ts.map +1 -0
  8. package/dist/connection/EonConnection.js +15 -0
  9. package/dist/connection/EonConnection.js.map +1 -0
  10. package/dist/connection/config.d.ts +56 -0
  11. package/dist/connection/config.d.ts.map +1 -0
  12. package/dist/connection/config.js +14 -0
  13. package/dist/connection/config.js.map +1 -0
  14. package/dist/connection/websocket.d.ts +16 -0
  15. package/dist/connection/websocket.d.ts.map +1 -0
  16. package/dist/connection/websocket.js +383 -0
  17. package/dist/connection/websocket.js.map +1 -0
  18. package/dist/decorators/superTable.d.ts +73 -0
  19. package/dist/decorators/superTable.d.ts.map +1 -0
  20. package/dist/decorators/superTable.js +98 -0
  21. package/dist/decorators/superTable.js.map +1 -0
  22. package/dist/index.d.ts +20 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +19 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/ingest/schemaless.d.ts +22 -0
  27. package/dist/ingest/schemaless.d.ts.map +1 -0
  28. package/dist/ingest/schemaless.js +161 -0
  29. package/dist/ingest/schemaless.js.map +1 -0
  30. package/dist/ingest/sql.d.ts +23 -0
  31. package/dist/ingest/sql.d.ts.map +1 -0
  32. package/dist/ingest/sql.js +59 -0
  33. package/dist/ingest/sql.js.map +1 -0
  34. package/dist/ingest/stmt.d.ts +82 -0
  35. package/dist/ingest/stmt.d.ts.map +1 -0
  36. package/dist/ingest/stmt.js +246 -0
  37. package/dist/ingest/stmt.js.map +1 -0
  38. package/dist/metadata-keys.d.ts +17 -0
  39. package/dist/metadata-keys.d.ts.map +1 -0
  40. package/dist/metadata-keys.js +17 -0
  41. package/dist/metadata-keys.js.map +1 -0
  42. package/dist/query/TimeSeriesQuery.d.ts +121 -0
  43. package/dist/query/TimeSeriesQuery.d.ts.map +1 -0
  44. package/dist/query/TimeSeriesQuery.js +291 -0
  45. package/dist/query/TimeSeriesQuery.js.map +1 -0
  46. package/dist/query/native.d.ts +22 -0
  47. package/dist/query/native.d.ts.map +1 -0
  48. package/dist/query/native.js +135 -0
  49. package/dist/query/native.js.map +1 -0
  50. package/dist/repository/SuperTableRepository.d.ts +80 -0
  51. package/dist/repository/SuperTableRepository.d.ts.map +1 -0
  52. package/dist/repository/SuperTableRepository.js +232 -0
  53. package/dist/repository/SuperTableRepository.js.map +1 -0
  54. package/dist/schema/CreateStableSpec.d.ts +140 -0
  55. package/dist/schema/CreateStableSpec.d.ts.map +1 -0
  56. package/dist/schema/CreateStableSpec.js +41 -0
  57. package/dist/schema/CreateStableSpec.js.map +1 -0
  58. package/dist/schema/EonMigrationRunner.d.ts +71 -0
  59. package/dist/schema/EonMigrationRunner.d.ts.map +1 -0
  60. package/dist/schema/EonMigrationRunner.js +295 -0
  61. package/dist/schema/EonMigrationRunner.js.map +1 -0
  62. package/dist/schema/EonSchema.d.ts +128 -0
  63. package/dist/schema/EonSchema.d.ts.map +1 -0
  64. package/dist/schema/EonSchema.js +309 -0
  65. package/dist/schema/EonSchema.js.map +1 -0
  66. package/dist/schema/Migration.d.ts +47 -0
  67. package/dist/schema/Migration.d.ts.map +1 -0
  68. package/dist/schema/Migration.js +55 -0
  69. package/dist/schema/Migration.js.map +1 -0
  70. package/dist/schema/compile.d.ts +33 -0
  71. package/dist/schema/compile.d.ts.map +1 -0
  72. package/dist/schema/compile.js +70 -0
  73. package/dist/schema/compile.js.map +1 -0
  74. package/dist/schema/sync.d.ts +45 -0
  75. package/dist/schema/sync.d.ts.map +1 -0
  76. package/dist/schema/sync.js +102 -0
  77. package/dist/schema/sync.js.map +1 -0
  78. package/dist/services/connection.d.ts +33 -0
  79. package/dist/services/connection.d.ts.map +1 -0
  80. package/dist/services/connection.js +71 -0
  81. package/dist/services/connection.js.map +1 -0
  82. package/dist/testing/Factory.d.ts +43 -0
  83. package/dist/testing/Factory.d.ts.map +1 -0
  84. package/dist/testing/Factory.js +134 -0
  85. package/dist/testing/Factory.js.map +1 -0
  86. package/dist/testing/FakeEonConnection.d.ts +43 -0
  87. package/dist/testing/FakeEonConnection.d.ts.map +1 -0
  88. package/dist/testing/FakeEonConnection.js +315 -0
  89. package/dist/testing/FakeEonConnection.js.map +1 -0
  90. package/dist/testing/index.d.ts +34 -0
  91. package/dist/testing/index.d.ts.map +1 -0
  92. package/dist/testing/index.js +67 -0
  93. package/dist/testing/index.js.map +1 -0
  94. package/index.darwin-arm64.node +0 -0
  95. package/index.darwin-x64.node +0 -0
  96. package/index.linux-arm64-gnu.node +0 -0
  97. package/index.linux-x64-gnu.node +0 -0
  98. package/index.win32-x64-msvc.node +0 -0
  99. package/package.json +65 -0
  100. package/scripts/copy-napi.mjs +72 -0
  101. package/src/EonProvider.ts +222 -0
  102. package/src/connection/EonConnection.ts +146 -0
  103. package/src/connection/config.ts +60 -0
  104. package/src/connection/websocket.ts +436 -0
  105. package/src/decorators/superTable.ts +169 -0
  106. package/src/index.ts +118 -0
  107. package/src/ingest/schemaless.ts +211 -0
  108. package/src/ingest/sql.ts +73 -0
  109. package/src/ingest/stmt.ts +335 -0
  110. package/src/metadata-keys.ts +20 -0
  111. package/src/query/TimeSeriesQuery.ts +480 -0
  112. package/src/query/native.ts +180 -0
  113. package/src/repository/SuperTableRepository.ts +347 -0
  114. package/src/schema/CreateStableSpec.ts +184 -0
  115. package/src/schema/EonMigrationRunner.ts +378 -0
  116. package/src/schema/EonSchema.ts +396 -0
  117. package/src/schema/Migration.ts +66 -0
  118. package/src/schema/compile.ts +109 -0
  119. package/src/schema/sync.ts +142 -0
  120. package/src/services/connection.ts +89 -0
  121. package/src/testing/Factory.ts +186 -0
  122. package/src/testing/FakeEonConnection.ts +351 -0
  123. package/src/testing/index.ts +81 -0
@@ -0,0 +1,315 @@
1
+ /**
2
+ * `FakeEonConnection` — a hand-rolled in-memory `EonConnection` for fast,
3
+ * deterministic unit tests without a live TDengine (58.6). The atlas analogue is
4
+ * a REAL in-memory SQLite (`testing/TestDatabase.ts`); TDengine has no embeddable
5
+ * engine, so this is a deliberately narrow test double, NOT a SQL engine.
6
+ *
7
+ * ── Scope (named boundary) ─────────────────────────────────────────────────
8
+ * - `exec(sql)` RECORDS every statement (assertable via {@link statements}) and,
9
+ * for recognised `CREATE TABLE`/`CREATE STABLE`/`INSERT` forms, updates a
10
+ * per-table row store.
11
+ * - `query(sql)` answers ONLY flat `SELECT [cols] FROM t [WHERE col <op> val]
12
+ * [LIMIT n]`. Windowed / aggregate SQL (`INTERVAL`/`FILL`/`PARTITION BY`/
13
+ * `avg(...)`) is NOT interpreted — it throws `E_EON_FAKE_UNSUPPORTED` pointing
14
+ * the caller to the docker integration harness (`describeIfTdengine`).
15
+ * - `ingestColumnar`/`schemaless` are STMT/line-protocol paths that need a live
16
+ * connector — they throw `E_EON_FAKE_UNSUPPORTED`. (The 58.6 factory persists
17
+ * through literal `exec` INSERTs, which the store DOES handle.)
18
+ * - `ping()`/`close()` are no-ops.
19
+ */
20
+ const WINDOWED = /\b(INTERVAL|FILL|PARTITION\s+BY|SLIDING)\b/i;
21
+ export class FakeEonConnection {
22
+ transport = "fake";
23
+ /** Every `exec`ed statement, in order — assert against this in tests. */
24
+ statements = [];
25
+ #store = new Map();
26
+ async exec(sql) {
27
+ this.statements.push(sql);
28
+ const trimmed = sql.trim();
29
+ if (/^CREATE\s+(STABLE|TABLE)\b/i.test(trimmed)) {
30
+ const table = extractCreateTarget(trimmed);
31
+ if (table !== undefined && !this.#store.has(table)) {
32
+ this.#store.set(table, []);
33
+ }
34
+ return { rowsAffected: 0 };
35
+ }
36
+ if (/^INSERT\s+INTO\b/i.test(trimmed)) {
37
+ const rows = parseInsert(trimmed);
38
+ if (rows !== undefined) {
39
+ const existing = this.#store.get(rows.table) ?? [];
40
+ existing.push(...rows.rows);
41
+ this.#store.set(rows.table, existing);
42
+ return { rowsAffected: rows.rows.length };
43
+ }
44
+ }
45
+ if (/^DELETE\s+FROM\b/i.test(trimmed)) {
46
+ const affected = this.#applyDelete(trimmed);
47
+ return { rowsAffected: affected };
48
+ }
49
+ // DROP / USE / other DDL: recorded, no store change.
50
+ if (/^DROP\s+(STABLE|TABLE)\b/i.test(trimmed)) {
51
+ const table = extractDropTarget(trimmed);
52
+ if (table !== undefined)
53
+ this.#store.delete(table);
54
+ }
55
+ return { rowsAffected: 0 };
56
+ }
57
+ async query(sql) {
58
+ const trimmed = sql.trim();
59
+ if (WINDOWED.test(trimmed) || hasAggregate(trimmed)) {
60
+ throw new Error(`[E_EON_FAKE_UNSUPPORTED] FakeEonConnection answers only flat SELECT; windowed/aggregate SQL needs a live TDengine (use describeIfTdengine). Query: ${trimmed}`);
61
+ }
62
+ const parsed = parseSelect(trimmed);
63
+ if (parsed === undefined) {
64
+ throw new Error(`[E_EON_FAKE_UNSUPPORTED] FakeEonConnection could not parse this SELECT: ${trimmed}`);
65
+ }
66
+ let rows = [...(this.#store.get(parsed.table) ?? [])];
67
+ if (parsed.where !== undefined) {
68
+ const { column, op, value } = parsed.where;
69
+ rows = rows.filter((r) => compareOp(r[column], op, value));
70
+ }
71
+ if (parsed.limit !== undefined)
72
+ rows = rows.slice(0, parsed.limit);
73
+ if (parsed.columns === "*")
74
+ return rows;
75
+ const cols = parsed.columns;
76
+ return rows.map((r) => {
77
+ const projected = {};
78
+ for (const c of cols)
79
+ projected[c] = r[c];
80
+ return projected;
81
+ });
82
+ }
83
+ async ingestColumnar(request) {
84
+ void request;
85
+ throw new Error("[E_EON_FAKE_UNSUPPORTED] FakeEonConnection has no STMT columnar path; test bulk ingest against a live TDengine (describeIfTdengine).");
86
+ }
87
+ async schemaless(lines, options) {
88
+ void lines;
89
+ void options;
90
+ throw new Error("[E_EON_FAKE_UNSUPPORTED] FakeEonConnection has no line-protocol path; test schemaless ingest against a live TDengine (describeIfTdengine).");
91
+ }
92
+ async ping() { }
93
+ async close() { }
94
+ /** Clear recorded statements and the row store. */
95
+ reset() {
96
+ this.statements.length = 0;
97
+ this.#store.clear();
98
+ }
99
+ /** Read the current rows for a table (a copy) — a test-inspection helper. */
100
+ rows(table) {
101
+ return [...(this.#store.get(table) ?? [])];
102
+ }
103
+ #applyDelete(sql) {
104
+ const match = /^DELETE\s+FROM\s+`([^`]+)`\s+WHERE\s+`([^`]+)`\s*=\s*(.+)$/i.exec(sql);
105
+ if (match === null)
106
+ return 0;
107
+ const [, table, column, rawValue] = match;
108
+ if (table === undefined || column === undefined || rawValue === undefined) {
109
+ return 0;
110
+ }
111
+ const value = parseLiteral(rawValue.trim());
112
+ const existing = this.#store.get(table);
113
+ if (existing === undefined)
114
+ return 0;
115
+ const kept = existing.filter((r) => r[column] !== value);
116
+ this.#store.set(table, kept);
117
+ return existing.length - kept.length;
118
+ }
119
+ }
120
+ /** Detect a function-call in the SELECT projection (`avg(...)`, `count(*)`, …). */
121
+ function hasAggregate(sql) {
122
+ const match = /^SELECT\s+(.+?)\s+FROM\b/i.exec(sql);
123
+ if (match === null)
124
+ return false;
125
+ const projection = match[1] ?? "";
126
+ return /[A-Za-z_][A-Za-z0-9_]*\s*\(/.test(projection);
127
+ }
128
+ function extractCreateTarget(sql) {
129
+ const match = /^CREATE\s+(?:STABLE|TABLE)\s+(?:IF\s+NOT\s+EXISTS\s+)?`([^`]+)`/i.exec(sql);
130
+ return match?.[1];
131
+ }
132
+ function extractDropTarget(sql) {
133
+ const match = /^DROP\s+(?:STABLE|TABLE)\s+(?:IF\s+EXISTS\s+)?`([^`]+)`/i.exec(sql);
134
+ return match?.[1];
135
+ }
136
+ /** Parse a literal `INSERT` (plain or `USING … TAGS`) into rows keyed by column. */
137
+ function parseInsert(sql) {
138
+ const tableMatch = /^INSERT\s+INTO\s+`([^`]+)`/i.exec(sql);
139
+ const table = tableMatch?.[1];
140
+ if (table === undefined)
141
+ return undefined;
142
+ // Strip an optional child-create `USING `stb` TAGS (...)` clause.
143
+ const body = sql.replace(/\bUSING\s+`[^`]+`\s+TAGS\s*\([^)]*\)/i, "");
144
+ const colsMatch = /\(([^)]*)\)\s*VALUES/i.exec(body);
145
+ const valuesPart = body.slice(body.search(/VALUES/i) + "VALUES".length);
146
+ if (colsMatch === null)
147
+ return undefined;
148
+ const columns = (colsMatch[1] ?? "")
149
+ .split(",")
150
+ .map((c) => c.trim().replace(/^`|`$/g, ""));
151
+ const rows = [];
152
+ for (const tuple of splitTuples(valuesPart)) {
153
+ const values = splitValues(tuple).map(parseLiteral);
154
+ const row = {};
155
+ columns.forEach((c, i) => {
156
+ row[c] = values[i];
157
+ });
158
+ rows.push(row);
159
+ }
160
+ return { table, rows };
161
+ }
162
+ function parseSelect(sql) {
163
+ const match = /^SELECT\s+(.+?)\s+FROM\s+`([^`]+)`\s*(?:WHERE\s+(.+?))?\s*(?:LIMIT\s+(\d+))?\s*$/i.exec(sql);
164
+ if (match === null)
165
+ return undefined;
166
+ const [, rawCols, table, rawWhere, rawLimit] = match;
167
+ if (rawCols === undefined || table === undefined)
168
+ return undefined;
169
+ const columns = rawCols.trim() === "*"
170
+ ? "*"
171
+ : rawCols.split(",").map((c) => c.trim().replace(/^`|`$/g, ""));
172
+ const result = { columns, table };
173
+ if (rawWhere !== undefined) {
174
+ const clause = rawWhere.trim();
175
+ // A multi-predicate WHERE (`a` = 1 AND `b` = 2) or an unparseable clause
176
+ // (non-backtick column, unknown operator) is NOT supported. Return
177
+ // undefined so the caller throws E_EON_FAKE_UNSUPPORTED rather than
178
+ // silently dropping the predicate and returning every row (fail-loud).
179
+ if (hasBooleanConnector(clause))
180
+ return undefined;
181
+ const w = /^`([^`]+)`\s*(=|!=|<>|>=|<=|>|<)\s*(.+)$/.exec(clause);
182
+ if (w === null ||
183
+ w[1] === undefined ||
184
+ w[2] === undefined ||
185
+ w[3] === undefined) {
186
+ return undefined;
187
+ }
188
+ result.where = {
189
+ column: w[1],
190
+ op: w[2],
191
+ value: parseLiteral(w[3].trim()),
192
+ };
193
+ }
194
+ if (rawLimit !== undefined)
195
+ result.limit = Number(rawLimit);
196
+ return result;
197
+ }
198
+ /**
199
+ * True if a WHERE clause has a top-level `AND`/`OR` connector (a multi-predicate
200
+ * filter the flat store cannot evaluate). Single-quoted string literals are
201
+ * blanked first so an `AND` inside a value (`'a AND b'`) is not misread.
202
+ */
203
+ function hasBooleanConnector(clause) {
204
+ const unquoted = clause.replace(/'(?:\\.|[^'\\])*'/g, "''");
205
+ return /\b(?:AND|OR)\b/i.test(unquoted);
206
+ }
207
+ function compareOp(left, op, right) {
208
+ switch (op) {
209
+ case "=":
210
+ return left === right;
211
+ case "!=":
212
+ case "<>":
213
+ return left !== right;
214
+ default: {
215
+ const l = Number(left);
216
+ const r = Number(right);
217
+ if (Number.isNaN(l) || Number.isNaN(r))
218
+ return false;
219
+ if (op === ">")
220
+ return l > r;
221
+ if (op === ">=")
222
+ return l >= r;
223
+ if (op === "<")
224
+ return l < r;
225
+ if (op === "<=")
226
+ return l <= r;
227
+ return false;
228
+ }
229
+ }
230
+ }
231
+ /** Split a `VALUES` clause into per-row tuples, respecting quoted strings. */
232
+ function splitTuples(valuesPart) {
233
+ const tuples = [];
234
+ let depth = 0;
235
+ let inString = false;
236
+ let start = -1;
237
+ for (let i = 0; i < valuesPart.length; i++) {
238
+ const ch = valuesPart[i];
239
+ if (inString) {
240
+ if (ch === "\\")
241
+ i++; // skip the escaped char
242
+ else if (ch === "'")
243
+ inString = false;
244
+ continue;
245
+ }
246
+ if (ch === "'") {
247
+ inString = true;
248
+ }
249
+ else if (ch === "(") {
250
+ if (depth === 0)
251
+ start = i + 1;
252
+ depth++;
253
+ }
254
+ else if (ch === ")") {
255
+ depth--;
256
+ if (depth === 0 && start >= 0) {
257
+ tuples.push(valuesPart.slice(start, i));
258
+ start = -1;
259
+ }
260
+ }
261
+ }
262
+ return tuples;
263
+ }
264
+ /** Split a tuple body into top-level comma-separated value tokens. */
265
+ function splitValues(tuple) {
266
+ const values = [];
267
+ let inString = false;
268
+ let current = "";
269
+ for (let i = 0; i < tuple.length; i++) {
270
+ const ch = tuple[i];
271
+ if (inString) {
272
+ current += ch;
273
+ if (ch === "\\") {
274
+ const next = tuple[i + 1];
275
+ if (next !== undefined) {
276
+ current += next;
277
+ i++;
278
+ }
279
+ }
280
+ else if (ch === "'") {
281
+ inString = false;
282
+ }
283
+ continue;
284
+ }
285
+ if (ch === "'") {
286
+ inString = true;
287
+ current += ch;
288
+ }
289
+ else if (ch === ",") {
290
+ values.push(current.trim());
291
+ current = "";
292
+ }
293
+ else {
294
+ current += ch;
295
+ }
296
+ }
297
+ if (current.trim().length > 0)
298
+ values.push(current.trim());
299
+ return values;
300
+ }
301
+ /** Parse a single SQL literal token back to a JS value (inverse of `render_literal`). */
302
+ function parseLiteral(token) {
303
+ if (token === "NULL")
304
+ return null;
305
+ if (token === "true")
306
+ return true;
307
+ if (token === "false")
308
+ return false;
309
+ if (token.startsWith("'") && token.endsWith("'")) {
310
+ return token.slice(1, -1).replace(/\\(['\\])/g, "$1");
311
+ }
312
+ const num = Number(token);
313
+ return Number.isNaN(num) ? token : num;
314
+ }
315
+ //# sourceMappingURL=FakeEonConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeEonConnection.js","sourceRoot":"","sources":["../../src/testing/FakeEonConnection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,MAAM,QAAQ,GAAG,6CAA6C,CAAC;AAE/D,MAAM,OAAO,iBAAiB;IACpB,SAAS,GAAW,MAAM,CAAC;IACpC,yEAAyE;IAChE,UAAU,GAAa,EAAE,CAAC;IAC1B,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE3C,KAAK,CAAC,IAAI,CAAC,GAAW;QACrB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,6BAA6B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5B,CAAC;YACD,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC5B,CAAC;QACD,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACtC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC3C,CAAC;QACF,CAAC;QACD,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC5C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;QACnC,CAAC;QACD,qDAAqD;QACrD,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,KAAK,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC5B,CAAC;IAGD,KAAK,CAAC,KAAK,CAAC,GAAW;QACtB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACd,sJAAsJ,OAAO,EAAE,CAC/J,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACd,2EAA2E,OAAO,EAAE,CACpF,CAAC;QACH,CAAC;QACD,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3C,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,MAAM,CAAC,OAAO,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACxC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACrB,MAAM,SAAS,GAAQ,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,IAAI;gBAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,OAAO,SAAS,CAAC;QAClB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CACnB,OAA0B;QAE1B,KAAK,OAAO,CAAC;QACb,MAAM,IAAI,KAAK,CACd,sIAAsI,CACtI,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CACf,KAAwB,EACxB,OAA8B;QAE9B,KAAK,KAAK,CAAC;QACX,KAAK,OAAO,CAAC;QACb,MAAM,IAAI,KAAK,CACd,4IAA4I,CAC5I,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,KAAmB,CAAC;IAC9B,KAAK,CAAC,KAAK,KAAmB,CAAC;IAE/B,mDAAmD;IACnD,KAAK;QACJ,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,6EAA6E;IAC7E,IAAI,CAAC,KAAa;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,CAAC,GAAW;QACvB,MAAM,KAAK,GACV,6DAA6D,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzE,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;QAC7B,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3E,OAAO,CAAC,CAAC;QACV,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC7B,OAAO,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,CAAC;CACD;AAED,mFAAmF;AACnF,SAAS,YAAY,CAAC,GAAW;IAChC,MAAM,KAAK,GAAG,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,6BAA6B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACvC,MAAM,KAAK,GACV,kEAAkE,CAAC,IAAI,CACtE,GAAG,CACH,CAAC;IACH,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACrC,MAAM,KAAK,GAAG,0DAA0D,CAAC,IAAI,CAC5E,GAAG,CACH,CAAC;IACF,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAOD,oFAAoF;AACpF,SAAS,WAAW,CAAC,GAAW;IAC/B,MAAM,UAAU,GAAG,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,kEAAkE;IAClE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxE,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SAClC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACxB,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AASD,SAAS,WAAW,CAAC,GAAW;IAC/B,MAAM,KAAK,GACV,mFAAmF,CAAC,IAAI,CACvF,GAAG,CACH,CAAC;IACH,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;IACrD,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACnE,MAAM,OAAO,GACZ,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG;QACrB,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAChD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,yEAAyE;QACzE,mEAAmE;QACnE,oEAAoE;QACpE,uEAAuE;QACvE,IAAI,mBAAmB,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QAClD,MAAM,CAAC,GAAG,0CAA0C,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClE,IACC,CAAC,KAAK,IAAI;YACV,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;YAClB,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;YAClB,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EACjB,CAAC;YACF,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,CAAC,KAAK,GAAG;YACd,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YACZ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YACR,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SAChC,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,MAAc;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAC5D,OAAO,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,SAAS,CAAC,IAAa,EAAE,EAAU,EAAE,KAAc;IAC3D,QAAQ,EAAE,EAAE,CAAC;QACZ,KAAK,GAAG;YACP,OAAO,IAAI,KAAK,KAAK,CAAC;QACvB,KAAK,IAAI,CAAC;QACV,KAAK,IAAI;YACR,OAAO,IAAI,KAAK,KAAK,CAAC;QACvB,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;YACrD,IAAI,EAAE,KAAK,GAAG;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,EAAE,KAAK,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,EAAE,KAAK,GAAG;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,EAAE,KAAK,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,SAAS,WAAW,CAAC,UAAkB;IACtC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,EAAE,KAAK,IAAI;gBACd,CAAC,EAAE,CAAC,CAAC,wBAAwB;iBACzB,IAAI,EAAE,KAAK,GAAG;gBAAE,QAAQ,GAAG,KAAK,CAAC;YACtC,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,QAAQ,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACvB,IAAI,KAAK,KAAK,CAAC;gBAAE,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,EAAE,CAAC;QACT,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACvB,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBACxC,KAAK,GAAG,CAAC,CAAC,CAAC;YACZ,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,sEAAsE;AACtE,SAAS,WAAW,CAAC,KAAa;IACjC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,EAAE,CAAC;YACd,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC1B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACxB,OAAO,IAAI,IAAI,CAAC;oBAChB,CAAC,EAAE,CAAC;gBACL,CAAC;YACF,CAAC;iBAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACvB,QAAQ,GAAG,KAAK,CAAC;YAClB,CAAC;YACD,SAAS;QACV,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,IAAI,EAAE,CAAC;QACf,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5B,OAAO,GAAG,EAAE,CAAC;QACd,CAAC;aAAM,CAAC;YACP,OAAO,IAAI,EAAE,CAAC;QACf,CAAC;IACF,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC;AACf,CAAC;AAED,yFAAyF;AACzF,SAAS,YAAY,CAAC,KAAa;IAClC,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Test helpers for @c9up/eon — the REAL-connection harness for integration
3
+ * suites (58.2) PLUS the in-memory fake store + factory (58.6).
4
+ *
5
+ * `EON_TEST_URL` gates the live paths: unset → local dev without a server, so
6
+ * integration suites skip via `describeIfTdengine` (mirrors atlas's "no external
7
+ * DB required for unit tests" posture). CI sets it, so the roundtrip runs for
8
+ * real — no silent cap. The fake store + factory need NO server.
9
+ */
10
+ import type { EonConnectionConfig } from "../connection/config.js";
11
+ import type { EonConnection } from "../connection/EonConnection.js";
12
+ export { type FactoryBuilder, factory } from "./Factory.js";
13
+ export { FakeEonConnection } from "./FakeEonConnection.js";
14
+ /** Whether an `EON_TEST_URL` is configured (a live TDengine is reachable). */
15
+ export declare function hasTestServer(): boolean;
16
+ /**
17
+ * Register a suite that runs only when a test server is configured, else skips —
18
+ * so integration suites gate uniformly. CI (with `EON_TEST_URL`) runs them for
19
+ * real; local dev without a server skips them.
20
+ */
21
+ export declare function describeIfTdengine(name: string, factory: () => void): void;
22
+ /**
23
+ * Open a connection to the test server (`EON_TEST_URL`), applying root/taosdata
24
+ * defaults and a generous connect-retry for a cold docker server. Callers gate
25
+ * with `hasTestServer()` / `describeIfTdengine` first.
26
+ */
27
+ export declare function connectTestEon(overrides?: Partial<EonConnectionConfig>): Promise<EonConnection>;
28
+ /**
29
+ * Reset a database for test isolation: drop it if present, then recreate it at
30
+ * millisecond precision. The name is validated against a safe alphabet before
31
+ * interpolation — a test-only helper, but no injection footgun.
32
+ */
33
+ export declare function resetDatabase(conn: EonConnection, db: string): Promise<void>;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,EAAE,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQ3D,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAM1E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC7B,SAAS,GAAE,OAAO,CAAC,mBAAmB,CAAM,GAC1C,OAAO,CAAC,aAAa,CAAC,CAexB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,MAAM,GACR,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Test helpers for @c9up/eon — the REAL-connection harness for integration
3
+ * suites (58.2) PLUS the in-memory fake store + factory (58.6).
4
+ *
5
+ * `EON_TEST_URL` gates the live paths: unset → local dev without a server, so
6
+ * integration suites skip via `describeIfTdengine` (mirrors atlas's "no external
7
+ * DB required for unit tests" posture). CI sets it, so the roundtrip runs for
8
+ * real — no silent cap. The fake store + factory need NO server.
9
+ */
10
+ import { describe } from "vitest";
11
+ import { connectWsEon } from "../connection/websocket.js";
12
+ export { factory } from "./Factory.js";
13
+ export { FakeEonConnection } from "./FakeEonConnection.js";
14
+ /** The live TDengine URL for integration tests (taosAdapter WS), or `undefined`. */
15
+ function testUrl() {
16
+ const url = process.env.EON_TEST_URL;
17
+ return typeof url === "string" && url.length > 0 ? url : undefined;
18
+ }
19
+ /** Whether an `EON_TEST_URL` is configured (a live TDengine is reachable). */
20
+ export function hasTestServer() {
21
+ return testUrl() !== undefined;
22
+ }
23
+ /**
24
+ * Register a suite that runs only when a test server is configured, else skips —
25
+ * so integration suites gate uniformly. CI (with `EON_TEST_URL`) runs them for
26
+ * real; local dev without a server skips them.
27
+ */
28
+ export function describeIfTdengine(name, factory) {
29
+ if (hasTestServer()) {
30
+ describe(name, factory);
31
+ }
32
+ else {
33
+ describe.skip(name, factory);
34
+ }
35
+ }
36
+ /**
37
+ * Open a connection to the test server (`EON_TEST_URL`), applying root/taosdata
38
+ * defaults and a generous connect-retry for a cold docker server. Callers gate
39
+ * with `hasTestServer()` / `describeIfTdengine` first.
40
+ */
41
+ export function connectTestEon(overrides = {}) {
42
+ const url = testUrl();
43
+ if (!url) {
44
+ throw new Error("[eon] connectTestEon requires EON_TEST_URL (a live TDengine taosAdapter WS URL, e.g. ws://localhost:6041).");
45
+ }
46
+ return connectWsEon({
47
+ url,
48
+ user: "root",
49
+ password: "taosdata",
50
+ connectRetries: 10,
51
+ connectBackoffMs: 250,
52
+ ...overrides,
53
+ });
54
+ }
55
+ /**
56
+ * Reset a database for test isolation: drop it if present, then recreate it at
57
+ * millisecond precision. The name is validated against a safe alphabet before
58
+ * interpolation — a test-only helper, but no injection footgun.
59
+ */
60
+ export async function resetDatabase(conn, db) {
61
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(db)) {
62
+ throw new Error(`[eon] resetDatabase: unsafe database name '${db}'`);
63
+ }
64
+ await conn.exec(`DROP DATABASE IF EXISTS ${db}`);
65
+ await conn.exec(`CREATE DATABASE ${db} PRECISION 'ms'`);
66
+ }
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAuB,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,oFAAoF;AACpF,SAAS,OAAO;IACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACrC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,aAAa;IAC5B,OAAO,OAAO,EAAE,KAAK,SAAS,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAAmB;IACnE,IAAI,aAAa,EAAE,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC7B,YAA0C,EAAE;IAE5C,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACd,4GAA4G,CAC5G,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;QACnB,GAAG;QACH,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU;QACpB,cAAc,EAAE,EAAE;QAClB,gBAAgB,EAAE,GAAG;QACrB,GAAG,SAAS;KACZ,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,IAAmB,EACnB,EAAU;IAEV,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,IAAI,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;AACzD,CAAC"}
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@c9up/eon",
3
+ "version": "0.1.0",
4
+ "description": "Eon — time-series data layer for the Ream framework (TDengine-backed)",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "LICENSE",
11
+ "README.md",
12
+ "dist",
13
+ "index.*.node",
14
+ "scripts",
15
+ "src"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ },
22
+ "./provider": {
23
+ "types": "./dist/EonProvider.d.ts",
24
+ "import": "./dist/EonProvider.js"
25
+ },
26
+ "./services/connection": {
27
+ "types": "./dist/services/connection.d.ts",
28
+ "import": "./dist/services/connection.js"
29
+ },
30
+ "./testing": {
31
+ "types": "./dist/testing/index.d.ts",
32
+ "import": "./dist/testing/index.js"
33
+ }
34
+ },
35
+ "dependencies": {
36
+ "@tdengine/websocket": "3.5.0",
37
+ "reflect-metadata": "^0.2"
38
+ },
39
+ "devDependencies": {
40
+ "@biomejs/biome": "^2.4.10",
41
+ "typescript": "^6.0.2",
42
+ "vitest": "^4.1.2",
43
+ "@types/node": "^22"
44
+ },
45
+ "engines": {
46
+ "node": ">=22.0.0"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/C9up/eon.git"
54
+ },
55
+ "scripts": {
56
+ "build": "tsc -p tsconfig.build.json",
57
+ "build:rust": "cargo build --release -p eon-query-napi",
58
+ "build:napi": "pnpm build:rust && node scripts/copy-napi.mjs",
59
+ "test": "vitest run",
60
+ "test:rust": "cargo test -p eon-query",
61
+ "lint": "biome check src/",
62
+ "test:coverage": "vitest run --coverage",
63
+ "typecheck": "tsc --noEmit"
64
+ }
65
+ }
@@ -0,0 +1,72 @@
1
+ // Eon ships ONE NAPI artefact:
2
+ // - eon-query-napi → index.<suffix>.node
3
+ //
4
+ // Usage:
5
+ // node scripts/copy-napi.mjs # eon-query → index.<suffix>.node
6
+
7
+ import { copyFileSync, existsSync } from 'node:fs'
8
+ import { dirname, join } from 'node:path'
9
+ import { arch, env, platform } from 'node:process'
10
+ import { fileURLToPath } from 'node:url'
11
+
12
+ const here = dirname(fileURLToPath(import.meta.url))
13
+ const root = join(here, '..')
14
+
15
+ // Cross-compile aware: set CARGO_BUILD_TARGET (e.g. x86_64-apple-darwin on an
16
+ // arm64 runner so we don't depend on the scarce macos-13 Intel runners) and we
17
+ // read target/<triple>/release. Unset = host platform / target/release.
18
+ const tripleMap = {
19
+ 'x86_64-unknown-linux-gnu': { suffix: 'linux-x64-gnu', os: 'linux' },
20
+ 'aarch64-unknown-linux-gnu': { suffix: 'linux-arm64-gnu', os: 'linux' },
21
+ 'x86_64-apple-darwin': { suffix: 'darwin-x64', os: 'darwin' },
22
+ 'aarch64-apple-darwin': { suffix: 'darwin-arm64', os: 'darwin' },
23
+ 'x86_64-pc-windows-msvc': { suffix: 'win32-x64-msvc', os: 'win32' },
24
+ }
25
+ const hostSuffixMap = {
26
+ 'linux-x64': 'linux-x64-gnu',
27
+ 'linux-arm64': 'linux-arm64-gnu',
28
+ 'darwin-x64': 'darwin-x64',
29
+ 'darwin-arm64': 'darwin-arm64',
30
+ 'win32-x64': 'win32-x64-msvc',
31
+ }
32
+
33
+ const basename = 'index'
34
+ const crate = 'eon_query_napi'
35
+
36
+ const triple = env.CARGO_BUILD_TARGET ?? ''
37
+ let suffix
38
+ let os
39
+ let releaseDir
40
+ if (triple) {
41
+ const entry = tripleMap[triple]
42
+ if (!entry) {
43
+ throw new Error(`[eon:napi] unsupported CARGO_BUILD_TARGET: ${triple}`)
44
+ }
45
+ suffix = entry.suffix
46
+ os = entry.os
47
+ releaseDir = join(root, 'target', triple, 'release')
48
+ } else {
49
+ suffix = hostSuffixMap[`${platform}-${arch}`]
50
+ os = platform
51
+ releaseDir = join(root, 'target', 'release')
52
+ if (!suffix) {
53
+ throw new Error(`[eon:napi] unsupported platform/arch: ${platform}-${arch}`)
54
+ }
55
+ }
56
+
57
+ const candidates = os === 'win32'
58
+ ? [join(releaseDir, `${crate}.dll`), join(releaseDir, `lib${crate}.dll`)]
59
+ : os === 'darwin'
60
+ ? [join(releaseDir, `lib${crate}.dylib`)]
61
+ : [join(releaseDir, `lib${crate}.so`)]
62
+
63
+ const source = candidates.find((candidate) => existsSync(candidate))
64
+ if (!source) {
65
+ throw new Error(
66
+ `[eon:napi] native library not found. Looked for:\n${candidates.map((p) => `- ${p}`).join('\n')}`,
67
+ )
68
+ }
69
+
70
+ const target = join(root, `${basename}.${suffix}.node`)
71
+ copyFileSync(source, target)
72
+ console.log(`[eon:napi] copied ${source} -> ${target}`)