@hedystia/db 2.0.5 → 2.0.7

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 (55) hide show
  1. package/dist/cache/index.mjs +12 -0
  2. package/dist/cache/index.mjs.map +1 -0
  3. package/dist/cache/manager.mjs +156 -153
  4. package/dist/cache/manager.mjs.map +1 -1
  5. package/dist/cache/memory-store.mjs +113 -111
  6. package/dist/cache/memory-store.mjs.map +1 -1
  7. package/dist/cli/commands/migrate.cjs +78 -0
  8. package/dist/cli/commands/migrate.cjs.map +1 -0
  9. package/dist/cli/commands/migrate.mjs +83 -0
  10. package/dist/cli/commands/migrate.mjs.map +1 -0
  11. package/dist/cli.cjs +36 -0
  12. package/dist/cli.cjs.map +1 -1
  13. package/dist/cli.mjs +37 -0
  14. package/dist/cli.mjs.map +1 -1
  15. package/dist/core/database.cjs +72 -29
  16. package/dist/core/database.cjs.map +1 -1
  17. package/dist/core/database.d.cts +65 -0
  18. package/dist/core/database.d.mts +65 -0
  19. package/dist/core/database.mjs +88 -34
  20. package/dist/core/database.mjs.map +1 -1
  21. package/dist/core/repository.mjs +414 -410
  22. package/dist/core/repository.mjs.map +1 -1
  23. package/dist/drivers/driver.mjs +9 -7
  24. package/dist/drivers/driver.mjs.map +1 -1
  25. package/dist/drivers/file.mjs +315 -312
  26. package/dist/drivers/file.mjs.map +1 -1
  27. package/dist/drivers/index.mjs +15 -6
  28. package/dist/drivers/index.mjs.map +1 -1
  29. package/dist/drivers/mysql.mjs +261 -256
  30. package/dist/drivers/mysql.mjs.map +1 -1
  31. package/dist/drivers/sql-compiler.mjs +4 -1
  32. package/dist/drivers/sql-compiler.mjs.map +1 -1
  33. package/dist/drivers/sqlite.cjs +12 -1
  34. package/dist/drivers/sqlite.cjs.map +1 -1
  35. package/dist/drivers/sqlite.mjs +258 -242
  36. package/dist/drivers/sqlite.mjs.map +1 -1
  37. package/dist/errors.mjs +48 -64
  38. package/dist/errors.mjs.map +1 -1
  39. package/dist/index.mjs +21 -9
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/schema/column.mjs +155 -157
  42. package/dist/schema/column.mjs.map +1 -1
  43. package/dist/schema/columns/index.mjs +103 -171
  44. package/dist/schema/columns/index.mjs.map +1 -1
  45. package/dist/schema/index.mjs +15 -0
  46. package/dist/schema/index.mjs.map +1 -0
  47. package/dist/schema/registry.mjs +122 -119
  48. package/dist/schema/registry.mjs.map +1 -1
  49. package/dist/schema/table.mjs +4 -1
  50. package/dist/schema/table.mjs.map +1 -1
  51. package/dist/sync/synchronizer.mjs +2 -1
  52. package/dist/sync/synchronizer.mjs.map +1 -1
  53. package/dist/types.d.cts +67 -6
  54. package/dist/types.d.mts +67 -6
  55. package/package.json +1 -1
@@ -4,20 +4,74 @@ import { SchemaRegistry } from "../schema/registry.cjs";
4
4
 
5
5
  //#region src/core/database.d.ts
6
6
  type TypedTableRepository<S extends readonly AnyTableDef[], T extends AnyTableDef> = {
7
+ /**
8
+ * Find all rows matching the given options
9
+ * @param options - Filter, sort, paginate, and eagerly load relations
10
+ * @returns Array of matching rows
11
+ */
7
12
  find<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O>[]>;
13
+ /**
14
+ * Find all rows matching the given options (alias for {@link find})
15
+ * @param options - Filter, sort, paginate, and eagerly load relations
16
+ * @returns Array of matching rows
17
+ */
8
18
  findMany<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O>[]>;
19
+ /**
20
+ * Find the first row matching the given options
21
+ * @param options - Filter, sort, and eagerly load relations
22
+ * @returns The first matching row, or `null` if none found
23
+ */
9
24
  findFirst<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O> | null>;
25
+ /**
26
+ * Insert one or more rows into the table
27
+ * @param data - Row data (or array of row data) to insert
28
+ * @returns The inserted row
29
+ */
10
30
  insert(data: Partial<InferRow<T>> | Partial<InferRow<T>>[]): Promise<InferRow<T>>;
31
+ /**
32
+ * Insert multiple rows into the table
33
+ * @param data - Array of row data to insert
34
+ * @returns Array of inserted rows
35
+ */
11
36
  insertMany(data: Partial<InferRow<T>>[]): Promise<InferRow<T>[]>;
37
+ /**
38
+ * Update rows matching the where clause
39
+ * @param options - Where clause and partial data to apply
40
+ * @returns Array of updated rows
41
+ */
12
42
  update(options: UpdateOptions<InferRow<T>>): Promise<InferRow<T>[]>;
43
+ /**
44
+ * Delete rows matching the where clause
45
+ * @param options - Where clause to select rows for deletion
46
+ * @returns Number of deleted rows
47
+ */
13
48
  delete(options: DeleteOptions<InferRow<T>>): Promise<number>;
49
+ /**
50
+ * Count rows matching the where clause
51
+ * @param options - Optional where clause to filter rows
52
+ * @returns Number of matching rows
53
+ */
14
54
  count(options?: Pick<QueryOptions<InferRow<T>>, "where">): Promise<number>;
55
+ /**
56
+ * Check whether at least one row matches the where clause
57
+ * @param options - Where clause to check
58
+ * @returns `true` if a matching row exists, `false` otherwise
59
+ */
15
60
  exists(options: Pick<QueryOptions<InferRow<T>>, "where">): Promise<boolean>;
61
+ /**
62
+ * Insert a row if it doesn't exist, or update it if it does
63
+ * @param options - Where clause to check, data to create, and data to update
64
+ * @returns The created or updated row
65
+ */
16
66
  upsert(options: {
17
67
  where: WhereClause<InferRow<T>>;
18
68
  create: Partial<InferRow<T>>;
19
69
  update: Partial<InferRow<T>>;
20
70
  }): Promise<InferRow<T>>;
71
+ /**
72
+ * Remove all rows from the table
73
+ * @returns Resolves when the table has been truncated
74
+ */
21
75
  truncate(): Promise<void>;
22
76
  };
