@strapi/data-transfer 4.20.5 → 5.0.0-alpha.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 (45) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +170 -1104
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +171 -1100
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/strapi/providers/local-destination/strategies/restore/index.d.ts.map +1 -1
  8. package/dist/strapi/providers/local-source/assets.d.ts +1 -0
  9. package/dist/strapi/providers/local-source/assets.d.ts.map +1 -1
  10. package/dist/strapi/providers/local-source/configuration.d.ts +1 -0
  11. package/dist/strapi/providers/local-source/configuration.d.ts.map +1 -1
  12. package/dist/strapi/providers/local-source/entities.d.ts +1 -0
  13. package/dist/strapi/providers/local-source/entities.d.ts.map +1 -1
  14. package/dist/strapi/providers/local-source/links.d.ts +1 -0
  15. package/dist/strapi/providers/local-source/links.d.ts.map +1 -1
  16. package/dist/strapi/providers/remote-source/index.d.ts.map +1 -1
  17. package/dist/strapi/remote/handlers/utils.d.ts +1 -1
  18. package/dist/strapi/remote/handlers/utils.d.ts.map +1 -1
  19. package/dist/utils/components.d.ts +1 -4
  20. package/dist/utils/components.d.ts.map +1 -1
  21. package/dist/utils/encryption/decrypt.d.ts +1 -0
  22. package/dist/utils/encryption/decrypt.d.ts.map +1 -1
  23. package/dist/utils/encryption/encrypt.d.ts +1 -0
  24. package/dist/utils/encryption/encrypt.d.ts.map +1 -1
  25. package/package.json +12 -15
  26. package/dist/commands/commander.d.ts +0 -36
  27. package/dist/commands/commander.d.ts.map +0 -1
  28. package/dist/commands/data-transfer.d.ts +0 -63
  29. package/dist/commands/data-transfer.d.ts.map +0 -1
  30. package/dist/commands/export/action.d.ts +0 -21
  31. package/dist/commands/export/action.d.ts.map +0 -1
  32. package/dist/commands/export/command.d.ts +0 -9
  33. package/dist/commands/export/command.d.ts.map +0 -1
  34. package/dist/commands/helpers.d.ts +0 -31
  35. package/dist/commands/helpers.d.ts.map +0 -1
  36. package/dist/commands/import/action.d.ts +0 -20
  37. package/dist/commands/import/action.d.ts.map +0 -1
  38. package/dist/commands/import/command.d.ts +0 -9
  39. package/dist/commands/import/command.d.ts.map +0 -1
  40. package/dist/commands/index.d.ts +0 -4
  41. package/dist/commands/index.d.ts.map +0 -1
  42. package/dist/commands/transfer/action.d.ts +0 -19
  43. package/dist/commands/transfer/action.d.ts.map +0 -1
  44. package/dist/commands/transfer/command.d.ts +0 -9
  45. package/dist/commands/transfer/command.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -2,29 +2,22 @@ import { Transform, PassThrough, Writable, Readable, Duplex, pipeline } from "st
2
2
  import path, { extname, join, posix } from "path";
3
3
  import { EOL } from "os";
4
4
  import { chain } from "stream-chain";
5
- import { isArray, zip, isObject, uniq, isEqual, mapValues, pick, reject as reject$1, capitalize, isNumber, isEmpty, last, difference, set, omit, has, pipe, assign, map as map$1, size, isNil, clone, get, once, castArray, keyBy, isString, isNaN, merge, isFinite, toNumber } from "lodash/fp";
5
+ import { isArray, zip, isObject, uniq, isEqual, mapValues, pick, reject as reject$1, capitalize, isNumber, isEmpty, last, difference, set, omit, has, pipe, assign, map as map$1, size, isNil, clone, get, once, castArray, keyBy } from "lodash/fp";
6
6
  import { diff as diff$1 } from "semver";
7
7
  import { scryptSync, createCipheriv, createDecipheriv, randomUUID } from "crypto";
8
8
  import { EventEmitter } from "events";
9
9
  import * as fse from "fs-extra";
10
10
  import fse__default, { createReadStream, stat, createWriteStream, rm } from "fs-extra";
11
11
  import _ from "lodash";
12
- import { contentTypes, mapAsync } from "@strapi/utils";
12
+ import { contentTypes, async } from "@strapi/utils";
13
13
  import chalk from "chalk";
14
- import https from "https";
15
- import http from "http";
14
+ import * as webStream from "stream/web";
16
15
  import { WebSocket } from "ws";
17
16
  import zip$1 from "zlib";
18
17
  import tar from "tar";
19
18
  import { parser } from "stream-json/jsonl/Parser";
20
19
  import tar$1 from "tar-stream";
21
20
  import { stringer } from "stream-json/jsonl/Stringer";
22
- import { Option, InvalidOptionArgumentError } from "commander";
23
- import Table from "cli-table3";
24
- import { createLogger, configs } from "@strapi/logger";
25
- import strapiFactory from "@strapi/strapi";
26
- import ora from "ora";
27
- import inquirer from "inquirer";
28
21
  const getEncryptionStrategy = (algorithm) => {
29
22
  const strategies2 = {
30
23
  "aes-128-ecb"(key) {
@@ -89,7 +82,7 @@ const getDecryptionStrategy = (algorithm) => {
89
82
  const createDecryptionCipher = (key, algorithm = "aes-128-ecb") => {
90
83
  return getDecryptionStrategy(algorithm)(key);
91
84
  };
92
- const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
85
+ const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
93
86
  __proto__: null,
94
87
  createDecryptionCipher,
95
88
  createEncryptionCipher
@@ -301,9 +294,9 @@ const middleware = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
301
294
  __proto__: null,
302
295
  runMiddleware
303
296
  }, Symbol.toStringTag, { value: "Module" }));
304
- const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
297
+ const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
305
298
  __proto__: null,
306
- encryption: index$7,
299
+ encryption: index$9,
307
300
  json,
308
301
  middleware,
309
302
  schema,
@@ -366,11 +359,11 @@ class TransferEngineError extends DataTransferError {
366
359
  super("engine", severity, message, details);
367
360
  }
368
361
  }
369
- let TransferEngineInitializationError$1 = class TransferEngineInitializationError extends TransferEngineError {
362
+ class TransferEngineInitializationError extends TransferEngineError {
370
363
  constructor(message) {
371
364
  super(SeverityKind.FATAL, message, { step: "initialization" });
372
365
  }
373
- };
366
+ }
374
367
  class TransferEngineValidationError extends TransferEngineError {
375
368
  constructor(message, details) {
376
369
  super(SeverityKind.FATAL, message, { step: "validation", details });
@@ -384,7 +377,7 @@ class TransferEngineTransferError extends TransferEngineError {
384
377
  const errors = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
385
378
  __proto__: null,
386
379
  TransferEngineError,
387
- TransferEngineInitializationError: TransferEngineInitializationError$1,
380
+ TransferEngineInitializationError,
388
381
  TransferEngineTransferError,
389
382
  TransferEngineValidationError
390
383
  }, Symbol.toStringTag, { value: "Module" }));
@@ -496,8 +489,8 @@ const TransferGroupPresets = {
496
489
  configuration: true
497
490
  }
498
491
  };
