velocious 1.0.93 → 1.0.94

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 (33) hide show
  1. package/package.json +1 -1
  2. package/src/application.js +19 -0
  3. package/src/cli/base-command.js +1 -0
  4. package/src/cli/commands/db/migrate.js +2 -0
  5. package/src/cli/commands/generate/base-models.js +7 -0
  6. package/src/cli/commands/generate/model.js +1 -1
  7. package/src/configuration-resolver.js +6 -3
  8. package/src/configuration.js +27 -4
  9. package/src/database/drivers/base-column.js +69 -0
  10. package/src/database/drivers/base-columns-index.js +19 -0
  11. package/src/database/drivers/base-foreign-key.js +12 -0
  12. package/src/database/drivers/base-table.js +32 -0
  13. package/src/database/drivers/base.js +125 -3
  14. package/src/database/migrator.js +17 -2
  15. package/src/database/query/drop-table-base.js +8 -0
  16. package/src/database/query/index.js +42 -0
  17. package/src/database/query-parser/from-parser.js +17 -6
  18. package/src/database/query-parser/group-parser.js +21 -8
  19. package/src/database/record/index.js +5 -0
  20. package/src/database/record/relationships/base.js +18 -3
  21. package/src/database/table-data/index.js +198 -6
  22. package/src/environment-handlers/base.js +58 -0
  23. package/src/environment-handlers/browser.js +0 -24
  24. package/src/environment-handlers/node/cli/commands/generate/base-models.js +80 -0
  25. package/src/environment-handlers/node.js +6 -1
  26. package/src/initializer.js +4 -0
  27. package/src/logger.js +54 -2
  28. package/src/routes/base-route.js +25 -4
  29. package/src/routes/get-route.js +3 -1
  30. package/src/routes/namespace-route.js +3 -1
  31. package/src/routes/post-route.js +3 -1
  32. package/src/routes/resource-route.js +3 -1
  33. package/src/utils/backtrace-cleaner.js +10 -0
@@ -10,6 +10,10 @@ import TableForeignKey from "../table-data/table-foreign-key.js"
10
10
  import wait from "awaitery/src/wait.js"
11
11
 
