tina4-nodejs 3.13.92 → 3.13.95

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 (193) hide show
  1. package/CLAUDE.md +170 -28
  2. package/README.md +2 -2
  3. package/package.json +13 -9
  4. package/packages/cli/dist/bin.js +33126 -30055
  5. package/packages/cli/src/commands/metrics.ts +17 -11
  6. package/packages/cli/src/commands/serve.ts +10 -9
  7. package/packages/core/dist/index.js +33062 -29908
  8. package/packages/core/src/ai.ts +7 -1
  9. package/packages/core/src/auth.ts +191 -39
  10. package/packages/core/src/background.ts +19 -19
  11. package/packages/core/src/cache.ts +492 -49
  12. package/packages/core/src/devAdmin.ts +79 -32
  13. package/packages/core/src/devMailbox.ts +20 -44
  14. package/packages/core/src/dispatchPipeline.ts +285 -0
  15. package/packages/core/src/dotenv.ts +185 -40
  16. package/packages/core/src/index.ts +7 -6
  17. package/packages/core/src/logger.ts +257 -36
  18. package/packages/core/src/mcp.ts +1 -1
  19. package/packages/core/src/messenger.ts +81 -13
  20. package/packages/core/src/metrics.ts +199 -961
  21. package/packages/core/src/middleware.ts +390 -123
  22. package/packages/core/src/queue.ts +188 -32
  23. package/packages/core/src/queueBackends/kafkaBackend.ts +109 -13
  24. package/packages/core/src/queueBackends/liteBackend.ts +13 -0
  25. package/packages/core/src/queueBackends/mongoBackend.ts +101 -9
  26. package/packages/core/src/queueBackends/rabbitmqBackend.ts +22 -4
  27. package/packages/core/src/rateLimiter.ts +10 -5
  28. package/packages/core/src/request.ts +6 -9
  29. package/packages/core/src/response.ts +46 -1
  30. package/packages/core/src/router.ts +29 -4
  31. package/packages/core/src/server.ts +751 -414
  32. package/packages/core/src/session.ts +244 -27
  33. package/packages/core/src/sessionHandlers/childError.ts +72 -0
  34. package/packages/core/src/sessionHandlers/databaseHandler.ts +338 -48
  35. package/packages/core/src/sessionHandlers/memcachedHandler.ts +181 -0
  36. package/packages/core/src/sessionHandlers/mongoClient.ts +293 -202
  37. package/packages/core/src/sessionHandlers/mongoHandler.ts +88 -8
  38. package/packages/core/src/sessionHandlers/respClient.ts +16 -143
  39. package/packages/core/src/sessionHandlers/sqlClient.ts +290 -0
  40. package/packages/core/src/sessionHandlers/syncBridge.ts +190 -0
  41. package/packages/core/src/sessionHandlers/syncSocket.ts +236 -0
  42. package/packages/core/src/testClient.ts +18 -5
  43. package/packages/core/src/trustedProxy.ts +249 -0
  44. package/packages/core/src/types.ts +29 -5
  45. package/packages/core/src/websocket.ts +66 -0
  46. package/packages/frond/dist/index.js +74 -31
  47. package/packages/frond/src/engine.ts +99 -33
  48. package/packages/orm/dist/index.js +26554 -23400
  49. package/packages/orm/src/adapters/firebird.ts +183 -56
  50. package/packages/orm/src/adapters/mongodb.ts +25 -4
  51. package/packages/orm/src/adapters/mssql.ts +114 -29
  52. package/packages/orm/src/adapters/mysql.ts +103 -40
  53. package/packages/orm/src/adapters/odbc.ts +44 -21
  54. package/packages/orm/src/adapters/postgres.ts +118 -26
  55. package/packages/orm/src/adapters/sqlDialect.ts +120 -0
  56. package/packages/orm/src/adapters/sqlite.ts +64 -25
  57. package/packages/orm/src/baseModel.ts +135 -40
  58. package/packages/orm/src/cachedDatabase.ts +43 -19
  59. package/packages/orm/src/connectTimeout.ts +265 -0
  60. package/packages/orm/src/database.ts +338 -198
  61. package/packages/orm/src/databaseResult.ts +65 -13
  62. package/packages/orm/src/databaseUrl.ts +484 -0
  63. package/packages/orm/src/docstore.ts +386 -145
  64. package/packages/orm/src/index.ts +13 -3
  65. package/packages/orm/src/migration.ts +18 -3
  66. package/packages/orm/src/queryBuilder.ts +38 -4
  67. package/packages/orm/src/sqlTranslator.ts +310 -4
  68. package/packages/orm/src/types.ts +15 -4
  69. package/types/cli/src/bin.d.ts +92 -0
  70. package/types/cli/src/commands/build.d.ts +2 -0
  71. package/types/cli/src/commands/generate.d.ts +47 -0
  72. package/types/cli/src/commands/init.d.ts +1 -0
  73. package/types/cli/src/commands/metrics.d.ts +6 -0
  74. package/types/cli/src/commands/migrate.d.ts +1 -0
  75. package/types/cli/src/commands/migrateCreate.d.ts +1 -0
  76. package/types/cli/src/commands/migrateRollback.d.ts +1 -0
  77. package/types/cli/src/commands/migrateStatus.d.ts +1 -0
  78. package/types/cli/src/commands/queue.d.ts +20 -0
  79. package/types/cli/src/commands/routes.d.ts +1 -0
  80. package/types/cli/src/commands/seed.d.ts +1 -0
  81. package/types/cli/src/commands/serve.d.ts +6 -0
  82. package/types/cli/src/commands/test.d.ts +1 -0
  83. package/types/core/src/ai.d.ts +64 -0
  84. package/types/core/src/api.d.ts +262 -0
  85. package/types/core/src/auth.d.ts +177 -0
  86. package/types/core/src/authGate.d.ts +20 -0
  87. package/types/core/src/background.d.ts +34 -0
  88. package/types/core/src/cache.d.ts +163 -0
  89. package/types/core/src/constants.d.ts +38 -0
  90. package/types/core/src/container.d.ts +44 -0
  91. package/types/core/src/context/chunker.d.ts +31 -0
  92. package/types/core/src/context/index.d.ts +93 -0
  93. package/types/core/src/devAdmin.d.ts +179 -0
  94. package/types/core/src/devMailbox.d.ts +54 -0
  95. package/types/core/src/dispatchPipeline.d.ts +117 -0
  96. package/types/core/src/docs.d.ts +141 -0
  97. package/types/core/src/docsAutoDiscovery.d.ts +6 -0
  98. package/types/core/src/dotenv.d.ts +87 -0
  99. package/types/core/src/env.d.ts +28 -0
  100. package/types/core/src/errorOverlay.d.ts +36 -0
  101. package/types/core/src/events.d.ts +75 -0
  102. package/types/core/src/fakeData.d.ts +55 -0
  103. package/types/core/src/feedback.d.ts +90 -0
  104. package/types/core/src/graphql.d.ts +207 -0
  105. package/types/core/src/health.d.ts +22 -0
  106. package/types/core/src/htmlElement.d.ts +75 -0
  107. package/types/core/src/i18n.d.ts +37 -0
  108. package/types/core/src/index.d.ts +92 -0
  109. package/types/core/src/job.d.ts +39 -0
  110. package/types/core/src/logger.d.ts +200 -0
  111. package/types/core/src/mcp.d.ts +248 -0
  112. package/types/core/src/messenger.d.ts +191 -0
  113. package/types/core/src/metrics.d.ts +41 -0
  114. package/types/core/src/middleware.d.ts +330 -0
  115. package/types/core/src/mqtt.d.ts +257 -0
  116. package/types/core/src/mqttMessage.d.ts +67 -0
  117. package/types/core/src/plan.d.ts +96 -0
  118. package/types/core/src/projectIndex.d.ts +56 -0
  119. package/types/core/src/queue.d.ts +268 -0
  120. package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
  121. package/types/core/src/queueBackends/liteBackend.d.ts +128 -0
  122. package/types/core/src/queueBackends/mongoBackend.d.ts +119 -0
  123. package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
  124. package/types/core/src/rateLimiter.d.ts +49 -0
  125. package/types/core/src/request.d.ts +25 -0
  126. package/types/core/src/response.d.ts +28 -0
  127. package/types/core/src/routeDiscovery.d.ts +12 -0
  128. package/types/core/src/router.d.ts +366 -0
  129. package/types/core/src/scss.d.ts +19 -0
  130. package/types/core/src/server.d.ts +146 -0
  131. package/types/core/src/service.d.ts +115 -0
  132. package/types/core/src/session.d.ts +341 -0
  133. package/types/core/src/sessionHandlers/childError.d.ts +34 -0
  134. package/types/core/src/sessionHandlers/databaseHandler.d.ts +97 -0
  135. package/types/core/src/sessionHandlers/memcachedHandler.d.ts +60 -0
  136. package/types/core/src/sessionHandlers/mongoClient.d.ts +35 -0
  137. package/types/core/src/sessionHandlers/mongoHandler.d.ts +109 -0
  138. package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
  139. package/types/core/src/sessionHandlers/sqlClient.d.ts +39 -0
  140. package/types/core/src/sessionHandlers/syncBridge.d.ts +91 -0
  141. package/types/core/src/sessionHandlers/syncSocket.d.ts +49 -0
  142. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
  143. package/types/core/src/static.d.ts +2 -0
  144. package/types/core/src/test.d.ts +94 -0
  145. package/types/core/src/testClient.d.ts +36 -0
  146. package/types/core/src/testing.d.ts +58 -0
  147. package/types/core/src/trustedProxy.d.ts +44 -0
  148. package/types/core/src/types.d.ts +242 -0
  149. package/types/core/src/validator.d.ts +52 -0
  150. package/types/core/src/websocket.d.ts +402 -0
  151. package/types/core/src/websocketBackplane.d.ts +166 -0
  152. package/types/core/src/websocketConnection.d.ts +54 -0
  153. package/types/core/src/wsdl.d.ts +101 -0
  154. package/types/frond/src/engine.d.ts +263 -0
  155. package/types/frond/src/index.d.ts +2 -0
  156. package/types/orm/src/adapters/firebird.d.ts +183 -0
  157. package/types/orm/src/adapters/mongodb.d.ts +81 -0
  158. package/types/orm/src/adapters/mssql.d.ts +77 -0
  159. package/types/orm/src/adapters/mysql.d.ts +67 -0
  160. package/types/orm/src/adapters/odbc.d.ts +94 -0
  161. package/types/orm/src/adapters/postgres.d.ts +86 -0
  162. package/types/orm/src/adapters/sqlDialect.d.ts +71 -0
  163. package/types/orm/src/adapters/sqlite.d.ts +68 -0
  164. package/types/orm/src/autoCrud.d.ts +73 -0
  165. package/types/orm/src/baseModel.d.ts +427 -0
  166. package/types/orm/src/cachedDatabase.d.ts +190 -0
  167. package/types/orm/src/connectTimeout.d.ts +100 -0
  168. package/types/orm/src/database.d.ts +655 -0
  169. package/types/orm/src/databaseResult.d.ts +109 -0
  170. package/types/orm/src/databaseUrl.d.ts +125 -0
  171. package/types/orm/src/docstore.d.ts +241 -0
  172. package/types/orm/src/fakeData.d.ts +22 -0
  173. package/types/orm/src/index.d.ts +43 -0
  174. package/types/orm/src/migration.d.ts +275 -0
  175. package/types/orm/src/model.d.ts +7 -0
  176. package/types/orm/src/query.d.ts +14 -0
  177. package/types/orm/src/queryBuilder.d.ts +193 -0
  178. package/types/orm/src/realtime/index.d.ts +7 -0
  179. package/types/orm/src/realtime/models/attachment.d.ts +43 -0
  180. package/types/orm/src/realtime/models/channel.d.ts +32 -0
  181. package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
  182. package/types/orm/src/realtime/models/message.d.ts +36 -0
  183. package/types/orm/src/realtime/models/workspace.d.ts +26 -0
  184. package/types/orm/src/realtime/realtime.d.ts +24 -0
  185. package/types/orm/src/realtime/storage.d.ts +61 -0
  186. package/types/orm/src/seeder.d.ts +118 -0
  187. package/types/orm/src/sqlTranslator.d.ts +258 -0
  188. package/types/orm/src/types.d.ts +148 -0
  189. package/types/orm/src/validation.d.ts +6 -0
  190. package/types/swagger/src/generator.d.ts +46 -0
  191. package/types/swagger/src/index.d.ts +2 -0
  192. package/types/swagger/src/ui.d.ts +11 -0
  193. package/packages/core/src/sessionHandlers/redisHandler.ts +0 -206
