@strapi/data-transfer 4.6.0 → 4.7.0-beta.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.
@@ -374,7 +374,7 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
374
374
  keys.forEach((key) => {
375
375
  const sourceSchema = sourceSchemas[key];
376
376
  const destinationSchema = destinationSchemas[key];
377
- const schemaDiffs = (0, validation_1.compareSchemas)(destinationSchema, sourceSchema, strategy);
377
+ const schemaDiffs = (0, validation_1.compareSchemas)(sourceSchema, destinationSchema, strategy);
378
378
  if (schemaDiffs.length) {
379
379
  diffs[key] = schemaDiffs;
380
380
  }
@@ -388,13 +388,16 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
388
388
  .map((diff) => {
389
389
  const path = diff.path.join('.');
390
390
  if (diff.kind === 'added') {
391
- return `Added "${path}": "${diff.value}" (${diff.type})`;
391
+ return `${path} exists in destination schema but not in source schema`;
392
392
  }
393
393
  if (diff.kind === 'deleted') {
394
- return `Removed "${path}"`;
394
+ return `${path} exists in source schema but not in destination schema`;
395
395
  }
396
396
  if (diff.kind === 'modified') {
397
- return `Modified "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
397
+ if (diff.types[0] === diff.types[1]) {
398
+ return `Schema value changed at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
399
+ }
400
+ return `Schema has differing data types at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
398
401
  }
399
402
  throw new errors_1.TransferEngineValidationError(`Invalid diff found for "${uid}"`, {
400
403
  check: `schema on ${uid}`,
@@ -19,6 +19,7 @@ const stream_chain_1 = require("stream-chain");
19
19
  const stream_1 = require("stream");
20
20
  const encryption_1 = require("../../../utils/encryption");
21
21
  const utils_1 = require("./utils");
22
+ const providers_1 = require("../../../errors/providers");
22
23
  const createLocalFileDestinationProvider = (options) => {
23
24
  return new LocalFileDestinationProvider(options);
24
25
  };
@@ -47,6 +48,12 @@ class LocalFileDestinationProvider {
47
48
  }
48
49
  __classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream = tar_stream_1.default.pack();
49
50
  const outStream = (0, fs_extra_1.createWriteStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get));
51
+ outStream.on('error', (err) => {
52
+ if (err.code === 'ENOSPC') {
53
+ throw new providers_1.ProviderTransferError("Your server doesn't have space to proceed with the import.");
54
+ }
55
+ throw err;
56
+ });
50
57
  const archiveTransforms = [];
51
58
  if (compression.enabled) {
52
59
  archiveTransforms.push(this.createGzip());
@@ -26,6 +26,7 @@ const stream_1 = require("stream");
26
26
  const Parser_1 = require("stream-json/jsonl/Parser");
27
27
  const encryption_1 = require("../../../utils/encryption");
28
28
  const stream_2 = require("../../../utils/stream");
29
+ const providers_1 = require("../../../errors/providers");
29
30
  /**
30
31
  * Constant for the metadata file path
31
32
  */
@@ -56,7 +57,10 @@ class LocalFileSourceProvider {
56
57
  __classPrivateFieldSet(this, _LocalFileSourceProvider_metadata, await this.getMetadata(), "f");
57
58
  }
58
59
  catch (e) {
59
- throw new Error(`Can't read file "${filePath}".`);
60
+ if (this.options?.encryption?.enabled) {
61
+ throw new providers_1.ProviderInitializationError(`Key is incorrect or the file '${filePath}' is not a valid Strapi data file.`);
62
+ }
63
+ throw new providers_1.ProviderInitializationError(`File '${filePath}' is not a valid Strapi data file.`);
60
64
  }
61
65
  }
62
66
  getMetadata() {
@@ -147,13 +151,24 @@ _LocalFileSourceProvider_metadata = new WeakMap(), _LocalFileSourceProvider_inst
147
151
  async onentry(entry) {
148
152
  const transforms = [
149
153
  // JSONL parser to read the data chunks one by one (line by line)
150
- (0, Parser_1.parser)(),
154
+ (0, Parser_1.parser)({
155
+ checkErrors: true,
156
+ }),
151
157
  // The JSONL parser returns each line as key/value
152
158
  (line) => line.value,
153
159
  ];
154
160
  const stream = entry.pipe((0, stream_chain_1.chain)(transforms));
155
- for await (const chunk of stream) {
156
- outStream.write(chunk);
161
+ try {
162
+ for await (const chunk of stream) {
163
+ outStream.write(chunk);
164
+ }
165
+ }
166
+ catch (e) {
167
+ outStream.destroy(new providers_1.ProviderTransferError(`Error parsing backup files from backup file ${entry.path}: ${e.message}`, {
168
+ details: {
169
+ error: e,
170
+ },
171
+ }));
157
172
  }
158
173
  },
159
174
  }),
@@ -163,7 +178,9 @@ _LocalFileSourceProvider_metadata = new WeakMap(), _LocalFileSourceProvider_inst
163
178
  outStream.end();
164
179
  });
