@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
@@ -1,4 +1,6 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="lodash" />
3
+ import { Readable } from 'stream';
2
4
  import type { IMetadata, ISourceProvider, ProviderType } from '../../../types';
3
5
  export interface ILocalStrapiSourceProviderOptions {
4
6
  getStrapi(): Strapi.Strapi | Promise<Strapi.Strapi>;
@@ -14,13 +16,12 @@ declare class LocalStrapiSourceProvider implements ISourceProvider {
14
16
  bootstrap(): Promise<void>;
15
17
  close(): Promise<void>;
16
18
  getMetadata(): IMetadata;
17
- streamEntities(): Promise<NodeJS.ReadableStream>;
18
- streamLinks(): NodeJS.ReadableStream;
19
- streamConfiguration(): NodeJS.ReadableStream;
20
- getSchemas(): {
21
- [x: string]: Partial<any>;
22
- };
23
- streamSchemas(): NodeJS.ReadableStream;
19
+ streamEntities(): Promise<Readable>;
20
+ streamLinks(): Readable;
21
+ streamConfiguration(): Readable;
22
+ getSchemas(): import("lodash").Dictionary<Partial<import("@strapi/strapi").Schema>>;
23
+ streamSchemas(): Readable;
24
+ streamAssets(): Readable;
24
25
  }
25
26
  export declare type ILocalStrapiSourceProvider = InstanceType<typeof LocalStrapiSourceProvider>;
26
27
  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
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.createLocalStrapiSourceProvider = void 0;
4
27
  const stream_chain_1 = require("stream-chain");
@@ -6,7 +29,8 @@ const stream_1 = require("stream");
6
29
  const entities_1 = require("./entities");
7
30
  const links_1 = require("./links");
8
31
  const configuration_1 = require("./configuration");
9
- const utils_1 = require("../../utils");
32
+ const assets_1 = require("./assets");
33
+ const utils = __importStar(require("../../utils"));
10
34
  const createLocalStrapiSourceProvider = (options) => {
11
35
  return new LocalStrapiSourceProvider(options);
12
36
  };
@@ -74,10 +98,16 @@ class LocalStrapiSourceProvider {
74
98
  ...this.strapi.contentTypes,
75
99
  ...this.strapi.components,
76
100
  };
77
- return (0, utils_1.mapSchemasValues)(schemas);
101
+ return utils.schema.mapSchemasValues(schemas);
78
102
  }
79
103
  streamSchemas() {
80
104
  return stream_1.Readable.from(Object.values(this.getSchemas()));
81
105
  }
106
+ streamAssets() {
107
+ if (!this.strapi) {
108
+ throw new Error('Not able to stream assets. Strapi instance not found');
109
+ }
110
+ return (0, assets_1.createAssetsStream)(this.strapi);
111
+ }
82
112
  }
83
113
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  import { Readable } from 'stream';
2
2
  /**
3
- * Create a Duplex instance which will stream all the links from a Strapi instance
3
+ * Create a Readable which will stream all the links from a Strapi instance
4
4
  */
5
5
  export declare const createLinksStream: (strapi: Strapi.Strapi) => Readable;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLinksStream = void 0;
