velocious 1.0.96 → 1.0.98

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 (86) hide show
  1. package/eslint.config.js +1 -0
  2. package/package.json +2 -1
  3. package/spec/database/connection/drivers/mysql/query-parser-spec.js +4 -4
  4. package/spec/http-server/post-spec.js +2 -0
  5. package/src/application.js +27 -9
  6. package/src/configuration-resolver.js +29 -10
  7. package/src/configuration-types.js +44 -0
  8. package/src/configuration.js +63 -33
  9. package/src/database/drivers/base-column.js +6 -1
  10. package/src/database/drivers/base-columns-index.js +11 -1
  11. package/src/database/drivers/base-foreign-key.js +45 -0
  12. package/src/database/drivers/base-table.js +24 -2
  13. package/src/database/drivers/base.js +211 -39
  14. package/src/database/drivers/mssql/index.js +1 -3
  15. package/src/database/drivers/sqlite/sql/alter-table.js +4 -2
  16. package/src/database/handler.js +5 -0
  17. package/src/database/migration/index.js +77 -19
  18. package/src/database/migrator/files-finder.js +21 -22
  19. package/src/database/migrator/types.js +29 -0
  20. package/src/database/migrator.js +98 -59
  21. package/src/database/pool/async-tracked-multi-connection.js +42 -7
  22. package/src/database/pool/base-methods-forward.js +37 -0
  23. package/src/database/pool/base.js +79 -46
  24. package/src/database/pool/single-multi-use.js +18 -3
  25. package/src/database/query/alter-table-base.js +4 -4
  26. package/src/database/query/base.js +9 -2
  27. package/src/database/query/create-database-base.js +8 -0
  28. package/src/database/query/create-index-base.js +20 -5
  29. package/src/database/query/create-table-base.js +28 -9
  30. package/src/database/query/from-base.js +17 -0
  31. package/src/database/query/from-plain.js +8 -3
  32. package/src/database/query/from-table.js +8 -3
  33. package/src/database/query/index.js +43 -32
  34. package/src/database/query/join-base.js +28 -1
  35. package/src/database/query/join-object.js +67 -0
  36. package/src/database/query/join-plain.js +6 -1
  37. package/src/database/query/order-base.js +18 -0
  38. package/src/database/query/order-plain.js +8 -2
  39. package/src/database/query/select-base.js +15 -0
  40. package/src/database/query/select-plain.js +6 -1
  41. package/src/database/query/select-table-and-column.js +8 -2
  42. package/src/database/query/where-base.js +23 -1
  43. package/src/database/query/where-hash.js +15 -0
  44. package/src/database/query/where-plain.js +6 -0
  45. package/src/database/query-parser/base-query-parser.js +8 -2
  46. package/src/database/query-parser/from-parser.js +2 -0
  47. package/src/database/query-parser/joins-parser.js +10 -45
  48. package/src/database/query-parser/select-parser.js +2 -0
  49. package/src/database/record/index.js +1 -1
  50. package/src/database/table-data/index.js +39 -121
  51. package/src/database/table-data/table-column.js +54 -25
  52. package/src/database/table-data/table-foreign-key.js +5 -3
  53. package/src/database/table-data/table-index.js +12 -6
  54. package/src/database/table-data/table-reference.js +2 -0
  55. package/src/database/use-database.js +4 -2
  56. package/src/environment-handlers/base.js +41 -8
  57. package/src/environment-handlers/node/cli/commands/destroy/migration.js +3 -0
  58. package/src/environment-handlers/node/cli/commands/generate/migration.js +3 -0
  59. package/src/environment-handlers/node/cli/commands/generate/model.js +3 -0
  60. package/src/environment-handlers/node/cli/commands/init.js +3 -0
  61. package/src/environment-handlers/node/cli/commands/test.js +17 -3
  62. package/src/environment-handlers/node.js +59 -28
  63. package/src/http-client/header.js +6 -0
  64. package/src/http-client/request.js +31 -5
  65. package/src/http-client/response.js +31 -7
  66. package/src/http-server/client/index.js +24 -4
  67. package/src/http-server/client/request-buffer/form-data-part.js +11 -0
  68. package/src/http-server/client/request-buffer/header.js +6 -0
  69. package/src/http-server/client/request-buffer/index.js +91 -13
  70. package/src/http-server/client/request-parser.js +26 -0
  71. package/src/http-server/client/request-runner.js +15 -3
  72. package/src/http-server/client/request.js +17 -0
  73. package/src/http-server/client/response.js +41 -1
  74. package/src/http-server/index.js +32 -4
  75. package/src/http-server/server-client.js +33 -2
  76. package/src/http-server/worker-handler/index.js +42 -9
  77. package/src/http-server/worker-handler/worker-script.js +2 -0
  78. package/src/http-server/worker-handler/worker-thread.js +34 -6
  79. package/src/logger.js +21 -15
  80. package/src/routes/app-routes.js +1 -1
  81. package/src/testing/test-files-finder.js +96 -9
  82. package/src/testing/test-runner.js +77 -25
  83. package/src/utils/backtrace-cleaner.js +6 -4
  84. package/src/utils/ensure-error.js +13 -0
  85. package/src/utils/file-exists.js +3 -1
  86. package/src/utils/rest-args-error.js +2 -0
