@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/server",
3
- "version": "1.25.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.0",
25
+ "@ditojs/admin": "^1.26.0",
26
26
  "@ditojs/build": "^1.25.0",
27
- "@ditojs/router": "^1.25.1",
28
- "@ditojs/utils": "^1.25.0",
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": "bebbf44ddf15a565e50ed8b2cbe0bf8a463c276d",
93
+ "gitHead": "198c9832c863003c8c8fcd147bf61a5f99a39c91",
94
94
  "scripts": {
95
95
  "types": "tsc --noEmit ./src/index.d.ts"
96
96
  },
@@ -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
- `Unable to import asset from foreign source: '${
864
- file.name
865
- }' ('${
866
- url
867
- }'): The source needs to be explicitly allowed.`
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
- console.info(
871
- `${
872
- pico.red('INFO:')
873
- } Asset ${
874
- pico.green(`'${file.name}'`)
875
- } is from a foreign source, fetching from ${
876
- pico.green(`'${url}'`)
877
- } and adding to storage ${
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
- const buffer = await response.arrayBuffer()
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
- `Unable to import asset from foreign source: '${
900
- file.name
901
- }' ('${
902
- file.key
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.logging = this.app.config.log.routes
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.log(
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
@@ -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 })
@@ -44,7 +44,6 @@ export class DiskStorage extends Storage {
44
44
  const dir = path.dirname(filePath)
45
45
  await fs.mkdir(dir, { recursive: true })
46
46
  await fs.writeFile(filePath, data)
47
- return file
48
47
  }
49
48
 
50
49
  // @override
@@ -111,12 +111,10 @@ export class S3Storage extends Storage {
111
111
  ContentType: file.type,
112
112
  Body: data
113
113
  })
114
- // "Convert" `file` to something looking more like a S3 `storageFile`.
115
- // For now, only the `location` property is of interest:
116
- return {
117
- ...file,
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
@@ -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
- this.concurrency = config.concurrency ?? null
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
- const storageFile = await this._addFile(file, data)
101
+ await this._addFile(file, data)
100
102
  file.size = Buffer.byteLength(data)
101
- file.url = this._getFileUrl(storageFile)
102
- // TODO: Support `config.readImageSize`, but this can only be done onces
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
  }