12
12
  export default class VelociousDatabaseDriversBase {
13
+ /**
14
+ * @param {object} config
15
+ * @param {import("../../configuration.js").default} configuration
16
+ */
13
17
  constructor(config, configuration) {
14
18
  this._args = config
15
19
  this.configuration = configuration
@@ -19,6 +23,14 @@ export default class VelociousDatabaseDriversBase {
19
23
  this._transactionsActionsMutex = new Mutex()
20
24
  }
21
25
 
26
+ /**
27
+ * @param {string} tableName
28
+ * @param {string} columnName
29
+ * @param {string} referencedTableName
30
+ * @param {string} referencedColumnName
31
+ * @param {object} args
32
+ * @returns {Promise<void>}
33
+ */
22
34
  async addForeignKey(tableName, columnName, referencedTableName, referencedColumnName, args) {
23
35
  const tableForeignKeyArgs = Object.assign(
24
36
  {
@@ -41,6 +53,18 @@ export default class VelociousDatabaseDriversBase {
41
53
  }
42
54
  }
43
55
 
56
+ /**
57
+ * @interface
58
+ * @returns {Promise<string[]>}
59
+ */
60
+ alterTableSql() {
61
+ throw new Error("alterTableSql not implemented")
62
+ }
63
+
64
+ /**
65
+ * @param {...Parameters<this["createTableSql"]>} args
66
+ * @returns {void}
67
+ */
44
68
  async createTable(...args) {
45
69
  const sqls = this.createTableSql(...args)
46
70
 
@@ -49,12 +73,20 @@ export default class VelociousDatabaseDriversBase {
49
73
  }
50
74
  }
51
75
 
76
+ /**
77
+ * @param {...Parameters<this["deleteSql"]>} args
78
+ * @returns {void}
79
+ */
52
80
  async delete(...args) {
53
81
  const sql = this.deleteSql(...args)
54
82
 
55
83
  await this.query(sql)
56
84
  }
57
85
 
86
+ /**
87
+ * @param {...Parameters<this['dropTableSql']>} args
88
+ * @returns {void}
89
+ */
58
90
  async dropTable(...args) {
59
91
  const sqls = this.dropTableSql(...args)
60
92
 
@@ -63,20 +95,45 @@ export default class VelociousDatabaseDriversBase {
63
95
  }
64
96
  }
65
97
 
98
+ /**
99
+ * @interface
100
+ * @param {string} _tableName
101
+ * @param {object} _args
102
+ * @param {boolean} _args.cascade
103
+ * @param {boolean} _args.ifExists
104
+ * @returns {string}
105
+ */
106
+ dropTableSql(_tableName, _args) { // eslint-disable-line no-unused-vars
107
+ throw new Error("dropTableSql not implemented")
108
+ }
109
+
110
+ /**
111
+ * @returns {object}
112
+ */
66
113
  getArgs() {
67
114
  return this._args
68
115
  }
69
116
 
117
+ /**
118
+ * @returns {import("../../configuration.js").default}
119
+ */
70
120
  getConfiguration() {
71
121
  if (!this.configuration) throw new Error("No configuration set")
72
122
 
73
123
  return this.configuration
74
124
  }
75
125
 
126
+ /**
127
+ * @returns {number}
128
+ */
76
129
  getIdSeq() {
77
130
  return this.idSeq
78
131
  }
79
132
 
133
+ /**
134
+ * @interface
135
+ * @returns {Array<import("./base-table.js").default>}
136
+ */
80
137
  getTables() {
81
138
  throw new Error(`${this.constructor.name}#getTables not implemented`)
82
139
  }
@@ -106,6 +163,10 @@ export default class VelociousDatabaseDriversBase {
106
163
  await this.query(sql)
107
164
  }
108
165
 
166
+ /**
167
+ * @interface
168
+ * @returns {Promise<number>}
169
+ */
109
170
  lastInsertID() {
110
171
  throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
111
172
  }
@@ -181,8 +242,12 @@ export default class VelociousDatabaseDriversBase {
181
242
  return await this.query(sql)
182
243
  }
183
244
 
184
- setIdSeq(id) {
185
- this.idSeq = id
245
+ /**
246
+ * @param {number} newIdSeq
247
+ * @returns {void}
248
+ */
249
+ setIdSeq(newIdSeq) {
250
+ this.idSeq = newIdSeq
186
251
  }
187
252
 
188
253
  /**
@@ -246,6 +311,9 @@ export default class VelociousDatabaseDriversBase {
246
311
  return result
247
312
  }
248
313
 
314
+ /**
315
+ * @returns {Promise<void>}
316
+ */
249
317
  async startTransaction() {
250
318
  await this._transactionsActionsMutex.sync(async () => {
251
319
  await this._startTransactionAction()
@@ -253,10 +321,16 @@ export default class VelociousDatabaseDriversBase {
253
321
  })
254
322
  }
255
323
 
324
+ /**
325
+ * @returns {Promise<void>}
326
+ */
256
327
  async _startTransactionAction() {
257
328
  await this.query("BEGIN TRANSACTION")
258
329
  }
259
330
 
331
+ /**
332
+ * @returns {Promise<void>}
333
+ */
260
334
  async commitTransaction() {
261
335
  await this._transactionsActionsMutex.sync(async () => {
262
336
  await this._commitTransactionAction()
@@ -264,13 +338,16 @@ export default class VelociousDatabaseDriversBase {
264
338
  })
265
339
  }
266
340
 
341
+ /**
342
+ * @returns {Promise<void>}
343
+ */
267
344
  async _commitTransactionAction() {
268
345
  await this.query("COMMIT")
269
346
  }
270
347
 
271
348
  /**
272
349
  * @param {string} sql
273
- * @returns {Promise<Array>}
350
+ * @returns {Promise<Array<Record<string, any>>>}
274
351
  */
275
352
  async query(sql) {
276
353
  let tries = 0
@@ -292,10 +369,18 @@ export default class VelociousDatabaseDriversBase {
292
369
  }
293
370
  }
294
371
 
372
+ /**
373
+ * @interface
374
+ * @param {Error} _error
375
+ * @returns {boolean}
376
+ */
295
377
  retryableDatabaseError(_error) { // eslint-disable-line no-unused-vars
296
378
  return false
297
379
  }
298
380
 
381
+ /**
382
+ * @returns {Promise<void>}
383
+ */
299
384
  async rollbackTransaction() {
300
385
  await this._transactionsActionsMutex.sync(async () => {
301
386
  await this._rollbackTransactionAction()
@@ -303,20 +388,34 @@ export default class VelociousDatabaseDriversBase {
303
388
  })
304
389
  }
305
390
 
391
+ /**
392
+ * @returns {Promise<void>}
393
+ */
306
394
  async _rollbackTransactionAction() {
307
395
  await this.query("ROLLBACK")
308
396
  }
309
397
 
398
+ /**
399
+ * @returns {string}
400
+ */
310
401
  generateSavePointName() {
311
402
  return `sp${new UUID(4).format().replaceAll("-", "")}`
312
403
  }
313
404
 
405
+ /**
406
+ * @param {string} savePointName
407
+ * @returns {Promise<void>}
408
+ */
314
409
  async startSavePoint(savePointName) {
315
410
  await this._transactionsActionsMutex.sync(async () => {
316
411
  await this._startSavePointAction(savePointName)
317
412
  })
318
413
  }
319
414
 
415
+ /**
416
+ * @param {string} savePointName
417
+ * @returns {Promise<void>}
418
+ */
320
419
  async _startSavePointAction(savePointName) {
321
420
  await this.query(`SAVEPOINT ${savePointName}`)
322
421
  }
@@ -343,26 +442,45 @@ export default class VelociousDatabaseDriversBase {
343
442
  }
344
443
  }
345
444
 
445
+ /**
446
+ * @param {string} savePointName
447
+ * @returns {Promise<void>}
448
+ */
346
449
  async releaseSavePoint(savePointName) {
347
450
  await this._transactionsActionsMutex.sync(async () => {
348
451
  await this._releaseSavePointAction(savePointName)
349
452
  })
350
453
  }
351
454
 
455
+ /**
456
+ * @param {string} savePointName
457
+ * @returns {Promise<void>}
458
+ */
352
459
  async _releaseSavePointAction(savePointName) {
353
460
  await this.query(`RELEASE SAVEPOINT ${savePointName}`)
354
461
  }
355
462
 
463
+ /**
464
+ * @param {string} savePointName
465
+ * @returns {Promise<void>}
466
+ */
356
467
  async rollbackSavePoint(savePointName) {
357
468
  await this._transactionsActionsMutex.sync(async () => {
358
469
  await this._rollbackSavePointAction(savePointName)
359
470
  })
360
471
  }
361
472
 
473
+ /**
474
+ * @param {string} savePointName
475
+ * @returns {Promise<void>}
476
+ */
362
477
  async _rollbackSavePointAction(savePointName) {
363
478
  await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}`)
364
479
  }
365
480
 
481
+ /**
482
+ * @returns {Promise<void>}
483
+ */
366
484
  async truncateAllTables() {
367
485
  await this.withDisabledForeignKeys(async () => {
368
486
  let tries = 0
@@ -408,6 +526,10 @@ export default class VelociousDatabaseDriversBase {
408
526
  await this.query(sql)
409
527
  }
410
528
 
529
+ /**
530
+ * @param {function() : void} callback
531
+ * @returns {Promise<any>}
532
+ */
411
533
  async withDisabledForeignKeys(callback) {
412
534
  await this.disableForeignKeys()
413
535
 
@@ -5,20 +5,30 @@ import restArgsError from "../utils/rest-args-error.js"
5
5
  import TableData from "./table-data/index.js"
6
6
 
7
7
  export default class VelociousDatabaseMigrator {
8
+ /**
9
+ * @param {object} args
10
+ * @param {import("../configuration.js").default} args.configuration
11
+ */
8
12
  constructor({configuration, ...restArgs}) {
9
13
  restArgsError(restArgs)
10
14
 
11
15
  if (!configuration) throw new Error("configuration argument is required")
12
16
 
13
17
  this.configuration = configuration
14
- this.logger = new Logger(this)
18
+ this.logger = new Logger(this, {debug: false})
15
19
  }
16
20
 
21
+ /**
22
+ * @returns {Promise<void>}
23
+ */
17
24
  async prepare() {
18
25
  await this.createMigrationsTable()
19
26
  await this.loadMigrationsVersions()
20
27
  }
21
28
 
29
+ /**
30
+ * @returns {Promise<void>}
31
+ */
22
32
  async createMigrationsTable() {
23
33
  const dbs = await this.configuration.getCurrentConnections()
24
34
 
@@ -48,6 +58,11 @@ export default class VelociousDatabaseMigrator {
48
58
  }
49
59
  }
50
60
 
61
+ /**
62
+ * @param {string} dbIdentifier
63
+ * @param {string} version
64
+ * @returns {Promise<boolean>}
65
+ */
51
66
  hasRunMigrationVersion(dbIdentifier, version) {
52
67
  if (!this.migrationsVersions) throw new Error("Migrations versions hasn't been loaded yet")
53
68
  if (!this.migrationsVersions[dbIdentifier]) throw new Error(`Migrations versions hasn't been loaded yet for db: ${dbIdentifier}`)
@@ -197,7 +212,7 @@ export default class VelociousDatabaseMigrator {
197
212
  for (const migration of files) {
198
213
  await this.runMigrationFile({
199
214
  migration,
200
- require: requireContext(migration.file).default
215
+ require: () => requireContext(migration.file).default
201
216
  })
202
217
  }
203
218
  }
@@ -3,6 +3,14 @@ import QueryBase from "./base.js"
3
3
  import restArgsError from "../../utils/rest-args-error.js"
4
4
 
5
5
  export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
6
+ /**
7
+ * @param {object} args
8
+ * @param {boolean} args.cascade
9
+ * @param {import("./../drivers/base.js").default} args.driver
10
+ * @param {boolean} args.ifExists
11
+ * @param {object} args.options
12
+ * @param {string} args.tableName
13
+ */
6
14
  constructor({cascade, driver, ifExists, options, tableName, ...restArgs}) {
7
15
  super({driver, options})
8
16
 
@@ -11,7 +11,34 @@ import WhereHash from "./where-hash.js"
11
11
  import WherePlain from "./where-plain.js"
12
12
  import restArgsError from "../../utils/rest-args-error.js"
13
13
 
14
+ /**
15
+ * @typedef {Record<string, boolean|NestedPreloadRecord>} NestedPreloadRecord
16
+ */
17
+
14
18
  export default class VelociousDatabaseQuery {
19
+ /**
20
+ * @param {object} args
21
+ * @template {import("../drivers/base.js").default} Tdriver
22
+ * @param {Tdriver} args.driver
23
+ * @template {import("./from-base.js").default} TfromBase
24
+ * @param {TfromBase[]} args.froms
25
+ * @param {string[]} args.groups
26
+ * @template {import("./join-base.js").default} TjoinBase
27
+ * @param {TjoinBase[]} args.joins
28
+ * @param {import("../handler.js").default} args.handler
29
+ * @param {number} args.limit
30
+ * @template {import("../record/index.js").default} Trecord
31
+ * @param {typeof Trecord} args.modelClass
32
+ * @param {number} args.offset
33
+ * @template {import("./order-basejs").default} TorderBase
34
+ * @param {TorderBase[]} args.orders
35
+ * @param {number} args.page
36
+ * @param {number} args.perPage
37
+ * @param {NestedPreloadRecord} args.preload
38
+ * @param {Record<string, Array<string>>} args.selects
39
+ * @template {import("./where-base.js").default} TwhereBase
40
+ * @param {TwhereBase[]} args.wheres
41
+ */
15
42
  constructor({driver, froms = [], groups = [], joins = [], handler, limit = null, modelClass, offset = null, orders = [], page = null, perPage, preload = {}, selects = [], wheres = [], ...restArgs}) {
16
43
  if (!driver) throw new Error("No driver given to query")
17
44
  if (!handler) throw new Error("No handler given to query")
@@ -100,6 +127,21 @@ export default class VelociousDatabaseQuery {
100
127
  return countResult
101
128
  }
102
129
 
130
+ /**
131
+ * @template {import("./from-base.js").default} T
132
+ * @returns {T[]}
133
+ */
134
+ getFroms() {
135
+ return this._froms
136
+ }
137
+
138
+ /**
139
+ * @returns {string[]}
140
+ */
141
+ getGroups() {
142
+ return this._groups
143
+ }
144
+
103
145
  /**
104
146
  * @returns {import("../query-parser/options.js").default}
105
147
  */
@@ -1,20 +1,31 @@
1
- import {digs} from "diggerize"
1
+ // @ts-check
2
+
3
+ import restArgsError from "../../utils/rest-args-error.js"
2
4
 
3
5
  export default class VelociousDatabaseQueryParserFromParser {
4
- constructor({pretty, query}) {
6
+ /**
7
+ * @param {object} args
8
+ * @param {boolean} args.pretty
9
+ * @param {import("../query/index.js").default} args.query
10
+ */
11
+ constructor({pretty, query, ...restArgs}) {
12
+ restArgsError(restArgs)
13
+
5
14
  this.pretty = pretty
6
15
  this.query = query
7
16
  }
8
17
 
18
+ /** @returns {string} */
9
19
  toSql() {
10
- const {pretty, query} = digs(this, "pretty", "query")
20
+ const {pretty, query} = this
21
+ const froms = query.getFroms()
11
22
 
12
23
  let sql = " FROM"
13
24
 
14
- for (const fromKey in query._froms) {
15
- const from = query._froms[fromKey]
25
+ for (const fromKey in froms) {
26
+ const from = froms[fromKey]
16
27
 
17
- if (fromKey > 0) {
28
+ if (typeof fromKey == "number" && fromKey > 0) {
18
29
  sql += ","
19
30
  }
20
31
 
@@ -1,24 +1,37 @@
1
- import {digs} from "diggerize"
1
+ // @ts-check
2
+
3
+ import restArgsError from "../../utils/rest-args-error.js"
2
4
 
3
5
  export default class VelociousDatabaseQueryParserFromParser {
4
- constructor({pretty, query}) {
6
+ /**
7
+ * @param {object} args
8
+ * @param {boolean} args.pretty
9
+ * @param {import("../query/index.js").default} args.query
10
+ */
11
+ constructor({pretty, query, ...restArgs}) {
12
+ restArgsError(restArgs)
13
+
5
14
  this.pretty = pretty
6
15
  this.query = query
7
16
  }
8
17
 
18
+ /**
19
+ * @returns {string}
20
+ */
9
21
  toSql() {
10
- const {pretty, query} = digs(this, "pretty", "query")
22
+ const {pretty, query} = this
23
+ const groups = query.getGroups()
11
24
 
12
- if (query._groups.length == 0) {
25
+ if (groups.length == 0) {
13
26
  return ""
14
27
  }
15
28
 
16
29
  let sql = " GROUP BY"
17
30
 
18
- for (const groupKey in query._groups) {
19
- const group = query._groups[groupKey]
31
+ for (const groupKey in groups) {
32
+ const group = groups[groupKey]
20
33
 
21
- if (groupKey > 0) {
34
+ if (typeof groupKey == "number" && groupKey > 0) {
22
35
  sql += ","
23
36
  }
24
37
 
@@ -31,7 +44,7 @@ export default class VelociousDatabaseQueryParserFromParser {
31
44
  if (typeof group == "string") {
32
45
  sql += group
33
46
  } else {
34
- sql += group.toSql()
47
+ throw new Error(`Unsupported group type: ${typeof group}`)
35
48
  }
36
49
  }
37
50
 
@@ -306,6 +306,7 @@ class VelociousDatabaseRecord {
306
306
  * Adds a has-many-relationship to the model class.
307
307
  * @param {string} relationshipName The name of the relationship (e.g. "posts")
308
308
  * @param {object} options The options for the relationship (e.g. {className: "Post"})
309
+ * @returns {void}
309
310
  */
310
311
  static hasMany(relationshipName, options = {}) {
311
312
  return this._defineRelationship(relationshipName, Object.assign({type: "hasMany"}, options))
@@ -315,6 +316,7 @@ class VelociousDatabaseRecord {
315
316
  * Adds a has-one-relationship to the model class.
316
317
  * @param {string} relationshipName The name of the relationship (e.g. "post")
317
318
  * @param {object} options The options for the relationship (e.g. {className: "Post"})
319
+ * @returns {void}
318
320
  */
319
321
  static hasOne(relationshipName, options = {}) {
320
322
  return this._defineRelationship(relationshipName, Object.assign({type: "hasOne"}, options))
@@ -526,6 +528,9 @@ class VelociousDatabaseRecord {
526
528
  return this._columnNames
527
529
  }
528
530
 
531
+ /**
532
+ * @returns {import("../drivers/base-table.js").default}
533
+ */
529
534
  static _getTable() {
530
535
  if (!this._table) throw new Error(`${this.name} hasn't been initialized yet`)
531
536
 
@@ -1,7 +1,22 @@
1
1
  import restArgsError from "../../../utils/rest-args-error.js"
2
2
 
3
3
  export default class VelociousDatabaseRecordBaseRelationship {
4
- constructor({className, configuration, dependent, foreignKey, inverseOf, klass, modelClass, primaryKey = "id", relationshipName, through, type, ...restArgs}) { // eslint-disable-line no-unused-vars
4
+ /**
5
+ * @param {object} args
6
+ * @param {string} args.className
7
+ * @param {import("../../../configuration.js").default} args.configuration
8
+ * @param {string} args.dependent
9
+ * @param {boolean|object} args.foreignKey
10
+ * @param {string} args.inverseOf
11
+ * @param {typeof import("../index.js").default} args.klass
12
+ * @param {typeof import("../index.js").default} args.modelClass
13
+ * @param {string} args.primaryKey
14
+ * @param {boolean} args.polymorphic
15
+ * @param {string} args.relationshipName
16
+ * @param {string} args.through
17
+ * @param {string} args.type
18
+ */
19
+ constructor({className, configuration, dependent, foreignKey, inverseOf, klass, modelClass, primaryKey = "id", polymorphic, relationshipName, through, type, ...restArgs}) { // eslint-disable-line no-unused-vars
5
20
  restArgsError(restArgs)
6
21
 
7
22
  if (!modelClass) throw new Error(`'modelClass' wasn't given for ${relationshipName}`)
@@ -14,6 +29,7 @@ export default class VelociousDatabaseRecordBaseRelationship {
14
29
  this._inverseOf
15
30
  this.klass = klass
16
31
  this.modelClass = modelClass
32
+ this._polymorphic = polymorphic
17
33
  this._primaryKey = primaryKey
18
34
  this.relationshipName = relationshipName
19
35
  this.through = through
@@ -42,8 +58,7 @@ export default class VelociousDatabaseRecordBaseRelationship {
42
58
  }
43
59
 
44
60
  /**
45
- * @template T extends import("../index.js").default
46
- * @returns {typeof T}
61
+ * @returns {typeof import("../index.js").default}
47
62
  */
48
63
  getModelClass() { return this.modelClass }
49
64