@uql/core 3.1.0 → 3.1.2

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 (170) hide show
  1. package/CHANGELOG.md +134 -176
  2. package/README.md +413 -0
  3. package/package.json +31 -26
  4. package/dist/package.json +0 -131
  5. package/src/@types/index.d.ts +0 -1
  6. package/src/@types/jest.d.ts +0 -6
  7. package/src/browser/http/bus.spec.ts +0 -22
  8. package/src/browser/http/bus.ts +0 -17
  9. package/src/browser/http/http.spec.ts +0 -70
  10. package/src/browser/http/http.ts +0 -55
  11. package/src/browser/http/index.ts +0 -2
  12. package/src/browser/index.ts +0 -4
  13. package/src/browser/options.spec.ts +0 -37
  14. package/src/browser/options.ts +0 -18
  15. package/src/browser/querier/genericClientRepository.spec.ts +0 -105
  16. package/src/browser/querier/genericClientRepository.ts +0 -49
  17. package/src/browser/querier/httpQuerier.ts +0 -82
  18. package/src/browser/querier/index.ts +0 -3
  19. package/src/browser/querier/querier.util.spec.ts +0 -35
  20. package/src/browser/querier/querier.util.ts +0 -18
  21. package/src/browser/type/clientQuerier.ts +0 -45
  22. package/src/browser/type/clientQuerierPool.ts +0 -5
  23. package/src/browser/type/clientRepository.ts +0 -22
  24. package/src/browser/type/index.ts +0 -4
  25. package/src/browser/type/request.ts +0 -25
  26. package/src/dialect/abstractDialect.ts +0 -28
  27. package/src/dialect/abstractSqlDialect-spec.ts +0 -1309
  28. package/src/dialect/abstractSqlDialect.ts +0 -805
  29. package/src/dialect/index.ts +0 -3
  30. package/src/dialect/namingStrategy.spec.ts +0 -52
  31. package/src/dialect/queryContext.ts +0 -69
  32. package/src/entity/decorator/definition.spec.ts +0 -736
  33. package/src/entity/decorator/definition.ts +0 -265
  34. package/src/entity/decorator/entity.ts +0 -8
  35. package/src/entity/decorator/field.ts +0 -9
  36. package/src/entity/decorator/id.ts +0 -9
  37. package/src/entity/decorator/index.ts +0 -5
  38. package/src/entity/decorator/relation.spec.ts +0 -41
  39. package/src/entity/decorator/relation.ts +0 -34
  40. package/src/entity/index.ts +0 -1
  41. package/src/express/@types/express.d.ts +0 -8
  42. package/src/express/@types/index.d.ts +0 -1
  43. package/src/express/index.ts +0 -2
  44. package/src/express/querierMiddleware.ts +0 -217
  45. package/src/express/query.util.spec.ts +0 -40
  46. package/src/express/query.util.ts +0 -21
  47. package/src/index.ts +0 -9
  48. package/src/maria/index.ts +0 -3
  49. package/src/maria/mariaDialect.spec.ts +0 -207
  50. package/src/maria/mariaDialect.ts +0 -42
  51. package/src/maria/mariaQuerierPool.test.ts +0 -23
  52. package/src/maria/mariadbQuerier.test.ts +0 -23
  53. package/src/maria/mariadbQuerier.ts +0 -45
  54. package/src/maria/mariadbQuerierPool.ts +0 -21
  55. package/src/migrate/cli.ts +0 -301
  56. package/src/migrate/generator/index.ts +0 -4
  57. package/src/migrate/generator/mongoSchemaGenerator.spec.ts +0 -112
  58. package/src/migrate/generator/mongoSchemaGenerator.ts +0 -115
  59. package/src/migrate/generator/mysqlSchemaGenerator.spec.ts +0 -34
  60. package/src/migrate/generator/mysqlSchemaGenerator.ts +0 -92
  61. package/src/migrate/generator/postgresSchemaGenerator.spec.ts +0 -44
  62. package/src/migrate/generator/postgresSchemaGenerator.ts +0 -127
  63. package/src/migrate/generator/sqliteSchemaGenerator.spec.ts +0 -33
  64. package/src/migrate/generator/sqliteSchemaGenerator.ts +0 -81
  65. package/src/migrate/index.ts +0 -41
  66. package/src/migrate/introspection/index.ts +0 -4
  67. package/src/migrate/introspection/mongoIntrospector.spec.ts +0 -75
  68. package/src/migrate/introspection/mongoIntrospector.ts +0 -47
  69. package/src/migrate/introspection/mysqlIntrospector.spec.ts +0 -113
  70. package/src/migrate/introspection/mysqlIntrospector.ts +0 -278
  71. package/src/migrate/introspection/postgresIntrospector.spec.ts +0 -112
  72. package/src/migrate/introspection/postgresIntrospector.ts +0 -329
  73. package/src/migrate/introspection/sqliteIntrospector.spec.ts +0 -112
  74. package/src/migrate/introspection/sqliteIntrospector.ts +0 -296
  75. package/src/migrate/migrator-mongo.test.ts +0 -54
  76. package/src/migrate/migrator.spec.ts +0 -255
  77. package/src/migrate/migrator.test.ts +0 -94
  78. package/src/migrate/migrator.ts +0 -719
  79. package/src/migrate/namingStrategy.spec.ts +0 -22
  80. package/src/migrate/schemaGenerator-advanced.spec.ts +0 -138
  81. package/src/migrate/schemaGenerator.spec.ts +0 -190
  82. package/src/migrate/schemaGenerator.ts +0 -478
  83. package/src/migrate/storage/databaseStorage.spec.ts +0 -69
  84. package/src/migrate/storage/databaseStorage.ts +0 -100
  85. package/src/migrate/storage/index.ts +0 -2
  86. package/src/migrate/storage/jsonStorage.ts +0 -58
  87. package/src/migrate/type.ts +0 -1
  88. package/src/mongo/index.ts +0 -3
  89. package/src/mongo/mongoDialect.spec.ts +0 -251
  90. package/src/mongo/mongoDialect.ts +0 -238
  91. package/src/mongo/mongodbQuerier.test.ts +0 -45
  92. package/src/mongo/mongodbQuerier.ts +0 -256
  93. package/src/mongo/mongodbQuerierPool.test.ts +0 -25
  94. package/src/mongo/mongodbQuerierPool.ts +0 -24
  95. package/src/mysql/index.ts +0 -3
  96. package/src/mysql/mysql2Querier.test.ts +0 -20
  97. package/src/mysql/mysql2Querier.ts +0 -49
  98. package/src/mysql/mysql2QuerierPool.test.ts +0 -20
  99. package/src/mysql/mysql2QuerierPool.ts +0 -21
  100. package/src/mysql/mysqlDialect.spec.ts +0 -20
  101. package/src/mysql/mysqlDialect.ts +0 -16
  102. package/src/namingStrategy/defaultNamingStrategy.ts +0 -18
  103. package/src/namingStrategy/index.spec.ts +0 -36
  104. package/src/namingStrategy/index.ts +0 -2
  105. package/src/namingStrategy/snakeCaseNamingStrategy.ts +0 -15
  106. package/src/options.spec.ts +0 -41
  107. package/src/options.ts +0 -18
  108. package/src/postgres/index.ts +0 -3
  109. package/src/postgres/manual-types.d.ts +0 -4
  110. package/src/postgres/pgQuerier.test.ts +0 -25
  111. package/src/postgres/pgQuerier.ts +0 -45
  112. package/src/postgres/pgQuerierPool.test.ts +0 -28
  113. package/src/postgres/pgQuerierPool.ts +0 -21
  114. package/src/postgres/postgresDialect.spec.ts +0 -428
  115. package/src/postgres/postgresDialect.ts +0 -144
  116. package/src/querier/abstractQuerier-test.ts +0 -584
  117. package/src/querier/abstractQuerier.ts +0 -353
  118. package/src/querier/abstractQuerierPool-test.ts +0 -20
  119. package/src/querier/abstractQuerierPool.ts +0 -18
  120. package/src/querier/abstractSqlQuerier-spec.ts +0 -979
  121. package/src/querier/abstractSqlQuerier-test.ts +0 -21
  122. package/src/querier/abstractSqlQuerier.ts +0 -138
  123. package/src/querier/decorator/index.ts +0 -3
  124. package/src/querier/decorator/injectQuerier.spec.ts +0 -74
  125. package/src/querier/decorator/injectQuerier.ts +0 -45
  126. package/src/querier/decorator/serialized.spec.ts +0 -98
  127. package/src/querier/decorator/serialized.ts +0 -13
  128. package/src/querier/decorator/transactional.spec.ts +0 -240
  129. package/src/querier/decorator/transactional.ts +0 -56
  130. package/src/querier/index.ts +0 -4
  131. package/src/repository/genericRepository.spec.ts +0 -111
  132. package/src/repository/genericRepository.ts +0 -74
  133. package/src/repository/index.ts +0 -1
  134. package/src/sqlite/index.ts +0 -3
  135. package/src/sqlite/manual-types.d.ts +0 -4
  136. package/src/sqlite/sqliteDialect.spec.ts +0 -155
  137. package/src/sqlite/sqliteDialect.ts +0 -76
  138. package/src/sqlite/sqliteQuerier.spec.ts +0 -36
  139. package/src/sqlite/sqliteQuerier.test.ts +0 -21
  140. package/src/sqlite/sqliteQuerier.ts +0 -37
  141. package/src/sqlite/sqliteQuerierPool.test.ts +0 -12
  142. package/src/sqlite/sqliteQuerierPool.ts +0 -38
  143. package/src/test/entityMock.ts +0 -375
  144. package/src/test/index.ts +0 -3
  145. package/src/test/it.util.ts +0 -69
  146. package/src/test/spec.util.ts +0 -57
  147. package/src/type/entity.ts +0 -218
  148. package/src/type/index.ts +0 -9
  149. package/src/type/migration.ts +0 -241
  150. package/src/type/namingStrategy.ts +0 -17
  151. package/src/type/querier.ts +0 -143
  152. package/src/type/querierPool.ts +0 -26
  153. package/src/type/query.ts +0 -506
  154. package/src/type/repository.ts +0 -142
  155. package/src/type/universalQuerier.ts +0 -133
  156. package/src/type/utility.ts +0 -21
  157. package/src/util/dialect.util-extra.spec.ts +0 -96
  158. package/src/util/dialect.util.spec.ts +0 -23
  159. package/src/util/dialect.util.ts +0 -134
  160. package/src/util/index.ts +0 -5
  161. package/src/util/object.util.spec.ts +0 -29
  162. package/src/util/object.util.ts +0 -27
  163. package/src/util/raw.ts +0 -11
  164. package/src/util/sql.util-extra.spec.ts +0 -17
  165. package/src/util/sql.util.spec.ts +0 -208
  166. package/src/util/sql.util.ts +0 -104
  167. package/src/util/string.util.spec.ts +0 -46
  168. package/src/util/string.util.ts +0 -35
  169. package/tsconfig.build.json +0 -5
  170. package/tsconfig.json +0 -8
