@strapi/data-transfer 5.4.2 → 5.5.1

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 (33) hide show
  1. package/dist/engine/index.d.ts +1 -1
  2. package/dist/engine/index.d.ts.map +1 -1
  3. package/dist/errors/constants.d.ts +1 -1
  4. package/dist/errors/constants.d.ts.map +1 -1
  5. package/dist/file/providers/destination/index.d.ts +1 -1
  6. package/dist/file/providers/destination/index.d.ts.map +1 -1
  7. package/dist/file/providers/source/index.d.ts +1 -1
  8. package/dist/file/providers/source/index.d.ts.map +1 -1
  9. package/dist/index.js +152 -92
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +151 -90
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/strapi/providers/local-destination/index.d.ts +1 -1
  14. package/dist/strapi/providers/local-destination/index.d.ts.map +1 -1
  15. package/dist/strapi/providers/local-source/index.d.ts +1 -1
  16. package/dist/strapi/providers/local-source/index.d.ts.map +1 -1
  17. package/dist/strapi/providers/remote-destination/index.d.ts +1 -1
  18. package/dist/strapi/providers/remote-destination/index.d.ts.map +1 -1
  19. package/dist/strapi/providers/remote-source/index.d.ts +1 -1
  20. package/dist/strapi/providers/remote-source/index.d.ts.map +1 -1
  21. package/dist/strapi/providers/utils.d.ts +2 -1
  22. package/dist/strapi/providers/utils.d.ts.map +1 -1
  23. package/dist/strapi/remote/handlers/abstract.d.ts +4 -0
  24. package/dist/strapi/remote/handlers/abstract.d.ts.map +1 -1
  25. package/dist/strapi/remote/handlers/pull.d.ts.map +1 -1
  26. package/dist/strapi/remote/handlers/push.d.ts.map +1 -1
  27. package/dist/strapi/remote/handlers/utils.d.ts.map +1 -1
  28. package/dist/{engine → utils}/diagnostic.d.ts +1 -1
  29. package/dist/utils/diagnostic.d.ts.map +1 -0
  30. package/dist/utils/index.d.ts +1 -0
  31. package/dist/utils/index.d.ts.map +1 -1
  32. package/package.json +7 -8
  33. package/dist/engine/diagnostic.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -298,8 +298,57 @@ const middleware = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
298
298
  __proto__: null,
299
299
  runMiddleware
300
300
  }, Symbol.toStringTag, { value: "Module" }));
301
+ const createDiagnosticReporter = (options = {}) => {
302
+ const { stackSize = -1 } = options;
303
+ const emitter = new EventEmitter();
304
+ const stack = [];
305
+ const addListener = (event, listener) => {
306
+ emitter.on(event, listener);
307
+ };
308
+ const isDiagnosticValid = (diagnostic2) => {
309
+ if (!diagnostic2.kind || !diagnostic2.details || !diagnostic2.details.message) {
310
+ return false;
311
+ }
312
+ return true;
313
+ };
314
+ return {
315
+ stack: {
316
+ get size() {
317
+ return stack.length;
318
+ },
319
+ get items() {
320
+ return stack;
321
+ }
322
+ },
323
+ report(diagnostic2) {
324
+ if (!isDiagnosticValid(diagnostic2)) {
325
+ return this;
326
+ }
327
+ emitter.emit("diagnostic", diagnostic2);
328
+ emitter.emit(`diagnostic.${diagnostic2.kind}`, diagnostic2);
329
+ if (stackSize !== -1 && stack.length >= stackSize) {
330
+ stack.shift();
331
+ }
332
+ stack.push(diagnostic2);
333
+ return this;
334
+ },
335
+ onDiagnostic(listener) {
336
+ addListener("diagnostic", listener);
337
+ return this;
338
+ },
339
+ on(kind, listener) {
340
+ addListener(`diagnostic.${kind}`, listener);
341
+ return this;
342
+ }
343
+ };
344
+ };
345
+ const diagnostic = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
346
+ __proto__: null,
347
+ createDiagnosticReporter
348
+ }, Symbol.toStringTag, { value: "Module" }));
301
349
  const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
