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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "forj",
3
3
  "description": "SQLite ORM and Query Builder whitout dependencies",
4
- "version": "0.1.3",
4
+ "version": "0.1.5",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
7
7
  "files": ["src"],
@@ -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 = tableName(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 { tableName, tableSlug } from '../utils'
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 = tableName(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 = tableName(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 ' : ''}${tableName(table)};`
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 ' : ''}[${tableName(view)}];`
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 ${tableName(from)} RENAME TO ${tableName(to)};`
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='${tableName(table)}';`
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(${tableName(table)});`
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(${tableName(table)});`
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 ${tableName(table)};`)
183
+ return tables.map(table => `DROP TABLE IF EXISTS ${sqlName(table)};`)
184
184
  }
185
185
  }
@@ -31,7 +31,7 @@ export class Schema {
31
31
  }
32
32
 
33
33
  // mudei tudo this.#executeSql -> this.#addStatement
34
- // static async #executeSql(...sql: string[] | string[][]): Promise<void> {
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 async create(table: string, fn: BlueprintFn, exist: boolean = false): Promise<void> {
44
+ static #blueprint(table: string, ...fns: BlueprintFn[]) {
45
45
  const blueprint = new Blueprint(table)
46
- fn(blueprint)
47
- await this.#addStatement(Builder.create(blueprint, exist))
46
+ fns.flatMap(fn => fn && fn(blueprint))
47
+ return blueprint
48
48
  }
49
49
 
50
- static async createIfNotExists(table: string, fn: BlueprintFn): Promise<void> {
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 async table(table: string, fn: BlueprintFn): Promise<void> {
55
- const blueprint = new Blueprint(table)
56
- fn(blueprint)
57
- await this.#addStatement(Builder.alter(blueprint))
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 async drop(table: string): Promise<void> {
61
- await this.#addStatement(Builder.drop(table))
76
+ static drop(table: string) {
77
+ this.#addStatement(Builder.drop(table))
62
78
  }
63
79
 
64
- static async dropIfExists(table: string): Promise<void> {
65
- await this.#addStatement(Builder.dropIfExists(table))
80
+ static dropIfExists(table: string) {
81
+ this.#addStatement(Builder.dropIfExists(table))
66
82
  }
67
83
 
68
- static async rename(from: string, to: string): Promise<void> {
69
- await this.#addStatement(Builder.rename(from, to))
84
+ static rename(from: string, to: string) {
85
+ this.#addStatement(Builder.rename(from, to))
70
86
  }
71
87
 
72
- static async dropView(view: string): Promise<void> {
73
- await this.#addStatement(Builder.dropView(view))
88
+ static dropView(view: string) {
89
+ this.#addStatement(Builder.dropView(view))
74
90
  }
75
91
 
76
- static async dropViewIfExists(view: string): Promise<void> {
77
- await this.#addStatement(Builder.dropViewIfExists(view))
92
+ static dropViewIfExists(view: string) {
93
+ this.#addStatement(Builder.dropViewIfExists(view))
78
94
  }
79
95
 
80
- static async disableForeignKeyConstraints(): Promise<void> {
96
+ static disableForeignKeyConstraints() {
81
97
  this.#foreignKeyConstraintsEnabled = false
82
- await this.#addStatement('PRAGMA foreign_keys = OFF;')
98
+ this.#addStatement('PRAGMA foreign_keys = OFF;')
83
99
  }
84
100
 
85
- static async enableForeignKeyConstraints(): Promise<void> {
101
+ static enableForeignKeyConstraints() {
86
102
  this.#foreignKeyConstraintsEnabled = true
87
- await this.#addStatement('PRAGMA foreign_keys = ON;')
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 async dropAllTables(): Promise<void> {
117
+ // static dropAllTables() {
102
118
  // const tables = await this.getAllTables()
103
119
  // const sql = Builder.dropAllTables(tables)
104
- // await this.#addStatement(sql)
120
+ // this.#addStatement(sql)
105
121
  // }
106
122
 
107
- // static async hasTable(table: string): Promise<boolean> {
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 async hasColumn(table: string, columnName: string): Promise<boolean> {
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 async hasColumns(table: string, ...columnNames: string[]): Promise<boolean> {
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 async getAllTables(): Promise<string[]> {
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 async getColumns(table: string): Promise<any[]> {
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 async getColumnType(table: string, columnName: string): Promise<string | null> {
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 tableName(name: string) {
156
+ export function sqlName(name?: string) {
157
157
  return !name
158
158
  || !name.match(/^[a-zA-Z_]/)
159
159
  || name.match(/\W/)