23
77
  type ExtractRepos<S> = S extends readonly AnyTableDef[] ? { [T in S[number] as T["__name"]]: TypedTableRepository<S, T> } : S extends Record<string, any> ? { [K in keyof S as S[K] extends AnyTableDef ? K : never]: TypedTableRepository<InferSchemas<S>, Extract<S[K], AnyTableDef>> } : never;
@@ -60,6 +114,17 @@ type DatabaseInstance<S> = ExtractRepos<S> & {
60
114
  * @returns {Promise<T>} Result
61
115
  */
62
116
  transaction<T>(fn: () => Promise<T>): Promise<T>;
117
+ /**
118
+ * Run pending migrations manually
119
+ * @returns {Promise<void>}
120
+ */
121
+ migrateUp(): Promise<void>;
122
+ /**
123
+ * Rollback migrations
124
+ * @param {number} [steps=1] - Number of migrations to rollback
125
+ * @returns {Promise<string[]>} Names of rolled back migrations
126
+ */
127
+ migrateDown(steps?: number): Promise<string[]>;
63
128
  };
64
129
  declare function database<const S extends readonly AnyTableDef[] | Record<string, any>>(config: DatabaseConfig & {
65
130
  schemas: S;
@@ -4,20 +4,74 @@ import { SchemaRegistry } from "../schema/registry.mjs";
4
4
 
5
5
  //#region src/core/database.d.ts
6
6
  type TypedTableRepository<S extends readonly AnyTableDef[], T extends AnyTableDef> = {
7
+ /**
8
+ * Find all rows matching the given options
9
+ * @param options - Filter, sort, paginate, and eagerly load relations
10
+ * @returns Array of matching rows
11
+ */
7
12
  find<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O>[]>;
13
+ /**
14
+ * Find all rows matching the given options (alias for {@link find})
15
+ * @param options - Filter, sort, paginate, and eagerly load relations
16
+ * @returns Array of matching rows
17
+ */
8
18
  findMany<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O>[]>;
19
+ /**
20
+ * Find the first row matching the given options
21
+ * @param options - Filter, sort, and eagerly load relations
22
+ * @returns The first matching row, or `null` if none found
23
+ */
9
24
  findFirst<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(options?: O): Promise<ResolveResult<S, T, O> | null>;
25
+ /**
26
+ * Insert one or more rows into the table
27
+ * @param data - Row data (or array of row data) to insert
28
+ * @returns The inserted row
29
+ */
10
30
  insert(data: Partial<InferRow<T>> | Partial<InferRow<T>>[]): Promise<InferRow<T>>;
31
+ /**
32
+ * Insert multiple rows into the table
33
+ * @param data - Array of row data to insert
34
+ * @returns Array of inserted rows
35
+ */
11
36
  insertMany(data: Partial<InferRow<T>>[]): Promise<InferRow<T>[]>;
37
+ /**
38
+ * Update rows matching the where clause
39
+ * @param options - Where clause and partial data to apply
40
+ * @returns Array of updated rows
41
+ */
12
42
  update(options: UpdateOptions<InferRow<T>>): Promise<InferRow<T>[]>;
43
+ /**
44
+ * Delete rows matching the where clause
45
+ * @param options - Where clause to select rows for deletion
46
+ * @returns Number of deleted rows
47
+ */
13
48
  delete(options: DeleteOptions<InferRow<T>>): Promise<number>;
49
+ /**
50
+ * Count rows matching the where clause
51
+ * @param options - Optional where clause to filter rows
52
+ * @returns Number of matching rows
53
+ */
14
54
  count(options?: Pick<QueryOptions<InferRow<T>>, "where">): Promise<number>;
55
+ /**
56
+ * Check whether at least one row matches the where clause
57
+ * @param options - Where clause to check
58
+ * @returns `true` if a matching row exists, `false` otherwise
59
+ */
15
60
  exists(options: Pick<QueryOptions<InferRow<T>>, "where">): Promise<boolean>;
61
+ /**
62
+ * Insert a row if it doesn't exist, or update it if it does
63
+ * @param options - Where clause to check, data to create, and data to update
64
+ * @returns The created or updated row
65
+ */
16
66
  upsert(options: {
17
67
  where: WhereClause<InferRow<T>>;
18
68
  create: Partial<InferRow<T>>;
19
69
  update: Partial<InferRow<T>>;
20
70
  }): Promise<InferRow<T>>;
71
+ /**
72
+ * Remove all rows from the table
73
+ * @returns Resolves when the table has been truncated
74
+ */
21
75
  truncate(): Promise<void>;
22
76
  };
23
77
  type ExtractRepos<S> = S extends readonly AnyTableDef[] ? { [T in S[number] as T["__name"]]: TypedTableRepository<S, T> } : S extends Record<string, any> ? { [K in keyof S as S[K] extends AnyTableDef ? K : never]: TypedTableRepository<InferSchemas<S>, Extract<S[K], AnyTableDef>> } : never;
@@ -60,6 +114,17 @@ type DatabaseInstance<S> = ExtractRepos<S> & {
60
114
  * @returns {Promise<T>} Result
61
115
  */
62
116
  transaction<T>(fn: () => Promise<T>): Promise<T>;
117
+ /**
118
+ * Run pending migrations manually
119
+ * @returns {Promise<void>}
120
+ */
121
+ migrateUp(): Promise<void>;
122
+ /**
123
+ * Rollback migrations
124
+ * @param {number} [steps=1] - Number of migrations to rollback
125
+ * @returns {Promise<string[]>} Names of rolled back migrations
126
+ */
127
+ migrateDown(steps?: number): Promise<string[]>;
63
128
  };
64
129
  declare function database<const S extends readonly AnyTableDef[] | Record<string, any>>(config: DatabaseConfig & {
65
130
  schemas: S;
@@ -1,11 +1,13 @@
1
+ import { __esmMin } from "../_virtual/_rolldown/runtime.mjs";
1
2
  import { MIGRATIONS_TABLE, init_constants } from "../constants.mjs";
2
3
  import { CacheManager } from "../cache/manager.mjs";
3
- import { DatabaseError } from "../errors.mjs";
4
- import { createDriver } from "../drivers/index.mjs";
4
+ import { init_cache } from "../cache/index.mjs";
5
+ import { DatabaseError, init_errors } from "../errors.mjs";
6
+ import { createDriver, init_drivers } from "../drivers/index.mjs";
5
7
  import { SchemaRegistry } from "../schema/registry.mjs";
6
- import { TableRepository } from "./repository.mjs";
8
+ import { init_schema } from "../schema/index.mjs";
9
+ import { TableRepository, init_repository } from "./repository.mjs";
7
10
  //#region src/core/database.ts
8
- init_constants();
9
11
  /**
10
12
  * Create a database instance with typed repositories for each schema
11
13
  * @param {DatabaseConfig} config - Database configuration
@@ -23,7 +25,13 @@ function database(config) {
23
25
  const schemas = normalizeSchemas(config.schemas);
24
26
  const registry = new SchemaRegistry();
25
27
  registry.register(schemas);
26
- const connectionConfig = Array.isArray(config.connection) ? config.connection[0] : config.connection;
28
+ const dbName = typeof config.database === "string" ? config.database : config.database.name;
29
+ let connectionConfig;
30
+ if (Array.isArray(config.connection)) if (dbName === "sqlite") connectionConfig = config.connection.find((c) => "filename" in c) ?? config.connection[0];
31
+ else if (dbName === "mysql" || dbName === "mariadb") connectionConfig = config.connection.find((c) => "host" in c) ?? config.connection[0];
32
+ else if (dbName === "file") connectionConfig = config.connection.find((c) => "directory" in c) ?? config.connection[0];
33
+ else connectionConfig = config.connection[0];
34
+ else connectionConfig = config.connection;
27
35
  if (!connectionConfig) throw new DatabaseError("Connection config is required");
28
36
  const driver = createDriver(config.database, connectionConfig);
29
37
  const cache = new CacheManager(config.cache);
@@ -82,6 +90,18 @@ function database(config) {
82
90
  transaction: async (fn) => {
83
91
  await ensureInitialized();
84
92
  return driver.transaction(fn);
93
+ },
94
+ migrateUp: async () => {
95
+ await ensureInitialized();
96
+ if (config.migrations) {
97
+ const migrations = normalizeMigrations(config.migrations);
98
+ if (migrations.length > 0) await runMigrations(driver, registry, migrations);
99
+ }
100
+ },
101
+ migrateDown: async (steps = 1) => {
102
+ await ensureInitialized();
103
+ if (config.migrations) return rollbackMigrations(driver, registry, normalizeMigrations(config.migrations), steps);
104
+ return [];
85
105
  }
86
106
  };
87
107
  for (const schema of schemas) {
@@ -98,8 +118,8 @@ function database(config) {
98
118
  }
99
119
  return instance;
100
120
  }
101
- async function runMigrations(driver, registry, migrations) {
102
- const migrationsTableMeta = {
121
+ function getMigrationsTableMeta() {
122
+ return {
103
123
  name: MIGRATIONS_TABLE,
104
124
  columns: [
105
125
  {
@@ -132,40 +152,74 @@ async function runMigrations(driver, registry, migrations) {
132
152
  }
133
153
  ]
134
154
  };
135
- if (!await driver.tableExists("__hedystia_migrations")) await driver.createTable(migrationsTableMeta);
155
+ }
156
+ function createMigrationContext(driver, registry) {
157
+ return {
158
+ schema: {
159
+ createTable: async (tableDef) => {
160
+ const meta = registry.getTable(tableDef.__name);
161
+ if (meta) await driver.createTable(meta);
162
+ },
163
+ dropTable: async (name) => {
164
+ await driver.dropTable(name);
165
+ },
166
+ addColumn: async (table, _name, column) => {
167
+ await driver.addColumn(table, column);
168
+ },
169
+ dropColumn: async (table, name) => {
170
+ await driver.dropColumn(table, name);
171
+ },
172
+ renameColumn: async (table, oldName, newName) => {
173
+ await driver.renameColumn(table, oldName, newName);
174
+ },
175
+ addIndex: async () => {},
176
+ dropIndex: async () => {}
177
+ },
178
+ sql: async (query, params) => {
179
+ return driver.execute(query, params);
180
+ }
181
+ };
182
+ }
183
+ async function ensureMigrationsTable(driver) {
184
+ if (!await driver.tableExists("__hedystia_migrations")) await driver.createTable(getMigrationsTableMeta());
185
+ }
186
+ async function runMigrations(driver, registry, migrations) {
187
+ await ensureMigrationsTable(driver);
136
188
  const executed = await driver.query(`SELECT name FROM \`${MIGRATIONS_TABLE}\``);
137
189
  const executedNames = new Set(executed.map((r) => r.name));
190
+ const ctx = createMigrationContext(driver, registry);
138
191
  for (const migration of migrations) {
139
192
  if (executedNames.has(migration.name)) continue;
140
- await migration.up({
141
- schema: {
142
- createTable: async (tableDef) => {
143
- const meta = registry.getTable(tableDef.__name);
144
- if (meta) await driver.createTable(meta);
145
- },
146
- dropTable: async (name) => {
147
- await driver.dropTable(name);
148
- },
149
- addColumn: async (table, _name, column) => {
150
- await driver.addColumn(table, column);
151
- },
152
- dropColumn: async (table, name) => {
153
- await driver.dropColumn(table, name);
154
- },
155
- renameColumn: async (table, oldName, newName) => {
156
- await driver.renameColumn(table, oldName, newName);
157
- },
158
- addIndex: async () => {},
159
- dropIndex: async () => {}
160
- },
161
- sql: async (query, params) => {
162
- return driver.execute(query, params);
163
- }
164
- });
193
+ await migration.up(ctx);
165
194
  await driver.execute(`INSERT INTO \`${MIGRATIONS_TABLE}\` (\`name\`, \`executed_at\`) VALUES (?, ?)`, [migration.name, /* @__PURE__ */ new Date()]);
166
195
  }
167
196
  }
