tina4-nodejs 3.13.92 → 3.13.94

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 (134) hide show
  1. package/CLAUDE.md +16 -3
  2. package/README.md +1 -1
  3. package/package.json +12 -9
  4. package/packages/cli/dist/bin.js +1260 -969
  5. package/packages/core/dist/index.js +1260 -969
  6. package/packages/core/src/devMailbox.ts +20 -44
  7. package/packages/core/src/index.ts +2 -2
  8. package/packages/core/src/messenger.ts +72 -0
  9. package/packages/core/src/queueBackends/kafkaBackend.ts +108 -12
  10. package/packages/core/src/sessionHandlers/childError.ts +72 -0
  11. package/packages/core/src/sessionHandlers/mongoClient.ts +9 -3
  12. package/packages/core/src/sessionHandlers/redisHandler.ts +18 -5
  13. package/packages/core/src/sessionHandlers/respClient.ts +5 -1
  14. package/packages/frond/dist/index.js +74 -31
  15. package/packages/frond/src/engine.ts +99 -33
  16. package/packages/orm/dist/index.js +3055 -2764
  17. package/packages/orm/src/adapters/sqlite.ts +4 -1
  18. package/packages/orm/src/database.ts +108 -8
  19. package/types/cli/src/bin.d.ts +92 -0
  20. package/types/cli/src/commands/build.d.ts +2 -0
  21. package/types/cli/src/commands/generate.d.ts +47 -0
  22. package/types/cli/src/commands/init.d.ts +1 -0
  23. package/types/cli/src/commands/metrics.d.ts +6 -0
  24. package/types/cli/src/commands/migrate.d.ts +1 -0
  25. package/types/cli/src/commands/migrateCreate.d.ts +1 -0
  26. package/types/cli/src/commands/migrateRollback.d.ts +1 -0
  27. package/types/cli/src/commands/migrateStatus.d.ts +1 -0
  28. package/types/cli/src/commands/queue.d.ts +20 -0
  29. package/types/cli/src/commands/routes.d.ts +1 -0
  30. package/types/cli/src/commands/seed.d.ts +1 -0
  31. package/types/cli/src/commands/serve.d.ts +6 -0
  32. package/types/cli/src/commands/test.d.ts +1 -0
  33. package/types/core/src/ai.d.ts +64 -0
  34. package/types/core/src/api.d.ts +262 -0
  35. package/types/core/src/auth.d.ts +154 -0
  36. package/types/core/src/authGate.d.ts +20 -0
  37. package/types/core/src/background.d.ts +34 -0
  38. package/types/core/src/cache.d.ts +160 -0
  39. package/types/core/src/constants.d.ts +38 -0
  40. package/types/core/src/container.d.ts +44 -0
  41. package/types/core/src/context/chunker.d.ts +31 -0
  42. package/types/core/src/context/index.d.ts +93 -0
  43. package/types/core/src/devAdmin.d.ts +179 -0
  44. package/types/core/src/devMailbox.d.ts +54 -0
  45. package/types/core/src/docs.d.ts +141 -0
  46. package/types/core/src/docsAutoDiscovery.d.ts +6 -0
  47. package/types/core/src/dotenv.d.ts +65 -0
  48. package/types/core/src/env.d.ts +28 -0
  49. package/types/core/src/errorOverlay.d.ts +36 -0
  50. package/types/core/src/events.d.ts +75 -0
  51. package/types/core/src/fakeData.d.ts +55 -0
  52. package/types/core/src/feedback.d.ts +90 -0
  53. package/types/core/src/graphql.d.ts +207 -0
  54. package/types/core/src/health.d.ts +22 -0
  55. package/types/core/src/htmlElement.d.ts +75 -0
  56. package/types/core/src/i18n.d.ts +37 -0
  57. package/types/core/src/index.d.ts +93 -0
  58. package/types/core/src/job.d.ts +39 -0
  59. package/types/core/src/logger.d.ts +123 -0
  60. package/types/core/src/mcp.d.ts +248 -0
  61. package/types/core/src/messenger.d.ts +191 -0
  62. package/types/core/src/metrics.d.ts +77 -0
  63. package/types/core/src/middleware.d.ts +207 -0
  64. package/types/core/src/mqtt.d.ts +257 -0
  65. package/types/core/src/mqttMessage.d.ts +67 -0
  66. package/types/core/src/plan.d.ts +96 -0
  67. package/types/core/src/projectIndex.d.ts +56 -0
  68. package/types/core/src/queue.d.ts +219 -0
  69. package/types/core/src/queueBackends/kafkaBackend.d.ts +117 -0
  70. package/types/core/src/queueBackends/liteBackend.d.ts +119 -0
  71. package/types/core/src/queueBackends/mongoBackend.d.ts +97 -0
  72. package/types/core/src/queueBackends/rabbitmqBackend.d.ts +55 -0
  73. package/types/core/src/rateLimiter.d.ts +49 -0
  74. package/types/core/src/request.d.ts +25 -0
  75. package/types/core/src/response.d.ts +28 -0
  76. package/types/core/src/routeDiscovery.d.ts +12 -0
  77. package/types/core/src/router.d.ts +355 -0
  78. package/types/core/src/scss.d.ts +19 -0
  79. package/types/core/src/server.d.ts +131 -0
  80. package/types/core/src/service.d.ts +115 -0
  81. package/types/core/src/session.d.ts +256 -0
  82. package/types/core/src/sessionHandlers/childError.d.ts +34 -0
  83. package/types/core/src/sessionHandlers/databaseHandler.d.ts +42 -0
  84. package/types/core/src/sessionHandlers/mongoClient.d.ts +24 -0
  85. package/types/core/src/sessionHandlers/mongoHandler.d.ts +61 -0
  86. package/types/core/src/sessionHandlers/redisHandler.d.ts +60 -0
  87. package/types/core/src/sessionHandlers/respClient.d.ts +22 -0
  88. package/types/core/src/sessionHandlers/valkeyHandler.d.ts +65 -0
  89. package/types/core/src/static.d.ts +2 -0
  90. package/types/core/src/test.d.ts +94 -0
  91. package/types/core/src/testClient.d.ts +36 -0
  92. package/types/core/src/testing.d.ts +58 -0
  93. package/types/core/src/types.d.ts +219 -0
  94. package/types/core/src/validator.d.ts +52 -0
  95. package/types/core/src/websocket.d.ts +376 -0
  96. package/types/core/src/websocketBackplane.d.ts +166 -0
  97. package/types/core/src/websocketConnection.d.ts +54 -0
  98. package/types/core/src/wsdl.d.ts +101 -0
  99. package/types/frond/src/engine.d.ts +263 -0
  100. package/types/frond/src/index.d.ts +2 -0
  101. package/types/orm/src/adapters/firebird.d.ts +138 -0
  102. package/types/orm/src/adapters/mongodb.d.ts +81 -0
  103. package/types/orm/src/adapters/mssql.d.ts +70 -0
  104. package/types/orm/src/adapters/mysql.d.ts +66 -0
  105. package/types/orm/src/adapters/odbc.d.ts +97 -0
  106. package/types/orm/src/adapters/postgres.d.ts +85 -0
  107. package/types/orm/src/adapters/sqlite.d.ts +56 -0
  108. package/types/orm/src/autoCrud.d.ts +73 -0
  109. package/types/orm/src/baseModel.d.ts +391 -0
  110. package/types/orm/src/cachedDatabase.d.ts +177 -0
  111. package/types/orm/src/database.d.ts +609 -0
  112. package/types/orm/src/databaseResult.d.ts +85 -0
  113. package/types/orm/src/docstore.d.ts +182 -0
  114. package/types/orm/src/fakeData.d.ts +22 -0
  115. package/types/orm/src/index.d.ts +40 -0
  116. package/types/orm/src/migration.d.ts +275 -0
  117. package/types/orm/src/model.d.ts +7 -0
  118. package/types/orm/src/query.d.ts +14 -0
  119. package/types/orm/src/queryBuilder.d.ts +173 -0
  120. package/types/orm/src/realtime/index.d.ts +7 -0
  121. package/types/orm/src/realtime/models/attachment.d.ts +43 -0
  122. package/types/orm/src/realtime/models/channel.d.ts +32 -0
  123. package/types/orm/src/realtime/models/channelMember.d.ts +32 -0
  124. package/types/orm/src/realtime/models/message.d.ts +36 -0
  125. package/types/orm/src/realtime/models/workspace.d.ts +26 -0
  126. package/types/orm/src/realtime/realtime.d.ts +24 -0
  127. package/types/orm/src/realtime/storage.d.ts +61 -0
  128. package/types/orm/src/seeder.d.ts +118 -0
  129. package/types/orm/src/sqlTranslator.d.ts +134 -0
  130. package/types/orm/src/types.d.ts +138 -0
  131. package/types/orm/src/validation.d.ts +6 -0
  132. package/types/swagger/src/generator.d.ts +46 -0
  133. package/types/swagger/src/index.d.ts +2 -0
  134. package/types/swagger/src/ui.d.ts +11 -0
