@strapi/data-transfer 4.6.0-alpha.0 → 4.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/encryption/decrypt.js +4 -4
  2. package/dist/encryption/encrypt.js +4 -4
  3. package/dist/engine/index.d.ts +11 -10
  4. package/dist/engine/index.js +145 -166
  5. package/dist/providers/{local-file-destination-provider.d.ts → local-file-destination-provider/index.d.ts} +9 -5
  6. package/dist/providers/{local-file-destination-provider.js → local-file-destination-provider/index.js} +54 -82
  7. package/dist/providers/local-file-destination-provider/utils.d.ts +9 -0
  8. package/dist/providers/local-file-destination-provider/utils.js +61 -0
  9. package/dist/providers/{local-file-source-provider.d.ts → local-file-source-provider/index.d.ts} +18 -22
  10. package/dist/providers/{local-file-source-provider.js → local-file-source-provider/index.js} +91 -36
  11. package/dist/providers/local-strapi-destination-provider/index.d.ts +31 -0
  12. package/dist/providers/local-strapi-destination-provider/index.js +187 -0
  13. package/dist/providers/local-strapi-destination-provider/strategies/index.d.ts +1 -0
  14. package/dist/providers/local-strapi-destination-provider/strategies/index.js +28 -0
  15. package/dist/providers/local-strapi-destination-provider/strategies/restore/configuration.d.ts +5 -0
  16. package/dist/providers/local-strapi-destination-provider/strategies/restore/configuration.js +44 -0
  17. package/dist/providers/local-strapi-destination-provider/strategies/restore/entities.d.ts +9 -0
  18. package/dist/providers/local-strapi-destination-provider/strategies/restore/entities.js +88 -0
  19. package/dist/providers/local-strapi-destination-provider/strategies/restore/index.d.ts +32 -0
  20. package/dist/providers/local-strapi-destination-provider/strategies/restore/index.js +106 -0
  21. package/dist/providers/local-strapi-destination-provider/strategies/restore/links.d.ts +3 -0
  22. package/dist/providers/local-strapi-destination-provider/strategies/restore/links.js +29 -0
  23. package/dist/providers/local-strapi-source-provider/assets.d.ts +5 -0
  24. package/dist/providers/local-strapi-source-provider/assets.js +31 -0
  25. package/dist/providers/local-strapi-source-provider/configuration.js +1 -1
  26. package/dist/providers/local-strapi-source-provider/entities.js +29 -9
  27. package/dist/providers/local-strapi-source-provider/index.d.ts +8 -7
  28. package/dist/providers/local-strapi-source-provider/index.js +32 -2
  29. package/dist/providers/local-strapi-source-provider/{links/index.d.ts → links.d.ts} +1 -1
  30. package/dist/providers/local-strapi-source-provider/links.js +23 -0
  31. package/dist/providers/shared/index.d.ts +1 -0
  32. package/dist/providers/shared/index.js +28 -0
  33. package/dist/providers/shared/strapi/entity.d.ts +19 -0
  34. package/dist/providers/shared/strapi/entity.js +130 -0
  35. package/dist/providers/shared/strapi/index.d.ts +2 -0
  36. package/dist/providers/shared/strapi/index.js +29 -0
  37. package/dist/providers/shared/strapi/link.d.ts +6 -0
  38. package/dist/providers/shared/strapi/link.js +201 -0
  39. package/dist/providers/test-utils/index.d.ts +111 -0
  40. package/dist/providers/test-utils/index.js +64 -0
  41. package/dist/strategies/index.d.ts +3 -3
  42. package/dist/strategies/index.js +27 -4
  43. package/dist/utils/index.d.ts +3 -0
  44. package/dist/utils/index.js +30 -0
  45. package/dist/utils/json.d.ts +23 -0
  46. package/dist/{utils.js → utils/json.js} +9 -38
  47. package/dist/utils/schema.d.ts +3 -0
  48. package/dist/utils/schema.js +22 -0
  49. package/dist/utils/stream.d.ts +10 -0
  50. package/dist/utils/stream.js +39 -0
  51. package/jest.config.js +3 -1
  52. package/package.json +4 -4
  53. package/dist/providers/local-strapi-destination-provider.d.ts +0 -22
  54. package/dist/providers/local-strapi-destination-provider.js +0 -78
  55. package/dist/providers/local-strapi-source-provider/links/index.js +0 -37
  56. package/dist/providers/local-strapi-source-provider/links/utils.d.ts +0 -27
  57. package/dist/providers/local-strapi-source-provider/links/utils.js +0 -155
  58. package/dist/utils.d.ts +0 -10
