velocious 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/bin/{velocious.mjs → velocious.js} +1 -1
  2. package/package.json +7 -5
  3. package/peak_flow.yml +1 -1
  4. package/spec/cli/commands/db/{create-spec.mjs → create-spec.js} +3 -3
  5. package/spec/cli/commands/db/{migrate-spec.mjs → migrate-spec.js} +4 -2
  6. package/spec/cli/commands/destroy/{migration-spec.mjs → migration-spec.js} +2 -2
  7. package/spec/cli/commands/generate/{migration-spec.mjs → migration-spec.js} +3 -3
  8. package/spec/cli/commands/{init-spec.mjs → init-spec.js} +6 -6
  9. package/spec/cli/commands/test/{test-files-finder-spec.mjs → test-files-finder-spec.js} +2 -2
  10. package/spec/database/connection/drivers/mysql/{query-parser-spec.mjs → query-parser-spec.js} +6 -6
  11. package/spec/database/drivers/mysql/{connection-spec.mjs → connection-spec.js} +2 -2
  12. package/spec/database/record/create-spec.js +23 -0
  13. package/spec/database/record/{destroy-spec.mjs → destroy-spec.js} +2 -2
  14. package/spec/database/record/{find-spec.mjs → find-spec.js} +2 -3
  15. package/spec/database/record/query-spec.js +37 -0
  16. package/spec/database/record/{update-spec.mjs → update-spec.js} +2 -2
  17. package/spec/dummy/{index.mjs → index.js} +16 -4
  18. package/spec/dummy/src/config/configuration.example.js +36 -0
  19. package/spec/dummy/src/config/configuration.peakflow.js +37 -0
  20. package/spec/dummy/src/config/{routes.mjs → routes.js} +1 -1
  21. package/spec/dummy/src/database/migrations/{20230728075328-create-projects.mjs → 20230728075328-create-projects.js} +1 -2
  22. package/spec/dummy/src/database/migrations/{20230728075329-create-tasks.mjs → 20230728075329-create-tasks.js} +1 -2
  23. package/spec/dummy/src/database/migrations/20250605133926-create-project-translations.js +16 -0
  24. package/spec/dummy/src/models/project.js +9 -0
  25. package/spec/dummy/src/models/task.js +8 -0
  26. package/spec/dummy/src/routes/tasks/{controller.mjs → controller.js} +2 -2
  27. package/spec/http-server/{client-spec.mjs → client-spec.js} +3 -3
  28. package/spec/http-server/{get-spec.mjs → get-spec.js} +1 -1
  29. package/spec/http-server/{post-spec.mjs → post-spec.js} +2 -2
  30. package/spec/support/jasmine.json +2 -2
  31. package/src/{application.mjs → application.js} +3 -3
  32. package/src/big-brother.js +37 -0
  33. package/src/cli/commands/db/{create.mjs → create.js} +9 -7
  34. package/src/cli/commands/db/{migrate.mjs → migrate.js} +4 -5
  35. package/src/cli/commands/destroy/{migration.mjs → migration.js} +2 -2
  36. package/src/cli/commands/generate/{migration.mjs → migration.js} +5 -5
  37. package/src/cli/commands/generate/{model.mjs → model.js} +5 -5
  38. package/src/cli/commands/{init.mjs → init.js} +6 -6
  39. package/src/cli/commands/{server.mjs → server.js} +1 -1
  40. package/src/cli/commands/test/{index.mjs → index.js} +3 -3
  41. package/src/cli/commands/test/{test-files-finder.mjs → test-files-finder.js} +1 -1
  42. package/src/cli/{index.mjs → index.js} +4 -4
  43. package/src/{configuration-resolver.mjs → configuration-resolver.js} +2 -2
  44. package/src/{configuration.mjs → configuration.js} +39 -3
  45. package/src/database/drivers/{base.mjs → base.js} +23 -4
  46. package/src/database/drivers/mysql/column.js +8 -0
  47. package/src/database/drivers/mysql/{index.mjs → index.js} +44 -12
  48. package/src/database/drivers/{sqlite/options.mjs → mysql/options.js} +2 -1
  49. package/src/database/drivers/mysql/query-parser.js +4 -0
  50. package/src/database/drivers/mysql/sql/{create-database.mjs → create-database.js} +1 -1
  51. package/src/database/drivers/{sqlite/sql/create-table.mjs → mysql/sql/create-table.js} +1 -1
  52. package/src/database/drivers/mysql/sql/{delete.mjs → delete.js} +1 -1
  53. package/src/database/drivers/{sqlite/sql/insert.mjs → mysql/sql/insert.js} +1 -1
  54. package/src/database/drivers/mysql/sql/{update.mjs → update.js} +1 -1
  55. package/src/database/drivers/mysql/table.js +25 -0
  56. package/src/database/drivers/sqlite/base.js +108 -0
  57. package/src/database/drivers/sqlite/column.js +10 -0
  58. package/src/database/drivers/sqlite/{index.native.mjs → index.native.js} +19 -22
  59. package/src/database/drivers/sqlite/index.web.js +55 -0
  60. package/src/database/drivers/{mysql/options.mjs → sqlite/options.js} +3 -2
  61. package/src/database/drivers/sqlite/query-parser.js +4 -0
  62. package/src/database/drivers/sqlite/query.native.js +24 -0
  63. package/src/database/drivers/sqlite/query.web.js +34 -0
  64. package/src/database/drivers/sqlite/sql/create-index.js +4 -0
  65. package/src/database/drivers/{mysql/sql/create-table.mjs → sqlite/sql/create-table.js} +1 -1
  66. package/src/database/drivers/sqlite/sql/{delete.mjs → delete.js} +1 -1
  67. package/src/database/drivers/{mysql/sql/insert.mjs → sqlite/sql/insert.js} +1 -1
  68. package/src/database/drivers/sqlite/sql/{update.mjs → update.js} +1 -1
  69. package/src/database/drivers/sqlite/table.js +24 -0
  70. package/src/database/initializer-from-require-context.js +21 -0
  71. package/src/database/{migrate-from-require-context.mjs → migrate-from-require-context.js} +2 -2
  72. package/src/database/migration/index.js +50 -0
  73. package/src/database/{migrator.mjs → migrator.js} +4 -2
  74. package/src/database/pool/{async-tracked-multi-connection.mjs → async-tracked-multi-connection.js} +1 -1
  75. package/src/database/pool/{base.mjs → base.js} +6 -1
  76. package/src/database/pool/{single-multi-use.mjs → single-multi-use.js} +1 -1
  77. package/src/database/query/{base.mjs → base.js} +2 -1
  78. package/src/database/query/{create-database-base.mjs → create-database-base.js} +1 -1
  79. package/src/database/query/create-index-base.js +50 -0
  80. package/src/database/query/create-table-base.js +92 -0
  81. package/src/database/query/{delete-base.mjs → delete-base.js} +1 -1
  82. package/src/database/query/{from-plain.mjs → from-plain.js} +1 -1
  83. package/src/database/query/{from-table.mjs → from-table.js} +1 -1
  84. package/src/database/query/index.js +206 -0
  85. package/src/database/query/{join-plain.mjs → join-plain.js} +1 -1
  86. package/src/database/query/{order-plain.mjs → order-plain.js} +1 -1
  87. package/src/database/query/preloader/belongs-to.js +52 -0
  88. package/src/database/query/preloader/has-many.js +55 -0
  89. package/src/database/query/preloader.js +41 -0
  90. package/src/database/query/{select-plain.mjs → select-plain.js} +1 -1
  91. package/src/database/query/{select-table-and-column.mjs → select-table-and-column.js} +1 -1
  92. package/src/database/query/where-base.js +9 -0
  93. package/src/database/query/where-hash.js +35 -0
  94. package/src/database/query/where-plain.js +13 -0
  95. package/src/database/query-parser/base-query-parser.js +33 -0
  96. package/src/database/query-parser/group-parser.js +40 -0
  97. package/src/database/query-parser/joins-parser.js +71 -0
  98. package/src/database/query-parser/limit-parser.js +40 -0
  99. package/src/database/query-parser/{options.mjs → options.js} +2 -1
  100. package/src/database/query-parser/order-parser.js +39 -0
  101. package/src/database/query-parser/{select-parser.mjs → select-parser.js} +5 -1
  102. package/src/database/query-parser/where-parser.js +39 -0
  103. package/src/database/record/index.js +622 -0
  104. package/src/database/record/instance-relationships/base.js +28 -0
  105. package/src/database/record/instance-relationships/belongs-to.js +20 -0
  106. package/src/database/record/instance-relationships/has-many.js +47 -0
  107. package/src/database/record/relationships/base.js +32 -0
  108. package/src/database/record/relationships/belongs-to.js +12 -0
  109. package/src/database/record/relationships/has-many.js +12 -0
  110. package/src/database/table-data/{index.mjs → index.js} +15 -25
  111. package/src/http-server/client/{index.mjs → index.js} +3 -3
  112. package/src/http-server/client/request-buffer/{index.mjs → index.js} +4 -4
  113. package/src/http-server/client/{request-parser.mjs → request-parser.js} +2 -2
  114. package/src/http-server/client/{request-runner.mjs → request-runner.js} +3 -3
  115. package/src/http-server/client/{request.mjs → request.js} +1 -1
  116. package/src/http-server/{index.mjs → index.js} +3 -3
  117. package/src/http-server/{server-client.mjs → server-client.js} +1 -1
  118. package/src/http-server/worker-handler/{index.mjs → index.js} +2 -2
  119. package/src/http-server/worker-handler/{worker-script.mjs → worker-script.js} +1 -1
  120. package/src/http-server/worker-handler/{worker-thread.mjs → worker-thread.js} +12 -9
  121. package/src/routes/{app-routes.mjs → app-routes.js} +1 -1
  122. package/src/routes/{base-route.mjs → base-route.js} +2 -2
  123. package/src/routes/{get-route.mjs → get-route.js} +1 -1
  124. package/src/routes/{index.mjs → index.js} +1 -1
  125. package/src/routes/{resolver.mjs → resolver.js} +1 -1
  126. package/src/routes/{resource-route.mjs → resource-route.js} +1 -1
  127. package/src/routes/{root-route.mjs → root-route.js} +1 -1
  128. package/src/templates/{configuration.mjs → configuration.js} +3 -3
  129. package/src/templates/{generate-migration.mjs → generate-migration.js} +1 -1
  130. package/src/templates/generate-model.js +6 -0
  131. package/src/templates/{routes.mjs → routes.js} +1 -1
  132. package/src/utils/rest-args-error.js +9 -0
  133. package/spec/database/record/create-spec.mjs +0 -14
  134. package/spec/dummy/src/config/configuration.example.mjs +0 -21
  135. package/spec/dummy/src/config/configuration.peakflow.mjs +0 -22
  136. package/spec/dummy/src/models/task.mjs +0 -4
  137. package/src/database/drivers/mysql/query-parser.mjs +0 -25
  138. package/src/database/drivers/sqlite/base.mjs +0 -36
  139. package/src/database/drivers/sqlite/index.web.mjs +0 -45
  140. package/src/database/drivers/sqlite/query-parser.mjs +0 -25
  141. package/src/database/drivers/sqlite/query.native.mjs +0 -9
  142. package/src/database/drivers/sqlite/query.web.mjs +0 -9
  143. package/src/database/drivers/sqlite/table.mjs +0 -9
  144. package/src/database/migration/index.mjs +0 -18
  145. package/src/database/query/create-table-base.mjs +0 -69
  146. package/src/database/query/index.mjs +0 -144
  147. package/src/database/query-parser/joins-parser.mjs +0 -30
  148. package/src/database/record/index.mjs +0 -187
  149. package/src/templates/generate-model.mjs +0 -4
  150. /package/{index.mjs → index.js} +0 -0
  151. /package/spec/dummy/{dummy-directory.mjs → dummy-directory.js} +0 -0
  152. /package/src/cli/{base-command.mjs → base-command.js} +0 -0
  153. /package/src/cli/commands/test/{test-runner.mjs → test-runner.js} +0 -0
  154. /package/src/{controller.mjs → controller.js} +0 -0
  155. /package/src/database/drivers/mysql/{connect-connection.mjs → connect-connection.js} +0 -0
  156. /package/src/database/drivers/mysql/{query.mjs → query.js} +0 -0
  157. /package/src/database/{handler.mjs → handler.js} +0 -0
  158. /package/src/database/query/{from-base.mjs → from-base.js} +0 -0
  159. /package/src/database/query/{insert-base.mjs → insert-base.js} +0 -0
  160. /package/src/database/query/{join-base.mjs → join-base.js} +0 -0
  161. /package/src/database/query/{order-base.mjs → order-base.js} +0 -0
  162. /package/src/database/query/{select-base.mjs → select-base.js} +0 -0
  163. /package/src/database/query/{update-base.mjs → update-base.js} +0 -0
  164. /package/src/database/query-parser/{from-parser.mjs → from-parser.js} +0 -0
  165. /package/src/database/record/{record-not-found-error.mjs → record-not-found-error.js} +0 -0
  166. /package/src/{error-logger.mjs → error-logger.js} +0 -0
  167. /package/src/http-server/client/{params-to-object.mjs → params-to-object.js} +0 -0
  168. /package/src/http-server/client/request-buffer/{form-data-part.mjs → form-data-part.js} +0 -0
  169. /package/src/http-server/client/request-buffer/{header.mjs → header.js} +0 -0
  170. /package/src/http-server/client/{response.mjs → response.js} +0 -0
  171. /package/src/{logger.mjs → logger.js} +0 -0
  172. /package/src/spec/{index.mjs → index.js} +0 -0
  173. /package/src/utils/{file-exists.mjs → file-exists.js} +0 -0