@@ -1,3 +1,37 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {object} CreateIndexSqlArgs
5
+ * @property {Array<string | import("./../table-data/table-column.js").default>} columns
6
+ * @property {boolean} [ifNotExists]
7
+ * @property {string} [name]
8
+ * @property {boolean} [unique]
9
+ * @property {string} tableName
10
+ */
11
+ /**
12
+ * @typedef {object} DropTableSqlArgsType
13
+ * @property {boolean} [cascade]
14
+ * @property {boolean} [ifExists]
15
+ */
16
+ /**
17
+ * @typedef {object} DeleteSqlArgsType
18
+ * @property {string} tableName
19
+ * @property {{[key: string]: any}} conditions
20
+ */
21
+ /**
22
+ * @typedef {object} InsertSqlArgsType
23
+ * @property {string[]} [columns]
24
+ * @property {{[key: string]: any}} [data]
25
+ * @property {boolean} [multiple]
26
+ * @property {boolean} [returnLastInsertedColumnNames]
27
+ * @property {Array<Array<any>>} [rows]
28
+ * @property {string} tableName
29
+ */
30
+ /**
31
+ * @typedef {Record<string, any>} QueryRowType
32
+ * @typedef {Array<QueryRowType>} QueryResultType
33
+ */
34
+
1
35
  import {Logger} from "../../logger.js"
2
36
  import Query from "../query/index.js"
3
37
  import Handler from "../handler.js"
@@ -10,6 +44,9 @@ import TableForeignKey from "../table-data/table-foreign-key.js"
10
44
  import wait from "awaitery/src/wait.js"
11
45
 
