@ditojs/server 2.16.0 → 2.18.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 +16 -16
- package/src/app/Application.js +2 -1
- package/src/models/Model.js +7 -1
- package/src/query/QueryBuilder.js +13 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.18.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,15 +22,15 @@
|
|
|
22
22
|
"node >= 18"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@ditojs/admin": "^2.
|
|
26
|
-
"@ditojs/build": "^2.
|
|
27
|
-
"@ditojs/router": "^2.
|
|
28
|
-
"@ditojs/utils": "^2.
|
|
29
|
-
"@koa/cors": "^
|
|
25
|
+
"@ditojs/admin": "^2.18.0",
|
|
26
|
+
"@ditojs/build": "^2.18.0",
|
|
27
|
+
"@ditojs/router": "^2.18.0",
|
|
28
|
+
"@ditojs/utils": "^2.18.0",
|
|
29
|
+
"@koa/cors": "^5.0.0",
|
|
30
30
|
"@koa/multer": "^3.0.2",
|
|
31
31
|
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
|
32
|
-
"@vitejs/plugin-vue": "^4.5.
|
|
33
|
-
"@vue/compiler-sfc": "^3.3.
|
|
32
|
+
"@vitejs/plugin-vue": "^4.5.2",
|
|
33
|
+
"@vue/compiler-sfc": "^3.3.11",
|
|
34
34
|
"ajv": "^8.12.0",
|
|
35
35
|
"ajv-formats": "^2.1.1",
|
|
36
36
|
"bcryptjs": "^2.4.3",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"mime-types": "^2.1.35",
|
|
55
55
|
"multer": "^1.4.5-lts.1",
|
|
56
56
|
"multer-s3": "https://github.com/ditojs/multer-s3#dito",
|
|
57
|
-
"nanoid": "^5.0.
|
|
57
|
+
"nanoid": "^5.0.4",
|
|
58
58
|
"parse-duration": "^1.1.0",
|
|
59
59
|
"passport-local": "^1.0.0",
|
|
60
60
|
"passthrough-counter": "^1.0.0",
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"pino-pretty": "^10.2.3",
|
|
65
65
|
"pluralize": "^8.0.0",
|
|
66
66
|
"repl": "^0.1.3",
|
|
67
|
-
"type-fest": "^4.8.
|
|
67
|
+
"type-fest": "^4.8.3",
|
|
68
68
|
"uuid": "^9.0.1",
|
|
69
|
-
"vite": "^5.0.
|
|
70
|
-
"vue": "^3.3.
|
|
69
|
+
"vite": "^5.0.8",
|
|
70
|
+
"vue": "^3.3.11"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
73
|
"@aws-sdk/client-s3": "^3.0.0",
|
|
@@ -82,13 +82,13 @@
|
|
|
82
82
|
"@types/koa-session": "^6.4.5",
|
|
83
83
|
"@types/koa-static": "^4.0.4",
|
|
84
84
|
"@types/koa__cors": "^4.0.3",
|
|
85
|
-
"@types/node": "^20.10.
|
|
86
|
-
"knex": "^3.0
|
|
85
|
+
"@types/node": "^20.10.4",
|
|
86
|
+
"knex": "^3.1.0",
|
|
87
87
|
"objection": "^3.1.3",
|
|
88
|
-
"typescript": "^5.3.
|
|
88
|
+
"typescript": "^5.3.3"
|
|
89
89
|
},
|
|
90
90
|
"types": "types",
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "a19a3a9b1378a2da1edd05e88d383f48b2932f75",
|
|
92
92
|
"scripts": {
|
|
93
93
|
"types": "tsc --noEmit --esModuleInterop ./types/index.d.ts"
|
|
94
94
|
},
|
package/src/app/Application.js
CHANGED
|
@@ -882,6 +882,7 @@ export class Application extends Koa {
|
|
|
882
882
|
storage,
|
|
883
883
|
addedFiles,
|
|
884
884
|
removedFiles,
|
|
885
|
+
changedFiles,
|
|
885
886
|
trx = null
|
|
886
887
|
) {
|
|
887
888
|
let importedFiles = []
|
|
@@ -889,7 +890,7 @@ export class Application extends Koa {
|
|
|
889
890
|
if (AssetModel) {
|
|
890
891
|
importedFiles = await this.addForeignAssets(
|
|
891
892
|
storage,
|
|
892
|
-
addedFiles,
|
|
893
|
+
[...addedFiles, ...changedFiles],
|
|
893
894
|
trx
|
|
894
895
|
)
|
|
895
896
|
if (
|
package/src/models/Model.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isPromise,
|
|
8
8
|
asArray,
|
|
9
9
|
flatten,
|
|
10
|
+
equals,
|
|
10
11
|
parseDataPath,
|
|
11
12
|
normalizeDataPath,
|
|
12
13
|
getValueAtDataPath,
|
|
@@ -1066,8 +1067,12 @@ export class Model extends objection.Model {
|
|
|
1066
1067
|
const afterFiles = afterFilesPerDataPath[dataPath] || []
|
|
1067
1068
|
const beforeByKey = mapFilesByKey(beforeFiles)
|
|
1068
1069
|
const afterByKey = mapFilesByKey(afterFiles)
|
|
1069
|
-
const removedFiles = beforeFiles.filter(file => !afterByKey[file.key])
|
|
1070
1070
|
const addedFiles = afterFiles.filter(file => !beforeByKey[file.key])
|
|
1071
|
+
const removedFiles = beforeFiles.filter(file => !afterByKey[file.key])
|
|
1072
|
+
const changedFiles = afterFiles.filter(file => {
|
|
1073
|
+
const beforeFile = beforeByKey[file.key]
|
|
1074
|
+
return beforeFile && !equals(file, beforeFile)
|
|
1075
|
+
})
|
|
1071
1076
|
// Also handle modified files, which are files where the data property
|
|
1072
1077
|
// is changed before update / patch, meaning the file is changed.
|
|
1073
1078
|
// NOTE: This will change the content for all the references to it,
|
|
@@ -1080,6 +1085,7 @@ export class Model extends objection.Model {
|
|
|
1080
1085
|
storage,
|
|
1081
1086
|
addedFiles,
|
|
1082
1087
|
removedFiles,
|
|
1088
|
+
changedFiles,
|
|
1083
1089
|
transaction
|
|
1084
1090
|
))
|
|
1085
1091
|
)
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
mapKeys,
|
|
9
9
|
getValueAtDataPath,
|
|
10
10
|
setValueAtDataPath,
|
|
11
|
+
normalizeDataPath,
|
|
11
12
|
parseDataPath,
|
|
12
13
|
deprecate
|
|
13
14
|
} from '@ditojs/utils'
|
|
@@ -686,7 +687,7 @@ export class QueryBuilder extends objection.QueryBuilder {
|
|
|
686
687
|
if (options?.cyclic && method.startsWith('upsert')) {
|
|
687
688
|
// `_upsertCyclicDitoGraphAndFetch()` needs to run asynchronously,
|
|
688
689
|
// but we can't do so here and `runBefore()` executes too late,
|
|
689
|
-
// so use
|
|
690
|
+
// so use `#executeFirst()` to work around it.
|
|
690
691
|
this.#executeFirst = async () => {
|
|
691
692
|
this.#executeFirst = null
|
|
692
693
|
handleGraph(
|
|
@@ -727,11 +728,22 @@ export class QueryBuilder extends objection.QueryBuilder {
|
|
|
727
728
|
// Now clone the data and delete all references from it, for the initial
|
|
728
729
|
// upsert.
|
|
729
730
|
const cloned = clone(data)
|
|
731
|
+
const sparseArrays = {}
|
|
730
732
|
for (const path of Object.keys(references)) {
|
|
731
733
|
const parts = parseDataPath(path)
|
|
732
734
|
const key = parts.pop()
|
|
733
735
|
const parent = getValueAtDataPath(cloned, parts)
|
|
734
736
|
delete parent[key]
|
|
737
|
+
if (isArray(parent)) {
|
|
738
|
+
// For arrays, deleting the entry at `key` will leave 'holes' in the
|
|
739
|
+
// array and make it sparse. Collect it in order to compress it later.
|
|
740
|
+
sparseArrays[normalizeDataPath(parts)] = parent
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Now condense the sparse arrays to remove the empty entries again:
|
|
745
|
+
for (const [dataPath, array] of Object.entries(sparseArrays)) {
|
|
746
|
+
setValueAtDataPath(cloned, dataPath, Object.values(array))
|
|
735
747
|
}
|
|
736
748
|
|
|
737
749
|
// TODO: The model isn't necessarily fetched with data in the same order as
|