@ditojs/server 1.25.1 → 1.26.0
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 +5 -5
- package/src/app/Application.js +19 -22
- package/src/controllers/CollectionController.js +1 -0
- package/src/controllers/Controller.js +37 -19
- package/src/controllers/RelationController.js +5 -0
- package/src/services/Service.js +1 -1
- package/src/storage/DiskStorage.js +0 -1
- package/src/storage/S3Storage.js +4 -6
- package/src/storage/Storage.js +6 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Server – Dito.js is a declarative and modern web framework, based on Objection.js, Koa.js and Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/server",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"node >= 18"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@ditojs/admin": "^1.
|
|
25
|
+
"@ditojs/admin": "^1.26.0",
|
|
26
26
|
"@ditojs/build": "^1.25.0",
|
|
27
|
-
"@ditojs/router": "^1.
|
|
28
|
-
"@ditojs/utils": "^1.
|
|
27
|
+
"@ditojs/router": "^1.26.0",
|
|
28
|
+
"@ditojs/utils": "^1.26.0",
|
|
29
29
|
"@koa/cors": "^4.0.0",
|
|
30
30
|
"@koa/multer": "^3.0.2",
|
|
31
31
|
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"typescript": "^4.9.5"
|
|
91
91
|
},
|
|
92
92
|
"types": "types",
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "198c9832c863003c8c8fcd147bf61a5f99a39c91",
|
|
94
94
|
"scripts": {
|
|
95
95
|
"types": "tsc --noEmit ./src/index.d.ts"
|
|
96
96
|
},
|
package/src/app/Application.js
CHANGED
|
@@ -860,31 +860,28 @@ export class Application extends Koa {
|
|
|
860
860
|
const { url } = file
|
|
861
861
|
if (!storage.isImportSourceAllowed(url)) {
|
|
862
862
|
throw new AssetError(
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
863
|
+
`Unable to import asset from foreign source: '${
|
|
864
|
+
file.name
|
|
865
|
+
}' ('${
|
|
866
|
+
url
|
|
867
|
+
}'): The source needs to be explicitly allowed.`
|
|
868
868
|
)
|
|
869
869
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
pico.green(`'${storage.name}'`)
|
|
879
|
-
}...`
|
|
870
|
+
this.logger.info(
|
|
871
|
+
`Asset ${
|
|
872
|
+
pico.green(`'${file.name}'`)
|
|
873
|
+
} is from a foreign source, fetching from ${
|
|
874
|
+
pico.green(`'${url}'`)
|
|
875
|
+
} and adding to storage ${
|
|
876
|
+
pico.green(`'${storage.name}'`)
|
|
877
|
+
}...`
|
|
880
878
|
)
|
|
881
879
|
if (url.startsWith('file://')) {
|
|
882
880
|
const filepath = path.resolve(url.substring(7))
|
|
883
881
|
data = await fs.readFile(filepath)
|
|
884
882
|
} else {
|
|
885
883
|
const response = await fetch(url)
|
|
886
|
-
|
|
887
|
-
data = new DataView(buffer)
|
|
884
|
+
data = await response.arrayBuffer()
|
|
888
885
|
}
|
|
889
886
|
}
|
|
890
887
|
const importedFile = await storage.addFile(file, data)
|
|
@@ -896,11 +893,11 @@ export class Application extends Koa {
|
|
|
896
893
|
importedFiles.push(importedFile)
|
|
897
894
|
} else {
|
|
898
895
|
throw new AssetError(
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
896
|
+
`Unable to import asset from foreign source: '${
|
|
897
|
+
file.name
|
|
898
|
+
}' ('${
|
|
899
|
+
file.key
|
|
900
|
+
}')`
|
|
904
901
|
)
|
|
905
902
|
}
|
|
906
903
|
} else {
|
|
@@ -24,6 +24,7 @@ export class CollectionController extends Controller {
|
|
|
24
24
|
|
|
25
25
|
// @override
|
|
26
26
|
setup() {
|
|
27
|
+
this.logController()
|
|
27
28
|
this.collection = this.setupActions('collection')
|
|
28
29
|
this.member = this.isOneToOne ? {} : this.setupActions('member')
|
|
29
30
|
this.assets = this.setupAssets()
|
|
@@ -26,7 +26,7 @@ export class Controller {
|
|
|
26
26
|
constructor(app, namespace) {
|
|
27
27
|
this.app = app
|
|
28
28
|
this.namespace = namespace
|
|
29
|
-
this.
|
|
29
|
+
this.logRoutes = this.app.config.log.routes
|
|
30
30
|
this.level = 0
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -60,21 +60,12 @@ export class Controller {
|
|
|
60
60
|
// mapped parameters or wildcards. Consider `path` / `route` instead?
|
|
61
61
|
const url = path ? `/${path}` : ''
|
|
62
62
|
this.url = namespace ? `/${namespace}${url}` : url
|
|
63
|
-
this.log(
|
|
64
|
-
`${
|
|
65
|
-
namespace ? pico.green(`/${namespace}/`) : ''
|
|
66
|
-
}${
|
|
67
|
-
pico.cyan(path)
|
|
68
|
-
}${
|
|
69
|
-
pico.white(':')
|
|
70
|
-
}`,
|
|
71
|
-
this.level
|
|
72
|
-
)
|
|
73
63
|
}
|
|
74
64
|
}
|
|
75
65
|
|
|
76
66
|
// @overridable
|
|
77
67
|
setup() {
|
|
68
|
+
this.logController()
|
|
78
69
|
this.actions ||= this.reflectActionsObject()
|
|
79
70
|
// Now that the instance fields are reflected in the `controller` object
|
|
80
71
|
// we can use the normal inheritance mechanism through `setupActions()`:
|
|
@@ -94,6 +85,40 @@ export class Controller {
|
|
|
94
85
|
// middleware. For normal routes, use `this.app.addRoute()` instead.
|
|
95
86
|
}
|
|
96
87
|
|
|
88
|
+
// @overridable
|
|
89
|
+
logController() {
|
|
90
|
+
const { path, namespace } = this
|
|
91
|
+
this.logRoute(
|
|
92
|
+
`${
|
|
93
|
+
namespace ? pico.green(`/${namespace}/`) : ''
|
|
94
|
+
}${
|
|
95
|
+
pico.cyan(path)
|
|
96
|
+
}${
|
|
97
|
+
pico.white(':')
|
|
98
|
+
}`,
|
|
99
|
+
this.level
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
logRoute(str, indent = 0) {
|
|
104
|
+
if (this.logRoutes) {
|
|
105
|
+
console.info(`${' '.repeat(indent)}${str}`)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Only use this method to get a logger instance that is bound to the context,
|
|
110
|
+
// otherwise use the cached getter.
|
|
111
|
+
getLogger(ctx) {
|
|
112
|
+
const logger = ctx?.logger ?? this.app.logger
|
|
113
|
+
return logger.child({ name: this.name })
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
get logger() {
|
|
117
|
+
const value = this.getLogger()
|
|
118
|
+
Object.defineProperty(this, 'logger', { value })
|
|
119
|
+
return value
|
|
120
|
+
}
|
|
121
|
+
|
|
97
122
|
reflectActionsObject() {
|
|
98
123
|
// On base controllers, the actions can be defined directly in the class
|
|
99
124
|
// instead of inside an actions object, as is done with model and relation
|
|
@@ -122,7 +147,7 @@ export class Controller {
|
|
|
122
147
|
}
|
|
123
148
|
|
|
124
149
|
setupRoute(method, url, transacted, authorize, action, middlewares) {
|
|
125
|
-
this.
|
|
150
|
+
this.logRoute(
|
|
126
151
|
`${
|
|
127
152
|
pico.magenta(method.toUpperCase())
|
|
128
153
|
} ${
|
|
@@ -382,7 +407,6 @@ export class Controller {
|
|
|
382
407
|
// so add its own keys to the already allowed inherited keys so far.
|
|
383
408
|
Object.assign(allowMap, getFilteredMap(getOwnKeys(current)))
|
|
384
409
|
}
|
|
385
|
-
// console.log('allow', Object.keys(allowMap))
|
|
386
410
|
}
|
|
387
411
|
|
|
388
412
|
const handleAuthorize = authorize => {
|
|
@@ -538,12 +562,6 @@ export class Controller {
|
|
|
538
562
|
throw new AuthorizationError()
|
|
539
563
|
}
|
|
540
564
|
}
|
|
541
|
-
|
|
542
|
-
log(str, indent = 0) {
|
|
543
|
-
if (this.logging) {
|
|
544
|
-
console.info(`${' '.repeat(indent)}${str}`)
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
565
|
}
|
|
548
566
|
|
|
549
567
|
EventEmitter.mixin(Controller.prototype)
|
|
@@ -48,6 +48,11 @@ export class RelationController extends CollectionController {
|
|
|
48
48
|
super.configure()
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// @override
|
|
52
|
+
logController() {
|
|
53
|
+
// The parent controller logs itself already, that's enough.
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
// @override
|
|
52
57
|
inheritValues(type) {
|
|
53
58
|
// Since RelationController are mapped to nested `relations` objects in
|
package/src/services/Service.js
CHANGED
|
@@ -32,7 +32,7 @@ export class Service {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Only use this method to get a logger instance that is bound to the context,
|
|
35
|
-
// otherwise use the getter.
|
|
35
|
+
// otherwise use the cached getter.
|
|
36
36
|
getLogger(ctx) {
|
|
37
37
|
const logger = ctx?.logger ?? this.app.logger
|
|
38
38
|
return logger.child({ name: this.#loggerName })
|
package/src/storage/S3Storage.js
CHANGED
|
@@ -111,12 +111,10 @@ export class S3Storage extends Storage {
|
|
|
111
111
|
ContentType: file.type,
|
|
112
112
|
Body: data
|
|
113
113
|
})
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
location: result.Location
|
|
119
|
-
}
|
|
114
|
+
// In `Storage.addFile()` this will get overridden with the result of
|
|
115
|
+
// `_getUrl()` if it exists, but is used as a fallback otherwise,
|
|
116
|
+
// see `_getFileUrl()`.
|
|
117
|
+
file.url = result.Location
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
// @override
|
package/src/storage/Storage.js
CHANGED
|
@@ -18,7 +18,9 @@ export class Storage {
|
|
|
18
18
|
this.name = config.name
|
|
19
19
|
this.url = config.url
|
|
20
20
|
this.path = config.path
|
|
21
|
-
|
|
21
|
+
// Use a default concurrency of 8 for storage IO, e.g. the importing of
|
|
22
|
+
// foreign assets.
|
|
23
|
+
this.concurrency = config.concurrency ?? 8
|
|
22
24
|
// The actual multer storage object.
|
|
23
25
|
this.storage = null
|
|
24
26
|
}
|
|
@@ -96,10 +98,10 @@ export class Storage {
|
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
async addFile(file, data) {
|
|
99
|
-
|
|
101
|
+
await this._addFile(file, data)
|
|
100
102
|
file.size = Buffer.byteLength(data)
|
|
101
|
-
file.url = this._getFileUrl(
|
|
102
|
-
// TODO: Support `config.readImageSize`, but this can only be done
|
|
103
|
+
file.url = this._getFileUrl(file)
|
|
104
|
+
// TODO: Support `config.readImageSize`, but this can only be done once
|
|
103
105
|
// there are separate storage instances per model assets config!
|
|
104
106
|
return this.convertAssetFile(file)
|
|
105
107
|
}
|