302
350
  __proto__: null,
351
+ diagnostics: diagnostic,
303
352
  encryption: index$9,
304
353
  json,
305
354
  middleware,
@@ -400,50 +449,6 @@ const validateProvider = (type, provider) => {
400
449
  );
401
450
  }
402
451
  };
403
- const createDiagnosticReporter = (options = {}) => {
404
- const { stackSize = -1 } = options;
405
- const emitter = new EventEmitter();
406
- const stack = [];
407
- const addListener = (event, listener) => {
408
- emitter.on(event, listener);
409
- };
410
- const isDiagnosticValid = (diagnostic) => {
411
- if (!diagnostic.kind || !diagnostic.details || !diagnostic.details.message) {
412
- return false;
413
- }
414
- return true;
415
- };
416
- return {
417
- stack: {
418
- get size() {
419
- return stack.length;
420
- },
421
- get items() {
422
- return stack;
423
- }
424
- },
425
- report(diagnostic) {
426
- if (!isDiagnosticValid(diagnostic)) {
427
- return this;
428
- }
429
- emitter.emit("diagnostic", diagnostic);
430
- emitter.emit(`diagnostic.${diagnostic.kind}`, diagnostic);
431
- if (stackSize !== -1 && stack.length >= stackSize) {
432
- stack.shift();
433
- }
434
- stack.push(diagnostic);
435
- return this;
436
- },
437
- onDiagnostic(listener) {
438
- addListener("diagnostic", listener);
439
- return this;
440
- },
441
- on(kind, listener) {
442
- addListener(`diagnostic.${kind}`, listener);
443
- return this;
444
- }
445
- };
446
- };
447
452
  class ProviderError extends DataTransferError {
448
453
  constructor(severity, message, details) {
449
454
  super("provider", severity, message, details);
@@ -576,7 +581,7 @@ class TransferEngine {
576
581
  reportInfo(message, params) {
577
582
  this.diagnostics.report({
578
583
  kind: "info",
579
- details: { createdAt: /* @__PURE__ */ new Date(), message, params, source: "engine" }
584
+ details: { createdAt: /* @__PURE__ */ new Date(), message, params, origin: "engine" }
580
585
  });
581
586
  }
582
587
  /**
@@ -1907,7 +1912,7 @@ class LocalStrapiDestinationProvider {
1907
1912
  details: {
1908
1913
  createdAt: /* @__PURE__ */ new Date(),
1909
1914
  message,
1910
- source: "local-destination-provider"
1915
+ origin: "local-destination-provider"
1911
1916
  },
1912
1917
  kind: "info"
1913
1918
  });
