velocious 1.0.4 → 1.0.6
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/index.mjs +1 -19
- package/package.json +6 -3
- package/spec/cli/commands/db/create-spec.mjs +1 -1
- package/spec/cli/commands/db/migrate-spec.mjs +2 -0
- package/spec/database/connection/drivers/mysql/query-parser-spec.mjs +6 -5
- package/spec/database/drivers/mysql/connection-spec.mjs +2 -3
- package/spec/database/record/create-spec.mjs +9 -0
- package/spec/database/record/find-spec.mjs +0 -1
- package/spec/database/record/query-spec.mjs +37 -0
- package/spec/dummy/index.mjs +14 -2
- package/spec/dummy/src/config/configuration.example.mjs +16 -1
- package/spec/dummy/src/config/configuration.peakflow.mjs +16 -1
- package/spec/dummy/src/database/migrations/20230728075328-create-projects.mjs +0 -1
- package/spec/dummy/src/database/migrations/20230728075329-create-tasks.mjs +0 -1
- package/spec/dummy/src/database/migrations/20250605133926-create-project-translations.mjs +16 -0
- package/spec/dummy/src/models/project.mjs +9 -0
- package/spec/dummy/src/models/task.mjs +6 -2
- package/src/big-brother.mjs +37 -0
- package/src/cli/commands/db/create.mjs +8 -6
- package/src/cli/commands/db/migrate.mjs +1 -2
- package/src/cli/commands/generate/migration.mjs +1 -1
- package/src/cli/commands/generate/model.mjs +1 -1
- package/src/configuration.mjs +39 -3
- package/src/database/drivers/base.mjs +60 -0
- package/src/database/drivers/mysql/column.mjs +8 -0
- package/src/database/drivers/mysql/index.mjs +34 -2
- package/src/database/drivers/mysql/options.mjs +1 -0
- package/src/database/drivers/mysql/query-parser.mjs +2 -23
- package/src/database/drivers/mysql/table.mjs +25 -0
- package/src/database/drivers/sqlite/base.mjs +108 -0
- package/src/database/drivers/sqlite/column.mjs +10 -0
- package/src/database/drivers/sqlite/index.native.mjs +22 -63
- package/src/database/drivers/sqlite/index.web.mjs +28 -37
- package/src/database/drivers/sqlite/options.mjs +2 -1
- package/src/database/drivers/sqlite/query-parser.mjs +2 -23
- package/src/database/drivers/sqlite/query.native.mjs +16 -1
- package/src/database/drivers/sqlite/query.web.mjs +27 -2
- package/src/database/drivers/sqlite/sql/create-index.mjs +4 -0
- package/src/database/drivers/sqlite/table.mjs +24 -0
- package/src/database/initializer-from-require-context.mjs +21 -0
- package/src/database/migrate-from-require-context.mjs +11 -2
- package/src/database/migration/index.mjs +34 -2
- package/src/database/migrator.mjs +75 -0
- package/src/database/pool/async-tracked-multi-connection.mjs +1 -1
- package/src/database/pool/base.mjs +19 -1
- package/src/database/pool/single-multi-use.mjs +1 -1
- package/src/database/query/base.mjs +2 -1
- package/src/database/query/create-index-base.mjs +50 -0
- package/src/database/query/create-table-base.mjs +40 -17
- package/src/database/query/index.mjs +83 -21
- package/src/database/query/insert-base.mjs +4 -0
- package/src/database/query/preloader/belongs-to.mjs +52 -0
- package/src/database/query/preloader/has-many.mjs +55 -0
- package/src/database/query/preloader.mjs +41 -0
- package/src/database/query/where-base.mjs +9 -0
- package/src/database/query/where-hash.mjs +35 -0
- package/src/database/query/where-plain.mjs +13 -0
- package/src/database/query-parser/base-query-parser.mjs +33 -0
- package/src/database/query-parser/group-parser.mjs +40 -0
- package/src/database/query-parser/joins-parser.mjs +48 -7
- package/src/database/query-parser/limit-parser.mjs +40 -0
- package/src/database/query-parser/options.mjs +4 -3
- package/src/database/query-parser/order-parser.mjs +39 -0
- package/src/database/query-parser/select-parser.mjs +5 -1
- package/src/database/query-parser/where-parser.mjs +39 -0
- package/src/database/record/index.mjs +464 -29
- package/src/database/record/instance-relationships/base.mjs +28 -0
- package/src/database/record/instance-relationships/belongs-to.mjs +20 -0
- package/src/database/record/instance-relationships/has-many.mjs +47 -0
- package/src/database/record/relationships/base.mjs +32 -0
- package/src/database/record/relationships/belongs-to.mjs +12 -0
- package/src/database/record/relationships/has-many.mjs +12 -0
- package/src/database/table-data/index.mjs +15 -25
- package/src/http-server/worker-handler/worker-thread.mjs +7 -4
- package/src/templates/generate-model.mjs +3 -1
- package/src/utils/rest-args-error.mjs +9 -0
- package/src/database/drivers/index.mjs +0 -5
- package/src/database/index.mjs +0 -15
- package/src/database/migrator/index.mjs +0 -15
package/index.mjs
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import Cli from "./src/cli/index.mjs"
|
|
3
|
-
import Configuration from "./src/configuration.mjs"
|
|
4
|
-
import Controller from "./src/controller.mjs"
|
|
5
|
-
import Database from "./src/database/index.mjs"
|
|
6
|
-
import HttpServer from "./src/http-server/index.mjs"
|
|
7
|
-
import Routes from "./src/routes/index.mjs"
|
|
8
|
-
import Spec from "./src/spec/index.mjs"
|
|
9
|
-
|
|
10
|
-
export {
|
|
11
|
-
Application,
|
|
12
|
-
Cli,
|
|
13
|
-
Configuration,
|
|
14
|
-
Controller,
|
|
15
|
-
Database,
|
|
16
|
-
HttpServer,
|
|
17
|
-
Routes,
|
|
18
|
-
Spec
|
|
19
|
-
}
|
|
1
|
+
export {}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"velocious": "bin/velocious.mjs"
|
|
4
4
|
},
|
|
5
5
|
"name": "velocious",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.6",
|
|
7
7
|
"main": "index.mjs",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"test": "jasmine",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git+https://github.com/kaspernj/velocious.git"
|
|
16
16
|
},
|
|
17
|
-
"author": "
|
|
17
|
+
"author": "kasper@diestoeckels.de",
|
|
18
18
|
"license": "ISC",
|
|
19
19
|
"bugs": {
|
|
20
20
|
"url": "https://github.com/kaspernj/velocious/issues"
|
|
@@ -24,14 +24,17 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"jasmine": "^5.0.2",
|
|
26
26
|
"mysql": "^2.18.1",
|
|
27
|
-
"node-fetch": "^3.3.1"
|
|
27
|
+
"node-fetch": "^3.3.1",
|
|
28
|
+
"require-context": "^1.1.0"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
31
|
+
"better-localstorage": "^1.0.7",
|
|
30
32
|
"diggerize": "^1.0.5",
|
|
31
33
|
"ejs": "^3.1.6",
|
|
32
34
|
"escape-string-regexp": "^1.0.5",
|
|
33
35
|
"incorporator": "^1.0.2",
|
|
34
36
|
"inflection": "^3.0.0",
|
|
37
|
+
"sql-escape-string": "^1.1.0",
|
|
35
38
|
"sql.js": "^1.12.0",
|
|
36
39
|
"strftime": "^0.10.2"
|
|
37
40
|
}
|
|
@@ -17,7 +17,7 @@ describe("Cli - Commands - db:create", () => {
|
|
|
17
17
|
sql: 'CREATE DATABASE IF NOT EXISTS `velocious_test`'
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
|
-
createSchemaMigrationsTableSql: 'CREATE TABLE IF NOT EXISTS schema_migrations (`version` varchar(255) PRIMARY KEY)'
|
|
20
|
+
createSchemaMigrationsTableSql: 'CREATE TABLE IF NOT EXISTS schema_migrations (`version` varchar(255) PRIMARY KEY NOT NULL)'
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
)
|
|
@@ -17,6 +17,7 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
17
17
|
await db.withConnection(async () => {
|
|
18
18
|
await db.query("DROP TABLE IF EXISTS tasks")
|
|
19
19
|
await db.query("DROP TABLE IF EXISTS projects")
|
|
20
|
+
await db.query("DROP TABLE IF EXISTS project_translations")
|
|
20
21
|
})
|
|
21
22
|
|
|
22
23
|
await cli.execute()
|
|
@@ -29,6 +30,7 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
29
30
|
|
|
30
31
|
expect(tablesResult).toEqual(
|
|
31
32
|
[
|
|
33
|
+
{Tables_in_velocious_test: "project_translations"},
|
|
32
34
|
{Tables_in_velocious_test: "projects"},
|
|
33
35
|
{Tables_in_velocious_test: "tasks"}
|
|
34
36
|
]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import DatabaseHandler from "../../../../../src/database/handler.mjs"
|
|
2
|
+
import DatabaseQuery from "../../../../../src/database/query/index.mjs"
|
|
2
3
|
import MysqlQueryParser from "../../../../../src/database/drivers/mysql/query-parser.mjs"
|
|
3
4
|
|
|
4
5
|
import FromTable from "../../../../../src/database/query/from-table.mjs"
|
|
@@ -10,8 +11,8 @@ const mysqlDriver = new MysqlDriverClass()
|
|
|
10
11
|
|
|
11
12
|
describe("database - connection - drivers - mysql - query parser", () => {
|
|
12
13
|
it("generates sql with selects, joins and orders", () => {
|
|
13
|
-
const handler = new
|
|
14
|
-
const query = new
|
|
14
|
+
const handler = new DatabaseHandler()
|
|
15
|
+
const query = new DatabaseQuery({driver: mysqlDriver, handler})
|
|
15
16
|
.select(["tasks.id", "tasks.name"])
|
|
16
17
|
.from("tasks")
|
|
17
18
|
.joins("LEFT JOIN projects ON projects.id = tasks.project_id")
|
|
@@ -22,8 +23,8 @@ describe("database - connection - drivers - mysql - query parser", () => {
|
|
|
22
23
|
})
|
|
23
24
|
|
|
24
25
|
it("generates sql with selects, joins and orders", () => {
|
|
25
|
-
const handler = new
|
|
26
|
-
const query = new
|
|
26
|
+
const handler = new DatabaseHandler()
|
|
27
|
+
const query = new DatabaseQuery({driver: mysqlDriver, handler})
|
|
27
28
|
.select([
|
|
28
29
|
new SelectTableAndColumn({tableName: "tasks", columnName: "id"}),
|
|
29
30
|
new SelectTableAndColumn({tableName: "tasks", columnName: "name"})
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import DatabaseDriversMysql from "../../../../src/database/drivers/mysql/index.mjs"
|
|
2
2
|
import configuration from "../../../dummy/src/config/configuration.mjs"
|
|
3
3
|
import {digg} from "diggerize"
|
|
4
4
|
|
|
5
5
|
const mysqlConfig = digg(configuration, "database", "default", "master")
|
|
6
|
-
const Mysql = Database.Drivers.Mysql
|
|
7
6
|
|
|
8
7
|
describe("Database - Drivers - Mysql - Connection", () => {
|
|
9
8
|
it("connects", async () => {
|
|
10
|
-
const mysql = new
|
|
9
|
+
const mysql = new DatabaseDriversMysql(mysqlConfig)
|
|
11
10
|
|
|
12
11
|
await mysql.connect()
|
|
13
12
|
|
|
@@ -5,10 +5,19 @@ describe("Record - create", () => {
|
|
|
5
5
|
it("creates a new simple record", async () => {
|
|
6
6
|
await Dummy.run(async () => {
|
|
7
7
|
const task = new Task({name: "Test task"})
|
|
8
|
+
const project = task.buildProject({nameEn: "Test project", nameDe: "Test projekt"})
|
|
8
9
|
|
|
9
10
|
await task.save()
|
|
10
11
|
|
|
11
12
|
expect(task.id()).not.toBeUndefined()
|
|
13
|
+
expect(task.name()).toEqual("Test task")
|
|
14
|
+
expect(task.project().id()).toEqual(project.id())
|
|
15
|
+
expect(task.project()).toEqual(project)
|
|
16
|
+
|
|
17
|
+
expect(project.id()).not.toBeUndefined()
|
|
18
|
+
expect(project.name()).toEqual("Test project")
|
|
19
|
+
expect(project.nameDe()).toEqual("Test projekt")
|
|
20
|
+
expect(project.nameEn()).toEqual("Test project")
|
|
12
21
|
})
|
|
13
22
|
})
|
|
14
23
|
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Dummy from "../../dummy/index.mjs"
|
|
2
|
+
import Task from "../../dummy/src/models/task.mjs"
|
|
3
|
+
|
|
4
|
+
describe("Record - query", () => {
|
|
5
|
+
it("queries for records", async () => {
|
|
6
|
+
await Dummy.run(async () => {
|
|
7
|
+
const task = new Task({name: "Test task"})
|
|
8
|
+
const project = task.buildProject({nameEn: "Test project", nameDe: "Test projekt"})
|
|
9
|
+
|
|
10
|
+
await task.save()
|
|
11
|
+
|
|
12
|
+
expect(task.id()).not.toBeUndefined()
|
|
13
|
+
expect(task.name()).toEqual("Test task")
|
|
14
|
+
expect(task.project().id()).toEqual(project.id())
|
|
15
|
+
expect(task.project()).toEqual(project)
|
|
16
|
+
|
|
17
|
+
expect(project.id()).not.toBeUndefined()
|
|
18
|
+
expect(project.name()).toEqual("Test project")
|
|
19
|
+
expect(project.nameDe()).toEqual("Test projekt")
|
|
20
|
+
expect(project.nameEn()).toEqual("Test project")
|
|
21
|
+
|
|
22
|
+
const tasks = await Task.preload({project: {translations: true}}).toArray()
|
|
23
|
+
const newTask = tasks[0]
|
|
24
|
+
const newProject = newTask.project()
|
|
25
|
+
|
|
26
|
+
expect(newTask.id()).not.toBeUndefined()
|
|
27
|
+
expect(newTask.name()).toEqual("Test task")
|
|
28
|
+
expect(task.project().id()).toEqual(newProject.id())
|
|
29
|
+
expect(newTask.project()).toEqual(newProject)
|
|
30
|
+
|
|
31
|
+
expect(newProject.id()).not.toBeUndefined()
|
|
32
|
+
expect(newProject.name()).toEqual("Test project")
|
|
33
|
+
expect(newProject.nameDe()).toEqual("Test projekt")
|
|
34
|
+
expect(newProject.nameEn()).toEqual("Test project")
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
})
|
package/spec/dummy/index.mjs
CHANGED
|
@@ -11,11 +11,23 @@ export default class Dummy {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
static async prepare() {
|
|
14
|
+
dummyConfiguration.setCurrent()
|
|
15
|
+
|
|
14
16
|
const db = dummyConfiguration.getDatabasePool()
|
|
15
17
|
|
|
16
18
|
await db.withConnection(async () => {
|
|
17
19
|
await db.query("DROP TABLE IF EXISTS tasks")
|
|
18
|
-
await db.query("
|
|
20
|
+
await db.query("DROP TABLE IF EXISTS projects")
|
|
21
|
+
await db.query("DROP TABLE IF EXISTS project_translations")
|
|
22
|
+
|
|
23
|
+
await db.query("CREATE TABLE tasks (id MEDIUMINT NOT NULL AUTO_INCREMENT, project_id MEDIUMINT, name VARCHAR(255), description TEXT, PRIMARY KEY (id))")
|
|
24
|
+
await db.query("CREATE TABLE projects (id MEDIUMINT NOT NULL AUTO_INCREMENT, PRIMARY KEY (id))")
|
|
25
|
+
await db.query("CREATE TABLE project_translations (id MEDIUMINT NOT NULL AUTO_INCREMENT, project_id MEDIUMINT, locale VARCHAR(255), name VARCHAR(255), PRIMARY KEY (id))")
|
|
26
|
+
await db.query("CREATE UNIQUE INDEX unique_project_translation ON project_translations (project_id, locale)")
|
|
27
|
+
|
|
28
|
+
if (!dummyConfiguration.isInitialized()) {
|
|
29
|
+
await dummyConfiguration.initialize()
|
|
30
|
+
}
|
|
19
31
|
})
|
|
20
32
|
}
|
|
21
33
|
|
|
@@ -25,10 +37,10 @@ export default class Dummy {
|
|
|
25
37
|
|
|
26
38
|
async run(callback) {
|
|
27
39
|
await dummyConfiguration.getDatabasePool().withConnection(async () => {
|
|
40
|
+
await Dummy.prepare()
|
|
28
41
|
await this.start()
|
|
29
42
|
|
|
30
43
|
try {
|
|
31
|
-
await Dummy.prepare()
|
|
32
44
|
await callback()
|
|
33
45
|
} finally {
|
|
34
46
|
await this.stop()
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import AsyncTrackedMultiConnection from "../../../../src/database/pool/async-tracked-multi-connection.mjs"
|
|
2
2
|
import Configuration from "../../../../src/configuration.mjs"
|
|
3
3
|
import dummyDirectory from "../../dummy-directory.mjs"
|
|
4
|
+
import fs from "fs/promises"
|
|
5
|
+
import InitializerFromRequireContext from "../../../../src/database/initializer-from-require-context.mjs"
|
|
4
6
|
import MysqlDriver from "../../../../src/database/drivers/mysql/index.mjs"
|
|
7
|
+
import path from "path"
|
|
8
|
+
import requireContext from "require-context"
|
|
5
9
|
|
|
6
10
|
export default new Configuration({
|
|
7
11
|
database: {
|
|
@@ -17,5 +21,16 @@ export default new Configuration({
|
|
|
17
21
|
}
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
|
-
directory: dummyDirectory()
|
|
24
|
+
directory: dummyDirectory(),
|
|
25
|
+
initializeModels: async ({configuration}) => {
|
|
26
|
+
const modelsPath = await fs.realpath(`${path.dirname(import.meta.dirname)}/../src/models`)
|
|
27
|
+
const requireContextModels = requireContext(modelsPath, true, /^(.+)\.mjs$/)
|
|
28
|
+
const initializerFromRequireContext = new InitializerFromRequireContext({requireContext: requireContextModels})
|
|
29
|
+
|
|
30
|
+
await configuration.getDatabasePool().withConnection(async () => {
|
|
31
|
+
await initializerFromRequireContext.initialize({configuration})
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
locale: () => "en",
|
|
35
|
+
locales: ["de", "en"]
|
|
21
36
|
})
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import AsyncTrackedMultiConnection from "../../../../src/database/pool/async-tracked-multi-connection.mjs"
|
|
2
2
|
import Configuration from "../../../../src/configuration.mjs"
|
|
3
3
|
import dummyDirectory from "../../dummy-directory.mjs"
|
|
4
|
+
import fs from "fs/promises"
|
|
5
|
+
import InitializerFromRequireContext from "../../../../src/database/initializer-from-require-context.mjs"
|
|
4
6
|
import MysqlDriver from "../../../../src/database/drivers/mysql/index.mjs"
|
|
7
|
+
import path from "path"
|
|
8
|
+
import requireContext from "require-context"
|
|
5
9
|
|
|
6
10
|
export default new Configuration({
|
|
7
11
|
database: {
|
|
@@ -18,5 +22,16 @@ export default new Configuration({
|
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
|
-
directory: dummyDirectory()
|
|
25
|
+
directory: dummyDirectory(),
|
|
26
|
+
initializeModels: async ({configuration}) => {
|
|
27
|
+
const modelsPath = await fs.realpath(`${path.dirname(import.meta.dirname)}/../src/models`)
|
|
28
|
+
const requireContextModels = requireContext(modelsPath, true, /^(.+)\.mjs$/)
|
|
29
|
+
const initializerFromRequireContext = new InitializerFromRequireContext({requireContext: requireContextModels})
|
|
30
|
+
|
|
31
|
+
await configuration.getDatabasePool().withConnection(async () => {
|
|
32
|
+
await initializerFromRequireContext.initialize({configuration})
|
|
33
|
+
})
|
|
34
|
+
},
|
|
35
|
+
locale: () => "en",
|
|
36
|
+
locales: ["de", "en"]
|
|
22
37
|
})
|
|
@@ -3,7 +3,6 @@ import Migration from "../../../../../src/database/migration/index.mjs"
|
|
|
3
3
|
export default class CreateProjects extends Migration {
|
|
4
4
|
async change() {
|
|
5
5
|
await this.createTable("projects", (table) => {
|
|
6
|
-
table.bigint("id", {autoIncrement: true, primaryKey: true})
|
|
7
6
|
table.string("name", {maxLength: 100, null: false})
|
|
8
7
|
table.timestamps()
|
|
9
8
|
})
|
|
@@ -3,7 +3,6 @@ import Migration from "../../../../../src/database/migration/index.mjs"
|
|
|
3
3
|
export default class CreateTasks extends Migration {
|
|
4
4
|
async change() {
|
|
5
5
|
await this.createTable("tasks", (table) => {
|
|
6
|
-
table.bigint("id", {autoIncrement: true, primaryKey: true})
|
|
7
6
|
table.references("project")
|
|
8
7
|
table.string("name")
|
|
9
8
|
table.text("description")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Migration from "../../../../../src/database/migration/index.mjs"
|
|
2
|
+
|
|
3
|
+
export default class CreateProjectTranslations extends Migration {
|
|
4
|
+
async up() {
|
|
5
|
+
await this.createTable("project_translations", (t) => {
|
|
6
|
+
t.references("project", {null: false})
|
|
7
|
+
t.string("locale", {null: false})
|
|
8
|
+
t.string("name")
|
|
9
|
+
t.timestamps()
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async down() {
|
|
14
|
+
await this.dropTable("project_translations")
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import DatabaseRecord from "../../../../src/database/record/index.mjs"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class Task extends DatabaseRecord {
|
|
4
4
|
}
|
|
5
|
+
|
|
6
|
+
Task.belongsTo("project")
|
|
7
|
+
|
|
8
|
+
export default Task
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export default class VelociousBigBrother {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.enabledLoggers = {
|
|
4
|
+
databaseQuery: false
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
checkExists(name) {
|
|
9
|
+
if (!(name in this.enabledLoggers)) throw new Error(`Invalid logger name: ${name}`)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
isEnabled(name) {
|
|
13
|
+
this.checkExists(name)
|
|
14
|
+
|
|
15
|
+
return this.enabledLoggers[name]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async run({after, before, name}, callback) {
|
|
19
|
+
this.checkExists(name)
|
|
20
|
+
|
|
21
|
+
if (!this.enabledLoggers[name]) {
|
|
22
|
+
return await callback()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (before) {
|
|
26
|
+
before()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const startTime = new Date()
|
|
30
|
+
const result = await callback()
|
|
31
|
+
const endTime = new Date()
|
|
32
|
+
|
|
33
|
+
if (after) {
|
|
34
|
+
after({result})
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -39,12 +39,14 @@ export default class DbCreate extends BaseCommand{
|
|
|
39
39
|
|
|
40
40
|
schemaMigrationsTable.string("version", {null: false, primaryKey: true})
|
|
41
41
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
const createSchemaMigrationsTableSqls = this.databaseConnection.createTableSql(schemaMigrationsTable)
|
|
43
|
+
|
|
44
|
+
for (const createSchemaMigrationsTableSql of createSchemaMigrationsTableSqls) {
|
|
45
|
+
if (this.args.testing) {
|
|
46
|
+
this.result.push({createSchemaMigrationsTableSql})
|
|
47
|
+
} else {
|
|
48
|
+
await this.databaseConnection.query(createSchemaMigrationsTableSql)
|
|
49
|
+
}
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import BaseCommand from "../../base-command.mjs"
|
|
2
|
-
import {digg} from "diggerize"
|
|
3
2
|
import fs from "node:fs/promises"
|
|
4
|
-
import inflection from "inflection"
|
|
3
|
+
import * as inflection from "inflection"
|
|
5
4
|
|
|
6
5
|
export default class DbMigrate extends BaseCommand {
|
|
7
6
|
async execute() {
|
|
@@ -3,7 +3,7 @@ import {dirname} from "path"
|
|
|
3
3
|
import {fileURLToPath} from "url"
|
|
4
4
|
import fileExists from "../../../utils/file-exists.mjs"
|
|
5
5
|
import fs from "node:fs/promises"
|
|
6
|
-
import inflection from "inflection"
|
|
6
|
+
import * as inflection from "inflection"
|
|
7
7
|
import strftime from "strftime"
|
|
8
8
|
|
|
9
9
|
export default class DbGenerateMigration extends BaseCommand {
|
|
@@ -3,7 +3,7 @@ import {dirname} from "path"
|
|
|
3
3
|
import {fileURLToPath} from "url"
|
|
4
4
|
import fileExists from "../../../utils/file-exists.mjs"
|
|
5
5
|
import fs from "node:fs/promises"
|
|
6
|
-
import inflection from "inflection"
|
|
6
|
+
import * as inflection from "inflection"
|
|
7
7
|
|
|
8
8
|
export default class DbGenerateModel extends BaseCommand {
|
|
9
9
|
async execute() {
|
package/src/configuration.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {digg} from "diggerize"
|
|
2
|
+
import restArgsError from "./utils/rest-args-error.mjs"
|
|
2
3
|
|
|
3
4
|
export default class VelociousConfiguration {
|
|
4
5
|
static current(throwError = true) {
|
|
@@ -7,10 +8,19 @@ export default class VelociousConfiguration {
|
|
|
7
8
|
return this.velociousConfiguration
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
constructor({database, debug, directory}) {
|
|
11
|
+
constructor({database, debug, directory, initializeModels, locale, locales, ...restArgs}) {
|
|
12
|
+
restArgsError(restArgs)
|
|
13
|
+
|
|
14
|
+
if (!initializeModels) throw new Error("initializeModels wasn't given")
|
|
15
|
+
|
|
11
16
|
this.database = database
|
|
12
17
|
this.debug = debug
|
|
13
18
|
this._directory = directory
|
|
19
|
+
this._initializeModels = initializeModels
|
|
20
|
+
this._isInitialized = false
|
|
21
|
+
this.locale = locale
|
|
22
|
+
this.locales = locales
|
|
23
|
+
this.modelClasses = {}
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
getDatabasePool() {
|
|
@@ -39,6 +49,26 @@ export default class VelociousConfiguration {
|
|
|
39
49
|
return this._directory
|
|
40
50
|
}
|
|
41
51
|
|
|
52
|
+
getLocale() {
|
|
53
|
+
if (typeof this.locale == "function") {
|
|
54
|
+
return this.locale()
|
|
55
|
+
} else if (this.locale) {
|
|
56
|
+
return this.locale
|
|
57
|
+
} else {
|
|
58
|
+
return this.getLocales()[0]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getLocales = () => digg(this, "locales")
|
|
63
|
+
|
|
64
|
+
getModelClass(name) {
|
|
65
|
+
const modelClass = this.modelClasses[name]
|
|
66
|
+
|
|
67
|
+
if (!modelClass) throw new Error(`No such model class ${name} in ${Object.keys(this.modelClasses).join(", ")}}`)
|
|
68
|
+
|
|
69
|
+
return modelClass
|
|
70
|
+
}
|
|
71
|
+
|
|
42
72
|
initializeDatabasePool() {
|
|
43
73
|
if (!this.database) throw new Error("No 'database' was given")
|
|
44
74
|
if (this.databasePool) throw new Error("DatabasePool has already been initialized")
|
|
@@ -50,9 +80,15 @@ export default class VelociousConfiguration {
|
|
|
50
80
|
}
|
|
51
81
|
|
|
52
82
|
isDatabasePoolInitialized = () => Boolean(this.databasePool)
|
|
83
|
+
isInitialized = () => this._isInitialized
|
|
84
|
+
|
|
85
|
+
async initialize() {
|
|
86
|
+
await this._initializeModels({configuration: this})
|
|
87
|
+
this._isInitialized = true
|
|
88
|
+
}
|
|
53
89
|
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
registerModelClass(modelClass) {
|
|
91
|
+
this.modelClasses[modelClass.name] = modelClass
|
|
56
92
|
}
|
|
57
93
|
|
|
58
94
|
setCurrent() {
|
|
@@ -1,8 +1,25 @@
|
|
|
1
|
+
import Query from "../query/index.mjs"
|
|
2
|
+
import Handler from "../handler.mjs"
|
|
3
|
+
|
|
1
4
|
export default class VelociousDatabaseDriversBase {
|
|
2
5
|
constructor(args) {
|
|
3
6
|
this._args = args
|
|
4
7
|
}
|
|
5
8
|
|
|
9
|
+
async createTable(...args) {
|
|
10
|
+
const sqls = this.createTableSql(...args)
|
|
11
|
+
|
|
12
|
+
for (const sql of sqls) {
|
|
13
|
+
await this.query(sql)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async delete(...args) {
|
|
18
|
+
const sql = this.deleteSql(...args)
|
|
19
|
+
|
|
20
|
+
await this.query(sql)
|
|
21
|
+
}
|
|
22
|
+
|
|
6
23
|
getArgs() {
|
|
7
24
|
return this._args
|
|
8
25
|
}
|
|
@@ -11,7 +28,50 @@ export default class VelociousDatabaseDriversBase {
|
|
|
11
28
|
return this.idSeq
|
|
12
29
|
}
|
|
13
30
|
|
|
31
|
+
getTables() {
|
|
32
|
+
throw new Error(`${this.constructor.name}#getTables not implemented`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async getTableByName(name) {
|
|
36
|
+
const tables = await this.getTables()
|
|
37
|
+
const table = tables.find((table) => table.getName() == name)
|
|
38
|
+
|
|
39
|
+
if (!table) throw new Error(`Couldn't find a table by that name: ${name}`)
|
|
40
|
+
|
|
41
|
+
return table
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async insert(...args) {
|
|
45
|
+
const sql = this.insertSql(...args)
|
|
46
|
+
|
|
47
|
+
await this.query(sql)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
lastInsertID() {
|
|
51
|
+
throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async select(tableName) {
|
|
55
|
+
const handler = new Handler()
|
|
56
|
+
const query = new Query({
|
|
57
|
+
driver: this,
|
|
58
|
+
handler
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const sql = query
|
|
62
|
+
.from(tableName)
|
|
63
|
+
.toSql()
|
|
64
|
+
|
|
65
|
+
return await this.query(sql)
|
|
66
|
+
}
|
|
67
|
+
|
|
14
68
|
setIdSeq(id) {
|
|
15
69
|
this.idSeq = id
|
|
16
70
|
}
|
|
71
|
+
|
|
72
|
+
async update(...args) {
|
|
73
|
+
const sql = this.updateSql(...args)
|
|
74
|
+
|
|
75
|
+
await this.query(sql)
|
|
76
|
+
}
|
|
17
77
|
}
|
|
@@ -9,6 +9,7 @@ import Options from "./options.mjs"
|
|
|
9
9
|
import mysql from "mysql"
|
|
10
10
|
import query from "./query.mjs"
|
|
11
11
|
import QueryParser from "./query-parser.mjs"
|
|
12
|
+
import Table from "./table.mjs"
|
|
12
13
|
import Update from "./sql/update.mjs"
|
|
13
14
|
|
|
14
15
|
export default class VelociousDatabaseDriversMysql extends Base{
|
|
@@ -64,13 +65,25 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
64
65
|
return new QueryParser({query}).toSql()
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
escape(string) {
|
|
68
69
|
if (!this.connection) throw new Error("Can't escape before connected")
|
|
69
70
|
|
|
70
71
|
return this.connection.escape(string)
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
quote(string) {
|
|
75
|
+
return `${this.escape(string)}`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
quoteColumn = (string) => {
|
|
79
|
+
if (string.includes("`")) throw new Error(`Possible SQL injection in column name: ${string}`)
|
|
80
|
+
|
|
81
|
+
return `\`${string}\``
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
quoteTable = (string) => {
|
|
85
|
+
if (string.includes("`")) throw new Error(`Possible SQL injection in table name: ${string}`)
|
|
86
|
+
|
|
74
87
|
return `\`${string}\``
|
|
75
88
|
}
|
|
76
89
|
|
|
@@ -86,6 +99,25 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
86
99
|
return insert.toSql()
|
|
87
100
|
}
|
|
88
101
|
|
|
102
|
+
async getTables() {
|
|
103
|
+
const result = await this.query("SHOW FULL TABLES")
|
|
104
|
+
const tables = []
|
|
105
|
+
|
|
106
|
+
for (const row of result) {
|
|
107
|
+
const table = new Table(this, row)
|
|
108
|
+
|
|
109
|
+
tables.push(table)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return tables
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async lastInsertID() {
|
|
116
|
+
const result = await this.query("SELECT LAST_INSERT_ID() AS last_insert_id")
|
|
117
|
+
|
|
118
|
+
return digg(result, 0, "last_insert_id")
|
|
119
|
+
}
|
|
120
|
+
|
|
89
121
|
options() {
|
|
90
122
|
if (!this._options) {
|
|
91
123
|
this._options = new Options({driver: this})
|