@ditojs/server 1.23.0 → 1.24.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.23.0",
3
+ "version": "1.24.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.23.0",
26
- "@ditojs/build": "^1.23.0",
27
- "@ditojs/router": "^1.23.0",
28
- "@ditojs/utils": "^1.23.0",
25
+ "@ditojs/admin": "^1.24.0",
26
+ "@ditojs/build": "^1.24.0",
27
+ "@ditojs/router": "^1.24.0",
28
+ "@ditojs/utils": "^1.24.0",
29
29
  "@koa/cors": "^4.0.0",
30
30
  "@koa/multer": "^3.0.2",
31
31
  "@originjs/vite-plugin-commonjs": "^1.0.3",
@@ -35,9 +35,8 @@
35
35
  "bytes": "^3.1.2",
36
36
  "data-uri-to-buffer": "^4.0.1",
37
37
  "eventemitter2": "^6.4.9",
38
- "file-type": "^18.2.0",
38
+ "file-type": "^18.2.1",
39
39
  "image-size": "^1.0.2",
40
- "is-svg": "^4.3.2",
41
40
  "koa": "^2.14.1",
42
41
  "koa-bodyparser": "^4.3.0",
43
42
  "koa-compose": "^4.1.0",
@@ -59,12 +58,12 @@
59
58
  "passthrough-counter": "^1.0.0",
60
59
  "picocolors": "^1.0.0",
61
60
  "picomatch": "^2.3.1",
62
- "pino": "^8.9.0",
63
- "pino-pretty": "^9.1.1",
61
+ "pino": "^8.11.0",
62
+ "pino-pretty": "^9.4.0",
64
63
  "pluralize": "^8.0.0",
65
64
  "repl": "^0.1.3",
66
65
  "uuid": "^9.0.0",
67
- "vite": "^4.1.1",
66
+ "vite": "^4.1.4",
68
67
  "vite-plugin-vue2": "^2.0.3",
69
68
  "vue": "^2.7.14",
70
69
  "vue-template-compiler": "^2.7.14"
@@ -83,15 +82,15 @@
83
82
  "@types/koa-response-time": "^2.1.2",
84
83
  "@types/koa-session": "^5.10.6",
85
84
  "@types/koa-static": "^4.0.2",
86
- "@types/koa__cors": "^3.3.0",
87
- "@types/node": "^18.11.19",
85
+ "@types/koa__cors": "^3.3.1",
86
+ "@types/node": "^18.14.2",
88
87
  "knex": "^2.4.2",
89
88
  "objection": "^3.0.1",
90
- "type-fest": "^3.5.5",
89
+ "type-fest": "^3.6.1",
91
90
  "typescript": "^4.9.5"
92
91
  },
93
92
  "types": "types",
94
- "gitHead": "3258fd030226062efa6837bfc5e5a761e80cead5",
93
+ "gitHead": "0ca96ce0335509daa9ebbac278ae2d346015baad",
95
94
  "scripts": {
96
95
  "types": "tsc --noEmit ./src/index.d.ts"
97
96
  },
@@ -706,7 +706,7 @@ export class Application extends Koa {
706
706
  this.on('error', this.logError)
707
707
  }
708
708
  // It's ok to call this multiple times, because only the entries in the
709
- // registres (storages, services, models, controllers) that weren't
709
+ // registers (storages, services, models, controllers) that weren't
710
710
  // initialized yet will be initialized.
711
711
  await this.setup()
712
712
  await this.emit('before:start')
@@ -797,7 +797,7 @@ export class Application extends Koa {
797
797
  return null
798
798
  }
799
799
 
