@strapi/data-transfer 5.12.0 → 5.12.2

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 (213) hide show
  1. package/dist/engine/errors.js +39 -0
  2. package/dist/engine/errors.js.map +1 -0
  3. package/dist/engine/errors.mjs +34 -0
  4. package/dist/engine/errors.mjs.map +1 -0
  5. package/dist/engine/index.js +797 -0
  6. package/dist/engine/index.js.map +1 -0
  7. package/dist/engine/index.mjs +792 -0
  8. package/dist/engine/index.mjs.map +1 -0
  9. package/dist/engine/validation/provider.js +19 -0
  10. package/dist/engine/validation/provider.js.map +1 -0
  11. package/dist/engine/validation/provider.mjs +17 -0
  12. package/dist/engine/validation/provider.mjs.map +1 -0
  13. package/dist/engine/validation/schemas/index.js +57 -0
  14. package/dist/engine/validation/schemas/index.js.map +1 -0
  15. package/dist/engine/validation/schemas/index.mjs +55 -0
  16. package/dist/engine/validation/schemas/index.mjs.map +1 -0
  17. package/dist/errors/base.js +13 -0
  18. package/dist/errors/base.js.map +1 -0
  19. package/dist/errors/base.mjs +11 -0
  20. package/dist/errors/base.mjs.map +1 -0
  21. package/dist/errors/constants.js +10 -0
  22. package/dist/errors/constants.js.map +1 -0
  23. package/dist/errors/constants.mjs +8 -0
  24. package/dist/errors/constants.mjs.map +1 -0
  25. package/dist/errors/providers.js +41 -0
  26. package/dist/errors/providers.js.map +1 -0
  27. package/dist/errors/providers.mjs +36 -0
  28. package/dist/errors/providers.mjs.map +1 -0
  29. package/dist/file/index.js +8 -0
  30. package/dist/file/index.js.map +1 -0
  31. package/dist/file/index.mjs +3 -0
  32. package/dist/file/index.mjs.map +1 -0
  33. package/dist/file/providers/destination/index.js +248 -0
  34. package/dist/file/providers/destination/index.js.map +1 -0
  35. package/dist/file/providers/destination/index.mjs +246 -0
  36. package/dist/file/providers/destination/index.mjs.map +1 -0
  37. package/dist/file/providers/destination/utils.js +63 -0
  38. package/dist/file/providers/destination/utils.js.map +1 -0
  39. package/dist/file/providers/destination/utils.mjs +60 -0
  40. package/dist/file/providers/destination/utils.mjs.map +1 -0
  41. package/dist/file/providers/index.js +10 -0
  42. package/dist/file/providers/index.js.map +1 -0
  43. package/dist/file/providers/index.mjs +3 -0
  44. package/dist/file/providers/index.mjs.map +1 -0
  45. package/dist/file/providers/source/index.js +288 -0
  46. package/dist/file/providers/source/index.js.map +1 -0
  47. package/dist/file/providers/source/index.mjs +286 -0
  48. package/dist/file/providers/source/index.mjs.map +1 -0
  49. package/dist/file/providers/source/utils.js +56 -0
  50. package/dist/file/providers/source/utils.js.map +1 -0
  51. package/dist/file/providers/source/utils.mjs +52 -0
  52. package/dist/file/providers/source/utils.mjs.map +1 -0
  53. package/dist/index.js +8 -5692
  54. package/dist/index.js.map +1 -1
  55. package/dist/index.mjs +8 -5674
  56. package/dist/index.mjs.map +1 -1
  57. package/dist/strapi/index.js +12 -0
  58. package/dist/strapi/index.js.map +1 -0
  59. package/dist/strapi/index.mjs +7 -0
  60. package/dist/strapi/index.mjs.map +1 -0
  61. package/dist/strapi/providers/index.js +16 -0
  62. package/dist/strapi/providers/index.js.map +1 -0
  63. package/dist/strapi/providers/index.mjs +7 -0
  64. package/dist/strapi/providers/index.mjs.map +1 -0
  65. package/dist/strapi/providers/local-destination/index.js +419 -0
  66. package/dist/strapi/providers/local-destination/index.js.map +1 -0
  67. package/dist/strapi/providers/local-destination/index.mjs +396 -0
  68. package/dist/strapi/providers/local-destination/index.mjs.map +1 -0
  69. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js +52 -0
  70. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js.map +1 -0
  71. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs +49 -0
  72. package/dist/strapi/providers/local-destination/strategies/restore/configuration.mjs.map +1 -0
  73. package/dist/strapi/providers/local-destination/strategies/restore/entities.js +64 -0
  74. package/dist/strapi/providers/local-destination/strategies/restore/entities.js.map +1 -0
  75. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs +62 -0
  76. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs.map +1 -0
  77. package/dist/strapi/providers/local-destination/strategies/restore/index.js +126 -0
  78. package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -0
  79. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs +122 -0
  80. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs.map +1 -0
  81. package/dist/strapi/providers/local-destination/strategies/restore/links.js +60 -0
  82. package/dist/strapi/providers/local-destination/strategies/restore/links.js.map +1 -0
  83. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs +58 -0
  84. package/dist/strapi/providers/local-destination/strategies/restore/links.mjs.map +1 -0
  85. package/dist/strapi/providers/local-source/assets.js +123 -0
  86. package/dist/strapi/providers/local-source/assets.js.map +1 -0
  87. package/dist/strapi/providers/local-source/assets.mjs +121 -0
  88. package/dist/strapi/providers/local-source/assets.mjs.map +1 -0
  89. package/dist/strapi/providers/local-source/configuration.js +39 -0
  90. package/dist/strapi/providers/local-source/configuration.js.map +1 -0
  91. package/dist/strapi/providers/local-source/configuration.mjs +37 -0
  92. package/dist/strapi/providers/local-source/configuration.mjs.map +1 -0
  93. package/dist/strapi/providers/local-source/entities.js +62 -0
  94. package/dist/strapi/providers/local-source/entities.js.map +1 -0
  95. package/dist/strapi/providers/local-source/entities.mjs +59 -0
  96. package/dist/strapi/providers/local-source/entities.mjs.map +1 -0
  97. package/dist/strapi/providers/local-source/index.js +154 -0
  98. package/dist/strapi/providers/local-source/index.js.map +1 -0
  99. package/dist/strapi/providers/local-source/index.mjs +152 -0
  100. package/dist/strapi/providers/local-source/index.mjs.map +1 -0
  101. package/dist/strapi/providers/local-source/links.js +26 -0
  102. package/dist/strapi/providers/local-source/links.js.map +1 -0
  103. package/dist/strapi/providers/local-source/links.mjs +24 -0
  104. package/dist/strapi/providers/local-source/links.mjs.map +1 -0
  105. package/dist/strapi/providers/remote-destination/index.js +392 -0
  106. package/dist/strapi/providers/remote-destination/index.js.map +1 -0
  107. package/dist/strapi/providers/remote-destination/index.mjs +390 -0
  108. package/dist/strapi/providers/remote-destination/index.mjs.map +1 -0
  109. package/dist/strapi/providers/remote-source/index.js +405 -0
  110. package/dist/strapi/providers/remote-source/index.js.map +1 -0
  111. package/dist/strapi/providers/remote-source/index.mjs +403 -0
  112. package/dist/strapi/providers/remote-source/index.mjs.map +1 -0
  113. package/dist/strapi/providers/utils.js +173 -0
  114. package/dist/strapi/providers/utils.js.map +1 -0
  115. package/dist/strapi/providers/utils.mjs +169 -0
  116. package/dist/strapi/providers/utils.mjs.map +1 -0
  117. package/dist/strapi/queries/entity.js +125 -0
  118. package/dist/strapi/queries/entity.js.map +1 -0
  119. package/dist/strapi/queries/entity.mjs +123 -0
  120. package/dist/strapi/queries/entity.mjs.map +1 -0
  121. package/dist/strapi/queries/index.js +10 -0
  122. package/dist/strapi/queries/index.js.map +1 -0
  123. package/dist/strapi/queries/index.mjs +5 -0
  124. package/dist/strapi/queries/index.mjs.map +1 -0
  125. package/dist/strapi/queries/link.js +298 -0
  126. package/dist/strapi/queries/link.js.map +1 -0
  127. package/dist/strapi/queries/link.mjs +295 -0
  128. package/dist/strapi/queries/link.mjs.map +1 -0
  129. package/dist/strapi/remote/constants.js +11 -0
  130. package/dist/strapi/remote/constants.js.map +1 -0
  131. package/dist/strapi/remote/constants.mjs +8 -0
  132. package/dist/strapi/remote/constants.mjs.map +1 -0
  133. package/dist/strapi/remote/flows/default.js +43 -0
  134. package/dist/strapi/remote/flows/default.js.map +1 -0
  135. package/dist/strapi/remote/flows/default.mjs +41 -0
  136. package/dist/strapi/remote/flows/default.mjs.map +1 -0
  137. package/dist/strapi/remote/flows/index.js +54 -0
  138. package/dist/strapi/remote/flows/index.js.map +1 -0
  139. package/dist/strapi/remote/flows/index.mjs +52 -0
  140. package/dist/strapi/remote/flows/index.mjs.map +1 -0
  141. package/dist/strapi/remote/handlers/constants.js +10 -0
  142. package/dist/strapi/remote/handlers/constants.js.map +1 -0
  143. package/dist/strapi/remote/handlers/constants.mjs +8 -0
  144. package/dist/strapi/remote/handlers/constants.mjs.map +1 -0
  145. package/dist/strapi/remote/handlers/index.js +12 -0
  146. package/dist/strapi/remote/handlers/index.js.map +1 -0
  147. package/dist/strapi/remote/handlers/index.mjs +4 -0
  148. package/dist/strapi/remote/handlers/index.mjs.map +1 -0
  149. package/dist/strapi/remote/handlers/pull.js +348 -0
  150. package/dist/strapi/remote/handlers/pull.js.map +1 -0
  151. package/dist/strapi/remote/handlers/pull.mjs +346 -0
  152. package/dist/strapi/remote/handlers/pull.mjs.map +1 -0
  153. package/dist/strapi/remote/handlers/push.js +400 -0
  154. package/dist/strapi/remote/handlers/push.js.map +1 -0
  155. package/dist/strapi/remote/handlers/push.mjs +398 -0
  156. package/dist/strapi/remote/handlers/push.mjs.map +1 -0
  157. package/dist/strapi/remote/handlers/utils.js +316 -0
  158. package/dist/strapi/remote/handlers/utils.js.map +1 -0
  159. package/dist/strapi/remote/handlers/utils.mjs +310 -0
  160. package/dist/strapi/remote/handlers/utils.mjs.map +1 -0
  161. package/dist/strapi/remote/index.js +10 -0
  162. package/dist/strapi/remote/index.js.map +1 -0
  163. package/dist/strapi/remote/index.mjs +5 -0
  164. package/dist/strapi/remote/index.mjs.map +1 -0
  165. package/dist/utils/components.js +178 -0
  166. package/dist/utils/components.js.map +1 -0
  167. package/dist/utils/components.mjs +171 -0
  168. package/dist/utils/components.mjs.map +1 -0
  169. package/dist/utils/diagnostic.js +51 -0
  170. package/dist/utils/diagnostic.js.map +1 -0
  171. package/dist/utils/diagnostic.mjs +49 -0
  172. package/dist/utils/diagnostic.mjs.map +1 -0
  173. package/dist/utils/encryption/decrypt.js +47 -0
  174. package/dist/utils/encryption/decrypt.js.map +1 -0
  175. package/dist/utils/encryption/decrypt.mjs +45 -0
  176. package/dist/utils/encryption/decrypt.mjs.map +1 -0
  177. package/dist/utils/encryption/encrypt.js +47 -0
  178. package/dist/utils/encryption/encrypt.js.map +1 -0
  179. package/dist/utils/encryption/encrypt.mjs +45 -0
  180. package/dist/utils/encryption/encrypt.mjs.map +1 -0
  181. package/dist/utils/encryption/index.js +10 -0
  182. package/dist/utils/encryption/index.js.map +1 -0
  183. package/dist/utils/encryption/index.mjs +3 -0
  184. package/dist/utils/encryption/index.mjs.map +1 -0
  185. package/dist/utils/index.js +20 -0
  186. package/dist/utils/index.js.map +1 -0
  187. package/dist/utils/index.mjs +15 -0
  188. package/dist/utils/index.mjs.map +1 -0
  189. package/dist/utils/json.js +96 -0
  190. package/dist/utils/json.js.map +1 -0
  191. package/dist/utils/json.mjs +94 -0
  192. package/dist/utils/json.mjs.map +1 -0
  193. package/dist/utils/middleware.js +14 -0
  194. package/dist/utils/middleware.js.map +1 -0
  195. package/dist/utils/middleware.mjs +12 -0
  196. package/dist/utils/middleware.mjs.map +1 -0
  197. package/dist/utils/providers.js +12 -0
  198. package/dist/utils/providers.js.map +1 -0
  199. package/dist/utils/providers.mjs +10 -0
  200. package/dist/utils/providers.mjs.map +1 -0
  201. package/dist/utils/schema.js +32 -0
  202. package/dist/utils/schema.js.map +1 -0
  203. package/dist/utils/schema.mjs +29 -0
  204. package/dist/utils/schema.mjs.map +1 -0
  205. package/dist/utils/stream.js +59 -0
  206. package/dist/utils/stream.js.map +1 -0
  207. package/dist/utils/stream.mjs +55 -0
  208. package/dist/utils/stream.mjs.map +1 -0
  209. package/dist/utils/transaction.js +93 -0
  210. package/dist/utils/transaction.js.map +1 -0
  211. package/dist/utils/transaction.mjs +91 -0
  212. package/dist/utils/transaction.mjs.map +1 -0
  213. package/package.json +5 -5