@@ -0,0 +1,206 @@
1
+ import FromPlain from "./from-plain.js"
2
+ import {incorporate} from "incorporator"
3
+ import * as inflection from "inflection"
4
+ import JoinPlain from "./join-plain.js"
5
+ import OrderPlain from "./order-plain.js"
6
+ import Preloader from "./preloader.js"
7
+ import SelectPlain from "./select-plain.js"
8
+ import WhereHash from "./where-hash.js"
9
+ import WherePlain from "./where-plain.js"
10
+
11
+ export default class VelociousDatabaseQuery {
12
+ constructor({driver, froms = [], groups = [], joins = [], handler, limits = [], modelClass, orders = [], preload = {}, selects = [], wheres = []}) {
13
+ if (!driver) throw new Error("No driver given to query")
14
+ if (!handler) throw new Error("No handler given to query")
15
+
16
+ this.driver = driver
17
+ this.handler = handler
18
+ this.modelClass = modelClass
19
+ this._froms = froms
20
+ this._groups = groups
21
+ this._joins = joins
22
+ this._limits = limits
23
+ this._orders = orders
24
+ this._preload = preload
25
+ this._selects = selects
26
+ this._wheres = wheres
27
+ }
28
+
29
+ clone() {
30
+ const newQuery = new VelociousDatabaseQuery({
31
+ driver: this.driver,
32
+ froms: [...this._froms],
33
+ handler: this.handler.clone(),
34
+ groups: [...this._groups],
35
+ joins: [...this._joins],
36
+ limits: [...this._limits],
37
+ modelClass: this.modelClass,
38
+ orders: [...this._orders],
39
+ preload: {...this._preload},
40
+ selects: [...this._selects],
41
+ wheres: [...this._wheres]
42
+ })
43
+
44
+ return newQuery
45
+ }
46
+
47
+ getOptions = () => this.driver.options()
48
+
49
+ async findBy(conditions) {
50
+ const newConditions = {}
51
+
52
+ for (const key in conditions) {
53
+ const keyUnderscore = inflection.underscore(key)
54
+
55
+ newConditions[keyUnderscore] = conditions[key]
56
+ }
57
+
58
+ return await this.clone().where(newConditions).first()
59
+ }
60
+
61
+ async findOrCreateBy(conditions) {
62
+ const record = await this.findOrInitializeBy(conditions)
63
+
64
+ if (record.isNewRecord()) {
65
+ await record.save()
66
+ }
67
+
68
+ return record
69
+ }
70
+
71
+ async findOrInitializeBy(conditions) {
72
+ const record = await this.findBy(conditions)
73
+
74
+ if (record) return record
75
+
76
+ const newRecord = new this.modelClass(conditions)
77
+
78
+ return newRecord
79
+ }
80
+
81
+ async first() {
82
+ const newQuery = this.clone()
83
+ const results = await newQuery.limit(1).reorder(this.modelClass.orderableColumn()).toArray()
84
+
85
+ return results[0]
86
+ }
87
+
88
+ from(from) {
89
+ if (typeof from == "string") from = new FromPlain({plain: from, query: this})
90
+
91
+ from.query = this
92
+
93
+ this._froms.push(from)
94
+ return this
95
+ }
96
+
97
+ group(group) {
98
+ this._groups.push(group)
99
+ return this
100
+ }
101
+
102
+ joins(join) {
103
+ if (typeof join == "string") {
104
+ join = new JoinPlain({plain: join, query: this})
105
+ } else if (typeof join == "object") {
106
+ // Do nothing
107
+ } else {
108
+ throw new Error(`Unknown type of join: ${typeof join}`)
109
+ }
110
+
111
+ this._joins.push(join)
112
+ return this
113
+ }
114
+
115
+ last = async () => await this.clone().reverseOrder().first()
116
+
117
+ limit(value) {
118
+ this._limits.push(value)
119
+ return this
120
+ }
121
+
122
+ order(order) {
123
+ if (typeof order == "number" || typeof order == "string") order = new OrderPlain({plain: order, query: this})
124
+
125
+ order.query = this
126
+
127
+ this._orders.push(order)
128
+ return this
129
+ }
130
+
131
+ preload(data) {
132
+ incorporate(this._preload, data)
133
+ return this
134
+ }
135
+
136
+ reorder(order) {
137
+ this._orders = []
138
+ this.order(order)
139
+ return this
140
+ }
141
+
142
+ reverseOrder() {
143
+ for (const order of this._orders) {
144
+ order.setReverseOrder(true)
145
+ }
146
+
147
+ return this
148
+ }
149
+
150
+ select(select) {
151
+ if (Array.isArray(select)) {
152
+ for (const selectInArray of select) {
153
+ this.select(selectInArray)
154
+ }
155
+
156
+ return this
157
+ }
158
+
159
+ if (typeof select == "string") select = new SelectPlain({plain: select})
160
+
161
+ select.query = this
162
+
163
+ this._selects.push(select)
164
+ return this
165
+ }
166
+
167
+ async toArray() {
168
+ const sql = this.toSql()
169
+ const results = await this.driver.query(sql)
170
+ const models = []
171
+
172
+ for (const result of results) {
173
+ const model = new this.modelClass()
174
+
175
+ model.loadExistingRecord(result)
176
+ models.push(model)
177
+ }
178
+
179
+ if (Object.keys(this._preload).length > 0 && models.length > 0) {
180
+ const preloader = new Preloader({
181
+ modelClass: this.modelClass,
182
+ models,
183
+ preload: this._preload
184
+ })
185
+
186
+ await preloader.run()
187
+ }
188
+
189
+ return models
190
+ }
191
+
192
+ toSql = () => this.driver.queryToSql(this)
193
+
194
+ where(where) {
195
+ if (typeof where == "string") {
196
+ where = new WherePlain(this, where)
197
+ } else if (typeof where == "object" && (where.constructor.name == "object" || where.constructor.name == "Object")) {
198
+ where = new WhereHash(this, where)
199
+ } else {
200
+ throw new Error(`Invalid type of where: ${typeof where} (${where.constructor.name})`)
201
+ }
202
+
203
+ this._wheres.push(where)
204
+ return this
205
+ }
206
+ }
@@ -1,4 +1,4 @@
1
- import JoinBase from "./join-base.mjs"
1
+ import JoinBase from "./join-base.js"
2
2
 