800
- async handleAdddedAndRemovedAssets(
800
+ async handleAddedAndRemovedAssets(
801
801
  storage,
802
802
  addedFiles,
803
803
  removedFiles,
@@ -808,7 +808,7 @@ export class Application extends Koa {
808
808
  cleanupTimeThreshold = 0
809
809
  } = {}
810
810
  } = this.config
811
- // Only remove unused assets that haven't seen changes for given timeframe.
811
+ // Only remove unused assets that haven't seen changes for given time frame.
812
812
  const timeThreshold = isString(cleanupTimeThreshold)
813
813
  ? parseDuration(cleanupTimeThreshold)
814
814
  : cleanupTimeThreshold
@@ -985,14 +985,14 @@ export class Model extends objection.Model {
985
985
  const removedFiles = beforeFiles.filter(file => !afterByKey[file.key])
986
986
  const addedFiles = afterFiles.filter(file => !beforeByKey[file.key])
987
987
  // Also handle modified files, which are files where the data property
988
- // is changed before update / patch, meanting the file is changed.
988
+ // is changed before update / patch, meaning the file is changed.
989
989
  // NOTE: This will change the content for all the references to it,
990
990
  // and thus should only really be used when there's only one reference.
991
991
  const modifiedFiles = afterFiles.filter(
992
992
  file => file.data && beforeByKey[file.key]
993
993
  )
994
994
  importedFiles.push(
995
- ...await this.app.handleAdddedAndRemovedAssets(
995
+ ...await this.app.handleAddedAndRemovedAssets(
996
996
  storage,
997
997
  addedFiles,
998
998
  removedFiles,
@@ -8,11 +8,13 @@ const SYMBOL_STORAGE = Symbol('storage')
8
8
  const SYMBOL_DATA = Symbol('data')
9
9
 
10
10
  export class AssetFile {
11
- constructor(name, data, type) {
11
+ constructor({ name, data, type, width, height }) {
12
12
  this.key = AssetFile.getUniqueKey(name)
13
13
  this.name = name
14
14
  // Set `type` before `data`, so it can be used as default in `set data`
15
15
  this.type = type
16
+ this.width = width
17
+ this.height = height
16
18
  this.data = data
17
19
  }
18
20
 
@@ -60,8 +62,8 @@ export class AssetFile {
60
62
  return object
61
63
  }
62
64
 
63
- static create({ name, data, type }) {
64
- return new AssetFile(name, data, type)
65
+ static create(options) {
66
+ return new AssetFile(options)
65
67
  }
66
68
 
67
69
  static getUniqueKey(name) {
@@ -38,11 +38,11 @@ export class DiskStorage extends Storage {
38
38
  }
39
39
 
40
40
  // @override
41
- async _addFile(file, buffer) {
41
+ async _addFile(file, data) {
42
42
  const filePath = this._getFilePath(file)
43
43
  const dir = path.dirname(filePath)
44
44
  await fs.mkdir(dir, { recursive: true })
45
- await fs.writeFile(filePath, buffer)
45
+ await fs.writeFile(filePath, data)
46
46
  return file
47
47
  }
48
48
 
@@ -1,9 +1,9 @@
1
1
  import multerS3 from 'multer-s3'
2
2
  import { fileTypeFromBuffer } from 'file-type'
3
- import isSvg from 'is-svg'
4
3
  import { Storage } from './Storage.js'
5
4
  import { PassThrough } from 'stream'
6
5
  import consumers from 'stream/consumers'
6
+ import imageSize from 'image-size'
7
7
 
8
8
  export class S3Storage extends Storage {
9
9
  static type = 's3'
@@ -56,7 +56,7 @@ export class S3Storage extends Storage {
56
56
  const onData = chunk => {
57
57
  if (!data) {
58
58
  // 2. Try reading the mimetype from the first chunk.
59
- const type = fileTypeFromBuffer(chunk)?.mime
59
+ const type = getFileTypeFromBuffer(chunk)
60
60
  if (type) {
61
61
  stream.off('data', onData)
62
62
  done(type)
@@ -64,11 +64,9 @@ export class S3Storage extends Storage {
64
64
  // 3. If that fails, keep collecting all chunks and determine
65
65
  // the mimetype using the full data.
66
66
  stream.once('end', () => {
67
- const type = (
68
- fileTypeFromBuffer(data)?.mime ||
69
- (isSvg(data) ? 'image/svg+xml' : 'application/octet-stream')
67
+ done(
68
+ getFileTypeFromBuffer(data) || 'application/octet-stream'
70
69
  )
71
- done(type)
72
70
  })
73
71
  }
74
72
  }
@@ -107,19 +105,19 @@ export class S3Storage extends Storage {
107
105
  }
108
106
 
109
107
  // @override
110
- async _addFile(file, buffer) {
111
- const data = await this.s3.putObject({
108
+ async _addFile(file, data) {
109
+ const result = await this.s3.putObject({
112
110
  Bucket: this.bucket,
113
111
  ACL: this.acl,
114
112
  Key: file.key,
115
113
  ContentType: file.type,
116
- Body: buffer
114
+ Body: data
117
115
  })
118
116
  // "Convert" `file` to something looking more like a S3 `storageFile`.
119
117
  // For now, only the `location` property is of interest:
120
118
  return {
121
119
  ...file,
122
- location: data.Location
120
+ location: result.Location
123
121
  }
124
122
  }
125
123
 
@@ -163,3 +161,33 @@ export class S3Storage extends Storage {
163
161
  return files
164
162
  }
165
163
  }
164
+
165
+ function getFileTypeFromBuffer(buffer) {
166
+ const type = fileTypeFromBuffer(buffer)
167
+ if (type) {
168
+ return type.mime
169
+ }
170
+ try {
171
+ const { type } = imageSize(buffer)
172
+ return {
173
+ jpg: 'image/jpeg',
174
+ png: 'image/png',
175
+ gif: 'image/gif',
176
+ svg: 'image/svg+xml',
177
+ webp: 'image/webp',
178
+ tiff: 'image/tiff',
179
+ j2c: 'image/jp2',
180
+ jp2: 'image/jp2',
181
+ ktx: 'image/ktx',
182
+ bmp: 'image/bmp',
183
+ tga: 'image/x-targa',
184
+ cur: 'image/x-win-bitmap',
185
+ icns: 'image/x-icon',
186
+ ico: 'image/x-icon',
187
+ pnm: 'image/x-portable-anymap',
188
+ dds: 'image/vnd-ms.dds',
189
+ psd: 'image/vnd.adobe.photoshop'
190
+ }[type]
191
+ } catch (err) {}
192
+ return null
193
+ }
@@ -94,9 +94,9 @@ export class Storage {
94
94
  return storageFiles.map(storageFile => this.convertStorageFile(storageFile))
95
95
  }
96
96
 
97
- async addFile(file, buffer) {
98
- const storageFile = await this._addFile(file, buffer)
99
- file.size = Buffer.byteLength(buffer)
97
+ async addFile(file, data) {
98
+ const storageFile = await this._addFile(file, data)
99
+ file.size = Buffer.byteLength(data)
100
100
  file.url = this._getFileUrl(storageFile)
101
101
  // TODO: Support `config.readImageSize`, but this can only be done onces
102
102
  // there are separate storage instances per model assets config!
@@ -146,7 +146,7 @@ export class Storage {
146
146
  _getFileUrl(_file) {}
147
147
 
148
148
  // @overridable
149
- async _addFile(_file, _buffer) {}
149
+ async _addFile(_file, _data) {}
150
150
 
151
151
  // @overridable
152
152
  async _removeFile(_file) {}