@strapi/core 0.0.0-experimental.18019758d6ccd252f2f00bcc32c191402af2e60a → 0.0.0-experimental.1bca8e0e074de8b0775bcddc7656fbc9e9f1393b

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.

Potentially problematic release.


This version of @strapi/core might be problematic. Click here for more details.

Files changed (264) hide show
  1. package/LICENSE +18 -3
  2. package/dist/Strapi.d.ts +3 -1
  3. package/dist/Strapi.d.ts.map +1 -1
  4. package/dist/Strapi.js +59 -15
  5. package/dist/Strapi.js.map +1 -1
  6. package/dist/Strapi.mjs +38 -13
  7. package/dist/Strapi.mjs.map +1 -1
  8. package/dist/configuration/get-dirs.js +2 -2
  9. package/dist/configuration/get-dirs.js.map +1 -1
  10. package/dist/configuration/index.js +2 -2
  11. package/dist/configuration/index.js.map +1 -1
  12. package/dist/core-api/controller/collection-type.d.ts.map +1 -1
  13. package/dist/core-api/controller/collection-type.js +5 -3
  14. package/dist/core-api/controller/collection-type.js.map +1 -1
  15. package/dist/core-api/controller/collection-type.mjs +2 -0
  16. package/dist/core-api/controller/collection-type.mjs.map +1 -1
  17. package/dist/core-api/controller/index.js +2 -2
  18. package/dist/core-api/controller/index.js.map +1 -1
  19. package/dist/core-api/controller/single-type.d.ts.map +1 -1
  20. package/dist/core-api/controller/single-type.js +3 -2
  21. package/dist/core-api/controller/single-type.js.map +1 -1
  22. package/dist/core-api/controller/single-type.mjs +1 -0
  23. package/dist/core-api/controller/single-type.mjs.map +1 -1
  24. package/dist/core-api/controller/transform.js +8 -8
  25. package/dist/core-api/controller/transform.js.map +1 -1
  26. package/dist/core-api/service/collection-type.d.ts +1 -7
  27. package/dist/core-api/service/collection-type.d.ts.map +1 -1
  28. package/dist/core-api/service/collection-type.js +5 -3
  29. package/dist/core-api/service/collection-type.js.map +1 -1
  30. package/dist/core-api/service/collection-type.mjs +6 -4
  31. package/dist/core-api/service/collection-type.mjs.map +1 -1
  32. package/dist/core-api/service/pagination.d.ts +4 -11
  33. package/dist/core-api/service/pagination.d.ts.map +1 -1
  34. package/dist/core-api/service/pagination.js +18 -44
  35. package/dist/core-api/service/pagination.js.map +1 -1
  36. package/dist/core-api/service/pagination.mjs +16 -42
  37. package/dist/core-api/service/pagination.mjs.map +1 -1
  38. package/dist/core-api/service/single-type.d.ts.map +1 -1
  39. package/dist/core-api/service/single-type.js +2 -1
  40. package/dist/core-api/service/single-type.js.map +1 -1
  41. package/dist/core-api/service/single-type.mjs +2 -1
  42. package/dist/core-api/service/single-type.mjs.map +1 -1
  43. package/dist/domain/content-type/index.js +4 -4
  44. package/dist/domain/content-type/index.js.map +1 -1
  45. package/dist/ee/index.js +3 -3
  46. package/dist/ee/index.js.map +1 -1
  47. package/dist/factories.js +4 -4
  48. package/dist/factories.js.map +1 -1
  49. package/dist/index.d.ts +14 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/loaders/apis.d.ts.map +1 -1
  54. package/dist/loaders/apis.js +12 -12
  55. package/dist/loaders/apis.js.map +1 -1
  56. package/dist/loaders/apis.mjs +10 -10
  57. package/dist/loaders/apis.mjs.map +1 -1
  58. package/dist/loaders/plugins/get-enabled-plugins.d.ts.map +1 -1
  59. package/dist/loaders/plugins/get-enabled-plugins.js +13 -13
  60. package/dist/loaders/plugins/get-enabled-plugins.js.map +1 -1
  61. package/dist/loaders/plugins/get-enabled-plugins.mjs +5 -5
  62. package/dist/loaders/plugins/get-enabled-plugins.mjs.map +1 -1
  63. package/dist/loaders/plugins/get-user-plugins-config.js +2 -2
  64. package/dist/loaders/plugins/get-user-plugins-config.js.map +1 -1
  65. package/dist/loaders/plugins/index.js +6 -6
  66. package/dist/loaders/plugins/index.js.map +1 -1
  67. package/dist/middlewares/body.js +2 -2
  68. package/dist/middlewares/body.js.map +1 -1
  69. package/dist/middlewares/cors.d.ts.map +1 -1
  70. package/dist/middlewares/cors.js +9 -7
  71. package/dist/middlewares/cors.js.map +1 -1
  72. package/dist/middlewares/cors.mjs +9 -7
  73. package/dist/middlewares/cors.mjs.map +1 -1
  74. package/dist/middlewares/public.js +2 -2
  75. package/dist/middlewares/public.js.map +1 -1
  76. package/dist/middlewares/query.d.ts.map +1 -1
  77. package/dist/middlewares/query.js.map +1 -1
  78. package/dist/middlewares/query.mjs.map +1 -1
  79. package/dist/middlewares/responses.js +2 -2
  80. package/dist/middlewares/responses.js.map +1 -1
  81. package/dist/middlewares/security.d.ts.map +1 -1
  82. package/dist/middlewares/security.js +12 -5
  83. package/dist/middlewares/security.js.map +1 -1
  84. package/dist/middlewares/security.mjs +11 -4
  85. package/dist/middlewares/security.mjs.map +1 -1
  86. package/dist/middlewares/session.js +2 -2
  87. package/dist/middlewares/session.js.map +1 -1
  88. package/dist/migrations/database/5.0.0-discard-drafts.d.ts +30 -0
  89. package/dist/migrations/database/5.0.0-discard-drafts.d.ts.map +1 -0
  90. package/dist/migrations/database/5.0.0-discard-drafts.js +50 -0
  91. package/dist/migrations/database/5.0.0-discard-drafts.js.map +1 -0
  92. package/dist/migrations/database/5.0.0-discard-drafts.mjs +50 -0
  93. package/dist/migrations/database/5.0.0-discard-drafts.mjs.map +1 -0
  94. package/dist/migrations/draft-publish.d.ts.map +1 -1
  95. package/dist/migrations/draft-publish.js +14 -31
  96. package/dist/migrations/draft-publish.js.map +1 -1
  97. package/dist/migrations/draft-publish.mjs +15 -32
  98. package/dist/migrations/draft-publish.mjs.map +1 -1
  99. package/dist/providers/registries.d.ts.map +1 -1
  100. package/dist/providers/registries.js +2 -0
  101. package/dist/providers/registries.js.map +1 -1
  102. package/dist/providers/registries.mjs +2 -0
  103. package/dist/providers/registries.mjs.map +1 -1
  104. package/dist/registries/apis.js +2 -2
  105. package/dist/registries/apis.js.map +1 -1
  106. package/dist/registries/components.js +2 -2
  107. package/dist/registries/components.js.map +1 -1
  108. package/dist/registries/content-types.js +3 -3
  109. package/dist/registries/content-types.js.map +1 -1
  110. package/dist/registries/controllers.js +3 -3
  111. package/dist/registries/controllers.js.map +1 -1
  112. package/dist/registries/custom-fields.js +4 -4
  113. package/dist/registries/custom-fields.js.map +1 -1
  114. package/dist/registries/hooks.js +2 -2
  115. package/dist/registries/hooks.js.map +1 -1
  116. package/dist/registries/middlewares.js +3 -3
  117. package/dist/registries/middlewares.js.map +1 -1
  118. package/dist/registries/modules.js +3 -3
  119. package/dist/registries/modules.js.map +1 -1
  120. package/dist/registries/plugins.js +2 -2
  121. package/dist/registries/plugins.js.map +1 -1
  122. package/dist/registries/policies.js +4 -4
  123. package/dist/registries/policies.js.map +1 -1
  124. package/dist/registries/services.js +3 -3
  125. package/dist/registries/services.js.map +1 -1
  126. package/dist/services/auth/index.js +3 -3
  127. package/dist/services/auth/index.js.map +1 -1
  128. package/dist/services/core-store.js +3 -3
  129. package/dist/services/core-store.js.map +1 -1
  130. package/dist/services/cron.js +3 -3
  131. package/dist/services/cron.js.map +1 -1
  132. package/dist/services/document-service/attributes/index.js +2 -2
  133. package/dist/services/document-service/attributes/index.js.map +1 -1
  134. package/dist/services/document-service/attributes/transforms.js +3 -3
  135. package/dist/services/document-service/attributes/transforms.js.map +1 -1
  136. package/dist/services/document-service/components.js +15 -15
  137. package/dist/services/document-service/components.js.map +1 -1
  138. package/dist/services/document-service/draft-and-publish.js +16 -16
  139. package/dist/services/document-service/draft-and-publish.js.map +1 -1
  140. package/dist/services/document-service/entries.d.ts +1 -1
  141. package/dist/services/document-service/entries.d.ts.map +1 -1
  142. package/dist/services/document-service/entries.js +7 -6
  143. package/dist/services/document-service/entries.js.map +1 -1
  144. package/dist/services/document-service/entries.mjs +2 -1
  145. package/dist/services/document-service/entries.mjs.map +1 -1
  146. package/dist/services/document-service/events.d.ts +25 -0
  147. package/dist/services/document-service/events.d.ts.map +1 -0
  148. package/dist/services/document-service/events.js +47 -0
  149. package/dist/services/document-service/events.js.map +1 -0
  150. package/dist/services/document-service/events.mjs +47 -0
  151. package/dist/services/document-service/events.mjs.map +1 -0
  152. package/dist/services/document-service/index.d.ts.map +1 -1
  153. package/dist/services/document-service/index.js.map +1 -1
  154. package/dist/services/document-service/index.mjs.map +1 -1
  155. package/dist/services/document-service/internationalization.d.ts.map +1 -1
  156. package/dist/services/document-service/internationalization.js +21 -12
  157. package/dist/services/document-service/internationalization.js.map +1 -1
  158. package/dist/services/document-service/internationalization.mjs +14 -5
  159. package/dist/services/document-service/internationalization.mjs.map +1 -1
  160. package/dist/services/document-service/params.js +2 -2
  161. package/dist/services/document-service/params.js.map +1 -1
  162. package/dist/services/document-service/repository.d.ts.map +1 -1
  163. package/dist/services/document-service/repository.js +80 -52
  164. package/dist/services/document-service/repository.js.map +1 -1
  165. package/dist/services/document-service/repository.mjs +75 -47
  166. package/dist/services/document-service/repository.mjs.map +1 -1
  167. package/dist/services/document-service/transform/id-transform.js +2 -2
  168. package/dist/services/document-service/transform/id-transform.js.map +1 -1
  169. package/dist/services/document-service/transform/query.js +3 -3
  170. package/dist/services/document-service/transform/query.js.map +1 -1
  171. package/dist/services/document-service/transform/relations/extract/data-ids.d.ts.map +1 -1
  172. package/dist/services/document-service/transform/relations/extract/data-ids.js +5 -2
  173. package/dist/services/document-service/transform/relations/extract/data-ids.js.map +1 -1
  174. package/dist/services/document-service/transform/relations/extract/data-ids.mjs +3 -0
  175. package/dist/services/document-service/transform/relations/extract/data-ids.mjs.map +1 -1
  176. package/dist/services/document-service/transform/relations/transform/data-ids.d.ts.map +1 -1
  177. package/dist/services/document-service/transform/relations/transform/data-ids.js +5 -2
  178. package/dist/services/document-service/transform/relations/transform/data-ids.js.map +1 -1
  179. package/dist/services/document-service/transform/relations/transform/data-ids.mjs +3 -0
  180. package/dist/services/document-service/transform/relations/transform/data-ids.mjs.map +1 -1
  181. package/dist/services/document-service/transform/relations/utils/dp.js +2 -2
  182. package/dist/services/document-service/transform/relations/utils/dp.js.map +1 -1
  183. package/dist/services/document-service/transform/relations/utils/map-relation.d.ts.map +1 -1
  184. package/dist/services/document-service/transform/relations/utils/map-relation.js +13 -9
  185. package/dist/services/document-service/transform/relations/utils/map-relation.js.map +1 -1
  186. package/dist/services/document-service/transform/relations/utils/map-relation.mjs +7 -3
  187. package/dist/services/document-service/transform/relations/utils/map-relation.mjs.map +1 -1
  188. package/dist/services/document-service/utils/populate.d.ts.map +1 -1
  189. package/dist/services/document-service/utils/populate.js +4 -0
  190. package/dist/services/document-service/utils/populate.js.map +1 -1
  191. package/dist/services/document-service/utils/populate.mjs +4 -0
  192. package/dist/services/document-service/utils/populate.mjs.map +1 -1
  193. package/dist/services/entity-validator/index.d.ts +14 -1
  194. package/dist/services/entity-validator/index.d.ts.map +1 -1
  195. package/dist/services/entity-validator/index.js +106 -49
  196. package/dist/services/entity-validator/index.js.map +1 -1
  197. package/dist/services/entity-validator/index.mjs +87 -30
  198. package/dist/services/entity-validator/index.mjs.map +1 -1
  199. package/dist/services/entity-validator/validators.d.ts +10 -8
  200. package/dist/services/entity-validator/validators.d.ts.map +1 -1
  201. package/dist/services/entity-validator/validators.js +61 -19
  202. package/dist/services/entity-validator/validators.js.map +1 -1
  203. package/dist/services/entity-validator/validators.mjs +54 -11
  204. package/dist/services/entity-validator/validators.mjs.map +1 -1
  205. package/dist/services/event-hub.d.ts +1 -0
  206. package/dist/services/event-hub.d.ts.map +1 -1
  207. package/dist/services/event-hub.js +9 -4
  208. package/dist/services/event-hub.js.map +1 -1
  209. package/dist/services/event-hub.mjs +9 -4
  210. package/dist/services/event-hub.mjs.map +1 -1
  211. package/dist/services/server/compose-endpoint.js +7 -7
  212. package/dist/services/server/compose-endpoint.js.map +1 -1
  213. package/dist/services/server/index.js +1 -1
  214. package/dist/services/server/index.js.map +1 -1
  215. package/dist/services/server/index.mjs +1 -1
  216. package/dist/services/server/index.mjs.map +1 -1
  217. package/dist/services/server/koa.d.ts.map +1 -1
  218. package/dist/services/server/koa.js +4 -4
  219. package/dist/services/server/koa.js.map +1 -1
  220. package/dist/services/server/koa.mjs +1 -1
  221. package/dist/services/server/koa.mjs.map +1 -1
  222. package/dist/services/server/middleware.js +3 -3
  223. package/dist/services/server/middleware.js.map +1 -1
  224. package/dist/services/server/routing.js +2 -2
  225. package/dist/services/server/routing.js.map +1 -1
  226. package/dist/services/utils/dynamic-zones.js +5 -5
  227. package/dist/services/utils/dynamic-zones.js.map +1 -1
  228. package/dist/services/webhook-runner.d.ts +2 -1
  229. package/dist/services/webhook-runner.d.ts.map +1 -1
  230. package/dist/services/webhook-runner.js.map +1 -1
  231. package/dist/services/webhook-runner.mjs.map +1 -1
  232. package/dist/services/webhook-store.d.ts +2 -8
  233. package/dist/services/webhook-store.d.ts.map +1 -1
  234. package/dist/services/webhook-store.js +9 -2
  235. package/dist/services/webhook-store.js.map +1 -1
  236. package/dist/services/webhook-store.mjs +9 -2
  237. package/dist/services/webhook-store.mjs.map +1 -1
  238. package/dist/utils/cron.js +3 -3
  239. package/dist/utils/cron.js.map +1 -1
  240. package/dist/utils/fetch.d.ts.map +1 -1
  241. package/dist/utils/fetch.js +4 -3
  242. package/dist/utils/fetch.js.map +1 -1
  243. package/dist/utils/fetch.mjs +4 -3
  244. package/dist/utils/fetch.mjs.map +1 -1
  245. package/dist/utils/filepath-to-prop-path.d.ts +1 -1
  246. package/dist/utils/filepath-to-prop-path.d.ts.map +1 -1
  247. package/dist/utils/filepath-to-prop-path.js +27 -6
  248. package/dist/utils/filepath-to-prop-path.js.map +1 -1
  249. package/dist/utils/filepath-to-prop-path.mjs +25 -5
  250. package/dist/utils/filepath-to-prop-path.mjs.map +1 -1
  251. package/dist/utils/is-initialized.js +3 -3
  252. package/dist/utils/is-initialized.js.map +1 -1
  253. package/dist/utils/startup-logger.js +4 -4
  254. package/dist/utils/startup-logger.js.map +1 -1
  255. package/dist/utils/startup-logger.mjs +3 -3
  256. package/dist/utils/startup-logger.mjs.map +1 -1
  257. package/dist/utils/transform-content-types-to-models.d.ts.map +1 -1
  258. package/dist/utils/transform-content-types-to-models.js +16 -4
  259. package/dist/utils/transform-content-types-to-models.js.map +1 -1
  260. package/dist/utils/transform-content-types-to-models.mjs +15 -3
  261. package/dist/utils/transform-content-types-to-models.mjs.map +1 -1
  262. package/package.json +22 -18
  263. package/dist/services/document-service/document-engine.d.ts +0 -1
  264. package/dist/services/document-service/document-engine.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"data-ids.mjs","sources":["../../../../../../src/services/document-service/transform/relations/transform/data-ids.ts"],"sourcesContent":["import { curry } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nimport { ID, LongHandDocument } from '../utils/types';\nimport { IdMap } from '../../id-map';\nimport { getRelationTargetLocale } from '../utils/i18n';\nimport { getRelationTargetStatus } from '../utils/dp';\nimport { mapRelation, traverseEntityRelations } from '../utils/map-relation';\n\ninterface Options {\n uid: UID.Schema;\n locale?: string | null;\n status?: 'draft' | 'published';\n allowMissingId?: boolean; // Whether to ignore missing ids and not throw any error\n}\n\n/**\n * Get the entry ids for a given documentId.\n */\nconst getRelationIds = curry(\n (idMap: IdMap, targetUid: UID.Schema, source: Options, relation: LongHandDocument) => {\n // locale to connect to\n const targetLocale = getRelationTargetLocale(relation, {\n targetUid,\n sourceUid: source.uid,\n sourceLocale: source.locale,\n });\n\n // status(es) to connect to\n const targetStatus = getRelationTargetStatus(relation, {\n targetUid,\n sourceUid: source.uid,\n sourceStatus: source.status,\n });\n\n const ids: ID[] = [];\n\n // Find mapping between documentID -> id(s).\n // There are scenarios where a single documentID can map to multiple ids.\n // e.g when connecting Non DP -> DP and connecting to both the draft and publish version at the same time\n for (const tStatus of targetStatus) {\n const entryId = idMap.get({\n uid: targetUid,\n documentId: relation.documentId,\n locale: targetLocale,\n status: tStatus,\n });\n\n if (entryId) ids.push(entryId);\n }\n\n if (!ids.length && !source.allowMissingId) {\n throw new errors.ValidationError(\n `Document with id \"${relation.documentId}\", locale \"${targetLocale}\" not found`\n );\n }\n\n return ids;\n }\n);\n\n/**\n * Iterate over all relations of a data object and transform all relational document ids to entity ids.\n */\nconst transformDataIdsVisitor = (idMap: IdMap, data: Record<string, any>, source: Options) => {\n return traverseEntityRelations(\n async ({ key, value, attribute }, { set }) => {\n // Find relational attributes, and return the document ids\n const targetUid = attribute.target!;\n const getIds = getRelationIds(idMap, targetUid, source);\n\n // Transform the relation documentId to entity id\n const newRelation = await mapRelation((relation) => {\n if (!relation || !relation.documentId) {\n return relation;\n }\n\n const ids = getIds(relation);\n\n // Handle positional arguments\n const position = { ...relation.position };\n\n if (position.before) {\n const beforeRelation = { ...relation, ...position, documentId: position.before };\n position.before = getIds(beforeRelation).at(0);\n }\n\n if (position.after) {\n const afterRelation = { ...relation, ...position, documentId: position.after };\n position.after = getIds(afterRelation).at(0);\n }\n\n // Transform all ids to new relations\n return ids?.map((id) => {\n const newRelation = { id } as typeof relation;\n if (relation.position) {\n newRelation.position = position;\n }\n\n return newRelation;\n });\n }, value as any);\n\n set(key, newRelation as any);\n },\n { schema: strapi.getModel(source.uid), getModel: strapi.getModel.bind(strapi) },\n data\n );\n};\n\nexport { transformDataIdsVisitor };\n"],"names":["traverseEntityRelations","mapRelation","newRelation"],"mappings":";;;;;AAqBA,MAAM,iBAAiB;AAAA,EACrB,CAAC,OAAc,WAAuB,QAAiB,aAA+B;AAE9E,UAAA,eAAe,wBAAwB,UAAU;AAAA,MACrD;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IAAA,CACtB;AAGK,UAAA,eAAe,wBAAwB,UAAU;AAAA,MACrD;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IAAA,CACtB;AAED,UAAM,MAAY,CAAA;AAKlB,eAAW,WAAW,cAAc;AAC5B,YAAA,UAAU,MAAM,IAAI;AAAA,QACxB,KAAK;AAAA,QACL,YAAY,SAAS;AAAA,QACrB,QAAQ;AAAA,QACR,QAAQ;AAAA,MAAA,CACT;AAEG,UAAA;AAAS,YAAI,KAAK,OAAO;AAAA,IAC/B;AAEA,QAAI,CAAC,IAAI,UAAU,CAAC,OAAO,gBAAgB;AACzC,YAAM,IAAI,OAAO;AAAA,QACf,qBAAqB,SAAS,UAAU,cAAc,YAAY;AAAA,MAAA;AAAA,IAEtE;AAEO,WAAA;AAAA,EACT;AACF;AAKA,MAAM,0BAA0B,CAAC,OAAc,MAA2B,WAAoB;AACrF,SAAAA;AAAAA,IACL,OAAO,EAAE,KAAK,OAAO,aAAa,EAAE,UAAU;AAE5C,YAAM,YAAY,UAAU;AAC5B,YAAM,SAAS,eAAe,OAAO,WAAW,MAAM;AAGtD,YAAM,cAAc,MAAMC,mBAAY,CAAC,aAAa;AAClD,YAAI,CAAC,YAAY,CAAC,SAAS,YAAY;AAC9B,iBAAA;AAAA,QACT;AAEM,cAAA,MAAM,OAAO,QAAQ;AAG3B,cAAM,WAAW,EAAE,GAAG,SAAS,SAAS;AAExC,YAAI,SAAS,QAAQ;AACb,gBAAA,iBAAiB,EAAE,GAAG,UAAU,GAAG,UAAU,YAAY,SAAS;AACxE,mBAAS,SAAS,OAAO,cAAc,EAAE,GAAG,CAAC;AAAA,QAC/C;AAEA,YAAI,SAAS,OAAO;AACZ,gBAAA,gBAAgB,EAAE,GAAG,UAAU,GAAG,UAAU,YAAY,SAAS;AACvE,mBAAS,QAAQ,OAAO,aAAa,EAAE,GAAG,CAAC;AAAA,QAC7C;AAGO,eAAA,KAAK,IAAI,CAAC,OAAO;AAChBC,gBAAAA,eAAc,EAAE;AACtB,cAAI,SAAS,UAAU;AACrBA,yBAAY,WAAW;AAAA,UACzB;AAEOA,iBAAAA;AAAAA,QAAA,CACR;AAAA,SACA,KAAY;AAEf,UAAI,KAAK,WAAkB;AAAA,IAC7B;AAAA,IACA,EAAE,QAAQ,OAAO,SAAS,OAAO,GAAG,GAAG,UAAU,OAAO,SAAS,KAAK,MAAM,EAAE;AAAA,IAC9E;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"data-ids.mjs","sources":["../../../../../../src/services/document-service/transform/relations/transform/data-ids.ts"],"sourcesContent":["import { curry } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nimport { ID, LongHandDocument } from '../utils/types';\nimport { IdMap } from '../../id-map';\nimport { getRelationTargetLocale } from '../utils/i18n';\nimport { getRelationTargetStatus } from '../utils/dp';\nimport { mapRelation, traverseEntityRelations } from '../utils/map-relation';\n\ninterface Options {\n uid: UID.Schema;\n locale?: string | null;\n status?: 'draft' | 'published';\n allowMissingId?: boolean; // Whether to ignore missing ids and not throw any error\n}\n\n/**\n * Get the entry ids for a given documentId.\n */\nconst getRelationIds = curry(\n (idMap: IdMap, targetUid: UID.Schema, source: Options, relation: LongHandDocument) => {\n // locale to connect to\n const targetLocale = getRelationTargetLocale(relation, {\n targetUid,\n sourceUid: source.uid,\n sourceLocale: source.locale,\n });\n\n // status(es) to connect to\n const targetStatus = getRelationTargetStatus(relation, {\n targetUid,\n sourceUid: source.uid,\n sourceStatus: source.status,\n });\n\n const ids: ID[] = [];\n\n // Find mapping between documentID -> id(s).\n // There are scenarios where a single documentID can map to multiple ids.\n // e.g when connecting Non DP -> DP and connecting to both the draft and publish version at the same time\n for (const tStatus of targetStatus) {\n const entryId = idMap.get({\n uid: targetUid,\n documentId: relation.documentId,\n locale: targetLocale,\n status: tStatus,\n });\n\n if (entryId) ids.push(entryId);\n }\n\n if (!ids.length && !source.allowMissingId) {\n throw new errors.ValidationError(\n `Document with id \"${relation.documentId}\", locale \"${targetLocale}\" not found`\n );\n }\n\n return ids;\n }\n);\n\n/**\n * Iterate over all relations of a data object and transform all relational document ids to entity ids.\n */\nconst transformDataIdsVisitor = (idMap: IdMap, data: Record<string, any>, source: Options) => {\n return traverseEntityRelations(\n async ({ key, value, attribute }, { set }) => {\n if (!attribute) {\n return;\n }\n\n // Find relational attributes, and return the document ids\n const targetUid = attribute.target!;\n const getIds = getRelationIds(idMap, targetUid, source);\n\n // Transform the relation documentId to entity id\n const newRelation = await mapRelation((relation) => {\n if (!relation || !relation.documentId) {\n return relation;\n }\n\n const ids = getIds(relation);\n\n // Handle positional arguments\n const position = { ...relation.position };\n\n if (position.before) {\n const beforeRelation = { ...relation, ...position, documentId: position.before };\n position.before = getIds(beforeRelation).at(0);\n }\n\n if (position.after) {\n const afterRelation = { ...relation, ...position, documentId: position.after };\n position.after = getIds(afterRelation).at(0);\n }\n\n // Transform all ids to new relations\n return ids?.map((id) => {\n const newRelation = { id } as typeof relation;\n if (relation.position) {\n newRelation.position = position;\n }\n\n return newRelation;\n });\n }, value as any);\n\n set(key, newRelation as any);\n },\n { schema: strapi.getModel(source.uid), getModel: strapi.getModel.bind(strapi) },\n data\n );\n};\n\nexport { transformDataIdsVisitor };\n"],"names":["traverseEntityRelations","mapRelation","newRelation"],"mappings":";;;;;AAqBA,MAAM,iBAAiB;AAAA,EACrB,CAAC,OAAc,WAAuB,QAAiB,aAA+B;AAE9E,UAAA,eAAe,wBAAwB,UAAU;AAAA,MACrD;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IAAA,CACtB;AAGK,UAAA,eAAe,wBAAwB,UAAU;AAAA,MACrD;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IAAA,CACtB;AAED,UAAM,MAAY,CAAA;AAKlB,eAAW,WAAW,cAAc;AAC5B,YAAA,UAAU,MAAM,IAAI;AAAA,QACxB,KAAK;AAAA,QACL,YAAY,SAAS;AAAA,QACrB,QAAQ;AAAA,QACR,QAAQ;AAAA,MAAA,CACT;AAEG,UAAA;AAAS,YAAI,KAAK,OAAO;AAAA,IAC/B;AAEA,QAAI,CAAC,IAAI,UAAU,CAAC,OAAO,gBAAgB;AACzC,YAAM,IAAI,OAAO;AAAA,QACf,qBAAqB,SAAS,UAAU,cAAc,YAAY;AAAA,MAAA;AAAA,IAEtE;AAEO,WAAA;AAAA,EACT;AACF;AAKA,MAAM,0BAA0B,CAAC,OAAc,MAA2B,WAAoB;AACrF,SAAAA;AAAAA,IACL,OAAO,EAAE,KAAK,OAAO,aAAa,EAAE,UAAU;AAC5C,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAGA,YAAM,YAAY,UAAU;AAC5B,YAAM,SAAS,eAAe,OAAO,WAAW,MAAM;AAGtD,YAAM,cAAc,MAAMC,mBAAY,CAAC,aAAa;AAClD,YAAI,CAAC,YAAY,CAAC,SAAS,YAAY;AAC9B,iBAAA;AAAA,QACT;AAEM,cAAA,MAAM,OAAO,QAAQ;AAG3B,cAAM,WAAW,EAAE,GAAG,SAAS,SAAS;AAExC,YAAI,SAAS,QAAQ;AACb,gBAAA,iBAAiB,EAAE,GAAG,UAAU,GAAG,UAAU,YAAY,SAAS;AACxE,mBAAS,SAAS,OAAO,cAAc,EAAE,GAAG,CAAC;AAAA,QAC/C;AAEA,YAAI,SAAS,OAAO;AACZ,gBAAA,gBAAgB,EAAE,GAAG,UAAU,GAAG,UAAU,YAAY,SAAS;AACvE,mBAAS,QAAQ,OAAO,aAAa,EAAE,GAAG,CAAC;AAAA,QAC7C;AAGO,eAAA,KAAK,IAAI,CAAC,OAAO;AAChBC,gBAAAA,eAAc,EAAE;AACtB,cAAI,SAAS,UAAU;AACrBA,yBAAY,WAAW;AAAA,UACzB;AAEOA,iBAAAA;AAAAA,QAAA,CACR;AAAA,SACA,KAAY;AAEf,UAAI,KAAK,WAAkB;AAAA,IAC7B;AAAA,IACA,EAAE,QAAQ,OAAO,SAAS,OAAO,GAAG,GAAG,UAAU,OAAO,SAAS,KAAK,MAAM,EAAE;AAAA,IAC9E;AAAA,EAAA;AAEJ;"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const _ = require("lodash/fp");
3
+ const fp = require("lodash/fp");
4
4
  const strapiUtils = require("@strapi/utils");
5
5
  const getRelationTargetStatus = (relation, opts) => {
6
6
  const targetContentType = strapi.getModel(opts.targetUid);
@@ -10,7 +10,7 @@ const getRelationTargetStatus = (relation, opts) => {
10
10
  if (!targetHasDP) {
11
11
  return ["published"];
12
12
  }
13
- if (sourceHasDP && !_.isNil(opts.sourceStatus)) {
13
+ if (sourceHasDP && !fp.isNil(opts.sourceStatus)) {
14
14
  return [opts.sourceStatus];
15
15
  }
16
16
  if (relation.status) {
@@ -1 +1 @@
1
- {"version":3,"file":"dp.js","sources":["../../../../../../src/services/document-service/transform/relations/utils/dp.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\n\nimport { contentTypes } from '@strapi/utils';\nimport { UID } from '@strapi/types';\n\nimport { LongHandDocument } from './types';\n\ntype Status = 'draft' | 'published';\n\nexport const getRelationTargetStatus = (\n relation: Pick<LongHandDocument, 'documentId' | 'status'>,\n opts: {\n targetUid: UID.Schema;\n sourceUid: UID.Schema;\n sourceStatus?: Status;\n }\n): Status[] => {\n // Ignore if the target content type does not have draft and publish enabled\n const targetContentType = strapi.getModel(opts.targetUid);\n const sourceContentType = strapi.getModel(opts.sourceUid);\n\n const targetHasDP = contentTypes.hasDraftAndPublish(targetContentType);\n const sourceHasDP = contentTypes.hasDraftAndPublish(sourceContentType);\n\n if (!targetHasDP) {\n return ['published'];\n }\n\n /**\n * If both source and target have DP enabled,\n * connect it to the same status as the source status\n */\n if (sourceHasDP && !isNil(opts.sourceStatus)) {\n return [opts.sourceStatus];\n }\n\n /**\n * Use the status from the relation if it's set\n */\n if (relation.status) {\n switch (relation.status) {\n case 'published':\n return ['published'];\n default:\n // Default to draft if it's an invalid status (e.g. modified)\n return ['draft'];\n }\n }\n\n /**\n * If DP is disabled and relation does not specify any status\n * Connect to both draft and published versions\n */\n if (!sourceHasDP) {\n return ['draft', 'published'];\n }\n\n // Default to draft as a fallback\n return ['draft'];\n};\n"],"names":["contentTypes","isNil"],"mappings":";;;;AASa,MAAA,0BAA0B,CACrC,UACA,SAKa;AAEb,QAAM,oBAAoB,OAAO,SAAS,KAAK,SAAS;AACxD,QAAM,oBAAoB,OAAO,SAAS,KAAK,SAAS;AAElD,QAAA,cAAcA,YAAAA,aAAa,mBAAmB,iBAAiB;AAC/D,QAAA,cAAcA,YAAAA,aAAa,mBAAmB,iBAAiB;AAErE,MAAI,CAAC,aAAa;AAChB,WAAO,CAAC,WAAW;AAAA,EACrB;AAMA,MAAI,eAAe,CAACC,EAAAA,MAAM,KAAK,YAAY,GAAG;AACrC,WAAA,CAAC,KAAK,YAAY;AAAA,EAC3B;AAKA,MAAI,SAAS,QAAQ;AACnB,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AACH,eAAO,CAAC,WAAW;AAAA,MACrB;AAEE,eAAO,CAAC,OAAO;AAAA,IACnB;AAAA,EACF;AAMA,MAAI,CAAC,aAAa;AACT,WAAA,CAAC,SAAS,WAAW;AAAA,EAC9B;AAGA,SAAO,CAAC,OAAO;AACjB;;"}
1
+ {"version":3,"file":"dp.js","sources":["../../../../../../src/services/document-service/transform/relations/utils/dp.ts"],"sourcesContent":["import { isNil } from 'lodash/fp';\n\nimport { contentTypes } from '@strapi/utils';\nimport { UID } from '@strapi/types';\n\nimport { LongHandDocument } from './types';\n\ntype Status = 'draft' | 'published';\n\nexport const getRelationTargetStatus = (\n relation: Pick<LongHandDocument, 'documentId' | 'status'>,\n opts: {\n targetUid: UID.Schema;\n sourceUid: UID.Schema;\n sourceStatus?: Status;\n }\n): Status[] => {\n // Ignore if the target content type does not have draft and publish enabled\n const targetContentType = strapi.getModel(opts.targetUid);\n const sourceContentType = strapi.getModel(opts.sourceUid);\n\n const targetHasDP = contentTypes.hasDraftAndPublish(targetContentType);\n const sourceHasDP = contentTypes.hasDraftAndPublish(sourceContentType);\n\n if (!targetHasDP) {\n return ['published'];\n }\n\n /**\n * If both source and target have DP enabled,\n * connect it to the same status as the source status\n */\n if (sourceHasDP && !isNil(opts.sourceStatus)) {\n return [opts.sourceStatus];\n }\n\n /**\n * Use the status from the relation if it's set\n */\n if (relation.status) {\n switch (relation.status) {\n case 'published':\n return ['published'];\n default:\n // Default to draft if it's an invalid status (e.g. modified)\n return ['draft'];\n }\n }\n\n /**\n * If DP is disabled and relation does not specify any status\n * Connect to both draft and published versions\n */\n if (!sourceHasDP) {\n return ['draft', 'published'];\n }\n\n // Default to draft as a fallback\n return ['draft'];\n};\n"],"names":["contentTypes","isNil"],"mappings":";;;;AASa,MAAA,0BAA0B,CACrC,UACA,SAKa;AAEb,QAAM,oBAAoB,OAAO,SAAS,KAAK,SAAS;AACxD,QAAM,oBAAoB,OAAO,SAAS,KAAK,SAAS;AAElD,QAAA,cAAcA,YAAAA,aAAa,mBAAmB,iBAAiB;AAC/D,QAAA,cAAcA,YAAAA,aAAa,mBAAmB,iBAAiB;AAErE,MAAI,CAAC,aAAa;AAChB,WAAO,CAAC,WAAW;AAAA,EACrB;AAMA,MAAI,eAAe,CAACC,GAAAA,MAAM,KAAK,YAAY,GAAG;AACrC,WAAA,CAAC,KAAK,YAAY;AAAA,EAC3B;AAKA,MAAI,SAAS,QAAQ;AACnB,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AACH,eAAO,CAAC,WAAW;AAAA,MACrB;AAEE,eAAO,CAAC,OAAO;AAAA,IACnB;AAAA,EACF;AAMA,MAAI,CAAC,aAAa;AACT,WAAA,CAAC,SAAS,WAAW;AAAA,EAC9B;AAGA,SAAO,CAAC,OAAO;AACjB;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"map-relation.d.ts","sourceRoot":"","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAgJnC,QAAA,MAAM,kBAAkB,+CA/GD,GAAG,KAAK,GAAG,8BA+GW,CAAC;AAC9C,QAAA,MAAM,8BAA8B,kPAAiC,CAAC;AAEtE,OAAO,EACL,kBAAkB,IAAI,WAAW,EACjC,8BAA8B,IAAI,uBAAuB,GAC1D,CAAC"}
1
+ {"version":3,"file":"map-relation.d.ts","sourceRoot":"","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAsJnC,QAAA,MAAM,kBAAkB,+CArHD,GAAG,KAAK,GAAG,8BAqHW,CAAC;AAC9C,QAAA,MAAM,8BAA8B,kPAAiC,CAAC;AAEtE,OAAO,EACL,kBAAkB,IAAI,WAAW,EACjC,8BAA8B,IAAI,uBAAuB,GAC1D,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const _ = require("lodash/fp");
3
+ const fp = require("lodash/fp");
4
4
  const strapiUtils = require("@strapi/utils");
5
5
  const isNumeric = (value) => {
6
6
  if (Array.isArray(value))
@@ -9,7 +9,7 @@ const isNumeric = (value) => {
9
9
  return !Number.isNaN(parsed);
10
10
  };
11
11
  const toArray = (value) => {
12
- if (_.isNil(value))
12
+ if (fp.isNil(value))
13
13
  return value;
14
14
  if (Array.isArray(value))
15
15
  return value;
@@ -23,13 +23,13 @@ const mapRelation = async (callback, rel, isRecursive = false) => {
23
23
  }
24
24
  return { set: toArray(value) };
25
25
  };
26
- if (_.isNil(relation)) {
26
+ if (fp.isNil(relation)) {
27
27
  return callback(relation);
28
28
  }
29
29
  if (Array.isArray(relation)) {
30
30
  return strapiUtils.async.map(relation, (r) => mapRelation(callback, r, true)).then((result) => result.flat().filter(Boolean)).then(wrapInSet);
31
31
  }
32
- if (_.isObject(relation)) {
32
+ if (fp.isObject(relation)) {
33
33
  if ("id" in relation || "documentId" in relation) {
34
34
  const result = await callback(relation);
35
35
  return wrapInSet(result);
@@ -64,13 +64,17 @@ const mapRelation = async (callback, rel, isRecursive = false) => {
64
64
  const traverseEntityRelations = async (visitor, options, data) => {
65
65
  return strapiUtils.traverseEntity(
66
66
  async (options2, utils) => {
67
- if (options2.attribute.type !== "relation") {
67
+ const { attribute } = options2;
68
+ if (!attribute) {
68
69
  return;
69
70
  }
70
- if (options2.attribute.useJoinTable === false) {
71
+ if (attribute.type !== "relation") {
71
72
  return;
72
73
  }
73
- const target = options2.attribute.target;
74
+ if (attribute.useJoinTable === false) {
75
+ return;
76
+ }
77
+ const target = attribute.target;
74
78
  if (!target) {
75
79
  return;
76
80
  }
@@ -80,8 +84,8 @@ const traverseEntityRelations = async (visitor, options, data) => {
80
84
  data
81
85
  );
82
86
  };
83
- const mapRelationCurried = _.curry(mapRelation);
84
- const traverseEntityRelationsCurried = _.curry(traverseEntityRelations);
87
+ const mapRelationCurried = fp.curry(mapRelation);
88
+ const traverseEntityRelationsCurried = fp.curry(traverseEntityRelations);
85
89
  exports.mapRelation = mapRelationCurried;
86
90
  exports.traverseEntityRelations = traverseEntityRelationsCurried;
87
91
  //# sourceMappingURL=map-relation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-relation.js","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"sourcesContent":["/* eslint-disable node/no-callback-literal */\nimport { isObject, curry, isNil } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { traverseEntity, async } from '@strapi/utils';\n\nimport { Relation } from './types';\n\nconst isNumeric = (value: any): value is number => {\n if (Array.isArray(value)) return false; // Handle [1, 'docId'] case\n const parsed = parseInt(value, 10);\n return !Number.isNaN(parsed);\n};\n\nconst toArray = (value: any) => {\n // Keep value as it is if it's a nullish value\n if (isNil(value)) return value;\n if (Array.isArray(value)) return value;\n\n return [value];\n};\n\n/**\n * There are multiple ways to create Strapi relations.\n * This is a utility to traverse and transform relation data\n *\n *\n * For consistency and ease of use, the response will always be an object with the following shape:\n * { set: [{...}], connect: [{...}], disconnect: [{...}] }\n *\n * @example\n * transformRelationData({\n * onLongHand: (relation) => {\n * // Change the id of the relation\n * return { id: 'other' };\n * },\n * }, relation)\n */\nconst mapRelation = async (\n callback: (relation: any) => any,\n rel: Relation,\n isRecursive = false\n): Promise<Relation> => {\n let relation: Relation = rel;\n\n const wrapInSet = (value: any) => {\n // Ignore wrapping if it's a recursive call\n if (isRecursive) {\n return value;\n }\n return { set: toArray(value) };\n };\n\n // undefined | null\n if (isNil(relation)) {\n return callback(relation);\n }\n\n // LongHand[] | ShortHand[]\n if (Array.isArray(relation)) {\n return async\n .map(relation, (r: Relation) => mapRelation(callback, r, true))\n .then((result: any) => result.flat().filter(Boolean))\n .then(wrapInSet);\n }\n\n // LongHand\n if (isObject(relation)) {\n // { id: 1 } || { documentId: 1 }\n if ('id' in relation || 'documentId' in relation) {\n const result = await callback(relation);\n return wrapInSet(result);\n }\n\n // If not connecting anything, return default visitor\n if (!relation.set && !relation.disconnect && !relation.connect) {\n return callback(relation);\n }\n\n // { set }\n if (relation.set) {\n const set: any = await mapRelation(callback, relation.set, true);\n relation = { ...relation, set: toArray(set) };\n }\n\n // { disconnect}\n if (relation.disconnect) {\n const disconnect: any = await mapRelation(callback, relation.disconnect, true);\n relation = { ...relation, disconnect: toArray(disconnect) };\n }\n\n // { connect }\n if (relation.connect) {\n // Transform the relation to connect\n const connect: any = await mapRelation(callback, relation.connect, true);\n relation = { ...relation, connect: toArray(connect) };\n }\n\n return relation;\n }\n\n // ShortHand\n if (isNumeric(relation)) {\n const result = await callback({ id: relation });\n return wrapInSet(result);\n }\n\n if (typeof relation === 'string') {\n const result = await callback({ documentId: relation });\n return wrapInSet(result);\n }\n\n // Anything else\n return callback(relation);\n};\n\ntype TraverseEntity = Parameters<typeof traverseEntity>;\n\n/**\n * Utility function, same as `traverseEntity` but only for relations.\n */\nconst traverseEntityRelations = async (\n visitor: TraverseEntity[0],\n options: TraverseEntity[1],\n data: TraverseEntity[2]\n) => {\n return traverseEntity(\n async (options, utils) => {\n if (options.attribute.type !== 'relation') {\n return;\n }\n\n // TODO: Handle join columns\n if (options.attribute.useJoinTable === false) {\n return;\n }\n\n // TODO: Handle morph relations (they have multiple targets)\n const target = options.attribute.target as UID.Schema | undefined;\n if (!target) {\n return;\n }\n\n return visitor(options, utils);\n },\n options,\n data\n );\n};\n\nconst mapRelationCurried = curry(mapRelation);\nconst traverseEntityRelationsCurried = curry(traverseEntityRelations);\n\nexport {\n mapRelationCurried as mapRelation,\n traverseEntityRelationsCurried as traverseEntityRelations,\n};\n"],"names":["isNil","async","isObject","traverseEntity","options","curry"],"mappings":";;;;AAQA,MAAM,YAAY,CAAC,UAAgC;AAC7C,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAC3B,QAAA,SAAS,SAAS,OAAO,EAAE;AAC1B,SAAA,CAAC,OAAO,MAAM,MAAM;AAC7B;AAEA,MAAM,UAAU,CAAC,UAAe;AAE9B,MAAIA,EAAAA,MAAM,KAAK;AAAU,WAAA;AACrB,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAEjC,SAAO,CAAC,KAAK;AACf;AAkBA,MAAM,cAAc,OAClB,UACA,KACA,cAAc,UACQ;AACtB,MAAI,WAAqB;AAEnB,QAAA,YAAY,CAAC,UAAe;AAEhC,QAAI,aAAa;AACR,aAAA;AAAA,IACT;AACA,WAAO,EAAE,KAAK,QAAQ,KAAK,EAAE;AAAA,EAAA;AAI3B,MAAAA,EAAAA,MAAM,QAAQ,GAAG;AACnB,WAAO,SAAS,QAAQ;AAAA,EAC1B;AAGI,MAAA,MAAM,QAAQ,QAAQ,GAAG;AACpB,WAAAC,YAAA,MACJ,IAAI,UAAU,CAAC,MAAgB,YAAY,UAAU,GAAG,IAAI,CAAC,EAC7D,KAAK,CAAC,WAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,EACnD,KAAK,SAAS;AAAA,EACnB;AAGI,MAAAC,EAAAA,SAAS,QAAQ,GAAG;AAElB,QAAA,QAAQ,YAAY,gBAAgB,UAAU;AAC1C,YAAA,SAAS,MAAM,SAAS,QAAQ;AACtC,aAAO,UAAU,MAAM;AAAA,IACzB;AAGI,QAAA,CAAC,SAAS,OAAO,CAAC,SAAS,cAAc,CAAC,SAAS,SAAS;AAC9D,aAAO,SAAS,QAAQ;AAAA,IAC1B;AAGA,QAAI,SAAS,KAAK;AAChB,YAAM,MAAW,MAAM,YAAY,UAAU,SAAS,KAAK,IAAI;AAC/D,iBAAW,EAAE,GAAG,UAAU,KAAK,QAAQ,GAAG;IAC5C;AAGA,QAAI,SAAS,YAAY;AACvB,YAAM,aAAkB,MAAM,YAAY,UAAU,SAAS,YAAY,IAAI;AAC7E,iBAAW,EAAE,GAAG,UAAU,YAAY,QAAQ,UAAU;IAC1D;AAGA,QAAI,SAAS,SAAS;AAEpB,YAAM,UAAe,MAAM,YAAY,UAAU,SAAS,SAAS,IAAI;AACvE,iBAAW,EAAE,GAAG,UAAU,SAAS,QAAQ,OAAO;IACpD;AAEO,WAAA;AAAA,EACT;AAGI,MAAA,UAAU,QAAQ,GAAG;AACvB,UAAM,SAAS,MAAM,SAAS,EAAE,IAAI,SAAU,CAAA;AAC9C,WAAO,UAAU,MAAM;AAAA,EACzB;AAEI,MAAA,OAAO,aAAa,UAAU;AAChC,UAAM,SAAS,MAAM,SAAS,EAAE,YAAY,SAAU,CAAA;AACtD,WAAO,UAAU,MAAM;AAAA,EACzB;AAGA,SAAO,SAAS,QAAQ;AAC1B;AAOA,MAAM,0BAA0B,OAC9B,SACA,SACA,SACG;AACI,SAAAC,YAAA;AAAA,IACL,OAAOC,UAAS,UAAU;AACpBA,UAAAA,SAAQ,UAAU,SAAS,YAAY;AACzC;AAAA,MACF;AAGIA,UAAAA,SAAQ,UAAU,iBAAiB,OAAO;AAC5C;AAAA,MACF;AAGM,YAAA,SAASA,SAAQ,UAAU;AACjC,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEO,aAAA,QAAQA,UAAS,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAEM,MAAA,qBAAqBC,QAAM,WAAW;AACtC,MAAA,iCAAiCA,QAAM,uBAAuB;;;"}
1
+ {"version":3,"file":"map-relation.js","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"sourcesContent":["/* eslint-disable node/no-callback-literal */\nimport { isObject, curry, isNil } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { traverseEntity, async } from '@strapi/utils';\n\nimport { Relation } from './types';\n\nconst isNumeric = (value: any): value is number => {\n if (Array.isArray(value)) return false; // Handle [1, 'docId'] case\n const parsed = parseInt(value, 10);\n return !Number.isNaN(parsed);\n};\n\nconst toArray = (value: any) => {\n // Keep value as it is if it's a nullish value\n if (isNil(value)) return value;\n if (Array.isArray(value)) return value;\n\n return [value];\n};\n\n/**\n * There are multiple ways to create Strapi relations.\n * This is a utility to traverse and transform relation data\n *\n *\n * For consistency and ease of use, the response will always be an object with the following shape:\n * { set: [{...}], connect: [{...}], disconnect: [{...}] }\n *\n * @example\n * transformRelationData({\n * onLongHand: (relation) => {\n * // Change the id of the relation\n * return { id: 'other' };\n * },\n * }, relation)\n */\nconst mapRelation = async (\n callback: (relation: any) => any,\n rel: Relation,\n isRecursive = false\n): Promise<Relation> => {\n let relation: Relation = rel;\n\n const wrapInSet = (value: any) => {\n // Ignore wrapping if it's a recursive call\n if (isRecursive) {\n return value;\n }\n return { set: toArray(value) };\n };\n\n // undefined | null\n if (isNil(relation)) {\n return callback(relation);\n }\n\n // LongHand[] | ShortHand[]\n if (Array.isArray(relation)) {\n return async\n .map(relation, (r: Relation) => mapRelation(callback, r, true))\n .then((result: any) => result.flat().filter(Boolean))\n .then(wrapInSet);\n }\n\n // LongHand\n if (isObject(relation)) {\n // { id: 1 } || { documentId: 1 }\n if ('id' in relation || 'documentId' in relation) {\n const result = await callback(relation);\n return wrapInSet(result);\n }\n\n // If not connecting anything, return default visitor\n if (!relation.set && !relation.disconnect && !relation.connect) {\n return callback(relation);\n }\n\n // { set }\n if (relation.set) {\n const set: any = await mapRelation(callback, relation.set, true);\n relation = { ...relation, set: toArray(set) };\n }\n\n // { disconnect}\n if (relation.disconnect) {\n const disconnect: any = await mapRelation(callback, relation.disconnect, true);\n relation = { ...relation, disconnect: toArray(disconnect) };\n }\n\n // { connect }\n if (relation.connect) {\n // Transform the relation to connect\n const connect: any = await mapRelation(callback, relation.connect, true);\n relation = { ...relation, connect: toArray(connect) };\n }\n\n return relation;\n }\n\n // ShortHand\n if (isNumeric(relation)) {\n const result = await callback({ id: relation });\n return wrapInSet(result);\n }\n\n if (typeof relation === 'string') {\n const result = await callback({ documentId: relation });\n return wrapInSet(result);\n }\n\n // Anything else\n return callback(relation);\n};\n\ntype TraverseEntity = Parameters<typeof traverseEntity>;\n\n/**\n * Utility function, same as `traverseEntity` but only for relations.\n */\nconst traverseEntityRelations = async (\n visitor: TraverseEntity[0],\n options: TraverseEntity[1],\n data: TraverseEntity[2]\n) => {\n return traverseEntity(\n async (options, utils) => {\n const { attribute } = options;\n\n if (!attribute) {\n return;\n }\n\n if (attribute.type !== 'relation') {\n return;\n }\n\n // TODO: Handle join columns\n if (attribute.useJoinTable === false) {\n return;\n }\n\n // TODO: Handle morph relations (they have multiple targets)\n const target = attribute.target as UID.Schema | undefined;\n if (!target) {\n return;\n }\n\n return visitor(options, utils);\n },\n options,\n data\n );\n};\n\nconst mapRelationCurried = curry(mapRelation);\nconst traverseEntityRelationsCurried = curry(traverseEntityRelations);\n\nexport {\n mapRelationCurried as mapRelation,\n traverseEntityRelationsCurried as traverseEntityRelations,\n};\n"],"names":["isNil","async","isObject","traverseEntity","options","curry"],"mappings":";;;;AAQA,MAAM,YAAY,CAAC,UAAgC;AAC7C,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAC3B,QAAA,SAAS,SAAS,OAAO,EAAE;AAC1B,SAAA,CAAC,OAAO,MAAM,MAAM;AAC7B;AAEA,MAAM,UAAU,CAAC,UAAe;AAE9B,MAAIA,GAAAA,MAAM,KAAK;AAAU,WAAA;AACrB,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAEjC,SAAO,CAAC,KAAK;AACf;AAkBA,MAAM,cAAc,OAClB,UACA,KACA,cAAc,UACQ;AACtB,MAAI,WAAqB;AAEnB,QAAA,YAAY,CAAC,UAAe;AAEhC,QAAI,aAAa;AACR,aAAA;AAAA,IACT;AACA,WAAO,EAAE,KAAK,QAAQ,KAAK,EAAE;AAAA,EAAA;AAI3B,MAAAA,GAAAA,MAAM,QAAQ,GAAG;AACnB,WAAO,SAAS,QAAQ;AAAA,EAC1B;AAGI,MAAA,MAAM,QAAQ,QAAQ,GAAG;AACpB,WAAAC,YAAA,MACJ,IAAI,UAAU,CAAC,MAAgB,YAAY,UAAU,GAAG,IAAI,CAAC,EAC7D,KAAK,CAAC,WAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,EACnD,KAAK,SAAS;AAAA,EACnB;AAGI,MAAAC,GAAAA,SAAS,QAAQ,GAAG;AAElB,QAAA,QAAQ,YAAY,gBAAgB,UAAU;AAC1C,YAAA,SAAS,MAAM,SAAS,QAAQ;AACtC,aAAO,UAAU,MAAM;AAAA,IACzB;AAGI,QAAA,CAAC,SAAS,OAAO,CAAC,SAAS,cAAc,CAAC,SAAS,SAAS;AAC9D,aAAO,SAAS,QAAQ;AAAA,IAC1B;AAGA,QAAI,SAAS,KAAK;AAChB,YAAM,MAAW,MAAM,YAAY,UAAU,SAAS,KAAK,IAAI;AAC/D,iBAAW,EAAE,GAAG,UAAU,KAAK,QAAQ,GAAG;IAC5C;AAGA,QAAI,SAAS,YAAY;AACvB,YAAM,aAAkB,MAAM,YAAY,UAAU,SAAS,YAAY,IAAI;AAC7E,iBAAW,EAAE,GAAG,UAAU,YAAY,QAAQ,UAAU;IAC1D;AAGA,QAAI,SAAS,SAAS;AAEpB,YAAM,UAAe,MAAM,YAAY,UAAU,SAAS,SAAS,IAAI;AACvE,iBAAW,EAAE,GAAG,UAAU,SAAS,QAAQ,OAAO;IACpD;AAEO,WAAA;AAAA,EACT;AAGI,MAAA,UAAU,QAAQ,GAAG;AACvB,UAAM,SAAS,MAAM,SAAS,EAAE,IAAI,SAAU,CAAA;AAC9C,WAAO,UAAU,MAAM;AAAA,EACzB;AAEI,MAAA,OAAO,aAAa,UAAU;AAChC,UAAM,SAAS,MAAM,SAAS,EAAE,YAAY,SAAU,CAAA;AACtD,WAAO,UAAU,MAAM;AAAA,EACzB;AAGA,SAAO,SAAS,QAAQ;AAC1B;AAOA,MAAM,0BAA0B,OAC9B,SACA,SACA,SACG;AACI,SAAAC,YAAA;AAAA,IACL,OAAOC,UAAS,UAAU;AAClB,YAAA,EAAE,UAAcA,IAAAA;AAEtB,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAEI,UAAA,UAAU,SAAS,YAAY;AACjC;AAAA,MACF;AAGI,UAAA,UAAU,iBAAiB,OAAO;AACpC;AAAA,MACF;AAGA,YAAM,SAAS,UAAU;AACzB,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEO,aAAA,QAAQA,UAAS,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAEM,MAAA,qBAAqBC,SAAM,WAAW;AACtC,MAAA,iCAAiCA,SAAM,uBAAuB;;;"}
@@ -62,13 +62,17 @@ const mapRelation = async (callback, rel, isRecursive = false) => {
62
62
  const traverseEntityRelations = async (visitor, options, data) => {
63
63
  return traverseEntity(
64
64
  async (options2, utils) => {
65
- if (options2.attribute.type !== "relation") {
65
+ const { attribute } = options2;
66
+ if (!attribute) {
66
67
  return;
67
68
  }
68
- if (options2.attribute.useJoinTable === false) {
69
+ if (attribute.type !== "relation") {
69
70
  return;
70
71
  }
71
- const target = options2.attribute.target;
72
+ if (attribute.useJoinTable === false) {
73
+ return;
74
+ }
75
+ const target = attribute.target;
72
76
  if (!target) {
73
77
  return;
74
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"map-relation.mjs","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"sourcesContent":["/* eslint-disable node/no-callback-literal */\nimport { isObject, curry, isNil } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { traverseEntity, async } from '@strapi/utils';\n\nimport { Relation } from './types';\n\nconst isNumeric = (value: any): value is number => {\n if (Array.isArray(value)) return false; // Handle [1, 'docId'] case\n const parsed = parseInt(value, 10);\n return !Number.isNaN(parsed);\n};\n\nconst toArray = (value: any) => {\n // Keep value as it is if it's a nullish value\n if (isNil(value)) return value;\n if (Array.isArray(value)) return value;\n\n return [value];\n};\n\n/**\n * There are multiple ways to create Strapi relations.\n * This is a utility to traverse and transform relation data\n *\n *\n * For consistency and ease of use, the response will always be an object with the following shape:\n * { set: [{...}], connect: [{...}], disconnect: [{...}] }\n *\n * @example\n * transformRelationData({\n * onLongHand: (relation) => {\n * // Change the id of the relation\n * return { id: 'other' };\n * },\n * }, relation)\n */\nconst mapRelation = async (\n callback: (relation: any) => any,\n rel: Relation,\n isRecursive = false\n): Promise<Relation> => {\n let relation: Relation = rel;\n\n const wrapInSet = (value: any) => {\n // Ignore wrapping if it's a recursive call\n if (isRecursive) {\n return value;\n }\n return { set: toArray(value) };\n };\n\n // undefined | null\n if (isNil(relation)) {\n return callback(relation);\n }\n\n // LongHand[] | ShortHand[]\n if (Array.isArray(relation)) {\n return async\n .map(relation, (r: Relation) => mapRelation(callback, r, true))\n .then((result: any) => result.flat().filter(Boolean))\n .then(wrapInSet);\n }\n\n // LongHand\n if (isObject(relation)) {\n // { id: 1 } || { documentId: 1 }\n if ('id' in relation || 'documentId' in relation) {\n const result = await callback(relation);\n return wrapInSet(result);\n }\n\n // If not connecting anything, return default visitor\n if (!relation.set && !relation.disconnect && !relation.connect) {\n return callback(relation);\n }\n\n // { set }\n if (relation.set) {\n const set: any = await mapRelation(callback, relation.set, true);\n relation = { ...relation, set: toArray(set) };\n }\n\n // { disconnect}\n if (relation.disconnect) {\n const disconnect: any = await mapRelation(callback, relation.disconnect, true);\n relation = { ...relation, disconnect: toArray(disconnect) };\n }\n\n // { connect }\n if (relation.connect) {\n // Transform the relation to connect\n const connect: any = await mapRelation(callback, relation.connect, true);\n relation = { ...relation, connect: toArray(connect) };\n }\n\n return relation;\n }\n\n // ShortHand\n if (isNumeric(relation)) {\n const result = await callback({ id: relation });\n return wrapInSet(result);\n }\n\n if (typeof relation === 'string') {\n const result = await callback({ documentId: relation });\n return wrapInSet(result);\n }\n\n // Anything else\n return callback(relation);\n};\n\ntype TraverseEntity = Parameters<typeof traverseEntity>;\n\n/**\n * Utility function, same as `traverseEntity` but only for relations.\n */\nconst traverseEntityRelations = async (\n visitor: TraverseEntity[0],\n options: TraverseEntity[1],\n data: TraverseEntity[2]\n) => {\n return traverseEntity(\n async (options, utils) => {\n if (options.attribute.type !== 'relation') {\n return;\n }\n\n // TODO: Handle join columns\n if (options.attribute.useJoinTable === false) {\n return;\n }\n\n // TODO: Handle morph relations (they have multiple targets)\n const target = options.attribute.target as UID.Schema | undefined;\n if (!target) {\n return;\n }\n\n return visitor(options, utils);\n },\n options,\n data\n );\n};\n\nconst mapRelationCurried = curry(mapRelation);\nconst traverseEntityRelationsCurried = curry(traverseEntityRelations);\n\nexport {\n mapRelationCurried as mapRelation,\n traverseEntityRelationsCurried as traverseEntityRelations,\n};\n"],"names":["options"],"mappings":";;AAQA,MAAM,YAAY,CAAC,UAAgC;AAC7C,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAC3B,QAAA,SAAS,SAAS,OAAO,EAAE;AAC1B,SAAA,CAAC,OAAO,MAAM,MAAM;AAC7B;AAEA,MAAM,UAAU,CAAC,UAAe;AAE9B,MAAI,MAAM,KAAK;AAAU,WAAA;AACrB,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAEjC,SAAO,CAAC,KAAK;AACf;AAkBA,MAAM,cAAc,OAClB,UACA,KACA,cAAc,UACQ;AACtB,MAAI,WAAqB;AAEnB,QAAA,YAAY,CAAC,UAAe;AAEhC,QAAI,aAAa;AACR,aAAA;AAAA,IACT;AACA,WAAO,EAAE,KAAK,QAAQ,KAAK,EAAE;AAAA,EAAA;AAI3B,MAAA,MAAM,QAAQ,GAAG;AACnB,WAAO,SAAS,QAAQ;AAAA,EAC1B;AAGI,MAAA,MAAM,QAAQ,QAAQ,GAAG;AACpB,WAAA,MACJ,IAAI,UAAU,CAAC,MAAgB,YAAY,UAAU,GAAG,IAAI,CAAC,EAC7D,KAAK,CAAC,WAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,EACnD,KAAK,SAAS;AAAA,EACnB;AAGI,MAAA,SAAS,QAAQ,GAAG;AAElB,QAAA,QAAQ,YAAY,gBAAgB,UAAU;AAC1C,YAAA,SAAS,MAAM,SAAS,QAAQ;AACtC,aAAO,UAAU,MAAM;AAAA,IACzB;AAGI,QAAA,CAAC,SAAS,OAAO,CAAC,SAAS,cAAc,CAAC,SAAS,SAAS;AAC9D,aAAO,SAAS,QAAQ;AAAA,IAC1B;AAGA,QAAI,SAAS,KAAK;AAChB,YAAM,MAAW,MAAM,YAAY,UAAU,SAAS,KAAK,IAAI;AAC/D,iBAAW,EAAE,GAAG,UAAU,KAAK,QAAQ,GAAG;IAC5C;AAGA,QAAI,SAAS,YAAY;AACvB,YAAM,aAAkB,MAAM,YAAY,UAAU,SAAS,YAAY,IAAI;AAC7E,iBAAW,EAAE,GAAG,UAAU,YAAY,QAAQ,UAAU;IAC1D;AAGA,QAAI,SAAS,SAAS;AAEpB,YAAM,UAAe,MAAM,YAAY,UAAU,SAAS,SAAS,IAAI;AACvE,iBAAW,EAAE,GAAG,UAAU,SAAS,QAAQ,OAAO;IACpD;AAEO,WAAA;AAAA,EACT;AAGI,MAAA,UAAU,QAAQ,GAAG;AACvB,UAAM,SAAS,MAAM,SAAS,EAAE,IAAI,SAAU,CAAA;AAC9C,WAAO,UAAU,MAAM;AAAA,EACzB;AAEI,MAAA,OAAO,aAAa,UAAU;AAChC,UAAM,SAAS,MAAM,SAAS,EAAE,YAAY,SAAU,CAAA;AACtD,WAAO,UAAU,MAAM;AAAA,EACzB;AAGA,SAAO,SAAS,QAAQ;AAC1B;AAOA,MAAM,0BAA0B,OAC9B,SACA,SACA,SACG;AACI,SAAA;AAAA,IACL,OAAOA,UAAS,UAAU;AACpBA,UAAAA,SAAQ,UAAU,SAAS,YAAY;AACzC;AAAA,MACF;AAGIA,UAAAA,SAAQ,UAAU,iBAAiB,OAAO;AAC5C;AAAA,MACF;AAGM,YAAA,SAASA,SAAQ,UAAU;AACjC,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEO,aAAA,QAAQA,UAAS,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAEM,MAAA,qBAAqB,MAAM,WAAW;AACtC,MAAA,iCAAiC,MAAM,uBAAuB;"}
1
+ {"version":3,"file":"map-relation.mjs","sources":["../../../../../../src/services/document-service/transform/relations/utils/map-relation.ts"],"sourcesContent":["/* eslint-disable node/no-callback-literal */\nimport { isObject, curry, isNil } from 'lodash/fp';\n\nimport type { UID } from '@strapi/types';\nimport { traverseEntity, async } from '@strapi/utils';\n\nimport { Relation } from './types';\n\nconst isNumeric = (value: any): value is number => {\n if (Array.isArray(value)) return false; // Handle [1, 'docId'] case\n const parsed = parseInt(value, 10);\n return !Number.isNaN(parsed);\n};\n\nconst toArray = (value: any) => {\n // Keep value as it is if it's a nullish value\n if (isNil(value)) return value;\n if (Array.isArray(value)) return value;\n\n return [value];\n};\n\n/**\n * There are multiple ways to create Strapi relations.\n * This is a utility to traverse and transform relation data\n *\n *\n * For consistency and ease of use, the response will always be an object with the following shape:\n * { set: [{...}], connect: [{...}], disconnect: [{...}] }\n *\n * @example\n * transformRelationData({\n * onLongHand: (relation) => {\n * // Change the id of the relation\n * return { id: 'other' };\n * },\n * }, relation)\n */\nconst mapRelation = async (\n callback: (relation: any) => any,\n rel: Relation,\n isRecursive = false\n): Promise<Relation> => {\n let relation: Relation = rel;\n\n const wrapInSet = (value: any) => {\n // Ignore wrapping if it's a recursive call\n if (isRecursive) {\n return value;\n }\n return { set: toArray(value) };\n };\n\n // undefined | null\n if (isNil(relation)) {\n return callback(relation);\n }\n\n // LongHand[] | ShortHand[]\n if (Array.isArray(relation)) {\n return async\n .map(relation, (r: Relation) => mapRelation(callback, r, true))\n .then((result: any) => result.flat().filter(Boolean))\n .then(wrapInSet);\n }\n\n // LongHand\n if (isObject(relation)) {\n // { id: 1 } || { documentId: 1 }\n if ('id' in relation || 'documentId' in relation) {\n const result = await callback(relation);\n return wrapInSet(result);\n }\n\n // If not connecting anything, return default visitor\n if (!relation.set && !relation.disconnect && !relation.connect) {\n return callback(relation);\n }\n\n // { set }\n if (relation.set) {\n const set: any = await mapRelation(callback, relation.set, true);\n relation = { ...relation, set: toArray(set) };\n }\n\n // { disconnect}\n if (relation.disconnect) {\n const disconnect: any = await mapRelation(callback, relation.disconnect, true);\n relation = { ...relation, disconnect: toArray(disconnect) };\n }\n\n // { connect }\n if (relation.connect) {\n // Transform the relation to connect\n const connect: any = await mapRelation(callback, relation.connect, true);\n relation = { ...relation, connect: toArray(connect) };\n }\n\n return relation;\n }\n\n // ShortHand\n if (isNumeric(relation)) {\n const result = await callback({ id: relation });\n return wrapInSet(result);\n }\n\n if (typeof relation === 'string') {\n const result = await callback({ documentId: relation });\n return wrapInSet(result);\n }\n\n // Anything else\n return callback(relation);\n};\n\ntype TraverseEntity = Parameters<typeof traverseEntity>;\n\n/**\n * Utility function, same as `traverseEntity` but only for relations.\n */\nconst traverseEntityRelations = async (\n visitor: TraverseEntity[0],\n options: TraverseEntity[1],\n data: TraverseEntity[2]\n) => {\n return traverseEntity(\n async (options, utils) => {\n const { attribute } = options;\n\n if (!attribute) {\n return;\n }\n\n if (attribute.type !== 'relation') {\n return;\n }\n\n // TODO: Handle join columns\n if (attribute.useJoinTable === false) {\n return;\n }\n\n // TODO: Handle morph relations (they have multiple targets)\n const target = attribute.target as UID.Schema | undefined;\n if (!target) {\n return;\n }\n\n return visitor(options, utils);\n },\n options,\n data\n );\n};\n\nconst mapRelationCurried = curry(mapRelation);\nconst traverseEntityRelationsCurried = curry(traverseEntityRelations);\n\nexport {\n mapRelationCurried as mapRelation,\n traverseEntityRelationsCurried as traverseEntityRelations,\n};\n"],"names":["options"],"mappings":";;AAQA,MAAM,YAAY,CAAC,UAAgC;AAC7C,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAC3B,QAAA,SAAS,SAAS,OAAO,EAAE;AAC1B,SAAA,CAAC,OAAO,MAAM,MAAM;AAC7B;AAEA,MAAM,UAAU,CAAC,UAAe;AAE9B,MAAI,MAAM,KAAK;AAAU,WAAA;AACrB,MAAA,MAAM,QAAQ,KAAK;AAAU,WAAA;AAEjC,SAAO,CAAC,KAAK;AACf;AAkBA,MAAM,cAAc,OAClB,UACA,KACA,cAAc,UACQ;AACtB,MAAI,WAAqB;AAEnB,QAAA,YAAY,CAAC,UAAe;AAEhC,QAAI,aAAa;AACR,aAAA;AAAA,IACT;AACA,WAAO,EAAE,KAAK,QAAQ,KAAK,EAAE;AAAA,EAAA;AAI3B,MAAA,MAAM,QAAQ,GAAG;AACnB,WAAO,SAAS,QAAQ;AAAA,EAC1B;AAGI,MAAA,MAAM,QAAQ,QAAQ,GAAG;AACpB,WAAA,MACJ,IAAI,UAAU,CAAC,MAAgB,YAAY,UAAU,GAAG,IAAI,CAAC,EAC7D,KAAK,CAAC,WAAgB,OAAO,OAAO,OAAO,OAAO,CAAC,EACnD,KAAK,SAAS;AAAA,EACnB;AAGI,MAAA,SAAS,QAAQ,GAAG;AAElB,QAAA,QAAQ,YAAY,gBAAgB,UAAU;AAC1C,YAAA,SAAS,MAAM,SAAS,QAAQ;AACtC,aAAO,UAAU,MAAM;AAAA,IACzB;AAGI,QAAA,CAAC,SAAS,OAAO,CAAC,SAAS,cAAc,CAAC,SAAS,SAAS;AAC9D,aAAO,SAAS,QAAQ;AAAA,IAC1B;AAGA,QAAI,SAAS,KAAK;AAChB,YAAM,MAAW,MAAM,YAAY,UAAU,SAAS,KAAK,IAAI;AAC/D,iBAAW,EAAE,GAAG,UAAU,KAAK,QAAQ,GAAG;IAC5C;AAGA,QAAI,SAAS,YAAY;AACvB,YAAM,aAAkB,MAAM,YAAY,UAAU,SAAS,YAAY,IAAI;AAC7E,iBAAW,EAAE,GAAG,UAAU,YAAY,QAAQ,UAAU;IAC1D;AAGA,QAAI,SAAS,SAAS;AAEpB,YAAM,UAAe,MAAM,YAAY,UAAU,SAAS,SAAS,IAAI;AACvE,iBAAW,EAAE,GAAG,UAAU,SAAS,QAAQ,OAAO;IACpD;AAEO,WAAA;AAAA,EACT;AAGI,MAAA,UAAU,QAAQ,GAAG;AACvB,UAAM,SAAS,MAAM,SAAS,EAAE,IAAI,SAAU,CAAA;AAC9C,WAAO,UAAU,MAAM;AAAA,EACzB;AAEI,MAAA,OAAO,aAAa,UAAU;AAChC,UAAM,SAAS,MAAM,SAAS,EAAE,YAAY,SAAU,CAAA;AACtD,WAAO,UAAU,MAAM;AAAA,EACzB;AAGA,SAAO,SAAS,QAAQ;AAC1B;AAOA,MAAM,0BAA0B,OAC9B,SACA,SACA,SACG;AACI,SAAA;AAAA,IACL,OAAOA,UAAS,UAAU;AAClB,YAAA,EAAE,UAAcA,IAAAA;AAEtB,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAEI,UAAA,UAAU,SAAS,YAAY;AACjC;AAAA,MACF;AAGI,UAAA,UAAU,iBAAiB,OAAO;AACpC;AAAA,MACF;AAGA,YAAM,SAAS,UAAU;AACzB,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AAEO,aAAA,QAAQA,UAAS,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAEM,MAAA,qBAAqB,MAAM,WAAW;AACtC,MAAA,iCAAiC,MAAM,uBAAuB;"}
@@ -1 +1 @@
1
- {"version":3,"file":"populate.d.ts","sourceRoot":"","sources":["../../../../src/services/document-service/utils/populate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGpC,UAAU,OAAO;IACf;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAGD,eAAO,MAAM,eAAe,QAAS,IAAI,MAAM,SAAQ,OAAO,QA8C7D,CAAC"}
1
+ {"version":3,"file":"populate.d.ts","sourceRoot":"","sources":["../../../../src/services/document-service/utils/populate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGpC,UAAU,OAAO;IACf;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAGD,eAAO,MAAM,eAAe,QAAS,IAAI,MAAM,SAAQ,OAAO,QAoD7D,CAAC"}
@@ -7,6 +7,10 @@ const getDeepPopulate = (uid, opts = {}) => {
7
7
  return attributes.reduce((acc, [attributeName, attribute]) => {
8
8
  switch (attribute.type) {
9
9
  case "relation": {
10
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
11
+ if (isMorphRelation) {
12
+ break;
13
+ }
10
14
  const isVisible = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
11
15
  if (isVisible) {
12
16
  acc[attributeName] = { select: opts.relationalFields };
@@ -1 +1 @@
1
- {"version":3,"file":"populate.js","sources":["../../../../src/services/document-service/utils/populate.ts"],"sourcesContent":["import { UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\ninterface Options {\n /**\n * Fields to select when populating relations\n */\n relationalFields?: string[];\n}\n\n// We want to build a populate object based on the schema\nexport const getDeepPopulate = (uid: UID.Schema, opts: Options = {}) => {\n const model = strapi.getModel(uid);\n const attributes = Object.entries(model.attributes);\n\n return attributes.reduce((acc: any, [attributeName, attribute]) => {\n switch (attribute.type) {\n case 'relation': {\n // TODO: Should this just be a plain list?\n // Ignore createdBy, updatedBy, ...\n const isVisible = contentTypes.isVisibleAttribute(model, attributeName);\n if (isVisible) {\n acc[attributeName] = { select: opts.relationalFields };\n }\n break;\n }\n\n case 'media': {\n acc[attributeName] = { select: ['id'] };\n break;\n }\n\n case 'component': {\n const populate = getDeepPopulate(attribute.component, opts);\n acc[attributeName] = { populate };\n break;\n }\n\n case 'dynamiczone': {\n // Use fragments to populate the dynamic zone components\n const populatedComponents = (attribute.components || []).reduce(\n (acc: any, componentUID: UID.Component) => {\n acc[componentUID] = { populate: getDeepPopulate(componentUID, opts) };\n return acc;\n },\n {}\n );\n\n acc[attributeName] = { on: populatedComponents };\n break;\n }\n default:\n break;\n }\n\n return acc;\n }, {});\n};\n"],"names":["contentTypes","acc"],"mappings":";;;AAWO,MAAM,kBAAkB,CAAC,KAAiB,OAAgB,OAAO;AAChE,QAAA,QAAQ,OAAO,SAAS,GAAG;AACjC,QAAM,aAAa,OAAO,QAAQ,MAAM,UAAU;AAElD,SAAO,WAAW,OAAO,CAAC,KAAU,CAAC,eAAe,SAAS,MAAM;AACjE,YAAQ,UAAU,MAAM;AAAA,MACtB,KAAK,YAAY;AAGf,cAAM,YAAYA,YAAA,aAAa,mBAAmB,OAAO,aAAa;AACtE,YAAI,WAAW;AACb,cAAI,aAAa,IAAI,EAAE,QAAQ,KAAK,iBAAiB;AAAA,QACvD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,SAAS;AACZ,YAAI,aAAa,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;AACtC;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,WAAW,gBAAgB,UAAU,WAAW,IAAI;AACtD,YAAA,aAAa,IAAI,EAAE;AACvB;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,cAAM,uBAAuB,UAAU,cAAc,CAAI,GAAA;AAAA,UACvD,CAACC,MAAU,iBAAgC;AACzCA,iBAAI,YAAY,IAAI,EAAE,UAAU,gBAAgB,cAAc,IAAI;AAC3DA,mBAAAA;AAAAA,UACT;AAAA,UACA,CAAC;AAAA,QAAA;AAGH,YAAI,aAAa,IAAI,EAAE,IAAI,oBAAoB;AAC/C;AAAA,MACF;AAAA,IAGF;AAEO,WAAA;AAAA,EACT,GAAG,CAAE,CAAA;AACP;;"}
1
+ {"version":3,"file":"populate.js","sources":["../../../../src/services/document-service/utils/populate.ts"],"sourcesContent":["import { UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\ninterface Options {\n /**\n * Fields to select when populating relations\n */\n relationalFields?: string[];\n}\n\n// We want to build a populate object based on the schema\nexport const getDeepPopulate = (uid: UID.Schema, opts: Options = {}) => {\n const model = strapi.getModel(uid);\n const attributes = Object.entries(model.attributes);\n\n return attributes.reduce((acc: any, [attributeName, attribute]) => {\n switch (attribute.type) {\n case 'relation': {\n // TODO: Support polymorphic relations\n const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');\n if (isMorphRelation) {\n break;\n }\n\n // TODO: Should this just be a plain list?\n // Ignore createdBy, updatedBy, ...\n const isVisible = contentTypes.isVisibleAttribute(model, attributeName);\n if (isVisible) {\n acc[attributeName] = { select: opts.relationalFields };\n }\n break;\n }\n\n case 'media': {\n acc[attributeName] = { select: ['id'] };\n break;\n }\n\n case 'component': {\n const populate = getDeepPopulate(attribute.component, opts);\n acc[attributeName] = { populate };\n break;\n }\n\n case 'dynamiczone': {\n // Use fragments to populate the dynamic zone components\n const populatedComponents = (attribute.components || []).reduce(\n (acc: any, componentUID: UID.Component) => {\n acc[componentUID] = { populate: getDeepPopulate(componentUID, opts) };\n return acc;\n },\n {}\n );\n\n acc[attributeName] = { on: populatedComponents };\n break;\n }\n default:\n break;\n }\n\n return acc;\n }, {});\n};\n"],"names":["contentTypes","acc"],"mappings":";;;AAWO,MAAM,kBAAkB,CAAC,KAAiB,OAAgB,OAAO;AAChE,QAAA,QAAQ,OAAO,SAAS,GAAG;AACjC,QAAM,aAAa,OAAO,QAAQ,MAAM,UAAU;AAElD,SAAO,WAAW,OAAO,CAAC,KAAU,CAAC,eAAe,SAAS,MAAM;AACjE,YAAQ,UAAU,MAAM;AAAA,MACtB,KAAK,YAAY;AAEf,cAAM,kBAAkB,UAAU,SAAS,YAAY,EAAE,WAAW,OAAO;AAC3E,YAAI,iBAAiB;AACnB;AAAA,QACF;AAIA,cAAM,YAAYA,YAAA,aAAa,mBAAmB,OAAO,aAAa;AACtE,YAAI,WAAW;AACb,cAAI,aAAa,IAAI,EAAE,QAAQ,KAAK,iBAAiB;AAAA,QACvD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,SAAS;AACZ,YAAI,aAAa,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;AACtC;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,WAAW,gBAAgB,UAAU,WAAW,IAAI;AACtD,YAAA,aAAa,IAAI,EAAE;AACvB;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,cAAM,uBAAuB,UAAU,cAAc,CAAI,GAAA;AAAA,UACvD,CAACC,MAAU,iBAAgC;AACzCA,iBAAI,YAAY,IAAI,EAAE,UAAU,gBAAgB,cAAc,IAAI;AAC3DA,mBAAAA;AAAAA,UACT;AAAA,UACA,CAAC;AAAA,QAAA;AAGH,YAAI,aAAa,IAAI,EAAE,IAAI,oBAAoB;AAC/C;AAAA,MACF;AAAA,IAGF;AAEO,WAAA;AAAA,EACT,GAAG,CAAE,CAAA;AACP;;"}
@@ -5,6 +5,10 @@ const getDeepPopulate = (uid, opts = {}) => {
5
5
  return attributes.reduce((acc, [attributeName, attribute]) => {
6
6
  switch (attribute.type) {
7
7
  case "relation": {
8
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
9
+ if (isMorphRelation) {
10
+ break;
11
+ }
8
12
  const isVisible = contentTypes.isVisibleAttribute(model, attributeName);
9
13
  if (isVisible) {
10
14
  acc[attributeName] = { select: opts.relationalFields };
@@ -1 +1 @@
1
- {"version":3,"file":"populate.mjs","sources":["../../../../src/services/document-service/utils/populate.ts"],"sourcesContent":["import { UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\ninterface Options {\n /**\n * Fields to select when populating relations\n */\n relationalFields?: string[];\n}\n\n// We want to build a populate object based on the schema\nexport const getDeepPopulate = (uid: UID.Schema, opts: Options = {}) => {\n const model = strapi.getModel(uid);\n const attributes = Object.entries(model.attributes);\n\n return attributes.reduce((acc: any, [attributeName, attribute]) => {\n switch (attribute.type) {\n case 'relation': {\n // TODO: Should this just be a plain list?\n // Ignore createdBy, updatedBy, ...\n const isVisible = contentTypes.isVisibleAttribute(model, attributeName);\n if (isVisible) {\n acc[attributeName] = { select: opts.relationalFields };\n }\n break;\n }\n\n case 'media': {\n acc[attributeName] = { select: ['id'] };\n break;\n }\n\n case 'component': {\n const populate = getDeepPopulate(attribute.component, opts);\n acc[attributeName] = { populate };\n break;\n }\n\n case 'dynamiczone': {\n // Use fragments to populate the dynamic zone components\n const populatedComponents = (attribute.components || []).reduce(\n (acc: any, componentUID: UID.Component) => {\n acc[componentUID] = { populate: getDeepPopulate(componentUID, opts) };\n return acc;\n },\n {}\n );\n\n acc[attributeName] = { on: populatedComponents };\n break;\n }\n default:\n break;\n }\n\n return acc;\n }, {});\n};\n"],"names":["acc"],"mappings":";AAWO,MAAM,kBAAkB,CAAC,KAAiB,OAAgB,OAAO;AAChE,QAAA,QAAQ,OAAO,SAAS,GAAG;AACjC,QAAM,aAAa,OAAO,QAAQ,MAAM,UAAU;AAElD,SAAO,WAAW,OAAO,CAAC,KAAU,CAAC,eAAe,SAAS,MAAM;AACjE,YAAQ,UAAU,MAAM;AAAA,MACtB,KAAK,YAAY;AAGf,cAAM,YAAY,aAAa,mBAAmB,OAAO,aAAa;AACtE,YAAI,WAAW;AACb,cAAI,aAAa,IAAI,EAAE,QAAQ,KAAK,iBAAiB;AAAA,QACvD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,SAAS;AACZ,YAAI,aAAa,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;AACtC;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,WAAW,gBAAgB,UAAU,WAAW,IAAI;AACtD,YAAA,aAAa,IAAI,EAAE;AACvB;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,cAAM,uBAAuB,UAAU,cAAc,CAAI,GAAA;AAAA,UACvD,CAACA,MAAU,iBAAgC;AACzCA,iBAAI,YAAY,IAAI,EAAE,UAAU,gBAAgB,cAAc,IAAI;AAC3DA,mBAAAA;AAAAA,UACT;AAAA,UACA,CAAC;AAAA,QAAA;AAGH,YAAI,aAAa,IAAI,EAAE,IAAI,oBAAoB;AAC/C;AAAA,MACF;AAAA,IAGF;AAEO,WAAA;AAAA,EACT,GAAG,CAAE,CAAA;AACP;"}
1
+ {"version":3,"file":"populate.mjs","sources":["../../../../src/services/document-service/utils/populate.ts"],"sourcesContent":["import { UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\ninterface Options {\n /**\n * Fields to select when populating relations\n */\n relationalFields?: string[];\n}\n\n// We want to build a populate object based on the schema\nexport const getDeepPopulate = (uid: UID.Schema, opts: Options = {}) => {\n const model = strapi.getModel(uid);\n const attributes = Object.entries(model.attributes);\n\n return attributes.reduce((acc: any, [attributeName, attribute]) => {\n switch (attribute.type) {\n case 'relation': {\n // TODO: Support polymorphic relations\n const isMorphRelation = attribute.relation.toLowerCase().startsWith('morph');\n if (isMorphRelation) {\n break;\n }\n\n // TODO: Should this just be a plain list?\n // Ignore createdBy, updatedBy, ...\n const isVisible = contentTypes.isVisibleAttribute(model, attributeName);\n if (isVisible) {\n acc[attributeName] = { select: opts.relationalFields };\n }\n break;\n }\n\n case 'media': {\n acc[attributeName] = { select: ['id'] };\n break;\n }\n\n case 'component': {\n const populate = getDeepPopulate(attribute.component, opts);\n acc[attributeName] = { populate };\n break;\n }\n\n case 'dynamiczone': {\n // Use fragments to populate the dynamic zone components\n const populatedComponents = (attribute.components || []).reduce(\n (acc: any, componentUID: UID.Component) => {\n acc[componentUID] = { populate: getDeepPopulate(componentUID, opts) };\n return acc;\n },\n {}\n );\n\n acc[attributeName] = { on: populatedComponents };\n break;\n }\n default:\n break;\n }\n\n return acc;\n }, {});\n};\n"],"names":["acc"],"mappings":";AAWO,MAAM,kBAAkB,CAAC,KAAiB,OAAgB,OAAO;AAChE,QAAA,QAAQ,OAAO,SAAS,GAAG;AACjC,QAAM,aAAa,OAAO,QAAQ,MAAM,UAAU;AAElD,SAAO,WAAW,OAAO,CAAC,KAAU,CAAC,eAAe,SAAS,MAAM;AACjE,YAAQ,UAAU,MAAM;AAAA,MACtB,KAAK,YAAY;AAEf,cAAM,kBAAkB,UAAU,SAAS,YAAY,EAAE,WAAW,OAAO;AAC3E,YAAI,iBAAiB;AACnB;AAAA,QACF;AAIA,cAAM,YAAY,aAAa,mBAAmB,OAAO,aAAa;AACtE,YAAI,WAAW;AACb,cAAI,aAAa,IAAI,EAAE,QAAQ,KAAK,iBAAiB;AAAA,QACvD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,SAAS;AACZ,YAAI,aAAa,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;AACtC;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,WAAW,gBAAgB,UAAU,WAAW,IAAI;AACtD,YAAA,aAAa,IAAI,EAAE;AACvB;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,cAAM,uBAAuB,UAAU,cAAc,CAAI,GAAA;AAAA,UACvD,CAACA,MAAU,iBAAgC;AACzCA,iBAAI,YAAY,IAAI,EAAE,UAAU,gBAAgB,cAAc,IAAI;AAC3DA,mBAAAA;AAAAA,UACT;AAAA,UACA,CAAC;AAAA,QAAA;AAGH,YAAI,aAAa,IAAI,EAAE,IAAI,oBAAoB;AAC/C;AAAA,MACF;AAAA,IAGF;AAEO,WAAA;AAAA,EACT,GAAG,CAAE,CAAA;AACP;"}
@@ -2,7 +2,20 @@
2
2
  * Entity validator
3
3
  * Module that will validate input data for entity creation or edition
4
4
  */
5
- import { Modules } from '@strapi/types';
5
+ import { Modules, Struct } from '@strapi/types';
6
+ export type ComponentContext = {
7
+ parentContent: {
8
+ model: Struct.Schema;
9
+ id?: number;
10
+ options?: ValidatorContext;
11
+ };
12
+ pathToComponent: string[];
13
+ repeatableData: Modules.EntityValidator.Entity[];
14
+ };
15
+ interface ValidatorContext {
16
+ isDraft?: boolean;
17
+ locale?: string | null;
18
+ }
6
19
  declare const entityValidator: Modules.EntityValidator.EntityValidator;
7
20
  export default entityValidator;
8
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/entity-validator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,OAAO,EAAuB,MAAM,eAAe,CAAC;AAmf7D,QAAA,MAAM,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,eAG9C,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/entity-validator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,OAAO,EAAO,MAAM,EAAU,MAAM,eAAe,CAAC;AAa7D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE;QAEb,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QAErB,EAAE,CAAC,EAAE,MAAM,CAAC;QAGZ,OAAO,CAAC,EAAE,gBAAgB,CAAC;KAC5B,CAAC;IAEF,eAAe,EAAE,MAAM,EAAE,CAAC;IAG1B,cAAc,EAAE,OAAO,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;CAClD,CAAC;AAWF,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA8hBD,QAAA,MAAM,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,eAG9C,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- const _$1 = require("lodash");
3
- const _ = require("lodash/fp");
2
+ const _ = require("lodash");
3
+ const fp = require("lodash/fp");
4
4
  const strapiUtils = require("@strapi/utils");
5
5
  const validators = require("./validators.js");
6
6
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
@@ -55,7 +55,11 @@ const addDefault = (createOrUpdate) => {
55
55
  };
56
56
  };
57
57
  const preventCast = (validator) => validator.transform((val, originalVal) => originalVal);
58
- const createComponentValidator = (createOrUpdate) => ({ attr, updatedAttribute }, { isDraft }) => {
58
+ const createComponentValidator = (createOrUpdate) => ({
59
+ attr,
60
+ updatedAttribute,
61
+ componentContext
62
+ }, { isDraft }) => {
59
63
  const model = strapi.getModel(attr.component);
60
64
  if (!model) {
61
65
  throw new Error("Validation failed: Model not found");
@@ -63,7 +67,10 @@ const createComponentValidator = (createOrUpdate) => ({ attr, updatedAttribute }
63
67
  if (attr?.repeatable) {
64
68
  let validator2 = yup.array().of(
65
69
  yup.lazy(
66
- (item) => createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }).notNull()
70
+ (item) => createModelValidator(createOrUpdate)(
71
+ { componentContext, model, data: item },
72
+ { isDraft }
73
+ ).notNull()
67
74
  )
68
75
  );
69
76
  validator2 = addRequiredValidation(createOrUpdate)(validator2, {
@@ -74,7 +81,11 @@ const createComponentValidator = (createOrUpdate) => ({ attr, updatedAttribute }
74
81
  return validator2;
75
82
  }
76
83
  let validator = createModelValidator(createOrUpdate)(
77
- { model, data: updatedAttribute.value },
84
+ {
85
+ model,
86
+ data: updatedAttribute.value,
87
+ componentContext
88
+ },
78
89
  { isDraft }
79
90
  );
80
91
  validator = addRequiredValidation(createOrUpdate)(validator, {
@@ -83,15 +94,20 @@ const createComponentValidator = (createOrUpdate) => ({ attr, updatedAttribute }
83
94
  });
84
95
  return validator;
85
96
  };
86
- const createDzValidator = (createOrUpdate) => ({ attr, updatedAttribute }, { isDraft }) => {
97
+ const createDzValidator = (createOrUpdate) => ({ attr, updatedAttribute, componentContext }, { isDraft }) => {
87
98
  let validator;
88
99
  validator = yup.array().of(
89
100
  yup.lazy((item) => {
90
- const model = strapi.getModel(_.prop("__component", item));
101
+ const model = strapi.getModel(fp.prop("__component", item));
91
102
  const schema = yup.object().shape({
92
103
  __component: yup.string().required().oneOf(Object.keys(strapi.components))
93
104
  }).notNull();
94
- return model ? schema.concat(createModelValidator(createOrUpdate)({ model, data: item }, { isDraft })) : schema;
105
+ return model ? schema.concat(
106
+ createModelValidator(createOrUpdate)(
107
+ { model, data: item, componentContext },
108
+ { isDraft }
109
+ )
110
+ ) : schema;
95
111
  })
96
112
  // FIXME: yup v1
97
113
  );
@@ -102,22 +118,20 @@ const createDzValidator = (createOrUpdate) => ({ attr, updatedAttribute }, { isD
102
118
  validator = addMinMax(validator, { attr, updatedAttribute });
103
119
  return validator;
104
120
  };
105
- const createRelationValidator = (createOrUpdate) => ({ attr, updatedAttribute }, { isDraft }) => {
121
+ const createRelationValidator = ({
122
+ updatedAttribute
123
+ }) => {
106
124
  let validator;
107
125
  if (Array.isArray(updatedAttribute.value)) {
108
126
  validator = yup.array().of(yup.mixed());
109
127
  } else {
110
128
  validator = yup.mixed();
111
129
  }
112
- validator = addRequiredValidation(createOrUpdate)(validator, {
113
- attr: { required: !isDraft && attr.required },
114
- updatedAttribute
115
- });
116
130
  return validator;
117
131
  };
118
132
  const createScalarAttributeValidator = (createOrUpdate) => (metas, options) => {
119
133
  let validator;
120
- if (_.has(metas.attr.type, validators)) {
134
+ if (fp.has(metas.attr.type, validators)) {
121
135
  validator = validators[metas.attr.type](metas, options);
122
136
  } else {
123
137
  validator = yup.mixed();
@@ -136,35 +150,58 @@ const createAttributeValidator = (createOrUpdate) => (metas, options) => {
136
150
  validator = createScalarAttributeValidator(createOrUpdate)(metas, options);
137
151
  } else {
138
152
  if (metas.attr.type === "component") {
153
+ const pathToComponent = [
154
+ ...metas?.componentContext?.pathToComponent ?? [],
155
+ metas.updatedAttribute.name
156
+ ];
157
+ const repeatableData = metas.attr.repeatable && pathToComponent.length === 1 ? metas.updatedAttribute.value : metas.componentContext?.repeatableData;
158
+ const newComponentContext = {
159
+ ...metas?.componentContext ?? {},
160
+ pathToComponent,
161
+ repeatableData
162
+ };
139
163
  validator = createComponentValidator(createOrUpdate)(
140
- { attr: metas.attr, updatedAttribute: metas.updatedAttribute },
141
- options
142
- );
143
- } else if (metas.attr.type === "dynamiczone") {
144
- validator = createDzValidator(createOrUpdate)(metas, options);
145
- } else if (metas.attr.type === "relation") {
146
- validator = createRelationValidator(createOrUpdate)(
147
164
  {
165
+ componentContext: newComponentContext,
148
166
  attr: metas.attr,
149
167
  updatedAttribute: metas.updatedAttribute
150
168
  },
151
169
  options
152
170
  );
171
+ } else if (metas.attr.type === "dynamiczone") {
172
+ const pathToComponent = [
173
+ ...metas?.componentContext?.pathToComponent ?? [],
174
+ metas.updatedAttribute.name
175
+ ];
176
+ const newComponentContext = {
177
+ ...metas?.componentContext ?? {},
178
+ pathToComponent
179
+ };
180
+ validator = createDzValidator(createOrUpdate)(
181
+ { ...metas, componentContext: newComponentContext },
182
+ options
183
+ );
184
+ } else if (metas.attr.type === "relation") {
185
+ validator = createRelationValidator({
186
+ attr: metas.attr,
187
+ updatedAttribute: metas.updatedAttribute
188
+ });
153
189
  }
154
190
  validator = preventCast(validator);
155
191
  }
156
192
  validator = addDefault(createOrUpdate)(validator, metas);
157
193
  return validator;
158
194
  };
159
- const createModelValidator = (createOrUpdate) => ({ model, data, entity }, options) => {
195
+ const createModelValidator = (createOrUpdate) => ({ componentContext, model, data, entity }, options) => {
160
196
  const writableAttributes = model ? getWritableAttributes(model) : [];
161
197
  const schema = writableAttributes.reduce(
162
198
  (validators2, attributeName) => {
163
199
  const metas = {
164
200
  attr: model.attributes[attributeName],
165
- updatedAttribute: { name: attributeName, value: _.prop(attributeName, data) },
201
+ updatedAttribute: { name: attributeName, value: fp.prop(attributeName, data) },
166
202
  model,
167
- entity
203
+ entity,
204
+ componentContext
168
205
  };
169
206
  const validator = createAttributeValidator(createOrUpdate)(metas, options);
170
207
  validators2[attributeName] = validator;
@@ -176,29 +213,49 @@ const createModelValidator = (createOrUpdate) => ({ model, data, entity }, optio
176
213
  };
177
214
  const createValidateEntity = (createOrUpdate) => {
178
215
  return async (model, data, options, entity) => {
179
- if (!_.isObject(data)) {
216
+ if (!fp.isObject(data)) {
180
217
  const { displayName } = model.info;
181
218
  throw new ValidationError(
182
219
  `Invalid payload submitted for the ${createOrUpdate} of an entity of type ${displayName}. Expected an object, but got ${typeof data}`
183
220
  );
184
221
  }
185
222
  const validator = createModelValidator(createOrUpdate)(
186
- { model, data, entity },
223
+ {
224
+ model,
225
+ data,
226
+ entity,
227
+ componentContext: {
228
+ // Set up the initial component context.
229
+ // Keeping track of parent content type context in which a component will be used.
230
+ // This is necessary to validate component field constraints such as uniqueness.
231
+ parentContent: {
232
+ id: entity?.id,
233
+ model,
234
+ options
235
+ },
236
+ pathToComponent: [],
237
+ repeatableData: []
238
+ }
239
+ },
187
240
  {
188
241
  isDraft: options?.isDraft ?? false,
189
242
  locale: options?.locale ?? null
190
243
  }
191
- ).test("relations-test", "check that all relations exist", async function(data2) {
192
- try {
193
- await checkRelationsExist(buildRelationsStore({ uid: model.uid, data: data2 }));
194
- } catch (e) {
195
- return this.createError({
196
- path: this.path,
197
- message: e instanceof ValidationError && e.message || "Invalid relations"
198
- });
244
+ ).test(
245
+ "relations-test",
246
+ "check that all relations exist",
247
+ async function relationsValidation(data2) {
248
+ try {
249
+ await checkRelationsExist(buildRelationsStore({ uid: model.uid, data: data2 }));
250
+ } catch (e) {
251
+ return this.createError({
252
+ path: this.path,
253
+ message: e instanceof ValidationError && e.message || "Invalid relations"
254
+ });
255
+ }
256
+ return true;
199
257
  }
200
- return true;
201
- }).required();
258
+ ).required();
202
259
  return validateYupSchema(validator, {
203
260
  strict: false,
204
261
  abortEarly: false
@@ -212,7 +269,7 @@ const buildRelationsStore = ({
212
269
  if (!uid) {
213
270
  throw new ValidationError(`Cannot build relations store: "uid" is undefined`);
214
271
  }
215
- if (_.isEmpty(data)) {
272
+ if (fp.isEmpty(data)) {
216
273
  return {};
217
274
  }
218
275
  const currentModel = strapi.getModel(uid);
@@ -220,7 +277,7 @@ const buildRelationsStore = ({
220
277
  (result, attributeName) => {
221
278
  const attribute = currentModel.attributes[attributeName];
222
279
  const value = data[attributeName];
223
- if (_$1.isNil(value)) {
280
+ if (_.isNil(value)) {
224
281
  return result;
225
282
  }
226
283
  switch (attribute.type) {
@@ -236,16 +293,16 @@ const buildRelationsStore = ({
236
293
  let source;
237
294
  if (Array.isArray(value)) {
238
295
  source = value;
239
- } else if (_.isObject(value)) {
240
- if ("connect" in value && !_$1.isNil(value.connect)) {
296
+ } else if (fp.isObject(value)) {
297
+ if ("connect" in value && !_.isNil(value.connect)) {
241
298
  source = value.connect;
242
- } else if ("set" in value && !_$1.isNil(value.set)) {
299
+ } else if ("set" in value && !_.isNil(value.set)) {
243
300
  source = value.set;
244
301
  } else {
245
302
  source = [];
246
303
  }
247
304
  } else {
248
- source = _$1.castArray(value);
305
+ source = _.castArray(value);
249
306
  }
250
307
  const idArray = source.map((v) => ({
251
308
  id: typeof v === "object" ? v.id : v
@@ -255,20 +312,20 @@ const buildRelationsStore = ({
255
312
  break;
256
313
  }
257
314
  case "component": {
258
- return _$1.castArray(value).reduce((relationsStore, componentValue) => {
315
+ return _.castArray(value).reduce((relationsStore, componentValue) => {
259
316
  if (!attribute.component) {
260
317
  throw new ValidationError(
261
318
  `Cannot build relations store from component, component identifier is undefined`
262
319
  );
263
320
  }
264
- return _$1.mergeWith(
321
+ return _.mergeWith(
265
322
  relationsStore,
266
323
  buildRelationsStore({
267
324
  uid: attribute.component,
268
325
  data: componentValue
269
326
  }),
270
327
  (objValue, srcValue) => {
271
- if (_$1.isArray(objValue)) {
328
+ if (_.isArray(objValue)) {
272
329
  return objValue.concat(srcValue);
273
330
  }
274
331
  }
@@ -276,21 +333,21 @@ const buildRelationsStore = ({
276
333
  }, result);
277
334
  }
278
335
  case "dynamiczone": {
279
- return _$1.castArray(value).reduce((relationsStore, dzValue) => {
336
+ return _.castArray(value).reduce((relationsStore, dzValue) => {
280
337
  const value2 = dzValue;
281
338
  if (!value2.__component) {
282
339
  throw new ValidationError(
283
340
  `Cannot build relations store from dynamiczone, component identifier is undefined`
284
341
  );
285
342
  }
286
- return _$1.mergeWith(
343
+ return _.mergeWith(
287
344
  relationsStore,
288
345
  buildRelationsStore({
289
346
  uid: value2.__component,
290
347
  data: value2
291
348
  }),
292
349
  (objValue, srcValue) => {
293
- if (_$1.isArray(objValue)) {
350
+ if (_.isArray(objValue)) {
294
351
  return objValue.concat(srcValue);
295
352
  }
296
353
  }
@@ -307,7 +364,7 @@ const checkRelationsExist = async (relationsStore = {}) => {
307
364
  const promises = [];
308
365
  for (const [key, value] of Object.entries(relationsStore)) {
309
366
  const evaluate = async () => {
310
- const uniqueValues = _$1.uniqBy(value, `id`);
367
+ const uniqueValues = _.uniqBy(value, `id`);
311
368
  const count = await strapi.db.query(key).count({
312
369
  where: {
313
370
  id: {