197
+ async function rollbackMigrations(driver, registry, migrations, steps = 1) {
198
+ await ensureMigrationsTable(driver);
199
+ const executedNames = (await driver.query(`SELECT name FROM \`${MIGRATIONS_TABLE}\` ORDER BY id DESC`)).map((r) => r.name);
200
+ const ctx = createMigrationContext(driver, registry);
201
+ const migrationMap = new Map(migrations.map((m) => [m.name, m]));
202
+ const rolledBack = [];
203
+ const toRollback = executedNames.slice(0, steps);
204
+ for (const name of toRollback) {
205
+ const migration = migrationMap.get(name);
206
+ if (!migration) continue;
207
+ await migration.down(ctx);
208
+ await driver.execute(`DELETE FROM \`${MIGRATIONS_TABLE}\` WHERE \`name\` = ?`, [name]);
209
+ rolledBack.push(name);
210
+ }
211
+ return rolledBack;
212
+ }
213
+ var init_database = __esmMin((() => {
214
+ init_cache();
215
+ init_constants();
216
+ init_drivers();
217
+ init_errors();
218
+ init_schema();
219
+ init_repository();
220
+ }));
168
221
  //#endregion
169
- export { database };
222
+ init_database();
223
+ export { database, init_database };
170
224
 
171
225
  //# sourceMappingURL=database.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.mjs","names":[],"sources":["../../src/core/database.ts"],"sourcesContent":["import { CacheManager } from \"../cache\";\nimport { MIGRATIONS_TABLE } from \"../constants\";\nimport { createDriver } from \"../drivers\";\nimport { DatabaseError } from \"../errors\";\nimport { SchemaRegistry } from \"../schema\";\nimport type {\n AnyTableDef,\n ConnectionConfig,\n DatabaseConfig,\n DatabaseDriver,\n DeleteOptions,\n InferRow,\n InferSchemas,\n MigrationDefinition,\n QueryOptions,\n RelationQueryMap,\n ResolveResult,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\nimport { TableRepository } from \"./repository\";\n\ntype TypedTableRepository<S extends readonly AnyTableDef[], T extends AnyTableDef> = {\n find<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O>[]>;\n\n findMany<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O>[]>;\n\n findFirst<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O> | null>;\n\n insert(data: Partial<InferRow<T>> | Partial<InferRow<T>>[]): Promise<InferRow<T>>;\n insertMany(data: Partial<InferRow<T>>[]): Promise<InferRow<T>[]>;\n update(options: UpdateOptions<InferRow<T>>): Promise<InferRow<T>[]>;\n delete(options: DeleteOptions<InferRow<T>>): Promise<number>;\n count(options?: Pick<QueryOptions<InferRow<T>>, \"where\">): Promise<number>;\n exists(options: Pick<QueryOptions<InferRow<T>>, \"where\">): Promise<boolean>;\n upsert(options: {\n where: WhereClause<InferRow<T>>;\n create: Partial<InferRow<T>>;\n update: Partial<InferRow<T>>;\n }): Promise<InferRow<T>>;\n truncate(): Promise<void>;\n};\n\ntype ExtractRepos<S> = S extends readonly AnyTableDef[]\n ? { [T in S[number] as T[\"__name\"]]: TypedTableRepository<S, T> }\n : S extends Record<string, any>\n ? {\n [K in keyof S as S[K] extends AnyTableDef ? K : never]: TypedTableRepository<\n InferSchemas<S>,\n Extract<S[K], AnyTableDef>\n >;\n }\n : never;\n\ntype DatabaseInstance<S> = ExtractRepos<S> & {\n /**\n * Initialize the database connection, create tables and run migrations\n * @returns {Promise<void>}\n */\n initialize(): Promise<void>;\n /**\n * Close the database connection\n * @returns {Promise<void>}\n */\n close(): Promise<void>;\n /**\n * Get the underlying database driver\n * @returns {DatabaseDriver} The database driver\n */\n getDriver(): DatabaseDriver;\n /**\n * Get the schema registry\n * @returns {SchemaRegistry} The schema registry\n */\n getRegistry(): SchemaRegistry;\n /**\n * Get the cache manager\n * @returns {CacheManager} The cache manager\n */\n getCache(): CacheManager;\n /**\n * Execute a raw SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n raw(sql: string, params?: unknown[]): Promise<any[]>;\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n transaction<T>(fn: () => Promise<T>): Promise<T>;\n};\n\n/**\n * Create a database instance with typed repositories for each schema\n * @param {DatabaseConfig} config - Database configuration\n * @returns {DatabaseInstance<S>} Database instance with table repositories\n */\nfunction normalizeMigrations(\n migrations: MigrationDefinition[] | Record<string, unknown>,\n): MigrationDefinition[] {\n if (Array.isArray(migrations)) {\n return migrations;\n }\n return Object.values(migrations).filter(\n (v): v is MigrationDefinition =>\n v != null && typeof v === \"object\" && \"name\" in v && \"up\" in v && \"down\" in v,\n );\n}\n\nfunction normalizeSchemas<S extends readonly AnyTableDef[]>(schemas: any): S {\n if (Array.isArray(schemas)) {\n return schemas as any as S;\n }\n return Object.values(schemas).filter(\n (v): v is AnyTableDef => v != null && typeof v === \"object\" && (v as any).__table === true,\n ) as any;\n}\n\nexport function database<const S extends readonly AnyTableDef[] | Record<string, any>>(\n config: DatabaseConfig & { schemas: S },\n): DatabaseInstance<S> {\n const schemas = normalizeSchemas(config.schemas) as any;\n const registry = new SchemaRegistry();\n registry.register(schemas);\n\n const connectionConfig = Array.isArray(config.connection)\n ? config.connection[0]\n : config.connection;\n\n if (!connectionConfig) {\n throw new DatabaseError(\"Connection config is required\");\n }\n\n const driver = createDriver(config.database, connectionConfig as ConnectionConfig);\n const cache = new CacheManager(config.cache);\n\n let initialized = false;\n let initPromise: Promise<void> | null = null;\n\n const ensureInitialized = async () => {\n if (initialized) {\n return;\n }\n if (initPromise) {\n return initPromise;\n }\n initPromise = doInit();\n await initPromise;\n initialized = true;\n };\n\n const doInit = async () => {\n await driver.connect();\n\n if (config.syncSchemas) {\n const allMetadata = driver.getAllTableColumns ? await driver.getAllTableColumns() : null;\n\n const syncPromises = Array.from(registry.getAllTables()).map(async ([, tableMeta]) => {\n const existingCols = allMetadata ? allMetadata[tableMeta.name] : null;\n const exists = allMetadata ? !!existingCols : await driver.tableExists(tableMeta.name);\n\n if (!exists) {\n await driver.createTable(tableMeta);\n } else {\n const cols = existingCols || (await driver.getTableColumns(tableMeta.name));\n const existingNames = new Set(cols.map((c) => c.name));\n const addColumnPromises = tableMeta.columns\n .filter((colMeta) => !existingNames.has(colMeta.name))\n .map((colMeta) => driver.addColumn(tableMeta.name, colMeta));\n await Promise.all(addColumnPromises);\n }\n });\n await Promise.all(syncPromises);\n }\n\n if (config.runMigrations && config.migrations) {\n const migrations = normalizeMigrations(config.migrations);\n if (migrations.length > 0) {\n await runMigrations(driver, registry, migrations);\n }\n }\n };\n\n const repos = new Map<string, TableRepository<any>>();\n for (const schema of schemas) {\n const repo = new TableRepository(schema.__name, driver, cache, registry, schema.__cache);\n repos.set(schema.__name, repo);\n }\n\n const instance: any = {\n initialize: async () => {\n await ensureInitialized();\n },\n close: async () => {\n await driver.disconnect();\n cache.clear();\n initialized = false;\n initPromise = null;\n },\n getDriver: () => driver,\n getRegistry: () => registry,\n getCache: () => cache,\n raw: async (sql: string, params?: unknown[]) => {\n await ensureInitialized();\n return driver.query(sql, params);\n },\n transaction: async <T>(fn: () => Promise<T>) => {\n await ensureInitialized();\n return driver.transaction(fn);\n },\n };\n\n for (const schema of schemas) {\n const repo = repos.get(schema.__name)!;\n const proxy = new Proxy(repo, {\n get(target, prop, receiver) {\n const original = Reflect.get(target, prop, receiver);\n if (typeof original === \"function\") {\n return async (...args: any[]) => {\n await ensureInitialized();\n return original.apply(target, args);\n };\n }\n return original;\n },\n });\n instance[schema.__name] = proxy;\n }\n\n return instance as any as DatabaseInstance<S>;\n}\n\nasync function runMigrations(\n driver: DatabaseDriver,\n registry: SchemaRegistry,\n migrations: MigrationDefinition[],\n): Promise<void> {\n const migrationsTableMeta: TableMetadata = {\n name: MIGRATIONS_TABLE,\n columns: [\n {\n name: \"id\",\n type: \"integer\",\n primaryKey: true,\n autoIncrement: true,\n notNull: true,\n unique: true,\n defaultValue: undefined,\n },\n {\n name: \"name\",\n type: \"varchar\",\n primaryKey: false,\n autoIncrement: false,\n notNull: true,\n unique: true,\n defaultValue: undefined,\n length: 255,\n },\n {\n name: \"executed_at\",\n type: \"datetime\",\n primaryKey: false,\n autoIncrement: false,\n notNull: true,\n unique: false,\n defaultValue: undefined,\n },\n ],\n };\n\n const exists = await driver.tableExists(MIGRATIONS_TABLE);\n if (!exists) {\n await driver.createTable(migrationsTableMeta);\n }\n\n const executed = await driver.query(`SELECT name FROM \\`${MIGRATIONS_TABLE}\\``);\n const executedNames = new Set(executed.map((r: any) => r.name));\n\n for (const migration of migrations) {\n if (executedNames.has(migration.name)) {\n continue;\n }\n\n const ctx = {\n schema: {\n createTable: async (tableDef: AnyTableDef) => {\n const meta = registry.getTable(tableDef.__name);\n if (meta) {\n await driver.createTable(meta);\n }\n },\n dropTable: async (name: string) => {\n await driver.dropTable(name);\n },\n addColumn: async (table: string, _name: string, column: any) => {\n await driver.addColumn(table, column);\n },\n dropColumn: async (table: string, name: string) => {\n await driver.dropColumn(table, name);\n },\n renameColumn: async (table: string, oldName: string, newName: string) => {\n await driver.renameColumn(table, oldName, newName);\n },\n addIndex: async () => {},\n dropIndex: async () => {},\n },\n sql: async (query: string, params?: unknown[]) => {\n return driver.execute(query, params);\n },\n };\n\n await migration.up(ctx);\n\n await driver.execute(\n `INSERT INTO \\`${MIGRATIONS_TABLE}\\` (\\`name\\`, \\`executed_at\\`) VALUES (?, ?)`,\n [migration.name, new Date()],\n );\n }\n}\n"],"mappings":";;;;;;;gBACgD;;;;;;AA0GhD,SAAS,oBACP,YACuB;AACvB,KAAI,MAAM,QAAQ,WAAW,CAC3B,QAAO;AAET,QAAO,OAAO,OAAO,WAAW,CAAC,QAC9B,MACC,KAAK,QAAQ,OAAO,MAAM,YAAY,UAAU,KAAK,QAAQ,KAAK,UAAU,EAC/E;;AAGH,SAAS,iBAAmD,SAAiB;AAC3E,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO;AAET,QAAO,OAAO,OAAO,QAAQ,CAAC,QAC3B,MAAwB,KAAK,QAAQ,OAAO,MAAM,YAAa,EAAU,YAAY,KACvF;;AAGH,SAAgB,SACd,QACqB;CACrB,MAAM,UAAU,iBAAiB,OAAO,QAAQ;CAChD,MAAM,WAAW,IAAI,gBAAgB;AACrC,UAAS,SAAS,QAAQ;CAE1B,MAAM,mBAAmB,MAAM,QAAQ,OAAO,WAAW,GACrD,OAAO,WAAW,KAClB,OAAO;AAEX,KAAI,CAAC,iBACH,OAAM,IAAI,cAAc,gCAAgC;CAG1D,MAAM,SAAS,aAAa,OAAO,UAAU,iBAAqC;CAClF,MAAM,QAAQ,IAAI,aAAa,OAAO,MAAM;CAE5C,IAAI,cAAc;CAClB,IAAI,cAAoC;CAExC,MAAM,oBAAoB,YAAY;AACpC,MAAI,YACF;AAEF,MAAI,YACF,QAAO;AAET,gBAAc,QAAQ;AACtB,QAAM;AACN,gBAAc;;CAGhB,MAAM,SAAS,YAAY;AACzB,QAAM,OAAO,SAAS;AAEtB,MAAI,OAAO,aAAa;GACtB,MAAM,cAAc,OAAO,qBAAqB,MAAM,OAAO,oBAAoB,GAAG;GAEpF,MAAM,eAAe,MAAM,KAAK,SAAS,cAAc,CAAC,CAAC,IAAI,OAAO,GAAG,eAAe;IACpF,MAAM,eAAe,cAAc,YAAY,UAAU,QAAQ;AAGjE,QAAI,EAFW,cAAc,CAAC,CAAC,eAAe,MAAM,OAAO,YAAY,UAAU,KAAK,EAGpF,OAAM,OAAO,YAAY,UAAU;SAC9B;KACL,MAAM,OAAO,gBAAiB,MAAM,OAAO,gBAAgB,UAAU,KAAK;KAC1E,MAAM,gBAAgB,IAAI,IAAI,KAAK,KAAK,MAAM,EAAE,KAAK,CAAC;KACtD,MAAM,oBAAoB,UAAU,QACjC,QAAQ,YAAY,CAAC,cAAc,IAAI,QAAQ,KAAK,CAAC,CACrD,KAAK,YAAY,OAAO,UAAU,UAAU,MAAM,QAAQ,CAAC;AAC9D,WAAM,QAAQ,IAAI,kBAAkB;;KAEtC;AACF,SAAM,QAAQ,IAAI,aAAa;;AAGjC,MAAI,OAAO,iBAAiB,OAAO,YAAY;GAC7C,MAAM,aAAa,oBAAoB,OAAO,WAAW;AACzD,OAAI,WAAW,SAAS,EACtB,OAAM,cAAc,QAAQ,UAAU,WAAW;;;CAKvD,MAAM,wBAAQ,IAAI,KAAmC;AACrD,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,OAAO,IAAI,gBAAgB,OAAO,QAAQ,QAAQ,OAAO,UAAU,OAAO,QAAQ;AACxF,QAAM,IAAI,OAAO,QAAQ,KAAK;;CAGhC,MAAM,WAAgB;EACpB,YAAY,YAAY;AACtB,SAAM,mBAAmB;;EAE3B,OAAO,YAAY;AACjB,SAAM,OAAO,YAAY;AACzB,SAAM,OAAO;AACb,iBAAc;AACd,iBAAc;;EAEhB,iBAAiB;EACjB,mBAAmB;EACnB,gBAAgB;EAChB,KAAK,OAAO,KAAa,WAAuB;AAC9C,SAAM,mBAAmB;AACzB,UAAO,OAAO,MAAM,KAAK,OAAO;;EAElC,aAAa,OAAU,OAAyB;AAC9C,SAAM,mBAAmB;AACzB,UAAO,OAAO,YAAY,GAAG;;EAEhC;AAED,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,OAAO,MAAM,IAAI,OAAO,OAAO;EACrC,MAAM,QAAQ,IAAI,MAAM,MAAM,EAC5B,IAAI,QAAQ,MAAM,UAAU;GAC1B,MAAM,WAAW,QAAQ,IAAI,QAAQ,MAAM,SAAS;AACpD,OAAI,OAAO,aAAa,WACtB,QAAO,OAAO,GAAG,SAAgB;AAC/B,UAAM,mBAAmB;AACzB,WAAO,SAAS,MAAM,QAAQ,KAAK;;AAGvC,UAAO;KAEV,CAAC;AACF,WAAS,OAAO,UAAU;;AAG5B,QAAO;;AAGT,eAAe,cACb,QACA,UACA,YACe;CACf,MAAM,sBAAqC;EACzC,MAAM;EACN,SAAS;GACP;IACE,MAAM;IACN,MAAM;IACN,YAAY;IACZ,eAAe;IACf,SAAS;IACT,QAAQ;IACR,cAAc,KAAA;IACf;GACD;IACE,MAAM;IACN,MAAM;IACN,YAAY;IACZ,eAAe;IACf,SAAS;IACT,QAAQ;IACR,cAAc,KAAA;IACd,QAAQ;IACT;GACD;IACE,MAAM;IACN,MAAM;IACN,YAAY;IACZ,eAAe;IACf,SAAS;IACT,QAAQ;IACR,cAAc,KAAA;IACf;GACF;EACF;AAGD,KAAI,CADW,MAAM,OAAO,YAAA,wBAA6B,CAEvD,OAAM,OAAO,YAAY,oBAAoB;CAG/C,MAAM,WAAW,MAAM,OAAO,MAAM,sBAAsB,iBAAiB,IAAI;CAC/E,MAAM,gBAAgB,IAAI,IAAI,SAAS,KAAK,MAAW,EAAE,KAAK,CAAC;AAE/D,MAAK,MAAM,aAAa,YAAY;AAClC,MAAI,cAAc,IAAI,UAAU,KAAK,CACnC;AA+BF,QAAM,UAAU,GA5BJ;GACV,QAAQ;IACN,aAAa,OAAO,aAA0B;KAC5C,MAAM,OAAO,SAAS,SAAS,SAAS,OAAO;AAC/C,SAAI,KACF,OAAM,OAAO,YAAY,KAAK;;IAGlC,WAAW,OAAO,SAAiB;AACjC,WAAM,OAAO,UAAU,KAAK;;IAE9B,WAAW,OAAO,OAAe,OAAe,WAAgB;AAC9D,WAAM,OAAO,UAAU,OAAO,OAAO;;IAEvC,YAAY,OAAO,OAAe,SAAiB;AACjD,WAAM,OAAO,WAAW,OAAO,KAAK;;IAEtC,cAAc,OAAO,OAAe,SAAiB,YAAoB;AACvE,WAAM,OAAO,aAAa,OAAO,SAAS,QAAQ;;IAEpD,UAAU,YAAY;IACtB,WAAW,YAAY;IACxB;GACD,KAAK,OAAO,OAAe,WAAuB;AAChD,WAAO,OAAO,QAAQ,OAAO,OAAO;;GAEvC,CAEsB;AAEvB,QAAM,OAAO,QACX,iBAAiB,iBAAiB,+CAClC,CAAC,UAAU,sBAAM,IAAI,MAAM,CAAC,CAC7B"}
