velocious 1.0.99 → 1.0.100

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.99",
6
+ "version": "1.0.100",
7
7
  "main": "index.js",
8
8
  "scripts": {
9
9
  "lint": "eslint",
@@ -0,0 +1,28 @@
1
+ // @ts-check
2
+
3
+ import Dummy from "../../dummy/index.js"
4
+ import dummyConfiguration from "../../dummy/src/config/configuration.js"
5
+ import {describe, it} from "../../../src/testing/test.js"
6
+ import Migration from "../../../src/database/migration/index.js"
7
+
8
+ describe("database - migration", () => {
9
+ it("checks if a column exists", async () => {
10
+ await Dummy.run(async () => {
11
+ await dummyConfiguration.ensureConnections(async (dbs) => {
12
+ const migration = new Migration({
13
+ configuration: dummyConfiguration,
14
+ databaseIdentifier: "default",
15
+ db: dbs.default
16
+ })
17
+
18
+ const projectsIDExists = await migration.columnExists("projects", "id")
19
+
20
+ expect(projectsIDExists).toBe(true)
21
+
22
+ const projectsSomeNonExistingColumnExists = await migration.columnExists("projects", "some_non_existing_column")
23
+
24
+ expect(projectsSomeNonExistingColumnExists).toBe(false)
25
+ })
26
+ })
27
+ })
28
+ })
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import Dummy from "../../dummy/index.js"
2
4
  import Project from "../../dummy/src/models/project.js"
3
5
  import Task from "../../dummy/src/models/task.js"
@@ -51,7 +53,7 @@ describe("Record - create", () => {
51
53
 
52
54
  expect(tasksRelationship.getPreloaded()).toBeTrue()
53
55
 
54
- const projectTasksIDs = project.tasks().loaded().map((task) => task.id())
56
+ const projectTasksIDs = project.tasksLoaded().map((task) => task.id())
55
57
 
56
58
  expect(projectTasksIDs).toEqual([task.id()])
57
59
  })
@@ -65,17 +67,17 @@ describe("Record - create", () => {
65
67
 
66
68
  await project.save()
67
69
 
68
- const tasks = project.tasks().loaded()
70
+ const tasks = project.tasksLoaded()
69
71
  const task1 = tasks.find((task) => task.name() == "Test task 1")
70
72
  const task2 = tasks.find((task) => task.name() == "Test task 2")
71
73
 
72
74
  expect(tasks.length).toEqual(2)
73
75
 
74
- expect(task1.projectId()).toEqual(project.id())
75
- expect(task1.project().id()).toEqual(project.id())
76
+ expect(task1?.projectId()).toEqual(project.id())
77
+ expect(task1?.project().id()).toEqual(project.id())
76
78
 
77
- expect(task2.projectId()).toEqual(project.id())
78
- expect(task2.project().id()).toEqual(project.id())
79
+ expect(task2?.projectId()).toEqual(project.id())
80
+ expect(task2?.project().id()).toEqual(project.id())
79
81
  })
80
82
 
81
83
  it("creates a new task with an existing project", async () => {
@@ -111,7 +113,12 @@ describe("Record - create", () => {
111
113
  throw new Error("Didnt expect to succeed")
112
114
  } catch (error) {
113
115
  expect(error).toBeInstanceOf(ValidationError)
114
- expect(error.message).toEqual("Name can't be blank")
116
+
117
+ if (error instanceof Error) {
118
+ expect(error.message).toEqual("Name can't be blank")
119
+ } else {
120
+ throw new Error(`Expected error to be an instance of Error: ${typeof error}`)
121
+ }
115
122
  }
116
123
 
117
124
  const projectsCount = await Project.count()
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import Dummy from "../dummy/index.js"
2
4
  import dummyConfiguration from "../dummy/src/config/configuration.js"
3
5
  import Project from "../dummy/src/models/project.js"
@@ -26,7 +28,12 @@ describe("database - transactions", () => {
26
28
  })
27
29
  } catch (error) {
28
30
  expect(error).toBeInstanceOf(ValidationError)
29
- expect(error.message).toEqual("Name can't be blank")
31
+
32
+ if (error instanceof Error) {
33
+ expect(error.message).toEqual("Name can't be blank")
34
+ } else {
35
+ throw new Error(`'error' wasn't an 'Error': ${typeof error}`)
36
+ }
30
37
  }
31
38
  })
32
39
  })
