forj 0.1.2 → 0.1.4

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.2",
4
+ "version": "0.1.4",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
7
7
  "files": ["src"],
@@ -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,65 @@ 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[], fn: BlueprintFn): void
60
+ static createPivot(table: string, columns: string[] | BlueprintFn, fn?: BlueprintFn) {
61
+ const hasColumn = Array.isArray(columns)
62
+ columns = hasColumn ? columns as string[] : [] // @ts-ignore
63
+ fn = hasColumn ? fn : columns
64
+
65
+ this.#addStatement(Builder.create(this.#blueprint(table, fn as BlueprintFn, (table: Blueprint) => {
66
+ columns.forEach(column => table.foreignId(column))
67
+ table.primary(table.columns.map(c => c.name))
68
+ })).slice(0, -1) + ' WITHOUT ROWID;')
69
+ }
70
+
71
+ static table(table: string, fn: BlueprintFn) {
72
+ this.#addStatement(Builder.alter(this.#blueprint(table, fn)))
58
73
  }
59
74
 
60
- static async drop(table: string): Promise<void> {
61
- await this.#addStatement(Builder.drop(table))
75
+ static drop(table: string) {
76
+ this.#addStatement(Builder.drop(table))
62
77
  }
63
78
 
64
- static async dropIfExists(table: string): Promise<void> {
65
- await this.#addStatement(Builder.dropIfExists(table))
79
+ static dropIfExists(table: string) {
80
+ this.#addStatement(Builder.dropIfExists(table))
66
81
  }
67
82
 
68
- static async rename(from: string, to: string): Promise<void> {
69
- await this.#addStatement(Builder.rename(from, to))
83
+ static rename(from: string, to: string) {
84
+ this.#addStatement(Builder.rename(from, to))
70
85
  }
71
86
 
72
- static async dropView(view: string): Promise<void> {
73
- await this.#addStatement(Builder.dropView(view))
87
+ static dropView(view: string) {
88
+ this.#addStatement(Builder.dropView(view))
74
89
  }
75
90
 
76
- static async dropViewIfExists(view: string): Promise<void> {
77
- await this.#addStatement(Builder.dropViewIfExists(view))
91
+ static dropViewIfExists(view: string) {
92
+ this.#addStatement(Builder.dropViewIfExists(view))
78
93
  }
79
94
 
80
- static async disableForeignKeyConstraints(): Promise<void> {
95
+ static disableForeignKeyConstraints() {
81
96
  this.#foreignKeyConstraintsEnabled = false
82
- await this.#addStatement('PRAGMA foreign_keys = OFF;')
97
+ this.#addStatement('PRAGMA foreign_keys = OFF;')
83
98
  }
84
99
 
85
- static async enableForeignKeyConstraints(): Promise<void> {
100
+ static enableForeignKeyConstraints() {
86
101
  this.#foreignKeyConstraintsEnabled = true
87
- await this.#addStatement('PRAGMA foreign_keys = ON;')
102
+ this.#addStatement('PRAGMA foreign_keys = ON;')
88
103
  }
89
104
 
90
105
  static isForeignKeyConstraintsEnabled(): boolean {
@@ -98,13 +113,13 @@ export class Schema {
98
113
  return this.sql
99
114
  }
100
115
 
101
- // static async dropAllTables(): Promise<void> {
116
+ // static dropAllTables() {
102
117
  // const tables = await this.getAllTables()
103
118
  // const sql = Builder.dropAllTables(tables)
104
- // await this.#addStatement(sql)
119
+ // this.#addStatement(sql)
105
120
  // }
106
121
 
107
- // static async hasTable(table: string): Promise<boolean> {
122
+ // static hasTable(table: string): Promise<boolean> {
108
123
  // if (!this.#c)
109
124
  // throw new Error('Database connection not set')
110
125
 
@@ -113,7 +128,7 @@ export class Schema {
113
128
  // return result.length > 0
114
129
  // }
115
130
 
116
- // static async hasColumn(table: string, columnName: string): Promise<boolean> {
131
+ // static hasColumn(table: string, columnName: string): Promise<boolean> {
117
132
  // if (!this.#c)
118
133
  // throw new Error('Database connection not set')
119
134
 
@@ -122,7 +137,7 @@ export class Schema {
122
137
  // return result.some((row: any) => row.name === columnName)
123
138
  // }
124
139
 
125
- // static async hasColumns(table: string, ...columnNames: string[]): Promise<boolean> {
140
+ // static hasColumns(table: string, ...columnNames: string[]): Promise<boolean> {
126
141
  // if (!this.#c)
127
142
  // throw new Error('Database connection not set')
128
143
 
@@ -133,7 +148,7 @@ export class Schema {
133
148
  // return columnNames.every(col => existingColumns.includes(col))
134
149
  // }
135
150
 
136
- // static async getAllTables(): Promise<string[]> {
151
+ // static getAllTables(): Promise<string[]> {
137
152
  // if (!this.#c)
138
153
  // throw new Error('Database connection not set')
139
154
 
@@ -142,7 +157,7 @@ export class Schema {
142
157
  // return result.map((row: any) => row.name)
143
158
  // }
144
159
 
145
- // static async getColumns(table: string): Promise<any[]> {
160
+ // static getColumns(table: string): Promise<any[]> {
146
161
  // if (!this.#c)
147
162
  // throw new Error('Database connection not set')
148
163
 
@@ -150,7 +165,7 @@ export class Schema {
150
165
  // return await this.#c.query(sql)
151
166
  // }
152
167
 
153
- // static async getColumnType(table: string, columnName: string): Promise<string | null> {
168
+ // static getColumnType(table: string, columnName: string): Promise<string | null> {
154
169
  // if (!this.#c) {
155
170
  // throw new Error('Database connection not set')
156
171
  // }
package/src/utils.ts CHANGED
@@ -132,41 +132,34 @@ export function isJoinCompare(val: any, schema?: DBSchema) {
132
132
  const keys = zGet(val, schema)
133
133
  return keys && keys?.length
134
134
  }
135
-
136
- const reservedWords = new Set([
137
- 'ABORT', 'ACTION', 'ADD', 'AFTER', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS',
138
- 'ASC', 'ATTACH', 'AUTOINCREMENT', 'BEFORE', 'BEGIN', 'BETWEEN', 'BY',
139
- 'CASCADE', 'CASE', 'CAST', 'CHECK', 'COLLATE', 'COLUMN', 'COMMIT',
140
- 'CONFLICT', 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT', 'CURRENT_DATE',
141
- 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'DATABASE', 'DEFAULT', 'DEFERRABLE',
142
- 'DEFERRED', 'DELETE', 'DESC', 'DETACH', 'DISTINCT', 'DROP', 'EACH',
143
- 'ELSE', 'END', 'ESCAPE', 'EXCEPT', 'EXCLUSIVE', 'EXISTS', 'EXPLAIN',
144
- 'FAIL', 'FOR', 'FOREIGN', 'FROM', 'FULL', 'GLOB', 'GROUP', 'HAVING',
145
- 'IF', 'IGNORE', 'IMMEDIATE', 'IN', 'INDEX', 'INDEXED', 'INITIALLY',
146
- 'INNER', 'INSERT', 'INSTEAD', 'INTERSECT', 'INTO', 'IS', 'ISNULL',
147
- 'JOIN', 'KEY', 'LEFT', 'LIKE', 'LIMIT', 'MATCH', 'NATURAL', 'NO',
148
- 'NOT', 'NOTNULL', 'NULL', 'OF', 'OFFSET', 'ON', 'OR', 'ORDER',
149
- 'OUTER', 'PLAN', 'PRAGMA', 'PRIMARY', 'QUERY', 'RAISE', 'RECURSIVE',
150
- 'REFERENCES', 'REGEXP', 'REINDEX', 'RELEASE', 'RENAME', 'REPLACE',
151
- 'RESTRICT', 'RIGHT', 'ROLLBACK', 'ROW', 'SAVEPOINT', 'SELECT',
152
- 'SET', 'TABLE', 'TEMP', 'TEMPORARY', 'THEN', 'TO', 'TRANSACTION',
153
- 'TRIGGER', 'UNION', 'UNIQUE', 'UPDATE', 'USING', 'VACUUM', 'VALUES',
154
- 'VIEW', 'VIRTUAL', 'WHEN', 'WHERE', 'WITH', 'WITHOUT',
135
+ // List taken from `aKeywordTable` in https://github.com/sqlite/sqlite/blob/378bf82e2bc09734b8c5869f9b148efe37d29527/tool/mkkeywordhash.c#L172
136
+ // prettier-ignore
137
+ export const SQLITE_KEYWORDS = new Set([
138
+ 'ABORT', 'ACTION', 'ADD', 'AFTER', 'ALL', 'ALTER', 'ALWAYS', 'ANALYZE', 'AND', 'AS', 'ASC',
139
+ 'ATTACH', 'AUTOINCREMENT', 'BEFORE', 'BEGIN', 'BETWEEN', 'BY', 'CASCADE', 'CASE', 'CAST',
140
+ 'CHECK', 'COLLATE', 'COLUMN', 'COMMIT', 'CONFLICT', 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT',
141
+ 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'DATABASE', 'DEFAULT', 'DEFERRED',
142
+ 'DEFERRABLE', 'DELETE', 'DESC', 'DETACH', 'DISTINCT', 'DO', 'DROP', 'END', 'EACH', 'ELSE',
143
+ 'ESCAPE', 'EXCEPT', 'EXCLUSIVE', 'EXCLUDE', 'EXISTS', 'EXPLAIN', 'FAIL', 'FILTER', 'FIRST',
144
+ 'FOLLOWING', 'FOR', 'FOREIGN', 'FROM', 'FULL', 'GENERATED', 'GLOB', 'GROUP', 'GROUPS', 'HAVING',
145
+ 'IF', 'IGNORE', 'IMMEDIATE', 'IN', 'INDEX', 'INDEXED', 'INITIALLY', 'INNER', 'INSERT', 'INSTEAD',
146
+ 'INTERSECT', 'INTO', 'IS', 'ISNULL', 'JOIN', 'KEY', 'LAST', 'LEFT', 'LIKE', 'LIMIT', 'MATCH',
147
+ 'MATERIALIZED', 'NATURAL', 'NO', 'NOT', 'NOTHING', 'NOTNULL', 'NULL', 'NULLS', 'OF', 'OFFSET',
148
+ 'ON', 'OR', 'ORDER', 'OTHERS', 'OUTER', 'OVER', 'PARTITION', 'PLAN', 'PRAGMA', 'PRECEDING',
149
+ 'PRIMARY', 'QUERY', 'RAISE', 'RANGE', 'RECURSIVE', 'REFERENCES', 'REGEXP', 'REINDEX', 'RELEASE',
150
+ 'RENAME', 'REPLACE', 'RESTRICT', 'RETURNING', 'RIGHT', 'ROLLBACK', 'ROW', 'ROWS', 'SAVEPOINT',
151
+ 'SELECT', 'SET', 'TABLE', 'TEMP', 'TEMPORARY', 'THEN', 'TIES', 'TO', 'TRANSACTION', 'TRIGGER',
152
+ 'UNBOUNDED', 'UNION', 'UNIQUE', 'UPDATE', 'USING', 'VACUUM', 'VALUES', 'VIEW', 'VIRTUAL', 'WHEN',
153
+ 'WHERE', 'WINDOW', 'WITH', 'WITHOUT',
155
154
  ])
156
- export function tableName(name: string) {
157
- name = name.trim()
158
- if (!name || name?.includes('.'))
159
- throw new Error(`Invalid table name "${!name ? 'empty' : name}"`)
160
-
161
- if (
162
- /^[0-9]/.test(name)
163
- || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)
164
- || reservedWords.has(name.toUpperCase())
165
- ) {
166
- return `"${name}"`
167
- }
168
155
 
169
- return name
156
+ export function tableName(name: string) {
157
+ return !name
158
+ || !name.match(/^[a-zA-Z_]/)
159
+ || name.match(/\W/)
160
+ || SQLITE_KEYWORDS.has(name.toUpperCase())
161
+ ? `"${name}"`
162
+ : name
170
163
  }
171
164
 
172
165
  export function tableSlug(name: string) {