velocious 1.0.10 → 1.0.12
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/package.json +1 -1
- package/spec/database/record/translation-fallbacks-spec.js +24 -0
- package/spec/dummy/src/config/configuration.example.js +4 -0
- package/spec/dummy/src/config/configuration.peakflow.js +4 -0
- package/src/configuration.js +9 -3
- package/src/database/drivers/sqlite/base.js +1 -1
- package/src/database/drivers/sqlite/index.js +52 -0
- package/src/database/drivers/sqlite/query.js +20 -0
- package/src/database/migrate-from-require-context.js +2 -2
- package/src/database/migrator.js +1 -1
- package/src/database/query/index.js +16 -0
- package/src/database/record/index.js +25 -18
- package/src/templates/configuration.js +4 -0
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Dummy from "../../dummy/index.js"
|
|
2
|
+
import Task from "../../dummy/src/models/task.js"
|
|
3
|
+
|
|
4
|
+
describe("Record - create", () => {
|
|
5
|
+
it("creates a new simple record", async () => {
|
|
6
|
+
await Dummy.run(async () => {
|
|
7
|
+
const task = new Task({name: "Test task"})
|
|
8
|
+
const project = task.buildProject({nameDe: "Test projekt"})
|
|
9
|
+
|
|
10
|
+
expect(project.name()).toEqual("Test projekt")
|
|
11
|
+
expect(project.nameEn()).toEqual(undefined)
|
|
12
|
+
expect(project.nameDe()).toEqual("Test projekt")
|
|
13
|
+
|
|
14
|
+
await task.save()
|
|
15
|
+
|
|
16
|
+
const sameTask = await Task.preload({project: {translations: true}}).find(task.id())
|
|
17
|
+
const sameProject = sameTask.project()
|
|
18
|
+
|
|
19
|
+
expect(sameProject.name()).toEqual("Test projekt")
|
|
20
|
+
expect(sameProject.nameEn()).toEqual(undefined)
|
|
21
|
+
expect(sameProject.nameDe()).toEqual("Test projekt")
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
})
|
package/src/configuration.js
CHANGED
|
@@ -8,7 +8,7 @@ export default class VelociousConfiguration {
|
|
|
8
8
|
return this.velociousConfiguration
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
constructor({database, debug, directory, initializeModels, locale, locales, ...restArgs}) {
|
|
11
|
+
constructor({database, debug, directory, initializeModels, locale, localeFallbacks, locales, ...restArgs}) {
|
|
12
12
|
restArgsError(restArgs)
|
|
13
13
|
|
|
14
14
|
if (!initializeModels) throw new Error("initializeModels wasn't given")
|
|
@@ -19,6 +19,7 @@ export default class VelociousConfiguration {
|
|
|
19
19
|
this._initializeModels = initializeModels
|
|
20
20
|
this._isInitialized = false
|
|
21
21
|
this.locale = locale
|
|
22
|
+
this.localeFallbacks = localeFallbacks
|
|
22
23
|
this.locales = locales
|
|
23
24
|
this.modelClasses = {}
|
|
24
25
|
}
|
|
@@ -31,7 +32,7 @@ export default class VelociousConfiguration {
|
|
|
31
32
|
return this.databasePool
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
getDatabasePoolType
|
|
35
|
+
getDatabasePoolType() {
|
|
35
36
|
const poolTypeClass = digg(this, "database", "default", "master", "poolType")
|
|
36
37
|
|
|
37
38
|
if (!poolTypeClass) {
|
|
@@ -41,7 +42,7 @@ export default class VelociousConfiguration {
|
|
|
41
42
|
return poolTypeClass
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
getDirectory
|
|
45
|
+
getDirectory() {
|
|
45
46
|
if (!this._directory) {
|
|
46
47
|
this._directory = process.cwd()
|
|
47
48
|
}
|
|
@@ -49,6 +50,11 @@ export default class VelociousConfiguration {
|
|
|
49
50
|
return this._directory
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
getLocaleFallbacks = () => this.localeFallbacks
|
|
54
|
+
setLocaleFallbacks(newLocaleFallbacks) {
|
|
55
|
+
this.localeFallbacks = newLocaleFallbacks
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
getLocale() {
|
|
53
59
|
if (typeof this.locale == "function") {
|
|
54
60
|
return this.locale()
|
|
@@ -9,7 +9,7 @@ import escapeString from "sql-string-escape"
|
|
|
9
9
|
import Insert from "../sqlite/sql/insert.js"
|
|
10
10
|
import Options from "../sqlite/options.js"
|
|
11
11
|
import QueryParser from "../sqlite/query-parser.js"
|
|
12
|
-
import Table from "./table"
|
|
12
|
+
import Table from "./table.js"
|
|
13
13
|
import Update from "../sqlite/sql/update.js"
|
|
14
14
|
|
|
15
15
|
export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import debounce from "debounce"
|
|
2
|
+
import {digg} from "diggerize"
|
|
3
|
+
import fs from "fs/promises"
|
|
4
|
+
import query from "./query.js"
|
|
5
|
+
import sqlite3 from "sqlite3"
|
|
6
|
+
import {open} from "sqlite"
|
|
7
|
+
|
|
8
|
+
import Base from "./base.js"
|
|
9
|
+
|
|
10
|
+
export default class VelociousDatabaseDriversSqliteNode extends Base {
|
|
11
|
+
async connect() {
|
|
12
|
+
const args = this.getArgs()
|
|
13
|
+
const databasePath = `db/${this.localStorageName()}.sqlite`
|
|
14
|
+
|
|
15
|
+
if (args.reset) {
|
|
16
|
+
await fs.unlink(databasePath)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.connection = await open({
|
|
20
|
+
filename: databasePath,
|
|
21
|
+
driver: sqlite3.Database
|
|
22
|
+
})
|
|
23
|
+
await this.registerVersion()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
localStorageName = () => `VelociousDatabaseDriversSqlite---${digg(this.getArgs(), "name")}`
|
|
27
|
+
disconnect = () => this.saveDatabase()
|
|
28
|
+
saveDatabase = async () => {
|
|
29
|
+
const localStorageContent = this.connection.export()
|
|
30
|
+
await this.betterLocaleStorage.set(this.localStorageName(), localStorageContent)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
saveDatabaseDebounce = debounce(this.saveDatabase, 500)
|
|
34
|
+
|
|
35
|
+
async close() {
|
|
36
|
+
await this.saveDatabase()
|
|
37
|
+
await this.connection.end()
|
|
38
|
+
this.connection = undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
query = async (sql) => {
|
|
42
|
+
const result = await query(this.connection, sql)
|
|
43
|
+
const downcasedSQL = sql.toLowerCase().trim()
|
|
44
|
+
|
|
45
|
+
// Auto-save database in local storage in case we can find manipulating instructions in the SQL
|
|
46
|
+
if (downcasedSQL.startsWith("delete ") || downcasedSQL.startsWith("insert into ") || downcasedSQL.startsWith("update ")) {
|
|
47
|
+
this.saveDatabaseDebounce()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return result
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default async function query(connection, sql) {
|
|
2
|
+
const rows = []
|
|
3
|
+
let result
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
result = await connection.all(sql)
|
|
7
|
+
} catch (error) {
|
|
8
|
+
let sqlInErrorMessage = `${sql}`
|
|
9
|
+
|
|
10
|
+
if (sqlInErrorMessage.length >= 4096) {
|
|
11
|
+
sqlInErrorMessage = `${sqlInErrorMessage.substring(0, 4096)}...`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
error.message += `\n\n${sqlInErrorMessage}`
|
|
15
|
+
|
|
16
|
+
throw error
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return result
|
|
20
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Configuration from "../configuration.js"
|
|
2
2
|
import * as inflection from "inflection"
|
|
3
|
-
import Migrator from "./migrator"
|
|
3
|
+
import Migrator from "./migrator.js"
|
|
4
4
|
|
|
5
5
|
export default class VelociousDatabaseMigrateFromRequireContext {
|
|
6
6
|
constructor(configuration) {
|
|
@@ -13,7 +13,7 @@ export default class VelociousDatabaseMigrateFromRequireContext {
|
|
|
13
13
|
|
|
14
14
|
const files = requireContext.keys()
|
|
15
15
|
.map((file) => {
|
|
16
|
-
const match = file.match(
|
|
16
|
+
const match = file.match(/(\d{14})-(.+)\.js$/)
|
|
17
17
|
|
|
18
18
|
if (!match) return null
|
|
19
19
|
|
package/src/database/migrator.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as inflection from "inflection"
|
|
|
4
4
|
import JoinPlain from "./join-plain.js"
|
|
5
5
|
import OrderPlain from "./order-plain.js"
|
|
6
6
|
import Preloader from "./preloader.js"
|
|
7
|
+
import RecordNotFoundError from "../record/record-not-found-error.js"
|
|
7
8
|
import SelectPlain from "./select-plain.js"
|
|
8
9
|
import WhereHash from "./where-hash.js"
|
|
9
10
|
import WherePlain from "./where-plain.js"
|
|
@@ -46,6 +47,21 @@ export default class VelociousDatabaseQuery {
|
|
|
46
47
|
|
|
47
48
|
getOptions = () => this.driver.options()
|
|
48
49
|
|
|
50
|
+
async find(recordId) {
|
|
51
|
+
const conditions = {}
|
|
52
|
+
|
|
53
|
+
conditions[this.modelClass.primaryKey()] = recordId
|
|
54
|
+
|
|
55
|
+
const query = this.clone().where(conditions)
|
|
56
|
+
const record = await query.first()
|
|
57
|
+
|
|
58
|
+
if (!record) {
|
|
59
|
+
throw new RecordNotFoundError(`Couldn't find ${this.modelClass.name} with '${this.modelClass.primaryKey()}'=${recordId}`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return record
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
async findBy(conditions) {
|
|
50
66
|
const newConditions = {}
|
|
51
67
|
|
|
@@ -7,7 +7,6 @@ import HasManyRelationship from "./relationships/has-many.js"
|
|
|
7
7
|
import HasManyInstanceRelationship from "./instance-relationships/has-many.js"
|
|
8
8
|
import * as inflection from "inflection"
|
|
9
9
|
import Query from "../query/index.js"
|
|
10
|
-
import RecordNotFoundError from "./record-not-found-error.js"
|
|
11
10
|
|
|
12
11
|
export default class VelociousDatabaseRecord {
|
|
13
12
|
static _relationshipExists(relationshipName) {
|
|
@@ -125,21 +124,6 @@ export default class VelociousDatabaseRecord {
|
|
|
125
124
|
return record
|
|
126
125
|
}
|
|
127
126
|
|
|
128
|
-
static async find(recordId) {
|
|
129
|
-
const conditions = {}
|
|
130
|
-
|
|
131
|
-
conditions[this.primaryKey()] = recordId
|
|
132
|
-
|
|
133
|
-
const query = this.where(conditions)
|
|
134
|
-
const record = await query.first()
|
|
135
|
-
|
|
136
|
-
if (!record) {
|
|
137
|
-
throw new RecordNotFoundError(`Couldn't find ${this.name} with '${this.primaryKey()}'=${recordId}`)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return record
|
|
141
|
-
}
|
|
142
|
-
|
|
143
127
|
static _getConfiguration() {
|
|
144
128
|
if (!this._configuration) {
|
|
145
129
|
this._configuration = Configuration.current()
|
|
@@ -161,7 +145,7 @@ export default class VelociousDatabaseRecord {
|
|
|
161
145
|
}
|
|
162
146
|
|
|
163
147
|
static async initializeRecord({configuration}) {
|
|
164
|
-
if (!configuration) throw new Error(
|
|
148
|
+
if (!configuration) throw new Error(`No configuration given for ${this.name}`)
|
|
165
149
|
|
|
166
150
|
this._configuration = configuration
|
|
167
151
|
this._configuration.registerModelClass(this)
|
|
@@ -211,7 +195,7 @@ export default class VelociousDatabaseRecord {
|
|
|
211
195
|
this.prototype[name] = function () {
|
|
212
196
|
const locale = this._getConfiguration().getLocale()
|
|
213
197
|
|
|
214
|
-
return this.
|
|
198
|
+
return this._getTranslatedAttributeWithFallback(name, locale)
|
|
215
199
|
}
|
|
216
200
|
|
|
217
201
|
this.prototype[setterMethodName] = function (newValue) {
|
|
@@ -419,6 +403,25 @@ export default class VelociousDatabaseRecord {
|
|
|
419
403
|
}
|
|
420
404
|
}
|
|
421
405
|
|
|
406
|
+
_getTranslatedAttributeWithFallback(name, locale) {
|
|
407
|
+
let localesInOrder
|
|
408
|
+
const fallbacks = this._getConfiguration().getLocaleFallbacks()
|
|
409
|
+
|
|
410
|
+
if (fallbacks && locale in fallbacks) {
|
|
411
|
+
localesInOrder = fallbacks[locale]
|
|
412
|
+
} else {
|
|
413
|
+
localesInOrder = [locale]
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
for (const fallbackLocale of localesInOrder) {
|
|
417
|
+
const result = this._getTranslatedAttribute(name, fallbackLocale)
|
|
418
|
+
|
|
419
|
+
if (result && result.trim() != "") {
|
|
420
|
+
return result
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
422
425
|
_setTranslatedAttribute(name, locale, newValue) {
|
|
423
426
|
let translation = this.translations().loaded()?.find((translation) => translation.locale() == locale)
|
|
424
427
|
|
|
@@ -454,6 +457,10 @@ export default class VelociousDatabaseRecord {
|
|
|
454
457
|
return this._newQuery()
|
|
455
458
|
}
|
|
456
459
|
|
|
460
|
+
static async find(...args) {
|
|
461
|
+
return this._newQuery().find(...args)
|
|
462
|
+
}
|
|
463
|
+
|
|
457
464
|
static async findBy(...args) {
|
|
458
465
|
return this._newQuery().findBy(...args)
|
|
459
466
|
}
|