@@ -7,17 +7,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
7
7
  var __importDefault = (this && this.__importDefault) || function (mod) {
8
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
9
9
  };
10
- var _LocalFileDestinationProvider_instances, _LocalFileDestinationProvider_providersMetadata, _LocalFileDestinationProvider_archive, _LocalFileDestinationProvider_archivePath_get, _LocalFileDestinationProvider_getDataTransformers, _LocalFileDestinationProvider_writeMetadata, _LocalFileDestinationProvider_getMetadataStream;
10
+ var _LocalFileDestinationProvider_instances, _LocalFileDestinationProvider_providersMetadata, _LocalFileDestinationProvider_archive, _LocalFileDestinationProvider_archivePath_get, _LocalFileDestinationProvider_writeMetadata, _LocalFileDestinationProvider_getMetadataStream;
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.createLocalFileDestinationProvider = void 0;
13
- const fs_extra_1 = __importDefault(require("fs-extra"));
14
- const path_1 = __importDefault(require("path"));
13
+ const fs_extra_1 = require("fs-extra");
15
14
  const tar_stream_1 = __importDefault(require("tar-stream"));
15
+ const path_1 = __importDefault(require("path"));
16
16
  const zlib_1 = __importDefault(require("zlib"));
17
- const stream_1 = require("stream");
18
17
  const Stringer_1 = require("stream-json/jsonl/Stringer");
19
18
  const stream_chain_1 = require("stream-chain");
20
- const encrypt_1 = require("../encryption/encrypt");
19
+ const stream_1 = require("stream");
20
+ const encrypt_1 = require("../../encryption/encrypt");
21
+ const utils_1 = require("./utils");
21
22
  const createLocalFileDestinationProvider = (options) => {
22
23
  return new LocalFileDestinationProvider(options);
23
24
  };
@@ -36,16 +37,19 @@ class LocalFileDestinationProvider {
36
37
  __classPrivateFieldGet(this, _LocalFileDestinationProvider_providersMetadata, "f")[target] = metadata;
37
38
  return this;
38
39
  }
40
+ createGzip() {
41
+ return zlib_1.default.createGzip();
42
+ }
39
43
  bootstrap() {
40
44
  const { compression, encryption } = this.options;
41
45
  if (encryption.enabled && !encryption.key) {
42
46
  throw new Error("Can't encrypt without a key");
43
47
  }
44
48
  __classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream = tar_stream_1.default.pack();
45
- const outStream = fs_extra_1.default.createWriteStream(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get));
49
+ const outStream = (0, fs_extra_1.createWriteStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get));
46
50
  const archiveTransforms = [];
47
51
  if (compression.enabled) {
48
- archiveTransforms.push(zlib_1.default.createGzip());
52
+ archiveTransforms.push(this.createGzip());
49
53
  }
50
54
  if (encryption.enabled && encryption.key) {
51
55
  archiveTransforms.push((0, encrypt_1.createEncryptionCipher)(encryption.key));
@@ -68,7 +72,7 @@ class LocalFileDestinationProvider {
68
72
  }
69
73
  async rollback() {
70
74
  await this.close();
71
- fs_extra_1.default.rmSync(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get), { force: true });
75
+ await (0, fs_extra_1.rm)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get), { force: true });
72
76
  }
