forj 0.1.3 → 0.1.5
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/package.json +1 -1
- package/src/migrations/blueprint.ts +1 -2
- package/src/migrations/builder.ts +18 -18
- package/src/migrations/schema.ts +47 -31
- package/src/utils.ts +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import pluralize from 'pluralize'
|
|
2
2
|
import Column from './column'
|
|
3
3
|
import ForeignKey from './foreign-key'
|
|
4
|
-
import { tableName } from '../utils'
|
|
5
4
|
import type {
|
|
6
5
|
ColumnDefinition, IndexDefinition, ForeignKeyDefinition,
|
|
7
6
|
} from './types'
|
|
@@ -15,7 +14,7 @@ export class Blueprint {
|
|
|
15
14
|
#renameColumns: Map<string, string> = new Map()
|
|
16
15
|
|
|
17
16
|
constructor(table: string) {
|
|
18
|
-
this.#table =
|
|
17
|
+
this.#table = table
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
#column(definition: ColumnDefinition) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Blueprint } from './blueprint'
|
|
2
|
-
import {
|
|
2
|
+
import { sqlName, tableSlug } from '../utils'
|
|
3
3
|
import type { ColumnDefinition, IndexDefinition, ForeignKeyDefinition } from './types'
|
|
4
4
|
|
|
5
5
|
export default class SchemaBuilder {
|
|
6
6
|
static create(blueprint: Blueprint, exist: boolean = false): string {
|
|
7
|
-
const table = blueprint.table
|
|
7
|
+
const table = sqlName(blueprint.table)
|
|
8
8
|
const columns = blueprint.columns
|
|
9
9
|
const indexes = blueprint.indexes
|
|
10
10
|
const foreignKeys = blueprint.foreignKeys
|
|
@@ -23,7 +23,7 @@ export default class SchemaBuilder {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
static alter(blueprint: Blueprint): string[] {
|
|
26
|
-
const table = blueprint.table
|
|
26
|
+
const table = sqlName(blueprint.table)
|
|
27
27
|
const statements: string[] = []
|
|
28
28
|
|
|
29
29
|
const columns = blueprint.columns
|
|
@@ -31,10 +31,10 @@ export default class SchemaBuilder {
|
|
|
31
31
|
columns.forEach(col => statements.push(`ALTER TABLE ${table} ADD COLUMN ${this.#column(col)};`))
|
|
32
32
|
|
|
33
33
|
const dropColumns = blueprint.dropColumns
|
|
34
|
-
dropColumns.forEach(col => statements.push(`ALTER TABLE ${table} DROP COLUMN ${col};`))
|
|
34
|
+
dropColumns.forEach(col => statements.push(`ALTER TABLE ${table} DROP COLUMN ${sqlName(col)};`))
|
|
35
35
|
|
|
36
36
|
const renameColumns = blueprint.renameColumns
|
|
37
|
-
renameColumns.forEach((newName, oldName) => statements.push(`ALTER TABLE ${table} RENAME COLUMN ${oldName} TO ${newName};`))
|
|
37
|
+
renameColumns.forEach((newName, oldName) => statements.push(`ALTER TABLE ${table} RENAME COLUMN ${sqlName(oldName)} TO ${sqlName(newName)};`))
|
|
38
38
|
|
|
39
39
|
const indexes = blueprint.indexes
|
|
40
40
|
indexes.forEach(idx => {
|
|
@@ -49,7 +49,7 @@ export default class SchemaBuilder {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
static #column(column: ColumnDefinition) {
|
|
52
|
-
let sql = `${column.name} ${column.type}`
|
|
52
|
+
let sql = `${sqlName(column.name)} ${column.type}`
|
|
53
53
|
|
|
54
54
|
if (column.length && !column.type.includes('('))
|
|
55
55
|
sql += `(${column.length})`
|
|
@@ -99,8 +99,8 @@ export default class SchemaBuilder {
|
|
|
99
99
|
|
|
100
100
|
static #index(index: IndexDefinition, table: string): string {
|
|
101
101
|
const indexName = index.name || tableSlug(table) +`_${index.columns.join('_')}_${index.type}`
|
|
102
|
-
const columns = index.columns.join(', ')
|
|
103
|
-
table =
|
|
102
|
+
const columns = index.columns.map(column => sqlName(column)).join(', ')
|
|
103
|
+
table = sqlName(table)
|
|
104
104
|
|
|
105
105
|
switch (index.type) {
|
|
106
106
|
case 'primary':
|
|
@@ -116,8 +116,8 @@ export default class SchemaBuilder {
|
|
|
116
116
|
|
|
117
117
|
static #indexStatement(index: IndexDefinition, table: string): string {
|
|
118
118
|
const indexName = index.name || tableSlug(table) +`_${index.columns.join('_')}_${index.type}`
|
|
119
|
-
const columns = index.columns.join(', ')
|
|
120
|
-
table =
|
|
119
|
+
const columns = index.columns.map(column => sqlName(column)).join(', ')
|
|
120
|
+
table = sqlName(table)
|
|
121
121
|
|
|
122
122
|
switch (index.type) {
|
|
123
123
|
case 'primary':
|
|
@@ -132,7 +132,7 @@ export default class SchemaBuilder {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
static #foreignKey(fk: ColumnDefinition | ForeignKeyDefinition, column: boolean = false): string {
|
|
135
|
-
let sql = (column ? '' : `FOREIGN KEY (${fk.name})`) +` REFERENCES ${fk.on}(${fk.references})`
|
|
135
|
+
let sql = (column ? '' : `FOREIGN KEY (${sqlName(fk.name)})`) +` REFERENCES ${sqlName(fk.on)}(${sqlName(fk.references)})`
|
|
136
136
|
|
|
137
137
|
if (fk.onDelete)
|
|
138
138
|
sql += ` ON DELETE ${fk.onDelete.toUpperCase()}`
|
|
@@ -144,7 +144,7 @@ export default class SchemaBuilder {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
static drop(table: string, exist: boolean = false) {
|
|
147
|
-
return `DROP TABLE ${exist ? 'IF EXISTS ' : ''}${
|
|
147
|
+
return `DROP TABLE ${exist ? 'IF EXISTS ' : ''}${sqlName(table)};`
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
static dropIfExists(table: string) {
|
|
@@ -152,7 +152,7 @@ export default class SchemaBuilder {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
static dropView(view: string, exist: boolean = false) {
|
|
155
|
-
return `DROP VIEW ${exist ? 'IF EXISTS ' : ''}[${
|
|
155
|
+
return `DROP VIEW ${exist ? 'IF EXISTS ' : ''}[${sqlName(view)}];`
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
static dropViewIfExists(view: string) {
|
|
@@ -160,15 +160,15 @@ export default class SchemaBuilder {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
static rename(from: string, to: string) {
|
|
163
|
-
return `ALTER TABLE ${
|
|
163
|
+
return `ALTER TABLE ${sqlName(from)} RENAME TO ${sqlName(to)};`
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
static hasTable(table: string) {
|
|
167
|
-
return `SELECT name FROM sqlite_master WHERE type='table' AND name='${
|
|
167
|
+
return `SELECT name FROM sqlite_master WHERE type='table' AND name='${sqlName(table)}';`
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
static hasColumn(table: string, columnName: string) { // TODO refactor..
|
|
171
|
-
return `PRAGMA table_info(${
|
|
171
|
+
return `PRAGMA table_info(${sqlName(table)});`
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
static getAllTables() {
|
|
@@ -176,10 +176,10 @@ export default class SchemaBuilder {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
static getColumns(table: string): string {
|
|
179
|
-
return `PRAGMA table_info(${
|
|
179
|
+
return `PRAGMA table_info(${sqlName(table)});`
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
static dropAllTables(tables: string[]) {
|
|
183
|
-
return tables.map(table => `DROP TABLE IF EXISTS ${
|
|
183
|
+
return tables.map(table => `DROP TABLE IF EXISTS ${sqlName(table)};`)
|
|
184
184
|
}
|
|
185
185
|
}
|
package/src/migrations/schema.ts
CHANGED
|
@@ -31,7 +31,7 @@ export class Schema {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// mudei tudo this.#executeSql -> this.#addStatement
|
|
34
|
-
// static
|
|
34
|
+
// static #executeSql(...sql: string[] | string[][]) {
|
|
35
35
|
// sql = sql.flat(Infinity) as string[]
|
|
36
36
|
// // if (this.#c) {
|
|
37
37
|
// // for (const statement of sql) {
|
|
@@ -41,50 +41,66 @@ export class Schema {
|
|
|
41
41
|
// this.#addStatement(...sql)
|
|
42
42
|
// }
|
|
43
43
|
|
|
44
|
-
static
|
|
44
|
+
static #blueprint(table: string, ...fns: BlueprintFn[]) {
|
|
45
45
|
const blueprint = new Blueprint(table)
|
|
46
|
-
fn(blueprint)
|
|
47
|
-
|
|
46
|
+
fns.flatMap(fn => fn && fn(blueprint))
|
|
47
|
+
return blueprint
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
static
|
|
50
|
+
static create(table: string, fn: BlueprintFn, exist: boolean = false) {
|
|
51
|
+
this.#addStatement(Builder.create(this.#blueprint(table, fn), exist))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static createIfNotExists(table: string, fn: BlueprintFn) {
|
|
51
55
|
this.create(table, fn, true)
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
static
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
static createPivot(table: string, fn: BlueprintFn): void
|
|
59
|
+
static createPivot(table: string, columns: string[]): void
|
|
60
|
+
static createPivot(table: string, columns: string[], fn: BlueprintFn): void
|
|
61
|
+
static createPivot(table: string, columns: string[] | BlueprintFn, fn?: BlueprintFn) {
|
|
62
|
+
const hasColumn = Array.isArray(columns)
|
|
63
|
+
columns = hasColumn ? columns as string[] : [] // @ts-ignore
|
|
64
|
+
fn = hasColumn ? fn : columns
|
|
65
|
+
|
|
66
|
+
this.#addStatement(Builder.create(this.#blueprint(table, fn as BlueprintFn, (table: Blueprint) => {
|
|
67
|
+
columns.forEach(column => table.foreignId(column))
|
|
68
|
+
table.primary(table.columns.map(c => c.name))
|
|
69
|
+
})).slice(0, -1) + ' WITHOUT ROWID;')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static table(table: string, fn: BlueprintFn) {
|
|
73
|
+
this.#addStatement(Builder.alter(this.#blueprint(table, fn)))
|
|
58
74
|
}
|
|
59
75
|
|
|
60
|
-
static
|
|
61
|
-
|
|
76
|
+
static drop(table: string) {
|
|
77
|
+
this.#addStatement(Builder.drop(table))
|
|
62
78
|
}
|
|
63
79
|
|
|
64
|
-
static
|
|
65
|
-
|
|
80
|
+
static dropIfExists(table: string) {
|
|
81
|
+
this.#addStatement(Builder.dropIfExists(table))
|
|
66
82
|
}
|
|
67
83
|
|
|
68
|
-
static
|
|
69
|
-
|
|
84
|
+
static rename(from: string, to: string) {
|
|
85
|
+
this.#addStatement(Builder.rename(from, to))
|
|
70
86
|
}
|
|
71
87
|
|
|
72
|
-
static
|
|
73
|
-
|
|
88
|
+
static dropView(view: string) {
|
|
89
|
+
this.#addStatement(Builder.dropView(view))
|
|
74
90
|
}
|
|
75
91
|
|
|
76
|
-
static
|
|
77
|
-
|
|
92
|
+
static dropViewIfExists(view: string) {
|
|
93
|
+
this.#addStatement(Builder.dropViewIfExists(view))
|
|
78
94
|
}
|
|
79
95
|
|
|
80
|
-
static
|
|
96
|
+
static disableForeignKeyConstraints() {
|
|
81
97
|
this.#foreignKeyConstraintsEnabled = false
|
|
82
|
-
|
|
98
|
+
this.#addStatement('PRAGMA foreign_keys = OFF;')
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
static
|
|
101
|
+
static enableForeignKeyConstraints() {
|
|
86
102
|
this.#foreignKeyConstraintsEnabled = true
|
|
87
|
-
|
|
103
|
+
this.#addStatement('PRAGMA foreign_keys = ON;')
|
|
88
104
|
}
|
|
89
105
|
|
|
90
106
|
static isForeignKeyConstraintsEnabled(): boolean {
|
|
@@ -98,13 +114,13 @@ export class Schema {
|
|
|
98
114
|
return this.sql
|
|
99
115
|
}
|
|
100
116
|
|
|
101
|
-
// static
|
|
117
|
+
// static dropAllTables() {
|
|
102
118
|
// const tables = await this.getAllTables()
|
|
103
119
|
// const sql = Builder.dropAllTables(tables)
|
|
104
|
-
//
|
|
120
|
+
// this.#addStatement(sql)
|
|
105
121
|
// }
|
|
106
122
|
|
|
107
|
-
// static
|
|
123
|
+
// static hasTable(table: string): Promise<boolean> {
|
|
108
124
|
// if (!this.#c)
|
|
109
125
|
// throw new Error('Database connection not set')
|
|
110
126
|
|
|
@@ -113,7 +129,7 @@ export class Schema {
|
|
|
113
129
|
// return result.length > 0
|
|
114
130
|
// }
|
|
115
131
|
|
|
116
|
-
// static
|
|
132
|
+
// static hasColumn(table: string, columnName: string): Promise<boolean> {
|
|
117
133
|
// if (!this.#c)
|
|
118
134
|
// throw new Error('Database connection not set')
|
|
119
135
|
|
|
@@ -122,7 +138,7 @@ export class Schema {
|
|
|
122
138
|
// return result.some((row: any) => row.name === columnName)
|
|
123
139
|
// }
|
|
124
140
|
|
|
125
|
-
// static
|
|
141
|
+
// static hasColumns(table: string, ...columnNames: string[]): Promise<boolean> {
|
|
126
142
|
// if (!this.#c)
|
|
127
143
|
// throw new Error('Database connection not set')
|
|
128
144
|
|
|
@@ -133,7 +149,7 @@ export class Schema {
|
|
|
133
149
|
// return columnNames.every(col => existingColumns.includes(col))
|
|
134
150
|
// }
|
|
135
151
|
|
|
136
|
-
// static
|
|
152
|
+
// static getAllTables(): Promise<string[]> {
|
|
137
153
|
// if (!this.#c)
|
|
138
154
|
// throw new Error('Database connection not set')
|
|
139
155
|
|
|
@@ -142,7 +158,7 @@ export class Schema {
|
|
|
142
158
|
// return result.map((row: any) => row.name)
|
|
143
159
|
// }
|
|
144
160
|
|
|
145
|
-
// static
|
|
161
|
+
// static getColumns(table: string): Promise<any[]> {
|
|
146
162
|
// if (!this.#c)
|
|
147
163
|
// throw new Error('Database connection not set')
|
|
148
164
|
|
|
@@ -150,7 +166,7 @@ export class Schema {
|
|
|
150
166
|
// return await this.#c.query(sql)
|
|
151
167
|
// }
|
|
152
168
|
|
|
153
|
-
// static
|
|
169
|
+
// static getColumnType(table: string, columnName: string): Promise<string | null> {
|
|
154
170
|
// if (!this.#c) {
|
|
155
171
|
// throw new Error('Database connection not set')
|
|
156
172
|
// }
|
package/src/utils.ts
CHANGED
|
@@ -153,7 +153,7 @@ export const SQLITE_KEYWORDS = new Set([
|
|
|
153
153
|
'WHERE', 'WINDOW', 'WITH', 'WITHOUT',
|
|
154
154
|
])
|
|
155
155
|
|
|
156
|
-
export function
|
|
156
|
+
export function sqlName(name?: string) {
|
|
157
157
|
return !name
|
|
158
158
|
|| !name.match(/^[a-zA-Z_]/)
|
|
159
159
|
|| name.match(/\W/)
|