@@ -0,0 +1,67 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class AccountBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {string | null}
22
+ */
23
+ name() { return this.readAttribute("name") }
24
+
25
+ /**
26
+ * @param {string | null} newValue
27
+ * @returns {void}
28
+ */
29
+ setName(newValue) { return this._setColumnAttribute("name", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasName() { return this._hasAttribute(this.name()) }
35
+
36
+ /**
37
+ * @returns {Date | null}
38
+ */
39
+ createdAt() { return this.readAttribute("createdAt") }
40
+
41
+ /**
42
+ * @param {Date | null} newValue
43
+ * @returns {void}
44
+ */
45
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
51
+
52
+ /**
53
+ * @returns {Date | null}
54
+ */
55
+ updatedAt() { return this.readAttribute("updatedAt") }
56
+
57
+ /**
58
+ * @param {Date | null} newValue
59
+ * @returns {void}
60
+ */
61
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
62
+
63
+ /**
64
+ * @returns {boolean}
65
+ */
66
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
67
+ }
@@ -0,0 +1,109 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class AuthenticationTokenBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {string | null}
22
+ */
23
+ userToken() { return this.readAttribute("userToken") }
24
+
25
+ /**
26
+ * @param {string | null} newValue
27
+ * @returns {void}
28
+ */
29
+ setUserToken(newValue) { return this._setColumnAttribute("userToken", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasUserToken() { return this._hasAttribute(this.userToken()) }
35
+
36
+ /**
37
+ * @returns {number | null}
38
+ */
39
+ userId() { return this.readAttribute("userId") }
40
+
41
+ /**
42
+ * @param {number | null} newValue
43
+ * @returns {void}
44
+ */
45
+ setUserId(newValue) { return this._setColumnAttribute("userId", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasUserId() { return this._hasAttribute(this.userId()) }
51
+
52
+ /**
53
+ * @returns {Date | null}
54
+ */
55
+ createdAt() { return this.readAttribute("createdAt") }
56
+
57
+ /**
58
+ * @param {Date | null} newValue
59
+ * @returns {void}
60
+ */
61
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
62
+
63
+ /**
64
+ * @returns {boolean}
65
+ */
66
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
67
+
68
+ /**
69
+ * @returns {Date | null}
70
+ */
71
+ updatedAt() { return this.readAttribute("updatedAt") }
72
+
73
+ /**
74
+ * @param {Date | null} newValue
75
+ * @returns {void}
76
+ */
77
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
78
+
79
+ /**
80
+ * @returns {boolean}
81
+ */
82
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
83
+
84
+ /**
85
+ * @interface
86
+ * @returns {import("../models/user.js").default}
87
+ */
88
+ user() { return this.getRelationshipByName("user").loaded() }
89
+
90
+ /**
91
+ * @interface
92
+ * @param {Record<string, any>} attributes
93
+ * @returns {import("../models/user.js").default}
94
+ */
95
+ buildUser(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
96
+
97
+ /**
98
+ * @interface
99
+ * @returns {Promise<void>}
100
+ */
101
+ loadUser() { throw new Error("Not implemented") }
102
+
103
+ /**
104
+ * @interface
105
+ * @param {import("../models/user.js").default} newModel
106
+ * @returns {void}
107
+ */
108
+ setUser(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
109
+ }
@@ -0,0 +1,102 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class ProjectDetailBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {number}
22
+ */
23
+ projectId() { return this.readAttribute("projectId") }
24
+
25
+ /**
26
+ * @param {number} newValue
27
+ * @returns {void}
28
+ */
29
+ setProjectId(newValue) { return this._setColumnAttribute("projectId", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasProjectId() { return this._hasAttribute(this.projectId()) }
35
+
36
+ note() { return this.readAttribute("note") }
37
+
38
+ setNote(newValue) { return this._setColumnAttribute("note", newValue) }
39
+
40
+ /**
41
+ * @returns {boolean}
42
+ */
43
+ hasNote() { return this._hasAttribute(this.note()) }
44
+
45
+ /**
46
+ * @returns {Date | null}
47
+ */
48
+ createdAt() { return this.readAttribute("createdAt") }
49
+
50
+ /**
51
+ * @param {Date | null} newValue
52
+ * @returns {void}
53
+ */
54
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
55
+
56
+ /**
57
+ * @returns {boolean}
58
+ */
59
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
60
+
61
+ /**
62
+ * @returns {Date | null}
63
+ */
64
+ updatedAt() { return this.readAttribute("updatedAt") }
65
+
66
+ /**
67
+ * @param {Date | null} newValue
68
+ * @returns {void}
69
+ */
70
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
71
+
72
+ /**
73
+ * @returns {boolean}
74
+ */
75
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
76
+
77
+ /**
78
+ * @interface
79
+ * @returns {import("../models/project.js").default}
80
+ */
81
+ project() { return this.getRelationshipByName("project").loaded() }
82
+
83
+ /**
84
+ * @interface
85
+ * @param {Record<string, any>} attributes
86
+ * @returns {import("../models/project.js").default}
87
+ */
88
+ buildProject(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
89
+
90
+ /**
91
+ * @interface
92
+ * @returns {Promise<void>}
93
+ */
94
+ loadProject() { throw new Error("Not implemented") }
95
+
96
+ /**
97
+ * @interface
98
+ * @param {import("../models/project.js").default} newModel
99
+ * @returns {void}
100
+ */
101
+ setProject(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
102
+ }
@@ -0,0 +1,125 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class ProjectTranslationBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {number}
22
+ */
23
+ projectId() { return this.readAttribute("projectId") }
24
+
25
+ /**
26
+ * @param {number} newValue
27
+ * @returns {void}
28
+ */
29
+ setProjectId(newValue) { return this._setColumnAttribute("projectId", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasProjectId() { return this._hasAttribute(this.projectId()) }
35
+
36
+ /**
37
+ * @returns {string}
38
+ */
39
+ locale() { return this.readAttribute("locale") }
40
+
41
+ /**
42
+ * @param {string} newValue
43
+ * @returns {void}
44
+ */
45
+ setLocale(newValue) { return this._setColumnAttribute("locale", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasLocale() { return this._hasAttribute(this.locale()) }
51
+
52
+ /**
53
+ * @returns {string | null}
54
+ */
55
+ name() { return this.readAttribute("name") }
56
+
57
+ /**
58
+ * @param {string | null} newValue
59
+ * @returns {void}
60
+ */
61
+ setName(newValue) { return this._setColumnAttribute("name", newValue) }
62
+
63
+ /**
64
+ * @returns {boolean}
65
+ */
66
+ hasName() { return this._hasAttribute(this.name()) }
67
+
68
+ /**
69
+ * @returns {Date | null}
70
+ */
71
+ createdAt() { return this.readAttribute("createdAt") }
72
+
73
+ /**
74
+ * @param {Date | null} newValue
75
+ * @returns {void}
76
+ */
77
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
78
+
79
+ /**
80
+ * @returns {boolean}
81
+ */
82
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
83
+
84
+ /**
85
+ * @returns {Date | null}
86
+ */
87
+ updatedAt() { return this.readAttribute("updatedAt") }
88
+
89
+ /**
90
+ * @param {Date | null} newValue
91
+ * @returns {void}
92
+ */
93
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
94
+
95
+ /**
96
+ * @returns {boolean}
97
+ */
98
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
99
+
100
+ /**
101
+ * @interface
102
+ * @returns {import("../models/project.js").default}
103
+ */
104
+ project() { return this.getRelationshipByName("project").loaded() }
105
+
106
+ /**
107
+ * @interface
108
+ * @param {Record<string, any>} attributes
109
+ * @returns {import("../models/project.js").default}
110
+ */
111
+ buildProject(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
112
+
113
+ /**
114
+ * @interface
115
+ * @returns {Promise<void>}
116
+ */
117
+ loadProject() { throw new Error("Not implemented") }
118
+
119
+ /**
120
+ * @interface
121
+ * @param {import("../models/project.js").default} newModel
122
+ * @returns {void}
123
+ */
124
+ setProject(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
125
+ }
@@ -0,0 +1,184 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class ProjectBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {string | null}
22
+ */
23
+ creatingUserReference() { return this.readAttribute("creatingUserReference") }
24
+
25
+ /**
26
+ * @param {string | null} newValue
27
+ * @returns {void}
28
+ */
29
+ setCreatingUserReference(newValue) { return this._setColumnAttribute("creatingUserReference", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasCreatingUserReference() { return this._hasAttribute(this.creatingUserReference()) }
35
+
36
+ /**
37
+ * @returns {Date | null}
38
+ */
39
+ createdAt() { return this.readAttribute("createdAt") }
40
+
41
+ /**
42
+ * @param {Date | null} newValue
43
+ * @returns {void}
44
+ */
45
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
51
+
52
+ /**
53
+ * @returns {Date | null}
54
+ */
55
+ updatedAt() { return this.readAttribute("updatedAt") }
56
+
57
+ /**
58
+ * @param {Date | null} newValue
59
+ * @returns {void}
60
+ */
61
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
62
+
63
+ /**
64
+ * @returns {boolean}
65
+ */
66
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
67
+
68
+ /**
69
+ * @returns {string | null}
70
+ */
71
+ name() { return this._getTranslatedAttributeWithFallback("name", this._getConfiguration().getLocale()) }
72
+
73
+ /**
74
+ * @returns {string | null}
75
+ */
76
+ nameDe() { return this._getTranslatedAttributeWithFallback("name", "de") }
77
+
78
+ /**
79
+ * @returns {string | null}
80
+ */
81
+ nameEn() { return this._getTranslatedAttributeWithFallback("name", "en") }
82
+
83
+ /**
84
+ * @interface
85
+ * @returns {import("../models/user.js").default}
86
+ */
87
+ creatingUser() { return this.getRelationshipByName("creatingUser").loaded() }
88
+
89
+ /**
90
+ * @interface
91
+ * @param {Record<string, any>} attributes
92
+ * @returns {import("../models/user.js").default}
93
+ */
94
+ buildCreatingUser(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
95
+
96
+ /**
97
+ * @interface
98
+ * @returns {Promise<void>}
99
+ */
100
+ loadCreatingUser() { throw new Error("Not implemented") }
101
+
102
+ /**
103
+ * @interface
104
+ * @param {import("../models/user.js").default} newModel
105
+ * @returns {void}
106
+ */
107
+ setCreatingUser(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
108
+
109
+ /**
110
+ * @interface
111
+ * @returns {import("velocious/src/database/query/index.js").default<import("../models/task.js").default>}
112
+ */
113
+ tasks() { return this.getRelationshipByName("tasks") }
114
+
115
+ /**
116
+ * @interface
117
+ * @returns {Array<import("../models/task.js").default>}
118
+ */
119
+ tasksLoaded() { return this.getRelationshipByName("tasks").loaded() }
120
+
121
+ /**
122
+ * @interface
123
+ * @returns {Promise<void>}
124
+ */
125
+ loadTasks() { throw new Error("Not implemented") }
126
+
127
+ /**
128
+ * @interface
129
+ * @param {Array<import("../models/task.js").default>} newModels
130
+ * @returns {void}
131
+ */
132
+ setTasks(newModels) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
133
+
134
+ /**
135
+ * @interface
136
+ * @returns {import("../models/project-detail.js").default}
137
+ */
138
+ projectDetail() { return this.getRelationshipByName("projectDetail").loaded() }
139
+
140
+ /**
141
+ * @interface
142
+ * @param {Record<string, any>} attributes
143
+ * @returns {import("../models/project-detail.js").default}
144
+ */
145
+ buildProjectDetail(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
146
+
147
+ /**
148
+ * @interface
149
+ * @returns {Promise<void>}
150
+ */
151
+ loadProjectDetail() { throw new Error("Not implemented") }
152
+
153
+ /**
154
+ * @interface
155
+ * @param {import("../models/project-detail.js").default} newModel
156
+ * @returns {void}
157
+ */
158
+ setProjectDetail(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
159
+
160
+ /**
161
+ * @interface
162
+ * @returns {import("velocious/src/database/query/index.js").default<import("velocious/src/database/record/index.js").default>}
163
+ */
164
+ translations() { return this.getRelationshipByName("translations") }
165
+
166
+ /**
167
+ * @interface
168
+ * @returns {Array<import("velocious/src/database/record/index.js").default>}
169
+ */
170
+ translationsLoaded() { return this.getRelationshipByName("translations").loaded() }
171
+
172
+ /**
173
+ * @interface
174
+ * @returns {Promise<void>}
175
+ */
176
+ loadTranslations() { throw new Error("Not implemented") }
177
+
178
+ /**
179
+ * @interface
180
+ * @param {Array<import("velocious/src/database/record/index.js").default>} newModels
181
+ * @returns {void}
182
+ */
183
+ setTranslations(newModels) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
184
+ }
@@ -0,0 +1,118 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class TaskBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {number}
22
+ */
23
+ projectId() { return this.readAttribute("projectId") }
24
+
25
+ /**
26
+ * @param {number} newValue
27
+ * @returns {void}
28
+ */
29
+ setProjectId(newValue) { return this._setColumnAttribute("projectId", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasProjectId() { return this._hasAttribute(this.projectId()) }
35
+
36
+ /**
37
+ * @returns {string | null}
38
+ */
39
+ name() { return this.readAttribute("name") }
40
+
41
+ /**
42
+ * @param {string | null} newValue
43
+ * @returns {void}
44
+ */
45
+ setName(newValue) { return this._setColumnAttribute("name", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasName() { return this._hasAttribute(this.name()) }
51
+
52
+ description() { return this.readAttribute("description") }
53
+
54
+ setDescription(newValue) { return this._setColumnAttribute("description", newValue) }
55
+
56
+ /**
57
+ * @returns {boolean}
58
+ */
59
+ hasDescription() { return this._hasAttribute(this.description()) }
60
+
61
+ /**
62
+ * @returns {Date | null}
63
+ */
64
+ createdAt() { return this.readAttribute("createdAt") }
65
+
66
+ /**
67
+ * @param {Date | null} newValue
68
+ * @returns {void}
69
+ */
70
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
71
+
72
+ /**
73
+ * @returns {boolean}
74
+ */
75
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
76
+
77
+ /**
78
+ * @returns {Date | null}
79
+ */
80
+ updatedAt() { return this.readAttribute("updatedAt") }
81
+
82
+ /**
83
+ * @param {Date | null} newValue
84
+ * @returns {void}
85
+ */
86
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
87
+
88
+ /**
89
+ * @returns {boolean}
90
+ */
91
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
92
+
93
+ /**
94
+ * @interface
95
+ * @returns {import("../models/project.js").default}
96
+ */
97
+ project() { return this.getRelationshipByName("project").loaded() }
98
+
99
+ /**
100
+ * @interface
101
+ * @param {Record<string, any>} attributes
102
+ * @returns {import("../models/project.js").default}
103
+ */
104
+ buildProject(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
105
+
106
+ /**
107
+ * @interface
108
+ * @returns {Promise<void>}
109
+ */
110
+ loadProject() { throw new Error("Not implemented") }
111
+
112
+ /**
113
+ * @interface
114
+ * @param {import("../models/project.js").default} newModel
115
+ * @returns {void}
116
+ */
117
+ setProject(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
118
+ }
@@ -0,0 +1,175 @@
1
+ import Record from "../../../../src/database/record/index.js"
2
+
3
+ export default class UserBase extends Record {
4
+ /**
5
+ * @returns {number}
6
+ */
7
+ id() { return this.readAttribute("id") }
8
+
9
+ /**
10
+ * @param {number} newValue
11
+ * @returns {void}
12
+ */
13
+ setId(newValue) { return this._setColumnAttribute("id", newValue) }
14
+
15
+ /**
16
+ * @returns {boolean}
17
+ */
18
+ hasId() { return this._hasAttribute(this.id()) }
19
+
20
+ /**
21
+ * @returns {string}
22
+ */
23
+ email() { return this.readAttribute("email") }
24
+
25
+ /**
26
+ * @param {string} newValue
27
+ * @returns {void}
28
+ */
29
+ setEmail(newValue) { return this._setColumnAttribute("email", newValue) }
30
+
31
+ /**
32
+ * @returns {boolean}
33
+ */
34
+ hasEmail() { return this._hasAttribute(this.email()) }
35
+
36
+ /**
37
+ * @returns {string}
38
+ */
39
+ encryptedPassword() { return this.readAttribute("encryptedPassword") }
40
+
41
+ /**
42
+ * @param {string} newValue
43
+ * @returns {void}
44
+ */
45
+ setEncryptedPassword(newValue) { return this._setColumnAttribute("encryptedPassword", newValue) }
46
+
47
+ /**
48
+ * @returns {boolean}
49
+ */
50
+ hasEncryptedPassword() { return this._hasAttribute(this.encryptedPassword()) }
51
+
52
+ /**
53
+ * @returns {string | null}
54
+ */
55
+ reference() { return this.readAttribute("reference") }
56
+
57
+ /**
58
+ * @param {string | null} newValue
59
+ * @returns {void}
60
+ */
61
+ setReference(newValue) { return this._setColumnAttribute("reference", newValue) }
62
+
63
+ /**
64
+ * @returns {boolean}
65
+ */
66
+ hasReference() { return this._hasAttribute(this.reference()) }
67
+
68
+ /**
69
+ * @returns {Date | null}
70
+ */
71
+ createdAt() { return this.readAttribute("createdAt") }
72
+
73
+ /**
74
+ * @param {Date | null} newValue
75
+ * @returns {void}
76
+ */
77
+ setCreatedAt(newValue) { return this._setColumnAttribute("createdAt", newValue) }
78
+
79
+ /**
80
+ * @returns {boolean}
81
+ */
82
+ hasCreatedAt() { return this._hasAttribute(this.createdAt()) }
83
+
84
+ /**
85
+ * @returns {Date | null}
86
+ */
87
+ updatedAt() { return this.readAttribute("updatedAt") }
88
+
89
+ /**
90
+ * @param {Date | null} newValue
91
+ * @returns {void}
92
+ */
93
+ setUpdatedAt(newValue) { return this._setColumnAttribute("updatedAt", newValue) }
94
+
95
+ /**
96
+ * @returns {boolean}
97
+ */
98
+ hasUpdatedAt() { return this._hasAttribute(this.updatedAt()) }
99
+
100
+ /**
101
+ * @interface
102
+ * @returns {import("../models/project.js").default}
103
+ */
104
+ createdProject() { return this.getRelationshipByName("createdProject").loaded() }
105
+
106
+ /**
107
+ * @interface
108
+ * @param {Record<string, any>} attributes
109
+ * @returns {import("../models/project.js").default}
110
+ */
111
+ buildCreatedProject(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
112
+
113
+ /**
114
+ * @interface
115
+ * @returns {Promise<void>}
116
+ */
117
+ loadCreatedProject() { throw new Error("Not implemented") }
118
+
119
+ /**
120
+ * @interface
121
+ * @param {import("../models/project.js").default} newModel
122
+ * @returns {void}
123
+ */
124
+ setCreatedProject(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
125
+
126
+ /**
127
+ * @interface
128
+ * @returns {import("velocious/src/database/query/index.js").default<import("../models/authentication-token.js").default>}
129
+ */
130
+ authenticationTokens() { return this.getRelationshipByName("authenticationTokens") }
131
+
132
+ /**
133
+ * @interface
134
+ * @returns {Array<import("../models/authentication-token.js").default>}
135
+ */
136
+ authenticationTokensLoaded() { return this.getRelationshipByName("authenticationTokens").loaded() }
137
+
138
+ /**
139
+ * @interface
140
+ * @returns {Promise<void>}
141
+ */
142
+ loadAuthenticationTokens() { throw new Error("Not implemented") }
143
+
144
+ /**
145
+ * @interface
146
+ * @param {Array<import("../models/authentication-token.js").default>} newModels
147
+ * @returns {void}
148
+ */
149
+ setAuthenticationTokens(newModels) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
150
+
151
+ /**
152
+ * @interface
153
+ * @returns {import("velocious/src/database/query/index.js").default<import("../models/project.js").default>}
154
+ */
155
+ createdProjects() { return this.getRelationshipByName("createdProjects") }
156
+
157
+ /**
158
+ * @interface
159
+ * @returns {Array<import("../models/project.js").default>}
160
+ */
161
+ createdProjectsLoaded() { return this.getRelationshipByName("createdProjects").loaded() }
162
+
163
+ /**
164
+ * @interface
165
+ * @returns {Promise<void>}
166
+ */
167
+ loadCreatedProjects() { throw new Error("Not implemented") }
168
+
169
+ /**
170
+ * @interface
171
+ * @param {Array<import("../models/project.js").default>} newModels
172
+ * @returns {void}
173
+ */
174
+ setCreatedProjects(newModels) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars
175
+ }
@@ -1,6 +1,6 @@
1
- import DatabaseRecord from "../../../../src/database/record/index.js"
1
+ import AccountBase from "../model-bases/account.js"
2
2
 
3
- class Account extends DatabaseRecord {
3
+ class Account extends AccountBase {
4
4
  }
5
5
 
6
6
  Account.setDatabaseIdentifier("mssql")
@@ -1,6 +1,6 @@
1
- import Record from "../../../../src/database/record/index.js"
1
+ import AuthenticationTokenBase from "../model-bases/authentication-token.js"
2
2
 
3
- class AuthenticationToken extends Record {
3
+ class AuthenticationToken extends AuthenticationTokenBase {
4
4
  }
5
5
 
6
6
  AuthenticationToken.belongsTo("user")
@@ -1,6 +1,6 @@
1
- import DatabaseRecord from "../../../../src/database/record/index.js"
1
+ import ProjectDetailsBase from "../model-bases/project-detail.js"
2
2
 
3
- class ProjectDetail extends DatabaseRecord {
3
+ class ProjectDetail extends ProjectDetailsBase {
4
4
  }
5
5
 
6
6
  ProjectDetail.belongsTo("project")
@@ -1,6 +1,6 @@
1
- import DatabaseRecord from "../../../../src/database/record/index.js"
1
+ import ProjectBase from "../model-bases/project.js"
2
2
 
3
- class Project extends DatabaseRecord {
3
+ class Project extends ProjectBase {
4
4
  }
5
5
 
6
6
  Project.belongsTo("creatingUser", {className: "User", foreignKey: "creating_user_reference", primaryKey: "reference"})
@@ -1,6 +1,6 @@
1
- import Record from "../../../../src/database/record/index.js"
1
+ import TaskBase from "../model-bases/task.js"
2
2
 
3
- class Task extends Record {
3
+ class Task extends TaskBase {
4
4
  }
5
5
 
6
6
  Task.belongsTo("project")
@@ -1,7 +1,7 @@
1
- import Record from "../../../../src/database/record/index.js"
1
+ import UserBase from "../model-bases/user.js"
2
2
  import UserModule from "../../../../src/database/record/user-module.js"
3
3
 
4
- class User extends Record {
4
+ class User extends UserBase {
5
5
  }
6
6
 
7
7
  User.hasOne("createdProject", {className: "Project", foreignKey: "creating_user_reference", primaryKey: "reference"})
@@ -1,5 +1,9 @@
1
1
  // @ts-check
2
2
 
3
+ /**
4
+ * @typedef {function(Record<string, import("./database/drivers/base.js").default>) : Promise<void>} WithConnectionsCallbackType
5
+ */
6
+
3
7
  import {digg} from "diggerize"
4
8
  import restArgsError from "./utils/rest-args-error.js"
5
9
  import {withTrackedStack} from "./utils/with-tracked-stack.js"
@@ -320,7 +324,7 @@ export default class VelociousConfiguration {
320
324
  }
321
325
 
322
326
  /**
323
- * @param {Function} callback
327
+ * @param {WithConnectionsCallbackType} callback
324
328
  * @returns {Promise<void>}
325
329
  */
326
330
  async withConnections(callback) {
@@ -376,7 +380,7 @@ export default class VelociousConfiguration {
376
380
  }
377
381
 
378
382
  /**
379
- * @param {Function} callback
383
+ * @param {WithConnectionsCallbackType} callback
380
384
  * @returns {Promise<void>}
381
385
  */
382
386
  async ensureConnections(callback) {
@@ -83,7 +83,15 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
83
83
 
84
84
  getType() {
85
85
  const type = digg(this, "data", "Type")
86
+
87
+ if (type.match(/^[a-z]+$/)) {
88
+ return type
89
+ }
90
+
86
91
  const match = type.match(/^(.+)\((\d+)\)$/)
92
+
93
+ if (!match) throw new Error(`Couldn't match column type from: ${type}`)
94
+
87
95
  const columnType = match[1]
88
96
 
89
97
  return columnType
@@ -223,13 +223,15 @@ export default class VelociousDatabaseMigration {
223
223
  async columnExists(tableName, columnName) {
224
224
  const table = await this.getDriver().getTableByName(tableName)
225
225
 
226
- if (!table) throw new Error(`Table ${tableName} does not exist`)
227
-
228
- const column = await table.getColumnByName(columnName)
226
+ if (table) {
227
+ const column = await table.getColumnByName(columnName)
229
228
 
230
- if (!column) throw new Error(`Column ${columnName} does not exist in table ${tableName}`)
229
+ if (column) {
230
+ return true
231
+ }
232
+ }
231
233
 
232
- return Boolean(column)
234
+ return Boolean(false)
233
235
  }
234
236
 
235
237
  /**
@@ -269,7 +269,7 @@ class VelociousDatabaseRecord {
269
269
  }
270
270
 
271
271
  /**
272
- * @param {Record<string, any>} attributes
272
+ * @param {Record<string, any>} [attributes]
273
273
  * @returns {Promise<InstanceType<typeof this>>}
274
274
  */
275
275
  static async create(attributes) {
@@ -511,6 +511,9 @@ class VelociousDatabaseRecord {
511
511
  }
512
512
  }
513
513
 
514
+ /**
515
+ * @returns {import("../drivers/base-column.js").default[]}
516
+ */
514
517
  static getColumns() {
515
518
  if (!this._columns) throw new Error(`${this.name} hasn't been initialized yet`)
516
519
 
@@ -763,7 +766,7 @@ class VelociousDatabaseRecord {
763
766
  }
764
767
 
765
768
  /**
766
- * @returns {VelociousDatabaseRecord}
769
+ * @returns {typeof VelociousDatabaseRecord}
767
770
  */
768
771
  static getTranslationClass() {
769
772
  if (this._translationClass) return this._translationClass
@@ -9,6 +9,11 @@ export default class DbGenerateModel extends BaseCommand {
9
9
 
10
10
  const modelsDir = `${process.cwd()}/src/model-bases`
11
11
  const modelClasses = this.getConfiguration().getModelClasses()
12
+ let devMode = false
13
+
14
+ if (modelsDir.endsWith("velocious/spec/dummy/src/model-bases")) {
15
+ devMode = true
16
+ }
12
17
 
13
18
  if (!await fileExists(modelsDir)) {
14
19
  await fs.mkdir(modelsDir, {recursive: true})
@@ -23,7 +28,13 @@ export default class DbGenerateModel extends BaseCommand {
23
28
 
24
29
  console.log(`create src/model-bases/${modelBaseFileName}`)
25
30
 
26
- let fileContent = `import Record from "velocious/src/database/record/index.js"\n\n`
31
+ let fileContent = ""
32
+
33
+ if (devMode) {
34
+ fileContent += `import Record from "../../../../src/database/record/index.js"\n\n`
35
+ } else {
36
+ fileContent += `import Record from "velocious/src/database/record/index.js"\n\n`
37
+ }
27
38
 
28
39
  fileContent += `export default class ${modelNameCamelized}Base extends Record {\n`
29
40
 
@@ -33,15 +44,7 @@ export default class DbGenerateModel extends BaseCommand {
33
44
  for (const column of columns) {
34
45
  const camelizedColumnName = inflection.camelize(column.getName(), true)
35
46
  const camelizedColumnNameBigFirst = inflection.camelize(column.getName())
36
- let jsdocType
37
-
38
- if (column.getType() == "varchar") {
39
- jsdocType = "string"
40
- } else if (["bigint", "int", "integer", "smallint"].includes(column.getType())) {
41
- jsdocType = "number"
42
- } else if (["date", "datetime"].includes(column.getType())) {
43
- jsdocType = "Date"
44
- }
47
+ const jsdocType = this.jsDocTypeFromColumn(column)
45
48
 
46
49
  if (methodsCount > 0) {
47
50
  fileContent += "\n"
@@ -49,7 +52,7 @@ export default class DbGenerateModel extends BaseCommand {
49
52
 
50
53
  if (jsdocType) {
51
54
  fileContent += " /**\n"
52
- fileContent += ` * @returns {${jsdocType}}\n`
55
+ fileContent += ` * @returns {${jsdocType}${column.getNull() ? " | null" : ""}}\n`
53
56
  fileContent += " */\n"
54
57
  }
55
58
 
@@ -57,7 +60,7 @@ export default class DbGenerateModel extends BaseCommand {
57
60
 
58
61
  if (jsdocType) {
59
62
  fileContent += " /**\n"
60
- fileContent += ` * @param {${jsdocType}} newValue\n`
63
+ fileContent += ` * @param {${jsdocType}${column.getNull() ? " | null" : ""}} newValue\n`
61
64
  fileContent += " * @returns {void}\n"
62
65
  fileContent += " */\n"
63
66
  }
@@ -72,6 +75,46 @@ export default class DbGenerateModel extends BaseCommand {
72
75
  methodsCount++
73
76
  }
74
77
 
78
+ if (modelClass._translations) {
79
+ const TranslationClass = modelClass.getTranslationClass()
80
+ const translationColumns = TranslationClass.getColumns()
81
+
82
+ for (const name in modelClass._translations) {
83
+ const nameUnderscore = inflection.underscore(name)
84
+ const column = translationColumns.find((translationColumn) => translationColumn.getName() === nameUnderscore)
85
+ let translationJsdocType
86
+
87
+ if (column) {
88
+ translationJsdocType = this.jsDocTypeFromColumn(column)
89
+ }
90
+
91
+ if (translationJsdocType) {
92
+ fileContent += `\n`
93
+ fileContent += " /**\n"
94
+ fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`
95
+ fileContent += " */\n"
96
+ }
97
+
98
+ fileContent += ` ${name}() { return this._getTranslatedAttributeWithFallback("${name}", this._getConfiguration().getLocale()) }\n`
99
+ methodsCount++
100
+
101
+ for (const locale of this.getConfiguration().getLocales()) {
102
+ const localeMethodName = `${name}${inflection.camelize(locale)}`
103
+
104
+ if (translationJsdocType) {
105
+ fileContent += `\n`
106
+ fileContent += " /**\n"
107
+ fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`
108
+ fileContent += " */\n"
109
+ }
110
+
111
+ fileContent += ` ${localeMethodName}() { return this._getTranslatedAttributeWithFallback("${name}", "${locale}") }\n`
112
+
113
+ methodsCount++
114
+ }
115
+ }
116
+ }
117
+
75
118
  for (const relationship of modelClass.getRelationships()) {
76
119
  let fileName, fullFilePath
77
120
 
@@ -104,9 +147,10 @@ export default class DbGenerateModel extends BaseCommand {
104
147
  fileContent += "\n"
105
148
  fileContent += " /**\n"
106
149
  fileContent += " * @interface\n"
150
+ fileContent += " * @param {Record<string, any>} attributes\n"
107
151
  fileContent += ` * @returns {import("${modelFilePath}").default}\n`
108
152
  fileContent += " */\n"
109
- fileContent += ` build${inflection.camelize(relationship.getRelationshipName())}() { throw new Error("Not implemented") }\n`
153
+ fileContent += ` build${inflection.camelize(relationship.getRelationshipName())}(attributes) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars\n`
110
154
 
111
155
  fileContent += "\n"
112
156
  fileContent += " /**\n"
@@ -121,7 +165,7 @@ export default class DbGenerateModel extends BaseCommand {
121
165
  fileContent += ` * @param {import("${modelFilePath}").default} newModel\n`
122
166
  fileContent += ` * @returns {void}\n`
123
167
  fileContent += " */\n"
124
- fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}() { throw new Error("Not implemented") }\n`
168
+ fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModel) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars\n`
125
169
  } else if (relationship.getType() == "hasMany") {
126
170
  let recordImport
127
171
 
@@ -155,9 +199,9 @@ export default class DbGenerateModel extends BaseCommand {
155
199
  fileContent += " /**\n"
156
200
  fileContent += " * @interface\n"
157
201
  fileContent += ` * @param {Array<import("${recordImport}").default>} newModels\n`
158
- fileContent += " * @returns {void>}\n"
202
+ fileContent += " * @returns {void}\n"
159
203
  fileContent += " */\n"
160
- fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}() { throw new Error("Not implemented") }\n`
204
+ fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModels) { throw new Error("Not implemented") } // eslint-disable-line no-unused-vars\n`
161
205
  } else {
162
206
  throw new Error(`Unknown relationship type: ${relationship.getType()}`)
163
207
  }
@@ -170,4 +214,18 @@ export default class DbGenerateModel extends BaseCommand {
170
214
  await fs.writeFile(modelPath, fileContent)
171
215
  }
172
216
  }
217
+
218
+ /**
219
+ * @param {import("../../../../../database/drivers/base-column.js").default} column
220
+ * @returns {string | undefined}
221
+ */
222
+ jsDocTypeFromColumn(column) {
223
+ if (column.getType() == "varchar") {
224
+ return "string"
225
+ } else if (["bigint", "int", "integer", "smallint"].includes(column.getType())) {
226
+ return "number"
227
+ } else if (["date", "datetime"].includes(column.getType())) {
228
+ return "Date"
229
+ }
230
+ }
173
231
  }
@@ -315,7 +315,7 @@ class Expect {
315
315
  /**
316
316
  * @param {string} description
317
317
  * @param {object|() => Promise<void>} arg1
318
- * @param {undefined|() => Promise<void>} arg2
318
+ * @param {undefined|() => Promise<void>} [arg2]
319
319
  * @returns {void}
320
320
  */
321
321
  async function describe(description, arg1, arg2) {
@@ -361,7 +361,7 @@ function expect(arg) {
361
361
  /**
362
362
  * @param {string} description
363
363
  * @param {object|() => Promise<void>} arg1
364
- * @param {undefined|() => Promise<void>} arg2
364
+ * @param {undefined|() => Promise<void>} [arg2]
365
365
  * @returns {void}
366
366
  */
367
367
  function it(description, arg1, arg2) {
@@ -386,7 +386,7 @@ function it(description, arg1, arg2) {
386
386
  /**
387
387
  * @param {string} description
388
388
  * @param {object|() => Promise<void>} arg1
389
- * @param {undefined|() => Promise<void>} arg2
389
+ * @param {undefined|() => Promise<void>} [arg2]
390
390
  * @returns {void}
391
391
  */
392
392
  function fit(description, arg1, arg2) {