@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/server",
3
- "version": "2.16.0",
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.16.0",
26
- "@ditojs/build": "^2.16.0",
27
- "@ditojs/router": "^2.16.0",
28
- "@ditojs/utils": "^2.16.0",
29
- "@koa/cors": "^4.0.0",
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.0",
33
- "@vue/compiler-sfc": "^3.3.9",
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.3",
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.2",
67
+ "type-fest": "^4.8.3",
68
68
  "uuid": "^9.0.1",
69
- "vite": "^5.0.2",
70
- "vue": "^3.3.9"
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.0",
86
- "knex": "^3.0.1",
85
+ "@types/node": "^20.10.4",
86
+ "knex": "^3.1.0",
87
87
  "objection": "^3.1.3",
88
- "typescript": "^5.3.2"
88
+ "typescript": "^5.3.3"
89
89
  },
90
90
  "types": "types",
91
- "gitHead": "333d379f78a3d7469ca79993acd51b48e069ec9a",
91
+ "gitHead": "a19a3a9b1378a2da1edd05e88d383f48b2932f75",
92
92
  "scripts": {
93
93
  "types": "tsc --noEmit --esModuleInterop ./types/index.d.ts"
94
94
  },
@@ -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 (
@@ -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 `_executeFirst()` to work around it.
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