@@ -0,0 +1,85 @@
1
+ import type { DatabaseAdapter } from "./types.js";
2
+ /** Column metadata returned by columnInfo(). */
3
+ export interface ColumnInfoResult {
4
+ name: string;
5
+ type: string;
6
+ size: number | null;
7
+ decimals: number | null;
8
+ nullable: boolean;
9
+ primary_key: boolean;
10
+ }
11
+ /**
12
+ * DatabaseResult — wraps fetched rows with convenience methods.
13
+ *
14
+ * Mirrors Python's `DatabaseResult` dataclass from tina4_python.database.adapter.
15
+ * Provides iteration, JSON/CSV export, pagination metadata, and array-like access.
16
+ */
17
+ export declare class DatabaseResult implements Iterable<Record<string, unknown>> {
18
+ readonly records: Record<string, unknown>[];
19
+ readonly columns: string[];
20
+ readonly count: number;
21
+ readonly limit: number;
22
+ readonly offset: number;
23
+ private readonly _adapter?;
24
+ private readonly _sql?;
25
+ private _columnInfoCache?;
26
+ [index: number]: Record<string, unknown> | undefined;
27
+ constructor(records?: Record<string, unknown>[], columns?: string[], count?: number, limit?: number, offset?: number, adapter?: DatabaseAdapter, sql?: string);
28
+ /** JSON string of records. */
29
+ toJson(): string;
30
+ /** CSV with header row. */
31
+ toCsv(): string;
32
+ /** Same as records — plain array of row objects. */
33
+ toArray(): Record<string, unknown>[];
34
+ /** Pagination envelope — accepts either (page, perPage) or (offset, limit) style.
35
+ *
36
+ * When called with two arguments both >= 0 and the first >= the second
37
+ * (i.e. offset-style), pass `{ offset, limit }` as the first argument.
38
+ * The simplest way is to always use the default (page, perPage) form and
39
+ * let the autoCRUD layer supply offset/limit from the query string.
40
+ *
41
+ * Returns a superset of keys for backwards-compatibility across all clients.
42
+ */
43
+ toPaginate(page?: number, perPage?: number): {
44
+ records: Record<string, unknown>[];
45
+ data: Record<string, unknown>[];
46
+ count: number;
47
+ total: number;
48
+ limit: number;
49
+ offset: number;
50
+ page: number;
51
+ per_page: number;
52
+ perPage: number;
53
+ totalPages: number;
54
+ total_pages: number;
55
+ has_next: boolean;
56
+ has_prev: boolean;
57
+ };
58
+ /** Iterable — for (const row of result) */
59
+ [Symbol.iterator](): Iterator<Record<string, unknown>>;
60
+ /** Total count — cross-framework parity with Python/Ruby. */
61
+ size(): number;
62
+ /** Number of records in this page. */
63
+ get length(): number;
64
+ /** Array-like indexed access with negative index support. */
65
+ at(index: number): Record<string, unknown> | undefined;
66
+ /** JSON.stringify support — serialises as the records array. */
67
+ toJSON(): Record<string, unknown>[];
68
+ /**
69
+ * Return column metadata for the query's table.
70
+ *
71
+ * Lazy — only queries the database when explicitly called. Caches the
72
+ * result so subsequent calls return immediately without re-querying.
73
+ */
74
+ columnInfo(): ColumnInfoResult[];
75
+ /** Extract table name from a SQL query using simple regex. */
76
+ private _extractTableFromSql;
77
+ /** Query the database adapter for column metadata. */
78
+ private _queryColumnMetadata;
79
+ /** Normalize adapter column info to standard format. */
80
+ private _normalizeColumns;
81
+ /** Parse size and decimals from a type string like VARCHAR(255) or NUMERIC(10,2). */
82
+ private _parseTypeSize;
83
+ /** Derive basic column info from record keys when no adapter is available. */
84
+ private _fallbackColumnInfo;
85
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Tina4 DocStore - pymongo-style document storage with a zero-config SQLite (JSON1) fallback.
3
+ *
4
+ * A document store with the everyday MongoDB driver collection API, backed by
5
+ * SQLite's JSON1 extension when no MongoDB server is configured.
6
+ *
7
+ * import { getCollection, ObjectId } from "@tina4/orm";
8
+ *
9
+ * const orders = getCollection("orders"); // SqliteCollection when no Mongo configured
10
+ * const { insertedId } = await orders.insertOne({ customer_id: 1, total: 9.99 });
11
+ * for (const o of await orders.find({ customer_id: { $in: [1, 2] } }).sort("created_at", -1).limit(10).toArray()) {
12
+ * // ...
13
+ * }
14
+ * await orders.updateOne({ _id: insertedId }, { $set: { status: "shipped" } });
15
+ *
16
+ * `getCollection(name)` returns a real MongoDB driver `Collection` when a Mongo
17
+ * URI is configured (TINA4_MONGO_URI, else TINA4_SESSION_MONGO_URI - the same
18
+ * names the queue/session Mongo backends read), and otherwise a SqliteCollection
19
+ * backed by a local SQLite file. This mirrors the file-based fallbacks the queue,
20
+ * cache, and session subsystems already provide: an app that talks to Mongo in
21
+ * production runs serverless in local dev with no code change - only the backend
22
+ * differs.
23
+ *
24
+ * Design (the SQLite backend):
25
+ * - Each collection is a table `(_id TEXT PRIMARY KEY, doc TEXT)`; `doc` is JSON.
26
+ * - Query filters are pushed down to SQL over `json_extract(doc, '$.field')`
27
+ * (lazy, not a full in-memory scan), supporting equality, $in/$nin,
28
+ * $gt/$gte/$lt/$lte, $ne, $exists, $regex, and implicit-AND / $or / $and.
29
+ * - Updates: $set, $unset, $inc, and full-document replace.
30
+ * - Cursors: sort / limit / skip / projection.
31
+ * - IDs are a built-in 12-byte ObjectId (zero-dependency; interchangeable with
32
+ * the driver's ObjectId as a 24-hex string).
33
+ *
34
+ * Type round-trip is by value, not by wrapper object, so json_extract stays
35
+ * queryable and sortable: a Date is stored as an ISO-8601 UTC string and an
36
+ * ObjectId as its 24-hex string, and reads rehydrate a strict-ISO string back to
37
+ * a Date and a 24-hex string back to an ObjectId. That keeps range queries and
38
+ * sorts working on date and id fields - the trade-off (a plain 24-hex / ISO
39
+ * string becomes an ObjectId / Date on read) is acceptable for the local dev store.
40
+ *
41
+ * Deliberate non-goals: aggregation pipeline, $elemMatch, geo. This is the
42
+ * everyday CRUD + filter subset, not full Mongo parity.
43
+ */
44
+ import { DatabaseSync } from "node:sqlite";
45
+ /** Raised when a value cannot be parsed as an ObjectId. */
46
+ export declare class InvalidId extends Error {
47
+ constructor(message: string);
48
+ }
49
+ /**
50
+ * A 12-byte MongoDB-style ObjectId, with no external dependency.
51
+ *
52
+ * Layout: 4-byte big-endian seconds since epoch, 5-byte per-process random,
53
+ * 3-byte big-endian counter. Renders as a 24-char hex string, so it is
54
+ * interchangeable with the driver's ObjectId wherever the string form is used.
55
+ */
56
+ export declare class ObjectId {
57
+ private static _counter;
58
+ private static _process;
59
+ private readonly _bytes;
60
+ constructor(oid?: ObjectId | Buffer | Uint8Array | string | null);
61
+ private static _generate;
62
+ static isValid(value: unknown): boolean;
63
+ get binary(): Buffer;
64
+ /** The timestamp embedded in the id (the first 4 bytes), as a Date. */
65
+ get generationTime(): Date;
66
+ toString(): string;
67
+ toJSON(): string;
68
+ equals(other: unknown): boolean;
69
+ }
70
+ /** Value -> JSON-serialisable, sortable scalar form (for storage/queries). */
71
+ export declare function encodeValue(value: unknown): unknown;
72
+ /** Stored JSON value -> rich value, rehydrating ObjectId (24-hex) and Date (ISO). */
73
+ export declare function decodeValue(value: unknown): unknown;
74
+ interface CompiledFilter {
75
+ where: string;
76
+ params: unknown[];
77
+ }
78
+ /**
79
+ * Compile a Mongo-style filter object into { where, params }.
80
+ *
81
+ * Returns { where: "1=1", params: [] } for an empty filter. Supports implicit
82
+ * AND across keys, $or / $and, and the per-field operator set.
83
+ */
84
+ export declare function compileFilter(query?: Record<string, unknown> | null): CompiledFilter;
85
+ export interface InsertOneResult {
86
+ acknowledged: boolean;
87
+ insertedId: unknown;
88
+ }
89
+ export interface InsertManyResult {
90
+ acknowledged: boolean;
91
+ insertedIds: unknown[];
92
+ }
93
+ export interface UpdateResult {
94
+ acknowledged: boolean;
95
+ matchedCount: number;
96
+ modifiedCount: number;
97
+ upsertedId: unknown | null;
98
+ }
99
+ export interface DeleteResult {
100
+ acknowledged: boolean;
101
+ deletedCount: number;
102
+ }
103
+ /** Lazy result cursor. Builds and runs SQL only when materialised (toArray). */
104
+ export declare class Cursor {
105
+ private readonly collection;
106
+ private readonly where;
107
+ private readonly params;
108
+ private readonly projection?;
109
+ private _sort;
110
+ private _limit;
111
+ private _skip;
112
+ constructor(collection: SqliteCollection, where: string, params: unknown[], projection?: (Record<string, unknown> | null) | undefined);
113
+ sort(keyOrList: string | [string, number][], direction?: number): this;
114
+ limit(n: number): this;
115
+ skip(n: number): this;
116
+ private buildSql;
117
+ /** Materialise the cursor into an array of decoded documents. */
118
+ toArray(): Record<string, unknown>[];
119
+ /** Alias for toArray() (pymongo's to_list / driver's toArray). */
120
+ toList(length?: number): Record<string, unknown>[];
121
+ [Symbol.iterator](): Iterator<Record<string, unknown>>;
122
+ }
123
+ /** A SQLite-backed collection exposing the everyday MongoDB driver API. */
124
+ export declare class SqliteCollection {
125
+ readonly connection: DatabaseSync;
126
+ private readonly name;
127
+ readonly quoted: string;
128
+ constructor(connection: DatabaseSync, name: string);
129
+ private dump;
130
+ /** Decode a stored JSON document (rehydrating ObjectId/Date), with optional projection. */
131
+ load(docText: string, projection?: Record<string, unknown> | null): Record<string, unknown>;
132
+ insertOne(document: Record<string, unknown>): InsertOneResult;
133
+ insertMany(documents: Record<string, unknown>[]): InsertManyResult;
134
+ find(filter?: Record<string, unknown> | null, projection?: Record<string, unknown> | null): Cursor;
135
+ findOne(filter?: Record<string, unknown> | null, projection?: Record<string, unknown> | null): Record<string, unknown> | null;
136
+ countDocuments(filter?: Record<string, unknown> | null): number;
137
+ estimatedDocumentCount(): number;
138
+ distinct(key: string, filter?: Record<string, unknown> | null): unknown[];
139
+ private matchingRows;
140
+ private firstMatch;
141
+ private writeBack;
142
+ private doUpsert;
143
+ updateOne(filter: Record<string, unknown> | null | undefined, update: Record<string, unknown>, options?: {
144
+ upsert?: boolean;
145
+ }): UpdateResult;
146
+ updateMany(filter: Record<string, unknown> | null | undefined, update: Record<string, unknown>, options?: {
147
+ upsert?: boolean;
148
+ }): UpdateResult;
149
+ replaceOne(filter: Record<string, unknown> | null | undefined, replacement: Record<string, unknown>, options?: {
150
+ upsert?: boolean;
151
+ }): UpdateResult;
152
+ deleteOne(filter?: Record<string, unknown> | null): DeleteResult;
153
+ deleteMany(filter?: Record<string, unknown> | null): DeleteResult;
154
+ drop(): void;
155
+ }
156
+ /** A SQLite-backed document database (a file of collection tables). */
157
+ export declare class SqliteDatabase {
158
+ readonly path: string;
159
+ private readonly conn;
160
+ private readonly collections;
161
+ constructor(path?: string);
162
+ getCollection(name: string): SqliteCollection;
163
+ listCollectionNames(): string[];
164
+ close(): void;
165
+ }
166
+ /** True when no Mongo is configured, so the SQLite fallback is in effect. */
167
+ export declare function isServerless(): boolean;
168
+ /**
169
+ * Return a collection for `name`.
170
+ *
171
+ * A real MongoDB driver `Collection` when a Mongo URI is configured (and the
172
+ * `mongodb` driver is installed); otherwise a `SqliteCollection` backed by the
173
+ * local SQLite file. Same call sites either way - only the backend differs.
174
+ *
175
+ * The real-Mongo path is async (the driver connects lazily), so this returns a
176
+ * Promise when Mongo is configured. In serverless mode it returns a
177
+ * SqliteCollection synchronously (the common local-dev case).
178
+ */
179
+ export declare function getCollection(name: string): SqliteCollection | Promise<unknown>;
180
+ /** Drop the cached default SQLite store (test helper). */
181
+ export declare function resetDefaultStore(): void;
182
+ export {};
@@ -0,0 +1,22 @@
1
+ import { FakeData as CoreFakeData } from "../../core/src/fakeData.js";
2
+ import type { FieldDefinition } from "./types.js";
3
+ /**
4
+ * ORM-aware FakeData — wraps the core FakeData and adds forField()
5
+ * which generates appropriate fake data based on an ORM FieldDefinition.
6
+ */
7
+ export declare class FakeData extends CoreFakeData {
8
+ constructor(seed?: number);
9
+ /**
10
+ * Generate a Date object within a year range.
11
+ * Matches the Python API's datetime() method.
12
+ */
13
+ datetime(startYear?: number, endYear?: number): Date;
14
+ /**
15
+ * Generate a fake value appropriate for an ORM field definition.
16
+ * Respects min/max, minLength/maxLength, and type constraints.
17
+ *
18
+ * @param fieldDef - An ORM FieldDefinition object
19
+ * @param columnName - Optional column name for heuristic matching (e.g. "email", "phone")
20
+ */
21
+ forField(fieldDef: FieldDefinition, columnName?: string): unknown;
22
+ }
@@ -0,0 +1,40 @@
1
+ export type { FieldType, FieldDefinition, ModelDefinition, DatabaseAdapter, DatabaseResult as DatabaseWriteResult, ColumnInfo, QueryOptions, RelationshipDefinition, PaginatedResult, } from "./types.js";
2
+ export { FetchResult } from "./types.js";
3
+ export { DatabaseResult } from "./databaseResult.js";
4
+ export type { ColumnInfoResult } from "./databaseResult.js";
5
+ export { Database, initDatabase, getAdapter, setAdapter, bindDatabase, createAdapterFromUrl, closeDatabase, parseDatabaseUrl, setNamedAdapter, getNamedAdapter, resolveDbPool, stripTrailingSemicolons, wrapWithCache, resetRequestCaches } from "./database.js";
6
+ export { adapterFetch, adapterQuery, adapterFetchOne, adapterExecute, adapterStartTransaction, adapterCommit, adapterRollback, adapterTableExists, adapterTables, adapterColumns, adapterCreateTable, extractLastInsertId, } from "./database.js";
7
+ export type { DatabaseConfig, ParsedDatabaseUrl } from "./database.js";
8
+ export { discoverModels } from "./model.js";
9
+ export type { DiscoveredModel } from "./model.js";
10
+ export { syncModels, ensureMigrationTable, getNextBatch, isMigrationApplied, recordMigration, applyMigration, rollback, getAppliedMigrations, getLastBatchMigrations, removeMigrationRecord, migrate, createMigration, status, Migration, splitStatements, parseSetTerm, normalizeQuotes, sortMigrationFiles, shouldSkipCreateTable, } from "./migration.js";
11
+ export type { MigrationResult, MigrationStatus } from "./migration.js";
12
+ export { AutoCrud, generateCrudRoutes, crudEligibleModels } from "./autoCrud.js";
13
+ export type { AutoCrudOptions } from "./autoCrud.js";
14
+ export { buildQuery, parseQueryString } from "./query.js";
15
+ export { validate } from "./validation.js";
16
+ export type { ValidationError } from "./validation.js";
17
+ export { BaseModel, snakeToCamel, camelToSnake } from "./baseModel.js";
18
+ export { QueryBuilder } from "./queryBuilder.js";
19
+ export { SQLTranslator, QueryCache } from "./sqlTranslator.js";
20
+ export { CachedDatabaseAdapter } from "./cachedDatabase.js";
21
+ export type { CachedAdapterOptions } from "./cachedDatabase.js";
22
+ export { FakeData } from "./fakeData.js";
23
+ export { seedTable, seedOrm, seedModels, autoFieldMap } from "./seeder.js";
24
+ export type { SeedSummary, SeedOptions } from "./seeder.js";
25
+ export { ObjectId, InvalidId, SqliteDatabase, SqliteCollection, Cursor, getCollection, isServerless, resetDefaultStore, encodeValue, decodeValue, compileFilter, } from "./docstore.js";
26
+ export type { InsertOneResult, InsertManyResult, UpdateResult, DeleteResult, } from "./docstore.js";
27
+ export { SQLiteAdapter } from "./adapters/sqlite.js";
28
+ export { PostgresAdapter } from "./adapters/postgres.js";
29
+ export type { PostgresConfig } from "./adapters/postgres.js";
30
+ export { MysqlAdapter } from "./adapters/mysql.js";
31
+ export type { MysqlConfig } from "./adapters/mysql.js";
32
+ export { MssqlAdapter } from "./adapters/mssql.js";
33
+ export type { MssqlConfig } from "./adapters/mssql.js";
34
+ export { FirebirdAdapter, normalizeFirebirdDbIdentifier, resolveFirebirdCharset } from "./adapters/firebird.js";
35
+ export type { FirebirdConfig } from "./adapters/firebird.js";
36
+ export { MongodbAdapter } from "./adapters/mongodb.js";
37
+ export type { MongoConfig } from "./adapters/mongodb.js";
38
+ export { OdbcAdapter } from "./adapters/odbc.js";
39
+ export type { OdbcConfig } from "./adapters/odbc.js";
40
+ export { realtime, iceServers, type RealtimeOptions, LocalStorage, S3Storage, selectStorage, storageKey, type StorageBackend, Workspace as RealtimeWorkspace, Channel as RealtimeChannel, ChannelMember as RealtimeChannelMember, Message as RealtimeMessage, Attachment as RealtimeAttachment, } from "./realtime/index.js";
@@ -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;