73
77
  getMetadata() {
74
78
  return null;
@@ -77,53 +81,73 @@ class LocalFileDestinationProvider {
77
81
  if (!__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream) {
78
82
  throw new Error('Archive stream is unavailable');
79
83
  }
80
- const filePathFactory = createFilePathFactory('schemas');
81
- const entryStream = createTarEntryStream(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSize);
84
+ const filePathFactory = (0, utils_1.createFilePathFactory)('schemas');
85
+ const entryStream = (0, utils_1.createTarEntryStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSizeJsonl);
82
86
  return (0, stream_chain_1.chain)([(0, Stringer_1.stringer)(), entryStream]);
83
87
  }
84
88
  getEntitiesStream() {
85
89
  if (!__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream) {
86
90
  throw new Error('Archive stream is unavailable');
87
91
  }
88
- const filePathFactory = createFilePathFactory('entities');
89
- const entryStream = createTarEntryStream(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSize);
92
+ const filePathFactory = (0, utils_1.createFilePathFactory)('entities');
93
+ const entryStream = (0, utils_1.createTarEntryStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSizeJsonl);
90
94
  return (0, stream_chain_1.chain)([(0, Stringer_1.stringer)(), entryStream]);
91
95
  }
92
96
  getLinksStream() {
93
97
  if (!__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream) {
94
98
  throw new Error('Archive stream is unavailable');
95
99
  }
96
- const filePathFactory = createFilePathFactory('links');
97
- const entryStream = createTarEntryStream(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSize);
100
+ const filePathFactory = (0, utils_1.createFilePathFactory)('links');
101
+ const entryStream = (0, utils_1.createTarEntryStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSizeJsonl);
98
102
  return (0, stream_chain_1.chain)([(0, Stringer_1.stringer)(), entryStream]);
99
103
  }
100
104
  getConfigurationStream() {
101
105
  if (!__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream) {
102
106
  throw new Error('Archive stream is unavailable');
103
107
  }
104
- const filePathFactory = createFilePathFactory('configuration');
105
- const entryStream = createTarEntryStream(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSize);
108
+ const filePathFactory = (0, utils_1.createFilePathFactory)('configuration');
109
+ const entryStream = (0, utils_1.createTarEntryStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream, filePathFactory, this.options.file.maxSizeJsonl);
106
110
  return (0, stream_chain_1.chain)([(0, Stringer_1.stringer)(), entryStream]);
107
111
  }
112
+ getAssetsStream() {
113
+ const { stream: archiveStream } = __classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f");
114
+ if (!archiveStream) {
115
+ throw new Error('Archive stream is unavailable');
116
+ }
117
+ return new stream_1.Writable({
118
+ objectMode: true,
119
+ write(data, _encoding, callback) {
120
+ const entryPath = path_1.default.join('assets', 'uploads', data.filename);
121
+ const entry = archiveStream.entry({
122
+ name: entryPath,
123
+ size: data.stats.size,
124
+ });
125
+ if (!entry) {
126
+ callback(new Error(`Failed to created a tar entry for ${entryPath}`));
127
+ return;
128
+ }
129
+ data.stream.pipe(entry);
130
+ entry
131
+ .on('finish', () => {
132
+ callback(null);
133
+ })
134
+ .on('error', (error) => {
135
+ callback(error);
136
+ });
137
+ },
138
+ });
139
+ }
108
140
  }
