@strapi/data-transfer 5.4.1 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/errors/constants.d.ts +1 -1
- package/dist/errors/constants.d.ts.map +1 -1
- package/dist/file/providers/destination/index.d.ts +2 -1
- package/dist/file/providers/destination/index.d.ts.map +1 -1
- package/dist/file/providers/source/index.d.ts +2 -1
- package/dist/file/providers/source/index.d.ts.map +1 -1
- package/dist/index.js +304 -95
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +303 -93
- package/dist/index.mjs.map +1 -1
- package/dist/strapi/providers/local-destination/index.d.ts +2 -1
- package/dist/strapi/providers/local-destination/index.d.ts.map +1 -1
- package/dist/strapi/providers/local-source/index.d.ts +3 -1
- package/dist/strapi/providers/local-source/index.d.ts.map +1 -1
- package/dist/strapi/providers/remote-destination/index.d.ts +2 -1
- package/dist/strapi/providers/remote-destination/index.d.ts.map +1 -1
- package/dist/strapi/providers/remote-source/index.d.ts +2 -1
- package/dist/strapi/providers/remote-source/index.d.ts.map +1 -1
- package/dist/strapi/providers/utils.d.ts +3 -2
- package/dist/strapi/providers/utils.d.ts.map +1 -1
- package/dist/strapi/remote/handlers/abstract.d.ts +4 -0
- package/dist/strapi/remote/handlers/abstract.d.ts.map +1 -1
- package/dist/strapi/remote/handlers/pull.d.ts.map +1 -1
- package/dist/strapi/remote/handlers/push.d.ts.map +1 -1
- package/dist/strapi/remote/handlers/utils.d.ts.map +1 -1
- package/dist/{engine → utils}/diagnostic.d.ts +1 -0
- package/dist/utils/diagnostic.d.ts.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/engine/diagnostic.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -21,8 +21,7 @@ const tar$1 = require("tar-stream");
|
|
|
21
21
|
const Stringer = require("stream-json/jsonl/Stringer");
|
|
22
22
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
23
23
|
function _interopNamespace(e) {
|
|
24
|
-
if (e && e.__esModule)
|
|
25
|
-
return e;
|
|
24
|
+
if (e && e.__esModule) return e;
|
|
26
25
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
27
26
|
if (e) {
|
|
28
27
|
for (const k in e) {
|
|
@@ -326,8 +325,57 @@ const middleware = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
326
325
|
__proto__: null,
|
|
327
326
|
runMiddleware
|
|
328
327
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
328
|
+
const createDiagnosticReporter = (options = {}) => {
|
|
329
|
+
const { stackSize = -1 } = options;
|
|
330
|
+
const emitter = new events.EventEmitter();
|
|
331
|
+
const stack = [];
|
|
332
|
+
const addListener = (event, listener) => {
|
|
333
|
+
emitter.on(event, listener);
|
|
334
|
+
};
|
|
335
|
+
const isDiagnosticValid = (diagnostic2) => {
|
|
336
|
+
if (!diagnostic2.kind || !diagnostic2.details || !diagnostic2.details.message) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
return true;
|
|
340
|
+
};
|
|
341
|
+
return {
|
|
342
|
+
stack: {
|
|
343
|
+
get size() {
|
|
344
|
+
return stack.length;
|
|
345
|
+
},
|
|
346
|
+
get items() {
|
|
347
|
+
return stack;
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
report(diagnostic2) {
|
|
351
|
+
if (!isDiagnosticValid(diagnostic2)) {
|
|
352
|
+
return this;
|
|
353
|
+
}
|
|
354
|
+
emitter.emit("diagnostic", diagnostic2);
|
|
355
|
+
emitter.emit(`diagnostic.${diagnostic2.kind}`, diagnostic2);
|
|
356
|
+
if (stackSize !== -1 && stack.length >= stackSize) {
|
|
357
|
+
stack.shift();
|
|
358
|
+
}
|
|
359
|
+
stack.push(diagnostic2);
|
|
360
|
+
return this;
|
|
361
|
+
},
|
|
362
|
+
onDiagnostic(listener) {
|
|
363
|
+
addListener("diagnostic", listener);
|
|
364
|
+
return this;
|
|
365
|
+
},
|
|
366
|
+
on(kind, listener) {
|
|
367
|
+
addListener(`diagnostic.${kind}`, listener);
|
|
368
|
+
return this;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
const diagnostic = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
373
|
+
__proto__: null,
|
|
374
|
+
createDiagnosticReporter
|
|
375
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
329
376
|
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
330
377
|
__proto__: null,
|
|
378
|
+
diagnostics: diagnostic,
|
|
331
379
|
encryption: index$9,
|
|
332
380
|
json,
|
|
333
381
|
middleware,
|
|
@@ -428,50 +476,6 @@ const validateProvider = (type, provider) => {
|
|
|
428
476
|
);
|
|
429
477
|
}
|
|
430
478
|
};
|
|
431
|
-
const createDiagnosticReporter = (options = {}) => {
|
|
432
|
-
const { stackSize = -1 } = options;
|
|
433
|
-
const emitter = new events.EventEmitter();
|
|
434
|
-
const stack = [];
|
|
435
|
-
const addListener = (event, listener) => {
|
|
436
|
-
emitter.on(event, listener);
|
|
437
|
-
};
|
|
438
|
-
const isDiagnosticValid = (diagnostic) => {
|
|
439
|
-
if (!diagnostic.kind || !diagnostic.details || !diagnostic.details.message) {
|
|
440
|
-
return false;
|
|
441
|
-
}
|
|
442
|
-
return true;
|
|
443
|
-
};
|
|
444
|
-
return {
|
|
445
|
-
stack: {
|
|
446
|
-
get size() {
|
|
447
|
-
return stack.length;
|
|
448
|
-
},
|
|
449
|
-
get items() {
|
|
450
|
-
return stack;
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
report(diagnostic) {
|
|
454
|
-
if (!isDiagnosticValid(diagnostic)) {
|
|
455
|
-
return this;
|
|
456
|
-
}
|
|
457
|
-
emitter.emit("diagnostic", diagnostic);
|
|
458
|
-
emitter.emit(`diagnostic.${diagnostic.kind}`, diagnostic);
|
|
459
|
-
if (stackSize !== -1 && stack.length >= stackSize) {
|
|
460
|
-
stack.shift();
|
|
461
|
-
}
|
|
462
|
-
stack.push(diagnostic);
|
|
463
|
-
return this;
|
|
464
|
-
},
|
|
465
|
-
onDiagnostic(listener) {
|
|
466
|
-
addListener("diagnostic", listener);
|
|
467
|
-
return this;
|
|
468
|
-
},
|
|
469
|
-
on(kind, listener) {
|
|
470
|
-
addListener(`diagnostic.${kind}`, listener);
|
|
471
|
-
return this;
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
};
|
|
475
479
|
class ProviderError extends DataTransferError {
|
|
476
480
|
constructor(severity, message, details) {
|
|
477
481
|
super("provider", severity, message, details);
|
|
@@ -604,7 +608,7 @@ class TransferEngine {
|
|
|
604
608
|
reportInfo(message, params) {
|
|
605
609
|
this.diagnostics.report({
|
|
606
610
|
kind: "info",
|
|
607
|
-
details: { createdAt: /* @__PURE__ */ new Date(), message, params }
|
|
611
|
+
details: { createdAt: /* @__PURE__ */ new Date(), message, params, origin: "engine" }
|
|
608
612
|
});
|
|
609
613
|
}
|
|
610
614
|
/**
|
|
@@ -896,8 +900,8 @@ ${formattedDiffs}`,
|
|
|
896
900
|
*/
|
|
897
901
|
async bootstrap() {
|
|
898
902
|
const results = await Promise.allSettled([
|
|
899
|
-
this.sourceProvider.bootstrap?.(),
|
|
900
|
-
this.destinationProvider.bootstrap?.()
|
|
903
|
+
this.sourceProvider.bootstrap?.(this.diagnostics),
|
|
904
|
+
this.destinationProvider.bootstrap?.(this.diagnostics)
|
|
901
905
|
]);
|
|
902
906
|
results.forEach((result) => {
|
|
903
907
|
if (result.status === "rejected") {
|
|
@@ -1902,6 +1906,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1902
1906
|
transaction;
|
|
1903
1907
|
uploadsBackupDirectoryName;
|
|
1904
1908
|
onWarning;
|
|
1909
|
+
#diagnostics;
|
|
1905
1910
|
/**
|
|
1906
1911
|
* The entities mapper is used to map old entities to their new IDs
|
|
1907
1912
|
*/
|
|
@@ -1911,7 +1916,8 @@ class LocalStrapiDestinationProvider {
|
|
|
1911
1916
|
this.#entitiesMapper = {};
|
|
1912
1917
|
this.uploadsBackupDirectoryName = `uploads_backup_${Date.now()}`;
|
|
1913
1918
|
}
|
|
1914
|
-
async bootstrap() {
|
|
1919
|
+
async bootstrap(diagnostics) {
|
|
1920
|
+
this.#diagnostics = diagnostics;
|
|
1915
1921
|
this.#validateOptions();
|
|
1916
1922
|
this.strapi = await this.options.getStrapi();
|
|
1917
1923
|
if (!this.strapi) {
|
|
@@ -1928,6 +1934,16 @@ class LocalStrapiDestinationProvider {
|
|
|
1928
1934
|
const excluded = this.options.restore?.entities?.exclude && this.options.restore?.entities.exclude.includes(type);
|
|
1929
1935
|
return !excluded && !notIncluded;
|
|
1930
1936
|
};
|
|
1937
|
+
#reportInfo(message) {
|
|
1938
|
+
this.#diagnostics?.report({
|
|
1939
|
+
details: {
|
|
1940
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1941
|
+
message,
|
|
1942
|
+
origin: "local-destination-provider"
|
|
1943
|
+
},
|
|
1944
|
+
kind: "info"
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1931
1947
|
async close() {
|
|
1932
1948
|
const { autoDestroy } = this.options;
|
|
1933
1949
|
this.transaction?.end();
|
|
@@ -1936,6 +1952,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1936
1952
|
}
|
|
1937
1953
|
}
|
|
1938
1954
|
#validateOptions() {
|
|
1955
|
+
this.#reportInfo("validating options");
|
|
1939
1956
|
if (!VALID_CONFLICT_STRATEGIES.includes(this.options.strategy)) {
|
|
1940
1957
|
throw new ProviderValidationError(`Invalid strategy ${this.options.strategy}`, {
|
|
1941
1958
|
check: "strategy",
|
|
@@ -1952,10 +1969,12 @@ class LocalStrapiDestinationProvider {
|
|
|
1952
1969
|
if (!this.options.restore) {
|
|
1953
1970
|
throw new ProviderValidationError("Missing restore options");
|
|
1954
1971
|
}
|
|
1972
|
+
this.#reportInfo("deleting record ");
|
|
1955
1973
|
return deleteRecords(this.strapi, this.options.restore);
|
|
1956
1974
|
}
|
|
1957
1975
|
async #deleteAllAssets(trx) {
|
|
1958
1976
|
assertValidStrapi(this.strapi);
|
|
1977
|
+
this.#reportInfo("deleting all assets");
|
|
1959
1978
|
if (!this.#areAssetsIncluded()) {
|
|
1960
1979
|
return;
|
|
1961
1980
|
}
|
|
@@ -1968,9 +1987,12 @@ class LocalStrapiDestinationProvider {
|
|
|
1968
1987
|
}
|
|
1969
1988
|
}
|
|
1970
1989
|
}
|
|
1990
|
+
this.#reportInfo("deleted all assets");
|
|
1971
1991
|
}
|
|
1972
1992
|
async rollback() {
|
|
1993
|
+
this.#reportInfo("Rolling back transaction");
|
|
1973
1994
|
await this.transaction?.rollback();
|
|
1995
|
+
this.#reportInfo("Rolled back transaction");
|
|
1974
1996
|
}
|
|
1975
1997
|
async beforeTransfer() {
|
|
1976
1998
|
if (!this.strapi) {
|
|
@@ -1989,6 +2011,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1989
2011
|
});
|
|
1990
2012
|
}
|
|
1991
2013
|
getMetadata() {
|
|
2014
|
+
this.#reportInfo("getting metadata");
|
|
1992
2015
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
1993
2016
|
const strapiVersion = this.strapi.config.get("info.strapi");
|
|
1994
2017
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2000,6 +2023,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2000
2023
|
};
|
|
2001
2024
|
}
|
|
2002
2025
|
getSchemas() {
|
|
2026
|
+
this.#reportInfo("getting schema");
|
|
2003
2027
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
2004
2028
|
const schemas = schemasToValidJSON({
|
|
2005
2029
|
...this.strapi.contentTypes,
|
|
@@ -2009,6 +2033,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2009
2033
|
}
|
|
2010
2034
|
createEntitiesWriteStream() {
|
|
2011
2035
|
assertValidStrapi(this.strapi, "Not able to import entities");
|
|
2036
|
+
this.#reportInfo("creating entities stream");
|
|
2012
2037
|
const { strategy } = this.options;
|
|
2013
2038
|
const updateMappingTable = (type, oldID, newID) => {
|
|
2014
2039
|
if (!this.#entitiesMapper[type]) {
|
|
@@ -2035,6 +2060,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2035
2060
|
return;
|
|
2036
2061
|
}
|
|
2037
2062
|
if (this.strapi.config.get("plugin::upload").provider === "local") {
|
|
2063
|
+
this.#reportInfo("creating assets backup directory");
|
|
2038
2064
|
const assetsDirectory = path__default.default.join(this.strapi.dirs.static.public, "uploads");
|
|
2039
2065
|
const backupDirectory = path__default.default.join(
|
|
2040
2066
|
this.strapi.dirs.static.public,
|
|
@@ -2050,6 +2076,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2050
2076
|
await fse__namespace.move(assetsDirectory, backupDirectory);
|
|
2051
2077
|
await fse__namespace.mkdir(assetsDirectory);
|
|
2052
2078
|
await fse__namespace.outputFile(path__default.default.join(assetsDirectory, ".gitkeep"), "");
|
|
2079
|
+
this.#reportInfo(`created assets backup directory ${backupDirectory}`);
|
|
2053
2080
|
} catch (err) {
|
|
2054
2081
|
throw new ProviderTransferError(
|
|
2055
2082
|
"The backup folder for the assets could not be created inside the public folder. Please ensure Strapi has write permissions on the public directory",
|
|
@@ -2067,17 +2094,20 @@ class LocalStrapiDestinationProvider {
|
|
|
2067
2094
|
return;
|
|
2068
2095
|
}
|
|
2069
2096
|
if (this.strapi.config.get("plugin::upload").provider === "local") {
|
|
2097
|
+
this.#reportInfo("removing assets backup");
|
|
2070
2098
|
assertValidStrapi(this.strapi);
|
|
2071
2099
|
const backupDirectory = path__default.default.join(
|
|
2072
2100
|
this.strapi.dirs.static.public,
|
|
2073
2101
|
this.uploadsBackupDirectoryName
|
|
2074
2102
|
);
|
|
2075
2103
|
await fse__namespace.rm(backupDirectory, { recursive: true, force: true });
|
|
2104
|
+
this.#reportInfo("successfully removed assets backup");
|
|
2076
2105
|
}
|
|
2077
2106
|
}
|
|
2078
2107
|
// TODO: Move this logic to the restore strategy
|
|
2079
2108
|
async createAssetsWriteStream() {
|
|
2080
2109
|
assertValidStrapi(this.strapi, "Not able to stream Assets");
|
|
2110
|
+
this.#reportInfo("creating assets write stream");
|
|
2081
2111
|
if (!this.#areAssetsIncluded()) {
|
|
2082
2112
|
throw new ProviderTransferError(
|
|
2083
2113
|
"Attempting to transfer assets when `assets` is not set in restore options"
|
|
@@ -2086,7 +2116,6 @@ class LocalStrapiDestinationProvider {
|
|
|
2086
2116
|
const removeAssetsBackup = this.#removeAssetsBackup.bind(this);
|
|
2087
2117
|
const strapi2 = this.strapi;
|
|
2088
2118
|
const transaction2 = this.transaction;
|
|
2089
|
-
const backupDirectory = this.uploadsBackupDirectoryName;
|
|
2090
2119
|
const fileEntitiesMapper = this.#entitiesMapper["plugin::upload.file"];
|
|
2091
2120
|
const restoreMediaEntitiesContent = this.#isContentTypeIncluded("plugin::upload.file");
|
|
2092
2121
|
return new stream$1.Writable({
|
|
@@ -2097,47 +2126,28 @@ class LocalStrapiDestinationProvider {
|
|
|
2097
2126
|
},
|
|
2098
2127
|
async write(chunk, _encoding, callback) {
|
|
2099
2128
|
await transaction2?.attach(async () => {
|
|
2100
|
-
if (!chunk.metadata) {
|
|
2101
|
-
const assetsDirectory = path__default.default.join(strapi2.dirs.static.public, "uploads");
|
|
2102
|
-
const entryPath = path__default.default.join(assetsDirectory, chunk.filename);
|
|
2103
|
-
const writableStream = fse__namespace.createWriteStream(entryPath);
|
|
2104
|
-
chunk.stream.pipe(writableStream).on("close", () => {
|
|
2105
|
-
callback(null);
|
|
2106
|
-
}).on("error", async (error) => {
|
|
2107
|
-
const errorMessage = error.code === "ENOSPC" ? " Your server doesn't have space to proceed with the import. " : " ";
|
|
2108
|
-
try {
|
|
2109
|
-
await fse__namespace.rm(assetsDirectory, { recursive: true, force: true });
|
|
2110
|
-
this.destroy(
|
|
2111
|
-
new ProviderTransferError(
|
|
2112
|
-
`There was an error during the transfer process.${errorMessage}The original files have been restored to ${assetsDirectory}`
|
|
2113
|
-
)
|
|
2114
|
-
);
|
|
2115
|
-
} catch (err) {
|
|
2116
|
-
throw new ProviderTransferError(
|
|
2117
|
-
`There was an error doing the rollback process. The original files are in ${backupDirectory}, but we failed to restore them to ${assetsDirectory}`
|
|
2118
|
-
);
|
|
2119
|
-
} finally {
|
|
2120
|
-
callback(error);
|
|
2121
|
-
}
|
|
2122
|
-
});
|
|
2123
|
-
return;
|
|
2124
|
-
}
|
|
2125
2129
|
const uploadData = {
|
|
2126
2130
|
...chunk.metadata,
|
|
2127
2131
|
stream: stream$1.Readable.from(chunk.stream),
|
|
2128
2132
|
buffer: chunk?.buffer
|
|
2129
2133
|
};
|
|
2130
2134
|
const provider = strapi2.config.get("plugin::upload").provider;
|
|
2135
|
+
const fileId = fileEntitiesMapper?.[uploadData.id];
|
|
2136
|
+
if (!fileId) {
|
|
2137
|
+
callback(new Error(`File ID not found for ID: ${uploadData.id}`));
|
|
2138
|
+
}
|
|
2131
2139
|
try {
|
|
2132
2140
|
await strapi2.plugin("upload").provider.uploadStream(uploadData);
|
|
2133
2141
|
if (!restoreMediaEntitiesContent) {
|
|
2134
2142
|
return callback();
|
|
2135
2143
|
}
|
|
2136
2144
|
if (uploadData?.type) {
|
|
2137
|
-
const condition = uploadData?.id ? { id: fileEntitiesMapper[uploadData.id] } : { hash: uploadData.mainHash };
|
|
2138
2145
|
const entry2 = await strapi2.db.query("plugin::upload.file").findOne({
|
|
2139
|
-
where:
|
|
2146
|
+
where: { id: fileId }
|
|
2140
2147
|
});
|
|
2148
|
+
if (!entry2) {
|
|
2149
|
+
throw new Error("file not found");
|
|
2150
|
+
}
|
|
2141
2151
|
const specificFormat = entry2?.formats?.[uploadData.type];
|
|
2142
2152
|
if (specificFormat) {
|
|
2143
2153
|
specificFormat.url = uploadData.url;
|
|
@@ -2152,8 +2162,11 @@ class LocalStrapiDestinationProvider {
|
|
|
2152
2162
|
return callback();
|
|
2153
2163
|
}
|
|
2154
2164
|
const entry = await strapi2.db.query("plugin::upload.file").findOne({
|
|
2155
|
-
where: { id:
|
|
2165
|
+
where: { id: fileId }
|
|
2156
2166
|
});
|
|
2167
|
+
if (!entry) {
|
|
2168
|
+
throw new Error("file not found");
|
|
2169
|
+
}
|
|
2157
2170
|
entry.url = uploadData.url;
|
|
2158
2171
|
await strapi2.db.query("plugin::upload.file").update({
|
|
2159
2172
|
where: { id: entry.id },
|
|
@@ -2172,6 +2185,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2172
2185
|
}
|
|
2173
2186
|
async createConfigurationWriteStream() {
|
|
2174
2187
|
assertValidStrapi(this.strapi, "Not able to stream Configurations");
|
|
2188
|
+
this.#reportInfo("creating configuration write stream");
|
|
2175
2189
|
const { strategy } = this.options;
|
|
2176
2190
|
if (strategy === "restore") {
|
|
2177
2191
|
return createConfigurationWriteStream(this.strapi, this.transaction);
|
|
@@ -2183,6 +2197,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2183
2197
|
});
|
|
2184
2198
|
}
|
|
2185
2199
|
async createLinksWriteStream() {
|
|
2200
|
+
this.#reportInfo("creating links write stream");
|
|
2186
2201
|
if (!this.strapi) {
|
|
2187
2202
|
throw new Error("Not able to stream links. Strapi instance not found");
|
|
2188
2203
|
}
|
|
@@ -2381,12 +2396,24 @@ class LocalStrapiSourceProvider {
|
|
|
2381
2396
|
type = "source";
|
|
2382
2397
|
options;
|
|
2383
2398
|
strapi;
|
|
2399
|
+
#diagnostics;
|
|
2384
2400
|
constructor(options) {
|
|
2385
2401
|
this.options = options;
|
|
2386
2402
|
}
|
|
2387
|
-
async bootstrap() {
|
|
2403
|
+
async bootstrap(diagnostics) {
|
|
2404
|
+
this.#diagnostics = diagnostics;
|
|
2388
2405
|
this.strapi = await this.options.getStrapi();
|
|
2389
2406
|
}
|
|
2407
|
+
#reportInfo(message) {
|
|
2408
|
+
this.#diagnostics?.report({
|
|
2409
|
+
details: {
|
|
2410
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2411
|
+
message,
|
|
2412
|
+
origin: "local-source-provider"
|
|
2413
|
+
},
|
|
2414
|
+
kind: "info"
|
|
2415
|
+
});
|
|
2416
|
+
}
|
|
2390
2417
|
async close() {
|
|
2391
2418
|
const { autoDestroy } = this.options;
|
|
2392
2419
|
if (autoDestroy === void 0 || autoDestroy === true) {
|
|
@@ -2394,6 +2421,7 @@ class LocalStrapiSourceProvider {
|
|
|
2394
2421
|
}
|
|
2395
2422
|
}
|
|
2396
2423
|
getMetadata() {
|
|
2424
|
+
this.#reportInfo("getting metadata");
|
|
2397
2425
|
const strapiVersion = strapi.config.get("info.strapi");
|
|
2398
2426
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2399
2427
|
return {
|
|
@@ -2405,6 +2433,7 @@ class LocalStrapiSourceProvider {
|
|
|
2405
2433
|
}
|
|
2406
2434
|
async createEntitiesReadStream() {
|
|
2407
2435
|
assertValidStrapi(this.strapi, "Not able to stream entities");
|
|
2436
|
+
this.#reportInfo("creating entities read stream");
|
|
2408
2437
|
return streamChain.chain([
|
|
2409
2438
|
// Entities stream
|
|
2410
2439
|
createEntitiesStream(this.strapi),
|
|
@@ -2414,14 +2443,17 @@ class LocalStrapiSourceProvider {
|
|
|
2414
2443
|
}
|
|
2415
2444
|
createLinksReadStream() {
|
|
2416
2445
|
assertValidStrapi(this.strapi, "Not able to stream links");
|
|
2446
|
+
this.#reportInfo("creating links read stream");
|
|
2417
2447
|
return createLinksStream(this.strapi);
|
|
2418
2448
|
}
|
|
2419
2449
|
createConfigurationReadStream() {
|
|
2420
2450
|
assertValidStrapi(this.strapi, "Not able to stream configuration");
|
|
2451
|
+
this.#reportInfo("creating configuration read stream");
|
|
2421
2452
|
return createConfigurationStream(this.strapi);
|
|
2422
2453
|
}
|
|
2423
2454
|
getSchemas() {
|
|
2424
2455
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
2456
|
+
this.#reportInfo("getting schemas");
|
|
2425
2457
|
const schemas = schemasToValidJSON({
|
|
2426
2458
|
...this.strapi.contentTypes,
|
|
2427
2459
|
...this.strapi.components
|
|
@@ -2433,13 +2465,14 @@ class LocalStrapiSourceProvider {
|
|
|
2433
2465
|
}
|
|
2434
2466
|
createAssetsReadStream() {
|
|
2435
2467
|
assertValidStrapi(this.strapi, "Not able to stream assets");
|
|
2468
|
+
this.#reportInfo("creating assets read stream");
|
|
2436
2469
|
return createAssetsStream(this.strapi);
|
|
2437
2470
|
}
|
|
2438
2471
|
}
|
|
2439
2472
|
const createDispatcher = (ws2, retryMessageOptions = {
|
|
2440
2473
|
retryMessageMaxRetries: 5,
|
|
2441
2474
|
retryMessageTimeout: 3e4
|
|
2442
|
-
}) => {
|
|
2475
|
+
}, reportInfo) => {
|
|
2443
2476
|
const state = {};
|
|
2444
2477
|
const dispatch = async (message, options = {}) => {
|
|
2445
2478
|
if (!ws2) {
|
|
@@ -2452,6 +2485,16 @@ const createDispatcher = (ws2, retryMessageOptions = {
|
|
|
2452
2485
|
if (options.attachTransfer) {
|
|
2453
2486
|
Object.assign(payload, { transferID: state.transfer?.id });
|
|
2454
2487
|
}
|
|
2488
|
+
if (message.type === "command") {
|
|
2489
|
+
reportInfo?.(
|
|
2490
|
+
`dispatching message command:${message.command} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2491
|
+
);
|
|
2492
|
+
} else if (message.type === "transfer") {
|
|
2493
|
+
const messageToSend = message;
|
|
2494
|
+
reportInfo?.(
|
|
2495
|
+
`dispatching message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2455
2498
|
const stringifiedPayload = JSON.stringify(payload);
|
|
2456
2499
|
ws2.send(stringifiedPayload, (error) => {
|
|
2457
2500
|
if (error) {
|
|
@@ -2474,6 +2517,16 @@ const createDispatcher = (ws2, retryMessageOptions = {
|
|
|
2474
2517
|
const interval = setInterval(sendPeriodically, retryMessageTimeout);
|
|
2475
2518
|
const onResponse = (raw) => {
|
|
2476
2519
|
const response = JSON.parse(raw.toString());
|
|
2520
|
+
if (message.type === "command") {
|
|
2521
|
+
reportInfo?.(
|
|
2522
|
+
`received response to message command: ${message.command} uuid: ${uuid} sent: ${numberOfTimesMessageWasSent}`
|
|
2523
|
+
);
|
|
2524
|
+
} else if (message.type === "transfer") {
|
|
2525
|
+
const messageToSend = message;
|
|
2526
|
+
reportInfo?.(
|
|
2527
|
+
`received response to message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2477
2530
|
if (response.uuid === uuid) {
|
|
2478
2531
|
clearInterval(interval);
|
|
2479
2532
|
if (response.error) {
|
|
@@ -2530,7 +2583,7 @@ const createDispatcher = (ws2, retryMessageOptions = {
|
|
|
2530
2583
|
dispatchTransferStep
|
|
2531
2584
|
};
|
|
2532
2585
|
};
|
|
2533
|
-
const connectToWebsocket = (address, options) => {
|
|
2586
|
+
const connectToWebsocket = (address, options, diagnostics) => {
|
|
2534
2587
|
return new Promise((resolve, reject2) => {
|
|
2535
2588
|
const server = new ws.WebSocket(address, options);
|
|
2536
2589
|
server.once("open", () => {
|
|
@@ -2564,6 +2617,14 @@ const connectToWebsocket = (address, options) => {
|
|
|
2564
2617
|
)
|
|
2565
2618
|
);
|
|
2566
2619
|
});
|
|
2620
|
+
server.on("message", (raw) => {
|
|
2621
|
+
const response = JSON.parse(raw.toString());
|
|
2622
|
+
if (response.diagnostic) {
|
|
2623
|
+
diagnostics?.report({
|
|
2624
|
+
...response.diagnostic
|
|
2625
|
+
});
|
|
2626
|
+
}
|
|
2627
|
+
});
|
|
2567
2628
|
server.once("error", (err) => {
|
|
2568
2629
|
reject2(
|
|
2569
2630
|
new ProviderTransferError(err.message, {
|
|
@@ -2605,6 +2666,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
2605
2666
|
dispatcher;
|
|
2606
2667
|
transferID;
|
|
2607
2668
|
stats;
|
|
2669
|
+
#diagnostics;
|
|
2608
2670
|
constructor(options) {
|
|
2609
2671
|
this.options = options;
|
|
2610
2672
|
this.ws = null;
|
|
@@ -2731,7 +2793,18 @@ class RemoteStrapiDestinationProvider {
|
|
|
2731
2793
|
}
|
|
2732
2794
|
});
|
|
2733
2795
|
}
|
|
2734
|
-
|
|
2796
|
+
#reportInfo(message) {
|
|
2797
|
+
this.#diagnostics?.report({
|
|
2798
|
+
details: {
|
|
2799
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2800
|
+
message,
|
|
2801
|
+
origin: "remote-destination-provider"
|
|
2802
|
+
},
|
|
2803
|
+
kind: "info"
|
|
2804
|
+
});
|
|
2805
|
+
}
|
|
2806
|
+
async bootstrap(diagnostics) {
|
|
2807
|
+
this.#diagnostics = diagnostics;
|
|
2735
2808
|
const { url, auth } = this.options;
|
|
2736
2809
|
const validProtocols = ["https:", "http:"];
|
|
2737
2810
|
let ws2;
|
|
@@ -2748,11 +2821,12 @@ class RemoteStrapiDestinationProvider {
|
|
|
2748
2821
|
const wsUrl = `${wsProtocol}//${url.host}${trimTrailingSlash(
|
|
2749
2822
|
url.pathname
|
|
2750
2823
|
)}${TRANSFER_PATH}/push`;
|
|
2824
|
+
this.#reportInfo("establishing websocket connection");
|
|
2751
2825
|
if (!auth) {
|
|
2752
|
-
ws2 = await connectToWebsocket(wsUrl);
|
|
2826
|
+
ws2 = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
|
|
2753
2827
|
} else if (auth.type === "token") {
|
|
2754
2828
|
const headers = { Authorization: `Bearer ${auth.token}` };
|
|
2755
|
-
ws2 = await connectToWebsocket(wsUrl, { headers });
|
|
2829
|
+
ws2 = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
|
|
2756
2830
|
} else {
|
|
2757
2831
|
throw new ProviderValidationError("Auth method not available", {
|
|
2758
2832
|
check: "auth.type",
|
|
@@ -2761,10 +2835,19 @@ class RemoteStrapiDestinationProvider {
|
|
|
2761
2835
|
}
|
|
2762
2836
|
});
|
|
2763
2837
|
}
|
|
2838
|
+
this.#reportInfo("established websocket connection");
|
|
2764
2839
|
this.ws = ws2;
|
|
2765
2840
|
const { retryMessageOptions } = this.options;
|
|
2766
|
-
this
|
|
2841
|
+
this.#reportInfo("creating dispatcher");
|
|
2842
|
+
this.dispatcher = createDispatcher(
|
|
2843
|
+
this.ws,
|
|
2844
|
+
retryMessageOptions,
|
|
2845
|
+
(message) => this.#reportInfo(message)
|
|
2846
|
+
);
|
|
2847
|
+
this.#reportInfo("created dispatcher");
|
|
2848
|
+
this.#reportInfo("initialize transfer");
|
|
2767
2849
|
this.transferID = await this.initTransfer();
|
|
2850
|
+
this.#reportInfo(`initialized transfer ${this.transferID}`);
|
|
2768
2851
|
this.dispatcher.setTransferProperties({ id: this.transferID, kind: "push" });
|
|
2769
2852
|
await this.dispatcher.dispatchTransferAction("bootstrap");
|
|
2770
2853
|
}
|
|
@@ -2891,6 +2974,7 @@ class RemoteStrapiSourceProvider {
|
|
|
2891
2974
|
this.dispatcher = null;
|
|
2892
2975
|
}
|
|
2893
2976
|
results;
|
|
2977
|
+
#diagnostics;
|
|
2894
2978
|
async #createStageReadStream(stage) {
|
|
2895
2979
|
const startResult = await this.#startStep(stage);
|
|
2896
2980
|
if (startResult instanceof Error) {
|
|
@@ -3073,7 +3157,18 @@ class RemoteStrapiSourceProvider {
|
|
|
3073
3157
|
}
|
|
3074
3158
|
return res.transferID;
|
|
3075
3159
|
}
|
|
3076
|
-
|
|
3160
|
+
#reportInfo(message) {
|
|
3161
|
+
this.#diagnostics?.report({
|
|
3162
|
+
details: {
|
|
3163
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3164
|
+
message,
|
|
3165
|
+
origin: "remote-source-provider"
|
|
3166
|
+
},
|
|
3167
|
+
kind: "info"
|
|
3168
|
+
});
|
|
3169
|
+
}
|
|
3170
|
+
async bootstrap(diagnostics) {
|
|
3171
|
+
this.#diagnostics = diagnostics;
|
|
3077
3172
|
const { url, auth } = this.options;
|
|
3078
3173
|
let ws2;
|
|
3079
3174
|
this.assertValidProtocol(url);
|
|
@@ -3081,11 +3176,12 @@ class RemoteStrapiSourceProvider {
|
|
|
3081
3176
|
const wsUrl = `${wsProtocol}//${url.host}${trimTrailingSlash(
|
|
3082
3177
|
url.pathname
|
|
3083
3178
|
)}${TRANSFER_PATH}/pull`;
|
|
3179
|
+
this.#reportInfo("establishing websocket connection");
|
|
3084
3180
|
if (!auth) {
|
|
3085
|
-
ws2 = await connectToWebsocket(wsUrl);
|
|
3181
|
+
ws2 = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
|
|
3086
3182
|
} else if (auth.type === "token") {
|
|
3087
3183
|
const headers = { Authorization: `Bearer ${auth.token}` };
|
|
3088
|
-
ws2 = await connectToWebsocket(wsUrl, { headers });
|
|
3184
|
+
ws2 = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
|
|
3089
3185
|
} else {
|
|
3090
3186
|
throw new ProviderValidationError("Auth method not available", {
|
|
3091
3187
|
check: "auth.type",
|
|
@@ -3094,10 +3190,19 @@ class RemoteStrapiSourceProvider {
|
|
|
3094
3190
|
}
|
|
3095
3191
|
});
|
|
3096
3192
|
}
|
|
3193
|
+
this.#reportInfo("established websocket connection");
|
|
3097
3194
|
this.ws = ws2;
|
|
3098
3195
|
const { retryMessageOptions } = this.options;
|
|
3099
|
-
this
|
|
3196
|
+
this.#reportInfo("creating dispatcher");
|
|
3197
|
+
this.dispatcher = createDispatcher(
|
|
3198
|
+
this.ws,
|
|
3199
|
+
retryMessageOptions,
|
|
3200
|
+
(message) => this.#reportInfo(message)
|
|
3201
|
+
);
|
|
3202
|
+
this.#reportInfo("creating dispatcher");
|
|
3203
|
+
this.#reportInfo("initialize transfer");
|
|
3100
3204
|
const transferID = await this.initTransfer();
|
|
3205
|
+
this.#reportInfo(`initialized transfer ${transferID}`);
|
|
3101
3206
|
this.dispatcher.setTransferProperties({ id: transferID, kind: "pull" });
|
|
3102
3207
|
await this.dispatcher.dispatchTransferAction("bootstrap");
|
|
3103
3208
|
}
|
|
@@ -3327,6 +3432,7 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3327
3432
|
const cb = (ws2) => {
|
|
3328
3433
|
const state = { id: void 0 };
|
|
3329
3434
|
const messageUUIDs = /* @__PURE__ */ new Set();
|
|
3435
|
+
const diagnostics = createDiagnosticReporter();
|
|
3330
3436
|
const cannotRespondHandler = (err) => {
|
|
3331
3437
|
strapi?.log?.error(
|
|
3332
3438
|
"[Data transfer] Cannot send error response to client, closing connection"
|
|
@@ -3360,6 +3466,9 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3360
3466
|
set response(response) {
|
|
3361
3467
|
state.response = response;
|
|
3362
3468
|
},
|
|
3469
|
+
get diagnostics() {
|
|
3470
|
+
return diagnostics;
|
|
3471
|
+
},
|
|
3363
3472
|
addUUID(uuid) {
|
|
3364
3473
|
messageUUIDs.add(uuid);
|
|
3365
3474
|
},
|
|
@@ -3475,6 +3584,10 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3475
3584
|
onError() {
|
|
3476
3585
|
},
|
|
3477
3586
|
onClose() {
|
|
3587
|
+
},
|
|
3588
|
+
onInfo() {
|
|
3589
|
+
},
|
|
3590
|
+
onWarning() {
|
|
3478
3591
|
}
|
|
3479
3592
|
};
|
|
3480
3593
|
const handler = Object.assign(Object.create(prototype), implementation(prototype));
|
|
@@ -3507,6 +3620,14 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3507
3620
|
cannotRespondHandler(err);
|
|
3508
3621
|
}
|
|
3509
3622
|
});
|
|
3623
|
+
diagnostics.onDiagnostic((diagnostic2) => {
|
|
3624
|
+
const uuid = crypto.randomUUID();
|
|
3625
|
+
const payload = JSON.stringify({
|
|
3626
|
+
diagnostic: diagnostic2,
|
|
3627
|
+
uuid
|
|
3628
|
+
});
|
|
3629
|
+
handler.send(payload);
|
|
3630
|
+
});
|
|
3510
3631
|
};
|
|
3511
3632
|
try {
|
|
3512
3633
|
handleWSUpgrade(wss, ctx, cb);
|
|
@@ -3542,6 +3663,26 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3542
3663
|
verifyAuth() {
|
|
3543
3664
|
return proto.verifyAuth.call(this, TRANSFER_KIND$1);
|
|
3544
3665
|
},
|
|
3666
|
+
onInfo(message) {
|
|
3667
|
+
this.diagnostics?.report({
|
|
3668
|
+
details: {
|
|
3669
|
+
message,
|
|
3670
|
+
origin: "push-handler",
|
|
3671
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3672
|
+
},
|
|
3673
|
+
kind: "info"
|
|
3674
|
+
});
|
|
3675
|
+
},
|
|
3676
|
+
onWarning(message) {
|
|
3677
|
+
this.diagnostics?.report({
|
|
3678
|
+
details: {
|
|
3679
|
+
message,
|
|
3680
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3681
|
+
origin: "push-handler"
|
|
3682
|
+
},
|
|
3683
|
+
kind: "warning"
|
|
3684
|
+
});
|
|
3685
|
+
},
|
|
3545
3686
|
cleanup() {
|
|
3546
3687
|
proto.cleanup.call(this);
|
|
3547
3688
|
this.streams = {};
|
|
@@ -3618,6 +3759,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3618
3759
|
proto.addUUID(uuid);
|
|
3619
3760
|
if (type === "command") {
|
|
3620
3761
|
const { command } = msg;
|
|
3762
|
+
this.onInfo(`received command:${command} uuid:${uuid}`);
|
|
3621
3763
|
await this.executeAndRespond(uuid, () => {
|
|
3622
3764
|
this.assertValidTransferCommand(command);
|
|
3623
3765
|
if (command === "status") {
|
|
@@ -3626,6 +3768,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3626
3768
|
return this[command](msg.params);
|
|
3627
3769
|
});
|
|
3628
3770
|
} else if (type === "transfer") {
|
|
3771
|
+
this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
|
|
3629
3772
|
await this.executeAndRespond(uuid, async () => {
|
|
3630
3773
|
await this.verifyAuth();
|
|
3631
3774
|
this.assertValidTransfer();
|
|
@@ -3727,6 +3870,9 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3727
3870
|
}
|
|
3728
3871
|
this.flow?.set(step);
|
|
3729
3872
|
}
|
|
3873
|
+
if (action === "bootstrap") {
|
|
3874
|
+
return this.provider?.[action](this.diagnostics);
|
|
3875
|
+
}
|
|
3730
3876
|
return this.provider?.[action]();
|
|
3731
3877
|
},
|
|
3732
3878
|
async streamAsset(payload) {
|
|
@@ -3792,6 +3938,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3792
3938
|
getStrapi: () => strapi
|
|
3793
3939
|
});
|
|
3794
3940
|
this.provider.onWarning = (message) => {
|
|
3941
|
+
this.onWarning(message);
|
|
3795
3942
|
strapi.log.warn(message);
|
|
3796
3943
|
};
|
|
3797
3944
|
return { transferID: this.transferID };
|
|
@@ -3832,6 +3979,26 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3832
3979
|
this.streams = {};
|
|
3833
3980
|
delete this.provider;
|
|
3834
3981
|
},
|
|
3982
|
+
onInfo(message) {
|
|
3983
|
+
this.diagnostics?.report({
|
|
3984
|
+
details: {
|
|
3985
|
+
message,
|
|
3986
|
+
origin: "pull-handler",
|
|
3987
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3988
|
+
},
|
|
3989
|
+
kind: "info"
|
|
3990
|
+
});
|
|
3991
|
+
},
|
|
3992
|
+
onWarning(message) {
|
|
3993
|
+
this.diagnostics?.report({
|
|
3994
|
+
details: {
|
|
3995
|
+
message,
|
|
3996
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3997
|
+
origin: "pull-handler"
|
|
3998
|
+
},
|
|
3999
|
+
kind: "warning"
|
|
4000
|
+
});
|
|
4001
|
+
},
|
|
3835
4002
|
assertValidTransferAction(action) {
|
|
3836
4003
|
const validActions = VALID_TRANSFER_ACTIONS;
|
|
3837
4004
|
if (validActions.includes(action)) {
|
|
@@ -3861,6 +4028,7 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3861
4028
|
proto.addUUID(uuid);
|
|
3862
4029
|
if (type === "command") {
|
|
3863
4030
|
const { command } = msg;
|
|
4031
|
+
this.onInfo(`received command:${command} uuid:${uuid}`);
|
|
3864
4032
|
await this.executeAndRespond(uuid, () => {
|
|
3865
4033
|
this.assertValidTransferCommand(command);
|
|
3866
4034
|
if (command === "status") {
|
|
@@ -3869,6 +4037,7 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3869
4037
|
return this[command](msg.params);
|
|
3870
4038
|
});
|
|
3871
4039
|
} else if (type === "transfer") {
|
|
4040
|
+
this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
|
|
3872
4041
|
await this.executeAndRespond(uuid, async () => {
|
|
3873
4042
|
await this.verifyAuth();
|
|
3874
4043
|
this.assertValidTransfer();
|
|
@@ -3890,6 +4059,9 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3890
4059
|
async onTransferAction(msg) {
|
|
3891
4060
|
const { action } = msg;
|
|
3892
4061
|
this.assertValidTransferAction(action);
|
|
4062
|
+
if (action === "bootstrap") {
|
|
4063
|
+
return this.provider?.[action](this.diagnostics);
|
|
4064
|
+
}
|
|
3893
4065
|
return this.provider?.[action]();
|
|
3894
4066
|
},
|
|
3895
4067
|
async flush(stage, id) {
|
|
@@ -4088,6 +4260,7 @@ class LocalFileSourceProvider {
|
|
|
4088
4260
|
name = "source::local-file";
|
|
4089
4261
|
options;
|
|
4090
4262
|
#metadata;
|
|
4263
|
+
#diagnostics;
|
|
4091
4264
|
constructor(options) {
|
|
4092
4265
|
this.options = options;
|
|
4093
4266
|
const { encryption } = this.options;
|
|
@@ -4095,10 +4268,21 @@ class LocalFileSourceProvider {
|
|
|
4095
4268
|
throw new Error("Missing encryption key");
|
|
4096
4269
|
}
|
|
4097
4270
|
}
|
|
4271
|
+
#reportInfo(message) {
|
|
4272
|
+
this.#diagnostics?.report({
|
|
4273
|
+
details: {
|
|
4274
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4275
|
+
message,
|
|
4276
|
+
origin: "file-source-provider"
|
|
4277
|
+
},
|
|
4278
|
+
kind: "info"
|
|
4279
|
+
});
|
|
4280
|
+
}
|
|
4098
4281
|
/**
|
|
4099
4282
|
* Pre flight checks regarding the provided options, making sure that the file can be opened (decrypted, decompressed), etc.
|
|
4100
4283
|
*/
|
|
4101
|
-
async bootstrap() {
|
|
4284
|
+
async bootstrap(diagnostics) {
|
|
4285
|
+
this.#diagnostics = diagnostics;
|
|
4102
4286
|
const { path: filePath } = this.options.file;
|
|
4103
4287
|
try {
|
|
4104
4288
|
await this.#loadMetadata();
|
|
@@ -4123,12 +4307,14 @@ class LocalFileSourceProvider {
|
|
|
4123
4307
|
return this.#parseJSONFile(backupStream, path2);
|
|
4124
4308
|
}
|
|
4125
4309
|
async getMetadata() {
|
|
4310
|
+
this.#reportInfo("getting metadata");
|
|
4126
4311
|
if (!this.#metadata) {
|
|
4127
4312
|
await this.#loadMetadata();
|
|
4128
4313
|
}
|
|
4129
4314
|
return this.#metadata ?? null;
|
|
4130
4315
|
}
|
|
4131
4316
|
async getSchemas() {
|
|
4317
|
+
this.#reportInfo("getting schemas");
|
|
4132
4318
|
const schemaCollection = await collect(
|
|
4133
4319
|
this.createSchemasReadStream()
|
|
4134
4320
|
);
|
|
@@ -4139,21 +4325,26 @@ class LocalFileSourceProvider {
|
|
|
4139
4325
|
return schemasToValidJSON(schemas);
|
|
4140
4326
|
}
|
|
4141
4327
|
createEntitiesReadStream() {
|
|
4328
|
+
this.#reportInfo("creating entities read stream");
|
|
4142
4329
|
return this.#streamJsonlDirectory("entities");
|
|
4143
4330
|
}
|
|
4144
4331
|
createSchemasReadStream() {
|
|
4332
|
+
this.#reportInfo("creating schemas read stream");
|
|
4145
4333
|
return this.#streamJsonlDirectory("schemas");
|
|
4146
4334
|
}
|
|
4147
4335
|
createLinksReadStream() {
|
|
4336
|
+
this.#reportInfo("creating links read stream");
|
|
4148
4337
|
return this.#streamJsonlDirectory("links");
|
|
4149
4338
|
}
|
|
4150
4339
|
createConfigurationReadStream() {
|
|
4340
|
+
this.#reportInfo("creating configuration read stream");
|
|
4151
4341
|
return this.#streamJsonlDirectory("configuration");
|
|
4152
4342
|
}
|
|
4153
4343
|
createAssetsReadStream() {
|
|
4154
4344
|
const inStream = this.#getBackupStream();
|
|
4155
4345
|
const outStream = new stream$1.PassThrough({ objectMode: true });
|
|
4156
4346
|
const loadAssetMetadata = this.#loadAssetMetadata.bind(this);
|
|
4347
|
+
this.#reportInfo("creating assets read stream");
|
|
4157
4348
|
stream$1.pipeline(
|
|
4158
4349
|
[
|
|
4159
4350
|
inStream,
|
|
@@ -4173,9 +4364,7 @@ class LocalFileSourceProvider {
|
|
|
4173
4364
|
try {
|
|
4174
4365
|
metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
|
|
4175
4366
|
} catch (error) {
|
|
4176
|
-
|
|
4177
|
-
` Failed to read metadata for ${file}, Strapi will try to fix this issue automatically`
|
|
4178
|
-
);
|
|
4367
|
+
throw new Error(`Failed to read metadata for ${file}`);
|
|
4179
4368
|
}
|
|
4180
4369
|
const asset = {
|
|
4181
4370
|
metadata,
|
|
@@ -4354,9 +4543,20 @@ class LocalFileDestinationProvider {
|
|
|
4354
4543
|
results = {};
|
|
4355
4544
|
#providersMetadata = {};
|
|
4356
4545
|
#archive = {};
|
|
4546
|
+
#diagnostics;
|
|
4357
4547
|
constructor(options) {
|
|
4358
4548
|
this.options = options;
|
|
4359
4549
|
}
|
|
4550
|
+
#reportInfo(message) {
|
|
4551
|
+
this.#diagnostics?.report({
|
|
4552
|
+
details: {
|
|
4553
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4554
|
+
message,
|
|
4555
|
+
origin: "file-destination-provider"
|
|
4556
|
+
},
|
|
4557
|
+
kind: "info"
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4360
4560
|
get #archivePath() {
|
|
4361
4561
|
const { encryption, compression, file } = this.options;
|
|
4362
4562
|
let filePath = `${file.path}.tar`;
|
|
@@ -4373,9 +4573,11 @@ class LocalFileDestinationProvider {
|
|
|
4373
4573
|
return this;
|
|
4374
4574
|
}
|
|
4375
4575
|
createGzip() {
|
|
4576
|
+
this.#reportInfo("creating gzip");
|
|
4376
4577
|
return zip__default.default.createGzip();
|
|
4377
4578
|
}
|
|
4378
|
-
bootstrap() {
|
|
4579
|
+
bootstrap(diagnostics) {
|
|
4580
|
+
this.#diagnostics = diagnostics;
|
|
4379
4581
|
const { compression, encryption } = this.options;
|
|
4380
4582
|
if (encryption.enabled && !encryption.key) {
|
|
4381
4583
|
throw new Error("Can't encrypt without a key");
|
|
@@ -4414,6 +4616,7 @@ class LocalFileDestinationProvider {
|
|
|
4414
4616
|
}
|
|
4415
4617
|
}
|
|
4416
4618
|
async rollback() {
|
|
4619
|
+
this.#reportInfo("rolling back");
|
|
4417
4620
|
await this.close();
|
|
4418
4621
|
await fse.rm(this.#archivePath, { force: true });
|
|
4419
4622
|
}
|
|
@@ -4421,6 +4624,7 @@ class LocalFileDestinationProvider {
|
|
|
4421
4624
|
return null;
|
|
4422
4625
|
}
|
|
4423
4626
|
async #writeMetadata() {
|
|
4627
|
+
this.#reportInfo("writing metadata");
|
|
4424
4628
|
const metadata = this.#providersMetadata.source;
|
|
4425
4629
|
if (metadata) {
|
|
4426
4630
|
await new Promise((resolve) => {
|
|
@@ -4441,6 +4645,7 @@ class LocalFileDestinationProvider {
|
|
|
4441
4645
|
if (!this.#archive.stream) {
|
|
4442
4646
|
throw new Error("Archive stream is unavailable");
|
|
4443
4647
|
}
|
|
4648
|
+
this.#reportInfo("creating schemas write stream");
|
|
4444
4649
|
const filePathFactory = createFilePathFactory("schemas");
|
|
4445
4650
|
const entryStream = createTarEntryStream(
|
|
4446
4651
|
this.#archive.stream,
|
|
@@ -4453,6 +4658,7 @@ class LocalFileDestinationProvider {
|
|
|
4453
4658
|
if (!this.#archive.stream) {
|
|
4454
4659
|
throw new Error("Archive stream is unavailable");
|
|
4455
4660
|
}
|
|
4661
|
+
this.#reportInfo("creating entities write stream");
|
|
4456
4662
|
const filePathFactory = createFilePathFactory("entities");
|
|
4457
4663
|
const entryStream = createTarEntryStream(
|
|
4458
4664
|
this.#archive.stream,
|
|
@@ -4465,6 +4671,7 @@ class LocalFileDestinationProvider {
|
|
|
4465
4671
|
if (!this.#archive.stream) {
|
|
4466
4672
|
throw new Error("Archive stream is unavailable");
|
|
4467
4673
|
}
|
|
4674
|
+
this.#reportInfo("creating links write stream");
|
|
4468
4675
|
const filePathFactory = createFilePathFactory("links");
|
|
4469
4676
|
const entryStream = createTarEntryStream(
|
|
4470
4677
|
this.#archive.stream,
|
|
@@ -4477,6 +4684,7 @@ class LocalFileDestinationProvider {
|
|
|
4477
4684
|
if (!this.#archive.stream) {
|
|
4478
4685
|
throw new Error("Archive stream is unavailable");
|
|
4479
4686
|
}
|
|
4687
|
+
this.#reportInfo("creating configuration write stream");
|
|
4480
4688
|
const filePathFactory = createFilePathFactory("configuration");
|
|
4481
4689
|
const entryStream = createTarEntryStream(
|
|
4482
4690
|
this.#archive.stream,
|
|
@@ -4490,6 +4698,7 @@ class LocalFileDestinationProvider {
|
|
|
4490
4698
|
if (!archiveStream) {
|
|
4491
4699
|
throw new Error("Archive stream is unavailable");
|
|
4492
4700
|
}
|
|
4701
|
+
this.#reportInfo("creating assets write stream");
|
|
4493
4702
|
return new stream$1.Writable({
|
|
4494
4703
|
objectMode: true,
|
|
4495
4704
|
write(data, _encoding, callback) {
|