499
- const DEFAULT_VERSION_STRATEGY$1 = "ignore";
500
- const DEFAULT_SCHEMA_STRATEGY$1 = "strict";
492
+ const DEFAULT_VERSION_STRATEGY = "ignore";
493
+ const DEFAULT_SCHEMA_STRATEGY = "strict";
501
494
  class TransferEngine {
502
495
  sourceProvider;
503
496
  destinationProvider;
@@ -690,7 +683,7 @@ class TransferEngine {
690
683
  * If there is a mismatch, throws a validation error.
691
684
  */
692
685
  #assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
693
- const strategy = this.options.versionStrategy || DEFAULT_VERSION_STRATEGY$1;
686
+ const strategy = this.options.versionStrategy || DEFAULT_VERSION_STRATEGY;
694
687
  const reject2 = () => {
695
688
  throw new TransferEngineValidationError(
696
689
  `The source and destination provide are targeting incompatible Strapi versions (using the "${strategy}" strategy). The source (${this.sourceProvider.name}) version is ${sourceVersion} and the destination (${this.destinationProvider.name}) version is ${destinationVersion}`,
@@ -733,7 +726,7 @@ class TransferEngine {
733
726
  * If there are differences and/or incompatibilities between source and destination schemas, then throw a validation error.
734
727
  */
735
728
  #assertSchemasMatching(sourceSchemas, destinationSchemas) {
736
- const strategy = this.options.schemaStrategy || DEFAULT_SCHEMA_STRATEGY$1;
729
+ const strategy = this.options.schemaStrategy || DEFAULT_SCHEMA_STRATEGY;
737
730
  if (strategy === "ignore") {
738
731
  return;
739
732
  }
@@ -1110,16 +1103,16 @@ ${formattedDiffs}`,
1110
1103
  await this.#transferStage({ stage, source, destination, transform, tracker });
1111
1104
  }
1112
1105
  }
1113
- const createTransferEngine$2 = (sourceProvider, destinationProvider, options) => {
1106
+ const createTransferEngine = (sourceProvider, destinationProvider, options) => {
1114
1107
  return new TransferEngine(sourceProvider, destinationProvider, options);
1115
1108
  };
1116
- const engineDatatransfer = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1109
+ const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1117
1110
  __proto__: null,
1118
- DEFAULT_SCHEMA_STRATEGY: DEFAULT_SCHEMA_STRATEGY$1,
1119
- DEFAULT_VERSION_STRATEGY: DEFAULT_VERSION_STRATEGY$1,
1111
+ DEFAULT_SCHEMA_STRATEGY,
1112
+ DEFAULT_VERSION_STRATEGY,
1120
1113
  TRANSFER_STAGES,
1121
1114
  TransferGroupPresets,
1122
- createTransferEngine: createTransferEngine$2,
1115
+ createTransferEngine,
1123
1116
  errors
1124
1117
  }, Symbol.toStringTag, { value: "Module" }));
1125
1118
  const isDialectMySQL = () => strapi.db?.dialect.client === "mysql";
@@ -1149,7 +1142,7 @@ const createComponents = async (uid, data) => {
1149
1142
  if (!Array.isArray(componentValue)) {
1150
1143
  throw new Error("Expected an array to create repeatable component");
1151
1144
  }
1152
- const components = await mapAsync(
1145
+ const components = await async.map(
1153
1146
  componentValue,
1154
1147
  (value) => createComponent(componentUID, value),
1155
1148
  { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }
@@ -1193,7 +1186,7 @@ const createComponents = async (uid, data) => {
1193
1186
  }
1194
1187
  };
1195
1188
  };
1196
- componentBody[attributeName] = await mapAsync(
1189
+ componentBody[attributeName] = await async.map(
1197
1190
  dynamiczoneValues,
1198
1191
  createDynamicZoneComponents,
1199
1192
  { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }
@@ -1208,7 +1201,7 @@ const getComponents = async (uid, entity2) => {
1208
1201
  if (_.isEmpty(componentAttributes)) {
1209
1202
  return {};
1210
1203
  }
1211
- return strapi.query(uid).load(entity2, componentAttributes);
1204
+ return strapi.db.query(uid).load(entity2, componentAttributes);
1212
1205
  };
1213
1206
  const deleteComponents = async (uid, entityToDelete, { loadComponents = true } = {}) => {
1214
1207
  const { attributes = {} } = strapi.getModel(uid);
@@ -1218,7 +1211,7 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
1218
1211
  if (attribute.type === "component" || attribute.type === "dynamiczone") {
1219
1212
  let value;
1220
1213
  if (loadComponents) {
1221
- value = await strapi.query(uid).load(entityToDelete, attributeName);
1214
+ value = await strapi.db.query(uid).load(entityToDelete, attributeName);
1222
1215
  } else {
1223
1216
  value = entityToDelete[attributeName];
1224
1217
  }
@@ -1227,7 +1220,7 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
1227
1220
  }
1228
1221
  if (attribute.type === "component") {
1229
1222
  const { component: componentUID } = attribute;
1230
- await mapAsync(
1223
+ await async.map(
1231
1224
  _.castArray(value),
1232
1225
  (subValue) => deleteComponent(componentUID, subValue),
1233
1226
  {
@@ -1235,7 +1228,7 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
1235
1228
  }
1236
1229
  );
1237
1230
  } else {
1238
- await mapAsync(
1231
+ await async.map(
1239
1232
  _.castArray(value),
1240
1233
  (subValue) => deleteComponent(subValue.__component, subValue),
1241
1234
  { concurrency: isDialectMySQL() && !strapi.db?.inTransaction() ? 1 : Infinity }
@@ -1256,11 +1249,11 @@ const createComponent = async (uid, data) => {
1256
1249
  // ... and assign the newly created component instead
1257
1250
  assign(componentData)
1258
1251
  );
1259
- return strapi.query(uid).create({ data: transform(data) });
1252
+ return strapi.db.query(uid).create({ data: transform(data) });
1260
1253
  };
1261
1254
  const deleteComponent = async (uid, componentToDelete) => {
1262
1255
  await deleteComponents(uid, componentToDelete);
1263
- await strapi.query(uid).delete({ where: { id: componentToDelete.id } });
1256
+ await strapi.db.query(uid).delete({ where: { id: componentToDelete.id } });
1264
1257
  };
1265
1258
  const sanitizeComponentLikeAttributes = (model, data) => {
1266
1259
  const { attributes } = model;
@@ -1612,7 +1605,7 @@ const link = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
1612
1605
  __proto__: null,
1613
1606
  createLinkQuery
1614
1607
  }, Symbol.toStringTag, { value: "Module" }));
1615
- const index$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1608
+ const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1616
1609
  __proto__: null,
1617
1610
  entity,
1618
1611
  link
@@ -1691,7 +1684,7 @@ const restoreCoreStore = async (strapi2, values) => {
1691
1684
  };
1692
1685
  const restoreWebhooks = async (strapi2, values) => {
1693
1686
  const data = omitInvalidCreationAttributes(values);
1694
- return strapi2.db.query("webhook").create({ data });
1687
+ return strapi2.db.query("strapi::webhook").create({ data });
1695
1688
  };
1696
1689
  const restoreConfigs = async (strapi2, config) => {
1697
1690
  if (config.type === "core-store") {
@@ -1779,10 +1772,8 @@ const deleteRecords = async (strapi2, options) => {
1779
1772
  };
1780
1773
  const deleteEntitiesRecords = async (strapi2, options = {}) => {
1781
1774
  const { entities } = options;
1782
- const query = createEntityQuery(strapi2);
1783
- const contentTypes2 = Object.values(
1784
- strapi2.contentTypes
1785
- );
1775
+ const models = strapi2.get("models").get();
1776
+ const contentTypes2 = Object.values(strapi2.contentTypes);
1786
1777
  const contentTypesToClear = contentTypes2.filter((contentType) => {
1787
1778
  let removeThisContentType = true;
1788
1779
  if (entities?.include) {
@@ -1795,17 +1786,35 @@ const deleteEntitiesRecords = async (strapi2, options = {}) => {
1795
1786
  removeThisContentType = entities.filters.every((filter2) => filter2(contentType));
1796
1787
  }
1797
1788
  return removeThisContentType;
1789
+ }).map((contentType) => contentType.uid);
1790
+ const modelsToClear = models.filter((model) => {
1791
+ if (contentTypesToClear.includes(model.uid)) {
1792
+ return false;
1793
+ }
1794
+ let removeThisModel = true;
1795
+ if (entities?.include) {
1796
+ removeThisModel = entities.include.includes(model.uid);
1797
+ }
1798
+ if (entities?.exclude && entities.exclude.includes(model.uid)) {
1799
+ removeThisModel = false;
1800
+ }
1801
+ return removeThisModel;
1802
+ }).map((model) => model.uid);
1803
+ const [results, updateResults] = useResults([...contentTypesToClear, ...modelsToClear]);
1804
+ const contentTypeQuery = createEntityQuery(strapi2);
1805
+ const contentTypePromises = contentTypesToClear.map(async (uid) => {
1806
+ const result = await contentTypeQuery(uid).deleteMany(entities?.params);
1807
+ if (result) {
1808
+ updateResults(result.count || 0, uid);
1809
+ }
1798
1810
  });
1799
- const [results, updateResults] = useResults(
1800
- contentTypesToClear.map((contentType) => contentType.uid)
1801
- );
1802
- const deletePromises = contentTypesToClear.map(async (contentType) => {
1803
- const result = await query(contentType.uid).deleteMany(entities?.params);
1811
+ const modelsPromises = modelsToClear.map(async (uid) => {
1812
+ const result = await strapi2.db.query(uid).deleteMany({});
1804
1813
  if (result) {
1805
- updateResults(result.count || 0, contentType.uid);
1814
+ updateResults(result.count || 0, uid);
1806
1815
  }
1807
1816
  });
1808
- await Promise.all(deletePromises);
1817
+ await Promise.all([...contentTypePromises, ...modelsPromises]);
1809
1818
  return results;
1810
1819
  };
1811
1820
  const deleteConfigurationRecords = async (strapi2, options = {}) => {
@@ -1815,7 +1824,7 @@ const deleteConfigurationRecords = async (strapi2, options = {}) => {
1815
1824
  models.push("strapi::core-store");
1816
1825
  }
1817
1826
  if (webhook) {
1818
- models.push("webhook");
1827
+ models.push("strapi::webhook");
1819
1828
  }
1820
1829
  const [results, updateResults] = useResults(models);
1821
1830
  const deletePromises = models.map(async (uid) => {
@@ -1849,7 +1858,7 @@ const assertValidStrapi = (strapi2, msg = "") => {
1849
1858
  }
1850
1859
  };
1851
1860
  const VALID_CONFLICT_STRATEGIES = ["restore"];
1852
- const DEFAULT_CONFLICT_STRATEGY$1 = "restore";
1861
+ const DEFAULT_CONFLICT_STRATEGY = "restore";
1853
1862
  class LocalStrapiDestinationProvider {
1854
1863
  name = "destination::local-strapi";
1855
1864
  type = "destination";
@@ -1916,10 +1925,10 @@ class LocalStrapiDestinationProvider {
1916
1925
  return;
1917
1926
  }
1918
1927
  const stream2 = this.strapi.db.queryBuilder("plugin::upload.file").select("*").transacting(trx).stream();
1919
- for await (const file2 of stream2) {
1920
- await this.strapi.plugin("upload").provider.delete(file2);
1921
- if (file2.formats) {
1922
- for (const fileFormat of Object.values(file2.formats)) {
1928
+ for await (const file of stream2) {
1929
+ await this.strapi.plugin("upload").provider.delete(file);
1930
+ if (file.formats) {
1931
+ for (const fileFormat of Object.values(file.formats)) {
1923
1932
  await this.strapi.plugin("upload").provider.delete(fileFormat);
1924
1933
  }
1925
1934
  }
@@ -1990,7 +1999,7 @@ class LocalStrapiDestinationProvider {
1990
1999
  if (!this.#areAssetsIncluded()) {
1991
2000
  return;
1992
2001
  }
1993
- if (this.strapi.config.get("plugin.upload").provider === "local") {
2002
+ if (this.strapi.config.get("plugin::upload").provider === "local") {
1994
2003
  const assetsDirectory = path.join(this.strapi.dirs.static.public, "uploads");
1995
2004
  const backupDirectory = path.join(
1996
2005
  this.strapi.dirs.static.public,
@@ -2022,7 +2031,7 @@ class LocalStrapiDestinationProvider {
2022
2031
  if (!this.#areAssetsIncluded()) {
2023
2032
  return;
2024
2033
  }
2025
- if (this.strapi.config.get("plugin.upload").provider === "local") {
2034
+ if (this.strapi.config.get("plugin::upload").provider === "local") {
2026
2035
  assertValidStrapi(this.strapi);
2027
2036
  const backupDirectory = path.join(
2028
2037
  this.strapi.dirs.static.public,
@@ -2083,7 +2092,7 @@ class LocalStrapiDestinationProvider {
2083
2092
  stream: Readable.from(chunk.stream),
2084
2093
  buffer: chunk?.buffer
2085
2094
  };
2086
- const provider = strapi2.config.get("plugin.upload").provider;
2095
+ const provider = strapi2.config.get("plugin::upload").provider;
2087
2096
  try {
2088
2097
  await strapi2.plugin("upload").provider.uploadStream(uploadData);
2089
2098
  if (!restoreMediaEntitiesContent) {
@@ -2154,7 +2163,7 @@ class LocalStrapiDestinationProvider {
2154
2163
  });
2155
2164
  }
2156
2165
  }
2157
- const createLocalStrapiDestinationProvider$2 = (options) => {
2166
+ const createLocalStrapiDestinationProvider = (options) => {
2158
2167
  return new LocalStrapiDestinationProvider(options);
2159
2168
  };
2160
2169
  const createEntitiesStream = (strapi2) => {
@@ -2218,7 +2227,7 @@ const createConfigurationStream = (strapi2) => {
2218
2227
  wrapConfigurationItem("core-store")
2219
2228
  ]);
2220
2229
  const webhooksStream = chain([
2221
- strapi2.db.queryBuilder("webhook").stream(),
2230
+ strapi2.db.queryBuilder("strapi::webhook").stream(),
2222
2231
  wrapConfigurationItem("webhook")
2223
2232
  ]);
2224
2233
  const streams = [coreStoreStream, webhooksStream];
@@ -2234,44 +2243,42 @@ const wrapConfigurationItem = (type) => (value) => ({
2234
2243
  type,
2235
2244
  value
2236
2245
  });
2237
- const protocolForPath = (filepath) => {
2238
- return filepath?.startsWith("https") ? https : http;
2239
- };
2240
- function getFileStream(filepath, isLocal = false) {
2246
+ function getFileStream(filepath, strapi2, isLocal = false) {
2241
2247
  if (isLocal) {
2242
2248
  return createReadStream(filepath);
2243
2249
  }
2244
2250
  const readableStream = new PassThrough();
2245
- protocolForPath(filepath).get(filepath, (res) => {
2246
- if (res.statusCode !== 200) {
2247
- readableStream.emit(
2248
- "error",
2249
- new Error(`Request failed with status code ${res.statusCode}`)
2250
- );
2251
+ strapi2.fetch(filepath).then((res) => {
2252
+ if (res.status !== 200) {
2253
+ readableStream.emit("error", new Error(`Request failed with status code ${res.status}`));
2251
2254
  return;
2252
2255
  }
2253
- res.pipe(readableStream);
2254
- }).on("error", (error) => {
2256
+ if (res.body) {
2257
+ Readable.fromWeb(new webStream.ReadableStream(res.body)).pipe(readableStream);
2258
+ } else {
2259
+ readableStream.emit("error", new Error("Empty data found for file"));
2260
+ }
2261
+ }).catch((error) => {
2255
2262
  readableStream.emit("error", error);
2256
2263
  });
2257
2264
  return readableStream;
2258
2265
  }
2259
- function getFileStats(filepath, isLocal = false) {
2266
+ function getFileStats(filepath, strapi2, isLocal = false) {
2260
2267
  if (isLocal) {
2261
2268
  return stat(filepath);
2262
2269
  }
2263
2270
  return new Promise((resolve, reject2) => {
2264
- protocolForPath(filepath).get(filepath, (res) => {
2265
- if (res.statusCode !== 200) {
2266
- reject2(new Error(`Request failed with status code ${res.statusCode}`));
2271
+ strapi2.fetch(filepath).then((res) => {
2272
+ if (res.status !== 200) {
2273
+ reject2(new Error(`Request failed with status code ${res.status}`));
2267
2274
  return;
2268
2275
  }
2269
- const contentLength = res.headers["content-length"];
2276
+ const contentLength = res.headers.get("content-length");
2270
2277
  const stats = {
2271
2278
  size: contentLength ? parseInt(contentLength, 10) : 0
2272
2279
  };
2273
2280
  resolve(stats);
2274
- }).on("error", (error) => {
2281
+ }).catch((error) => {
2275
2282
  reject2(error);
2276
2283
  });
2277
2284
  });
@@ -2279,25 +2286,25 @@ function getFileStats(filepath, isLocal = false) {
2279
2286
  const createAssetsStream = (strapi2) => {
2280
2287
  const generator = async function* () {
2281
2288
  const stream2 = strapi2.db.queryBuilder("plugin::upload.file").select("*").stream();
2282
- for await (const file2 of stream2) {
2283
- const isLocalProvider = file2.provider === "local";
2284
- const filepath = isLocalProvider ? join(strapi2.dirs.static.public, file2.url) : file2.url;
2285
- const stats = await getFileStats(filepath, isLocalProvider);
2286
- const stream22 = getFileStream(filepath, isLocalProvider);
2289
+ for await (const file of stream2) {
2290
+ const isLocalProvider = file.provider === "local";
2291
+ const filepath = isLocalProvider ? join(strapi2.dirs.static.public, file.url) : file.url;
2292
+ const stats = await getFileStats(filepath, strapi2, isLocalProvider);
2293
+ const stream22 = getFileStream(filepath, strapi2, isLocalProvider);
2287
2294
  yield {
2288
- metadata: file2,
2295
+ metadata: file,
2289
2296
  filepath,
2290
- filename: file2.hash + file2.ext,
2297
+ filename: file.hash + file.ext,
2291
2298
  stream: stream22,
2292
2299
  stats: { size: stats.size }
2293
2300
  };
2294
- if (file2.formats) {
2295
- for (const format of Object.keys(file2.formats)) {
2296
- const fileFormat = file2.formats[format];
2301
+ if (file.formats) {
2302
+ for (const format of Object.keys(file.formats)) {
2303
+ const fileFormat = file.formats[format];
2297
2304
  const fileFormatFilepath = isLocalProvider ? join(strapi2.dirs.static.public, fileFormat.url) : fileFormat.url;
2298
- const fileFormatStats = await getFileStats(fileFormatFilepath, isLocalProvider);
2299
- const fileFormatStream = getFileStream(fileFormatFilepath, isLocalProvider);
2300
- const metadata = { ...fileFormat, type: format, id: file2.id, mainHash: file2.hash };
2305
+ const fileFormatStats = await getFileStats(fileFormatFilepath, strapi2, isLocalProvider);
2306
+ const fileFormatStream = getFileStream(fileFormatFilepath, strapi2, isLocalProvider);
2307
+ const metadata = { ...fileFormat, type: format, id: file.id, mainHash: file.hash };
2301
2308
  yield {
2302
2309
  metadata,
2303
2310
  filepath: fileFormatFilepath,
@@ -2311,7 +2318,7 @@ const createAssetsStream = (strapi2) => {
2311
2318
  };
2312
2319
  return Duplex.from(generator());
2313
2320
  };
2314
- const createLocalStrapiSourceProvider$2 = (options) => {
2321
+ const createLocalStrapiSourceProvider = (options) => {
2315
2322
  return new LocalStrapiSourceProvider(options);
2316
2323
  };
2317
2324
  class LocalStrapiSourceProvider {
@@ -2439,8 +2446,8 @@ const createDispatcher = (ws, retryMessageOptions = {
2439
2446
  const dispatchCommand = (payload) => {
2440
2447
  return dispatch({ type: "command", ...payload });
2441
2448
  };
2442
- const dispatchTransferAction = async (action2) => {
2443
- const payload = { type: "transfer", kind: "action", action: action2 };
2449
+ const dispatchTransferAction = async (action) => {
2450
+ const payload = { type: "transfer", kind: "action", action };
2444
2451
  return dispatch(payload, { attachTransfer: true }) ?? Promise.resolve(null);
2445
2452
  };
2446
2453
  const dispatchTransferStep = async (payload) => {
@@ -2774,7 +2781,7 @@ class RemoteStrapiDestinationProvider {
2774
2781
  });
2775
2782
  }
2776
2783
  }
2777
- const createRemoteStrapiDestinationProvider$1 = (options) => {
2784
+ const createRemoteStrapiDestinationProvider = (options) => {
2778
2785
  return new RemoteStrapiDestinationProvider(options);
2779
2786
  };
2780
2787
  class RemoteStrapiSourceProvider {
@@ -2846,15 +2853,15 @@ class RemoteStrapiSourceProvider {
2846
2853
  const pass = new PassThrough({ objectMode: true });
2847
2854
  stream2.on("data", async (payload) => {
2848
2855
  for (const item of payload) {
2849
- const { action: action2 } = item;
2850
- if (action2 === "start") {
2856
+ const { action } = item;
2857
+ if (action === "start") {
2851
2858
  assets[item.assetID] = { ...item.data, stream: new PassThrough() };
2852
2859
  await this.writeAsync(pass, assets[item.assetID]);
2853
- } else if (action2 === "stream") {
2860
+ } else if (action === "stream") {
2854
2861
  const rawBuffer = item.data;
2855
2862
  const chunk = Buffer.from(rawBuffer.data);
2856
2863
  await this.writeAsync(assets[item.assetID].stream, chunk);
2857
- } else if (action2 === "end") {
2864
+ } else if (action === "end") {
2858
2865
  await new Promise((resolve, reject2) => {
2859
2866
  const { stream: assetStream } = assets[item.assetID];
2860
2867
  assetStream.on("close", () => {
@@ -2982,17 +2989,17 @@ class RemoteStrapiSourceProvider {
2982
2989
  return null;
2983
2990
  }
2984
2991
  }
2985
- const createRemoteStrapiSourceProvider$1 = (options) => {
2992
+ const createRemoteStrapiSourceProvider = (options) => {
2986
2993
  return new RemoteStrapiSourceProvider(options);
2987
2994
  };
2988
- const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2995
+ const index$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2989
2996
  __proto__: null,
2990
- DEFAULT_CONFLICT_STRATEGY: DEFAULT_CONFLICT_STRATEGY$1,
2997
+ DEFAULT_CONFLICT_STRATEGY,
2991
2998
  VALID_CONFLICT_STRATEGIES,
2992
- createLocalStrapiDestinationProvider: createLocalStrapiDestinationProvider$2,
2993
- createLocalStrapiSourceProvider: createLocalStrapiSourceProvider$2,
2994
- createRemoteStrapiDestinationProvider: createRemoteStrapiDestinationProvider$1,
2995
- createRemoteStrapiSourceProvider: createRemoteStrapiSourceProvider$1
2999
+ createLocalStrapiDestinationProvider,
3000
+ createLocalStrapiSourceProvider,
3001
+ createRemoteStrapiDestinationProvider,
3002
+ createRemoteStrapiSourceProvider
2996
3003
  }, Symbol.toStringTag, { value: "Module" }));
2997
3004
  const DEFAULT_TRANSFER_FLOW = [
2998
3005
  {
@@ -3199,9 +3206,9 @@ const handlerControllerFactory = (implementation) => (options) => {
3199
3206
  throw new Error("Invalid Transfer Process");
3200
3207
  }
3201
3208
  },
3202
- assertValidTransferCommand(command2) {
3203
- const isDefined = typeof this[command2] === "function";
3204
- const isValidTransferCommand = VALID_TRANSFER_COMMANDS.includes(command2);
3209
+ assertValidTransferCommand(command) {
3210
+ const isDefined = typeof this[command] === "function";
3211
+ const isValidTransferCommand = VALID_TRANSFER_COMMANDS.includes(command);
3205
3212
  if (!isDefined || !isValidTransferCommand) {
3206
3213
  throw new Error("Invalid transfer command");
3207
3214
  }
@@ -3385,12 +3392,12 @@ const createPushController = handlerControllerFactory((proto) => ({
3385
3392
  throw new Error("Invalid Transfer Process");
3386
3393
  }
3387
3394
  },
3388
- assertValidTransferAction(action2) {
3389
- if (VALID_TRANSFER_ACTIONS$1.includes(action2)) {
3395
+ assertValidTransferAction(action) {
3396
+ if (VALID_TRANSFER_ACTIONS$1.includes(action)) {
3390
3397
  return;
3391
3398
  }
3392
- throw new ProviderTransferError(`Invalid action provided: "${action2}"`, {
3393
- action: action2,
3399
+ throw new ProviderTransferError(`Invalid action provided: "${action}"`, {
3400
+ action,
3394
3401
  validActions: Object.keys(VALID_TRANSFER_ACTIONS$1)
3395
3402
  });
3396
3403
  },
@@ -3441,13 +3448,13 @@ const createPushController = handlerControllerFactory((proto) => ({
3441
3448
  const { uuid, type } = msg;
3442
3449
  proto.addUUID(uuid);
3443
3450
  if (type === "command") {
3444
- const { command: command2 } = msg;
3451
+ const { command } = msg;
3445
3452
  await this.executeAndRespond(uuid, () => {
3446
- this.assertValidTransferCommand(command2);
3447
- if (command2 === "status") {
3453
+ this.assertValidTransferCommand(command);
3454
+ if (command === "status") {
3448
3455
  return this.status();
3449
3456
  }
3450
- return this[command2](msg.params);
3457
+ return this[command](msg.params);
3451
3458
  });
3452
3459
  } else if (type === "transfer") {
3453
3460
  await this.executeAndRespond(uuid, async () => {
@@ -3532,19 +3539,19 @@ const createPushController = handlerControllerFactory((proto) => ({
3532
3539
  }
3533
3540
  },
3534
3541
  async onTransferAction(msg) {
3535
- const { action: action2 } = msg;
3536
- this.assertValidTransferAction(action2);
3537
- const step = { kind: "action", action: action2 };
3542
+ const { action } = msg;
3543
+ this.assertValidTransferAction(action);
3544
+ const step = { kind: "action", action };
3538
3545
  const isStepRegistered = this.flow?.has(step);
3539
3546
  if (isStepRegistered) {
3540
3547
  if (this.flow?.cannot(step)) {
3541
- throw new ProviderTransferError(`Invalid action "${action2}" found for the current flow `, {
3542
- action: action2
3548
+ throw new ProviderTransferError(`Invalid action "${action}" found for the current flow `, {
3549
+ action
3543
3550
  });
3544
3551
  }
3545
3552
  this.flow?.set(step);
3546
3553
  }
3547
- return this.provider?.[action2]();
3554
+ return this.provider?.[action]();
3548
3555
  },
3549
3556
  async streamAsset(payload) {
3550
3557
  const assetsStream = this.streams?.assets;
@@ -3553,20 +3560,20 @@ const createPushController = handlerControllerFactory((proto) => ({
3553
3560
  return;
3554
3561
  }
3555
3562
  for (const item of payload) {
3556
- const { action: action2, assetID } = item;
3563
+ const { action, assetID } = item;
3557
3564
  if (!assetsStream) {
3558
3565
  throw new Error("Stream not defined");
3559
3566
  }
3560
- if (action2 === "start") {
3567
+ if (action === "start") {
3561
3568
  this.assets[assetID] = { ...item.data, stream: new PassThrough() };
3562
3569
  writeAsync(assetsStream, this.assets[assetID]);
3563
3570
  }
3564
- if (action2 === "stream") {
3571
+ if (action === "stream") {
3565
3572
  const rawBuffer = item.data;
3566
3573
  const chunk = Buffer.from(rawBuffer.data);
3567
3574
  await writeAsync(this.assets[assetID].stream, chunk);
3568
3575
  }
3569
- if (action2 === "end") {
3576
+ if (action === "end") {
3570
3577
  await new Promise((resolve, reject2) => {
3571
3578
  const { stream: assetStream } = this.assets[assetID];
3572
3579
  assetStream.on("close", () => {
@@ -3595,7 +3602,7 @@ const createPushController = handlerControllerFactory((proto) => ({
3595
3602
  this.assets = {};
3596
3603
  this.streams = {};
3597
3604
  this.flow = createFlow(DEFAULT_TRANSFER_FLOW);
3598
- this.provider = createLocalStrapiDestinationProvider$2({
3605
+ this.provider = createLocalStrapiDestinationProvider({
3599
3606
  ...params.options,
3600
3607
  autoDestroy: false,
3601
3608
  getStrapi: () => strapi
@@ -3641,13 +3648,13 @@ const createPullController = handlerControllerFactory((proto) => ({
3641
3648
  this.streams = {};
3642
3649
  delete this.provider;
3643
3650
  },
3644
- assertValidTransferAction(action2) {
3651
+ assertValidTransferAction(action) {
3645
3652
  const validActions = VALID_TRANSFER_ACTIONS;
3646
- if (validActions.includes(action2)) {
3653
+ if (validActions.includes(action)) {
3647
3654
  return;
3648
3655
  }
3649
- throw new ProviderTransferError(`Invalid action provided: "${action2}"`, {
3650
- action: action2,
3656
+ throw new ProviderTransferError(`Invalid action provided: "${action}"`, {
3657
+ action,
3651
3658
  validActions: Object.keys(VALID_TRANSFER_ACTIONS)
3652
3659
  });
3653
3660
  },
@@ -3669,13 +3676,13 @@ const createPullController = handlerControllerFactory((proto) => ({
3669
3676
  const { uuid, type } = msg;
3670
3677
  proto.addUUID(uuid);
3671
3678
  if (type === "command") {
3672
- const { command: command2 } = msg;
3679
+ const { command } = msg;
3673
3680
  await this.executeAndRespond(uuid, () => {
3674
- this.assertValidTransferCommand(command2);
3675
- if (command2 === "status") {
3681
+ this.assertValidTransferCommand(command);
3682
+ if (command === "status") {
3676
3683
  return this.status();
3677
3684
  }
3678
- return this[command2](msg.params);
3685
+ return this[command](msg.params);
3679
3686
  });
3680
3687
  } else if (type === "transfer") {
3681
3688
  await this.executeAndRespond(uuid, async () => {
@@ -3697,9 +3704,9 @@ const createPullController = handlerControllerFactory((proto) => ({
3697
3704
  }
3698
3705
  },
3699
3706
  async onTransferAction(msg) {
3700
- const { action: action2 } = msg;
3701
- this.assertValidTransferAction(action2);
3702
- return this.provider?.[action2]();
3707
+ const { action } = msg;
3708
+ this.assertValidTransferAction(action);
3709
+ return this.provider?.[action]();
3703
3710
  },
3704
3711
  async flush(stage, id) {
3705
3712
  const batchSize = 1024 * 1024;
@@ -3746,8 +3753,8 @@ const createPullController = handlerControllerFactory((proto) => ({
3746
3753
  }
3747
3754
  },
3748
3755
  async onTransferStep(msg) {
3749
- const { step, action: action2 } = msg;
3750
- if (action2 === "start") {
3756
+ const { step, action } = msg;
3757
+ if (action === "start") {
3751
3758
  if (this.streams?.[step] instanceof Readable) {
3752
3759
  throw new Error("Stream already created, something went wrong");
3753
3760
  }
@@ -3756,7 +3763,7 @@ const createPullController = handlerControllerFactory((proto) => ({
3756
3763
  this.flush(step, flushUUID);
3757
3764
  return { ok: true, id: flushUUID };
3758
3765
  }
3759
- if (action2 === "end") {
3766
+ if (action === "end") {
3760
3767
  const stream2 = this.streams?.[step];
3761
3768
  if (stream2?.readableEnded === false) {
3762
3769
  await new Promise((resolve) => {
@@ -3828,7 +3835,7 @@ const createPullController = handlerControllerFactory((proto) => ({
3828
3835
  this.transferID = randomUUID();
3829
3836
  this.startedAt = Date.now();
3830
3837
  this.streams = {};
3831
- this.provider = createLocalStrapiSourceProvider$2({
3838
+ this.provider = createLocalStrapiSourceProvider({
3832
3839
  autoDestroy: false,
3833
3840
  getStrapi: () => strapi
3834
3841
  });
@@ -3856,22 +3863,22 @@ const createPullController = handlerControllerFactory((proto) => ({
3856
3863
  return { active: false, kind: null, elapsed: null, startedAt: null };
3857
3864
  }
3858
3865
  }));
3859
- const index$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3866
+ const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3860
3867
  __proto__: null,
3861
3868
  createPullController,
3862
3869
  createPushController,
3863
3870
  handlerControllerFactory
3864
3871
  }, Symbol.toStringTag, { value: "Module" }));
3865
- const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3872
+ const index$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3866
3873
  __proto__: null,
3867
3874
  constants,
3868
- handlers: index$3
3875
+ handlers: index$4
3869
3876
  }, Symbol.toStringTag, { value: "Module" }));
3870
- const strapiDatatransfer = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3877
+ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3871
3878
  __proto__: null,
3872
- providers: index$4,
3873
- queries: index$5,
3874
- remote: index$2
3879
+ providers: index$5,
3880
+ queries: index$6,
3881
+ remote: index$3
3875
3882
  }, Symbol.toStringTag, { value: "Module" }));
3876
3883
  const isFilePathInDirname = (posixDirName, filePath) => {
3877
3884
  const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));
@@ -3889,7 +3896,7 @@ const unknownPathToPosix = (filePath) => {
3889
3896
  return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);
3890
3897
  };
3891
3898
  const METADATA_FILE_PATH = "metadata.json";
3892
- const createLocalFileSourceProvider$1 = (options) => {
3899
+ const createLocalFileSourceProvider = (options) => {
3893
3900
  return new LocalFileSourceProvider(options);
3894
3901
  };
3895
3902
  class LocalFileSourceProvider {
@@ -3974,18 +3981,18 @@ class LocalFileSourceProvider {
3974
3981
  async onentry(entry) {
3975
3982
  const { path: filePath, size: size2 = 0 } = entry;
3976
3983
  const normalizedPath = unknownPathToPosix(filePath);
3977
- const file2 = path.basename(normalizedPath);
3984
+ const file = path.basename(normalizedPath);
3978
3985
  let metadata;
3979
3986
  try {
3980
- metadata = await loadAssetMetadata(`assets/metadata/${file2}.json`);
3987
+ metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
3981
3988
  } catch (error) {
3982
3989
  console.warn(
3983
- ` Failed to read metadata for ${file2}, Strapi will try to fix this issue automatically`
3990
+ ` Failed to read metadata for ${file}, Strapi will try to fix this issue automatically`
3984
3991
  );
3985
3992
  }
3986
3993
  const asset = {
3987
3994
  metadata,
3988
- filename: file2,
3995
+ filename: file,
3989
3996
  filepath: normalizedPath,
3990
3997
  stats: { size: size2 },
3991
3998
  stream: entry
@@ -3999,10 +4006,10 @@ class LocalFileSourceProvider {
3999
4006
  return outStream;
4000
4007
  }
4001
4008
  #getBackupStream() {
4002
- const { file: file2, encryption, compression } = this.options;
4009
+ const { file, encryption, compression } = this.options;
4003
4010
  const streams = [];
4004
4011
  try {
4005
- streams.push(fse__default.createReadStream(file2.path));
4012
+ streams.push(fse__default.createReadStream(file.path));
4006
4013
  } catch (e) {
4007
4014
  throw new Error(`Could not read backup file path provided at "${this.options.file.path}"`);
4008
4015
  }
@@ -4150,7 +4157,7 @@ const createTarEntryStream = (archive, pathFactory, maxSize = 256e6) => {
4150
4157
  }
4151
4158
  });
4152
4159
  };
4153
- const createLocalFileDestinationProvider$1 = (options) => {
4160
+ const createLocalFileDestinationProvider = (options) => {
4154
4161
  return new LocalFileDestinationProvider(options);
4155
4162
  };
4156
4163
  class LocalFileDestinationProvider {
@@ -4164,8 +4171,8 @@ class LocalFileDestinationProvider {
4164
4171
  this.options = options;
4165
4172
  }
4166
4173
  get #archivePath() {
4167
- const { encryption, compression, file: file2 } = this.options;
4168
- let filePath = `${file2.path}.tar`;
4174
+ const { encryption, compression, file } = this.options;
4175
+ let filePath = `${file.path}.tar`;
4169
4176
  if (compression.enabled) {
4170
4177
  filePath += ".gz";
4171
4178
  }
@@ -4329,953 +4336,17 @@ class LocalFileDestinationProvider {
4329
4336
  }
4330
4337
  const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4331
4338
  __proto__: null,
4332
- createLocalFileDestinationProvider: createLocalFileDestinationProvider$1,
4333
- createLocalFileSourceProvider: createLocalFileSourceProvider$1
4334
- }, Symbol.toStringTag, { value: "Module" }));
4335
- const file = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4336
- __proto__: null,
4337
- providers: index$1
4339
+ createLocalFileDestinationProvider,
4340
+ createLocalFileSourceProvider
4338
4341
  }, Symbol.toStringTag, { value: "Module" }));
4339
- const bytesPerKb = 1024;
4340
- const sizes = ["B ", "KB", "MB", "GB", "TB", "PB"];
4341
- const readableBytes = (bytes, decimals = 1, padStart = 0) => {
4342
- if (!bytes) {
4343
- return "0";
4344
- }
4345
- const i = Math.floor(Math.log(bytes) / Math.log(bytesPerKb));
4346
- const result = `${parseFloat((bytes / bytesPerKb ** i).toFixed(decimals))} ${sizes[i].padStart(
4347
- 2
4348
- )}`;
4349
- return result.padStart(padStart);
4350
- };
4351
- const exitWith = (code, message, options = {}) => {
4352
- const { logger = console, prc = process } = options;
4353
- const log = (message2) => {
4354
- if (code === 0) {
4355
- logger.log(chalk.green(message2));
4356
- } else {
4357
- logger.error(chalk.red(message2));
4358
- }
4359
- };
4360
- if (isString(message)) {
4361
- log(message);
4362
- } else if (isArray(message)) {
4363
- message.forEach((msg) => log(msg));
4364
- }
4365
- prc.exit(code);
4366
- };
4367
- const assertUrlHasProtocol = (url, protocol) => {
4368
- if (!url.protocol) {
4369
- exitWith(1, `${url.toString()} does not have a protocol`);
4370
- }
4371
- if (!protocol) {
4372
- return;
4373
- }
4374
- if (isString(protocol)) {
4375
- if (protocol !== url.protocol) {
4376
- exitWith(1, `${url.toString()} must have the protocol ${protocol}`);
4377
- }
4378
- return;
4379
- }
4380
- if (!protocol.some((protocol2) => url.protocol === protocol2)) {
4381
- return exitWith(
4382
- 1,
4383
- `${url.toString()} must have one of the following protocols: ${protocol.join(",")}`
4384
- );
4385
- }
4386
- };
4387
- const ifOptions = (conditionCallback, isMetCallback = async () => {
4388
- }, isNotMetCallback = async () => {
4389
- }) => {
4390
- return async (command2) => {
4391
- const opts = command2.opts();
4392
- if (await conditionCallback(opts)) {
4393
- await isMetCallback(command2);
4394
- } else {
4395
- await isNotMetCallback(command2);
4396
- }
4397
- };
4398
- };
4399
- const parseList = (value) => {
4400
- try {
4401
- return value.split(",").map((item) => item.trim());
4402
- } catch (e) {
4403
- exitWith(1, `Unrecognized input: ${value}`);
4404
- }
4405
- return [];
4406
- };
4407
- const getParseListWithChoices = (choices, errorMessage = "Invalid options:") => {
4408
- return (value) => {
4409
- const list = parseList(value);
4410
- const invalid = list.filter((item) => {
4411
- return !choices.includes(item);
4412
- });
4413
- if (invalid.length > 0) {
4414
- exitWith(1, `${errorMessage}: ${invalid.join(",")}`);
4415
- }
4416
- return list;
4417
- };
4418
- };
4419
- const parseInteger = (value) => {
4420
- const parsedValue = parseInt(value, 10);
4421
- if (isNaN(parsedValue)) {
4422
- throw new InvalidOptionArgumentError(`Not an integer: ${value}`);
4423
- }
4424
- return parsedValue;
4425
- };
4426
- const parseURL = (value) => {
4427
- try {
4428
- const url = new URL(value);
4429
- if (!url.host) {
4430
- throw new InvalidOptionArgumentError(`Could not parse url ${value}`);
4431
- }
4432
- return url;
4433
- } catch (e) {
4434
- throw new InvalidOptionArgumentError(`Could not parse url ${value}`);
4435
- }
4436
- };
4437
- const promptEncryptionKey = async (thisCommand) => {
4438
- const opts = thisCommand.opts();
4439
- if (!opts.encrypt && opts.key) {
4440
- return exitWith(1, "Key may not be present unless encryption is used");
4441
- }
4442
- if (opts.encrypt && !(opts.key && opts.key.length > 0)) {
4443
- try {
4444
- const answers = await inquirer.prompt([
4445
- {
4446
- type: "password",
4447
- message: "Please enter an encryption key",
4448
- name: "key",
4449
- validate(key) {
4450
- if (key.length > 0)
4451
- return true;
4452
- return "Key must be present when using the encrypt option";
4453
- }
4454
- }
4455
- ]);
4456
- opts.key = answers.key;
4457
- } catch (e) {
4458
- return exitWith(1, "Failed to get encryption key");
4459
- }
4460
- if (!opts.key) {
4461
- return exitWith(1, "Failed to get encryption key");
4462
- }
4463
- }
4464
- };
4465
- const getCommanderConfirmMessage = (message, { failMessage } = {}) => {
4466
- return async (command2) => {
4467
- const confirmed = await confirmMessage(message, { force: command2.opts().force });
4468
- if (!confirmed) {
4469
- exitWith(1, failMessage);
4470
- }
4471
- };
4472
- };
4473
- const confirmMessage = async (message, { force } = {}) => {
4474
- if (force === true) {
4475
- console.log(`${chalk.green("?")} ${chalk.bold(message)} ${chalk.cyan("Yes")}`);
4476
- return true;
4477
- }
4478
- const answers = await inquirer.prompt([
4479
- {
4480
- type: "confirm",
4481
- message,
4482
- name: `confirm`,
4483
- default: false
4484
- }
4485
- ]);
4486
- return answers.confirm;
4487
- };
4488
- const forceOption = new Option(
4489
- "--force",
4490
- `Automatically answer "yes" to all prompts, including potentially destructive requests, and run non-interactively.`
4491
- );
4492
- const {
4493
- errors: { TransferEngineInitializationError: TransferEngineInitializationError2 }
4494
- } = engineDatatransfer;
4495
- const exitMessageText = (process2, error = false) => {
4496
- const processCapitalized = process2[0].toUpperCase() + process2.slice(1);
4497
- if (!error) {
4498
- return chalk.bold(
4499
- chalk.green(`${processCapitalized} process has been completed successfully!`)
4500
- );
4501
- }
4502
- return chalk.bold(chalk.red(`${processCapitalized} process failed.`));
4503
- };
4504
- const pad = (n) => {
4505
- return (n < 10 ? "0" : "") + String(n);
4506
- };
4507
- const yyyymmddHHMMSS = () => {
4508
- const date = /* @__PURE__ */ new Date();
4509
- return date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
4510
- };
4511
- const getDefaultExportName = () => {
4512
- return `export_${yyyymmddHHMMSS()}`;
4513
- };
4514
- const buildTransferTable = (resultData) => {
4515
- if (!resultData) {
4516
- return;
4517
- }
4518
- const table = new Table({
4519
- head: ["Type", "Count", "Size"].map((text) => chalk.bold.blue(text))
4520
- });
4521
- let totalBytes = 0;
4522
- let totalItems = 0;
4523
- Object.keys(resultData).forEach((stage) => {
4524
- const item = resultData[stage];
4525
- if (!item) {
4526
- return;
4527
- }
4528
- table.push([
4529
- { hAlign: "left", content: chalk.bold(stage) },
4530
- { hAlign: "right", content: item.count },
4531
- { hAlign: "right", content: `${readableBytes(item.bytes, 1, 11)} ` }
4532
- ]);
4533
- totalBytes += item.bytes;
4534
- totalItems += item.count;
4535
- if (item.aggregates) {
4536
- Object.keys(item.aggregates).sort().forEach((subkey) => {
4537
- if (!item.aggregates) {
4538
- return;
4539
- }
4540
- const subitem = item.aggregates[subkey];
4541
- table.push([
4542
- { hAlign: "left", content: `-- ${chalk.bold.grey(subkey)}` },
4543
- { hAlign: "right", content: chalk.grey(subitem.count) },
4544
- { hAlign: "right", content: chalk.grey(`(${readableBytes(subitem.bytes, 1, 11)})`) }
4545
- ]);
4546
- });
4547
- }
4548
- });
4549
- table.push([
4550
- { hAlign: "left", content: chalk.bold.green("Total") },
4551
- { hAlign: "right", content: chalk.bold.green(totalItems) },
4552
- { hAlign: "right", content: `${chalk.bold.green(readableBytes(totalBytes, 1, 11))} ` }
4553
- ]);
4554
- return table;
4555
- };
4556
- const DEFAULT_IGNORED_CONTENT_TYPES = [
4557
- "admin::permission",
4558
- "admin::user",
4559
- "admin::role",
4560
- "admin::api-token",
4561
- "admin::api-token-permission",
4562
- "admin::transfer-token",
4563
- "admin::transfer-token-permission",
4564
- "admin::audit-log",
4565
- "plugin::content-releases.release",
4566
- "plugin::content-releases.release-action"
4567
- ];
4568
- const abortTransfer = async ({
4569
- engine,
4570
- strapi: strapi2
4571
- }) => {
4572
- try {
4573
- await engine.abortTransfer();
4574
- await strapi2.destroy();
4575
- } catch (e) {
4576
- return false;
4577
- }
4578
- return true;
4579
- };
4580
- const setSignalHandler = async (handler, signals = ["SIGINT", "SIGTERM", "SIGQUIT"]) => {
4581
- signals.forEach((signal) => {
4582
- process.removeAllListeners(signal);
4583
- process.on(signal, handler);
4584
- });
4585
- };
4586
- const createStrapiInstance = async (opts = {}) => {
4587
- try {
4588
- const appContext = await strapiFactory.compile();
4589
- const app = strapiFactory({ ...opts, ...appContext });
4590
- app.log.level = opts.logLevel || "error";
4591
- return await app.load();
4592
- } catch (error) {
4593
- if (error instanceof Error && "code" in error && error.code === "ECONNREFUSED") {
4594
- throw new Error("Process failed. Check the database connection with your Strapi project.");
4595
- }
4596
- throw error;
4597
- }
4598
- };
4599
- const transferDataTypes = Object.keys(TransferGroupPresets);
4600
- const throttleOption = new Option(
4601
- "--throttle <delay after each entity>",
4602
- `Add a delay in milliseconds between each transferred entity`
4603
- ).argParser(parseInteger).hideHelp();
4604
- const excludeOption = new Option(
4605
- "--exclude <comma-separated data types>",
4606
- `Exclude data using comma-separated types. Available types: ${transferDataTypes.join(",")}`
4607
- ).argParser(getParseListWithChoices(transferDataTypes, 'Invalid options for "exclude"'));
4608
- const onlyOption = new Option(
4609
- "--only <command-separated data types>",
4610
- `Include only these types of data (plus schemas). Available types: ${transferDataTypes.join(",")}`
4611
- ).argParser(getParseListWithChoices(transferDataTypes, 'Invalid options for "only"'));
4612
- const validateExcludeOnly = (command2) => {
4613
- const { exclude, only } = command2.opts();
4614
- if (!only || !exclude) {
4615
- return;
4616
- }
4617
- const choicesInBoth = only.filter((n) => {
4618
- return exclude.indexOf(n) !== -1;
4619
- });
4620
- if (choicesInBoth.length > 0) {
4621
- exitWith(
4622
- 1,
4623
- `Data types may not be used in both "exclude" and "only" in the same command. Found in both: ${choicesInBoth.join(
4624
- ","
4625
- )}`
4626
- );
4627
- }
4628
- };
4629
- const errorColors = {
4630
- fatal: chalk.red,
4631
- error: chalk.red,
4632
- silly: chalk.yellow
4633
- };
4634
- const formatDiagnostic = (operation) => ({ details, kind }) => {
4635
- const logger = createLogger(
4636
- configs.createOutputFileConfiguration(`${operation}_error_log_${Date.now()}.log`)
4637
- );
4638
- try {
4639
- if (kind === "error") {
4640
- const { message, severity = "fatal" } = details;
4641
- const colorizeError = errorColors[severity];
4642
- const errorMessage = colorizeError(`[${severity.toUpperCase()}] ${message}`);
4643
- logger.error(errorMessage);
4644
- }
4645
- if (kind === "info") {
4646
- const { message, params } = details;
4647
- const msg = `${message}
4648
- ${params ? JSON.stringify(params, null, 2) : ""}`;
4649
- logger.info(msg);
4650
- }
4651
- if (kind === "warning") {
4652
- const { origin: origin2, message } = details;
4653
- logger.warn(`(${origin2 ?? "transfer"}) ${message}`);
4654
- }
4655
- } catch (err) {
4656
- logger.error(err);
4657
- }
4658
- };
4659
- const loadersFactory = (defaultLoaders = {}) => {
4660
- const loaders = defaultLoaders;
4661
- const updateLoader = (stage, data) => {
4662
- if (!(stage in loaders)) {
4663
- createLoader(stage);
4664
- }
4665
- const stageData = data[stage];
4666
- const elapsedTime = stageData?.startTime ? (stageData?.endTime || Date.now()) - stageData.startTime : 0;
4667
- const size2 = `size: ${readableBytes(stageData?.bytes ?? 0)}`;
4668
- const elapsed = `elapsed: ${elapsedTime} ms`;
4669
- const speed = elapsedTime > 0 ? `(${readableBytes((stageData?.bytes ?? 0) * 1e3 / elapsedTime)}/s)` : "";
4670
- loaders[stage].text = `${stage}: ${stageData?.count ?? 0} transfered (${size2}) (${elapsed}) ${!stageData?.endTime ? speed : ""}`;
4671
- return loaders[stage];
4672
- };
4673
- const createLoader = (stage) => {
4674
- Object.assign(loaders, { [stage]: ora() });
4675
- return loaders[stage];
4676
- };
4677
- const getLoader = (stage) => {
4678
- return loaders[stage];
4679
- };
4680
- return {
4681
- updateLoader,
4682
- createLoader,
4683
- getLoader
4684
- };
4685
- };
4686
- const getTransferTelemetryPayload = (engine) => {
4687
- return {
4688
- eventProperties: {
4689
- source: engine?.sourceProvider?.name,
4690
- destination: engine?.destinationProvider?.name
4691
- }
4692
- };
4693
- };
4694
- const getDiffHandler = (engine, {
4695
- force,
4696
- action: action2
4697
- }) => {
4698
- return async (context, next) => {
4699
- setSignalHandler(async () => {
4700
- await abortTransfer({ engine, strapi });
4701
- exitWith(1, exitMessageText(action2, true));
4702
- });
4703
- let workflowsStatus;
4704
- const source = "Schema Integrity";
4705
- Object.entries(context.diffs).forEach(([uid, diffs]) => {
4706
- for (const diff2 of diffs) {
4707
- const path2 = [uid].concat(diff2.path).join(".");
4708
- const endPath = diff2.path[diff2.path.length - 1];
4709
- if (uid === "admin::workflow" || uid === "admin::workflow-stage" || endPath?.startsWith("strapi_stage") || endPath?.startsWith("strapi_assignee")) {
4710
- workflowsStatus = diff2.kind;
4711
- } else if (diff2.kind === "added") {
4712
- engine.reportWarning(chalk.red(`${chalk.bold(path2)} does not exist on source`), source);
4713
- } else if (diff2.kind === "deleted") {
4714
- engine.reportWarning(
4715
- chalk.red(`${chalk.bold(path2)} does not exist on destination`),
4716
- source
4717
- );
4718
- } else if (diff2.kind === "modified") {
4719
- engine.reportWarning(chalk.red(`${chalk.bold(path2)} has a different data type`), source);
4720
- }
4721
- }
4722
- });
4723
- if (workflowsStatus === "added") {
4724
- engine.reportWarning(chalk.red(`Review workflows feature does not exist on source`), source);
4725
- } else if (workflowsStatus === "deleted") {
4726
- engine.reportWarning(
4727
- chalk.red(`Review workflows feature does not exist on destination`),
4728
- source
4729
- );
4730
- } else if (workflowsStatus === "modified") {
4731
- engine.panic(
4732
- new TransferEngineInitializationError2("Unresolved differences in schema [review workflows]")
4733
- );
4734
- }
4735
- const confirmed = await confirmMessage(
4736
- "There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?",
4737
- {
4738
- force
4739
- }
4740
- );
4741
- setSignalHandler(() => abortTransfer({ engine, strapi }));
4742
- if (confirmed) {
4743
- context.ignoredDiffs = merge(context.diffs, context.ignoredDiffs);
4744
- }
4745
- return next(context);
4746
- };
4747
- };
4748
- const getAssetsBackupHandler = (engine, {
4749
- force,
4750
- action: action2
4751
- }) => {
4752
- return async (context, next) => {
4753
- setSignalHandler(async () => {
4754
- await abortTransfer({ engine, strapi });
4755
- exitWith(1, exitMessageText(action2, true));
4756
- });
4757
- console.warn(
4758
- "The backup for the assets could not be created inside the public directory. Ensure Strapi has write permissions on the public directory."
4759
- );
4760
- const confirmed = await confirmMessage(
4761
- "Do you want to continue without backing up your public/uploads files?",
4762
- {
4763
- force
4764
- }
4765
- );
4766
- if (confirmed) {
4767
- context.ignore = true;
4768
- }
4769
- setSignalHandler(() => abortTransfer({ engine, strapi }));
4770
- return next(context);
4771
- };
4772
- };
4773
- const shouldSkipStage = (opts, dataKind) => {
4774
- if (opts.exclude?.includes(dataKind)) {
4775
- return true;
4776
- }
4777
- if (opts.only) {
4778
- return !opts.only.includes(dataKind);
4779
- }
4780
- return false;
4781
- };
4782
- const parseRestoreFromOptions = (opts) => {
4783
- const entitiesOptions = {
4784
- exclude: DEFAULT_IGNORED_CONTENT_TYPES,
4785
- include: void 0
4786
- };
4787
- if (opts.only && !opts.only.includes("content") || opts.exclude?.includes("content")) {
4788
- entitiesOptions.include = [];
4789
- }
4790
- const restoreConfig = {
4791
- entities: entitiesOptions,
4792
- assets: !shouldSkipStage(opts, "files"),
4793
- configuration: {
4794
- webhook: !shouldSkipStage(opts, "config"),
4795
- coreStore: !shouldSkipStage(opts, "config")
4796
- }
4797
- };
4798
- return restoreConfig;
4799
- };
4800
- const {
4801
- providers: { createLocalFileDestinationProvider }
4802
- } = file;
4803
- const {
4804
- providers: { createLocalStrapiSourceProvider: createLocalStrapiSourceProvider$1 }
4805
- } = strapiDatatransfer;
4806
- const BYTES_IN_MB = 1024 * 1024;
4807
- const action$2 = async (opts) => {
4808
- if (!isObject(opts)) {
4809
- exitWith(1, "Could not parse command arguments");
4810
- }
4811
- const strapi2 = await createStrapiInstance();
4812
- const source = createSourceProvider(strapi2);
4813
- const destination = createDestinationProvider(opts);
4814
- const engine = createTransferEngine$2(source, destination, {
4815
- versionStrategy: "ignore",
4816
- // for an export to file, versionStrategy will always be skipped
4817
- schemaStrategy: "ignore",
4818
- // for an export to file, schemaStrategy will always be skipped
4819
- exclude: opts.exclude,
4820
- only: opts.only,
4821
- throttle: opts.throttle,
4822
- transforms: {
4823
- links: [
4824
- {
4825
- filter(link2) {
4826
- return !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.left.type) && !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.right.type);
4827
- }
4828
- }
4829
- ],
4830
- entities: [
4831
- {
4832
- filter(entity2) {
4833
- return !DEFAULT_IGNORED_CONTENT_TYPES.includes(entity2.type);
4834
- }
4835
- }
4836
- ]
4837
- }
4838
- });
4839
- engine.diagnostics.onDiagnostic(formatDiagnostic("export"));
4840
- const progress = engine.progress.stream;
4841
- const { updateLoader } = loadersFactory();
4842
- progress.on(`stage::start`, ({ stage, data }) => {
4843
- updateLoader(stage, data).start();
4844
- });
4845
- progress.on("stage::finish", ({ stage, data }) => {
4846
- updateLoader(stage, data).succeed();
4847
- });
4848
- progress.on("stage::progress", ({ stage, data }) => {
4849
- updateLoader(stage, data);
4850
- });
4851
- progress.on("transfer::start", async () => {
4852
- console.log(`Starting export...`);
4853
- await strapi2.telemetry.send("didDEITSProcessStart", getTransferTelemetryPayload(engine));
4854
- });
4855
- let results;
4856
- let outFile;
4857
- try {
4858
- setSignalHandler(() => abortTransfer({ engine, strapi: strapi2 }));
4859
- results = await engine.transfer();
4860
- outFile = results.destination?.file?.path ?? "";
4861
- const outFileExists = await fse__default.pathExists(outFile);
4862
- if (!outFileExists) {
4863
- throw new TransferEngineTransferError(`Export file not created "${outFile}"`);
4864
- }
4865
- await strapi2.telemetry.send("didDEITSProcessFinish", getTransferTelemetryPayload(engine));
4866
- try {
4867
- const table = buildTransferTable(results.engine);
4868
- console.log(table?.toString());
4869
- } catch (e) {
4870
- console.error("There was an error displaying the results of the transfer.");
4871
- }
4872
- console.log(`Export archive is in ${chalk.green(outFile)}`);
4873
- exitWith(0, exitMessageText("export"));
4874
- } catch {
4875
- await strapi2.telemetry.send("didDEITSProcessFail", getTransferTelemetryPayload(engine));
4876
- exitWith(1, exitMessageText("export", true));
4877
- }
4878
- };
4879
- const createSourceProvider = (strapi2) => {
4880
- return createLocalStrapiSourceProvider$1({
4881
- async getStrapi() {
4882
- return strapi2;
4883
- }
4884
- });
4885
- };
4886
- const createDestinationProvider = (opts) => {
4887
- const { file: file2, compress, encrypt, key, maxSizeJsonl } = opts;
4888
- const filepath = isString(file2) && file2.length > 0 ? file2 : getDefaultExportName();
4889
- const maxSizeJsonlInMb = isFinite(toNumber(maxSizeJsonl)) ? toNumber(maxSizeJsonl) * BYTES_IN_MB : void 0;
4890
- return createLocalFileDestinationProvider({
4891
- file: {
4892
- path: filepath,
4893
- maxSizeJsonl: maxSizeJsonlInMb
4894
- },
4895
- encryption: {
4896
- enabled: encrypt ?? false,
4897
- key: encrypt ? key : void 0
4898
- },
4899
- compression: {
4900
- enabled: compress ?? false
4901
- }
4902
- });
4903
- };
4904
- const command$2 = ({ command: command2 }) => {
4905
- command2.command("export").description("Export data from Strapi to file").allowExcessArguments(false).addOption(
4906
- new Option("--no-encrypt", `Disables 'aes-128-ecb' encryption of the output file`).default(
4907
- true
4908
- )
4909
- ).addOption(
4910
- new Option("--no-compress", "Disables gzip compression of output file").default(true)
4911
- ).addOption(
4912
- new Option(
4913
- "-k, --key <string>",
4914
- "Provide encryption key in command instead of using the prompt"
4915
- )
4916
- ).addOption(
4917
- new Option("-f, --file <file>", "name to use for exported file (without extensions)")
4918
- ).addOption(excludeOption).addOption(onlyOption).addOption(throttleOption).hook("preAction", validateExcludeOnly).hook("preAction", promptEncryptionKey).action(action$2);
4919
- };
4920
- const {
4921
- providers: { createLocalFileSourceProvider }
4922
- } = file;
4923
- const {
4924
- providers: { createLocalStrapiDestinationProvider: createLocalStrapiDestinationProvider$1, DEFAULT_CONFLICT_STRATEGY }
4925
- } = strapiDatatransfer;
4926
- const { createTransferEngine: createTransferEngine$1, DEFAULT_VERSION_STRATEGY, DEFAULT_SCHEMA_STRATEGY } = engineDatatransfer;
4927
- const action$1 = async (opts) => {
4928
- if (!isObject(opts)) {
4929
- exitWith(1, "Could not parse arguments");
4930
- }
4931
- const sourceOptions = getLocalFileSourceOptions(opts);
4932
- const source = createLocalFileSourceProvider(sourceOptions);
4933
- const strapiInstance = await createStrapiInstance();
4934
- const engineOptions = {
4935
- versionStrategy: DEFAULT_VERSION_STRATEGY,
4936
- schemaStrategy: DEFAULT_SCHEMA_STRATEGY,
4937
- exclude: opts.exclude,
4938
- only: opts.only,
4939
- throttle: opts.throttle,
4940
- transforms: {
4941
- links: [
4942
- {
4943
- filter(link2) {
4944
- return !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.left.type) && !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.right.type);
4945
- }
4946
- }
4947
- ],
4948
- entities: [
4949
- {
4950
- filter: (entity2) => !DEFAULT_IGNORED_CONTENT_TYPES.includes(entity2.type)
4951
- }
4952
- ]
4953
- }
4954
- };
4955
- const destinationOptions = {
4956
- async getStrapi() {
4957
- return strapiInstance;
4958
- },
4959
- autoDestroy: false,
4960
- strategy: opts.conflictStrategy || DEFAULT_CONFLICT_STRATEGY,
4961
- restore: parseRestoreFromOptions(engineOptions)
4962
- };
4963
- const destination = createLocalStrapiDestinationProvider$1(destinationOptions);
4964
- destination.onWarning = (message) => console.warn(`
4965
- ${chalk.yellow("warn")}: ${message}`);
4966
- const engine2 = createTransferEngine$1(source, destination, engineOptions);
4967
- engine2.diagnostics.onDiagnostic(formatDiagnostic("import"));
4968
- const progress = engine2.progress.stream;
4969
- const { updateLoader } = loadersFactory();
4970
- engine2.onSchemaDiff(getDiffHandler(engine2, { force: opts.force, action: "import" }));
4971
- progress.on(`stage::start`, ({ stage, data }) => {
4972
- updateLoader(stage, data).start();
4973
- });
4974
- progress.on("stage::finish", ({ stage, data }) => {
4975
- updateLoader(stage, data).succeed();
4976
- });
4977
- progress.on("stage::progress", ({ stage, data }) => {
4978
- updateLoader(stage, data);
4979
- });
4980
- progress.on("transfer::start", async () => {
4981
- console.log("Starting import...");
4982
- await strapiInstance.telemetry.send(
4983
- "didDEITSProcessStart",
4984
- getTransferTelemetryPayload(engine2)
4985
- );
4986
- });
4987
- let results;
4988
- try {
4989
- setSignalHandler(() => abortTransfer({ engine: engine2, strapi }));
4990
- results = await engine2.transfer();
4991
- try {
4992
- const table = buildTransferTable(results.engine);
4993
- console.log(table?.toString());
4994
- } catch (e) {
4995
- console.error("There was an error displaying the results of the transfer.");
4996
- }
4997
- await strapiInstance.telemetry.send(
4998
- "didDEITSProcessFinish",
4999
- getTransferTelemetryPayload(engine2)
5000
- );
5001
- await strapiInstance.destroy();
5002
- exitWith(0, exitMessageText("import"));
5003
- } catch (e) {
5004
- await strapiInstance.telemetry.send("didDEITSProcessFail", getTransferTelemetryPayload(engine2));
5005
- exitWith(1, exitMessageText("import", true));
5006
- }
5007
- };
5008
- const getLocalFileSourceOptions = (opts) => {
5009
- const options = {
5010
- file: { path: opts.file ?? "" },
5011
- compression: { enabled: !!opts.decompress },
5012
- encryption: { enabled: !!opts.decrypt, key: opts.key }
5013
- };
5014
- return options;
5015
- };
5016
- const command$1 = ({ command: command2 }) => {
5017
- command2.command("import").description("Import data from file to Strapi").allowExcessArguments(false).requiredOption(
5018
- "-f, --file <file>",
5019
- "path and filename for the Strapi export file you want to import"
5020
- ).addOption(
5021
- new Option(
5022
- "-k, --key <string>",
5023
- "Provide encryption key in command instead of using the prompt"
5024
- )
5025
- ).addOption(forceOption).addOption(excludeOption).addOption(onlyOption).addOption(throttleOption).hook("preAction", validateExcludeOnly).hook("preAction", async (thisCommand) => {
5026
- const opts = thisCommand.opts();
5027
- const ext = path.extname(String(opts.file));
5028
- if (ext === ".enc") {
5029
- if (!opts.key) {
5030
- const answers = await inquirer.prompt([
5031
- {
5032
- type: "password",
5033
- message: "Please enter your decryption key",
5034
- name: "key"
5035
- }
5036
- ]);
5037
- if (!answers.key?.length) {
5038
- exitWith(1, "No key entered, aborting import.");
5039
- }
5040
- opts.key = answers.key;
5041
- }
5042
- }
5043
- }).hook("preAction", (thisCommand) => {
5044
- const opts = thisCommand.opts();
5045
- const { extname: extname2, parse } = path;
5046
- let file2 = opts.file;
5047
- if (extname2(file2) === ".enc") {
5048
- file2 = parse(file2).name;
5049
- thisCommand.opts().decrypt = true;
5050
- } else {
5051
- thisCommand.opts().decrypt = false;
5052
- }
5053
- if (extname2(file2) === ".gz") {
5054
- file2 = parse(file2).name;
5055
- thisCommand.opts().decompress = true;
5056
- } else {
5057
- thisCommand.opts().decompress = false;
5058
- }
5059
- if (extname2(file2) !== ".tar") {
5060
- exitWith(
5061
- 1,
5062
- `The file '${opts.file}' does not appear to be a valid Strapi data file. It must have an extension ending in .tar[.gz][.enc]`
5063
- );
5064
- }
5065
- }).hook(
5066
- "preAction",
5067
- getCommanderConfirmMessage(
5068
- "The import will delete your existing data! Are you sure you want to proceed?",
5069
- { failMessage: "Import process aborted" }
5070
- )
5071
- ).action(action$1);
5072
- };
5073
- const { createTransferEngine } = engineDatatransfer;
5074
- const {
5075
- providers: {
5076
- createRemoteStrapiDestinationProvider,
5077
- createLocalStrapiSourceProvider,
5078
- createLocalStrapiDestinationProvider,
5079
- createRemoteStrapiSourceProvider
5080
- }
5081
- } = strapiDatatransfer;
5082
- const action = async (opts) => {
5083
- if (!isObject(opts)) {
5084
- exitWith(1, "Could not parse command arguments");
5085
- }
5086
- if (!(opts.from || opts.to) || opts.from && opts.to) {
5087
- exitWith(1, "Exactly one source (from) or destination (to) option must be provided");
5088
- }
5089
- const strapi2 = await createStrapiInstance();
5090
- let source;
5091
- let destination;
5092
- if (!opts.from) {
5093
- source = createLocalStrapiSourceProvider({
5094
- getStrapi: () => strapi2
5095
- });
5096
- } else {
5097
- if (!opts.fromToken) {
5098
- exitWith(1, "Missing token for remote destination");
5099
- }
5100
- source = createRemoteStrapiSourceProvider({
5101
- getStrapi: () => strapi2,
5102
- url: opts.from,
5103
- auth: {
5104
- type: "token",
5105
- token: opts.fromToken
5106
- }
5107
- });
5108
- }
5109
- if (!opts.to) {
5110
- destination = createLocalStrapiDestinationProvider({
5111
- getStrapi: () => strapi2,
5112
- strategy: "restore",
5113
- restore: parseRestoreFromOptions(opts)
5114
- });
5115
- } else {
5116
- if (!opts.toToken) {
5117
- exitWith(1, "Missing token for remote destination");
5118
- }
5119
- destination = createRemoteStrapiDestinationProvider({
5120
- url: opts.to,
5121
- auth: {
5122
- type: "token",
5123
- token: opts.toToken
5124
- },
5125
- strategy: "restore",
5126
- restore: parseRestoreFromOptions(opts)
5127
- });
5128
- }
5129
- if (!source || !destination) {
5130
- exitWith(1, "Could not create providers");
5131
- }
5132
- const engine = createTransferEngine(source, destination, {
5133
- versionStrategy: "exact",
5134
- schemaStrategy: "strict",
5135
- exclude: opts.exclude,
5136
- only: opts.only,
5137
- throttle: opts.throttle,
5138
- transforms: {
5139
- links: [
5140
- {
5141
- filter(link2) {
5142
- return !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.left.type) && !DEFAULT_IGNORED_CONTENT_TYPES.includes(link2.right.type);
5143
- }
5144
- }
5145
- ],
5146
- entities: [
5147
- {
5148
- filter(entity2) {
5149
- return !DEFAULT_IGNORED_CONTENT_TYPES.includes(entity2.type);
5150
- }
5151
- }
5152
- ]
5153
- }
5154
- });
5155
- engine.diagnostics.onDiagnostic(formatDiagnostic("transfer"));
5156
- const progress = engine.progress.stream;
5157
- const { updateLoader } = loadersFactory();
5158
- engine.onSchemaDiff(getDiffHandler(engine, { force: opts.force, action: "transfer" }));
5159
- engine.addErrorHandler(
5160
- "ASSETS_DIRECTORY_ERR",
5161
- getAssetsBackupHandler(engine, { force: opts.force, action: "transfer" })
5162
- );
5163
- progress.on(`stage::start`, ({ stage, data }) => {
5164
- updateLoader(stage, data).start();
5165
- });
5166
- progress.on("stage::finish", ({ stage, data }) => {
5167
- updateLoader(stage, data).succeed();
5168
- });
5169
- progress.on("stage::progress", ({ stage, data }) => {
5170
- updateLoader(stage, data);
5171
- });
5172
- progress.on("stage::error", ({ stage, data }) => {
5173
- updateLoader(stage, data).fail();
5174
- });
5175
- progress.on("transfer::start", async () => {
5176
- console.log(`Starting transfer...`);
5177
- await strapi2.telemetry.send("didDEITSProcessStart", getTransferTelemetryPayload(engine));
5178
- });
5179
- let results;
5180
- try {
5181
- setSignalHandler(() => abortTransfer({ engine, strapi: strapi2 }));
5182
- results = await engine.transfer();
5183
- await strapi2.telemetry.send("didDEITSProcessFinish", getTransferTelemetryPayload(engine));
5184
- try {
5185
- const table = buildTransferTable(results.engine);
5186
- console.log(table?.toString());
5187
- } catch (e) {
5188
- console.error("There was an error displaying the results of the transfer.");
5189
- }
5190
- exitWith(0, exitMessageText("transfer"));
5191
- } catch (e) {
5192
- await strapi2.telemetry.send("didDEITSProcessFail", getTransferTelemetryPayload(engine));
5193
- exitWith(1, exitMessageText("transfer", true));
5194
- }
5195
- };
5196
- const command = ({ command: command2 }) => {
5197
- command2.command("transfer").description("Transfer data from one source to another").allowExcessArguments(false).addOption(
5198
- new Option(
5199
- "--from <sourceURL>",
5200
- `URL of the remote Strapi instance to get data from`
5201
- ).argParser(parseURL)
5202
- ).addOption(new Option("--from-token <token>", `Transfer token for the remote Strapi source`)).addOption(
5203
- new Option(
5204
- "--to <destinationURL>",
5205
- `URL of the remote Strapi instance to send data to`
5206
- ).argParser(parseURL)
5207
- ).addOption(new Option("--to-token <token>", `Transfer token for the remote Strapi destination`)).addOption(forceOption).addOption(excludeOption).addOption(onlyOption).addOption(throttleOption).hook("preAction", validateExcludeOnly).hook(
5208
- "preAction",
5209
- ifOptions(
5210
- (opts) => !(opts.from || opts.to) || opts.from && opts.to,
5211
- async () => exitWith(
5212
- 1,
5213
- "Exactly one remote source (from) or destination (to) option must be provided"
5214
- )
5215
- )
5216
- ).hook(
5217
- "preAction",
5218
- ifOptions(
5219
- (opts) => opts.from,
5220
- async (thisCommand) => {
5221
- assertUrlHasProtocol(thisCommand.opts().from, ["https:", "http:"]);
5222
- if (!thisCommand.opts().fromToken) {
5223
- const answers = await inquirer.prompt([
5224
- {
5225
- type: "password",
5226
- message: "Please enter your transfer token for the remote Strapi source",
5227
- name: "fromToken"
5228
- }
5229
- ]);
5230
- if (!answers.fromToken?.length) {
5231
- exitWith(1, "No token provided for remote source, aborting transfer.");
5232
- }
5233
- thisCommand.opts().fromToken = answers.fromToken;
5234
- }
5235
- await getCommanderConfirmMessage(
5236
- "The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?",
5237
- { failMessage: "Transfer process aborted" }
5238
- )(thisCommand);
5239
- }
5240
- )
5241
- ).hook(
5242
- "preAction",
5243
- ifOptions(
5244
- (opts) => opts.to,
5245
- async (thisCommand) => {
5246
- assertUrlHasProtocol(thisCommand.opts().to, ["https:", "http:"]);
5247
- if (!thisCommand.opts().toToken) {
5248
- const answers = await inquirer.prompt([
5249
- {
5250
- type: "password",
5251
- message: "Please enter your transfer token for the remote Strapi destination",
5252
- name: "toToken"
5253
- }
5254
- ]);
5255
- if (!answers.toToken?.length) {
5256
- exitWith(1, "No token provided for remote destination, aborting transfer.");
5257
- }
5258
- thisCommand.opts().toToken = answers.toToken;
5259
- }
5260
- await getCommanderConfirmMessage(
5261
- "The transfer will delete existing data from the remote Strapi! Are you sure you want to proceed?",
5262
- { failMessage: "Transfer process aborted" }
5263
- )(thisCommand);
5264
- }
5265
- )
5266
- ).action(action);
5267
- };
5268
4342
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
5269
4343
  __proto__: null,
5270
- export: command$2,
5271
- import: command$1,
5272
- transfer: command
4344
+ providers: index$1
5273
4345
  }, Symbol.toStringTag, { value: "Module" }));
5274
4346
  export {
5275
- index as commands,
5276
- engineDatatransfer as engine,
5277
- file,
5278
- strapiDatatransfer as strapi,
5279
- index$6 as utils
4347
+ index$7 as engine,
4348
+ index as file,
4349
+ index$2 as strapi,
4350
+ index$8 as utils
5280
4351
  };
5281
4352
  //# sourceMappingURL=index.mjs.map