@strapi/data-transfer 5.48.0 → 5.49.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.
Files changed (210) hide show
  1. package/dist/directory/providers/destination/index.d.ts +1 -1
  2. package/dist/directory/providers/destination/index.d.ts.map +1 -1
  3. package/dist/directory/providers/destination/index.js +16 -11
  4. package/dist/directory/providers/destination/index.js.map +1 -1
  5. package/dist/directory/providers/destination/index.mjs.map +1 -1
  6. package/dist/directory/providers/destination/utils.js +6 -2
  7. package/dist/directory/providers/destination/utils.js.map +1 -1
  8. package/dist/directory/providers/source/index.d.ts +1 -1
  9. package/dist/directory/providers/source/index.d.ts.map +1 -1
  10. package/dist/directory/providers/source/index.js +25 -20
  11. package/dist/directory/providers/source/index.js.map +1 -1
  12. package/dist/directory/providers/source/index.mjs.map +1 -1
  13. package/dist/engine/index.d.ts +1 -1
  14. package/dist/engine/index.d.ts.map +1 -1
  15. package/dist/engine/index.js.map +1 -1
  16. package/dist/engine/index.mjs.map +1 -1
  17. package/dist/engine/validation/provider.d.ts +1 -1
  18. package/dist/engine/validation/provider.d.ts.map +1 -1
  19. package/dist/engine/validation/provider.js.map +1 -1
  20. package/dist/engine/validation/provider.mjs.map +1 -1
  21. package/dist/errors/providers.d.ts +1 -1
  22. package/dist/errors/providers.d.ts.map +1 -1
  23. package/dist/errors/providers.js.map +1 -1
  24. package/dist/errors/providers.mjs.map +1 -1
  25. package/dist/file/providers/destination/index.d.ts +1 -1
  26. package/dist/file/providers/destination/index.d.ts.map +1 -1
  27. package/dist/file/providers/destination/index.js +10 -4
  28. package/dist/file/providers/destination/index.js.map +1 -1
  29. package/dist/file/providers/destination/index.mjs.map +1 -1
  30. package/dist/file/providers/source/index.d.ts +1 -1
  31. package/dist/file/providers/source/index.d.ts.map +1 -1
  32. package/dist/file/providers/source/index.js +9 -3
  33. package/dist/file/providers/source/index.js.map +1 -1
  34. package/dist/file/providers/source/index.mjs.map +1 -1
  35. package/dist/file/providers/source/utils.js +10 -6
  36. package/dist/file/providers/source/utils.js.map +1 -1
  37. package/dist/strapi/providers/local-destination/assets-destination-writable.d.ts +9 -4
  38. package/dist/strapi/providers/local-destination/assets-destination-writable.d.ts.map +1 -1
  39. package/dist/strapi/providers/local-destination/assets-destination-writable.js +67 -49
  40. package/dist/strapi/providers/local-destination/assets-destination-writable.js.map +1 -1
  41. package/dist/strapi/providers/local-destination/assets-destination-writable.mjs +67 -49
  42. package/dist/strapi/providers/local-destination/assets-destination-writable.mjs.map +1 -1
  43. package/dist/strapi/providers/local-destination/index.d.ts +1 -1
  44. package/dist/strapi/providers/local-destination/index.d.ts.map +1 -1
  45. package/dist/strapi/providers/local-destination/index.js +11 -7
  46. package/dist/strapi/providers/local-destination/index.js.map +1 -1
  47. package/dist/strapi/providers/local-destination/index.mjs.map +1 -1
  48. package/dist/strapi/providers/local-destination/strategies/restore/configuration.d.ts +1 -1
  49. package/dist/strapi/providers/local-destination/strategies/restore/configuration.d.ts.map +1 -1
  50. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js +9 -3
  51. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js.map +1 -1
  52. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs +4 -2
  53. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs.map +1 -1
  54. package/dist/strapi/providers/local-destination/strategies/restore/entities.d.ts +1 -1
  55. package/dist/strapi/providers/local-destination/strategies/restore/entities.d.ts.map +1 -1
  56. package/dist/strapi/providers/local-destination/strategies/restore/entities.js +13 -25
  57. package/dist/strapi/providers/local-destination/strategies/restore/entities.js.map +1 -1
  58. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs +14 -26
  59. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs.map +1 -1
  60. package/dist/strapi/providers/local-destination/strategies/restore/index.js +0 -4
  61. package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -1
  62. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs +0 -4
  63. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs.map +1 -1
  64. package/dist/strapi/providers/local-destination/strategies/restore/links.d.ts +1 -1
  65. package/dist/strapi/providers/local-destination/strategies/restore/links.d.ts.map +1 -1
  66. package/dist/strapi/providers/local-destination/strategies/restore/links.js +22 -3
  67. package/dist/strapi/providers/local-destination/strategies/restore/links.js.map +1 -1
  68. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs +22 -3
  69. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs.map +1 -1
  70. package/dist/strapi/providers/local-source/assets.d.ts +1 -1
  71. package/dist/strapi/providers/local-source/assets.d.ts.map +1 -1
  72. package/dist/strapi/providers/local-source/assets.js.map +1 -1
  73. package/dist/strapi/providers/local-source/assets.mjs.map +1 -1
  74. package/dist/strapi/providers/local-source/configuration.d.ts.map +1 -1
  75. package/dist/strapi/providers/local-source/configuration.js +8 -0
  76. package/dist/strapi/providers/local-source/configuration.js.map +1 -1
  77. package/dist/strapi/providers/local-source/configuration.mjs +8 -0
  78. package/dist/strapi/providers/local-source/configuration.mjs.map +1 -1
  79. package/dist/strapi/providers/local-source/entities.d.ts +3 -1
  80. package/dist/strapi/providers/local-source/entities.d.ts.map +1 -1
  81. package/dist/strapi/providers/local-source/entities.js +7 -3
  82. package/dist/strapi/providers/local-source/entities.js.map +1 -1
  83. package/dist/strapi/providers/local-source/entities.mjs +7 -3
  84. package/dist/strapi/providers/local-source/entities.mjs.map +1 -1
  85. package/dist/strapi/providers/local-source/estimate-asset-totals.d.ts +1 -1
  86. package/dist/strapi/providers/local-source/estimate-asset-totals.d.ts.map +1 -1
  87. package/dist/strapi/providers/local-source/estimate-asset-totals.js.map +1 -1
  88. package/dist/strapi/providers/local-source/estimate-asset-totals.mjs.map +1 -1
  89. package/dist/strapi/providers/local-source/index.d.ts +2 -2
  90. package/dist/strapi/providers/local-source/index.d.ts.map +1 -1
  91. package/dist/strapi/providers/local-source/index.js +6 -1
  92. package/dist/strapi/providers/local-source/index.js.map +1 -1
  93. package/dist/strapi/providers/local-source/index.mjs +6 -1
  94. package/dist/strapi/providers/local-source/index.mjs.map +1 -1
  95. package/dist/strapi/providers/local-source/links.js.map +1 -1
  96. package/dist/strapi/providers/local-source/links.mjs.map +1 -1
  97. package/dist/strapi/providers/remote-destination/index.d.ts +2 -2
  98. package/dist/strapi/providers/remote-destination/index.d.ts.map +1 -1
  99. package/dist/strapi/providers/remote-destination/index.js +24 -3
  100. package/dist/strapi/providers/remote-destination/index.js.map +1 -1
  101. package/dist/strapi/providers/remote-destination/index.mjs +25 -4
  102. package/dist/strapi/providers/remote-destination/index.mjs.map +1 -1
  103. package/dist/strapi/providers/remote-source/index.d.ts +2 -2
  104. package/dist/strapi/providers/remote-source/index.d.ts.map +1 -1
  105. package/dist/strapi/providers/remote-source/index.js.map +1 -1
  106. package/dist/strapi/providers/remote-source/index.mjs.map +1 -1
  107. package/dist/strapi/providers/utils.d.ts +2 -2
  108. package/dist/strapi/providers/utils.d.ts.map +1 -1
  109. package/dist/strapi/providers/utils.js.map +1 -1
  110. package/dist/strapi/providers/utils.mjs.map +1 -1
  111. package/dist/strapi/queries/link.d.ts +1 -1
  112. package/dist/strapi/queries/link.d.ts.map +1 -1
  113. package/dist/strapi/queries/link.js.map +1 -1
  114. package/dist/strapi/queries/link.mjs.map +1 -1
  115. package/dist/strapi/remote/flows/index.d.ts +1 -1
  116. package/dist/strapi/remote/flows/index.d.ts.map +1 -1
  117. package/dist/strapi/remote/flows/index.js.map +1 -1
  118. package/dist/strapi/remote/flows/index.mjs.map +1 -1
  119. package/dist/strapi/remote/handlers/pull.d.ts +1 -1
  120. package/dist/strapi/remote/handlers/pull.d.ts.map +1 -1
  121. package/dist/strapi/remote/handlers/pull.js +3 -3
  122. package/dist/strapi/remote/handlers/pull.js.map +1 -1
  123. package/dist/strapi/remote/handlers/pull.mjs +3 -3
  124. package/dist/strapi/remote/handlers/pull.mjs.map +1 -1
  125. package/dist/strapi/remote/handlers/push.d.ts +1 -1
  126. package/dist/strapi/remote/handlers/push.d.ts.map +1 -1
  127. package/dist/strapi/remote/handlers/push.js +8 -1
  128. package/dist/strapi/remote/handlers/push.js.map +1 -1
  129. package/dist/strapi/remote/handlers/push.mjs +8 -1
  130. package/dist/strapi/remote/handlers/push.mjs.map +1 -1
  131. package/dist/strapi/remote/handlers/utils.d.ts +1 -1
  132. package/dist/strapi/remote/handlers/utils.d.ts.map +1 -1
  133. package/dist/strapi/remote/handlers/utils.js.map +1 -1
  134. package/dist/strapi/remote/handlers/utils.mjs.map +1 -1
  135. package/dist/strapi/utils/project-settings-logos.d.ts +29 -0
  136. package/dist/strapi/utils/project-settings-logos.d.ts.map +1 -0
  137. package/dist/strapi/utils/project-settings-logos.js +174 -0
  138. package/dist/strapi/utils/project-settings-logos.js.map +1 -0
  139. package/dist/strapi/utils/project-settings-logos.mjs +169 -0
  140. package/dist/strapi/utils/project-settings-logos.mjs.map +1 -0
  141. package/dist/types/common-entities.d.ts +152 -0
  142. package/dist/types/common-entities.d.ts.map +1 -0
  143. package/dist/types/encryption.d.ts +11 -0
  144. package/dist/types/encryption.d.ts.map +1 -0
  145. package/dist/types/index.d.ts +7 -0
  146. package/dist/types/index.d.ts.map +1 -0
  147. package/dist/types/providers.d.ts +50 -0
  148. package/dist/types/providers.d.ts.map +1 -0
  149. package/dist/types/remote/index.d.ts +2 -0
  150. package/dist/types/remote/index.d.ts.map +1 -0
  151. package/dist/types/remote/protocol/auth.d.ts +5 -0
  152. package/dist/types/remote/protocol/auth.d.ts.map +1 -0
  153. package/dist/types/remote/protocol/client/commands.d.ts +37 -0
  154. package/dist/types/remote/protocol/client/commands.d.ts.map +1 -0
  155. package/dist/types/remote/protocol/client/index.d.ts +9 -0
  156. package/dist/types/remote/protocol/client/index.d.ts.map +1 -0
  157. package/dist/types/remote/protocol/client/transfer/action.d.ts +5 -0
  158. package/dist/types/remote/protocol/client/transfer/action.d.ts.map +1 -0
  159. package/dist/types/remote/protocol/client/transfer/index.d.ts +12 -0
  160. package/dist/types/remote/protocol/client/transfer/index.d.ts.map +1 -0
  161. package/dist/types/remote/protocol/client/transfer/pull.d.ts +25 -0
  162. package/dist/types/remote/protocol/client/transfer/pull.d.ts.map +1 -0
  163. package/dist/types/remote/protocol/client/transfer/push.d.ts +29 -0
  164. package/dist/types/remote/protocol/client/transfer/push.d.ts.map +1 -0
  165. package/dist/types/remote/protocol/client/transfer/utils.d.ts +49 -0
  166. package/dist/types/remote/protocol/client/transfer/utils.d.ts.map +1 -0
  167. package/dist/types/remote/protocol/index.d.ts +4 -0
  168. package/dist/types/remote/protocol/index.d.ts.map +1 -0
  169. package/dist/types/remote/protocol/server/error.d.ts +18 -0
  170. package/dist/types/remote/protocol/server/error.d.ts.map +1 -0
  171. package/dist/types/remote/protocol/server/index.d.ts +3 -0
  172. package/dist/types/remote/protocol/server/index.d.ts.map +1 -0
  173. package/dist/types/remote/protocol/server/messaging.d.ts +37 -0
  174. package/dist/types/remote/protocol/server/messaging.d.ts.map +1 -0
  175. package/dist/types/transfer-engine.d.ts +149 -0
  176. package/dist/types/transfer-engine.d.ts.map +1 -0
  177. package/dist/types/utils.d.ts +83 -0
  178. package/dist/types/utils.d.ts.map +1 -0
  179. package/dist/utils/components.d.ts +21 -1
  180. package/dist/utils/components.d.ts.map +1 -1
  181. package/dist/utils/components.js +76 -24
  182. package/dist/utils/components.js.map +1 -1
  183. package/dist/utils/components.mjs +70 -22
  184. package/dist/utils/components.mjs.map +1 -1
  185. package/dist/utils/encryption/decrypt.d.ts +1 -1
  186. package/dist/utils/encryption/decrypt.d.ts.map +1 -1
  187. package/dist/utils/encryption/decrypt.js.map +1 -1
  188. package/dist/utils/encryption/decrypt.mjs.map +1 -1
  189. package/dist/utils/encryption/encrypt.d.ts +1 -1
  190. package/dist/utils/encryption/encrypt.d.ts.map +1 -1
  191. package/dist/utils/encryption/encrypt.js.map +1 -1
  192. package/dist/utils/encryption/encrypt.mjs.map +1 -1
  193. package/dist/utils/index.js +1 -0
  194. package/dist/utils/index.js.map +1 -1
  195. package/dist/utils/index.mjs +1 -1
  196. package/dist/utils/middleware.d.ts +1 -1
  197. package/dist/utils/middleware.d.ts.map +1 -1
  198. package/dist/utils/middleware.js.map +1 -1
  199. package/dist/utils/middleware.mjs.map +1 -1
  200. package/dist/utils/transaction.d.ts +1 -1
  201. package/dist/utils/transaction.d.ts.map +1 -1
  202. package/dist/utils/transaction.js.map +1 -1
  203. package/dist/utils/transaction.mjs.map +1 -1
  204. package/dist/utils/transfer-asset-chunk.d.ts +22 -0
  205. package/dist/utils/transfer-asset-chunk.d.ts.map +1 -1
  206. package/dist/utils/transfer-asset-chunk.js +25 -0
  207. package/dist/utils/transfer-asset-chunk.js.map +1 -1
  208. package/dist/utils/transfer-asset-chunk.mjs +25 -1
  209. package/dist/utils/transfer-asset-chunk.mjs.map +1 -1
  210. package/package.json +11 -9
