@superfunctions/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +248 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +114 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/generate.d.ts +5 -0
  7. package/dist/commands/generate.d.ts.map +1 -0
  8. package/dist/commands/generate.js +233 -0
  9. package/dist/commands/generate.js.map +1 -0
  10. package/dist/commands/status.d.ts +5 -0
  11. package/dist/commands/status.d.ts.map +1 -0
  12. package/dist/commands/status.js +148 -0
  13. package/dist/commands/status.js.map +1 -0
  14. package/dist/index.d.ts +39 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +9 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/types/library-schema.d.ts +24 -0
  19. package/dist/types/library-schema.d.ts.map +1 -0
  20. package/dist/types/library-schema.js +2 -0
  21. package/dist/types/library-schema.js.map +1 -0
  22. package/dist/utils/adapter-helper.d.ts +21 -0
  23. package/dist/utils/adapter-helper.d.ts.map +1 -0
  24. package/dist/utils/adapter-helper.js +217 -0
  25. package/dist/utils/adapter-helper.js.map +1 -0
  26. package/dist/utils/config.d.ts +4 -0
  27. package/dist/utils/config.d.ts.map +1 -0
  28. package/dist/utils/config.js +31 -0
  29. package/dist/utils/config.js.map +1 -0
  30. package/dist/utils/discover-configs.d.ts +11 -0
  31. package/dist/utils/discover-configs.d.ts.map +1 -0
  32. package/dist/utils/discover-configs.js +76 -0
  33. package/dist/utils/discover-configs.js.map +1 -0
  34. package/dist/utils/generators.d.ts +31 -0
  35. package/dist/utils/generators.d.ts.map +1 -0
  36. package/dist/utils/generators.js +302 -0
  37. package/dist/utils/generators.js.map +1 -0
  38. package/dist/utils/introspection.d.ts +55 -0
  39. package/dist/utils/introspection.d.ts.map +1 -0
  40. package/dist/utils/introspection.js +263 -0
  41. package/dist/utils/introspection.js.map +1 -0
  42. package/dist/utils/libraries.d.ts +7 -0
  43. package/dist/utils/libraries.d.ts.map +1 -0
  44. package/dist/utils/libraries.js +28 -0
  45. package/dist/utils/libraries.js.map +1 -0
  46. package/dist/utils/load-library-config.d.ts +6 -0
  47. package/dist/utils/load-library-config.d.ts.map +1 -0
  48. package/dist/utils/load-library-config.js +34 -0
  49. package/dist/utils/load-library-config.js.map +1 -0
  50. package/dist/utils/schema-diff.d.ts +48 -0
  51. package/dist/utils/schema-diff.d.ts.map +1 -0
  52. package/dist/utils/schema-diff.js +105 -0
  53. package/dist/utils/schema-diff.js.map +1 -0
  54. package/package.json +54 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Migration file generators for different ORMs
