@vendure/dashboard 3.2.0 → 3.2.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/LICENSE.md +42 -0
- package/README.md +12 -12
- package/dist/plugin/vite-plugin-admin-api-schema.js +2 -2
- package/dist/plugin/vite-plugin-dashboard-metadata.js +4 -4
- package/dist/plugin/vite-plugin-theme.d.ts +55 -0
- package/dist/plugin/vite-plugin-theme.js +130 -0
- package/dist/plugin/vite-plugin-ui-config.js +2 -2
- package/dist/plugin/vite-plugin-vendure-dashboard.d.ts +2 -1
- package/dist/plugin/vite-plugin-vendure-dashboard.js +2 -0
- package/index.html +15 -15
- package/lingui.config.js +12 -12
- package/package.json +15 -5
- package/src/app/app-providers.tsx +30 -30
- package/src/app/main.tsx +97 -97
- package/src/app/routes/__root.tsx +24 -24
- package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +79 -79
- package/src/app/routes/_authenticated/_administrators/administrators.tsx +86 -86
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +155 -155
- package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +133 -133
- package/src/app/routes/_authenticated/_assets/assets.tsx +19 -19
- package/src/app/routes/_authenticated/_channels/channels.graphql.ts +93 -93
- package/src/app/routes/_authenticated/_channels/channels.tsx +60 -60
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +248 -248
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +133 -133
- package/src/app/routes/_authenticated/_collections/collections.tsx +195 -195
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +224 -224
- package/src/app/routes/_authenticated/_collections/components/collection-contents-preview-table.tsx +127 -127
- package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +46 -46
- package/src/app/routes/_authenticated/_collections/components/collection-contents-table.tsx +82 -82
- package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +91 -91
- package/src/app/routes/_authenticated/_countries/countries.graphql.ts +69 -69
- package/src/app/routes/_authenticated/_countries/countries.tsx +67 -67
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +122 -122
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +44 -44
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +129 -129
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +71 -71
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +68 -68
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +111 -111
- package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +155 -155
- package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +344 -344
- package/src/app/routes/_authenticated/_customers/components/customer-group-controls.tsx +4 -4
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +78 -78
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history.tsx +77 -77
- package/src/app/routes/_authenticated/_customers/components/customer-history/index.ts +3 -3
- package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +169 -169
- package/src/app/routes/_authenticated/_customers/components/customer-order-table.tsx +88 -88
- package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +33 -33
- package/src/app/routes/_authenticated/_customers/customers.graphql.ts +204 -204
- package/src/app/routes/_authenticated/_customers/customers.tsx +82 -82
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +274 -274
- package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +129 -129
- package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +46 -46
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +97 -97
- package/src/app/routes/_authenticated/_facets/facets.graphql.ts +104 -104
- package/src/app/routes/_authenticated/_facets/facets.tsx +97 -97
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +139 -139
- package/src/app/routes/_authenticated/_global-settings/global-settings.graphql.ts +28 -28
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +161 -161
- package/src/app/routes/_authenticated/_orders/components/order-address.tsx +58 -58
- package/src/app/routes/_authenticated/_orders/components/order-history/index.ts +3 -3
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +72 -72
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +96 -96
- package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +171 -171
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +169 -169
- package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +38 -38
- package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +61 -61
- package/src/app/routes/_authenticated/_orders/orders.graphql.ts +325 -325
- package/src/app/routes/_authenticated/_orders/orders.tsx +120 -120
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +133 -133
- package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +104 -104
- package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +100 -100
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +83 -83
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +64 -64
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +183 -183
- package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +87 -87
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +123 -123
- package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +78 -78
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +331 -331
- package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +228 -228
- package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +462 -462
- package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +95 -95
- package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +87 -87
- package/src/app/routes/_authenticated/_products/products.graphql.ts +116 -116
- package/src/app/routes/_authenticated/_products/products.tsx +48 -48
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +196 -196
- package/src/app/routes/_authenticated/_profile/profile.graphql.ts +23 -23
- package/src/app/routes/_authenticated/_profile/profile.tsx +122 -122
- package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +107 -107
- package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +107 -107
- package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +96 -96
- package/src/app/routes/_authenticated/_promotions/promotions.tsx +61 -61
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +235 -235
- package/src/app/routes/_authenticated/_roles/components/expandable-permissions.tsx +54 -54
- package/src/app/routes/_authenticated/_roles/components/permissions-grid.tsx +116 -116
- package/src/app/routes/_authenticated/_roles/roles.graphql.ts +67 -67
- package/src/app/routes/_authenticated/_roles/roles.tsx +96 -96
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +142 -142
- package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +61 -61
- package/src/app/routes/_authenticated/_sellers/sellers.tsx +51 -51
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +111 -111
- package/src/app/routes/_authenticated/_shipping-methods/components/fulfillment-handler-selector.tsx +56 -56
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +101 -101
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +101 -101
- package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-method-dialog.tsx +32 -32
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +83 -83
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +55 -55
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +171 -171
- package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +62 -62
- package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +48 -48
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +115 -115
- package/src/app/routes/_authenticated/_system/components/payload-dialog.tsx +34 -34
- package/src/app/routes/_authenticated/_system/healthchecks.tsx +93 -93
- package/src/app/routes/_authenticated/_system/job-queue.graphql.ts +43 -43
- package/src/app/routes/_authenticated/_system/job-queue.tsx +161 -161
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +63 -63
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +65 -65
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +115 -115
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +75 -75
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +108 -108
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +148 -148
- package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +31 -31
- package/src/app/routes/_authenticated/_zones/components/zone-countries-table.tsx +79 -79
- package/src/app/routes/_authenticated/_zones/zones.graphql.ts +96 -96
- package/src/app/routes/_authenticated/_zones/zones.tsx +57 -57
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +103 -103
- package/src/app/routes/_authenticated/index.tsx +194 -194
- package/src/app/routes/_authenticated.tsx +25 -25
- package/src/app/routes/login.tsx +48 -48
- package/src/app/styles.css +82 -82
- package/src/app/tailwindcss-animate.css +275 -275
- package/src/i18n/locales/de.po +1579 -1579
- package/src/i18n/locales/en.po +1579 -1579
- package/src/lib/components/data-display/boolean.tsx +23 -23
- package/src/lib/components/data-display/date-time.tsx +13 -13
- package/src/lib/components/data-display/json.tsx +5 -5
- package/src/lib/components/data-display/money.tsx +15 -15
- package/src/lib/components/data-input/affixed-input.tsx +49 -49
- package/src/lib/components/data-input/customer-group-input.tsx +72 -72
- package/src/lib/components/data-input/datetime-input.tsx +149 -149
- package/src/lib/components/data-input/facet-value-input.tsx +68 -68
- package/src/lib/components/data-input/money-input.tsx +112 -112
- package/src/lib/components/data-input/richt-text-input.tsx +99 -99
- package/src/lib/components/data-table/data-table-column-header.tsx +73 -73
- package/src/lib/components/data-table/data-table-faceted-filter.tsx +172 -172
- package/src/lib/components/data-table/data-table-filter-dialog.tsx +73 -73
- package/src/lib/components/data-table/data-table-pagination.tsx +87 -87
- package/src/lib/components/data-table/data-table-view-options.tsx +53 -53
- package/src/lib/components/data-table/data-table.tsx +218 -218
- package/src/lib/components/layout/app-layout.tsx +42 -42
- package/src/lib/components/layout/app-sidebar.tsx +34 -34
- package/src/lib/components/layout/channel-switcher.tsx +87 -87
- package/src/lib/components/layout/content-language-selector.tsx +41 -41
- package/src/lib/components/layout/generated-breadcrumbs.tsx +82 -82
- package/src/lib/components/layout/language-dialog.tsx +104 -104
- package/src/lib/components/layout/nav-main.tsx +178 -178
- package/src/lib/components/layout/nav-projects.tsx +81 -81
- package/src/lib/components/layout/nav-user.tsx +176 -176
- package/src/lib/components/layout/prerelease-popup.tsx +38 -38
- package/src/lib/components/login/login-form.tsx +173 -173
- package/src/lib/components/shared/alerts.tsx +20 -20
- package/src/lib/components/shared/animated-number.tsx +49 -49
- package/src/lib/components/shared/asset-gallery.tsx +433 -433
- package/src/lib/components/shared/asset-picker-dialog.tsx +71 -71
- package/src/lib/components/shared/asset-preview-dialog.tsx +48 -48
- package/src/lib/components/shared/asset-preview.tsx +345 -345
- package/src/lib/components/shared/assigned-facet-values.tsx +68 -68
- package/src/lib/components/shared/channel-code-label.tsx +7 -7
- package/src/lib/components/shared/channel-selector.tsx +51 -51
- package/src/lib/components/shared/configurable-operation-arg-input.tsx +51 -51
- package/src/lib/components/shared/configurable-operation-input.tsx +133 -133
- package/src/lib/components/shared/confirmation-dialog.tsx +58 -58
- package/src/lib/components/shared/copyable-text.tsx +31 -31
- package/src/lib/components/shared/country-selector.tsx +105 -105
- package/src/lib/components/shared/currency-selector.tsx +33 -33
- package/src/lib/components/shared/custom-fields-form.tsx +86 -86
- package/src/lib/components/shared/customer-address-form.tsx +330 -330
- package/src/lib/components/shared/customer-group-chip.tsx +30 -30
- package/src/lib/components/shared/customer-group-selector.tsx +62 -62
- package/src/lib/components/shared/customer-selector.tsx +107 -107
- package/src/lib/components/shared/detail-page-button.tsx +22 -22
- package/src/lib/components/shared/entity-assets.tsx +340 -340
- package/src/lib/components/shared/error-page.tsx +31 -31
- package/src/lib/components/shared/facet-value-chip.tsx +44 -44
- package/src/lib/components/shared/facet-value-selector.tsx +306 -306
- package/src/lib/components/shared/focal-point-control.tsx +64 -64
- package/src/lib/components/shared/form-field-wrapper.tsx +37 -37
- package/src/lib/components/shared/history-timeline/history-entry.tsx +112 -112
- package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +28 -28
- package/src/lib/components/shared/history-timeline/history-note-editor.tsx +60 -60
- package/src/lib/components/shared/history-timeline/history-note-input.tsx +39 -39
- package/src/lib/components/shared/history-timeline/history-timeline.tsx +56 -56
- package/src/lib/components/shared/icon-mark.tsx +18 -18
- package/src/lib/components/shared/language-selector.tsx +48 -48
- package/src/lib/components/shared/logo-mark.tsx +24 -24
- package/src/lib/components/shared/multi-select.tsx +159 -159
- package/src/lib/components/shared/option-value-input.tsx +94 -94
- package/src/lib/components/shared/paginated-list-data-table.tsx +520 -520
- package/src/lib/components/shared/permission-guard.tsx +20 -20
- package/src/lib/components/shared/role-code-label.tsx +8 -8
- package/src/lib/components/shared/role-selector.tsx +56 -56
- package/src/lib/components/shared/seller-selector.tsx +107 -107
- package/src/lib/components/shared/tax-category-selector.tsx +65 -65
- package/src/lib/components/shared/translatable-form-field.tsx +74 -74
- package/src/lib/components/shared/vendure-image.tsx +159 -159
- package/src/lib/components/shared/zone-selector.tsx +66 -66
- package/src/lib/components/ui/accordion.tsx +59 -59
- package/src/lib/components/ui/alert-dialog.tsx +128 -128
- package/src/lib/components/ui/alert.tsx +60 -60
- package/src/lib/components/ui/avatar.tsx +38 -38
- package/src/lib/components/ui/badge.tsx +38 -38
- package/src/lib/components/ui/breadcrumb.tsx +102 -102
- package/src/lib/components/ui/button.tsx +51 -51
- package/src/lib/components/ui/calendar.tsx +69 -69
- package/src/lib/components/ui/card.tsx +47 -47
- package/src/lib/components/ui/checkbox.tsx +27 -27
- package/src/lib/components/ui/collapsible.tsx +33 -33
- package/src/lib/components/ui/command.tsx +133 -133
- package/src/lib/components/ui/dialog.tsx +116 -116
- package/src/lib/components/ui/dropdown-menu.tsx +220 -220
- package/src/lib/components/ui/form.tsx +141 -141
- package/src/lib/components/ui/hover-card.tsx +36 -36
- package/src/lib/components/ui/input.tsx +19 -19
- package/src/lib/components/ui/label.tsx +21 -21
- package/src/lib/components/ui/pagination.tsx +127 -127
- package/src/lib/components/ui/popover.tsx +40 -40
- package/src/lib/components/ui/scroll-area.tsx +50 -50
- package/src/lib/components/ui/select.tsx +161 -161
- package/src/lib/components/ui/separator.tsx +26 -26
- package/src/lib/components/ui/sheet.tsx +118 -118
- package/src/lib/components/ui/sidebar.tsx +696 -696
- package/src/lib/components/ui/skeleton.tsx +13 -13
- package/src/lib/components/ui/sonner.tsx +27 -27
- package/src/lib/components/ui/switch.tsx +26 -26
- package/src/lib/components/ui/table.tsx +82 -82
- package/src/lib/components/ui/tabs.tsx +48 -48
- package/src/lib/components/ui/textarea.tsx +18 -18
- package/src/lib/components/ui/tooltip.tsx +51 -51
- package/src/lib/constants.ts +326 -326
- package/src/lib/framework/component-registry/component-registry.tsx +70 -70
- package/src/lib/framework/component-registry/dynamic-component.tsx +58 -58
- package/src/lib/framework/dashboard-widget/base-widget.tsx +97 -97
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +96 -96
- package/src/lib/framework/dashboard-widget/latest-orders-widget/latest-orders-widget.graphql.ts +35 -35
- package/src/lib/framework/dashboard-widget/metrics-widget/chart.tsx +24 -24
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +82 -82
- package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +14 -14
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +167 -167
- package/src/lib/framework/dashboard-widget/orders-summary/order-summary-widget.graphql.ts +14 -14
- package/src/lib/framework/dashboard-widget/types.ts +22 -22
- package/src/lib/framework/dashboard-widget/widget-extensions.tsx +19 -19
- package/src/lib/framework/defaults.ts +219 -219
- package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +242 -242
- package/src/lib/framework/document-introspection/add-custom-fields.ts +246 -246
- package/src/lib/framework/document-introspection/get-document-structure.spec.ts +310 -310
- package/src/lib/framework/document-introspection/get-document-structure.ts +460 -460
- package/src/lib/framework/document-introspection/hooks.ts +10 -10
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +66 -66
- package/src/lib/framework/extension-api/extension-api-types.ts +58 -58
- package/src/lib/framework/extension-api/use-dashboard-extensions.ts +26 -26
- package/src/lib/framework/form-engine/form-schema-tools.ts +98 -98
- package/src/lib/framework/form-engine/use-generated-form.tsx +116 -116
- package/src/lib/framework/layout-engine/layout-extensions.ts +30 -30
- package/src/lib/framework/layout-engine/location-wrapper.tsx +96 -96
- package/src/lib/framework/layout-engine/page-layout.tsx +272 -272
- package/src/lib/framework/nav-menu/nav-menu-extensions.ts +66 -66
- package/src/lib/framework/page/detail-page-route-loader.tsx +48 -48
- package/src/lib/framework/page/detail-page.tsx +131 -131
- package/src/lib/framework/page/list-page.tsx +166 -166
- package/src/lib/framework/page/page-api.ts +9 -9
- package/src/lib/framework/page/page-types.ts +51 -51
- package/src/lib/framework/page/use-detail-page.ts +217 -217
- package/src/lib/framework/page/use-extended-router.tsx +69 -69
- package/src/lib/framework/registry/global-registry.ts +46 -46
- package/src/lib/framework/registry/registry-types.ts +15 -15
- package/src/lib/graphql/api.ts +61 -61
- package/src/lib/graphql/fragments.tsx +54 -54
- package/src/lib/graphql/graphql-env.d.ts +499 -499
- package/src/lib/graphql/graphql.ts +15 -15
- package/src/lib/hooks/use-auth.tsx +11 -11
- package/src/lib/hooks/use-channel.ts +12 -12
- package/src/lib/hooks/use-custom-field-config.ts +10 -10
- package/src/lib/hooks/use-grouped-permissions.ts +54 -54
- package/src/lib/hooks/use-local-format.ts +119 -119
- package/src/lib/hooks/use-mobile.ts +19 -19
- package/src/lib/hooks/use-page.tsx +10 -10
- package/src/lib/hooks/use-permissions.ts +22 -22
- package/src/lib/hooks/use-server-config.ts +4 -4
- package/src/lib/hooks/use-theme.ts +10 -10
- package/src/lib/hooks/use-user-settings.tsx +12 -12
- package/src/lib/index.ts +149 -149
- package/src/lib/lib/trans.tsx +16 -16
- package/src/lib/lib/utils.ts +60 -60
- package/src/lib/providers/auth.tsx +152 -152
- package/src/lib/providers/channel-provider.tsx +121 -121
- package/src/lib/providers/i18n-provider.tsx +28 -28
- package/src/lib/providers/server-config.tsx +279 -279
- package/src/lib/providers/theme-provider.tsx +54 -54
- package/src/lib/providers/user-settings.tsx +89 -89
- package/src/lib/virtual.d.ts +12 -12
- package/vite/config-loader.ts +181 -181
- package/vite/constants.ts +280 -280
- package/vite/index.ts +1 -1
- package/vite/schema-generator.ts +40 -40
- package/vite/ui-config.ts +60 -60
- package/vite/vite-plugin-admin-api-schema.ts +141 -141
- package/vite/vite-plugin-config-loader.ts +64 -64
- package/vite/vite-plugin-config.ts +42 -42
- package/vite/vite-plugin-dashboard-metadata.ts +58 -58
- package/vite/vite-plugin-gql-tada.ts +62 -62
- package/vite/vite-plugin-theme.ts +195 -195
- package/vite/vite-plugin-ui-config.ts +60 -60
- package/vite/vite-plugin-vendure-dashboard.ts +118 -118
- package/dist/plugin/.vendure-dashboard-temp/dev-config.js +0 -227
- package/dist/plugin/.vendure-dashboard-temp/dev-config.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/api/api-extensions.js +0 -33
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/api/api-extensions.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/api/mv.resolver.js +0 -69
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/api/mv.resolver.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-order-process.js +0 -110
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-order-process.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-order-seller-strategy.js +0 -134
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-order-seller-strategy.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-payment-handler.js +0 -86
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-payment-handler.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-shipping-eligibility-checker.js +0 -49
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-shipping-eligibility-checker.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-shipping-line-assignment-strategy.js +0 -57
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/config/mv-shipping-line-assignment-strategy.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/constants.js +0 -20
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/constants.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/multivendor.plugin.js +0 -151
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/multivendor.plugin.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/payment/mv-connect-sdk.js +0 -47
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/payment/mv-connect-sdk.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/service/mv.service.js +0 -222
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/service/mv.service.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/types.js +0 -4
- package/dist/plugin/.vendure-dashboard-temp/example-plugins/multivendor-plugin/types.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/package.json +0 -3
- package/dist/plugin/.vendure-dashboard-temp/schema.graphql +0 -6378
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/api-extensions.js +0 -103
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/api-extensions.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-entity.resolver.js +0 -105
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-entity.resolver.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-admin.resolver.js +0 -183
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-admin.resolver.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-entity.resolver.js +0 -113
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-entity.resolver.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-shop.resolver.js +0 -112
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/api/product-review-shop.resolver.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/entities/product-review.entity.js +0 -111
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/entities/product-review.entity.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/generated-admin-types.js +0 -616
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/generated-admin-types.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/generated-shop-types.js +0 -563
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/generated-shop-types.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/reviews-plugin.js +0 -135
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/reviews-plugin.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/types.js +0 -4
- package/dist/plugin/.vendure-dashboard-temp/test-plugins/reviews/types.js.map +0 -1
- package/dist/plugin/.vendure-dashboard-temp/tsconfig.json +0 -10
- package/dist/plugin/vite-plugin-set-root.d.ts +0 -4
- package/dist/plugin/vite-plugin-set-root.js +0 -15
- package/src/app/routeTree.gen.ts +0 -1372
|
@@ -1,460 +1,460 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DocumentNode,
|
|
3
|
-
OperationDefinitionNode,
|
|
4
|
-
FieldNode,
|
|
5
|
-
FragmentDefinitionNode,
|
|
6
|
-
FragmentSpreadNode,
|
|
7
|
-
VariableDefinitionNode,
|
|
8
|
-
} from 'graphql';
|
|
9
|
-
import { DefinitionNode, NamedTypeNode, SelectionSetNode, TypeNode } from 'graphql/language/ast.js';
|
|
10
|
-
import { schemaInfo } from 'virtual:admin-api-schema';
|
|
11
|
-
|
|
12
|
-
// for debug purposes
|
|
13
|
-
(window as any).schemaInfo = schemaInfo;
|
|
14
|
-
|
|
15
|
-
export interface FieldInfo {
|
|
16
|
-
name: string;
|
|
17
|
-
type: string;
|
|
18
|
-
nullable: boolean;
|
|
19
|
-
list: boolean;
|
|
20
|
-
isPaginatedList: boolean;
|
|
21
|
-
isScalar: boolean;
|
|
22
|
-
typeInfo?: FieldInfo[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @description
|
|
27
|
-
* Given a DocumentNode of a PaginatedList query, returns information about each
|
|
28
|
-
* of the selected fields.
|
|
29
|
-
*
|
|
30
|
-
* Inside React components, use the `useListQueryFields` hook to get this information.
|
|
31
|
-
*/
|
|
32
|
-
export function getListQueryFields(documentNode: DocumentNode): FieldInfo[] {
|
|
33
|
-
const fields: FieldInfo[] = [];
|
|
34
|
-
const fragments: Record<string, FragmentDefinitionNode> = {};
|
|
35
|
-
|
|
36
|
-
// Collect all fragment definitions
|
|
37
|
-
documentNode.definitions.forEach(def => {
|
|
38
|
-
if (def.kind === 'FragmentDefinition') {
|
|
39
|
-
fragments[def.name.value] = def;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const operationDefinition = documentNode.definitions.find(
|
|
44
|
-
(def): def is OperationDefinitionNode =>
|
|
45
|
-
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
for (const query of operationDefinition?.selectionSet.selections ?? []) {
|
|
49
|
-
if (query.kind === 'Field') {
|
|
50
|
-
const queryField = query;
|
|
51
|
-
const fieldInfo = getQueryInfo(queryField.name.value);
|
|
52
|
-
if (fieldInfo.isPaginatedList) {
|
|
53
|
-
processPaginatedList(queryField, fieldInfo, fields, fragments);
|
|
54
|
-
} else if (queryField.selectionSet) {
|
|
55
|
-
// Check for nested paginated lists
|
|
56
|
-
findNestedPaginatedLists(queryField, fieldInfo.type, fields, fragments);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return fields;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function processPaginatedList(
|
|
65
|
-
field: FieldNode,
|
|
66
|
-
fieldInfo: FieldInfo,
|
|
67
|
-
fields: FieldInfo[],
|
|
68
|
-
fragments: Record<string, FragmentDefinitionNode>,
|
|
69
|
-
) {
|
|
70
|
-
const itemsField = field.selectionSet?.selections.find(
|
|
71
|
-
selection => selection.kind === 'Field' && selection.name.value === 'items',
|
|
72
|
-
) as FieldNode;
|
|
73
|
-
if (!itemsField) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const typeFields = schemaInfo.types[fieldInfo.type];
|
|
77
|
-
const isPaginatedList = typeFields.hasOwnProperty('items') && typeFields.hasOwnProperty('totalItems');
|
|
78
|
-
if (!isPaginatedList) {
|
|
79
|
-
throw new Error(`Could not determine type of items in ${fieldInfo.name}`);
|
|
80
|
-
}
|
|
81
|
-
const itemsType = getObjectFieldInfo(fieldInfo.type, 'items')?.type;
|
|
82
|
-
if (!itemsType) {
|
|
83
|
-
throw new Error(`Could not determine type of items in ${fieldInfo.name}`);
|
|
84
|
-
}
|
|
85
|
-
for (const item of itemsField.selectionSet?.selections ?? []) {
|
|
86
|
-
if (item.kind === 'Field' || item.kind === 'FragmentSpread') {
|
|
87
|
-
collectFields(itemsType, item, fields, fragments);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function findNestedPaginatedLists(
|
|
93
|
-
field: FieldNode,
|
|
94
|
-
parentType: string,
|
|
95
|
-
fields: FieldInfo[],
|
|
96
|
-
fragments: Record<string, FragmentDefinitionNode>,
|
|
97
|
-
) {
|
|
98
|
-
for (const selection of field.selectionSet?.selections ?? []) {
|
|
99
|
-
if (selection.kind === 'Field') {
|
|
100
|
-
const fieldInfo = getObjectFieldInfo(parentType, selection.name.value);
|
|
101
|
-
if (!fieldInfo) {
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
if (fieldInfo.isPaginatedList) {
|
|
105
|
-
processPaginatedList(selection, fieldInfo, fields, fragments);
|
|
106
|
-
} else if (selection.selectionSet && !fieldInfo.isScalar) {
|
|
107
|
-
// Continue recursion
|
|
108
|
-
findNestedPaginatedLists(selection, fieldInfo.type, fields, fragments);
|
|
109
|
-
}
|
|
110
|
-
} else if (selection.kind === 'FragmentSpread') {
|
|
111
|
-
// Handle fragment spread on the parent type
|
|
112
|
-
const fragmentName = selection.name.value;
|
|
113
|
-
const fragment = fragments[fragmentName];
|
|
114
|
-
if (fragment && fragment.typeCondition.name.value === parentType) {
|
|
115
|
-
for (const fragmentSelection of fragment.selectionSet.selections) {
|
|
116
|
-
if (fragmentSelection.kind === 'Field') {
|
|
117
|
-
const fieldInfo = getObjectFieldInfo(parentType, fragmentSelection.name.value);
|
|
118
|
-
if (!fieldInfo) {
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (fieldInfo.isPaginatedList) {
|
|
122
|
-
processPaginatedList(fragmentSelection, fieldInfo, fields, fragments);
|
|
123
|
-
} else if (fragmentSelection.selectionSet && !fieldInfo.isScalar) {
|
|
124
|
-
findNestedPaginatedLists(fragmentSelection, fieldInfo.type, fields, fragments);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @description
|
|
135
|
-
* This function is used to get the fields of the operation variables from a DocumentNode.
|
|
136
|
-
*
|
|
137
|
-
* For example, in the following query:
|
|
138
|
-
*
|
|
139
|
-
* ```graphql
|
|
140
|
-
* mutation UpdateProduct($input: UpdateProductInput!) {
|
|
141
|
-
* updateProduct(input: $input) {
|
|
142
|
-
* ...ProductDetail
|
|
143
|
-
* }
|
|
144
|
-
* }
|
|
145
|
-
* ```
|
|
146
|
-
*
|
|
147
|
-
* The operation variables fields are the fields of the `UpdateProductInput` type.
|
|
148
|
-
*/
|
|
149
|
-
export function getOperationVariablesFields(documentNode: DocumentNode): FieldInfo[] {
|
|
150
|
-
const fields: FieldInfo[] = [];
|
|
151
|
-
|
|
152
|
-
const operationDefinition = documentNode.definitions.find(
|
|
153
|
-
(def): def is OperationDefinitionNode => def.kind === 'OperationDefinition',
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (operationDefinition?.variableDefinitions) {
|
|
157
|
-
operationDefinition.variableDefinitions.forEach(variable => {
|
|
158
|
-
const unwrappedType = unwrapVariableDefinitionType(variable.type);
|
|
159
|
-
const inputName = unwrappedType.name.value;
|
|
160
|
-
const inputFields = getInputTypeInfo(inputName);
|
|
161
|
-
fields.push(...inputFields);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return fields;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function unwrapVariableDefinitionType(type: TypeNode): NamedTypeNode {
|
|
169
|
-
if (type.kind === 'NonNullType') {
|
|
170
|
-
return unwrapVariableDefinitionType(type.type);
|
|
171
|
-
}
|
|
172
|
-
if (type.kind === 'ListType') {
|
|
173
|
-
return unwrapVariableDefinitionType(type.type);
|
|
174
|
-
}
|
|
175
|
-
return type;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* @description
|
|
180
|
-
* This function is used to get the name of the query from a DocumentNode.
|
|
181
|
-
*
|
|
182
|
-
* For example, in the following query:
|
|
183
|
-
*
|
|
184
|
-
* ```graphql
|
|
185
|
-
* query ProductDetail($id: ID!) {
|
|
186
|
-
* product(id: $id) {
|
|
187
|
-
* ...ProductDetail
|
|
188
|
-
* }
|
|
189
|
-
* }
|
|
190
|
-
* ```
|
|
191
|
-
*
|
|
192
|
-
* The query name is `product`.
|
|
193
|
-
*/
|
|
194
|
-
export function getQueryName(documentNode: DocumentNode): string {
|
|
195
|
-
const operationDefinition = documentNode.definitions.find(
|
|
196
|
-
(def): def is OperationDefinitionNode =>
|
|
197
|
-
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
198
|
-
);
|
|
199
|
-
const firstSelection = operationDefinition?.selectionSet.selections[0];
|
|
200
|
-
if (firstSelection?.kind === 'Field') {
|
|
201
|
-
return firstSelection.name.value;
|
|
202
|
-
} else {
|
|
203
|
-
throw new Error('Could not determine query name');
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* @description
|
|
209
|
-
* This function is used to get the type information of the query from a DocumentNode.
|
|
210
|
-
*
|
|
211
|
-
* For example, in the following query:
|
|
212
|
-
*
|
|
213
|
-
* ```graphql
|
|
214
|
-
* query ProductDetail($id: ID!) {
|
|
215
|
-
* product(id: $id) {
|
|
216
|
-
* ...ProductDetail
|
|
217
|
-
* }
|
|
218
|
-
* }
|
|
219
|
-
* ```
|
|
220
|
-
*
|
|
221
|
-
* The query type field will be the `Product` type.
|
|
222
|
-
*/
|
|
223
|
-
export function getQueryTypeFieldInfo(documentNode: DocumentNode): FieldInfo {
|
|
224
|
-
const name = getQueryName(documentNode);
|
|
225
|
-
return getQueryInfo(name);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* @description
|
|
230
|
-
* This function is used to get the path to the paginated list from a DocumentNode.
|
|
231
|
-
*
|
|
232
|
-
* For example, in the following query:
|
|
233
|
-
*
|
|
234
|
-
* ```graphql
|
|
235
|
-
* query GetProductList($options: ProductListOptions) {
|
|
236
|
-
* products(options: $options) {
|
|
237
|
-
* items {
|
|
238
|
-
* ...ProductDetail
|
|
239
|
-
* }
|
|
240
|
-
* totalCount
|
|
241
|
-
* }
|
|
242
|
-
* }
|
|
243
|
-
* ```
|
|
244
|
-
*
|
|
245
|
-
* The path to the paginated list is `['products']`.
|
|
246
|
-
*/
|
|
247
|
-
export function getObjectPathToPaginatedList(
|
|
248
|
-
documentNode: DocumentNode,
|
|
249
|
-
currentPath: string[] = [],
|
|
250
|
-
): string[] {
|
|
251
|
-
// get the query OperationDefinition
|
|
252
|
-
const operationDefinition = documentNode.definitions.find(
|
|
253
|
-
(def): def is OperationDefinitionNode =>
|
|
254
|
-
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
255
|
-
);
|
|
256
|
-
if (!operationDefinition) {
|
|
257
|
-
throw new Error('Could not find query operation definition');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return findPaginatedListPath(operationDefinition.selectionSet, 'Query', currentPath);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function findPaginatedListPath(
|
|
264
|
-
selectionSet: SelectionSetNode,
|
|
265
|
-
parentType: string,
|
|
266
|
-
currentPath: string[] = [],
|
|
267
|
-
): string[] {
|
|
268
|
-
for (const selection of selectionSet.selections) {
|
|
269
|
-
if (selection.kind === 'Field') {
|
|
270
|
-
const fieldNode = selection;
|
|
271
|
-
const fieldInfo = getObjectFieldInfo(parentType, fieldNode.name.value);
|
|
272
|
-
if (!fieldInfo) {
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
const newPath = [...currentPath, fieldNode.name.value];
|
|
276
|
-
|
|
277
|
-
if (fieldInfo.isPaginatedList) {
|
|
278
|
-
return newPath;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// If this field has a selection set, recursively search it
|
|
282
|
-
if (fieldNode.selectionSet && !fieldInfo.isScalar) {
|
|
283
|
-
const result = findPaginatedListPath(fieldNode.selectionSet, fieldInfo.type, newPath);
|
|
284
|
-
if (result.length > 0) {
|
|
285
|
-
return result;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return [];
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @description
|
|
296
|
-
* This function is used to get the name of the mutation from a DocumentNode.
|
|
297
|
-
*
|
|
298
|
-
* For example, in the following mutation:
|
|
299
|
-
*
|
|
300
|
-
* ```graphql
|
|
301
|
-
* mutation CreateProduct($input: CreateProductInput!) {
|
|
302
|
-
* createProduct(input: $input) {
|
|
303
|
-
* ...ProductDetail
|
|
304
|
-
* }
|
|
305
|
-
* }
|
|
306
|
-
* ```
|
|
307
|
-
*
|
|
308
|
-
* The mutation name is `createProduct`.
|
|
309
|
-
*/
|
|
310
|
-
export function getMutationName(documentNode: DocumentNode): string {
|
|
311
|
-
const operationDefinition = documentNode.definitions.find(
|
|
312
|
-
(def): def is OperationDefinitionNode =>
|
|
313
|
-
def.kind === 'OperationDefinition' && def.operation === 'mutation',
|
|
314
|
-
);
|
|
315
|
-
const firstSelection = operationDefinition?.selectionSet.selections[0];
|
|
316
|
-
if (firstSelection?.kind === 'Field') {
|
|
317
|
-
return firstSelection.name.value;
|
|
318
|
-
} else {
|
|
319
|
-
throw new Error('Could not determine mutation name');
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* @description
|
|
325
|
-
* This function is used to get the type information of an operation from a DocumentNode.
|
|
326
|
-
*/
|
|
327
|
-
export function getOperationTypeInfo(
|
|
328
|
-
definitionNode: DefinitionNode | FieldNode,
|
|
329
|
-
parentTypeName?: string,
|
|
330
|
-
): FieldInfo | undefined {
|
|
331
|
-
if (definitionNode.kind === 'OperationDefinition') {
|
|
332
|
-
const firstSelection = definitionNode?.selectionSet.selections[0];
|
|
333
|
-
if (firstSelection?.kind === 'Field') {
|
|
334
|
-
return getQueryInfo(firstSelection.name.value);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
if (definitionNode.kind === 'Field' && parentTypeName) {
|
|
338
|
-
const fieldInfo = getObjectFieldInfo(parentTypeName, definitionNode.name.value);
|
|
339
|
-
return fieldInfo;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export function getTypeFieldInfo(typeName: string): FieldInfo[] {
|
|
344
|
-
return Object.entries(schemaInfo.types[typeName])
|
|
345
|
-
.map(([fieldName]) => {
|
|
346
|
-
const fieldInfo = getObjectFieldInfo(typeName, fieldName);
|
|
347
|
-
if (!fieldInfo) {
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
return fieldInfo;
|
|
351
|
-
})
|
|
352
|
-
.filter(x => x != null) as FieldInfo[];
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function getQueryInfo(name: string): FieldInfo {
|
|
356
|
-
const fieldInfo = schemaInfo.types.Query[name];
|
|
357
|
-
return {
|
|
358
|
-
name,
|
|
359
|
-
type: fieldInfo[0],
|
|
360
|
-
nullable: fieldInfo[1],
|
|
361
|
-
list: fieldInfo[2],
|
|
362
|
-
isPaginatedList: fieldInfo[3],
|
|
363
|
-
isScalar: schemaInfo.scalars.includes(fieldInfo[0]),
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function getInputTypeInfo(name: string): FieldInfo[] {
|
|
368
|
-
return Object.entries(schemaInfo.inputs[name]).map(([fieldName, fieldInfo]: [string, any]) => {
|
|
369
|
-
const type = fieldInfo[0];
|
|
370
|
-
const isScalar = isScalarType(type);
|
|
371
|
-
const isEnum = isEnumType(type);
|
|
372
|
-
return {
|
|
373
|
-
name: fieldName,
|
|
374
|
-
type,
|
|
375
|
-
nullable: fieldInfo[1],
|
|
376
|
-
list: fieldInfo[2],
|
|
377
|
-
isPaginatedList: fieldInfo[3],
|
|
378
|
-
isScalar,
|
|
379
|
-
typeInfo: !isScalar && !isEnum ? getInputTypeInfo(type) : undefined,
|
|
380
|
-
};
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export function isScalarType(type: string): boolean {
|
|
385
|
-
return schemaInfo.scalars.includes(type);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export function isEnumType(type: string): boolean {
|
|
389
|
-
return schemaInfo.enums[type] != null;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function getObjectFieldInfo(typeName: string, fieldName: string): FieldInfo | undefined {
|
|
393
|
-
const fieldInfo = schemaInfo.types[typeName]?.[fieldName];
|
|
394
|
-
if (!fieldInfo) {
|
|
395
|
-
return undefined;
|
|
396
|
-
}
|
|
397
|
-
const type = fieldInfo[0];
|
|
398
|
-
const isScalar = isScalarType(type);
|
|
399
|
-
return {
|
|
400
|
-
name: fieldName,
|
|
401
|
-
type: fieldInfo[0],
|
|
402
|
-
nullable: fieldInfo[1],
|
|
403
|
-
list: fieldInfo[2],
|
|
404
|
-
isPaginatedList: fieldInfo[3],
|
|
405
|
-
isScalar,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function collectFields(
|
|
410
|
-
typeName: string,
|
|
411
|
-
fieldNode: FieldNode | FragmentSpreadNode,
|
|
412
|
-
fields: FieldInfo[],
|
|
413
|
-
fragments: Record<string, FragmentDefinitionNode>,
|
|
414
|
-
) {
|
|
415
|
-
if (fieldNode.kind === 'Field') {
|
|
416
|
-
const fieldInfo = getObjectFieldInfo(typeName, fieldNode.name.value);
|
|
417
|
-
if (!fieldInfo) {
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
fields.push(fieldInfo);
|
|
421
|
-
if (fieldNode.selectionSet) {
|
|
422
|
-
fieldNode.selectionSet.selections.forEach(subSelection => {
|
|
423
|
-
if (subSelection.kind === 'Field') {
|
|
424
|
-
collectFields(fieldInfo.type, subSelection, [], fragments);
|
|
425
|
-
} else if (subSelection.kind === 'FragmentSpread') {
|
|
426
|
-
const fragmentName = subSelection.name.value;
|
|
427
|
-
const fragment = fragments[fragmentName];
|
|
428
|
-
if (!fragment) {
|
|
429
|
-
throw new Error(
|
|
430
|
-
`Fragment "${fragmentName}" not found. Make sure to include it in the "${typeName}" type query.`,
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
// We only want to collect fields from the fragment if it's the same type as
|
|
434
|
-
// the field we're collecting from
|
|
435
|
-
if (fragment.name.value !== typeName) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
if (fragment) {
|
|
439
|
-
fragment.selectionSet.selections.forEach(fragmentSelection => {
|
|
440
|
-
if (fragmentSelection.kind === 'Field') {
|
|
441
|
-
collectFields(typeName, fragmentSelection, fields, fragments);
|
|
442
|
-
}
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
if (fieldNode.kind === 'FragmentSpread') {
|
|
450
|
-
const fragmentName = fieldNode.name.value;
|
|
451
|
-
const fragment = fragments[fragmentName];
|
|
452
|
-
if (fragment) {
|
|
453
|
-
fragment.selectionSet.selections.forEach(fragmentSelection => {
|
|
454
|
-
if (fragmentSelection.kind === 'Field') {
|
|
455
|
-
collectFields(typeName, fragmentSelection, fields, fragments);
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
DocumentNode,
|
|
3
|
+
OperationDefinitionNode,
|
|
4
|
+
FieldNode,
|
|
5
|
+
FragmentDefinitionNode,
|
|
6
|
+
FragmentSpreadNode,
|
|
7
|
+
VariableDefinitionNode,
|
|
8
|
+
} from 'graphql';
|
|
9
|
+
import { DefinitionNode, NamedTypeNode, SelectionSetNode, TypeNode } from 'graphql/language/ast.js';
|
|
10
|
+
import { schemaInfo } from 'virtual:admin-api-schema';
|
|
11
|
+
|
|
12
|
+
// for debug purposes
|
|
13
|
+
(window as any).schemaInfo = schemaInfo;
|
|
14
|
+
|
|
15
|
+
export interface FieldInfo {
|
|
16
|
+
name: string;
|
|
17
|
+
type: string;
|
|
18
|
+
nullable: boolean;
|
|
19
|
+
list: boolean;
|
|
20
|
+
isPaginatedList: boolean;
|
|
21
|
+
isScalar: boolean;
|
|
22
|
+
typeInfo?: FieldInfo[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @description
|
|
27
|
+
* Given a DocumentNode of a PaginatedList query, returns information about each
|
|
28
|
+
* of the selected fields.
|
|
29
|
+
*
|
|
30
|
+
* Inside React components, use the `useListQueryFields` hook to get this information.
|
|
31
|
+
*/
|
|
32
|
+
export function getListQueryFields(documentNode: DocumentNode): FieldInfo[] {
|
|
33
|
+
const fields: FieldInfo[] = [];
|
|
34
|
+
const fragments: Record<string, FragmentDefinitionNode> = {};
|
|
35
|
+
|
|
36
|
+
// Collect all fragment definitions
|
|
37
|
+
documentNode.definitions.forEach(def => {
|
|
38
|
+
if (def.kind === 'FragmentDefinition') {
|
|
39
|
+
fragments[def.name.value] = def;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const operationDefinition = documentNode.definitions.find(
|
|
44
|
+
(def): def is OperationDefinitionNode =>
|
|
45
|
+
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
for (const query of operationDefinition?.selectionSet.selections ?? []) {
|
|
49
|
+
if (query.kind === 'Field') {
|
|
50
|
+
const queryField = query;
|
|
51
|
+
const fieldInfo = getQueryInfo(queryField.name.value);
|
|
52
|
+
if (fieldInfo.isPaginatedList) {
|
|
53
|
+
processPaginatedList(queryField, fieldInfo, fields, fragments);
|
|
54
|
+
} else if (queryField.selectionSet) {
|
|
55
|
+
// Check for nested paginated lists
|
|
56
|
+
findNestedPaginatedLists(queryField, fieldInfo.type, fields, fragments);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return fields;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function processPaginatedList(
|
|
65
|
+
field: FieldNode,
|
|
66
|
+
fieldInfo: FieldInfo,
|
|
67
|
+
fields: FieldInfo[],
|
|
68
|
+
fragments: Record<string, FragmentDefinitionNode>,
|
|
69
|
+
) {
|
|
70
|
+
const itemsField = field.selectionSet?.selections.find(
|
|
71
|
+
selection => selection.kind === 'Field' && selection.name.value === 'items',
|
|
72
|
+
) as FieldNode;
|
|
73
|
+
if (!itemsField) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const typeFields = schemaInfo.types[fieldInfo.type];
|
|
77
|
+
const isPaginatedList = typeFields.hasOwnProperty('items') && typeFields.hasOwnProperty('totalItems');
|
|
78
|
+
if (!isPaginatedList) {
|
|
79
|
+
throw new Error(`Could not determine type of items in ${fieldInfo.name}`);
|
|
80
|
+
}
|
|
81
|
+
const itemsType = getObjectFieldInfo(fieldInfo.type, 'items')?.type;
|
|
82
|
+
if (!itemsType) {
|
|
83
|
+
throw new Error(`Could not determine type of items in ${fieldInfo.name}`);
|
|
84
|
+
}
|
|
85
|
+
for (const item of itemsField.selectionSet?.selections ?? []) {
|
|
86
|
+
if (item.kind === 'Field' || item.kind === 'FragmentSpread') {
|
|
87
|
+
collectFields(itemsType, item, fields, fragments);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function findNestedPaginatedLists(
|
|
93
|
+
field: FieldNode,
|
|
94
|
+
parentType: string,
|
|
95
|
+
fields: FieldInfo[],
|
|
96
|
+
fragments: Record<string, FragmentDefinitionNode>,
|
|
97
|
+
) {
|
|
98
|
+
for (const selection of field.selectionSet?.selections ?? []) {
|
|
99
|
+
if (selection.kind === 'Field') {
|
|
100
|
+
const fieldInfo = getObjectFieldInfo(parentType, selection.name.value);
|
|
101
|
+
if (!fieldInfo) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (fieldInfo.isPaginatedList) {
|
|
105
|
+
processPaginatedList(selection, fieldInfo, fields, fragments);
|
|
106
|
+
} else if (selection.selectionSet && !fieldInfo.isScalar) {
|
|
107
|
+
// Continue recursion
|
|
108
|
+
findNestedPaginatedLists(selection, fieldInfo.type, fields, fragments);
|
|
109
|
+
}
|
|
110
|
+
} else if (selection.kind === 'FragmentSpread') {
|
|
111
|
+
// Handle fragment spread on the parent type
|
|
112
|
+
const fragmentName = selection.name.value;
|
|
113
|
+
const fragment = fragments[fragmentName];
|
|
114
|
+
if (fragment && fragment.typeCondition.name.value === parentType) {
|
|
115
|
+
for (const fragmentSelection of fragment.selectionSet.selections) {
|
|
116
|
+
if (fragmentSelection.kind === 'Field') {
|
|
117
|
+
const fieldInfo = getObjectFieldInfo(parentType, fragmentSelection.name.value);
|
|
118
|
+
if (!fieldInfo) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (fieldInfo.isPaginatedList) {
|
|
122
|
+
processPaginatedList(fragmentSelection, fieldInfo, fields, fragments);
|
|
123
|
+
} else if (fragmentSelection.selectionSet && !fieldInfo.isScalar) {
|
|
124
|
+
findNestedPaginatedLists(fragmentSelection, fieldInfo.type, fields, fragments);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @description
|
|
135
|
+
* This function is used to get the fields of the operation variables from a DocumentNode.
|
|
136
|
+
*
|
|
137
|
+
* For example, in the following query:
|
|
138
|
+
*
|
|
139
|
+
* ```graphql
|
|
140
|
+
* mutation UpdateProduct($input: UpdateProductInput!) {
|
|
141
|
+
* updateProduct(input: $input) {
|
|
142
|
+
* ...ProductDetail
|
|
143
|
+
* }
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* The operation variables fields are the fields of the `UpdateProductInput` type.
|
|
148
|
+
*/
|
|
149
|
+
export function getOperationVariablesFields(documentNode: DocumentNode): FieldInfo[] {
|
|
150
|
+
const fields: FieldInfo[] = [];
|
|
151
|
+
|
|
152
|
+
const operationDefinition = documentNode.definitions.find(
|
|
153
|
+
(def): def is OperationDefinitionNode => def.kind === 'OperationDefinition',
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (operationDefinition?.variableDefinitions) {
|
|
157
|
+
operationDefinition.variableDefinitions.forEach(variable => {
|
|
158
|
+
const unwrappedType = unwrapVariableDefinitionType(variable.type);
|
|
159
|
+
const inputName = unwrappedType.name.value;
|
|
160
|
+
const inputFields = getInputTypeInfo(inputName);
|
|
161
|
+
fields.push(...inputFields);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return fields;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function unwrapVariableDefinitionType(type: TypeNode): NamedTypeNode {
|
|
169
|
+
if (type.kind === 'NonNullType') {
|
|
170
|
+
return unwrapVariableDefinitionType(type.type);
|
|
171
|
+
}
|
|
172
|
+
if (type.kind === 'ListType') {
|
|
173
|
+
return unwrapVariableDefinitionType(type.type);
|
|
174
|
+
}
|
|
175
|
+
return type;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @description
|
|
180
|
+
* This function is used to get the name of the query from a DocumentNode.
|
|
181
|
+
*
|
|
182
|
+
* For example, in the following query:
|
|
183
|
+
*
|
|
184
|
+
* ```graphql
|
|
185
|
+
* query ProductDetail($id: ID!) {
|
|
186
|
+
* product(id: $id) {
|
|
187
|
+
* ...ProductDetail
|
|
188
|
+
* }
|
|
189
|
+
* }
|
|
190
|
+
* ```
|
|
191
|
+
*
|
|
192
|
+
* The query name is `product`.
|
|
193
|
+
*/
|
|
194
|
+
export function getQueryName(documentNode: DocumentNode): string {
|
|
195
|
+
const operationDefinition = documentNode.definitions.find(
|
|
196
|
+
(def): def is OperationDefinitionNode =>
|
|
197
|
+
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
198
|
+
);
|
|
199
|
+
const firstSelection = operationDefinition?.selectionSet.selections[0];
|
|
200
|
+
if (firstSelection?.kind === 'Field') {
|
|
201
|
+
return firstSelection.name.value;
|
|
202
|
+
} else {
|
|
203
|
+
throw new Error('Could not determine query name');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @description
|
|
209
|
+
* This function is used to get the type information of the query from a DocumentNode.
|
|
210
|
+
*
|
|
211
|
+
* For example, in the following query:
|
|
212
|
+
*
|
|
213
|
+
* ```graphql
|
|
214
|
+
* query ProductDetail($id: ID!) {
|
|
215
|
+
* product(id: $id) {
|
|
216
|
+
* ...ProductDetail
|
|
217
|
+
* }
|
|
218
|
+
* }
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* The query type field will be the `Product` type.
|
|
222
|
+
*/
|
|
223
|
+
export function getQueryTypeFieldInfo(documentNode: DocumentNode): FieldInfo {
|
|
224
|
+
const name = getQueryName(documentNode);
|
|
225
|
+
return getQueryInfo(name);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @description
|
|
230
|
+
* This function is used to get the path to the paginated list from a DocumentNode.
|
|
231
|
+
*
|
|
232
|
+
* For example, in the following query:
|
|
233
|
+
*
|
|
234
|
+
* ```graphql
|
|
235
|
+
* query GetProductList($options: ProductListOptions) {
|
|
236
|
+
* products(options: $options) {
|
|
237
|
+
* items {
|
|
238
|
+
* ...ProductDetail
|
|
239
|
+
* }
|
|
240
|
+
* totalCount
|
|
241
|
+
* }
|
|
242
|
+
* }
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* The path to the paginated list is `['products']`.
|
|
246
|
+
*/
|
|
247
|
+
export function getObjectPathToPaginatedList(
|
|
248
|
+
documentNode: DocumentNode,
|
|
249
|
+
currentPath: string[] = [],
|
|
250
|
+
): string[] {
|
|
251
|
+
// get the query OperationDefinition
|
|
252
|
+
const operationDefinition = documentNode.definitions.find(
|
|
253
|
+
(def): def is OperationDefinitionNode =>
|
|
254
|
+
def.kind === 'OperationDefinition' && def.operation === 'query',
|
|
255
|
+
);
|
|
256
|
+
if (!operationDefinition) {
|
|
257
|
+
throw new Error('Could not find query operation definition');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return findPaginatedListPath(operationDefinition.selectionSet, 'Query', currentPath);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function findPaginatedListPath(
|
|
264
|
+
selectionSet: SelectionSetNode,
|
|
265
|
+
parentType: string,
|
|
266
|
+
currentPath: string[] = [],
|
|
267
|
+
): string[] {
|
|
268
|
+
for (const selection of selectionSet.selections) {
|
|
269
|
+
if (selection.kind === 'Field') {
|
|
270
|
+
const fieldNode = selection;
|
|
271
|
+
const fieldInfo = getObjectFieldInfo(parentType, fieldNode.name.value);
|
|
272
|
+
if (!fieldInfo) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const newPath = [...currentPath, fieldNode.name.value];
|
|
276
|
+
|
|
277
|
+
if (fieldInfo.isPaginatedList) {
|
|
278
|
+
return newPath;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// If this field has a selection set, recursively search it
|
|
282
|
+
if (fieldNode.selectionSet && !fieldInfo.isScalar) {
|
|
283
|
+
const result = findPaginatedListPath(fieldNode.selectionSet, fieldInfo.type, newPath);
|
|
284
|
+
if (result.length > 0) {
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @description
|
|
296
|
+
* This function is used to get the name of the mutation from a DocumentNode.
|
|
297
|
+
*
|
|
298
|
+
* For example, in the following mutation:
|
|
299
|
+
*
|
|
300
|
+
* ```graphql
|
|
301
|
+
* mutation CreateProduct($input: CreateProductInput!) {
|
|
302
|
+
* createProduct(input: $input) {
|
|
303
|
+
* ...ProductDetail
|
|
304
|
+
* }
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* The mutation name is `createProduct`.
|
|
309
|
+
*/
|
|
310
|
+
export function getMutationName(documentNode: DocumentNode): string {
|
|
311
|
+
const operationDefinition = documentNode.definitions.find(
|
|
312
|
+
(def): def is OperationDefinitionNode =>
|
|
313
|
+
def.kind === 'OperationDefinition' && def.operation === 'mutation',
|
|
314
|
+
);
|
|
315
|
+
const firstSelection = operationDefinition?.selectionSet.selections[0];
|
|
316
|
+
if (firstSelection?.kind === 'Field') {
|
|
317
|
+
return firstSelection.name.value;
|
|
318
|
+
} else {
|
|
319
|
+
throw new Error('Could not determine mutation name');
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @description
|
|
325
|
+
* This function is used to get the type information of an operation from a DocumentNode.
|
|
326
|
+
*/
|
|
327
|
+
export function getOperationTypeInfo(
|
|
328
|
+
definitionNode: DefinitionNode | FieldNode,
|
|
329
|
+
parentTypeName?: string,
|
|
330
|
+
): FieldInfo | undefined {
|
|
331
|
+
if (definitionNode.kind === 'OperationDefinition') {
|
|
332
|
+
const firstSelection = definitionNode?.selectionSet.selections[0];
|
|
333
|
+
if (firstSelection?.kind === 'Field') {
|
|
334
|
+
return getQueryInfo(firstSelection.name.value);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (definitionNode.kind === 'Field' && parentTypeName) {
|
|
338
|
+
const fieldInfo = getObjectFieldInfo(parentTypeName, definitionNode.name.value);
|
|
339
|
+
return fieldInfo;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function getTypeFieldInfo(typeName: string): FieldInfo[] {
|
|
344
|
+
return Object.entries(schemaInfo.types[typeName])
|
|
345
|
+
.map(([fieldName]) => {
|
|
346
|
+
const fieldInfo = getObjectFieldInfo(typeName, fieldName);
|
|
347
|
+
if (!fieldInfo) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
return fieldInfo;
|
|
351
|
+
})
|
|
352
|
+
.filter(x => x != null) as FieldInfo[];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function getQueryInfo(name: string): FieldInfo {
|
|
356
|
+
const fieldInfo = schemaInfo.types.Query[name];
|
|
357
|
+
return {
|
|
358
|
+
name,
|
|
359
|
+
type: fieldInfo[0],
|
|
360
|
+
nullable: fieldInfo[1],
|
|
361
|
+
list: fieldInfo[2],
|
|
362
|
+
isPaginatedList: fieldInfo[3],
|
|
363
|
+
isScalar: schemaInfo.scalars.includes(fieldInfo[0]),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function getInputTypeInfo(name: string): FieldInfo[] {
|
|
368
|
+
return Object.entries(schemaInfo.inputs[name]).map(([fieldName, fieldInfo]: [string, any]) => {
|
|
369
|
+
const type = fieldInfo[0];
|
|
370
|
+
const isScalar = isScalarType(type);
|
|
371
|
+
const isEnum = isEnumType(type);
|
|
372
|
+
return {
|
|
373
|
+
name: fieldName,
|
|
374
|
+
type,
|
|
375
|
+
nullable: fieldInfo[1],
|
|
376
|
+
list: fieldInfo[2],
|
|
377
|
+
isPaginatedList: fieldInfo[3],
|
|
378
|
+
isScalar,
|
|
379
|
+
typeInfo: !isScalar && !isEnum ? getInputTypeInfo(type) : undefined,
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function isScalarType(type: string): boolean {
|
|
385
|
+
return schemaInfo.scalars.includes(type);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function isEnumType(type: string): boolean {
|
|
389
|
+
return schemaInfo.enums[type] != null;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function getObjectFieldInfo(typeName: string, fieldName: string): FieldInfo | undefined {
|
|
393
|
+
const fieldInfo = schemaInfo.types[typeName]?.[fieldName];
|
|
394
|
+
if (!fieldInfo) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
const type = fieldInfo[0];
|
|
398
|
+
const isScalar = isScalarType(type);
|
|
399
|
+
return {
|
|
400
|
+
name: fieldName,
|
|
401
|
+
type: fieldInfo[0],
|
|
402
|
+
nullable: fieldInfo[1],
|
|
403
|
+
list: fieldInfo[2],
|
|
404
|
+
isPaginatedList: fieldInfo[3],
|
|
405
|
+
isScalar,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function collectFields(
|
|
410
|
+
typeName: string,
|
|
411
|
+
fieldNode: FieldNode | FragmentSpreadNode,
|
|
412
|
+
fields: FieldInfo[],
|
|
413
|
+
fragments: Record<string, FragmentDefinitionNode>,
|
|
414
|
+
) {
|
|
415
|
+
if (fieldNode.kind === 'Field') {
|
|
416
|
+
const fieldInfo = getObjectFieldInfo(typeName, fieldNode.name.value);
|
|
417
|
+
if (!fieldInfo) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
fields.push(fieldInfo);
|
|
421
|
+
if (fieldNode.selectionSet) {
|
|
422
|
+
fieldNode.selectionSet.selections.forEach(subSelection => {
|
|
423
|
+
if (subSelection.kind === 'Field') {
|
|
424
|
+
collectFields(fieldInfo.type, subSelection, [], fragments);
|
|
425
|
+
} else if (subSelection.kind === 'FragmentSpread') {
|
|
426
|
+
const fragmentName = subSelection.name.value;
|
|
427
|
+
const fragment = fragments[fragmentName];
|
|
428
|
+
if (!fragment) {
|
|
429
|
+
throw new Error(
|
|
430
|
+
`Fragment "${fragmentName}" not found. Make sure to include it in the "${typeName}" type query.`,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
// We only want to collect fields from the fragment if it's the same type as
|
|
434
|
+
// the field we're collecting from
|
|
435
|
+
if (fragment.name.value !== typeName) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (fragment) {
|
|
439
|
+
fragment.selectionSet.selections.forEach(fragmentSelection => {
|
|
440
|
+
if (fragmentSelection.kind === 'Field') {
|
|
441
|
+
collectFields(typeName, fragmentSelection, fields, fragments);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (fieldNode.kind === 'FragmentSpread') {
|
|
450
|
+
const fragmentName = fieldNode.name.value;
|
|
451
|
+
const fragment = fragments[fragmentName];
|
|
452
|
+
if (fragment) {
|
|
453
|
+
fragment.selectionSet.selections.forEach(fragmentSelection => {
|
|
454
|
+
if (fragmentSelection.kind === 'Field') {
|
|
455
|
+
collectFields(typeName, fragmentSelection, fields, fragments);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|