@c9up/eon 0.1.0 → 0.2.1

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 (91) hide show
  1. package/README.md +5 -0
  2. package/dist/EonProvider.d.ts +6 -0
  3. package/dist/EonProvider.d.ts.map +1 -1
  4. package/dist/EonProvider.js +43 -0
  5. package/dist/EonProvider.js.map +1 -1
  6. package/dist/configure.d.ts +17 -0
  7. package/dist/configure.d.ts.map +1 -0
  8. package/dist/configure.js +19 -0
  9. package/dist/configure.js.map +1 -0
  10. package/dist/connection/config.d.ts +8 -0
  11. package/dist/connection/config.d.ts.map +1 -1
  12. package/dist/connection/config.js.map +1 -1
  13. package/dist/connection/websocket.d.ts +13 -0
  14. package/dist/connection/websocket.d.ts.map +1 -1
  15. package/dist/connection/websocket.js +16 -1
  16. package/dist/connection/websocket.js.map +1 -1
  17. package/dist/health.d.ts +50 -0
  18. package/dist/health.d.ts.map +1 -0
  19. package/dist/health.js +73 -0
  20. package/dist/health.js.map +1 -0
  21. package/dist/index.d.ts +4 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +4 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/query/TimeSeriesQuery.d.ts +12 -1
  26. package/dist/query/TimeSeriesQuery.d.ts.map +1 -1
  27. package/dist/query/TimeSeriesQuery.js +12 -1
  28. package/dist/query/TimeSeriesQuery.js.map +1 -1
  29. package/dist/schema/EonMigrationRunner.d.ts +35 -3
  30. package/dist/schema/EonMigrationRunner.d.ts.map +1 -1
  31. package/dist/schema/EonMigrationRunner.js +169 -7
  32. package/dist/schema/EonMigrationRunner.js.map +1 -1
  33. package/dist/schema/index.d.ts +15 -0
  34. package/dist/schema/index.d.ts.map +1 -0
  35. package/dist/schema/index.js +15 -0
  36. package/dist/schema/index.js.map +1 -0
  37. package/dist/testing/FakeEonConnection.d.ts +1 -1
  38. package/dist/testing/FakeEonConnection.d.ts.map +1 -1
  39. package/dist/testing/FakeEonConnection.js +27 -3
  40. package/dist/testing/FakeEonConnection.js.map +1 -1
  41. package/dist/testing/FakeEonConsumer.d.ts +28 -0
  42. package/dist/testing/FakeEonConsumer.d.ts.map +1 -0
  43. package/dist/testing/FakeEonConsumer.js +66 -0
  44. package/dist/testing/FakeEonConsumer.js.map +1 -0
  45. package/dist/testing/cleanup.d.ts +50 -0
  46. package/dist/testing/cleanup.d.ts.map +1 -0
  47. package/dist/testing/cleanup.js +88 -0
  48. package/dist/testing/cleanup.js.map +1 -0
  49. package/dist/testing/index.d.ts +6 -6
  50. package/dist/testing/index.d.ts.map +1 -1
  51. package/dist/testing/index.js +6 -14
  52. package/dist/testing/index.js.map +1 -1
  53. package/dist/testing/vitest.d.ts +7 -0
  54. package/dist/testing/vitest.d.ts.map +1 -0
  55. package/dist/testing/vitest.js +28 -0
  56. package/dist/testing/vitest.js.map +1 -0
  57. package/dist/tmq/EonConsumer.d.ts +99 -0
  58. package/dist/tmq/EonConsumer.d.ts.map +1 -0
  59. package/dist/tmq/EonConsumer.js +27 -0
  60. package/dist/tmq/EonConsumer.js.map +1 -0
  61. package/dist/tmq/index.d.ts +4 -0
  62. package/dist/tmq/index.d.ts.map +1 -0
  63. package/dist/tmq/index.js +4 -0
  64. package/dist/tmq/index.js.map +1 -0
  65. package/dist/tmq/websocket.d.ts +11 -0
  66. package/dist/tmq/websocket.d.ts.map +1 -0
  67. package/dist/tmq/websocket.js +189 -0
  68. package/dist/tmq/websocket.js.map +1 -0
  69. package/index.darwin-arm64.node +0 -0
  70. package/index.darwin-x64.node +0 -0
  71. package/index.linux-arm64-gnu.node +0 -0
  72. package/index.linux-x64-gnu.node +0 -0
  73. package/index.win32-x64-msvc.node +0 -0
  74. package/package.json +32 -3
  75. package/src/EonProvider.ts +61 -0
  76. package/src/configure.ts +38 -0
  77. package/src/connection/config.ts +8 -0
  78. package/src/connection/websocket.ts +17 -0
  79. package/src/health.ts +99 -0
  80. package/src/index.ts +17 -1
  81. package/src/query/TimeSeriesQuery.ts +12 -1
  82. package/src/schema/EonMigrationRunner.ts +205 -9
  83. package/src/schema/index.ts +28 -0
  84. package/src/testing/FakeEonConnection.ts +37 -7
  85. package/src/testing/FakeEonConsumer.ts +93 -0
  86. package/src/testing/cleanup.ts +120 -0
  87. package/src/testing/index.ts +11 -14
  88. package/src/testing/vitest.ts +27 -0
  89. package/src/tmq/EonConsumer.ts +111 -0
  90. package/src/tmq/index.ts +10 -0
  91. package/src/tmq/websocket.ts +217 -0