12
46
  export default class VelociousDatabaseDriversBase {
47
+ /** @type {number | undefined} */
48
+ idSeq = undefined
49
+
13
50
  /**
14
51
  * @param {object} config
15
52
  * @param {import("../../configuration.js").default} configuration
@@ -55,18 +92,36 @@ export default class VelociousDatabaseDriversBase {
55
92
 
56
93
  /**
57
94
  * @interface
95
+ * @param {import("../table-data/index.js").default} _tableData
58
96
  * @returns {Promise<string[]>}
59
97
  */
60
- alterTableSql() {
98
+ alterTableSql(_tableData) { // eslint-disable-line no-unused-vars
61
99
  throw new Error("alterTableSql not implemented")
62
100
  }
63
101
 
64
102
  /**
65
- * @param {...Parameters<this["createTableSql"]>} args
66
- * @returns {void}
103
+ * @interface
104
+ * @returns {Promise<void>}
105
+ */
106
+ connect() {
107
+ throw new Error("'connect' not implemented")
108
+ }
109
+
110
+ /**
111
+ * @interface
112
+ * @param {CreateIndexSqlArgs} indexData
113
+ * @returns {string}
114
+ */
115
+ createIndexSql(indexData) { // eslint-disable-line no-unused-vars
116
+ throw new Error("'createIndexSql' not implemented")
117
+ }
118
+
119
+ /**
120
+ * @param {import("../table-data/index.js").default} tableData
121
+ * @returns {Promise<void>}
67
122
  */
68
- async createTable(...args) {
69
- const sqls = this.createTableSql(...args)
123
+ async createTable(tableData) {
124
+ const sqls = this.createTableSql(tableData)
70
125
 
71
126
  for (const sql of sqls) {
72
127
  await this.query(sql)
@@ -74,21 +129,40 @@ export default class VelociousDatabaseDriversBase {
74
129
  }
75
130
 
76
131
  /**
77
- * @param {...Parameters<this["deleteSql"]>} args
78
- * @returns {void}
132
+ * @interface
133
+ * @param {import("../table-data/index.js").default} tableData
134
+ * @returns {string[]}
79
135
  */
80
- async delete(...args) {
81
- const sql = this.deleteSql(...args)
136
+ createTableSql(tableData) { // eslint-disable-line no-unused-vars
137
+ throw new Error("'createTableSql' not implemented")
138
+ }
139
+
140
+ /**
141
+ * @param {DeleteSqlArgsType} args
142
+ * @returns {Promise<void>}
143
+ */
144
+ async delete(args) {
145
+ const sql = this.deleteSql(args)
82
146
 
83
147
  await this.query(sql)
84
148
  }
85
149
 
86
150
  /**
87
- * @param {...Parameters<this['dropTableSql']>} args
88
- * @returns {void}
151
+ * @interface
152
+ * @param {DeleteSqlArgsType} args
153
+ * @returns {string}
89
154
  */
90
- async dropTable(...args) {
91
- const sqls = this.dropTableSql(...args)
155
+ deleteSql(args) { // eslint-disable-line no-unused-vars
156
+ throw new Error(`'deleteSql' not implemented`)
157
+ }
158
+
159
+ /**
160
+ * @param {string} tableName
161
+ * @param {DropTableSqlArgsType} [args]
162
+ * @returns {Promise<void>}
163
+ */
164
+ async dropTable(tableName, args) {
165
+ const sqls = this.dropTableSql(tableName, args)
92
166
 
93
167
  for (const sql of sqls) {
94
168
  await this.query(sql)
@@ -97,16 +171,23 @@ export default class VelociousDatabaseDriversBase {
97
171
 
98
172
  /**
99
173
  * @interface
100
- * @param {string} _tableName
101
- * @param {object} _args
102
- * @param {boolean} _args.cascade
103
- * @param {boolean} _args.ifExists
174
+ * @param {string} tableName
175
+ * @param {DropTableSqlArgsType} [args]
104
176
  * @returns {string}
105
177
  */
106
- dropTableSql(_tableName, _args) { // eslint-disable-line no-unused-vars
178
+ dropTableSql(tableName, args) { // eslint-disable-line no-unused-vars
107
179
  throw new Error("dropTableSql not implemented")
108
180
  }
109
181
 
182
+ /**
183
+ * @interface
184
+ * @param {any} value
185
+ * @returns {any}
186
+ */
187
+ escape(value) { // eslint-disable-line no-unused-vars
188
+ throw new Error("'escape' not implemented")
189
+ }
190
+
110
191
  /**
111
192
  * @returns {object}
112
193
  */
@@ -124,7 +205,7 @@ export default class VelociousDatabaseDriversBase {
124
205
  }
125
206
 
126
207
  /**
127
- * @returns {number}
208
+ * @returns {number | undefined}
128
209
  */
129
210
  getIdSeq() {
130
211
  return this.idSeq
@@ -138,6 +219,12 @@ export default class VelociousDatabaseDriversBase {
138
219
  throw new Error(`${this.constructor.name}#getTables not implemented`)
139
220
  }
140
221
 
222
+ /**
223
+ * @param {string} name
224
+ * @param {object} [args]
225
+ * @param {boolean} args.throwError
226
+ * @returns {Promise<import("./base-table.js").default | undefined>}
227
+ */
141
228
  async getTableByName(name, args) {
142
229
  const tables = await this.getTables()
143
230
  const table = tables.find((table) => table.getName() == name)
@@ -148,21 +235,32 @@ export default class VelociousDatabaseDriversBase {
148
235
  }
149
236
 
150
237
  /**
151
- * @param {object} args
152
- * @param {Array} args.columns
153
- * @param {object} args.data
154
- * @param {boolean} args.multiple
155
- * @param {boolean} args.returnLastInsertedColumnNames
156
- * @param {Array} args.rows
157
- * @param {string} args.tableName
238
+ * @interface
239
+ * @returns {string}
240
+ */
241
+ getType() {
242
+ throw new Error("'type' not implemented")
243
+ }
244
+
245
+ /**
246
+ * @param {InsertSqlArgsType} args
158
247
  * @returns {Promise<void>}
159
248
  */
160
- async insert(...args) {
161
- const sql = this.insertSql(...args)
249
+ async insert(args) {
250
+ const sql = this.insertSql(args)
162
251
 
163
252
  await this.query(sql)
164
253
  }
165
254
 
255
+ /**
256
+ * @interface
257
+ * @param {InsertSqlArgsType} args
258
+ * @returns {string}
259
+ */
260
+ insertSql(args) { // eslint-disable-line no-unused-vars
261
+ throw new Error("'insertSql' not implemented")
262
+ }
263
+
166
264
  /**
167
265
  * @interface
168
266
  * @returns {Promise<number>}
@@ -171,6 +269,10 @@ export default class VelociousDatabaseDriversBase {
171
269
  throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
172
270
  }
173
271
 
272
+ /**
273
+ * @param {any} value
274
+ * @returns {any}
275
+ */
174
276
  _convertValue(value) {
175
277
  if (value instanceof Date) {
176
278
  return strftime("%F %T.%L", value)
@@ -179,6 +281,14 @@ export default class VelociousDatabaseDriversBase {
179
281
  return value
180
282
  }
181
283
 
284
+ /**
285
+ * @interface
286
+ * @returns {import("../query-parser/options.js").default}
287
+ */
288
+ options() {
289
+ throw new Error("'options' not implemented.")
290
+ }
291
+
182
292
  /**
183
293
  * @param {string} value
184
294
  * @returns {string}
@@ -230,7 +340,7 @@ export default class VelociousDatabaseDriversBase {
230
340
 
231
341
  /**
232
342
  * @param {string} tableName
233
- * @returns {Promise<Array>}
343
+ * @returns {Promise<QueryResultType>}
234
344
  */
235
345
  async select(tableName) {
236
346
  const query = this.newQuery()
@@ -243,13 +353,21 @@ export default class VelociousDatabaseDriversBase {
243
353
  }
244
354
 
245
355
  /**
246
- * @param {number} newIdSeq
356
+ * @param {number | undefined} newIdSeq
247
357
  * @returns {void}
248
358
  */
249
359
  setIdSeq(newIdSeq) {
250
360
  this.idSeq = newIdSeq
251
361
  }
252
362
 
363
+ /**
364
+ * @interface
365
+ * @returns {boolean}
366
+ */
367
+ shouldSetAutoIncrementWhenPrimaryKey() {
368
+ throw new Error(`'shouldSetAutoIncrementWhenPrimaryKey' not implemented`)
369
+ }
370
+
253
371
  /**
254
372
  * @param {string} tableName
255
373
  * @returns {Promise<boolean>}
@@ -263,6 +381,10 @@ export default class VelociousDatabaseDriversBase {
263
381
  return false
264
382
  }
265
383
 
384
+ /**
385
+ * @param {() => Promise<void>} callback
386
+ * @returns {Promise<any>}
387
+ */
266
388
  async transaction(callback) {
267
389
  const savePointName = this.generateSavePointName()
268
390
  let transactionStarted = false
@@ -293,7 +415,11 @@ export default class VelociousDatabaseDriversBase {
293
415
  await this.commitTransaction()
294
416
  }
295
417
  } catch (error) {
296
- this.logger.debug("Transaction error", error.message)
418
+ if (error instanceof Error) {
419
+ this.logger.debug("Transaction error", error.message)
420
+ } else {
421
+ this.logger.debug("Transaction error", error)
422
+ }
297
423
 
298
424
  if (savePointStarted) {
299
425
  this.logger.debug("Rollback savepoint", savePointName)
@@ -347,7 +473,7 @@ export default class VelociousDatabaseDriversBase {
347
473
 
348
474
  /**
349
475
  * @param {string} sql
350
- * @returns {Promise<Array<Record<string, any>>>}
476
+ * @returns {Promise<QueryResultType>}
351
477
  */
352
478
  async query(sql) {
353
479
  let tries = 0
@@ -358,7 +484,7 @@ export default class VelociousDatabaseDriversBase {
358
484
  try {
359
485
  return await this._queryActual(sql)
360
486
  } catch (error) {
361
- if (tries < 5 && this.retryableDatabaseError(error)) {
487
+ if (error instanceof Error && tries < 5 && this.retryableDatabaseError(error)) {
362
488
  await wait(100)
363
489
  this.logger.warn(`Retrying query because failed with: ${error.stack}`)
364
490
  // Retry
@@ -367,8 +493,26 @@ export default class VelociousDatabaseDriversBase {
367
493
  }
368
494
  }
369
495
  }
496
+
497
+ throw new Error("'query' unexpected came here")
370
498
  }
371
499
 
500
+ /**
501
+ * @interface
502
+ * @param {string} sql
503
+ * @returns {Promise<QueryResultType>}
504
+ */
505
+ _queryActual(sql) { // eslint-disable-line no-unused-vars
506
+ throw new Error(`queryActual not implemented`)
507
+ }
508
+
509
+ /**
510
+ * @interface
511
+ * @param {Query} _query
512
+ * @returns {string}
513
+ */
514
+ queryToSql(_query) { throw new Error("queryToSql not implemented") } // eslint-disable-line no-unused-vars
515
+
372
516
  /**
373
517
  * @interface
374
518
  * @param {Error} _error
@@ -514,18 +658,46 @@ export default class VelociousDatabaseDriversBase {
514
658
  }
515
659
 
516
660
  /**
517
- * @param {object} args
518
- * @param {object} args.conditions
519
- * @param {object} args.data
520
- * @param {string} args.tableName
661
+ * @typedef {object}UpdateSqlArgsType
662
+ * @property {object} conditions
663
+ * @property {object} data
664
+ * @property {string} tableName
665
+ */
666
+ /**
667
+ * @param {UpdateSqlArgsType} args
521
668
  * @returns {Promise<void>}
522
669
  */
523
- async update(...args) {
524
- const sql = this.updateSql(...args)
670
+ async update(args) {
671
+ const sql = this.updateSql(args)
525
672
 
526
673
  await this.query(sql)
527
674
  }
528
675
 
676
+ /**
677
+ * @interface
678
+ * @param {UpdateSqlArgsType} args
679
+ * @returns {string}
680
+ */
681
+ updateSql(args) { // eslint-disable-line no-unused-vars
682
+ throw new Error("'disableForeignKeys' not implemented")
683
+ }
684
+
685
+ /**
686
+ * @interface
687
+ * @returns {Promise<void>}
688
+ */
689
+ disableForeignKeys() {
690
+ throw new Error("'disableForeignKeys' not implemented")
691
+ }
692
+
693
+ /**
694
+ * @interface
695
+ * @returns {Promise<void>}
696
+ */
697
+ enableForeignKeys() {
698
+ throw new Error("'enableForeignKeys' not implemented")
699
+ }
700
+
529
701
  /**
530
702
  * @param {function() : void} callback
531
703
  * @returns {Promise<any>}
@@ -202,9 +202,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
202
202
  }
203
203
 
204
204
  /**
205
- * @param {object} args
206
- * @param {string} args.tableName
207
- * @param {object} args.conditions
205
+ * @param {import("../base.js").DeleteSqlArgsType} args
208
206
  */
209
207
  deleteSql({tableName, conditions}) {
210
208
  const deleteInstruction = new Delete({conditions, driver: this, tableName})
@@ -136,9 +136,11 @@ export default class VelociousDatabaseConnectionDriversSqliteSqlAlterTable exten
136
136
  tableName,
137
137
  unique: actualTableIndex.getUnique()
138
138
  }
139
- const sql = new CreateIndexBase(createIndexArgs).toSql()
139
+ const createIndexSQLs = new CreateIndexBase(createIndexArgs).toSqls()
140
140
 
141
- sqls.push(sql)
141
+ for (const createIndexSQL of createIndexSQLs) {
142
+ sqls.push(createIndexSQL)
143
+ }
142
144
  }
143
145
 
144
146
  return sqls
@@ -1,4 +1,9 @@
1
+ // @ts-check
2
+
1
3
  export default class VelociousDatabaseHandler {
4
+ /**
5
+ * @returns {VelociousDatabaseHandler}
6
+ */
2
7
  clone() {
3
8
  const newHandler = new VelociousDatabaseHandler()
4
9
 
@@ -1,21 +1,40 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {object} AddColumnArgsType
5
+ * @property {any} default
6
+ * @property {object} foreignKey
7
+ * @property {boolean} nullable
8
+ * @property {boolean} primaryKey
9
+ * @property {boolean} unique
10
+ */
11
+
1
12
  import * as inflection from "inflection"
2
13
  import restArgsError from "../../utils/rest-args-error.js"
3
14
  import TableData from "../table-data/index.js"
15
+ class NotImplementedError extends Error {}
16
+
17
+ export {NotImplementedError}
4
18
 
5
19
  export default class VelociousDatabaseMigration {
20
+ /**
21
+ * @param {string[]} databaseIdentifiers
22
+ * @returns {void}
23
+ */
6
24
  static onDatabases(databaseIdentifiers) {
7
25
  this._databaseIdentifiers = databaseIdentifiers
8
26
  }
9
27
 
28
+ /** @returns {string[] | undefined} */
10
29
  static getDatabaseIdentifiers() {
11
30
  return this._databaseIdentifiers
12
31
  }
13
32
 
14
33
  /**
15
34
  * @param {object} args
16
- * @param {string} args.configuration
35
+ * @param {import("../../configuration.js").default} args.configuration
17
36
  * @param {string} args.databaseIdentifier
18
- * @param {object} args.db
37
+ * @param {import("../drivers/base.js").default} args.db
19
38
  */
20
39
  constructor({configuration, databaseIdentifier = "default", db}) {
21
40
  if (!databaseIdentifier) throw new Error("No database identifier given")
@@ -32,12 +51,25 @@ export default class VelociousDatabaseMigration {
32
51
  return this._databaseIdentifier
33
52
  }
34
53
 
54
+ /** @returns {import("../drivers/base.js").default} */
35
55
  getDriver() { return this._db }
36
56
  connection() { return this.getDriver() }
37
57
 
58
+ async change() {
59
+ throw new NotImplementedError("'change' not implemented")
60
+ }
61
+
62
+ async up() {
63
+ throw new NotImplementedError("'change' not implemented")
64
+ }
65
+
66
+ async down() {
67
+ throw new NotImplementedError("'change' not implemented")
68
+ }
69
+
38
70
  /**
39
71
  * @param {string} sql
40
- * @returns {Promise<Array>}
72
+ * @returns {Promise<import("../drivers/base.js").QueryResultType>}
41
73
  */
42
74
  async execute(sql) {
43
75
  return await this.connection().query(sql)
@@ -47,12 +79,7 @@ export default class VelociousDatabaseMigration {
47
79
  * @param {string} tableName
48
80
  * @param {string} columnName
49
81
  * @param {string} columnType
50
- * @param {object} args
51
- * @param {object} args.default
52
- * @param {object} args.foreignKey
53
- * @param {object} args.nullable
54
- * @param {object} args.primaryKey
55
- * @param {object} args.unique
82
+ * @param {AddColumnArgsType} [args]
56
83
  * @returns {Promise<void>}
57
84
  */
58
85
  async addColumn(tableName, columnName, columnType, args) {
@@ -88,13 +115,16 @@ export default class VelociousDatabaseMigration {
88
115
  }
89
116
  }
90
117
 
118
+ /**
119
+ * @typedef {object} AddIndexArgsType
120
+ * @property {boolean} [ifNotExists]
121
+ * @property {string} [name]
122
+ * @property {boolean} [unique]
123
+ */
91
124
  /**
92
125
  * @param {string} tableName
93
- * @param {Array} columns
94
- * @param {object} args
95
- * @param {boolean} args.ifNotExists
96
- * @param {string} args.name
97
- * @param {boolean} args.unique
126
+ * @param {Array<string | import("../table-data/table-column.js").default>} columns
127
+ * @param {AddIndexArgsType} [args]
98
128
  * @returns {Promise<void>}
99
129
  */
100
130
  async addIndex(tableName, columns, args) {
@@ -175,8 +205,13 @@ export default class VelociousDatabaseMigration {
175
205
  */
176
206
  async changeColumnNull(tableName, columnName, nullable) {
177
207
  const table = await this.getDriver().getTableByName(tableName)
208
+
209
+ if (!table) throw new Error(`Table ${tableName} does not exist`)
210
+
178
211
  const column = await table.getColumnByName(columnName)
179
212
 
213
+ if (!column) throw new Error(`Column ${columnName} does not exist in table ${tableName}`)
214
+
180
215
  await column.changeNullable(nullable)
181
216
  }
182
217
 
@@ -187,20 +222,34 @@ export default class VelociousDatabaseMigration {
187
222
  */
188
223
  async columnExists(tableName, columnName) {
189
224
  const table = await this.getDriver().getTableByName(tableName)
225
+
226
+ if (!table) throw new Error(`Table ${tableName} does not exist`)
227
+
190
228
  const column = await table.getColumnByName(columnName)
191
229
 
230
+ if (!column) throw new Error(`Column ${columnName} does not exist in table ${tableName}`)
231
+
192
232
  return Boolean(column)
193
233
  }
194
234
 
235
+ /**
236
+ * @typedef {object} CreateTableIdArgsType
237
+ * @property {any} [default]
238
+ * @property {string} [type]
239
+ */
240
+ /**
241
+ * @typedef {object} CreateTableArgsType
242
+ * @property {CreateTableIdArgsType | false} [id]
243
+ */
195
244
  /**
196
245
  * @param {string} tableName
197
- * @param {function() : void} arg1
246
+ * @param {function(TableData) : void} arg1
198
247
  * @returns {Promise<void>}
199
248
  */
200
249
  /**
201
250
  * @param {string} tableName
202
- * @param {object} arg1
203
- * @param {function() : void} arg2
251
+ * @param {CreateTableArgsType} arg1
252
+ * @param {function(TableData) : void} arg2
204
253
  * @returns {Promise<void>}
205
254
  */
206
255
  async createTable(tableName, arg1, arg2) {
@@ -218,7 +267,16 @@ export default class VelociousDatabaseMigration {
218
267
  const {id = {}, ...restArgs} = args
219
268
  const databaseIdentifier = this._getDatabaseIdentifier()
220
269
  const databasePool = this.configuration.getDatabasePool(databaseIdentifier)
221
- const {default: idDefault, type: idType = databasePool.primaryKeyType(), ...restArgsId} = id
270
+ let idDefault, idType, restArgsId
271
+
272
+ if (id !== false) {
273
+ ({default: idDefault, type: idType, ...restArgsId} = id)
274
+ }
275
+
276
+ if (!idType) {
277
+ idType = databasePool.primaryKeyType()
278
+ }
279
+
222
280
  const tableData = new TableData(tableName)
223
281
 
224
282
  restArgsError(restArgs)
@@ -227,7 +285,7 @@ export default class VelociousDatabaseMigration {
227
285
  if (!(idType in tableData)) throw new Error(`Unsupported primary key type: ${idType}`)
228
286
 
229
287
  if (id !== false) {
230
- tableData[idType]("id", {autoIncrement: true, default: idDefault, null: false, primaryKey: true})
288
+ tableData.addColumn("id", {autoIncrement: true, default: idDefault, null: false, primaryKey: true, type: idType})
231
289
  }
232
290
 
233
291
  if (callback) {
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import fs from "fs/promises"
2
4
  import * as inflection from "inflection"
3
5
 
@@ -17,36 +19,33 @@ export default class VelociousDatabaseMigratorFilesFinder {
17
19
  }
18
20
 
19
21
  /**
20
- * @returns {Promise<Array<{
21
- * file: string,
22
- * fullPath: string,
23
- * date: number,
24
- * migrationClassName: string
25
- * }>>}
22
+ * @returns {Promise<Array<import("./types.js").MigrationObjectType>>}
26
23
  */
27
24
  async findFiles() {
28
25
  let files = await fs.readdir(this.path)
29
26
 
30
- files = files
31
- .map((file) => {
32
- const match = file.match(/^(\d{14})-(.+)\.js$/)
27
+ /** @type {import("./types.js").MigrationObjectType[]} */
28
+ let result = []
29
+
30
+ for (const file of files) {
31
+ const match = file.match(/^(\d{14})-(.+)\.js$/)
33
32
 
34
- if (!match) return null
33
+ if (!match) continue
35
34
 
36
- const date = parseInt(match[1])
37
- const migrationName = match[2]
38
- const migrationClassName = inflection.camelize(migrationName.replaceAll("-", "_"))
35
+ const date = parseInt(match[1])
36
+ const migrationName = match[2]
37
+ const migrationClassName = inflection.camelize(migrationName.replaceAll("-", "_"))
39
38
 
40
- return {
41
- file,
42
- fullPath: `${this.path}/${file}`,
43
- date,
44
- migrationClassName
45
- }
39
+ result.push({
40
+ file,
41
+ fullPath: `${this.path}/${file}`,
42
+ date,
43
+ migrationClassName
46
44
  })
47
- .filter((migration) => Boolean(migration))
48
- .sort((migration1, migration2) => migration1.date - migration2.date)
45
+ }
46
+
47
+ result = result.sort((migration1, migration2) => migration1.date - migration2.date)
49
48
 
50
- return files
49
+ return result
51
50
  }
52
51
  }