1
+ {"version":3,"file":"database.mjs","names":[],"sources":["../../src/core/database.ts"],"sourcesContent":["import { CacheManager } from \"../cache\";\nimport { MIGRATIONS_TABLE } from \"../constants\";\nimport { createDriver } from \"../drivers\";\nimport { DatabaseError } from \"../errors\";\nimport { SchemaRegistry } from \"../schema\";\nimport type {\n AnyTableDef,\n ConnectionConfig,\n DatabaseConfig,\n DatabaseDriver,\n DeleteOptions,\n InferRow,\n InferSchemas,\n MigrationDefinition,\n QueryOptions,\n RelationQueryMap,\n ResolveResult,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\nimport { TableRepository } from \"./repository\";\n\ntype TypedTableRepository<S extends readonly AnyTableDef[], T extends AnyTableDef> = {\n /**\n * Find all rows matching the given options\n * @param options - Filter, sort, paginate, and eagerly load relations\n * @returns Array of matching rows\n */\n find<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O>[]>;\n\n /**\n * Find all rows matching the given options (alias for {@link find})\n * @param options - Filter, sort, paginate, and eagerly load relations\n * @returns Array of matching rows\n */\n findMany<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O>[]>;\n\n /**\n * Find the first row matching the given options\n * @param options - Filter, sort, and eagerly load relations\n * @returns The first matching row, or `null` if none found\n */\n findFirst<O extends QueryOptions<InferRow<T>, RelationQueryMap<S, T>> = {}>(\n options?: O,\n ): Promise<ResolveResult<S, T, O> | null>;\n\n /**\n * Insert one or more rows into the table\n * @param data - Row data (or array of row data) to insert\n * @returns The inserted row\n */\n insert(data: Partial<InferRow<T>> | Partial<InferRow<T>>[]): Promise<InferRow<T>>;\n\n /**\n * Insert multiple rows into the table\n * @param data - Array of row data to insert\n * @returns Array of inserted rows\n */\n insertMany(data: Partial<InferRow<T>>[]): Promise<InferRow<T>[]>;\n\n /**\n * Update rows matching the where clause\n * @param options - Where clause and partial data to apply\n * @returns Array of updated rows\n */\n update(options: UpdateOptions<InferRow<T>>): Promise<InferRow<T>[]>;\n\n /**\n * Delete rows matching the where clause\n * @param options - Where clause to select rows for deletion\n * @returns Number of deleted rows\n */\n delete(options: DeleteOptions<InferRow<T>>): Promise<number>;\n\n /**\n * Count rows matching the where clause\n * @param options - Optional where clause to filter rows\n * @returns Number of matching rows\n */\n count(options?: Pick<QueryOptions<InferRow<T>>, \"where\">): Promise<number>;\n\n /**\n * Check whether at least one row matches the where clause\n * @param options - Where clause to check\n * @returns `true` if a matching row exists, `false` otherwise\n */\n exists(options: Pick<QueryOptions<InferRow<T>>, \"where\">): Promise<boolean>;\n\n /**\n * Insert a row if it doesn't exist, or update it if it does\n * @param options - Where clause to check, data to create, and data to update\n * @returns The created or updated row\n */\n upsert(options: {\n where: WhereClause<InferRow<T>>;\n create: Partial<InferRow<T>>;\n update: Partial<InferRow<T>>;\n }): Promise<InferRow<T>>;\n\n /**\n * Remove all rows from the table\n * @returns Resolves when the table has been truncated\n */\n truncate(): Promise<void>;\n};\n\ntype ExtractRepos<S> = S extends readonly AnyTableDef[]\n ? { [T in S[number] as T[\"__name\"]]: TypedTableRepository<S, T> }\n : S extends Record<string, any>\n ? {\n [K in keyof S as S[K] extends AnyTableDef ? K : never]: TypedTableRepository<\n InferSchemas<S>,\n Extract<S[K], AnyTableDef>\n >;\n }\n : never;\n\ntype DatabaseInstance<S> = ExtractRepos<S> & {\n /**\n * Initialize the database connection, create tables and run migrations\n * @returns {Promise<void>}\n */\n initialize(): Promise<void>;\n /**\n * Close the database connection\n * @returns {Promise<void>}\n */\n close(): Promise<void>;\n /**\n * Get the underlying database driver\n * @returns {DatabaseDriver} The database driver\n */\n getDriver(): DatabaseDriver;\n /**\n * Get the schema registry\n * @returns {SchemaRegistry} The schema registry\n */\n getRegistry(): SchemaRegistry;\n /**\n * Get the cache manager\n * @returns {CacheManager} The cache manager\n */\n getCache(): CacheManager;\n /**\n * Execute a raw SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n raw(sql: string, params?: unknown[]): Promise<any[]>;\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n transaction<T>(fn: () => Promise<T>): Promise<T>;\n /**\n * Run pending migrations manually\n * @returns {Promise<void>}\n */\n migrateUp(): Promise<void>;\n /**\n * Rollback migrations\n * @param {number} [steps=1] - Number of migrations to rollback\n * @returns {Promise<string[]>} Names of rolled back migrations\n */\n migrateDown(steps?: number): Promise<string[]>;\n};\n\n/**\n * Create a database instance with typed repositories for each schema\n * @param {DatabaseConfig} config - Database configuration\n * @returns {DatabaseInstance<S>} Database instance with table repositories\n */\nfunction normalizeMigrations(\n migrations: MigrationDefinition[] | Record<string, unknown>,\n): MigrationDefinition[] {\n if (Array.isArray(migrations)) {\n return migrations;\n }\n return Object.values(migrations).filter(\n (v): v is MigrationDefinition =>\n v != null && typeof v === \"object\" && \"name\" in v && \"up\" in v && \"down\" in v,\n );\n}\n\nfunction normalizeSchemas<S extends readonly AnyTableDef[]>(schemas: any): S {\n if (Array.isArray(schemas)) {\n return schemas as any as S;\n }\n return Object.values(schemas).filter(\n (v): v is AnyTableDef => v != null && typeof v === \"object\" && (v as any).__table === true,\n ) as any;\n}\n\nexport function database<const S extends readonly AnyTableDef[] | Record<string, any>>(\n config: DatabaseConfig & { schemas: S },\n): DatabaseInstance<S> {\n const schemas = normalizeSchemas(config.schemas) as any;\n const registry = new SchemaRegistry();\n registry.register(schemas);\n\n const dbName = typeof config.database === \"string\" ? config.database : config.database.name;\n\n let connectionConfig: ConnectionConfig | undefined;\n if (Array.isArray(config.connection)) {\n if (dbName === \"sqlite\") {\n connectionConfig = config.connection.find((c) => \"filename\" in c) ?? config.connection[0];\n } else if (dbName === \"mysql\" || dbName === \"mariadb\") {\n connectionConfig = config.connection.find((c) => \"host\" in c) ?? config.connection[0];\n } else if (dbName === \"file\") {\n connectionConfig = config.connection.find((c) => \"directory\" in c) ?? config.connection[0];\n } else {\n connectionConfig = config.connection[0];\n }\n } else {\n connectionConfig = config.connection;\n }\n\n if (!connectionConfig) {\n throw new DatabaseError(\"Connection config is required\");\n }\n\n const driver = createDriver(config.database, connectionConfig as ConnectionConfig);\n const cache = new CacheManager(config.cache);\n\n let initialized = false;\n let initPromise: Promise<void> | null = null;\n\n const ensureInitialized = async () => {\n if (initialized) {\n return;\n }\n if (initPromise) {\n return initPromise;\n }\n initPromise = doInit();\n await initPromise;\n initialized = true;\n };\n\n const doInit = async () => {\n await driver.connect();\n\n if (config.syncSchemas) {\n const allMetadata = driver.getAllTableColumns ? await driver.getAllTableColumns() : null;\n\n const syncPromises = Array.from(registry.getAllTables()).map(async ([, tableMeta]) => {\n const existingCols = allMetadata ? allMetadata[tableMeta.name] : null;\n const exists = allMetadata ? !!existingCols : await driver.tableExists(tableMeta.name);\n\n if (!exists) {\n await driver.createTable(tableMeta);\n } else {\n const cols = existingCols || (await driver.getTableColumns(tableMeta.name));\n const existingNames = new Set(cols.map((c) => c.name));\n const addColumnPromises = tableMeta.columns\n .filter((colMeta) => !existingNames.has(colMeta.name))\n .map((colMeta) => driver.addColumn(tableMeta.name, colMeta));\n await Promise.all(addColumnPromises);\n }\n });\n await Promise.all(syncPromises);\n }\n\n if (config.runMigrations && config.migrations) {\n const migrations = normalizeMigrations(config.migrations);\n if (migrations.length > 0) {\n await runMigrations(driver, registry, migrations);\n }\n }\n };\n\n const repos = new Map<string, TableRepository<any>>();\n for (const schema of schemas) {\n const repo = new TableRepository(schema.__name, driver, cache, registry, schema.__cache);\n repos.set(schema.__name, repo);\n }\n\n const instance: any = {\n initialize: async () => {\n await ensureInitialized();\n },\n close: async () => {\n await driver.disconnect();\n cache.clear();\n initialized = false;\n initPromise = null;\n },\n getDriver: () => driver,\n getRegistry: () => registry,\n getCache: () => cache,\n raw: async (sql: string, params?: unknown[]) => {\n await ensureInitialized();\n return driver.query(sql, params);\n },\n transaction: async <T>(fn: () => Promise<T>) => {\n await ensureInitialized();\n return driver.transaction(fn);\n },\n migrateUp: async () => {\n await ensureInitialized();\n if (config.migrations) {\n const migrations = normalizeMigrations(config.migrations);\n if (migrations.length > 0) {\n await runMigrations(driver, registry, migrations);\n }\n }\n },\n migrateDown: async (steps = 1) => {\n await ensureInitialized();\n if (config.migrations) {\n const migrations = normalizeMigrations(config.migrations);\n return rollbackMigrations(driver, registry, migrations, steps);\n }\n return [];\n },\n };\n\n for (const schema of schemas) {\n const repo = repos.get(schema.__name)!;\n const proxy = new Proxy(repo, {\n get(target, prop, receiver) {\n const original = Reflect.get(target, prop, receiver);\n if (typeof original === \"function\") {\n return async (...args: any[]) => {\n await ensureInitialized();\n return original.apply(target, args);\n };\n }\n return original;\n },\n });\n instance[schema.__name] = proxy;\n }\n\n return instance as any as DatabaseInstance<S>;\n}\n\nfunction getMigrationsTableMeta(): TableMetadata {\n return {\n name: MIGRATIONS_TABLE,\n columns: [\n {\n name: \"id\",\n type: \"integer\",\n primaryKey: true,\n autoIncrement: true,\n notNull: true,\n unique: true,\n defaultValue: undefined,\n },\n {\n name: \"name\",\n type: \"varchar\",\n primaryKey: false,\n autoIncrement: false,\n notNull: true,\n unique: true,\n defaultValue: undefined,\n length: 255,\n },\n {\n name: \"executed_at\",\n type: \"datetime\",\n primaryKey: false,\n autoIncrement: false,\n notNull: true,\n unique: false,\n defaultValue: undefined,\n },\n ],\n };\n}\n\nfunction createMigrationContext(\n driver: DatabaseDriver,\n registry: SchemaRegistry,\n): MigrationDefinition[\"up\"] extends (ctx: infer C) => any ? C : never {\n return {\n schema: {\n createTable: async (tableDef: AnyTableDef) => {\n const meta = registry.getTable(tableDef.__name);\n if (meta) {\n await driver.createTable(meta);\n }\n },\n dropTable: async (name: string) => {\n await driver.dropTable(name);\n },\n addColumn: async (table: string, _name: string, column: any) => {\n await driver.addColumn(table, column);\n },\n dropColumn: async (table: string, name: string) => {\n await driver.dropColumn(table, name);\n },\n renameColumn: async (table: string, oldName: string, newName: string) => {\n await driver.renameColumn(table, oldName, newName);\n },\n addIndex: async () => {},\n dropIndex: async () => {},\n },\n sql: async (query: string, params?: unknown[]) => {\n return driver.execute(query, params);\n },\n };\n}\n\nasync function ensureMigrationsTable(driver: DatabaseDriver): Promise<void> {\n const exists = await driver.tableExists(MIGRATIONS_TABLE);\n if (!exists) {\n await driver.createTable(getMigrationsTableMeta());\n }\n}\n\nasync function runMigrations(\n driver: DatabaseDriver,\n registry: SchemaRegistry,\n migrations: MigrationDefinition[],\n): Promise<void> {\n await ensureMigrationsTable(driver);\n\n const executed = await driver.query(`SELECT name FROM \\`${MIGRATIONS_TABLE}\\``);\n const executedNames = new Set(executed.map((r: any) => r.name));\n\n const ctx = createMigrationContext(driver, registry);\n\n for (const migration of migrations) {\n if (executedNames.has(migration.name)) {\n continue;\n }\n\n await migration.up(ctx);\n\n await driver.execute(\n `INSERT INTO \\`${MIGRATIONS_TABLE}\\` (\\`name\\`, \\`executed_at\\`) VALUES (?, ?)`,\n [migration.name, new Date()],\n );\n }\n}\n\nasync function rollbackMigrations(\n driver: DatabaseDriver,\n registry: SchemaRegistry,\n migrations: MigrationDefinition[],\n steps = 1,\n): Promise<string[]> {\n await ensureMigrationsTable(driver);\n\n const executed = await driver.query(`SELECT name FROM \\`${MIGRATIONS_TABLE}\\` ORDER BY id DESC`);\n const executedNames = executed.map((r: any) => r.name as string);\n\n const ctx = createMigrationContext(driver, registry);\n const migrationMap = new Map(migrations.map((m) => [m.name, m]));\n const rolledBack: string[] = [];\n\n const toRollback = executedNames.slice(0, steps);\n\n for (const name of toRollback) {\n const migration = migrationMap.get(name);\n if (!migration) {\n continue;\n }\n\n await migration.down(ctx);\n\n await driver.execute(`DELETE FROM \\`${MIGRATIONS_TABLE}\\` WHERE \\`name\\` = ?`, [name]);\n rolledBack.push(name);\n }\n\n return rolledBack;\n}\n"],"mappings":"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"}