@@ -0,0 +1,298 @@
1
+ 'use strict';
2
+
3
+ var fp = require('lodash/fp');
4
+
5
+ // TODO: Remove any types when we'll have types for DB metadata
6
+ const createLinkQuery = (strapi, trx)=>{
7
+ const query = ()=>{
8
+ const { connection } = strapi.db;
9
+ // TODO: Export utils from database and use the addSchema that is already written
10
+ const addSchema = (tableName)=>{
11
+ const schemaName = connection.client.connectionSettings.schema;
12
+ return schemaName ? `${schemaName}.${tableName}` : tableName;
13
+ };
14
+ async function* generateAllForAttribute(uid, fieldName) {
15
+ const metadata = strapi.db.metadata.get(uid);
16
+ if (!metadata) {
17
+ throw new Error(`No metadata found for ${uid}`);
18
+ }
19
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
20
+ if (!(fieldName in attributes)) {
21
+ throw new Error(`${fieldName} is not a valid relational attribute name`);
22
+ }
23
+ const attribute = attributes[fieldName];
24
+ const kind = getLinkKind(attribute, uid);
25
+ const { relation, target } = attribute;
26
+ // The relation is stored in the same table
27
+ // TODO: handle manyToOne joinColumn
28
+ if (attribute.joinColumn) {
29
+ const joinColumnName = attribute.joinColumn.name;
30
+ const qb = connection.queryBuilder().select('id', joinColumnName).from(addSchema(metadata.tableName));
31
+ if (trx) {
32
+ qb.transacting(trx);
33
+ }
34
+ // TODO: stream the query to improve performances
35
+ const entries = await qb;
36
+ for (const entry of entries){
37
+ const ref = entry[joinColumnName];
38
+ if (ref !== null) {
39
+ yield {
40
+ kind,
41
+ relation,
42
+ left: {
43
+ type: uid,
44
+ ref: entry.id,
45
+ field: fieldName
46
+ },
47
+ right: {
48
+ type: target,
49
+ ref
50
+ }
51
+ };
52
+ }
53
+ }
54
+ }
55
+ // The relation uses a join table
56
+ if (attribute.joinTable) {
57
+ const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName } = attribute.joinTable;
58
+ const qb = connection.queryBuilder().from(addSchema(name));
59
+ const columns = {
60
+ left: {
61
+ ref: null
62
+ },
63
+ right: {
64
+ ref: null
65
+ }
66
+ };
67
+ const left = {
68
+ type: uid,
69
+ field: fieldName
70
+ };
71
+ const right = {};
72
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
73
+ right.type = attribute.target;
74
+ right.field = attribute.inversedBy;
75
+ columns.left.ref = joinColumn.name;
76
+ columns.right.ref = inverseJoinColumn.name;
77
+ if (orderColumnName) {
78
+ columns.left.order = orderColumnName;
79
+ }
80
+ if (inverseOrderColumnName) {
81
+ columns.right.order = inverseOrderColumnName;
82
+ }
83
+ }
84
+ if (kind === 'relation.morph') {
85
+ columns.left.ref = joinColumn.name;
86
+ columns.right.ref = morphColumn.idColumn.name;
87
+ columns.right.type = morphColumn.typeColumn.name;
88
+ columns.right.field = 'field';
89
+ columns.right.order = 'order';
90
+ }
91
+ const validColumns = [
92
+ // Left
93
+ columns.left.ref,
94
+ columns.left.order,
95
+ // Right
96
+ columns.right.ref,
97
+ columns.right.type,
98
+ columns.right.field,
99
+ columns.right.order
100
+ ].filter((column)=>!fp.isNil(column));
101
+ qb.select(validColumns);
102
+ if (trx) {
103
+ qb.transacting(trx);
104
+ }
105
+ // TODO: stream the query to improve performances
106
+ const entries = await qb;
107
+ for (const entry of entries){
108
+ if (columns.left.ref) {
109
+ left.ref = entry[columns.left.ref];
110
+ }
111
+ if (columns.right.ref) {
112
+ right.ref = entry[columns.right.ref];
113
+ }
114
+ if (columns.left.order) {
115
+ left.pos = entry[columns.left.order];
116
+ }
117
+ if (columns.right.order) {
118
+ right.pos = entry[columns.right.order];
119
+ }
120
+ if (columns.right.type) {
121
+ right.type = entry[columns.right.type];
122
+ }
123
+ if (columns.right.field) {
124
+ right.field = entry[columns.right.field];
125
+ }
126
+ const link = {
127
+ kind,
128
+ relation,
129
+ left: fp.clone(left),
130
+ right: fp.clone(right)
131
+ };
132
+ yield link;
133
+ }
134
+ }
135
+ if (attribute.morphColumn) {
136
+ const { typeColumn, idColumn } = attribute.morphColumn;
137
+ const qb = connection.queryBuilder().select('id', typeColumn.name, idColumn.name).from(addSchema(metadata.tableName)).whereNotNull(typeColumn.name).whereNotNull(idColumn.name);
138
+ if (trx) {
139
+ qb.transacting(trx);
140
+ }
141
+ const entries = await qb;
142
+ for (const entry of entries){
143
+ const ref = entry[idColumn.name];
144
+ yield {
145
+ kind,
146
+ relation,
147
+ left: {
148
+ type: uid,
149
+ ref: entry.id,
150
+ field: fieldName
151
+ },
152
+ right: {
153
+ type: entry[typeColumn.name],
154
+ ref
155
+ }
156
+ };
157
+ }
158
+ }
159
+ }
160
+ async function* generateAll(uid) {
161
+ const metadata = strapi.db.metadata.get(uid);
162
+ if (!metadata) {
163
+ throw new Error(`No metadata found for ${uid}`);
164
+ }
165
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
166
+ for (const fieldName of Object.keys(attributes)){
167
+ for await (const link of generateAllForAttribute(uid, fieldName)){
168
+ yield link;
169
+ }
170
+ }
171
+ }
172
+ const insert = async (link)=>{
173
+ const { kind, left, right } = link;
174
+ const metadata = strapi.db.metadata.get(left.type);
175
+ const attribute = metadata.attributes[left.field];
176
+ const payload = {};
177
+ /**
178
+ * This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages
179
+ * and a user is importing EE data into a CE project.
180
+ */ if (!attribute) {
181
+ return;
182
+ }
183
+ if (attribute.type !== 'relation') {
184
+ throw new Error(`Attribute ${left.field} is not a relation`);
185
+ }
186
+ if ('joinColumn' in attribute && attribute.joinColumn) {
187
+ const joinColumnName = attribute.joinColumn.name;
188
+ // Note: this addSchema may not be necessary, but is added for safety
189
+ const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
190
+ [joinColumnName]: right.ref
191
+ });
192
+ if (trx) {
193
+ qb.transacting(trx);
194
+ }
195
+ await qb;
196
+ }
197
+ if ('joinTable' in attribute && attribute.joinTable) {
198
+ const { joinTable } = attribute;
199
+ if (joinTable.joinColumn) {
200
+ Object.assign(payload, {
201
+ [joinTable.joinColumn.name]: left.ref
202
+ });
203
+ }
204
+ const assignInverseColumn = ()=>{
205
+ if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {
206
+ Object.assign(payload, {
207
+ [joinTable.inverseJoinColumn.name]: right.ref
208
+ });
209
+ }
210
+ };
211
+ const assignOrderColumns = ()=>{
212
+ if ('orderColumnName' in joinTable && joinTable.orderColumnName) {
213
+ Object.assign(payload, {
214
+ [joinTable.orderColumnName]: left.pos ?? null
215
+ });
216
+ }
217
+ if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {
218
+ Object.assign(payload, {
219
+ [joinTable.inverseOrderColumnName]: right.pos ?? null
220
+ });
221
+ }
222
+ };
223
+ const assignMorphColumns = ()=>{
224
+ if ('morphColumn' in joinTable && joinTable.morphColumn) {
225
+ const { idColumn, typeColumn } = joinTable.morphColumn ?? {};
226
+ if (idColumn) {
227
+ Object.assign(payload, {
228
+ [idColumn.name]: right.ref
229
+ });
230
+ }
231
+ if (typeColumn) {
232
+ Object.assign(payload, {
233
+ [typeColumn.name]: right.type
234
+ });
235
+ }
236
+ Object.assign(payload, {
237
+ order: right.pos ?? null,
238
+ field: right.field ?? null
239
+ });
240
+ }
241
+ };
242
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
243
+ assignInverseColumn();
244
+ }
245
+ if (kind === 'relation.morph') {
246
+ assignMorphColumns();
247
+ }
248
+ assignOrderColumns();
249
+ const qb = connection.insert(payload).into(addSchema(joinTable.name));
250
+ if (trx) {
251
+ await qb.transacting(trx);
252
+ }
253
+ }
254
+ if ('morphColumn' in attribute && attribute.morphColumn) {
255
+ const { morphColumn } = attribute;
256
+ const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
257
+ [morphColumn.idColumn.name]: right.ref,
258
+ [morphColumn.typeColumn.name]: right.type
259
+ });
260
+ if (trx) {
261
+ qb.transacting(trx);
262
+ }
263
+ await qb;
264
+ }
265
+ };
266
+ return {
267
+ generateAll,
268
+ generateAllForAttribute,
269
+ insert
270
+ };
271
+ };
272
+ return query;
273
+ };
274
+ const filterValidRelationalAttributes = (attributes)=>{
275
+ const isOwner = (attribute)=>{
276
+ return attribute.owner || !attribute.mappedBy && !attribute.morphBy;
277
+ };
278
+ const isComponentLike = (attribute)=>attribute.joinTable?.name.endsWith('_cmps');
279
+ return Object.entries(attributes).filter(([, attribute])=>{
280
+ return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);
281
+ }).reduce((acc, [key, attribute])=>({
282
+ ...acc,
283
+ [key]: attribute
284
+ }), {});
285
+ };
286
+ const getLinkKind = (attribute, uid)=>{
287
+ if (attribute.relation.startsWith('morph')) {
288
+ return 'relation.morph';
289
+ }
290
+ if (attribute.target === uid) {
291
+ return 'relation.circular';
292
+ }
293
+ return 'relation.basic';
294
+ };
295
+
296
+ exports.createLinkQuery = createLinkQuery;
297
+ exports.filterValidRelationalAttributes = filterValidRelationalAttributes;
298
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sources":["../../../src/strapi/queries/link.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { clone, isNil } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\n\nimport { ILink } from '../../../types';\n\n// TODO: Remove any types when we'll have types for DB metadata\n\nexport const createLinkQuery = (strapi: Core.Strapi, trx?: Knex.Transaction) => {\n const query = () => {\n const { connection } = strapi.db;\n\n // TODO: Export utils from database and use the addSchema that is already written\n const addSchema = (tableName: string) => {\n const schemaName = connection.client.connectionSettings.schema;\n return schemaName ? `${schemaName}.${tableName}` : tableName;\n };\n\n async function* generateAllForAttribute(uid: string, fieldName: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n if (!(fieldName in attributes)) {\n throw new Error(`${fieldName} is not a valid relational attribute name`);\n }\n\n const attribute = attributes[fieldName];\n\n const kind = getLinkKind(attribute, uid);\n const { relation, target } = attribute;\n\n // The relation is stored in the same table\n // TODO: handle manyToOne joinColumn\n if (attribute.joinColumn) {\n const joinColumnName: string = attribute.joinColumn.name;\n\n const qb = connection\n .queryBuilder()\n .select('id', joinColumnName)\n .from(addSchema(metadata.tableName));\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[joinColumnName];\n\n if (ref !== null) {\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: target, ref },\n };\n }\n }\n }\n\n // The relation uses a join table\n if (attribute.joinTable) {\n const {\n name,\n joinColumn,\n inverseJoinColumn,\n orderColumnName,\n morphColumn,\n inverseOrderColumnName,\n } = attribute.joinTable;\n\n const qb = connection.queryBuilder().from(addSchema(name));\n\n type Columns = {\n left: { ref: string | null; order?: string };\n right: { ref: string | null; order?: string; type?: string; field?: string };\n };\n\n const columns: Columns = {\n left: { ref: null },\n right: { ref: null },\n };\n\n const left: Partial<ILink['left']> = { type: uid, field: fieldName };\n const right: Partial<ILink['right']> = {};\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n right.type = attribute.target;\n right.field = attribute.inversedBy;\n\n columns.left.ref = joinColumn.name;\n columns.right.ref = inverseJoinColumn.name;\n\n if (orderColumnName) {\n columns.left.order = orderColumnName as string;\n }\n\n if (inverseOrderColumnName) {\n columns.right.order = inverseOrderColumnName as string;\n }\n }\n\n if (kind === 'relation.morph') {\n columns.left.ref = joinColumn.name;\n\n columns.right.ref = morphColumn.idColumn.name;\n columns.right.type = morphColumn.typeColumn.name;\n columns.right.field = 'field';\n columns.right.order = 'order';\n }\n\n const validColumns = [\n // Left\n columns.left.ref,\n columns.left.order,\n // Right\n columns.right.ref,\n columns.right.type,\n columns.right.field,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column));\n\n qb.select(validColumns);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n if (columns.left.ref) {\n left.ref = entry[columns.left.ref];\n }\n\n if (columns.right.ref) {\n right.ref = entry[columns.right.ref];\n }\n\n if (columns.left.order) {\n left.pos = entry[columns.left.order as string];\n }\n\n if (columns.right.order) {\n right.pos = entry[columns.right.order as string];\n }\n\n if (columns.right.type) {\n right.type = entry[columns.right.type as string];\n }\n\n if (columns.right.field) {\n right.field = entry[columns.right.field as string];\n }\n\n const link: ILink = {\n kind,\n relation,\n left: clone(left as ILink['left']),\n right: clone(right as ILink['right']),\n };\n\n yield link;\n }\n }\n\n if (attribute.morphColumn) {\n const { typeColumn, idColumn } = attribute.morphColumn;\n\n const qb = connection\n .queryBuilder()\n .select('id', typeColumn.name, idColumn.name)\n .from(addSchema(metadata.tableName))\n .whereNotNull(typeColumn.name)\n .whereNotNull(idColumn.name);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[idColumn.name];\n\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: entry[typeColumn.name], ref },\n };\n }\n }\n }\n\n async function* generateAll(uid: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n for (const fieldName of Object.keys(attributes)) {\n for await (const link of generateAllForAttribute(uid, fieldName)) {\n yield link;\n }\n }\n }\n\n const insert = async (link: ILink) => {\n const { kind, left, right } = link;\n\n const metadata = strapi.db.metadata.get(left.type);\n const attribute = metadata.attributes[left.field];\n\n const payload = {};\n\n /**\n * This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages\n * and a user is importing EE data into a CE project.\n */\n if (!attribute) {\n return;\n }\n\n if (attribute.type !== 'relation') {\n throw new Error(`Attribute ${left.field} is not a relation`);\n }\n\n if ('joinColumn' in attribute && attribute.joinColumn) {\n const joinColumnName = attribute.joinColumn.name;\n\n // Note: this addSchema may not be necessary, but is added for safety\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({ [joinColumnName]: right.ref });\n if (trx) {\n qb.transacting(trx);\n }\n await qb;\n }\n\n if ('joinTable' in attribute && attribute.joinTable) {\n const { joinTable } = attribute;\n\n if (joinTable.joinColumn) {\n Object.assign(payload, { [joinTable.joinColumn.name]: left.ref });\n }\n\n const assignInverseColumn = () => {\n if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {\n Object.assign(payload, {\n [joinTable.inverseJoinColumn.name]: right.ref,\n });\n }\n };\n\n const assignOrderColumns = () => {\n if ('orderColumnName' in joinTable && joinTable.orderColumnName) {\n Object.assign(payload, { [joinTable.orderColumnName]: left.pos ?? null });\n }\n\n if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {\n Object.assign(payload, { [joinTable.inverseOrderColumnName]: right.pos ?? null });\n }\n };\n\n const assignMorphColumns = () => {\n if ('morphColumn' in joinTable && joinTable.morphColumn) {\n const { idColumn, typeColumn } = joinTable.morphColumn ?? {};\n\n if (idColumn) {\n Object.assign(payload, { [idColumn.name]: right.ref });\n }\n\n if (typeColumn) {\n Object.assign(payload, { [typeColumn.name]: right.type });\n }\n\n Object.assign(payload, { order: right.pos ?? null, field: right.field ?? null });\n }\n };\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n assignInverseColumn();\n }\n\n if (kind === 'relation.morph') {\n assignMorphColumns();\n }\n\n assignOrderColumns();\n const qb = connection.insert(payload).into(addSchema(joinTable.name));\n if (trx) {\n await qb.transacting(trx);\n }\n }\n\n if ('morphColumn' in attribute && attribute.morphColumn) {\n const { morphColumn } = attribute;\n\n const qb = connection(addSchema(metadata.tableName))\n .where('id', left.ref)\n .update({\n [morphColumn.idColumn.name]: right.ref,\n [morphColumn.typeColumn.name]: right.type,\n });\n\n if (trx) {\n qb.transacting(trx);\n }\n\n await qb;\n }\n };\n\n return { generateAll, generateAllForAttribute, insert };\n };\n\n return query;\n};\n\nexport const filterValidRelationalAttributes = (attributes: Record<string, any>) => {\n const isOwner = (attribute: any) => {\n return attribute.owner || (!attribute.mappedBy && !attribute.morphBy);\n };\n\n const isComponentLike = (attribute: any) => attribute.joinTable?.name.endsWith('_cmps');\n\n return Object.entries(attributes)\n .filter(([, attribute]) => {\n return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);\n })\n .reduce<Record<string, any>>((acc, [key, attribute]) => ({ ...acc, [key]: attribute }), {});\n};\n\nconst getLinkKind = (attribute: any, uid: string): ILink['kind'] => {\n if (attribute.relation.startsWith('morph')) {\n return 'relation.morph';\n }\n\n if (attribute.target === uid) {\n return 'relation.circular';\n }\n\n return 'relation.basic';\n};\n"],"names":["createLinkQuery","strapi","trx","query","connection","db","addSchema","tableName","schemaName","client","connectionSettings","schema","generateAllForAttribute","uid","fieldName","metadata","get","Error","attributes","filterValidRelationalAttributes","attribute","kind","getLinkKind","relation","target","joinColumn","joinColumnName","name","qb","queryBuilder","select","from","transacting","entries","entry","ref","left","type","id","field","right","joinTable","inverseJoinColumn","orderColumnName","morphColumn","inverseOrderColumnName","columns","inversedBy","order","idColumn","typeColumn","validColumns","filter","column","isNil","pos","link","clone","whereNotNull","generateAll","Object","keys","insert","payload","where","update","assign","assignInverseColumn","assignOrderColumns","assignMorphColumns","into","isOwner","owner","mappedBy","morphBy","isComponentLike","endsWith","reduce","acc","key","startsWith"],"mappings":"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"}
@@ -0,0 +1,295 @@
1
+ import { isNil, clone } from 'lodash/fp';
2
+
3
+ // TODO: Remove any types when we'll have types for DB metadata
4
+ const createLinkQuery = (strapi, trx)=>{
5
+ const query = ()=>{
6
+ const { connection } = strapi.db;
7
+ // TODO: Export utils from database and use the addSchema that is already written
8
+ const addSchema = (tableName)=>{
9
+ const schemaName = connection.client.connectionSettings.schema;
10
+ return schemaName ? `${schemaName}.${tableName}` : tableName;
11
+ };
12
+ async function* generateAllForAttribute(uid, fieldName) {
13
+ const metadata = strapi.db.metadata.get(uid);
14
+ if (!metadata) {
15
+ throw new Error(`No metadata found for ${uid}`);
16
+ }
17
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
18
+ if (!(fieldName in attributes)) {
19
+ throw new Error(`${fieldName} is not a valid relational attribute name`);
20
+ }
21
+ const attribute = attributes[fieldName];
22
+ const kind = getLinkKind(attribute, uid);
23
+ const { relation, target } = attribute;
24
+ // The relation is stored in the same table
25
+ // TODO: handle manyToOne joinColumn
26
+ if (attribute.joinColumn) {
27
+ const joinColumnName = attribute.joinColumn.name;
28
+ const qb = connection.queryBuilder().select('id', joinColumnName).from(addSchema(metadata.tableName));
29
+ if (trx) {
30
+ qb.transacting(trx);
31
+ }
32
+ // TODO: stream the query to improve performances
33
+ const entries = await qb;
34
+ for (const entry of entries){
35
+ const ref = entry[joinColumnName];
36
+ if (ref !== null) {
37
+ yield {
38
+ kind,
39
+ relation,
40
+ left: {
41
+ type: uid,
42
+ ref: entry.id,
43
+ field: fieldName
44
+ },
45
+ right: {
46
+ type: target,
47
+ ref
48
+ }
49
+ };
50
+ }
51
+ }
52
+ }
53
+ // The relation uses a join table
54
+ if (attribute.joinTable) {
55
+ const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName } = attribute.joinTable;
56
+ const qb = connection.queryBuilder().from(addSchema(name));
57
+ const columns = {
58
+ left: {
59
+ ref: null
60
+ },
61
+ right: {
62
+ ref: null
63
+ }
64
+ };
65
+ const left = {
66
+ type: uid,
67
+ field: fieldName
68
+ };
69
+ const right = {};
70
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
71
+ right.type = attribute.target;
72
+ right.field = attribute.inversedBy;
73
+ columns.left.ref = joinColumn.name;
74
+ columns.right.ref = inverseJoinColumn.name;
75
+ if (orderColumnName) {
76
+ columns.left.order = orderColumnName;
77
+ }
78
+ if (inverseOrderColumnName) {
79
+ columns.right.order = inverseOrderColumnName;
80
+ }
81
+ }
82
+ if (kind === 'relation.morph') {
83
+ columns.left.ref = joinColumn.name;
84
+ columns.right.ref = morphColumn.idColumn.name;
85
+ columns.right.type = morphColumn.typeColumn.name;
86
+ columns.right.field = 'field';
87
+ columns.right.order = 'order';
88
+ }
89
+ const validColumns = [
90
+ // Left
91
+ columns.left.ref,
92
+ columns.left.order,
93
+ // Right
94
+ columns.right.ref,
95
+ columns.right.type,
96
+ columns.right.field,
97
+ columns.right.order
98
+ ].filter((column)=>!isNil(column));
99
+ qb.select(validColumns);
100
+ if (trx) {
101
+ qb.transacting(trx);
102
+ }
103
+ // TODO: stream the query to improve performances
104
+ const entries = await qb;
105
+ for (const entry of entries){
106
+ if (columns.left.ref) {
107
+ left.ref = entry[columns.left.ref];
108
+ }
109
+ if (columns.right.ref) {
110
+ right.ref = entry[columns.right.ref];
111
+ }
112
+ if (columns.left.order) {
113
+ left.pos = entry[columns.left.order];
114
+ }
115
+ if (columns.right.order) {
116
+ right.pos = entry[columns.right.order];
117
+ }
118
+ if (columns.right.type) {
119
+ right.type = entry[columns.right.type];
120
+ }
121
+ if (columns.right.field) {
122
+ right.field = entry[columns.right.field];
123
+ }
124
+ const link = {
125
+ kind,
126
+ relation,
127
+ left: clone(left),
128
+ right: clone(right)
129
+ };
130
+ yield link;
131
+ }
132
+ }
133
+ if (attribute.morphColumn) {
134
+ const { typeColumn, idColumn } = attribute.morphColumn;
135
+ const qb = connection.queryBuilder().select('id', typeColumn.name, idColumn.name).from(addSchema(metadata.tableName)).whereNotNull(typeColumn.name).whereNotNull(idColumn.name);
136
+ if (trx) {
137
+ qb.transacting(trx);
138
+ }
139
+ const entries = await qb;
140
+ for (const entry of entries){
141
+ const ref = entry[idColumn.name];
142
+ yield {
143
+ kind,
144
+ relation,
145
+ left: {
146
+ type: uid,
147
+ ref: entry.id,
148
+ field: fieldName
149
+ },
150
+ right: {
151
+ type: entry[typeColumn.name],
152
+ ref
153
+ }
154
+ };
155
+ }
156
+ }
157
+ }
158
+ async function* generateAll(uid) {
159
+ const metadata = strapi.db.metadata.get(uid);
160
+ if (!metadata) {
161
+ throw new Error(`No metadata found for ${uid}`);
162
+ }
163
+ const attributes = filterValidRelationalAttributes(metadata.attributes);
164
+ for (const fieldName of Object.keys(attributes)){
165
+ for await (const link of generateAllForAttribute(uid, fieldName)){
166
+ yield link;
167
+ }
168
+ }
169
+ }
170
+ const insert = async (link)=>{
171
+ const { kind, left, right } = link;
172
+ const metadata = strapi.db.metadata.get(left.type);
173
+ const attribute = metadata.attributes[left.field];
174
+ const payload = {};
175
+ /**
176
+ * This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages
177
+ * and a user is importing EE data into a CE project.
178
+ */ if (!attribute) {
179
+ return;
180
+ }
181
+ if (attribute.type !== 'relation') {
182
+ throw new Error(`Attribute ${left.field} is not a relation`);
183
+ }
184
+ if ('joinColumn' in attribute && attribute.joinColumn) {
185
+ const joinColumnName = attribute.joinColumn.name;
186
+ // Note: this addSchema may not be necessary, but is added for safety
187
+ const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
188
+ [joinColumnName]: right.ref
189
+ });
190
+ if (trx) {
191
+ qb.transacting(trx);
192
+ }
193
+ await qb;
194
+ }
195
+ if ('joinTable' in attribute && attribute.joinTable) {
196
+ const { joinTable } = attribute;
197
+ if (joinTable.joinColumn) {
198
+ Object.assign(payload, {
199
+ [joinTable.joinColumn.name]: left.ref
200
+ });
201
+ }
202
+ const assignInverseColumn = ()=>{
203
+ if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {
204
+ Object.assign(payload, {
205
+ [joinTable.inverseJoinColumn.name]: right.ref
206
+ });
207
+ }
208
+ };
209
+ const assignOrderColumns = ()=>{
210
+ if ('orderColumnName' in joinTable && joinTable.orderColumnName) {
211
+ Object.assign(payload, {
212
+ [joinTable.orderColumnName]: left.pos ?? null
213
+ });
214
+ }
215
+ if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {
216
+ Object.assign(payload, {
217
+ [joinTable.inverseOrderColumnName]: right.pos ?? null
218
+ });
219
+ }
220
+ };
221
+ const assignMorphColumns = ()=>{
222
+ if ('morphColumn' in joinTable && joinTable.morphColumn) {
223
+ const { idColumn, typeColumn } = joinTable.morphColumn ?? {};
224
+ if (idColumn) {
225
+ Object.assign(payload, {
226
+ [idColumn.name]: right.ref
227
+ });
228
+ }
229
+ if (typeColumn) {
230
+ Object.assign(payload, {
231
+ [typeColumn.name]: right.type
232
+ });
233
+ }
234
+ Object.assign(payload, {
235
+ order: right.pos ?? null,
236
+ field: right.field ?? null
237
+ });
238
+ }
239
+ };
240
+ if (kind === 'relation.basic' || kind === 'relation.circular') {
241
+ assignInverseColumn();
242
+ }
243
+ if (kind === 'relation.morph') {
244
+ assignMorphColumns();
245
+ }
246
+ assignOrderColumns();
247
+ const qb = connection.insert(payload).into(addSchema(joinTable.name));
248
+ if (trx) {
249
+ await qb.transacting(trx);
250
+ }
251
+ }
252
+ if ('morphColumn' in attribute && attribute.morphColumn) {
253
+ const { morphColumn } = attribute;
254
+ const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
255
+ [morphColumn.idColumn.name]: right.ref,
256
+ [morphColumn.typeColumn.name]: right.type
257
+ });
258
+ if (trx) {
259
+ qb.transacting(trx);
260
+ }
261
+ await qb;
262
+ }
263
+ };
264
+ return {
265
+ generateAll,
266
+ generateAllForAttribute,
267
+ insert
268
+ };
269
+ };
270
+ return query;
271
+ };
272
+ const filterValidRelationalAttributes = (attributes)=>{
273
+ const isOwner = (attribute)=>{
274
+ return attribute.owner || !attribute.mappedBy && !attribute.morphBy;
275
+ };
276
+ const isComponentLike = (attribute)=>attribute.joinTable?.name.endsWith('_cmps');
277
+ return Object.entries(attributes).filter(([, attribute])=>{
278
+ return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);
279
+ }).reduce((acc, [key, attribute])=>({
280
+ ...acc,
281
+ [key]: attribute
282
+ }), {});
283
+ };
284
+ const getLinkKind = (attribute, uid)=>{
285
+ if (attribute.relation.startsWith('morph')) {
286
+ return 'relation.morph';
287
+ }
288
+ if (attribute.target === uid) {
289
+ return 'relation.circular';
290
+ }
291
+ return 'relation.basic';
292
+ };
293
+
294
+ export { createLinkQuery, filterValidRelationalAttributes };
295
+ //# sourceMappingURL=link.mjs.map