velocious 1.0.85 → 1.0.87
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/bin/velocious.js +10 -1
- package/eslint.config.js +33 -0
- package/package.json +7 -2
- package/peak_flow.yml +6 -0
- package/spec/cli/commands/db/create-spec.js +4 -0
- package/spec/cli/commands/db/migrate-spec.js +4 -2
- package/spec/cli/commands/db/rollback-spec.js +179 -0
- package/spec/cli/commands/destroy/migration-spec.js +4 -0
- package/spec/cli/commands/generate/migration-spec.js +4 -0
- package/spec/cli/commands/init-spec.js +4 -0
- package/spec/dummy/index.js +7 -4
- package/spec/dummy/src/config/configuration.example.js +2 -0
- package/spec/dummy/src/config/configuration.peakflow.mariadb.js +2 -0
- package/spec/dummy/src/config/configuration.peakflow.mssql.js +2 -0
- package/spec/dummy/src/config/configuration.peakflow.pgsql.js +2 -0
- package/spec/dummy/src/config/configuration.peakflow.sqlite.js +2 -0
- package/spec/dummy/src/database/migrations/20250921121002-create-project-details.js +3 -1
- package/src/application.js +12 -0
- package/src/cli/base-command.js +9 -5
- package/src/cli/browser-cli.js +37 -0
- package/src/cli/commands/db/create.js +5 -5
- package/src/cli/commands/db/drop.js +4 -5
- package/src/cli/commands/db/migrate.js +6 -10
- package/src/cli/commands/db/reset.js +8 -12
- package/src/cli/commands/db/rollback.js +15 -0
- package/src/cli/commands/destroy/migration.js +2 -2
- package/src/cli/commands/generate/migration.js +3 -6
- package/src/cli/commands/generate/model.js +3 -6
- package/src/cli/commands/init.js +5 -8
- package/src/cli/commands/server.js +3 -3
- package/src/cli/commands/test.js +1 -1
- package/src/cli/index.js +15 -63
- package/src/cli/use-browser-cli.js +25 -0
- package/src/configuration-resolver.js +1 -1
- package/src/configuration.js +118 -9
- package/src/controller.js +29 -0
- package/src/database/drivers/base-column.js +14 -0
- package/src/database/drivers/base-columns-index.js +3 -0
- package/src/database/drivers/base-foreign-key.js +3 -0
- package/src/database/drivers/base-table.js +3 -0
- package/src/database/drivers/base.js +55 -1
- package/src/database/drivers/mssql/index.js +64 -1
- package/src/database/drivers/mysql/columns-index.js +0 -1
- package/src/database/drivers/sqlite/base.js +39 -0
- package/src/database/drivers/sqlite/connection-remote.js +1 -1
- package/src/database/drivers/sqlite/sql/alter-table.js +1 -1
- package/src/database/drivers/sqlite/sql/delete.js +15 -10
- package/src/database/migration/index.js +122 -1
- package/src/database/migrator/files-finder.js +13 -1
- package/src/database/migrator.js +125 -24
- package/src/database/pool/single-multi-use.js +1 -1
- package/src/database/query/alter-table-base.js +11 -0
- package/src/database/query/base.js +7 -0
- package/src/database/query/create-database-base.js +3 -0
- package/src/database/query/create-index-base.js +3 -1
- package/src/database/query/create-table-base.js +3 -0
- package/src/database/query/drop-table-base.js +4 -1
- package/src/database/query/from-base.js +7 -0
- package/src/database/query/index.js +96 -6
- package/src/database/query/insert-base.js +6 -0
- package/src/database/query/join-base.js +3 -0
- package/src/database/query/order-base.js +3 -0
- package/src/database/query/select-base.js +3 -0
- package/src/database/query/update-base.js +3 -0
- package/src/database/query/where-base.js +3 -0
- package/src/database/record/index.js +272 -19
- package/src/database/record/instance-relationships/base.js +66 -1
- package/src/database/record/relationships/base.js +41 -1
- package/src/database/record/validators/base.js +10 -0
- package/src/database/record/validators/presence.js +1 -1
- package/src/database/table-data/table-column.js +37 -3
- package/src/database/table-data/table-index.js +1 -1
- package/src/database/use-database.js +2 -2
- package/src/environment-handlers/base.js +53 -0
- package/src/environment-handlers/browser.js +171 -0
- package/src/environment-handlers/node.js +162 -0
- package/src/http-server/client/request-buffer/index.js +9 -9
- package/src/http-server/index.js +6 -0
- package/src/http-server/worker-handler/index.js +20 -19
- package/src/initializer.js +17 -1
- package/src/logger.js +3 -0
- package/src/routes/app-routes.js +6 -2
- package/src/routes/base-route.js +1 -1
- package/src/routes/get-route.js +1 -1
- package/src/routes/namespace-route.js +1 -1
- package/src/routes/post-route.js +1 -1
- package/src/routes/resolver.js +1 -1
- package/src/routes/resource-route.js +1 -1
- package/src/templates/configuration.js +4 -0
- package/src/testing/request-client.js +26 -3
- package/src/testing/test-files-finder.js +2 -2
- package/src/testing/test-runner.js +74 -28
- package/src/testing/test.js +62 -0
- package/src/utils/file-exists.js +7 -5
- package/src/utils/rest-args-error.js +5 -3
package/src/database/migrator.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import {digg} from "diggerize"
|
|
2
2
|
import * as inflection from "inflection"
|
|
3
3
|
import {Logger} from "../logger.js"
|
|
4
|
+
import restArgsError from "../utils/rest-args-error.js"
|
|
4
5
|
import TableData from "./table-data/index.js"
|
|
5
6
|
|
|
6
7
|
export default class VelociousDatabaseMigrator {
|
|
7
|
-
constructor({configuration}) {
|
|
8
|
+
constructor({configuration, ...restArgs}) {
|
|
9
|
+
restArgsError(restArgs)
|
|
10
|
+
|
|
11
|
+
if (!configuration) throw new Error("configuration argument is required")
|
|
12
|
+
|
|
8
13
|
this.configuration = configuration
|
|
9
14
|
this.logger = new Logger(this)
|
|
10
15
|
}
|
|
@@ -62,13 +67,21 @@ export default class VelociousDatabaseMigrator {
|
|
|
62
67
|
requireMigration: async () => {
|
|
63
68
|
const migrationImport = await importCallback(migration.fullPath)
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
if (!migrationImport) {
|
|
71
|
+
throw new Error(`Migration file must export migration class: ${migration.fullPath}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return migrationImport
|
|
66
75
|
}
|
|
67
76
|
})
|
|
68
77
|
}
|
|
69
78
|
})
|
|
70
79
|
}
|
|
71
80
|
|
|
81
|
+
/**
|
|
82
|
+
* @param {*} requireContext
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
72
85
|
async migrateFilesFromRequireContext(requireContext) {
|
|
73
86
|
const files = requireContext
|
|
74
87
|
.keys()
|
|
@@ -111,6 +124,9 @@ export default class VelociousDatabaseMigrator {
|
|
|
111
124
|
})
|
|
112
125
|
}
|
|
113
126
|
|
|
127
|
+
/**
|
|
128
|
+
* @returns {Promise<void>}
|
|
129
|
+
*/
|
|
114
130
|
async loadMigrationsVersions() {
|
|
115
131
|
this.migrationsVersions = {}
|
|
116
132
|
|
|
@@ -142,6 +158,9 @@ export default class VelociousDatabaseMigrator {
|
|
|
142
158
|
}
|
|
143
159
|
}
|
|
144
160
|
|
|
161
|
+
/**
|
|
162
|
+
* @returns {Promise<boolean>}
|
|
163
|
+
*/
|
|
145
164
|
async migrationsTableExist(db) {
|
|
146
165
|
const schemaTable = await db.getTableByName("schema_migrations", {throwError: false})
|
|
147
166
|
|
|
@@ -150,10 +169,12 @@ export default class VelociousDatabaseMigrator {
|
|
|
150
169
|
return true
|
|
151
170
|
}
|
|
152
171
|
|
|
172
|
+
/**
|
|
173
|
+
* @returns {Promise<void>}
|
|
174
|
+
*/
|
|
153
175
|
async executeRequireContext(requireContext) {
|
|
154
176
|
const migrationFiles = requireContext.keys()
|
|
155
|
-
|
|
156
|
-
files = migrationFiles
|
|
177
|
+
const files = migrationFiles
|
|
157
178
|
.map((file) => {
|
|
158
179
|
const match = file.match(/^(\d{14})-(.+)\.js$/)
|
|
159
180
|
|
|
@@ -165,7 +186,7 @@ export default class VelociousDatabaseMigrator {
|
|
|
165
186
|
|
|
166
187
|
return {
|
|
167
188
|
file,
|
|
168
|
-
fullPath: `${migrationsPath}/${file}`,
|
|
189
|
+
fullPath: `${migrationsPath}/${file}`, // eslint-disable-line no-undef
|
|
169
190
|
date,
|
|
170
191
|
migrationClassName
|
|
171
192
|
}
|
|
@@ -181,6 +202,9 @@ export default class VelociousDatabaseMigrator {
|
|
|
181
202
|
}
|
|
182
203
|
}
|
|
183
204
|
|
|
205
|
+
/**
|
|
206
|
+
* @returns {Promise<void>}
|
|
207
|
+
*/
|
|
184
208
|
async reset() {
|
|
185
209
|
const dbs = await this.configuration.getCurrentConnections()
|
|
186
210
|
|
|
@@ -205,7 +229,7 @@ export default class VelociousDatabaseMigrator {
|
|
|
205
229
|
}
|
|
206
230
|
|
|
207
231
|
break
|
|
208
|
-
} catch (error) {
|
|
232
|
+
} catch (error) { // eslint-disable-line no-unused-vars
|
|
209
233
|
if (errors.length > 0 && anyTableDropped) {
|
|
210
234
|
// Retry
|
|
211
235
|
} else {
|
|
@@ -217,13 +241,69 @@ export default class VelociousDatabaseMigrator {
|
|
|
217
241
|
}
|
|
218
242
|
}
|
|
219
243
|
|
|
220
|
-
|
|
244
|
+
/**
|
|
245
|
+
* @param {{date: number}[]} files
|
|
246
|
+
* @param {function(string) : void} importCallback Function to import a file
|
|
247
|
+
* @returns {Promise<void>}
|
|
248
|
+
*/
|
|
249
|
+
async rollback(files, importCallback) {
|
|
250
|
+
const latestMigrationVersion = await this._latestMigrationVersion()
|
|
251
|
+
|
|
252
|
+
if (!latestMigrationVersion) {
|
|
253
|
+
throw new Error("No migrations have been run yet")
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const latestMigrationVersionNumber = parseInt(latestMigrationVersion)
|
|
257
|
+
const migration = files.find((file) => file.date == latestMigrationVersionNumber)
|
|
258
|
+
|
|
259
|
+
if (!migration) {
|
|
260
|
+
throw new Error(`Migration file for version ${latestMigrationVersionNumber} not found`)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
await this.runMigrationFile({
|
|
264
|
+
migration,
|
|
265
|
+
requireMigration: async () => await importCallback(migration.fullPath),
|
|
266
|
+
direction: "down"
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @returns {Promise<string | null>} The latest migration version
|
|
272
|
+
*/
|
|
273
|
+
async _latestMigrationVersion() {
|
|
274
|
+
if (!this.migrationsVersions) await this.loadMigrationsVersions()
|
|
275
|
+
|
|
276
|
+
let highestVersion
|
|
277
|
+
|
|
278
|
+
for (const dbIdentifier in this.migrationsVersions) {
|
|
279
|
+
for (const migrationVersion in this.migrationsVersions[dbIdentifier]) {
|
|
280
|
+
if (!highestVersion || migrationVersion > highestVersion) {
|
|
281
|
+
highestVersion = migrationVersion
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return highestVersion
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @param {object} args
|
|
291
|
+
* @param {object} args.migration
|
|
292
|
+
* @param {function() : void} args.requireMigration
|
|
293
|
+
* @param {string} args.direction
|
|
294
|
+
*/
|
|
295
|
+
async runMigrationFile({migration, requireMigration, direction = "up"}) {
|
|
221
296
|
if (!this.configuration) throw new Error("No configuration set")
|
|
222
297
|
if (!this.configuration.isDatabasePoolInitialized()) await this.configuration.initializeDatabasePool()
|
|
223
298
|
if (!this.migrationsVersions) await this.loadMigrationsVersions()
|
|
224
299
|
|
|
225
300
|
const dbs = await this.configuration.getCurrentConnections()
|
|
226
301
|
const migrationClass = await requireMigration()
|
|
302
|
+
|
|
303
|
+
if (!migrationClass || typeof migrationClass !== "function") {
|
|
304
|
+
throw new Error(`Migration ${migration.file} must export a default migration class. Type: ${typeof migrationClass}`)
|
|
305
|
+
}
|
|
306
|
+
|
|
227
307
|
const migrationDatabaseIdentifiers = migrationClass.getDatabaseIdentifiers() || ["default"]
|
|
228
308
|
|
|
229
309
|
for (const dbIdentifier in dbs) {
|
|
@@ -239,9 +319,18 @@ export default class VelociousDatabaseMigrator {
|
|
|
239
319
|
continue
|
|
240
320
|
}
|
|
241
321
|
|
|
242
|
-
if (
|
|
243
|
-
this.
|
|
244
|
-
|
|
322
|
+
if (direction == "up") {
|
|
323
|
+
if (this.hasRunMigrationVersion(dbIdentifier, migration.date)) {
|
|
324
|
+
this.logger.debug(`${dbIdentifier} has already run migration ${migration.file}`)
|
|
325
|
+
continue
|
|
326
|
+
}
|
|
327
|
+
} else if (direction == "down") {
|
|
328
|
+
if (!this.hasRunMigrationVersion(dbIdentifier, migration.date)) {
|
|
329
|
+
this.logger.debug(`${dbIdentifier} hasn't run migration ${migration.file}`)
|
|
330
|
+
continue
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
throw new Error(`Unknown direction: ${direction}`)
|
|
245
334
|
}
|
|
246
335
|
|
|
247
336
|
this.logger.debug(`Running migration on ${dbIdentifier}: ${migration.file}`, {migrationDatabaseIdentifiers})
|
|
@@ -252,23 +341,35 @@ export default class VelociousDatabaseMigrator {
|
|
|
252
341
|
configuration: this.configuration,
|
|
253
342
|
db
|
|
254
343
|
})
|
|
344
|
+
const dateString = `${digg(migration, "date")}`
|
|
345
|
+
|
|
346
|
+
if (direction == "up") {
|
|
347
|
+
if (migrationInstance.change) {
|
|
348
|
+
await migrationInstance.change()
|
|
349
|
+
} else if (migrationInstance.up) {
|
|
350
|
+
await migrationInstance.up()
|
|
351
|
+
} else {
|
|
352
|
+
throw new Error(`'change' or 'up' didn't exist on migration: ${migration.file}`)
|
|
353
|
+
}
|
|
255
354
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
} else {
|
|
261
|
-
throw new Error(`'change' or 'up' didn't exist on migration: ${migration.file}`)
|
|
262
|
-
}
|
|
355
|
+
const existingSchemaMigrations = await db.newQuery()
|
|
356
|
+
.from("schema_migrations")
|
|
357
|
+
.where({version: dateString})
|
|
358
|
+
.results()
|
|
263
359
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
.
|
|
360
|
+
if (existingSchemaMigrations.length == 0) {
|
|
361
|
+
await db.insert({tableName: "schema_migrations", data: {version: dateString}})
|
|
362
|
+
}
|
|
363
|
+
} else if (direction == "down") {
|
|
364
|
+
if (migrationInstance.down) {
|
|
365
|
+
await migrationInstance.down()
|
|
366
|
+
} else {
|
|
367
|
+
throw new Error(`'down' didn't exist on migration: ${migration.file}`)
|
|
368
|
+
}
|
|
269
369
|
|
|
270
|
-
|
|
271
|
-
|
|
370
|
+
await db.delete({tableName: "schema_migrations", conditions: {version: dateString}})
|
|
371
|
+
} else {
|
|
372
|
+
throw new Error(`Unknown direction: ${direction}`)
|
|
272
373
|
}
|
|
273
374
|
}
|
|
274
375
|
}
|
|
@@ -4,6 +4,12 @@ import restArgsError from "../../utils/rest-args-error.js"
|
|
|
4
4
|
import TableData from "../table-data/index.js"
|
|
5
5
|
|
|
6
6
|
export default class VelociousDatabaseQueryAlterTableBase extends QueryBase {
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} args
|
|
9
|
+
* @template Tdriver extends import("../driver/base.js").default
|
|
10
|
+
* @param {Tdriver} args.driver
|
|
11
|
+
* @param {TableData} args.tableData
|
|
12
|
+
*/
|
|
7
13
|
constructor({driver, tableData, ...restArgs}) {
|
|
8
14
|
restArgsError(restArgs)
|
|
9
15
|
|
|
@@ -13,6 +19,9 @@ export default class VelociousDatabaseQueryAlterTableBase extends QueryBase {
|
|
|
13
19
|
this.tableData = tableData
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
/**
|
|
23
|
+
* @returns {string[]}
|
|
24
|
+
*/
|
|
16
25
|
toSqls() {
|
|
17
26
|
const databaseType = this.getDriver().getType()
|
|
18
27
|
const sqls = []
|
|
@@ -30,6 +39,8 @@ export default class VelociousDatabaseQueryAlterTableBase extends QueryBase {
|
|
|
30
39
|
sql += column.getSQL({driver: this.getDriver(), forAlterTable: true})
|
|
31
40
|
} else if (column.getNewName()) {
|
|
32
41
|
sql += `RENAME COLUMN ${options.quoteColumnName(column.getName())} TO ${options.quoteColumnName(column.getNewName())}`
|
|
42
|
+
} else if (column.getDropColumn()) {
|
|
43
|
+
sql += `DROP COLUMN ${options.quoteColumnName}`
|
|
33
44
|
} else {
|
|
34
45
|
if (databaseType == "mssql" || databaseType == "pgsql") {
|
|
35
46
|
sql += "ALTER COLUMN "
|
|
@@ -18,6 +18,9 @@ export default class VelociousDatabaseQueryBase {
|
|
|
18
18
|
return this._driver
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @returns {import("../query-parser/options.js").default}
|
|
23
|
+
*/
|
|
21
24
|
getOptions() {
|
|
22
25
|
return this._options
|
|
23
26
|
}
|
|
@@ -26,6 +29,10 @@ export default class VelociousDatabaseQueryBase {
|
|
|
26
29
|
return this.getDriver().getType()
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @interface
|
|
34
|
+
* @returns {string[]}
|
|
35
|
+
*/
|
|
29
36
|
toSql() {
|
|
30
37
|
throw new Error("'toSql' wasn't implemented")
|
|
31
38
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {digs} from "diggerize"
|
|
2
1
|
import QueryBase from "./base.js"
|
|
3
2
|
|
|
4
3
|
export default class VelociousDatabaseQueryCreateIndexBase extends QueryBase {
|
|
@@ -35,6 +34,9 @@ export default class VelociousDatabaseQueryCreateIndexBase extends QueryBase {
|
|
|
35
34
|
return indexName
|
|
36
35
|
}
|
|
37
36
|
|
|
37
|
+
/**
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
38
40
|
toSql() {
|
|
39
41
|
const databaseType = this.getDriver().getType()
|
|
40
42
|
const indexName = this.name || this.generateIndexName()
|
|
@@ -13,6 +13,9 @@ export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
|
|
|
13
13
|
this.tableName = tableName
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @returns {string[]}
|
|
18
|
+
*/
|
|
16
19
|
toSql() {
|
|
17
20
|
const databaseType = this.getDatabaseType()
|
|
18
21
|
const options = this.getOptions()
|
|
@@ -40,6 +43,6 @@ export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
|
|
|
40
43
|
|
|
41
44
|
sqls.push(sql)
|
|
42
45
|
|
|
43
|
-
return
|
|
46
|
+
return sqls
|
|
44
47
|
}
|
|
45
48
|
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export default class VelociousDatabaseQueryFromBase {
|
|
2
|
+
/**
|
|
3
|
+
* @returns {import("../query-parser/options.js").default}
|
|
4
|
+
*/
|
|
2
5
|
getOptions() {
|
|
3
6
|
return this.query.getOptions()
|
|
4
7
|
}
|
|
5
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @interface
|
|
11
|
+
* @returns {string[]}
|
|
12
|
+
*/
|
|
6
13
|
toSql() {
|
|
7
14
|
throw new Error("'toSql' wasn't implemented")
|
|
8
15
|
}
|
|
@@ -35,6 +35,9 @@ export default class VelociousDatabaseQuery {
|
|
|
35
35
|
this._wheres = wheres
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @returns {VelociousDatabaseQuery}
|
|
40
|
+
*/
|
|
38
41
|
clone() {
|
|
39
42
|
const newQuery = new VelociousDatabaseQuery({
|
|
40
43
|
driver: this.driver,
|
|
@@ -56,6 +59,9 @@ export default class VelociousDatabaseQuery {
|
|
|
56
59
|
return newQuery
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @returns {Promise<number>}
|
|
64
|
+
*/
|
|
59
65
|
async count() {
|
|
60
66
|
// Generate count SQL
|
|
61
67
|
let sql = `COUNT(${this.driver.quoteTable(this.modelClass.tableName())}.${this.driver.quoteColumn(this.modelClass.primaryKey())})`
|
|
@@ -94,8 +100,14 @@ export default class VelociousDatabaseQuery {
|
|
|
94
100
|
return countResult
|
|
95
101
|
}
|
|
96
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @returns {import("../query-parser/options.js").default}
|
|
105
|
+
*/
|
|
97
106
|
getOptions() { return this.driver.options() }
|
|
98
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @returns {Promise<void>}
|
|
110
|
+
*/
|
|
99
111
|
async destroyAll() {
|
|
100
112
|
const records = await this.toArray()
|
|
101
113
|
|
|
@@ -104,6 +116,10 @@ export default class VelociousDatabaseQuery {
|
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
|
|
119
|
+
/**
|
|
120
|
+
* @param {number|string} recordId
|
|
121
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
122
|
+
*/
|
|
107
123
|
async find(recordId) {
|
|
108
124
|
const conditions = {}
|
|
109
125
|
|
|
@@ -119,6 +135,10 @@ export default class VelociousDatabaseQuery {
|
|
|
119
135
|
return record
|
|
120
136
|
}
|
|
121
137
|
|
|
138
|
+
/**
|
|
139
|
+
* @param {object} conditions
|
|
140
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
141
|
+
*/
|
|
122
142
|
async findBy(conditions) {
|
|
123
143
|
const newConditions = {}
|
|
124
144
|
|
|
@@ -131,6 +151,10 @@ export default class VelociousDatabaseQuery {
|
|
|
131
151
|
return await this.clone().where(newConditions).first()
|
|
132
152
|
}
|
|
133
153
|
|
|
154
|
+
/**
|
|
155
|
+
* @param {...Parameters<this["findOrInitializeBy"]>} args
|
|
156
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
157
|
+
*/
|
|
134
158
|
async findOrCreateBy(...args) {
|
|
135
159
|
const record = await this.findOrInitializeBy(...args)
|
|
136
160
|
|
|
@@ -141,6 +165,10 @@ export default class VelociousDatabaseQuery {
|
|
|
141
165
|
return record
|
|
142
166
|
}
|
|
143
167
|
|
|
168
|
+
/**
|
|
169
|
+
* @param {object} conditions
|
|
170
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
171
|
+
*/
|
|
144
172
|
async findByOrFail(conditions) {
|
|
145
173
|
const newConditions = {}
|
|
146
174
|
|
|
@@ -159,6 +187,11 @@ export default class VelociousDatabaseQuery {
|
|
|
159
187
|
return model
|
|
160
188
|
}
|
|
161
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @param {object} conditions
|
|
192
|
+
* @param {function() : void} callback
|
|
193
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
194
|
+
*/
|
|
162
195
|
async findOrInitializeBy(conditions, callback) {
|
|
163
196
|
const record = await this.findBy(conditions)
|
|
164
197
|
|
|
@@ -173,6 +206,9 @@ export default class VelociousDatabaseQuery {
|
|
|
173
206
|
return newRecord
|
|
174
207
|
}
|
|
175
208
|
|
|
209
|
+
/**
|
|
210
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
211
|
+
*/
|
|
176
212
|
async first() {
|
|
177
213
|
const newQuery = this.clone().limit(1).reorder(`${this.driver.quoteTable(this.modelClass.tableName())}.${this.driver.quoteColumn(this.modelClass.orderableColumn())}`)
|
|
178
214
|
const results = await newQuery.toArray()
|
|
@@ -180,6 +216,10 @@ export default class VelociousDatabaseQuery {
|
|
|
180
216
|
return results[0]
|
|
181
217
|
}
|
|
182
218
|
|
|
219
|
+
/**
|
|
220
|
+
* @param {string|FromPlain} from
|
|
221
|
+
* @returns {this}
|
|
222
|
+
*/
|
|
183
223
|
from(from) {
|
|
184
224
|
if (typeof from == "string") from = new FromPlain({plain: from, query: this})
|
|
185
225
|
|
|
@@ -189,11 +229,19 @@ export default class VelociousDatabaseQuery {
|
|
|
189
229
|
return this
|
|
190
230
|
}
|
|
191
231
|
|
|
232
|
+
/**
|
|
233
|
+
* @param {string} group
|
|
234
|
+
* @returns {this}
|
|
235
|
+
*/
|
|
192
236
|
group(group) {
|
|
193
237
|
this._groups.push(group)
|
|
194
238
|
return this
|
|
195
239
|
}
|
|
196
240
|
|
|
241
|
+
/**
|
|
242
|
+
* @param {string|JoinPlain} join
|
|
243
|
+
* @returns {this}
|
|
244
|
+
*/
|
|
197
245
|
joins(join) {
|
|
198
246
|
if (typeof join == "string") {
|
|
199
247
|
join = new JoinPlain({plain: join, query: this})
|
|
@@ -207,6 +255,9 @@ export default class VelociousDatabaseQuery {
|
|
|
207
255
|
return this
|
|
208
256
|
}
|
|
209
257
|
|
|
258
|
+
/**
|
|
259
|
+
* @returns {Promise<InstanceType<this["modelClass"]>>}
|
|
260
|
+
*/
|
|
210
261
|
async last() {
|
|
211
262
|
const primaryKey = this.modelClass.primaryKey()
|
|
212
263
|
const tableName = this.modelClass.tableName()
|
|
@@ -215,16 +266,28 @@ export default class VelociousDatabaseQuery {
|
|
|
215
266
|
return results[0]
|
|
216
267
|
}
|
|
217
268
|
|
|
269
|
+
/**
|
|
270
|
+
* @param {number} value
|
|
271
|
+
* @returns {this}
|
|
272
|
+
*/
|
|
218
273
|
limit(value) {
|
|
219
274
|
this._limit = value
|
|
220
275
|
return this
|
|
221
276
|
}
|
|
222
277
|
|
|
278
|
+
/**
|
|
279
|
+
* @param {number} value
|
|
280
|
+
* @returns {this}
|
|
281
|
+
*/
|
|
223
282
|
offset(value) {
|
|
224
283
|
this._offset = value
|
|
225
284
|
return this
|
|
226
285
|
}
|
|
227
286
|
|
|
287
|
+
/**
|
|
288
|
+
* @param {*} order
|
|
289
|
+
* @returns {this}
|
|
290
|
+
*/
|
|
228
291
|
order(order) {
|
|
229
292
|
if (typeof order == "number" || typeof order == "string") order = new OrderPlain({plain: order, query: this})
|
|
230
293
|
|
|
@@ -234,6 +297,10 @@ export default class VelociousDatabaseQuery {
|
|
|
234
297
|
return this
|
|
235
298
|
}
|
|
236
299
|
|
|
300
|
+
/**
|
|
301
|
+
* @param {number} pageNumber
|
|
302
|
+
* @returns {this}
|
|
303
|
+
*/
|
|
237
304
|
page(pageNumber) {
|
|
238
305
|
const perPage = this._perPage || 30
|
|
239
306
|
const offset = (pageNumber - 1) * perPage
|
|
@@ -245,22 +312,37 @@ export default class VelociousDatabaseQuery {
|
|
|
245
312
|
return this
|
|
246
313
|
}
|
|
247
314
|
|
|
315
|
+
/**
|
|
316
|
+
* @param {number} perPage
|
|
317
|
+
* @returns {this}
|
|
318
|
+
*/
|
|
248
319
|
perPage(perPage) {
|
|
249
320
|
this._perPage = perPage
|
|
250
321
|
return this
|
|
251
322
|
}
|
|
252
323
|
|
|
324
|
+
/**
|
|
325
|
+
* @param {string} data
|
|
326
|
+
* @returns {this}
|
|
327
|
+
*/
|
|
253
328
|
preload(data) {
|
|
254
329
|
incorporate(this._preload, data)
|
|
255
330
|
return this
|
|
256
331
|
}
|
|
257
332
|
|
|
333
|
+
/**
|
|
334
|
+
* @param {string|OrderPlain} order
|
|
335
|
+
* @returns {this}
|
|
336
|
+
*/
|
|
258
337
|
reorder(order) {
|
|
259
338
|
this._orders = []
|
|
260
339
|
this.order(order)
|
|
261
340
|
return this
|
|
262
341
|
}
|
|
263
342
|
|
|
343
|
+
/**
|
|
344
|
+
* @returns {this}
|
|
345
|
+
*/
|
|
264
346
|
reverseOrder() {
|
|
265
347
|
for (const order of this._orders) {
|
|
266
348
|
order.setReverseOrder(true)
|
|
@@ -269,6 +351,10 @@ export default class VelociousDatabaseQuery {
|
|
|
269
351
|
return this
|
|
270
352
|
}
|
|
271
353
|
|
|
354
|
+
/**
|
|
355
|
+
* @param {string|SelectPlain} select
|
|
356
|
+
* @returns {this}
|
|
357
|
+
*/
|
|
272
358
|
select(select) {
|
|
273
359
|
if (Array.isArray(select)) {
|
|
274
360
|
for (const selectInArray of select) {
|
|
@@ -286,23 +372,28 @@ export default class VelociousDatabaseQuery {
|
|
|
286
372
|
return this
|
|
287
373
|
}
|
|
288
374
|
|
|
375
|
+
/**
|
|
376
|
+
* @returns {Promise<Array<object>>} Array of results from the database
|
|
377
|
+
*/
|
|
289
378
|
async _executeQuery() {
|
|
290
379
|
const sql = this.toSql()
|
|
291
380
|
const results = await this.driver.query(sql)
|
|
292
381
|
|
|
293
|
-
this.logger.debug("SQL:", sql)
|
|
382
|
+
this.logger.debug(() => ["SQL:", sql])
|
|
294
383
|
|
|
295
384
|
return results
|
|
296
385
|
}
|
|
297
386
|
|
|
387
|
+
/**
|
|
388
|
+
* @returns {Promise<Array<object>>} Array of results from the database
|
|
389
|
+
*/
|
|
298
390
|
async results() {
|
|
299
391
|
return await this._executeQuery()
|
|
300
392
|
}
|
|
301
393
|
|
|
302
394
|
/**
|
|
303
395
|
* Converts query results to array of model instances
|
|
304
|
-
*
|
|
305
|
-
* @returns {Promise<Array>} Array of model instances
|
|
396
|
+
* @returns {Promise<Array<InstanceType<this["modelClass"]>>>}
|
|
306
397
|
*/
|
|
307
398
|
async toArray() {
|
|
308
399
|
const models = []
|
|
@@ -330,13 +421,12 @@ export default class VelociousDatabaseQuery {
|
|
|
330
421
|
|
|
331
422
|
/**
|
|
332
423
|
* Generates SQL string representing this query
|
|
333
|
-
*
|
|
334
|
-
* @returns {String} SQL string representing this query
|
|
424
|
+
* @returns {string} SQL string representing this query
|
|
335
425
|
*/
|
|
336
426
|
toSql() { return this.driver.queryToSql(this) }
|
|
337
427
|
|
|
338
428
|
/**
|
|
339
|
-
* @param {
|
|
429
|
+
* @param {object|string} where
|
|
340
430
|
* @returns {VelociousDatabaseQuery} This query instance
|
|
341
431
|
*/
|
|
342
432
|
where(where) {
|
|
@@ -16,10 +16,16 @@ export default class VelociousDatabaseQueryInsertBase {
|
|
|
16
16
|
this.tableName = tableName
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @returns {import("../query-parser/options.js").default}
|
|
21
|
+
*/
|
|
19
22
|
getOptions() {
|
|
20
23
|
return this.driver.options()
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @returns {string} SQL statement
|
|
28
|
+
*/
|
|
23
29
|
toSql() {
|
|
24
30
|
const {driver} = this
|
|
25
31
|
|