@@ -5,9 +5,14 @@ var stream = require('stream');
5
5
  /**
6
6
  * Writable for restoring upload assets during a local push destination transfer.
7
7
  *
8
- * The Writable `write()` callback must return as soon as the chunk is accepted — **before**
9
- * `uploadStream` finishes so the remote push handler can feed PassThrough data in the same
10
- * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).
8
+ * Design constraints:
9
+ * 1. The `write()` callback must return **before** `uploadStream` finishes so the remote push
10
+ * handler can continue feeding chunks to the PassThrough stream in the same WebSocket batch
11
+ * (avoids deadlock — see `streamAsset` in the remote push handler).
12
+ * 2. `uploadStream` is only called **after** the PassThrough has been fully drained (all chunks
13
+ * received and the stream ended). This gives the upload provider a pre-filled synchronous
14
+ * Readable rather than a lazy async wrapper, which avoids `Buffer.from(undefined)` crashes
15
+ * in upload providers that call `stream.read()` before any data has been buffered.
11
16
  */ function createAssetsDestinationWritable(options) {
12
17
  const { strapi, transaction, resolveUploadFileId, restoreMediaEntitiesContent, removeAssetsBackup } = options;
13
18
  let pendingUploads = 0;
@@ -23,29 +28,60 @@ var stream = require('stream');
23
28
  next();
24
29
  },