109
141
  _LocalFileDestinationProvider_providersMetadata = new WeakMap(), _LocalFileDestinationProvider_archive = new WeakMap(), _LocalFileDestinationProvider_instances = new WeakSet(), _LocalFileDestinationProvider_archivePath_get = function _LocalFileDestinationProvider_archivePath_get() {
110
142
  const { encryption, compression, file } = this.options;
111
- let path = `${file.path}.tar`;
143
+ let filePath = `${file.path}.tar`;
112
144
  if (compression.enabled) {
113
- path += '.gz';
145
+ filePath += '.gz';
114
146
  }
115
147
  if (encryption.enabled) {
116
- path += '.enc';
117
- }
118
- return path;
119
- }, _LocalFileDestinationProvider_getDataTransformers = function _LocalFileDestinationProvider_getDataTransformers(options = {}) {
120
- const { jsonl = true } = options;
121
- const transforms = [];
122
- if (jsonl) {
123
- // Convert to stringified JSON lines
124
- transforms.push((0, Stringer_1.stringer)());
148
+ filePath += '.enc';
125
149
  }
126
- return transforms;
150
+ return filePath;
127
151
  }, _LocalFileDestinationProvider_writeMetadata = async function _LocalFileDestinationProvider_writeMetadata() {
128
152
  const metadata = __classPrivateFieldGet(this, _LocalFileDestinationProvider_providersMetadata, "f").source;
129
153
  if (metadata) {
@@ -138,58 +162,6 @@ _LocalFileDestinationProvider_providersMetadata = new WeakMap(), _LocalFileDesti
138
162
  if (!stream) {
139
163
  throw new Error('Archive stream is unavailable');
140
164
  }
141
- return createTarEntryStream(stream, () => 'metadata.json');
142
- };
143
- /**
144
- * Create a file path factory for a given path & prefix.
145
- * Upon being called, the factory will return a file path for a given index
146
- */
147
- const createFilePathFactory = (type) => (fileIndex = 0) => {
148
- return path_1.default.join(
149
- // "{type}" directory
150
- type,
151
- // "${type}_XXXXX.jsonl" file
152
- `${type}_${String(fileIndex).padStart(5, '0')}.jsonl`);
153
- };
154
- const createTarEntryStream = (archive, pathFactory, maxSize = 2.56e8) => {
155
- let fileIndex = 0;
156
- let buffer = '';
157
- const flush = async () => {
158
- if (!buffer) {
159
- return;
160
- }
161
- const name = pathFactory(fileIndex++);
162
- const size = buffer.length;
163
- await new Promise((resolve, reject) => {
164
- archive.entry({ name, size }, buffer, (err) => {
165
- if (err) {
166
- reject(err);
167
- }
168
- resolve();
169
- });
170
- });
171
- buffer = '';
172
- };
173
- const push = (chunk) => {
174
- buffer += chunk;
175
- };
176
- return new stream_1.Writable({
177
- async destroy(err, callback) {
178
- await flush();
179
- callback(err);
180
- },
181
- async write(chunk, _encoding, callback) {
182
- const size = chunk.length;
183
- if (chunk.length > maxSize) {
184
- callback(new Error(`payload too large: ${chunk.length}>${maxSize}`));
185
- return;
186
- }
187
- if (buffer.length + size > maxSize) {
188
- await flush();
189
- }
190
- push(chunk);
191
- callback(null);
192
- },
193
- });
165
+ return (0, utils_1.createTarEntryStream)(stream, () => 'metadata.json');
194
166
  };
195
- //# sourceMappingURL=local-file-destination-provider.js.map
167
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import { Writable } from 'stream';
3
+ import tar from 'tar-stream';
4
+ /**
5
+ * Create a file path factory for a given path & prefix.
6
+ * Upon being called, the factory will return a file path for a given index
7
+ */
8
+ export declare const createFilePathFactory: (type: string) => (fileIndex?: number) => string;
9
+ export declare const createTarEntryStream: (archive: tar.Pack, pathFactory: (index?: number | undefined) => string, maxSize?: number) => Writable;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTarEntryStream = exports.createFilePathFactory = void 0;
4
+ const stream_1 = require("stream");
5
+ const path_1 = require("path");
6
+ /**
7
+ * Create a file path factory for a given path & prefix.
8
+ * Upon being called, the factory will return a file path for a given index
9
+ */
10
+ const createFilePathFactory = (type) => (fileIndex = 0) => {
11
+ return (0, path_1.join)(
12
+ // "{type}" directory
13
+ type,
14
+ // "${type}_XXXXX.jsonl" file
15
+ `${type}_${String(fileIndex).padStart(5, '0')}.jsonl`);
16
+ };
17
+ exports.createFilePathFactory = createFilePathFactory;
18
+ const createTarEntryStream = (archive, pathFactory, maxSize = 2.56e8) => {
19
+ let fileIndex = 0;
20
+ let buffer = '';
21
+ const flush = async () => {
22
+ if (!buffer) {
23
+ return;
24
+ }
25
+ fileIndex += 1;
26
+ const name = pathFactory(fileIndex);
27
+ const size = buffer.length;
28
+ await new Promise((resolve, reject) => {
29
+ archive.entry({ name, size }, buffer, (err) => {
30
+ if (err) {
31
+ reject(err);
32
+ }
33
+ resolve();
34
+ });
35
+ });
36
+ buffer = '';
37
+ };
38
+ const push = (chunk) => {
39
+ buffer += chunk;
40
+ };
41
+ return new stream_1.Writable({
42
+ async destroy(err, callback) {
43
+ await flush();
44
+ callback(err);
45
+ },
46
+ async write(chunk, _encoding, callback) {
47
+ const size = chunk.length;
48
+ if (chunk.length > maxSize) {
49
+ callback(new Error(`payload too large: ${chunk.length}>${maxSize}`));
50
+ return;
51
+ }
52
+ if (buffer.length + size > maxSize) {
53
+ await flush();
54
+ }
55
+ push(chunk);
56
+ callback(null);
57
+ },
58
+ });
59
+ };
60
+ exports.createTarEntryStream = createTarEntryStream;
61
+ //# sourceMappingURL=utils.js.map
@@ -1,26 +1,21 @@
1
1
  /// <reference types="lodash" />
2
2
  /// <reference types="node" />
3
- import type { IMetadata, ISourceProvider, ProviderType } from '../../types';
3
+ import type { Readable } from 'stream';
4
+ import type { IMetadata, ISourceProvider, ProviderType } from '../../../types';
4
5
  /**
5
6
  * Provider options
6
7
  */
7
8
  export interface ILocalFileSourceProviderOptions {
8
- /**
9
- * Path to the backup archive
10
- */
11
- backupFilePath: string;
12
- /**
13
- * Whether the backup data is encrypted or not
14
- */
15
- encrypted?: boolean;
16
- /**
17
- * Encryption key used to decrypt the encrypted data (if necessary)
18
- */
19
- encryptionKey?: string;
20
- /**
21
- * Whether the backup data is compressed or not
22
- */
23
- compressed?: boolean;
9
+ file: {
10
+ path: string;
11
+ };
12
+ encryption: {
13
+ enabled: boolean;
14
+ key?: string;
15
+ };
16
+ compression: {
17
+ enabled: boolean;
18
+ };
24
19
  }
25
20
  export declare const createLocalFileSourceProvider: (options: ILocalFileSourceProviderOptions) => LocalFileSourceProvider;
26
21
  declare class LocalFileSourceProvider implements ISourceProvider {
@@ -32,12 +27,13 @@ declare class LocalFileSourceProvider implements ISourceProvider {
32
27
  /**
33
28
  * Pre flight checks regarding the provided options (making sure that the provided path is correct, etc...)
34
29
  */
35
- bootstrap(): void;
30
+ bootstrap(): Promise<void>;
36
31
  getMetadata(): Promise<IMetadata>;
37
32
  getSchemas(): Promise<import("lodash").Dictionary<unknown>>;
38
- streamEntities(): NodeJS.ReadableStream;
39
- streamSchemas(): NodeJS.ReadableStream | Promise<NodeJS.ReadableStream>;
40
- streamLinks(): NodeJS.ReadableStream;
41
- streamConfiguration(): NodeJS.ReadableStream;
33
+ streamEntities(): Readable;
34
+ streamSchemas(): Readable;
35
+ streamLinks(): Readable;
36
+ streamConfiguration(): Readable;
37
+ streamAssets(): Readable | Promise<Readable>;
42
38
  }
43
39
  export {};
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
26
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
27
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
@@ -10,15 +33,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
33
  var _LocalFileSourceProvider_instances, _LocalFileSourceProvider_getBackupStream, _LocalFileSourceProvider_streamJsonlDirectory, _LocalFileSourceProvider_parseJSONFile;
11
34
  Object.defineProperty(exports, "__esModule", { value: true });
12
35
  exports.createLocalFileSourceProvider = void 0;
13
- const fs_1 = __importDefault(require("fs"));
36
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
37
  const zlib_1 = __importDefault(require("zlib"));
15
38
  const tar_1 = __importDefault(require("tar"));
39
+ const path_1 = __importDefault(require("path"));
16
40
  const fp_1 = require("lodash/fp");
17
41
  const stream_chain_1 = require("stream-chain");
18
42
  const stream_1 = require("stream");
19
43
  const Parser_1 = require("stream-json/jsonl/Parser");
20
- const encryption_1 = require("../encryption");
21
- const utils_1 = require("../utils");
44
+ const encryption_1 = require("../../encryption");
45
+ const utils = __importStar(require("../../utils"));
22
46
  /**
23
47
  * Constant for the metadata file path
24
48
  */
@@ -33,19 +57,22 @@ class LocalFileSourceProvider {
33
57
  this.type = 'source';
34
58
  this.name = 'source::local-file';
35
59
  this.options = options;
36
- if (this.options.encrypted && this.options.encryptionKey === undefined) {
60
+ const { encryption } = this.options;
61
+ if (encryption.enabled && encryption.key === undefined) {
37
62
  throw new Error('Missing encryption key');
38
63
  }
39
64
  }
40
65
  /**
41
66
  * Pre flight checks regarding the provided options (making sure that the provided path is correct, etc...)
42
67
  */
43
- bootstrap() {
44
- const path = this.options.backupFilePath;
45
- const isValidBackupPath = fs_1.default.existsSync(path);
46
- // Check if the provided path exists
47
- if (!isValidBackupPath) {
48
- throw new Error(`Invalid backup file path provided. "${path}" does not exist on the filesystem.`);
68
+ async bootstrap() {
69
+ const { path: filePath } = this.options.file;
70
+ try {
71
+ // This is only to show a nicer error, it doesn't ensure the file will still exist when we try to open it later
72
+ await fs_extra_1.default.access(filePath, fs_extra_1.default.constants.R_OK);
73
+ }
74
+ catch (e) {
75
+ throw new Error(`Can't access file "${filePath}".`);
49
76
  }
50
77
  }
51
78
  getMetadata() {
@@ -55,7 +82,7 @@ class LocalFileSourceProvider {
55
82
  return __classPrivateFieldGet(this, _LocalFileSourceProvider_instances, "m", _LocalFileSourceProvider_parseJSONFile).call(this, backupStream, METADATA_FILE_PATH);
56
83
  }
57
84
  async getSchemas() {
58
- const schemas = await (0, utils_1.collect)(this.streamSchemas());
85
+ const schemas = await utils.stream.collect(this.streamSchemas());
59
86
  return (0, fp_1.keyBy)('uid', schemas);
60
87
  }
61
88
  streamEntities() {
@@ -71,46 +98,74 @@ class LocalFileSourceProvider {
71
98
  // NOTE: TBD
72
99
  return __classPrivateFieldGet(this, _LocalFileSourceProvider_instances, "m", _LocalFileSourceProvider_streamJsonlDirectory).call(this, 'configuration');
73
100
  }
101
+ streamAssets() {
102
+ const inStream = __classPrivateFieldGet(this, _LocalFileSourceProvider_instances, "m", _LocalFileSourceProvider_getBackupStream).call(this);
103
+ const outStream = new stream_1.PassThrough({ objectMode: true });
104
+ (0, stream_1.pipeline)([
105
+ inStream,
106
+ new tar_1.default.Parse({
107
+ filter(filePath, entry) {
108
+ if (entry.type !== 'File') {
109
+ return false;
110
+ }
111
+ const parts = filePath.split('/');
112
+ return parts[0] === 'assets' && parts[1] === 'uploads';
113
+ },
114
+ onentry(entry) {
115
+ const { path: filePath, size = 0 } = entry;
116
+ const file = path_1.default.basename(filePath);
117
+ const asset = {
118
+ filename: file,
119
+ filepath: filePath,
120
+ stats: { size },
121
+ stream: entry,
122
+ };
123
+ outStream.write(asset);
124
+ },
125
+ }),
126
+ ], () => outStream.end());
127
+ return outStream;
128
+ }
74
129
  }
75
- _LocalFileSourceProvider_instances = new WeakSet(), _LocalFileSourceProvider_getBackupStream = function _LocalFileSourceProvider_getBackupStream(decompress = true) {
76
- const path = this.options.backupFilePath;
77
- const readStream = fs_1.default.createReadStream(path);
78
- const streams = [readStream];
79
- // Handle decompression
80
- if (decompress) {
130
+ _LocalFileSourceProvider_instances = new WeakSet(), _LocalFileSourceProvider_getBackupStream = function _LocalFileSourceProvider_getBackupStream() {
131
+ const { file, encryption, compression } = this.options;
132
+ const streams = [];
133
+ try {
134
+ streams.push(fs_extra_1.default.createReadStream(file.path));
135
+ }
136
+ catch (e) {
137
+ throw new Error(`Could not read backup file path provided at "${this.options.file.path}"`);
138
+ }
139
+ if (encryption.enabled && encryption.key) {
140
+ streams.push((0, encryption_1.createDecryptionCipher)(encryption.key));
141
+ }
142
+ if (compression.enabled) {
81
143
  streams.push(zlib_1.default.createGunzip());
82
144
  }
83
145
  return (0, stream_chain_1.chain)(streams);
84
146
  }, _LocalFileSourceProvider_streamJsonlDirectory = function _LocalFileSourceProvider_streamJsonlDirectory(directory) {
85
- const options = this.options;
86
147
  const inStream = __classPrivateFieldGet(this, _LocalFileSourceProvider_instances, "m", _LocalFileSourceProvider_getBackupStream).call(this);
87
148
  const outStream = new stream_1.PassThrough({ objectMode: true });
88
149
  (0, stream_1.pipeline)([
89
150
  inStream,
90
151
  new tar_1.default.Parse({
91
- filter(path, entry) {
152
+ filter(filePath, entry) {
92
153
  if (entry.type !== 'File') {
93
154
  return false;
94
155
  }
95
- const parts = path.split('/');
156
+ const parts = filePath.split('/');
96
157
  if (parts.length !== 2) {
97
158
  return false;
98
159
  }
99
160
  return parts[0] === directory;
100
161
  },
101
162
  onentry(entry) {
102
- const transforms = [];
103
- if (options.encrypted) {
104
- transforms.push((0, encryption_1.createDecryptionCipher)(options.encryptionKey));
105
- }
106
- if (options.compressed) {
107
- transforms.push(zlib_1.default.createGunzip());
108
- }
109
- transforms.push(
110
- // JSONL parser to read the data chunks one by one (line by line)
111
- (0, Parser_1.parser)(),
112
- // The JSONL parser returns each line as key/value
113
- (line) => line.value);
163
+ const transforms = [
164
+ // JSONL parser to read the data chunks one by one (line by line)
165
+ (0, Parser_1.parser)(),
166
+ // The JSONL parser returns each line as key/value
167
+ (line) => line.value,
168
+ ];
114
169
  entry
115
170
  // Pipe transforms
116
171
  .pipe((0, stream_chain_1.chain)(transforms))
@@ -135,8 +190,8 @@ _LocalFileSourceProvider_instances = new WeakSet(), _LocalFileSourceProvider_get
135
190
  /**
136
191
  * Filter the parsed entries to only keep the one that matches the given filepath
137
192
  */
138
- filter(path, entry) {
139
- return path === filePath && entry.type === 'File';
193
+ filter(entryPath, entry) {
194
+ return entryPath === filePath && entry.type === 'File';
140
195
  },
141
196
  /**
142
197
  * Whenever an entry passes the filter method, process it
@@ -155,8 +210,8 @@ _LocalFileSourceProvider_instances = new WeakSet(), _LocalFileSourceProvider_get
155
210
  ], () => {
156
211
  // If the promise hasn't been resolved and we've parsed all
157
212
  // the archive entries, then the file doesn't exist
158
- reject(`${filePath} not found in the archive stream`);
213
+ reject(new Error(`File "${filePath}" not found`));
159
214
  });
160
215
  });
161
216
  };
162
- //# sourceMappingURL=local-file-source-provider.js.map
217
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,31 @@
1
+ /// <reference types="lodash" />
2
+ /// <reference types="node" />
3
+ import { Writable } from 'stream';
4
+ import type { IDestinationProvider, IMetadata, ProviderType } from '../../../types';
5
+ import { restore } from './strategies';
6
+ export declare const VALID_CONFLICT_STRATEGIES: string[];
7
+ export declare const DEFAULT_CONFLICT_STRATEGY = "restore";
8
+ interface ILocalStrapiDestinationProviderOptions {
9
+ getStrapi(): Strapi.Strapi | Promise<Strapi.Strapi>;
10
+ restore?: restore.IRestoreOptions;
11
+ strategy: 'restore' | 'merge';
12
+ }
13
+ declare class LocalStrapiDestinationProvider implements IDestinationProvider {
14
+ #private;
15
+ name: string;
16
+ type: ProviderType;
17
+ options: ILocalStrapiDestinationProviderOptions;
18
+ strapi?: Strapi.Strapi;
19
+ constructor(options: ILocalStrapiDestinationProviderOptions);
20
+ bootstrap(): Promise<void>;
21
+ close(): Promise<void>;
22
+ beforeTransfer(): Promise<void>;
23
+ getMetadata(): IMetadata | Promise<IMetadata>;
24
+ getSchemas(): import("lodash").Dictionary<Partial<import("@strapi/strapi").Schema>>;
25
+ getEntitiesStream(): Writable;
26
+ getAssetsStream(): Promise<Writable>;
27
+ getConfigurationStream(): Promise<Writable>;
28
+ getLinksStream(): Promise<Writable>;
29
+ }
30
+ export declare const createLocalStrapiDestinationProvider: (options: ILocalStrapiDestinationProviderOptions) => LocalStrapiDestinationProvider;
31
+ export {};