3
+ */
4
+ import type { TableSchema } from '@superfunctions/db';
5
+ import type { MigrationPlan } from './schema-diff.js';
6
+ export type Dialect = 'postgres' | 'mysql' | 'sqlite';
7
+ export interface DrizzleMigrationFile {
8
+ filename: string;
9
+ content: string;
10
+ }
11
+ /**
12
+ * Generate Drizzle migration file from migration plan
13
+ */
14
+ export declare function generateDrizzleMigration(plan: MigrationPlan, schemas: TableSchema[], dialect: Dialect): DrizzleMigrationFile;
15
+ export interface PrismaMigrationFile {
16
+ filename: string;
17
+ content: string;
18
+ }
19
+ /**
20
+ * Generate Prisma migration file from migration plan
21
+ */
22
+ export declare function generatePrismaMigration(plan: MigrationPlan, schemas: TableSchema[], dialect: Dialect): PrismaMigrationFile;
23
+ export interface KyselyMigrationFile {
24
+ filename: string;
25
+ content: string;
26
+ }
27
+ /**
28
+ * Generate Kysely TypeScript migration file from migration plan
29
+ */
30
+ export declare function generateKyselyMigration(plan: MigrationPlan, schemas: TableSchema[], dialect: Dialect): KyselyMigrationFile;
31
+ //# sourceMappingURL=generators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/utils/generators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjE,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AA8KtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,OAAO,GACf,oBAAoB,CA0CtB;AAMD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,OAAO,GACf,mBAAmB,CA0CrB;AAMD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,OAAO,GACf,mBAAmB,CAgGrB"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Migration file generators for different ORMs
3
+ */
4
+ /**
5
+ * Map FieldSchema type to SQL type for given dialect
6
+ */
7
+ function fieldTypeToSQL(field, dialect) {
8
+ const baseType = field.type;
9
+ switch (dialect) {
10
+ case 'postgres':
11
+ switch (baseType) {
12
+ case 'string':
13
+ return 'TEXT';
14
+ case 'number':
15
+ return 'INTEGER';
16
+ case 'bigint':
17
+ return 'BIGINT';
18
+ case 'boolean':
19
+ return 'BOOLEAN';
20
+ case 'date':
21
+ return 'TIMESTAMP';
22
+ case 'json':
23
+ return 'JSONB';
24
+ default:
25
+ return 'TEXT';
26
+ }
27
+ case 'mysql':
28
+ switch (baseType) {
29
+ case 'string':
30
+ return 'TEXT';
31
+ case 'number':
32
+ return 'INT';
33
+ case 'bigint':
34
+ return 'BIGINT';
35
+ case 'boolean':
36
+ return 'BOOLEAN';
37
+ case 'date':
38
+ return 'DATETIME';
39
+ case 'json':
40
+ return 'JSON';
41
+ default:
42
+ return 'TEXT';
43
+ }
44
+ case 'sqlite':
45
+ switch (baseType) {
46
+ case 'string':
47
+ return 'TEXT';
48
+ case 'number':
49
+ case 'bigint':
50
+ return 'INTEGER';
51
+ case 'boolean':
52
+ return 'INTEGER'; // SQLite uses INTEGER for boolean
53
+ case 'date':
54
+ return 'TEXT'; // SQLite stores dates as TEXT
55
+ case 'json':
56
+ return 'TEXT'; // SQLite stores JSON as TEXT
57
+ default:
58
+ return 'TEXT';
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Generate CREATE TABLE statement
64
+ */
65
+ function generateCreateTableSQL(schema, dialect, ifNotExists = true) {
66
+ const columns = [];
67
+ // Add columns
68
+ for (const [fieldName, field] of Object.entries(schema.fields)) {
69
+ const colName = field.fieldName ?? fieldName;
70
+ const sqlType = fieldTypeToSQL(field, dialect);
71
+ const parts = [colName, sqlType];
72
+ if (field.required) {
73
+ parts.push('NOT NULL');
74
+ }
75
+ if (field.unique) {
76
+ parts.push('UNIQUE');
77
+ }
78
+ if (field.defaultValue !== undefined) {
79
+ const defaultVal = typeof field.defaultValue === 'string'
80
+ ? `'${field.defaultValue}'`
81
+ : field.defaultValue;
82
+ parts.push(`DEFAULT ${defaultVal}`);
83
+ }
84
+ columns.push(` ${parts.join(' ')}`);
85
+ }
86
+ // Add primary key (assume 'id' field is primary)
87
+ const idField = Object.keys(schema.fields).find((f) => f === 'id');
88
+ if (idField) {
89
+ columns.push(` PRIMARY KEY (${schema.fields[idField].fieldName ?? 'id'})`);
90
+ }
91
+ const ifNotExistsClause = ifNotExists ? 'IF NOT EXISTS ' : '';
92
+ return `CREATE TABLE ${ifNotExistsClause}${schema.modelName} (\n${columns.join(',\n')}\n);`;
93
+ }
94
+ /**
95
+ * Generate ALTER TABLE statements for column changes
96
+ */
97
+ function generateAlterTableSQL(diff, schema, dialect) {
98
+ const statements = [];
99
+ // Add missing columns
100
+ if (diff.missingColumns) {
101
+ for (const colName of diff.missingColumns) {
102
+ const field = Object.entries(schema.fields).find(([name, f]) => (f.fieldName ?? name) === colName)?.[1];
103
+ if (!field)
104
+ continue;
105
+ const sqlType = fieldTypeToSQL(field, dialect);
106
+ const parts = [sqlType];
107
+ if (field.required)
108
+ parts.push('NOT NULL');
109
+ if (field.unique)
110
+ parts.push('UNIQUE');
111
+ if (dialect === 'mysql') {
112
+ statements.push(`ALTER TABLE ${diff.tableName} ADD COLUMN ${colName} ${parts.join(' ')};`);
113
+ }
114
+ else {
115
+ statements.push(`ALTER TABLE ${diff.tableName} ADD COLUMN ${colName} ${parts.join(' ')};`);
116
+ }
117
+ }
118
+ }
119
+ // Drop extra columns (commented out by default for safety)
120
+ if (diff.extraColumns && diff.extraColumns.length > 0) {
121
+ statements.push(`-- WARNING: The following columns exist but are not in the schema:`);
122
+ for (const colName of diff.extraColumns) {
123
+ statements.push(`-- ALTER TABLE ${diff.tableName} DROP COLUMN ${colName};`);
124
+ }
125
+ }
126
+ // Handle column changes (NOT NULL, etc)
127
+ if (diff.columnChanges) {
128
+ for (const change of diff.columnChanges) {
129
+ statements.push(`-- TODO: Handle column change for ${diff.tableName}.${change.column}: ${change.change}`);
130
+ }
131
+ }
132
+ return statements;
133
+ }
134
+ /**
135
+ * Generate DROP TABLE statement
136
+ */
137
+ function generateDropTableSQL(tableName, ifExists = true) {
138
+ const ifExistsClause = ifExists ? 'IF EXISTS ' : '';
139
+ return `-- DROP TABLE ${ifExistsClause}${tableName}; -- Commented out for safety`;
140
+ }
141
+ /**
142
+ * Generate Drizzle migration file from migration plan
143
+ */
144
+ export function generateDrizzleMigration(plan, schemas, dialect) {
145
+ const timestamp = Date.now();
146
+ const filename = `${timestamp}_${plan.namespace}_v${plan.toVersion}.sql`;
147
+ const statements = [];
148
+ statements.push(`-- Migration for ${plan.namespace}`);
149
+ statements.push(`-- From version ${plan.fromVersion} to ${plan.toVersion}`);
150
+ statements.push('');
151
+ for (const diff of plan.changes) {
152
+ if (diff.action === 'create') {
153
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
154
+ if (schema) {
155
+ statements.push(generateCreateTableSQL(schema, dialect));
156
+ statements.push('');
157
+ }
158
+ }
159
+ else if (diff.action === 'alter') {
160
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
161
+ if (schema) {
162
+ const alterStatements = generateAlterTableSQL(diff, schema, dialect);
163
+ statements.push(...alterStatements);
164
+ statements.push('');
165
+ }
166
+ }
167
+ else if (diff.action === 'drop') {
168
+ statements.push(generateDropTableSQL(diff.tableName));
169
+ statements.push('');
170
+ }
171
+ }
172
+ // Add schema version update
173
+ statements.push(`-- Update schema version`);
174
+ statements.push(`UPDATE _superfunctions_schema_versions SET version = ${plan.toVersion} WHERE namespace = '${plan.namespace}';`);
175
+ statements.push(`INSERT INTO _superfunctions_schema_versions (namespace, version, updated_at) SELECT '${plan.namespace}', ${plan.toVersion}, CURRENT_TIMESTAMP WHERE NOT EXISTS (SELECT 1 FROM _superfunctions_schema_versions WHERE namespace = '${plan.namespace}');`);
176
+ return {
177
+ filename,
178
+ content: statements.join('\n'),
179
+ };
180
+ }
181
+ /**
182
+ * Generate Prisma migration file from migration plan
183
+ */
184
+ export function generatePrismaMigration(plan, schemas, dialect) {
185
+ const timestamp = Date.now();
186
+ const filename = `${timestamp}_${plan.namespace}_v${plan.toVersion}`;
187
+ const statements = [];
188
+ statements.push(`-- Migration for ${plan.namespace}`);
189
+ statements.push(`-- From version ${plan.fromVersion} to ${plan.toVersion}`);
190
+ statements.push('');
191
+ for (const diff of plan.changes) {
192
+ if (diff.action === 'create') {
193
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
194
+ if (schema) {
195
+ statements.push(generateCreateTableSQL(schema, dialect));
196
+ statements.push('');
197
+ }
198
+ }
199
+ else if (diff.action === 'alter') {
200
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
201
+ if (schema) {
202
+ const alterStatements = generateAlterTableSQL(diff, schema, dialect);
203
+ statements.push(...alterStatements);
204
+ statements.push('');
205
+ }
206
+ }
207
+ else if (diff.action === 'drop') {
208
+ statements.push(generateDropTableSQL(diff.tableName));
209
+ statements.push('');
210
+ }
211
+ }
212
+ // Add schema version update
213
+ statements.push(`-- Update schema version`);
214
+ statements.push(`UPDATE _superfunctions_schema_versions SET version = ${plan.toVersion}, updated_at = CURRENT_TIMESTAMP WHERE namespace = '${plan.namespace}';`);
215
+ statements.push(`INSERT INTO _superfunctions_schema_versions (namespace, version, updated_at) SELECT '${plan.namespace}', ${plan.toVersion}, CURRENT_TIMESTAMP WHERE NOT EXISTS (SELECT 1 FROM _superfunctions_schema_versions WHERE namespace = '${plan.namespace}');`);
216
+ return {
217
+ filename: `${filename}/migration.sql`,
218
+ content: statements.join('\n'),
219
+ };
220
+ }
221
+ /**
222
+ * Generate Kysely TypeScript migration file from migration plan
223
+ */
224
+ export function generateKyselyMigration(plan, schemas, dialect) {
225
+ const timestamp = Date.now();
226
+ const filename = `${timestamp}_${plan.namespace}_v${plan.toVersion}.ts`;
227
+ const upStatements = [];
228
+ const downStatements = [];
229
+ for (const diff of plan.changes) {
230
+ if (diff.action === 'create') {
231
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
232
+ if (schema) {
233
+ // Up: create table
234
+ upStatements.push(` await db.schema.createTable('${schema.modelName}')`);
235
+ for (const [fieldName, field] of Object.entries(schema.fields)) {
236
+ const colName = field.fieldName ?? fieldName;
237
+ const sqlType = fieldTypeToSQL(field, dialect);
238
+ let chainBuilder = ` .addColumn('${colName}', '${sqlType.toLowerCase()}'`;
239
+ if (field.required)
240
+ chainBuilder += `, (col) => col.notNull()`;
241
+ chainBuilder += `)`;
242
+ upStatements.push(chainBuilder);
243
+ }
244
+ upStatements.push(` .execute();`);
245
+ // Down: drop table
246
+ downStatements.push(` await db.schema.dropTable('${schema.modelName}').execute();`);
247
+ }
248
+ }
249
+ else if (diff.action === 'alter') {
250
+ const schema = schemas.find((s) => s.modelName === diff.tableName);
251
+ if (schema && diff.missingColumns) {
252
+ for (const colName of diff.missingColumns) {
253
+ const field = Object.entries(schema.fields).find(([name, f]) => (f.fieldName ?? name) === colName)?.[1];
254
+ if (!field)
255
+ continue;
256
+ const sqlType = fieldTypeToSQL(field, dialect);
257
+ upStatements.push(` await db.schema.alterTable('${diff.tableName}').addColumn('${colName}', '${sqlType.toLowerCase()}', (col) => ${field.required ? 'col.notNull()' : 'col'}).execute();`);
258
+ downStatements.push(` await db.schema.alterTable('${diff.tableName}').dropColumn('${colName}').execute();`);
259
+ }
260
+ }
261
+ }
262
+ else if (diff.action === 'drop') {
263
+ upStatements.push(` // await db.schema.dropTable('${diff.tableName}').execute();`);
264
+ downStatements.push(` // Recreate ${diff.tableName} if needed`);
265
+ }
266
+ }
267
+ // Add schema version updates
268
+ upStatements.push(``);
269
+ upStatements.push(` // Update schema version`);
270
+ upStatements.push(` await db.insertInto('_superfunctions_schema_versions')`);
271
+ upStatements.push(` .values({`);
272
+ upStatements.push(` namespace: '${plan.namespace}',`);
273
+ upStatements.push(` version: ${plan.toVersion},`);
274
+ upStatements.push(` updated_at: new Date(),`);
275
+ upStatements.push(` })`);
276
+ upStatements.push(` .onConflict((oc) => oc.column('namespace').doUpdateSet({`);
277
+ upStatements.push(` version: ${plan.toVersion},`);
278
+ upStatements.push(` updated_at: new Date(),`);
279
+ upStatements.push(` }))`);
280
+ upStatements.push(` .execute();`);
281
+ downStatements.push(``);
282
+ downStatements.push(` // Revert schema version`);
283
+ downStatements.push(` await db.updateTable('_superfunctions_schema_versions')`);
284
+ downStatements.push(` .set({ version: ${plan.fromVersion}, updated_at: new Date() })`);
285
+ downStatements.push(` .where('namespace', '=', '${plan.namespace}')`);
286
+ downStatements.push(` .execute();`);
287
+ const content = `import { Kysely } from 'kysely';
288
+
289
+ export async function up(db: Kysely<any>): Promise<void> {
290
+ ${upStatements.join('\n')}
291
+ }
292
+
293
+ export async function down(db: Kysely<any>): Promise<void> {
294
+ ${downStatements.join('\n')}
295
+ }
296
+ `;
297
+ return {
298
+ filename,
299
+ content,
300
+ };
301
+ }
302
+ //# sourceMappingURL=generators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generators.js","sourceRoot":"","sources":["../../src/utils/generators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Schema introspection utilities for different database types
3
+ * Queries information_schema or equivalent to discover current database structure
4
+ */
5
+ import type { TableSchema, FieldSchema } from '@superfunctions/db';
6
+ export interface DatabaseColumn {
7
+ tableName: string;
8
+ columnName: string;
9
+ dataType: string;
10
+ isNullable: boolean;
11
+ defaultValue: string | null;
12
+ isPrimaryKey: boolean;
13
+ isUnique: boolean;
14
+ }
15
+ export interface DatabaseTable {
16
+ name: string;
17
+ columns: DatabaseColumn[];
18
+ indexes: DatabaseIndex[];
19
+ constraints: DatabaseConstraint[];
20
+ }
21
+ export interface DatabaseIndex {
22
+ name: string;
23
+ tableName: string;
24
+ columns: string[];
25
+ isUnique: boolean;
26
+ }
27
+ export interface DatabaseConstraint {
28
+ name: string;
29
+ type: 'PRIMARY KEY' | 'FOREIGN KEY' | 'UNIQUE' | 'CHECK';
30
+ tableName: string;
31
+ columns: string[];
32
+ referencedTable?: string;
33
+ referencedColumns?: string[];
34
+ }
35
+ /**
36
+ * Introspect PostgreSQL database schema
37
+ */
38
+ export declare function introspectPostgres(db: any, schema?: string, tablePrefix?: string): Promise<DatabaseTable[]>;
39
+ /**
40
+ * Introspect MySQL database schema
41
+ */
42
+ export declare function introspectMySQL(db: any, database: string, tablePrefix?: string): Promise<DatabaseTable[]>;
43
+ /**
44
+ * Introspect SQLite database schema
45
+ */
46
+ export declare function introspectSQLite(db: any, tablePrefix?: string): Promise<DatabaseTable[]>;
47
+ /**
48
+ * Convert database column type to FieldSchema type
49
+ */
50
+ export declare function mapDatabaseTypeToFieldType(dbType: string): FieldSchema['type'];
51
+ /**
52
+ * Convert DatabaseTable to TableSchema
53
+ */
54
+ export declare function databaseTableToSchema(dbTable: DatabaseTable): TableSchema;
55
+ //# sourceMappingURL=introspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../../src/utils/introspection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,GAAG,EACP,MAAM,GAAE,MAAiB,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,EAAE,CAAC,CA2F1B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,GAAG,EACP,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,EAAE,CAAC,CA8E1B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,GAAG,EACP,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,EAAE,CAAC,CAuD1B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CA6B9E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,CAsBzE"}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Schema introspection utilities for different database types
3
+ * Queries information_schema or equivalent to discover current database structure
4
+ */
5
+ /**
6
+ * Introspect PostgreSQL database schema
7
+ */
8
+ export async function introspectPostgres(db, schema = 'public', tablePrefix) {
9
+ // Query tables
10
+ const tablesQuery = `
11
+ SELECT table_name
12
+ FROM information_schema.tables
13
+ WHERE table_schema = $1
14
+ AND table_type = 'BASE TABLE'
15
+ ${tablePrefix ? `AND table_name LIKE $2` : ''}
16
+ ORDER BY table_name
17
+ `;
18
+ const tables = await db.query(tablesQuery, tablePrefix ? [schema, `${tablePrefix}%`] : [schema]);
19
+ const result = [];
20
+ for (const { table_name } of tables.rows) {
21
+ // Query columns
22
+ const columnsQuery = `
23
+ SELECT
24
+ c.column_name,
25
+ c.data_type,
26
+ c.is_nullable,
27
+ c.column_default,
28
+ CASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as is_primary_key,
29
+ CASE WHEN uq.column_name IS NOT NULL THEN true ELSE false END as is_unique
30
+ FROM information_schema.columns c
31
+ LEFT JOIN (
32
+ SELECT ku.column_name
33
+ FROM information_schema.table_constraints tc
34
+ JOIN information_schema.key_column_usage ku
35
+ ON tc.constraint_name = ku.constraint_name
36
+ WHERE tc.table_schema = $1
37
+ AND tc.table_name = $2
38
+ AND tc.constraint_type = 'PRIMARY KEY'
39
+ ) pk ON c.column_name = pk.column_name
40
+ LEFT JOIN (
41
+ SELECT ku.column_name
42
+ FROM information_schema.table_constraints tc
43
+ JOIN information_schema.key_column_usage ku
44
+ ON tc.constraint_name = ku.constraint_name
45
+ WHERE tc.table_schema = $1
46
+ AND tc.table_name = $2
47
+ AND tc.constraint_type = 'UNIQUE'
48
+ ) uq ON c.column_name = uq.column_name
49
+ WHERE c.table_schema = $1
50
+ AND c.table_name = $2
51
+ ORDER BY c.ordinal_position
52
+ `;
53
+ const columns = await db.query(columnsQuery, [schema, table_name]);
54
+ // Query indexes
55
+ const indexesQuery = `
56
+ SELECT
57
+ i.indexname as name,
58
+ i.tablename,
59
+ ARRAY_AGG(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns,
60
+ ix.indisunique as is_unique
61
+ FROM pg_indexes i
62
+ JOIN pg_class c ON c.relname = i.indexname
63
+ JOIN pg_index ix ON ix.indexrelid = c.oid
64
+ JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
65
+ WHERE i.schemaname = $1
66
+ AND i.tablename = $2
67
+ GROUP BY i.indexname, i.tablename, ix.indisunique
68
+ `;
69
+ const indexes = await db.query(indexesQuery, [schema, table_name]);
70
+ result.push({
71
+ name: table_name,
72
+ columns: columns.rows.map((c) => ({
73
+ tableName: table_name,
74
+ columnName: c.column_name,
75
+ dataType: c.data_type,
76
+ isNullable: c.is_nullable === 'YES',
77
+ defaultValue: c.column_default,
78
+ isPrimaryKey: c.is_primary_key,
79
+ isUnique: c.is_unique,
80
+ })),
81
+ indexes: indexes.rows.map((idx) => ({
82
+ name: idx.name,
83
+ tableName: idx.tablename,
84
+ columns: idx.columns,
85
+ isUnique: idx.is_unique,
86
+ })),
87
+ constraints: [],
88
+ });
89
+ }
90
+ return result;
91
+ }
92
+ /**
93
+ * Introspect MySQL database schema
94
+ */
95
+ export async function introspectMySQL(db, database, tablePrefix) {
96
+ // Query tables
97
+ const tablesQuery = `
98
+ SELECT TABLE_NAME as table_name
99
+ FROM information_schema.TABLES
100
+ WHERE TABLE_SCHEMA = ?
101
+ AND TABLE_TYPE = 'BASE TABLE'
102
+ ${tablePrefix ? `AND TABLE_NAME LIKE ?` : ''}
103
+ ORDER BY TABLE_NAME
104
+ `;
105
+ const [tables] = await db.query(tablesQuery, tablePrefix ? [database, `${tablePrefix}%`] : [database]);
106
+ const result = [];
107
+ for (const { table_name } of tables) {
108
+ // Query columns
109
+ const columnsQuery = `
110
+ SELECT
111
+ COLUMN_NAME as column_name,
112
+ DATA_TYPE as data_type,
113
+ IS_NULLABLE as is_nullable,
114
+ COLUMN_DEFAULT as column_default,
115
+ COLUMN_KEY as column_key
116
+ FROM information_schema.COLUMNS
117
+ WHERE TABLE_SCHEMA = ?
118
+ AND TABLE_NAME = ?
119
+ ORDER BY ORDINAL_POSITION
120
+ `;
121
+ const [columns] = await db.query(columnsQuery, [database, table_name]);
122
+ // Query indexes
123
+ const indexesQuery = `
124
+ SELECT
125
+ INDEX_NAME as name,
126
+ TABLE_NAME as table_name,
127
+ NON_UNIQUE as non_unique,
128
+ COLUMN_NAME as column_name
129
+ FROM information_schema.STATISTICS
130
+ WHERE TABLE_SCHEMA = ?
131
+ AND TABLE_NAME = ?
132
+ ORDER BY INDEX_NAME, SEQ_IN_INDEX
133
+ `;
134
+ const [indexRows] = await db.query(indexesQuery, [database, table_name]);
135
+ // Group indexes by name
136
+ const indexMap = new Map();
137
+ for (const row of indexRows) {
138
+ if (!indexMap.has(row.name)) {
139
+ indexMap.set(row.name, {
140
+ name: row.name,
141
+ tableName: row.table_name,
142
+ columns: [],
143
+ isUnique: row.non_unique === 0,
144
+ });
145
+ }
146
+ indexMap.get(row.name).columns.push(row.column_name);
147
+ }
148
+ result.push({
149
+ name: table_name,
150
+ columns: columns.map((c) => ({
151
+ tableName: table_name,
152
+ columnName: c.column_name,
153
+ dataType: c.data_type,
154
+ isNullable: c.is_nullable === 'YES',
155
+ defaultValue: c.column_default,
156
+ isPrimaryKey: c.column_key === 'PRI',
157
+ isUnique: c.column_key === 'UNI',
158
+ })),
159
+ indexes: Array.from(indexMap.values()),
160
+ constraints: [],
161
+ });
162
+ }
163
+ return result;
164
+ }
165
+ /**
166
+ * Introspect SQLite database schema
167
+ */
168
+ export async function introspectSQLite(db, tablePrefix) {
169
+ // Query tables
170
+ const tablesQuery = `
171
+ SELECT name as table_name
172
+ FROM sqlite_master
173
+ WHERE type = 'table'
174
+ AND name NOT LIKE 'sqlite_%'
175
+ ${tablePrefix ? `AND name LIKE ?` : ''}
176
+ ORDER BY name
177
+ `;
178
+ const tables = await db.all(tablesQuery, tablePrefix ? [`${tablePrefix}%`] : []);
179
+ const result = [];
180
+ for (const { table_name } of tables) {
181
+ // Query columns using PRAGMA
182
+ const columns = await db.all(`PRAGMA table_info(${table_name})`);
183
+ // Query indexes
184
+ const indexesQuery = await db.all(`SELECT name FROM sqlite_master WHERE type = 'index' AND tbl_name = ?`, [table_name]);
185
+ const indexes = [];
186
+ for (const { name } of indexesQuery) {
187
+ const indexInfo = await db.all(`PRAGMA index_info(${name})`);
188
+ indexes.push({
189
+ name,
190
+ tableName: table_name,
191
+ columns: indexInfo.map((i) => i.name),
192
+ isUnique: false, // Would need index_list to determine
193
+ });
194
+ }
195
+ result.push({
196
+ name: table_name,
197
+ columns: columns.map((c) => ({
198
+ tableName: table_name,
199
+ columnName: c.name,
200
+ dataType: c.type,
201
+ isNullable: c.notnull === 0,
202
+ defaultValue: c.dflt_value,
203
+ isPrimaryKey: c.pk === 1,
204
+ isUnique: false,
205
+ })),
206
+ indexes,
207
+ constraints: [],
208
+ });
209
+ }
210
+ return result;
211
+ }
212
+ /**
213
+ * Convert database column type to FieldSchema type
214
+ */
215
+ export function mapDatabaseTypeToFieldType(dbType) {
216
+ const normalized = dbType.toLowerCase();
217
+ if (normalized.includes('int') || normalized.includes('serial')) {
218
+ return normalized.includes('big') ? 'bigint' : 'number';
219
+ }
220
+ if (normalized.includes('varchar') ||
221
+ normalized.includes('text') ||
222
+ normalized.includes('char')) {
223
+ return 'string';
224
+ }
225
+ if (normalized.includes('bool')) {
226
+ return 'boolean';
227
+ }
228
+ if (normalized.includes('timestamp') ||
229
+ normalized.includes('date') ||
230
+ normalized.includes('time')) {
231
+ return 'date';
232
+ }
233
+ if (normalized.includes('json')) {
234
+ return 'json';
235
+ }
236
+ // Default to string for unknown types
237
+ return 'string';
238
+ }
239
+ /**
240
+ * Convert DatabaseTable to TableSchema
241
+ */
242
+ export function databaseTableToSchema(dbTable) {
243
+ const fields = {};
244
+ for (const col of dbTable.columns) {
245
+ fields[col.columnName] = {
246
+ type: mapDatabaseTypeToFieldType(col.dataType),
247
+ required: !col.isNullable,
248
+ unique: col.isUnique || col.isPrimaryKey,
249
+ fieldName: col.columnName,
250
+ };
251
+ }
252
+ return {
253
+ modelName: dbTable.name,
254
+ fields,
255
+ indexes: dbTable.indexes.map((idx) => ({
256
+ name: idx.name,
257
+ fields: idx.columns,
258
+ unique: idx.isUnique,
259
+ })),
260
+ constraints: [],
261
+ };
262
+ }
263
+ //# sourceMappingURL=introspection.js.map