25
30
  write (chunk, _encoding, callback) {
26
- const uploadData = {
27
- ...chunk.metadata,
28
- stream: stream.Readable.from(chunk.stream),
29
- buffer: chunk?.buffer
30
- };
31
31
  const provider = strapi.config.get('plugin::upload').provider;
32
- const fileId = resolveUploadFileId(uploadData);
32
+ const fileId = resolveUploadFileId(chunk.metadata);
33
33
  if (!fileId) {
34
- callback(new Error(`File ID not found for ID: ${uploadData.id}`));
34
+ callback(new Error(`File ID not found for ID: ${chunk.metadata.id}`));
35
35
  return;
36
36
  }
37
37
  if (!transaction) {
38
38
  callback(new Error('Transaction not available for asset upload'));
39
39
  return;
40
40
  }
41
+ // Accumulate all binary chunks from the PassThrough as they arrive (flowing mode).
42
+ // uploadStream is only started once the stream ends — see constraint (2) above.
43
+ const bufferedChunks = [];
44
+ chunk.stream.on('data', (c)=>bufferedChunks.push(c));
41
45
  pendingUploads += 1;
42
- transaction.attach(async ()=>{
43
- try {
44
- await strapi.plugin('upload').provider.uploadStream(uploadData);
45
- if (!restoreMediaEntitiesContent) {
46
- return;
47
- }
48
- if (uploadData?.type) {
46
+ chunk.stream.once('end', ()=>{
47
+ // Build uploadData here so the stream is fully populated before the provider reads it.
48
+ const uploadData = {
49
+ ...chunk.metadata,
50
+ stream: stream.Readable.from(bufferedChunks),
51
+ ...chunk.buffer != null ? {
52
+ buffer: chunk.buffer
53
+ } : {}
54
+ };
55
+ transaction.attach(async ()=>{
56
+ try {
57
+ await strapi.plugin('upload').provider.uploadStream(uploadData);
58
+ if (!restoreMediaEntitiesContent) {
59
+ return;
60
+ }
61
+ if (uploadData?.type) {
62
+ const entry = await strapi.db.query('plugin::upload.file').findOne({
63
+ where: {
64
+ id: fileId
65
+ }
66
+ });
67
+ if (!entry) {
68
+ throw new Error('file not found');
69
+ }
70
+ const specificFormat = entry?.formats?.[uploadData.type];
71
+ if (specificFormat) {
72
+ specificFormat.url = uploadData.url;
73
+ }
74
+ await strapi.db.query('plugin::upload.file').update({
75
+ where: {
76
+ id: entry.id
77
+ },
78
+ data: {
79
+ formats: entry.formats,
80
+ provider
81
+ }
82
+ });
83
+ return;
84
+ }
49
85
  const entry = await strapi.db.query('plugin::upload.file').findOne({
50
86
  where: {
51
87
  id: fileId
@@ -54,50 +90,32 @@ var stream = require('stream');
54
90
  if (!entry) {
55
91
  throw new Error('file not found');
56
92
  }
57
- const specificFormat = entry?.formats?.[uploadData.type];
58
- if (specificFormat) {
59
- specificFormat.url = uploadData.url;
60
- }
93
+ entry.url = uploadData.url;
61
94
  await strapi.db.query('plugin::upload.file').update({
62
95
  where: {
63
96
  id: entry.id
64
97
  },
65
98
  data: {
66
- formats: entry.formats,
99
+ url: entry.url,
67
100
  provider
68
101
  }
69
102
  });
70
- return;
103
+ } catch (error) {
104
+ throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);
71
105
  }
72
- const entry = await strapi.db.query('plugin::upload.file').findOne({
73
- where: {
74
- id: fileId
75
- }
106
+ }).finally(()=>{
107
+ pendingUploads -= 1;
108
+ }).catch((error)=>{
109
+ const err = error instanceof Error ? error : new Error(String(error));
110
+ process.nextTick(()=>{
111
+ this.destroy(err);
76
112
  });
77
- if (!entry) {
78
- throw new Error('file not found');
79
- }
80
- entry.url = uploadData.url;
81
- await strapi.db.query('plugin::upload.file').update({
82
- where: {
83
- id: entry.id
84
- },
85
- data: {
86
- url: entry.url,
87
- provider
88
- }
89
- });
90
- } catch (error) {
91
- throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);
92
- }
93
- }).finally(()=>{
94
- pendingUploads -= 1;
95
- }).catch((error)=>{
96
- const err = error instanceof Error ? error : new Error(String(error));
97
- process.nextTick(()=>{
98
- this.destroy(err);
99
113
  });
100
114
  });
115
+ chunk.stream.once('error', (err)=>{
116
+ pendingUploads -= 1;
117
+ process.nextTick(()=>this.destroy(err));
118
+ });
101
119
  callback();
102
120
  }
103
121
  });
@@ -1 +1 @@
1
- {"version":3,"file":"assets-destination-writable.js","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"sourcesContent":["import { Writable, Readable } from 'stream';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../../types';\nimport type { Transaction } from '../../../../types/utils';\n\nexport interface CreateAssetsDestinationWritableOptions {\n strapi: Core.Strapi;\n transaction: Transaction;\n resolveUploadFileId: (metadata: { id: number }) => number | undefined;\n restoreMediaEntitiesContent: boolean;\n removeAssetsBackup: () => Promise<void>;\n}\n\n/**\n * Writable for restoring upload assets during a local push destination transfer.\n *\n * The Writable `write()` callback must return as soon as the chunk is accepted — **before**\n * `uploadStream` finishes so the remote push handler can feed PassThrough data in the same\n * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).\n */\nexport function createAssetsDestinationWritable(\n options: CreateAssetsDestinationWritableOptions\n): Writable {\n const {\n strapi,\n transaction,\n resolveUploadFileId,\n restoreMediaEntitiesContent,\n removeAssetsBackup,\n } = options;\n\n let pendingUploads = 0;\n\n return new Writable({\n objectMode: true,\n async final(next) {\n while (pendingUploads > 0) {\n await new Promise<void>((resolve) => {\n setImmediate(resolve);\n });\n }\n await removeAssetsBackup();\n next();\n },\n write(chunk: IAsset, _encoding, callback) {\n const uploadData = {\n ...chunk.metadata,\n stream: Readable.from(chunk.stream),\n buffer: chunk?.buffer,\n };\n\n const provider = strapi.config.get<{ provider: string }>('plugin::upload').provider;\n\n const fileId = resolveUploadFileId(uploadData);\n if (!fileId) {\n callback(new Error(`File ID not found for ID: ${uploadData.id}`));\n return;\n }\n\n if (!transaction) {\n callback(new Error('Transaction not available for asset upload'));\n return;\n }\n\n pendingUploads += 1;\n transaction\n .attach(async () => {\n try {\n await strapi.plugin('upload').provider.uploadStream(uploadData);\n\n if (!restoreMediaEntitiesContent) {\n return;\n }\n\n if (uploadData?.type) {\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n const specificFormat = entry?.formats?.[uploadData.type];\n if (specificFormat) {\n specificFormat.url = uploadData.url;\n }\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n formats: entry.formats,\n provider,\n },\n });\n return;\n }\n\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n entry.url = uploadData.url;\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n url: entry.url,\n provider,\n },\n });\n } catch (error) {\n throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);\n }\n })\n .finally(() => {\n pendingUploads -= 1;\n })\n .catch((error: unknown) => {\n const err = error instanceof Error ? error : new Error(String(error));\n process.nextTick(() => {\n this.destroy(err);\n });\n });\n\n callback();\n },\n });\n}\n"],"names":["createAssetsDestinationWritable","options","strapi","transaction","resolveUploadFileId","restoreMediaEntitiesContent","removeAssetsBackup","pendingUploads","Writable","objectMode","final","next","Promise","resolve","setImmediate","write","chunk","_encoding","callback","uploadData","metadata","stream","Readable","from","buffer","provider","config","get","fileId","Error","id","attach","plugin","uploadStream","type","entry","db","query","findOne","where","specificFormat","formats","url","update","data","error","filename","finally","catch","err","String","process","nextTick","destroy"],"mappings":"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"}
1
+ {"version":3,"file":"assets-destination-writable.js","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"sourcesContent":["import { Writable, Readable } from 'stream';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\nimport type { Transaction } from '../../../types/utils';\n\nexport interface CreateAssetsDestinationWritableOptions {\n strapi: Core.Strapi;\n transaction: Transaction;\n resolveUploadFileId: (metadata: { id: number }) => number | undefined;\n restoreMediaEntitiesContent: boolean;\n removeAssetsBackup: () => Promise<void>;\n}\n\n/**\n * Writable for restoring upload assets during a local push destination transfer.\n *\n * Design constraints:\n * 1. The `write()` callback must return **before** `uploadStream` finishes so the remote push\n * handler can continue feeding chunks to the PassThrough stream in the same WebSocket batch\n * (avoids deadlock see `streamAsset` in the remote push handler).\n * 2. `uploadStream` is only called **after** the PassThrough has been fully drained (all chunks\n * received and the stream ended). This gives the upload provider a pre-filled synchronous\n * Readable rather than a lazy async wrapper, which avoids `Buffer.from(undefined)` crashes\n * in upload providers that call `stream.read()` before any data has been buffered.\n */\nexport function createAssetsDestinationWritable(\n options: CreateAssetsDestinationWritableOptions\n): Writable {\n const {\n strapi,\n transaction,\n resolveUploadFileId,\n restoreMediaEntitiesContent,\n removeAssetsBackup,\n } = options;\n\n let pendingUploads = 0;\n\n return new Writable({\n objectMode: true,\n async final(next) {\n while (pendingUploads > 0) {\n await new Promise<void>((resolve) => {\n setImmediate(resolve);\n });\n }\n await removeAssetsBackup();\n next();\n },\n write(chunk: IAsset, _encoding, callback) {\n const provider = strapi.config.get<{ provider: string }>('plugin::upload').provider;\n\n const fileId = resolveUploadFileId(chunk.metadata);\n if (!fileId) {\n callback(new Error(`File ID not found for ID: ${chunk.metadata.id}`));\n return;\n }\n\n if (!transaction) {\n callback(new Error('Transaction not available for asset upload'));\n return;\n }\n\n // Accumulate all binary chunks from the PassThrough as they arrive (flowing mode).\n // uploadStream is only started once the stream ends — see constraint (2) above.\n const bufferedChunks: Buffer[] = [];\n chunk.stream.on('data', (c: Buffer) => bufferedChunks.push(c));\n\n pendingUploads += 1;\n\n chunk.stream.once('end', () => {\n // Build uploadData here so the stream is fully populated before the provider reads it.\n const uploadData = {\n ...chunk.metadata,\n stream: Readable.from(bufferedChunks),\n ...(chunk.buffer != null ? { buffer: chunk.buffer } : {}),\n };\n\n transaction\n .attach(async () => {\n try {\n await strapi.plugin('upload').provider.uploadStream(uploadData);\n\n if (!restoreMediaEntitiesContent) {\n return;\n }\n\n if (uploadData?.type) {\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n const specificFormat = entry?.formats?.[uploadData.type];\n if (specificFormat) {\n specificFormat.url = uploadData.url;\n }\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n formats: entry.formats,\n provider,\n },\n });\n return;\n }\n\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n entry.url = uploadData.url;\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n url: entry.url,\n provider,\n },\n });\n } catch (error) {\n throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);\n }\n })\n .finally(() => {\n pendingUploads -= 1;\n })\n .catch((error: unknown) => {\n const err = error instanceof Error ? error : new Error(String(error));\n process.nextTick(() => {\n this.destroy(err);\n });\n });\n });\n\n chunk.stream.once('error', (err) => {\n pendingUploads -= 1;\n process.nextTick(() => this.destroy(err));\n });\n\n callback();\n },\n });\n}\n"],"names":["createAssetsDestinationWritable","options","strapi","transaction","resolveUploadFileId","restoreMediaEntitiesContent","removeAssetsBackup","pendingUploads","Writable","objectMode","final","next","Promise","resolve","setImmediate","write","chunk","_encoding","callback","provider","config","get","fileId","metadata","Error","id","bufferedChunks","stream","on","c","push","once","uploadData","Readable","from","buffer","attach","plugin","uploadStream","type","entry","db","query","findOne","where","specificFormat","formats","url","update","data","error","filename","finally","catch","err","String","process","nextTick","destroy"],"mappings":"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"}
@@ -3,9 +3,14 @@ import { Writable, Readable } from 'stream';
3
3
  /**
4
4
  * Writable for restoring upload assets during a local push destination transfer.
5
5
  *
6
- * The Writable `write()` callback must return as soon as the chunk is accepted — **before**
7
- * `uploadStream` finishes so the remote push handler can feed PassThrough data in the same
8
- * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).
6
+ * Design constraints:
7
+ * 1. The `write()` callback must return **before** `uploadStream` finishes so the remote push
8
+ * handler can continue feeding chunks to the PassThrough stream in the same WebSocket batch
9
+ * (avoids deadlock — see `streamAsset` in the remote push handler).
10
+ * 2. `uploadStream` is only called **after** the PassThrough has been fully drained (all chunks
11
+ * received and the stream ended). This gives the upload provider a pre-filled synchronous
12
+ * Readable rather than a lazy async wrapper, which avoids `Buffer.from(undefined)` crashes
13
+ * in upload providers that call `stream.read()` before any data has been buffered.
9
14
  */ function createAssetsDestinationWritable(options) {
10
15
  const { strapi, transaction, resolveUploadFileId, restoreMediaEntitiesContent, removeAssetsBackup } = options;
11
16
  let pendingUploads = 0;
@@ -21,29 +26,60 @@ import { Writable, Readable } from 'stream';
21
26
  next();
22
27
  },
23
28
  write (chunk, _encoding, callback) {
24
- const uploadData = {
25
- ...chunk.metadata,
26
- stream: Readable.from(chunk.stream),
27
- buffer: chunk?.buffer
28
- };
29
29
  const provider = strapi.config.get('plugin::upload').provider;
30
- const fileId = resolveUploadFileId(uploadData);
30
+ const fileId = resolveUploadFileId(chunk.metadata);
31
31
  if (!fileId) {
32
- callback(new Error(`File ID not found for ID: ${uploadData.id}`));
32
+ callback(new Error(`File ID not found for ID: ${chunk.metadata.id}`));
33
33
  return;
34
34
  }
35
35
  if (!transaction) {
36
36
  callback(new Error('Transaction not available for asset upload'));
37
37
  return;
38
38
  }
39
+ // Accumulate all binary chunks from the PassThrough as they arrive (flowing mode).
40
+ // uploadStream is only started once the stream ends — see constraint (2) above.
41
+ const bufferedChunks = [];
42
+ chunk.stream.on('data', (c)=>bufferedChunks.push(c));
39
43
  pendingUploads += 1;
40
- transaction.attach(async ()=>{
41
- try {
42
- await strapi.plugin('upload').provider.uploadStream(uploadData);
43
- if (!restoreMediaEntitiesContent) {
44
- return;
45
- }
46
- if (uploadData?.type) {
44
+ chunk.stream.once('end', ()=>{
45
+ // Build uploadData here so the stream is fully populated before the provider reads it.
46
+ const uploadData = {
47
+ ...chunk.metadata,
48
+ stream: Readable.from(bufferedChunks),
49
+ ...chunk.buffer != null ? {
50
+ buffer: chunk.buffer
51
+ } : {}
52
+ };
53
+ transaction.attach(async ()=>{
54
+ try {
55
+ await strapi.plugin('upload').provider.uploadStream(uploadData);
56
+ if (!restoreMediaEntitiesContent) {
57
+ return;
58
+ }
59
+ if (uploadData?.type) {
60
+ const entry = await strapi.db.query('plugin::upload.file').findOne({
61
+ where: {
62
+ id: fileId
63
+ }
64
+ });
65
+ if (!entry) {
66
+ throw new Error('file not found');
67
+ }
68
+ const specificFormat = entry?.formats?.[uploadData.type];
69
+ if (specificFormat) {
70
+ specificFormat.url = uploadData.url;
71
+ }
72
+ await strapi.db.query('plugin::upload.file').update({
73
+ where: {
74
+ id: entry.id
75
+ },
76
+ data: {
77
+ formats: entry.formats,
78
+ provider
79
+ }
80
+ });
81
+ return;
82
+ }
47
83
  const entry = await strapi.db.query('plugin::upload.file').findOne({
48
84
  where: {
49
85
  id: fileId
@@ -52,50 +88,32 @@ import { Writable, Readable } from 'stream';
52
88
  if (!entry) {
53
89
  throw new Error('file not found');
54
90
  }
55
- const specificFormat = entry?.formats?.[uploadData.type];
56
- if (specificFormat) {
57
- specificFormat.url = uploadData.url;
58
- }
91
+ entry.url = uploadData.url;
59
92
  await strapi.db.query('plugin::upload.file').update({
60
93
  where: {
61
94
  id: entry.id
62
95
  },
63
96
  data: {
64
- formats: entry.formats,
97
+ url: entry.url,
65
98
  provider
66
99
  }
67
100
  });
68
- return;
101
+ } catch (error) {
102
+ throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);
69
103
  }
70
- const entry = await strapi.db.query('plugin::upload.file').findOne({
71
- where: {
72
- id: fileId
73
- }
104
+ }).finally(()=>{
105
+ pendingUploads -= 1;
106
+ }).catch((error)=>{
107
+ const err = error instanceof Error ? error : new Error(String(error));
108
+ process.nextTick(()=>{
109
+ this.destroy(err);
74
110
  });
75
- if (!entry) {
76
- throw new Error('file not found');
77
- }
78
- entry.url = uploadData.url;
79
- await strapi.db.query('plugin::upload.file').update({
80
- where: {
81
- id: entry.id
82
- },
83
- data: {
84
- url: entry.url,
85
- provider
86
- }
87
- });
88
- } catch (error) {
89
- throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);
90
- }
91
- }).finally(()=>{
92
- pendingUploads -= 1;
93
- }).catch((error)=>{
94
- const err = error instanceof Error ? error : new Error(String(error));
95
- process.nextTick(()=>{
96
- this.destroy(err);
97
111
  });
98
112
  });
113
+ chunk.stream.once('error', (err)=>{
114
+ pendingUploads -= 1;
115
+ process.nextTick(()=>this.destroy(err));
116
+ });
99
117
  callback();
100
118
  }
101
119
  });
@@ -1 +1 @@
1
- {"version":3,"file":"assets-destination-writable.mjs","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"sourcesContent":["import { Writable, Readable } from 'stream';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../../types';\nimport type { Transaction } from '../../../../types/utils';\n\nexport interface CreateAssetsDestinationWritableOptions {\n strapi: Core.Strapi;\n transaction: Transaction;\n resolveUploadFileId: (metadata: { id: number }) => number | undefined;\n restoreMediaEntitiesContent: boolean;\n removeAssetsBackup: () => Promise<void>;\n}\n\n/**\n * Writable for restoring upload assets during a local push destination transfer.\n *\n * The Writable `write()` callback must return as soon as the chunk is accepted — **before**\n * `uploadStream` finishes so the remote push handler can feed PassThrough data in the same\n * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).\n */\nexport function createAssetsDestinationWritable(\n options: CreateAssetsDestinationWritableOptions\n): Writable {\n const {\n strapi,\n transaction,\n resolveUploadFileId,\n restoreMediaEntitiesContent,\n removeAssetsBackup,\n } = options;\n\n let pendingUploads = 0;\n\n return new Writable({\n objectMode: true,\n async final(next) {\n while (pendingUploads > 0) {\n await new Promise<void>((resolve) => {\n setImmediate(resolve);\n });\n }\n await removeAssetsBackup();\n next();\n },\n write(chunk: IAsset, _encoding, callback) {\n const uploadData = {\n ...chunk.metadata,\n stream: Readable.from(chunk.stream),\n buffer: chunk?.buffer,\n };\n\n const provider = strapi.config.get<{ provider: string }>('plugin::upload').provider;\n\n const fileId = resolveUploadFileId(uploadData);\n if (!fileId) {\n callback(new Error(`File ID not found for ID: ${uploadData.id}`));\n return;\n }\n\n if (!transaction) {\n callback(new Error('Transaction not available for asset upload'));\n return;\n }\n\n pendingUploads += 1;\n transaction\n .attach(async () => {\n try {\n await strapi.plugin('upload').provider.uploadStream(uploadData);\n\n if (!restoreMediaEntitiesContent) {\n return;\n }\n\n if (uploadData?.type) {\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n const specificFormat = entry?.formats?.[uploadData.type];\n if (specificFormat) {\n specificFormat.url = uploadData.url;\n }\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n formats: entry.formats,\n provider,\n },\n });\n return;\n }\n\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n entry.url = uploadData.url;\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n url: entry.url,\n provider,\n },\n });\n } catch (error) {\n throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);\n }\n })\n .finally(() => {\n pendingUploads -= 1;\n })\n .catch((error: unknown) => {\n const err = error instanceof Error ? error : new Error(String(error));\n process.nextTick(() => {\n this.destroy(err);\n });\n });\n\n callback();\n },\n });\n}\n"],"names":["createAssetsDestinationWritable","options","strapi","transaction","resolveUploadFileId","restoreMediaEntitiesContent","removeAssetsBackup","pendingUploads","Writable","objectMode","final","next","Promise","resolve","setImmediate","write","chunk","_encoding","callback","uploadData","metadata","stream","Readable","from","buffer","provider","config","get","fileId","Error","id","attach","plugin","uploadStream","type","entry","db","query","findOne","where","specificFormat","formats","url","update","data","error","filename","finally","catch","err","String","process","nextTick","destroy"],"mappings":"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"}
1
+ {"version":3,"file":"assets-destination-writable.mjs","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"sourcesContent":["import { Writable, Readable } from 'stream';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\nimport type { Transaction } from '../../../types/utils';\n\nexport interface CreateAssetsDestinationWritableOptions {\n strapi: Core.Strapi;\n transaction: Transaction;\n resolveUploadFileId: (metadata: { id: number }) => number | undefined;\n restoreMediaEntitiesContent: boolean;\n removeAssetsBackup: () => Promise<void>;\n}\n\n/**\n * Writable for restoring upload assets during a local push destination transfer.\n *\n * Design constraints:\n * 1. The `write()` callback must return **before** `uploadStream` finishes so the remote push\n * handler can continue feeding chunks to the PassThrough stream in the same WebSocket batch\n * (avoids deadlock see `streamAsset` in the remote push handler).\n * 2. `uploadStream` is only called **after** the PassThrough has been fully drained (all chunks\n * received and the stream ended). This gives the upload provider a pre-filled synchronous\n * Readable rather than a lazy async wrapper, which avoids `Buffer.from(undefined)` crashes\n * in upload providers that call `stream.read()` before any data has been buffered.\n */\nexport function createAssetsDestinationWritable(\n options: CreateAssetsDestinationWritableOptions\n): Writable {\n const {\n strapi,\n transaction,\n resolveUploadFileId,\n restoreMediaEntitiesContent,\n removeAssetsBackup,\n } = options;\n\n let pendingUploads = 0;\n\n return new Writable({\n objectMode: true,\n async final(next) {\n while (pendingUploads > 0) {\n await new Promise<void>((resolve) => {\n setImmediate(resolve);\n });\n }\n await removeAssetsBackup();\n next();\n },\n write(chunk: IAsset, _encoding, callback) {\n const provider = strapi.config.get<{ provider: string }>('plugin::upload').provider;\n\n const fileId = resolveUploadFileId(chunk.metadata);\n if (!fileId) {\n callback(new Error(`File ID not found for ID: ${chunk.metadata.id}`));\n return;\n }\n\n if (!transaction) {\n callback(new Error('Transaction not available for asset upload'));\n return;\n }\n\n // Accumulate all binary chunks from the PassThrough as they arrive (flowing mode).\n // uploadStream is only started once the stream ends — see constraint (2) above.\n const bufferedChunks: Buffer[] = [];\n chunk.stream.on('data', (c: Buffer) => bufferedChunks.push(c));\n\n pendingUploads += 1;\n\n chunk.stream.once('end', () => {\n // Build uploadData here so the stream is fully populated before the provider reads it.\n const uploadData = {\n ...chunk.metadata,\n stream: Readable.from(bufferedChunks),\n ...(chunk.buffer != null ? { buffer: chunk.buffer } : {}),\n };\n\n transaction\n .attach(async () => {\n try {\n await strapi.plugin('upload').provider.uploadStream(uploadData);\n\n if (!restoreMediaEntitiesContent) {\n return;\n }\n\n if (uploadData?.type) {\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n const specificFormat = entry?.formats?.[uploadData.type];\n if (specificFormat) {\n specificFormat.url = uploadData.url;\n }\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n formats: entry.formats,\n provider,\n },\n });\n return;\n }\n\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n entry.url = uploadData.url;\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n url: entry.url,\n provider,\n },\n });\n } catch (error) {\n throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);\n }\n })\n .finally(() => {\n pendingUploads -= 1;\n })\n .catch((error: unknown) => {\n const err = error instanceof Error ? error : new Error(String(error));\n process.nextTick(() => {\n this.destroy(err);\n });\n });\n });\n\n chunk.stream.once('error', (err) => {\n pendingUploads -= 1;\n process.nextTick(() => this.destroy(err));\n });\n\n callback();\n },\n });\n}\n"],"names":["createAssetsDestinationWritable","options","strapi","transaction","resolveUploadFileId","restoreMediaEntitiesContent","removeAssetsBackup","pendingUploads","Writable","objectMode","final","next","Promise","resolve","setImmediate","write","chunk","_encoding","callback","provider","config","get","fileId","metadata","Error","id","bufferedChunks","stream","on","c","push","once","uploadData","Readable","from","buffer","attach","plugin","uploadStream","type","entry","db","query","findOne","where","specificFormat","formats","url","update","data","error","filename","finally","catch","err","String","process","nextTick","destroy"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { Writable } from 'stream';
3
3
  import type { Core, Struct } from '@strapi/types';
4
- import type { IDestinationProvider, IMetadata, ProviderType, Transaction } from '../../../../types';
4
+ import type { IDestinationProvider, IMetadata, ProviderType, Transaction } from '../../../types';
5
5
  import type { IDiagnosticReporter } from '../../../utils/diagnostic';
6
6
  import { restore } from './strategies';
7
7
  export declare const VALID_CONFLICT_STRATEGIES: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/strapi/providers/local-destination/index.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAY,MAAM,QAAQ,CAAC;AAI5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AASvC,eAAO,MAAM,yBAAyB,UAAc,CAAC;AACrD,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,MAAM,WAAW,sCAAsC;IACrD,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,sFAAsF;IACtF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,cAAM,8BAA+B,YAAW,oBAAoB;;IAClE,IAAI,SAA+B;IAEnC,IAAI,EAAE,YAAY,CAAiB;IAEnC,OAAO,EAAE,sCAAsC,CAAC;IAEhD,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,0BAA0B,EAAE,MAAM,CAAC;IAEnC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;gBASxC,OAAO,EAAE,sCAAsC;IAMrD,SAAS,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmEtB,QAAQ;IAMR,cAAc;IA2BpB,WAAW,IAAI,SAAS;IAcxB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IAY3C,yBAAyB,IAAI,QAAQ;IA2F/B,uBAAuB,IAAI,OAAO,CAAC,QAAQ,CAAC;IAoB5C,8BAA8B,IAAI,OAAO,CAAC,QAAQ,CAAC;IAgBnD,sBAAsB,IAAI,OAAO,CAAC,QAAQ,CAAC;CAmBlD;AAED,eAAO,MAAM,oCAAoC,YACtC,sCAAsC,mCAGhD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/strapi/providers/local-destination/index.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAY,MAAM,QAAQ,CAAC;AAI5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AASvC,eAAO,MAAM,yBAAyB,UAAc,CAAC;AACrD,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,MAAM,WAAW,sCAAsC;IACrD,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,sFAAsF;IACtF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,cAAM,8BAA+B,YAAW,oBAAoB;;IAClE,IAAI,SAA+B;IAEnC,IAAI,EAAE,YAAY,CAAiB;IAEnC,OAAO,EAAE,sCAAsC,CAAC;IAEhD,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,0BAA0B,EAAE,MAAM,CAAC;IAEnC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;gBASxC,OAAO,EAAE,sCAAsC;IAMrD,SAAS,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmEtB,QAAQ;IAMR,cAAc;IA2BpB,WAAW,IAAI,SAAS;IAcxB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IAY3C,yBAAyB,IAAI,QAAQ;IA2F/B,uBAAuB,IAAI,OAAO,CAAC,QAAQ,CAAC;IAoB5C,8BAA8B,IAAI,OAAO,CAAC,QAAQ,CAAC;IAgBnD,sBAAsB,IAAI,OAAO,CAAC,QAAQ,CAAC;CAmBlD;AAED,eAAO,MAAM,oCAAoC,YACtC,sCAAsC,mCAGhD,CAAC"}
@@ -18,7 +18,10 @@ var entities = require('./strategies/restore/entities.js');
18
18
  var configuration = require('./strategies/restore/configuration.js');
19
19
  var links = require('./strategies/restore/links.js');
20
20
 
21
- function _interopNamespaceDefault(e) {
21
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
22
+
23
+ function _interopNamespace(e) {
24
+ if (e && e.__esModule) return e;
22
25
  var n = Object.create(null);
23
26
  if (e) {
24
27
  Object.keys(e).forEach(function (k) {
@@ -35,7 +38,8 @@ function _interopNamespaceDefault(e) {
35
38
  return Object.freeze(n);
36
39
  }
37
40
 
38
- var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
41
+ var path__default = /*#__PURE__*/_interopDefault(path);
42
+ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
39
43
 
40
44
  function _class_private_field_loose_base(receiver, privateKey) {
41
45
  if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
@@ -309,18 +313,18 @@ async function handleAssetsBackup() {
309
313
  }
310
314
  if (this.strapi.config.get('plugin::upload').provider === 'local') {
311
315
  _class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating assets backup directory');
312
- const assetsDirectory = path.join(this.strapi.dirs.static.public, 'uploads');
313
- const backupDirectory = path.join(this.strapi.dirs.static.public, this.uploadsBackupDirectoryName);
316
+ const assetsDirectory = path__default.default.join(this.strapi.dirs.static.public, 'uploads');
317
+ const backupDirectory = path__default.default.join(this.strapi.dirs.static.public, this.uploadsBackupDirectoryName);
314
318
  try {
315
319
  // Check access before attempting to do anything
316
320
  await fs__namespace.access(assetsDirectory, // eslint-disable-next-line no-bitwise
317
321
  fs__namespace.constants.W_OK | fs__namespace.constants.R_OK | fs__namespace.constants.F_OK);
318
322
  // eslint-disable-next-line no-bitwise
319
- await fs__namespace.access(path.join(assetsDirectory, '..'), fs__namespace.constants.W_OK | fs__namespace.constants.R_OK);
323
+ await fs__namespace.access(path__default.default.join(assetsDirectory, '..'), fs__namespace.constants.W_OK | fs__namespace.constants.R_OK);
320
324
  await fs__namespace.move(assetsDirectory, backupDirectory);
321
325
  await fs__namespace.mkdir(assetsDirectory);
322
326
  // Create a .gitkeep file to ensure the directory is not empty
323
- await fs__namespace.outputFile(path.join(assetsDirectory, '.gitkeep'), '');
327
+ await fs__namespace.outputFile(path__default.default.join(assetsDirectory, '.gitkeep'), '');
324
328
  _class_private_field_loose_base(this, _reportInfo)[_reportInfo](`created assets backup directory ${backupDirectory}`);
325
329
  } catch (err) {
326
330
  throw new providers.ProviderTransferError('The backup folder for the assets could not be created inside the public folder. Please ensure Strapi has write permissions on the public directory', {
@@ -340,7 +344,7 @@ async function removeAssetsBackup() {
340
344
  if (this.strapi.config.get('plugin::upload').provider === 'local') {
341
345
  _class_private_field_loose_base(this, _reportInfo)[_reportInfo]('removing assets backup');
342
346
  providers$1.assertValidStrapi(this.strapi);
343
- const backupDirectory = path.join(this.strapi.dirs.static.public, this.uploadsBackupDirectoryName);
347
+ const backupDirectory = path__default.default.join(this.strapi.dirs.static.public, this.uploadsBackupDirectoryName);
344
348
  await fs__namespace.rm(backupDirectory, {
345
349
  recursive: true,
346
350
  force: true