@xleddyl/nuxt-cms 0.9.3 → 0.10.0
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/README.md +1 -1
- package/dist/module.d.mts +20 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1037 -148
- package/dist/runtime/app/blocks/CmsBlocks.d.vue.ts +1 -1
- package/dist/runtime/app/blocks/CmsBlocks.vue +57 -9
- package/dist/runtime/app/blocks/CmsBlocks.vue.d.ts +1 -1
- package/dist/runtime/app/blocks/CmsField.d.ts +24 -0
- package/dist/runtime/app/blocks/CmsField.js +16 -0
- package/dist/runtime/app/blocks/node.d.ts +37 -0
- package/dist/runtime/app/blocks/node.js +17 -0
- package/dist/runtime/app/blocks/resolve.d.ts +18 -0
- package/dist/runtime/app/blocks/resolve.js +34 -0
- package/dist/runtime/app/components/cms/BlockPicker.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue +87 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.d.vue.ts +38 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue +44 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue.d.ts +38 -0
- package/dist/runtime/app/components/cms/BlockTree.d.vue.ts +29 -0
- package/dist/runtime/app/components/cms/BlockTree.vue +322 -0
- package/dist/runtime/app/components/cms/BlockTree.vue.d.ts +29 -0
- package/dist/runtime/app/components/cms/BlocksField.vue +569 -218
- package/dist/runtime/app/components/cms/BrandMark.vue +7 -13
- package/dist/runtime/app/components/cms/ConfirmGroups.vue +15 -13
- package/dist/runtime/app/components/cms/{BlockPalette.vue.d.ts → EditorHistory.d.vue.ts} +6 -5
- package/dist/runtime/app/components/cms/EditorHistory.vue +34 -0
- package/dist/runtime/app/components/cms/{BlockPalette.d.vue.ts → EditorHistory.vue.d.ts} +6 -5
- package/dist/runtime/app/components/cms/EntryDrawer.d.vue.ts +11 -5
- package/dist/runtime/app/components/cms/EntryDrawer.vue +183 -152
- package/dist/runtime/app/components/cms/EntryDrawer.vue.d.ts +11 -5
- package/dist/runtime/app/components/cms/EntryForm.d.vue.ts +16 -4
- package/dist/runtime/app/components/cms/EntryForm.vue +106 -146
- package/dist/runtime/app/components/cms/EntryForm.vue.d.ts +16 -4
- package/dist/runtime/app/components/cms/FieldInput.vue +10 -2
- package/dist/runtime/app/components/cms/FormSections.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/FormSections.vue +71 -0
- package/dist/runtime/app/components/cms/FormSections.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/ImportModal.vue +46 -58
- package/dist/runtime/app/components/cms/LinkField.d.vue.ts +16 -0
- package/dist/runtime/app/components/cms/LinkField.vue +250 -0
- package/dist/runtime/app/components/cms/LinkField.vue.d.ts +16 -0
- package/dist/runtime/app/components/cms/ListFilters.vue +10 -12
- package/dist/runtime/app/components/cms/LocaleSwitch.d.vue.ts +2 -1
- package/dist/runtime/app/components/cms/LocaleSwitch.vue +29 -5
- package/dist/runtime/app/components/cms/LocaleSwitch.vue.d.ts +2 -1
- package/dist/runtime/app/components/cms/MediaDetail.d.vue.ts +2 -0
- package/dist/runtime/app/components/cms/MediaDetail.vue +112 -83
- package/dist/runtime/app/components/cms/MediaDetail.vue.d.ts +2 -0
- package/dist/runtime/app/components/cms/MediaField.vue +35 -25
- package/dist/runtime/app/components/cms/MediaFolderPicker.vue +26 -71
- package/dist/runtime/app/components/cms/MediaGallery.d.vue.ts +1 -0
- package/dist/runtime/app/components/cms/MediaGallery.vue +442 -419
- package/dist/runtime/app/components/cms/MediaGallery.vue.d.ts +1 -0
- package/dist/runtime/app/components/cms/MediaThumb.vue +9 -25
- package/dist/runtime/app/components/cms/MediaUpload.vue +1 -1
- package/dist/runtime/app/components/cms/{BlockOutline.d.vue.ts → NestedBlockList.d.vue.ts} +5 -5
- package/dist/runtime/app/components/cms/NestedBlockList.vue +87 -0
- package/dist/runtime/app/components/cms/{BlockOutline.vue.d.ts → NestedBlockList.vue.d.ts} +5 -5
- package/dist/runtime/app/components/cms/PoweredBy.vue +12 -5
- package/dist/runtime/app/components/cms/PresetModal.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/PresetModal.vue +70 -0
- package/dist/runtime/app/components/cms/PresetModal.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/RelationField.vue +2 -8
- package/dist/runtime/app/components/cms/SettingsAccount.vue +60 -71
- package/dist/runtime/app/components/cms/SettingsColumns.vue +47 -69
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue +50 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntry.d.vue.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntry.vue +11 -95
- package/dist/runtime/app/components/cms/SettingsEntry.vue.d.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntryActions.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue +42 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue +17 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsLayout.vue +18 -14
- package/dist/runtime/app/components/cms/SettingsPresetForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue +60 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresets.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue +65 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.d.vue.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue +45 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue.d.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue +59 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue +77 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue +117 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue +43 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSite.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue +140 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.d.vue.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue +82 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue.d.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue +179 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUsers.d.vue.ts +9 -6
- package/dist/runtime/app/components/cms/SettingsUsers.vue +88 -234
- package/dist/runtime/app/components/cms/SettingsUsers.vue.d.ts +9 -6
- package/dist/runtime/app/components/cms/SharePreview.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/SharePreview.vue +219 -0
- package/dist/runtime/app/components/cms/SharePreview.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/SlugField.vue +5 -3
- package/dist/runtime/app/components/cms/StatusBadge.vue +9 -8
- package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue +45 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationMenu.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue +28 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/VisualEditor.d.vue.ts +22 -4
- package/dist/runtime/app/components/cms/VisualEditor.vue +1152 -335
- package/dist/runtime/app/components/cms/VisualEditor.vue.d.ts +22 -4
- package/dist/runtime/app/components/cms/WelcomeModal.vue +32 -50
- package/dist/runtime/app/composables/cms-clipboard.d.ts +8 -0
- package/dist/runtime/app/composables/cms-clipboard.js +38 -0
- package/dist/runtime/app/composables/cms-confirm.d.ts +6 -8
- package/dist/runtime/app/composables/cms-confirm.js +5 -7
- package/dist/runtime/app/composables/cms-entry-disabled.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry-disabled.js +7 -0
- package/dist/runtime/app/composables/cms-entry-form.d.ts +15 -0
- package/dist/runtime/app/composables/cms-entry-form.js +40 -0
- package/dist/runtime/app/composables/cms-entry-settings.d.ts +30 -0
- package/dist/runtime/app/composables/cms-entry-settings.js +122 -0
- package/dist/runtime/app/composables/cms-entry.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry.js +36 -11
- package/dist/runtime/app/composables/cms-history.d.ts +10 -0
- package/dist/runtime/app/composables/cms-history.js +24 -0
- package/dist/runtime/app/composables/cms-link-targets.d.ts +10 -0
- package/dist/runtime/app/composables/cms-link-targets.js +40 -0
- package/dist/runtime/app/composables/cms-link-usage.d.ts +1 -0
- package/dist/runtime/app/composables/cms-link-usage.js +45 -0
- package/dist/runtime/app/composables/cms-media-library.d.ts +19 -9
- package/dist/runtime/app/composables/cms-media-library.js +31 -13
- package/dist/runtime/app/composables/cms-media-uploader.js +6 -20
- package/dist/runtime/app/composables/cms-permissions.d.ts +18 -0
- package/dist/runtime/app/composables/cms-permissions.js +54 -0
- package/dist/runtime/app/composables/cms-presets.d.ts +11 -0
- package/dist/runtime/app/composables/cms-presets.js +40 -0
- package/dist/runtime/app/composables/cms-preview-mode.d.ts +4 -0
- package/dist/runtime/app/composables/cms-preview-mode.js +8 -0
- package/dist/runtime/app/composables/cms-query.d.ts +3 -0
- package/dist/runtime/app/composables/cms-query.js +45 -20
- package/dist/runtime/app/composables/cms-record-list.d.ts +31 -0
- package/dist/runtime/app/composables/cms-record-list.js +75 -0
- package/dist/runtime/app/composables/cms-route.d.ts +6 -0
- package/dist/runtime/app/composables/cms-route.js +36 -0
- package/dist/runtime/app/composables/cms-runtime.d.ts +1 -0
- package/dist/runtime/app/composables/cms-save-handoff.d.ts +4 -0
- package/dist/runtime/app/composables/cms-save-handoff.js +19 -0
- package/dist/runtime/app/composables/cms-seo.d.ts +12 -0
- package/dist/runtime/app/composables/cms-seo.js +69 -0
- package/dist/runtime/app/composables/cms-settings-form.d.ts +13 -0
- package/dist/runtime/app/composables/cms-settings-form.js +29 -0
- package/dist/runtime/app/composables/cms-settings-sections.d.ts +26 -0
- package/dist/runtime/app/composables/cms-settings-sections.js +181 -0
- package/dist/runtime/app/composables/cms-settings-stores.d.ts +52 -0
- package/dist/runtime/app/composables/cms-settings-stores.js +156 -0
- package/dist/runtime/app/composables/cms-settings.d.ts +3 -3
- package/dist/runtime/app/composables/cms-settings.js +14 -8
- package/dist/runtime/app/composables/cms-site-disabled.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site-disabled.js +8 -0
- package/dist/runtime/app/composables/cms-site.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site.js +22 -0
- package/dist/runtime/app/composables/cms-toast.d.ts +2 -8
- package/dist/runtime/app/composables/cms-toast.js +3 -9
- package/dist/runtime/app/composables/cms-translation-actions.d.ts +15 -0
- package/dist/runtime/app/composables/cms-translation-actions.js +108 -0
- package/dist/runtime/app/css-url.d.ts +4 -0
- package/dist/runtime/app/image/CmsImage.d.vue.ts +89 -0
- package/dist/runtime/app/image/CmsImage.vue +91 -0
- package/dist/runtime/app/image/CmsImage.vue.d.ts +89 -0
- package/dist/runtime/app/layouts/cms-admin.d.vue.ts +2 -2
- package/dist/runtime/app/layouts/cms-admin.vue +98 -76
- package/dist/runtime/app/layouts/cms-admin.vue.d.ts +2 -2
- package/dist/runtime/app/layouts/cms-editor.vue +7 -2
- package/dist/runtime/app/links/CmsLink.d.vue.ts +18 -0
- package/dist/runtime/app/links/CmsLink.vue +18 -0
- package/dist/runtime/app/links/CmsLink.vue.d.ts +18 -0
- package/dist/runtime/app/middleware/cms-auth.js +13 -1
- package/dist/runtime/app/pages/admin-collection.vue +473 -297
- package/dist/runtime/app/pages/admin-content.vue +190 -53
- package/dist/runtime/app/pages/admin-entry.vue +79 -75
- package/dist/runtime/app/pages/admin-index.vue +18 -5
- package/dist/runtime/app/pages/admin-login.vue +1 -1
- package/dist/runtime/app/pages/admin-logout.vue +1 -1
- package/dist/runtime/app/pages/admin-media.vue +3 -3
- package/dist/runtime/app/pages/admin-preview.vue +112 -24
- package/dist/runtime/app/plugins/cms-field.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-field.js +8 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.js +19 -0
- package/dist/runtime/app/plugins/cms-preview.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview.js +27 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.d.vue.ts +7 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue +63 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue.d.ts +7 -0
- package/dist/runtime/app/preview/PreviewOverlay.d.vue.ts +17 -3
- package/dist/runtime/app/preview/PreviewOverlay.vue +629 -166
- package/dist/runtime/app/preview/PreviewOverlay.vue.d.ts +17 -3
- package/dist/runtime/app/preview/field-marker.d.ts +12 -0
- package/dist/runtime/app/preview/field-marker.js +20 -0
- package/dist/runtime/app/preview/inline-text.d.ts +15 -0
- package/dist/runtime/app/preview/inline-text.js +158 -0
- package/dist/runtime/app/utils/block-editor.d.ts +22 -0
- package/dist/runtime/app/utils/block-editor.js +12 -0
- package/dist/runtime/app/utils/keyboard.d.ts +6 -0
- package/dist/runtime/app/utils/keyboard.js +52 -0
- package/dist/runtime/app/utils/redirects.d.ts +6 -0
- package/dist/runtime/app/utils/redirects.js +7 -0
- package/dist/runtime/app/utils/ui.d.ts +8 -0
- package/dist/runtime/app/utils/ui.js +15 -1
- package/dist/runtime/app/utils/users.d.ts +15 -0
- package/dist/runtime/app/utils/users.js +14 -0
- package/dist/runtime/assets/cms.css +1 -1
- package/dist/runtime/generate.js +16 -2
- package/dist/runtime/server/api/collection-export.get.js +3 -2
- package/dist/runtime/server/api/collection-import.post.js +39 -11
- package/dist/runtime/server/api/collection.get.js +29 -10
- package/dist/runtime/server/api/collection.post.js +28 -11
- package/dist/runtime/server/api/collection.put.js +35 -13
- package/dist/runtime/server/api/item.delete.js +19 -7
- package/dist/runtime/server/api/item.get.js +3 -2
- package/dist/runtime/server/api/item.put.js +52 -18
- package/dist/runtime/server/api/link-usage.post.d.ts +5 -0
- package/dist/runtime/server/api/link-usage.post.js +21 -0
- package/dist/runtime/server/api/media-delete.post.js +4 -2
- package/dist/runtime/server/api/media-download.get.js +2 -2
- package/dist/runtime/server/api/media-folder.delete.js +8 -2
- package/dist/runtime/server/api/media-folder.patch.js +10 -2
- package/dist/runtime/server/api/media-folder.post.js +4 -2
- package/dist/runtime/server/api/media-move.post.js +7 -4
- package/dist/runtime/server/api/media-presign.post.js +2 -2
- package/dist/runtime/server/api/media-upload.put.js +2 -2
- package/dist/runtime/server/api/media-usage.post.d.ts +2 -4
- package/dist/runtime/server/api/media-usage.post.js +13 -9
- package/dist/runtime/server/api/media.delete.js +4 -2
- package/dist/runtime/server/api/media.get.js +22 -7
- package/dist/runtime/server/api/media.post.js +4 -2
- package/dist/runtime/server/api/media.put.js +33 -16
- package/dist/runtime/server/api/preset.delete.d.ts +4 -0
- package/dist/runtime/server/api/preset.delete.js +9 -0
- package/dist/runtime/server/api/preset.put.d.ts +3 -0
- package/dist/runtime/server/api/preset.put.js +23 -0
- package/dist/runtime/server/api/presets-field.get.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.get.js +13 -0
- package/dist/runtime/server/api/presets-field.post.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.post.js +36 -0
- package/dist/runtime/server/api/presets.get.d.ts +3 -0
- package/dist/runtime/server/api/presets.get.js +7 -0
- package/dist/runtime/server/api/preview-link.delete.d.ts +4 -0
- package/dist/runtime/server/api/preview-link.delete.js +15 -0
- package/dist/runtime/server/api/preview-links.get.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.get.js +10 -0
- package/dist/runtime/server/api/preview-links.post.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.post.js +17 -0
- package/dist/runtime/server/api/preview.get.d.ts +3 -0
- package/dist/runtime/server/api/preview.get.js +7 -0
- package/dist/runtime/server/api/redirect.delete.d.ts +4 -0
- package/dist/runtime/server/api/redirect.delete.js +10 -0
- package/dist/runtime/server/api/redirect.put.d.ts +3 -0
- package/dist/runtime/server/api/redirect.put.js +8 -0
- package/dist/runtime/server/api/redirects-import.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects-import.post.js +13 -0
- package/dist/runtime/server/api/redirects.get.d.ts +3 -0
- package/dist/runtime/server/api/redirects.get.js +7 -0
- package/dist/runtime/server/api/redirects.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects.post.js +7 -0
- package/dist/runtime/server/api/search.get.js +8 -3
- package/dist/runtime/server/api/settings.delete.js +2 -2
- package/dist/runtime/server/api/settings.get.js +4 -2
- package/dist/runtime/server/api/settings.put.js +2 -2
- package/dist/runtime/server/api/site.get.d.ts +3 -0
- package/dist/runtime/server/api/site.get.js +7 -0
- package/dist/runtime/server/api/site.put.d.ts +3 -0
- package/dist/runtime/server/api/site.put.js +16 -0
- package/dist/runtime/server/api/tags.get.js +3 -2
- package/dist/runtime/server/api/user.delete.js +8 -2
- package/dist/runtime/server/api/user.put.js +14 -4
- package/dist/runtime/server/api/users.get.js +2 -2
- package/dist/runtime/server/api/users.post.js +8 -4
- package/dist/runtime/server/middleware/hidden-site.d.ts +2 -0
- package/dist/runtime/server/middleware/hidden-site.js +8 -0
- package/dist/runtime/server/middleware/preview-links.d.ts +2 -0
- package/dist/runtime/server/middleware/preview-links.js +6 -0
- package/dist/runtime/server/middleware/redirects.d.ts +2 -0
- package/dist/runtime/server/middleware/redirects.js +18 -0
- package/dist/runtime/server/plugins/session-validate.js +4 -1
- package/dist/runtime/server/plugins/webhooks.d.ts +3 -0
- package/dist/runtime/server/plugins/webhooks.js +27 -0
- package/dist/runtime/server/routes/graphql.js +5 -3
- package/dist/runtime/server/routes/robots.d.ts +2 -0
- package/dist/runtime/server/routes/robots.js +16 -0
- package/dist/runtime/server/routes/sitemap.d.ts +2 -0
- package/dist/runtime/server/routes/sitemap.js +67 -0
- package/dist/runtime/server/utils/cached-value.d.ts +5 -0
- package/dist/runtime/server/utils/cached-value.js +24 -0
- package/dist/runtime/server/utils/content-routes.d.ts +5 -0
- package/dist/runtime/server/utils/content-routes.js +29 -0
- package/dist/runtime/server/utils/field-rules.d.ts +19 -0
- package/dist/runtime/server/utils/field-rules.js +72 -0
- package/dist/runtime/server/utils/graphql.d.ts +3 -1
- package/dist/runtime/server/utils/graphql.js +145 -29
- package/dist/runtime/server/utils/hooks.d.ts +14 -0
- package/dist/runtime/server/utils/hooks.js +71 -0
- package/dist/runtime/server/utils/import.d.ts +7 -2
- package/dist/runtime/server/utils/import.js +108 -14
- package/dist/runtime/server/utils/link-usage.d.ts +4 -0
- package/dist/runtime/server/utils/link-usage.js +28 -0
- package/dist/runtime/server/utils/media-references.d.ts +6 -1
- package/dist/runtime/server/utils/media-references.js +49 -20
- package/dist/runtime/server/utils/media-usage.d.ts +2 -0
- package/dist/runtime/server/utils/media-usage.js +5 -3
- package/dist/runtime/server/utils/page-rows.d.ts +2 -0
- package/dist/runtime/server/utils/page-rows.js +42 -29
- package/dist/runtime/server/utils/permissions.d.ts +14 -0
- package/dist/runtime/server/utils/permissions.js +43 -0
- package/dist/runtime/server/utils/presets.d.ts +18 -0
- package/dist/runtime/server/utils/presets.js +68 -0
- package/dist/runtime/server/utils/preview-links.d.ts +207 -0
- package/dist/runtime/server/utils/preview-links.js +161 -0
- package/dist/runtime/server/utils/redirects.d.ts +31 -0
- package/dist/runtime/server/utils/redirects.js +240 -0
- package/dist/runtime/server/utils/registry.js +4 -1
- package/dist/runtime/server/utils/relations.d.ts +8 -0
- package/dist/runtime/server/utils/relations.js +25 -6
- package/dist/runtime/server/utils/require-admin.d.ts +0 -1
- package/dist/runtime/server/utils/require-admin.js +4 -8
- package/dist/runtime/server/utils/search.d.ts +1 -0
- package/dist/runtime/server/utils/search.js +44 -19
- package/dist/runtime/server/utils/single-row.d.ts +3 -0
- package/dist/runtime/server/utils/single-row.js +4 -0
- package/dist/runtime/server/utils/site.d.ts +23 -0
- package/dist/runtime/server/utils/site.js +79 -0
- package/dist/runtime/server/utils/sitemap.d.ts +12 -0
- package/dist/runtime/server/utils/sitemap.js +109 -0
- package/dist/runtime/server/utils/user-management.d.ts +4 -0
- package/dist/runtime/server/utils/user-management.js +20 -0
- package/dist/runtime/server/utils/users.d.ts +1 -1
- package/dist/runtime/server/utils/users.js +1 -1
- package/dist/runtime/server/utils/visibility.d.ts +1 -0
- package/dist/runtime/server/utils/visibility.js +6 -1
- package/dist/runtime/server/utils/webhooks.d.ts +24 -0
- package/dist/runtime/server/utils/webhooks.js +90 -0
- package/dist/runtime/shared/block-paths.d.ts +66 -0
- package/dist/runtime/shared/block-paths.js +310 -0
- package/dist/runtime/shared/block-picker.d.ts +18 -0
- package/dist/runtime/shared/block-picker.js +31 -0
- package/dist/runtime/shared/block-signature.d.ts +4 -0
- package/dist/runtime/shared/block-signature.js +46 -0
- package/dist/runtime/shared/clipboard.d.ts +31 -0
- package/dist/runtime/shared/clipboard.js +206 -0
- package/dist/runtime/shared/conditions.d.ts +36 -0
- package/dist/runtime/shared/conditions.js +100 -0
- package/dist/runtime/shared/content-routes.d.ts +42 -0
- package/dist/runtime/shared/content-routes.js +237 -0
- package/dist/runtime/shared/duplicate.js +2 -1
- package/dist/runtime/shared/editor-layout.d.ts +18 -0
- package/dist/runtime/shared/editor-layout.js +9 -0
- package/dist/runtime/shared/field-options.d.ts +21 -0
- package/dist/runtime/shared/field-options.js +90 -0
- package/dist/runtime/shared/graphql-sdl.d.ts +1 -0
- package/dist/runtime/shared/graphql-sdl.js +50 -26
- package/dist/runtime/shared/history.d.ts +27 -0
- package/dist/runtime/shared/history.js +123 -0
- package/dist/runtime/shared/hooks.d.ts +45 -0
- package/dist/runtime/shared/hooks.js +28 -0
- package/dist/runtime/shared/index.d.ts +90 -21
- package/dist/runtime/shared/index.js +121 -37
- package/dist/runtime/shared/inline-text.d.ts +38 -0
- package/dist/runtime/shared/inline-text.js +85 -0
- package/dist/runtime/shared/layout.d.ts +2 -1
- package/dist/runtime/shared/layout.js +3 -0
- package/dist/runtime/shared/links.d.ts +48 -0
- package/dist/runtime/shared/links.js +155 -0
- package/dist/runtime/shared/list-filters.d.ts +2 -0
- package/dist/runtime/shared/list-filters.js +2 -0
- package/dist/runtime/shared/media-focal.d.ts +30 -0
- package/dist/runtime/shared/media-focal.js +52 -0
- package/dist/runtime/shared/migrations-dir.d.ts +14 -0
- package/dist/runtime/shared/migrations-dir.js +48 -2
- package/dist/runtime/shared/presets.d.ts +67 -0
- package/dist/runtime/shared/presets.js +127 -0
- package/dist/runtime/shared/preview-links.d.ts +64 -0
- package/dist/runtime/shared/preview-links.js +54 -0
- package/dist/runtime/shared/preview.d.ts +124 -21
- package/dist/runtime/shared/preview.js +419 -81
- package/dist/runtime/shared/redirects.d.ts +75 -0
- package/dist/runtime/shared/redirects.js +230 -0
- package/dist/runtime/shared/roles.d.ts +57 -0
- package/dist/runtime/shared/roles.js +293 -0
- package/dist/runtime/shared/save-state.d.ts +8 -0
- package/dist/runtime/shared/save-state.js +15 -0
- package/dist/runtime/shared/search.d.ts +16 -1
- package/dist/runtime/shared/search.js +41 -7
- package/dist/runtime/shared/seo.d.ts +167 -0
- package/dist/runtime/shared/seo.js +335 -0
- package/dist/runtime/shared/transfer.js +2 -1
- package/dist/runtime/shared/translations.d.ts +29 -0
- package/dist/runtime/shared/translations.js +123 -0
- package/dist/runtime/shared/users.d.ts +1 -1
- package/dist/runtime/shared/validation.d.ts +23 -1
- package/dist/runtime/shared/validation.js +214 -64
- package/dist/runtime/webhooks.d.ts +33 -0
- package/dist/runtime/webhooks.js +57 -0
- package/dist/types.d.mts +5 -1
- package/package.json +6 -2
- package/dist/runtime/app/components/cms/BlockOutline.vue +0 -88
- package/dist/runtime/app/components/cms/BlockPalette.vue +0 -31
- package/dist/runtime/app/components/cms/SettingsModal.d.vue.ts +0 -12
- package/dist/runtime/app/components/cms/SettingsModal.vue +0 -126
- package/dist/runtime/app/components/cms/SettingsModal.vue.d.ts +0 -12
- package/dist/runtime/app/composables/cms-field-focus.d.ts +0 -4
- package/dist/runtime/app/composables/cms-field-focus.js +0 -20
|
@@ -22,28 +22,46 @@ import { useRuntimeConfig } from "#imports";
|
|
|
22
22
|
import {
|
|
23
23
|
CONTENT_SLUG_FIELD,
|
|
24
24
|
CONTENT_PUBLISHED_AT_FIELD,
|
|
25
|
+
contentItemPath,
|
|
26
|
+
contentItemPaths,
|
|
27
|
+
contentRouteLocales,
|
|
25
28
|
decodeTranslatableMedia,
|
|
26
29
|
entryFieldsFor,
|
|
30
|
+
blockFieldsDeep,
|
|
31
|
+
blocksFieldPaths,
|
|
27
32
|
hasTranslatableBlockFields,
|
|
33
|
+
isExternalLinkUrl,
|
|
28
34
|
isMultiValueField,
|
|
29
35
|
isPrivateField,
|
|
36
|
+
isRoutedContent,
|
|
37
|
+
isStringListField,
|
|
30
38
|
isTranslatableMediaField,
|
|
39
|
+
linkHref,
|
|
40
|
+
linkLabelText,
|
|
41
|
+
localeText,
|
|
31
42
|
localizeBlocks,
|
|
43
|
+
mapBlocks,
|
|
32
44
|
mediaPublicUrl,
|
|
33
45
|
mediaTypeFor,
|
|
34
46
|
pickTranslatedMedia,
|
|
47
|
+
previewGrantAllows,
|
|
35
48
|
publicBlocks,
|
|
49
|
+
readLinkValue,
|
|
50
|
+
relationTarget,
|
|
36
51
|
translatableFieldKeys
|
|
37
52
|
} from "../../shared/index.js";
|
|
38
53
|
import {
|
|
54
|
+
SITE_QUERY_FIELD,
|
|
39
55
|
blockTypeName,
|
|
40
56
|
blocksFieldTypeName,
|
|
41
57
|
renderGraphqlSdl,
|
|
42
58
|
typeName
|
|
43
59
|
} from "../../shared/graphql-sdl.js";
|
|
44
60
|
import { normalizeTimestampFields } from "../../shared/timestamps.js";
|
|
61
|
+
import { findContentByPath } from "./content-routes.js";
|
|
45
62
|
import { useMediaIndex } from "./media-index.js";
|
|
46
63
|
import { readPages } from "./page-storage.js";
|
|
64
|
+
import { readSiteSettings } from "./site.js";
|
|
47
65
|
import {
|
|
48
66
|
isListFilterOperator,
|
|
49
67
|
joinListCondition,
|
|
@@ -51,7 +69,8 @@ import {
|
|
|
51
69
|
listFilterValues
|
|
52
70
|
} from "./list-filter.js";
|
|
53
71
|
import { getContentI18n, resolveTable, tableColumns } from "./registry.js";
|
|
54
|
-
import {
|
|
72
|
+
import { singleRowFirst } from "./single-row.js";
|
|
73
|
+
import { visibilityConditions, visibleOrPreviewConditions } from "./visibility.js";
|
|
55
74
|
const MAX_LIMIT = 100;
|
|
56
75
|
const DEFAULT_LIMIT = 50;
|
|
57
76
|
const LOCALE = Symbol("locale");
|
|
@@ -98,6 +117,12 @@ function tableFor(name) {
|
|
|
98
117
|
function publishedFilter(entry, table) {
|
|
99
118
|
return visibilityConditions(entry, tableColumns(table));
|
|
100
119
|
}
|
|
120
|
+
function previewItemId(ctx, name) {
|
|
121
|
+
return previewGrantAllows(ctx.preview, name) ? ctx.preview.itemId : void 0;
|
|
122
|
+
}
|
|
123
|
+
function singleItemFilter(entry, table, ctx, name) {
|
|
124
|
+
return visibleOrPreviewConditions(entry, tableColumns(table), previewItemId(ctx, name));
|
|
125
|
+
}
|
|
101
126
|
function localeOf(parent) {
|
|
102
127
|
return parent[LOCALE] ?? getContentI18n().defaultLocale;
|
|
103
128
|
}
|
|
@@ -111,6 +136,23 @@ function resolveLocaleArg(locale) {
|
|
|
111
136
|
}
|
|
112
137
|
return String(locale);
|
|
113
138
|
}
|
|
139
|
+
function linkSource(value, locale) {
|
|
140
|
+
const link = readLinkValue(value);
|
|
141
|
+
if (!link || !link.url && !(link.entry && link.id)) return null;
|
|
142
|
+
return { link, locale };
|
|
143
|
+
}
|
|
144
|
+
function blockLinks(field, value, locale) {
|
|
145
|
+
return mapBlocks(field, value, (item, block) => {
|
|
146
|
+
const keys = Object.entries(block?.fields ?? {}).filter(([, blockField]) => blockField.type === "link").map(([key]) => key);
|
|
147
|
+
if (!keys.length) return item;
|
|
148
|
+
const resolved = { ...item };
|
|
149
|
+
for (const key of keys) resolved[key] = linkSource(resolved[key], locale);
|
|
150
|
+
return resolved;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function hasBlockLinks(field) {
|
|
154
|
+
return blockFieldsDeep(field).some((blockField) => blockField.type === "link");
|
|
155
|
+
}
|
|
114
156
|
function localizeRow(entry, row, locale) {
|
|
115
157
|
const { defaultLocale } = getContentI18n();
|
|
116
158
|
const result = normalizeTimestampFields({ ...row, [LOCALE]: locale });
|
|
@@ -125,9 +167,15 @@ function localizeRow(entry, row, locale) {
|
|
|
125
167
|
result[key] = value?.[locale] ?? value?.[defaultLocale] ?? null;
|
|
126
168
|
}
|
|
127
169
|
for (const [key, field] of Object.entries(fields)) {
|
|
128
|
-
if (isPrivateField(field)
|
|
170
|
+
if (isPrivateField(field)) continue;
|
|
171
|
+
if (field.type === "link") {
|
|
172
|
+
result[key] = linkSource(result[key], locale);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (field.type !== "blocks") continue;
|
|
129
176
|
const visible = publicBlocks(field, result[key]);
|
|
130
|
-
|
|
177
|
+
const localized = hasTranslatableBlockFields(field) ? localizeBlocks(field, visible, locale, defaultLocale) : visible;
|
|
178
|
+
result[key] = hasBlockLinks(field) ? blockLinks(field, localized, locale) : localized;
|
|
131
179
|
}
|
|
132
180
|
return result;
|
|
133
181
|
}
|
|
@@ -234,8 +282,8 @@ async function resolveMedia(ctx, key) {
|
|
|
234
282
|
if (isLocalMedia()) {
|
|
235
283
|
const file = (await useMediaIndex()).get(key);
|
|
236
284
|
if (!file) return null;
|
|
237
|
-
const
|
|
238
|
-
return mediaObject(key, { ...file,
|
|
285
|
+
const meta = await loadMediaMeta(ctx).load(key);
|
|
286
|
+
return mediaObject(key, { ...file, ...meta });
|
|
239
287
|
}
|
|
240
288
|
const row = await loadMedia(ctx).load(key);
|
|
241
289
|
return row ? mediaObject(key, row) : null;
|
|
@@ -261,9 +309,9 @@ function loadManyToMany(ctx, name, key, field) {
|
|
|
261
309
|
`m2m:${name}:${key}`,
|
|
262
310
|
async (sourceIds) => {
|
|
263
311
|
const config = cmsConfig;
|
|
264
|
-
const targetEntry = config[field
|
|
312
|
+
const targetEntry = config[relationTarget(field)];
|
|
265
313
|
const join = cmsTables[`${name}_${key}`];
|
|
266
|
-
const target = tableFor(field
|
|
314
|
+
const target = tableFor(relationTarget(field));
|
|
267
315
|
const joinCols = tableColumns(join);
|
|
268
316
|
const rows = await useDb().select({ sourceId: joinCols.sourceId, target }).from(join).innerJoin(target, eq(joinCols.targetId, tableColumns(target).id)).where(
|
|
269
317
|
and(inArray(joinCols.sourceId, sourceIds), ...publishedFilter(targetEntry, target))
|
|
@@ -293,14 +341,47 @@ function loadMedia(ctx) {
|
|
|
293
341
|
);
|
|
294
342
|
});
|
|
295
343
|
}
|
|
296
|
-
function
|
|
297
|
-
return getLoader(ctx, "
|
|
344
|
+
function loadMediaMeta(ctx) {
|
|
345
|
+
return getLoader(ctx, "mediaMeta", async (keys) => {
|
|
298
346
|
const media = cmsTables.cms_media;
|
|
299
347
|
const columns = tableColumns(media);
|
|
300
|
-
const rows = await useDb().select({
|
|
301
|
-
|
|
348
|
+
const rows = await useDb().select({
|
|
349
|
+
key: columns.key,
|
|
350
|
+
alt: columns.alt,
|
|
351
|
+
focalX: columns.focalX,
|
|
352
|
+
focalY: columns.focalY
|
|
353
|
+
}).from(media).where(inArray(columns.key, keys));
|
|
354
|
+
return new Map(
|
|
355
|
+
rows.map((row) => [
|
|
356
|
+
row.key,
|
|
357
|
+
{
|
|
358
|
+
alt: row.alt ?? null,
|
|
359
|
+
focalX: row.focalX ?? null,
|
|
360
|
+
focalY: row.focalY ?? null
|
|
361
|
+
}
|
|
362
|
+
])
|
|
363
|
+
);
|
|
302
364
|
});
|
|
303
365
|
}
|
|
366
|
+
async function resolveLinkHref(ctx, source) {
|
|
367
|
+
const config = cmsConfig;
|
|
368
|
+
const { link, locale } = source;
|
|
369
|
+
const entry = link.entry ? config[link.entry] : void 0;
|
|
370
|
+
if (link.url || !link.entry || !link.id || !isRoutedContent(entry))
|
|
371
|
+
return linkHref(config, link, locale);
|
|
372
|
+
const target = await loadById(ctx, link.entry).load(link.id);
|
|
373
|
+
return target ? linkHref(config, link, locale, target) : null;
|
|
374
|
+
}
|
|
375
|
+
function linkResolvers() {
|
|
376
|
+
return {
|
|
377
|
+
href: (source, _args, ctx) => resolveLinkHref(ctx, source),
|
|
378
|
+
label: (source) => linkLabelText(source.link.label, source.locale, getContentI18n().defaultLocale),
|
|
379
|
+
newTab: (source) => !!source.link.newTab,
|
|
380
|
+
external: (source) => isExternalLinkUrl(source.link.url),
|
|
381
|
+
entry: (source) => source.link.url ? null : source.link.entry ?? null,
|
|
382
|
+
id: (source) => source.link.url ? null : source.link.id ?? null
|
|
383
|
+
};
|
|
384
|
+
}
|
|
304
385
|
function mediaObject(key, row) {
|
|
305
386
|
return {
|
|
306
387
|
key,
|
|
@@ -311,6 +392,8 @@ function mediaObject(key, row) {
|
|
|
311
392
|
size: row?.size ?? null,
|
|
312
393
|
width: row?.width ?? null,
|
|
313
394
|
height: row?.height ?? null,
|
|
395
|
+
focalX: row?.focalX ?? null,
|
|
396
|
+
focalY: row?.focalY ?? null,
|
|
314
397
|
type: mediaTypeFor(row?.mime, key)
|
|
315
398
|
};
|
|
316
399
|
}
|
|
@@ -321,25 +404,33 @@ function entryResolvers(config, name, entry) {
|
|
|
321
404
|
if (field.type === "relation" && field.cardinality === "many-to-many") {
|
|
322
405
|
resolvers[key] = async (parent, _args, ctx) => {
|
|
323
406
|
const rows = await loadManyToMany(ctx, name, key, field).load(parent.id);
|
|
324
|
-
return (rows ?? []).map(
|
|
407
|
+
return (rows ?? []).map(
|
|
408
|
+
(row) => localizeRow(config[relationTarget(field)], row, localeOf(parent))
|
|
409
|
+
);
|
|
325
410
|
};
|
|
326
411
|
} else if (field.type === "relation") {
|
|
327
412
|
resolvers[key] = async (parent, _args, ctx) => {
|
|
328
413
|
const id = parent[key];
|
|
329
414
|
if (id == null) return null;
|
|
330
|
-
const row = await loadById(ctx, field
|
|
331
|
-
return row ? localizeRow(config[field
|
|
415
|
+
const row = await loadById(ctx, relationTarget(field)).load(id);
|
|
416
|
+
return row ? localizeRow(config[relationTarget(field)], row, localeOf(parent)) : null;
|
|
332
417
|
};
|
|
333
418
|
} else if (field.type === "media") {
|
|
334
419
|
resolvers[key] = (parent, _args, ctx) => resolveMedia(ctx, parent[key]);
|
|
420
|
+
} else if (isStringListField(field)) {
|
|
421
|
+
resolvers[key] = (parent) => Array.isArray(parent[key]) ? parent[key] : [];
|
|
335
422
|
}
|
|
336
423
|
}
|
|
424
|
+
if (isRoutedContent(entry)) {
|
|
425
|
+
resolvers.path = (parent) => contentItemPath(entry, parent, localeOf(parent));
|
|
426
|
+
resolvers.paths = (parent) => contentItemPaths(entry, parent, contentRouteLocales(getContentI18n()));
|
|
427
|
+
}
|
|
337
428
|
return resolvers;
|
|
338
429
|
}
|
|
339
|
-
function blockResolvers(name,
|
|
430
|
+
function blockResolvers(name, schemaPath, field) {
|
|
340
431
|
const resolvers = {};
|
|
341
|
-
resolvers[blocksFieldTypeName(name,
|
|
342
|
-
__resolveType: (value) => blockTypeName(name,
|
|
432
|
+
resolvers[blocksFieldTypeName(name, schemaPath)] = {
|
|
433
|
+
__resolveType: (value) => blockTypeName(name, schemaPath, String(value.type))
|
|
343
434
|
};
|
|
344
435
|
for (const [blockName, block] of Object.entries(field.blocks ?? {})) {
|
|
345
436
|
const mediaFields = Object.entries(block.fields).filter(([, f]) => f.type === "media");
|
|
@@ -348,7 +439,7 @@ function blockResolvers(name, key, field) {
|
|
|
348
439
|
for (const [blockFieldKey] of mediaFields) {
|
|
349
440
|
fieldLevel[blockFieldKey] = (parent, _args, ctx) => resolveMedia(ctx, parent[blockFieldKey]);
|
|
350
441
|
}
|
|
351
|
-
resolvers[blockTypeName(name,
|
|
442
|
+
resolvers[blockTypeName(name, schemaPath, blockName)] = fieldLevel;
|
|
352
443
|
}
|
|
353
444
|
return resolvers;
|
|
354
445
|
}
|
|
@@ -357,14 +448,24 @@ export function buildCmsSchema() {
|
|
|
357
448
|
const entries = Object.entries(config);
|
|
358
449
|
const queryResolvers = {};
|
|
359
450
|
const typeResolvers = {};
|
|
451
|
+
queryResolvers[SITE_QUERY_FIELD] = async (_, args, ctx) => {
|
|
452
|
+
const locale = resolveLocaleArg(args.locale);
|
|
453
|
+
const { defaultLocale } = getContentI18n();
|
|
454
|
+
const settings = await readSiteSettings();
|
|
455
|
+
return {
|
|
456
|
+
name: localeText(settings.name, locale, defaultLocale),
|
|
457
|
+
titleTemplate: settings.titleTemplate,
|
|
458
|
+
description: localeText(settings.description, locale, defaultLocale),
|
|
459
|
+
image: await resolveMedia(ctx, settings.image),
|
|
460
|
+
hidden: settings.hidden
|
|
461
|
+
};
|
|
462
|
+
};
|
|
360
463
|
for (const [name, entry] of entries) {
|
|
361
464
|
const gqlType = typeName(name);
|
|
362
465
|
const fieldLevel = entryResolvers(config, name, entry);
|
|
363
466
|
if (Object.keys(fieldLevel).length) typeResolvers[gqlType] = fieldLevel;
|
|
364
|
-
for (const
|
|
365
|
-
|
|
366
|
-
Object.assign(typeResolvers, blockResolvers(name, key, field));
|
|
367
|
-
}
|
|
467
|
+
for (const { field, schemaPath } of blocksFieldPaths(entryFieldsFor(entry)))
|
|
468
|
+
Object.assign(typeResolvers, blockResolvers(name, schemaPath, field));
|
|
368
469
|
if (entry.kind === "page") {
|
|
369
470
|
queryResolvers[name] = async (_, args) => {
|
|
370
471
|
const locale = resolveLocaleArg(args.locale);
|
|
@@ -383,7 +484,7 @@ export function buildCmsSchema() {
|
|
|
383
484
|
const locale = resolveLocaleArg(args.locale);
|
|
384
485
|
const table = tableFor(name);
|
|
385
486
|
const published = publishedFilter(entry, table);
|
|
386
|
-
const [row] = await useDb().select().from(table).where(published.length ? and(...published) : void 0).limit(1);
|
|
487
|
+
const [row] = await useDb().select().from(table).where(published.length ? and(...published) : void 0).orderBy(singleRowFirst(tableColumns(table).id, entry.id)).limit(1);
|
|
387
488
|
return row ? localizeRow(entry, row, locale) : null;
|
|
388
489
|
};
|
|
389
490
|
continue;
|
|
@@ -400,18 +501,32 @@ export function buildCmsSchema() {
|
|
|
400
501
|
const rows = await useDb().select().from(table).where(where.length ? and(...where) : void 0).orderBy(...sortOrder(entry, table, args.sort)).limit(limit).offset(offset);
|
|
401
502
|
return rows.map((row) => localizeRow(entry, row, locale));
|
|
402
503
|
};
|
|
403
|
-
queryResolvers[`${name}ById`] = async (_, args) => {
|
|
504
|
+
queryResolvers[`${name}ById`] = async (_, args, ctx) => {
|
|
404
505
|
const locale = resolveLocaleArg(args.locale);
|
|
405
506
|
const table = tableFor(name);
|
|
406
|
-
const [row] = await useDb().select().from(table).where(
|
|
507
|
+
const [row] = await useDb().select().from(table).where(
|
|
508
|
+
and(
|
|
509
|
+
eq(tableColumns(table).id, args.id),
|
|
510
|
+
...singleItemFilter(entry, table, ctx, name)
|
|
511
|
+
)
|
|
512
|
+
).limit(1);
|
|
407
513
|
return row ? localizeRow(entry, row, locale) : null;
|
|
408
514
|
};
|
|
409
515
|
if (entry.kind === "content") {
|
|
410
|
-
queryResolvers[`${name}BySlug`] = async (_, args) => {
|
|
516
|
+
queryResolvers[`${name}BySlug`] = async (_, args, ctx) => {
|
|
411
517
|
const locale = resolveLocaleArg(args.locale);
|
|
412
518
|
const table = tableFor(name);
|
|
413
519
|
const slug = tableColumns(table)[CONTENT_SLUG_FIELD];
|
|
414
|
-
const [row] = await useDb().select().from(table).where(and(eq(slug, args.slug), ...
|
|
520
|
+
const [row] = await useDb().select().from(table).where(and(eq(slug, args.slug), ...singleItemFilter(entry, table, ctx, name))).limit(1);
|
|
521
|
+
return row ? localizeRow(entry, row, locale) : null;
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (isRoutedContent(entry)) {
|
|
525
|
+
queryResolvers[`${name}ByPath`] = async (_, args, ctx) => {
|
|
526
|
+
const locale = resolveLocaleArg(args.locale);
|
|
527
|
+
const row = await findContentByPath(name, args.path, locale, {
|
|
528
|
+
previewId: previewItemId(ctx, name)
|
|
529
|
+
});
|
|
415
530
|
return row ? localizeRow(entry, row, locale) : null;
|
|
416
531
|
};
|
|
417
532
|
}
|
|
@@ -435,11 +550,12 @@ export function buildCmsSchema() {
|
|
|
435
550
|
typeDefs: renderGraphqlSdl(config),
|
|
436
551
|
resolvers: {
|
|
437
552
|
JSON: jsonScalar,
|
|
553
|
+
CmsLink: linkResolvers(),
|
|
438
554
|
Query: queryResolvers,
|
|
439
555
|
...typeResolvers
|
|
440
556
|
}
|
|
441
557
|
});
|
|
442
558
|
}
|
|
443
|
-
export function createGraphqlContext() {
|
|
444
|
-
return { loaders: /* @__PURE__ */ new Map() };
|
|
559
|
+
export function createGraphqlContext(preview = null) {
|
|
560
|
+
return { loaders: /* @__PURE__ */ new Map(), preview };
|
|
445
561
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import type { CmsEntryChange, CmsHookName, CmsHookUser, CmsMediaChange, CmsRuntimeHooks } from '../../shared/hooks.js';
|
|
3
|
+
import type { CmsSessionUser } from '../../shared/users.js';
|
|
4
|
+
type HookCallback = (...args: unknown[]) => unknown;
|
|
5
|
+
export interface CmsHookHost {
|
|
6
|
+
callHookWith: (caller: (hooks: HookCallback[], args: unknown[]) => Promise<void>, name: string, ...args: unknown[]) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export type CmsHookLogger = (message: string, error: unknown) => void;
|
|
9
|
+
export declare function hookUser(user: CmsSessionUser): CmsHookUser;
|
|
10
|
+
export declare function runHooksIsolated(name: string, hooks: HookCallback[], args: unknown[], log?: CmsHookLogger): Promise<void>;
|
|
11
|
+
export declare function dispatchCmsHook<Name extends CmsHookName>(host: () => CmsHookHost, event: H3Event, name: Name, payload: Parameters<CmsRuntimeHooks[Name]>[0], log?: CmsHookLogger): Promise<void>;
|
|
12
|
+
export declare function emitEntryChange(event: H3Event, user: CmsSessionUser, change: Omit<CmsEntryChange, 'user' | 'at' | 'path' | 'status' | 'item'> & Partial<Pick<CmsEntryChange, 'path' | 'status' | 'item'>>): Promise<void>;
|
|
13
|
+
export declare function emitMediaChange(event: H3Event, user: CmsSessionUser, change: Pick<CmsMediaChange, 'action' | 'keys'> & Partial<Pick<CmsMediaChange, 'folder' | 'from'>>): Promise<void>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useNitroApp } from "nitropack/runtime";
|
|
2
|
+
import { CMS_ENTRY_CHANGE_HOOK, CMS_MEDIA_CHANGE_HOOK } from "../../shared/hooks.js";
|
|
3
|
+
const logHookError = (message, error) => console.error(message, error);
|
|
4
|
+
export function hookUser(user) {
|
|
5
|
+
return {
|
|
6
|
+
id: user.id ?? null,
|
|
7
|
+
email: user.email,
|
|
8
|
+
name: user.name ?? null,
|
|
9
|
+
role: user.role ?? (user.id ? "admin" : "superadmin")
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function runHooksIsolated(name, hooks, args, log = logHookError) {
|
|
13
|
+
return Promise.all(
|
|
14
|
+
hooks.map(
|
|
15
|
+
(hook) => Promise.resolve().then(() => hook(...args)).catch((error) => {
|
|
16
|
+
log(`[nuxt-cms] a '${name}' hook failed:`, error);
|
|
17
|
+
})
|
|
18
|
+
)
|
|
19
|
+
).then(() => void 0);
|
|
20
|
+
}
|
|
21
|
+
export function dispatchCmsHook(host, event, name, payload, log = logHookError) {
|
|
22
|
+
const context = { event };
|
|
23
|
+
const task = Promise.resolve().then(
|
|
24
|
+
() => host().callHookWith(
|
|
25
|
+
(hooks, args) => runHooksIsolated(name, hooks, args, log),
|
|
26
|
+
name,
|
|
27
|
+
payload,
|
|
28
|
+
context
|
|
29
|
+
)
|
|
30
|
+
).catch((error) => {
|
|
31
|
+
log(`[nuxt-cms] the '${name}' hooks failed:`, error);
|
|
32
|
+
});
|
|
33
|
+
const waitUntil = event.waitUntil;
|
|
34
|
+
if (typeof waitUntil === "function") {
|
|
35
|
+
try {
|
|
36
|
+
waitUntil.call(event, task);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log(`[nuxt-cms] waitUntil failed for '${name}':`, error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return task;
|
|
42
|
+
}
|
|
43
|
+
function cloneItem(item) {
|
|
44
|
+
try {
|
|
45
|
+
return structuredClone(item);
|
|
46
|
+
} catch {
|
|
47
|
+
return { ...item };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function hookHost() {
|
|
51
|
+
return useNitroApp().hooks;
|
|
52
|
+
}
|
|
53
|
+
export function emitEntryChange(event, user, change) {
|
|
54
|
+
return dispatchCmsHook(hookHost, event, CMS_ENTRY_CHANGE_HOOK, {
|
|
55
|
+
path: null,
|
|
56
|
+
status: null,
|
|
57
|
+
...change,
|
|
58
|
+
item: change.item ? cloneItem(change.item) : null,
|
|
59
|
+
user: hookUser(user),
|
|
60
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function emitMediaChange(event, user, change) {
|
|
64
|
+
return dispatchCmsHook(hookHost, event, CMS_MEDIA_CHANGE_HOOK, {
|
|
65
|
+
folder: null,
|
|
66
|
+
from: null,
|
|
67
|
+
...change,
|
|
68
|
+
user: hookUser(user),
|
|
69
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
70
|
+
});
|
|
71
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { SQLiteTable } from 'drizzle-orm/sqlite-core';
|
|
2
2
|
import type { CmsDb } from '#cms-db';
|
|
3
|
-
import type { CmsEntry, CmsI18n } from '../../shared/index.js';
|
|
3
|
+
import type { CmsConfig, CmsEntry, CmsI18n } from '../../shared/index.js';
|
|
4
4
|
import type { CmsImportAction, CmsImportIssue, CmsImportMode, CmsImportPreview, CmsImportSourceRow, CmsTransferFormat } from '../../shared/transfer.js';
|
|
5
5
|
import type { MediaLookup } from './media-references.js';
|
|
6
|
+
import type { CmsRedirectPlan } from '../../shared/index.js';
|
|
6
7
|
type Row = Record<string, unknown>;
|
|
7
8
|
export interface PreparedImportRow {
|
|
8
9
|
index: number;
|
|
@@ -18,8 +19,10 @@ export interface ImportContext {
|
|
|
18
19
|
table: SQLiteTable;
|
|
19
20
|
mode: CmsImportMode;
|
|
20
21
|
media: MediaLookup | null;
|
|
22
|
+
canPublish?: boolean;
|
|
21
23
|
}
|
|
22
|
-
export declare function
|
|
24
|
+
export declare function existingImportIds(db: CmsDb, table: SQLiteTable, rows: CmsImportSourceRow[]): Promise<Set<string>>;
|
|
25
|
+
export declare function validateImportRows(entry: CmsEntry, rows: CmsImportSourceRow[], i18n: CmsI18n, isCreate?: (id: string | null) => boolean, config?: CmsConfig): PreparedImportRow[];
|
|
23
26
|
export declare function checkImportRows(rows: PreparedImportRow[], context: ImportContext): Promise<PreparedImportRow[]>;
|
|
24
27
|
export declare function importPreview(entry: CmsEntry, rows: PreparedImportRow[], options: {
|
|
25
28
|
format: CmsTransferFormat;
|
|
@@ -27,5 +30,7 @@ export declare function importPreview(entry: CmsEntry, rows: PreparedImportRow[]
|
|
|
27
30
|
defaultLocale: string;
|
|
28
31
|
errors?: string[];
|
|
29
32
|
}): CmsImportPreview;
|
|
33
|
+
export declare function assignImportIds(entry: CmsEntry, rows: PreparedImportRow[]): PreparedImportRow[];
|
|
30
34
|
export declare function importWriteStatements(db: CmsDb, name: string, entry: CmsEntry, table: SQLiteTable, rows: PreparedImportRow[]): PromiseLike<unknown>[];
|
|
35
|
+
export declare function planImportRedirects(db: CmsDb, entry: CmsEntry, table: SQLiteTable, rows: PreparedImportRow[]): Promise<CmsRedirectPlan | null>;
|
|
31
36
|
export {};
|
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import { eq, inArray } from "drizzle-orm";
|
|
1
|
+
import { eq, inArray, sql } from "drizzle-orm";
|
|
2
|
+
import {
|
|
3
|
+
isRoutedContent,
|
|
4
|
+
mergeContentMoves,
|
|
5
|
+
relationTarget,
|
|
6
|
+
rowAfterUpdate
|
|
7
|
+
} from "../../shared/index.js";
|
|
2
8
|
import { uniqueFieldKeys } from "../../shared/duplicate.js";
|
|
9
|
+
import {
|
|
10
|
+
changedImmutableKeys,
|
|
11
|
+
immutableFieldKeys,
|
|
12
|
+
isCaseInsensitiveUnique,
|
|
13
|
+
uniqueCompareValue,
|
|
14
|
+
withEntryDefaults
|
|
15
|
+
} from "../../shared/field-options.js";
|
|
3
16
|
import { IMPORT_ID_PATTERN, importIssuePath, importRowTitle } from "../../shared/transfer.js";
|
|
4
|
-
import { buildEntrySchema } from "../../shared/validation.js";
|
|
17
|
+
import { buildEntrySchema, validationMessages } from "../../shared/validation.js";
|
|
5
18
|
import { customId } from "./custom-id.js";
|
|
6
19
|
import { mediaReferences } from "./media-references.js";
|
|
7
20
|
import {
|
|
@@ -11,11 +24,18 @@ import {
|
|
|
11
24
|
withTimestamps,
|
|
12
25
|
withUpdatedAt
|
|
13
26
|
} from "./registry.js";
|
|
27
|
+
import { contentMovesOf, planContentRedirects } from "./redirects.js";
|
|
14
28
|
import { manyToManyStatements, splitRelationValues } from "./relations.js";
|
|
15
29
|
import { chunks, KEY_CHUNK } from "./write-statements.js";
|
|
16
30
|
const META_KEYS = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt"]);
|
|
17
|
-
export function
|
|
18
|
-
const
|
|
31
|
+
export async function existingImportIds(db, table, rows) {
|
|
32
|
+
const ids = rows.flatMap(
|
|
33
|
+
(row) => typeof row.values.id === "string" && IMPORT_ID_PATTERN.test(row.values.id) ? [row.values.id] : []
|
|
34
|
+
);
|
|
35
|
+
return ids.length ? existingIds(db, table, ids) : /* @__PURE__ */ new Set();
|
|
36
|
+
}
|
|
37
|
+
export function validateImportRows(entry, rows, i18n, isCreate = () => true, config) {
|
|
38
|
+
const schema = buildEntrySchema({ ...entry, config }, i18n);
|
|
19
39
|
return rows.map((row) => {
|
|
20
40
|
const errors = [...row.errors];
|
|
21
41
|
const rawId = row.values.id;
|
|
@@ -28,9 +48,10 @@ export function validateImportRows(entry, rows, i18n) {
|
|
|
28
48
|
message: "Invalid id: use letters, numbers, _ and -, up to 128 characters"
|
|
29
49
|
});
|
|
30
50
|
}
|
|
31
|
-
const
|
|
51
|
+
const given = Object.fromEntries(
|
|
32
52
|
Object.entries(row.values).filter(([key]) => !META_KEYS.has(key))
|
|
33
53
|
);
|
|
54
|
+
const input = isCreate(id) ? withEntryDefaults(entry.fields, given, i18n) : given;
|
|
34
55
|
const result = schema.safeParse(input);
|
|
35
56
|
if (!result.success) {
|
|
36
57
|
const reported = new Set(errors.map((issue) => issue.path));
|
|
@@ -82,16 +103,17 @@ async function checkIds(rows, context) {
|
|
|
82
103
|
async function checkRelations(rows, context) {
|
|
83
104
|
const fileIds = new Set(rows.flatMap((row) => row.id ? [row.id] : []));
|
|
84
105
|
for (const [key, field] of Object.entries(context.entry.fields)) {
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
const to = relationTarget(field);
|
|
107
|
+
if (field.type !== "relation" || !to) continue;
|
|
108
|
+
const target = resolveTable(to);
|
|
87
109
|
if (!target) continue;
|
|
88
110
|
const wanted = rows.flatMap((row) => relationIds(row.values?.[key]));
|
|
89
111
|
if (!wanted.length) continue;
|
|
90
112
|
const found = await existingIds(context.db, target, wanted);
|
|
91
|
-
if (
|
|
113
|
+
if (to === context.name) for (const id of fileIds) found.add(id);
|
|
92
114
|
for (const row of rows) {
|
|
93
115
|
const missing = relationIds(row.values?.[key]).filter((id) => !found.has(id));
|
|
94
|
-
if (missing.length) addError(row, key, `Unknown ${
|
|
116
|
+
if (missing.length) addError(row, key, `Unknown ${to} id: ${missing.join(", ")}`);
|
|
95
117
|
}
|
|
96
118
|
}
|
|
97
119
|
}
|
|
@@ -99,25 +121,45 @@ async function checkUnique(rows, context) {
|
|
|
99
121
|
const columns = context.table;
|
|
100
122
|
for (const key of uniqueFieldKeys(context.entry)) {
|
|
101
123
|
const column = columns[key];
|
|
124
|
+
const field = context.entry.fields[key];
|
|
102
125
|
if (!column) continue;
|
|
103
126
|
const owners = /* @__PURE__ */ new Map();
|
|
104
127
|
for (const row of rows) {
|
|
105
128
|
const value = row.values?.[key];
|
|
106
|
-
if (typeof value
|
|
107
|
-
const
|
|
129
|
+
if (!(typeof value === "string" && value || typeof value === "number")) continue;
|
|
130
|
+
const compared = uniqueCompareValue(field, value);
|
|
131
|
+
const owner = owners.get(compared);
|
|
108
132
|
if (owner) addError(row, key, `Same value as row ${owner.index}`);
|
|
109
|
-
else owners.set(
|
|
133
|
+
else owners.set(compared, row);
|
|
110
134
|
}
|
|
135
|
+
const lower = isCaseInsensitiveUnique(field);
|
|
111
136
|
for (const chunk of chunks([...owners.keys()], KEY_CHUNK)) {
|
|
112
|
-
const found = await context.db.select({ id: columns.id, value: column }).from(context.table).where(inArray(column, chunk));
|
|
137
|
+
const found = await context.db.select({ id: columns.id, value: column }).from(context.table).where(lower ? inArray(sql`lower(${column})`, chunk) : inArray(column, chunk));
|
|
113
138
|
for (const match of found) {
|
|
114
|
-
const row = owners.get(
|
|
139
|
+
const row = owners.get(uniqueCompareValue(field, match.value));
|
|
115
140
|
if (row && row.id !== String(match.id))
|
|
116
141
|
addError(row, key, "This value is already used by another entry");
|
|
117
142
|
}
|
|
118
143
|
}
|
|
119
144
|
}
|
|
120
145
|
}
|
|
146
|
+
async function checkImmutable(rows, context) {
|
|
147
|
+
const columns = context.table;
|
|
148
|
+
const keys = immutableFieldKeys(context.entry.fields).filter((key) => columns[key]);
|
|
149
|
+
const updated = rows.filter((row) => row.action === "update" && row.id && row.values);
|
|
150
|
+
if (!keys.length || !updated.length) return;
|
|
151
|
+
const saved = /* @__PURE__ */ new Map();
|
|
152
|
+
const selection = Object.fromEntries(keys.map((key) => [key, columns[key]]));
|
|
153
|
+
for (const chunk of chunks([...new Set(updated.map((row) => row.id))], KEY_CHUNK)) {
|
|
154
|
+
const found = await context.db.select({ ...selection, id: columns.id }).from(context.table).where(inArray(columns.id, chunk));
|
|
155
|
+
for (const match of found) saved.set(String(match.id), match);
|
|
156
|
+
}
|
|
157
|
+
const message = validationMessages().immutable;
|
|
158
|
+
for (const row of updated) {
|
|
159
|
+
for (const key of changedImmutableKeys(context.entry.fields, saved.get(row.id), row.values))
|
|
160
|
+
addError(row, key, message);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
121
163
|
async function checkMedia(rows, context) {
|
|
122
164
|
if (!context.media) return;
|
|
123
165
|
const references = new Map(
|
|
@@ -133,11 +175,37 @@ async function checkMedia(rows, context) {
|
|
|
133
175
|
}
|
|
134
176
|
}
|
|
135
177
|
}
|
|
178
|
+
async function publishedIds(db, table, ids) {
|
|
179
|
+
const columns = table;
|
|
180
|
+
const found = /* @__PURE__ */ new Set();
|
|
181
|
+
for (const chunk of chunks([...new Set(ids)], KEY_CHUNK)) {
|
|
182
|
+
const rows = await db.select({ id: columns.id, status: columns.status }).from(table).where(inArray(columns.id, chunk));
|
|
183
|
+
for (const row of rows) if (row.status === "published") found.add(String(row.id));
|
|
184
|
+
}
|
|
185
|
+
return found;
|
|
186
|
+
}
|
|
187
|
+
async function checkPublish(rows, context) {
|
|
188
|
+
if (context.canPublish !== false || !context.entry.drafts) return;
|
|
189
|
+
const permission = `${context.name}.publish`;
|
|
190
|
+
for (const row of rows) {
|
|
191
|
+
if (row.values?.status === "published")
|
|
192
|
+
addError(row, "status", `Publishing needs the ${permission} permission`);
|
|
193
|
+
}
|
|
194
|
+
const updated = rows.flatMap((row) => row.action === "update" && row.id ? [row.id] : []);
|
|
195
|
+
if (!updated.length) return;
|
|
196
|
+
const published = await publishedIds(context.db, context.table, updated);
|
|
197
|
+
for (const row of rows) {
|
|
198
|
+
if (row.action === "update" && row.id && published.has(row.id))
|
|
199
|
+
addError(row, "id", `Editing a published item needs the ${permission} permission`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
136
202
|
export async function checkImportRows(rows, context) {
|
|
137
203
|
await checkIds(rows, context);
|
|
138
204
|
await checkRelations(rows, context);
|
|
139
205
|
await checkUnique(rows, context);
|
|
206
|
+
await checkImmutable(rows, context);
|
|
140
207
|
await checkMedia(rows, context);
|
|
208
|
+
await checkPublish(rows, context);
|
|
141
209
|
return rows;
|
|
142
210
|
}
|
|
143
211
|
export function importPreview(entry, rows, options) {
|
|
@@ -165,6 +233,9 @@ function deferredSelfRelations(entry, name) {
|
|
|
165
233
|
([, field]) => field.type === "relation" && field.to === name && field.cardinality !== "many-to-many" && !field.required
|
|
166
234
|
).map(([key]) => key);
|
|
167
235
|
}
|
|
236
|
+
export function assignImportIds(entry, rows) {
|
|
237
|
+
return rows.map((row) => row.values && !row.id ? { ...row, id: customId(entry.id) } : row);
|
|
238
|
+
}
|
|
168
239
|
export function importWriteStatements(db, name, entry, table, rows) {
|
|
169
240
|
const idCol = table.id;
|
|
170
241
|
const created = new Set(
|
|
@@ -200,3 +271,26 @@ export function importWriteStatements(db, name, entry, table, rows) {
|
|
|
200
271
|
}
|
|
201
272
|
return [...main, ...later];
|
|
202
273
|
}
|
|
274
|
+
export async function planImportRedirects(db, entry, table, rows) {
|
|
275
|
+
if (!isRoutedContent(entry)) return null;
|
|
276
|
+
const updates = rows.filter((row) => row.action === "update" && row.values && row.id);
|
|
277
|
+
if (!updates.length) return null;
|
|
278
|
+
const idCol = table.id;
|
|
279
|
+
const before = /* @__PURE__ */ new Map();
|
|
280
|
+
for (const ids of chunks(
|
|
281
|
+
updates.map((row) => row.id),
|
|
282
|
+
KEY_CHUNK
|
|
283
|
+
)) {
|
|
284
|
+
const found = await db.select().from(table).where(inArray(idCol, ids));
|
|
285
|
+
for (const row of found) before.set(String(row.id), row);
|
|
286
|
+
}
|
|
287
|
+
const moves = [];
|
|
288
|
+
for (const row of updates) {
|
|
289
|
+
const existing = before.get(row.id);
|
|
290
|
+
if (!existing) continue;
|
|
291
|
+
const { values } = splitRelationValues(entry, encodeColumnValues(entry, row.values));
|
|
292
|
+
const after = rowAfterUpdate(existing, withContentDefaults(entry, values));
|
|
293
|
+
moves.push(contentMovesOf(entry, existing, after));
|
|
294
|
+
}
|
|
295
|
+
return planContentRedirects(mergeContentMoves(moves));
|
|
296
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MediaUsage } from '../../shared/index.js';
|
|
2
|
+
import type { MediaUsageSource } from './media-references.js';
|
|
3
|
+
export declare function collectLinkUsage(sources: MediaUsageSource[], keys: string[]): Record<string, MediaUsage[]>;
|
|
4
|
+
export declare function loadLinkUsage(keys: string[], include?: (name: string) => boolean): Promise<Record<string, MediaUsage[]>>;
|