@strapi/data-transfer 4.8.2 → 4.9.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 (34) hide show
  1. package/lib/engine/index.d.ts +1 -0
  2. package/lib/engine/index.js +30 -4
  3. package/lib/strapi/providers/index.d.ts +1 -0
  4. package/lib/strapi/providers/index.js +1 -0
  5. package/lib/strapi/providers/remote-destination/index.d.ts +1 -1
  6. package/lib/strapi/providers/remote-destination/index.js +3 -3
  7. package/lib/strapi/providers/remote-source/index.d.ts +36 -0
  8. package/lib/strapi/providers/remote-source/index.js +228 -0
  9. package/lib/strapi/providers/{remote-destination/utils.d.ts → utils.d.ts} +3 -3
  10. package/lib/strapi/providers/{remote-destination/utils.js → utils.js} +1 -1
  11. package/lib/strapi/remote/constants.d.ts +3 -1
  12. package/lib/strapi/remote/constants.js +1 -1
  13. package/lib/strapi/remote/flows/index.d.ts +4 -4
  14. package/lib/strapi/remote/handlers/abstract.d.ts +62 -0
  15. package/lib/strapi/remote/handlers/abstract.js +3 -0
  16. package/lib/strapi/remote/handlers/constants.d.ts +2 -0
  17. package/lib/strapi/remote/handlers/constants.js +5 -0
  18. package/lib/strapi/remote/handlers/index.d.ts +3 -0
  19. package/lib/strapi/remote/handlers/index.js +10 -0
  20. package/lib/strapi/remote/handlers/pull.d.ts +22 -0
  21. package/lib/strapi/remote/handlers/pull.js +186 -0
  22. package/lib/strapi/remote/handlers/push.d.ts +75 -0
  23. package/lib/strapi/remote/handlers/push.js +297 -0
  24. package/lib/strapi/remote/handlers/utils.d.ts +25 -0
  25. package/lib/strapi/remote/handlers/utils.js +181 -0
  26. package/lib/strapi/remote/index.d.ts +0 -1
  27. package/lib/strapi/remote/index.js +1 -2
  28. package/package.json +4 -4
  29. package/lib/strapi/remote/controllers/index.d.ts +0 -1
  30. package/lib/strapi/remote/controllers/index.js +0 -18
  31. package/lib/strapi/remote/controllers/push.d.ts +0 -26
  32. package/lib/strapi/remote/controllers/push.js +0 -116
  33. package/lib/strapi/remote/handlers.d.ts +0 -10
  34. package/lib/strapi/remote/handlers.js +0 -285
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlerControllerFactory = exports.handleWSUpgrade = exports.isDataTransferMessage = exports.assertValidHeader = exports.transformUpgradeHeader = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const ws_1 = require("ws");
6
+ const providers_1 = require("../../../errors/providers");
7
+ const constants_1 = require("./constants");
8
+ const transformUpgradeHeader = (header = '') => {
9
+ return header.split(',').map((s) => s.trim().toLowerCase());
10
+ };
11
+ exports.transformUpgradeHeader = transformUpgradeHeader;
12
+ /**
13
+ * Make sure that the upgrade header is a valid websocket one
14
+ */
15
+ const assertValidHeader = (ctx) => {
16
+ const upgradeHeader = (0, exports.transformUpgradeHeader)(ctx.headers.upgrade);
17
+ if (!upgradeHeader.includes('websocket')) {
18
+ throw new Error('Invalid Header');
19
+ }
20
+ };
21
+ exports.assertValidHeader = assertValidHeader;
22
+ const isDataTransferMessage = (message) => {
23
+ if (!message || typeof message !== 'object') {
24
+ return false;
25
+ }
26
+ const { uuid, type } = message;
27
+ if (typeof uuid !== 'string' || typeof type !== 'string') {
28
+ return false;
29
+ }
30
+ if (!['command', 'transfer'].includes(type)) {
31
+ return false;
32
+ }
33
+ return true;
34
+ };
35
+ exports.isDataTransferMessage = isDataTransferMessage;
36
+ /**
37
+ * Handle the upgrade to ws connection
38
+ */
39
+ const handleWSUpgrade = (wss, ctx, callback) => {
40
+ (0, exports.assertValidHeader)(ctx);
41
+ wss.handleUpgrade(ctx.req, ctx.request.socket, Buffer.alloc(0), (client, request) => {
42
+ // Create a connection between the client & the server
43
+ wss.emit('connection', client, ctx.req);
44
+ // Invoke the ws callback
45
+ callback(client, request);
46
+ });
47
+ ctx.respond = false;
48
+ };
49
+ exports.handleWSUpgrade = handleWSUpgrade;
50
+ // Protocol related functions
51
+ const handlerControllerFactory = (implementation) => (options) => {
52
+ const { verify, server: serverOptions } = options ?? {};
53
+ const wss = new ws_1.WebSocket.Server({ ...serverOptions, noServer: true });
54
+ return async (ctx) => {
55
+ (0, exports.handleWSUpgrade)(wss, ctx, (ws) => {
56
+ const state = { id: undefined };
57
+ const prototype = {
58
+ // Transfer ID
59
+ get transferID() {
60
+ return state.id;
61
+ },
62
+ set transferID(id) {
63
+ state.id = id;
64
+ },
65
+ // Started at
66
+ get startedAt() {
67
+ return state.startedAt;
68
+ },
69
+ set startedAt(timestamp) {
70
+ state.startedAt = timestamp;
71
+ },
72
+ isTransferStarted() {
73
+ return this.transferID !== undefined && this.startedAt !== undefined;
74
+ },
75
+ assertValidTransfer() {
76
+ const isStarted = this.isTransferStarted();
77
+ if (!isStarted) {
78
+ throw new Error('Invalid Transfer Process');
79
+ }
80
+ },
81
+ assertValidTransferCommand(command) {
82
+ const isDefined = typeof this[command] === 'function';
83
+ const isValidTransferCommand = constants_1.VALID_TRANSFER_COMMANDS.includes(command);
84
+ if (!isDefined || !isValidTransferCommand) {
85
+ throw new Error('Invalid transfer command');
86
+ }
87
+ },
88
+ respond(uuid, e, data) {
89
+ return new Promise((resolve, reject) => {
90
+ if (!uuid && !e) {
91
+ reject(new Error('Missing uuid for this message'));
92
+ return;
93
+ }
94
+ const payload = JSON.stringify({
95
+ uuid,
96
+ data: data ?? null,
97
+ error: e
98
+ ? {
99
+ code: e?.name ?? 'ERR',
100
+ message: e?.message,
101
+ }
102
+ : null,
103
+ });
104
+ this.send(payload, (error) => (error ? reject(error) : resolve()));
105
+ });
106
+ },
107
+ send(message, cb) {
108
+ ws.send(message, cb);
109
+ },
110
+ confirm(message) {
111
+ return new Promise((resolve, reject) => {
112
+ const uuid = (0, crypto_1.randomUUID)();
113
+ const payload = JSON.stringify({ uuid, data: message });
114
+ this.send(payload, (error) => {
115
+ if (error) {
116
+ reject(error);
117
+ }
118
+ });
119
+ const onResponse = (raw) => {
120
+ const response = JSON.parse(raw.toString());
121
+ if (response.uuid === uuid) {
122
+ if (response.error) {
123
+ return reject(new Error(response.error.message));
124
+ }
125
+ resolve(response.data ?? null);
126
+ }
127
+ else {
128
+ ws.once('message', onResponse);
129
+ }
130
+ };
131
+ ws.once('message', onResponse);
132
+ });
133
+ },
134
+ async executeAndRespond(uuid, fn) {
135
+ try {
136
+ const response = await fn();
137
+ this.respond(uuid, null, response);
138
+ }
139
+ catch (e) {
140
+ if (e instanceof Error) {
141
+ this.respond(uuid, e);
142
+ }
143
+ else if (typeof e === 'string') {
144
+ this.respond(uuid, new providers_1.ProviderTransferError(e));
145
+ }
146
+ else {
147
+ this.respond(uuid, new providers_1.ProviderTransferError('Unexpected error', {
148
+ error: e,
149
+ }));
150
+ }
151
+ }
152
+ },
153
+ cleanup() {
154
+ this.transferID = undefined;
155
+ this.startedAt = undefined;
156
+ },
157
+ teardown() {
158
+ this.cleanup();
159
+ },
160
+ verifyAuth(scope) {
161
+ return verify(ctx, scope);
162
+ },
163
+ // Transfer commands
164
+ init() { },
165
+ end() { },
166
+ status() { },
167
+ // Default prototype implementation for events
168
+ onMessage() { },
169
+ onError() { },
170
+ onClose() { },
171
+ };
172
+ const handler = Object.assign(Object.create(prototype), implementation(prototype));
173
+ // Bind ws events to handler methods
174
+ ws.on('close', (...args) => handler.onClose(...args));
175
+ ws.on('error', (...args) => handler.onError(...args));
176
+ ws.on('message', (...args) => handler.onMessage(...args));
177
+ });
178
+ };
179
+ };
180
+ exports.handlerControllerFactory = handlerControllerFactory;
181
+ //# sourceMappingURL=utils.js.map
@@ -1,3 +1,2 @@
1
- export * as controllers from './controllers';
2
1
  export * as constants from './constants';