@@ -2084,7 +2089,6 @@ class LocalStrapiDestinationProvider {
2084
2089
  const removeAssetsBackup = this.#removeAssetsBackup.bind(this);
2085
2090
  const strapi2 = this.strapi;
2086
2091
  const transaction2 = this.transaction;
2087
- const backupDirectory = this.uploadsBackupDirectoryName;
2088
2092
  const fileEntitiesMapper = this.#entitiesMapper["plugin::upload.file"];
2089
2093
  const restoreMediaEntitiesContent = this.#isContentTypeIncluded("plugin::upload.file");
2090
2094
  return new Writable({
@@ -2095,47 +2099,28 @@ class LocalStrapiDestinationProvider {
2095
2099
  },
2096
2100
  async write(chunk, _encoding, callback) {
2097
2101
  await transaction2?.attach(async () => {
2098
- if (!chunk.metadata) {
2099
- const assetsDirectory = path.join(strapi2.dirs.static.public, "uploads");
2100
- const entryPath = path.join(assetsDirectory, chunk.filename);
2101
- const writableStream = fse.createWriteStream(entryPath);
2102
- chunk.stream.pipe(writableStream).on("close", () => {
2103
- callback(null);
2104
- }).on("error", async (error) => {
2105
- const errorMessage = error.code === "ENOSPC" ? " Your server doesn't have space to proceed with the import. " : " ";
2106
- try {
2107
- await fse.rm(assetsDirectory, { recursive: true, force: true });
2108
- this.destroy(
2109
- new ProviderTransferError(
2110
- `There was an error during the transfer process.${errorMessage}The original files have been restored to ${assetsDirectory}`
2111
- )
2112
- );
2113
- } catch (err) {
2114
- throw new ProviderTransferError(
2115
- `There was an error doing the rollback process. The original files are in ${backupDirectory}, but we failed to restore them to ${assetsDirectory}`
2116
- );
2117
- } finally {
2118
- callback(error);
2119
- }
2120
- });
2121
- return;
2122
- }
2123
2102
  const uploadData = {
2124
2103
  ...chunk.metadata,
2125
2104
  stream: Readable.from(chunk.stream),
2126
2105
  buffer: chunk?.buffer
2127
2106
  };
2128
2107
  const provider = strapi2.config.get("plugin::upload").provider;
2108
+ const fileId = fileEntitiesMapper?.[uploadData.id];
2109
+ if (!fileId) {
2110
+ callback(new Error(`File ID not found for ID: ${uploadData.id}`));
2111
+ }
2129
2112
  try {
2130
2113
  await strapi2.plugin("upload").provider.uploadStream(uploadData);
2131
2114
  if (!restoreMediaEntitiesContent) {
2132
2115
  return callback();
2133
2116
  }
2134
2117
  if (uploadData?.type) {
2135
- const condition = uploadData?.id ? { id: fileEntitiesMapper[uploadData.id] } : { hash: uploadData.mainHash };
2136
2118
  const entry2 = await strapi2.db.query("plugin::upload.file").findOne({
2137
- where: condition
2119
+ where: { id: fileId }
2138
2120
  });
2121
+ if (!entry2) {
2122
+ throw new Error("file not found");
2123
+ }
2139
2124
  const specificFormat = entry2?.formats?.[uploadData.type];
2140
2125
  if (specificFormat) {
2141
2126
  specificFormat.url = uploadData.url;
@@ -2150,8 +2135,11 @@ class LocalStrapiDestinationProvider {
2150
2135
  return callback();
2151
2136
  }
2152
2137
  const entry = await strapi2.db.query("plugin::upload.file").findOne({
2153
- where: { id: fileEntitiesMapper[uploadData.id] }
2138
+ where: { id: fileId }
2154
2139
  });
2140
+ if (!entry) {
2141
+ throw new Error("file not found");
2142
+ }
2155
2143
  entry.url = uploadData.url;
2156
2144
  await strapi2.db.query("plugin::upload.file").update({
2157
2145
  where: { id: entry.id },
@@ -2394,7 +2382,7 @@ class LocalStrapiSourceProvider {
2394
2382
  details: {
2395
2383
  createdAt: /* @__PURE__ */ new Date(),
2396
2384
  message,
2397
- source: "local-source-provider"
2385
+ origin: "local-source-provider"
2398
2386
  },
2399
2387
  kind: "info"
2400
2388
  });
@@ -2504,12 +2492,12 @@ const createDispatcher = (ws, retryMessageOptions = {
2504
2492
  const response = JSON.parse(raw.toString());
2505
2493
  if (message.type === "command") {
2506
2494
  reportInfo?.(
2507
- `recieved response to message command: ${message.command} uuid: ${uuid} sent: ${numberOfTimesMessageWasSent}`
2495
+ `received response to message command: ${message.command} uuid: ${uuid} sent: ${numberOfTimesMessageWasSent}`
2508
2496
  );
2509
2497
  } else if (message.type === "transfer") {
2510
2498
  const messageToSend = message;
2511
2499
  reportInfo?.(
2512
- `recieved response to message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
2500
+ `received response to message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
2513
2501
  );
2514
2502
  }
2515
2503
  if (response.uuid === uuid) {
@@ -2568,7 +2556,7 @@ const createDispatcher = (ws, retryMessageOptions = {
2568
2556
  dispatchTransferStep
2569
2557
  };
2570
2558
  };
2571
- const connectToWebsocket = (address, options) => {
2559
+ const connectToWebsocket = (address, options, diagnostics) => {
2572
2560
  return new Promise((resolve, reject2) => {
2573
2561
  const server = new WebSocket(address, options);
2574
2562
  server.once("open", () => {
@@ -2602,6 +2590,14 @@ const connectToWebsocket = (address, options) => {
2602
2590
  )
2603
2591
  );
2604
2592
  });
2593
+ server.on("message", (raw) => {
2594
+ const response = JSON.parse(raw.toString());
2595
+ if (response.diagnostic) {
2596
+ diagnostics?.report({
2597
+ ...response.diagnostic
2598
+ });
2599
+ }
2600
+ });
2605
2601
  server.once("error", (err) => {
2606
2602
  reject2(
2607
2603
  new ProviderTransferError(err.message, {
@@ -2775,7 +2771,7 @@ class RemoteStrapiDestinationProvider {
2775
2771
  details: {
2776
2772
  createdAt: /* @__PURE__ */ new Date(),
2777
2773
  message,
2778
- source: "remote-destination-provider"
2774
+ origin: "remote-destination-provider"
2779
2775
  },
2780
2776
  kind: "info"
2781
2777
  });
@@ -2800,10 +2796,10 @@ class RemoteStrapiDestinationProvider {
2800
2796
  )}${TRANSFER_PATH}/push`;
2801
2797
  this.#reportInfo("establishing websocket connection");
2802
2798
  if (!auth) {
2803
- ws = await connectToWebsocket(wsUrl);
2799
+ ws = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
2804
2800
  } else if (auth.type === "token") {
2805
2801
  const headers = { Authorization: `Bearer ${auth.token}` };
2806
- ws = await connectToWebsocket(wsUrl, { headers });
2802
+ ws = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
2807
2803
  } else {
2808
2804
  throw new ProviderValidationError("Auth method not available", {
2809
2805
  check: "auth.type",
@@ -3139,7 +3135,7 @@ class RemoteStrapiSourceProvider {
3139
3135
  details: {
3140
3136
  createdAt: /* @__PURE__ */ new Date(),
3141
3137
  message,
3142
- source: "remote-source-provider"
3138
+ origin: "remote-source-provider"
3143
3139
  },
3144
3140
  kind: "info"
3145
3141
  });
@@ -3155,10 +3151,10 @@ class RemoteStrapiSourceProvider {
3155
3151
  )}${TRANSFER_PATH}/pull`;
3156
3152
  this.#reportInfo("establishing websocket connection");
3157
3153
  if (!auth) {
3158
- ws = await connectToWebsocket(wsUrl);
3154
+ ws = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
3159
3155
  } else if (auth.type === "token") {
3160
3156
  const headers = { Authorization: `Bearer ${auth.token}` };
3161
- ws = await connectToWebsocket(wsUrl, { headers });
3157
+ ws = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
3162
3158
  } else {
3163
3159
  throw new ProviderValidationError("Auth method not available", {
3164
3160
  check: "auth.type",
@@ -3409,6 +3405,7 @@ const handlerControllerFactory = (implementation) => (options) => {
3409
3405
  const cb = (ws) => {
3410
3406
  const state = { id: void 0 };
3411
3407
  const messageUUIDs = /* @__PURE__ */ new Set();
3408
+ const diagnostics = createDiagnosticReporter();
3412
3409
  const cannotRespondHandler = (err) => {
3413
3410
  strapi?.log?.error(
3414
3411
  "[Data transfer] Cannot send error response to client, closing connection"
@@ -3442,6 +3439,9 @@ const handlerControllerFactory = (implementation) => (options) => {
3442
3439
  set response(response) {
3443
3440
  state.response = response;
3444
3441
  },
3442
+ get diagnostics() {
3443
+ return diagnostics;
3444
+ },
3445
3445
  addUUID(uuid) {
3446
3446
  messageUUIDs.add(uuid);
3447
3447
  },
@@ -3557,6 +3557,10 @@ const handlerControllerFactory = (implementation) => (options) => {
3557
3557
  onError() {
3558
3558
  },
3559
3559
  onClose() {
3560
+ },
3561
+ onInfo() {
3562
+ },
3563
+ onWarning() {
3560
3564
  }
3561
3565
  };
3562
3566
  const handler = Object.assign(Object.create(prototype), implementation(prototype));
@@ -3589,6 +3593,14 @@ const handlerControllerFactory = (implementation) => (options) => {
3589
3593
  cannotRespondHandler(err);
3590
3594
  }
3591
3595
  });
3596
+ diagnostics.onDiagnostic((diagnostic2) => {
3597
+ const uuid = randomUUID();
3598
+ const payload = JSON.stringify({
3599
+ diagnostic: diagnostic2,
3600
+ uuid
3601
+ });
3602
+ handler.send(payload);
3603
+ });
3592
3604
  };
3593
3605
  try {
3594
3606
  handleWSUpgrade(wss, ctx, cb);
@@ -3624,6 +3636,26 @@ const createPushController = handlerControllerFactory((proto) => ({
3624
3636
  verifyAuth() {
3625
3637
  return proto.verifyAuth.call(this, TRANSFER_KIND$1);
3626
3638
  },
3639
+ onInfo(message) {
3640
+ this.diagnostics?.report({
3641
+ details: {
3642
+ message,
3643
+ origin: "push-handler",
3644
+ createdAt: /* @__PURE__ */ new Date()
3645
+ },
3646
+ kind: "info"
3647
+ });
3648
+ },
3649
+ onWarning(message) {
3650
+ this.diagnostics?.report({
3651
+ details: {
3652
+ message,
3653
+ createdAt: /* @__PURE__ */ new Date(),
3654
+ origin: "push-handler"
3655
+ },
3656
+ kind: "warning"
3657
+ });
3658
+ },
3627
3659
  cleanup() {
3628
3660
  proto.cleanup.call(this);
3629
3661
  this.streams = {};
@@ -3700,6 +3732,7 @@ const createPushController = handlerControllerFactory((proto) => ({
3700
3732
  proto.addUUID(uuid);
3701
3733
  if (type === "command") {
3702
3734
  const { command } = msg;
3735
+ this.onInfo(`received command:${command} uuid:${uuid}`);
3703
3736
  await this.executeAndRespond(uuid, () => {
3704
3737
  this.assertValidTransferCommand(command);
3705
3738
  if (command === "status") {
@@ -3708,6 +3741,7 @@ const createPushController = handlerControllerFactory((proto) => ({
3708
3741
  return this[command](msg.params);
3709
3742
  });
3710
3743
  } else if (type === "transfer") {
3744
+ this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
3711
3745
  await this.executeAndRespond(uuid, async () => {
3712
3746
  await this.verifyAuth();
3713
3747
  this.assertValidTransfer();
@@ -3809,6 +3843,9 @@ const createPushController = handlerControllerFactory((proto) => ({
3809
3843
  }
3810
3844
  this.flow?.set(step);
3811
3845
  }
3846
+ if (action === "bootstrap") {
3847
+ return this.provider?.[action](this.diagnostics);
3848
+ }
3812
3849
  return this.provider?.[action]();
3813
3850
  },
3814
3851
  async streamAsset(payload) {
@@ -3874,6 +3911,7 @@ const createPushController = handlerControllerFactory((proto) => ({
3874
3911
  getStrapi: () => strapi
3875
3912
  });
3876
3913
  this.provider.onWarning = (message) => {
3914
+ this.onWarning(message);
3877
3915
  strapi.log.warn(message);
3878
3916
  };
3879
3917
  return { transferID: this.transferID };
@@ -3914,6 +3952,26 @@ const createPullController = handlerControllerFactory((proto) => ({
3914
3952
  this.streams = {};
3915
3953
  delete this.provider;
3916
3954
  },
3955
+ onInfo(message) {
3956
+ this.diagnostics?.report({
3957
+ details: {
3958
+ message,
3959
+ origin: "pull-handler",
3960
+ createdAt: /* @__PURE__ */ new Date()
3961
+ },
3962
+ kind: "info"
3963
+ });
3964
+ },
3965
+ onWarning(message) {
3966
+ this.diagnostics?.report({
3967
+ details: {
3968
+ message,
3969
+ createdAt: /* @__PURE__ */ new Date(),
3970
+ origin: "pull-handler"
3971
+ },
3972
+ kind: "warning"
3973
+ });
3974
+ },
3917
3975
  assertValidTransferAction(action) {
3918
3976
  const validActions = VALID_TRANSFER_ACTIONS;
3919
3977
  if (validActions.includes(action)) {
@@ -3943,6 +4001,7 @@ const createPullController = handlerControllerFactory((proto) => ({
3943
4001
  proto.addUUID(uuid);
3944
4002
  if (type === "command") {
3945
4003
  const { command } = msg;
4004
+ this.onInfo(`received command:${command} uuid:${uuid}`);
3946
4005
  await this.executeAndRespond(uuid, () => {
3947
4006
  this.assertValidTransferCommand(command);
3948
4007
  if (command === "status") {
@@ -3951,6 +4010,7 @@ const createPullController = handlerControllerFactory((proto) => ({
3951
4010
  return this[command](msg.params);
3952
4011
  });
3953
4012
  } else if (type === "transfer") {
4013
+ this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
3954
4014
  await this.executeAndRespond(uuid, async () => {
3955
4015
  await this.verifyAuth();
3956
4016
  this.assertValidTransfer();
@@ -3972,6 +4032,9 @@ const createPullController = handlerControllerFactory((proto) => ({
3972
4032
  async onTransferAction(msg) {
3973
4033
  const { action } = msg;
3974
4034
  this.assertValidTransferAction(action);
4035
+ if (action === "bootstrap") {
4036
+ return this.provider?.[action](this.diagnostics);
4037
+ }
3975
4038
  return this.provider?.[action]();
3976
4039
  },
3977
4040
  async flush(stage, id) {
@@ -4183,7 +4246,7 @@ class LocalFileSourceProvider {
4183
4246
  details: {
4184
4247
  createdAt: /* @__PURE__ */ new Date(),
4185
4248
  message,
4186
- source: "file-source-provider"
4249
+ origin: "file-source-provider"
4187
4250
  },
4188
4251
  kind: "info"
4189
4252
  });
@@ -4274,9 +4337,7 @@ class LocalFileSourceProvider {
4274
4337
  try {
4275
4338
  metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
4276
4339
  } catch (error) {
4277
- console.warn(
4278
- ` Failed to read metadata for ${file}, Strapi will try to fix this issue automatically`
4279
- );
4340
+ throw new Error(`Failed to read metadata for ${file}`);
4280
4341
  }
4281
4342
  const asset = {
4282
4343
  metadata,
@@ -4464,7 +4525,7 @@ class LocalFileDestinationProvider {
4464
4525
  details: {
4465
4526
  createdAt: /* @__PURE__ */ new Date(),
4466
4527
  message,
4467
- source: "file-destination-provider"
4528
+ origin: "file-destination-provider"
4468
4529
  },
4469
4530
  kind: "info"
4470
4531
  });