velocious 1.0.103 → 1.0.105
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/create-spec.js +7 -0
- package/spec/dummy/dummy-directory.js +2 -0
- package/spec/dummy/index.js +5 -1
- package/spec/dummy/src/model-bases/project.js +18 -0
- package/src/application.js +1 -0
- package/src/configuration-types.js +6 -0
- package/src/controller.js +44 -24
- package/src/database/drivers/base-foreign-key.js +1 -1
- package/src/database/drivers/base.js +2 -2
- package/src/database/drivers/mssql/column.js +6 -0
- package/src/database/drivers/mssql/columns-index.js +2 -5
- package/src/database/drivers/mssql/foreign-key.js +2 -0
- package/src/database/drivers/mssql/options.js +25 -0
- package/src/database/drivers/mssql/query-parser.js +2 -0
- package/src/database/drivers/mysql/options.js +9 -0
- package/src/database/drivers/mysql/sql/alter-table.js +2 -0
- package/src/database/drivers/mysql/sql/create-database.js +2 -0
- package/src/database/drivers/mysql/sql/create-index.js +2 -0
- package/src/database/drivers/mysql/sql/create-table.js +2 -0
- package/src/database/drivers/mysql/sql/delete.js +2 -0
- package/src/database/drivers/mysql/sql/drop-table.js +2 -0
- package/src/database/drivers/mysql/sql/insert.js +2 -0
- package/src/database/drivers/mysql/sql/update.js +2 -0
- package/src/database/drivers/pgsql/column.js +6 -0
- package/src/database/drivers/pgsql/columns-index.js +2 -0
- package/src/database/drivers/pgsql/foreign-key.js +2 -0
- package/src/database/drivers/pgsql/options.js +9 -0
- package/src/database/drivers/pgsql/query-parser.js +2 -0
- package/src/database/drivers/pgsql/sql/alter-table.js +2 -0
- package/src/database/drivers/pgsql/sql/create-database.js +5 -4
- package/src/database/drivers/pgsql/sql/create-index.js +2 -0
- package/src/database/drivers/pgsql/sql/create-table.js +2 -0
- package/src/database/drivers/pgsql/sql/delete.js +2 -0
- package/src/database/drivers/pgsql/sql/drop-table.js +2 -0
- package/src/database/drivers/pgsql/sql/insert.js +2 -0
- package/src/database/drivers/pgsql/sql/update.js +2 -0
- package/src/database/drivers/pgsql/table.js +6 -0
- package/src/database/drivers/sqlite/columns-index.js +2 -6
- package/src/database/drivers/sqlite/connection-remote.js +7 -0
- package/src/database/drivers/sqlite/connection-sql-js.js +12 -2
- package/src/database/drivers/sqlite/foreign-key.js +7 -0
- package/src/database/drivers/sqlite/index.js +7 -1
- package/src/database/drivers/sqlite/index.web.js +12 -3
- package/src/database/drivers/sqlite/options.js +9 -0
- package/src/database/drivers/sqlite/query-parser.js +2 -0
- package/src/database/drivers/sqlite/query.js +19 -6
- package/src/database/drivers/sqlite/query.web.js +13 -1
- package/src/database/initializer-from-require-context.js +11 -1
- package/src/database/migrator/types.js +2 -0
- package/src/database/pool/base-methods-forward.js +7 -0
- package/src/database/query/delete-base.js +8 -0
- package/src/database/query/preloader/belongs-to.js +16 -1
- package/src/database/query/preloader/has-many.js +19 -1
- package/src/database/query/preloader/has-one.js +20 -2
- package/src/database/query/preloader.js +19 -4
- package/src/database/query/update-base.js +9 -0
- package/src/database/query-parser/limit-parser.js +7 -2
- package/src/database/query-parser/options.js +47 -6
- package/src/database/query-parser/order-parser.js +11 -6
- package/src/database/query-parser/select-parser.js +8 -5
- package/src/database/query-parser/where-parser.js +11 -5
- package/src/database/record/index.js +28 -24
- package/src/database/record/instance-relationships/base.js +10 -1
- package/src/database/record/record-not-found-error.js +2 -0
- package/src/database/record/user-module.js +13 -0
- package/src/database/record/validators/uniqueness.js +13 -2
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +19 -0
- package/src/error-logger.js +17 -3
- package/src/http-client/index.js +34 -2
- package/src/http-client/request.js +1 -1
- package/src/http-server/client/params-to-object.js +28 -0
- package/src/initializer.js +2 -0
- package/src/routes/app-routes.js +3 -1
- package/src/routes/base-route.js +67 -58
- package/src/routes/basic-route.js +76 -0
- package/src/routes/get-route.js +21 -5
- package/src/routes/index.js +10 -0
- package/src/routes/namespace-route.js +21 -5
- package/src/routes/post-route.js +20 -5
- package/src/routes/resolver.js +15 -2
- package/src/routes/resource-route.js +21 -5
- package/src/routes/root-route.js +3 -3
- package/src/testing/request-client.js +19 -14
- package/src/testing/test-runner.js +16 -10
- package/src/testing/test.js +70 -22
- package/src/utils/with-tracked-stack-async-hooks.js +22 -4
- package/src/utils/with-tracked-stack.js +9 -0
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
2
|
|
|
3
3
|
export default class VelocuiousDatabaseQueryParserOrderParser {
|
|
4
|
+
/**
|
|
5
|
+
* @param {object} args
|
|
6
|
+
* @param {boolean} args.pretty
|
|
7
|
+
* @param {import("../query/index.js").default} args.query
|
|
8
|
+
*/
|
|
4
9
|
constructor({pretty, query}) {
|
|
5
10
|
this.pretty = pretty
|
|
6
11
|
this.query = query
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
toSql() {
|
|
10
|
-
const {pretty, query} =
|
|
15
|
+
const {pretty, query} = this
|
|
11
16
|
let sql = ""
|
|
12
17
|
|
|
13
18
|
if (query._orders.length == 0) return sql
|
|
@@ -19,11 +24,10 @@ export default class VelocuiousDatabaseQueryParserOrderParser {
|
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
sql += "ORDER BY"
|
|
27
|
+
let count = 0
|
|
22
28
|
|
|
23
|
-
for (const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (orderKey > 0) sql += " ,"
|
|
29
|
+
for (const order of query._orders) {
|
|
30
|
+
if (count > 0) sql += " ,"
|
|
27
31
|
|
|
28
32
|
if (pretty) {
|
|
29
33
|
sql += "\n "
|
|
@@ -32,6 +36,7 @@ export default class VelocuiousDatabaseQueryParserOrderParser {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
sql += order.toSql()
|
|
39
|
+
count++
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
return sql
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
2
3
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
3
4
|
|
|
4
5
|
export default class VelociousDatabaseQueryParserSelectParser {
|
|
@@ -15,7 +16,7 @@ export default class VelociousDatabaseQueryParserSelectParser {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
toSql() {
|
|
18
|
-
const {pretty, query} =
|
|
19
|
+
const {pretty, query} = this
|
|
19
20
|
|
|
20
21
|
let sql = ""
|
|
21
22
|
|
|
@@ -27,14 +28,14 @@ export default class VelociousDatabaseQueryParserSelectParser {
|
|
|
27
28
|
sql += " "
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
const selectValue = query._selects[selectKey]
|
|
31
|
+
let count = 0
|
|
32
32
|
|
|
33
|
+
for (const selectValue of query._selects) {
|
|
33
34
|
selectValue.setQuery(query)
|
|
34
35
|
|
|
35
36
|
sql += selectValue.toSql()
|
|
36
37
|
|
|
37
|
-
if (
|
|
38
|
+
if (count + 1 < query._selects.length) {
|
|
38
39
|
if (pretty) {
|
|
39
40
|
sql += ","
|
|
40
41
|
sql += " "
|
|
@@ -42,6 +43,8 @@ export default class VelociousDatabaseQueryParserSelectParser {
|
|
|
42
43
|
sql += ", "
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
|
|
47
|
+
count++
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
if (query.getSelects().length == 0) {
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
2
|
|
|
3
3
|
export default class VelocuiousDatabaseQueryParserWhereParser {
|
|
4
|
+
/**
|
|
5
|
+
* @param {object} args
|
|
6
|
+
* @param {boolean} args.pretty
|
|
7
|
+
* @param {import("../query/index.js").default} args.query
|
|
8
|
+
*/
|
|
4
9
|
constructor({pretty, query}) {
|
|
5
10
|
this.pretty = pretty
|
|
6
11
|
this.query = query
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
toSql() {
|
|
10
|
-
const {pretty, query} =
|
|
15
|
+
const {pretty, query} = this
|
|
11
16
|
let sql = ""
|
|
12
17
|
|
|
13
18
|
if (query._wheres.length == 0) return sql
|
|
@@ -20,10 +25,10 @@ export default class VelocuiousDatabaseQueryParserWhereParser {
|
|
|
20
25
|
|
|
21
26
|
sql += "WHERE"
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
const where = query._wheres[whereKey]
|
|
28
|
+
let count = 0
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
for (const where of query._wheres) {
|
|
31
|
+
if (count > 0) sql += " AND"
|
|
27
32
|
|
|
28
33
|
if (pretty) {
|
|
29
34
|
sql += "\n "
|
|
@@ -32,6 +37,7 @@ export default class VelocuiousDatabaseQueryParserWhereParser {
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
sql += where.toSql()
|
|
40
|
+
count++
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
return sql
|
|
@@ -468,9 +468,6 @@ class VelociousDatabaseRecord {
|
|
|
468
468
|
const columnNameToAttributeName = this.getColumnNameToAttributeNameMap()
|
|
469
469
|
const attributeNameToColumnName = this.getAttributeNameToColumnNameMap()
|
|
470
470
|
|
|
471
|
-
/** @type {Record<string, (this: VelociousDatabaseRecord) => unknown>} */
|
|
472
|
-
const proto = /** @type {any} */ (this.prototype);
|
|
473
|
-
|
|
474
471
|
for (const column of this._columns) {
|
|
475
472
|
this._columnsAsHash[column.getName()] = column
|
|
476
473
|
|
|
@@ -480,17 +477,18 @@ class VelociousDatabaseRecord {
|
|
|
480
477
|
attributeNameToColumnName[camelizedColumnName] = column.getName()
|
|
481
478
|
columnNameToAttributeName[column.getName()] = camelizedColumnName
|
|
482
479
|
|
|
483
|
-
|
|
480
|
+
// @ts-expect-error
|
|
481
|
+
this.prototype[camelizedColumnName] = function() {
|
|
484
482
|
return this.readAttribute(camelizedColumnName)
|
|
485
483
|
}
|
|
486
484
|
|
|
487
485
|
// @ts-expect-error
|
|
488
|
-
|
|
489
|
-
// @ts-expect-error
|
|
486
|
+
this.prototype[`set${camelizedColumnNameBigFirst}`] = function(newValue) {
|
|
490
487
|
return this._setColumnAttribute(camelizedColumnName, newValue)
|
|
491
488
|
}
|
|
492
489
|
|
|
493
|
-
|
|
490
|
+
// @ts-expect-error
|
|
491
|
+
this.prototype[`has${camelizedColumnNameBigFirst}`] = function() {
|
|
494
492
|
// @ts-expect-error
|
|
495
493
|
let value = this[camelizedColumnName]()
|
|
496
494
|
|
|
@@ -539,24 +537,20 @@ class VelociousDatabaseRecord {
|
|
|
539
537
|
const nameCamelized = inflection.camelize(name)
|
|
540
538
|
const setterMethodName = `set${nameCamelized}`
|
|
541
539
|
|
|
542
|
-
/** @type {Record<string, unknown>} */
|
|
543
540
|
// @ts-expect-error
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
/** @type {Record<string, (this: VelociousDatabaseRecord) => unknown>} */
|
|
547
|
-
const proto = /** @type {any} */ (this.prototype);
|
|
548
|
-
|
|
549
|
-
proto[name] = function getTranslatedAttribute() {
|
|
541
|
+
this.prototype[name] = function getTranslatedAttribute() {
|
|
550
542
|
const locale = this._getConfiguration().getLocale()
|
|
551
543
|
|
|
552
544
|
return this._getTranslatedAttributeWithFallback(name, locale)
|
|
553
545
|
}
|
|
554
546
|
|
|
555
|
-
|
|
556
|
-
|
|
547
|
+
// @ts-expect-error
|
|
548
|
+
this.prototype[`has${nameCamelized}`] = function hasTranslatedAttribute() {
|
|
549
|
+
// @ts-expect-error
|
|
550
|
+
const candidate = this[name]
|
|
557
551
|
|
|
558
552
|
if (typeof candidate == "function") {
|
|
559
|
-
const value = candidate()
|
|
553
|
+
const value = candidate.bind(this)()
|
|
560
554
|
|
|
561
555
|
return this._hasAttribute(value)
|
|
562
556
|
} else {
|
|
@@ -565,11 +559,9 @@ class VelociousDatabaseRecord {
|
|
|
565
559
|
}
|
|
566
560
|
|
|
567
561
|
// @ts-expect-error
|
|
568
|
-
|
|
569
|
-
// @ts-expect-error
|
|
562
|
+
this.prototype[setterMethodName] = function setTranslatedAttribute(newValue) {
|
|
570
563
|
const locale = this._getConfiguration().getLocale()
|
|
571
564
|
|
|
572
|
-
// @ts-expect-error
|
|
573
565
|
return this._setTranslatedAttribute(name, locale, newValue)
|
|
574
566
|
}
|
|
575
567
|
|
|
@@ -577,6 +569,7 @@ class VelociousDatabaseRecord {
|
|
|
577
569
|
const localeCamelized = inflection.camelize(locale)
|
|
578
570
|
const getterMethodNameLocalized = `${name}${localeCamelized}`
|
|
579
571
|
const setterMethodNameLocalized = `${setterMethodName}${localeCamelized}`
|
|
572
|
+
const hasMethodNameLocalized = `has${inflection.camelize(name)}${localeCamelized}`
|
|
580
573
|
|
|
581
574
|
// @ts-expect-error
|
|
582
575
|
this.prototype[getterMethodNameLocalized] = function getTranslatedAttributeWithLocale() {
|
|
@@ -587,6 +580,20 @@ class VelociousDatabaseRecord {
|
|
|
587
580
|
this.prototype[setterMethodNameLocalized] = function setTranslatedAttributeWithLocale(newValue) {
|
|
588
581
|
return this._setTranslatedAttribute(name, locale, newValue)
|
|
589
582
|
}
|
|
583
|
+
|
|
584
|
+
// @ts-expect-error
|
|
585
|
+
this.prototype[hasMethodNameLocalized] = function hasTranslatedAttribute() {
|
|
586
|
+
// @ts-expect-error
|
|
587
|
+
const candidate = this[getterMethodNameLocalized]
|
|
588
|
+
|
|
589
|
+
if (typeof candidate == "function") {
|
|
590
|
+
const value = candidate.bind(this)()
|
|
591
|
+
|
|
592
|
+
return this._hasAttribute(value)
|
|
593
|
+
} else {
|
|
594
|
+
throw new Error(`Expected candidate to be a function but it was: ${typeof candidate}`)
|
|
595
|
+
}
|
|
596
|
+
}
|
|
590
597
|
}
|
|
591
598
|
}
|
|
592
599
|
}
|
|
@@ -621,10 +628,7 @@ class VelociousDatabaseRecord {
|
|
|
621
628
|
return this._attributes[columnName]
|
|
622
629
|
}
|
|
623
630
|
|
|
624
|
-
/**
|
|
625
|
-
*
|
|
626
|
-
* @returns {typeof VelociousDatabaseRecord}
|
|
627
|
-
*/
|
|
631
|
+
/** @returns {typeof VelociousDatabaseRecord} */
|
|
628
632
|
getModelClass() {
|
|
629
633
|
const modelClass = /** @type {typeof VelociousDatabaseRecord} */ (this.constructor)
|
|
630
634
|
|
|
@@ -15,6 +15,15 @@ export default class VelociousDatabaseRecordBaseInstanceRelationship {
|
|
|
15
15
|
this.relationship = relationship
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @abstract
|
|
20
|
+
* @param {import("../index.js").default[]} records
|
|
21
|
+
* @returns {void}
|
|
22
|
+
*/
|
|
23
|
+
addToLoaded(records) { // eslint-disable-line no-unused-vars
|
|
24
|
+
throw new Error("addToLoaded not implemented")
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
/**
|
|
19
28
|
* @abstract
|
|
20
29
|
* @param {Record<string, any>} attributes
|
|
@@ -62,7 +71,7 @@ export default class VelociousDatabaseRecordBaseInstanceRelationship {
|
|
|
62
71
|
return this._loaded
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
/** @param {import("../index.js").default|Array<import("../index.js").default
|
|
74
|
+
/** @param {import("../index.js").default|Array<import("../index.js").default>|undefined} model */
|
|
66
75
|
setLoaded(model) { this._loaded = model }
|
|
67
76
|
|
|
68
77
|
/** @returns {import("../index.js").default | import("../index.js").default[] | undefined} */
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import bcryptjs from "bcryptjs"
|
|
2
4
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
3
5
|
|
|
4
6
|
export default class UserModule {
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} args
|
|
9
|
+
* @param {string} args.secretKey
|
|
10
|
+
*/
|
|
5
11
|
constructor({secretKey, ...restArgs}) {
|
|
6
12
|
restArgsError(restArgs)
|
|
7
13
|
|
|
@@ -10,18 +16,25 @@ export default class UserModule {
|
|
|
10
16
|
this.secretKey = secretKey
|
|
11
17
|
}
|
|
12
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @param {typeof import("./index.js").default} UserClass
|
|
21
|
+
*/
|
|
13
22
|
attachTo(UserClass) {
|
|
23
|
+
// @ts-expect-error
|
|
14
24
|
UserClass.prototype.setPassword = function(newPassword) {
|
|
15
25
|
const salt = bcryptjs.genSaltSync(10)
|
|
16
26
|
const encryptedPassword = bcryptjs.hashSync(newPassword, salt)
|
|
17
27
|
|
|
28
|
+
// @ts-expect-error
|
|
18
29
|
this.setEncryptedPassword(encryptedPassword)
|
|
19
30
|
}
|
|
20
31
|
|
|
32
|
+
// @ts-expect-error
|
|
21
33
|
UserClass.prototype.setPasswordConfirmation = function(newPasswordConfirmation) {
|
|
22
34
|
const salt = bcryptjs.genSaltSync(10)
|
|
23
35
|
const encryptedPassword = bcryptjs.hashSync(newPasswordConfirmation, salt)
|
|
24
36
|
|
|
37
|
+
// @ts-expect-error
|
|
25
38
|
this._encryptedPasswordConfirmation = encryptedPassword
|
|
26
39
|
}
|
|
27
40
|
}
|
|
@@ -1,18 +1,29 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import Base from "./base.js"
|
|
2
4
|
import * as inflection from "inflection"
|
|
3
5
|
|
|
4
6
|
export default class VelociousDatabaseRecordValidatorsUniqueness extends Base {
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} args
|
|
9
|
+
* @param {import("../index.js").default} args.model
|
|
10
|
+
* @param {string} args.attributeName
|
|
11
|
+
* @returns {Promise<void>}
|
|
12
|
+
*/
|
|
5
13
|
async validate({model, attributeName}) {
|
|
6
|
-
const modelClass = model.constructor
|
|
14
|
+
const modelClass = /** @type {typeof import("../index.js").default} */ (model.constructor)
|
|
15
|
+
|
|
7
16
|
const connection = modelClass.connection()
|
|
8
17
|
const tableName = modelClass._getTable().getName()
|
|
9
18
|
const attributeValue = model.readAttribute(attributeName)
|
|
10
19
|
const attributeNameUnderscore = inflection.underscore(attributeName)
|
|
20
|
+
|
|
21
|
+
/** @type {Record<string, any>} */
|
|
11
22
|
const whereArgs = {}
|
|
12
23
|
|
|
13
24
|
whereArgs[attributeNameUnderscore] = attributeValue
|
|
14
25
|
|
|
15
|
-
let existingRecordQuery =
|
|
26
|
+
let existingRecordQuery = modelClass
|
|
16
27
|
.select(modelClass.primaryKey())
|
|
17
28
|
.where(whereArgs)
|
|
18
29
|
|
|
@@ -98,6 +98,16 @@ export default class DbGenerateModel extends BaseCommand {
|
|
|
98
98
|
fileContent += ` ${name}() { return this._getTranslatedAttributeWithFallback("${name}", this._getConfiguration().getLocale()) }\n`
|
|
99
99
|
methodsCount++
|
|
100
100
|
|
|
101
|
+
const hasName = `has${inflection.camelize(name)}`
|
|
102
|
+
|
|
103
|
+
fileContent += `\n`
|
|
104
|
+
fileContent += " /**\n"
|
|
105
|
+
fileContent += ` * @abstract\n`
|
|
106
|
+
fileContent += ` * @returns {boolean}\n`
|
|
107
|
+
fileContent += " */\n"
|
|
108
|
+
fileContent += ` ${hasName}() { throw new Error("${hasName} not implemented") }\n`
|
|
109
|
+
methodsCount++
|
|
110
|
+
|
|
101
111
|
for (const locale of this.getConfiguration().getLocales()) {
|
|
102
112
|
const localeMethodName = `${name}${inflection.camelize(locale)}`
|
|
103
113
|
|
|
@@ -109,7 +119,16 @@ export default class DbGenerateModel extends BaseCommand {
|
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
fileContent += ` ${localeMethodName}() { return this._getTranslatedAttributeWithFallback("${name}", "${locale}") }\n`
|
|
122
|
+
methodsCount++
|
|
123
|
+
|
|
124
|
+
const localeHasName = `has${inflection.camelize(localeMethodName)}`
|
|
112
125
|
|
|
126
|
+
fileContent += `\n`
|
|
127
|
+
fileContent += " /**\n"
|
|
128
|
+
fileContent += ` * @abstract\n`
|
|
129
|
+
fileContent += ` * @returns {boolean}\n`
|
|
130
|
+
fileContent += " */\n"
|
|
131
|
+
fileContent += ` ${localeHasName}() { throw new Error("${localeHasName} not implemented") }\n`
|
|
113
132
|
methodsCount++
|
|
114
133
|
}
|
|
115
134
|
}
|
package/src/error-logger.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {(...args: any[]) => Promise<void>} callback
|
|
5
|
+
*/
|
|
1
6
|
export default function errorLogger(callback) {
|
|
7
|
+
/**
|
|
8
|
+
* @param {...any} args
|
|
9
|
+
* @returns {Promise<void>}
|
|
10
|
+
*/
|
|
2
11
|
return async function(...args) {
|
|
3
12
|
try {
|
|
4
13
|
await callback(...args)
|
|
5
14
|
} catch (error) {
|
|
6
|
-
|
|
15
|
+
if (error instanceof Error) {
|
|
16
|
+
console.error(`ErrorLogger: ${error.message}`)
|
|
7
17
|
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
if (error.stack) {
|
|
19
|
+
console.error("Stack", error.stack)
|
|
20
|
+
} else {
|
|
21
|
+
console.error("No stack")
|
|
22
|
+
}
|
|
10
23
|
} else {
|
|
24
|
+
console.error(`ErrorLogger: ${error}`)
|
|
11
25
|
console.error("No stack")
|
|
12
26
|
}
|
|
13
27
|
|
package/src/http-client/index.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import net from "net"
|
|
2
4
|
import Request from "./request.js"
|
|
3
5
|
import Response from "./response.js"
|
|
4
6
|
import {Logger} from "../logger.js"
|
|
5
7
|
|
|
6
8
|
export default class HttpClient {
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} args
|
|
11
|
+
* @param {boolean} [args.debug]
|
|
12
|
+
* @param {Array<import("./header.js").default>} [args.headers]
|
|
13
|
+
* @param {string} [args.version]
|
|
14
|
+
*/
|
|
7
15
|
constructor({debug = false, headers, version = "1.1"}) {
|
|
8
16
|
this.headers = headers || []
|
|
9
17
|
this.logger = new Logger(this, {debug})
|
|
@@ -15,7 +23,7 @@ export default class HttpClient {
|
|
|
15
23
|
this.connectionReject = reject
|
|
16
24
|
this.connection = net.createConnection(3006, "127.0.0.1", () => {
|
|
17
25
|
this.connectionReject = null
|
|
18
|
-
resolve()
|
|
26
|
+
resolve(null)
|
|
19
27
|
})
|
|
20
28
|
|
|
21
29
|
this.connection.on("data", this.onConnectionData)
|
|
@@ -24,6 +32,12 @@ export default class HttpClient {
|
|
|
24
32
|
})
|
|
25
33
|
}
|
|
26
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} path
|
|
37
|
+
* @param {object} [options]
|
|
38
|
+
* @param {Array<import("./header.js").default>} [options.headers]
|
|
39
|
+
* @returns {Promise<{request: import("./request.js").default, response: import("./response.js").default}>}
|
|
40
|
+
*/
|
|
27
41
|
get(path, {headers} = {}) {
|
|
28
42
|
if (!this.connection) throw new Error("Not connected yet")
|
|
29
43
|
|
|
@@ -41,7 +55,7 @@ export default class HttpClient {
|
|
|
41
55
|
|
|
42
56
|
for (const header of this.headers) {
|
|
43
57
|
const existingNewHeader = newHeaders.find((newHeader) => {
|
|
44
|
-
return newHeader.
|
|
58
|
+
return newHeader.getName().toLowerCase().trim() === header.getName().toLowerCase().trim()
|
|
45
59
|
})
|
|
46
60
|
|
|
47
61
|
if (!existingNewHeader) {
|
|
@@ -56,8 +70,14 @@ export default class HttpClient {
|
|
|
56
70
|
this.currentRequest.stream((chunk) => {
|
|
57
71
|
this.logger.debug(() => [`Writing: ${chunk}`])
|
|
58
72
|
|
|
73
|
+
if (!this.connection) {
|
|
74
|
+
throw new Error("No connection to write to")
|
|
75
|
+
}
|
|
76
|
+
|
|
59
77
|
this.connection.write(chunk, "utf8", (error) => {
|
|
60
78
|
if (error) {
|
|
79
|
+
if (!this.currentRequestReject) throw new Error("No current request reject function")
|
|
80
|
+
|
|
61
81
|
this.currentRequestReject(error)
|
|
62
82
|
}
|
|
63
83
|
})
|
|
@@ -65,7 +85,12 @@ export default class HttpClient {
|
|
|
65
85
|
})
|
|
66
86
|
}
|
|
67
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @param {Buffer} data
|
|
90
|
+
*/
|
|
68
91
|
onConnectionData = (data) => {
|
|
92
|
+
if (!this.currentResponse) throw new Error("No current response to feed data to")
|
|
93
|
+
|
|
69
94
|
this.currentResponse.feed(data)
|
|
70
95
|
}
|
|
71
96
|
|
|
@@ -73,6 +98,9 @@ export default class HttpClient {
|
|
|
73
98
|
this.connection = null
|
|
74
99
|
}
|
|
75
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @param {Error} error
|
|
103
|
+
*/
|
|
76
104
|
onConnectionError = (error) => {
|
|
77
105
|
if (this.connectionReject) {
|
|
78
106
|
this.connectionReject(error)
|
|
@@ -90,6 +118,10 @@ export default class HttpClient {
|
|
|
90
118
|
}
|
|
91
119
|
|
|
92
120
|
onResponseComplete = () => {
|
|
121
|
+
if (!this.currentRequestResolve) throw new Error("No current request resolve function")
|
|
122
|
+
if (!this.currentRequest) throw new Error("No current request")
|
|
123
|
+
if (!this.currentResponse) throw new Error("No current response")
|
|
124
|
+
|
|
93
125
|
this.currentRequestResolve({
|
|
94
126
|
request: this.currentRequest,
|
|
95
127
|
response: this.currentResponse
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
export default class ParamsToObject {
|
|
4
|
+
/**
|
|
5
|
+
* @param {Record<string, string>} object
|
|
6
|
+
*/
|
|
2
7
|
constructor(object) {
|
|
3
8
|
this.object = object
|
|
4
9
|
}
|
|
@@ -15,6 +20,11 @@ export default class ParamsToObject {
|
|
|
15
20
|
return result
|
|
16
21
|
}
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} key
|
|
25
|
+
* @param {string} value
|
|
26
|
+
* @param {Record<string, any> | any[]} result
|
|
27
|
+
*/
|
|
18
28
|
treatInitial(key, value, result) {
|
|
19
29
|
const firstMatch = key.match(/^(.+?)(\[([\s\S]+$))/)
|
|
20
30
|
|
|
@@ -22,43 +32,61 @@ export default class ParamsToObject {
|
|
|
22
32
|
const inputName = firstMatch[1]
|
|
23
33
|
const rest = firstMatch[2]
|
|
24
34
|
|
|
35
|
+
/** @type {Array<any> | Record<string, any>} */
|
|
25
36
|
let newResult
|
|
26
37
|
|
|
27
38
|
if (inputName in result) {
|
|
39
|
+
// @ts-expect-error
|
|
28
40
|
newResult = result[inputName]
|
|
29
41
|
} else if (rest == "[]") {
|
|
30
42
|
newResult = []
|
|
43
|
+
// @ts-expect-error
|
|
31
44
|
result[inputName] = newResult
|
|
32
45
|
} else {
|
|
33
46
|
newResult = {}
|
|
47
|
+
// @ts-expect-error
|
|
34
48
|
result[inputName] = newResult
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
this.treatSecond(value, rest, newResult)
|
|
38
52
|
} else {
|
|
53
|
+
// @ts-expect-error
|
|
39
54
|
result[key] = value
|
|
40
55
|
}
|
|
41
56
|
}
|
|
42
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} value
|
|
60
|
+
* @param {string} rest
|
|
61
|
+
* @param {Record<string, any> | any[]} result
|
|
62
|
+
*/
|
|
43
63
|
treatSecond(value, rest, result) {
|
|
44
64
|
const secondMatch = rest.match(/^\[(.*?)\]([\s\S]*)$/)
|
|
65
|
+
|
|
66
|
+
if (!secondMatch) throw new Error(`Could not parse rest part: ${rest}`)
|
|
67
|
+
|
|
45
68
|
const key = secondMatch[1]
|
|
46
69
|
const newRest = secondMatch[2]
|
|
47
70
|
|
|
71
|
+
/** @type {Array<any> | Record<string, any>} */
|
|
48
72
|
let newResult
|
|
49
73
|
|
|
50
74
|
if (rest == "[]") {
|
|
51
75
|
result.push(value)
|
|
52
76
|
} else if (newRest == "") {
|
|
77
|
+
// @ts-expect-error
|
|
53
78
|
result[key] = value
|
|
54
79
|
} else {
|
|
55
80
|
if (typeof result == "object" && key in result) {
|
|
81
|
+
// @ts-expect-error
|
|
56
82
|
newResult = result[key]
|
|
57
83
|
} else if (newRest == "[]") {
|
|
58
84
|
newResult = []
|
|
85
|
+
// @ts-expect-error
|
|
59
86
|
result[key] = newResult
|
|
60
87
|
} else {
|
|
61
88
|
newResult = {}
|
|
89
|
+
// @ts-expect-error
|
|
62
90
|
result[key] = newResult
|
|
63
91
|
}
|
|
64
92
|
|
package/src/initializer.js
CHANGED
package/src/routes/app-routes.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import {digg} from "diggerize"
|
|
2
4
|
|
|
3
5
|
export default class VelociousRoutesAppRoutes {
|
|
4
6
|
/**
|
|
5
7
|
* @param {import("../configuration.js").default} configuration
|
|
6
|
-
* @returns {import("./index.js").default}
|
|
8
|
+
* @returns {Promise<import("./index.js").default>}
|
|
7
9
|
*/
|
|
8
10
|
static async getRoutes(configuration) {
|
|
9
11
|
// Every client need to make their own routes because they probably can't be shared across different worker threads
|