bun-query-builder 0.1.5 → 0.1.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.
- package/dist/actions/benchmark.d.ts +9 -5
- package/dist/actions/cache.d.ts +2 -14
- package/dist/actions/console.d.ts +0 -6
- package/dist/actions/data.d.ts +3 -13
- package/dist/actions/db-info.d.ts +4 -9
- package/dist/actions/db-optimize.d.ts +4 -5
- package/dist/actions/db-wipe.d.ts +4 -5
- package/dist/actions/file.d.ts +2 -1
- package/dist/actions/index.d.ts +25 -25
- package/dist/actions/inspect.d.ts +3 -9
- package/dist/actions/introspect.d.ts +2 -1
- package/dist/actions/make-model.d.ts +3 -5
- package/dist/actions/migrate-generate.d.ts +4 -5
- package/dist/actions/migrate-rollback.d.ts +4 -11
- package/dist/actions/migrate-status.d.ts +5 -9
- package/dist/actions/migrate.d.ts +13 -21
- package/dist/actions/model-show.d.ts +3 -5
- package/dist/actions/query-explain-all.d.ts +3 -5
- package/dist/actions/relation-diagram.d.ts +5 -5
- package/dist/actions/seed.d.ts +7 -17
- package/dist/actions/sql.d.ts +2 -1
- package/dist/actions/unsafe.d.ts +2 -1
- package/dist/actions/validate.d.ts +4 -9
- package/dist/actions/wait-ready.d.ts +2 -1
- package/dist/client.d.ts +199 -189
- package/dist/config.d.ts +2 -1
- package/dist/db.d.ts +8 -9
- package/dist/drivers/index.d.ts +8 -6
- package/dist/drivers/mysql.d.ts +169 -19
- package/dist/drivers/postgres.d.ts +155 -19
- package/dist/drivers/sqlite.d.ts +157 -19
- package/dist/factory.d.ts +3 -6
- package/dist/index.d.ts +11 -11
- package/dist/index.js +3502 -299
- package/dist/loader.d.ts +3 -2
- package/dist/meta.d.ts +3 -2
- package/dist/migrations.d.ts +42 -47
- package/dist/schema.d.ts +30 -177
- package/dist/seeder.d.ts +12 -17
- package/dist/types.d.ts +42 -143
- package/package.json +5 -4
package/dist/drivers/mysql.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColumnPlan, IndexPlan, TablePlan } from '../migrations';
|
|
2
|
+
|
|
2
3
|
export declare interface DialectDriver {
|
|
3
4
|
createEnumType: (enumTypeName: string, values: string[]) => string
|
|
4
5
|
createTable: (table: TablePlan) => string
|
|
@@ -15,23 +16,172 @@ export declare interface DialectDriver {
|
|
|
15
16
|
recordMigrationQuery: () => string
|
|
16
17
|
}
|
|
17
18
|
export declare class MySQLDriver implements DialectDriver {
|
|
18
|
-
private quoteIdentifier(id: string): string
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
private quoteIdentifier(id: string): string {
|
|
20
|
+
return `\`${id}\``
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private getColumnType(column: ColumnPlan): string {
|
|
24
|
+
switch (column.type) {
|
|
25
|
+
case 'string': return 'varchar(255)'
|
|
26
|
+
case 'text': return 'text'
|
|
27
|
+
case 'boolean': return 'tinyint(1)'
|
|
28
|
+
case 'integer': return 'integer'
|
|
29
|
+
case 'bigint': return 'bigint'
|
|
30
|
+
case 'float': return 'real'
|
|
31
|
+
case 'double': return 'double precision'
|
|
32
|
+
case 'decimal': return 'decimal(10,2)'
|
|
33
|
+
case 'date': return 'date'
|
|
34
|
+
case 'datetime': return 'datetime'
|
|
35
|
+
case 'json': return 'json'
|
|
36
|
+
case 'enum':
|
|
37
|
+
if (column.enumValues && column.enumValues.length > 0) {
|
|
38
|
+
const enumValues = column.enumValues.map(v => `'${v.replace(/'/g, '\'\'')}'`).join(', ')
|
|
39
|
+
return `ENUM(${enumValues})`
|
|
40
|
+
}
|
|
41
|
+
return 'text'
|
|
42
|
+
default: return 'text'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private getPrimaryKeyType(column: ColumnPlan): string {
|
|
47
|
+
return this.getColumnType(column)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private getAutoIncrementClause(column: ColumnPlan): string {
|
|
51
|
+
if (column.isPrimaryKey && (column.type === 'integer' || column.type === 'bigint')) {
|
|
52
|
+
return 'auto_increment'
|
|
53
|
+
}
|
|
54
|
+
return ''
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private getDefaultValue(column: ColumnPlan): string {
|
|
58
|
+
if (!column.hasDefault || column.defaultValue === undefined) {
|
|
59
|
+
return ''
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const dv = column.defaultValue
|
|
63
|
+
if (typeof dv === 'string') {
|
|
64
|
+
return `default '${dv.replace(/'/g, '\'\'')}'`
|
|
65
|
+
}
|
|
66
|
+
else if (typeof dv === 'number' || typeof dv === 'bigint') {
|
|
67
|
+
return `default ${dv}`
|
|
68
|
+
}
|
|
69
|
+
else if (typeof dv === 'boolean') {
|
|
70
|
+
return `default ${dv ? 1 : 0}`
|
|
71
|
+
}
|
|
72
|
+
else if (dv instanceof Date) {
|
|
73
|
+
return `default '${dv.toISOString()}'`
|
|
74
|
+
}
|
|
75
|
+
return ''
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createEnumType(_enumTypeName: string, _values: string[]): string {
|
|
79
|
+
return ''
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
createTable(table: TablePlan): string {
|
|
83
|
+
const columns = table.columns.map(c => this.renderColumn(c)).join(',\n ')
|
|
84
|
+
return `CREATE TABLE ${this.quoteIdentifier(table.table)} (\n ${columns}\n);`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
createIndex(tableName: string, index: IndexPlan): string {
|
|
88
|
+
const kind = index.type === 'unique' ? 'UNIQUE ' : ''
|
|
89
|
+
const idxName = `${tableName}_${index.name}`
|
|
90
|
+
const columns = index.columns.map(c => this.quoteIdentifier(c)).join(', ')
|
|
91
|
+
return `CREATE ${kind}INDEX ${this.quoteIdentifier(idxName)} ON ${this.quoteIdentifier(tableName)} (${columns});`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
addForeignKey(tableName: string, columnName: string, refTable: string, refColumn: string): string {
|
|
95
|
+
const fkName = `${tableName}_${columnName}_fk`
|
|
96
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD CONSTRAINT ${this.quoteIdentifier(fkName)} FOREIGN KEY (${this.quoteIdentifier(columnName)}) REFERENCES ${this.quoteIdentifier(refTable)}(${this.quoteIdentifier(refColumn)});`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
addColumn(tableName: string, column: ColumnPlan): string {
|
|
100
|
+
const typeSql = this.getColumnType(column)
|
|
101
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
102
|
+
|
|
103
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
104
|
+
parts.push('not null')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const defaultValue = this.getDefaultValue(column)
|
|
108
|
+
if (defaultValue) {
|
|
109
|
+
parts.push(defaultValue)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD COLUMN ${parts.join(' ')};`
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
modifyColumn(tableName: string, column: ColumnPlan): string {
|
|
116
|
+
const typeSql = this.getColumnType(column)
|
|
117
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
118
|
+
|
|
119
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
120
|
+
parts.push('not null')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const defaultValue = this.getDefaultValue(column)
|
|
124
|
+
if (defaultValue) {
|
|
125
|
+
parts.push(defaultValue)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} MODIFY COLUMN ${parts.join(' ')};`
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
dropTable(tableName: string): string {
|
|
132
|
+
return `DROP TABLE IF EXISTS ${this.quoteIdentifier(tableName)}`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
dropColumn(tableName: string, columnName: string): string {
|
|
136
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} DROP COLUMN ${this.quoteIdentifier(columnName)};`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
dropIndex(tableName: string, indexName: string): string {
|
|
140
|
+
const fullIndexName = `${tableName}_${indexName}`
|
|
141
|
+
return `DROP INDEX ${this.quoteIdentifier(fullIndexName)} ON ${this.quoteIdentifier(tableName)};`
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
dropEnumType(_enumTypeName: string): string {
|
|
145
|
+
return ''
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
createMigrationsTable(): string {
|
|
149
|
+
return `CREATE TABLE IF NOT EXISTS migrations (
|
|
150
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
151
|
+
migration VARCHAR(255) NOT NULL UNIQUE,
|
|
152
|
+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
153
|
+
)`
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getExecutedMigrationsQuery(): string {
|
|
157
|
+
return 'SELECT migration FROM migrations ORDER BY executed_at'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
recordMigrationQuery(): string {
|
|
161
|
+
return 'INSERT INTO migrations (migration) VALUES (?)'
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private renderColumn(column: ColumnPlan): string {
|
|
165
|
+
const typeSql = this.getColumnType(column)
|
|
166
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
167
|
+
|
|
168
|
+
if (column.isPrimaryKey) {
|
|
169
|
+
parts.push('PRIMARY KEY')
|
|
170
|
+
const autoIncrement = this.getAutoIncrementClause(column)
|
|
171
|
+
if (autoIncrement) {
|
|
172
|
+
parts.push(autoIncrement)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
177
|
+
parts.push('not null')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const defaultValue = this.getDefaultValue(column)
|
|
181
|
+
if (defaultValue) {
|
|
182
|
+
parts.push(defaultValue)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return parts.join(' ')
|
|
186
|
+
}
|
|
37
187
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColumnPlan, IndexPlan, TablePlan } from '../migrations';
|
|
2
|
+
|
|
2
3
|
export declare interface DialectDriver {
|
|
3
4
|
createEnumType: (enumTypeName: string, values: string[]) => string
|
|
4
5
|
createTable: (table: TablePlan) => string
|
|
@@ -15,23 +16,158 @@ export declare interface DialectDriver {
|
|
|
15
16
|
recordMigrationQuery: () => string
|
|
16
17
|
}
|
|
17
18
|
export declare class PostgresDriver implements DialectDriver {
|
|
18
|
-
private quoteIdentifier(id: string): string
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
private quoteIdentifier(id: string): string {
|
|
20
|
+
return `"${id}"`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private getColumnType(column: ColumnPlan): string {
|
|
24
|
+
switch (column.type) {
|
|
25
|
+
case 'string': return 'varchar(255)'
|
|
26
|
+
case 'text': return 'text'
|
|
27
|
+
case 'boolean': return 'boolean'
|
|
28
|
+
case 'integer': return 'integer'
|
|
29
|
+
case 'bigint': return 'bigint'
|
|
30
|
+
case 'float': return 'real'
|
|
31
|
+
case 'double': return 'double precision'
|
|
32
|
+
case 'decimal': return 'decimal(10,2)'
|
|
33
|
+
case 'date': return 'date'
|
|
34
|
+
case 'datetime': return 'timestamp'
|
|
35
|
+
case 'json': return 'jsonb'
|
|
36
|
+
case 'enum':
|
|
37
|
+
if (column.enumValues && column.enumValues.length > 0) {
|
|
38
|
+
return `${column.name}_type`
|
|
39
|
+
}
|
|
40
|
+
return 'text'
|
|
41
|
+
default: return 'text'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private getPrimaryKeyType(column: ColumnPlan): string {
|
|
46
|
+
switch (column.type) {
|
|
47
|
+
case 'integer': return 'SERIAL'
|
|
48
|
+
case 'bigint': return 'BIGSERIAL'
|
|
49
|
+
default: return this.getColumnType(column)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private getAutoIncrementClause(_column: ColumnPlan): string {
|
|
54
|
+
return ''
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private getDefaultValue(column: ColumnPlan): string {
|
|
58
|
+
if (!column.hasDefault || column.defaultValue === undefined) {
|
|
59
|
+
return ''
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const dv = column.defaultValue
|
|
63
|
+
if (typeof dv === 'string') {
|
|
64
|
+
return `default '${dv.replace(/'/g, '\'\'')}'`
|
|
65
|
+
}
|
|
66
|
+
else if (typeof dv === 'number' || typeof dv === 'bigint') {
|
|
67
|
+
return `default ${dv}`
|
|
68
|
+
}
|
|
69
|
+
else if (typeof dv === 'boolean') {
|
|
70
|
+
return `default ${dv ? 'true' : 'false'}`
|
|
71
|
+
}
|
|
72
|
+
else if (dv instanceof Date) {
|
|
73
|
+
return `default '${dv.toISOString()}'`
|
|
74
|
+
}
|
|
75
|
+
return ''
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createEnumType(enumTypeName: string, values: string[]): string {
|
|
79
|
+
const enumValues = values.map(v => `'${v.replace(/'/g, '\'\'')}'`).join(', ')
|
|
80
|
+
return `CREATE TYPE ${this.quoteIdentifier(enumTypeName)} AS ENUM (${enumValues});`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
createTable(table: TablePlan): string {
|
|
84
|
+
const columns = table.columns.map(c => this.renderColumn(c)).join(',\n ')
|
|
85
|
+
return `CREATE TABLE ${this.quoteIdentifier(table.table)} (\n ${columns}\n);`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
createIndex(tableName: string, index: IndexPlan): string {
|
|
89
|
+
const kind = index.type === 'unique' ? 'UNIQUE ' : ''
|
|
90
|
+
const idxName = `${tableName}_${index.name}`
|
|
91
|
+
const columns = index.columns.map(c => this.quoteIdentifier(c)).join(', ')
|
|
92
|
+
return `CREATE ${kind}INDEX ${this.quoteIdentifier(idxName)} ON ${this.quoteIdentifier(tableName)} (${columns});`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
addForeignKey(tableName: string, columnName: string, refTable: string, refColumn: string): string {
|
|
96
|
+
const fkName = `${tableName}_${columnName}_fk`
|
|
97
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD CONSTRAINT ${this.quoteIdentifier(fkName)} FOREIGN KEY (${this.quoteIdentifier(columnName)}) REFERENCES ${this.quoteIdentifier(refTable)}(${this.quoteIdentifier(refColumn)});`
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
addColumn(tableName: string, column: ColumnPlan): string {
|
|
101
|
+
const typeSql = this.getColumnType(column)
|
|
102
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
103
|
+
|
|
104
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
105
|
+
parts.push('not null')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const defaultValue = this.getDefaultValue(column)
|
|
109
|
+
if (defaultValue) {
|
|
110
|
+
parts.push(defaultValue)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD COLUMN ${parts.join(' ')};`
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
modifyColumn(tableName: string, column: ColumnPlan): string {
|
|
117
|
+
const typeSql = this.getColumnType(column)
|
|
118
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ALTER COLUMN ${this.quoteIdentifier(column.name)} TYPE ${typeSql} USING ${this.quoteIdentifier(column.name)}::${typeSql};`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
dropTable(tableName: string): string {
|
|
122
|
+
return `DROP TABLE IF EXISTS ${this.quoteIdentifier(tableName)} CASCADE`
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
dropColumn(tableName: string, columnName: string): string {
|
|
126
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} DROP COLUMN ${this.quoteIdentifier(columnName)};`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
dropIndex(tableName: string, indexName: string): string {
|
|
130
|
+
const fullIndexName = `${tableName}_${indexName}`
|
|
131
|
+
return `DROP INDEX IF EXISTS ${this.quoteIdentifier(fullIndexName)};`
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
dropEnumType(enumTypeName: string): string {
|
|
135
|
+
return `DROP TYPE IF EXISTS ${this.quoteIdentifier(enumTypeName)} CASCADE`
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
createMigrationsTable(): string {
|
|
139
|
+
return `CREATE TABLE IF NOT EXISTS migrations (
|
|
140
|
+
id SERIAL PRIMARY KEY,
|
|
141
|
+
migration VARCHAR(255) NOT NULL UNIQUE,
|
|
142
|
+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
143
|
+
)`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
getExecutedMigrationsQuery(): string {
|
|
147
|
+
return 'SELECT migration FROM migrations ORDER BY executed_at'
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
recordMigrationQuery(): string {
|
|
151
|
+
return 'INSERT INTO migrations (migration) VALUES ($1)'
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private renderColumn(column: ColumnPlan): string {
|
|
155
|
+
const typeSql = column.isPrimaryKey ? this.getPrimaryKeyType(column) : this.getColumnType(column)
|
|
156
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
157
|
+
|
|
158
|
+
if (column.isPrimaryKey) {
|
|
159
|
+
parts.push('PRIMARY KEY')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
163
|
+
parts.push('not null')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const defaultValue = this.getDefaultValue(column)
|
|
167
|
+
if (defaultValue) {
|
|
168
|
+
parts.push(defaultValue)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return parts.join(' ')
|
|
172
|
+
}
|
|
37
173
|
}
|
package/dist/drivers/sqlite.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColumnPlan, IndexPlan, TablePlan } from '../migrations';
|
|
2
|
+
|
|
2
3
|
export declare interface DialectDriver {
|
|
3
4
|
createEnumType: (enumTypeName: string, values: string[]) => string
|
|
4
5
|
createTable: (table: TablePlan) => string
|
|
@@ -15,23 +16,160 @@ export declare interface DialectDriver {
|
|
|
15
16
|
recordMigrationQuery: () => string
|
|
16
17
|
}
|
|
17
18
|
export declare class SQLiteDriver implements DialectDriver {
|
|
18
|
-
private quoteIdentifier(id: string): string
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
private quoteIdentifier(id: string): string {
|
|
20
|
+
return `"${id}"`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private getColumnType(column: ColumnPlan): string {
|
|
24
|
+
switch (column.type) {
|
|
25
|
+
case 'string': return 'TEXT'
|
|
26
|
+
case 'text': return 'TEXT'
|
|
27
|
+
case 'boolean': return 'INTEGER'
|
|
28
|
+
case 'integer': return 'INTEGER'
|
|
29
|
+
case 'bigint': return 'INTEGER'
|
|
30
|
+
case 'float': return 'REAL'
|
|
31
|
+
case 'double': return 'REAL'
|
|
32
|
+
case 'decimal': return 'REAL'
|
|
33
|
+
case 'date': return 'TEXT'
|
|
34
|
+
case 'datetime': return 'TEXT'
|
|
35
|
+
case 'json': return 'TEXT'
|
|
36
|
+
case 'enum':
|
|
37
|
+
if (column.enumValues && column.enumValues.length > 0) {
|
|
38
|
+
const enumValues = column.enumValues.map(v => `'${v.replace(/'/g, '\'\'')}'`).join(', ')
|
|
39
|
+
return `TEXT CHECK (${this.quoteIdentifier(column.name)} IN (${enumValues}))`
|
|
40
|
+
}
|
|
41
|
+
return 'TEXT'
|
|
42
|
+
default: return 'TEXT'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private getPrimaryKeyType(column: ColumnPlan): string {
|
|
47
|
+
return this.getColumnType(column)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private getAutoIncrementClause(column: ColumnPlan): string {
|
|
51
|
+
if (column.isPrimaryKey && (column.type === 'integer' || column.type === 'bigint')) {
|
|
52
|
+
return 'AUTOINCREMENT'
|
|
53
|
+
}
|
|
54
|
+
return ''
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private getDefaultValue(column: ColumnPlan): string {
|
|
58
|
+
if (!column.hasDefault || column.defaultValue === undefined) {
|
|
59
|
+
return ''
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const dv = column.defaultValue
|
|
63
|
+
if (typeof dv === 'string') {
|
|
64
|
+
return `default '${dv.replace(/'/g, '\'\'')}'`
|
|
65
|
+
}
|
|
66
|
+
else if (typeof dv === 'number' || typeof dv === 'bigint') {
|
|
67
|
+
return `default ${dv}`
|
|
68
|
+
}
|
|
69
|
+
else if (typeof dv === 'boolean') {
|
|
70
|
+
return `default ${dv ? 1 : 0}`
|
|
71
|
+
}
|
|
72
|
+
else if (dv instanceof Date) {
|
|
73
|
+
return `default '${dv.toISOString()}'`
|
|
74
|
+
}
|
|
75
|
+
return ''
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createEnumType(_enumTypeName: string, _values: string[]): string {
|
|
79
|
+
return ''
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
createTable(table: TablePlan): string {
|
|
83
|
+
const columns = table.columns.map(c => this.renderColumn(c)).join(',\n ')
|
|
84
|
+
return `CREATE TABLE ${this.quoteIdentifier(table.table)} (\n ${columns}\n);`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
createIndex(tableName: string, index: IndexPlan): string {
|
|
88
|
+
const kind = index.type === 'unique' ? 'UNIQUE ' : ''
|
|
89
|
+
const idxName = `${tableName}_${index.name}`
|
|
90
|
+
const columns = index.columns.map(c => this.quoteIdentifier(c)).join(', ')
|
|
91
|
+
return `CREATE ${kind}INDEX ${this.quoteIdentifier(idxName)} ON ${this.quoteIdentifier(tableName)} (${columns});`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
addForeignKey(tableName: string, columnName: string, refTable: string, refColumn: string): string {
|
|
95
|
+
const fkName = `${tableName}_${columnName}_fk`
|
|
96
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD CONSTRAINT ${this.quoteIdentifier(fkName)} FOREIGN KEY (${this.quoteIdentifier(columnName)}) REFERENCES ${this.quoteIdentifier(refTable)}(${this.quoteIdentifier(refColumn)});`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
addColumn(tableName: string, column: ColumnPlan): string {
|
|
100
|
+
const typeSql = this.getColumnType(column)
|
|
101
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
102
|
+
|
|
103
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
104
|
+
parts.push('not null')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const defaultValue = this.getDefaultValue(column)
|
|
108
|
+
if (defaultValue) {
|
|
109
|
+
parts.push(defaultValue)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} ADD COLUMN ${parts.join(' ')};`
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
modifyColumn(tableName: string, column: ColumnPlan): string {
|
|
116
|
+
return `-- SQLite does not support ALTER COLUMN. Manual table recreation needed to change ${this.quoteIdentifier(tableName)}.${this.quoteIdentifier(column.name)} type`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
dropTable(tableName: string): string {
|
|
120
|
+
return `DROP TABLE IF EXISTS ${this.quoteIdentifier(tableName)}`
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
dropColumn(tableName: string, columnName: string): string {
|
|
124
|
+
return `ALTER TABLE ${this.quoteIdentifier(tableName)} DROP COLUMN ${this.quoteIdentifier(columnName)};`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
dropIndex(tableName: string, indexName: string): string {
|
|
128
|
+
const fullIndexName = `${tableName}_${indexName}`
|
|
129
|
+
return `DROP INDEX IF EXISTS ${this.quoteIdentifier(fullIndexName)};`
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
dropEnumType(_enumTypeName: string): string {
|
|
133
|
+
return ''
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
createMigrationsTable(): string {
|
|
137
|
+
return `CREATE TABLE IF NOT EXISTS migrations (
|
|
138
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
139
|
+
migration TEXT NOT NULL UNIQUE,
|
|
140
|
+
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
141
|
+
)`
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getExecutedMigrationsQuery(): string {
|
|
145
|
+
return 'SELECT migration FROM migrations ORDER BY executed_at'
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
recordMigrationQuery(): string {
|
|
149
|
+
return 'INSERT INTO migrations (migration) VALUES (?)'
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private renderColumn(column: ColumnPlan): string {
|
|
153
|
+
const typeSql = this.getColumnType(column)
|
|
154
|
+
const parts: string[] = [this.quoteIdentifier(column.name), typeSql]
|
|
155
|
+
|
|
156
|
+
if (column.isPrimaryKey) {
|
|
157
|
+
parts.push('PRIMARY KEY')
|
|
158
|
+
const autoIncrement = this.getAutoIncrementClause(column)
|
|
159
|
+
if (autoIncrement) {
|
|
160
|
+
parts.push(autoIncrement)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!column.isNullable && !column.isPrimaryKey) {
|
|
165
|
+
parts.push('not null')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const defaultValue = this.getDefaultValue(column)
|
|
169
|
+
if (defaultValue) {
|
|
170
|
+
parts.push(defaultValue)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return parts.join(' ')
|
|
174
|
+
}
|
|
37
175
|
}
|
package/dist/factory.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import type { DatabaseSchema, ModelRecord } from './schema';
|
|
2
|
-
|
|
3
|
-
export type BuildDatabaseSchema<MRecord extends ModelRecord> = DatabaseSchema<MRecord>
|
|
4
|
-
export
|
|
5
|
-
export type ColumnsOf<DB, TTable extends keyof DB & string> = DB[TTable] extends { columns: infer C }
|
|
6
|
-
? C
|
|
7
|
-
: never
|
|
2
|
+
|
|
3
|
+
export declare type BuildDatabaseSchema<MRecord extends ModelRecord> = DatabaseSchema<MRecord>
|
|
4
|
+
export declare function buildDatabaseSchema<MRecord extends ModelRecord>(models: MRecord): BuildDatabaseSchema<MRecord>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export * from './actions'
|
|
2
|
-
export * from './client'
|
|
3
|
-
export * from './config'
|
|
4
|
-
export * from './drivers'
|
|
5
|
-
export * from './factory'
|
|
6
|
-
export * from './loader'
|
|
7
|
-
export * from './meta'
|
|
8
|
-
export * from './migrations'
|
|
9
|
-
export * from './schema'
|
|
10
|
-
export * from './seeder'
|
|
11
|
-
export * from './types'
|
|
1
|
+
export * from './actions'
|
|
2
|
+
export * from './client'
|
|
3
|
+
export * from './config'
|
|
4
|
+
export * from './drivers'
|
|
5
|
+
export * from './factory'
|
|
6
|
+
export * from './loader'
|
|
7
|
+
export * from './meta'
|
|
8
|
+
export * from './migrations'
|
|
9
|
+
export * from './schema'
|
|
10
|
+
export * from './seeder'
|
|
11
|
+
export * from './types'
|