velocious 1.0.84 → 1.0.86

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 (95) hide show
  1. package/bin/velocious.js +10 -1
  2. package/eslint.config.js +33 -0
  3. package/package.json +7 -2
  4. package/peak_flow.yml +6 -0
  5. package/spec/cli/commands/db/create-spec.js +4 -0
  6. package/spec/cli/commands/db/migrate-spec.js +4 -2
  7. package/spec/cli/commands/db/rollback-spec.js +179 -0
  8. package/spec/cli/commands/destroy/migration-spec.js +4 -0
  9. package/spec/cli/commands/generate/migration-spec.js +4 -0
  10. package/spec/cli/commands/init-spec.js +4 -0
  11. package/spec/dummy/index.js +7 -4
  12. package/spec/dummy/src/config/configuration.example.js +2 -0
  13. package/spec/dummy/src/config/configuration.peakflow.mariadb.js +2 -0
  14. package/spec/dummy/src/config/configuration.peakflow.mssql.js +2 -0
  15. package/spec/dummy/src/config/configuration.peakflow.pgsql.js +2 -0
  16. package/spec/dummy/src/config/configuration.peakflow.sqlite.js +2 -0
  17. package/spec/dummy/src/database/migrations/20250921121002-create-project-details.js +3 -1
  18. package/src/application.js +12 -0
  19. package/src/cli/base-command.js +9 -5
  20. package/src/cli/browser-cli.js +37 -0
  21. package/src/cli/commands/db/create.js +5 -5
  22. package/src/cli/commands/db/drop.js +4 -5
  23. package/src/cli/commands/db/migrate.js +6 -10
  24. package/src/cli/commands/db/reset.js +8 -12
  25. package/src/cli/commands/db/rollback.js +15 -0
  26. package/src/cli/commands/destroy/migration.js +2 -2
  27. package/src/cli/commands/generate/migration.js +3 -6
  28. package/src/cli/commands/generate/model.js +3 -6
  29. package/src/cli/commands/init.js +5 -8
  30. package/src/cli/commands/server.js +4 -3
  31. package/src/cli/commands/test.js +1 -1
  32. package/src/cli/index.js +15 -40
  33. package/src/cli/use-browser-cli.js +25 -0
  34. package/src/configuration-resolver.js +1 -1
  35. package/src/configuration.js +118 -9
  36. package/src/controller.js +29 -0
  37. package/src/database/drivers/base-column.js +14 -0
  38. package/src/database/drivers/base-columns-index.js +3 -0
  39. package/src/database/drivers/base-foreign-key.js +3 -0
  40. package/src/database/drivers/base-table.js +3 -0
  41. package/src/database/drivers/base.js +55 -1
  42. package/src/database/drivers/mssql/index.js +64 -1
  43. package/src/database/drivers/mysql/columns-index.js +0 -1
  44. package/src/database/drivers/sqlite/base.js +39 -0
  45. package/src/database/drivers/sqlite/connection-remote.js +1 -1
  46. package/src/database/drivers/sqlite/sql/alter-table.js +1 -1
  47. package/src/database/drivers/sqlite/sql/delete.js +15 -10
  48. package/src/database/migration/index.js +122 -1
  49. package/src/database/migrator/files-finder.js +13 -1
  50. package/src/database/migrator.js +125 -24
  51. package/src/database/pool/single-multi-use.js +1 -1
  52. package/src/database/query/alter-table-base.js +11 -0
  53. package/src/database/query/base.js +7 -0
  54. package/src/database/query/create-database-base.js +3 -0
  55. package/src/database/query/create-index-base.js +3 -1
  56. package/src/database/query/create-table-base.js +3 -0
  57. package/src/database/query/drop-table-base.js +4 -1
  58. package/src/database/query/from-base.js +7 -0
  59. package/src/database/query/index.js +105 -1
  60. package/src/database/query/insert-base.js +6 -0
  61. package/src/database/query/join-base.js +3 -0
  62. package/src/database/query/order-base.js +3 -0
  63. package/src/database/query/select-base.js +3 -0
  64. package/src/database/query/update-base.js +3 -0
  65. package/src/database/query/where-base.js +3 -0
  66. package/src/database/record/index.js +321 -14
  67. package/src/database/record/instance-relationships/base.js +66 -1
  68. package/src/database/record/relationships/base.js +41 -1
  69. package/src/database/record/validators/base.js +10 -0
  70. package/src/database/record/validators/presence.js +1 -1
  71. package/src/database/table-data/table-column.js +37 -3
  72. package/src/database/table-data/table-index.js +1 -1
  73. package/src/database/use-database.js +2 -2
  74. package/src/environment-handlers/base.js +53 -0
  75. package/src/environment-handlers/browser.js +171 -0
  76. package/src/environment-handlers/node.js +162 -0
  77. package/src/http-server/client/request-buffer/index.js +9 -9
  78. package/src/http-server/index.js +6 -0
  79. package/src/http-server/worker-handler/index.js +20 -19
  80. package/src/initializer.js +17 -1
  81. package/src/logger.js +3 -0
  82. package/src/routes/app-routes.js +6 -2
  83. package/src/routes/base-route.js +1 -1
  84. package/src/routes/get-route.js +1 -1
  85. package/src/routes/namespace-route.js +1 -1
  86. package/src/routes/post-route.js +1 -1
  87. package/src/routes/resolver.js +1 -1
  88. package/src/routes/resource-route.js +1 -1
  89. package/src/templates/configuration.js +4 -0
  90. package/src/testing/request-client.js +26 -3
  91. package/src/testing/test-files-finder.js +2 -2
  92. package/src/testing/test-runner.js +74 -28
  93. package/src/testing/test.js +62 -0
  94. package/src/utils/file-exists.js +7 -5
  95. package/src/utils/rest-args-error.js +5 -3