@@ -1,112 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
- import { Entity, Field, Id } from '../../entity/index.js';
3
- import type { IndexSchema, TableSchema } from '../../type/index.js';
4
- import { MongoSchemaGenerator } from './mongoSchemaGenerator.js';
5
-
6
- @Entity()
7
- class MongoUser {
8
- @Id() id?: string;
9
- @Field({ index: true }) username?: string;
10
- @Field({ index: 'idx_email', unique: true }) email?: string;
11
- }
12
-
13
- describe('MongoSchemaGenerator', () => {
14
- const generator = new MongoSchemaGenerator();
15
-
16
- it('should generate createCollection statement', () => {
17
- const json = generator.generateCreateTable(MongoUser);
18
- const cmd = JSON.parse(json);
19
-
20
- expect(cmd).toMatchObject({
21
- action: 'createCollection',
22
- name: 'MongoUser',
23
- });
24
- expect(cmd.indexes).toHaveLength(2);
25
- expect(cmd.indexes).toContainEqual({
26
- name: 'idx_MongoUser_username',
27
- columns: ['username'],
28
- unique: false,
29
- });
30
- expect(cmd.indexes).toContainEqual({
31
- name: 'idx_email',
32
- columns: ['email'],
33
- unique: true,
34
- });
35
- });
36
-
37
- it('should generate dropCollection statement', () => {
38
- const json = generator.generateDropTable(MongoUser);
39
- const cmd = JSON.parse(json);
40
-
41
- expect(cmd).toMatchObject({
42
- action: 'dropCollection',
43
- name: 'MongoUser',
44
- });
45
- });
46
-
47
- it('should generate createIndex statement', () => {
48
- const json = generator.generateCreateIndex('MongoUser', {
49
- name: 'idx_test',
50
- columns: ['test'],
51
- unique: true,
52
- } as IndexSchema);
53
- const cmd = JSON.parse(json);
54
-
55
- expect(cmd).toMatchObject({
56
- action: 'createIndex',
57
- collection: 'MongoUser',
58
- name: 'idx_test',
59
- key: { test: 1 },
60
- options: { unique: true, name: 'idx_test' },
61
- });
62
- });
63
-
64
- it('should generate dropIndex statement', () => {
65
- const json = generator.generateDropIndex('MongoUser', 'idx_test');
66
- const cmd = JSON.parse(json);
67
-
68
- expect(cmd).toMatchObject({
69
- action: 'dropIndex',
70
- collection: 'MongoUser',
71
- name: 'idx_test',
72
- });
73
- });
74
-
75
- it('diffSchema should return create if currentSchema is undefined', () => {
76
- const diff = generator.diffSchema(MongoUser, undefined);
77
- expect(diff).toMatchObject({
78
- tableName: 'MongoUser',
79
- type: 'create',
80
- });
81
- });
82
-
83
- it('diffSchema should return alter if indexes are missing', () => {
84
- const currentSchema: TableSchema = {
85
- name: 'MongoUser',
86
- columns: [],
87
- indexes: [{ name: 'idx_MongoUser_username', columns: ['username'], unique: false }],
88
- };
89
-
90
- const diff = generator.diffSchema(MongoUser, currentSchema);
91
- expect(diff).toMatchObject({
92
- tableName: 'MongoUser',
93
- type: 'alter',
94
- });
95
- expect(diff?.indexesToAdd).toHaveLength(1);
96
- expect(diff?.indexesToAdd?.[0].name).toBe('idx_email');
97
- });
98
-
99
- it('diffSchema should return undefined if in sync', () => {
100
- const currentSchema: import('../../type/index.js').TableSchema = {
101
- name: 'MongoUser',
102
- columns: [],
103
- indexes: [
104
- { name: 'idx_MongoUser_username', columns: ['username'], unique: false },
105
- { name: 'idx_email', columns: ['email'], unique: true },
106
- ],
107
- };
108
-
109
- const diff = generator.diffSchema(MongoUser, currentSchema);
110
- expect(diff).toBeUndefined();
111
- });
112
- });
@@ -1,115 +0,0 @@
1
- import { AbstractDialect } from '../../dialect/index.js';
2
- import { getMeta } from '../../entity/index.js';
3
- import type { IndexSchema, SchemaDiff, SchemaGenerator, TableSchema, Type } from '../../type/index.js';
4
-
5
- export class MongoSchemaGenerator extends AbstractDialect implements SchemaGenerator {
6
- generateCreateTable<E>(entity: Type<E>): string {
7
- const meta = getMeta(entity);
8
- const collectionName = this.resolveTableName(entity, meta);
9
- const indexes: IndexSchema[] = [];
10
-
11
- for (const key in meta.fields) {
12
- const field = meta.fields[key];
13
- if (field.index) {
14
- const columnName = this.resolveColumnName(key, field);
15
- const indexName = typeof field.index === 'string' ? field.index : `idx_${collectionName}_${columnName}`;
16
- indexes.push({
17
- name: indexName,
18
- columns: [columnName],
19
- unique: !!field.unique,
20
- });
21
- }
22
- }
23
-
24
- return JSON.stringify({ action: 'createCollection', name: collectionName, indexes });
25
- }
26
-
27
- generateDropTable<E>(entity: Type<E>): string {
28
- const meta = getMeta(entity);
29
- const collectionName = this.resolveTableName(entity, meta);
30
- return JSON.stringify({ action: 'dropCollection', name: collectionName });
31
- }
32
-
33
- generateAlterTable(diff: SchemaDiff): string[] {
34
- const statements: string[] = [];
35
- if (diff.indexesToAdd?.length) {
36
- for (const index of diff.indexesToAdd) {
37
- statements.push(this.generateCreateIndex(diff.tableName, index));
38
- }
39
- }
40
- return statements;
41
- }
42
-
43
- generateAlterTableDown(diff: SchemaDiff): string[] {
44
- const statements: string[] = [];
45
- if (diff.indexesToAdd?.length) {
46
- for (const index of diff.indexesToAdd) {
47
- statements.push(this.generateDropIndex(diff.tableName, index.name));
48
- }
49
- }
50
- return statements;
51
- }
52
-
53
- generateCreateIndex(tableName: string, index: IndexSchema): string {
54
- const key: Record<string, number> = {};
55
- for (const col of index.columns) {
56
- key[col] = 1;
57
- }
58
- return JSON.stringify({
59
- action: 'createIndex',
60
- collection: tableName,
61
- name: index.name,
62
- key,
63
- options: { unique: index.unique, name: index.name },
64
- });
65
- }
66
-
67
- generateDropIndex(tableName: string, indexName: string): string {
68
- return JSON.stringify({
69
- action: 'dropIndex',
70
- collection: tableName,
71
- name: indexName,
72
- });
73
- }
74
-
75
- getSqlType(): string {
76
- return '';
77
- }
78
-
79
- diffSchema<E>(entity: Type<E>, currentSchema: TableSchema | undefined): SchemaDiff | undefined {
80
- const meta = getMeta(entity);
81
- const collectionName = this.resolveTableName(entity, meta);
82
-
83
- if (!currentSchema) {
84
- return { tableName: collectionName, type: 'create' };
85
- }
86
-
87
- const indexesToAdd: IndexSchema[] = [];
88
- const existingIndexes = new Set(currentSchema.indexes?.map((i: IndexSchema) => i.name) ?? []);
89
-
90
- for (const key in meta.fields) {
91
- const field = meta.fields[key];
92
- if (field.index) {
93
- const columnName = this.resolveColumnName(key, field);
94
- const indexName = typeof field.index === 'string' ? field.index : `idx_${collectionName}_${columnName}`;
95
- if (!existingIndexes.has(indexName)) {
96
- indexesToAdd.push({
97
- name: indexName,
98
- columns: [columnName],
99
- unique: !!field.unique,
100
- });
101
- }
102
- }
103
- }
104
-
105
- if (indexesToAdd.length === 0) {
106
- return undefined;
107
- }
108
-
109
- return {
110
- tableName: collectionName,
111
- type: 'alter',
112
- indexesToAdd,
113
- };
114
- }
115
- }
@@ -1,34 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
- import { MysqlSchemaGenerator } from './mysqlSchemaGenerator.js';
3
-
4
- describe('MysqlSchemaGenerator Specifics', () => {
5
- const generator = new MysqlSchemaGenerator();
6
-
7
- it('should map column types correctly', () => {
8
- expect(generator.getSqlType({ columnType: 'varchar', length: 100 }, String)).toBe('VARCHAR(100)');
9
- expect(generator.getSqlType({ columnType: 'text' }, String)).toBe('TEXT');
10
- expect(generator.getSqlType({ columnType: 'int' }, Number)).toBe('INT');
11
- expect(generator.getSqlType({ columnType: 'bigint' }, Number)).toBe('BIGINT');
12
- expect(generator.getSqlType({ type: Boolean }, Boolean)).toBe('TINYINT(1)');
13
- expect(generator.getSqlType({ columnType: 'decimal', precision: 10, scale: 2 }, Number)).toBe('DECIMAL(10, 2)');
14
- });
15
-
16
- it('should generate ALTER COLUMN statements', () => {
17
- const col = {
18
- name: 'age',
19
- type: 'INT',
20
- nullable: false,
21
- defaultValue: 18,
22
- isPrimaryKey: false,
23
- isAutoIncrement: false,
24
- isUnique: false,
25
- };
26
- const statements = generator.generateAlterColumnStatements('users', col, 'INT NOT NULL DEFAULT 18');
27
-
28
- expect(statements).toEqual(['ALTER TABLE `users` MODIFY COLUMN INT NOT NULL DEFAULT 18;']);
29
- });
30
-
31
- it('should get table options', () => {
32
- expect(generator.getTableOptions()).toContain('ENGINE=InnoDB');
33
- });
34
- });
@@ -1,92 +0,0 @@
1
- import type { ColumnSchema, ColumnType, FieldOptions } from '../../type/index.js';
2
- import { AbstractSchemaGenerator } from '../schemaGenerator.js';
3
-
4
- /**
5
- * MySQL/MariaDB-specific schema generator
6
- */
7
- export class MysqlSchemaGenerator extends AbstractSchemaGenerator {
8
- protected readonly serialPrimaryKeyType = 'INT AUTO_INCREMENT PRIMARY KEY';
9
-
10
- public override mapColumnType(columnType: ColumnType, field: FieldOptions): string {
11
- switch (columnType) {
12
- case 'int':
13
- return 'INT';
14
- case 'smallint':
15
- return 'SMALLINT';
16
- case 'bigint':
17
- return 'BIGINT';
18
- case 'float':
19
- return 'FLOAT';
20
- case 'double':
21
- case 'real':
22
- return 'DOUBLE';
23
- case 'decimal':
24
- case 'numeric':
25
- if (field.precision !== undefined) {
26
- if (field.scale !== undefined) {
27
- return `DECIMAL(${field.precision}, ${field.scale})`;
28
- }
29
- return `DECIMAL(${field.precision})`;
30
- }
31
- return 'DECIMAL(10, 2)';
32
- case 'boolean':
33
- return 'TINYINT(1)';
34
- case 'char':
35
- return `CHAR(${field.length ?? 1})`;
36
- case 'varchar':
37
- return `VARCHAR(${field.length ?? 255})`;
38
- case 'text':
39
- return 'TEXT';
40
- case 'uuid':
41
- return 'CHAR(36)';
42
- case 'date':
43
- return 'DATE';
44
- case 'time':
45
- return 'TIME';
46
- case 'timestamp':
47
- case 'timestamptz':
48
- return 'TIMESTAMP';
49
- case 'json':
50
- case 'jsonb':
51
- return 'JSON';
52
- case 'blob':
53
- case 'bytea':
54
- return 'BLOB';
55
- case 'vector':
56
- // MySQL doesn't have native vector support, use JSON
57
- return 'JSON';
58
- case 'serial':
59
- return 'INT AUTO_INCREMENT';
60
- case 'bigserial':
61
- return 'BIGINT AUTO_INCREMENT';
62
- default:
63
- return 'TEXT';
64
- }
65
- }
66
-
67
- public override getBooleanType(): string {
68
- return 'TINYINT(1)';
69
- }
70
-
71
- public override generateAlterColumnStatements(
72
- tableName: string,
73
- column: ColumnSchema,
74
- newDefinition: string,
75
- ): string[] {
76
- return [`ALTER TABLE ${this.escapeId(tableName)} MODIFY COLUMN ${newDefinition};`];
77
- }
78
-
79
- public override generateColumnComment(tableName: string, columnName: string, comment: string): string {
80
- const escapedComment = comment.replace(/'/g, "''");
81
- return ` COMMENT '${escapedComment}'`;
82
- }
83
-
84
- override getTableOptions<E>(): string {
85
- return ' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci';
86
- }
87
-
88
- override generateDropIndex(tableName: string, indexName: string): string {
89
- // MySQL requires table name in DROP INDEX
90
- return `DROP INDEX ${this.escapeId(indexName)} ON ${this.escapeId(tableName)};`;
91
- }
92
- }
@@ -1,44 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
- import { PostgresSchemaGenerator } from './postgresSchemaGenerator.js';
3
-
4
- describe('PostgresSchemaGenerator Specifics', () => {
5
- const generator = new PostgresSchemaGenerator();
6
-
7
- it('should format default values correctly', () => {
8
- expect(generator.formatDefaultValue('test')).toBe("'test'");
9
- expect(generator.formatDefaultValue(123)).toBe('123');
10
- expect(generator.formatDefaultValue(true)).toBe('TRUE');
11
- expect(generator.formatDefaultValue(false)).toBe('FALSE');
12
- expect(generator.formatDefaultValue(null)).toBe('NULL');
13
- });
14
-
15
- it('should map column types correctly', () => {
16
- expect(generator.getSqlType({ columnType: 'varchar', length: 100 }, String)).toBe('VARCHAR(100)');
17
- expect(generator.getSqlType({ columnType: 'text' }, String)).toBe('TEXT');
18
- expect(generator.getSqlType({ columnType: 'int' }, Number)).toBe('INTEGER');
19
- expect(generator.getSqlType({ columnType: 'bigint' }, Number)).toBe('BIGINT');
20
- expect(generator.getSqlType({ type: Boolean }, Boolean)).toBe('BOOLEAN');
21
- expect(generator.getSqlType({ columnType: 'decimal', precision: 10, scale: 2 }, Number)).toBe('NUMERIC(10, 2)');
22
- });
23
-
24
- it('should generate DROP INDEX statement', () => {
25
- expect(generator.generateDropIndex('users', 'idx_test')).toBe('DROP INDEX IF EXISTS "idx_test";');
26
- });
27
-
28
- it('should generate ALTER COLUMN statements', () => {
29
- const col = {
30
- name: 'age',
31
- type: 'INTEGER',
32
- nullable: false,
33
- defaultValue: 18,
34
- isPrimaryKey: false,
35
- isAutoIncrement: false,
36
- isUnique: false,
37
- };
38
- const statements = generator.generateAlterColumnStatements('users', col, 'INTEGER');
39
-
40
- expect(statements).toContain('ALTER TABLE "users" ALTER COLUMN "age" TYPE INTEGER;');
41
- expect(statements).toContain('ALTER TABLE "users" ALTER COLUMN "age" SET NOT NULL;');
42
- expect(statements).toContain('ALTER TABLE "users" ALTER COLUMN "age" SET DEFAULT 18;');
43
- });
44
- });
@@ -1,127 +0,0 @@
1
- import type { ColumnSchema, ColumnType, FieldOptions, NamingStrategy } from '../../type/index.js';
2
- import { AbstractSchemaGenerator } from '../schemaGenerator.js';
3
-
4
- /**
5
- * PostgreSQL-specific schema generator
6
- */
7
- export class PostgresSchemaGenerator extends AbstractSchemaGenerator {
8
- protected readonly serialPrimaryKeyType = 'SERIAL PRIMARY KEY';
9
-
10
- constructor(namingStrategy?: NamingStrategy) {
11
- super(namingStrategy, '"');
12
- }
13
-
14
- public override mapColumnType(columnType: ColumnType, field: FieldOptions): string {
15
- switch (columnType) {
16
- case 'int':
17
- return 'INTEGER';
18
- case 'smallint':
19
- return 'SMALLINT';
20
- case 'bigint':
21
- return 'BIGINT';
22
- case 'float':
23
- case 'double':
24
- case 'real':
25
- return 'DOUBLE PRECISION';
26
- case 'decimal':
27
- case 'numeric':
28
- if (field.precision !== undefined) {
29
- if (field.scale !== undefined) {
30
- return `NUMERIC(${field.precision}, ${field.scale})`;
31
- }
32
- return `NUMERIC(${field.precision})`;
33
- }
34
- return 'NUMERIC';
35
- case 'boolean':
36
- return 'BOOLEAN';
37
- case 'char':
38
- return `CHAR(${field.length ?? 1})`;
39
- case 'varchar':
40
- return `VARCHAR(${field.length ?? 255})`;
41
- case 'text':
42
- return 'TEXT';
43
- case 'uuid':
44
- return 'UUID';
45
- case 'date':
46
- return 'DATE';
47
- case 'time':
48
- return 'TIME';
49
- case 'timestamp':
50
- return 'TIMESTAMP';
51
- case 'timestamptz':
52
- return 'TIMESTAMPTZ';
53
- case 'json':
54
- return 'JSON';
55
- case 'jsonb':
56
- return 'JSONB';
57
- case 'blob':
58
- case 'bytea':
59
- return 'BYTEA';
60
- case 'vector':
61
- if (field.length) {
62
- return `VECTOR(${field.length})`;
63
- }
64
- return 'VECTOR';
65
- case 'serial':
66
- return 'SERIAL';
67
- case 'bigserial':
68
- return 'BIGSERIAL';
69
- default:
70
- return 'TEXT';
71
- }
72
- }
73
-
74
- public override getBooleanType(): string {
75
- return 'BOOLEAN';
76
- }
77
-
78
- public override generateAlterColumnStatements(
79
- tableName: string,
80
- column: ColumnSchema,
81
- newDefinition: string,
82
- ): string[] {
83
- const statements: string[] = [];
84
- const escapedTableName = this.escapeId(tableName);
85
- const escapedColumnName = this.escapeId(column.name);
86
-
87
- // PostgreSQL uses separate ALTER COLUMN clauses for different changes
88
- // 1. Change type
89
- statements.push(`ALTER TABLE ${escapedTableName} ALTER COLUMN ${escapedColumnName} TYPE ${column.type};`);
90
-
91
- // 2. Change nullability
92
- if (column.nullable) {
93
- statements.push(`ALTER TABLE ${escapedTableName} ALTER COLUMN ${escapedColumnName} DROP NOT NULL;`);
94
- } else {
95
- statements.push(`ALTER TABLE ${escapedTableName} ALTER COLUMN ${escapedColumnName} SET NOT NULL;`);
96
- }
97
-
98
- // 3. Change default value
99
- if (column.defaultValue !== undefined) {
100
- statements.push(
101
- `ALTER TABLE ${escapedTableName} ALTER COLUMN ${escapedColumnName} SET DEFAULT ${this.formatDefaultValue(column.defaultValue)};`,
102
- );
103
- } else {
104
- statements.push(`ALTER TABLE ${escapedTableName} ALTER COLUMN ${escapedColumnName} DROP DEFAULT;`);
105
- }
106
-
107
- return statements;
108
- }
109
-
110
- public override generateColumnComment(tableName: string, columnName: string, comment: string): string {
111
- // PostgreSQL handles comments separately via COMMENT ON COLUMN
112
- return '';
113
- }
114
-
115
- /**
116
- * Generate COMMENT ON COLUMN statement for PostgreSQL
117
- */
118
- generateColumnCommentStatement(tableName: string, columnName: string, comment: string): string {
119
- const escapedComment = comment.replace(/'/g, "''");
120
- return `COMMENT ON COLUMN ${this.escapeId(tableName)}.${this.escapeId(columnName)} IS '${escapedComment}';`;
121
- }
122
-
123
- override generateDropIndex(tableName: string, indexName: string): string {
124
- // PostgreSQL doesn't require table name in DROP INDEX
125
- return `DROP INDEX IF EXISTS ${this.escapeId(indexName)};`;
126
- }
127
- }
@@ -1,33 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
- import { SqliteSchemaGenerator } from './sqliteSchemaGenerator.js';
3
-
4
- describe('SqliteSchemaGenerator Specifics', () => {
5
- const generator = new SqliteSchemaGenerator();
6
-
7
- it('should map column types correctly', () => {
8
- expect(generator.getSqlType({ columnType: 'varchar', length: 100 }, String)).toBe('TEXT');
9
- expect(generator.getSqlType({ columnType: 'int' }, Number)).toBe('INTEGER');
10
- expect(generator.getSqlType({ type: Boolean }, Boolean)).toBe('INTEGER');
11
- });
12
-
13
- it('should throw error on generateAlterColumnStatements', () => {
14
- const col = {
15
- name: 'age',
16
- type: 'INTEGER',
17
- nullable: false,
18
- isPrimaryKey: false,
19
- isAutoIncrement: false,
20
- isUnique: false,
21
- };
22
- expect(() => generator.generateAlterColumnStatements('users', col, 'INTEGER')).toThrow(
23
- 'SQLite does not support altering column',
24
- );
25
- });
26
-
27
- it('should format default values correctly', () => {
28
- expect(generator.formatDefaultValue('test')).toBe("'test'");
29
- expect(generator.formatDefaultValue(123)).toBe('123');
30
- expect(generator.formatDefaultValue(true)).toBe('1');
31
- expect(generator.formatDefaultValue(false)).toBe('0');
32
- });
33
- });
@@ -1,81 +0,0 @@
1
- import type { ColumnSchema, ColumnType, FieldOptions } from '../../type/index.js';
2
- import { AbstractSchemaGenerator } from '../schemaGenerator.js';
3
-
4
- /**
5
- * SQLite-specific schema generator
6
- */
7
- export class SqliteSchemaGenerator extends AbstractSchemaGenerator {
8
- protected readonly serialPrimaryKeyType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
9
-
10
- public override mapColumnType(columnType: ColumnType, field: FieldOptions): string {
11
- // SQLite has dynamic typing, but we use type affinity
12
- switch (columnType) {
13
- case 'int':
14
- case 'smallint':
15
- case 'bigint':
16
- case 'serial':
17
- case 'bigserial':
18
- return 'INTEGER';
19
- case 'float':
20
- case 'double':
21
- case 'real':
22
- case 'decimal':
23
- case 'numeric':
24
- return 'REAL';
25
- case 'boolean':
26
- return 'INTEGER'; // SQLite uses 0/1 for booleans
27
- case 'char':
28
- case 'varchar':
29
- case 'text':
30
- case 'uuid':
31
- return 'TEXT';
32
- case 'date':
33
- case 'time':
34
- case 'timestamp':
35
- case 'timestamptz':
36
- return 'TEXT'; // SQLite stores dates as TEXT or INTEGER
37
- case 'json':
38
- case 'jsonb':
39
- return 'TEXT'; // SQLite stores JSON as TEXT
40
- case 'blob':
41
- case 'bytea':
42
- return 'BLOB';
43
- case 'vector':
44
- return 'TEXT'; // Store as JSON array
45
- default:
46
- return 'TEXT';
47
- }
48
- }
49
-
50
- public override getBooleanType(): string {
51
- return 'INTEGER';
52
- }
53
-
54
- public override generateAlterColumnStatements(
55
- tableName: string,
56
- column: ColumnSchema,
57
- newDefinition: string,
58
- ): string[] {
59
- // SQLite has very limited ALTER TABLE support
60
- // Column type changes require recreating the table
61
- throw new Error(
62
- `SQLite does not support altering column '${column.name}' in table '${tableName}'. ` +
63
- 'You need to recreate the table to change column types.',
64
- );
65
- }
66
-
67
- public override generateColumnComment(tableName: string, columnName: string, comment: string): string {
68
- return '';
69
- }
70
-
71
- override generateDropIndex(tableName: string, indexName: string): string {
72
- return `DROP INDEX IF EXISTS ${this.escapeId(indexName)};`;
73
- }
74
-
75
- override formatDefaultValue(value: unknown): string {
76
- if (typeof value === 'boolean') {
77
- return value ? '1' : '0';
78
- }
79
- return super.formatDefaultValue(value);
80
- }
81
- }
@@ -1,41 +0,0 @@
1
- // Core types
2
-
3
- // Re-export core types for convenience
4
- // Migration-specific types
5
- export type {
6
- ColumnSchema,
7
- Dialect,
8
- ForeignKeySchema,
9
- IndexSchema,
10
- Migration,
11
- MigrationDefinition,
12
- MigrationResult,
13
- MigrationStorage,
14
- MigratorOptions,
15
- MongoQuerier,
16
- SchemaDiff,
17
- SchemaGenerator,
18
- SchemaIntrospector,
19
- SqlDialect,
20
- SqlQuerier,
21
- SqlQueryDialect,
22
- TableSchema,
23
- } from '../type/index.js';
24
- export { isSqlQuerier } from '../type/index.js';
25
- export {
26
- MysqlSchemaGenerator,
27
- MysqlSchemaGenerator as MariadbSchemaGenerator,
28
- } from './generator/mysqlSchemaGenerator.js';
29
- export { PostgresSchemaGenerator } from './generator/postgresSchemaGenerator.js';
30
- export { SqliteSchemaGenerator } from './generator/sqliteSchemaGenerator.js';
31
- // Schema introspection
32
- export { MariadbSchemaIntrospector, MysqlSchemaIntrospector } from './introspection/mysqlIntrospector.js';
33
- export { PostgresSchemaIntrospector } from './introspection/postgresIntrospector.js';
34
- export { SqliteSchemaIntrospector } from './introspection/sqliteIntrospector.js';
35
- // Main migrator
36
- export { defineMigration, Migrator } from './migrator.js';
37
- // Schema generators
38
- export { AbstractSchemaGenerator } from './schemaGenerator.js';
39
- // Storage implementations
40
- export { DatabaseMigrationStorage } from './storage/databaseStorage.js';
41
- export { JsonMigrationStorage } from './storage/jsonStorage.js';
@@ -1,4 +0,0 @@
1
- export * from './mongoIntrospector.js';
2
- export { MariadbSchemaIntrospector, MysqlSchemaIntrospector } from './mysqlIntrospector.js';
3
- export * from './postgresIntrospector.js';
4
- export * from './sqliteIntrospector.js';