@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,80 @@
1
+ /**
2
+ * `SuperTableRepository<TPoint>` — the Atlas-shaped ingest API for a TDengine
3
+ * super-table (story 58.4).
4
+ *
5
+ * Mirrors `@c9up/atlas` `BaseRepository` naming: `ingest` (≙ `create`) and
6
+ * `ingestMany` (≙ `createMany`, the bulk primitive), plus two extra write paths
7
+ * TDengine adds — `ingestSql` (literal INSERT) and `ingestSchemaless` (line
8
+ * protocol). It deliberately OMITS everything TDengine has no analogue for
9
+ * (AC8): no `save`/`upsert`/`firstOrCreate`, no `useTransaction`/BEGIN-COMMIT,
10
+ * no `RETURNING`, no DB-generated-PK hydrate-back. TDengine writes are
11
+ * append / last-write-wins by the caller-supplied timestamp.
12
+ *
13
+ * Schema is read ONLY through the 58.3 decorator metadata getters — never
14
+ * `key in instance` (the `@Column() declare x` pitfall, memory
15
+ * `project_atlas_declare_hydration`). The connection is injected structurally
16
+ * (agnostic leaf, AD1 — no `@c9up/ream` import).
17
+ */
18
+ import type { EonConnection, EonSchemalessOptions } from "../connection/EonConnection.js";
19
+ import { type IngestPoint } from "../ingest/stmt.js";
20
+ import { TimeSeriesQuery } from "../query/TimeSeriesQuery.js";
21
+ import { type SuperTableClass } from "../schema/compile.js";
22
+ /** Options for {@link SuperTableRepository}. */
23
+ export interface SuperTableRepositoryOptions {
24
+ /** STMT chunk size (rows per child per bind). Default {@link DEFAULT_BATCH_SIZE}. */
25
+ readonly batchSize?: number;
26
+ }
27
+ /**
28
+ * Repository for a TDengine super-table — atlas `BaseRepository` parity for the
29
+ * time-series model. NAMED deviation from atlas (prime directive: name any
30
+ * divergence): atlas types reads by constructing `new Entity()` instances; eon
31
+ * reads plain records and never constructs instances, so typed reads are opt-in
32
+ * through `query(mapPoint)` — the caller supplies the row → `E` mapper, composed
33
+ * on top of the bigint/timestamp-reviving base hydrator (no `as`, the decode
34
+ * stays honest). Called without a mapper, points stay `Record<string, unknown>`.
35
+ */
36
+ export declare class SuperTableRepository {
37
+ #private;
38
+ constructor(entityClass: SuperTableClass, conn: EonConnection, options?: SuperTableRepositoryOptions);
39
+ /**
40
+ * A fluent time-series read builder bound to this repository's connection and
41
+ * the entity's 58.3 schema metadata. Rows hydrate through a metadata-driven
42
+ * closure — declared columns by their `@Column`/`@Tag` metadata (bigint /
43
+ * timestamp revived as `bigint`), NEVER `key in instance` (the `declare`-field
44
+ * pitfall), and window pseudo-columns / aggregate aliases attached raw.
45
+ *
46
+ * Pass `mapPoint` to project each decoded row into a typed `E` (atlas-parity
47
+ * typed reads, no `as`): the mapper composes on top of the base hydrator so
48
+ * bigint/timestamp revival still happens first. Without a mapper, points stay
49
+ * `Record<string, unknown>`.
50
+ */
51
+ query(): TimeSeriesQuery<Record<string, unknown>>;
52
+ query<E extends object>(mapPoint: (row: Record<string, unknown>) => E): TimeSeriesQuery<E>;
53
+ /** Ingest a single point (≙ atlas `create`). */
54
+ ingest(point: IngestPoint): Promise<void>;
55
+ /**
56
+ * Bulk ingest via the columnar STMT path (≙ atlas `createMany`) — the default
57
+ * high-throughput, injection-safe write. Groups by child table, binds SoA
58
+ * columns once per batch. Returns total rows affected. `async` so a plan
59
+ * error (e.g. an unsafe-integer timestamp) surfaces as a rejection, not a
60
+ * synchronous throw at the call site.
61
+ */
62
+ ingestMany(points: readonly IngestPoint[]): Promise<{
63
+ rowsAffected: number;
64
+ }>;
65
+ /**
66
+ * Bulk ingest via literal SQL INSERT (AC5) — a convenience/fallback path run
67
+ * through `exec`. One `INSERT … USING … TAGS … VALUES` per child table; all
68
+ * value literals are rendered by the Rust compiler (no TS interpolation).
69
+ */
70
+ ingestSql(points: readonly IngestPoint[]): Promise<{
71
+ rowsAffected: number;
72
+ }>;
73
+ /**
74
+ * Bulk ingest via schemaless line protocol (AC4) — a documented ~8–10× slower
75
+ * helper, NOT the default bulk path. Renders points to InfluxDB line protocol
76
+ * from the entity metadata and passes them to the transport.
77
+ */
78
+ ingestSchemaless(points: readonly IngestPoint[], options?: EonSchemalessOptions): Promise<void>;
79
+ }
80
+ //# sourceMappingURL=SuperTableRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SuperTableRepository.d.ts","sourceRoot":"","sources":["../../src/repository/SuperTableRepository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACX,aAAa,EACb,oBAAoB,EACpB,MAAM,gCAAgC,CAAC;AASxC,OAAO,EAKN,KAAK,WAAW,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAEN,KAAK,eAAe,EACpB,MAAM,sBAAsB,CAAC;AAE9B,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC3C,qFAAqF;IACrF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;;gBAM/B,WAAW,EAAE,eAAe,EAC5B,IAAI,EAAE,aAAa,EACnB,OAAO,CAAC,EAAE,2BAA2B;IActC;;;;;;;;;;;OAWG;IACH,KAAK,IAAI,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,KAAK,CAAC,CAAC,SAAS,MAAM,EACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,GAC3C,eAAe,CAAC,CAAC,CAAC;IAqBrB,gDAAgD;IAC1C,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;;;;;OAMG;IACG,UAAU,CACf,MAAM,EAAE,SAAS,WAAW,EAAE,GAC5B,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAKpC;;;;OAIG;IACG,SAAS,CACd,MAAM,EAAE,SAAS,WAAW,EAAE,GAC5B,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAUpC;;;;OAIG;IACG,gBAAgB,CACrB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC;CAIhB"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * `SuperTableRepository<TPoint>` — the Atlas-shaped ingest API for a TDengine
3
+ * super-table (story 58.4).
4
+ *
5
+ * Mirrors `@c9up/atlas` `BaseRepository` naming: `ingest` (≙ `create`) and
6
+ * `ingestMany` (≙ `createMany`, the bulk primitive), plus two extra write paths
7
+ * TDengine adds — `ingestSql` (literal INSERT) and `ingestSchemaless` (line
8
+ * protocol). It deliberately OMITS everything TDengine has no analogue for
9
+ * (AC8): no `save`/`upsert`/`firstOrCreate`, no `useTransaction`/BEGIN-COMMIT,
10
+ * no `RETURNING`, no DB-generated-PK hydrate-back. TDengine writes are
11
+ * append / last-write-wins by the caller-supplied timestamp.
12
+ *
13
+ * Schema is read ONLY through the 58.3 decorator metadata getters — never
14
+ * `key in instance` (the `@Column() declare x` pitfall, memory
15
+ * `project_atlas_declare_hydration`). The connection is injected structurally
16
+ * (agnostic leaf, AD1 — no `@c9up/ream` import).
17
+ */
18
+ import { getColumnMetadata, getSuperTableMetadata, getTagMetadata, getTimestampColumn, } from "../decorators/superTable.js";
19
+ import { toLineProtocol } from "../ingest/schemaless.js";
20
+ import { buildLiteralInserts } from "../ingest/sql.js";
21
+ import { buildColumnarIngest, compileStmtTemplate, DEFAULT_BATCH_SIZE, toBindKind, } from "../ingest/stmt.js";
22
+ import { TimeSeriesQuery } from "../query/TimeSeriesQuery.js";
23
+ import { orderTimestampFirst, } from "../schema/compile.js";
24
+ /**
25
+ * Repository for a TDengine super-table — atlas `BaseRepository` parity for the
26
+ * time-series model. NAMED deviation from atlas (prime directive: name any
27
+ * divergence): atlas types reads by constructing `new Entity()` instances; eon
28
+ * reads plain records and never constructs instances, so typed reads are opt-in
29
+ * through `query(mapPoint)` — the caller supplies the row → `E` mapper, composed
30
+ * on top of the bigint/timestamp-reviving base hydrator (no `as`, the decode
31
+ * stays honest). Called without a mapper, points stay `Record<string, unknown>`.
32
+ */
33
+ export class SuperTableRepository {
34
+ #conn;
35
+ #plan;
36
+ #querySchema;
37
+ constructor(entityClass, conn, options) {
38
+ // Fail loud on a null/undefined connection — almost always a failed IoC
39
+ // injection (atlas `BaseRepository.ts:245` parity), not a runtime NPE later.
40
+ if (conn === null || conn === undefined) {
41
+ throw new Error(`[E_EON_MISSING_CONNECTION] SuperTableRepository for '${entityClass?.name ?? "<unknown entity>"}' requires an EonConnection (got ${conn === null ? "null" : "undefined"}). Check IoC constructor injection is wired.`);
42
+ }
43
+ this.#conn = conn;
44
+ this.#plan = buildPlan(entityClass, options);
45
+ this.#querySchema = buildQuerySchema(entityClass);
46
+ }
47
+ query(mapPoint) {
48
+ const base = this.#querySchema.hydrate;
49
+ if (mapPoint) {
50
+ return new TimeSeriesQuery(this.#querySchema.stable, this.#conn, (row) => mapPoint(base(row)), this.#querySchema.known);
51
+ }
52
+ return new TimeSeriesQuery(this.#querySchema.stable, this.#conn, base, this.#querySchema.known);
53
+ }
54
+ /** Ingest a single point (≙ atlas `create`). */
55
+ async ingest(point) {
56
+ await this.ingestMany([point]);
57
+ }
58
+ /**
59
+ * Bulk ingest via the columnar STMT path (≙ atlas `createMany`) — the default
60
+ * high-throughput, injection-safe write. Groups by child table, binds SoA
61
+ * columns once per batch. Returns total rows affected. `async` so a plan
62
+ * error (e.g. an unsafe-integer timestamp) surfaces as a rejection, not a
63
+ * synchronous throw at the call site.
64
+ */
65
+ async ingestMany(points) {
66
+ if (points.length === 0)
67
+ return { rowsAffected: 0 };
68
+ return this.#conn.ingestColumnar(buildColumnarIngest(this.#plan, points));
69
+ }
70
+ /**
71
+ * Bulk ingest via literal SQL INSERT (AC5) — a convenience/fallback path run
72
+ * through `exec`. One `INSERT … USING … TAGS … VALUES` per child table; all
73
+ * value literals are rendered by the Rust compiler (no TS interpolation).
74
+ */
75
+ async ingestSql(points) {
76
+ if (points.length === 0)
77
+ return { rowsAffected: 0 };
78
+ let rowsAffected = 0;
79
+ for (const sql of buildLiteralInserts(this.#plan, points)) {
80
+ const result = await this.#conn.exec(sql);
81
+ rowsAffected += result.rowsAffected;
82
+ }
83
+ return { rowsAffected };
84
+ }
85
+ /**
86
+ * Bulk ingest via schemaless line protocol (AC4) — a documented ~8–10× slower
87
+ * helper, NOT the default bulk path. Renders points to InfluxDB line protocol
88
+ * from the entity metadata and passes them to the transport.
89
+ */
90
+ async ingestSchemaless(points, options) {
91
+ if (points.length === 0)
92
+ return;
93
+ await this.#conn.schemaless(toLineProtocol(this.#plan, points), options);
94
+ }
95
+ }
96
+ /** Resolve the immutable ingest plan from a decorated super-table class. */
97
+ function buildPlan(entityClass, options) {
98
+ const meta = getSuperTableMetadata(entityClass);
99
+ if (!meta) {
100
+ throw new Error(`[E_EON_NOT_A_SUPERTABLE] ${entityClass.name} is not decorated with @SuperTable`);
101
+ }
102
+ const tsProperty = getTimestampColumn(entityClass);
103
+ if (!tsProperty) {
104
+ throw new Error(`[E_EON_NO_TIMESTAMP] super-table '${meta.name}' has no @Timestamp column`);
105
+ }
106
+ const columnMeta = getColumnMetadata(entityClass);
107
+ const tsColumn = columnMeta.find((c) => c.propertyKey === tsProperty);
108
+ if (!tsColumn) {
109
+ throw new Error(`[E_EON_NO_TIMESTAMP] super-table '${meta.name}' @Timestamp column '${tsProperty}' is not registered`);
110
+ }
111
+ // Timestamp first, from the SAME shared ordering the STABLE was created with
112
+ // (`orderTimestampFirst`), so the positional STMT bind lines up with the
113
+ // STABLE's physical columns and can never drift.
114
+ const ordered = orderTimestampFirst(columnMeta, tsColumn, tsProperty);
115
+ const columns = ordered.map((c) => ({
116
+ property: c.propertyKey,
117
+ kind: toBindKind(c.type, c.propertyKey),
118
+ }));
119
+ const tags = getTagMetadata(entityClass).map((t) => ({
120
+ property: t.propertyKey,
121
+ kind: toBindKind(t.type, t.propertyKey),
122
+ }));
123
+ if (tags.length === 0) {
124
+ throw new Error(`[E_EON_NO_TAGS] super-table '${meta.name}' has no @Tag columns; a child table cannot be routed without tags`);
125
+ }
126
+ const batchSize = options?.batchSize ?? DEFAULT_BATCH_SIZE;
127
+ if (!Number.isInteger(batchSize) || batchSize <= 0) {
128
+ throw new Error(`[E_EON_BATCH_SIZE] batchSize must be a positive integer (got ${batchSize})`);
129
+ }
130
+ const templateSql = compileStmtTemplate(meta.name, tags.map((t) => t.property), columns.map((c) => c.property));
131
+ return {
132
+ stable: meta.name,
133
+ templateSql,
134
+ tsProperty,
135
+ columns,
136
+ tags,
137
+ batchSize,
138
+ };
139
+ }
140
+ /**
141
+ * Build the read-side schema from the 58.3 decorator getters. The `@Column`/
142
+ * `@Tag` metadata is the ONLY source of truth — never `key in instance` (the
143
+ * `@Column() declare x` pitfall, memory `project_atlas_declare_hydration`).
144
+ */
145
+ function buildQuerySchema(entityClass) {
146
+ const meta = getSuperTableMetadata(entityClass);
147
+ if (!meta) {
148
+ throw new Error(`[E_EON_NOT_A_SUPERTABLE] ${entityClass.name} is not decorated with @SuperTable`);
149
+ }
150
+ const tsProperty = getTimestampColumn(entityClass);
151
+ if (!tsProperty) {
152
+ throw new Error(`[E_EON_NO_TIMESTAMP] super-table '${meta.name}' has no @Timestamp column`);
153
+ }
154
+ const columns = getColumnMetadata(entityClass);
155
+ const tags = getTagMetadata(entityClass);
156
+ const known = new Set([
157
+ ...columns.map((c) => c.propertyKey),
158
+ ...tags.map((t) => t.propertyKey),
159
+ ]);
160
+ // A column reads back as `bigint` when it is the timestamp primary column or
161
+ // its logical type is a 64-bit integer — parity with the compile-boundary
162
+ // precision guard, so a nanosecond `ts` or a BIGINT metric never narrows to a
163
+ // lossy double.
164
+ const bigintColumns = new Set();
165
+ for (const column of columns) {
166
+ if (column.propertyKey === tsProperty || isBigintLogicalType(column.type)) {
167
+ bigintColumns.add(column.propertyKey);
168
+ }
169
+ }
170
+ for (const tag of tags) {
171
+ if (isBigintLogicalType(tag.type))
172
+ bigintColumns.add(tag.propertyKey);
173
+ }
174
+ const hydrate = (row) => {
175
+ // Decode by metadata membership, iterating the raw row's own keys — never
176
+ // `for (key in instance)` (a `declare` field is not an own property).
177
+ const point = {};
178
+ for (const [key, value] of Object.entries(row)) {
179
+ if (!known.has(key))
180
+ continue;
181
+ // `defineProperty`, not assignment: a column named `__proto__`/`constructor`
182
+ // would otherwise hit the inherited accessor and re-parent `point`.
183
+ Object.defineProperty(point, key, {
184
+ value: bigintColumns.has(key) ? reviveBigInt(value) : value,
185
+ writable: true,
186
+ enumerable: true,
187
+ configurable: true,
188
+ });
189
+ }
190
+ return point;
191
+ };
192
+ return { stable: meta.name, hydrate, known };
193
+ }
194
+ /**
195
+ * Logical types that read back as 64-bit integers. Matched case-insensitively
196
+ * and including the `bigInteger` alias, so it stays in lock-step with the DDL /
197
+ * bind side (`TYPE_KIND_MAP` accepts `bigint`/`bigInteger`/any-case `BIGINT`) —
198
+ * a divergence here would read a genuine BIGINT column back as a lossy `number`.
199
+ */
200
+ function isBigintLogicalType(type) {
201
+ if (type === undefined)
202
+ return false;
203
+ const t = type.toLowerCase();
204
+ return t === "bigint" || t === "biginteger" || t === "timestamp";
205
+ }
206
+ /**
207
+ * Revive a raw column value into a `bigint` for a timestamp / BIGINT column.
208
+ * Accepts an existing `bigint`, an integer `number`, or an all-digits string;
209
+ * passes `null`/`undefined` through (a nullable window aggregate). Anything else
210
+ * — a fractional number, an unexpected type — fails loud rather than silently
211
+ * narrowing precision.
212
+ */
213
+ function reviveBigInt(value) {
214
+ if (typeof value === "bigint")
215
+ return value;
216
+ if (typeof value === "number") {
217
+ if (!Number.isInteger(value)) {
218
+ throw new Error(`[E_EON_HYDRATE_BIGINT] expected an integer for a bigint/timestamp column, got the non-integer ${value}`);
219
+ }
220
+ if (!Number.isSafeInteger(value)) {
221
+ throw new Error(`[E_EON_HYDRATE_BIGINT] integer ${value} exceeds the JS safe-integer range (2^53) and has already lost precision; the transport must hand a bigint/timestamp column back as bigint or a string, not a lossy number`);
222
+ }
223
+ return BigInt(value);
224
+ }
225
+ if (typeof value === "string" && /^-?\d+$/.test(value)) {
226
+ return BigInt(value);
227
+ }
228
+ if (value === null || value === undefined)
229
+ return value;
230
+ throw new Error(`[E_EON_HYDRATE_BIGINT] cannot revive a bigint/timestamp column from a ${typeof value}`);
231
+ }
232
+ //# sourceMappingURL=SuperTableRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SuperTableRepository.js","sourceRoot":"","sources":["../../src/repository/SuperTableRepository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,EACN,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,GAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACN,mBAAmB,EAEnB,mBAAmB,EACnB,kBAAkB,EAGlB,UAAU,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACN,mBAAmB,GAEnB,MAAM,sBAAsB,CAAC;AAQ9B;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAoB;IACvB,KAAK,CAAgB;IACrB,KAAK,CAAe;IACpB,YAAY,CAAc;IAEnC,YACC,WAA4B,EAC5B,IAAmB,EACnB,OAAqC;QAErC,wEAAwE;QACxE,6EAA6E;QAC7E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACd,wDAAwD,WAAW,EAAE,IAAI,IAAI,kBAAkB,oCAAoC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,8CAA8C,CACrN,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC;IAkBD,KAAK,CACJ,QAA8C;QAE9C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;QACvC,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,eAAe,CACzB,IAAI,CAAC,YAAY,CAAC,MAAM,EACxB,IAAI,CAAC,KAAK,EACV,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC5B,IAAI,CAAC,YAAY,CAAC,KAAK,CACvB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,eAAe,CACzB,IAAI,CAAC,YAAY,CAAC,MAAM,EACxB,IAAI,CAAC,KAAK,EACV,IAAI,EACJ,IAAI,CAAC,YAAY,CAAC,KAAK,CACvB,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,KAAK,CAAC,MAAM,CAAC,KAAkB;QAC9B,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CACf,MAA8B;QAE9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CACd,MAA8B;QAE9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QACpD,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1C,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,YAAY,EAAE,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CACrB,MAA8B,EAC9B,OAA8B;QAE9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAChC,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1E,CAAC;CACD;AAED,4EAA4E;AAC5E,SAAS,SAAS,CACjB,WAA4B,EAC5B,OAAqC;IAErC,MAAM,IAAI,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACd,4BAA4B,WAAW,CAAC,IAAI,oCAAoC,CAChF,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACd,qCAAqC,IAAI,CAAC,IAAI,4BAA4B,CAC1E,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC;IACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACd,qCAAqC,IAAI,CAAC,IAAI,wBAAwB,UAAU,qBAAqB,CACrG,CAAC;IACH,CAAC;IACD,6EAA6E;IAC7E,yEAAyE;IACzE,iDAAiD;IACjD,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtE,MAAM,OAAO,GAAiB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjD,QAAQ,EAAE,CAAC,CAAC,WAAW;QACvB,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC;KACvC,CAAC,CAAC,CAAC;IAEJ,MAAM,IAAI,GAAiB,cAAc,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,QAAQ,EAAE,CAAC,CAAC,WAAW;QACvB,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC;KACvC,CAAC,CAAC,CAAC;IACJ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACd,gCAAgC,IAAI,CAAC,IAAI,oEAAoE,CAC7G,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,kBAAkB,CAAC;IAC3D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACd,gEAAgE,SAAS,GAAG,CAC5E,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,mBAAmB,CACtC,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAC3B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAC9B,CAAC;IAEF,OAAO;QACN,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,WAAW;QACX,UAAU;QACV,OAAO;QACP,IAAI;QACJ,SAAS;KACT,CAAC;AACH,CAAC;AAYD;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,WAA4B;IACrD,MAAM,IAAI,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACd,4BAA4B,WAAW,CAAC,IAAI,oCAAoC,CAChF,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACd,qCAAqC,IAAI,CAAC,IAAI,4BAA4B,CAC1E,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS;QAC7B,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QACpC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;KACjC,CAAC,CAAC;IACH,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,gBAAgB;IAChB,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU,IAAI,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3E,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,CAAC;IACF,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAA4B,EAA2B,EAAE;QACzE,0EAA0E;QAC1E,sEAAsE;QACtE,MAAM,KAAK,GAA4B,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC9B,6EAA6E;YAC7E,oEAAoE;YACpE,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;gBAC3D,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aAClB,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,IAAwB;IACpD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,WAAW,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACd,iGAAiG,KAAK,EAAE,CACxG,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACd,kCAAkC,KAAK,4KAA4K,CACnN,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,IAAI,KAAK,CACd,yEAAyE,OAAO,KAAK,EAAE,CACvF,CAAC;AACH,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * TypeScript spec shapes mirroring the Rust `crates/eon-query/src/ddl.rs`
3
+ * structs, plus the logical → compiler-kind type map (parallel to atlas
4
+ * `schema/types.ts`).
5
+ *
6
+ * The facade assembles these plain JSON objects from decorator metadata and
7
+ * hands them to `compileStatementNative`; the Rust compiler owns all quoting,
8
+ * type-mapping, and schema-rule validation — the TS side never string-builds
9
+ * SQL (D1, the injection seam stays in Rust).
10
+ */
11
+ /** The user-facing logical type strings accepted on `@Column`/`@Tag`/`@Timestamp`. */
12
+ export type EonLogicalType = "timestamp" | "int" | "integer" | "bigint" | "biginteger" | "smallint" | "tinyint" | "float" | "double" | "bool" | "boolean" | "string" | "varchar" | "nchar" | "binary" | "varbinary" | "json" | "decimal";
13
+ export declare const TYPE_KIND_MAP: Record<string, string>;
14
+ /** A column or tag definition — the flattened `StableColumnDef` + `ColumnTypeSpec`. */
15
+ export interface EonColumnSpec {
16
+ name: string;
17
+ kind: string;
18
+ length: number | null;
19
+ precision: number | null;
20
+ scale: number | null;
21
+ }
22
+ export interface CreateStableSpec {
23
+ kind: "createStable";
24
+ name: string;
25
+ columns: EonColumnSpec[];
26
+ tags: EonColumnSpec[];
27
+ ifNotExists: boolean;
28
+ /** Optional STABLE `KEEP` retention (a 3.3.x+ TDengine feature). Validated as a duration in Rust. */
29
+ keep?: string;
30
+ }
31
+ /** One `ALTER STABLE` change — tagged on `op`, mirroring the Rust `AlterChange`. */
32
+ export type AlterChange = {
33
+ op: "addColumn";
34
+ name: string;
35
+ type: Omit<EonColumnSpec, "name">;
36
+ } | {
37
+ op: "dropColumn";
38
+ name: string;
39
+ } | {
40
+ op: "modifyColumn";
41
+ name: string;
42
+ type: Omit<EonColumnSpec, "name">;
43
+ } | {
44
+ op: "addTag";
45
+ name: string;
46
+ type: Omit<EonColumnSpec, "name">;
47
+ } | {
48
+ op: "dropTag";
49
+ name: string;
50
+ } | {
51
+ op: "modifyTag";
52
+ name: string;
53
+ type: Omit<EonColumnSpec, "name">;
54
+ } | {
55
+ op: "renameTag";
56
+ from: string;
57
+ to: string;
58
+ };
59
+ export interface AlterStableSpec {
60
+ kind: "alterStable";
61
+ name: string;
62
+ changes: AlterChange[];
63
+ }
64
+ export interface CreateChildTableSpec {
65
+ kind: "createChildTable";
66
+ name: string;
67
+ using: string;
68
+ tags: unknown[];
69
+ ifNotExists: boolean;
70
+ /** Inline tag values as SQL literals (58.3 `exec`) vs `?` placeholders (STMT, 58.4). */
71
+ literal: boolean;
72
+ /** Optional child-table `TTL` in whole days (`>= 0`, a 3.3.x+ TDengine feature). */
73
+ ttl?: number;
74
+ }
75
+ export interface DropStableSpec {
76
+ kind: "dropStable";
77
+ name: string;
78
+ ifExists: boolean;
79
+ }
80
+ /** TDengine timestamp precision — the create-only `PRECISION` database option. */
81
+ export type EonPrecision = "ms" | "us" | "ns";
82
+ /** TDengine `CACHEMODEL` allowlist. */
83
+ export type EonCacheModel = "none" | "last_row" | "last_value" | "both";
84
+ /**
85
+ * `CREATE DATABASE` options (retention / storage). Every value is validated in
86
+ * Rust (durations, precision/cachemodel/wal-level allowlists, `KEEP >= 3x
87
+ * DURATION`). Options are emitted only when present, in a fixed order.
88
+ */
89
+ export interface EonDatabaseOptions {
90
+ /** Retention duration (e.g. `"90d"`). Must be `>= 3 x DURATION` when both are set with the same unit. */
91
+ keep?: string;
92
+ /** Per-file time span (e.g. `"10d"`). Create-only — cannot be altered. */
93
+ duration?: string;
94
+ /** Timestamp precision. Create-only — cannot be altered. */
95
+ precision?: EonPrecision;
96
+ /** Write buffer size in MB. */
97
+ buffer?: number;
98
+ /** WAL level (1 or 2). */
99
+ walLevel?: 1 | 2;
100
+ /** Row cache mode. */
101
+ cachemodel?: EonCacheModel;
102
+ }
103
+ export interface CreateDatabaseSpec extends EonDatabaseOptions {
104
+ kind: "createDatabase";
105
+ name: string;
106
+ ifNotExists: boolean;
107
+ }
108
+ /**
109
+ * `ALTER DATABASE` — TDengine changes exactly ONE option per statement, so
110
+ * exactly one field must be set. Create-only options (`PRECISION`/`DURATION`)
111
+ * are intentionally absent here.
112
+ */
113
+ export interface EonAlterDatabaseOptions {
114
+ keep?: string;
115
+ buffer?: number;
116
+ walLevel?: 1 | 2;
117
+ cachemodel?: EonCacheModel;
118
+ replica?: number;
119
+ minrows?: number;
120
+ }
121
+ export interface AlterDatabaseSpec {
122
+ kind: "alterDatabase";
123
+ name: string;
124
+ /** The Rust-side option name (e.g. `"keep"`, `"wal_level"`). */
125
+ option: string;
126
+ value: string | number;
127
+ }
128
+ /** A basic (non-super) table: first column `TIMESTAMP`, then columns, no `TAGS`. */
129
+ export interface CreateTableSpec {
130
+ kind: "createTable";
131
+ name: string;
132
+ columns: EonColumnSpec[];
133
+ ifNotExists: boolean;
134
+ }
135
+ export interface DropTableSpec {
136
+ kind: "dropTable";
137
+ name: string;
138
+ ifExists: boolean;
139
+ }
140
+ //# sourceMappingURL=CreateStableSpec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateStableSpec.d.ts","sourceRoot":"","sources":["../../src/schema/CreateStableSpec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * TypeScript spec shapes mirroring the Rust `crates/eon-query/src/ddl.rs`
3
+ * structs, plus the logical → compiler-kind type map (parallel to atlas
4
+ * `schema/types.ts`).
5
+ *
6
+ * The facade assembles these plain JSON objects from decorator metadata and
7
+ * hands them to `compileStatementNative`; the Rust compiler owns all quoting,
8
+ * type-mapping, and schema-rule validation — the TS side never string-builds
9
+ * SQL (D1, the injection seam stays in Rust).
10
+ */
11
+ /**
12
+ * Map a logical type string to the compiler's `ColumnTypeKind` (serde
13
+ * camelCase). Common aliases collapse onto one kind (`int`/`integer` → `int`,
14
+ * `string`/`varchar` → `varchar`, `binary`/`varbinary` → `varbinary`). Physical
15
+ * TDengine types are resolved from these kinds in Rust (`Dialect::map_column_type`).
16
+ */
17
+ const TYPE_KIND_ENTRIES = {
18
+ timestamp: "timestamp",
19
+ int: "int",
20
+ integer: "int",
21
+ bigint: "bigInt",
22
+ biginteger: "bigInt",
23
+ smallint: "smallInt",
24
+ tinyint: "tinyInt",
25
+ float: "float",
26
+ double: "double",
27
+ bool: "bool",
28
+ boolean: "bool",
29
+ string: "varchar",
30
+ varchar: "varchar",
31
+ nchar: "nchar",
32
+ binary: "varbinary",
33
+ varbinary: "varbinary",
34
+ json: "json",
35
+ decimal: "decimal",
36
+ // `satisfies` makes this exhaustive + exact against EonLogicalType (a missing
37
+ // or stray key is a compile error) while the exported map stays string-keyed
38
+ // so an arbitrary logical string can be looked up without a cast.
39
+ };
40
+ export const TYPE_KIND_MAP = TYPE_KIND_ENTRIES;
41
+ //# sourceMappingURL=CreateStableSpec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateStableSpec.js","sourceRoot":"","sources":["../../src/schema/CreateStableSpec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuBH;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG;IACzB,SAAS,EAAE,WAAW;IACtB,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,WAAW;IACnB,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,8EAA8E;IAC9E,6EAA6E;IAC7E,kEAAkE;CACzB,CAAC;AAE3C,MAAM,CAAC,MAAM,aAAa,GAA2B,iBAAiB,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `EonMigrationRunner` — discovers, executes, and tracks eon (TDengine)
3
+ * migrations. Mirrors atlas `MigrationRunner` (`schema/MigrationRunner.ts`):
4
+ * sorted-file discovery, a `ream_`-prefixed tracking table, batch-based
5
+ * rollback, `init/status/migrate/rollback/reset/refresh/fresh/dryRun`.
6
+ *
7
+ * ── TWO named TDengine deviations from atlas (AC6) ──────────────────────────
8
+ *
9
+ * 1. **No transactions / no engine rollback.** TDengine DDL is non-transactional
10
+ * — a batch CANNOT be applied atomically. The runner executes statements
11
+ * **sequentially**; a mid-migration failure leaves earlier statements
12
+ * applied. The mitigation is idempotent DDL (`IF (NOT) EXISTS`, the
13
+ * `EonSchema` default) so a re-run converges. There is NO `runInTransaction`.
14
+ *
15
+ * 2. **No `UNIQUE`, no auto-increment.** The tracking table is a basic table
16
+ * `ream_eon_migrations(executed_at TIMESTAMP, name VARCHAR(255), batch INT)`;
17
+ * the applied-set is de-duped **by name in JS**, and each record is written
18
+ * with a strictly-increasing `executed_at` so rollback can delete it by that
19
+ * unique timestamp key (TDengine only allows a `DELETE` predicate on the
20
+ * primary timestamp column).
21
+ *
22
+ * Agnostic leaf: takes the connection structurally and a plain directory path —
23
+ * no `@c9up/ream` import, no app helper (`project_package_extraction`).
24
+ */
25
+ import type { EonConnection } from "../connection/EonConnection.js";
26
+ export interface EonMigrationOptions {
27
+ /** Directory holding migration files. Default `database/eon-migrations`. */
28
+ migrationsDir?: string;
29
+ /**
30
+ * Tracking-table name. Default `ream_eon_migrations`. Must match
31
+ * `/^[A-Za-z_][A-Za-z0-9_]*$/`. The `ream_` prefix marks it a framework/system
32
+ * table (`feedback_underscore_policy`) — keep it so cleanup helpers skip it.
33
+ */
34
+ tableName?: string;
35
+ }
36
+ export type MigrationState = "applied" | "pending";
37
+ export interface MigrationStatus {
38
+ name: string;
39
+ state: MigrationState;
40
+ batch?: number;
41
+ }
42
+ export declare class EonMigrationRunner {
43
+ #private;
44
+ constructor(conn: EonConnection, options?: EonMigrationOptions);
45
+ /** Create the tracking table (`IF NOT EXISTS`) via the basic-table DDL path. */
46
+ init(): Promise<void>;
47
+ /** The status of every discovered migration (applied vs pending). */
48
+ status(): Promise<MigrationStatus[]>;
49
+ /** Run every pending migration (filename order), recording each. */
50
+ migrate(): Promise<string[]>;
51
+ /** Roll back the most-recent batch (files in reverse order), running `down()`. */
52
+ rollback(): Promise<string[]>;
53
+ /** Roll back every applied batch (Lucid `migrate:reset`). */
54
+ reset(): Promise<string[]>;
55
+ /** Reset then re-run every migration (Lucid `migrate:refresh`). */
56
+ refresh(): Promise<{
57
+ rolled: string[];
58
+ executed: string[];
59
+ }>;
60
+ /** Alias of {@link refresh} (Lucid `migrate:fresh`). */
61
+ fresh(): Promise<{
62
+ rolled: string[];
63
+ executed: string[];
64
+ }>;
65
+ /** Compute the SQL each pending migration would emit, WITHOUT executing it. */
66
+ dryRun(): Promise<Array<{
67
+ name: string;
68
+ sql: string[];
69
+ }>>;
70
+ }
71
+ //# sourceMappingURL=EonMigrationRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EonMigrationRunner.d.ts","sourceRoot":"","sources":["../../src/schema/EonMigrationRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAUpE,MAAM,WAAW,mBAAmB;IACnC,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AASD,qBAAa,kBAAkB;;gBAKlB,IAAI,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB;IAYlE,gFAAgF;IAC1E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC3B,qEAAqE;IAC/D,MAAM,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAa1C,oEAAoE;IAC9D,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BlC,kFAAkF;IAC5E,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA2BnC,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAYhC,mEAAmE;IAC7D,OAAO,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAMlE,wDAAwD;IACxD,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAI1D,+EAA+E;IACzE,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAyI/D"}