@@ -0,0 +1,275 @@
1
+ import type { DatabaseAdapter } from "./types.js";
2
+ import type { DiscoveredModel } from "./model.js";
3
+ /**
4
+ * Make CREATE TABLE idempotent on engines lacking IF NOT EXISTS.
5
+ *
6
+ * Firebird and MSSQL do not support `CREATE TABLE IF NOT EXISTS`, so a raw
7
+ * CREATE in a re-run migration raises "object already exists". When the target
8
+ * table already exists on those engines, return a skip reason so the statement
9
+ * is skipped (mirrors the Firebird ALTER-TABLE-ADD idempotency guard).
10
+ * SQLite/MySQL/PostgreSQL support IF NOT EXISTS and are left to the engine.
11
+ * Only a genuine already-exists is skipped — every other error still raises.
12
+ */
13
+ export declare function shouldSkipCreateTable(db: DatabaseAdapter, stmt: string): Promise<string | null>;
14
+ /**
15
+ * Sync model definitions to the database (create tables, add columns).
16
+ */
17
+ export declare function syncModels(models: DiscoveredModel[]): Promise<void>;
18
+ /**
19
+ * Ensure the migration tracking table exists in the canonical shape (creating
20
+ * it or upgrading an older one in place) on the global adapter.
21
+ */
22
+ export declare function ensureMigrationTable(): Promise<void>;
23
+ /**
24
+ * Get the current batch number (max batch + 1).
25
+ */
26
+ export declare function getNextBatch(): Promise<number>;
27
+ /**
28
+ * Check if a migration has already been applied (a row with passed = 1).
29
+ */
30
+ export declare function isMigrationApplied(name: string): Promise<boolean>;
31
+ /**
32
+ * Record a migration as applied (public API). Routes through recordApplied() so
33
+ * a leftover passed=0 row for the same migration_name is deleted before the
34
+ * fresh row is written (at most one row per migration_name).
35
+ */
36
+ export declare function recordMigration(name: string, batch: number, passed?: number): Promise<void>;
37
+ /**
38
+ * Apply a migration (run its up function and record it).
39
+ */
40
+ export declare function applyMigration(name: string, up: () => void | Promise<void>, batch: number): Promise<void>;
41
+ /**
42
+ * Get all migrations from the last batch.
43
+ */
44
+ export declare function getLastBatchMigrations(): Promise<Array<{
45
+ id: number;
46
+ migration_name: string;
47
+ batch: number;
48
+ }>>;
49
+ /**
50
+ * Remove a migration record (used during rollback).
51
+ */
52
+ export declare function removeMigrationRecord(name: string): Promise<void>;
53
+ /**
54
+ * Rollback the last batch of migrations using .down.sql files.
55
+ *
56
+ * For each migration in the last batch (in reverse order):
57
+ * 1. Looks for a corresponding .down.sql file on disk
58
+ * 2. If found, reads and executes the SQL statements
59
+ * 3. If not found, logs a warning
60
+ * 4. Deletes the tracking record either way
61
+ *
62
+ * @param migrationsDir - Directory containing migration files (default: "migrations")
63
+ * @param delimiter - SQL statement delimiter (default: ";")
64
+ * @returns Array of the down-migration files that were run, e.g.
65
+ * "000001_create_users.down.sql". (The legacy down-FUNCTION Map API returns the
66
+ * bare migration name instead, since no .down.sql file is involved there.)
67
+ *
68
+ * NOTE on return form (intentional, cross-framework): migration return values reflect
69
+ * WHAT each method acted on, so the forms differ by method and that is by design (not
70
+ * unified). migrate()/getApplied()/getPending() return the up-migration filename
71
+ * ("name.sql"); rollback() returns the DOWN-migration filename it executed
72
+ * ("name.down.sql") — matching the Python master. So a caller diffing rollback()
73
+ * against getApplied() compares ".down.sql" vs ".sql": strip the suffixes (or compare
74
+ * the bare "name" stem) to relate them.
75
+ */
76
+ export declare function rollback(migrationsDir?: string | Map<string, () => void | Promise<void>>, delimiter?: string): Promise<string[]>;
77
+ /**
78
+ * Get all applied migrations.
79
+ */
80
+ export declare function getAppliedMigrations(): Promise<Array<{
81
+ id: number;
82
+ migration_name: string;
83
+ description: string;
84
+ batch: number;
85
+ executed_at: string;
86
+ passed: number;
87
+ }>>;
88
+ /**
89
+ * Result returned by the `migrate()` function.
90
+ */
91
+ export interface MigrationResult {
92
+ /** Filenames of successfully applied migrations. */
93
+ applied: string[];
94
+ /** Filenames that were already applied (skipped). */
95
+ skipped: string[];
96
+ /** Filenames that failed with error details. */
97
+ failed: string[];
98
+ }
99
+ /**
100
+ * Result returned by the `status()` function.
101
+ */
102
+ export interface MigrationStatus {
103
+ /** Filenames of completed (already applied) migrations. */
104
+ completed: string[];
105
+ /** Filenames of pending (not yet applied) migrations. */
106
+ pending: string[];
107
+ }
108
+ /**
109
+ * Replace smart/curly quotes with straight ASCII quotes so migration SQL
110
+ * authored or pasted from an editor/doc actually runs (those code points are
111
+ * not valid SQL delimiters). Already-straight quotes and ordinary string
112
+ * content are returned byte-for-byte unchanged.
113
+ */
114
+ export declare function normalizeQuotes(sql: string): string;
115
+ /**
116
+ * Return the new terminator from a `SET TERM <new> <current>` directive.
117
+ *
118
+ * `SET TERM` is a script-level directive (recognised by isql and other
119
+ * InterBase/Firebird tooling, not run by the engine) that changes the
120
+ * terminator separating statements. Recognising it lets a statement whose own
121
+ * body contains the default `;` terminator — a trigger, stored procedure or
122
+ * `EXECUTE BLOCK` — be kept intact rather than split on those inner `;`. The
123
+ * terminator may be more than one character (e.g. `!!`).
124
+ *
125
+ * @param statement A single, already-trimmed statement.
126
+ * @returns The new terminator, or `null` when `statement` is not a `SET TERM`
127
+ * directive.
128
+ */
129
+ export declare function parseSetTerm(statement: string): string | null;
130
+ /**
131
+ * Split SQL text into individual statements with a single-pass, quote- and
132
+ * comment-aware scanner. The split decision is made character by character so
133
+ * the delimiter only ever fires in real statement position.
134
+ *
135
+ * This is the fix for issue #54: the old implementation split on `delimiter`
136
+ * BEFORE stripping `-- …` line comments, so a `;` inside a line comment
137
+ * fragmented one statement into several broken pieces. A scanner that knows
138
+ * where it is (code / comment / string) cannot make that mistake.
139
+ *
140
+ * Handled, in priority order, only when NOT already inside a stored-proc block:
141
+ * - `$$ … $$` and `// … //` stored-proc blocks are kept intact (inner `;` never
142
+ * splits). A `//` preceded by `:` is a URL scheme (`https://…`), not a delimiter.
143
+ * - `/* … *​/` block comments are stripped.
144
+ * - `-- …` line comments are stripped to end of line (the newline is kept).
145
+ * - `'…'` single-quoted strings and `"…"` double-quoted identifiers are copied
146
+ * verbatim, honouring the SQL doubled-quote escape (`''` / `""`); a `;`, `--`
147
+ * or `/*` inside a literal is data, not a delimiter or comment.
148
+ * - A `SET TERM <new> <current>` directive switches the active terminator and is
149
+ * consumed (never emitted), so a statement whose own body contains the default
150
+ * terminator — a Firebird trigger, stored procedure or `EXECUTE BLOCK` —
151
+ * survives as one. Multi-character terminators (e.g. `!!`) are supported.
152
+ * Mirrors the tina4-python `_split_statements` / tina4-php / tina4-ruby scanner (parity).
153
+ */
154
+ export declare function splitStatements(sql: string, delimiter?: string): string[];
155
+ /**
156
+ * Sort migration filenames supporting both naming patterns:
157
+ * - Sequential: 000001_name.sql, 000002_name.sql
158
+ * - Timestamp: 20240315120000_name.sql (YYYYMMDDHHMMSS)
159
+ *
160
+ * Numeric-aware: a file with a leading numeric/timestamp prefix sorts first by
161
+ * that number (so `9_*` applies before `10_*` — a plain lexical sort misorders
162
+ * unpadded prefixes because "10" < "9"). Files with NO numeric prefix sort
163
+ * AFTER the numbered ones, then lexically. Mirrors Python's `_migration_sort_key`.
164
+ */
165
+ export declare function sortMigrationFiles(files: string[]): string[];
166
+ /**
167
+ * Run all pending SQL-file migrations.
168
+ *
169
+ * Supports both naming patterns:
170
+ * - Sequential: 000001_description.sql
171
+ * - Timestamp: YYYYMMDDHHMMSS_description.sql
172
+ *
173
+ * 1. Creates the `tina4_migration` tracking table if it doesn't exist.
174
+ * 2. Scans `migrationsDir` for `.sql` files (excluding `.down.sql`), sorted.
175
+ * 3. Skips files already recorded as applied.
176
+ * 4. Splits file content on `delimiter` and executes each statement.
177
+ * 5. On success records the migration with the current batch number.
178
+ * 6. On error logs and continues.
179
+ * 7. Returns a summary of applied / skipped / failed files.
180
+ *
181
+ * @param adapter - A DatabaseAdapter instance (or omit to use the global adapter).
182
+ * @param options - Optional configuration.
183
+ */
184
+ export declare function migrate(adapter?: DatabaseAdapter, options?: {
185
+ migrationsDir?: string;
186
+ delimiter?: string;
187
+ }): Promise<MigrationResult>;
188
+ /**
189
+ * Get migration status: which migrations are completed and which are pending.
190
+ *
191
+ * @param adapter - A DatabaseAdapter instance (or omit to use the global adapter).
192
+ * @param options - Optional configuration.
193
+ * @returns Object with `completed` and `pending` arrays of filenames.
194
+ */
195
+ export declare function status(adapter?: DatabaseAdapter, options?: {
196
+ migrationsDir?: string;
197
+ }): Promise<MigrationStatus>;
198
+ /**
199
+ * Create a new empty SQL migration file with a timestamp prefix.
200
+ *
201
+ * Creates BOTH the up migration (.sql) and the down migration (.down.sql).
202
+ *
203
+ * @param description - Human-readable description (used in filename).
204
+ * @param options - Optional configuration.
205
+ * @returns Object with paths to the created up and down files.
206
+ */
207
+ export declare function createMigration(description: string, options?: {
208
+ migrationsDir?: string;
209
+ kind?: "sql" | "class";
210
+ }): Promise<string | {
211
+ upPath: string;
212
+ downPath: string;
213
+ }>;
214
+ /**
215
+ * Create a new TypeScript class-based migration file with a timestamp prefix.
216
+ *
217
+ * @param description - Human-readable description (used in filename and class name).
218
+ * @param options - Optional configuration.
219
+ * @returns Path to the created file.
220
+ */
221
+ export declare function createClassMigration(description: string, options?: {
222
+ migrationsDir?: string;
223
+ }): Promise<string>;
224
+ /**
225
+ * Object-oriented Migration class — canonical Tina4 Migration API.
226
+ *
227
+ * Provides parity with Python, PHP, and Ruby:
228
+ * - migrate() Run all pending migrations
229
+ * - rollback(steps=1) Roll back last N batches
230
+ * - status() Show completed/pending
231
+ * - create(description) Scaffold new .sql + .down.sql files
232
+ * - getApplied() List applied migrations
233
+ * - getPending() List pending migration filenames
234
+ * - getFiles() List all migration files on disk
235
+ *
236
+ * @example
237
+ * const m = new Migration(db, { migrationsDir: "migrations" });
238
+ * await m.migrate();
239
+ * await m.rollback(2);
240
+ * await m.status();
241
+ * await m.create("add users table");
242
+ */
243
+ export declare class Migration {
244
+ private db?;
245
+ private dir;
246
+ private delimiter;
247
+ constructor(db?: DatabaseAdapter, options?: {
248
+ migrationsDir?: string;
249
+ delimiter?: string;
250
+ });
251
+ /** Run all pending migrations. Returns applied/skipped/failed summary. */
252
+ migrate(): Promise<MigrationResult>;
253
+ /** Roll back the last N batches. Returns list of rolled-back migration names. */
254
+ rollback(steps?: number): Promise<string[]>;
255
+ /** Get migration status: which are completed and which are pending. */
256
+ status(): Promise<MigrationStatus>;
257
+ /**
258
+ * Scaffold a new migration file.
259
+ *
260
+ * kind="sql" — creates {timestamp}_{description}.sql + .down.sql (default)
261
+ * kind="class" — creates {timestamp}_{description}.ts with a TypeScript class template
262
+ *
263
+ * Returns the path to the created up file (or class file).
264
+ */
265
+ create(description: string, kind?: "sql" | "class"): Promise<string | {
266
+ upPath: string;
267
+ downPath: string;
268
+ }>;
269
+ /** Return list of completed (applied) migration filenames. */
270
+ getApplied(): Promise<string[]>;
271
+ /** Return list of pending migration filenames. */
272
+ getPending(): Promise<string[]>;
273
+ /** Return sorted list of all migration files on disk (excludes .down.sql). */
274
+ getFiles(): string[];
275
+ }
@@ -0,0 +1,7 @@
1
+ import type { ModelDefinition } from "./types.js";
2
+ export interface DiscoveredModel {
3
+ definition: ModelDefinition;
4
+ filePath: string;
5
+ modelClass: any;
6
+ }
7
+ export declare function discoverModels(modelsDir: string): Promise<DiscoveredModel[]>;
@@ -0,0 +1,14 @@
1
+ import type { QueryOptions } from "./types.js";
2
+ export interface ParsedQuery {
3
+ where: string;
4
+ orderBy: string;
5
+ limit: number;
6
+ offset: number;
7
+ params: unknown[];
8
+ }
9
+ export declare function buildQuery(tableName: string, options: QueryOptions, extraConditions?: string[]): {
10
+ sql: string;
11
+ countSql: string;
12
+ params: unknown[];
13
+ };
14
+ export declare function parseQueryString(query: Record<string, string>): QueryOptions;
@@ -0,0 +1,193 @@
1
+ /**
2
+ * QueryBuilder — Fluent SQL query builder for Tina4 Node.js.
3
+ *
4
+ * Usage:
5
+ * // Standalone
6
+ * const result = QueryBuilder.fromTable("users", db)
7
+ * .select("id", "name")
8
+ * .where("active = ?", [1])
9
+ * .orderBy("name ASC")
10
+ * .limit(10)
11
+ * .get();
12
+ *
13
+ * // From ORM model
14
+ * const result = User.query()
15
+ * .where("age > ?", [18])
16
+ * .orderBy("name")
17
+ * .get();
18
+ */
19
+ import type { DatabaseAdapter } from "./types.js";
20
+ import { DatabaseResult } from "./databaseResult.js";
21
+ export declare class QueryBuilder {
22
+ private table;
23
+ private db;
24
+ private columns;
25
+ private wheres;
26
+ private params;
27
+ private joinClauses;
28
+ private groupByCols;
29
+ private havings;
30
+ private havingParams;
31
+ private orderByCols;
32
+ private limitVal;
33
+ private offsetVal;
34
+ /**
35
+ * Private constructor — use static factory methods.
36
+ */
37
+ private constructor();
38
+ /**
39
+ * Create a QueryBuilder for a table.
40
+ *
41
+ * @param tableName - Table name.
42
+ * @param db - Optional database adapter.
43
+ * @returns A new QueryBuilder instance.
44
+ */
45
+ static fromTable(tableName: string, db?: DatabaseAdapter): QueryBuilder;
46
+ /**
47
+ * Set the columns to select.
48
+ *
49
+ * @param cols - Column names.
50
+ * @returns this for chaining.
51
+ */
52
+ select(...cols: string[]): QueryBuilder;
53
+ /**
54
+ * Add a WHERE condition (AND).
55
+ *
56
+ * @param condition - SQL condition with ? placeholders.
57
+ * @param params - Parameter values.
58
+ * @returns this for chaining.
59
+ */
60
+ where(condition: string, params?: unknown[]): QueryBuilder;
61
+ /**
62
+ * Add a WHERE condition (OR).
63
+ *
64
+ * @param condition - SQL condition with ? placeholders.
65
+ * @param params - Parameter values.
66
+ * @returns this for chaining.
67
+ */
68
+ orWhere(condition: string, params?: unknown[]): QueryBuilder;
69
+ /**
70
+ * Add an INNER JOIN.
71
+ *
72
+ * @param table - Table to join.
73
+ * @param onClause - Join condition.
74
+ * @returns this for chaining.
75
+ */
76
+ join(table: string, onClause: string): QueryBuilder;
77
+ /**
78
+ * Add a LEFT JOIN.
79
+ *
80
+ * @param table - Table to join.
81
+ * @param onClause - Join condition.
82
+ * @returns this for chaining.
83
+ */
84
+ leftJoin(table: string, onClause: string): QueryBuilder;
85
+ /**
86
+ * Add a GROUP BY column.
87
+ *
88
+ * @param column - Column name.
89
+ * @returns this for chaining.
90
+ */
91
+ groupBy(column: string): QueryBuilder;
92
+ /**
93
+ * Add a HAVING clause.
94
+ *
95
+ * @param expression - HAVING expression with ? placeholders.
96
+ * @param params - Parameter values.
97
+ * @returns this for chaining.
98
+ */
99
+ having(expression: string, params?: unknown[]): QueryBuilder;
100
+ /**
101
+ * Add an ORDER BY clause.
102
+ *
103
+ * @param expression - Column and direction (e.g. "name ASC").
104
+ * @returns this for chaining.
105
+ */
106
+ orderBy(expression: string): QueryBuilder;
107
+ /**
108
+ * Set LIMIT and optional OFFSET.
109
+ *
110
+ * @param count - Maximum rows to return.
111
+ * @param offset - Number of rows to skip.
112
+ * @returns this for chaining.
113
+ */
114
+ limit(count: number, offset?: number): QueryBuilder;
115
+ /**
116
+ * Build and return the SQL string without executing.
117
+ *
118
+ * @returns The constructed SQL query.
119
+ */
120
+ toSql(): string;
121
+ /**
122
+ * Execute the query and return a DatabaseResult.
123
+ *
124
+ * BREAKING (3.13.95, parity): this returned a bare array of rows. The other
125
+ * three frameworks all return the DatabaseResult that `db.fetch()` produces:
126
+ * Python get() -> DatabaseResult (orm/query_builder/__init__.py)
127
+ * PHP get(): mixed -> $this->db->fetch(...)
128
+ * Ruby get -> @db.fetch(...)
129
+ * Node was the odd one out, so the same builder chain returned a different
130
+ * TYPE per language and portable code could not read `.records`, `.count`,
131
+ * `.limit` or `.offset` off it.
132
+ *
133
+ * MIGRATION: read `.records` for the rows.
134
+ * before: const rows = await qb.get(); rows.length
135
+ * after: const result = await qb.get(); result.records.length
136
+ * DatabaseResult is iterable, so `for (const row of result)` and
137
+ * `[...result]` work unchanged, and `response()`/`res.json()` already
138
+ * auto-serialize it to a JSON array.
139
+ *
140
+ * No default LIMIT is applied when `.limit()` was never called (v3.13.39) --
141
+ * a silent cap here was a data-loss-on-read footgun. That is unchanged.
142
+ *
143
+ * @returns DatabaseResult carrying `.records`, `.count`, `.limit`, `.offset`.
144
+ */
145
+ get(): Promise<DatabaseResult>;
146
+ /**
147
+ * Execute the query and return a single row.
148
+ *
149
+ * @returns A single row object, or null.
150
+ */
151
+ first<T = Record<string, unknown>>(): Promise<T | null>;
152
+ /**
153
+ * Execute the query and return the row count.
154
+ *
155
+ * @returns Number of matching rows.
156
+ */
157
+ count(): Promise<number>;
158
+ /**
159
+ * Check whether any matching rows exist.
160
+ *
161
+ * @returns True if at least one row matches.
162
+ */
163
+ exists(): Promise<boolean>;
164
+ /**
165
+ * Convert the fluent builder state into a MongoDB-compatible query document.
166
+ *
167
+ * @returns An object with filter, projection, sort, limit, skip (only non-empty keys).
168
+ */
169
+ toMongo(): {
170
+ filter?: Record<string, unknown>;
171
+ projection?: Record<string, number>;
172
+ sort?: Record<string, 1 | -1>;
173
+ limit?: number;
174
+ skip?: number;
175
+ };
176
+ /**
177
+ * Parse a single SQL condition string into a MongoDB filter object.
178
+ */
179
+ private parseConditionToMongo;
180
+ /**
181
+ * Merge multiple single-field mongo condition objects into one.
182
+ * Uses $and if field keys conflict.
183
+ */
184
+ private mergeMongoConditions;
185
+ /**
186
+ * Build the WHERE clause from accumulated conditions.
187
+ */
188
+ private buildWhere;
189
+ /**
190
+ * Ensure a database adapter is available.
191
+ */
192
+ private ensureDb;
193
+ }
@@ -0,0 +1,7 @@
1
+ export { realtime, iceServers, type RealtimeOptions } from "./realtime.js";
2
+ export { LocalStorage, S3Storage, selectStorage, storageKey, type StorageBackend, } from "./storage.js";
3
+ export { default as Workspace } from "./models/workspace.js";
4
+ export { default as Channel } from "./models/channel.js";
5
+ export { default as ChannelMember } from "./models/channelMember.js";
6
+ export { default as Message } from "./models/message.js";
7
+ export { default as Attachment } from "./models/attachment.js";
@@ -0,0 +1,43 @@
1
+ import { BaseModel } from "../../baseModel.js";
2
+ /**
3
+ * Attachment - a file linked to a channel (and optionally a message).
4
+ * channel_id scopes the file for permission checks; message_id is null until
5
+ * the file is attached to a posted message. storage_key is the StorageBackend
6
+ * key; the row carries only metadata, never the blob.
7
+ */
8
+ export default class Attachment extends BaseModel {
9
+ static tableName: string;
10
+ static fields: {
11
+ id: {
12
+ type: "integer";
13
+ primaryKey: boolean;
14
+ autoIncrement: boolean;
15
+ };
16
+ channel_id: {
17
+ type: "integer";
18
+ };
19
+ message_id: {
20
+ type: "integer";
21
+ };
22
+ storage_key: {
23
+ type: "string";
24
+ required: boolean;
25
+ maxLength: number;
26
+ };
27
+ filename: {
28
+ type: "string";
29
+ maxLength: number;
30
+ };
31
+ mime: {
32
+ type: "string";
33
+ maxLength: number;
34
+ };
35
+ size: {
36
+ type: "integer";
37
+ };
38
+ thumb_key: {
39
+ type: "string";
40
+ maxLength: number;
41
+ };
42
+ };
43
+ }
@@ -0,0 +1,32 @@
1
+ import { BaseModel } from "../../baseModel.js";
2
+ /**
3
+ * Channel - a conversation stream inside a workspace.
4
+ * kind is one of public | private | dm. workspace_id is a plain integer FK
5
+ * column (the realtime handlers query it directly).
6
+ */
7
+ export default class Channel extends BaseModel {
8
+ static tableName: string;
9
+ static fields: {
10
+ id: {
11
+ type: "integer";
12
+ primaryKey: boolean;
13
+ autoIncrement: boolean;
14
+ };
15
+ workspace_id: {
16
+ type: "integer";
17
+ };
18
+ name: {
19
+ type: "string";
20
+ required: boolean;
21
+ maxLength: number;
22
+ };
23
+ kind: {
24
+ type: "string";
25
+ default: string;
26
+ maxLength: number;
27
+ };
28
+ created_at: {
29
+ type: "datetime";
30
+ };
31
+ };
32
+ }
@@ -0,0 +1,32 @@
1
+ import { BaseModel } from "../../baseModel.js";
2
+ /**
3
+ * ChannelMember - a user's membership of a channel plus their read cursor.
4
+ * user_id is a string so it holds any identity shape the app puts in the JWT
5
+ * (an integer id, a UUID, an email). last_read_at is the read-receipt cursor.
6
+ */
7
+ export default class ChannelMember extends BaseModel {
8
+ static tableName: string;
9
+ static fields: {
10
+ id: {
11
+ type: "integer";
12
+ primaryKey: boolean;
13
+ autoIncrement: boolean;
14
+ };
15
+ channel_id: {
16
+ type: "integer";
17
+ };
18
+ user_id: {
19
+ type: "string";
20
+ required: boolean;
21
+ maxLength: number;
22
+ };
23
+ role: {
24
+ type: "string";
25
+ default: string;
26
+ maxLength: number;
27
+ };
28
+ last_read_at: {
29
+ type: "datetime";
30
+ };
31
+ };
32
+ }
@@ -0,0 +1,36 @@
1
+ import { BaseModel } from "../../baseModel.js";
2
+ /**
3
+ * Message - one posted message in a channel.
4
+ * thread_id is null for a top-level message, or the id of the parent message
5
+ * for a threaded reply. edited_at is null until an edit.
6
+ */
7
+ export default class Message extends BaseModel {
8
+ static tableName: string;
9
+ static fields: {
10
+ id: {
11
+ type: "integer";
12
+ primaryKey: boolean;
13
+ autoIncrement: boolean;
14
+ };
15
+ channel_id: {
16
+ type: "integer";
17
+ };
18
+ user_id: {
19
+ type: "string";
20
+ required: boolean;
21
+ maxLength: number;
22
+ };
23
+ body: {
24
+ type: "text";
25
+ };
26
+ thread_id: {
27
+ type: "integer";
28
+ };
29
+ created_at: {
30
+ type: "datetime";
31
+ };
32
+ edited_at: {
33
+ type: "datetime";
34
+ };
35
+ };
36
+ }
@@ -0,0 +1,26 @@
1
+ import { BaseModel } from "../../baseModel.js";
2
+ /**
3
+ * Workspace - the top-level container for channels (a "team" / "org").
4
+ * Framework-owned table: the tina4_rt_ prefix keeps it clear of an app's own
5
+ * domain tables (mirrors tina4_migration / tina4_sequences + the Python
6
+ * master's tina4_rt_* tables). Field keys are snake_case so the columns and
7
+ * JSON keys stay byte-identical to the master (no camelCase mapping needed).
8
+ */
9
+ export default class Workspace extends BaseModel {
10
+ static tableName: string;
11
+ static fields: {
12
+ id: {
13
+ type: "integer";
14
+ primaryKey: boolean;
15
+ autoIncrement: boolean;
16
+ };
17
+ name: {
18
+ type: "string";
19
+ required: boolean;
20
+ maxLength: number;
21
+ };
22
+ created_at: {
23
+ type: "datetime";
24
+ };
25
+ };
26
+ }