3
2
  export * as handlers from './handlers';
@@ -23,8 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.handlers = exports.constants = exports.controllers = void 0;
27
- exports.controllers = __importStar(require("./controllers"));
26
+ exports.handlers = exports.constants = void 0;
28
27
  exports.constants = __importStar(require("./constants"));
29
28
  exports.handlers = __importStar(require("./handlers"));
30
29
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/data-transfer",
3
- "version": "4.8.2",
3
+ "version": "4.9.0-beta.1",
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.8.2",
43
- "@strapi/strapi": "4.8.2",
42
+ "@strapi/logger": "4.9.0-beta.1",
43
+ "@strapi/strapi": "4.9.0-beta.1",
44
44
  "chalk": "4.1.2",
45
45
  "fs-extra": "10.0.0",
46
46
  "lodash": "4.17.21",
@@ -74,5 +74,5 @@
74
74
  "node": ">=14.19.1 <=18.x.x",
75
75
  "npm": ">=6.0.0"
76
76
  },
77
- "gitHead": "cc73bed97b19d44f7c7999ab44f1a4288590d7ab"
77
+ "gitHead": "ff37d666d0634fc84827e3d6419d916618275572"
78
78
  }
@@ -1 +0,0 @@
1
- export * from './push';
@@ -1,18 +0,0 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./push"), exports);
18
- //# sourceMappingURL=index.js.map
@@ -1,26 +0,0 @@
1
- /// <reference types="node" />
2
- import { Writable } from 'stream-chain';
3
- import type { IMetadata } from '../../../../types';
4
- import type { TransferPushMessage, TransferPushStep } from '../../../../types/remote/protocol/client';
5
- import { ILocalStrapiDestinationProviderOptions } from '../../providers';
6
- export interface IPushController {
7
- streams: {
8
- [stage in TransferPushStep]?: Writable;
9
- };
10
- actions: {
11
- getMetadata(): Promise<IMetadata>;
12
- getSchemas(): Strapi.Schemas;
13
- bootstrap(): Promise<void>;
14
- close(): Promise<void>;
15
- beforeTransfer(): Promise<void>;
16
- rollback(): Promise<void>;
17
- };
18
- transfer: {
19
- [key in TransferPushStep]: <T extends TransferPushMessage>(value: T extends {
20
- step: key;
21
- data: infer U;
22
- } ? U : never) => Promise<void>;
23
- };
24
- }
25
- declare const createPushController: (options: ILocalStrapiDestinationProviderOptions) => IPushController;
26
- export default createPushController;
@@ -1,116 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const stream_chain_1 = require("stream-chain");
4
- const providers_1 = require("../../providers");
5
- const createPushController = (options) => {
6
- const provider = (0, providers_1.createLocalStrapiDestinationProvider)(options);
7
- const streams = {};
8
- const assets = {};
9
- const writeAsync = (stream, data) => {
10
- return new Promise((resolve, reject) => {
11
- stream.write(data, (error) => {
12
- if (error) {
13
- reject(error);
14
- }
15
- resolve();
16
- });
17
- });
18
- };
19
- return {
20
- streams,
21
- actions: {
22
- async getSchemas() {
23
- return provider.getSchemas();
24
- },
25
- async getMetadata() {
26
- return provider.getMetadata();
27
- },
28
- async bootstrap() {
29
- return provider.bootstrap();
30
- },
31
- async close() {
32
- return provider.close();
33
- },
34
- async beforeTransfer() {
35
- return provider.beforeTransfer();
36
- },
37
- async rollback() {
38
- await provider.rollback();
39
- },
40
- },
41
- transfer: {
42
- async entities(entities) {
43
- if (!streams.entities) {
44
- streams.entities = provider.createEntitiesWriteStream();
45
- }
46
- for (const entity of entities) {
47
- if (streams.entities) {
48
- await writeAsync(streams.entities, entity);
49
- }
50
- }
51
- },
52
- async links(links) {
53
- if (!streams.links) {
54
- streams.links = await provider.createLinksWriteStream();
55
- }
56
- for (const link of links) {
57
- if (streams.links) {
58
- await writeAsync(streams.links, link);
59
- }
60
- }
61
- },
62
- async configuration(configs) {
63
- if (!streams.configuration) {
64
- streams.configuration = await provider.createConfigurationWriteStream();
65
- }
66
- for (const config of configs) {
67
- if (streams.configuration) {
68
- await writeAsync(streams.configuration, config);
69
- }
70
- }
71
- },
72
- async assets(payloads) {
73
- if (payloads === null) {
74
- streams.assets?.end();
75
- return;
76
- }
77
- if (!streams.assets) {
78
- streams.assets = await provider.createAssetsWriteStream();
79
- }
80
- for (const payload of payloads) {
81
- if (streams.assets.closed) {
82
- return;
83
- }
84
- const { action, assetID } = payload;
85
- if (action === 'start' && streams.assets) {
86
- assets[assetID] = { ...payload.data, stream: new stream_chain_1.PassThrough() };
87
- writeAsync(streams.assets, assets[assetID]);
88
- }
89
- if (action === 'stream') {
90
- // The buffer has gone through JSON operations and is now of shape { type: "Buffer"; data: UInt8Array }
91
- // We need to transform it back into a Buffer instance
92
- const rawBuffer = payload.data;
93
- const chunk = Buffer.from(rawBuffer.data);
94
- await writeAsync(assets[assetID].stream, chunk);
95
- }
96
- if (action === 'end') {
97
- await new Promise((resolve, reject) => {
98
- const { stream } = assets[assetID];
99
- stream
100
- .on('close', () => {
101
- delete assets[assetID];
102
- resolve();
103
- })
104
- .on('error', (e) => {
105
- reject(e);
106
- })
107
- .end();
108
- });
109
- }
110
- }
111
- },
112
- },
113
- };
114
- };
115
- exports.default = createPushController;
116
- //# sourceMappingURL=push.js.map
@@ -1,10 +0,0 @@
1
- import type { Context } from 'koa';
2
- import type { ServerOptions } from 'ws';
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 {};