3
3
  export default class VelociousDatabaseQueryJoinPlain extends JoinBase {
4
4
  constructor({plain}) {
@@ -1,4 +1,4 @@
1
- import OrderBase from "./order-base.mjs"
1
+ import OrderBase from "./order-base.js"
2
2
 
3
3
  export default class VelociousDatabaseQueryOrderPlain extends OrderBase {
4
4
  constructor({plain}) {
@@ -0,0 +1,52 @@
1
+ import * as inflection from "inflection"
2
+ import restArgsError from "../../../utils/rest-args-error.js"
3
+
4
+ export default class VelociousDatabaseQueryPreloaderBelongsTo {
5
+ constructor({models, relationship, ...restArgs}) {
6
+ restArgsError(restArgs)
7
+
8
+ this.models = models
9
+ this.relationship = relationship
10
+ }
11
+
12
+ async run() {
13
+ const foreignKeyValues = []
14
+ const modelsById = {}
15
+ const foreignKey = this.relationship.getForeignKey()
16
+ const foreignKeyCamelized = inflection.camelize(foreignKey, true)
17
+ const preloadCollections = {}
18
+
19
+ for (const model of this.models) {
20
+ const foreignKeyValue = model[foreignKeyCamelized]()
21
+
22
+ preloadCollections[model.id()] = []
23
+ foreignKeyValues.push(foreignKeyValue)
24
+ modelsById[model.id()] = model
25
+ }
26
+
27
+ const whereArgs = {}
28
+ const primaryKey = this.relationship.getPrimaryKey()
29
+
30
+ whereArgs[primaryKey] = foreignKeyValues
31
+
32
+ // Load target models to be preloaded on the given models
33
+ const targetModels = await this.relationship.getTargetModelClass().where(whereArgs).toArray()
34
+ const targetModelsById = {}
35
+
36
+ for (const targetModel of targetModels) {
37
+ targetModelsById[targetModel.id()] = targetModel
38
+ }
39
+
40
+ // Set the target preloaded models on the given models
41
+ for (const model of this.models) {
42
+ const foreignKeyValue = model[foreignKeyCamelized]()
43
+ const targetModel = targetModelsById[foreignKeyValue]
44
+ const modelRelationship = model.getRelationshipByName(this.relationship.getRelationshipName())
45
+
46
+ modelRelationship.setPreloaded(true)
47
+ modelRelationship.setLoaded(targetModel)
48
+ }
49
+
50
+ return targetModels
51
+ }
52
+ }
@@ -0,0 +1,55 @@
1
+ import * as inflection from "inflection"
2
+ import restArgsError from "../../../utils/rest-args-error.js"
3
+
4
+ export default class VelociousDatabaseQueryPreloaderHasMany {
5
+ constructor({models, relationship, ...restArgs}) {
6
+ restArgsError(restArgs)
7
+
8
+ this.models = models
9
+ this.relationship = relationship
10
+ }
11
+
12
+ async run() {
13
+ const modelIds = []
14
+ const modelsById = {}
15
+ const foreignKey = this.relationship.getForeignKey()
16
+ const foreignKeyCamelized = inflection.camelize(foreignKey, true)
17
+ const preloadCollections = {}
18
+
19
+ for (const model of this.models) {
20
+ preloadCollections[model.id()] = []
21
+ modelIds.push(model.id())
22
+
23
+ if (!(model.id in modelsById)) modelsById[model.id()] = []
24
+
25
+ modelsById[model.id()].push(model)
26
+ }
27
+
28
+ const whereArgs = {}
29
+
30
+ whereArgs[foreignKey] = modelIds
31
+
32
+ // Load target models to be preloaded on the given models
33
+ const targetModels = await this.relationship.getTargetModelClass().where(whereArgs).toArray()
34
+
35
+ for (const targetModel of targetModels) {
36
+ const foreignKeyValue = targetModel[foreignKeyCamelized]()
37
+
38
+ preloadCollections[foreignKeyValue].push(targetModel)
39
+ }
40
+
41
+ // Set the target preloaded models on the given models
42
+ for (const modelId in preloadCollections) {
43
+ const preloadedCollection = preloadCollections[modelId]
44
+
45
+ for (const model of modelsById[modelId]) {
46
+ const modelRelationship = model.getRelationshipByName(this.relationship.getRelationshipName())
47
+
48
+ modelRelationship.setPreloaded(true)
49
+ modelRelationship.addToLoaded(preloadedCollection)
50
+ }
51
+ }
52
+
53
+ return targetModels
54
+ }
55
+ }
@@ -0,0 +1,41 @@
1
+ import BelongsToPreloader from "./preloader/belongs-to.js"
2
+ import HasManyPreloader from "./preloader/has-many.js"
3
+ import restArgsError from "../../utils/rest-args-error.js"
4
+
5
+ export default class VelociousDatabaseQueryPreloader {
6
+ constructor({modelClass, models, preload, ...restArgs}) {
7
+ restArgsError(restArgs)
8
+
9
+ this.modelClass = modelClass
10
+ this.models = models
11
+ this.preload = preload
12
+ }
13
+
14
+ async run() {
15
+ for (const preloadRelationshipName in this.preload) {
16
+ const relationship = this.modelClass.getRelationshipByName(preloadRelationshipName)
17
+ let targetModels
18
+
19
+ if (relationship.getType() == "belongsTo") {
20
+ const hasManyPreloader = new BelongsToPreloader({models: this.models, relationship: relationship})
21
+
22
+ targetModels = await hasManyPreloader.run()
23
+ } else if (relationship.getType() == "hasMany") {
24
+ const hasManyPreloader = new HasManyPreloader({models: this.models, relationship: relationship})
25
+
26
+ targetModels = await hasManyPreloader.run()
27
+ } else {
28
+ throw new Error(`Unknown relationship type: ${relationship.getType()}`)
29
+ }
30
+
31
+ // Handle any further preloads in the tree
32
+ const newPreload = this.preload[preloadRelationshipName]
33
+
34
+ if (typeof newPreload == "object" && targetModels.length > 0) {
35
+ const preloader = new VelociousDatabaseQueryPreloader({modelClass: relationship.getTargetModelClass(), models: targetModels, preload: newPreload})
36
+
37
+ await preloader.run()
38
+ }
39
+ }
40
+ }
41
+ }
@@ -1,4 +1,4 @@
1
- import SelectBase from "./select-base.mjs"
1
+ import SelectBase from "./select-base.js"
2
2
 
3
3
  export default class VelociousDatabaseQuerySelectPlain extends SelectBase {
4
4
  constructor({plain}) {
@@ -1,4 +1,4 @@
1
- import SelectBase from "./select-base.mjs"
1
+ import SelectBase from "./select-base.js"
2
2
 
3
3
  export default class VelociousDatabaseQuerySelectTableAndColumn extends SelectBase {
4
4
  constructor({query, tableName, columnName}) {
@@ -0,0 +1,9 @@
1
+ export default class VelociousDatabaseQueryWhereBase {
2
+ getOptions() {
3
+ return this.query.getOptions()
4
+ }
5
+
6
+ toSql() {
7
+ throw new Error("'toSql' wasn't implemented")
8
+ }
9
+ }
@@ -0,0 +1,35 @@
1
+ import WhereBase from "./where-base.js"
2
+
3
+ export default class VelociousDatabaseQueryWhereHash extends WhereBase {
4
+ constructor(query, hash) {
5
+ super()
6
+ this.hash = hash
7
+ this.query = query
8
+ }
9
+
10
+ toSql() {
11
+ const options = this.getOptions()
12
+ let sql = "("
13
+ let index = 0
14
+
15
+ for (const whereKey in this.hash) {
16
+ const whereValue = this.hash[whereKey]
17
+
18
+ if (index > 0) sql += " AND "
19
+
20
+ sql += `${options.quoteColumnName(whereKey)}`
21
+
22
+ if (Array.isArray(whereValue)) {
23
+ sql += ` IN (${whereValue.map((value) => options.quote(value)).join(", ")})`
24
+ } else {
25
+ sql += ` = ${options.quote(whereValue)}`
26
+ }
27
+
28
+ index++
29
+ }
30
+
31
+ sql += ")"
32
+
33
+ return sql
34
+ }
35
+ }
@@ -0,0 +1,13 @@
1
+ import WhereBase from "./where-base.js"
2
+
3
+ export default class VelociousDatabaseQueryWhereHash extends WhereBase {
4
+ constructor(query, plain) {
5
+ super()
6
+ this.plain = plain
7
+ this.query = query
8
+ }
9
+
10
+ toSql() {
11
+ return this.plain
12
+ }
13
+ }
@@ -0,0 +1,33 @@
1
+ import {digs} from "diggerize"
2
+ import FromParser from "./from-parser.js"
3
+ import GroupParser from "./group-parser.js"
4
+ import JoinsParser from "./joins-parser.js"
5
+ import LimitParser from "./limit-parser.js"
6
+ import OrderParser from "./order-parser.js"
7
+ import SelectParser from "./select-parser.js"
8
+ import WhereParser from "./where-parser.js"
9
+
10
+ export default class VelociousDatabaseBaseQueryParser {
11
+ constructor({pretty, query}) {
12
+ if (!query) throw new Error("No query given")
13
+
14
+ this.pretty = pretty
15
+ this.query = query
16
+ }
17
+
18
+ toSql() {
19
+ const {pretty, query} = digs(this, "pretty", "query")
20
+
21
+ let sql = ""
22
+
23
+ sql += new SelectParser({pretty, query}).toSql()
24
+ sql += new FromParser({pretty, query}).toSql()
25
+ sql += new JoinsParser({pretty, query}).toSql()
26
+ sql += new WhereParser({pretty, query}).toSql()
27
+ sql += new GroupParser({pretty, query}).toSql()
28
+ sql += new OrderParser({pretty, query}).toSql()
29
+ sql += new LimitParser({pretty, query}).toSql()
30
+
31
+ return sql
32
+ }
33
+ }
@@ -0,0 +1,40 @@
1
+ import {digs} from "diggerize"
2
+
3
+ export default class VelociousDatabaseQueryParserFromParser {
4
+ constructor({pretty, query}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ }
8
+
9
+ toSql() {
10
+ const {pretty, query} = digs(this, "pretty", "query")
11
+
12
+ if (query._groups.length == 0) {
13
+ return ""
14
+ }
15
+
16
+ let sql = " GROUP BY"
17
+
18
+ for (const groupKey in query._groups) {
19
+ const group = query._groups[groupKey]
20
+
21
+ if (groupKey > 0) {
22
+ sql += ","
23
+ }
24
+
25
+ if (pretty) {
26
+ sql += "\n "
27
+ } else {
28
+ sql += " "
29
+ }
30
+
31
+ if (typeof group == "string") {
32
+ sql += group
33
+ } else {
34
+ sql += group.toSql()
35
+ }
36
+ }
37
+
38
+ return sql
39
+ }
40
+ }
@@ -0,0 +1,71 @@
1
+ import {digs} from "diggerize"
2
+ import JoinPlain from "../query/join-plain.js"
3
+
4
+ export default class VelocuiousDatabaseQueryParserJoinsParser {
5
+ constructor({pretty, query}) {
6
+ this.pretty = pretty
7
+ this.query = query
8
+ this.conn = this.query.driver
9
+ }
10
+
11
+ toSql() {
12
+ const {pretty, query} = digs(this, "pretty", "query")
13
+ let sql = ""
14
+
15
+ for (const joinKey in query._joins) {
16
+ const join = query._joins[joinKey]
17
+
18
+ if (join instanceof JoinPlain) {
19
+ if (joinKey == 0) {
20
+ if (pretty) {
21
+ sql += "\n\n"
22
+ } else {
23
+ sql += " "
24
+ }
25
+ }
26
+
27
+ sql += join.toSql()
28
+ } else if (typeof join == "object") {
29
+ sql = this.joinObject({join, modelClass: query.modelClass, sql})
30
+ } else {
31
+ throw new Error(`Unknown join object: ${join.constructor.name}`)
32
+ }
33
+ }
34
+
35
+ return sql
36
+ }
37
+
38
+ joinObject({join, modelClass, sql}) {
39
+ const {conn, pretty} = this
40
+
41
+ for (const joinKey in join) {
42
+ const joinValue = join[joinKey]
43
+ const relationship = modelClass.getRelationshipByName(joinKey)
44
+ const targetModelClass = relationship.getTargetModelClass()
45
+
46
+ if (pretty) {
47
+ sql += "\n\n"
48
+ } else {
49
+ sql += " "
50
+ }
51
+
52
+ sql += `LEFT JOIN ${conn.quoteTable(targetModelClass.tableName())} ON `
53
+
54
+ if (relationship.getType() == "belongsTo") {
55
+ sql += `${conn.quoteTable(targetModelClass.tableName())}.${conn.quoteColumn(relationship.getPrimaryKey())} = `
56
+ sql += `${conn.quoteTable(modelClass.tableName())}.${conn.quoteColumn(relationship.getForeignKey())}`
57
+ } else if (relationship.getType() == "hasMany" || relationship.getType() == "hasOne") {
58
+ sql += `${conn.quoteTable(targetModelClass.tableName())}.${conn.quoteColumn(relationship.getForeignKey())} = `
59
+ sql += `${conn.quoteTable(modelClass.tableName())}.${conn.quoteColumn(relationship.getPrimaryKey())}`
60
+ } else {
61
+ throw new Error(`Unknown relationship type: ${relationship.getType()}`)
62
+ }
63
+
64
+ if (typeof joinValue == "object") {
65
+ sql = this.joinObject({join: joinValue, modelClass: targetModelClass, sql})
66
+ }
67
+ }
68
+
69
+ return sql
70
+ }
71
+ }
@@ -0,0 +1,40 @@
1
+ import {digs} from "diggerize"
2
+
3
+ export default class VelocuiousDatabaseQueryParserLimitParser {
4
+ constructor({pretty, query}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ }
8
+
9
+ toSql() {
10
+ const {pretty, query} = digs(this, "pretty", "query")
11
+ let sql = ""
12
+
13
+ if (query._limits.length == 0) return sql
14
+ if (query._limits.length >= 2) throw new Error(`Multiple limits found: ${query._limits.join(", ")}`)
15
+
16
+ if (pretty) {
17
+ sql += "\n\n"
18
+ } else {
19
+ sql += " "
20
+ }
21
+
22
+ sql += "LIMIT"
23
+
24
+ for (const limitKey in query._limits) {
25
+ const limit = query._limits[limitKey]
26
+
27
+ if (limitKey > 0) sql += ","
28
+
29
+ if (pretty) {
30
+ sql += "\n "
31
+ } else {
32
+ sql += " "
33
+ }
34
+
35
+ sql += this.query.getOptions().quote(limit)
36
+ }
37
+
38
+ return sql
39
+ }
40
+ }
@@ -3,11 +3,12 @@ import {digg} from "diggerize"
3
3
  export default class VelociousDatabaseQueryParserOptions {
4
4
  constructor(options) {
5
5
  this.columnQuote = digg(options, "columnQuote")
6
+ this.indexQuote = digg(options, "indexQuote")
6
7
  this.driver = digg(options, "driver")
7
8
  this.tableQuote = digg(options, "tableQuote")
8
9
  this.stringQuote = digg(options, "stringQuote")
9
10
 
10
- if (!this.driver) throw new Error("No driver given")
11
+ if (!this.driver) throw new Error("No driver given to parser options")
11
12
  }
12
13
 
13
14
  quoteColumnName(columnName) {
@@ -0,0 +1,39 @@
1
+ import {digs} from "diggerize"
2
+
3
+ export default class VelocuiousDatabaseQueryParserOrderParser {
4
+ constructor({pretty, query}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ }
8
+
9
+ toSql() {
10
+ const {pretty, query} = digs(this, "pretty", "query")
11
+ let sql = ""
12
+
13
+ if (query._orders.length == 0) return sql
14
+
15
+ if (pretty) {
16
+ sql += "\n\n"
17
+ } else {
18
+ sql += " "
19
+ }
20
+
21
+ sql += "ORDER BY"
22
+
23
+ for (const orderKey in query._orders) {
24
+ const order = query._orders[orderKey]
25
+
26
+ if (orderKey > 0) sql += " ,"
27
+
28
+ if (pretty) {
29
+ sql += "\n "
30
+ } else {
31
+ sql += " "
32
+ }
33
+
34
+ sql += order.toSql()
35
+ }
36
+
37
+ return sql
38
+ }
39
+ }