@@ -0,0 +1,66 @@
1
+ import { EonConsumerError } from "../tmq/EonConsumer.js";
2
+ export class FakeEonConsumer {
3
+ #topics = [];
4
+ #queue = [];
5
+ #polled = 0;
6
+ #committed = 0;
7
+ #closed = false;
8
+ /** Queue messages a later `poll()` will return, in order. */
9
+ push(...messages) {
10
+ this.#queue.push(...messages);
11
+ return this;
12
+ }
13
+ /** How many messages have been acknowledged. */
14
+ get committedCount() {
15
+ return this.#committed;
16
+ }
17
+ /** Whether `close()` has run. */
18
+ get isClosed() {
19
+ return this.#closed;
20
+ }
21
+ #ensureOpen() {
22
+ if (this.#closed)
23
+ throw new EonConsumerError("eon: consumer is closed");
24
+ }
25
+ async subscribe(topics) {
26
+ this.#ensureOpen();
27
+ if (topics.length === 0) {
28
+ throw new EonConsumerError("eon: subscribe() needs at least one topic");
29
+ }
30
+ this.#topics = [...topics];
31
+ }
32
+ async subscription() {
33
+ this.#ensureOpen();
34
+ return [...this.#topics];
35
+ }
36
+ async poll(_timeoutMs) {
37
+ this.#ensureOpen();
38
+ // Drain, don't replay: a real poll never hands back the same rows twice.
39
+ const batch = this.#queue.splice(0, this.#queue.length);
40
+ this.#polled += batch.length;
41
+ return batch;
42
+ }
43
+ async commit() {
44
+ this.#ensureOpen();
45
+ this.#committed = this.#polled;
46
+ return this.#topics.map((topic) => ({ topic, vgroupId: 0 }));
47
+ }
48
+ async assignment(topics) {
49
+ this.#ensureOpen();
50
+ return (topics ?? this.#topics).map((topic) => ({ topic, vgroupId: 0 }));
51
+ }
52
+ async seek(partition) {
53
+ this.#ensureOpen();
54
+ if (partition.offset === undefined) {
55
+ throw new EonConsumerError("eon: seek() needs an offset");
56
+ }
57
+ }
58
+ async unsubscribe() {
59
+ this.#ensureOpen();
60
+ this.#topics = [];
61
+ }
62
+ async close() {
63
+ this.#closed = true;
64
+ }
65
+ }
66
+ //# sourceMappingURL=FakeEonConsumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeEonConsumer.js","sourceRoot":"","sources":["../../src/testing/FakeEonConsumer.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,OAAO,eAAe;IAC3B,OAAO,GAAa,EAAE,CAAC;IACvB,MAAM,GAAiB,EAAE,CAAC;IAC1B,OAAO,GAAG,CAAC,CAAC;IACZ,UAAU,GAAG,CAAC,CAAC;IACf,OAAO,GAAG,KAAK,CAAC;IAEhB,6DAA6D;IAC7D,IAAI,CAAC,GAAG,QAAsB;QAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,gDAAgD;IAChD,IAAI,cAAc;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IAED,iCAAiC;IACjC,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,WAAW;QACV,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,gBAAgB,CAAC,yBAAyB,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAgB;QAC/B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,gBAAgB,CAAC,2CAA2C,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QACjB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CACT,UAAkB;QAElB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,yEAAyE;QACzE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;QAC7B,OAAO,KAAwB,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,MAAM;QACX,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAiB;QACjC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAA4B;QACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;IAED,KAAK,CAAC,WAAW;QAChB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACrB,CAAC;CACD"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Test-database lifecycle for eon integration suites.
3
+ *
4
+ * Every integration file used to spell its own
5
+ * `await conn.exec("DROP DATABASE IF EXISTS " + TEST_DB)` in `afterAll` —
6
+ * seven copies of one rule, which is how a cleanup quietly stops matching its
7
+ * setup. Atlas ships `truncateAll` / `useTransaction` for the same reason;
8
+ * TDengine has no transactions, so the unit here is the database.
9
+ */
10
+ import type { EonConnection } from "../connection/EonConnection.js";
11
+ /**
12
+ * Drop a subscription topic if it exists. Safe to call when it never existed.
13
+ *
14
+ * Order matters: TDengine REFUSES to drop a database that still carries a
15
+ * topic ("Topic must be dropped first"), so a suite that creates one must drop
16
+ * it before {@link dropTestDatabase} or {@link createTestDatabase} — including
17
+ * on the setup path, where a topic left by a crashed previous run is exactly
18
+ * what breaks the next one.
19
+ */
20
+ export declare function dropTestTopic(conn: EonConnection, topic: string, options?: {
21
+ retries?: number;
22
+ delayMs?: number;
23
+ }): Promise<void>;
24
+ /**
25
+ * Drop a test database if it exists. Safe to call when it never existed.
26
+ *
27
+ * Fails if the database still carries a topic — see {@link dropTestTopic}.
28
+ */
29
+ export declare function dropTestDatabase(conn: EonConnection, database: string): Promise<void>;
30
+ /**
31
+ * Drop, recreate and `USE` a test database — the setup half of a suite.
32
+ *
33
+ * Dropping FIRST is the point: a suite that crashed mid-run leaves rows behind,
34
+ * and a `CREATE DATABASE IF NOT EXISTS` would then run against them. A test
35
+ * that passes only because the previous run left the right data is worse than
36
+ * one that fails.
37
+ */
38
+ export declare function createTestDatabase(conn: EonConnection, database: string, options?: {
39
+ keepMs?: number;
40
+ }): Promise<void>;
41
+ /**
42
+ * Run a body against a freshly created test database, dropping it afterwards
43
+ * whether the body threw or not.
44
+ *
45
+ * The `finally` is what the hand-written `afterAll` blocks kept getting right
46
+ * by accident: a failing assertion must still leave the server clean, or the
47
+ * next run inherits the wreckage of this one.
48
+ */
49
+ export declare function withTestDatabase<T>(conn: EonConnection, database: string, body: () => Promise<T>): Promise<T>;
50
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/testing/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAqBpE;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAClC,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACvC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,88 @@
1
+ /** TDengine identifiers: a letter or underscore, then letters, digits, underscores. */
2
+ const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
3
+ /**
4
+ * Guard an identifier before it is interpolated into DDL.
5
+ *
6
+ * `exec` takes literal SQL — TDengine binds no `?` in DDL — so a database name
7
+ * reaching these helpers is concatenated. A test name is not attacker-supplied,
8
+ * but a typo'd one silently becomes a different statement, and `DROP DATABASE`
9
+ * is the statement you least want to be surprising.
10
+ */
11
+ function assertIdentifier(name, what) {
12
+ if (!IDENTIFIER.test(name)) {
13
+ throw new Error(`[E_EON_TEST_IDENTIFIER] invalid ${what} '${name}'; must match ${IDENTIFIER}`);
14
+ }
15
+ }
16
+ /**
17
+ * Drop a subscription topic if it exists. Safe to call when it never existed.
18
+ *
19
+ * Order matters: TDengine REFUSES to drop a database that still carries a
20
+ * topic ("Topic must be dropped first"), so a suite that creates one must drop
21
+ * it before {@link dropTestDatabase} or {@link createTestDatabase} — including
22
+ * on the setup path, where a topic left by a crashed previous run is exactly
23
+ * what breaks the next one.
24
+ */
25
+ export async function dropTestTopic(conn, topic, options = {}) {
26
+ assertIdentifier(topic, "topic name");
27
+ const retries = options.retries ?? 10;
28
+ const delayMs = options.delayMs ?? 300;
29
+ // TDengine rebalances a topic's partitions for a moment after a consumer
30
+ // disconnects, and refuses DROP TOPIC with "Topic being rebalanced" until it
31
+ // settles. Any suite that subscribed hits this, so the wait belongs here
32
+ // rather than copy-pasted into each one — and it must be BOUNDED: retrying
33
+ // forever would turn a real failure into a hang.
34
+ for (let attempt = 0;; attempt++) {
35
+ try {
36
+ await conn.exec(`DROP TOPIC IF EXISTS ${topic}`);
37
+ return;
38
+ }
39
+ catch (error) {
40
+ const rebalancing = /being rebalanced/i.test(error instanceof Error ? error.message : String(error));
41
+ if (!rebalancing || attempt >= retries)
42
+ throw error;
43
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
44
+ }
45
+ }
46
+ }
47
+ /**
48
+ * Drop a test database if it exists. Safe to call when it never existed.
49
+ *
50
+ * Fails if the database still carries a topic — see {@link dropTestTopic}.
51
+ */
52
+ export async function dropTestDatabase(conn, database) {
53
+ assertIdentifier(database, "database name");
54
+ await conn.exec(`DROP DATABASE IF EXISTS ${database}`);
55
+ }
56
+ /**
57
+ * Drop, recreate and `USE` a test database — the setup half of a suite.
58
+ *
59
+ * Dropping FIRST is the point: a suite that crashed mid-run leaves rows behind,
60
+ * and a `CREATE DATABASE IF NOT EXISTS` would then run against them. A test
61
+ * that passes only because the previous run left the right data is worse than
62
+ * one that fails.
63
+ */
64
+ export async function createTestDatabase(conn, database, options = {}) {
65
+ assertIdentifier(database, "database name");
66
+ await conn.exec(`DROP DATABASE IF EXISTS ${database}`);
67
+ const keep = options.keepMs === undefined ? "" : ` KEEP ${options.keepMs}`;
68
+ await conn.exec(`CREATE DATABASE ${database}${keep}`);
69
+ await conn.exec(`USE ${database}`);
70
+ }
71
+ /**
72
+ * Run a body against a freshly created test database, dropping it afterwards
73
+ * whether the body threw or not.
74
+ *
75
+ * The `finally` is what the hand-written `afterAll` blocks kept getting right
76
+ * by accident: a failing assertion must still leave the server clean, or the
77
+ * next run inherits the wreckage of this one.
78
+ */
79
+ export async function withTestDatabase(conn, database, body) {
80
+ await createTestDatabase(conn, database);
81
+ try {
82
+ return await body();
83
+ }
84
+ finally {
85
+ await dropTestDatabase(conn, database);
86
+ }
87
+ }
88
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/testing/cleanup.ts"],"names":[],"mappings":"AAWA,uFAAuF;AACvF,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C;;;;;;;GAOG;AACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,IAAY;IACnD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACd,mCAAmC,IAAI,KAAK,IAAI,iBAAiB,UAAU,EAAE,CAC7E,CAAC;IACH,CAAC;AACF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,IAAmB,EACnB,KAAa,EACb,UAAkD,EAAE;IAEpD,gBAAgB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC;IAEvC,yEAAyE;IACzE,6EAA6E;IAC7E,yEAAyE;IACzE,2EAA2E;IAC3E,iDAAiD;IACjD,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QACnC,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;YACjD,OAAO;QACR,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAC3C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACtD,CAAC;YACF,IAAI,CAAC,WAAW,IAAI,OAAO,IAAI,OAAO;gBAAE,MAAM,KAAK,CAAC;YACpD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9D,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,IAAmB,EACnB,QAAgB;IAEhB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,IAAI,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,IAAmB,EACnB,QAAgB,EAChB,UAA+B,EAAE;IAEjC,gBAAgB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,IAAI,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC;IAC3E,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,QAAQ,GAAG,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,IAAmB,EACnB,QAAgB,EAChB,IAAsB;IAEtB,MAAM,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC;QACJ,OAAO,MAAM,IAAI,EAAE,CAAC;IACrB,CAAC;YAAS,CAAC;QACV,MAAM,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;AACF,CAAC"}
@@ -6,19 +6,19 @@
6
6
  * integration suites skip via `describeIfTdengine` (mirrors atlas's "no external
7
7
  * DB required for unit tests" posture). CI sets it, so the roundtrip runs for
8
8
  * real — no silent cap. The fake store + factory need NO server.
9
+ *
10
+ * This module is RUNNER-AGNOSTIC and must stay that way: it is a shipped export
11
+ * path, so anything it imports becomes a hard requirement for every consumer.
12
+ * `describeIfTdengine` lives in `./vitest.js` for that reason.
9
13
  */
10
14
  import type { EonConnectionConfig } from "../connection/config.js";
11
15
  import type { EonConnection } from "../connection/EonConnection.js";
16
+ export { createTestDatabase, dropTestDatabase, dropTestTopic, withTestDatabase, } from "./cleanup.js";
12
17
  export { type FactoryBuilder, factory } from "./Factory.js";
13
18
  export { FakeEonConnection } from "./FakeEonConnection.js";
19
+ export { FakeEonConsumer } from "./FakeEonConsumer.js";
14
20
  /** Whether an `EON_TEST_URL` is configured (a live TDengine is reachable). */
15
21
  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
22
  /**
23
23
  * Open a connection to the test server (`EON_TEST_URL`), applying root/taosdata
24
24
  * defaults and a generous connect-retry for a cold docker server. Callers gate
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQvD,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,OAAO,CAEvC;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"}
@@ -6,11 +6,16 @@
6
6
  * integration suites skip via `describeIfTdengine` (mirrors atlas's "no external
7
7
  * DB required for unit tests" posture). CI sets it, so the roundtrip runs for
8
8
  * real — no silent cap. The fake store + factory need NO server.
9
+ *
10
+ * This module is RUNNER-AGNOSTIC and must stay that way: it is a shipped export
11
+ * path, so anything it imports becomes a hard requirement for every consumer.
12
+ * `describeIfTdengine` lives in `./vitest.js` for that reason.
9
13
  */
10
- import { describe } from "vitest";
11
14
  import { connectWsEon } from "../connection/websocket.js";
15
+ export { createTestDatabase, dropTestDatabase, dropTestTopic, withTestDatabase, } from "./cleanup.js";
12
16
  export { factory } from "./Factory.js";
13
17
  export { FakeEonConnection } from "./FakeEonConnection.js";
18
+ export { FakeEonConsumer } from "./FakeEonConsumer.js";
14
19
  /** The live TDengine URL for integration tests (taosAdapter WS), or `undefined`. */
15
20
  function testUrl() {
16
21
  const url = process.env.EON_TEST_URL;
@@ -20,19 +25,6 @@ function testUrl() {
20
25
  export function hasTestServer() {
21
26
  return testUrl() !== undefined;
22
27
  }
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
28
  /**
37
29
  * Open a connection to the test server (`EON_TEST_URL`), applying root/taosdata
38
30
  * defaults and a generous connect-retry for a cold docker server. Callers gate
@@ -1 +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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAuB,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,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,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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Register a suite that runs only when a test server is configured, else skips —
3
+ * so integration suites gate uniformly. CI (with `EON_TEST_URL`) runs them for
4
+ * real; local dev without a server skips them.
5
+ */
6
+ export declare function describeIfTdengine(name: string, factory: () => void): void;
7
+ //# sourceMappingURL=vitest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/testing/vitest.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAM1E"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The vitest-flavoured half of eon's test helpers.
3
+ *
4
+ * Split out on purpose. `@c9up/eon/testing` is a SHIPPED export path, and a
5
+ * static `import { describe } from "vitest"` made merely importing it require
6
+ * vitest — which eon carries as a devDependency only. An app on helix (ream's
7
+ * own runner) reaching for `factory` or `FakeEonConnection` would have died on
8
+ * `Cannot find package 'vitest'`, the same shape as the @c9up/comet bug.
9
+ *
10
+ * Everything runner-agnostic stays in `./index.ts`. Only this file needs the
11
+ * runner, and vitest is declared an OPTIONAL peer for it.
12
+ */
13
+ import { describe } from "vitest";
14
+ import { hasTestServer } from "./index.js";
15
+ /**
16
+ * Register a suite that runs only when a test server is configured, else skips —
17
+ * so integration suites gate uniformly. CI (with `EON_TEST_URL`) runs them for
18
+ * real; local dev without a server skips them.
19
+ */
20
+ export function describeIfTdengine(name, factory) {
21
+ if (hasTestServer()) {
22
+ describe(name, factory);
23
+ }
24
+ else {
25
+ describe.skip(name, factory);
26
+ }
27
+ }
28
+ //# sourceMappingURL=vitest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/testing/vitest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Data subscription — TDengine's TMQ, as a transport-neutral seam.
3
+ *
4
+ * eon could write and read; it could not be TOLD when something arrived. TMQ is
5
+ * how TDengine streams changes to a consumer group, and without it an app that
6
+ * wants a live dashboard has to poll a `SELECT` on a timer.
7
+ *
8
+ * Mirrors {@link EonConnection}'s posture: this file declares the contract and
9
+ * leaks no ws type, so a native transport can implement the same seam later
10
+ * without any consumer changing.
11
+ */
12
+ /** Where a consumer group starts when it has no committed offset. */
13
+ export type EonOffsetReset = "earliest" | "latest" | "none";
14
+ export interface EonConsumerConfig {
15
+ /** taosAdapter WebSocket endpoint, e.g. `ws://localhost:6041`. */
16
+ url: string;
17
+ /**
18
+ * The consumer group.
19
+ *
20
+ * Two consumers sharing a group split the partitions between them; two with
21
+ * DIFFERENT groups each receive everything. Getting this wrong is the
22
+ * classic way to either duplicate every message or silently process half.
23
+ */
24
+ groupId: string;
25
+ /** Identifies this consumer within its group, in server-side diagnostics. */
26
+ clientId?: string;
27
+ user?: string;
28
+ password?: string;
29
+ token?: string;
30
+ database?: string;
31
+ /** Where to start with no committed offset. Default: `latest`. */
32
+ offsetReset?: EonOffsetReset;
33
+ /**
34
+ * Commit offsets on a timer.
35
+ *
36
+ * Default FALSE, which deviates from the driver: auto-commit acknowledges
37
+ * messages the app may not have finished with, so a crash loses them with no
38
+ * trace. Opt in once your handler is idempotent.
39
+ */
40
+ autoCommit?: boolean;
41
+ /** Auto-commit period in ms. Ignored unless `autoCommit` is true. */
42
+ autoCommitIntervalMs?: number;
43
+ /** Include the source table name with each message. Default: true. */
44
+ withTableName?: boolean;
45
+ }
46
+ /** One topic's worth of a poll. */
47
+ export interface EonMessage<T = Record<string, unknown>> {
48
+ topic: string;
49
+ rows: T[];
50
+ }
51
+ /** A position in one topic's virtual group. */
52
+ export interface EonTopicPartition {
53
+ topic: string;
54
+ vgroupId: number;
55
+ offset?: bigint;
56
+ begin?: bigint;
57
+ end?: bigint;
58
+ }
59
+ /**
60
+ * A subscribed consumer.
61
+ *
62
+ * The lifecycle is `subscribe` → `poll` in a loop → `commit` → `close`.
63
+ */
64
+ export interface EonConsumer {
65
+ /** Start receiving from these topics. Replaces any previous subscription. */
66
+ subscribe(topics: string[]): Promise<void>;
67
+ /** The topics currently subscribed to, as the server sees them. */
68
+ subscription(): Promise<string[]>;
69
+ /**
70
+ * Wait up to `timeoutMs` for messages. Resolves to an empty array on timeout
71
+ * — that is a normal quiet period, not an error.
72
+ */
73
+ poll<T = Record<string, unknown>>(timeoutMs: number): Promise<EonMessage<T>[]>;
74
+ /** Acknowledge everything polled so far. */
75
+ commit(): Promise<EonTopicPartition[]>;
76
+ /** The partitions assigned to this consumer. */
77
+ assignment(topics?: string[]): Promise<EonTopicPartition[]>;
78
+ /** Move one partition to an offset. */
79
+ seek(partition: EonTopicPartition): Promise<void>;
80
+ /** Stop receiving, without closing the connection. */
81
+ unsubscribe(): Promise<void>;
82
+ /** Release the consumer. Safe to call twice. */
83
+ close(): Promise<void>;
84
+ }
85
+ /**
86
+ * Raised by every consumer operation.
87
+ *
88
+ * Follows {@link EonConnectionError}'s shape — the connector's numeric code is
89
+ * carried verbatim rather than swallowed, so a caller can branch on it.
90
+ */
91
+ export declare class EonConsumerError extends Error {
92
+ /** The underlying TDengine numeric error code, when the failure came from the connector. */
93
+ readonly code?: number;
94
+ constructor(message: string, options?: {
95
+ cause?: unknown;
96
+ code?: number;
97
+ });
98
+ }
99
+ //# sourceMappingURL=EonConsumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EonConsumer.d.ts","sourceRoot":"","sources":["../../src/tmq/EonConsumer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,qEAAqE;AACrE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IACjC,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sEAAsE;IACtE,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,EAAE,CAAC;CACV;AAED,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC3B,6EAA6E;IAC7E,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,mEAAmE;IACnE,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC;;;OAGG;IACH,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5B,4CAA4C;IAC5C,MAAM,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC5D,uCAAuC;IACvC,IAAI,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sDAAsD;IACtD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,gDAAgD;IAChD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;CAQzE"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Data subscription — TDengine's TMQ, as a transport-neutral seam.
3
+ *
4
+ * eon could write and read; it could not be TOLD when something arrived. TMQ is
5
+ * how TDengine streams changes to a consumer group, and without it an app that
6
+ * wants a live dashboard has to poll a `SELECT` on a timer.
7
+ *
8
+ * Mirrors {@link EonConnection}'s posture: this file declares the contract and
9
+ * leaks no ws type, so a native transport can implement the same seam later
10
+ * without any consumer changing.
11
+ */
12
+ /**
13
+ * Raised by every consumer operation.
14
+ *
15
+ * Follows {@link EonConnectionError}'s shape — the connector's numeric code is
16
+ * carried verbatim rather than swallowed, so a caller can branch on it.
17
+ */
18
+ export class EonConsumerError extends Error {
19
+ /** The underlying TDengine numeric error code, when the failure came from the connector. */
20
+ code;
21
+ constructor(message, options) {
22
+ super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);
23
+ this.name = "EonConsumerError";
24
+ this.code = options?.code;
25
+ }
26
+ }
27
+ //# sourceMappingURL=EonConsumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EonConsumer.js","sourceRoot":"","sources":["../../src/tmq/EonConsumer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkFH;;;;;GAKG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAC1C,4FAA4F;IACnF,IAAI,CAAU;IAEvB,YAAY,OAAe,EAAE,OAA4C;QACxE,KAAK,CACJ,OAAO,EACP,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CACnE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;IAC3B,CAAC;CACD"}
@@ -0,0 +1,4 @@
1
+ /** `@c9up/eon/tmq` — data subscription, without the rest of the barrel. */
2
+ export { type EonConsumer, type EonConsumerConfig, EonConsumerError, type EonMessage, type EonOffsetReset, type EonTopicPartition, } from "./EonConsumer.js";
3
+ export { connectWsConsumer } from "./websocket.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tmq/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** `@c9up/eon/tmq` — data subscription, without the rest of the barrel. */
2
+ export { EonConsumerError, } from "./EonConsumer.js";
3
+ export { connectWsConsumer } from "./websocket.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tmq/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,OAAO,EAGN,gBAAgB,GAIhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type EonConsumer, type EonConsumerConfig } from "./EonConsumer.js";
2
+ /**
3
+ * Open a consumer against a taosAdapter WebSocket endpoint.
4
+ *
5
+ * `autoCommit` defaults to FALSE, where the driver defaults it on. Auto-commit
6
+ * acknowledges messages the handler may not have finished with, so a crash
7
+ * drops them silently; a subscription that loses data without saying so is
8
+ * worse than one that redelivers.
9
+ */
10
+ export declare function connectWsConsumer(config: EonConsumerConfig): Promise<EonConsumer>;
11
+ //# sourceMappingURL=websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/tmq/websocket.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,iBAAiB,EAItB,MAAM,kBAAkB,CAAC;AAgD1B;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,iBAAiB,GACvB,OAAO,CAAC,WAAW,CAAC,CAyItB"}