@@ -9,18 +9,30 @@ import HasOneRelationship from "./relationships/has-one.js"
9
9
  import HasOneInstanceRelationship from "./instance-relationships/has-one.js"
10
10
  import * as inflection from "inflection"
11
11
  import Query from "../query/index.js"
12
+ import restArgsError from "../../utils/rest-args-error.js"
12
13
  import ValidatorsPresence from "./validators/presence.js"
13
14
  import ValidatorsUniqueness from "./validators/uniqueness.js"
14
15
 
15
16
  class ValidationError extends Error {
17
+ /**
18
+ * @template T extends VelociousDatabaseRecord
19
+ * @returns {T}
20
+ */
16
21
  getModel() {
17
22
  return this._model
18
23
  }
19
24
 
25
+ /**
26
+ * @template T extends VelociousDatabaseRecord
27
+ * @param {T} model
28
+ */
20
29
  setModel(model) {
21
30
  this._model = model
22
31
  }
23
32
 
33
+ /**
34
+ * @returns {Array}
35
+ */
24
36
  getValidationErrors() {
25
37
  return this._validationErrors
26
38
  }
@@ -31,22 +43,38 @@ class ValidationError extends Error {
31
43
  }
32
44
 
33
45
  class VelociousDatabaseRecord {
46
+ /**
47
+ * @template T extends import("./validators/base.js").default
48
+ * @returns {Record<string, T>}
49
+ */
34
50
  static validatorTypes() {
35
51
  if (!this._validatorTypes) this._validatorTypes = {}
36
52
 
37
53
  return this._validatorTypes
38
54
  }
39
55
 
56
+ /**
57
+ * @param {string} name
58
+ * @template T extends import("./validators/base.js").default
59
+ * @param {T} validatorClass
60
+ */
40
61
  static registerValidatorType(name, validatorClass) {
41
62
  this.validatorTypes()[name] = validatorClass
42
63
  }
43
64
 
65
+ /**
66
+ * @template T extends import("./validators/base.js").default
67
+ * @returns {T}
68
+ */
44
69
  static getValidatorType(validatorName) {
45
70
  if (!(validatorName in this.validatorTypes())) throw new Error(`Validator type ${validatorName} not found`)
46
71
 
47
72
  return this.validatorTypes()[validatorName]
48
73
  }
49
74
 
75
+ /**
76
+ * @returns {boolean}
77
+ */
50
78
  static _relationshipExists(relationshipName) {
51
79
  if (this._relationships && relationshipName in this._relationships) {
52
80
  return true
@@ -160,6 +188,10 @@ class VelociousDatabaseRecord {
160
188
  this._relationships[relationshipName] = relationship
161
189
  }
162
190
 
191
+ /**
192
+ * @template T extends import("./relationships/index.js").default
193
+ * @returns {T}
194
+ */
163
195
  static getRelationshipByName(relationshipName) {
164
196
  if (!this._relationships) this._relationships = {}
165
197
 
@@ -170,16 +202,26 @@ class VelociousDatabaseRecord {
170
202
  return relationship
171
203
  }
172
204
 
205
+ /**
206
+ * @returns {Array}
207
+ */
173
208
  static getRelationships() {
174
209
  if (this._relationships) return Object.values(this._relationships)
175
210
 
176
211
  return []
177
212
  }
178
213
 
214
+ /**
215
+ * @returns {Array<string>}
216
+ */
179
217
  static getRelationshipNames() {
180
218
  return this.getRelationships().map((relationship) => relationship.getRelationshipName())
181
219
  }
182
220
 
221
+ /**
222
+ * @template T extends import("./instance-relationships/index.js").default
223
+ * @returns {T}
224
+ */
183
225
  getRelationshipByName(relationshipName) {
184
226
  if (!this._instanceRelationships) this._instanceRelationships = {}
185
227
 
@@ -204,10 +246,19 @@ class VelociousDatabaseRecord {
204
246
  return this._instanceRelationships[relationshipName]
205
247
  }
206
248
 
249
+ /**
250
+ * Adds a belongs-to-relationship to the model.
251
+ * @param {string} relationshipName The name of the relationship.
252
+ * @param {object} options The options for the relationship.
253
+ */
207
254
  static belongsTo(relationshipName, options) {
208
255
  this._defineRelationship(relationshipName, Object.assign({type: "belongsTo"}, options))
209
256
  }
210
257
 
258
+ /**
259
+ * @template T extends import("./database/drivers/base").default
260
+ * @returns {T}
261
+ */
211
262
  static connection() {
212
263
  const databasePool = this._getConfiguration().getDatabasePool(this.getDatabaseIdentifier())
213
264
  const connection = databasePool.getCurrentConnection()
@@ -217,6 +268,10 @@ class VelociousDatabaseRecord {
217
268
  return connection
218
269
  }
219
270
 
271
+ /**
272
+ * @param {object} attributes
273
+ * @returns {Promise<InstanceType<typeof this>>}
274
+ */
220
275
  static async create(attributes) {
221
276
  const record = new this(attributes)
222
277
 
@@ -225,6 +280,9 @@ class VelociousDatabaseRecord {
225
280
  return record
226
281
  }
227
282
 
283
+ /**
284
+ * @returns {import("../../configuration.js").default}
285
+ */
228
286
  static _getConfiguration() {
229
287
  if (!this._configuration) {
230
288
  this._configuration = Configuration.current()
@@ -237,27 +295,54 @@ class VelociousDatabaseRecord {
237
295
  return this._configuration
238
296
  }
239
297
 
298
+ /**
299
+ * @returns {import("../../configuration.js").default}
300
+ */
240
301
  _getConfiguration() {
241
302
  return this.constructor._getConfiguration()
242
303
  }
243
304
 
305
+ /**
306
+ * Adds a has-many-relationship to the model class.
307
+ * @param {string} relationshipName The name of the relationship (e.g. "posts")
308
+ * @param {object} options The options for the relationship (e.g. {className: "Post"})
309
+ */
244
310
  static hasMany(relationshipName, options = {}) {
245
311
  return this._defineRelationship(relationshipName, Object.assign({type: "hasMany"}, options))
246
312
  }
247
313
 
314
+ /**
315
+ * Adds a has-one-relationship to the model class.
316
+ * @param {string} relationshipName The name of the relationship (e.g. "post")
317
+ * @param {object} options The options for the relationship (e.g. {className: "Post"})
318
+ */
248
319
  static hasOne(relationshipName, options = {}) {
249
320
  return this._defineRelationship(relationshipName, Object.assign({type: "hasOne"}, options))
250
321
  }
251
322
 
323
+ /**
324
+ * @param {string} attributeName
325
+ * @returns {string}
326
+ */
252
327
  static humanAttributeName(attributeName) {
253
328
  const modelNameKey = inflection.underscore(this.constructor.name)
254
329
 
255
330
  return this._getConfiguration().getTranslator()(`velocious.database.record.attributes.${modelNameKey}.${attributeName}`, {defaultValue: inflection.camelize(attributeName)})
256
331
  }
257
332
 
333
+ /**
334
+ * @returns {string}
335
+ */
258
336
  static getDatabaseType() { return this._databaseType }
259
337
 
260
- static async initializeRecord({configuration}) {
338
+ /**
339
+ * @param {object} args
340
+ * @param {import("../configuration.js").default} args.configuration
341
+ * @returns {void}
342
+ */
343
+ static async initializeRecord({configuration, ...restArgs}) {
344
+ restArgsError(restArgs)
345
+
261
346
  if (!configuration) throw new Error(`No configuration given for ${this.name}`)
262
347
 
263
348
  this._configuration = configuration
@@ -298,6 +383,9 @@ class VelociousDatabaseRecord {
298
383
  this._initialized = true
299
384
  }
300
385
 
386
+ /**
387
+ * @returns {boolean}
388
+ */
301
389
  _hasAttribute(value) {
302
390
  if (typeof value == "string") {
303
391
  value = value.trim()
@@ -310,6 +398,9 @@ class VelociousDatabaseRecord {
310
398
  return false
311
399
  }
312
400
 
401
+ /**
402
+ * @returns {boolean}
403
+ */
313
404
  static isInitialized() {
314
405
  if (this._initialized) return true
315
406
 
@@ -363,14 +454,25 @@ class VelociousDatabaseRecord {
363
454
  }
364
455
  }
365
456
 
457
+ /**
458
+ * @returns {string}
459
+ */
366
460
  static getDatabaseIdentifier() {
367
461
  return this._databaseIdentifier || "default"
368
462
  }
369
463
 
464
+ /**
465
+ * @param {string} databaseIdentifier
466
+ * @returns {void}
467
+ */
370
468
  static setDatabaseIdentifier(databaseIdentifier) {
371
469
  this._databaseIdentifier = databaseIdentifier
372
470
  }
373
471
 
472
+ /**
473
+ * @param {string} name
474
+ * @returns {*}
475
+ */
374
476
  getAttribute(name) {
375
477
  const columnName = inflection.underscore(name)
376
478
 
@@ -381,6 +483,11 @@ class VelociousDatabaseRecord {
381
483
  return this._attributes[columnName]
382
484
  }
383
485
 
486
+ /**
487
+ * @param {string} name
488
+ * @param {*} newValue
489
+ * @returns {void}
490
+ */
384
491
  setAttribute(name, newValue) {
385
492
  const setterName = `set${inflection.camelize(name)}`
386
493
 
@@ -395,7 +502,7 @@ class VelociousDatabaseRecord {
395
502
 
396
503
  const columnName = this.constructor._attributeNameToColumnName[name]
397
504
 
398
- if (!columnName) throw new Error(`Couldn't figure out column name for attribute: ${attributeName}`)
505
+ if (!columnName) throw new Error(`Couldn't figure out column name for attribute: ${name}`)
399
506
 
400
507
  if (this._attributes[columnName] != newValue) {
401
508
  this._changes[columnName] = newValue
@@ -408,6 +515,9 @@ class VelociousDatabaseRecord {
408
515
  return this._columns
409
516
  }
410
517
 
518
+ /**
519
+ * @returns {Array<string>}
520
+ */
411
521
  static getColumnNames() {
412
522
  if (!this._columnNames) {
413
523
  this._columnNames = this.getColumns().map((column) => column.getName())
@@ -422,10 +532,18 @@ class VelociousDatabaseRecord {
422
532
  return this._table
423
533
  }
424
534
 
535
+ /**
536
+ * @param {Array<string>} columns
537
+ * @param {Array<Array<string>>} rows
538
+ * @returns {void}
539
+ */
425
540
  static async insertMultiple(columns, rows) {
426
541
  return await this.connection().insertMultiple(this.tableName(), columns, rows)
427
542
  }
428
543
 
544
+ /**
545
+ * @returns {number}
546
+ */
429
547
  static async nextPrimaryKey() {
430
548
  const primaryKey = this.primaryKey()
431
549
  const tableName = this.tableName()
@@ -439,16 +557,26 @@ class VelociousDatabaseRecord {
439
557
  }
440
558
  }
441
559
 
560
+ /**
561
+ * @param {string} primaryKey
562
+ * @returns {void}
563
+ */
442
564
  static setPrimaryKey(primaryKey) {
443
565
  this._primaryKey = primaryKey
444
566
  }
445
567
 
568
+ /**
569
+ * @returns {string}
570
+ */
446
571
  static primaryKey() {
447
572
  if (this._primaryKey) return this._primaryKey
448
573
 
449
574
  return "id"
450
575
  }
451
576
 
577
+ /**
578
+ * @returns {boolean}
579
+ */
452
580
  async save() {
453
581
  const isNewRecord = this.isNewRecord()
454
582
  let result
@@ -582,26 +710,40 @@ class VelociousDatabaseRecord {
582
710
  }
583
711
  }
584
712
 
713
+ /**
714
+ * @returns {string}
715
+ */
585
716
  static tableName() {
586
717
  if (!this._tableName) this._tableName = inflection.underscore(inflection.pluralize(this.name))
587
718
 
588
719
  return this._tableName
589
720
  }
590
721
 
722
+ /**
723
+ * @param {string} tableName
724
+ * @returns {void}
725
+ */
591
726
  static setTableName(tableName) {
592
727
  this._tableName = tableName
593
728
  }
594
729
 
730
+ /**
731
+ * @param {function() : void} callback
732
+ * @returns {*}
733
+ */
595
734
  static async transaction(callback) {
596
735
  const useTransactions = this.connection().getArgs().record?.transactions
597
736
 
598
737
  if (useTransactions !== false) {
599
- await this.connection().transaction(callback)
738
+ return await this.connection().transaction(callback)
600
739
  } else {
601
740
  return await callback()
602
741
  }
603
742
  }
604
743
 
744
+ /**
745
+ * @returns {void}
746
+ */
605
747
  static translates(...names) {
606
748
  for (const name of names) {
607
749
  if (!this._translations) this._translations = {}
@@ -615,6 +757,9 @@ class VelociousDatabaseRecord {
615
757
  }
616
758
  }
617
759
 
760
+ /**
761
+ * @returns {VelociousDatabaseRecord}
762
+ */
618
763
  static getTranslationClass() {
619
764
  if (this._translationClass) return this._translationClass
620
765
  if (this.tableName().endsWith("_translations")) throw new Error("Trying to define a translations class for a translation class")
@@ -632,6 +777,9 @@ class VelociousDatabaseRecord {
632
777
  return this._translationClass
633
778
  }
634
779
 
780
+ /**
781
+ * @returns {string}
782
+ */
635
783
  static getTranslationsTableName() {
636
784
  const tableNameParts = this.tableName().split("_")
637
785
 
@@ -640,6 +788,9 @@ class VelociousDatabaseRecord {
640
788
  return `${tableNameParts.join("_")}_translations`
641
789
  }
642
790
 
791
+ /**
792
+ * @returns {Promise<boolean>}
793
+ */
643
794
  static async hasTranslationsTable() {
644
795
  try {
645
796
  await this.connection().getTableByName(this.getTranslationsTableName())
@@ -650,6 +801,11 @@ class VelociousDatabaseRecord {
650
801
  }
651
802
  }
652
803
 
804
+ /**
805
+ * Adds a validation to an attribute.
806
+ * @param {string} attributeName The name of the attribute to validate.
807
+ * @param {object} validators The validators to add. Key is the validator name, value is the validator arguments.
808
+ */
653
809
  static async validates(attributeName, validators) {
654
810
  for (const validatorName in validators) {
655
811
  const validatorArgs = validators[validatorName]
@@ -663,6 +819,11 @@ class VelociousDatabaseRecord {
663
819
  }
664
820
  }
665
821
 
822
+ /**
823
+ * @param {string} name
824
+ * @param {string} locale
825
+ * @returns {*}
826
+ */
666
827
  _getTranslatedAttribute(name, locale) {
667
828
  const translation = this.translations().loaded().find((translation) => translation.locale() == locale)
668
829
 
@@ -671,6 +832,11 @@ class VelociousDatabaseRecord {
671
832
  }
672
833
  }
673
834
 
835
+ /**
836
+ * @param {string} name
837
+ * @param {string} locale
838
+ * @returns {*}
839
+ */
674
840
  _getTranslatedAttributeWithFallback(name, locale) {
675
841
  let localesInOrder
676
842
  const fallbacks = this._getConfiguration().getLocaleFallbacks()
@@ -690,6 +856,12 @@ class VelociousDatabaseRecord {
690
856
  }
691
857
  }
692
858
 
859
+ /**
860
+ * @param {string} name
861
+ * @param {string} locale
862
+ * @param {*} newValue
863
+ * @returns {void}
864
+ */
693
865
  _setTranslatedAttribute(name, locale, newValue) {
694
866
  let translation = this.translations().loaded()?.find((translation) => translation.locale() == locale)
695
867
 
@@ -704,6 +876,9 @@ class VelociousDatabaseRecord {
704
876
  translation.assign(assignments)
705
877
  }
706
878
 
879
+ /**
880
+ * @returns {Query}
881
+ */
707
882
  static _newQuery() {
708
883
  const handler = new Handler()
709
884
  const query = new Query({
@@ -715,80 +890,139 @@ class VelociousDatabaseRecord {
715
890
  return query.from(new FromTable({driver: this.connection(), tableName: this.tableName()}))
716
891
  }
717
892
 
893
+ /**
894
+ * @returns {string}
895
+ */
718
896
  static orderableColumn() {
719
897
  // FIXME: Allow to change to 'created_at' if using UUID?
720
898
 
721
899
  return this.primaryKey()
722
900
  }
723
901
 
724
- static all() {
725
- return this._newQuery()
902
+ /**
903
+ * @returns {Promise<Array<InstanceType<typeof this>>>}
904
+ */
905
+ static async all() {
906
+ return await this._newQuery()
726
907
  }
727
908
 
909
+ /**
910
+ * @returns {number}
911
+ */
728
912
  static async count() {
729
- return this._newQuery().count()
913
+ return await this._newQuery().count()
730
914
  }
731
915
 
732
916
  static async destroyAll(...args) {
733
- return this._newQuery().destroyAll(...args)
917
+ return await this._newQuery().destroyAll(...args)
734
918
  }
735
919
 
920
+ /**
921
+ * @param {...Parameters<Query["find"]>} args
922
+ * @returns {Promise<InstanceType<typeof this>>}
923
+ */
736
924
  static async find(...args) {
737
- return this._newQuery().find(...args)
925
+ return await this._newQuery().find(...args)
738
926
  }
739
927
 
928
+ /**
929
+ * @param {...Parameters<Query["findBy"]>} args
930
+ * @returns {Promise<InstanceType<typeof this>>}
931
+ */
740
932
  static async findBy(...args) {
741
- return this._newQuery().findBy(...args)
933
+ return await this._newQuery().findBy(...args)
742
934
  }
743
935
 
936
+ /**
937
+ * @param {...Parameters<Query["findByOrFail"]>} args
938
+ * @returns {Promise<InstanceType<typeof this>>}
939
+ */
744
940
  static async findByOrFail(...args) {
745
- return this._newQuery().findByOrFail(...args)
941
+ return await this._newQuery().findByOrFail(...args)
746
942
  }
747
943
 
944
+ /**
945
+ * @param {...Parameters<Query["findOrCreateBy"]>} args
946
+ * @returns {Promise<InstanceType<typeof this>>}
947
+ */
748
948
  static async findOrCreateBy(...args) {
749
- return this._newQuery().findOrCreateBy(...args)
949
+ return await this._newQuery().findOrCreateBy(...args)
750
950
  }
751
951
 
952
+ /**
953
+ * @param {...Parameters<Query["findOrInitializeBy"]>} args
954
+ * @returns {Promise<InstanceType<typeof this>>}
955
+ */
752
956
  static async findOrInitializeBy(...args) {
753
- return this._newQuery().findOrInitializeBy(...args)
957
+ return await this._newQuery().findOrInitializeBy(...args)
754
958
  }
755
959
 
960
+ /**
961
+ * @returns {Promise<InstanceType<typeof this>>}
962
+ */
756
963
  static async first() {
757
- return this._newQuery().first()
964
+ return await this._newQuery().first()
758
965
  }
759
966
 
967
+ /**
968
+ * @returns {Query}
969
+ */
760
970
  static joins(...args) {
761
971
  return this._newQuery().joins(...args)
762
972
  }
763
973
 
974
+ /**
975
+ * @returns {Promise<InstanceType<typeof this>>}
976
+ */
764
977
  static async last(...args) {
765
978
  return await this._newQuery().last(...args)
766
979
  }
767
980
 
981
+ /**
982
+ * @returns {Query}
983
+ */
768
984
  static limit(...args) {
769
985
  return this._newQuery().limit(...args)
770
986
  }
771
987
 
988
+ /**
989
+ * @returns {Query}
990
+ */
772
991
  static order(...args) {
773
992
  return this._newQuery().order(...args)
774
993
  }
775
994
 
995
+ /**
996
+ * @returns {Query}
997
+ */
776
998
  static preload(...args) {
777
999
  return this._newQuery().preload(...args)
778
1000
  }
779
1001
 
1002
+ /**
1003
+ * @returns {Query}
1004
+ */
780
1005
  static select(...args) {
781
1006
  return this._newQuery().select(...args)
782
1007
  }
783
1008
 
1009
+ /**
1010
+ * @returns {Query}
1011
+ */
784
1012
  static toArray(...args) {
785
1013
  return this._newQuery().toArray(...args)
786
1014
  }
787
1015
 
1016
+ /**
1017
+ * @returns {Query}
1018
+ */
788
1019
  static where(...args) {
789
1020
  return this._newQuery().where(...args)
790
1021
  }
791
1022
 
1023
+ /**
1024
+ * @param {object} changes
1025
+ */
792
1026
  constructor(changes = {}) {
793
1027
  this._attributes = {}
794
1028
  this._changes = {}
@@ -800,27 +1034,47 @@ class VelociousDatabaseRecord {
800
1034
  }
801
1035
  }
802
1036
 
1037
+ /**
1038
+ * @param {object} attributes
1039
+ * @returns {void}
1040
+ */
803
1041
  loadExistingRecord(attributes) {
804
1042
  this._attributes = attributes
805
1043
  this._isNewRecord = false
806
1044
  }
807
1045
 
1046
+ /**
1047
+ * Assigns the given attributes to the record.
1048
+ * @param {object} attributesToAssign
1049
+ * @returns {void}
1050
+ */
808
1051
  assign(attributesToAssign) {
809
1052
  for (const attributeToAssign in attributesToAssign) {
810
1053
  this.setAttribute(attributeToAssign, attributesToAssign[attributeToAssign])
811
1054
  }
812
1055
  }
813
1056
 
1057
+ /**
1058
+ * Returns a the current attributes of the record (original attributes from database plus changes)
1059
+ * @returns {void}
1060
+ */
814
1061
  attributes() {
815
1062
  return Object.assign({}, this._attributes, this._changes)
816
1063
  }
817
1064
 
1065
+ /**
1066
+ * @returns {import("../drivers/base.js").default}
1067
+ */
818
1068
  _connection() {
819
1069
  if (this.__connection) return this.__connection
820
1070
 
821
1071
  return this.constructor.connection()
822
1072
  }
823
1073
 
1074
+ /**
1075
+ * Destroys the record in the database and all of its dependent records.
1076
+ * @returns {void}
1077
+ */
824
1078
  async destroy() {
825
1079
  for (const relationship of this.constructor.getRelationships()) {
826
1080
  if (relationship.getDependent() != "destroy") {
@@ -867,8 +1121,15 @@ class VelociousDatabaseRecord {
867
1121
  await this._connection().query(sql)
868
1122
  }
869
1123
 
870
- _hasChanges = () => Object.keys(this._changes).length > 0
1124
+ /**
1125
+ * @returns {boolean}
1126
+ */
1127
+ _hasChanges() { return Object.keys(this._changes).length > 0 }
871
1128
 
1129
+ /**
1130
+ * Returns true if the model has been changed since it was loaded from the database.
1131
+ * @returns {boolean}
1132
+ */
872
1133
  isChanged() {
873
1134
  if (this.isNewRecord() || this._hasChanges()){
874
1135
  return true
@@ -898,6 +1159,10 @@ class VelociousDatabaseRecord {
898
1159
  return false
899
1160
  }
900
1161
 
1162
+ /**
1163
+ * Returns the changes that have been made to this record since it was loaded from the database.
1164
+ * @returns {object}
1165
+ */
901
1166
  changes() {
902
1167
  const changes = {}
903
1168
 
@@ -910,12 +1175,20 @@ class VelociousDatabaseRecord {
910
1175
  return changes
911
1176
  }
912
1177
 
1178
+ /**
1179
+ * @returns {string}
1180
+ */
913
1181
  _tableName() {
914
1182
  if (this.__tableName) return this.__tableName
915
1183
 
916
1184
  return this.constructor.tableName()
917
1185
  }
918
1186
 
1187
+ /**
1188
+ * Reads an attribute value from the record.
1189
+ * @param {string} attributeName The name of the attribute to read. This is the attribute name, not the column name.
1190
+ * @returns {void}
1191
+ */
919
1192
  readAttribute(attributeName) {
920
1193
  const columnName = this.constructor._attributeNameToColumnName[attributeName]
921
1194
 
@@ -924,6 +1197,10 @@ class VelociousDatabaseRecord {
924
1197
  return this.readColumn(columnName)
925
1198
  }
926
1199
 
1200
+ /**
1201
+ * Reads a column value from the record.
1202
+ * @param {string} attributeName The name of the column to read. This is the column name, not the attribute name.
1203
+ */
927
1204
  readColumn(attributeName) {
928
1205
  const column = this.constructor.getColumns().find((column) => column.getName() == attributeName)
929
1206
  let result
@@ -961,6 +1238,9 @@ class VelociousDatabaseRecord {
961
1238
  return belongsToChanges
962
1239
  }
963
1240
 
1241
+ /**
1242
+ * @returns {void}
1243
+ */
964
1244
  async _createNewRecord() {
965
1245
  if (!this.constructor.connection()["insertSql"]) {
966
1246
  throw new Error(`No insertSql on ${this.constructor.connection().constructor.name}`)
@@ -1006,6 +1286,9 @@ class VelociousDatabaseRecord {
1006
1286
  }
1007
1287
  }
1008
1288
 
1289
+ /**
1290
+ * @returns {void}
1291
+ */
1009
1292
  async _updateRecordWithChanges() {
1010
1293
  const conditions = {}
1011
1294
 
@@ -1028,6 +1311,9 @@ class VelociousDatabaseRecord {
1028
1311
  }
1029
1312
  }
1030
1313
 
1314
+ /**
1315
+ * @returns {number|string}
1316
+ */
1031
1317
  id() {
1032
1318
  if (!this.constructor._columnNameToAttributeName) {
1033
1319
  throw new Error(`Column names mapping hasn't been set on ${this.constructor.name}. Has the model been initialized?`)
@@ -1043,9 +1329,20 @@ class VelociousDatabaseRecord {
1043
1329
  return this.readAttribute(attributeName)
1044
1330
  }
1045
1331
 
1332
+ /**
1333
+ * @returns {boolean}
1334
+ */
1046
1335
  isPersisted() { return !this._isNewRecord }
1336
+
1337
+ /**
1338
+ * @returns {boolean}
1339
+ */
1047
1340
  isNewRecord() { return this._isNewRecord }
1048
1341
 
1342
+ /**
1343
+ * @param {boolean} newIsNewRecord
1344
+ * @returns {void}
1345
+ */
1049
1346
  setIsNewRecord(newIsNewRecord) {
1050
1347
  this._isNewRecord = newIsNewRecord
1051
1348
  }
@@ -1065,6 +1362,9 @@ class VelociousDatabaseRecord {
1065
1362
  this._changes = {}
1066
1363
  }
1067
1364
 
1365
+ /**
1366
+ * @returns {void}
1367
+ */
1068
1368
  async reload() {
1069
1369
  this._reloadWithId(this.readAttribute("id"))
1070
1370
  }
@@ -1094,6 +1394,9 @@ class VelociousDatabaseRecord {
1094
1394
  }
1095
1395
  }
1096
1396
 
1397
+ /**
1398
+ * @returns {Array<string>}
1399
+ */
1097
1400
  fullErrorMessages() {
1098
1401
  const validationErrorMessages = []
1099
1402
 
@@ -1110,6 +1413,10 @@ class VelociousDatabaseRecord {
1110
1413
  return validationErrorMessages
1111
1414
  }
1112
1415
 
1416
+ /**
1417
+ * Assigns the attributes to the record and saves it.
1418
+ * @param {object} attributesToAssign - The attributes to assign to the record.
1419
+ */
1113
1420
  async update(attributesToAssign) {
1114
1421
  if (attributesToAssign) this.assign(attributesToAssign)
1115
1422