4
+ const stream_1 = require("stream");
5
+ const link_1 = require("../shared/strapi/link");
6
+ /**
7
+ * Create a Readable which will stream all the links from a Strapi instance
8
+ */
9
+ const createLinksStream = (strapi) => {
10
+ const uids = [...Object.keys(strapi.contentTypes), ...Object.keys(strapi.components)];
11
+ // Async generator stream that returns every link from a Strapi instance
12
+ return stream_1.Readable.from((async function* linkGenerator() {
13
+ const query = (0, link_1.createLinkQuery)(strapi);
14
+ for (const uid of uids) {
15
+ const generator = query().generateAll(uid);
16
+ for await (const link of generator) {
17
+ yield link;
18
+ }
19
+ }
20
+ })());
21
+ };
22
+ exports.createLinksStream = createLinksStream;
23
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ export * as strapi from './strapi';
@@ -0,0 +1,28 @@
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
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.strapi = void 0;
27
+ exports.strapi = __importStar(require("./strapi"));
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,19 @@
1
+ import type { ContentTypeSchema } from '@strapi/strapi';
2
+ declare const createEntityQuery: (strapi: Strapi.Strapi) => (uid: string) => {
3
+ create: <T extends {
4
+ data: U;
5
+ }, U extends object>(params: T) => Promise<any>;
6
+ createMany: <T_1 extends {
7
+ data: U_1[];
8
+ }, U_1 extends object>(params: T_1) => Promise<{
9
+ count: number;
10
+ }>;
11
+ deleteMany: <T_2 extends object>(params?: T_2 | undefined) => Promise<{
12
+ count: number;
13
+ } | null>;
14
+ getDeepPopulateComponentLikeQuery: (contentType: ContentTypeSchema, params?: {
15
+ select: string;
16
+ }) => any;
17
+ readonly deepPopulateComponentLikeQuery: any;
18
+ };
19
+ export { createEntityQuery };
@@ -0,0 +1,130 @@
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
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.createEntityQuery = void 0;
27
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
28
+ // @ts-ignore
29
+ const componentsService = __importStar(require("@strapi/strapi/lib/services/entity-service/components"));
30
+ const fp_1 = require("lodash/fp");
31
+ const sanitizeComponentLikeAttributes = (model, data) => {
32
+ const { attributes } = model;
33
+ const componentLikeAttributesKey = Object.entries(attributes)
34
+ .filter(([, attribute]) => ['component', 'dynamiczone'].includes(attribute.type))
35
+ .map(([key]) => key);
36
+ return (0, fp_1.omit)(componentLikeAttributesKey, data);
37
+ };
38
+ const omitInvalidCreationAttributes = (0, fp_1.omit)(['id']);
39
+ const createEntityQuery = (strapi) => {
40
+ const components = {
41
+ async assignToEntity(uid, data) {
42
+ const model = strapi.getModel(uid);
43
+ const entityComponents = await componentsService.createComponents(uid, data);
44
+ const dataWithoutComponents = sanitizeComponentLikeAttributes(model, data);
45
+ return (0, fp_1.assign)(entityComponents, dataWithoutComponents);
46
+ },
47
+ async get(uid, entity) {
48
+ return componentsService.getComponents(uid, entity);
49
+ },
50
+ delete(uid, componentsToDelete) {
51
+ return componentsService.deleteComponents(uid, componentsToDelete, { loadComponents: false });
52
+ },
53
+ };
54
+ const query = (uid) => {
55
+ const create = async (params) => {
56
+ const dataWithComponents = await components.assignToEntity(uid, params.data);
57
+ const sanitizedData = omitInvalidCreationAttributes(dataWithComponents);
58
+ return strapi.db.query(uid).create({ ...params, data: sanitizedData });
59
+ };
60
+ const createMany = async (params) => {
61
+ return (Promise.resolve(params.data)
62
+ // Create components for each entity
63
+ .then((0, fp_1.map)((data) => components.assignToEntity(uid, data)))
64
+ // Remove unwanted attributes
65
+ .then((0, fp_1.map)(omitInvalidCreationAttributes))
66
+ // Execute a strapi db createMany query with all the entities + their created components
67
+ .then((data) => strapi.db.query(uid).createMany({ ...params, data })));
68
+ };
69
+ const deleteMany = async (params) => {
70
+ const entitiesToDelete = await strapi.db.query(uid).findMany(params ?? {});
71
+ if (!entitiesToDelete.length) {
72
+ return null;
73
+ }
74
+ const componentsToDelete = await Promise.all(entitiesToDelete.map((entityToDelete) => components.get(uid, entityToDelete)));
75
+ const deletedEntities = await strapi.db.query(uid).deleteMany(params);
76
+ await Promise.all(componentsToDelete.map((compos) => components.delete(uid, compos)));
77
+ return deletedEntities;
78
+ };
79
+ const getDeepPopulateComponentLikeQuery = (contentType, params = { select: '*' }) => {
80
+ const { attributes } = contentType;
81
+ const populate = {};
82
+ const entries = Object.entries(attributes);
83
+ for (const [key, attribute] of entries) {
84
+ if (attribute.type === 'component') {
85
+ const component = strapi.getModel(attribute.component);
86
+ const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
87
+ if (((0, fp_1.isArray)(subPopulate) || (0, fp_1.isObject)(subPopulate)) && (0, fp_1.size)(subPopulate) > 0) {
88
+ populate[key] = { ...params, populate: subPopulate };
89
+ }
90
+ if ((0, fp_1.isArray)(subPopulate) && (0, fp_1.isEmpty)(subPopulate)) {
91
+ populate[key] = { ...params };
92
+ }
93
+ }
94
+ if (attribute.type === 'dynamiczone') {
95
+ const { components: componentsUID } = attribute;
96
+ const on = {};
97
+ for (const componentUID of componentsUID) {
98
+ const component = strapi.getModel(componentUID);
99
+ const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
100
+ if (((0, fp_1.isArray)(subPopulate) || (0, fp_1.isObject)(subPopulate)) && (0, fp_1.size)(subPopulate) > 0) {
101
+ on[componentUID] = { ...params, populate: subPopulate };
102
+ }
103
+ if ((0, fp_1.isArray)(subPopulate) && (0, fp_1.isEmpty)(subPopulate)) {
104
+ on[componentUID] = { ...params };
105
+ }
106
+ }
107
+ populate[key] = (0, fp_1.size)(on) > 0 ? { on } : true;
108
+ }
109
+ }
110
+ const values = Object.values(populate);
111
+ if (values.every((value) => value === true)) {
112
+ return Object.keys(populate);
113
+ }
114
+ return populate;
115
+ };
116
+ return {
117
+ create,
118
+ createMany,
119
+ deleteMany,
120
+ getDeepPopulateComponentLikeQuery,
121
+ get deepPopulateComponentLikeQuery() {
122
+ const contentType = strapi.getModel(uid);
123
+ return getDeepPopulateComponentLikeQuery(contentType);
124
+ },
125
+ };
126
+ };
127
+ return query;
128
+ };
129
+ exports.createEntityQuery = createEntityQuery;
130
+ //# sourceMappingURL=entity.js.map
@@ -0,0 +1,2 @@
1
+ export * as entity from './entity';
2
+ export * as link from './link';
@@ -0,0 +1,29 @@
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
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.link = exports.entity = void 0;
27
+ exports.entity = __importStar(require("./entity"));
28
+ exports.link = __importStar(require("./link"));
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,6 @@
1
+ import { ILink } from '../../../../types';
2
+ export declare const createLinkQuery: (strapi: Strapi.Strapi) => () => {
3
+ generateAll: (uid: string) => AsyncGenerator<ILink>;
4
+ generateAllForAttribute: (uid: string, fieldName: string) => AsyncGenerator<ILink>;
5
+ insert: (link: ILink) => Promise<void>;
6
+ };
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLinkQuery = void 0;
4
+ const fp_1 = require("lodash/fp");
5
+ // TODO: Remove any types when we'll have types for DB metadata
6
+ const createLinkQuery = (strapi) => {
7
+ const query = () => {
8
+ const { connection } = strapi.db;
9
+ async function* generateAllForAttribute(uid, fieldName) {
10
+ const metadata = strapi.db.metadata.get(uid);
11
+ if (!metadata) {
12
+ throw new Error(`No metadata found for ${uid}`);
13
+ }
14
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
15
+ if (!(fieldName in attributes)) {
16
+ throw new Error(`${fieldName} is not a valid relational attribute name`);
17
+ }
18
+ const attribute = attributes[fieldName];
19
+ const kind = getLinkKind(attribute, uid);
20
+ const { relation, target } = attribute;
21
+ // The relation is stored in the same table
22
+ // TODO: handle manyToOne joinColumn
23
+ if (attribute.joinColumn) {
24
+ const joinColumnName = attribute.joinColumn.name;
25
+ const qb = connection.queryBuilder().select('id', joinColumnName).from(metadata.tableName);
26
+ // TODO: stream the query to improve performances
27
+ const entries = await qb;
28
+ for (const entry of entries) {
29
+ const ref = entry[joinColumnName];
30
+ if (ref !== null) {
31
+ yield {
32
+ kind,
33
+ relation,
34
+ left: { type: uid, ref: entry.id, field: fieldName },
35
+ right: { type: target, ref },
36
+ };
37
+ }
38
+ }
39
+ }
40
+ // The relation uses a join table
41
+ if (attribute.joinTable) {
42
+ const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName, } = attribute.joinTable;
43
+ const qb = connection.queryBuilder().from(name);
44
+ const columns = {
45
+ left: { ref: null },
46
+ right: { ref: null },
47
+ };
48
+ const left = { type: uid, field: fieldName };
49
+ const right = {};
50
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
51
+ right.type = attribute.target;
52
+ right.field = attribute.inversedBy;
53
+ columns.left.ref = joinColumn.name;
54
+ columns.right.ref = inverseJoinColumn.name;
55
+ if (orderColumnName) {
56
+ columns.left.order = orderColumnName;
57
+ }
58
+ if (inverseOrderColumnName) {
59
+ columns.right.order = inverseOrderColumnName;
60
+ }
61
+ }
62
+ if (kind === 'relation.morph') {
63
+ columns.left.ref = joinColumn.name;
64
+ columns.right.ref = morphColumn.idColumn.name;
65
+ columns.right.type = morphColumn.typeColumn.name;
66
+ columns.right.field = 'field';
67
+ columns.right.order = 'order';
68
+ }
69
+ const validColumns = [
70
+ // Left
71
+ columns.left.ref,
72
+ columns.left.order,
73
+ // Right
74
+ columns.right.ref,
75
+ columns.right.type,
76
+ columns.right.field,
77
+ columns.right.order,
78
+ ].filter((column) => !(0, fp_1.isNil)(column));
79
+ qb.select(validColumns);
80
+ // TODO: stream the query to improve performances
81
+ const entries = await qb;
82
+ for (const entry of entries) {
83
+ if (columns.left.ref) {
84
+ left.ref = entry[columns.left.ref];
85
+ }
86
+ if (columns.right.ref) {
87
+ right.ref = entry[columns.right.ref];
88
+ }
89
+ if (columns.left.order) {
90
+ left.pos = entry[columns.left.order];
91
+ }
92
+ if (columns.right.order) {
93
+ right.pos = entry[columns.right.order];
94
+ }
95
+ if (columns.right.type) {
96
+ right.type = entry[columns.right.type];
97
+ }
98
+ if (columns.right.field) {
99
+ right.field = entry[columns.right.field];
100
+ }
101
+ const link = {
102
+ kind,
103
+ relation,
104
+ left: (0, fp_1.clone)(left),
105
+ right: (0, fp_1.clone)(right),
106
+ };
107
+ yield link;
108
+ }
109
+ }
110
+ }
111
+ async function* generateAll(uid) {
112
+ const metadata = strapi.db.metadata.get(uid);
113
+ if (!metadata) {
114
+ throw new Error(`No metadata found for ${uid}`);
115
+ }
116
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
117
+ for (const fieldName of Object.keys(attributes)) {
118
+ for await (const link of generateAllForAttribute(uid, fieldName)) {
119
+ yield link;
120
+ }
121
+ }
122
+ }
123
+ const insert = async (link) => {
124
+ const { kind, left, right } = link;
125
+ const metadata = strapi.db.metadata.get(left.type);
126
+ const attribute = metadata.attributes[left.field];
127
+ const payload = {};
128
+ if (attribute.joinColumn) {
129
+ const joinColumnName = attribute.joinColumn.name;
130
+ await connection(metadata.tableName)
131
+ .where('id', left.ref)
132
+ .update({ [joinColumnName]: right.ref });
133
+ }
134
+ if (attribute.joinTable) {
135
+ const { name, joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName, morphColumn, } = attribute.joinTable;
136
+ if (joinColumn) {
137
+ Object.assign(payload, { [joinColumn.name]: left.ref });
138
+ }
139
+ const assignInverseColumn = () => {
140
+ if (inverseJoinColumn) {
141
+ Object.assign(payload, {
142
+ [inverseJoinColumn.name]: right.ref,
143
+ });
144
+ }
145
+ };
146
+ const assignOrderColumns = () => {
147
+ if (orderColumnName) {
148
+ Object.assign(payload, { [orderColumnName]: left.pos ?? null });
149
+ }
150
+ if (inverseOrderColumnName) {
151
+ Object.assign(payload, { [inverseOrderColumnName]: right.pos ?? null });
152
+ }
153
+ };
154
+ const assignMorphColumns = () => {
155
+ const { idColumn, typeColumn } = morphColumn ?? {};
156
+ if (idColumn) {
157
+ Object.assign(payload, { [idColumn.name]: right.ref });
158
+ }
159
+ if (typeColumn) {
160
+ Object.assign(payload, { [typeColumn.name]: right.type });
161
+ }
162
+ Object.assign(payload, { order: right.pos ?? null, field: right.field ?? null });
163
+ };
164
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
165
+ assignInverseColumn();
166
+ }
167
+ if (kind === 'relation.morph') {
168
+ assignMorphColumns();
169
+ }
170
+ assignOrderColumns();
171
+ await connection.insert(payload).into(name);
172
+ }
173
+ };
174
+ return { generateAll, generateAllForAttribute, insert };
175
+ };
176
+ return query;
177
+ };
178
+ exports.createLinkQuery = createLinkQuery;
179
+ const filterValidRelationalAttributes = (attributes) => {
180
+ const isOwner = (attribute) => {
181
+ return attribute.owner || (!attribute.mappedBy && !attribute.morphBy);
182
+ };
183
+ const isComponentLike = (attribute) => {
184
+ return attribute.component || attribute.components;
185
+ };
186
+ return Object.entries(attributes)
187
+ .filter(([, attribute]) => {
188
+ return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);
189
+ })
190
+ .reduce((acc, [key, attribute]) => ({ ...acc, [key]: attribute }), {});
191
+ };
192
+ const getLinkKind = (attribute, uid) => {
193
+ if (attribute.relation.startsWith('morph')) {
194
+ return 'relation.morph';
195
+ }
196
+ if (attribute.target === uid) {
197
+ return 'relation.circular';
198
+ }
199
+ return 'relation.basic';
200
+ };
201
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1,111 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="jest" />
3
+ import { Readable } from 'stream';
4
+ /**
5
+ * Collect every entity in a Readable stream
6
+ */
7
+ export declare const collect: <T = unknown>(stream: Readable) => Promise<T[]>;
8
+ /**
9
+ * Create a "Strapi" like object factory based on the
10
+ * given params and cast it to the correct type
11
+ */
12
+ export declare const getStrapiFactory: <T extends {
13
+ readonly EE?: unknown;
14
+ readonly config?: unknown;
15
+ readonly auth?: unknown;
16
+ readonly contentAPI?: unknown;
17
+ readonly sanitizers?: unknown;
18
+ readonly services?: unknown;
19
+ service?: unknown;
20
+ readonly controllers?: unknown;
21
+ controller?: unknown;
22
+ readonly contentTypes?: unknown;
23
+ contentType?: unknown;
24
+ readonly components?: unknown;
25
+ readonly customFields?: unknown;
26
+ readonly policies?: unknown;
27
+ policy?: unknown;
28
+ readonly middlewares?: unknown;
29
+ middleware?: unknown;
30
+ readonly plugins?: unknown;
31
+ plugin?: unknown;
32
+ readonly hooks?: unknown;
33
+ hook?: unknown;
34
+ readonly api?: unknown;
35
+ register?: unknown;
36
+ bootstrap?: unknown;
37
+ destroy?: unknown;
38
+ runLifecyclesFunctions?: unknown;
39
+ start?: unknown;
40
+ stopWithError?: unknown;
41
+ stop?: unknown;
42
+ load?: unknown;
43
+ reload?: unknown;
44
+ startWebhooks?: unknown;
45
+ postListen?: unknown;
46
+ listen?: unknown;
47
+ openAdmin?: unknown;
48
+ loadAdmin?: unknown;
49
+ loadPlugins?: unknown;
50
+ loadPolicies?: unknown;
51
+ loadAPIs?: unknown;
52
+ loadComponents?: unknown;
53
+ loadMiddlewares?: unknown;
54
+ loadApp?: unknown;
55
+ registerInternalHooks?: unknown;
56
+ getModel?: unknown;
57
+ query?: unknown;
58
+ container?: unknown;
59
+ dirs?: unknown;
60
+ isLoaded?: unknown;
61
+ server?: unknown;
62
+ fs?: unknown;
63
+ eventHub?: unknown;
64
+ startupLogger?: unknown;
65
+ log?: unknown;
66
+ cron?: unknown;
67
+ telemetry?: unknown;
68
+ db?: unknown;
69
+ store?: unknown;
70
+ entityValidator?: unknown;
71
+ entityService?: unknown;
72
+ }>(properties?: T | undefined) => () => import("@strapi/strapi").Strapi;
73
+ /**
74
+ * Union type used to represent the default content types available
75
+ */
76
+ export declare type ContentType = 'foo' | 'bar';
77
+ /**
78
+ * Factory to get default content types test values
79
+ */
80
+ export declare const getContentTypes: () => {
81
+ foo: {
82
+ uid: "foo";
83
+ attributes: {
84
+ [attribute: string]: unknown;
85
+ };
86
+ };
87
+ bar: {
88
+ uid: "bar";
89
+ attributes: {
90
+ [attribute: string]: unknown;
91
+ };
92
+ };
93
+ };
94
+ /**
95
+ * Create a factory of readable streams (wrapped with a jest mock function)
96
+ */
97
+ export declare const createMockedReadableFactory: <T extends string = ContentType>(source: { [ct in T]: {
98
+ [key: string]: unknown;
99
+ id: number;
100
+ }[]; }) => jest.Mock<Readable, [uid: T]>;
101
+ /**
102
+ * Create a factory of mocked query builders
103
+ */
104
+ export declare const createMockedQueryBuilder: <T extends string = ContentType>(data: { [key in T]: unknown[]; }) => jest.Mock<{
105
+ populate(populate: unknown): any;
106
+ stream(): Readable;
107
+ }, [uid: T]>;
108
+ /**
109
+ * Update the global store with the given strapi value
110
+ */
111
+ export declare const setGlobalStrapi: (strapi: Strapi.Strapi) => void;