@strapi/plugin-graphql 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.
- package/dist/admin/index.js +18 -143
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +14 -141
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/package.json.js +143 -0
- package/dist/admin/package.json.js.map +1 -0
- package/dist/admin/package.json.mjs +124 -0
- package/dist/admin/package.json.mjs.map +1 -0
- package/dist/admin/pluginId.js +6 -0
- package/dist/admin/pluginId.js.map +1 -0
- package/dist/admin/pluginId.mjs +4 -0
- package/dist/admin/pluginId.mjs.map +1 -0
- package/dist/admin/{chunks/dk-D3k_Atlh.js → translations/dk.json.js} +2 -2
- package/dist/admin/translations/dk.json.js.map +1 -0
- package/dist/admin/{chunks/dk-Bji21OvY.mjs → translations/dk.json.mjs} +1 -1
- package/dist/admin/translations/dk.json.mjs.map +1 -0
- package/dist/admin/{chunks/en-DzY_FEd6.js → translations/en.json.js} +2 -2
- package/dist/admin/translations/en.json.js.map +1 -0
- package/dist/admin/{chunks/en-COko3s6d.mjs → translations/en.json.mjs} +1 -1
- package/dist/admin/translations/en.json.mjs.map +1 -0
- package/dist/admin/{chunks/es-D02rvX4A.js → translations/es.json.js} +2 -2
- package/dist/admin/translations/es.json.js.map +1 -0
- package/dist/admin/{chunks/es-BoUVfXlb.mjs → translations/es.json.mjs} +1 -1
- package/dist/admin/translations/es.json.mjs.map +1 -0
- package/dist/admin/{chunks/fr-D9dcL-gU.js → translations/fr.json.js} +2 -2
- package/dist/admin/translations/fr.json.js.map +1 -0
- package/dist/admin/{chunks/fr-DFbQQgkK.mjs → translations/fr.json.mjs} +1 -1
- package/dist/admin/translations/fr.json.mjs.map +1 -0
- package/dist/admin/{chunks/pl-DRSWvr2y.js → translations/pl.json.js} +2 -2
- package/dist/admin/translations/pl.json.js.map +1 -0
- package/dist/admin/{chunks/pl-Bih5cA3Y.mjs → translations/pl.json.mjs} +1 -1
- package/dist/admin/translations/pl.json.mjs.map +1 -0
- package/dist/admin/{chunks/ru-zDn7cu6t.js → translations/ru.json.js} +2 -2
- package/dist/admin/translations/ru.json.js.map +1 -0
- package/dist/admin/{chunks/ru-Bxi2fB6E.mjs → translations/ru.json.mjs} +1 -1
- package/dist/admin/translations/ru.json.mjs.map +1 -0
- package/dist/admin/{chunks/sv-Dq2aVH0_.js → translations/sv.json.js} +2 -2
- package/dist/admin/translations/sv.json.js.map +1 -0
- package/dist/admin/{chunks/sv-B2uIJv_a.mjs → translations/sv.json.mjs} +1 -1
- package/dist/admin/translations/sv.json.mjs.map +1 -0
- package/dist/admin/{chunks/tr-B0yEuVnS.js → translations/tr.json.js} +2 -2
- package/dist/admin/translations/tr.json.js.map +1 -0
- package/dist/admin/{chunks/tr-DwO6hyQD.mjs → translations/tr.json.mjs} +1 -1
- package/dist/admin/translations/tr.json.mjs.map +1 -0
- package/dist/admin/{chunks/uk-DJGNjXWk.js → translations/uk.json.js} +2 -2
- package/dist/admin/translations/uk.json.js.map +1 -0
- package/dist/admin/{chunks/uk-_25RY9BK.mjs → translations/uk.json.mjs} +1 -1
- package/dist/admin/translations/uk.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-Hans-DxlDvlSo.js → translations/zh-Hans.json.js} +2 -2
- package/dist/admin/translations/zh-Hans.json.js.map +1 -0
- package/dist/admin/{chunks/zh-Hans-DUab611K.mjs → translations/zh-Hans.json.mjs} +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-BkiTjJnf.js → translations/zh.json.js} +2 -2
- package/dist/admin/translations/zh.json.js.map +1 -0
- package/dist/admin/{chunks/zh-DVvz1qsT.mjs → translations/zh.json.mjs} +1 -1
- package/dist/admin/translations/zh.json.mjs.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.js +11 -0
- package/dist/admin/utils/prefixPluginTranslations.js.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs +9 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -0
- package/dist/server/bootstrap.js +180 -0
- package/dist/server/bootstrap.js.map +1 -0
- package/dist/server/bootstrap.mjs +177 -0
- package/dist/server/bootstrap.mjs.map +1 -0
- package/dist/server/config/default-config.js +13 -0
- package/dist/server/config/default-config.js.map +1 -0
- package/dist/server/config/default-config.mjs +11 -0
- package/dist/server/config/default-config.mjs.map +1 -0
- package/dist/server/config/index.js +10 -0
- package/dist/server/config/index.js.map +1 -0
- package/dist/server/config/index.mjs +8 -0
- package/dist/server/config/index.mjs.map +1 -0
- package/dist/server/format-graphql-error.js +60 -0
- package/dist/server/format-graphql-error.js.map +1 -0
- package/dist/server/format-graphql-error.mjs +58 -0
- package/dist/server/format-graphql-error.mjs.map +1 -0
- package/dist/server/index.js +6 -3719
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +3 -3698
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/services/builders/dynamic-zones.js +75 -0
- package/dist/server/services/builders/dynamic-zones.js.map +1 -0
- package/dist/server/services/builders/dynamic-zones.mjs +73 -0
- package/dist/server/services/builders/dynamic-zones.mjs.map +1 -0
- package/dist/server/services/builders/entity.js +38 -0
- package/dist/server/services/builders/entity.js.map +1 -0
- package/dist/server/services/builders/entity.mjs +36 -0
- package/dist/server/services/builders/entity.mjs.map +1 -0
- package/dist/server/services/builders/enums.js +24 -0
- package/dist/server/services/builders/enums.js.map +1 -0
- package/dist/server/services/builders/enums.mjs +22 -0
- package/dist/server/services/builders/enums.mjs.map +1 -0
- package/dist/server/services/builders/filters/content-type.js +94 -0
- package/dist/server/services/builders/filters/content-type.js.map +1 -0
- package/dist/server/services/builders/filters/content-type.mjs +92 -0
- package/dist/server/services/builders/filters/content-type.mjs.map +1 -0
- package/dist/server/services/builders/filters/index.js +10 -0
- package/dist/server/services/builders/filters/index.js.map +1 -0
- package/dist/server/services/builders/filters/index.mjs +8 -0
- package/dist/server/services/builders/filters/index.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/and.js +17 -0
- package/dist/server/services/builders/filters/operators/and.js.map +1 -0
- package/dist/server/services/builders/filters/operators/and.mjs +15 -0
- package/dist/server/services/builders/filters/operators/and.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/between.js +17 -0
- package/dist/server/services/builders/filters/operators/between.js.map +1 -0
- package/dist/server/services/builders/filters/operators/between.mjs +15 -0
- package/dist/server/services/builders/filters/operators/between.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/contains.js +15 -0
- package/dist/server/services/builders/filters/operators/contains.js.map +1 -0
- package/dist/server/services/builders/filters/operators/contains.mjs +13 -0
- package/dist/server/services/builders/filters/operators/contains.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/containsi.js +15 -0
- package/dist/server/services/builders/filters/operators/containsi.js.map +1 -0
- package/dist/server/services/builders/filters/operators/containsi.mjs +13 -0
- package/dist/server/services/builders/filters/operators/containsi.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/ends-with.js +15 -0
- package/dist/server/services/builders/filters/operators/ends-with.js.map +1 -0
- package/dist/server/services/builders/filters/operators/ends-with.mjs +13 -0
- package/dist/server/services/builders/filters/operators/ends-with.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/eq.js +22 -0
- package/dist/server/services/builders/filters/operators/eq.js.map +1 -0
- package/dist/server/services/builders/filters/operators/eq.mjs +20 -0
- package/dist/server/services/builders/filters/operators/eq.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/eqi.js +15 -0
- package/dist/server/services/builders/filters/operators/eqi.js.map +1 -0
- package/dist/server/services/builders/filters/operators/eqi.mjs +13 -0
- package/dist/server/services/builders/filters/operators/eqi.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/gt.js +15 -0
- package/dist/server/services/builders/filters/operators/gt.js.map +1 -0
- package/dist/server/services/builders/filters/operators/gt.mjs +13 -0
- package/dist/server/services/builders/filters/operators/gt.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/gte.js +15 -0
- package/dist/server/services/builders/filters/operators/gte.js.map +1 -0
- package/dist/server/services/builders/filters/operators/gte.mjs +13 -0
- package/dist/server/services/builders/filters/operators/gte.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/in.js +17 -0
- package/dist/server/services/builders/filters/operators/in.js.map +1 -0
- package/dist/server/services/builders/filters/operators/in.mjs +15 -0
- package/dist/server/services/builders/filters/operators/in.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/index.js +57 -0
- package/dist/server/services/builders/filters/operators/index.js.map +1 -0
- package/dist/server/services/builders/filters/operators/index.mjs +55 -0
- package/dist/server/services/builders/filters/operators/index.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/lt.js +15 -0
- package/dist/server/services/builders/filters/operators/lt.js.map +1 -0
- package/dist/server/services/builders/filters/operators/lt.mjs +13 -0
- package/dist/server/services/builders/filters/operators/lt.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/lte.js +15 -0
- package/dist/server/services/builders/filters/operators/lte.js.map +1 -0
- package/dist/server/services/builders/filters/operators/lte.mjs +13 -0
- package/dist/server/services/builders/filters/operators/lte.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/ne.js +15 -0
- package/dist/server/services/builders/filters/operators/ne.js.map +1 -0
- package/dist/server/services/builders/filters/operators/ne.mjs +13 -0
- package/dist/server/services/builders/filters/operators/ne.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/nei.js +15 -0
- package/dist/server/services/builders/filters/operators/nei.js.map +1 -0
- package/dist/server/services/builders/filters/operators/nei.mjs +13 -0
- package/dist/server/services/builders/filters/operators/nei.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/not-contains.js +15 -0
- package/dist/server/services/builders/filters/operators/not-contains.js.map +1 -0
- package/dist/server/services/builders/filters/operators/not-contains.mjs +13 -0
- package/dist/server/services/builders/filters/operators/not-contains.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/not-containsi.js +15 -0
- package/dist/server/services/builders/filters/operators/not-containsi.js.map +1 -0
- package/dist/server/services/builders/filters/operators/not-containsi.mjs +13 -0
- package/dist/server/services/builders/filters/operators/not-containsi.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/not-in.js +17 -0
- package/dist/server/services/builders/filters/operators/not-in.js.map +1 -0
- package/dist/server/services/builders/filters/operators/not-in.mjs +15 -0
- package/dist/server/services/builders/filters/operators/not-in.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/not-null.js +13 -0
- package/dist/server/services/builders/filters/operators/not-null.js.map +1 -0
- package/dist/server/services/builders/filters/operators/not-null.mjs +11 -0
- package/dist/server/services/builders/filters/operators/not-null.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/not.js +24 -0
- package/dist/server/services/builders/filters/operators/not.js.map +1 -0
- package/dist/server/services/builders/filters/operators/not.mjs +22 -0
- package/dist/server/services/builders/filters/operators/not.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/null.js +13 -0
- package/dist/server/services/builders/filters/operators/null.js.map +1 -0
- package/dist/server/services/builders/filters/operators/null.mjs +11 -0
- package/dist/server/services/builders/filters/operators/null.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/or.js +17 -0
- package/dist/server/services/builders/filters/operators/or.js.map +1 -0
- package/dist/server/services/builders/filters/operators/or.mjs +15 -0
- package/dist/server/services/builders/filters/operators/or.mjs.map +1 -0
- package/dist/server/services/builders/filters/operators/starts-with.js +15 -0
- package/dist/server/services/builders/filters/operators/starts-with.js.map +1 -0
- package/dist/server/services/builders/filters/operators/starts-with.mjs +13 -0
- package/dist/server/services/builders/filters/operators/starts-with.mjs.map +1 -0
- package/dist/server/services/builders/generic-morph.js +38 -0
- package/dist/server/services/builders/generic-morph.js.map +1 -0
- package/dist/server/services/builders/generic-morph.mjs +36 -0
- package/dist/server/services/builders/generic-morph.mjs.map +1 -0
- package/dist/server/services/builders/index.js +75 -0
- package/dist/server/services/builders/index.js.map +1 -0
- package/dist/server/services/builders/index.mjs +73 -0
- package/dist/server/services/builders/index.mjs.map +1 -0
- package/dist/server/services/builders/input.js +89 -0
- package/dist/server/services/builders/input.js.map +1 -0
- package/dist/server/services/builders/input.mjs +87 -0
- package/dist/server/services/builders/input.mjs.map +1 -0
- package/dist/server/services/builders/mutations/collection-type.js +155 -0
- package/dist/server/services/builders/mutations/collection-type.js.map +1 -0
- package/dist/server/services/builders/mutations/collection-type.mjs +153 -0
- package/dist/server/services/builders/mutations/collection-type.mjs.map +1 -0
- package/dist/server/services/builders/mutations/index.js +12 -0
- package/dist/server/services/builders/mutations/index.js.map +1 -0
- package/dist/server/services/builders/mutations/index.mjs +10 -0
- package/dist/server/services/builders/mutations/index.mjs.map +1 -0
- package/dist/server/services/builders/mutations/single-type.js +123 -0
- package/dist/server/services/builders/mutations/single-type.js.map +1 -0
- package/dist/server/services/builders/mutations/single-type.mjs +121 -0
- package/dist/server/services/builders/mutations/single-type.mjs.map +1 -0
- package/dist/server/services/builders/queries/collection-type.js +152 -0
- package/dist/server/services/builders/queries/collection-type.js.map +1 -0
- package/dist/server/services/builders/queries/collection-type.mjs +150 -0
- package/dist/server/services/builders/queries/collection-type.mjs.map +1 -0
- package/dist/server/services/builders/queries/index.js +12 -0
- package/dist/server/services/builders/queries/index.js.map +1 -0
- package/dist/server/services/builders/queries/index.mjs +10 -0
- package/dist/server/services/builders/queries/index.mjs.map +1 -0
- package/dist/server/services/builders/queries/single-type.js +70 -0
- package/dist/server/services/builders/queries/single-type.js.map +1 -0
- package/dist/server/services/builders/queries/single-type.mjs +68 -0
- package/dist/server/services/builders/queries/single-type.mjs.map +1 -0
- package/dist/server/services/builders/relation-response-collection.js +35 -0
- package/dist/server/services/builders/relation-response-collection.js.map +1 -0
- package/dist/server/services/builders/relation-response-collection.mjs +33 -0
- package/dist/server/services/builders/relation-response-collection.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/association.js +74 -0
- package/dist/server/services/builders/resolvers/association.js.map +1 -0
- package/dist/server/services/builders/resolvers/association.mjs +72 -0
- package/dist/server/services/builders/resolvers/association.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/component.js +27 -0
- package/dist/server/services/builders/resolvers/component.js.map +1 -0
- package/dist/server/services/builders/resolvers/component.mjs +25 -0
- package/dist/server/services/builders/resolvers/component.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/dynamic-zone.js +12 -0
- package/dist/server/services/builders/resolvers/dynamic-zone.js.map +1 -0
- package/dist/server/services/builders/resolvers/dynamic-zone.mjs +10 -0
- package/dist/server/services/builders/resolvers/dynamic-zone.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/index.js +20 -0
- package/dist/server/services/builders/resolvers/index.js.map +1 -0
- package/dist/server/services/builders/resolvers/index.mjs +18 -0
- package/dist/server/services/builders/resolvers/index.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/pagination.js +29 -0
- package/dist/server/services/builders/resolvers/pagination.js.map +1 -0
- package/dist/server/services/builders/resolvers/pagination.mjs +27 -0
- package/dist/server/services/builders/resolvers/pagination.mjs.map +1 -0
- package/dist/server/services/builders/resolvers/query.js +55 -0
- package/dist/server/services/builders/resolvers/query.js.map +1 -0
- package/dist/server/services/builders/resolvers/query.mjs +53 -0
- package/dist/server/services/builders/resolvers/query.mjs.map +1 -0
- package/dist/server/services/builders/response-collection.js +50 -0
- package/dist/server/services/builders/response-collection.js.map +1 -0
- package/dist/server/services/builders/response-collection.mjs +48 -0
- package/dist/server/services/builders/response-collection.mjs.map +1 -0
- package/dist/server/services/builders/response.js +28 -0
- package/dist/server/services/builders/response.js.map +1 -0
- package/dist/server/services/builders/response.mjs +26 -0
- package/dist/server/services/builders/response.mjs.map +1 -0
- package/dist/server/services/builders/type.js +347 -0
- package/dist/server/services/builders/type.js.map +1 -0
- package/dist/server/services/builders/type.mjs +345 -0
- package/dist/server/services/builders/type.mjs.map +1 -0
- package/dist/server/services/builders/utils.js +113 -0
- package/dist/server/services/builders/utils.js.map +1 -0
- package/dist/server/services/builders/utils.mjs +111 -0
- package/dist/server/services/builders/utils.mjs.map +1 -0
- package/dist/server/services/constants.js +139 -0
- package/dist/server/services/constants.js.map +1 -0
- package/dist/server/services/constants.mjs +137 -0
- package/dist/server/services/constants.mjs.map +1 -0
- package/dist/server/services/content-api/index.js +184 -0
- package/dist/server/services/content-api/index.js.map +1 -0
- package/dist/server/services/content-api/index.mjs +182 -0
- package/dist/server/services/content-api/index.mjs.map +1 -0
- package/dist/server/services/content-api/policy.js +54 -0
- package/dist/server/services/content-api/policy.js.map +1 -0
- package/dist/server/services/content-api/policy.mjs +52 -0
- package/dist/server/services/content-api/policy.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/collection-type.js +41 -0
- package/dist/server/services/content-api/register-functions/collection-type.js.map +1 -0
- package/dist/server/services/content-api/register-functions/collection-type.mjs +39 -0
- package/dist/server/services/content-api/register-functions/collection-type.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/component.js +16 -0
- package/dist/server/services/content-api/register-functions/component.js.map +1 -0
- package/dist/server/services/content-api/register-functions/component.mjs +14 -0
- package/dist/server/services/content-api/register-functions/component.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/dynamic-zones.js +31 -0
- package/dist/server/services/content-api/register-functions/dynamic-zones.js.map +1 -0
- package/dist/server/services/content-api/register-functions/dynamic-zones.mjs +29 -0
- package/dist/server/services/content-api/register-functions/dynamic-zones.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/enums.js +23 -0
- package/dist/server/services/content-api/register-functions/enums.js.map +1 -0
- package/dist/server/services/content-api/register-functions/enums.mjs +21 -0
- package/dist/server/services/content-api/register-functions/enums.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/filters.js +16 -0
- package/dist/server/services/content-api/register-functions/filters.js.map +1 -0
- package/dist/server/services/content-api/register-functions/filters.mjs +14 -0
- package/dist/server/services/content-api/register-functions/filters.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/inputs.js +17 -0
- package/dist/server/services/content-api/register-functions/inputs.js.map +1 -0
- package/dist/server/services/content-api/register-functions/inputs.mjs +15 -0
- package/dist/server/services/content-api/register-functions/inputs.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/internals.js +16 -0
- package/dist/server/services/content-api/register-functions/internals.js.map +1 -0
- package/dist/server/services/content-api/register-functions/internals.mjs +14 -0
- package/dist/server/services/content-api/register-functions/internals.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/polymorphic.js +49 -0
- package/dist/server/services/content-api/register-functions/polymorphic.js.map +1 -0
- package/dist/server/services/content-api/register-functions/polymorphic.mjs +47 -0
- package/dist/server/services/content-api/register-functions/polymorphic.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/scalars.js +15 -0
- package/dist/server/services/content-api/register-functions/scalars.js.map +1 -0
- package/dist/server/services/content-api/register-functions/scalars.mjs +13 -0
- package/dist/server/services/content-api/register-functions/scalars.mjs.map +1 -0
- package/dist/server/services/content-api/register-functions/single-type.js +41 -0
- package/dist/server/services/content-api/register-functions/single-type.js.map +1 -0
- package/dist/server/services/content-api/register-functions/single-type.mjs +39 -0
- package/dist/server/services/content-api/register-functions/single-type.mjs.map +1 -0
- package/dist/server/services/content-api/wrap-resolvers.js +119 -0
- package/dist/server/services/content-api/wrap-resolvers.js.map +1 -0
- package/dist/server/services/content-api/wrap-resolvers.mjs +117 -0
- package/dist/server/services/content-api/wrap-resolvers.mjs.map +1 -0
- package/dist/server/services/extension/extension.js +84 -0
- package/dist/server/services/extension/extension.js.map +1 -0
- package/dist/server/services/extension/extension.mjs +63 -0
- package/dist/server/services/extension/extension.mjs.map +1 -0
- package/dist/server/services/extension/index.js +8 -0
- package/dist/server/services/extension/index.js.map +1 -0
- package/dist/server/services/extension/index.mjs +6 -0
- package/dist/server/services/extension/index.mjs.map +1 -0
- package/dist/server/services/extension/shadow-crud-manager.js +121 -0
- package/dist/server/services/extension/shadow-crud-manager.js.map +1 -0
- package/dist/server/services/extension/shadow-crud-manager.mjs +119 -0
- package/dist/server/services/extension/shadow-crud-manager.mjs.map +1 -0
- package/dist/server/services/format/index.js +10 -0
- package/dist/server/services/format/index.js.map +1 -0
- package/dist/server/services/format/index.mjs +8 -0
- package/dist/server/services/format/index.mjs.map +1 -0
- package/dist/server/services/format/return-types.js +27 -0
- package/dist/server/services/format/return-types.js.map +1 -0
- package/dist/server/services/format/return-types.mjs +25 -0
- package/dist/server/services/format/return-types.mjs.map +1 -0
- package/dist/server/services/index.js +24 -0
- package/dist/server/services/index.js.map +1 -0
- package/dist/server/services/index.mjs +22 -0
- package/dist/server/services/index.mjs.map +1 -0
- package/dist/server/services/internals/args/index.js +14 -0
- package/dist/server/services/internals/args/index.js.map +1 -0
- package/dist/server/services/internals/args/index.mjs +12 -0
- package/dist/server/services/internals/args/index.mjs.map +1 -0
- package/dist/server/services/internals/args/pagination.js +20 -0
- package/dist/server/services/internals/args/pagination.js.map +1 -0
- package/dist/server/services/internals/args/pagination.mjs +18 -0
- package/dist/server/services/internals/args/pagination.mjs.map +1 -0
- package/dist/server/services/internals/args/publication-status.js +14 -0
- package/dist/server/services/internals/args/publication-status.js.map +1 -0
- package/dist/server/services/internals/args/publication-status.mjs +12 -0
- package/dist/server/services/internals/args/publication-status.mjs.map +1 -0
- package/dist/server/services/internals/args/sort.js +11 -0
- package/dist/server/services/internals/args/sort.js.map +1 -0
- package/dist/server/services/internals/args/sort.mjs +9 -0
- package/dist/server/services/internals/args/sort.mjs.map +1 -0
- package/dist/server/services/internals/helpers/get-enabled-scalars.js +13 -0
- package/dist/server/services/internals/helpers/get-enabled-scalars.js.map +1 -0
- package/dist/server/services/internals/helpers/get-enabled-scalars.mjs +11 -0
- package/dist/server/services/internals/helpers/get-enabled-scalars.mjs.map +1 -0
- package/dist/server/services/internals/helpers/index.js +10 -0
- package/dist/server/services/internals/helpers/index.js.map +1 -0
- package/dist/server/services/internals/helpers/index.mjs +8 -0
- package/dist/server/services/internals/helpers/index.mjs.map +1 -0
- package/dist/server/services/internals/index.js +16 -0
- package/dist/server/services/internals/index.js.map +1 -0
- package/dist/server/services/internals/index.mjs +14 -0
- package/dist/server/services/internals/index.mjs.map +1 -0
- package/dist/server/services/internals/scalars/date.js +18 -0
- package/dist/server/services/internals/scalars/date.js.map +1 -0
- package/dist/server/services/internals/scalars/date.mjs +15 -0
- package/dist/server/services/internals/scalars/date.mjs.map +1 -0
- package/dist/server/services/internals/scalars/index.js +17 -0
- package/dist/server/services/internals/scalars/index.js.map +1 -0
- package/dist/server/services/internals/scalars/index.mjs +15 -0
- package/dist/server/services/internals/scalars/index.mjs.map +1 -0
- package/dist/server/services/internals/scalars/time.js +38 -0
- package/dist/server/services/internals/scalars/time.js.map +1 -0
- package/dist/server/services/internals/scalars/time.mjs +36 -0
- package/dist/server/services/internals/scalars/time.mjs.map +1 -0
- package/dist/server/services/internals/types/delete-mutation-response.js +18 -0
- package/dist/server/services/internals/types/delete-mutation-response.js.map +1 -0
- package/dist/server/services/internals/types/delete-mutation-response.mjs +16 -0
- package/dist/server/services/internals/types/delete-mutation-response.mjs.map +1 -0
- package/dist/server/services/internals/types/error.js +32 -0
- package/dist/server/services/internals/types/error.js.map +1 -0
- package/dist/server/services/internals/types/error.mjs +30 -0
- package/dist/server/services/internals/types/error.mjs.map +1 -0
- package/dist/server/services/internals/types/filters.js +35 -0
- package/dist/server/services/internals/types/filters.js.map +1 -0
- package/dist/server/services/internals/types/filters.mjs +33 -0
- package/dist/server/services/internals/types/filters.mjs.map +1 -0
- package/dist/server/services/internals/types/index.js +30 -0
- package/dist/server/services/internals/types/index.js.map +1 -0
- package/dist/server/services/internals/types/index.mjs +28 -0
- package/dist/server/services/internals/types/index.mjs.map +1 -0
- package/dist/server/services/internals/types/pagination.js +24 -0
- package/dist/server/services/internals/types/pagination.js.map +1 -0
- package/dist/server/services/internals/types/pagination.mjs +22 -0
- package/dist/server/services/internals/types/pagination.mjs.map +1 -0
- package/dist/server/services/internals/types/publication-status.js +22 -0
- package/dist/server/services/internals/types/publication-status.js.map +1 -0
- package/dist/server/services/internals/types/publication-status.mjs +20 -0
- package/dist/server/services/internals/types/publication-status.mjs.map +1 -0
- package/dist/server/services/internals/types/response-collection-meta.js +27 -0
- package/dist/server/services/internals/types/response-collection-meta.js.map +1 -0
- package/dist/server/services/internals/types/response-collection-meta.mjs +25 -0
- package/dist/server/services/internals/types/response-collection-meta.mjs.map +1 -0
- package/dist/server/services/type-registry.js +81 -0
- package/dist/server/services/type-registry.js.map +1 -0
- package/dist/server/services/type-registry.mjs +79 -0
- package/dist/server/services/type-registry.mjs.map +1 -0
- package/dist/server/services/utils/attributes.js +65 -0
- package/dist/server/services/utils/attributes.js.map +1 -0
- package/dist/server/services/utils/attributes.mjs +63 -0
- package/dist/server/services/utils/attributes.mjs.map +1 -0
- package/dist/server/services/utils/index.js +16 -0
- package/dist/server/services/utils/index.js.map +1 -0
- package/dist/server/services/utils/index.mjs +14 -0
- package/dist/server/services/utils/index.mjs.map +1 -0
- package/dist/server/services/utils/mappers/entity-to-response-entity.js +16 -0
- package/dist/server/services/utils/mappers/entity-to-response-entity.js.map +1 -0
- package/dist/server/services/utils/mappers/entity-to-response-entity.mjs +14 -0
- package/dist/server/services/utils/mappers/entity-to-response-entity.mjs.map +1 -0
- package/dist/server/services/utils/mappers/graphql-filters-to-strapi-query.js +95 -0
- package/dist/server/services/utils/mappers/graphql-filters-to-strapi-query.js.map +1 -0
- package/dist/server/services/utils/mappers/graphql-filters-to-strapi-query.mjs +93 -0
- package/dist/server/services/utils/mappers/graphql-filters-to-strapi-query.mjs.map +1 -0
- package/dist/server/services/utils/mappers/graphql-scalar-to-operators.js +15 -0
- package/dist/server/services/utils/mappers/graphql-scalar-to-operators.js.map +1 -0
- package/dist/server/services/utils/mappers/graphql-scalar-to-operators.mjs +13 -0
- package/dist/server/services/utils/mappers/graphql-scalar-to-operators.mjs.map +1 -0
- package/dist/server/services/utils/mappers/index.js +16 -0
- package/dist/server/services/utils/mappers/index.js.map +1 -0
- package/dist/server/services/utils/mappers/index.mjs +14 -0
- package/dist/server/services/utils/mappers/index.mjs.map +1 -0
- package/dist/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.js +23 -0
- package/dist/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.js.map +1 -0
- package/dist/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.mjs +21 -0
- package/dist/server/services/utils/mappers/strapi-scalar-to-graphql-scalar.mjs.map +1 -0
- package/dist/server/services/utils/naming.js +187 -0
- package/dist/server/services/utils/naming.js.map +1 -0
- package/dist/server/services/utils/naming.mjs +185 -0
- package/dist/server/services/utils/naming.mjs.map +1 -0
- package/dist/server/services/utils/playground.js +19 -0
- package/dist/server/services/utils/playground.js.map +1 -0
- package/dist/server/services/utils/playground.mjs +17 -0
- package/dist/server/services/utils/playground.mjs.map +1 -0
- package/package.json +6 -6
- package/dist/admin/chunks/dk-Bji21OvY.mjs.map +0 -1
- package/dist/admin/chunks/dk-D3k_Atlh.js.map +0 -1
- package/dist/admin/chunks/en-COko3s6d.mjs.map +0 -1
- package/dist/admin/chunks/en-DzY_FEd6.js.map +0 -1
- package/dist/admin/chunks/es-BoUVfXlb.mjs.map +0 -1
- package/dist/admin/chunks/es-D02rvX4A.js.map +0 -1
- package/dist/admin/chunks/fr-D9dcL-gU.js.map +0 -1
- package/dist/admin/chunks/fr-DFbQQgkK.mjs.map +0 -1
- package/dist/admin/chunks/pl-Bih5cA3Y.mjs.map +0 -1
- package/dist/admin/chunks/pl-DRSWvr2y.js.map +0 -1
- package/dist/admin/chunks/ru-Bxi2fB6E.mjs.map +0 -1
- package/dist/admin/chunks/ru-zDn7cu6t.js.map +0 -1
- package/dist/admin/chunks/sv-B2uIJv_a.mjs.map +0 -1
- package/dist/admin/chunks/sv-Dq2aVH0_.js.map +0 -1
- package/dist/admin/chunks/tr-B0yEuVnS.js.map +0 -1
- package/dist/admin/chunks/tr-DwO6hyQD.mjs.map +0 -1
- package/dist/admin/chunks/uk-DJGNjXWk.js.map +0 -1
- package/dist/admin/chunks/uk-_25RY9BK.mjs.map +0 -1
- package/dist/admin/chunks/zh-BkiTjJnf.js.map +0 -1
- package/dist/admin/chunks/zh-DVvz1qsT.mjs.map +0 -1
- package/dist/admin/chunks/zh-Hans-DUab611K.mjs.map +0 -1
- package/dist/admin/chunks/zh-Hans-DxlDvlSo.js.map +0 -1
package/dist/server/index.mjs
CHANGED
|
@@ -1,3701 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { koaMiddleware } from '@as-integrations/koa';
|
|
5
|
-
import depthLimit from 'graphql-depth-limit';
|
|
6
|
-
import bodyParser from 'koa-bodyparser';
|
|
7
|
-
import cors from '@koa/cors';
|
|
8
|
-
import { errors, policy, parseType, strings, contentTypes, async, pagination as pagination$1 } from '@strapi/utils';
|
|
9
|
-
import { unwrapResolverError } from '@apollo/server/errors';
|
|
10
|
-
import { GraphQLError, GraphQLObjectType, GraphQLScalarType, Kind, valueFromASTUntyped } from 'graphql';
|
|
11
|
-
import { pruneSchema } from '@graphql-tools/utils';
|
|
12
|
-
import * as nexus from 'nexus';
|
|
13
|
-
import { unionType, makeSchema, arg, list, inputObjectType, asNexusMethod, objectType, enumType, scalarType, nonNull, extendType, idArg } from 'nexus';
|
|
14
|
-
import { singular } from 'pluralize';
|
|
15
|
-
import { GraphQLDate, GraphQLJSON, GraphQLDateTime, GraphQLLong } from 'graphql-scalars';
|
|
16
|
-
|
|
17
|
-
var defaultConfig = {
|
|
18
|
-
shadowCRUD: true,
|
|
19
|
-
endpoint: '/graphql',
|
|
20
|
-
subscriptions: false,
|
|
21
|
-
maxLimit: -1,
|
|
22
|
-
apolloServer: {},
|
|
23
|
-
v4CompatibilityMode: process.env.STRAPI_GRAPHQL_V4_COMPATIBILITY_MODE ?? false
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const config = {
|
|
27
|
-
default: defaultConfig
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const { HttpError, ForbiddenError: ForbiddenError$1, UnauthorizedError, ApplicationError: ApplicationError$5, ValidationError: ValidationError$3 } = errors;
|
|
31
|
-
const formatToCode = (name)=>`STRAPI_${toUpper(snakeCase(name))}`;
|
|
32
|
-
const formatErrorToExtension = (error)=>({
|
|
33
|
-
error: pick([
|
|
34
|
-
'name',
|
|
35
|
-
'message',
|
|
36
|
-
'details'
|
|
37
|
-
])(error)
|
|
38
|
-
});
|
|
39
|
-
function createFormattedError(formattedError, message, code, originalError) {
|
|
40
|
-
const options = {
|
|
41
|
-
...formattedError,
|
|
42
|
-
extensions: {
|
|
43
|
-
...formattedError.extensions,
|
|
44
|
-
...formatErrorToExtension(originalError),
|
|
45
|
-
code
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
return new GraphQLError(message, options);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* The handler for Apollo Server v4's formatError config option
|
|
52
|
-
*
|
|
53
|
-
* Intercepts specific Strapi error types to send custom error response codes in the GraphQL response
|
|
54
|
-
*/ function formatGraphqlError(formattedError, error) {
|
|
55
|
-
const originalError = unwrapResolverError(error);
|
|
56
|
-
// If this error doesn't have an associated originalError, it
|
|
57
|
-
if (isEmpty(originalError)) {
|
|
58
|
-
return formattedError;
|
|
59
|
-
}
|
|
60
|
-
const { message = '', name = 'UNKNOWN' } = originalError;
|
|
61
|
-
if (originalError instanceof ForbiddenError$1 || originalError instanceof UnauthorizedError) {
|
|
62
|
-
return createFormattedError(formattedError, message, 'FORBIDDEN', originalError);
|
|
63
|
-
}
|
|
64
|
-
if (originalError instanceof ValidationError$3) {
|
|
65
|
-
return createFormattedError(formattedError, message, 'BAD_USER_INPUT', originalError);
|
|
66
|
-
}
|
|
67
|
-
if (originalError instanceof ApplicationError$5 || originalError instanceof HttpError) {
|
|
68
|
-
const errorName = formatToCode(name);
|
|
69
|
-
return createFormattedError(formattedError, message, errorName, originalError);
|
|
70
|
-
}
|
|
71
|
-
if (originalError instanceof GraphQLError) {
|
|
72
|
-
return formattedError;
|
|
73
|
-
}
|
|
74
|
-
// else if originalError doesn't appear to be from Strapi or GraphQL..
|
|
75
|
-
// Log the error
|
|
76
|
-
strapi.log.error(originalError);
|
|
77
|
-
// Create a generic 500 to send so we don't risk leaking any data
|
|
78
|
-
return createFormattedError(new GraphQLError('Internal Server Error'), 'Internal Server Error', 'INTERNAL_SERVER_ERROR', originalError);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const merge = mergeWith((a, b)=>{
|
|
82
|
-
if (isArray(a) && isArray(b)) {
|
|
83
|
-
return a.concat(b);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
const determineLandingPage = (strapi)=>{
|
|
87
|
-
const { config } = strapi.plugin('graphql');
|
|
88
|
-
const utils = strapi.plugin('graphql').service('utils');
|
|
89
|
-
/**
|
|
90
|
-
* configLanding page may be one of the following:
|
|
91
|
-
*
|
|
92
|
-
* - true: always use "playground" even in production
|
|
93
|
-
* - false: never show "playground" even in non-production
|
|
94
|
-
* - undefined: default Apollo behavior (hide playground on production)
|
|
95
|
-
* - a function that returns an Apollo plugin that implements renderLandingPage
|
|
96
|
-
** */ const configLandingPage = config('landingPage');
|
|
97
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
98
|
-
const localLanding = ()=>{
|
|
99
|
-
strapi.log.debug('Apollo landing page: local');
|
|
100
|
-
utils.playground.setEnabled(true);
|
|
101
|
-
return ApolloServerPluginLandingPageLocalDefault();
|
|
102
|
-
};
|
|
103
|
-
const prodLanding = ()=>{
|
|
104
|
-
strapi.log.debug('Apollo landing page: production');
|
|
105
|
-
utils.playground.setEnabled(false);
|
|
106
|
-
return ApolloServerPluginLandingPageProductionDefault();
|
|
107
|
-
};
|
|
108
|
-
const userLanding = (userFunction)=>{
|
|
109
|
-
strapi.log.debug('Apollo landing page: from user-defined function...');
|
|
110
|
-
const result = userFunction(strapi);
|
|
111
|
-
if (result === true) {
|
|
112
|
-
return localLanding();
|
|
113
|
-
}
|
|
114
|
-
if (result === false) {
|
|
115
|
-
return prodLanding();
|
|
116
|
-
}
|
|
117
|
-
strapi.log.debug('Apollo landing page: user-defined');
|
|
118
|
-
return result;
|
|
119
|
-
};
|
|
120
|
-
// DEPRECATED, remove in Strapi v6
|
|
121
|
-
const playgroundAlways = config('playgroundAlways');
|
|
122
|
-
if (playgroundAlways !== undefined) {
|
|
123
|
-
strapi.log.warn('The graphql config playgroundAlways is deprecated. This will be removed in Strapi 6. Please use landingPage instead. ');
|
|
124
|
-
}
|
|
125
|
-
if (playgroundAlways === false) {
|
|
126
|
-
strapi.log.warn('graphql config playgroundAlways:false has no effect, please use landingPage:false to disable Graphql Playground in all environments');
|
|
127
|
-
}
|
|
128
|
-
if (playgroundAlways || configLandingPage === true) {
|
|
129
|
-
return localLanding();
|
|
130
|
-
}
|
|
131
|
-
// if landing page has been disabled, use production
|
|
132
|
-
if (configLandingPage === false) {
|
|
133
|
-
return prodLanding();
|
|
134
|
-
}
|
|
135
|
-
// If user did not define any settings, use our defaults
|
|
136
|
-
if (configLandingPage === undefined) {
|
|
137
|
-
return isProduction ? prodLanding() : localLanding();
|
|
138
|
-
}
|
|
139
|
-
// if user provided a landing page function, return that
|
|
140
|
-
if (isFunction(configLandingPage)) {
|
|
141
|
-
return userLanding(configLandingPage);
|
|
142
|
-
}
|
|
143
|
-
// If no other setting could be found, default to production settings
|
|
144
|
-
strapi.log.warn('Your Graphql landing page has been disabled because there is a problem with your Graphql settings');
|
|
145
|
-
return prodLanding();
|
|
146
|
-
};
|
|
147
|
-
async function bootstrap({ strapi }) {
|
|
148
|
-
// Generate the GraphQL schema for the content API
|
|
149
|
-
const schema = strapi.plugin('graphql').service('content-api').buildSchema();
|
|
150
|
-
if (isEmpty(schema)) {
|
|
151
|
-
strapi.log.warn('The GraphQL schema has not been generated because it is empty');
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const { config } = strapi.plugin('graphql');
|
|
155
|
-
const path = config('endpoint');
|
|
156
|
-
const landingPage = determineLandingPage(strapi);
|
|
157
|
-
const defaultServerConfig = {
|
|
158
|
-
// Schema
|
|
159
|
-
schema,
|
|
160
|
-
// Validation
|
|
161
|
-
validationRules: [
|
|
162
|
-
depthLimit(config('depthLimit'))
|
|
163
|
-
],
|
|
164
|
-
// Errors
|
|
165
|
-
formatError: formatGraphqlError,
|
|
166
|
-
// Misc
|
|
167
|
-
cors: false,
|
|
168
|
-
uploads: false,
|
|
169
|
-
bodyParserConfig: true,
|
|
170
|
-
// send 400 http status instead of 200 for input validation errors
|
|
171
|
-
status400ForVariableCoercionErrors: true,
|
|
172
|
-
plugins: [
|
|
173
|
-
landingPage
|
|
174
|
-
],
|
|
175
|
-
cache: 'bounded'
|
|
176
|
-
};
|
|
177
|
-
const serverConfig = merge(defaultServerConfig, config('apolloServer'));
|
|
178
|
-
// Create a new Apollo server
|
|
179
|
-
const server = new ApolloServer(serverConfig);
|
|
180
|
-
try {
|
|
181
|
-
// server.start() must be called before using server.applyMiddleware()
|
|
182
|
-
await server.start();
|
|
183
|
-
} catch (error) {
|
|
184
|
-
if (error instanceof Error) {
|
|
185
|
-
strapi.log.error('Failed to start the Apollo server', error.message);
|
|
186
|
-
}
|
|
187
|
-
throw error;
|
|
188
|
-
}
|
|
189
|
-
// Create the route handlers for Strapi
|
|
190
|
-
const handler = [];
|
|
191
|
-
// add cors middleware
|
|
192
|
-
if (cors) {
|
|
193
|
-
handler.push(cors());
|
|
194
|
-
}
|
|
195
|
-
// add koa bodyparser middleware
|
|
196
|
-
if (isObject(serverConfig.bodyParserConfig)) {
|
|
197
|
-
handler.push(bodyParser(serverConfig.bodyParserConfig));
|
|
198
|
-
} else if (serverConfig.bodyParserConfig) {
|
|
199
|
-
handler.push(bodyParser());
|
|
200
|
-
} else {
|
|
201
|
-
strapi.log.debug('Body parser has been disabled for Apollo server');
|
|
202
|
-
}
|
|
203
|
-
// add the Strapi auth middleware
|
|
204
|
-
handler.push((ctx, next)=>{
|
|
205
|
-
ctx.state.route = {
|
|
206
|
-
info: {
|
|
207
|
-
// Indicate it's a content API route
|
|
208
|
-
type: 'content-api'
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
const isPlaygroundRequest = ctx.request.method === 'GET' && ctx.request.url === path && // Matches the GraphQL endpoint
|
|
212
|
-
strapi.plugin('graphql').service('utils').playground.isEnabled() && // Only allow if the Playground is enabled
|
|
213
|
-
ctx.request.header.accept?.includes('text/html'); // Specific to Playground UI loading
|
|
214
|
-
// Skip authentication for the GraphQL Playground UI
|
|
215
|
-
if (isPlaygroundRequest) {
|
|
216
|
-
return next();
|
|
217
|
-
}
|
|
218
|
-
return strapi.auth.authenticate(ctx, next);
|
|
219
|
-
});
|
|
220
|
-
// add the graphql server for koa
|
|
221
|
-
handler.push(koaMiddleware(server, {
|
|
222
|
-
// Initialize loaders for this request.
|
|
223
|
-
context: async ({ ctx })=>({
|
|
224
|
-
state: ctx.state,
|
|
225
|
-
koaContext: ctx
|
|
226
|
-
})
|
|
227
|
-
}));
|
|
228
|
-
// now that handlers are set up, add the graphql route to our apollo server
|
|
229
|
-
strapi.server.routes([
|
|
230
|
-
{
|
|
231
|
-
method: 'ALL',
|
|
232
|
-
path,
|
|
233
|
-
handler,
|
|
234
|
-
config: {
|
|
235
|
-
auth: false
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
]);
|
|
239
|
-
// Register destroy behavior
|
|
240
|
-
// We're doing it here instead of exposing a destroy method to the strapi-server.js
|
|
241
|
-
// file since we need to have access to the ApolloServer instance
|
|
242
|
-
strapi.plugin('graphql').destroy = async ()=>{
|
|
243
|
-
await server.stop();
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const { PolicyError } = errors;
|
|
248
|
-
const getPoliciesConfig = propOr([], 'policies');
|
|
249
|
-
const createPoliciesMiddleware = (resolverConfig, { strapi })=>{
|
|
250
|
-
const resolverPolicies = getPoliciesConfig(resolverConfig);
|
|
251
|
-
const policies = strapi.get('policies').resolve(resolverPolicies, {});
|
|
252
|
-
return async (resolve, parent, args, context, info)=>{
|
|
253
|
-
// Create a graphql policy context
|
|
254
|
-
const policyContext = createGraphQLPolicyContext(parent, args, context, info);
|
|
255
|
-
// Run policies & throw an error if one of them fails
|
|
256
|
-
for (const { handler, config } of policies){
|
|
257
|
-
const result = await handler(policyContext, config, {
|
|
258
|
-
strapi
|
|
259
|
-
});
|
|
260
|
-
if (![
|
|
261
|
-
true,
|
|
262
|
-
undefined
|
|
263
|
-
].includes(result)) {
|
|
264
|
-
throw new PolicyError();
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return resolve(parent, args, context, info);
|
|
268
|
-
};
|
|
269
|
-
};
|
|
270
|
-
const createGraphQLPolicyContext = (parent, args, context, info)=>{
|
|
271
|
-
const policyContext = {
|
|
272
|
-
get parent () {
|
|
273
|
-
return parent;
|
|
274
|
-
},
|
|
275
|
-
get args () {
|
|
276
|
-
return args;
|
|
277
|
-
},
|
|
278
|
-
get context () {
|
|
279
|
-
return context;
|
|
280
|
-
},
|
|
281
|
-
get info () {
|
|
282
|
-
return info;
|
|
283
|
-
},
|
|
284
|
-
get state () {
|
|
285
|
-
return this.context.state;
|
|
286
|
-
},
|
|
287
|
-
get http () {
|
|
288
|
-
return this.context.koaContext;
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
return policy.createPolicyContext('graphql', policyContext);
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const { ForbiddenError } = errors;
|
|
295
|
-
const introspectionQueries = [
|
|
296
|
-
'__Schema',
|
|
297
|
-
'__Type',
|
|
298
|
-
'__Field',
|
|
299
|
-
'__InputValue',
|
|
300
|
-
'__EnumValue',
|
|
301
|
-
'__Directive'
|
|
302
|
-
];
|
|
303
|
-
/**
|
|
304
|
-
* Get & parse middlewares definitions from the resolver's config
|
|
305
|
-
* @param {object} resolverConfig
|
|
306
|
-
* @param {object} strapi
|
|
307
|
-
* @return {function[]}
|
|
308
|
-
*/ const parseMiddlewares = (resolverConfig, strapi)=>{
|
|
309
|
-
const resolverMiddlewares = getOr([], 'middlewares', resolverConfig);
|
|
310
|
-
// TODO: [v4] to factorize with compose endpoints (routes)
|
|
311
|
-
return resolverMiddlewares.map((middleware)=>{
|
|
312
|
-
if (isFunction(middleware)) {
|
|
313
|
-
return middleware;
|
|
314
|
-
}
|
|
315
|
-
if (typeof middleware === 'string') {
|
|
316
|
-
return strapi.middleware(middleware);
|
|
317
|
-
}
|
|
318
|
-
if (typeof middleware === 'object') {
|
|
319
|
-
const { name, options = {} } = middleware;
|
|
320
|
-
return strapi.middleware(name)(options, {
|
|
321
|
-
strapi
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
throw new Error(`Invalid middleware type, expected (function,string,object), received ${typeof middleware}`);
|
|
325
|
-
});
|
|
326
|
-
};
|
|
327
|
-
/**
|
|
328
|
-
* Wrap the schema's resolvers if they've been
|
|
329
|
-
* customized using the GraphQL extension service
|
|
330
|
-
* @param {object} options
|
|
331
|
-
* @param {GraphQLSchema} options.schema
|
|
332
|
-
* @param {object} options.strapi
|
|
333
|
-
* @param {object} options.extension
|
|
334
|
-
* @return {GraphQLSchema}
|
|
335
|
-
*/ const wrapResolvers = ({ schema, strapi, extension = {} })=>{
|
|
336
|
-
// Get all the registered resolvers configuration
|
|
337
|
-
const { resolversConfig = {} } = extension;
|
|
338
|
-
// Fields filters
|
|
339
|
-
const isValidFieldName = (field)=>!field.startsWith('__');
|
|
340
|
-
const typeMap = schema.getTypeMap();
|
|
341
|
-
Object.entries(typeMap).forEach(([type, definition])=>{
|
|
342
|
-
const isGraphQLObjectType = definition instanceof GraphQLObjectType;
|
|
343
|
-
const isIgnoredType = introspectionQueries.includes(type);
|
|
344
|
-
if (!isGraphQLObjectType || isIgnoredType) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
const fields = definition.getFields();
|
|
348
|
-
const fieldsToProcess = Object.entries(fields).filter(([field])=>isValidFieldName(field));
|
|
349
|
-
for (const [fieldName, fieldDefinition] of fieldsToProcess){
|
|
350
|
-
const defaultResolver = get(fieldName);
|
|
351
|
-
const path = `${type}.${fieldName}`;
|
|
352
|
-
const resolverConfig = getOr({}, path, resolversConfig);
|
|
353
|
-
const { resolve: baseResolver = defaultResolver } = fieldDefinition;
|
|
354
|
-
// Parse & initialize the middlewares
|
|
355
|
-
const middlewares = parseMiddlewares(resolverConfig, strapi);
|
|
356
|
-
// Generate the policy middleware
|
|
357
|
-
const policyMiddleware = createPoliciesMiddleware(resolverConfig, {
|
|
358
|
-
strapi
|
|
359
|
-
});
|
|
360
|
-
// Add the policyMiddleware at the end of the middlewares collection
|
|
361
|
-
middlewares.push(policyMiddleware);
|
|
362
|
-
// Bind every middleware to the next one
|
|
363
|
-
const boundMiddlewares = middlewares.map((middleware, index, collection)=>{
|
|
364
|
-
return (parents, args, context, info)=>middleware(// Make sure the last middleware in the list calls the baseResolver
|
|
365
|
-
index >= collection.length - 1 ? baseResolver : boundMiddlewares[index + 1], parents, args, context, info);
|
|
366
|
-
});
|
|
367
|
-
/**
|
|
368
|
-
* GraphQL authorization flow
|
|
369
|
-
* @param {object} context
|
|
370
|
-
* @return {Promise<void>}
|
|
371
|
-
*/ const authorize = async ({ context })=>{
|
|
372
|
-
const authConfig = get('auth', resolverConfig);
|
|
373
|
-
const authContext = get('state.auth', context);
|
|
374
|
-
const isValidType = [
|
|
375
|
-
'Mutation',
|
|
376
|
-
'Query',
|
|
377
|
-
'Subscription'
|
|
378
|
-
].includes(type);
|
|
379
|
-
const hasConfig = !isNil(authConfig);
|
|
380
|
-
const isAuthDisabled = authConfig === false;
|
|
381
|
-
if ((isValidType || hasConfig) && !isAuthDisabled) {
|
|
382
|
-
try {
|
|
383
|
-
await strapi.auth.verify(authContext, authConfig);
|
|
384
|
-
} catch (error) {
|
|
385
|
-
throw new ForbiddenError();
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
/**
|
|
390
|
-
* Base resolver wrapper that handles authorization, middlewares & policies
|
|
391
|
-
* @return {Promise<any>}
|
|
392
|
-
*/ fieldDefinition.resolve = async (parent, args, context, info)=>{
|
|
393
|
-
await authorize({
|
|
394
|
-
context
|
|
395
|
-
});
|
|
396
|
-
// Execute middlewares (including the policy middleware which will always be included)
|
|
397
|
-
return first(boundMiddlewares)(parent, args, context, info);
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
return schema;
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
const registerCollectionType = (contentType, { registry, strapi, builders })=>{
|
|
405
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
406
|
-
const { naming } = getService('utils');
|
|
407
|
-
const { KINDS } = getService('constants');
|
|
408
|
-
const extension = getService('extension');
|
|
409
|
-
// Types name (as string)
|
|
410
|
-
const types = {
|
|
411
|
-
base: naming.getTypeName(contentType),
|
|
412
|
-
entity: naming.getEntityName(contentType),
|
|
413
|
-
response: naming.getEntityResponseName(contentType),
|
|
414
|
-
responseCollection: naming.getEntityResponseCollectionName(contentType),
|
|
415
|
-
relationResponseCollection: naming.getRelationResponseCollectionName(contentType),
|
|
416
|
-
queries: naming.getEntityQueriesTypeName(contentType),
|
|
417
|
-
mutations: naming.getEntityMutationsTypeName(contentType)
|
|
418
|
-
};
|
|
419
|
-
const getConfig = (kind)=>({
|
|
420
|
-
kind,
|
|
421
|
-
contentType
|
|
422
|
-
});
|
|
423
|
-
// Type definition
|
|
424
|
-
registry.register(types.base, builders.buildTypeDefinition(contentType), getConfig(KINDS.type));
|
|
425
|
-
// Higher level entity definition
|
|
426
|
-
registry.register(types.entity, builders.buildEntityDefinition(contentType), getConfig(KINDS.entity));
|
|
427
|
-
// Responses definition
|
|
428
|
-
registry.register(types.response, builders.buildResponseDefinition(contentType), getConfig(KINDS.entityResponse));
|
|
429
|
-
registry.register(types.responseCollection, builders.buildResponseCollectionDefinition(contentType), getConfig(KINDS.entityResponseCollection));
|
|
430
|
-
registry.register(types.relationResponseCollection, builders.buildRelationResponseCollectionDefinition(contentType), getConfig(KINDS.relationResponseCollection));
|
|
431
|
-
if (extension.shadowCRUD(contentType.uid).areQueriesEnabled()) {
|
|
432
|
-
// Query extensions
|
|
433
|
-
registry.register(types.queries, builders.buildCollectionTypeQueries(contentType), getConfig(KINDS.query));
|
|
434
|
-
}
|
|
435
|
-
if (extension.shadowCRUD(contentType.uid).areMutationsEnabled()) {
|
|
436
|
-
// Mutation extensions
|
|
437
|
-
registry.register(types.mutations, builders.buildCollectionTypeMutations(contentType), getConfig(KINDS.mutation));
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
const registerSingleType = (contentType, { registry, strapi, builders })=>{
|
|
442
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
443
|
-
const { naming } = getService('utils');
|
|
444
|
-
const { KINDS } = getService('constants');
|
|
445
|
-
const extension = getService('extension');
|
|
446
|
-
const types = {
|
|
447
|
-
base: naming.getTypeName(contentType),
|
|
448
|
-
entity: naming.getEntityName(contentType),
|
|
449
|
-
response: naming.getEntityResponseName(contentType),
|
|
450
|
-
responseCollection: naming.getEntityResponseCollectionName(contentType),
|
|
451
|
-
relationResponseCollection: naming.getRelationResponseCollectionName(contentType),
|
|
452
|
-
queries: naming.getEntityQueriesTypeName(contentType),
|
|
453
|
-
mutations: naming.getEntityMutationsTypeName(contentType)
|
|
454
|
-
};
|
|
455
|
-
const getConfig = (kind)=>({
|
|
456
|
-
kind,
|
|
457
|
-
contentType
|
|
458
|
-
});
|
|
459
|
-
// Single type's definition
|
|
460
|
-
registry.register(types.base, builders.buildTypeDefinition(contentType), getConfig(KINDS.type));
|
|
461
|
-
// Higher level entity definition
|
|
462
|
-
registry.register(types.entity, builders.buildEntityDefinition(contentType), getConfig(KINDS.entity));
|
|
463
|
-
// Responses definition
|
|
464
|
-
registry.register(types.response, builders.buildResponseDefinition(contentType), getConfig(KINDS.entityResponse));
|
|
465
|
-
// Response collection definition
|
|
466
|
-
registry.register(types.responseCollection, builders.buildResponseCollectionDefinition(contentType), getConfig(KINDS.entityResponseCollection));
|
|
467
|
-
registry.register(types.relationResponseCollection, builders.buildRelationResponseCollectionDefinition(contentType), getConfig(KINDS.relationResponseCollection));
|
|
468
|
-
if (extension.shadowCRUD(contentType.uid).areQueriesEnabled()) {
|
|
469
|
-
// Queries
|
|
470
|
-
registry.register(types.queries, builders.buildSingleTypeQueries(contentType), getConfig(KINDS.query));
|
|
471
|
-
}
|
|
472
|
-
if (extension.shadowCRUD(contentType.uid).areMutationsEnabled()) {
|
|
473
|
-
// Mutations
|
|
474
|
-
registry.register(types.mutations, builders.buildSingleTypeMutations(contentType), getConfig(KINDS.mutation));
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
const registerComponent = (contentType, { registry, strapi, builders })=>{
|
|
479
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
480
|
-
const { getComponentName } = getService('utils').naming;
|
|
481
|
-
const { KINDS } = getService('constants');
|
|
482
|
-
const name = getComponentName(contentType);
|
|
483
|
-
const definition = builders.buildTypeDefinition(contentType);
|
|
484
|
-
registry.register(name, definition, {
|
|
485
|
-
kind: KINDS.component,
|
|
486
|
-
contentType
|
|
487
|
-
});
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
const registerPolymorphicContentType = (contentType, { registry, strapi })=>{
|
|
491
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
492
|
-
const { naming, attributes: { isMorphRelation } } = getService('utils');
|
|
493
|
-
const { KINDS } = getService('constants');
|
|
494
|
-
const { attributes = {} } = contentType;
|
|
495
|
-
// Isolate its polymorphic attributes
|
|
496
|
-
const morphAttributes = Object.entries(attributes).filter(([, attribute])=>isMorphRelation(attribute));
|
|
497
|
-
// For each one of those polymorphic attribute
|
|
498
|
-
for (const [attributeName, attribute] of morphAttributes){
|
|
499
|
-
const name = naming.getMorphRelationTypeName(contentType, attributeName);
|
|
500
|
-
const { target } = attribute;
|
|
501
|
-
// Ignore those whose target is not an array
|
|
502
|
-
if (!Array.isArray(target)) {
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
// Transform target UIDs into types names
|
|
506
|
-
const members = target// Get content types definitions
|
|
507
|
-
.map((uid)=>strapi.getModel(uid))// Resolve types names
|
|
508
|
-
.map((contentType)=>naming.getTypeName(contentType));
|
|
509
|
-
// Register the new polymorphic union type
|
|
510
|
-
registry.register(name, unionType({
|
|
511
|
-
name,
|
|
512
|
-
resolveType (obj) {
|
|
513
|
-
const contentType = strapi.getModel(obj.__type);
|
|
514
|
-
if (!contentType) {
|
|
515
|
-
return null;
|
|
516
|
-
}
|
|
517
|
-
if (contentType.modelType === 'component') {
|
|
518
|
-
return naming.getComponentName(contentType);
|
|
519
|
-
}
|
|
520
|
-
return naming.getTypeName(contentType);
|
|
521
|
-
},
|
|
522
|
-
definition (t) {
|
|
523
|
-
t.members(...members);
|
|
524
|
-
}
|
|
525
|
-
}), {
|
|
526
|
-
kind: KINDS.morph,
|
|
527
|
-
contentType,
|
|
528
|
-
attributeName
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
const registerScalars = ({ registry, strapi })=>{
|
|
534
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
535
|
-
const { scalars } = getService('internals');
|
|
536
|
-
const { KINDS } = getService('constants');
|
|
537
|
-
Object.entries(scalars).forEach(([name, definition])=>{
|
|
538
|
-
registry.register(name, definition, {
|
|
539
|
-
kind: KINDS.scalar
|
|
540
|
-
});
|
|
541
|
-
});
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
const registerInternals = ({ registry, strapi })=>{
|
|
545
|
-
const { buildInternalTypes } = strapi.plugin('graphql').service('internals');
|
|
546
|
-
const internalTypes = buildInternalTypes({
|
|
547
|
-
strapi
|
|
548
|
-
});
|
|
549
|
-
for (const [kind, definitions] of Object.entries(internalTypes)){
|
|
550
|
-
registry.registerMany(Object.entries(definitions), {
|
|
551
|
-
kind
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
const registerDynamicZonesDefinition = (contentType, { registry, strapi, builders })=>{
|
|
557
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
558
|
-
const { naming, attributes: { isDynamicZone } } = getService('utils');
|
|
559
|
-
const { KINDS } = getService('constants');
|
|
560
|
-
const { attributes } = contentType;
|
|
561
|
-
const dynamicZoneAttributes = Object.keys(attributes).filter((attributeName)=>isDynamicZone(attributes[attributeName]));
|
|
562
|
-
for (const attributeName of dynamicZoneAttributes){
|
|
563
|
-
const attribute = attributes[attributeName];
|
|
564
|
-
const dzName = naming.getDynamicZoneName(contentType, attributeName);
|
|
565
|
-
const dzInputName = naming.getDynamicZoneInputName(contentType, attributeName);
|
|
566
|
-
const [type, input] = builders.buildDynamicZoneDefinition(attribute, dzName, dzInputName);
|
|
567
|
-
const baseConfig = {
|
|
568
|
-
contentType,
|
|
569
|
-
attributeName,
|
|
570
|
-
attribute
|
|
571
|
-
};
|
|
572
|
-
registry.register(dzName, type, {
|
|
573
|
-
kind: KINDS.dynamicZone,
|
|
574
|
-
...baseConfig
|
|
575
|
-
});
|
|
576
|
-
registry.register(dzInputName, input, {
|
|
577
|
-
kind: KINDS.input,
|
|
578
|
-
...baseConfig
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
const registerEnumsDefinition = (contentType, { registry, strapi, builders })=>{
|
|
584
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
585
|
-
const { naming, attributes: { isEnumeration } } = getService('utils');
|
|
586
|
-
const { KINDS } = getService('constants');
|
|
587
|
-
const { attributes } = contentType;
|
|
588
|
-
const enumAttributes = Object.keys(attributes).filter((attributeName)=>isEnumeration(attributes[attributeName]));
|
|
589
|
-
for (const attributeName of enumAttributes){
|
|
590
|
-
const attribute = attributes[attributeName];
|
|
591
|
-
const enumName = naming.getEnumName(contentType, attributeName);
|
|
592
|
-
const enumDefinition = builders.buildEnumTypeDefinition(attribute, enumName);
|
|
593
|
-
registry.register(enumName, enumDefinition, {
|
|
594
|
-
kind: KINDS.enum,
|
|
595
|
-
contentType,
|
|
596
|
-
attributeName,
|
|
597
|
-
attribute
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
const registerInputsDefinition = (contentType, { registry, strapi, builders })=>{
|
|
603
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
604
|
-
const { getComponentInputName, getContentTypeInputName } = getService('utils').naming;
|
|
605
|
-
const { KINDS } = getService('constants');
|
|
606
|
-
const { modelType } = contentType;
|
|
607
|
-
const type = (modelType === 'component' ? getComponentInputName : getContentTypeInputName).call(null, contentType);
|
|
608
|
-
const definition = builders.buildInputType(contentType);
|
|
609
|
-
registry.register(type, definition, {
|
|
610
|
-
kind: KINDS.input,
|
|
611
|
-
contentType
|
|
612
|
-
});
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
const registerFiltersDefinition = (contentType, { registry, strapi, builders })=>{
|
|
616
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
617
|
-
const { getFiltersInputTypeName } = getService('utils').naming;
|
|
618
|
-
const { KINDS } = getService('constants');
|
|
619
|
-
const type = getFiltersInputTypeName(contentType);
|
|
620
|
-
const definition = builders.buildContentTypeFilters(contentType);
|
|
621
|
-
registry.register(type, definition, {
|
|
622
|
-
kind: KINDS.filtersInput,
|
|
623
|
-
contentType
|
|
624
|
-
});
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
var contentAPI = (({ strapi })=>{
|
|
628
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
629
|
-
const { mergeSchemas, addResolversToSchema } = require('@graphql-tools/schema');
|
|
630
|
-
const { service: getGraphQLService } = strapi.plugin('graphql');
|
|
631
|
-
const { config } = strapi.plugin('graphql');
|
|
632
|
-
const { KINDS, GENERIC_MORPH_TYPENAME } = getGraphQLService('constants');
|
|
633
|
-
const extensionService = getGraphQLService('extension');
|
|
634
|
-
// Type Registry
|
|
635
|
-
let registry;
|
|
636
|
-
// Builders Instances
|
|
637
|
-
let builders;
|
|
638
|
-
const buildSchema = ()=>{
|
|
639
|
-
const isShadowCRUDEnabled = !!config('shadowCRUD');
|
|
640
|
-
// Create a new empty type registry
|
|
641
|
-
registry = getGraphQLService('type-registry').new();
|
|
642
|
-
// Reset the builders instances associated to the
|
|
643
|
-
// content-api, and link the new type registry
|
|
644
|
-
builders = getGraphQLService('builders').new('content-api', registry);
|
|
645
|
-
registerScalars({
|
|
646
|
-
registry,
|
|
647
|
-
strapi
|
|
648
|
-
});
|
|
649
|
-
registerInternals({
|
|
650
|
-
registry,
|
|
651
|
-
strapi
|
|
652
|
-
});
|
|
653
|
-
if (isShadowCRUDEnabled) {
|
|
654
|
-
shadowCRUD();
|
|
655
|
-
}
|
|
656
|
-
// Build a merged schema from both Nexus types & SDL type definitions
|
|
657
|
-
const schema = buildMergedSchema({
|
|
658
|
-
registry
|
|
659
|
-
});
|
|
660
|
-
// Generate the extension configuration for the content API.
|
|
661
|
-
// This extension instance needs to be generated after the Nexus schema's
|
|
662
|
-
// generation, so that configurations created during types definitions
|
|
663
|
-
// can be registered before being used in the wrap resolvers operation
|
|
664
|
-
const extension = extensionService.generate({
|
|
665
|
-
typeRegistry: registry
|
|
666
|
-
});
|
|
667
|
-
// Add the extension's resolvers to the final schema
|
|
668
|
-
const schemaWithResolvers = addResolversToSchema({
|
|
669
|
-
schema,
|
|
670
|
-
resolvers: extension.resolvers
|
|
671
|
-
});
|
|
672
|
-
// Create a configuration object for the artifacts generation
|
|
673
|
-
const outputs = {
|
|
674
|
-
schema: config('artifacts.schema', false),
|
|
675
|
-
typegen: config('artifacts.typegen', false)
|
|
676
|
-
};
|
|
677
|
-
const currentEnv = strapi.config.get('environment');
|
|
678
|
-
const nexusSchema = makeSchema({
|
|
679
|
-
types: [],
|
|
680
|
-
// Build the schema from the merged GraphQL schema.
|
|
681
|
-
// Since we're passing the schema to the mergeSchema property, it'll transform our SDL type definitions
|
|
682
|
-
// into Nexus type definition, thus allowing them to be handled by Nexus plugins & other processing
|
|
683
|
-
mergeSchema: {
|
|
684
|
-
schema: schemaWithResolvers
|
|
685
|
-
},
|
|
686
|
-
// Apply user-defined plugins
|
|
687
|
-
plugins: extension.plugins,
|
|
688
|
-
// Whether to generate artifacts (GraphQL schema, TS types definitions) or not.
|
|
689
|
-
// By default, we generate artifacts only on development environment
|
|
690
|
-
shouldGenerateArtifacts: config('generateArtifacts', currentEnv === 'development'),
|
|
691
|
-
// Artifacts generation configuration
|
|
692
|
-
outputs
|
|
693
|
-
});
|
|
694
|
-
// Wrap resolvers if needed (auth, middlewares, policies...) as configured in the extension
|
|
695
|
-
const wrappedNexusSchema = wrapResolvers({
|
|
696
|
-
schema: nexusSchema,
|
|
697
|
-
strapi,
|
|
698
|
-
extension
|
|
699
|
-
});
|
|
700
|
-
// Prune schema, remove unused types
|
|
701
|
-
// eg: removes registered subscriptions if they're disabled in the config)
|
|
702
|
-
const prunedNexusSchema = pruneSchema(wrappedNexusSchema);
|
|
703
|
-
return prunedNexusSchema;
|
|
704
|
-
};
|
|
705
|
-
const buildMergedSchema = ({ registry })=>{
|
|
706
|
-
// Here we extract types, plugins & typeDefs from a temporary generated
|
|
707
|
-
// extension since there won't be any addition allowed after schemas generation
|
|
708
|
-
const { types, typeDefs = [] } = extensionService.generate({
|
|
709
|
-
typeRegistry: registry
|
|
710
|
-
});
|
|
711
|
-
// Nexus schema built with user-defined & shadow CRUD auto generated Nexus types
|
|
712
|
-
const nexusSchema = makeSchema({
|
|
713
|
-
types: [
|
|
714
|
-
registry.definitions,
|
|
715
|
-
types
|
|
716
|
-
]
|
|
717
|
-
});
|
|
718
|
-
// Merge type definitions with the Nexus schema
|
|
719
|
-
return mergeSchemas({
|
|
720
|
-
typeDefs,
|
|
721
|
-
// Give access to the shadowCRUD & nexus based types
|
|
722
|
-
// Note: This is necessary so that types defined in SDL can reference types defined with Nexus
|
|
723
|
-
schemas: [
|
|
724
|
-
nexusSchema
|
|
725
|
-
]
|
|
726
|
-
});
|
|
727
|
-
};
|
|
728
|
-
const shadowCRUD = ()=>{
|
|
729
|
-
const extensionService = getGraphQLService('extension');
|
|
730
|
-
// Get every content type & component defined in Strapi
|
|
731
|
-
const contentTypes = [
|
|
732
|
-
...Object.values(strapi.components),
|
|
733
|
-
...Object.values(strapi.contentTypes)
|
|
734
|
-
];
|
|
735
|
-
// Disable Shadow CRUD for admin content types
|
|
736
|
-
contentTypes.map(prop('uid')).filter(startsWith('admin::')).forEach((uid)=>extensionService.shadowCRUD(uid).disable());
|
|
737
|
-
const contentTypesWithShadowCRUD = contentTypes.filter((ct)=>extensionService.shadowCRUD(ct.uid).isEnabled());
|
|
738
|
-
// Generate and register definitions for every content type
|
|
739
|
-
registerAPITypes(contentTypesWithShadowCRUD);
|
|
740
|
-
// Generate and register polymorphic types' definitions
|
|
741
|
-
registerMorphTypes(contentTypesWithShadowCRUD);
|
|
742
|
-
};
|
|
743
|
-
/**
|
|
744
|
-
* Register needed GraphQL types for every content type
|
|
745
|
-
* @param {object[]} contentTypes
|
|
746
|
-
*/ const registerAPITypes = (contentTypes)=>{
|
|
747
|
-
for (const contentType of contentTypes){
|
|
748
|
-
const { modelType } = contentType;
|
|
749
|
-
const registerOptions = {
|
|
750
|
-
registry,
|
|
751
|
-
strapi,
|
|
752
|
-
builders
|
|
753
|
-
};
|
|
754
|
-
// Generate various types associated to the content type
|
|
755
|
-
// (enums, dynamic-zones, filters, inputs...)
|
|
756
|
-
registerEnumsDefinition(contentType, registerOptions);
|
|
757
|
-
registerDynamicZonesDefinition(contentType, registerOptions);
|
|
758
|
-
registerFiltersDefinition(contentType, registerOptions);
|
|
759
|
-
registerInputsDefinition(contentType, registerOptions);
|
|
760
|
-
// Generate & register component's definition
|
|
761
|
-
if (modelType === 'component') {
|
|
762
|
-
registerComponent(contentType, registerOptions);
|
|
763
|
-
continue;
|
|
764
|
-
}
|
|
765
|
-
const { kind } = contentType;
|
|
766
|
-
// Generate & register single type's definition
|
|
767
|
-
if (kind === 'singleType') {
|
|
768
|
-
registerSingleType(contentType, registerOptions);
|
|
769
|
-
} else if (kind === 'collectionType') {
|
|
770
|
-
registerCollectionType(contentType, registerOptions);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
};
|
|
774
|
-
const registerMorphTypes = (contentTypes)=>{
|
|
775
|
-
// Create & register a union type that includes every type or component registered
|
|
776
|
-
const genericMorphType = builders.buildGenericMorphDefinition();
|
|
777
|
-
registry.register(GENERIC_MORPH_TYPENAME, genericMorphType, {
|
|
778
|
-
kind: KINDS.morph
|
|
779
|
-
});
|
|
780
|
-
for (const contentType of contentTypes){
|
|
781
|
-
registerPolymorphicContentType(contentType, {
|
|
782
|
-
registry,
|
|
783
|
-
strapi
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
return {
|
|
788
|
-
buildSchema
|
|
789
|
-
};
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
const { ApplicationError: ApplicationError$4 } = errors;
|
|
793
|
-
/**
|
|
794
|
-
* Create a new type registry
|
|
795
|
-
*/ const createTypeRegistry = ()=>{
|
|
796
|
-
const registry = new Map();
|
|
797
|
-
const typeRegistry = {
|
|
798
|
-
/**
|
|
799
|
-
* Register a new type definition
|
|
800
|
-
*/ register (name, definition, config = {}) {
|
|
801
|
-
if (registry.has(name)) {
|
|
802
|
-
throw new ApplicationError$4(`"${name}" has already been registered`);
|
|
803
|
-
}
|
|
804
|
-
registry.set(name, {
|
|
805
|
-
name,
|
|
806
|
-
definition,
|
|
807
|
-
config
|
|
808
|
-
});
|
|
809
|
-
return this;
|
|
810
|
-
},
|
|
811
|
-
/**
|
|
812
|
-
* Register many types definitions at once
|
|
813
|
-
* @param {[string, NexusAcceptedTypeDef][]} definitionsEntries
|
|
814
|
-
* @param {object | function} [config]
|
|
815
|
-
*/ registerMany (definitionsEntries, config = {}) {
|
|
816
|
-
for (const [name, definition] of definitionsEntries){
|
|
817
|
-
this.register(name, definition, isFunction(config) ? config(name, definition) : config);
|
|
818
|
-
}
|
|
819
|
-
return this;
|
|
820
|
-
},
|
|
821
|
-
/**
|
|
822
|
-
* Check if the given type name has already been added to the registry
|
|
823
|
-
* @param {string} name
|
|
824
|
-
* @return {boolean}
|
|
825
|
-
*/ has (name) {
|
|
826
|
-
return registry.has(name);
|
|
827
|
-
},
|
|
828
|
-
/**
|
|
829
|
-
* Get the type definition for `name`
|
|
830
|
-
* @param {string} name - The name of the type
|
|
831
|
-
*/ get (name) {
|
|
832
|
-
return registry.get(name);
|
|
833
|
-
},
|
|
834
|
-
/**
|
|
835
|
-
* Transform and return the registry as an object
|
|
836
|
-
* @return {Object<string, RegisteredTypeDef>}
|
|
837
|
-
*/ toObject () {
|
|
838
|
-
return Object.fromEntries(registry.entries());
|
|
839
|
-
},
|
|
840
|
-
/**
|
|
841
|
-
* Return the name of every registered type
|
|
842
|
-
* @return {string[]}
|
|
843
|
-
*/ get types () {
|
|
844
|
-
return Array.from(registry.keys());
|
|
845
|
-
},
|
|
846
|
-
/**
|
|
847
|
-
* Return all the registered definitions as an array
|
|
848
|
-
* @return {RegisteredTypeDef[]}
|
|
849
|
-
*/ get definitions () {
|
|
850
|
-
return Array.from(registry.values());
|
|
851
|
-
},
|
|
852
|
-
/**
|
|
853
|
-
* Filter and return the types definitions that matches the given predicate
|
|
854
|
-
* @param {function(RegisteredTypeDef): boolean} predicate
|
|
855
|
-
* @return {RegisteredTypeDef[]}
|
|
856
|
-
*/ where (predicate) {
|
|
857
|
-
return this.definitions.filter(predicate);
|
|
858
|
-
}
|
|
859
|
-
};
|
|
860
|
-
return typeRegistry;
|
|
861
|
-
};
|
|
862
|
-
var typeRegistry = (()=>({
|
|
863
|
-
new: createTypeRegistry
|
|
864
|
-
}));
|
|
865
|
-
|
|
866
|
-
const { ApplicationError: ApplicationError$3 } = errors;
|
|
867
|
-
var strapiScalarToGraphQLScalar = (({ strapi })=>{
|
|
868
|
-
const { STRAPI_SCALARS, SCALARS_ASSOCIATIONS } = strapi.plugin('graphql').service('constants');
|
|
869
|
-
const missingStrapiScalars = difference(STRAPI_SCALARS, Object.keys(SCALARS_ASSOCIATIONS));
|
|
870
|
-
if (missingStrapiScalars.length > 0) {
|
|
871
|
-
throw new ApplicationError$3('Some Strapi scalars are not handled in the GraphQL scalars mapper');
|
|
872
|
-
}
|
|
873
|
-
return {
|
|
874
|
-
/**
|
|
875
|
-
* Used to transform a Strapi scalar type into its GraphQL equivalent
|
|
876
|
-
*/ strapiScalarToGraphQLScalar (strapiScalar) {
|
|
877
|
-
return get(strapiScalar, SCALARS_ASSOCIATIONS);
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
});
|
|
881
|
-
|
|
882
|
-
// todo[v4]: Find a way to get that dynamically
|
|
883
|
-
const virtualScalarAttributes = [
|
|
884
|
-
'id',
|
|
885
|
-
'documentId'
|
|
886
|
-
];
|
|
887
|
-
var graphQLFiltersToStrapiQuery = (({ strapi })=>{
|
|
888
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
889
|
-
const recursivelyReplaceScalarOperators = (data)=>{
|
|
890
|
-
const { operators } = getService('builders').filters;
|
|
891
|
-
if (Array.isArray(data)) {
|
|
892
|
-
return data.map(recursivelyReplaceScalarOperators);
|
|
893
|
-
}
|
|
894
|
-
// Note: We need to make an exception for date since GraphQL
|
|
895
|
-
// automatically cast date strings to date instances in args
|
|
896
|
-
if (isDate(data) || !isObject(data)) {
|
|
897
|
-
return data;
|
|
898
|
-
}
|
|
899
|
-
const result = {};
|
|
900
|
-
for (const [key, value] of Object.entries(data)){
|
|
901
|
-
const isOperator = !!operators[key];
|
|
902
|
-
const newKey = isOperator ? operators[key].strapiOperator : key;
|
|
903
|
-
result[newKey] = recursivelyReplaceScalarOperators(value);
|
|
904
|
-
}
|
|
905
|
-
return result;
|
|
906
|
-
};
|
|
907
|
-
return {
|
|
908
|
-
/**
|
|
909
|
-
* Transform one or many GraphQL filters object into a valid Strapi query
|
|
910
|
-
* @param {object | object[]} filters
|
|
911
|
-
* @param {object} contentType
|
|
912
|
-
* @return {object | object[]}
|
|
913
|
-
*/ graphQLFiltersToStrapiQuery (filters, contentType) {
|
|
914
|
-
const { isStrapiScalar, isMedia, isRelation, isComponent } = getService('utils').attributes;
|
|
915
|
-
const { operators } = getService('builders').filters;
|
|
916
|
-
const ROOT_LEVEL_OPERATORS = [
|
|
917
|
-
operators.and,
|
|
918
|
-
operators.or,
|
|
919
|
-
operators.not
|
|
920
|
-
];
|
|
921
|
-
// Handle unwanted scenario where there is no filters defined
|
|
922
|
-
if (isNil(filters)) {
|
|
923
|
-
return {};
|
|
924
|
-
}
|
|
925
|
-
// If filters is a collection, then apply the transformation to every item of the list
|
|
926
|
-
if (Array.isArray(filters)) {
|
|
927
|
-
return filters.map((filtersItem)=>this.graphQLFiltersToStrapiQuery(filtersItem, contentType));
|
|
928
|
-
}
|
|
929
|
-
const resultMap = {};
|
|
930
|
-
const { attributes } = contentType;
|
|
931
|
-
const isAttribute = (attributeName)=>{
|
|
932
|
-
return virtualScalarAttributes.includes(attributeName) || has(attributeName, attributes);
|
|
933
|
-
};
|
|
934
|
-
for (const [key, value] of Object.entries(filters)){
|
|
935
|
-
// If the key is an attribute, update the value
|
|
936
|
-
if (isAttribute(key)) {
|
|
937
|
-
const attribute = attributes[key];
|
|
938
|
-
// If it's a scalar attribute
|
|
939
|
-
if (virtualScalarAttributes.includes(key) || isStrapiScalar(attribute)) {
|
|
940
|
-
// Replace (recursively) every GraphQL scalar operator with the associated Strapi operator
|
|
941
|
-
resultMap[key] = recursivelyReplaceScalarOperators(value);
|
|
942
|
-
} else if (isRelation(attribute) || isMedia(attribute)) {
|
|
943
|
-
// Fetch the model from the relation
|
|
944
|
-
const relModel = strapi.getModel(attribute.target);
|
|
945
|
-
// Recursively apply the mapping to the value using the fetched model,
|
|
946
|
-
// and update the value within `resultMap`
|
|
947
|
-
resultMap[key] = this.graphQLFiltersToStrapiQuery(value, relModel);
|
|
948
|
-
} else if (isComponent(attribute)) {
|
|
949
|
-
// Fetch the model from the component attribute
|
|
950
|
-
const componentModel = strapi.getModel(attribute.component);
|
|
951
|
-
// Recursively apply the mapping to the value using the fetched model,
|
|
952
|
-
// and update the value within `resultMap`
|
|
953
|
-
resultMap[key] = this.graphQLFiltersToStrapiQuery(value, componentModel);
|
|
954
|
-
}
|
|
955
|
-
} else {
|
|
956
|
-
const rootLevelOperator = ROOT_LEVEL_OPERATORS.find(propEq('fieldName', key));
|
|
957
|
-
// If it's a root level operator (AND, NOT, OR, ...)
|
|
958
|
-
if (rootLevelOperator) {
|
|
959
|
-
const { strapiOperator } = rootLevelOperator;
|
|
960
|
-
// Transform the current value recursively and add it to the resultMap
|
|
961
|
-
// object using the strapiOperator equivalent of the GraphQL key
|
|
962
|
-
resultMap[strapiOperator] = this.graphQLFiltersToStrapiQuery(value, contentType);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
return resultMap;
|
|
967
|
-
}
|
|
968
|
-
};
|
|
969
|
-
});
|
|
970
|
-
|
|
971
|
-
var graphqlScalarToOperators = (({ strapi })=>({
|
|
972
|
-
graphqlScalarToOperators (graphqlScalar) {
|
|
973
|
-
const { GRAPHQL_SCALAR_OPERATORS } = strapi.plugin('graphql').service('constants');
|
|
974
|
-
const { operators } = strapi.plugin('graphql').service('builders').filters;
|
|
975
|
-
const associations = mapValues(map((operatorName)=>operators[operatorName]), GRAPHQL_SCALAR_OPERATORS);
|
|
976
|
-
return get(graphqlScalar, associations);
|
|
977
|
-
}
|
|
978
|
-
}));
|
|
979
|
-
|
|
980
|
-
const entityToResponseEntity = (entity)=>({
|
|
981
|
-
id: entity.id,
|
|
982
|
-
attributes: entity
|
|
983
|
-
});
|
|
984
|
-
const entitiesToResponseEntities = map(entityToResponseEntity);
|
|
985
|
-
var entityToResponseEntity$1 = (()=>({
|
|
986
|
-
entityToResponseEntity,
|
|
987
|
-
entitiesToResponseEntities
|
|
988
|
-
}));
|
|
989
|
-
|
|
990
|
-
var mappers = ((context)=>({
|
|
991
|
-
...strapiScalarToGraphQLScalar(context),
|
|
992
|
-
...graphQLFiltersToStrapiQuery(context),
|
|
993
|
-
...graphqlScalarToOperators(context),
|
|
994
|
-
...entityToResponseEntity$1()
|
|
995
|
-
}));
|
|
996
|
-
|
|
997
|
-
var attributes = (({ strapi })=>{
|
|
998
|
-
/**
|
|
999
|
-
* Check if the given attribute is a Strapi scalar
|
|
1000
|
-
* @param {object} attribute
|
|
1001
|
-
* @return {boolean}
|
|
1002
|
-
*/ const isStrapiScalar = (attribute)=>{
|
|
1003
|
-
return strapi.plugin('graphql').service('constants').STRAPI_SCALARS.includes(attribute.type);
|
|
1004
|
-
};
|
|
1005
|
-
/**
|
|
1006
|
-
* Check if the given attribute is a GraphQL scalar
|
|
1007
|
-
* @param {object} attribute
|
|
1008
|
-
* @return {boolean}
|
|
1009
|
-
*/ const isGraphQLScalar = (attribute)=>{
|
|
1010
|
-
return strapi.plugin('graphql').service('constants').GRAPHQL_SCALARS.includes(attribute.type);
|
|
1011
|
-
};
|
|
1012
|
-
/**
|
|
1013
|
-
* Check if the given attribute is a polymorphic relation
|
|
1014
|
-
* @param {object} attribute
|
|
1015
|
-
* @return {boolean}
|
|
1016
|
-
*/ const isMorphRelation = (attribute)=>{
|
|
1017
|
-
return attribute.type === 'relation' && attribute.relation.includes('morph');
|
|
1018
|
-
};
|
|
1019
|
-
/**
|
|
1020
|
-
* Check if the given attribute is a media
|
|
1021
|
-
* @param {object} attribute
|
|
1022
|
-
* @return {boolean}
|
|
1023
|
-
*/ const isMedia = propEq('type', 'media');
|
|
1024
|
-
/**
|
|
1025
|
-
* Check if the given attribute is a relation
|
|
1026
|
-
* @param {object} attribute
|
|
1027
|
-
* @return {boolean}
|
|
1028
|
-
*/ const isRelation = propEq('type', 'relation');
|
|
1029
|
-
/**
|
|
1030
|
-
* Check if the given attribute is an enum
|
|
1031
|
-
* @param {object} attribute
|
|
1032
|
-
* @return {boolean}
|
|
1033
|
-
*/ const isEnumeration = propEq('type', 'enumeration');
|
|
1034
|
-
/**
|
|
1035
|
-
* Check if the given attribute is a component
|
|
1036
|
-
* @param {object} attribute
|
|
1037
|
-
* @return {boolean}
|
|
1038
|
-
*/ const isComponent = propEq('type', 'component');
|
|
1039
|
-
/**
|
|
1040
|
-
* Check if the given attribute is a dynamic zone
|
|
1041
|
-
* @param {object} attribute
|
|
1042
|
-
* @return {boolean}
|
|
1043
|
-
*/ const isDynamicZone = propEq('type', 'dynamiczone');
|
|
1044
|
-
return {
|
|
1045
|
-
isStrapiScalar,
|
|
1046
|
-
isGraphQLScalar,
|
|
1047
|
-
isMorphRelation,
|
|
1048
|
-
isMedia,
|
|
1049
|
-
isRelation,
|
|
1050
|
-
isEnumeration,
|
|
1051
|
-
isComponent,
|
|
1052
|
-
isDynamicZone
|
|
1053
|
-
};
|
|
1054
|
-
});
|
|
1055
|
-
|
|
1056
|
-
const { ApplicationError: ApplicationError$2 } = errors;
|
|
1057
|
-
var naming = (({ strapi })=>{
|
|
1058
|
-
/**
|
|
1059
|
-
* Build a type name for a enum based on a content type & an attribute name
|
|
1060
|
-
*/ const getEnumName = (contentType, attributeName)=>{
|
|
1061
|
-
const { attributes } = contentType;
|
|
1062
|
-
const { enumName } = attributes[attributeName];
|
|
1063
|
-
const { modelType } = contentType;
|
|
1064
|
-
const typeName = modelType === 'component' ? getComponentName(contentType) : getTypeName(contentType);
|
|
1065
|
-
const defaultEnumName = `ENUM_${typeName.toUpperCase()}_${attributeName.toUpperCase()}`;
|
|
1066
|
-
return enumName || defaultEnumName;
|
|
1067
|
-
};
|
|
1068
|
-
/**
|
|
1069
|
-
* Build the base type name for a given content type
|
|
1070
|
-
*/ const getTypeName = (contentType, { plurality = 'singular' } = {})=>{
|
|
1071
|
-
const plugin = get('plugin', contentType);
|
|
1072
|
-
const modelName = get('modelName', contentType);
|
|
1073
|
-
const name = plurality === 'singular' ? get('info.singularName', contentType) : get('info.pluralName', contentType);
|
|
1074
|
-
const transformedPlugin = upperFirst(camelCase(plugin));
|
|
1075
|
-
const transformedModelName = upperFirst(camelCase(name || singular(modelName)));
|
|
1076
|
-
return `${transformedPlugin}${transformedModelName}`;
|
|
1077
|
-
};
|
|
1078
|
-
/**
|
|
1079
|
-
* Build the entity's type name for a given content type
|
|
1080
|
-
*/ const getEntityName = (contentType)=>{
|
|
1081
|
-
return `${getTypeName(contentType)}Entity`;
|
|
1082
|
-
};
|
|
1083
|
-
/**
|
|
1084
|
-
* Build the entity meta type name for a given content type
|
|
1085
|
-
*/ const getEntityMetaName = (contentType)=>{
|
|
1086
|
-
return `${getEntityName(contentType)}Meta`;
|
|
1087
|
-
};
|
|
1088
|
-
/**
|
|
1089
|
-
* Build the entity response's type name for a given content type
|
|
1090
|
-
*/ const getEntityResponseName = (contentType)=>{
|
|
1091
|
-
return `${getEntityName(contentType)}Response`;
|
|
1092
|
-
};
|
|
1093
|
-
/**
|
|
1094
|
-
* Build the entity response collection's type name for a given content type
|
|
1095
|
-
*/ const getEntityResponseCollectionName = (contentType)=>{
|
|
1096
|
-
return `${getEntityName(contentType)}ResponseCollection`;
|
|
1097
|
-
};
|
|
1098
|
-
/**
|
|
1099
|
-
* Build the relation response collection's type name for a given content type
|
|
1100
|
-
*/ const getRelationResponseCollectionName = (contentType)=>{
|
|
1101
|
-
return `${getTypeName(contentType)}RelationResponseCollection`;
|
|
1102
|
-
};
|
|
1103
|
-
/**
|
|
1104
|
-
* Build a component type name based on its definition
|
|
1105
|
-
*/ const getComponentName = (contentType)=>{
|
|
1106
|
-
return contentType.globalId;
|
|
1107
|
-
};
|
|
1108
|
-
/**
|
|
1109
|
-
* Build a component type name based on a content type's attribute
|
|
1110
|
-
*/ const getComponentNameFromAttribute = (attribute)=>{
|
|
1111
|
-
return strapi.components[attribute.component].globalId;
|
|
1112
|
-
};
|
|
1113
|
-
/**
|
|
1114
|
-
* Build a dynamic zone type name based on a content type and an attribute name
|
|
1115
|
-
*/ const getDynamicZoneName = (contentType, attributeName)=>{
|
|
1116
|
-
const typeName = getTypeName(contentType);
|
|
1117
|
-
const dzName = upperFirst(camelCase(attributeName));
|
|
1118
|
-
const suffix = 'DynamicZone';
|
|
1119
|
-
return `${typeName}${dzName}${suffix}`;
|
|
1120
|
-
};
|
|
1121
|
-
/**
|
|
1122
|
-
* Build a dynamic zone input type name based on a content type and an attribute name
|
|
1123
|
-
*/ const getDynamicZoneInputName = (contentType, attributeName)=>{
|
|
1124
|
-
const dzName = getDynamicZoneName(contentType, attributeName);
|
|
1125
|
-
return `${dzName}Input`;
|
|
1126
|
-
};
|
|
1127
|
-
/**
|
|
1128
|
-
* Build a component input type name based on a content type and an attribute name
|
|
1129
|
-
*/ const getComponentInputName = (contentType)=>{
|
|
1130
|
-
const componentName = getComponentName(contentType);
|
|
1131
|
-
return `${componentName}Input`;
|
|
1132
|
-
};
|
|
1133
|
-
/**
|
|
1134
|
-
* Build a content type input name based on a content type and an attribute name
|
|
1135
|
-
*/ const getContentTypeInputName = (contentType)=>{
|
|
1136
|
-
const typeName = getTypeName(contentType);
|
|
1137
|
-
return `${typeName}Input`;
|
|
1138
|
-
};
|
|
1139
|
-
/**
|
|
1140
|
-
* Build the queries type name for a given content type
|
|
1141
|
-
*/ const getEntityQueriesTypeName = (contentType)=>{
|
|
1142
|
-
return `${getEntityName(contentType)}Queries`;
|
|
1143
|
-
};
|
|
1144
|
-
/**
|
|
1145
|
-
* Build the mutations type name for a given content type
|
|
1146
|
-
*/ const getEntityMutationsTypeName = (contentType)=>{
|
|
1147
|
-
return `${getEntityName(contentType)}Mutations`;
|
|
1148
|
-
};
|
|
1149
|
-
/**
|
|
1150
|
-
* Build the filters type name for a given content type
|
|
1151
|
-
*/ const getFiltersInputTypeName = (contentType)=>{
|
|
1152
|
-
const isComponent = contentType.modelType === 'component';
|
|
1153
|
-
const baseName = isComponent ? getComponentName(contentType) : getTypeName(contentType);
|
|
1154
|
-
return `${baseName}FiltersInput`;
|
|
1155
|
-
};
|
|
1156
|
-
/**
|
|
1157
|
-
* Build a filters type name for a given GraphQL scalar type
|
|
1158
|
-
*/ const getScalarFilterInputTypeName = (scalarType)=>{
|
|
1159
|
-
return `${scalarType}FilterInput`;
|
|
1160
|
-
};
|
|
1161
|
-
/**
|
|
1162
|
-
* Build a type name for a given content type & polymorphic attribute
|
|
1163
|
-
*/ const getMorphRelationTypeName = (contentType, attributeName)=>{
|
|
1164
|
-
const typeName = getTypeName(contentType);
|
|
1165
|
-
const formattedAttr = upperFirst(camelCase(attributeName));
|
|
1166
|
-
return `${typeName}${formattedAttr}Morph`;
|
|
1167
|
-
};
|
|
1168
|
-
/**
|
|
1169
|
-
* Build a custom type name generator with different customization options
|
|
1170
|
-
*/ const buildCustomTypeNameGenerator = (options)=>{
|
|
1171
|
-
// todo[v4]: use singularName & pluralName is available
|
|
1172
|
-
const { prefix = '', suffix = '', plurality = 'singular', firstLetterCase = 'upper' } = options;
|
|
1173
|
-
if (![
|
|
1174
|
-
'plural',
|
|
1175
|
-
'singular'
|
|
1176
|
-
].includes(plurality)) {
|
|
1177
|
-
throw new ApplicationError$2(`"plurality" param must be either "plural" or "singular", but got: "${plurality}"`);
|
|
1178
|
-
}
|
|
1179
|
-
const getCustomTypeName = pipe((ct)=>getTypeName(ct, {
|
|
1180
|
-
plurality
|
|
1181
|
-
}), firstLetterCase === 'upper' ? upperFirst : lowerFirst);
|
|
1182
|
-
return (contentType)=>`${prefix}${getCustomTypeName(contentType)}${suffix}`;
|
|
1183
|
-
};
|
|
1184
|
-
const getFindQueryName = buildCustomTypeNameGenerator({
|
|
1185
|
-
plurality: 'plural',
|
|
1186
|
-
firstLetterCase: 'lower'
|
|
1187
|
-
});
|
|
1188
|
-
const getFindConnectionQueryName = (contentType)=>{
|
|
1189
|
-
return `${getFindQueryName(contentType)}_connection`;
|
|
1190
|
-
};
|
|
1191
|
-
const getFindOneQueryName = buildCustomTypeNameGenerator({
|
|
1192
|
-
firstLetterCase: 'lower'
|
|
1193
|
-
});
|
|
1194
|
-
const getCreateMutationTypeName = buildCustomTypeNameGenerator({
|
|
1195
|
-
prefix: 'create',
|
|
1196
|
-
firstLetterCase: 'upper'
|
|
1197
|
-
});
|
|
1198
|
-
const getUpdateMutationTypeName = buildCustomTypeNameGenerator({
|
|
1199
|
-
prefix: 'update',
|
|
1200
|
-
firstLetterCase: 'upper'
|
|
1201
|
-
});
|
|
1202
|
-
const getDeleteMutationTypeName = buildCustomTypeNameGenerator({
|
|
1203
|
-
prefix: 'delete',
|
|
1204
|
-
firstLetterCase: 'upper'
|
|
1205
|
-
});
|
|
1206
|
-
return {
|
|
1207
|
-
getEnumName,
|
|
1208
|
-
getTypeName,
|
|
1209
|
-
getEntityName,
|
|
1210
|
-
getEntityMetaName,
|
|
1211
|
-
getEntityResponseName,
|
|
1212
|
-
getEntityResponseCollectionName,
|
|
1213
|
-
getRelationResponseCollectionName,
|
|
1214
|
-
getComponentName,
|
|
1215
|
-
getComponentNameFromAttribute,
|
|
1216
|
-
getDynamicZoneName,
|
|
1217
|
-
getDynamicZoneInputName,
|
|
1218
|
-
getComponentInputName,
|
|
1219
|
-
getContentTypeInputName,
|
|
1220
|
-
getEntityQueriesTypeName,
|
|
1221
|
-
getEntityMutationsTypeName,
|
|
1222
|
-
getFiltersInputTypeName,
|
|
1223
|
-
getScalarFilterInputTypeName,
|
|
1224
|
-
getMorphRelationTypeName,
|
|
1225
|
-
buildCustomTypeNameGenerator,
|
|
1226
|
-
getFindQueryName,
|
|
1227
|
-
getFindOneQueryName,
|
|
1228
|
-
getCreateMutationTypeName,
|
|
1229
|
-
getUpdateMutationTypeName,
|
|
1230
|
-
getDeleteMutationTypeName,
|
|
1231
|
-
getFindConnectionQueryName
|
|
1232
|
-
};
|
|
1233
|
-
});
|
|
1234
|
-
|
|
1235
|
-
// TODO: deprecate and remove this because it is only used to determine if we need helmet security exceptions
|
|
1236
|
-
// stores the state of the Apollo landingPage (playground)
|
|
1237
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1238
|
-
var playground = ((ctx)=>{
|
|
1239
|
-
let enabled = false;
|
|
1240
|
-
return {
|
|
1241
|
-
setEnabled (val) {
|
|
1242
|
-
enabled = val;
|
|
1243
|
-
},
|
|
1244
|
-
isEnabled () {
|
|
1245
|
-
return enabled;
|
|
1246
|
-
}
|
|
1247
|
-
};
|
|
1248
|
-
});
|
|
1249
|
-
|
|
1250
|
-
var utils$1 = ((context)=>({
|
|
1251
|
-
playground: playground(),
|
|
1252
|
-
naming: naming(context),
|
|
1253
|
-
attributes: attributes(context),
|
|
1254
|
-
mappers: mappers(context)
|
|
1255
|
-
}));
|
|
1256
|
-
|
|
1257
|
-
const PAGINATION_TYPE_NAME = 'Pagination';
|
|
1258
|
-
const DELETE_MUTATION_RESPONSE_TYPE_NAME = 'DeleteMutationResponse';
|
|
1259
|
-
const PUBLICATION_STATUS_TYPE_NAME = 'PublicationStatus';
|
|
1260
|
-
const ERROR_TYPE_NAME = 'Error';
|
|
1261
|
-
const RESPONSE_COLLECTION_META_TYPE_NAME = 'ResponseCollectionMeta';
|
|
1262
|
-
const GRAPHQL_SCALARS = [
|
|
1263
|
-
'ID',
|
|
1264
|
-
'Boolean',
|
|
1265
|
-
'Int',
|
|
1266
|
-
'String',
|
|
1267
|
-
'Long',
|
|
1268
|
-
'Float',
|
|
1269
|
-
'JSON',
|
|
1270
|
-
'Date',
|
|
1271
|
-
'Time',
|
|
1272
|
-
'DateTime'
|
|
1273
|
-
];
|
|
1274
|
-
const STRAPI_SCALARS = [
|
|
1275
|
-
'boolean',
|
|
1276
|
-
'integer',
|
|
1277
|
-
'string',
|
|
1278
|
-
'richtext',
|
|
1279
|
-
'blocks',
|
|
1280
|
-
'enumeration',
|
|
1281
|
-
'biginteger',
|
|
1282
|
-
'float',
|
|
1283
|
-
'decimal',
|
|
1284
|
-
'json',
|
|
1285
|
-
'date',
|
|
1286
|
-
'time',
|
|
1287
|
-
'datetime',
|
|
1288
|
-
'timestamp',
|
|
1289
|
-
'uid',
|
|
1290
|
-
'email',
|
|
1291
|
-
'password',
|
|
1292
|
-
'text'
|
|
1293
|
-
];
|
|
1294
|
-
const SCALARS_ASSOCIATIONS = {
|
|
1295
|
-
uid: 'String',
|
|
1296
|
-
email: 'String',
|
|
1297
|
-
password: 'String',
|
|
1298
|
-
text: 'String',
|
|
1299
|
-
boolean: 'Boolean',
|
|
1300
|
-
integer: 'Int',
|
|
1301
|
-
string: 'String',
|
|
1302
|
-
enumeration: 'String',
|
|
1303
|
-
richtext: 'String',
|
|
1304
|
-
blocks: 'JSON',
|
|
1305
|
-
biginteger: 'Long',
|
|
1306
|
-
float: 'Float',
|
|
1307
|
-
decimal: 'Float',
|
|
1308
|
-
json: 'JSON',
|
|
1309
|
-
date: 'Date',
|
|
1310
|
-
time: 'Time',
|
|
1311
|
-
datetime: 'DateTime',
|
|
1312
|
-
timestamp: 'DateTime'
|
|
1313
|
-
};
|
|
1314
|
-
const GENERIC_MORPH_TYPENAME = 'GenericMorph';
|
|
1315
|
-
const KINDS = {
|
|
1316
|
-
type: 'type',
|
|
1317
|
-
component: 'component',
|
|
1318
|
-
dynamicZone: 'dynamic-zone',
|
|
1319
|
-
enum: 'enum',
|
|
1320
|
-
entity: 'entity',
|
|
1321
|
-
entityResponse: 'entity-response',
|
|
1322
|
-
entityResponseCollection: 'entity-response-collection',
|
|
1323
|
-
relationResponseCollection: 'relation-response-collection',
|
|
1324
|
-
query: 'query',
|
|
1325
|
-
mutation: 'mutation',
|
|
1326
|
-
input: 'input',
|
|
1327
|
-
filtersInput: 'filters-input',
|
|
1328
|
-
scalar: 'scalar',
|
|
1329
|
-
morph: 'polymorphic',
|
|
1330
|
-
internal: 'internal'
|
|
1331
|
-
};
|
|
1332
|
-
const allOperators = [
|
|
1333
|
-
'and',
|
|
1334
|
-
'or',
|
|
1335
|
-
'not',
|
|
1336
|
-
'eq',
|
|
1337
|
-
'eqi',
|
|
1338
|
-
'ne',
|
|
1339
|
-
'nei',
|
|
1340
|
-
'startsWith',
|
|
1341
|
-
'endsWith',
|
|
1342
|
-
'contains',
|
|
1343
|
-
'notContains',
|
|
1344
|
-
'containsi',
|
|
1345
|
-
'notContainsi',
|
|
1346
|
-
'gt',
|
|
1347
|
-
'gte',
|
|
1348
|
-
'lt',
|
|
1349
|
-
'lte',
|
|
1350
|
-
'null',
|
|
1351
|
-
'notNull',
|
|
1352
|
-
'in',
|
|
1353
|
-
'notIn',
|
|
1354
|
-
'between'
|
|
1355
|
-
];
|
|
1356
|
-
const GRAPHQL_SCALAR_OPERATORS = {
|
|
1357
|
-
// ID
|
|
1358
|
-
ID: allOperators,
|
|
1359
|
-
// Booleans
|
|
1360
|
-
Boolean: allOperators,
|
|
1361
|
-
// Strings
|
|
1362
|
-
String: allOperators,
|
|
1363
|
-
// Numbers
|
|
1364
|
-
Int: allOperators,
|
|
1365
|
-
Long: allOperators,
|
|
1366
|
-
Float: allOperators,
|
|
1367
|
-
// Dates
|
|
1368
|
-
Date: allOperators,
|
|
1369
|
-
Time: allOperators,
|
|
1370
|
-
DateTime: allOperators,
|
|
1371
|
-
// Others
|
|
1372
|
-
JSON: allOperators
|
|
1373
|
-
};
|
|
1374
|
-
const ERROR_CODES = {
|
|
1375
|
-
emptyDynamicZone: 'dynamiczone.empty'
|
|
1376
|
-
};
|
|
1377
|
-
var constants = (()=>({
|
|
1378
|
-
PAGINATION_TYPE_NAME,
|
|
1379
|
-
RESPONSE_COLLECTION_META_TYPE_NAME,
|
|
1380
|
-
DELETE_MUTATION_RESPONSE_TYPE_NAME,
|
|
1381
|
-
PUBLICATION_STATUS_TYPE_NAME,
|
|
1382
|
-
GRAPHQL_SCALARS,
|
|
1383
|
-
STRAPI_SCALARS,
|
|
1384
|
-
GENERIC_MORPH_TYPENAME,
|
|
1385
|
-
KINDS,
|
|
1386
|
-
GRAPHQL_SCALAR_OPERATORS,
|
|
1387
|
-
SCALARS_ASSOCIATIONS,
|
|
1388
|
-
ERROR_CODES,
|
|
1389
|
-
ERROR_TYPE_NAME
|
|
1390
|
-
}));
|
|
1391
|
-
|
|
1392
|
-
const SortArg = arg({
|
|
1393
|
-
type: list('String'),
|
|
1394
|
-
default: []
|
|
1395
|
-
});
|
|
1396
|
-
|
|
1397
|
-
var publicationStatus$1 = (({ strapi })=>{
|
|
1398
|
-
const { PUBLICATION_STATUS_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1399
|
-
return arg({
|
|
1400
|
-
type: PUBLICATION_STATUS_TYPE_NAME,
|
|
1401
|
-
default: 'published'
|
|
1402
|
-
});
|
|
1403
|
-
});
|
|
1404
|
-
|
|
1405
|
-
const PaginationInputType = inputObjectType({
|
|
1406
|
-
name: 'PaginationArg',
|
|
1407
|
-
definition (t) {
|
|
1408
|
-
t.int('page');
|
|
1409
|
-
t.int('pageSize');
|
|
1410
|
-
t.int('start');
|
|
1411
|
-
t.int('limit');
|
|
1412
|
-
}
|
|
1413
|
-
});
|
|
1414
|
-
var PaginationArg = arg({
|
|
1415
|
-
type: PaginationInputType,
|
|
1416
|
-
default: {}
|
|
1417
|
-
});
|
|
1418
|
-
|
|
1419
|
-
var args = ((context)=>({
|
|
1420
|
-
SortArg,
|
|
1421
|
-
PaginationArg,
|
|
1422
|
-
PublicationStatusArg: publicationStatus$1(context)
|
|
1423
|
-
}));
|
|
1424
|
-
|
|
1425
|
-
const { ValidationError: ValidationError$2 } = errors;
|
|
1426
|
-
/**
|
|
1427
|
-
* A GraphQL scalar used to store Time (HH:mm:ss.SSS) values
|
|
1428
|
-
* @type {GraphQLScalarType}
|
|
1429
|
-
*/ const TimeScalar = new GraphQLScalarType({
|
|
1430
|
-
name: 'Time',
|
|
1431
|
-
description: 'A time string with format HH:mm:ss.SSS',
|
|
1432
|
-
serialize (value) {
|
|
1433
|
-
return parseType({
|
|
1434
|
-
type: 'time',
|
|
1435
|
-
value
|
|
1436
|
-
});
|
|
1437
|
-
},
|
|
1438
|
-
parseValue (value) {
|
|
1439
|
-
return parseType({
|
|
1440
|
-
type: 'time',
|
|
1441
|
-
value
|
|
1442
|
-
});
|
|
1443
|
-
},
|
|
1444
|
-
parseLiteral (ast) {
|
|
1445
|
-
if (ast.kind !== Kind.STRING) {
|
|
1446
|
-
throw new ValidationError$2('Time cannot represent non string type');
|
|
1447
|
-
}
|
|
1448
|
-
const { value } = ast;
|
|
1449
|
-
return parseType({
|
|
1450
|
-
type: 'time',
|
|
1451
|
-
value
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
});
|
|
1455
|
-
|
|
1456
|
-
const parseAndCast = (parseFn)=>(...args)=>{
|
|
1457
|
-
const parsedValue = parseFn(...args);
|
|
1458
|
-
if (parsedValue instanceof Date) {
|
|
1459
|
-
return parsedValue.toISOString().split('T')[0];
|
|
1460
|
-
}
|
|
1461
|
-
return parsedValue;
|
|
1462
|
-
};
|
|
1463
|
-
// GraphQLDate casts the date string to new Date, we want to keep it as a string so we cast it back to a string
|
|
1464
|
-
// see https://github.com/excitement-engineer/graphql-iso-date/issues/106
|
|
1465
|
-
GraphQLDate.parseValue = parseAndCast(GraphQLDate.parseValue);
|
|
1466
|
-
GraphQLDate.parseLiteral = parseAndCast(GraphQLDate.parseLiteral);
|
|
1467
|
-
|
|
1468
|
-
var scalars = (()=>({
|
|
1469
|
-
JSON: asNexusMethod(GraphQLJSON, 'json'),
|
|
1470
|
-
DateTime: asNexusMethod(GraphQLDateTime, 'dateTime'),
|
|
1471
|
-
Time: asNexusMethod(TimeScalar, 'time'),
|
|
1472
|
-
Date: asNexusMethod(GraphQLDate, 'date'),
|
|
1473
|
-
Long: asNexusMethod(GraphQLLong, 'long')
|
|
1474
|
-
}));
|
|
1475
|
-
|
|
1476
|
-
var pagination = (({ strapi })=>{
|
|
1477
|
-
const { PAGINATION_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1478
|
-
return {
|
|
1479
|
-
/**
|
|
1480
|
-
* Type definition for a Pagination object
|
|
1481
|
-
* @type {NexusObjectTypeDef}
|
|
1482
|
-
*/ Pagination: objectType({
|
|
1483
|
-
name: PAGINATION_TYPE_NAME,
|
|
1484
|
-
definition (t) {
|
|
1485
|
-
t.nonNull.int('total');
|
|
1486
|
-
t.nonNull.int('page');
|
|
1487
|
-
t.nonNull.int('pageSize');
|
|
1488
|
-
t.nonNull.int('pageCount');
|
|
1489
|
-
}
|
|
1490
|
-
})
|
|
1491
|
-
};
|
|
1492
|
-
});
|
|
1493
|
-
|
|
1494
|
-
var buildResponseCollectionMeta = (({ strapi })=>{
|
|
1495
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
1496
|
-
const { RESPONSE_COLLECTION_META_TYPE_NAME, PAGINATION_TYPE_NAME } = getService('constants');
|
|
1497
|
-
return {
|
|
1498
|
-
/**
|
|
1499
|
-
* A shared type definition used in EntitiesResponseCollection
|
|
1500
|
-
* to have information about the collection as a whole
|
|
1501
|
-
* @type {NexusObjectTypeDef}
|
|
1502
|
-
*/ ResponseCollectionMeta: objectType({
|
|
1503
|
-
name: RESPONSE_COLLECTION_META_TYPE_NAME,
|
|
1504
|
-
definition (t) {
|
|
1505
|
-
const { resolvePagination } = getService('builders').get('content-api');
|
|
1506
|
-
t.nonNull.field('pagination', {
|
|
1507
|
-
type: PAGINATION_TYPE_NAME,
|
|
1508
|
-
resolve: resolvePagination
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
})
|
|
1512
|
-
};
|
|
1513
|
-
});
|
|
1514
|
-
|
|
1515
|
-
var buildDeleteMutationResponse = (({ strapi })=>{
|
|
1516
|
-
const { DELETE_MUTATION_RESPONSE_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1517
|
-
return {
|
|
1518
|
-
DeleteMutationResponse: objectType({
|
|
1519
|
-
name: DELETE_MUTATION_RESPONSE_TYPE_NAME,
|
|
1520
|
-
definition (t) {
|
|
1521
|
-
t.nonNull.id('documentId');
|
|
1522
|
-
}
|
|
1523
|
-
})
|
|
1524
|
-
};
|
|
1525
|
-
});
|
|
1526
|
-
|
|
1527
|
-
var publicationStatus = (({ strapi })=>{
|
|
1528
|
-
const { PUBLICATION_STATUS_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1529
|
-
return {
|
|
1530
|
-
/**
|
|
1531
|
-
* An enum type definition representing a publication status
|
|
1532
|
-
* @type {NexusEnumTypeDef}
|
|
1533
|
-
*/ PublicationStatus: enumType({
|
|
1534
|
-
name: PUBLICATION_STATUS_TYPE_NAME,
|
|
1535
|
-
members: {
|
|
1536
|
-
DRAFT: 'draft',
|
|
1537
|
-
PUBLISHED: 'published'
|
|
1538
|
-
}
|
|
1539
|
-
})
|
|
1540
|
-
};
|
|
1541
|
-
});
|
|
1542
|
-
|
|
1543
|
-
/**
|
|
1544
|
-
* Build a map of filters type for every GraphQL scalars
|
|
1545
|
-
* @return {Object<string, NexusInputTypeDef>}
|
|
1546
|
-
*/ const buildScalarFilters = ({ strapi })=>{
|
|
1547
|
-
const { naming, mappers } = strapi.plugin('graphql').service('utils');
|
|
1548
|
-
const { helpers } = strapi.plugin('graphql').service('internals');
|
|
1549
|
-
return helpers.getEnabledScalars().reduce((acc, type)=>{
|
|
1550
|
-
const operators = mappers.graphqlScalarToOperators(type);
|
|
1551
|
-
const typeName = naming.getScalarFilterInputTypeName(type);
|
|
1552
|
-
if (!operators || operators.length === 0) {
|
|
1553
|
-
return acc;
|
|
1554
|
-
}
|
|
1555
|
-
return {
|
|
1556
|
-
...acc,
|
|
1557
|
-
[typeName]: inputObjectType({
|
|
1558
|
-
name: typeName,
|
|
1559
|
-
definition (t) {
|
|
1560
|
-
for (const operator of operators){
|
|
1561
|
-
operator.add(t, type);
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
})
|
|
1565
|
-
};
|
|
1566
|
-
}, {});
|
|
1567
|
-
};
|
|
1568
|
-
var filters$1 = ((context)=>({
|
|
1569
|
-
scalars: buildScalarFilters(context)
|
|
1570
|
-
}));
|
|
1571
|
-
|
|
1572
|
-
const { ValidationError: ValidationError$1 } = errors;
|
|
1573
|
-
/**
|
|
1574
|
-
* Build an Error object type
|
|
1575
|
-
* @return {Object<string, NexusObjectTypeDef>}
|
|
1576
|
-
*/ var error = (({ strapi })=>{
|
|
1577
|
-
const { ERROR_CODES, ERROR_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1578
|
-
return objectType({
|
|
1579
|
-
name: ERROR_TYPE_NAME,
|
|
1580
|
-
definition (t) {
|
|
1581
|
-
t.nonNull.string('code', {
|
|
1582
|
-
resolve (parent) {
|
|
1583
|
-
const code = get('code', parent);
|
|
1584
|
-
const isValidPlaceholderCode = Object.values(ERROR_CODES).includes(code);
|
|
1585
|
-
if (!isValidPlaceholderCode) {
|
|
1586
|
-
throw new ValidationError$1(`"${code}" is not a valid code value`);
|
|
1587
|
-
}
|
|
1588
|
-
return code;
|
|
1589
|
-
}
|
|
1590
|
-
});
|
|
1591
|
-
t.string('message');
|
|
1592
|
-
}
|
|
1593
|
-
});
|
|
1594
|
-
});
|
|
1595
|
-
|
|
1596
|
-
var types = ((context)=>()=>{
|
|
1597
|
-
const { strapi } = context;
|
|
1598
|
-
const { KINDS } = strapi.plugin('graphql').service('constants');
|
|
1599
|
-
return {
|
|
1600
|
-
[KINDS.internal]: {
|
|
1601
|
-
error: error(context),
|
|
1602
|
-
pagination: pagination(context),
|
|
1603
|
-
responseCollectionMeta: buildResponseCollectionMeta(context),
|
|
1604
|
-
deleteDocumentResponse: buildDeleteMutationResponse(context)
|
|
1605
|
-
},
|
|
1606
|
-
[KINDS.enum]: {
|
|
1607
|
-
publicationStatus: publicationStatus(context)
|
|
1608
|
-
},
|
|
1609
|
-
[KINDS.filtersInput]: {
|
|
1610
|
-
...filters$1(context)
|
|
1611
|
-
}
|
|
1612
|
-
};
|
|
1613
|
-
});
|
|
1614
|
-
|
|
1615
|
-
var getEnabledScalars = (({ strapi })=>()=>{
|
|
1616
|
-
const { GRAPHQL_SCALAR_OPERATORS } = strapi.plugin('graphql').service('constants');
|
|
1617
|
-
return Object.entries(GRAPHQL_SCALAR_OPERATORS)// To be valid, a GraphQL scalar must have at least one operator enabled
|
|
1618
|
-
.filter(([, value])=>value.length > 0)// Only keep the key (the scalar name)
|
|
1619
|
-
.map(first);
|
|
1620
|
-
});
|
|
1621
|
-
|
|
1622
|
-
var helpers = ((context)=>({
|
|
1623
|
-
getEnabledScalars: getEnabledScalars(context)
|
|
1624
|
-
}));
|
|
1625
|
-
|
|
1626
|
-
var internals = ((context)=>({
|
|
1627
|
-
args: args(context),
|
|
1628
|
-
scalars: scalars(),
|
|
1629
|
-
buildInternalTypes: types(context),
|
|
1630
|
-
helpers: helpers(context)
|
|
1631
|
-
}));
|
|
1632
|
-
|
|
1633
|
-
/**
|
|
1634
|
-
* Build a Nexus enum type from a Strapi enum attribute
|
|
1635
|
-
* @param {object} definition - The definition of the enum
|
|
1636
|
-
* @param {string[]} definition.enum - The params of the enum
|
|
1637
|
-
* @param {string} name - The name of the enum
|
|
1638
|
-
* @return {NexusEnumTypeDef}
|
|
1639
|
-
*/ const buildEnumTypeDefinition = (definition, name)=>{
|
|
1640
|
-
return enumType({
|
|
1641
|
-
name,
|
|
1642
|
-
members: definition.enum.reduce((acc, value)=>set(strings.toRegressedEnumValue(value), value, acc), {})
|
|
1643
|
-
});
|
|
1644
|
-
};
|
|
1645
|
-
var enums = (()=>({
|
|
1646
|
-
buildEnumTypeDefinition
|
|
1647
|
-
}));
|
|
1648
|
-
|
|
1649
|
-
const { ApplicationError: ApplicationError$1 } = errors;
|
|
1650
|
-
var dynamicZone = (({ strapi })=>{
|
|
1651
|
-
const buildTypeDefinition = (name, components)=>{
|
|
1652
|
-
const { ERROR_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
1653
|
-
const isEmpty = components.length === 0;
|
|
1654
|
-
const componentsTypeNames = components.map((componentUID)=>{
|
|
1655
|
-
const component = strapi.components[componentUID];
|
|
1656
|
-
if (!component) {
|
|
1657
|
-
throw new ApplicationError$1(`Trying to create a dynamic zone type with an unknown component: "${componentUID}"`);
|
|
1658
|
-
}
|
|
1659
|
-
return component.globalId;
|
|
1660
|
-
});
|
|
1661
|
-
return unionType({
|
|
1662
|
-
name,
|
|
1663
|
-
resolveType (obj) {
|
|
1664
|
-
if (isEmpty) {
|
|
1665
|
-
return ERROR_TYPE_NAME;
|
|
1666
|
-
}
|
|
1667
|
-
return strapi.components[obj.__component].globalId;
|
|
1668
|
-
},
|
|
1669
|
-
definition (t) {
|
|
1670
|
-
t.members(...componentsTypeNames, ERROR_TYPE_NAME);
|
|
1671
|
-
}
|
|
1672
|
-
});
|
|
1673
|
-
};
|
|
1674
|
-
const buildInputDefinition = (name, components)=>{
|
|
1675
|
-
const parseData = (value)=>{
|
|
1676
|
-
const component = Object.values(strapi.components).find((component)=>component.globalId === value.__typename);
|
|
1677
|
-
if (!component) {
|
|
1678
|
-
throw new ApplicationError$1(`Component not found. expected one of: ${components.map((uid)=>strapi.components[uid].globalId).join(', ')}`);
|
|
1679
|
-
}
|
|
1680
|
-
return {
|
|
1681
|
-
__component: component.uid,
|
|
1682
|
-
...omit([
|
|
1683
|
-
'__typename'
|
|
1684
|
-
], value)
|
|
1685
|
-
};
|
|
1686
|
-
};
|
|
1687
|
-
return scalarType({
|
|
1688
|
-
name,
|
|
1689
|
-
serialize: (value)=>value,
|
|
1690
|
-
parseValue: (value)=>parseData(value),
|
|
1691
|
-
parseLiteral (ast, variables) {
|
|
1692
|
-
if (ast.kind !== Kind.OBJECT) {
|
|
1693
|
-
return undefined;
|
|
1694
|
-
}
|
|
1695
|
-
const value = valueFromASTUntyped(ast, variables);
|
|
1696
|
-
return parseData(value);
|
|
1697
|
-
}
|
|
1698
|
-
});
|
|
1699
|
-
};
|
|
1700
|
-
return {
|
|
1701
|
-
/**
|
|
1702
|
-
* Build a Nexus dynamic zone type from a Strapi dz attribute
|
|
1703
|
-
*/ buildDynamicZoneDefinition (definition, name, inputName) {
|
|
1704
|
-
const { components } = definition;
|
|
1705
|
-
const typeDefinition = buildTypeDefinition(name, components);
|
|
1706
|
-
const inputDefinition = buildInputDefinition(inputName, components);
|
|
1707
|
-
return [
|
|
1708
|
-
typeDefinition,
|
|
1709
|
-
inputDefinition
|
|
1710
|
-
];
|
|
1711
|
-
}
|
|
1712
|
-
};
|
|
1713
|
-
});
|
|
1714
|
-
|
|
1715
|
-
var entity = (({ strapi })=>{
|
|
1716
|
-
const { naming } = strapi.plugin('graphql').service('utils');
|
|
1717
|
-
return {
|
|
1718
|
-
/**
|
|
1719
|
-
* Build a higher level type for a content type which contains the attributes, the ID and the metadata
|
|
1720
|
-
* @param {object} contentType The content type which will be used to build its entity type
|
|
1721
|
-
* @return {NexusObjectTypeDef}
|
|
1722
|
-
*/ buildEntityDefinition (contentType) {
|
|
1723
|
-
const { attributes } = contentType;
|
|
1724
|
-
const name = naming.getEntityName(contentType);
|
|
1725
|
-
const typeName = naming.getTypeName(contentType);
|
|
1726
|
-
return objectType({
|
|
1727
|
-
name,
|
|
1728
|
-
definition (t) {
|
|
1729
|
-
// Keep the ID attribute at the top level
|
|
1730
|
-
t.id('id', {
|
|
1731
|
-
resolve: prop('id')
|
|
1732
|
-
});
|
|
1733
|
-
if (!isEmpty(attributes)) {
|
|
1734
|
-
// Keep the fetched object into a dedicated `attributes` field
|
|
1735
|
-
t.field('attributes', {
|
|
1736
|
-
type: typeName,
|
|
1737
|
-
resolve: identity
|
|
1738
|
-
});
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
});
|
|
1742
|
-
}
|
|
1743
|
-
};
|
|
1744
|
-
});
|
|
1745
|
-
|
|
1746
|
-
var typeBuilder = ((context)=>{
|
|
1747
|
-
const { strapi } = context;
|
|
1748
|
-
const getGraphQLService = strapi.plugin('graphql').service;
|
|
1749
|
-
const extension = getGraphQLService('extension');
|
|
1750
|
-
/**
|
|
1751
|
-
* Add a scalar attribute to the type definition
|
|
1752
|
-
*
|
|
1753
|
-
* The attribute is added based on a simple association between a Strapi
|
|
1754
|
-
* type and a GraphQL type (the map is defined in `strapiTypeToGraphQLScalar`)
|
|
1755
|
-
*/ const addScalarAttribute = (options)=>{
|
|
1756
|
-
const { builder, attributeName, attribute } = options;
|
|
1757
|
-
const { mappers } = getGraphQLService('utils');
|
|
1758
|
-
const gqlType = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
1759
|
-
builder.field(attributeName, {
|
|
1760
|
-
type: gqlType
|
|
1761
|
-
});
|
|
1762
|
-
};
|
|
1763
|
-
/**
|
|
1764
|
-
* Add a component attribute to the type definition
|
|
1765
|
-
*
|
|
1766
|
-
* The attribute is added by fetching the component's type
|
|
1767
|
-
* name and using it as the attribute's type
|
|
1768
|
-
*/ const addComponentAttribute = (options)=>{
|
|
1769
|
-
const { builder, attributeName, contentType, attribute } = options;
|
|
1770
|
-
let localBuilder = builder;
|
|
1771
|
-
const { naming } = getGraphQLService('utils');
|
|
1772
|
-
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
1773
|
-
const { buildComponentResolver } = getGraphQLService('builders').get('content-api');
|
|
1774
|
-
const type = naming.getComponentNameFromAttribute(attribute);
|
|
1775
|
-
if (attribute.repeatable) {
|
|
1776
|
-
localBuilder = localBuilder.list;
|
|
1777
|
-
}
|
|
1778
|
-
const targetComponent = strapi.getModel(attribute.component);
|
|
1779
|
-
const resolve = buildComponentResolver({
|
|
1780
|
-
contentTypeUID: contentType.uid,
|
|
1781
|
-
attributeName,
|
|
1782
|
-
strapi
|
|
1783
|
-
});
|
|
1784
|
-
const args = getContentTypeArgs(targetComponent, {
|
|
1785
|
-
multiple: !!attribute.repeatable,
|
|
1786
|
-
isNested: true
|
|
1787
|
-
});
|
|
1788
|
-
localBuilder.field(attributeName, {
|
|
1789
|
-
type,
|
|
1790
|
-
resolve,
|
|
1791
|
-
args
|
|
1792
|
-
});
|
|
1793
|
-
};
|
|
1794
|
-
/**
|
|
1795
|
-
* Add a dynamic zone attribute to the type definition
|
|
1796
|
-
*
|
|
1797
|
-
* The attribute is added by fetching the dynamic zone's
|
|
1798
|
-
* type name and using it as the attribute's type
|
|
1799
|
-
*/ const addDynamicZoneAttribute = (options)=>{
|
|
1800
|
-
const { builder, attributeName, contentType } = options;
|
|
1801
|
-
const { naming } = getGraphQLService('utils');
|
|
1802
|
-
const { ERROR_CODES } = getGraphQLService('constants');
|
|
1803
|
-
const { buildDynamicZoneResolver } = getGraphQLService('builders').get('content-api');
|
|
1804
|
-
const { components } = contentType.attributes[attributeName];
|
|
1805
|
-
const isEmpty = components.length === 0;
|
|
1806
|
-
const type = naming.getDynamicZoneName(contentType, attributeName);
|
|
1807
|
-
const resolve = isEmpty ? constant({
|
|
1808
|
-
code: ERROR_CODES.emptyDynamicZone,
|
|
1809
|
-
message: `This dynamic zone don't have any component attached to it`
|
|
1810
|
-
}) : buildDynamicZoneResolver({
|
|
1811
|
-
contentTypeUID: contentType.uid,
|
|
1812
|
-
attributeName
|
|
1813
|
-
});
|
|
1814
|
-
builder.list.field(attributeName, {
|
|
1815
|
-
type,
|
|
1816
|
-
resolve
|
|
1817
|
-
});
|
|
1818
|
-
};
|
|
1819
|
-
/**
|
|
1820
|
-
* Add an enum attribute to the type definition
|
|
1821
|
-
*
|
|
1822
|
-
* The attribute is added by fetching the enum's type
|
|
1823
|
-
* name and using it as the attribute's type
|
|
1824
|
-
*/ const addEnumAttribute = (options)=>{
|
|
1825
|
-
const { builder, attributeName, contentType } = options;
|
|
1826
|
-
const { naming } = getGraphQLService('utils');
|
|
1827
|
-
const type = naming.getEnumName(contentType, attributeName);
|
|
1828
|
-
builder.field(attributeName, {
|
|
1829
|
-
type
|
|
1830
|
-
});
|
|
1831
|
-
};
|
|
1832
|
-
/**
|
|
1833
|
-
* Add a media attribute to the type definition
|
|
1834
|
-
*/ const addMediaAttribute = (options)=>{
|
|
1835
|
-
const { naming } = getGraphQLService('utils');
|
|
1836
|
-
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
1837
|
-
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
1838
|
-
const extension = getGraphQLService('extension');
|
|
1839
|
-
const { builder } = options;
|
|
1840
|
-
const { attributeName, attribute, contentType } = options;
|
|
1841
|
-
const fileUID = 'plugin::upload.file';
|
|
1842
|
-
if (extension.shadowCRUD(fileUID).isDisabled()) {
|
|
1843
|
-
return;
|
|
1844
|
-
}
|
|
1845
|
-
const fileContentType = strapi.contentTypes[fileUID];
|
|
1846
|
-
const resolve = buildAssociationResolver({
|
|
1847
|
-
contentTypeUID: contentType.uid,
|
|
1848
|
-
attributeName,
|
|
1849
|
-
strapi
|
|
1850
|
-
});
|
|
1851
|
-
const args = attribute.multiple ? getContentTypeArgs(fileContentType, {
|
|
1852
|
-
isNested: true
|
|
1853
|
-
}) : undefined;
|
|
1854
|
-
const typeName = naming.getTypeName(fileContentType);
|
|
1855
|
-
if (attribute.multiple) {
|
|
1856
|
-
builder.field(`${attributeName}_connection`, {
|
|
1857
|
-
type: naming.getRelationResponseCollectionName(fileContentType),
|
|
1858
|
-
resolve,
|
|
1859
|
-
args
|
|
1860
|
-
});
|
|
1861
|
-
builder.field(attributeName, {
|
|
1862
|
-
type: nonNull(list(typeName)),
|
|
1863
|
-
async resolve (...args) {
|
|
1864
|
-
const res = await resolve(...args);
|
|
1865
|
-
return res.nodes ?? [];
|
|
1866
|
-
},
|
|
1867
|
-
args
|
|
1868
|
-
});
|
|
1869
|
-
} else {
|
|
1870
|
-
builder.field(attributeName, {
|
|
1871
|
-
type: typeName,
|
|
1872
|
-
async resolve (...args) {
|
|
1873
|
-
const res = await resolve(...args);
|
|
1874
|
-
return res.value;
|
|
1875
|
-
},
|
|
1876
|
-
args
|
|
1877
|
-
});
|
|
1878
|
-
}
|
|
1879
|
-
};
|
|
1880
|
-
/**
|
|
1881
|
-
* Add a polymorphic relational attribute to the type definition
|
|
1882
|
-
*/ const addPolymorphicRelationalAttribute = (options)=>{
|
|
1883
|
-
const { GENERIC_MORPH_TYPENAME } = getGraphQLService('constants');
|
|
1884
|
-
const { naming } = getGraphQLService('utils');
|
|
1885
|
-
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
1886
|
-
let { builder } = options;
|
|
1887
|
-
const { attributeName, attribute, contentType } = options;
|
|
1888
|
-
const { target } = attribute;
|
|
1889
|
-
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
1890
|
-
if (isToManyRelation) {
|
|
1891
|
-
builder = builder.list;
|
|
1892
|
-
}
|
|
1893
|
-
// todo[v4]: How to handle polymorphic relation w/ entity response collection types?
|
|
1894
|
-
// -> Currently return raw polymorphic entities
|
|
1895
|
-
const resolve = buildAssociationResolver({
|
|
1896
|
-
contentTypeUID: contentType.uid,
|
|
1897
|
-
attributeName,
|
|
1898
|
-
strapi
|
|
1899
|
-
});
|
|
1900
|
-
// If there is no specific target specified, then use the GenericMorph type
|
|
1901
|
-
if (isUndefined(target)) {
|
|
1902
|
-
builder.field(attributeName, {
|
|
1903
|
-
type: GENERIC_MORPH_TYPENAME,
|
|
1904
|
-
resolve
|
|
1905
|
-
});
|
|
1906
|
-
} else if (isArray(target) && target.every(isString)) {
|
|
1907
|
-
const type = naming.getMorphRelationTypeName(contentType, attributeName);
|
|
1908
|
-
builder.field(attributeName, {
|
|
1909
|
-
type,
|
|
1910
|
-
resolve
|
|
1911
|
-
});
|
|
1912
|
-
}
|
|
1913
|
-
};
|
|
1914
|
-
/**
|
|
1915
|
-
* Add a regular relational attribute to the type definition
|
|
1916
|
-
*/ const addRegularRelationalAttribute = (options)=>{
|
|
1917
|
-
const { naming } = getGraphQLService('utils');
|
|
1918
|
-
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
1919
|
-
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
1920
|
-
const extension = getGraphQLService('extension');
|
|
1921
|
-
const { builder } = options;
|
|
1922
|
-
const { attributeName, attribute, contentType } = options;
|
|
1923
|
-
if (extension.shadowCRUD(attribute.target).isDisabled()) {
|
|
1924
|
-
return;
|
|
1925
|
-
}
|
|
1926
|
-
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
1927
|
-
const resolve = buildAssociationResolver({
|
|
1928
|
-
contentTypeUID: contentType.uid,
|
|
1929
|
-
attributeName,
|
|
1930
|
-
strapi
|
|
1931
|
-
});
|
|
1932
|
-
const targetContentType = strapi.getModel(attribute.target);
|
|
1933
|
-
const typeName = naming.getTypeName(targetContentType);
|
|
1934
|
-
const args = isToManyRelation ? getContentTypeArgs(targetContentType, {
|
|
1935
|
-
isNested: true
|
|
1936
|
-
}) : undefined;
|
|
1937
|
-
const resolverScope = `${targetContentType.uid}.find`;
|
|
1938
|
-
const resolverPath = `${naming.getTypeName(contentType)}.${attributeName}`;
|
|
1939
|
-
extension.use({
|
|
1940
|
-
resolversConfig: {
|
|
1941
|
-
[resolverPath]: {
|
|
1942
|
-
auth: {
|
|
1943
|
-
scope: [
|
|
1944
|
-
resolverScope
|
|
1945
|
-
]
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
});
|
|
1950
|
-
if (isToManyRelation) {
|
|
1951
|
-
builder.field(`${attributeName}_connection`, {
|
|
1952
|
-
type: naming.getRelationResponseCollectionName(targetContentType),
|
|
1953
|
-
resolve,
|
|
1954
|
-
args
|
|
1955
|
-
});
|
|
1956
|
-
extension.use({
|
|
1957
|
-
resolversConfig: {
|
|
1958
|
-
[`${resolverPath}_connection`]: {
|
|
1959
|
-
auth: {
|
|
1960
|
-
scope: [
|
|
1961
|
-
resolverScope
|
|
1962
|
-
]
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
});
|
|
1967
|
-
builder.field(attributeName, {
|
|
1968
|
-
type: nonNull(list(typeName)),
|
|
1969
|
-
async resolve (...args) {
|
|
1970
|
-
const res = await resolve(...args);
|
|
1971
|
-
return res.nodes ?? [];
|
|
1972
|
-
},
|
|
1973
|
-
args
|
|
1974
|
-
});
|
|
1975
|
-
} else {
|
|
1976
|
-
builder.field(attributeName, {
|
|
1977
|
-
type: typeName,
|
|
1978
|
-
async resolve (...args) {
|
|
1979
|
-
const res = await resolve(...args);
|
|
1980
|
-
return res.value;
|
|
1981
|
-
},
|
|
1982
|
-
args
|
|
1983
|
-
});
|
|
1984
|
-
}
|
|
1985
|
-
};
|
|
1986
|
-
const isNotPrivate = (contentType)=>(attributeName)=>{
|
|
1987
|
-
return !contentTypes.isPrivateAttribute(contentType, attributeName);
|
|
1988
|
-
};
|
|
1989
|
-
const isNotDisabled = (contentType)=>(attributeName)=>{
|
|
1990
|
-
return extension.shadowCRUD(contentType.uid).field(attributeName).hasOutputEnabled();
|
|
1991
|
-
};
|
|
1992
|
-
return {
|
|
1993
|
-
/**
|
|
1994
|
-
* Create a type definition for a given content type
|
|
1995
|
-
* @param contentType - The content type used to created the definition
|
|
1996
|
-
* @return {NexusObjectTypeDef}
|
|
1997
|
-
*/ buildTypeDefinition (contentType) {
|
|
1998
|
-
const utils = getGraphQLService('utils');
|
|
1999
|
-
const { getComponentName, getTypeName } = utils.naming;
|
|
2000
|
-
const { isStrapiScalar, isComponent, isDynamicZone, isEnumeration, isMedia, isMorphRelation, isRelation } = utils.attributes;
|
|
2001
|
-
const { attributes, modelType } = contentType;
|
|
2002
|
-
const attributesKey = Object.keys(attributes);
|
|
2003
|
-
const name = (modelType === 'component' ? getComponentName : getTypeName).call(null, contentType);
|
|
2004
|
-
return objectType({
|
|
2005
|
-
name,
|
|
2006
|
-
definition (t) {
|
|
2007
|
-
// add back the old id attribute on contentType if v4 compat is enabled
|
|
2008
|
-
if (modelType !== 'component' && isNotDisabled(contentType)('id') && strapi.plugin('graphql').config('v4CompatibilityMode', false)) {
|
|
2009
|
-
t.nonNull.id('id', {
|
|
2010
|
-
deprecation: 'Use `documentId` instead'
|
|
2011
|
-
});
|
|
2012
|
-
}
|
|
2013
|
-
if (modelType === 'component' && isNotDisabled(contentType)('id')) {
|
|
2014
|
-
t.nonNull.id('id');
|
|
2015
|
-
}
|
|
2016
|
-
if (modelType !== 'component' && isNotDisabled(contentType)('documentId')) {
|
|
2017
|
-
t.nonNull.id('documentId');
|
|
2018
|
-
}
|
|
2019
|
-
if (strapi.plugin('graphql').config('v4CompatibilityMode', false)) {
|
|
2020
|
-
t.nonNull.field('attributes', {
|
|
2021
|
-
deprecation: 'Use root level fields instead',
|
|
2022
|
-
type: name,
|
|
2023
|
-
resolve: (parent)=>parent
|
|
2024
|
-
});
|
|
2025
|
-
t.nonNull.field('data', {
|
|
2026
|
-
deprecation: 'Use root level fields instead',
|
|
2027
|
-
type: name,
|
|
2028
|
-
resolve: (parent)=>parent
|
|
2029
|
-
});
|
|
2030
|
-
}
|
|
2031
|
-
/** Attributes
|
|
2032
|
-
*
|
|
2033
|
-
* Attributes can be of 7 different kind:
|
|
2034
|
-
* - Scalar
|
|
2035
|
-
* - Component
|
|
2036
|
-
* - Dynamic Zone
|
|
2037
|
-
* - Enum
|
|
2038
|
-
* - Media
|
|
2039
|
-
* - Polymorphic Relations
|
|
2040
|
-
* - Regular Relations
|
|
2041
|
-
*
|
|
2042
|
-
* Here, we iterate over each non-private attribute
|
|
2043
|
-
* and add it to the type definition based on its type
|
|
2044
|
-
*/ attributesKey// Ignore private attributes
|
|
2045
|
-
.filter(isNotPrivate(contentType))// Ignore disabled fields (from extension service)
|
|
2046
|
-
.filter(isNotDisabled(contentType))// Add each attribute to the type definition
|
|
2047
|
-
.forEach((attributeName)=>{
|
|
2048
|
-
const attribute = attributes[attributeName];
|
|
2049
|
-
// We create a copy of the builder (t) to apply custom
|
|
2050
|
-
// rules only on the current attribute (eg: nonNull, list, ...)
|
|
2051
|
-
let builder = t;
|
|
2052
|
-
if (attribute.required) {
|
|
2053
|
-
builder = builder.nonNull;
|
|
2054
|
-
}
|
|
2055
|
-
const options = {
|
|
2056
|
-
builder,
|
|
2057
|
-
attributeName,
|
|
2058
|
-
attribute,
|
|
2059
|
-
contentType,
|
|
2060
|
-
context
|
|
2061
|
-
};
|
|
2062
|
-
// Enums
|
|
2063
|
-
if (isEnumeration(attribute)) {
|
|
2064
|
-
addEnumAttribute(options);
|
|
2065
|
-
} else if (isStrapiScalar(attribute)) {
|
|
2066
|
-
addScalarAttribute(options);
|
|
2067
|
-
} else if (isComponent(attribute)) {
|
|
2068
|
-
addComponentAttribute(options);
|
|
2069
|
-
} else if (isDynamicZone(attribute)) {
|
|
2070
|
-
addDynamicZoneAttribute(options);
|
|
2071
|
-
} else if (isMedia(attribute)) {
|
|
2072
|
-
addMediaAttribute(options);
|
|
2073
|
-
} else if (isMorphRelation(attribute)) {
|
|
2074
|
-
addPolymorphicRelationalAttribute(options);
|
|
2075
|
-
} else if (isRelation(attribute)) {
|
|
2076
|
-
addRegularRelationalAttribute(options);
|
|
2077
|
-
}
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
};
|
|
2083
|
-
});
|
|
2084
|
-
|
|
2085
|
-
var response = (({ strapi })=>{
|
|
2086
|
-
const { naming } = strapi.plugin('graphql').service('utils');
|
|
2087
|
-
return {
|
|
2088
|
-
/**
|
|
2089
|
-
* Build a type definition for a content API response for a given content type
|
|
2090
|
-
*/ buildResponseDefinition (contentType) {
|
|
2091
|
-
const name = naming.getEntityResponseName(contentType);
|
|
2092
|
-
const typeName = naming.getTypeName(contentType);
|
|
2093
|
-
return objectType({
|
|
2094
|
-
name,
|
|
2095
|
-
definition (t) {
|
|
2096
|
-
t.field('data', {
|
|
2097
|
-
type: typeName,
|
|
2098
|
-
resolve: prop('value')
|
|
2099
|
-
});
|
|
2100
|
-
}
|
|
2101
|
-
});
|
|
2102
|
-
}
|
|
2103
|
-
};
|
|
2104
|
-
});
|
|
2105
|
-
|
|
2106
|
-
var responseCollection = (({ strapi })=>{
|
|
2107
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
2108
|
-
const { naming } = getService('utils');
|
|
2109
|
-
const { RESPONSE_COLLECTION_META_TYPE_NAME, PAGINATION_TYPE_NAME } = getService('constants');
|
|
2110
|
-
return {
|
|
2111
|
-
/**
|
|
2112
|
-
* Build a type definition for a content API collection response for a given content type
|
|
2113
|
-
* @param {Schema.ContentType} contentType The content type which will be used to build its content API response definition
|
|
2114
|
-
* @return {NexusObjectTypeDef}
|
|
2115
|
-
*/ buildResponseCollectionDefinition (contentType) {
|
|
2116
|
-
const name = naming.getEntityResponseCollectionName(contentType);
|
|
2117
|
-
const typeName = naming.getTypeName(contentType);
|
|
2118
|
-
const { resolvePagination } = getService('builders').get('content-api');
|
|
2119
|
-
return objectType({
|
|
2120
|
-
name,
|
|
2121
|
-
definition (t) {
|
|
2122
|
-
// NOTE: add edges & cursor based pagination to support the relay spec in a later version
|
|
2123
|
-
t.nonNull.list.field('nodes', {
|
|
2124
|
-
type: nonNull(typeName),
|
|
2125
|
-
resolve: pipe(prop('nodes'), defaultTo([]))
|
|
2126
|
-
});
|
|
2127
|
-
t.nonNull.field('pageInfo', {
|
|
2128
|
-
type: PAGINATION_TYPE_NAME,
|
|
2129
|
-
resolve: resolvePagination
|
|
2130
|
-
});
|
|
2131
|
-
if (strapi.plugin('graphql').config('v4CompatibilityMode', false)) {
|
|
2132
|
-
t.nonNull.list.field('data', {
|
|
2133
|
-
deprecation: 'Use `nodes` field instead',
|
|
2134
|
-
type: nonNull(typeName),
|
|
2135
|
-
resolve: pipe(prop('nodes'), defaultTo([]))
|
|
2136
|
-
});
|
|
2137
|
-
t.nonNull.field('meta', {
|
|
2138
|
-
deprecation: 'Use the `pageInfo` field instead',
|
|
2139
|
-
type: RESPONSE_COLLECTION_META_TYPE_NAME,
|
|
2140
|
-
resolve: identity
|
|
2141
|
-
});
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
});
|
|
2145
|
-
}
|
|
2146
|
-
};
|
|
2147
|
-
});
|
|
2148
|
-
|
|
2149
|
-
var relationResponseCollection = (({ strapi })=>{
|
|
2150
|
-
const { naming } = strapi.plugin('graphql').service('utils');
|
|
2151
|
-
return {
|
|
2152
|
-
/**
|
|
2153
|
-
* Build a type definition for a content API relation's collection response for a given content type
|
|
2154
|
-
*/ buildRelationResponseCollectionDefinition (contentType) {
|
|
2155
|
-
const name = naming.getRelationResponseCollectionName(contentType);
|
|
2156
|
-
const typeName = naming.getTypeName(contentType);
|
|
2157
|
-
return objectType({
|
|
2158
|
-
name,
|
|
2159
|
-
definition (t) {
|
|
2160
|
-
t.nonNull.list.field('nodes', {
|
|
2161
|
-
type: nonNull(typeName),
|
|
2162
|
-
resolve: pipe(prop('nodes'), defaultTo([]))
|
|
2163
|
-
});
|
|
2164
|
-
if (strapi.plugin('graphql').config('v4CompatibilityMode', false)) {
|
|
2165
|
-
t.nonNull.list.field('data', {
|
|
2166
|
-
deprecation: 'Use `nodes` field instead',
|
|
2167
|
-
type: nonNull(typeName),
|
|
2168
|
-
resolve: pipe(prop('nodes'), defaultTo([]))
|
|
2169
|
-
});
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
});
|
|
2173
|
-
}
|
|
2174
|
-
};
|
|
2175
|
-
});
|
|
2176
|
-
|
|
2177
|
-
var createCollectionTypeQueriesBuilder = (({ strapi })=>{
|
|
2178
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
2179
|
-
const { naming } = getService('utils');
|
|
2180
|
-
const { transformArgs, getContentTypeArgs } = getService('builders').utils;
|
|
2181
|
-
const { toEntityResponseCollection } = getService('format').returnTypes;
|
|
2182
|
-
const { getFindOneQueryName, getTypeName, getFindQueryName, getFindConnectionQueryName, getEntityResponseCollectionName } = naming;
|
|
2183
|
-
const buildCollectionTypeQueries = (contentType)=>{
|
|
2184
|
-
const findOneQueryName = `Query.${getFindOneQueryName(contentType)}`;
|
|
2185
|
-
const findQueryName = `Query.${getFindQueryName(contentType)}`;
|
|
2186
|
-
const findConnectionQueryName = `Query.${getFindConnectionQueryName(contentType)}`;
|
|
2187
|
-
const extension = getService('extension');
|
|
2188
|
-
const registerAuthConfig = (action, auth)=>{
|
|
2189
|
-
return extension.use({
|
|
2190
|
-
resolversConfig: {
|
|
2191
|
-
[action]: {
|
|
2192
|
-
auth
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
});
|
|
2196
|
-
};
|
|
2197
|
-
const isActionEnabled = (action)=>{
|
|
2198
|
-
return extension.shadowCRUD(contentType.uid).isActionEnabled(action);
|
|
2199
|
-
};
|
|
2200
|
-
const isFindOneEnabled = isActionEnabled('findOne');
|
|
2201
|
-
const isFindEnabled = isActionEnabled('find');
|
|
2202
|
-
if (isFindOneEnabled) {
|
|
2203
|
-
registerAuthConfig(findOneQueryName, {
|
|
2204
|
-
scope: [
|
|
2205
|
-
`${contentType.uid}.findOne`
|
|
2206
|
-
]
|
|
2207
|
-
});
|
|
2208
|
-
}
|
|
2209
|
-
if (isFindEnabled) {
|
|
2210
|
-
registerAuthConfig(findQueryName, {
|
|
2211
|
-
scope: [
|
|
2212
|
-
`${contentType.uid}.find`
|
|
2213
|
-
]
|
|
2214
|
-
});
|
|
2215
|
-
registerAuthConfig(findConnectionQueryName, {
|
|
2216
|
-
scope: [
|
|
2217
|
-
`${contentType.uid}.find`
|
|
2218
|
-
]
|
|
2219
|
-
});
|
|
2220
|
-
}
|
|
2221
|
-
return extendType({
|
|
2222
|
-
type: 'Query',
|
|
2223
|
-
definition (t) {
|
|
2224
|
-
if (isFindOneEnabled) {
|
|
2225
|
-
addFindOneQuery(t, contentType);
|
|
2226
|
-
}
|
|
2227
|
-
if (isFindEnabled) {
|
|
2228
|
-
addFindConnectionQuery(t, contentType);
|
|
2229
|
-
addFindQuery(t, contentType);
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
});
|
|
2233
|
-
};
|
|
2234
|
-
/**
|
|
2235
|
-
* Register a "find one" query field to the nexus type definition
|
|
2236
|
-
*/ const addFindOneQuery = (t, contentType)=>{
|
|
2237
|
-
const findOneQueryName = getFindOneQueryName(contentType);
|
|
2238
|
-
const typeName = getTypeName(contentType);
|
|
2239
|
-
t.field(findOneQueryName, {
|
|
2240
|
-
type: typeName,
|
|
2241
|
-
extensions: {
|
|
2242
|
-
strapi: {
|
|
2243
|
-
contentType
|
|
2244
|
-
}
|
|
2245
|
-
},
|
|
2246
|
-
args: getContentTypeArgs(contentType, {
|
|
2247
|
-
multiple: false
|
|
2248
|
-
}),
|
|
2249
|
-
async resolve (parent, args, ctx) {
|
|
2250
|
-
const transformedArgs = transformArgs(args, {
|
|
2251
|
-
contentType
|
|
2252
|
-
});
|
|
2253
|
-
const { findOne } = getService('builders').get('content-api').buildQueriesResolvers({
|
|
2254
|
-
contentType
|
|
2255
|
-
});
|
|
2256
|
-
// queryResolvers will sanitize params
|
|
2257
|
-
return findOne(parent, transformedArgs, ctx);
|
|
2258
|
-
}
|
|
2259
|
-
});
|
|
2260
|
-
};
|
|
2261
|
-
/**
|
|
2262
|
-
* Register a "find" query field to the nexus type definition
|
|
2263
|
-
*/ const addFindQuery = (t, contentType)=>{
|
|
2264
|
-
const findQueryName = getFindQueryName(contentType);
|
|
2265
|
-
const typeName = getTypeName(contentType);
|
|
2266
|
-
t.field(findQueryName, {
|
|
2267
|
-
type: nonNull(list(typeName)),
|
|
2268
|
-
extensions: {
|
|
2269
|
-
strapi: {
|
|
2270
|
-
contentType
|
|
2271
|
-
}
|
|
2272
|
-
},
|
|
2273
|
-
args: getContentTypeArgs(contentType),
|
|
2274
|
-
async resolve (parent, args, ctx) {
|
|
2275
|
-
const transformedArgs = transformArgs(args, {
|
|
2276
|
-
contentType,
|
|
2277
|
-
usePagination: true
|
|
2278
|
-
});
|
|
2279
|
-
const { findMany } = getService('builders').get('content-api').buildQueriesResolvers({
|
|
2280
|
-
contentType
|
|
2281
|
-
});
|
|
2282
|
-
// queryResolvers will sanitize params
|
|
2283
|
-
return findMany(parent, transformedArgs, ctx);
|
|
2284
|
-
}
|
|
2285
|
-
});
|
|
2286
|
-
};
|
|
2287
|
-
/**
|
|
2288
|
-
* Register a "find" query field to the nexus type definition
|
|
2289
|
-
*/ const addFindConnectionQuery = (t, contentType)=>{
|
|
2290
|
-
const { uid } = contentType;
|
|
2291
|
-
const queryName = getFindConnectionQueryName(contentType);
|
|
2292
|
-
const responseCollectionTypeName = getEntityResponseCollectionName(contentType);
|
|
2293
|
-
t.field(queryName, {
|
|
2294
|
-
type: responseCollectionTypeName,
|
|
2295
|
-
extensions: {
|
|
2296
|
-
strapi: {
|
|
2297
|
-
contentType
|
|
2298
|
-
}
|
|
2299
|
-
},
|
|
2300
|
-
args: getContentTypeArgs(contentType),
|
|
2301
|
-
async resolve (parent, args, ctx) {
|
|
2302
|
-
const transformedArgs = transformArgs(args, {
|
|
2303
|
-
contentType,
|
|
2304
|
-
usePagination: true
|
|
2305
|
-
});
|
|
2306
|
-
const { findMany } = getService('builders').get('content-api').buildQueriesResolvers({
|
|
2307
|
-
contentType
|
|
2308
|
-
});
|
|
2309
|
-
// queryResolvers will sanitize params
|
|
2310
|
-
const nodes = await findMany(parent, transformedArgs, ctx);
|
|
2311
|
-
return toEntityResponseCollection(nodes, {
|
|
2312
|
-
args: transformedArgs,
|
|
2313
|
-
resourceUID: uid
|
|
2314
|
-
});
|
|
2315
|
-
}
|
|
2316
|
-
});
|
|
2317
|
-
};
|
|
2318
|
-
return {
|
|
2319
|
-
buildCollectionTypeQueries
|
|
2320
|
-
};
|
|
2321
|
-
});
|
|
2322
|
-
|
|
2323
|
-
var createSingleTypeQueriesBuilder = (({ strapi })=>{
|
|
2324
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
2325
|
-
const { naming } = getService('utils');
|
|
2326
|
-
const { transformArgs, getContentTypeArgs } = getService('builders').utils;
|
|
2327
|
-
const { getFindOneQueryName, getTypeName } = naming;
|
|
2328
|
-
const buildSingleTypeQueries = (contentType)=>{
|
|
2329
|
-
const findQueryName = `Query.${getFindOneQueryName(contentType)}`;
|
|
2330
|
-
const extension = getService('extension');
|
|
2331
|
-
const registerAuthConfig = (action, auth)=>{
|
|
2332
|
-
return extension.use({
|
|
2333
|
-
resolversConfig: {
|
|
2334
|
-
[action]: {
|
|
2335
|
-
auth
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
});
|
|
2339
|
-
};
|
|
2340
|
-
const isActionEnabled = (action)=>{
|
|
2341
|
-
return extension.shadowCRUD(contentType.uid).isActionEnabled(action);
|
|
2342
|
-
};
|
|
2343
|
-
const isFindEnabled = isActionEnabled('find');
|
|
2344
|
-
if (isFindEnabled) {
|
|
2345
|
-
registerAuthConfig(findQueryName, {
|
|
2346
|
-
scope: [
|
|
2347
|
-
`${contentType.uid}.find`
|
|
2348
|
-
]
|
|
2349
|
-
});
|
|
2350
|
-
}
|
|
2351
|
-
return extendType({
|
|
2352
|
-
type: 'Query',
|
|
2353
|
-
definition (t) {
|
|
2354
|
-
if (isFindEnabled) {
|
|
2355
|
-
addFindQuery(t, contentType);
|
|
2356
|
-
}
|
|
2357
|
-
}
|
|
2358
|
-
});
|
|
2359
|
-
};
|
|
2360
|
-
const addFindQuery = (t, contentType)=>{
|
|
2361
|
-
const findQueryName = getFindOneQueryName(contentType);
|
|
2362
|
-
const typeName = getTypeName(contentType);
|
|
2363
|
-
t.field(findQueryName, {
|
|
2364
|
-
type: typeName,
|
|
2365
|
-
extensions: {
|
|
2366
|
-
strapi: {
|
|
2367
|
-
contentType
|
|
2368
|
-
}
|
|
2369
|
-
},
|
|
2370
|
-
args: getContentTypeArgs(contentType),
|
|
2371
|
-
async resolve (parent, args, ctx) {
|
|
2372
|
-
const transformedArgs = transformArgs(args, {
|
|
2373
|
-
contentType
|
|
2374
|
-
});
|
|
2375
|
-
const { findFirst } = getService('builders').get('content-api').buildQueriesResolvers({
|
|
2376
|
-
contentType
|
|
2377
|
-
});
|
|
2378
|
-
return findFirst(parent, transformedArgs, ctx);
|
|
2379
|
-
}
|
|
2380
|
-
});
|
|
2381
|
-
};
|
|
2382
|
-
return {
|
|
2383
|
-
buildSingleTypeQueries
|
|
2384
|
-
};
|
|
2385
|
-
});
|
|
2386
|
-
|
|
2387
|
-
var queries = ((context)=>({
|
|
2388
|
-
...createCollectionTypeQueriesBuilder(context),
|
|
2389
|
-
...createSingleTypeQueriesBuilder(context)
|
|
2390
|
-
}));
|
|
2391
|
-
|
|
2392
|
-
var createCollectionTypeMutationsBuilder = (({ strapi })=>{
|
|
2393
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
2394
|
-
const { naming } = getService('utils');
|
|
2395
|
-
const { args } = getService('internals');
|
|
2396
|
-
const { getCreateMutationTypeName, getUpdateMutationTypeName, getDeleteMutationTypeName, getContentTypeInputName, getTypeName } = naming;
|
|
2397
|
-
const addCreateMutation = (t, contentType)=>{
|
|
2398
|
-
const { uid } = contentType;
|
|
2399
|
-
const createMutationName = getCreateMutationTypeName(contentType);
|
|
2400
|
-
const typeName = getTypeName(contentType);
|
|
2401
|
-
t.field(createMutationName, {
|
|
2402
|
-
type: typeName,
|
|
2403
|
-
extensions: {
|
|
2404
|
-
strapi: {
|
|
2405
|
-
contentType
|
|
2406
|
-
}
|
|
2407
|
-
},
|
|
2408
|
-
args: {
|
|
2409
|
-
// Create payload
|
|
2410
|
-
status: args.PublicationStatusArg,
|
|
2411
|
-
data: nonNull(getContentTypeInputName(contentType))
|
|
2412
|
-
},
|
|
2413
|
-
async resolve (parent, args, context) {
|
|
2414
|
-
const { auth } = context.state;
|
|
2415
|
-
// Sanitize input data
|
|
2416
|
-
const sanitizedInputData = await strapi.contentAPI.sanitize.input(args.data, contentType, {
|
|
2417
|
-
auth
|
|
2418
|
-
});
|
|
2419
|
-
return strapi.documents(uid).create({
|
|
2420
|
-
...args,
|
|
2421
|
-
data: sanitizedInputData
|
|
2422
|
-
});
|
|
2423
|
-
}
|
|
2424
|
-
});
|
|
2425
|
-
};
|
|
2426
|
-
const addUpdateMutation = (t, contentType)=>{
|
|
2427
|
-
const { uid } = contentType;
|
|
2428
|
-
const updateMutationName = getUpdateMutationTypeName(contentType);
|
|
2429
|
-
const typeName = getTypeName(contentType);
|
|
2430
|
-
t.field(updateMutationName, {
|
|
2431
|
-
type: typeName,
|
|
2432
|
-
extensions: {
|
|
2433
|
-
strapi: {
|
|
2434
|
-
contentType
|
|
2435
|
-
}
|
|
2436
|
-
},
|
|
2437
|
-
args: {
|
|
2438
|
-
documentId: nonNull(idArg()),
|
|
2439
|
-
status: args.PublicationStatusArg,
|
|
2440
|
-
data: nonNull(getContentTypeInputName(contentType))
|
|
2441
|
-
},
|
|
2442
|
-
async resolve (parent, args, context) {
|
|
2443
|
-
const { auth } = context.state;
|
|
2444
|
-
const { data, ...restParams } = args;
|
|
2445
|
-
// Sanitize input data
|
|
2446
|
-
const sanitizedInputData = await strapi.contentAPI.sanitize.input(data, contentType, {
|
|
2447
|
-
auth
|
|
2448
|
-
});
|
|
2449
|
-
return strapi.documents(uid).update({
|
|
2450
|
-
...restParams,
|
|
2451
|
-
data: sanitizedInputData
|
|
2452
|
-
});
|
|
2453
|
-
}
|
|
2454
|
-
});
|
|
2455
|
-
};
|
|
2456
|
-
const addDeleteMutation = (t, contentType)=>{
|
|
2457
|
-
const { uid } = contentType;
|
|
2458
|
-
const deleteMutationName = getDeleteMutationTypeName(contentType);
|
|
2459
|
-
const { DELETE_MUTATION_RESPONSE_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
2460
|
-
t.field(deleteMutationName, {
|
|
2461
|
-
type: DELETE_MUTATION_RESPONSE_TYPE_NAME,
|
|
2462
|
-
extensions: {
|
|
2463
|
-
strapi: {
|
|
2464
|
-
contentType
|
|
2465
|
-
}
|
|
2466
|
-
},
|
|
2467
|
-
args: {
|
|
2468
|
-
documentId: nonNull(idArg())
|
|
2469
|
-
},
|
|
2470
|
-
async resolve (parent, args) {
|
|
2471
|
-
const { documentId } = args;
|
|
2472
|
-
await strapi.documents(uid).delete({
|
|
2473
|
-
documentId
|
|
2474
|
-
});
|
|
2475
|
-
return {
|
|
2476
|
-
documentId
|
|
2477
|
-
};
|
|
2478
|
-
}
|
|
2479
|
-
});
|
|
2480
|
-
};
|
|
2481
|
-
return {
|
|
2482
|
-
buildCollectionTypeMutations (contentType) {
|
|
2483
|
-
const createMutationName = `Mutation.${getCreateMutationTypeName(contentType)}`;
|
|
2484
|
-
const updateMutationName = `Mutation.${getUpdateMutationTypeName(contentType)}`;
|
|
2485
|
-
const deleteMutationName = `Mutation.${getDeleteMutationTypeName(contentType)}`;
|
|
2486
|
-
const extension = getService('extension');
|
|
2487
|
-
const registerAuthConfig = (action, auth)=>{
|
|
2488
|
-
return extension.use({
|
|
2489
|
-
resolversConfig: {
|
|
2490
|
-
[action]: {
|
|
2491
|
-
auth
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
});
|
|
2495
|
-
};
|
|
2496
|
-
const isActionEnabled = (action)=>{
|
|
2497
|
-
return extension.shadowCRUD(contentType.uid).isActionEnabled(action);
|
|
2498
|
-
};
|
|
2499
|
-
const isCreateEnabled = isActionEnabled('create');
|
|
2500
|
-
const isUpdateEnabled = isActionEnabled('update');
|
|
2501
|
-
const isDeleteEnabled = isActionEnabled('delete');
|
|
2502
|
-
if (isCreateEnabled) {
|
|
2503
|
-
registerAuthConfig(createMutationName, {
|
|
2504
|
-
scope: [
|
|
2505
|
-
`${contentType.uid}.create`
|
|
2506
|
-
]
|
|
2507
|
-
});
|
|
2508
|
-
}
|
|
2509
|
-
if (isUpdateEnabled) {
|
|
2510
|
-
registerAuthConfig(updateMutationName, {
|
|
2511
|
-
scope: [
|
|
2512
|
-
`${contentType.uid}.update`
|
|
2513
|
-
]
|
|
2514
|
-
});
|
|
2515
|
-
}
|
|
2516
|
-
if (isDeleteEnabled) {
|
|
2517
|
-
registerAuthConfig(deleteMutationName, {
|
|
2518
|
-
scope: [
|
|
2519
|
-
`${contentType.uid}.delete`
|
|
2520
|
-
]
|
|
2521
|
-
});
|
|
2522
|
-
}
|
|
2523
|
-
return extendType({
|
|
2524
|
-
type: 'Mutation',
|
|
2525
|
-
definition (t) {
|
|
2526
|
-
if (isCreateEnabled) {
|
|
2527
|
-
addCreateMutation(t, contentType);
|
|
2528
|
-
}
|
|
2529
|
-
if (isUpdateEnabled) {
|
|
2530
|
-
addUpdateMutation(t, contentType);
|
|
2531
|
-
}
|
|
2532
|
-
if (isDeleteEnabled) {
|
|
2533
|
-
addDeleteMutation(t, contentType);
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
});
|
|
2537
|
-
}
|
|
2538
|
-
};
|
|
2539
|
-
});
|
|
2540
|
-
|
|
2541
|
-
const { NotFoundError } = errors;
|
|
2542
|
-
var createSingleTypeMutationsBuilder = (({ strapi })=>{
|
|
2543
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
2544
|
-
const { naming } = getService('utils');
|
|
2545
|
-
const { args } = getService('internals');
|
|
2546
|
-
const { getUpdateMutationTypeName, getTypeName, getContentTypeInputName, getDeleteMutationTypeName } = naming;
|
|
2547
|
-
const addUpdateMutation = (t, contentType)=>{
|
|
2548
|
-
const { uid } = contentType;
|
|
2549
|
-
const updateMutationName = getUpdateMutationTypeName(contentType);
|
|
2550
|
-
const typeName = getTypeName(contentType);
|
|
2551
|
-
t.field(updateMutationName, {
|
|
2552
|
-
type: typeName,
|
|
2553
|
-
extensions: {
|
|
2554
|
-
strapi: {
|
|
2555
|
-
contentType
|
|
2556
|
-
}
|
|
2557
|
-
},
|
|
2558
|
-
args: {
|
|
2559
|
-
// Update payload
|
|
2560
|
-
status: args.PublicationStatusArg,
|
|
2561
|
-
data: nonNull(getContentTypeInputName(contentType))
|
|
2562
|
-
},
|
|
2563
|
-
async resolve (parent, args, context) {
|
|
2564
|
-
const { auth } = context.state;
|
|
2565
|
-
// Sanitize input data
|
|
2566
|
-
const sanitizedInputData = await strapi.contentAPI.sanitize.input(args.data, contentType, {
|
|
2567
|
-
auth
|
|
2568
|
-
});
|
|
2569
|
-
const document = await strapi.db?.query(uid).findOne();
|
|
2570
|
-
if (document) {
|
|
2571
|
-
return strapi.documents(uid).update({
|
|
2572
|
-
...args,
|
|
2573
|
-
documentId: document.documentId,
|
|
2574
|
-
data: sanitizedInputData
|
|
2575
|
-
});
|
|
2576
|
-
}
|
|
2577
|
-
return strapi.documents(uid).create({
|
|
2578
|
-
...args,
|
|
2579
|
-
data: sanitizedInputData
|
|
2580
|
-
});
|
|
2581
|
-
}
|
|
2582
|
-
});
|
|
2583
|
-
};
|
|
2584
|
-
const addDeleteMutation = (t, contentType)=>{
|
|
2585
|
-
const { uid } = contentType;
|
|
2586
|
-
const deleteMutationName = getDeleteMutationTypeName(contentType);
|
|
2587
|
-
const { DELETE_MUTATION_RESPONSE_TYPE_NAME } = strapi.plugin('graphql').service('constants');
|
|
2588
|
-
t.field(deleteMutationName, {
|
|
2589
|
-
type: DELETE_MUTATION_RESPONSE_TYPE_NAME,
|
|
2590
|
-
extensions: {
|
|
2591
|
-
strapi: {
|
|
2592
|
-
contentType
|
|
2593
|
-
}
|
|
2594
|
-
},
|
|
2595
|
-
args: {},
|
|
2596
|
-
async resolve (parent, args) {
|
|
2597
|
-
const document = await strapi.db?.query(uid).findOne();
|
|
2598
|
-
if (!document) {
|
|
2599
|
-
throw new NotFoundError('Document not found');
|
|
2600
|
-
}
|
|
2601
|
-
await strapi.documents(uid).delete({
|
|
2602
|
-
...args,
|
|
2603
|
-
documentId: document.documentId
|
|
2604
|
-
});
|
|
2605
|
-
return document;
|
|
2606
|
-
}
|
|
2607
|
-
});
|
|
2608
|
-
};
|
|
2609
|
-
return {
|
|
2610
|
-
buildSingleTypeMutations (contentType) {
|
|
2611
|
-
const updateMutationName = `Mutation.${getUpdateMutationTypeName(contentType)}`;
|
|
2612
|
-
const deleteMutationName = `Mutation.${getDeleteMutationTypeName(contentType)}`;
|
|
2613
|
-
const extension = getService('extension');
|
|
2614
|
-
const registerAuthConfig = (action, auth)=>{
|
|
2615
|
-
return extension.use({
|
|
2616
|
-
resolversConfig: {
|
|
2617
|
-
[action]: {
|
|
2618
|
-
auth
|
|
2619
|
-
}
|
|
2620
|
-
}
|
|
2621
|
-
});
|
|
2622
|
-
};
|
|
2623
|
-
const isActionEnabled = (action)=>{
|
|
2624
|
-
return extension.shadowCRUD(contentType.uid).isActionEnabled(action);
|
|
2625
|
-
};
|
|
2626
|
-
const isUpdateEnabled = isActionEnabled('update');
|
|
2627
|
-
const isDeleteEnabled = isActionEnabled('delete');
|
|
2628
|
-
if (isUpdateEnabled) {
|
|
2629
|
-
registerAuthConfig(updateMutationName, {
|
|
2630
|
-
scope: [
|
|
2631
|
-
`${contentType.uid}.update`
|
|
2632
|
-
]
|
|
2633
|
-
});
|
|
2634
|
-
}
|
|
2635
|
-
if (isDeleteEnabled) {
|
|
2636
|
-
registerAuthConfig(deleteMutationName, {
|
|
2637
|
-
scope: [
|
|
2638
|
-
`${contentType.uid}.delete`
|
|
2639
|
-
]
|
|
2640
|
-
});
|
|
2641
|
-
}
|
|
2642
|
-
return extendType({
|
|
2643
|
-
type: 'Mutation',
|
|
2644
|
-
definition (t) {
|
|
2645
|
-
if (isUpdateEnabled) {
|
|
2646
|
-
addUpdateMutation(t, contentType);
|
|
2647
|
-
}
|
|
2648
|
-
if (isDeleteEnabled) {
|
|
2649
|
-
addDeleteMutation(t, contentType);
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
});
|
|
2653
|
-
}
|
|
2654
|
-
};
|
|
2655
|
-
});
|
|
2656
|
-
|
|
2657
|
-
var mutations = ((context)=>({
|
|
2658
|
-
...createCollectionTypeMutationsBuilder(context),
|
|
2659
|
-
...createSingleTypeMutationsBuilder(context)
|
|
2660
|
-
}));
|
|
2661
|
-
|
|
2662
|
-
var contentType = (({ strapi })=>{
|
|
2663
|
-
const rootLevelOperators = ()=>{
|
|
2664
|
-
const { operators } = strapi.plugin('graphql').service('builders').filters;
|
|
2665
|
-
return [
|
|
2666
|
-
operators.and,
|
|
2667
|
-
operators.or,
|
|
2668
|
-
operators.not
|
|
2669
|
-
];
|
|
2670
|
-
};
|
|
2671
|
-
const addScalarAttribute = (builder, attributeName, attribute)=>{
|
|
2672
|
-
const { naming, mappers } = strapi.plugin('graphql').service('utils');
|
|
2673
|
-
const gqlType = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
2674
|
-
builder.field(attributeName, {
|
|
2675
|
-
type: naming.getScalarFilterInputTypeName(gqlType)
|
|
2676
|
-
});
|
|
2677
|
-
};
|
|
2678
|
-
const addRelationalAttribute = (builder, attributeName, attribute)=>{
|
|
2679
|
-
const utils = strapi.plugin('graphql').service('utils');
|
|
2680
|
-
const extension = strapi.plugin('graphql').service('extension');
|
|
2681
|
-
const { getFiltersInputTypeName } = utils.naming;
|
|
2682
|
-
const { isMorphRelation } = utils.attributes;
|
|
2683
|
-
const model = 'target' in attribute && strapi.getModel(attribute.target);
|
|
2684
|
-
// If there is no model corresponding to the attribute configuration
|
|
2685
|
-
// or if the attribute is a polymorphic relation, then ignore it
|
|
2686
|
-
if (!model || isMorphRelation(attribute)) return;
|
|
2687
|
-
// If the target model is disabled, then ignore it too
|
|
2688
|
-
if (extension.shadowCRUD(model.uid).isDisabled()) return;
|
|
2689
|
-
builder.field(attributeName, {
|
|
2690
|
-
type: getFiltersInputTypeName(model)
|
|
2691
|
-
});
|
|
2692
|
-
};
|
|
2693
|
-
const addComponentAttribute = (builder, attributeName, attribute)=>{
|
|
2694
|
-
const utils = strapi.plugin('graphql').service('utils');
|
|
2695
|
-
const extension = strapi.plugin('graphql').service('extension');
|
|
2696
|
-
const { getFiltersInputTypeName } = utils.naming;
|
|
2697
|
-
const component = strapi.getModel(attribute.component);
|
|
2698
|
-
// If there is no component corresponding to the attribute configuration, then ignore it
|
|
2699
|
-
if (!component) return;
|
|
2700
|
-
// If the component is disabled, then ignore it too
|
|
2701
|
-
if (extension.shadowCRUD(component.uid).isDisabled()) return;
|
|
2702
|
-
builder.field(attributeName, {
|
|
2703
|
-
type: getFiltersInputTypeName(component)
|
|
2704
|
-
});
|
|
2705
|
-
};
|
|
2706
|
-
const buildContentTypeFilters = (contentType)=>{
|
|
2707
|
-
const utils = strapi.plugin('graphql').service('utils');
|
|
2708
|
-
const extension = strapi.plugin('graphql').service('extension');
|
|
2709
|
-
const { getFiltersInputTypeName, getScalarFilterInputTypeName } = utils.naming;
|
|
2710
|
-
const { isStrapiScalar, isRelation, isComponent } = utils.attributes;
|
|
2711
|
-
const { attributes } = contentType;
|
|
2712
|
-
const filtersTypeName = getFiltersInputTypeName(contentType);
|
|
2713
|
-
return inputObjectType({
|
|
2714
|
-
name: filtersTypeName,
|
|
2715
|
-
definition (t) {
|
|
2716
|
-
const validAttributes = Object.entries(attributes)// Remove private attributes
|
|
2717
|
-
.filter(([attributeName])=>!contentTypes.isPrivateAttribute(contentType, attributeName))// Remove attributes that have been disabled using the shadow CRUD extension API
|
|
2718
|
-
.filter(([attributeName])=>extension.shadowCRUD(contentType.uid).field(attributeName).hasFiltersEnabeld());
|
|
2719
|
-
const isIDFilterEnabled = extension.shadowCRUD(contentType.uid).field('documentId').hasFiltersEnabeld();
|
|
2720
|
-
// Add an ID filter to the collection types
|
|
2721
|
-
if (contentType.kind === 'collectionType' && isIDFilterEnabled) {
|
|
2722
|
-
t.field('documentId', {
|
|
2723
|
-
type: getScalarFilterInputTypeName('ID')
|
|
2724
|
-
});
|
|
2725
|
-
}
|
|
2726
|
-
// Add every defined attribute
|
|
2727
|
-
for (const [attributeName, attribute] of validAttributes){
|
|
2728
|
-
// Handle scalars
|
|
2729
|
-
if (isStrapiScalar(attribute)) {
|
|
2730
|
-
addScalarAttribute(t, attributeName, attribute);
|
|
2731
|
-
} else if (isRelation(attribute)) {
|
|
2732
|
-
addRelationalAttribute(t, attributeName, attribute);
|
|
2733
|
-
} else if (isComponent(attribute)) {
|
|
2734
|
-
addComponentAttribute(t, attributeName, attribute);
|
|
2735
|
-
}
|
|
2736
|
-
}
|
|
2737
|
-
// Conditional clauses
|
|
2738
|
-
for (const operator of rootLevelOperators()){
|
|
2739
|
-
operator.add(t, filtersTypeName);
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
});
|
|
2743
|
-
};
|
|
2744
|
-
return {
|
|
2745
|
-
buildContentTypeFilters
|
|
2746
|
-
};
|
|
2747
|
-
});
|
|
2748
|
-
|
|
2749
|
-
var filters = ((context)=>({
|
|
2750
|
-
...contentType(context)
|
|
2751
|
-
}));
|
|
2752
|
-
|
|
2753
|
-
const { isWritableAttribute } = contentTypes;
|
|
2754
|
-
var inputs = (({ strapi })=>{
|
|
2755
|
-
const { naming, mappers, attributes } = strapi.plugin('graphql').service('utils');
|
|
2756
|
-
const extension = strapi.plugin('graphql').service('extension');
|
|
2757
|
-
const { getComponentInputName, getContentTypeInputName, getEnumName, getDynamicZoneInputName } = naming;
|
|
2758
|
-
const { isStrapiScalar, isRelation, isMorphRelation, isMedia, isEnumeration, isComponent, isDynamicZone } = attributes;
|
|
2759
|
-
return {
|
|
2760
|
-
buildInputType (contentType) {
|
|
2761
|
-
const { attributes, modelType } = contentType;
|
|
2762
|
-
const name = (modelType === 'component' ? getComponentInputName : getContentTypeInputName).call(null, contentType);
|
|
2763
|
-
return inputObjectType({
|
|
2764
|
-
name,
|
|
2765
|
-
definition (t) {
|
|
2766
|
-
const isFieldEnabled = (fieldName)=>{
|
|
2767
|
-
return extension.shadowCRUD(contentType.uid).field(fieldName).hasInputEnabled();
|
|
2768
|
-
};
|
|
2769
|
-
const validAttributes = Object.entries(attributes)// Remove private attributes
|
|
2770
|
-
.filter(([attributeName])=>!contentTypes.isPrivateAttribute(contentType, attributeName))// Remove non-writable attributes
|
|
2771
|
-
.filter(([attributeName])=>isWritableAttribute(contentType, attributeName))// Remove filters that have been disabled using the shadow CRUD extension API
|
|
2772
|
-
.filter(([attributeName])=>isFieldEnabled(attributeName));
|
|
2773
|
-
// Add the ID for the component to enable inplace updates
|
|
2774
|
-
if (modelType === 'component' && isFieldEnabled('id')) {
|
|
2775
|
-
t.id('id');
|
|
2776
|
-
}
|
|
2777
|
-
validAttributes.forEach(([attributeName, attribute])=>{
|
|
2778
|
-
// Enums
|
|
2779
|
-
if (isEnumeration(attribute)) {
|
|
2780
|
-
const enumTypeName = getEnumName(contentType, attributeName);
|
|
2781
|
-
t.field(attributeName, {
|
|
2782
|
-
type: enumTypeName
|
|
2783
|
-
});
|
|
2784
|
-
} else if (isStrapiScalar(attribute)) {
|
|
2785
|
-
const gqlScalar = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
2786
|
-
t.field(attributeName, {
|
|
2787
|
-
type: gqlScalar
|
|
2788
|
-
});
|
|
2789
|
-
} else if (isMedia(attribute)) {
|
|
2790
|
-
const isMultiple = attribute.multiple === true;
|
|
2791
|
-
if (extension.shadowCRUD('plugin::upload.file').isDisabled()) {
|
|
2792
|
-
return;
|
|
2793
|
-
}
|
|
2794
|
-
if (isMultiple) {
|
|
2795
|
-
t.list.id(attributeName);
|
|
2796
|
-
} else {
|
|
2797
|
-
t.id(attributeName);
|
|
2798
|
-
}
|
|
2799
|
-
} else if (isRelation(attribute) && !isMorphRelation(attribute)) {
|
|
2800
|
-
if (extension.shadowCRUD(attribute.target).isDisabled()) {
|
|
2801
|
-
return;
|
|
2802
|
-
}
|
|
2803
|
-
const isToManyRelation = attribute.relation.endsWith('Many');
|
|
2804
|
-
if (isToManyRelation) {
|
|
2805
|
-
t.list.id(attributeName);
|
|
2806
|
-
} else {
|
|
2807
|
-
t.id(attributeName);
|
|
2808
|
-
}
|
|
2809
|
-
} else if (isComponent(attribute)) {
|
|
2810
|
-
const isRepeatable = attribute.repeatable === true;
|
|
2811
|
-
const component = strapi.components[attribute.component];
|
|
2812
|
-
const componentInputType = getComponentInputName(component);
|
|
2813
|
-
if (isRepeatable) {
|
|
2814
|
-
t.list.field(attributeName, {
|
|
2815
|
-
type: componentInputType
|
|
2816
|
-
});
|
|
2817
|
-
} else {
|
|
2818
|
-
t.field(attributeName, {
|
|
2819
|
-
type: componentInputType
|
|
2820
|
-
});
|
|
2821
|
-
}
|
|
2822
|
-
} else if (isDynamicZone(attribute)) {
|
|
2823
|
-
const dzInputName = getDynamicZoneInputName(contentType, attributeName);
|
|
2824
|
-
t.list.field(attributeName, {
|
|
2825
|
-
type: nonNull(dzInputName)
|
|
2826
|
-
});
|
|
2827
|
-
}
|
|
2828
|
-
});
|
|
2829
|
-
}
|
|
2830
|
-
});
|
|
2831
|
-
}
|
|
2832
|
-
};
|
|
2833
|
-
});
|
|
2834
|
-
|
|
2835
|
-
var genericMorph = (({ strapi, registry })=>{
|
|
2836
|
-
const { naming } = strapi.plugin('graphql').service('utils');
|
|
2837
|
-
const { KINDS, GENERIC_MORPH_TYPENAME } = strapi.plugin('graphql').service('constants');
|
|
2838
|
-
return {
|
|
2839
|
-
buildGenericMorphDefinition () {
|
|
2840
|
-
return unionType({
|
|
2841
|
-
name: GENERIC_MORPH_TYPENAME,
|
|
2842
|
-
resolveType (obj) {
|
|
2843
|
-
const contentType = strapi.getModel(obj.__type);
|
|
2844
|
-
if (!contentType) {
|
|
2845
|
-
return null;
|
|
2846
|
-
}
|
|
2847
|
-
if (contentType.modelType === 'component') {
|
|
2848
|
-
return naming.getComponentName(contentType);
|
|
2849
|
-
}
|
|
2850
|
-
return naming.getTypeName(contentType);
|
|
2851
|
-
},
|
|
2852
|
-
definition (t) {
|
|
2853
|
-
const members = registry// Resolve every content-type or component
|
|
2854
|
-
.where(({ config })=>[
|
|
2855
|
-
KINDS.type,
|
|
2856
|
-
KINDS.component
|
|
2857
|
-
].includes(config.kind))// Only keep their name (the type's id)
|
|
2858
|
-
.map(prop('name'));
|
|
2859
|
-
t.members(...members);
|
|
2860
|
-
}
|
|
2861
|
-
});
|
|
2862
|
-
}
|
|
2863
|
-
};
|
|
2864
|
-
});
|
|
2865
|
-
|
|
2866
|
-
const { ApplicationError } = errors;
|
|
2867
|
-
var associationResolvers = (({ strapi })=>{
|
|
2868
|
-
const { service: getGraphQLService } = strapi.plugin('graphql');
|
|
2869
|
-
const { isMorphRelation, isMedia } = getGraphQLService('utils').attributes;
|
|
2870
|
-
const { transformArgs } = getGraphQLService('builders').utils;
|
|
2871
|
-
const { toEntityResponse, toEntityResponseCollection } = getGraphQLService('format').returnTypes;
|
|
2872
|
-
return {
|
|
2873
|
-
buildAssociationResolver ({ contentTypeUID, attributeName }) {
|
|
2874
|
-
const contentType = strapi.getModel(contentTypeUID);
|
|
2875
|
-
const attribute = contentType.attributes[attributeName];
|
|
2876
|
-
if (!attribute) {
|
|
2877
|
-
throw new ApplicationError(`Failed to build an association resolver for ${contentTypeUID}::${attributeName}`);
|
|
2878
|
-
}
|
|
2879
|
-
const isMediaAttribute = isMedia(attribute);
|
|
2880
|
-
const isMorphAttribute = isMorphRelation(attribute);
|
|
2881
|
-
const targetUID = isMediaAttribute ? 'plugin::upload.file' : attribute.target;
|
|
2882
|
-
const isToMany = isMediaAttribute ? attribute.multiple : attribute.relation.endsWith('Many');
|
|
2883
|
-
const targetContentType = strapi.getModel(targetUID);
|
|
2884
|
-
return async (parent, args = {}, context = {})=>{
|
|
2885
|
-
const { auth } = context.state;
|
|
2886
|
-
const transformedArgs = transformArgs(args, {
|
|
2887
|
-
contentType: targetContentType,
|
|
2888
|
-
usePagination: true
|
|
2889
|
-
});
|
|
2890
|
-
await strapi.contentAPI.validate.query(transformedArgs, targetContentType, {
|
|
2891
|
-
auth
|
|
2892
|
-
});
|
|
2893
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(transformedArgs, targetContentType, {
|
|
2894
|
-
auth
|
|
2895
|
-
});
|
|
2896
|
-
const dbQuery = strapi.get('query-params').transform(targetUID, sanitizedQuery);
|
|
2897
|
-
const data = await strapi.db?.query(contentTypeUID).load(parent, attributeName, dbQuery);
|
|
2898
|
-
const info = {
|
|
2899
|
-
args: sanitizedQuery,
|
|
2900
|
-
resourceUID: targetUID
|
|
2901
|
-
};
|
|
2902
|
-
// If this a polymorphic association, it sanitizes & returns the raw data
|
|
2903
|
-
// Note: The value needs to be wrapped in a fake object that represents its parent
|
|
2904
|
-
// so that the sanitize util can work properly.
|
|
2905
|
-
if (isMorphAttribute) {
|
|
2906
|
-
// Helpers used for the data cleanup
|
|
2907
|
-
const wrapData = (dataToWrap)=>({
|
|
2908
|
-
[attributeName]: dataToWrap
|
|
2909
|
-
});
|
|
2910
|
-
const sanitizeData = (dataToSanitize)=>{
|
|
2911
|
-
return strapi.contentAPI.sanitize.output(dataToSanitize, contentType, {
|
|
2912
|
-
auth
|
|
2913
|
-
});
|
|
2914
|
-
};
|
|
2915
|
-
const unwrapData = get(attributeName);
|
|
2916
|
-
// Sanitizer definition
|
|
2917
|
-
const sanitizeMorphAttribute = async.pipe(wrapData, sanitizeData, unwrapData);
|
|
2918
|
-
return sanitizeMorphAttribute(data);
|
|
2919
|
-
}
|
|
2920
|
-
// If this is a to-many relation, it returns an object that
|
|
2921
|
-
// matches what the entity-response-collection's resolvers expect
|
|
2922
|
-
if (isToMany) {
|
|
2923
|
-
return toEntityResponseCollection(data, info);
|
|
2924
|
-
}
|
|
2925
|
-
// Else, it returns an object that matches
|
|
2926
|
-
// what the entity-response's resolvers expect
|
|
2927
|
-
return toEntityResponse(data, info);
|
|
2928
|
-
};
|
|
2929
|
-
}
|
|
2930
|
-
};
|
|
2931
|
-
});
|
|
2932
|
-
|
|
2933
|
-
var queriesResolvers = (({ strapi })=>({
|
|
2934
|
-
buildQueriesResolvers ({ contentType }) {
|
|
2935
|
-
const { uid } = contentType;
|
|
2936
|
-
return {
|
|
2937
|
-
async findMany (parent, args, ctx) {
|
|
2938
|
-
await strapi.contentAPI.validate.query(args, contentType, {
|
|
2939
|
-
auth: ctx?.state?.auth
|
|
2940
|
-
});
|
|
2941
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(args, contentType, {
|
|
2942
|
-
auth: ctx?.state?.auth
|
|
2943
|
-
});
|
|
2944
|
-
return strapi.documents(uid).findMany({
|
|
2945
|
-
status: 'published',
|
|
2946
|
-
...sanitizedQuery
|
|
2947
|
-
});
|
|
2948
|
-
},
|
|
2949
|
-
async findFirst (parent, args, ctx) {
|
|
2950
|
-
await strapi.contentAPI.validate.query(args, contentType, {
|
|
2951
|
-
auth: ctx?.state?.auth
|
|
2952
|
-
});
|
|
2953
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(args, contentType, {
|
|
2954
|
-
auth: ctx?.state?.auth
|
|
2955
|
-
});
|
|
2956
|
-
return strapi.documents(uid).findFirst({
|
|
2957
|
-
status: 'published',
|
|
2958
|
-
...sanitizedQuery
|
|
2959
|
-
});
|
|
2960
|
-
},
|
|
2961
|
-
async findOne (parent, args, ctx) {
|
|
2962
|
-
const { documentId } = args;
|
|
2963
|
-
await strapi.contentAPI.validate.query(args, contentType, {
|
|
2964
|
-
auth: ctx?.state?.auth
|
|
2965
|
-
});
|
|
2966
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(args, contentType, {
|
|
2967
|
-
auth: ctx?.state?.auth
|
|
2968
|
-
});
|
|
2969
|
-
return strapi.documents(uid).findOne({
|
|
2970
|
-
status: 'published',
|
|
2971
|
-
...omit([
|
|
2972
|
-
'id',
|
|
2973
|
-
'documentId'
|
|
2974
|
-
], sanitizedQuery),
|
|
2975
|
-
documentId
|
|
2976
|
-
});
|
|
2977
|
-
}
|
|
2978
|
-
};
|
|
2979
|
-
}
|
|
2980
|
-
}));
|
|
2981
|
-
|
|
2982
|
-
var componentResolvers = (({ strapi })=>({
|
|
2983
|
-
buildComponentResolver ({ contentTypeUID, attributeName }) {
|
|
2984
|
-
const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
|
|
2985
|
-
return async (parent, args, ctx)=>{
|
|
2986
|
-
const contentType = strapi.getModel(contentTypeUID);
|
|
2987
|
-
const { component: componentName } = contentType.attributes[attributeName];
|
|
2988
|
-
const component = strapi.getModel(componentName);
|
|
2989
|
-
const transformedArgs = transformArgs(args, {
|
|
2990
|
-
contentType: component,
|
|
2991
|
-
usePagination: true
|
|
2992
|
-
});
|
|
2993
|
-
await strapi.contentAPI.validate.query(transformedArgs, component, {
|
|
2994
|
-
auth: ctx?.state?.auth
|
|
2995
|
-
});
|
|
2996
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(transformedArgs, component, {
|
|
2997
|
-
auth: ctx?.state?.auth
|
|
2998
|
-
});
|
|
2999
|
-
const dbQuery = strapi.get('query-params').transform(component.uid, sanitizedQuery);
|
|
3000
|
-
return strapi.db?.query(contentTypeUID).load(parent, attributeName, dbQuery);
|
|
3001
|
-
};
|
|
3002
|
-
}
|
|
3003
|
-
}));
|
|
3004
|
-
|
|
3005
|
-
var dynamicZoneResolvers = (({ strapi })=>({
|
|
3006
|
-
buildDynamicZoneResolver ({ contentTypeUID, attributeName }) {
|
|
3007
|
-
return async (parent)=>{
|
|
3008
|
-
return strapi.db?.query(contentTypeUID).load(parent, attributeName);
|
|
3009
|
-
};
|
|
3010
|
-
}
|
|
3011
|
-
}));
|
|
3012
|
-
|
|
3013
|
-
var paginationResolvers = (({ strapi })=>({
|
|
3014
|
-
async resolvePagination (parent, _, ctx) {
|
|
3015
|
-
const { args, resourceUID } = parent.info;
|
|
3016
|
-
const { start, limit } = args;
|
|
3017
|
-
const safeLimit = Math.max(limit, 1);
|
|
3018
|
-
const contentType = strapi.getModel(resourceUID);
|
|
3019
|
-
await strapi.contentAPI.validate.query(args, contentType, {
|
|
3020
|
-
auth: ctx?.state?.auth
|
|
3021
|
-
});
|
|
3022
|
-
const sanitizedQuery = await strapi.contentAPI.sanitize.query(args, contentType, {
|
|
3023
|
-
auth: ctx?.state?.auth
|
|
3024
|
-
});
|
|
3025
|
-
const total = await strapi.documents(resourceUID).count(sanitizedQuery);
|
|
3026
|
-
const pageSize = limit === -1 ? total - start : safeLimit;
|
|
3027
|
-
const pageCount = limit === -1 ? safeLimit : Math.ceil(total / safeLimit);
|
|
3028
|
-
const page = limit === -1 ? safeLimit : Math.floor(start / safeLimit) + 1;
|
|
3029
|
-
return {
|
|
3030
|
-
total,
|
|
3031
|
-
page,
|
|
3032
|
-
pageSize,
|
|
3033
|
-
pageCount
|
|
3034
|
-
};
|
|
3035
|
-
}
|
|
3036
|
-
}));
|
|
3037
|
-
|
|
3038
|
-
var resolvers = ((context)=>({
|
|
3039
|
-
// Generics
|
|
3040
|
-
...associationResolvers(context),
|
|
3041
|
-
// Builders
|
|
3042
|
-
...queriesResolvers(context),
|
|
3043
|
-
...componentResolvers(context),
|
|
3044
|
-
...dynamicZoneResolvers(context),
|
|
3045
|
-
...paginationResolvers(context)
|
|
3046
|
-
}));
|
|
3047
|
-
|
|
3048
|
-
const AND_FIELD_NAME = 'and';
|
|
3049
|
-
var andOperator = (()=>({
|
|
3050
|
-
fieldName: AND_FIELD_NAME,
|
|
3051
|
-
strapiOperator: '$and',
|
|
3052
|
-
add (t, type) {
|
|
3053
|
-
t.field(AND_FIELD_NAME, {
|
|
3054
|
-
type: list(type)
|
|
3055
|
-
});
|
|
3056
|
-
}
|
|
3057
|
-
}));
|
|
3058
|
-
|
|
3059
|
-
const OR_FIELD_NAME = 'or';
|
|
3060
|
-
var orOperator = (()=>({
|
|
3061
|
-
fieldName: OR_FIELD_NAME,
|
|
3062
|
-
strapiOperator: '$or',
|
|
3063
|
-
add (t, type) {
|
|
3064
|
-
t.field(OR_FIELD_NAME, {
|
|
3065
|
-
type: list(type)
|
|
3066
|
-
});
|
|
3067
|
-
}
|
|
3068
|
-
}));
|
|
3069
|
-
|
|
3070
|
-
const NOT_FIELD_NAME = 'not';
|
|
3071
|
-
var notOperator = (({ strapi })=>({
|
|
3072
|
-
fieldName: NOT_FIELD_NAME,
|
|
3073
|
-
strapiOperator: '$not',
|
|
3074
|
-
add (t, type) {
|
|
3075
|
-
const { naming, attributes } = strapi.plugin('graphql').service('utils');
|
|
3076
|
-
if (attributes.isGraphQLScalar({
|
|
3077
|
-
type
|
|
3078
|
-
})) {
|
|
3079
|
-
t.field(NOT_FIELD_NAME, {
|
|
3080
|
-
type: naming.getScalarFilterInputTypeName(type)
|
|
3081
|
-
});
|
|
3082
|
-
} else {
|
|
3083
|
-
t.field(NOT_FIELD_NAME, {
|
|
3084
|
-
type
|
|
3085
|
-
});
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
}));
|
|
3089
|
-
|
|
3090
|
-
const { ValidationError } = errors;
|
|
3091
|
-
const EQ_FIELD_NAME = 'eq';
|
|
3092
|
-
var eqOperator = (({ strapi })=>({
|
|
3093
|
-
fieldName: EQ_FIELD_NAME,
|
|
3094
|
-
strapiOperator: '$eq',
|
|
3095
|
-
add (t, type) {
|
|
3096
|
-
const { GRAPHQL_SCALARS } = strapi.plugin('graphql').service('constants');
|
|
3097
|
-
if (!GRAPHQL_SCALARS.includes(type)) {
|
|
3098
|
-
throw new ValidationError(`Can't use "${EQ_FIELD_NAME}" operator. "${type}" is not a valid scalar`);
|
|
3099
|
-
}
|
|
3100
|
-
t.field(EQ_FIELD_NAME, {
|
|
3101
|
-
type
|
|
3102
|
-
});
|
|
3103
|
-
}
|
|
3104
|
-
}));
|
|
3105
|
-
|
|
3106
|
-
const EQI_FIELD_NAME = 'eqi';
|
|
3107
|
-
var eqiOperator = (()=>({
|
|
3108
|
-
fieldName: EQI_FIELD_NAME,
|
|
3109
|
-
strapiOperator: '$eqi',
|
|
3110
|
-
add (t, type) {
|
|
3111
|
-
t.field(EQI_FIELD_NAME, {
|
|
3112
|
-
type
|
|
3113
|
-
});
|
|
3114
|
-
}
|
|
3115
|
-
}));
|
|
3116
|
-
|
|
3117
|
-
const NE_FIELD_NAME = 'ne';
|
|
3118
|
-
var neOperator = (()=>({
|
|
3119
|
-
fieldName: NE_FIELD_NAME,
|
|
3120
|
-
strapiOperator: '$ne',
|
|
3121
|
-
add (t, type) {
|
|
3122
|
-
t.field(NE_FIELD_NAME, {
|
|
3123
|
-
type
|
|
3124
|
-
});
|
|
3125
|
-
}
|
|
3126
|
-
}));
|
|
3127
|
-
|
|
3128
|
-
const NEI_FIELD_NAME = 'nei';
|
|
3129
|
-
var neiOperator = (()=>({
|
|
3130
|
-
fieldName: NEI_FIELD_NAME,
|
|
3131
|
-
strapiOperator: '$nei',
|
|
3132
|
-
add (t, type) {
|
|
3133
|
-
t.field(NEI_FIELD_NAME, {
|
|
3134
|
-
type
|
|
3135
|
-
});
|
|
3136
|
-
}
|
|
3137
|
-
}));
|
|
3138
|
-
|
|
3139
|
-
const STARTS_WITH_FIELD_NAME = 'startsWith';
|
|
3140
|
-
var startsWithOperator = (()=>({
|
|
3141
|
-
fieldName: STARTS_WITH_FIELD_NAME,
|
|
3142
|
-
strapiOperator: '$startsWith',
|
|
3143
|
-
add (t, type) {
|
|
3144
|
-
t.field(STARTS_WITH_FIELD_NAME, {
|
|
3145
|
-
type
|
|
3146
|
-
});
|
|
3147
|
-
}
|
|
3148
|
-
}));
|
|
3149
|
-
|
|
3150
|
-
const ENDS_WITH_FIELD_NAME = 'endsWith';
|
|
3151
|
-
var endsWithOperator = (()=>({
|
|
3152
|
-
fieldName: ENDS_WITH_FIELD_NAME,
|
|
3153
|
-
strapiOperator: '$endsWith',
|
|
3154
|
-
add (t, type) {
|
|
3155
|
-
t.field(ENDS_WITH_FIELD_NAME, {
|
|
3156
|
-
type
|
|
3157
|
-
});
|
|
3158
|
-
}
|
|
3159
|
-
}));
|
|
3160
|
-
|
|
3161
|
-
const CONTAINS_FIELD_NAME = 'contains';
|
|
3162
|
-
var containsOperator = (()=>({
|
|
3163
|
-
fieldName: CONTAINS_FIELD_NAME,
|
|
3164
|
-
strapiOperator: '$contains',
|
|
3165
|
-
add (t, type) {
|
|
3166
|
-
t.field(CONTAINS_FIELD_NAME, {
|
|
3167
|
-
type
|
|
3168
|
-
});
|
|
3169
|
-
}
|
|
3170
|
-
}));
|
|
3171
|
-
|
|
3172
|
-
const NOT_CONTAINS_FIELD_NAME = 'notContains';
|
|
3173
|
-
var notContainsOperator = (()=>({
|
|
3174
|
-
fieldName: NOT_CONTAINS_FIELD_NAME,
|
|
3175
|
-
strapiOperator: '$notContains',
|
|
3176
|
-
add (t, type) {
|
|
3177
|
-
t.field(NOT_CONTAINS_FIELD_NAME, {
|
|
3178
|
-
type
|
|
3179
|
-
});
|
|
3180
|
-
}
|
|
3181
|
-
}));
|
|
3182
|
-
|
|
3183
|
-
const CONTAINSI_FIELD_NAME = 'containsi';
|
|
3184
|
-
var containsiOperator = (()=>({
|
|
3185
|
-
fieldName: CONTAINSI_FIELD_NAME,
|
|
3186
|
-
strapiOperator: '$containsi',
|
|
3187
|
-
add (t, type) {
|
|
3188
|
-
t.field(CONTAINSI_FIELD_NAME, {
|
|
3189
|
-
type
|
|
3190
|
-
});
|
|
3191
|
-
}
|
|
3192
|
-
}));
|
|
3193
|
-
|
|
3194
|
-
const NOT_CONTAINSI_FIELD_NAME = 'notContainsi';
|
|
3195
|
-
var notContainsiOperator = (()=>({
|
|
3196
|
-
fieldName: NOT_CONTAINSI_FIELD_NAME,
|
|
3197
|
-
strapiOperator: '$notContainsi',
|
|
3198
|
-
add (t, type) {
|
|
3199
|
-
t.field(NOT_CONTAINSI_FIELD_NAME, {
|
|
3200
|
-
type
|
|
3201
|
-
});
|
|
3202
|
-
}
|
|
3203
|
-
}));
|
|
3204
|
-
|
|
3205
|
-
const GT_FIELD_NAME = 'gt';
|
|
3206
|
-
var gtOperator = (()=>({
|
|
3207
|
-
fieldName: GT_FIELD_NAME,
|
|
3208
|
-
strapiOperator: '$gt',
|
|
3209
|
-
add (t, type) {
|
|
3210
|
-
t.field(GT_FIELD_NAME, {
|
|
3211
|
-
type
|
|
3212
|
-
});
|
|
3213
|
-
}
|
|
3214
|
-
}));
|
|
3215
|
-
|
|
3216
|
-
const GTE_FIELD_NAME = 'gte';
|
|
3217
|
-
var gteOperator = (()=>({
|
|
3218
|
-
fieldName: GTE_FIELD_NAME,
|
|
3219
|
-
strapiOperator: '$gte',
|
|
3220
|
-
add (t, type) {
|
|
3221
|
-
t.field(GTE_FIELD_NAME, {
|
|
3222
|
-
type
|
|
3223
|
-
});
|
|
3224
|
-
}
|
|
3225
|
-
}));
|
|
3226
|
-
|
|
3227
|
-
const LT_FIELD_NAME = 'lt';
|
|
3228
|
-
var ltOperator = (()=>({
|
|
3229
|
-
fieldName: LT_FIELD_NAME,
|
|
3230
|
-
strapiOperator: '$lt',
|
|
3231
|
-
add (t, type) {
|
|
3232
|
-
t.field(LT_FIELD_NAME, {
|
|
3233
|
-
type
|
|
3234
|
-
});
|
|
3235
|
-
}
|
|
3236
|
-
}));
|
|
3237
|
-
|
|
3238
|
-
const LTE_FIELD_NAME = 'lte';
|
|
3239
|
-
var lteOperator = (()=>({
|
|
3240
|
-
fieldName: LTE_FIELD_NAME,
|
|
3241
|
-
strapiOperator: '$lte',
|
|
3242
|
-
add (t, type) {
|
|
3243
|
-
t.field(LTE_FIELD_NAME, {
|
|
3244
|
-
type
|
|
3245
|
-
});
|
|
3246
|
-
}
|
|
3247
|
-
}));
|
|
3248
|
-
|
|
3249
|
-
const NULL_FIELD_NAME = 'null';
|
|
3250
|
-
var nullOperator = (()=>({
|
|
3251
|
-
fieldName: NULL_FIELD_NAME,
|
|
3252
|
-
strapiOperator: '$null',
|
|
3253
|
-
add (t) {
|
|
3254
|
-
t.boolean(NULL_FIELD_NAME);
|
|
3255
|
-
}
|
|
3256
|
-
}));
|
|
3257
|
-
|
|
3258
|
-
const NOT_NULL_FIELD_NAME = 'notNull';
|
|
3259
|
-
var notNullOperator = (()=>({
|
|
3260
|
-
fieldName: NOT_NULL_FIELD_NAME,
|
|
3261
|
-
strapiOperator: '$notNull',
|
|
3262
|
-
add (t) {
|
|
3263
|
-
t.boolean(NOT_NULL_FIELD_NAME);
|
|
3264
|
-
}
|
|
3265
|
-
}));
|
|
3266
|
-
|
|
3267
|
-
const IN_FIELD_NAME = 'in';
|
|
3268
|
-
var inOperator = (()=>({
|
|
3269
|
-
fieldName: IN_FIELD_NAME,
|
|
3270
|
-
strapiOperator: '$in',
|
|
3271
|
-
add (t, type) {
|
|
3272
|
-
t.field(IN_FIELD_NAME, {
|
|
3273
|
-
type: list(type)
|
|
3274
|
-
});
|
|
3275
|
-
}
|
|
3276
|
-
}));
|
|
3277
|
-
|
|
3278
|
-
const NOT_IN_FIELD_NAME = 'notIn';
|
|
3279
|
-
var notInOperator = (()=>({
|
|
3280
|
-
fieldName: NOT_IN_FIELD_NAME,
|
|
3281
|
-
strapiOperator: '$notIn',
|
|
3282
|
-
add (t, type) {
|
|
3283
|
-
t.field(NOT_IN_FIELD_NAME, {
|
|
3284
|
-
type: list(type)
|
|
3285
|
-
});
|
|
3286
|
-
}
|
|
3287
|
-
}));
|
|
3288
|
-
|
|
3289
|
-
const BETWEEN_FIELD_NAME = 'between';
|
|
3290
|
-
var betweenOperator = (()=>({
|
|
3291
|
-
fieldName: BETWEEN_FIELD_NAME,
|
|
3292
|
-
strapiOperator: '$between',
|
|
3293
|
-
add (t, type) {
|
|
3294
|
-
t.field(BETWEEN_FIELD_NAME, {
|
|
3295
|
-
type: list(type)
|
|
3296
|
-
});
|
|
3297
|
-
}
|
|
3298
|
-
}));
|
|
3299
|
-
|
|
3300
|
-
const operators = {
|
|
3301
|
-
and: andOperator,
|
|
3302
|
-
or: orOperator,
|
|
3303
|
-
not: notOperator,
|
|
3304
|
-
eq: eqOperator,
|
|
3305
|
-
eqi: eqiOperator,
|
|
3306
|
-
ne: neOperator,
|
|
3307
|
-
nei: neiOperator,
|
|
3308
|
-
startsWith: startsWithOperator,
|
|
3309
|
-
endsWith: endsWithOperator,
|
|
3310
|
-
contains: containsOperator,
|
|
3311
|
-
notContains: notContainsOperator,
|
|
3312
|
-
containsi: containsiOperator,
|
|
3313
|
-
notContainsi: notContainsiOperator,
|
|
3314
|
-
gt: gtOperator,
|
|
3315
|
-
gte: gteOperator,
|
|
3316
|
-
lt: ltOperator,
|
|
3317
|
-
lte: lteOperator,
|
|
3318
|
-
null: nullOperator,
|
|
3319
|
-
notNull: notNullOperator,
|
|
3320
|
-
in: inOperator,
|
|
3321
|
-
notIn: notInOperator,
|
|
3322
|
-
between: betweenOperator
|
|
3323
|
-
};
|
|
3324
|
-
// Instantiate every operator with the Strapi instance
|
|
3325
|
-
var operators$1 = (({ strapi })=>mapValues((opCtor)=>opCtor({
|
|
3326
|
-
strapi
|
|
3327
|
-
}), operators));
|
|
3328
|
-
|
|
3329
|
-
const { withDefaultPagination } = pagination$1;
|
|
3330
|
-
var utils = (({ strapi })=>{
|
|
3331
|
-
const { service: getService } = strapi.plugin('graphql');
|
|
3332
|
-
return {
|
|
3333
|
-
getContentTypeArgs (contentType, { multiple = true, isNested = false } = {}) {
|
|
3334
|
-
const { naming } = getService('utils');
|
|
3335
|
-
const { args } = getService('internals');
|
|
3336
|
-
const { modelType } = contentType;
|
|
3337
|
-
// Components
|
|
3338
|
-
if (modelType === 'component') {
|
|
3339
|
-
if (!multiple) return {};
|
|
3340
|
-
return {
|
|
3341
|
-
filters: naming.getFiltersInputTypeName(contentType),
|
|
3342
|
-
pagination: args.PaginationArg,
|
|
3343
|
-
sort: args.SortArg
|
|
3344
|
-
};
|
|
3345
|
-
}
|
|
3346
|
-
const { kind } = contentType;
|
|
3347
|
-
// Collection Types
|
|
3348
|
-
if (kind === 'collectionType') {
|
|
3349
|
-
if (!multiple) {
|
|
3350
|
-
return {
|
|
3351
|
-
documentId: nonNull(idArg()),
|
|
3352
|
-
status: args.PublicationStatusArg
|
|
3353
|
-
};
|
|
3354
|
-
}
|
|
3355
|
-
const params = {
|
|
3356
|
-
filters: naming.getFiltersInputTypeName(contentType),
|
|
3357
|
-
pagination: args.PaginationArg,
|
|
3358
|
-
sort: args.SortArg
|
|
3359
|
-
};
|
|
3360
|
-
if (!isNested) {
|
|
3361
|
-
Object.assign(params, {
|
|
3362
|
-
status: args.PublicationStatusArg
|
|
3363
|
-
});
|
|
3364
|
-
}
|
|
3365
|
-
return params;
|
|
3366
|
-
}
|
|
3367
|
-
// Single Types
|
|
3368
|
-
if (kind === 'singleType') {
|
|
3369
|
-
const params = {};
|
|
3370
|
-
if (!isNested) {
|
|
3371
|
-
Object.assign(params, {
|
|
3372
|
-
status: args.PublicationStatusArg
|
|
3373
|
-
});
|
|
3374
|
-
}
|
|
3375
|
-
return params;
|
|
3376
|
-
}
|
|
3377
|
-
},
|
|
3378
|
-
/**
|
|
3379
|
-
* Filter an object entries and keep only those whose value is a unique scalar attribute
|
|
3380
|
-
*/ getUniqueScalarAttributes (attributes) {
|
|
3381
|
-
const { isStrapiScalar } = getService('utils').attributes;
|
|
3382
|
-
const uniqueAttributes = entries(attributes).filter(([, attribute])=>isStrapiScalar(attribute) && 'unique' in attribute && attribute.unique);
|
|
3383
|
-
return Object.fromEntries(uniqueAttributes);
|
|
3384
|
-
},
|
|
3385
|
-
/**
|
|
3386
|
-
* Map each value from an attribute to a FiltersInput type name
|
|
3387
|
-
* @param {object} attributes - The attributes object to transform
|
|
3388
|
-
* @return {Object<string, string>}
|
|
3389
|
-
*/ scalarAttributesToFiltersMap (attributes) {
|
|
3390
|
-
return mapValues((attribute)=>{
|
|
3391
|
-
const { mappers, naming } = getService('utils');
|
|
3392
|
-
const gqlScalar = mappers.strapiScalarToGraphQLScalar(attribute.type);
|
|
3393
|
-
return naming.getScalarFilterInputTypeName(gqlScalar);
|
|
3394
|
-
}, attributes);
|
|
3395
|
-
},
|
|
3396
|
-
/**
|
|
3397
|
-
* Apply basic transform to GQL args
|
|
3398
|
-
*/ transformArgs (args, { contentType, usePagination = false }) {
|
|
3399
|
-
const { mappers } = getService('utils');
|
|
3400
|
-
const { config } = strapi.plugin('graphql');
|
|
3401
|
-
const { pagination = {}, filters = {} } = args;
|
|
3402
|
-
// Init
|
|
3403
|
-
const newArgs = omit([
|
|
3404
|
-
'pagination',
|
|
3405
|
-
'filters'
|
|
3406
|
-
], args);
|
|
3407
|
-
// Pagination
|
|
3408
|
-
if (usePagination) {
|
|
3409
|
-
const defaultLimit = config('defaultLimit');
|
|
3410
|
-
const maxLimit = config('maxLimit');
|
|
3411
|
-
Object.assign(newArgs, withDefaultPagination(pagination, {
|
|
3412
|
-
maxLimit,
|
|
3413
|
-
defaults: {
|
|
3414
|
-
offset: {
|
|
3415
|
-
limit: defaultLimit
|
|
3416
|
-
},
|
|
3417
|
-
page: {
|
|
3418
|
-
pageSize: defaultLimit
|
|
3419
|
-
}
|
|
3420
|
-
}
|
|
3421
|
-
}));
|
|
3422
|
-
}
|
|
3423
|
-
// Filters
|
|
3424
|
-
if (args.filters) {
|
|
3425
|
-
Object.assign(newArgs, {
|
|
3426
|
-
filters: mappers.graphQLFiltersToStrapiQuery(filters, contentType)
|
|
3427
|
-
});
|
|
3428
|
-
}
|
|
3429
|
-
return newArgs;
|
|
3430
|
-
}
|
|
3431
|
-
};
|
|
3432
|
-
});
|
|
3433
|
-
|
|
3434
|
-
const buildersFactories = [
|
|
3435
|
-
enums,
|
|
3436
|
-
dynamicZone,
|
|
3437
|
-
entity,
|
|
3438
|
-
typeBuilder,
|
|
3439
|
-
response,
|
|
3440
|
-
responseCollection,
|
|
3441
|
-
relationResponseCollection,
|
|
3442
|
-
queries,
|
|
3443
|
-
mutations,
|
|
3444
|
-
filters,
|
|
3445
|
-
inputs,
|
|
3446
|
-
genericMorph,
|
|
3447
|
-
resolvers
|
|
3448
|
-
];
|
|
3449
|
-
var builders = (({ strapi })=>{
|
|
3450
|
-
const buildersMap = new Map();
|
|
3451
|
-
return {
|
|
3452
|
-
/**
|
|
3453
|
-
* Instantiate every builder with a strapi instance & a type registry
|
|
3454
|
-
*/ new (name, registry) {
|
|
3455
|
-
const context = {
|
|
3456
|
-
strapi,
|
|
3457
|
-
registry
|
|
3458
|
-
};
|
|
3459
|
-
const builders = pipe(// Create a new instance of every builders
|
|
3460
|
-
map((factory)=>factory(context)), // Merge every builder into the same object
|
|
3461
|
-
reduce(merge$1, {})).call(null, buildersFactories);
|
|
3462
|
-
buildersMap.set(name, builders);
|
|
3463
|
-
return builders;
|
|
3464
|
-
},
|
|
3465
|
-
/**
|
|
3466
|
-
* Delete a set of builders instances from
|
|
3467
|
-
* the builders map for a given name
|
|
3468
|
-
*/ delete (name) {
|
|
3469
|
-
buildersMap.delete(name);
|
|
3470
|
-
},
|
|
3471
|
-
/**
|
|
3472
|
-
* Retrieve a set of builders instances from
|
|
3473
|
-
* the builders map for a given name
|
|
3474
|
-
*/ get (name) {
|
|
3475
|
-
return buildersMap.get(name);
|
|
3476
|
-
},
|
|
3477
|
-
filters: {
|
|
3478
|
-
operators: operators$1({
|
|
3479
|
-
strapi
|
|
3480
|
-
})
|
|
3481
|
-
},
|
|
3482
|
-
utils: utils({
|
|
3483
|
-
strapi
|
|
3484
|
-
})
|
|
3485
|
-
};
|
|
3486
|
-
});
|
|
3487
|
-
|
|
3488
|
-
const getDefaultContentTypeConfig = ()=>({
|
|
3489
|
-
enabled: true,
|
|
3490
|
-
mutations: true,
|
|
3491
|
-
queries: true,
|
|
3492
|
-
disabledActions: [],
|
|
3493
|
-
fields: new Map()
|
|
3494
|
-
});
|
|
3495
|
-
const getDefaultFieldConfig = ()=>({
|
|
3496
|
-
enabled: true,
|
|
3497
|
-
input: true,
|
|
3498
|
-
output: true,
|
|
3499
|
-
filters: true
|
|
3500
|
-
});
|
|
3501
|
-
const ALL_ACTIONS = '*';
|
|
3502
|
-
var createShadowCRUDManager = (()=>{
|
|
3503
|
-
const configs = new Map();
|
|
3504
|
-
return (uid)=>{
|
|
3505
|
-
if (!configs.has(uid)) {
|
|
3506
|
-
configs.set(uid, getDefaultContentTypeConfig());
|
|
3507
|
-
}
|
|
3508
|
-
return {
|
|
3509
|
-
isEnabled () {
|
|
3510
|
-
return configs.get(uid).enabled;
|
|
3511
|
-
},
|
|
3512
|
-
isDisabled () {
|
|
3513
|
-
return !this.isEnabled();
|
|
3514
|
-
},
|
|
3515
|
-
areQueriesEnabled () {
|
|
3516
|
-
return configs.get(uid).queries;
|
|
3517
|
-
},
|
|
3518
|
-
areQueriesDisabled () {
|
|
3519
|
-
return !this.areQueriesEnabled();
|
|
3520
|
-
},
|
|
3521
|
-
areMutationsEnabled () {
|
|
3522
|
-
return configs.get(uid).mutations;
|
|
3523
|
-
},
|
|
3524
|
-
areMutationsDisabled () {
|
|
3525
|
-
return !this.areMutationsEnabled();
|
|
3526
|
-
},
|
|
3527
|
-
isActionEnabled (action) {
|
|
3528
|
-
const matchingActions = [
|
|
3529
|
-
action,
|
|
3530
|
-
ALL_ACTIONS
|
|
3531
|
-
];
|
|
3532
|
-
return configs.get(uid).disabledActions.every((action)=>!matchingActions.includes(action));
|
|
3533
|
-
},
|
|
3534
|
-
isActionDisabled (action) {
|
|
3535
|
-
return !this.isActionEnabled(action);
|
|
3536
|
-
},
|
|
3537
|
-
disable () {
|
|
3538
|
-
configs.get(uid).enabled = false;
|
|
3539
|
-
return this;
|
|
3540
|
-
},
|
|
3541
|
-
disableQueries () {
|
|
3542
|
-
configs.get(uid).queries = false;
|
|
3543
|
-
return this;
|
|
3544
|
-
},
|
|
3545
|
-
disableMutations () {
|
|
3546
|
-
configs.get(uid).mutations = false;
|
|
3547
|
-
return this;
|
|
3548
|
-
},
|
|
3549
|
-
disableAction (action) {
|
|
3550
|
-
const config = configs.get(uid);
|
|
3551
|
-
if (!config.disabledActions.includes(action)) {
|
|
3552
|
-
config.disabledActions.push(action);
|
|
3553
|
-
}
|
|
3554
|
-
return this;
|
|
3555
|
-
},
|
|
3556
|
-
disableActions (actions = []) {
|
|
3557
|
-
actions.forEach((action)=>this.disableAction(action));
|
|
3558
|
-
return this;
|
|
3559
|
-
},
|
|
3560
|
-
field (fieldName) {
|
|
3561
|
-
const { fields } = configs.get(uid);
|
|
3562
|
-
if (!fields.has(fieldName)) {
|
|
3563
|
-
fields.set(fieldName, getDefaultFieldConfig());
|
|
3564
|
-
}
|
|
3565
|
-
return {
|
|
3566
|
-
isEnabled () {
|
|
3567
|
-
return fields.get(fieldName).enabled;
|
|
3568
|
-
},
|
|
3569
|
-
hasInputEnabled () {
|
|
3570
|
-
return fields.get(fieldName).input;
|
|
3571
|
-
},
|
|
3572
|
-
hasOutputEnabled () {
|
|
3573
|
-
return fields.get(fieldName).output;
|
|
3574
|
-
},
|
|
3575
|
-
hasFiltersEnabeld () {
|
|
3576
|
-
return fields.get(fieldName).filters;
|
|
3577
|
-
},
|
|
3578
|
-
disable () {
|
|
3579
|
-
fields.set(fieldName, {
|
|
3580
|
-
enabled: false,
|
|
3581
|
-
output: false,
|
|
3582
|
-
input: false,
|
|
3583
|
-
filters: false
|
|
3584
|
-
});
|
|
3585
|
-
return this;
|
|
3586
|
-
},
|
|
3587
|
-
disableOutput () {
|
|
3588
|
-
fields.get(fieldName).output = false;
|
|
3589
|
-
return this;
|
|
3590
|
-
},
|
|
3591
|
-
disableInput () {
|
|
3592
|
-
fields.get(fieldName).input = false;
|
|
3593
|
-
return this;
|
|
3594
|
-
},
|
|
3595
|
-
disableFilters () {
|
|
3596
|
-
fields.get(fieldName).filters = false;
|
|
3597
|
-
return this;
|
|
3598
|
-
}
|
|
3599
|
-
};
|
|
3600
|
-
}
|
|
3601
|
-
};
|
|
3602
|
-
};
|
|
3603
|
-
});
|
|
3604
|
-
|
|
3605
|
-
const getDefaultState = ()=>({
|
|
3606
|
-
types: [],
|
|
3607
|
-
typeDefs: [],
|
|
3608
|
-
resolvers: {},
|
|
3609
|
-
resolversConfig: {},
|
|
3610
|
-
plugins: []
|
|
3611
|
-
});
|
|
3612
|
-
const createExtension = ({ strapi })=>{
|
|
3613
|
-
const configs = [];
|
|
3614
|
-
return {
|
|
3615
|
-
shadowCRUD: createShadowCRUDManager(),
|
|
3616
|
-
/**
|
|
3617
|
-
* Register a new extension configuration
|
|
3618
|
-
*/ use (configuration) {
|
|
3619
|
-
configs.push(configuration);
|
|
3620
|
-
return this;
|
|
3621
|
-
},
|
|
3622
|
-
/**
|
|
3623
|
-
* Convert the registered configuration into a single extension object & return it
|
|
3624
|
-
*/ generate ({ typeRegistry }) {
|
|
3625
|
-
const resolveConfig = (config)=>{
|
|
3626
|
-
return typeof config === 'function' ? config({
|
|
3627
|
-
strapi,
|
|
3628
|
-
nexus,
|
|
3629
|
-
typeRegistry
|
|
3630
|
-
}) : config;
|
|
3631
|
-
};
|
|
3632
|
-
// Evaluate & merge every registered configuration object, then return the result
|
|
3633
|
-
return configs.reduce((acc, configuration)=>{
|
|
3634
|
-
const { types, typeDefs, resolvers, resolversConfig, plugins } = resolveConfig(configuration);
|
|
3635
|
-
// Register type definitions
|
|
3636
|
-
if (typeof typeDefs === 'string') {
|
|
3637
|
-
acc.typeDefs.push(typeDefs);
|
|
3638
|
-
}
|
|
3639
|
-
// Register nexus types
|
|
3640
|
-
if (Array.isArray(types)) {
|
|
3641
|
-
acc.types.push(...types);
|
|
3642
|
-
}
|
|
3643
|
-
// Register nexus plugins
|
|
3644
|
-
if (Array.isArray(plugins)) {
|
|
3645
|
-
acc.plugins.push(...plugins);
|
|
3646
|
-
}
|
|
3647
|
-
// Register resolvers
|
|
3648
|
-
if (typeof resolvers === 'object') {
|
|
3649
|
-
acc.resolvers = merge$1(acc.resolvers, resolvers);
|
|
3650
|
-
}
|
|
3651
|
-
// Register resolvers configuration
|
|
3652
|
-
if (typeof resolversConfig === 'object') {
|
|
3653
|
-
// TODO: smarter merge for auth, middlewares & policies
|
|
3654
|
-
acc.resolversConfig = merge$1(resolversConfig, acc.resolversConfig);
|
|
3655
|
-
}
|
|
3656
|
-
return acc;
|
|
3657
|
-
}, getDefaultState());
|
|
3658
|
-
}
|
|
3659
|
-
};
|
|
3660
|
-
};
|
|
3661
|
-
|
|
3662
|
-
var returnTypes = (()=>({
|
|
3663
|
-
toEntityResponse (value, info = {}) {
|
|
3664
|
-
const { args = {}, resourceUID } = info;
|
|
3665
|
-
return {
|
|
3666
|
-
value,
|
|
3667
|
-
info: {
|
|
3668
|
-
args,
|
|
3669
|
-
resourceUID
|
|
3670
|
-
}
|
|
3671
|
-
};
|
|
3672
|
-
},
|
|
3673
|
-
toEntityResponseCollection (nodes, info = {}) {
|
|
3674
|
-
const { args = {}, resourceUID } = info;
|
|
3675
|
-
return {
|
|
3676
|
-
nodes,
|
|
3677
|
-
info: {
|
|
3678
|
-
args,
|
|
3679
|
-
resourceUID
|
|
3680
|
-
}
|
|
3681
|
-
};
|
|
3682
|
-
}
|
|
3683
|
-
}));
|
|
3684
|
-
|
|
3685
|
-
var format = (()=>({
|
|
3686
|
-
returnTypes: returnTypes()
|
|
3687
|
-
}));
|
|
3688
|
-
|
|
3689
|
-
const services = {
|
|
3690
|
-
builders,
|
|
3691
|
-
'content-api': contentAPI,
|
|
3692
|
-
constants,
|
|
3693
|
-
extension: createExtension,
|
|
3694
|
-
format,
|
|
3695
|
-
internals,
|
|
3696
|
-
'type-registry': typeRegistry,
|
|
3697
|
-
utils: utils$1
|
|
3698
|
-
};
|
|
1
|
+
import { config } from './config/index.mjs';
|
|
2
|
+
import { bootstrap } from './bootstrap.mjs';
|
|
3
|
+
import { services } from './services/index.mjs';
|
|
3699
4
|
|
|
3700
5
|
var index = {
|
|
3701
6
|
config,
|