@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.mjs
CHANGED
|
@@ -298,8 +298,57 @@ const middleware = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
298
298
|
__proto__: null,
|
|
299
299
|
runMiddleware
|
|
300
300
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
301
|
+
const createDiagnosticReporter = (options = {}) => {
|
|
302
|
+
const { stackSize = -1 } = options;
|
|
303
|
+
const emitter = new EventEmitter();
|
|
304
|
+
const stack = [];
|
|
305
|
+
const addListener = (event, listener) => {
|
|
306
|
+
emitter.on(event, listener);
|
|
307
|
+
};
|
|
308
|
+
const isDiagnosticValid = (diagnostic2) => {
|
|
309
|
+
if (!diagnostic2.kind || !diagnostic2.details || !diagnostic2.details.message) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
return true;
|
|
313
|
+
};
|
|
314
|
+
return {
|
|
315
|
+
stack: {
|
|
316
|
+
get size() {
|
|
317
|
+
return stack.length;
|
|
318
|
+
},
|
|
319
|
+
get items() {
|
|
320
|
+
return stack;
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
report(diagnostic2) {
|
|
324
|
+
if (!isDiagnosticValid(diagnostic2)) {
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
emitter.emit("diagnostic", diagnostic2);
|
|
328
|
+
emitter.emit(`diagnostic.${diagnostic2.kind}`, diagnostic2);
|
|
329
|
+
if (stackSize !== -1 && stack.length >= stackSize) {
|
|
330
|
+
stack.shift();
|
|
331
|
+
}
|
|
332
|
+
stack.push(diagnostic2);
|
|
333
|
+
return this;
|
|
334
|
+
},
|
|
335
|
+
onDiagnostic(listener) {
|
|
336
|
+
addListener("diagnostic", listener);
|
|
337
|
+
return this;
|
|
338
|
+
},
|
|
339
|
+
on(kind, listener) {
|
|
340
|
+
addListener(`diagnostic.${kind}`, listener);
|
|
341
|
+
return this;
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
const diagnostic = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
346
|
+
__proto__: null,
|
|
347
|
+
createDiagnosticReporter
|
|
348
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
301
349
|
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
302
350
|
__proto__: null,
|
|
351
|
+
diagnostics: diagnostic,
|
|
303
352
|
encryption: index$9,
|
|
304
353
|
json,
|
|
305
354
|
middleware,
|
|
@@ -400,50 +449,6 @@ const validateProvider = (type, provider) => {
|
|
|
400
449
|
);
|
|
401
450
|
}
|
|
402
451
|
};
|
|
403
|
-
const createDiagnosticReporter = (options = {}) => {
|
|
404
|
-
const { stackSize = -1 } = options;
|
|
405
|
-
const emitter = new EventEmitter();
|
|
406
|
-
const stack = [];
|
|
407
|
-
const addListener = (event, listener) => {
|
|
408
|
-
emitter.on(event, listener);
|
|
409
|
-
};
|
|
410
|
-
const isDiagnosticValid = (diagnostic) => {
|
|
411
|
-
if (!diagnostic.kind || !diagnostic.details || !diagnostic.details.message) {
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
return true;
|
|
415
|
-
};
|
|
416
|
-
return {
|
|
417
|
-
stack: {
|
|
418
|
-
get size() {
|
|
419
|
-
return stack.length;
|
|
420
|
-
},
|
|
421
|
-
get items() {
|
|
422
|
-
return stack;
|
|
423
|
-
}
|
|
424
|
-
},
|
|
425
|
-
report(diagnostic) {
|
|
426
|
-
if (!isDiagnosticValid(diagnostic)) {
|
|
427
|
-
return this;
|
|
428
|
-
}
|
|
429
|
-
emitter.emit("diagnostic", diagnostic);
|
|
430
|
-
emitter.emit(`diagnostic.${diagnostic.kind}`, diagnostic);
|
|
431
|
-
if (stackSize !== -1 && stack.length >= stackSize) {
|
|
432
|
-
stack.shift();
|
|
433
|
-
}
|
|
434
|
-
stack.push(diagnostic);
|
|
435
|
-
return this;
|
|
436
|
-
},
|
|
437
|
-
onDiagnostic(listener) {
|
|
438
|
-
addListener("diagnostic", listener);
|
|
439
|
-
return this;
|
|
440
|
-
},
|
|
441
|
-
on(kind, listener) {
|
|
442
|
-
addListener(`diagnostic.${kind}`, listener);
|
|
443
|
-
return this;
|
|
444
|
-
}
|
|
445
|
-
};
|
|
446
|
-
};
|
|
447
452
|
class ProviderError extends DataTransferError {
|
|
448
453
|
constructor(severity, message, details) {
|
|
449
454
|
super("provider", severity, message, details);
|
|
@@ -576,7 +581,7 @@ class TransferEngine {
|
|
|
576
581
|
reportInfo(message, params) {
|
|
577
582
|
this.diagnostics.report({
|
|
578
583
|
kind: "info",
|
|
579
|
-
details: { createdAt: /* @__PURE__ */ new Date(), message, params }
|
|
584
|
+
details: { createdAt: /* @__PURE__ */ new Date(), message, params, origin: "engine" }
|
|
580
585
|
});
|
|
581
586
|
}
|
|
582
587
|
/**
|
|
@@ -868,8 +873,8 @@ ${formattedDiffs}`,
|
|
|
868
873
|
*/
|
|
869
874
|
async bootstrap() {
|
|
870
875
|
const results = await Promise.allSettled([
|
|
871
|
-
this.sourceProvider.bootstrap?.(),
|
|
872
|
-
this.destinationProvider.bootstrap?.()
|
|
876
|
+
this.sourceProvider.bootstrap?.(this.diagnostics),
|
|
877
|
+
this.destinationProvider.bootstrap?.(this.diagnostics)
|
|
873
878
|
]);
|
|
874
879
|
results.forEach((result) => {
|
|
875
880
|
if (result.status === "rejected") {
|
|
@@ -1874,6 +1879,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1874
1879
|
transaction;
|
|
1875
1880
|
uploadsBackupDirectoryName;
|
|
1876
1881
|
onWarning;
|
|
1882
|
+
#diagnostics;
|
|
1877
1883
|
/**
|
|
1878
1884
|
* The entities mapper is used to map old entities to their new IDs
|
|
1879
1885
|
*/
|
|
@@ -1883,7 +1889,8 @@ class LocalStrapiDestinationProvider {
|
|
|
1883
1889
|
this.#entitiesMapper = {};
|
|
1884
1890
|
this.uploadsBackupDirectoryName = `uploads_backup_${Date.now()}`;
|
|
1885
1891
|
}
|
|
1886
|
-
async bootstrap() {
|
|
1892
|
+
async bootstrap(diagnostics) {
|
|
1893
|
+
this.#diagnostics = diagnostics;
|
|
1887
1894
|
this.#validateOptions();
|
|
1888
1895
|
this.strapi = await this.options.getStrapi();
|
|
1889
1896
|
if (!this.strapi) {
|
|
@@ -1900,6 +1907,16 @@ class LocalStrapiDestinationProvider {
|
|
|
1900
1907
|
const excluded = this.options.restore?.entities?.exclude && this.options.restore?.entities.exclude.includes(type);
|
|
1901
1908
|
return !excluded && !notIncluded;
|
|
1902
1909
|
};
|
|
1910
|
+
#reportInfo(message) {
|
|
1911
|
+
this.#diagnostics?.report({
|
|
1912
|
+
details: {
|
|
1913
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1914
|
+
message,
|
|
1915
|
+
origin: "local-destination-provider"
|
|
1916
|
+
},
|
|
1917
|
+
kind: "info"
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1903
1920
|
async close() {
|
|
1904
1921
|
const { autoDestroy } = this.options;
|
|
1905
1922
|
this.transaction?.end();
|
|
@@ -1908,6 +1925,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1908
1925
|
}
|
|
1909
1926
|
}
|
|
1910
1927
|
#validateOptions() {
|
|
1928
|
+
this.#reportInfo("validating options");
|
|
1911
1929
|
if (!VALID_CONFLICT_STRATEGIES.includes(this.options.strategy)) {
|
|
1912
1930
|
throw new ProviderValidationError(`Invalid strategy ${this.options.strategy}`, {
|
|
1913
1931
|
check: "strategy",
|
|
@@ -1924,10 +1942,12 @@ class LocalStrapiDestinationProvider {
|
|
|
1924
1942
|
if (!this.options.restore) {
|
|
1925
1943
|
throw new ProviderValidationError("Missing restore options");
|
|
1926
1944
|
}
|
|
1945
|
+
this.#reportInfo("deleting record ");
|
|
1927
1946
|
return deleteRecords(this.strapi, this.options.restore);
|
|
1928
1947
|
}
|
|
1929
1948
|
async #deleteAllAssets(trx) {
|
|
1930
1949
|
assertValidStrapi(this.strapi);
|
|
1950
|
+
this.#reportInfo("deleting all assets");
|
|
1931
1951
|
if (!this.#areAssetsIncluded()) {
|
|
1932
1952
|
return;
|
|
1933
1953
|
}
|
|
@@ -1940,9 +1960,12 @@ class LocalStrapiDestinationProvider {
|
|
|
1940
1960
|
}
|
|
1941
1961
|
}
|
|
1942
1962
|
}
|
|
1963
|
+
this.#reportInfo("deleted all assets");
|
|
1943
1964
|
}
|
|
1944
1965
|
async rollback() {
|
|
1966
|
+
this.#reportInfo("Rolling back transaction");
|
|
1945
1967
|
await this.transaction?.rollback();
|
|
1968
|
+
this.#reportInfo("Rolled back transaction");
|
|
1946
1969
|
}
|
|
1947
1970
|
async beforeTransfer() {
|
|
1948
1971
|
if (!this.strapi) {
|
|
@@ -1961,6 +1984,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1961
1984
|
});
|
|
1962
1985
|
}
|
|
1963
1986
|
getMetadata() {
|
|
1987
|
+
this.#reportInfo("getting metadata");
|
|
1964
1988
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
1965
1989
|
const strapiVersion = this.strapi.config.get("info.strapi");
|
|
1966
1990
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1972,6 +1996,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1972
1996
|
};
|
|
1973
1997
|
}
|
|
1974
1998
|
getSchemas() {
|
|
1999
|
+
this.#reportInfo("getting schema");
|
|
1975
2000
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
1976
2001
|
const schemas = schemasToValidJSON({
|
|
1977
2002
|
...this.strapi.contentTypes,
|
|
@@ -1981,6 +2006,7 @@ class LocalStrapiDestinationProvider {
|
|
|
1981
2006
|
}
|
|
1982
2007
|
createEntitiesWriteStream() {
|
|
1983
2008
|
assertValidStrapi(this.strapi, "Not able to import entities");
|
|
2009
|
+
this.#reportInfo("creating entities stream");
|
|
1984
2010
|
const { strategy } = this.options;
|
|
1985
2011
|
const updateMappingTable = (type, oldID, newID) => {
|
|
1986
2012
|
if (!this.#entitiesMapper[type]) {
|
|
@@ -2007,6 +2033,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2007
2033
|
return;
|
|
2008
2034
|
}
|
|
2009
2035
|
if (this.strapi.config.get("plugin::upload").provider === "local") {
|
|
2036
|
+
this.#reportInfo("creating assets backup directory");
|
|
2010
2037
|
const assetsDirectory = path.join(this.strapi.dirs.static.public, "uploads");
|
|
2011
2038
|
const backupDirectory = path.join(
|
|
2012
2039
|
this.strapi.dirs.static.public,
|
|
@@ -2022,6 +2049,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2022
2049
|
await fse.move(assetsDirectory, backupDirectory);
|
|
2023
2050
|
await fse.mkdir(assetsDirectory);
|
|
2024
2051
|
await fse.outputFile(path.join(assetsDirectory, ".gitkeep"), "");
|
|
2052
|
+
this.#reportInfo(`created assets backup directory ${backupDirectory}`);
|
|
2025
2053
|
} catch (err) {
|
|
2026
2054
|
throw new ProviderTransferError(
|
|
2027
2055
|
"The backup folder for the assets could not be created inside the public folder. Please ensure Strapi has write permissions on the public directory",
|
|
@@ -2039,17 +2067,20 @@ class LocalStrapiDestinationProvider {
|
|
|
2039
2067
|
return;
|
|
2040
2068
|
}
|
|
2041
2069
|
if (this.strapi.config.get("plugin::upload").provider === "local") {
|
|
2070
|
+
this.#reportInfo("removing assets backup");
|
|
2042
2071
|
assertValidStrapi(this.strapi);
|
|
2043
2072
|
const backupDirectory = path.join(
|
|
2044
2073
|
this.strapi.dirs.static.public,
|
|
2045
2074
|
this.uploadsBackupDirectoryName
|
|
2046
2075
|
);
|
|
2047
2076
|
await fse.rm(backupDirectory, { recursive: true, force: true });
|
|
2077
|
+
this.#reportInfo("successfully removed assets backup");
|
|
2048
2078
|
}
|
|
2049
2079
|
}
|
|
2050
2080
|
// TODO: Move this logic to the restore strategy
|
|
2051
2081
|
async createAssetsWriteStream() {
|
|
2052
2082
|
assertValidStrapi(this.strapi, "Not able to stream Assets");
|
|
2083
|
+
this.#reportInfo("creating assets write stream");
|
|
2053
2084
|
if (!this.#areAssetsIncluded()) {
|
|
2054
2085
|
throw new ProviderTransferError(
|
|
2055
2086
|
"Attempting to transfer assets when `assets` is not set in restore options"
|
|
@@ -2058,7 +2089,6 @@ class LocalStrapiDestinationProvider {
|
|
|
2058
2089
|
const removeAssetsBackup = this.#removeAssetsBackup.bind(this);
|
|
2059
2090
|
const strapi2 = this.strapi;
|
|
2060
2091
|
const transaction2 = this.transaction;
|
|
2061
|
-
const backupDirectory = this.uploadsBackupDirectoryName;
|
|
2062
2092
|
const fileEntitiesMapper = this.#entitiesMapper["plugin::upload.file"];
|
|
2063
2093
|
const restoreMediaEntitiesContent = this.#isContentTypeIncluded("plugin::upload.file");
|
|
2064
2094
|
return new Writable({
|
|
@@ -2069,47 +2099,28 @@ class LocalStrapiDestinationProvider {
|
|
|
2069
2099
|
},
|
|
2070
2100
|
async write(chunk, _encoding, callback) {
|
|
2071
2101
|
await transaction2?.attach(async () => {
|
|
2072
|
-
if (!chunk.metadata) {
|
|
2073
|
-
const assetsDirectory = path.join(strapi2.dirs.static.public, "uploads");
|
|
2074
|
-
const entryPath = path.join(assetsDirectory, chunk.filename);
|
|
2075
|
-
const writableStream = fse.createWriteStream(entryPath);
|
|
2076
|
-
chunk.stream.pipe(writableStream).on("close", () => {
|
|
2077
|
-
callback(null);
|
|
2078
|
-
}).on("error", async (error) => {
|
|
2079
|
-
const errorMessage = error.code === "ENOSPC" ? " Your server doesn't have space to proceed with the import. " : " ";
|
|
2080
|
-
try {
|
|
2081
|
-
await fse.rm(assetsDirectory, { recursive: true, force: true });
|
|
2082
|
-
this.destroy(
|
|
2083
|
-
new ProviderTransferError(
|
|
2084
|
-
`There was an error during the transfer process.${errorMessage}The original files have been restored to ${assetsDirectory}`
|
|
2085
|
-
)
|
|
2086
|
-
);
|
|
2087
|
-
} catch (err) {
|
|
2088
|
-
throw new ProviderTransferError(
|
|
2089
|
-
`There was an error doing the rollback process. The original files are in ${backupDirectory}, but we failed to restore them to ${assetsDirectory}`
|
|
2090
|
-
);
|
|
2091
|
-
} finally {
|
|
2092
|
-
callback(error);
|
|
2093
|
-
}
|
|
2094
|
-
});
|
|
2095
|
-
return;
|
|
2096
|
-
}
|
|
2097
2102
|
const uploadData = {
|
|
2098
2103
|
...chunk.metadata,
|
|
2099
2104
|
stream: Readable.from(chunk.stream),
|
|
2100
2105
|
buffer: chunk?.buffer
|
|
2101
2106
|
};
|
|
2102
2107
|
const provider = strapi2.config.get("plugin::upload").provider;
|
|
2108
|
+
const fileId = fileEntitiesMapper?.[uploadData.id];
|
|
2109
|
+
if (!fileId) {
|
|
2110
|
+
callback(new Error(`File ID not found for ID: ${uploadData.id}`));
|
|
2111
|
+
}
|
|
2103
2112
|
try {
|
|
2104
2113
|
await strapi2.plugin("upload").provider.uploadStream(uploadData);
|
|
2105
2114
|
if (!restoreMediaEntitiesContent) {
|
|
2106
2115
|
return callback();
|
|
2107
2116
|
}
|
|
2108
2117
|
if (uploadData?.type) {
|
|
2109
|
-
const condition = uploadData?.id ? { id: fileEntitiesMapper[uploadData.id] } : { hash: uploadData.mainHash };
|
|
2110
2118
|
const entry2 = await strapi2.db.query("plugin::upload.file").findOne({
|
|
2111
|
-
where:
|
|
2119
|
+
where: { id: fileId }
|
|
2112
2120
|
});
|
|
2121
|
+
if (!entry2) {
|
|
2122
|
+
throw new Error("file not found");
|
|
2123
|
+
}
|
|
2113
2124
|
const specificFormat = entry2?.formats?.[uploadData.type];
|
|
2114
2125
|
if (specificFormat) {
|
|
2115
2126
|
specificFormat.url = uploadData.url;
|
|
@@ -2124,8 +2135,11 @@ class LocalStrapiDestinationProvider {
|
|
|
2124
2135
|
return callback();
|
|
2125
2136
|
}
|
|
2126
2137
|
const entry = await strapi2.db.query("plugin::upload.file").findOne({
|
|
2127
|
-
where: { id:
|
|
2138
|
+
where: { id: fileId }
|
|
2128
2139
|
});
|
|
2140
|
+
if (!entry) {
|
|
2141
|
+
throw new Error("file not found");
|
|
2142
|
+
}
|
|
2129
2143
|
entry.url = uploadData.url;
|
|
2130
2144
|
await strapi2.db.query("plugin::upload.file").update({
|
|
2131
2145
|
where: { id: entry.id },
|
|
@@ -2144,6 +2158,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2144
2158
|
}
|
|
2145
2159
|
async createConfigurationWriteStream() {
|
|
2146
2160
|
assertValidStrapi(this.strapi, "Not able to stream Configurations");
|
|
2161
|
+
this.#reportInfo("creating configuration write stream");
|
|
2147
2162
|
const { strategy } = this.options;
|
|
2148
2163
|
if (strategy === "restore") {
|
|
2149
2164
|
return createConfigurationWriteStream(this.strapi, this.transaction);
|
|
@@ -2155,6 +2170,7 @@ class LocalStrapiDestinationProvider {
|
|
|
2155
2170
|
});
|
|
2156
2171
|
}
|
|
2157
2172
|
async createLinksWriteStream() {
|
|
2173
|
+
this.#reportInfo("creating links write stream");
|
|
2158
2174
|
if (!this.strapi) {
|
|
2159
2175
|
throw new Error("Not able to stream links. Strapi instance not found");
|
|
2160
2176
|
}
|
|
@@ -2353,12 +2369,24 @@ class LocalStrapiSourceProvider {
|
|
|
2353
2369
|
type = "source";
|
|
2354
2370
|
options;
|
|
2355
2371
|
strapi;
|
|
2372
|
+
#diagnostics;
|
|
2356
2373
|
constructor(options) {
|
|
2357
2374
|
this.options = options;
|
|
2358
2375
|
}
|
|
2359
|
-
async bootstrap() {
|
|
2376
|
+
async bootstrap(diagnostics) {
|
|
2377
|
+
this.#diagnostics = diagnostics;
|
|
2360
2378
|
this.strapi = await this.options.getStrapi();
|
|
2361
2379
|
}
|
|
2380
|
+
#reportInfo(message) {
|
|
2381
|
+
this.#diagnostics?.report({
|
|
2382
|
+
details: {
|
|
2383
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2384
|
+
message,
|
|
2385
|
+
origin: "local-source-provider"
|
|
2386
|
+
},
|
|
2387
|
+
kind: "info"
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2362
2390
|
async close() {
|
|
2363
2391
|
const { autoDestroy } = this.options;
|
|
2364
2392
|
if (autoDestroy === void 0 || autoDestroy === true) {
|
|
@@ -2366,6 +2394,7 @@ class LocalStrapiSourceProvider {
|
|
|
2366
2394
|
}
|
|
2367
2395
|
}
|
|
2368
2396
|
getMetadata() {
|
|
2397
|
+
this.#reportInfo("getting metadata");
|
|
2369
2398
|
const strapiVersion = strapi.config.get("info.strapi");
|
|
2370
2399
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2371
2400
|
return {
|
|
@@ -2377,6 +2406,7 @@ class LocalStrapiSourceProvider {
|
|
|
2377
2406
|
}
|
|
2378
2407
|
async createEntitiesReadStream() {
|
|
2379
2408
|
assertValidStrapi(this.strapi, "Not able to stream entities");
|
|
2409
|
+
this.#reportInfo("creating entities read stream");
|
|
2380
2410
|
return chain([
|
|
2381
2411
|
// Entities stream
|
|
2382
2412
|
createEntitiesStream(this.strapi),
|
|
@@ -2386,14 +2416,17 @@ class LocalStrapiSourceProvider {
|
|
|
2386
2416
|
}
|
|
2387
2417
|
createLinksReadStream() {
|
|
2388
2418
|
assertValidStrapi(this.strapi, "Not able to stream links");
|
|
2419
|
+
this.#reportInfo("creating links read stream");
|
|
2389
2420
|
return createLinksStream(this.strapi);
|
|
2390
2421
|
}
|
|
2391
2422
|
createConfigurationReadStream() {
|
|
2392
2423
|
assertValidStrapi(this.strapi, "Not able to stream configuration");
|
|
2424
|
+
this.#reportInfo("creating configuration read stream");
|
|
2393
2425
|
return createConfigurationStream(this.strapi);
|
|
2394
2426
|
}
|
|
2395
2427
|
getSchemas() {
|
|
2396
2428
|
assertValidStrapi(this.strapi, "Not able to get Schemas");
|
|
2429
|
+
this.#reportInfo("getting schemas");
|
|
2397
2430
|
const schemas = schemasToValidJSON({
|
|
2398
2431
|
...this.strapi.contentTypes,
|
|
2399
2432
|
...this.strapi.components
|
|
@@ -2405,13 +2438,14 @@ class LocalStrapiSourceProvider {
|
|
|
2405
2438
|
}
|
|
2406
2439
|
createAssetsReadStream() {
|
|
2407
2440
|
assertValidStrapi(this.strapi, "Not able to stream assets");
|
|
2441
|
+
this.#reportInfo("creating assets read stream");
|
|
2408
2442
|
return createAssetsStream(this.strapi);
|
|
2409
2443
|
}
|
|
2410
2444
|
}
|
|
2411
2445
|
const createDispatcher = (ws, retryMessageOptions = {
|
|
2412
2446
|
retryMessageMaxRetries: 5,
|
|
2413
2447
|
retryMessageTimeout: 3e4
|
|
2414
|
-
}) => {
|
|
2448
|
+
}, reportInfo) => {
|
|
2415
2449
|
const state = {};
|
|
2416
2450
|
const dispatch = async (message, options = {}) => {
|
|
2417
2451
|
if (!ws) {
|
|
@@ -2424,6 +2458,16 @@ const createDispatcher = (ws, retryMessageOptions = {
|
|
|
2424
2458
|
if (options.attachTransfer) {
|
|
2425
2459
|
Object.assign(payload, { transferID: state.transfer?.id });
|
|
2426
2460
|
}
|
|
2461
|
+
if (message.type === "command") {
|
|
2462
|
+
reportInfo?.(
|
|
2463
|
+
`dispatching message command:${message.command} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2464
|
+
);
|
|
2465
|
+
} else if (message.type === "transfer") {
|
|
2466
|
+
const messageToSend = message;
|
|
2467
|
+
reportInfo?.(
|
|
2468
|
+
`dispatching message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2469
|
+
);
|
|
2470
|
+
}
|
|
2427
2471
|
const stringifiedPayload = JSON.stringify(payload);
|
|
2428
2472
|
ws.send(stringifiedPayload, (error) => {
|
|
2429
2473
|
if (error) {
|
|
@@ -2446,6 +2490,16 @@ const createDispatcher = (ws, retryMessageOptions = {
|
|
|
2446
2490
|
const interval = setInterval(sendPeriodically, retryMessageTimeout);
|
|
2447
2491
|
const onResponse = (raw) => {
|
|
2448
2492
|
const response = JSON.parse(raw.toString());
|
|
2493
|
+
if (message.type === "command") {
|
|
2494
|
+
reportInfo?.(
|
|
2495
|
+
`received response to message command: ${message.command} uuid: ${uuid} sent: ${numberOfTimesMessageWasSent}`
|
|
2496
|
+
);
|
|
2497
|
+
} else if (message.type === "transfer") {
|
|
2498
|
+
const messageToSend = message;
|
|
2499
|
+
reportInfo?.(
|
|
2500
|
+
`received response to message action:${messageToSend.action} ${messageToSend.kind === "step" ? `step:${messageToSend.step}` : ""} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`
|
|
2501
|
+
);
|
|
2502
|
+
}
|
|
2449
2503
|
if (response.uuid === uuid) {
|
|
2450
2504
|
clearInterval(interval);
|
|
2451
2505
|
if (response.error) {
|
|
@@ -2502,7 +2556,7 @@ const createDispatcher = (ws, retryMessageOptions = {
|
|
|
2502
2556
|
dispatchTransferStep
|
|
2503
2557
|
};
|
|
2504
2558
|
};
|
|
2505
|
-
const connectToWebsocket = (address, options) => {
|
|
2559
|
+
const connectToWebsocket = (address, options, diagnostics) => {
|
|
2506
2560
|
return new Promise((resolve, reject2) => {
|
|
2507
2561
|
const server = new WebSocket(address, options);
|
|
2508
2562
|
server.once("open", () => {
|
|
@@ -2536,6 +2590,14 @@ const connectToWebsocket = (address, options) => {
|
|
|
2536
2590
|
)
|
|
2537
2591
|
);
|
|
2538
2592
|
});
|
|
2593
|
+
server.on("message", (raw) => {
|
|
2594
|
+
const response = JSON.parse(raw.toString());
|
|
2595
|
+
if (response.diagnostic) {
|
|
2596
|
+
diagnostics?.report({
|
|
2597
|
+
...response.diagnostic
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2539
2601
|
server.once("error", (err) => {
|
|
2540
2602
|
reject2(
|
|
2541
2603
|
new ProviderTransferError(err.message, {
|
|
@@ -2577,6 +2639,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
2577
2639
|
dispatcher;
|
|
2578
2640
|
transferID;
|
|
2579
2641
|
stats;
|
|
2642
|
+
#diagnostics;
|
|
2580
2643
|
constructor(options) {
|
|
2581
2644
|
this.options = options;
|
|
2582
2645
|
this.ws = null;
|
|
@@ -2703,7 +2766,18 @@ class RemoteStrapiDestinationProvider {
|
|
|
2703
2766
|
}
|
|
2704
2767
|
});
|
|
2705
2768
|
}
|
|
2706
|
-
|
|
2769
|
+
#reportInfo(message) {
|
|
2770
|
+
this.#diagnostics?.report({
|
|
2771
|
+
details: {
|
|
2772
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2773
|
+
message,
|
|
2774
|
+
origin: "remote-destination-provider"
|
|
2775
|
+
},
|
|
2776
|
+
kind: "info"
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
async bootstrap(diagnostics) {
|
|
2780
|
+
this.#diagnostics = diagnostics;
|
|
2707
2781
|
const { url, auth } = this.options;
|
|
2708
2782
|
const validProtocols = ["https:", "http:"];
|
|
2709
2783
|
let ws;
|
|
@@ -2720,11 +2794,12 @@ class RemoteStrapiDestinationProvider {
|
|
|
2720
2794
|
const wsUrl = `${wsProtocol}//${url.host}${trimTrailingSlash(
|
|
2721
2795
|
url.pathname
|
|
2722
2796
|
)}${TRANSFER_PATH}/push`;
|
|
2797
|
+
this.#reportInfo("establishing websocket connection");
|
|
2723
2798
|
if (!auth) {
|
|
2724
|
-
ws = await connectToWebsocket(wsUrl);
|
|
2799
|
+
ws = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
|
|
2725
2800
|
} else if (auth.type === "token") {
|
|
2726
2801
|
const headers = { Authorization: `Bearer ${auth.token}` };
|
|
2727
|
-
ws = await connectToWebsocket(wsUrl, { headers });
|
|
2802
|
+
ws = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
|
|
2728
2803
|
} else {
|
|
2729
2804
|
throw new ProviderValidationError("Auth method not available", {
|
|
2730
2805
|
check: "auth.type",
|
|
@@ -2733,10 +2808,19 @@ class RemoteStrapiDestinationProvider {
|
|
|
2733
2808
|
}
|
|
2734
2809
|
});
|
|
2735
2810
|
}
|
|
2811
|
+
this.#reportInfo("established websocket connection");
|
|
2736
2812
|
this.ws = ws;
|
|
2737
2813
|
const { retryMessageOptions } = this.options;
|
|
2738
|
-
this
|
|
2814
|
+
this.#reportInfo("creating dispatcher");
|
|
2815
|
+
this.dispatcher = createDispatcher(
|
|
2816
|
+
this.ws,
|
|
2817
|
+
retryMessageOptions,
|
|
2818
|
+
(message) => this.#reportInfo(message)
|
|
2819
|
+
);
|
|
2820
|
+
this.#reportInfo("created dispatcher");
|
|
2821
|
+
this.#reportInfo("initialize transfer");
|
|
2739
2822
|
this.transferID = await this.initTransfer();
|
|
2823
|
+
this.#reportInfo(`initialized transfer ${this.transferID}`);
|
|
2740
2824
|
this.dispatcher.setTransferProperties({ id: this.transferID, kind: "push" });
|
|
2741
2825
|
await this.dispatcher.dispatchTransferAction("bootstrap");
|
|
2742
2826
|
}
|
|
@@ -2863,6 +2947,7 @@ class RemoteStrapiSourceProvider {
|
|
|
2863
2947
|
this.dispatcher = null;
|
|
2864
2948
|
}
|
|
2865
2949
|
results;
|
|
2950
|
+
#diagnostics;
|
|
2866
2951
|
async #createStageReadStream(stage) {
|
|
2867
2952
|
const startResult = await this.#startStep(stage);
|
|
2868
2953
|
if (startResult instanceof Error) {
|
|
@@ -3045,7 +3130,18 @@ class RemoteStrapiSourceProvider {
|
|
|
3045
3130
|
}
|
|
3046
3131
|
return res.transferID;
|
|
3047
3132
|
}
|
|
3048
|
-
|
|
3133
|
+
#reportInfo(message) {
|
|
3134
|
+
this.#diagnostics?.report({
|
|
3135
|
+
details: {
|
|
3136
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3137
|
+
message,
|
|
3138
|
+
origin: "remote-source-provider"
|
|
3139
|
+
},
|
|
3140
|
+
kind: "info"
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
async bootstrap(diagnostics) {
|
|
3144
|
+
this.#diagnostics = diagnostics;
|
|
3049
3145
|
const { url, auth } = this.options;
|
|
3050
3146
|
let ws;
|
|
3051
3147
|
this.assertValidProtocol(url);
|
|
@@ -3053,11 +3149,12 @@ class RemoteStrapiSourceProvider {
|
|
|
3053
3149
|
const wsUrl = `${wsProtocol}//${url.host}${trimTrailingSlash(
|
|
3054
3150
|
url.pathname
|
|
3055
3151
|
)}${TRANSFER_PATH}/pull`;
|
|
3152
|
+
this.#reportInfo("establishing websocket connection");
|
|
3056
3153
|
if (!auth) {
|
|
3057
|
-
ws = await connectToWebsocket(wsUrl);
|
|
3154
|
+
ws = await connectToWebsocket(wsUrl, void 0, this.#diagnostics);
|
|
3058
3155
|
} else if (auth.type === "token") {
|
|
3059
3156
|
const headers = { Authorization: `Bearer ${auth.token}` };
|
|
3060
|
-
ws = await connectToWebsocket(wsUrl, { headers });
|
|
3157
|
+
ws = await connectToWebsocket(wsUrl, { headers }, this.#diagnostics);
|
|
3061
3158
|
} else {
|
|
3062
3159
|
throw new ProviderValidationError("Auth method not available", {
|
|
3063
3160
|
check: "auth.type",
|
|
@@ -3066,10 +3163,19 @@ class RemoteStrapiSourceProvider {
|
|
|
3066
3163
|
}
|
|
3067
3164
|
});
|
|
3068
3165
|
}
|
|
3166
|
+
this.#reportInfo("established websocket connection");
|
|
3069
3167
|
this.ws = ws;
|
|
3070
3168
|
const { retryMessageOptions } = this.options;
|
|
3071
|
-
this
|
|
3169
|
+
this.#reportInfo("creating dispatcher");
|
|
3170
|
+
this.dispatcher = createDispatcher(
|
|
3171
|
+
this.ws,
|
|
3172
|
+
retryMessageOptions,
|
|
3173
|
+
(message) => this.#reportInfo(message)
|
|
3174
|
+
);
|
|
3175
|
+
this.#reportInfo("creating dispatcher");
|
|
3176
|
+
this.#reportInfo("initialize transfer");
|
|
3072
3177
|
const transferID = await this.initTransfer();
|
|
3178
|
+
this.#reportInfo(`initialized transfer ${transferID}`);
|
|
3073
3179
|
this.dispatcher.setTransferProperties({ id: transferID, kind: "pull" });
|
|
3074
3180
|
await this.dispatcher.dispatchTransferAction("bootstrap");
|
|
3075
3181
|
}
|
|
@@ -3299,6 +3405,7 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3299
3405
|
const cb = (ws) => {
|
|
3300
3406
|
const state = { id: void 0 };
|
|
3301
3407
|
const messageUUIDs = /* @__PURE__ */ new Set();
|
|
3408
|
+
const diagnostics = createDiagnosticReporter();
|
|
3302
3409
|
const cannotRespondHandler = (err) => {
|
|
3303
3410
|
strapi?.log?.error(
|
|
3304
3411
|
"[Data transfer] Cannot send error response to client, closing connection"
|
|
@@ -3332,6 +3439,9 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3332
3439
|
set response(response) {
|
|
3333
3440
|
state.response = response;
|
|
3334
3441
|
},
|
|
3442
|
+
get diagnostics() {
|
|
3443
|
+
return diagnostics;
|
|
3444
|
+
},
|
|
3335
3445
|
addUUID(uuid) {
|
|
3336
3446
|
messageUUIDs.add(uuid);
|
|
3337
3447
|
},
|
|
@@ -3447,6 +3557,10 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3447
3557
|
onError() {
|
|
3448
3558
|
},
|
|
3449
3559
|
onClose() {
|
|
3560
|
+
},
|
|
3561
|
+
onInfo() {
|
|
3562
|
+
},
|
|
3563
|
+
onWarning() {
|
|
3450
3564
|
}
|
|
3451
3565
|
};
|
|
3452
3566
|
const handler = Object.assign(Object.create(prototype), implementation(prototype));
|
|
@@ -3479,6 +3593,14 @@ const handlerControllerFactory = (implementation) => (options) => {
|
|
|
3479
3593
|
cannotRespondHandler(err);
|
|
3480
3594
|
}
|
|
3481
3595
|
});
|
|
3596
|
+
diagnostics.onDiagnostic((diagnostic2) => {
|
|
3597
|
+
const uuid = randomUUID();
|
|
3598
|
+
const payload = JSON.stringify({
|
|
3599
|
+
diagnostic: diagnostic2,
|
|
3600
|
+
uuid
|
|
3601
|
+
});
|
|
3602
|
+
handler.send(payload);
|
|
3603
|
+
});
|
|
3482
3604
|
};
|
|
3483
3605
|
try {
|
|
3484
3606
|
handleWSUpgrade(wss, ctx, cb);
|
|
@@ -3514,6 +3636,26 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3514
3636
|
verifyAuth() {
|
|
3515
3637
|
return proto.verifyAuth.call(this, TRANSFER_KIND$1);
|
|
3516
3638
|
},
|
|
3639
|
+
onInfo(message) {
|
|
3640
|
+
this.diagnostics?.report({
|
|
3641
|
+
details: {
|
|
3642
|
+
message,
|
|
3643
|
+
origin: "push-handler",
|
|
3644
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3645
|
+
},
|
|
3646
|
+
kind: "info"
|
|
3647
|
+
});
|
|
3648
|
+
},
|
|
3649
|
+
onWarning(message) {
|
|
3650
|
+
this.diagnostics?.report({
|
|
3651
|
+
details: {
|
|
3652
|
+
message,
|
|
3653
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3654
|
+
origin: "push-handler"
|
|
3655
|
+
},
|
|
3656
|
+
kind: "warning"
|
|
3657
|
+
});
|
|
3658
|
+
},
|
|
3517
3659
|
cleanup() {
|
|
3518
3660
|
proto.cleanup.call(this);
|
|
3519
3661
|
this.streams = {};
|
|
@@ -3590,6 +3732,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3590
3732
|
proto.addUUID(uuid);
|
|
3591
3733
|
if (type === "command") {
|
|
3592
3734
|
const { command } = msg;
|
|
3735
|
+
this.onInfo(`received command:${command} uuid:${uuid}`);
|
|
3593
3736
|
await this.executeAndRespond(uuid, () => {
|
|
3594
3737
|
this.assertValidTransferCommand(command);
|
|
3595
3738
|
if (command === "status") {
|
|
@@ -3598,6 +3741,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3598
3741
|
return this[command](msg.params);
|
|
3599
3742
|
});
|
|
3600
3743
|
} else if (type === "transfer") {
|
|
3744
|
+
this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
|
|
3601
3745
|
await this.executeAndRespond(uuid, async () => {
|
|
3602
3746
|
await this.verifyAuth();
|
|
3603
3747
|
this.assertValidTransfer();
|
|
@@ -3699,6 +3843,9 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3699
3843
|
}
|
|
3700
3844
|
this.flow?.set(step);
|
|
3701
3845
|
}
|
|
3846
|
+
if (action === "bootstrap") {
|
|
3847
|
+
return this.provider?.[action](this.diagnostics);
|
|
3848
|
+
}
|
|
3702
3849
|
return this.provider?.[action]();
|
|
3703
3850
|
},
|
|
3704
3851
|
async streamAsset(payload) {
|
|
@@ -3764,6 +3911,7 @@ const createPushController = handlerControllerFactory((proto) => ({
|
|
|
3764
3911
|
getStrapi: () => strapi
|
|
3765
3912
|
});
|
|
3766
3913
|
this.provider.onWarning = (message) => {
|
|
3914
|
+
this.onWarning(message);
|
|
3767
3915
|
strapi.log.warn(message);
|
|
3768
3916
|
};
|
|
3769
3917
|
return { transferID: this.transferID };
|
|
@@ -3804,6 +3952,26 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3804
3952
|
this.streams = {};
|
|
3805
3953
|
delete this.provider;
|
|
3806
3954
|
},
|
|
3955
|
+
onInfo(message) {
|
|
3956
|
+
this.diagnostics?.report({
|
|
3957
|
+
details: {
|
|
3958
|
+
message,
|
|
3959
|
+
origin: "pull-handler",
|
|
3960
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3961
|
+
},
|
|
3962
|
+
kind: "info"
|
|
3963
|
+
});
|
|
3964
|
+
},
|
|
3965
|
+
onWarning(message) {
|
|
3966
|
+
this.diagnostics?.report({
|
|
3967
|
+
details: {
|
|
3968
|
+
message,
|
|
3969
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3970
|
+
origin: "pull-handler"
|
|
3971
|
+
},
|
|
3972
|
+
kind: "warning"
|
|
3973
|
+
});
|
|
3974
|
+
},
|
|
3807
3975
|
assertValidTransferAction(action) {
|
|
3808
3976
|
const validActions = VALID_TRANSFER_ACTIONS;
|
|
3809
3977
|
if (validActions.includes(action)) {
|
|
@@ -3833,6 +4001,7 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3833
4001
|
proto.addUUID(uuid);
|
|
3834
4002
|
if (type === "command") {
|
|
3835
4003
|
const { command } = msg;
|
|
4004
|
+
this.onInfo(`received command:${command} uuid:${uuid}`);
|
|
3836
4005
|
await this.executeAndRespond(uuid, () => {
|
|
3837
4006
|
this.assertValidTransferCommand(command);
|
|
3838
4007
|
if (command === "status") {
|
|
@@ -3841,6 +4010,7 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3841
4010
|
return this[command](msg.params);
|
|
3842
4011
|
});
|
|
3843
4012
|
} else if (type === "transfer") {
|
|
4013
|
+
this.onInfo(`received transfer action:${msg.action} step:${msg.kind} uuid:${uuid}`);
|
|
3844
4014
|
await this.executeAndRespond(uuid, async () => {
|
|
3845
4015
|
await this.verifyAuth();
|
|
3846
4016
|
this.assertValidTransfer();
|
|
@@ -3862,6 +4032,9 @@ const createPullController = handlerControllerFactory((proto) => ({
|
|
|
3862
4032
|
async onTransferAction(msg) {
|
|
3863
4033
|
const { action } = msg;
|
|
3864
4034
|
this.assertValidTransferAction(action);
|
|
4035
|
+
if (action === "bootstrap") {
|
|
4036
|
+
return this.provider?.[action](this.diagnostics);
|
|
4037
|
+
}
|
|
3865
4038
|
return this.provider?.[action]();
|
|
3866
4039
|
},
|
|
3867
4040
|
async flush(stage, id) {
|
|
@@ -4060,6 +4233,7 @@ class LocalFileSourceProvider {
|
|
|
4060
4233
|
name = "source::local-file";
|
|
4061
4234
|
options;
|
|
4062
4235
|
#metadata;
|
|
4236
|
+
#diagnostics;
|
|
4063
4237
|
constructor(options) {
|
|
4064
4238
|
this.options = options;
|
|
4065
4239
|
const { encryption } = this.options;
|
|
@@ -4067,10 +4241,21 @@ class LocalFileSourceProvider {
|
|
|
4067
4241
|
throw new Error("Missing encryption key");
|
|
4068
4242
|
}
|
|
4069
4243
|
}
|
|
4244
|
+
#reportInfo(message) {
|
|
4245
|
+
this.#diagnostics?.report({
|
|
4246
|
+
details: {
|
|
4247
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4248
|
+
message,
|
|
4249
|
+
origin: "file-source-provider"
|
|
4250
|
+
},
|
|
4251
|
+
kind: "info"
|
|
4252
|
+
});
|
|
4253
|
+
}
|
|
4070
4254
|
/**
|
|
4071
4255
|
* Pre flight checks regarding the provided options, making sure that the file can be opened (decrypted, decompressed), etc.
|
|
4072
4256
|
*/
|
|
4073
|
-
async bootstrap() {
|
|
4257
|
+
async bootstrap(diagnostics) {
|
|
4258
|
+
this.#diagnostics = diagnostics;
|
|
4074
4259
|
const { path: filePath } = this.options.file;
|
|
4075
4260
|
try {
|
|
4076
4261
|
await this.#loadMetadata();
|
|
@@ -4095,12 +4280,14 @@ class LocalFileSourceProvider {
|
|
|
4095
4280
|
return this.#parseJSONFile(backupStream, path2);
|
|
4096
4281
|
}
|
|
4097
4282
|
async getMetadata() {
|
|
4283
|
+
this.#reportInfo("getting metadata");
|
|
4098
4284
|
if (!this.#metadata) {
|
|
4099
4285
|
await this.#loadMetadata();
|
|
4100
4286
|
}
|
|
4101
4287
|
return this.#metadata ?? null;
|
|
4102
4288
|
}
|
|
4103
4289
|
async getSchemas() {
|
|
4290
|
+
this.#reportInfo("getting schemas");
|
|
4104
4291
|
const schemaCollection = await collect(
|
|
4105
4292
|
this.createSchemasReadStream()
|
|
4106
4293
|
);
|
|
@@ -4111,21 +4298,26 @@ class LocalFileSourceProvider {
|
|
|
4111
4298
|
return schemasToValidJSON(schemas);
|
|
4112
4299
|
}
|
|
4113
4300
|
createEntitiesReadStream() {
|
|
4301
|
+
this.#reportInfo("creating entities read stream");
|
|
4114
4302
|
return this.#streamJsonlDirectory("entities");
|
|
4115
4303
|
}
|
|
4116
4304
|
createSchemasReadStream() {
|
|
4305
|
+
this.#reportInfo("creating schemas read stream");
|
|
4117
4306
|
return this.#streamJsonlDirectory("schemas");
|
|
4118
4307
|
}
|
|
4119
4308
|
createLinksReadStream() {
|
|
4309
|
+
this.#reportInfo("creating links read stream");
|
|
4120
4310
|
return this.#streamJsonlDirectory("links");
|
|
4121
4311
|
}
|
|
4122
4312
|
createConfigurationReadStream() {
|
|
4313
|
+
this.#reportInfo("creating configuration read stream");
|
|
4123
4314
|
return this.#streamJsonlDirectory("configuration");
|
|
4124
4315
|
}
|
|
4125
4316
|
createAssetsReadStream() {
|
|
4126
4317
|
const inStream = this.#getBackupStream();
|
|
4127
4318
|
const outStream = new PassThrough({ objectMode: true });
|
|
4128
4319
|
const loadAssetMetadata = this.#loadAssetMetadata.bind(this);
|
|
4320
|
+
this.#reportInfo("creating assets read stream");
|
|
4129
4321
|
pipeline(
|
|
4130
4322
|
[
|
|
4131
4323
|
inStream,
|
|
@@ -4145,9 +4337,7 @@ class LocalFileSourceProvider {
|
|
|
4145
4337
|
try {
|
|
4146
4338
|
metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
|
|
4147
4339
|
} catch (error) {
|
|
4148
|
-
|
|
4149
|
-
` Failed to read metadata for ${file}, Strapi will try to fix this issue automatically`
|
|
4150
|
-
);
|
|
4340
|
+
throw new Error(`Failed to read metadata for ${file}`);
|
|
4151
4341
|
}
|
|
4152
4342
|
const asset = {
|
|
4153
4343
|
metadata,
|
|
@@ -4326,9 +4516,20 @@ class LocalFileDestinationProvider {
|
|
|
4326
4516
|
results = {};
|
|
4327
4517
|
#providersMetadata = {};
|
|
4328
4518
|
#archive = {};
|
|
4519
|
+
#diagnostics;
|
|
4329
4520
|
constructor(options) {
|
|
4330
4521
|
this.options = options;
|
|
4331
4522
|
}
|
|
4523
|
+
#reportInfo(message) {
|
|
4524
|
+
this.#diagnostics?.report({
|
|
4525
|
+
details: {
|
|
4526
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4527
|
+
message,
|
|
4528
|
+
origin: "file-destination-provider"
|
|
4529
|
+
},
|
|
4530
|
+
kind: "info"
|
|
4531
|
+
});
|
|
4532
|
+
}
|
|
4332
4533
|
get #archivePath() {
|
|
4333
4534
|
const { encryption, compression, file } = this.options;
|
|
4334
4535
|
let filePath = `${file.path}.tar`;
|
|
@@ -4345,9 +4546,11 @@ class LocalFileDestinationProvider {
|
|
|
4345
4546
|
return this;
|
|
4346
4547
|
}
|
|
4347
4548
|
createGzip() {
|
|
4549
|
+
this.#reportInfo("creating gzip");
|
|
4348
4550
|
return zip$1.createGzip();
|
|
4349
4551
|
}
|
|
4350
|
-
bootstrap() {
|
|
4552
|
+
bootstrap(diagnostics) {
|
|
4553
|
+
this.#diagnostics = diagnostics;
|
|
4351
4554
|
const { compression, encryption } = this.options;
|
|
4352
4555
|
if (encryption.enabled && !encryption.key) {
|
|
4353
4556
|
throw new Error("Can't encrypt without a key");
|
|
@@ -4386,6 +4589,7 @@ class LocalFileDestinationProvider {
|
|
|
4386
4589
|
}
|
|
4387
4590
|
}
|
|
4388
4591
|
async rollback() {
|
|
4592
|
+
this.#reportInfo("rolling back");
|
|
4389
4593
|
await this.close();
|
|
4390
4594
|
await rm(this.#archivePath, { force: true });
|
|
4391
4595
|
}
|
|
@@ -4393,6 +4597,7 @@ class LocalFileDestinationProvider {
|
|
|
4393
4597
|
return null;
|
|
4394
4598
|
}
|
|
4395
4599
|
async #writeMetadata() {
|
|
4600
|
+
this.#reportInfo("writing metadata");
|
|
4396
4601
|
const metadata = this.#providersMetadata.source;
|
|
4397
4602
|
if (metadata) {
|
|
4398
4603
|
await new Promise((resolve) => {
|
|
@@ -4413,6 +4618,7 @@ class LocalFileDestinationProvider {
|
|
|
4413
4618
|
if (!this.#archive.stream) {
|
|
4414
4619
|
throw new Error("Archive stream is unavailable");
|
|
4415
4620
|
}
|
|
4621
|
+
this.#reportInfo("creating schemas write stream");
|
|
4416
4622
|
const filePathFactory = createFilePathFactory("schemas");
|
|
4417
4623
|
const entryStream = createTarEntryStream(
|
|
4418
4624
|
this.#archive.stream,
|
|
@@ -4425,6 +4631,7 @@ class LocalFileDestinationProvider {
|
|
|
4425
4631
|
if (!this.#archive.stream) {
|
|
4426
4632
|
throw new Error("Archive stream is unavailable");
|
|
4427
4633
|
}
|
|
4634
|
+
this.#reportInfo("creating entities write stream");
|
|
4428
4635
|
const filePathFactory = createFilePathFactory("entities");
|
|
4429
4636
|
const entryStream = createTarEntryStream(
|
|
4430
4637
|
this.#archive.stream,
|
|
@@ -4437,6 +4644,7 @@ class LocalFileDestinationProvider {
|
|
|
4437
4644
|
if (!this.#archive.stream) {
|
|
4438
4645
|
throw new Error("Archive stream is unavailable");
|
|
4439
4646
|
}
|
|
4647
|
+
this.#reportInfo("creating links write stream");
|
|
4440
4648
|
const filePathFactory = createFilePathFactory("links");
|
|
4441
4649
|
const entryStream = createTarEntryStream(
|
|
4442
4650
|
this.#archive.stream,
|
|
@@ -4449,6 +4657,7 @@ class LocalFileDestinationProvider {
|
|
|
4449
4657
|
if (!this.#archive.stream) {
|
|
4450
4658
|
throw new Error("Archive stream is unavailable");
|
|
4451
4659
|
}
|
|
4660
|
+
this.#reportInfo("creating configuration write stream");
|
|
4452
4661
|
const filePathFactory = createFilePathFactory("configuration");
|
|
4453
4662
|
const entryStream = createTarEntryStream(
|
|
4454
4663
|
this.#archive.stream,
|
|
@@ -4462,6 +4671,7 @@ class LocalFileDestinationProvider {
|
|
|
4462
4671
|
if (!archiveStream) {
|
|
4463
4672
|
throw new Error("Archive stream is unavailable");
|
|
4464
4673
|
}
|
|
4674
|
+
this.#reportInfo("creating assets write stream");
|
|
4465
4675
|
return new Writable({
|
|
4466
4676
|
objectMode: true,
|
|
4467
4677
|
write(data, _encoding, callback) {
|