165
180
  return outStream;
166
- }, _LocalFileSourceProvider_parseJSONFile = async function _LocalFileSourceProvider_parseJSONFile(fileStream, filePath) {
181
+ }, _LocalFileSourceProvider_parseJSONFile =
182
+ // For collecting an entire JSON file then parsing it, not for streaming JSONL
183
+ async function _LocalFileSourceProvider_parseJSONFile(fileStream, filePath) {
167
184
  return new Promise((resolve, reject) => {
168
185
  (0, stream_1.pipeline)([
169
186
  fileStream,
@@ -1,4 +1,3 @@
1
1
  export * as providers from './providers';
2
2
  export * as queries from './queries';
3
3
  export * as remote from './remote';
4
- export { default as register } from './register';
@@ -22,14 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.register = exports.remote = exports.queries = exports.providers = void 0;
26
+ exports.remote = exports.queries = exports.providers = void 0;
30
27
  exports.providers = __importStar(require("./providers"));
31
28
  exports.queries = __importStar(require("./queries"));
32
29
  exports.remote = __importStar(require("./remote"));
33
- var register_1 = require("./register");
34
- Object.defineProperty(exports, "register", { enumerable: true, get: function () { return __importDefault(register_1).default; } });
35
30
  //# sourceMappingURL=index.js.map
@@ -136,7 +136,7 @@ class LocalStrapiDestinationProvider {
136
136
  (0, providers_2.assertValidStrapi)(this.strapi, 'Not able to stream Assets');
137
137
  const assetsDirectory = path_1.default.join(this.strapi.dirs.static.public, 'uploads');
138
138
  const backupDirectory = path_1.default.join(this.strapi.dirs.static.public, `uploads_backup_${Date.now()}`);
139
- await fse.rename(assetsDirectory, backupDirectory);
139
+ await fse.move(assetsDirectory, backupDirectory);
140
140
  await fse.mkdir(assetsDirectory);
141
141
  // Create a .gitkeep file to ensure the directory is not empty
142
142
  await fse.outputFile(path_1.default.join(assetsDirectory, '.gitkeep'), '');
@@ -153,10 +153,13 @@ class LocalStrapiDestinationProvider {
153
153
  .pipe(writableStream)
154
154
  .on('close', callback)
155
155
  .on('error', async (error) => {
156
+ const errorMessage = error.code === 'ENOSPC'
157
+ ? " Your server doesn't have space to proceed with the import. "
158
+ : ' ';
156
159
  try {
157
160
  await fse.rm(assetsDirectory, { recursive: true, force: true });
158
- await fse.rename(backupDirectory, assetsDirectory);
159
- this.destroy(new providers_1.ProviderTransferError(`There was an error during the transfer process. The original files have been restored to ${assetsDirectory}`));
161
+ await fse.move(backupDirectory, assetsDirectory);
162
+ this.destroy(new providers_1.ProviderTransferError(`There was an error during the transfer process.${errorMessage}The original files have been restored to ${assetsDirectory}`));
160
163
  }
161
164
  catch (err) {
162
165
  throw new providers_1.ProviderTransferError(`There was an error doing the rollback process. The original files are in ${backupDirectory}, but we failed to restore them to ${assetsDirectory}`);
@@ -4,18 +4,13 @@ import { Writable } from 'stream';
4
4
  import { createDispatcher } from './utils';
5
5
  import type { IDestinationProvider, IMetadata, ProviderType } from '../../../../types';
6
6
  import type { ILocalStrapiDestinationProviderOptions } from '../local-destination';
7
- interface ITokenAuth {
7
+ interface ITransferTokenAuth {
8
8
  type: 'token';
9
9
  token: string;
10
10
  }
11
- interface ICredentialsAuth {
12
- type: 'credentials';
13
- email: string;
14
- password: string;
15
- }
16
11
  export interface IRemoteStrapiDestinationProviderOptions extends Pick<ILocalStrapiDestinationProviderOptions, 'restore' | 'strategy'> {
17
12
  url: URL;
18
- auth?: ITokenAuth | ICredentialsAuth;
13
+ auth?: ITransferTokenAuth;
19
14
  }
20
15
  declare class RemoteStrapiDestinationProvider implements IDestinationProvider {
21
16
  #private;
@@ -56,7 +56,6 @@ class RemoteStrapiDestinationProvider {
56
56
  }
57
57
  const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
58
58
  const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}`;
59
- const validAuthMethods = ['token'];
60
59
  // No auth defined, trying public access for transfer
61
60
  if (!auth) {
62
61
  ws = new ws_1.WebSocket(wsUrl);
@@ -68,11 +67,10 @@ class RemoteStrapiDestinationProvider {
68
67
  }
69
68
  // Invalid auth method provided
70
69
  else {
71
- throw new providers_1.ProviderValidationError('Auth method not implemented', {
70
+ throw new providers_1.ProviderValidationError('Auth method not available', {
72
71
  check: 'auth.type',
73
72
  details: {
74
73
  auth: auth.type,
75
- validAuthMethods,
76
74
  },
77
75
  });
78
76
  }
@@ -1,2 +1,2 @@
1
- export declare const TRANSFER_PATH = "/transfer";
2
- export declare const TRANSFER_METHODS: string[];
1
+ export declare const TRANSFER_PATH: "/transfer/runner/connect";
2
+ export declare const TRANSFER_METHODS: readonly ["push", "pull"];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TRANSFER_METHODS = exports.TRANSFER_PATH = void 0;
4
- exports.TRANSFER_PATH = '/transfer';
4
+ exports.TRANSFER_PATH = '/transfer/runner/connect';
5
5
  exports.TRANSFER_METHODS = ['push', 'pull'];
6
6
  //# sourceMappingURL=constants.js.map
@@ -1,3 +1,10 @@
1
1
  import type { Context } from 'koa';
2
2
  import type { ServerOptions } from 'ws';
3
- export declare const createTransferHandler: (options?: ServerOptions) => (ctx: Context) => Promise<void>;
3
+ import { TRANSFER_METHODS } from './constants';
4
+ declare type TransferMethod = typeof TRANSFER_METHODS[number];
5
+ interface IHandlerOptions {
6
+ verify: (ctx: Context, scope?: TransferMethod) => Promise<void>;
7
+ server?: ServerOptions;
8
+ }
9
+ export declare const createTransferHandler: (options: IHandlerOptions) => (ctx: Context) => Promise<void>;
10
+ export {};
@@ -9,185 +9,191 @@ const ws_1 = require("ws");
9
9
  const push_1 = __importDefault(require("./controllers/push"));
10
10
  const providers_1 = require("../../errors/providers");
11
11
  const constants_1 = require("./constants");
12
- const createTransferHandler = (options = {}) => async (ctx) => {
13
- const upgradeHeader = (ctx.request.headers.upgrade || '')
14
- .split(',')
15
- .map((s) => s.trim().toLowerCase());
12
+ const createTransferHandler = (options) => {
13
+ const { verify, server: serverOptions } = options;
16
14
  // Create the websocket server
17
- const wss = new ws_1.WebSocket.Server({ ...options, noServer: true });
18
- if (upgradeHeader.includes('websocket')) {
19
- wss.handleUpgrade(ctx.req, ctx.request.socket, Buffer.alloc(0), (ws) => {
20
- // Create a connection between the client & the server
21
- wss.emit('connection', ws, ctx.req);
22
- const state = {};
23
- let uuid;
24
- /**
25
- * Format error & message to follow the remote transfer protocol
26
- */
27
- const callback = (e = null, data) => {
28
- return new Promise((resolve, reject) => {
29
- if (!uuid) {
30
- reject(new Error('Missing uuid for this message'));
31
- return;
32
- }
33
- const payload = JSON.stringify({
34
- uuid,
35
- data: data ?? null,
36
- error: e
37
- ? {
38
- code: 'ERR',
39
- message: e?.message,
40
- }
41
- : null,
15
+ const wss = new ws_1.WebSocket.Server({ ...serverOptions, noServer: true });
16
+ return async (ctx) => {
17
+ const verifyAuth = (scope) => verify(ctx, scope);
18
+ const upgradeHeader = (ctx.request.headers.upgrade || '')
19
+ .split(',')
20
+ .map((s) => s.trim().toLowerCase());
21
+ if (upgradeHeader.includes('websocket')) {
22
+ wss.handleUpgrade(ctx.req, ctx.request.socket, Buffer.alloc(0), (ws) => {
23
+ // Create a connection between the client & the server
24
+ wss.emit('connection', ws, ctx.req);
25
+ const state = {};
26
+ let uuid;
27
+ /**
28
+ * Format error & message to follow the remote transfer protocol
29
+ */
30
+ const callback = (e = null, data) => {
31
+ return new Promise((resolve, reject) => {
32
+ if (!uuid) {
33
+ reject(new Error('Missing uuid for this message'));
34
+ return;
35
+ }
36
+ const payload = JSON.stringify({
37
+ uuid,
38
+ data: data ?? null,
39
+ error: e
40
+ ? {
41
+ code: 'ERR',
42
+ message: e?.message,
43
+ }
44
+ : null,
45
+ });
46
+ ws.send(payload, (error) => (error ? reject(error) : resolve()));
42
47
  });
43
- ws.send(payload, (error) => (error ? reject(error) : resolve()));
44
- });
45
- };
46
- /**
47
- * Wrap a function call to catch errors and answer the request with the correct format
48
- */
49
- const answer = async (fn) => {
50
- try {
51
- const response = await fn();
52
- callback(null, response);
53
- }
54
- catch (e) {
55
- if (e instanceof Error) {
56
- callback(e);
57
- }
58
- else if (typeof e === 'string') {
59
- callback(new providers_1.ProviderTransferError(e));
48
+ };
49
+ /**
50
+ * Wrap a function call to catch errors and answer the request with the correct format
51
+ */
52
+ const answer = async (fn) => {
53
+ try {
54
+ const response = await fn();
55
+ callback(null, response);
56
+ }
57
+ catch (e) {
58
+ if (e instanceof Error) {
59
+ callback(e);
60
+ }
61
+ else if (typeof e === 'string') {
62
+ callback(new providers_1.ProviderTransferError(e));
63
+ }
64
+ else {
65
+ callback(new providers_1.ProviderTransferError('Unexpected error', {
66
+ error: e,
67
+ }));
68
+ }
60
69
  }
70
+ };
71
+ const teardown = async () => {
72
+ await verifyAuth(state.transfer?.kind);
73
+ delete state.controller;
74
+ delete state.transfer;
75
+ return { ok: true };
76
+ };
77
+ const init = async (msg) => {
78
+ // TODO: this only checks for this instance of node: we should consider a database lock
79
+ if (state.controller) {
80
+ throw new providers_1.ProviderInitializationError('Transfer already in progres');
81
+ }
82
+ const { transfer } = msg.params;
83
+ await verifyAuth(transfer);
84
+ // Push transfer
85
+ if (transfer === 'push') {
86
+ const { options: controllerOptions } = msg.params;
87
+ state.controller = (0, push_1.default)({
88
+ ...controllerOptions,
89
+ autoDestroy: false,
90
+ getStrapi: () => strapi,
91
+ });
92
+ }
93
+ // Pull or any other string
61
94
  else {
62
- callback(new providers_1.ProviderTransferError('Unexpected error', {
63
- error: e,
64
- }));
95
+ throw new providers_1.ProviderTransferError(`Transfer type not implemented: "${transfer}"`, {
96
+ transfer,
97
+ validTransfers: constants_1.TRANSFER_METHODS,
98
+ });
65
99
  }
66
- }
67
- };
68
- const teardown = () => {
69
- delete state.controller;
70
- delete state.transfer;
71
- return { ok: true };
72
- };
73
- const init = (msg) => {
74
- // TODO: this only checks for this instance of node: we should consider a database lock
75
- if (state.controller) {
76
- throw new providers_1.ProviderInitializationError('Transfer already in progres');
77
- }
78
- const { transfer } = msg.params;
79
- // Push transfer
80
- if (transfer === 'push') {
81
- const { options: controllerOptions } = msg.params;
82
- state.controller = (0, push_1.default)({
83
- ...controllerOptions,
84
- autoDestroy: false,
85
- getStrapi: () => strapi,
86
- });
87
- }
88
- // Pull or any other string
89
- else {
90
- throw new providers_1.ProviderTransferError(`Transfer type not implemented: "${transfer}"`, {
91
- transfer,
92
- validTransfers: constants_1.TRANSFER_METHODS,
93
- });
94
- }
95
- state.transfer = { id: (0, crypto_1.randomUUID)(), kind: transfer };
96
- return { transferID: state.transfer.id };
97
- };
98
- /**
99
- * On command message (init, end, status, ...)
100
- */
101
- const onCommand = async (msg) => {
102
- const { command } = msg;
103
- if (command === 'init') {
104
- await answer(() => init(msg));
105
- }
106
- if (command === 'end') {
107
- await answer(teardown);
108
- }
109
- if (command === 'status') {
110
- await callback(new providers_1.ProviderTransferError('Command not implemented: "status"', {
111
- command,
112
- validCommands: ['init', 'end', 'status'],
113
- }));
114
- }
115
- };
116
- const onTransferCommand = async (msg) => {
117
- const { transferID, kind } = msg;
118
- const { controller } = state;
119
- // TODO: (re)move this check
120
- // It shouldn't be possible to start a pull transfer for now, so reaching
121
- // this code should be impossible too, but this has been added by security
122
- if (state.transfer?.kind === 'pull') {
123
- return callback(new providers_1.ProviderTransferError('Pull transfer not implemented'));
124
- }
125
- if (!controller) {
126
- return callback(new providers_1.ProviderTransferError("The transfer hasn't been initialized"));
127
- }
128
- if (!transferID) {
129
- return callback(new providers_1.ProviderTransferError('Missing transfer ID'));
130
- }
131
- // Action
132
- if (kind === 'action') {
133
- const { action } = msg;
134
- if (!(action in controller.actions)) {
135
- return callback(new providers_1.ProviderTransferError(`Invalid action provided: "${action}"`, {
136
- action,
137
- validActions: Object.keys(controller.actions),
100
+ state.transfer = { id: (0, crypto_1.randomUUID)(), kind: transfer };
101
+ return { transferID: state.transfer.id };
102
+ };
103
+ /**
104
+ * On command message (init, end, status, ...)
105
+ */
106
+ const onCommand = async (msg) => {
107
+ const { command } = msg;
108
+ if (command === 'init') {
109
+ await answer(() => init(msg));
110
+ }
111
+ if (command === 'end') {
112
+ await answer(teardown);
113
+ }
114
+ if (command === 'status') {
115
+ await callback(new providers_1.ProviderTransferError('Command not implemented: "status"', {
116
+ command,
117
+ validCommands: ['init', 'end', 'status'],
138
118
  }));
139
119
  }
140
- await answer(() => controller.actions[action]());
141
- }
142
- // Transfer
143
- else if (kind === 'step') {
144
- // We can only have push transfer message for the moment
145
- const message = msg;
146
- // TODO: lock transfer process
147
- if (message.action === 'start') {
148
- // console.log('Starting transfer for ', message.step);
149
- }
150
- // Stream step
151
- else if (message.action === 'stream') {
152
- await answer(() => controller.transfer[message.step]?.(message.data));
153
- }
154
- // TODO: unlock transfer process
155
- else if (message.action === 'end') {
156
- // console.log('Ending transfer for ', message.step);
157
- }
158
- }
159
- };
160
- ws.on('close', () => {
161
- teardown();
162
- });
163
- ws.on('error', (e) => {
164
- teardown();
165
- // TODO: is logging a console error to the running instance of Strapi ok to do? Should we check for an existing strapi.logger to use?
166
- console.error(e);
167
- });
168
- ws.on('message', async (raw) => {
169
- const msg = JSON.parse(raw.toString());
170
- if (!msg.uuid) {
171
- await callback(new providers_1.ProviderTransferError('Missing uuid in message'));
172
- return;
173
- }
174
- uuid = msg.uuid;
175
- // Regular command message (init, end, status)
176
- if (msg.type === 'command') {
177
- await onCommand(msg);
178
- }
179
- // Transfer message (the transfer must be initialized first)
180
- else if (msg.type === 'transfer') {
181
- await onTransferCommand(msg);
182
- }
183
- // Invalid messages
184
- else {
185
- await callback(new providers_1.ProviderTransferError('Bad request'));
186
- }
120
+ };
121
+ const onTransferCommand = async (msg) => {
122
+ const { transferID, kind } = msg;
123
+ const { controller } = state;
124
+ await verifyAuth(state.transfer?.kind);
125
+ // TODO: (re)move this check
126
+ // It shouldn't be possible to start a pull transfer for now, so reaching
127
+ // this code should be impossible too, but this has been added by security
128
+ if (state.transfer?.kind === 'pull') {
129
+ return callback(new providers_1.ProviderTransferError('Pull transfer not implemented'));
130
+ }
131
+ if (!controller) {
132
+ return callback(new providers_1.ProviderTransferError("The transfer hasn't been initialized"));
133
+ }
134
+ if (!transferID) {
135
+ return callback(new providers_1.ProviderTransferError('Missing transfer ID'));
136
+ }
137
+ // Action
138
+ if (kind === 'action') {
139
+ const { action } = msg;
140
+ if (!(action in controller.actions)) {
141
+ return callback(new providers_1.ProviderTransferError(`Invalid action provided: "${action}"`, {
142
+ action,
143
+ validActions: Object.keys(controller.actions),
144
+ }));
145
+ }
146
+ await answer(() => controller.actions[action]());
147
+ }
148
+ // Transfer
149
+ else if (kind === 'step') {
150
+ // We can only have push transfer message for the moment
151
+ const message = msg;
152
+ // TODO: lock transfer process
153
+ if (message.action === 'start') {
154
+ // console.log('Starting transfer for ', message.step);
155
+ }
156
+ // Stream step
157
+ else if (message.action === 'stream') {
158
+ await answer(() => controller.transfer[message.step]?.(message.data));
159
+ }
160
+ // TODO: unlock transfer process
161
+ else if (message.action === 'end') {
162
+ // console.log('Ending transfer for ', message.step);
163
+ }
164
+ }
165
+ };
166
+ ws.on('close', () => {
167
+ teardown();
168
+ });
169
+ ws.on('error', (e) => {
170
+ teardown();
171
+ strapi.log.error(e);
172
+ });
173
+ ws.on('message', async (raw) => {
174
+ const msg = JSON.parse(raw.toString());
175
+ if (!msg.uuid) {
176
+ await callback(new providers_1.ProviderTransferError('Missing uuid in message'));
177
+ return;
178
+ }
179
+ uuid = msg.uuid;
180
+ // Regular command message (init, end, status)
181
+ if (msg.type === 'command') {
182
+ await onCommand(msg);
183
+ }
184
+ // Transfer message (the transfer must be initialized first)
185
+ else if (msg.type === 'transfer') {
186
+ await onTransferCommand(msg);
187
+ }
188
+ // Invalid messages
189
+ else {
190
+ await callback(new providers_1.ProviderTransferError('Bad request'));
191
+ }
192
+ });
187
193
  });
188
- });
189
- ctx.respond = false;
190
- }
194
+ ctx.respond = false;
195
+ }
196
+ };
191
197
  };
192
198
  exports.createTransferHandler = createTransferHandler;
193
199
  //# sourceMappingURL=handlers.js.map
@@ -1,3 +1,3 @@
1
1
  export * as controllers from './controllers';
2
- export * as routes from './routes';
3
2
  export * as constants from './constants';
3
+ export * as handlers from './handlers';
@@ -23,8 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.constants = exports.routes = exports.controllers = void 0;
26
+ exports.handlers = exports.constants = exports.controllers = void 0;
27
27
  exports.controllers = __importStar(require("./controllers"));
28
- exports.routes = __importStar(require("./routes"));
29
28
  exports.constants = __importStar(require("./constants"));
29
+ exports.handlers = __importStar(require("./handlers"));
30
30
  //# sourceMappingURL=index.js.map
package/lib/utils/json.js CHANGED
@@ -33,12 +33,6 @@ const diff = (a, b, ctx = createContext()) => {
33
33
  });
34
34
  return diffs;
35
35
  };
36
- if (aType === 'undefined') {
37
- return added();
38
- }
39
- if (bType === 'undefined') {
40
- return deleted();
41
- }
42
36
  if ((0, fp_1.isArray)(a) && (0, fp_1.isArray)(b)) {
43
37
  let k = 0;
44
38
  for (const [aItem, bItem] of (0, fp_1.zip)(a, b)) {
@@ -60,6 +54,12 @@ const diff = (a, b, ctx = createContext()) => {
60
54
  return diffs;
61
55
  }
62
56
  if (!(0, fp_1.isEqual)(a, b)) {
57
+ if (aType === 'undefined') {
58
+ return added();
59
+ }
60
+ if (bType === 'undefined') {
61
+ return deleted();
62
+ }
63
63
  return modified();
64
64
  }
65
65
  return diffs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/data-transfer",
3
- "version": "4.6.0",
3
+ "version": "4.7.0-beta.0",
4
4
  "description": "Data transfer capabilities for Strapi",
5
5
  "keywords": [
6
6
  "strapi",
@@ -39,8 +39,8 @@
39
39
  "lib": "./lib"
40
40
  },
41
41
  "dependencies": {
42
- "@strapi/logger": "4.6.0",
43
- "@strapi/strapi": "4.6.0",
42
+ "@strapi/logger": "4.7.0-beta.0",
43
+ "@strapi/strapi": "4.7.0-beta.0",
44
44
  "chalk": "4.1.2",
45
45
  "fs-extra": "10.0.0",
46
46
  "lodash": "4.17.21",
@@ -60,7 +60,7 @@
60
60
  "@types/koa": "2.13.4",
61
61
  "@types/semver": "7.3.13",
62
62
  "@types/stream-chain": "2.0.1",
63
- "@types/stream-json": "1.7.2",
63
+ "@types/stream-json": "1.7.3",
64
64
  "@types/tar": "6.1.3",
65
65
  "@types/tar-stream": "2.2.2",
66
66
  "@types/uuid": "9.0.0",
@@ -73,5 +73,5 @@
73
73
  "node": ">=14.19.1 <=18.x.x",
74
74
  "npm": ">=6.0.0"
75
75
  },
76
- "gitHead": "a9e55435c489f3379d88565bf3f729deb29bfb45"
76
+ "gitHead": "880ba7af867ad43c4cc45b47467b76a9b5606b6e"
77
77
  }
@@ -1,7 +0,0 @@
1
- /**
2
- * This is intended to be called on Strapi register phase.
3
- *
4
- * It registers a transfer route in the Strapi admin router.
5
- */
6
- declare const register: (strapi: Strapi.Strapi) => void;
7
- export default register;
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const remote_1 = require("./remote");
4
- /**
5
- * This is intended to be called on Strapi register phase.
6
- *
7
- * It registers a transfer route in the Strapi admin router.
8
- */
9
- const register = (strapi) => {
10
- remote_1.routes.registerAdminTransferRoute(strapi);
11
- };
12
- exports.default = register;
13
- //# sourceMappingURL=register.js.map
@@ -1,21 +0,0 @@
1
- import type { Context } from 'koa';
2
- declare module '@strapi/strapi' {
3
- interface Strapi {
4
- admin: {
5
- routes: {
6
- method: string;
7
- path: string;
8
- handler: (ctx: Context) => Promise<void>;
9
- config: unknown;
10
- }[];
11
- };
12
- }
13
- }
14
- /**
15
- * Register a transfer route in the Strapi admin router.
16
- *
17
- * It exposes a WS server that can be used to run and manage transfer processes.
18
- *
19
- * @param strapi - A Strapi instance
20
- */
21
- export declare const registerAdminTransferRoute: (strapi: Strapi.Strapi) => void;
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerAdminTransferRoute = void 0;
4
- const constants_1 = require("./constants");
5
- const handlers_1 = require("./handlers");
6
- /**
7
- * Register a transfer route in the Strapi admin router.
8
- *
9
- * It exposes a WS server that can be used to run and manage transfer processes.
10
- *
11
- * @param strapi - A Strapi instance
12
- */
13
- const registerAdminTransferRoute = (strapi) => {
14
- strapi.admin.routes.push({
15
- method: 'GET',
16
- path: constants_1.TRANSFER_PATH,
17
- handler: (0, handlers_1.createTransferHandler)(),
18
- config: { auth: false },
19
- });
20
- };
21
- exports.registerAdminTransferRoute = registerAdminTransferRoute;
22
- //# sourceMappingURL=routes.js.map