includio-cms 0.25.0 → 0.27.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/API.md +97 -4
- package/CHANGELOG.md +118 -0
- package/DOCS.md +1 -1
- package/README.md +2 -0
- package/ROADMAP.md +14 -0
- package/dist/admin/auth-client.d.ts +42 -42
- package/dist/admin/client/account/lang.d.ts +1 -0
- package/dist/admin/client/account/lang.js +4 -2
- package/dist/admin/client/account/profile-section.svelte +2 -2
- package/dist/admin/client/account/security-section.svelte +27 -4
- package/dist/admin/client/account/sessions-section.svelte +1 -1
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
- package/dist/admin/client/admin/admin-layout.svelte +12 -2
- package/dist/admin/client/admin/admin-layout.svelte.d.ts +2 -1
- package/dist/admin/client/admin/dashboard-page.svelte +34 -10
- package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
- package/dist/admin/client/collection/collection-entries.svelte +52 -36
- package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection.svelte +28 -14
- package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
- package/dist/admin/client/collection/data-table.svelte +240 -130
- package/dist/admin/client/collection/data-table.svelte.d.ts +9 -0
- package/dist/admin/client/collection/date-cell.svelte +4 -4
- package/dist/admin/client/collection/row-actions.svelte +2 -1
- package/dist/admin/client/collection/sortable-header.svelte +33 -9
- package/dist/admin/client/collection/state-display.svelte +102 -0
- package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
- package/dist/admin/client/collection/status-badge.svelte +99 -11
- package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
- package/dist/admin/client/collection/table-pagination.svelte +21 -6
- package/dist/admin/client/collection/table-toolbar.svelte +105 -80
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
- package/dist/admin/client/entry/entry-form.svelte +36 -11
- package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry-header.svelte +22 -15
- package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry.svelte +269 -165
- package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
- package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
- package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
- package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
- package/dist/admin/client/entry/header/status-badge.svelte +60 -15
- package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
- package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
- package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
- package/dist/admin/client/entry/utils.d.ts +14 -0
- package/dist/admin/client/entry/utils.js +28 -0
- package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
- package/dist/admin/client/form/form-submissions.svelte +143 -194
- package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
- package/dist/admin/client/login/lang.d.ts +3 -0
- package/dist/admin/client/login/lang.js +10 -4
- package/dist/admin/client/login/login-form.svelte +8 -1
- package/dist/admin/client/login/reset-password-page.svelte +24 -3
- package/dist/admin/client/login/schema.d.ts +14 -2
- package/dist/admin/client/login/schema.js +19 -8
- package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
- package/dist/admin/client/media/media-page.svelte +1 -1
- package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
- package/dist/admin/client/shop/coupon-form.svelte +282 -138
- package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
- package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
- package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
- package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
- package/dist/admin/client/shop/coupon-schema.js +53 -0
- package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
- package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
- package/dist/admin/client/shop/refund-dialog.svelte +37 -1
- package/dist/admin/client/shop/refund-dialog.svelte.d.ts +3 -0
- package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
- package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
- package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
- package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
- package/dist/admin/client/shop/shop-order-detail-page.svelte +220 -84
- package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
- package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
- package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
- package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
- package/dist/admin/client/users/accept-invite-page.svelte +24 -3
- package/dist/admin/client/users/create-user-dialog.svelte +3 -8
- package/dist/admin/client/users/lang.d.ts +2 -0
- package/dist/admin/client/users/lang.js +4 -0
- package/dist/admin/client/users/pending-invitations.svelte +2 -9
- package/dist/admin/client/users/user-name-cell.svelte +20 -0
- package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
- package/dist/admin/client/users/user-role-badge.svelte +16 -0
- package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
- package/dist/admin/client/users/user-row-actions.svelte +72 -0
- package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
- package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
- package/dist/admin/client/users/users-page.svelte +283 -497
- package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
- package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
- package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
- package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
- package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
- package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
- package/dist/admin/components/fields/blocks-field.svelte +46 -1
- package/dist/admin/components/fields/boolean-field.svelte +1 -1
- package/dist/admin/components/fields/field-renderer.svelte +29 -22
- package/dist/admin/components/fields/file-field.svelte +344 -30
- package/dist/admin/components/fields/icon-field.svelte +86 -0
- package/dist/admin/components/fields/icon-field.svelte.d.ts +8 -0
- package/dist/admin/components/fields/icon-picker-dialog.svelte +174 -0
- package/dist/admin/components/fields/icon-picker-dialog.svelte.d.ts +11 -0
- package/dist/admin/components/fields/media-field.svelte +16 -2
- package/dist/admin/components/fields/object-field.svelte +27 -7
- package/dist/admin/components/fields/radio-field.svelte +22 -0
- package/dist/admin/components/fields/relation-field.svelte +123 -97
- package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +60 -30
- package/dist/admin/components/fields/shop-field.svelte +219 -24
- package/dist/admin/components/fields/simple-array-field.svelte +321 -151
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
- package/dist/admin/components/fields/slug-field.svelte +146 -21
- package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
- package/dist/admin/components/fields/text-field.svelte +7 -2
- package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
- package/dist/admin/components/fields/url-field.svelte +36 -23
- package/dist/admin/components/forms/form-error-summary.svelte +143 -0
- package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
- package/dist/admin/components/layout/app-sidebar.svelte +7 -2
- package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
- package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
- package/dist/admin/components/layout/lang.d.ts +5 -0
- package/dist/admin/components/layout/lang.js +10 -0
- package/dist/admin/components/layout/layout-renderer.svelte +71 -2
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
- package/dist/admin/components/layout/layout-tabs.svelte +173 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
- package/dist/admin/components/layout/nav-collections.svelte +23 -36
- package/dist/admin/components/layout/nav-forms.svelte +19 -35
- package/dist/admin/components/layout/nav-main.svelte +3 -28
- package/dist/admin/components/layout/nav-search.svelte +70 -2
- package/dist/admin/components/layout/nav-section.svelte +77 -0
- package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
- package/dist/admin/components/layout/nav-shop.svelte +3 -27
- package/dist/admin/components/layout/nav-singletons.svelte +16 -28
- package/dist/admin/components/layout/page-header.stories.svelte +93 -0
- package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
- package/dist/admin/components/layout/page-header.svelte +68 -0
- package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
- package/dist/admin/components/layout/site-header.svelte +9 -0
- package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
- package/dist/admin/components/media/file/file-name-input.svelte +6 -2
- package/dist/admin/components/media/file/file-preview.svelte +130 -17
- package/dist/admin/components/media/file-upload.svelte +16 -7
- package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
- package/dist/admin/components/media/files-list.svelte +153 -53
- package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
- package/dist/admin/components/media/media-library.svelte +577 -198
- package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
- package/dist/admin/components/media/media-selector.svelte +4 -2
- package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +4 -4
- package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
- package/dist/admin/components/tiptap/content-editor.svelte +28 -24
- package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
- package/dist/admin/components/tiptap/extensions.js +5 -1
- package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
- package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
- package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
- package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte +109 -0
- package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte.d.ts +9 -0
- package/dist/admin/helpers/build-icon-set-map.d.ts +8 -0
- package/dist/admin/helpers/build-icon-set-map.js +16 -0
- package/dist/admin/helpers/index.d.ts +2 -0
- package/dist/admin/helpers/index.js +2 -0
- package/dist/admin/i18n/errors.d.ts +140 -0
- package/dist/admin/i18n/errors.js +151 -0
- package/dist/admin/remote/entry.remote.d.ts +59 -4
- package/dist/admin/remote/entry.remote.js +239 -62
- package/dist/admin/remote/shop.remote.d.ts +87 -48
- package/dist/admin/remote/shop.remote.js +70 -8
- package/dist/admin/shared/password-generate.d.ts +6 -0
- package/dist/admin/shared/password-generate.js +40 -0
- package/dist/admin/shared/password-schema.d.ts +6 -0
- package/dist/admin/shared/password-schema.js +10 -3
- package/dist/admin/state/icon-sets.svelte.d.ts +9 -0
- package/dist/admin/state/icon-sets.svelte.js +20 -0
- package/dist/admin/styles/admin.css +23 -6
- package/dist/admin/styles/tokens.md +244 -0
- package/dist/admin/utils/accordionActivation.d.ts +13 -0
- package/dist/admin/utils/accordionActivation.js +35 -0
- package/dist/admin/utils/entryLabel.d.ts +23 -0
- package/dist/admin/utils/entryLabel.js +51 -12
- package/dist/admin/utils/field-a11y.d.ts +29 -0
- package/dist/admin/utils/field-a11y.js +23 -0
- package/dist/admin/utils/fieldPathElement.d.ts +9 -0
- package/dist/admin/utils/fieldPathElement.js +18 -0
- package/dist/admin/utils/fileDisplay.d.ts +10 -0
- package/dist/admin/utils/fileDisplay.js +26 -0
- package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
- package/dist/admin/utils/flattenFormErrors.js +102 -0
- package/dist/admin/utils/formatters.d.ts +12 -0
- package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
- package/dist/admin/utils/scrollWithin.d.ts +9 -0
- package/dist/admin/utils/scrollWithin.js +32 -0
- package/dist/admin/utils/tabActivation.d.ts +12 -0
- package/dist/admin/utils/tabActivation.js +24 -0
- package/dist/cli/scaffold/admin.js +2 -2
- package/dist/cms/runtime/schema.d.ts +1 -0
- package/dist/cms/runtime/schema.js +1 -0
- package/dist/cms/runtime/types.d.ts +80 -7
- package/dist/components/ui/accordion/accordion-content.svelte +17 -3
- package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
- package/dist/components/ui/alert/alert.stories.svelte +14 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +15 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
- package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
- package/dist/components/ui/button/button.stories.svelte +53 -6
- package/dist/components/ui/button/button.svelte +39 -5
- package/dist/components/ui/button/button.svelte.d.ts +4 -0
- package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
- package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
- package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/card/card.stories.svelte +7 -0
- package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
- package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.svelte +1 -1
- package/dist/components/ui/command/command.stories.svelte +18 -0
- package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
- package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
- package/dist/components/ui/dialog/dialog-content.svelte +5 -0
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
- package/dist/components/ui/field/field-context.svelte.js +9 -0
- package/dist/components/ui/field/field-control.svelte +18 -0
- package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
- package/dist/components/ui/field/field-description.svelte +12 -0
- package/dist/components/ui/field/field-error.svelte +14 -6
- package/dist/components/ui/field/field-label.svelte +10 -0
- package/dist/components/ui/field/field.stories.svelte +95 -9
- package/dist/components/ui/field/field.svelte +57 -0
- package/dist/components/ui/field/field.svelte.d.ts +2 -0
- package/dist/components/ui/field/index.d.ts +3 -1
- package/dist/components/ui/field/index.js +4 -2
- package/dist/components/ui/form/form-field-errors.svelte +1 -1
- package/dist/components/ui/form/form.stories.svelte +25 -0
- package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
- package/dist/components/ui/input/input.stories.svelte +26 -0
- package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
- package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
- package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/item/item.stories.svelte +61 -0
- package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
- package/dist/components/ui/label/label.stories.svelte +7 -0
- package/dist/components/ui/live-region/index.d.ts +1 -0
- package/dist/components/ui/live-region/index.js +1 -0
- package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
- package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
- package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
- package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
- package/dist/components/ui/live-region/live-region.svelte +12 -0
- package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
- package/dist/components/ui/popover/popover.stories.svelte +34 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
- package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select.stories.svelte +49 -0
- package/dist/components/ui/separator/separator.stories.svelte +18 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
- package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
- package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
- package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.svelte +6 -0
- package/dist/components/ui/sonner/index.d.ts +1 -1
- package/dist/components/ui/sonner/index.js +1 -1
- package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
- package/dist/components/ui/sonner/sonner.svelte +17 -1
- package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
- package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
- package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
- package/dist/components/ui/switch/switch.stories.svelte +56 -0
- package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table-cell.svelte +1 -1
- package/dist/components/ui/table/table-head.svelte +1 -1
- package/dist/components/ui/table/table.stories.svelte +68 -0
- package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table.svelte +1 -1
- package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
- package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
- package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
- package/dist/core/cms.d.ts +11 -2
- package/dist/core/cms.js +29 -0
- package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
- package/dist/core/fields/fieldSchemaToTs.js +241 -90
- package/dist/core/fields/layoutUtils.d.ts +4 -1
- package/dist/core/fields/layoutUtils.js +41 -4
- package/dist/core/fields/resolveSeo.d.ts +70 -0
- package/dist/core/fields/resolveSeo.js +88 -0
- package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
- package/dist/core/fields/seoFieldDescriptor.js +74 -0
- package/dist/core/fields/slugPath.d.ts +13 -0
- package/dist/core/fields/slugPath.js +32 -0
- package/dist/core/fields/urlUtils.d.ts +8 -0
- package/dist/core/fields/urlUtils.js +27 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/server/entries/operations/create.js +13 -0
- package/dist/core/server/entries/operations/get.d.ts +7 -0
- package/dist/core/server/entries/operations/get.js +10 -6
- package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
- package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
- package/dist/core/server/entries/operations/update.d.ts +6 -1
- package/dist/core/server/entries/operations/update.js +24 -1
- package/dist/core/server/fields/slugResolver.d.ts +3 -13
- package/dist/core/server/fields/slugResolver.js +8 -37
- package/dist/core/server/generator/fields.d.ts +2 -0
- package/dist/core/server/generator/fields.js +44 -18
- package/dist/core/server/generator/formFields.js +2 -1
- package/dist/core/server/generator/generator.js +6 -5
- package/dist/core/server/generator/utils.d.ts +1 -0
- package/dist/core/server/generator/utils.js +4 -0
- package/dist/db-postgres/schema/shop/order.d.ts +37 -1
- package/dist/db-postgres/schema/shop/order.js +3 -1
- package/dist/db-postgres/schema/shop/payment.d.ts +20 -0
- package/dist/db-postgres/schema/shop/payment.js +4 -1
- package/dist/db-postgres/schema/shop/product.d.ts +20 -0
- package/dist/db-postgres/schema/shop/product.js +3 -1
- package/dist/db-postgres/schema/shop/productVariant.d.ts +12 -2
- package/dist/db-postgres/schema/shop/productVariant.js +22 -0
- package/dist/shop/cart/types.d.ts +1 -0
- package/dist/shop/client/index.d.ts +54 -0
- package/dist/shop/client/index.js +5 -1
- package/dist/shop/expiry.d.ts +35 -0
- package/dist/shop/expiry.js +68 -0
- package/dist/shop/http/balance-handler.d.ts +20 -0
- package/dist/shop/http/balance-handler.js +91 -0
- package/dist/shop/http/cart-handler.js +19 -0
- package/dist/shop/http/checkout-handler.js +19 -1
- package/dist/shop/http/index.d.ts +2 -0
- package/dist/shop/http/index.js +2 -0
- package/dist/shop/http/upcoming-handler.d.ts +16 -0
- package/dist/shop/http/upcoming-handler.js +65 -0
- package/dist/shop/http/webhook-handler.js +46 -9
- package/dist/shop/index.d.ts +4 -1
- package/dist/shop/index.js +7 -1
- package/dist/shop/server/balance-payment.d.ts +40 -0
- package/dist/shop/server/balance-payment.js +140 -0
- package/dist/shop/server/cart-hydrate.js +2 -0
- package/dist/shop/server/init.d.ts +14 -0
- package/dist/shop/server/init.js +35 -0
- package/dist/shop/server/orders.d.ts +35 -0
- package/dist/shop/server/orders.js +155 -2
- package/dist/shop/server/payment-policy.d.ts +35 -0
- package/dist/shop/server/payment-policy.js +55 -0
- package/dist/shop/server/payments.d.ts +29 -0
- package/dist/shop/server/payments.js +64 -0
- package/dist/shop/server/populate.d.ts +1 -1
- package/dist/shop/server/refund.d.ts +17 -12
- package/dist/shop/server/refund.js +96 -13
- package/dist/shop/server/shop-data.d.ts +6 -1
- package/dist/shop/server/shop-data.js +44 -7
- package/dist/shop/template.d.ts +13 -0
- package/dist/shop/template.js +98 -0
- package/dist/shop/types.d.ts +142 -1
- package/dist/shop/variant-attributes.d.ts +28 -0
- package/dist/shop/variant-attributes.js +69 -0
- package/dist/sveltekit/server/handle.js +17 -0
- package/dist/sveltekit/server/index.d.ts +1 -0
- package/dist/sveltekit/server/index.js +2 -0
- package/dist/types/cms.d.ts +4 -3
- package/dist/types/cms.schema.d.ts +1 -1
- package/dist/types/cms.schema.js +13 -2
- package/dist/types/fields.d.ts +56 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +1 -1
- package/dist/types/layout.d.ts +35 -2
- package/dist/types/plugins.d.ts +40 -0
- package/dist/types/plugins.js +4 -1
- package/dist/updates/0.26.0/index.d.ts +2 -0
- package/dist/updates/0.26.0/index.js +51 -0
- package/dist/updates/0.26.1/index.d.ts +2 -0
- package/dist/updates/0.26.1/index.js +19 -0
- package/dist/updates/0.27.0/index.d.ts +2 -0
- package/dist/updates/0.27.0/index.js +50 -0
- package/dist/updates/index.js +7 -1
- package/package.json +29 -7
- package/dist/admin/client/collection/empty-state.svelte +0 -28
- package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
- package/dist/admin/client/form/submission-status-badge.svelte +0 -41
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
- package/dist/admin/components/media/file-preview.svelte +0 -51
- package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
- package/dist/admin/utils/formatDate.d.ts +0 -5
|
@@ -1,50 +1,21 @@
|
|
|
1
1
|
import { getCMS } from '../../cms.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* Falls back to 'seo.slug' if no slugField is configured.
|
|
6
|
-
*/
|
|
2
|
+
import { getSlugFromEntryData, resolveSlugPath, applyPathTemplate } from '../../fields/slugPath.js';
|
|
3
|
+
export { getSlugFromEntryData } from '../../fields/slugPath.js';
|
|
4
|
+
/** Get dot-path to slug field for a collection. Falls back to 'seo.slug'. */
|
|
7
5
|
export function getEntrySlugPath(configSlug) {
|
|
8
6
|
try {
|
|
9
|
-
|
|
10
|
-
return config.slugField || DEFAULT_SLUG_PATH;
|
|
7
|
+
return resolveSlugPath(getCMS().getBySlug(configSlug).slugField);
|
|
11
8
|
}
|
|
12
9
|
catch {
|
|
13
|
-
return
|
|
10
|
+
return resolveSlugPath(undefined);
|
|
14
11
|
}
|
|
15
12
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Traverse a dot-path in entry data and return the slug value.
|
|
18
|
-
* Handles both plain strings and localized objects { lang: string }.
|
|
19
|
-
*/
|
|
20
|
-
export function getSlugFromEntryData(data, slugPath, language) {
|
|
21
|
-
const parts = slugPath.split('.');
|
|
22
|
-
let current = data;
|
|
23
|
-
for (const part of parts) {
|
|
24
|
-
if (current == null || typeof current !== 'object')
|
|
25
|
-
return undefined;
|
|
26
|
-
current = current[part];
|
|
27
|
-
}
|
|
28
|
-
if (typeof current === 'string')
|
|
29
|
-
return current;
|
|
30
|
-
if (language && current != null && typeof current === 'object') {
|
|
31
|
-
return current[language];
|
|
32
|
-
}
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Build full entry path using collection's pathTemplate.
|
|
37
|
-
* If no template configured, returns the raw slug.
|
|
38
|
-
*/
|
|
13
|
+
/** Build full entry path using collection's pathTemplate. */
|
|
39
14
|
export function getEntryPath(configSlug, slug) {
|
|
40
15
|
try {
|
|
41
|
-
|
|
42
|
-
if (config.pathTemplate) {
|
|
43
|
-
return config.pathTemplate.replace('{slug}', slug);
|
|
44
|
-
}
|
|
16
|
+
return applyPathTemplate(getCMS().getBySlug(configSlug).pathTemplate, slug);
|
|
45
17
|
}
|
|
46
18
|
catch {
|
|
47
|
-
|
|
19
|
+
return applyPathTemplate(undefined, slug);
|
|
48
20
|
}
|
|
49
|
-
return slug;
|
|
50
21
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Field } from '../../../types/fields.js';
|
|
2
2
|
import type { CustomFieldDefinition } from '../../../types/plugins.js';
|
|
3
|
+
import type { VariantAttribute } from '../../../shop/types.js';
|
|
3
4
|
export declare function setGeneratorCustomFields(customFields: Map<string, CustomFieldDefinition>): void;
|
|
5
|
+
export declare function setGeneratorShopVariantAttributes(attrs: Record<string, VariantAttribute>): void;
|
|
4
6
|
export declare function generateTsTypeFromFields(fields: Field[]): string;
|
|
5
7
|
export declare function generateFlatTsTypeFromFields(fields: Field[]): string;
|
|
6
8
|
export interface InlineBlockTypeDef {
|
|
@@ -1,11 +1,44 @@
|
|
|
1
|
-
import { toPascalCase } from './utils.js';
|
|
1
|
+
import { toPascalCase, quoteKey } from './utils.js';
|
|
2
|
+
import { buildSeoTsType } from '../../fields/seoFieldDescriptor.js';
|
|
2
3
|
let _customFields = new Map();
|
|
4
|
+
let _shopVariantAttributes = {};
|
|
3
5
|
function isGuaranteed(f) {
|
|
4
6
|
return !!(f.required || f.type === 'seo' || f.defaultValue !== undefined);
|
|
5
7
|
}
|
|
6
8
|
export function setGeneratorCustomFields(customFields) {
|
|
7
9
|
_customFields = customFields;
|
|
8
10
|
}
|
|
11
|
+
export function setGeneratorShopVariantAttributes(attrs) {
|
|
12
|
+
_shopVariantAttributes = attrs;
|
|
13
|
+
}
|
|
14
|
+
function variantAttributeTsType(attr) {
|
|
15
|
+
switch (attr.type) {
|
|
16
|
+
case 'text':
|
|
17
|
+
case 'datetime':
|
|
18
|
+
case 'image':
|
|
19
|
+
case 'entry':
|
|
20
|
+
case 'slug':
|
|
21
|
+
return 'string';
|
|
22
|
+
case 'number':
|
|
23
|
+
return 'number';
|
|
24
|
+
case 'boolean':
|
|
25
|
+
return 'boolean';
|
|
26
|
+
case 'select':
|
|
27
|
+
return attr.options.map((o) => `'${o.value}'`).join(' | ');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function buildShopAttributesType() {
|
|
31
|
+
const entries = Object.entries(_shopVariantAttributes);
|
|
32
|
+
if (entries.length === 0)
|
|
33
|
+
return 'Record<string, string> | null';
|
|
34
|
+
const fields = entries
|
|
35
|
+
.map(([key, attr]) => {
|
|
36
|
+
const opt = attr.required ? '' : '?';
|
|
37
|
+
return `${quoteKey(key)}${opt}: ${variantAttributeTsType(attr)}`;
|
|
38
|
+
})
|
|
39
|
+
.join('; ');
|
|
40
|
+
return `{ ${fields} }`;
|
|
41
|
+
}
|
|
9
42
|
function getFieldTypeAsString(field) {
|
|
10
43
|
switch (field.type) {
|
|
11
44
|
case 'text':
|
|
@@ -43,7 +76,7 @@ function getFieldTypeAsString(field) {
|
|
|
43
76
|
case 'object':
|
|
44
77
|
return `{
|
|
45
78
|
slug: '${field.slug}';
|
|
46
|
-
data: {${field.fields.map((f) => ` ${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')}};
|
|
79
|
+
data: {${field.fields.map((f) => ` ${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')}};
|
|
47
80
|
}`;
|
|
48
81
|
case 'blocks':
|
|
49
82
|
return `
|
|
@@ -52,7 +85,7 @@ function getFieldTypeAsString(field) {
|
|
|
52
85
|
.map((f) => `
|
|
53
86
|
{
|
|
54
87
|
slug: '${f.slug}';
|
|
55
|
-
data: {${f.fields.map((f) => ` ${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')}};
|
|
88
|
+
data: {${f.fields.map((f) => ` ${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')}};
|
|
56
89
|
}
|
|
57
90
|
`)
|
|
58
91
|
.join(' | ')}
|
|
@@ -67,17 +100,10 @@ function getFieldTypeAsString(field) {
|
|
|
67
100
|
return 'UrlFieldData[]';
|
|
68
101
|
}
|
|
69
102
|
case 'slug':
|
|
103
|
+
case 'icon':
|
|
70
104
|
return 'string';
|
|
71
105
|
case 'seo':
|
|
72
|
-
return
|
|
73
|
-
slug: string;
|
|
74
|
-
canonicalUrl?: string;
|
|
75
|
-
title: string;
|
|
76
|
-
description?: string;
|
|
77
|
-
ogImage?: string;
|
|
78
|
-
keywords?: string;
|
|
79
|
-
customCode?: string;
|
|
80
|
-
}`;
|
|
106
|
+
return buildSeoTsType();
|
|
81
107
|
case 'shop':
|
|
82
108
|
return `{
|
|
83
109
|
basePrice: number;
|
|
@@ -89,7 +115,7 @@ function getFieldTypeAsString(field) {
|
|
|
89
115
|
name: Record<string, string> | null;
|
|
90
116
|
priceDelta: number;
|
|
91
117
|
stock: number | null;
|
|
92
|
-
attributes:
|
|
118
|
+
attributes: ${buildShopAttributesType()};
|
|
93
119
|
}>;
|
|
94
120
|
} | null`;
|
|
95
121
|
case 'url': {
|
|
@@ -110,12 +136,12 @@ function getFieldTypeAsString(field) {
|
|
|
110
136
|
}
|
|
111
137
|
export function generateTsTypeFromFields(fields) {
|
|
112
138
|
return `{
|
|
113
|
-
${fields.map((f) => ` ${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')};
|
|
139
|
+
${fields.map((f) => ` ${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFieldTypeAsString(f)}`).join(';\n')};
|
|
114
140
|
}`;
|
|
115
141
|
}
|
|
116
142
|
export function generateFlatTsTypeFromFields(fields) {
|
|
117
143
|
return `{
|
|
118
|
-
${fields.map((f) => ` ${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
144
|
+
${fields.map((f) => ` ${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
119
145
|
}`;
|
|
120
146
|
}
|
|
121
147
|
function getFlatFieldTypeAsString(field) {
|
|
@@ -133,7 +159,7 @@ function getFlatFieldTypeAsString(field) {
|
|
|
133
159
|
case 'object':
|
|
134
160
|
return `{
|
|
135
161
|
_slug: '${field.slug}';
|
|
136
|
-
${field.fields.map((f) => `${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
162
|
+
${field.fields.map((f) => `${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
137
163
|
}`;
|
|
138
164
|
case 'blocks':
|
|
139
165
|
return `
|
|
@@ -142,7 +168,7 @@ function getFlatFieldTypeAsString(field) {
|
|
|
142
168
|
.map((f) => `
|
|
143
169
|
{
|
|
144
170
|
_slug: '${f.slug}';
|
|
145
|
-
${f.fields.map((f) => `${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
171
|
+
${f.fields.map((f) => `${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
146
172
|
}
|
|
147
173
|
`)
|
|
148
174
|
.join(' | ')}
|
|
@@ -153,6 +179,6 @@ function getFlatFieldTypeAsString(field) {
|
|
|
153
179
|
}
|
|
154
180
|
export function generateInlineBlockTypeString(block) {
|
|
155
181
|
return `{
|
|
156
|
-
${block.fields.map((f) => ` ${f.slug}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
182
|
+
${block.fields.map((f) => ` ${quoteKey(f.slug)}${isGuaranteed(f) ? '' : '?'}: ${getFlatFieldTypeAsString(f)}`).join(';\n')};
|
|
157
183
|
}`;
|
|
158
184
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { quoteKey } from './utils.js';
|
|
1
2
|
function getFormFieldTypeAsString(field) {
|
|
2
3
|
switch (field.type) {
|
|
3
4
|
case 'text':
|
|
@@ -15,6 +16,6 @@ function getFormFieldTypeAsString(field) {
|
|
|
15
16
|
}
|
|
16
17
|
export function generateTsTypeFromFormFields(fields) {
|
|
17
18
|
return `{
|
|
18
|
-
${fields.map((f) => ` ${f.slug}: ${getFormFieldTypeAsString(f)}`).join(';\n')};
|
|
19
|
+
${fields.map((f) => ` ${quoteKey(f.slug)}: ${getFormFieldTypeAsString(f)}`).join(';\n')};
|
|
19
20
|
}`;
|
|
20
21
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { generateTsTypeFromFields, generateFlatTsTypeFromFields, generateInlineBlockTypeString, setGeneratorCustomFields } from './fields.js';
|
|
3
|
+
import { generateTsTypeFromFields, generateFlatTsTypeFromFields, generateInlineBlockTypeString, setGeneratorCustomFields, setGeneratorShopVariantAttributes } from './fields.js';
|
|
4
4
|
import { generateTsTypeFromFormFields } from './formFields.js';
|
|
5
5
|
import { generateZodSchemaStringFromFormFieldsAsString } from './formFieldSchemaToString.js';
|
|
6
|
-
import { toPascalCase } from './utils.js';
|
|
6
|
+
import { toPascalCase, quoteKey } from './utils.js';
|
|
7
7
|
import { getFieldsFromConfig } from '../../fields/layoutUtils.js';
|
|
8
8
|
function createCmsRuntimeDir() {
|
|
9
9
|
const cmsDir = join(process.cwd(), 'src/lib/cms/runtime');
|
|
@@ -54,7 +54,7 @@ function generateTypesStringForRecords(type, records) {
|
|
|
54
54
|
export type ${recordTypeString}EntryMap = {
|
|
55
55
|
${records
|
|
56
56
|
.map((single) => {
|
|
57
|
-
const key = single.slug
|
|
57
|
+
const key = quoteKey(single.slug);
|
|
58
58
|
return `${key}: ${toPascalCase(single.slug)}`;
|
|
59
59
|
})
|
|
60
60
|
.join(';\n')}
|
|
@@ -82,7 +82,7 @@ function generateTypesStringForForms(records) {
|
|
|
82
82
|
export type ${recordTypeString}EntryMap = {
|
|
83
83
|
${records
|
|
84
84
|
.map((single) => {
|
|
85
|
-
const key = single.slug
|
|
85
|
+
const key = quoteKey(single.slug);
|
|
86
86
|
return `${key}: ${toPascalCase(single.slug)}`;
|
|
87
87
|
})
|
|
88
88
|
.join(';\n')}
|
|
@@ -163,7 +163,7 @@ function generateTypes(config) {
|
|
|
163
163
|
const mapName = toPascalCase(record.slug) + toPascalCase(field.slug) + 'BlockDataMap';
|
|
164
164
|
code += `\nexport type ${mapName} = {\n`;
|
|
165
165
|
for (const block of cf.inlineBlocks) {
|
|
166
|
-
const key = block.slug
|
|
166
|
+
const key = quoteKey(block.slug);
|
|
167
167
|
code += ` ${key}: ${toPascalCase(block.slug)}BlockData;\n`;
|
|
168
168
|
}
|
|
169
169
|
code += `};\n`;
|
|
@@ -312,6 +312,7 @@ export function generateRuntime(config) {
|
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
setGeneratorCustomFields(customFields);
|
|
315
|
+
setGeneratorShopVariantAttributes(config.shop?.variantAttributes ?? {});
|
|
315
316
|
createCmsRuntimeDir();
|
|
316
317
|
generateTypes(config);
|
|
317
318
|
generateAPI(config);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OrderStatus } from '../../../shop/types.js';
|
|
1
|
+
import type { OrderStatus, PartialPayment } from '../../../shop/types.js';
|
|
2
2
|
export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
|
|
3
3
|
name: "shop_orders";
|
|
4
4
|
schema: undefined;
|
|
@@ -459,6 +459,42 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
|
|
|
459
459
|
identity: undefined;
|
|
460
460
|
generated: undefined;
|
|
461
461
|
}, {}, {}>;
|
|
462
|
+
partialPayment: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
463
|
+
name: "partial_payment";
|
|
464
|
+
tableName: "shop_orders";
|
|
465
|
+
dataType: "json";
|
|
466
|
+
columnType: "PgJsonb";
|
|
467
|
+
data: PartialPayment | null;
|
|
468
|
+
driverParam: unknown;
|
|
469
|
+
notNull: false;
|
|
470
|
+
hasDefault: false;
|
|
471
|
+
isPrimaryKey: false;
|
|
472
|
+
isAutoincrement: false;
|
|
473
|
+
hasRuntimeDefault: false;
|
|
474
|
+
enumValues: undefined;
|
|
475
|
+
baseColumn: never;
|
|
476
|
+
identity: undefined;
|
|
477
|
+
generated: undefined;
|
|
478
|
+
}, {}, {
|
|
479
|
+
$type: PartialPayment | null;
|
|
480
|
+
}>;
|
|
481
|
+
balanceOwed: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
482
|
+
name: "balance_owed";
|
|
483
|
+
tableName: "shop_orders";
|
|
484
|
+
dataType: "boolean";
|
|
485
|
+
columnType: "PgBoolean";
|
|
486
|
+
data: boolean;
|
|
487
|
+
driverParam: boolean;
|
|
488
|
+
notNull: true;
|
|
489
|
+
hasDefault: true;
|
|
490
|
+
isPrimaryKey: false;
|
|
491
|
+
isAutoincrement: false;
|
|
492
|
+
hasRuntimeDefault: false;
|
|
493
|
+
enumValues: undefined;
|
|
494
|
+
baseColumn: never;
|
|
495
|
+
identity: undefined;
|
|
496
|
+
generated: undefined;
|
|
497
|
+
}, {}, {}>;
|
|
462
498
|
createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
463
499
|
name: "created_at";
|
|
464
500
|
tableName: "shop_orders";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { boolean, integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
2
2
|
import { shopShippingMethodsTable } from './shippingMethod.js';
|
|
3
3
|
export const shopOrdersTable = pgTable('shop_orders', {
|
|
4
4
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
@@ -29,6 +29,8 @@ export const shopOrdersTable = pgTable('shop_orders', {
|
|
|
29
29
|
notes: text('notes'),
|
|
30
30
|
language: text('language'),
|
|
31
31
|
accessToken: uuid('access_token').defaultRandom().notNull(),
|
|
32
|
+
partialPayment: jsonb('partial_payment').$type(),
|
|
33
|
+
balanceOwed: boolean('balance_owed').default(false).notNull(),
|
|
32
34
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
33
35
|
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
|
|
34
36
|
});
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled';
|
|
2
|
+
/** `kind` distinguishes full / deposit / balance payment rows under paymentPolicy A-lite. */
|
|
3
|
+
export declare const shopPaymentKindEnum: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgEnum<["full", "deposit", "balance"]>;
|
|
4
|
+
export type ShopPaymentKind = 'full' | 'deposit' | 'balance';
|
|
2
5
|
export declare const shopPaymentsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
|
|
3
6
|
name: "shop_payments";
|
|
4
7
|
schema: undefined;
|
|
@@ -90,6 +93,23 @@ export declare const shopPaymentsTable: import("drizzle-orm/pg-core/table", { wi
|
|
|
90
93
|
}, {}, {
|
|
91
94
|
$type: ShopPaymentStatus;
|
|
92
95
|
}>;
|
|
96
|
+
kind: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
97
|
+
name: "kind";
|
|
98
|
+
tableName: "shop_payments";
|
|
99
|
+
dataType: "string";
|
|
100
|
+
columnType: "PgEnumColumn";
|
|
101
|
+
data: "full" | "deposit" | "balance";
|
|
102
|
+
driverParam: string;
|
|
103
|
+
notNull: true;
|
|
104
|
+
hasDefault: true;
|
|
105
|
+
isPrimaryKey: false;
|
|
106
|
+
isAutoincrement: false;
|
|
107
|
+
hasRuntimeDefault: false;
|
|
108
|
+
enumValues: ["full", "deposit", "balance"];
|
|
109
|
+
baseColumn: never;
|
|
110
|
+
identity: undefined;
|
|
111
|
+
generated: undefined;
|
|
112
|
+
}, {}, {}>;
|
|
93
113
|
amount: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
94
114
|
name: "amount";
|
|
95
115
|
tableName: "shop_payments";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { integer, jsonb, pgEnum, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
2
2
|
import { shopOrdersTable } from './order.js';
|
|
3
|
+
/** `kind` distinguishes full / deposit / balance payment rows under paymentPolicy A-lite. */
|
|
4
|
+
export const shopPaymentKindEnum = pgEnum('shop_payment_kind', ['full', 'deposit', 'balance']);
|
|
3
5
|
export const shopPaymentsTable = pgTable('shop_payments', {
|
|
4
6
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
5
7
|
orderId: uuid('order_id')
|
|
@@ -8,6 +10,7 @@ export const shopPaymentsTable = pgTable('shop_payments', {
|
|
|
8
10
|
provider: text('provider').notNull(),
|
|
9
11
|
providerRef: text('provider_ref'),
|
|
10
12
|
status: text('status').$type().notNull().default('pending'),
|
|
13
|
+
kind: shopPaymentKindEnum('kind').notNull().default('full'),
|
|
11
14
|
amount: integer('amount').notNull(),
|
|
12
15
|
currency: text('currency').notNull(),
|
|
13
16
|
raw: jsonb('raw'),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PaymentPolicy } from '../../../shop/types.js';
|
|
1
2
|
export declare const shopProductsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
|
|
2
3
|
name: "shop_products";
|
|
3
4
|
schema: undefined;
|
|
@@ -121,6 +122,25 @@ export declare const shopProductsTable: import("drizzle-orm/pg-core/table", { wi
|
|
|
121
122
|
identity: undefined;
|
|
122
123
|
generated: undefined;
|
|
123
124
|
}, {}, {}>;
|
|
125
|
+
paymentPolicy: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
126
|
+
name: "payment_policy";
|
|
127
|
+
tableName: "shop_products";
|
|
128
|
+
dataType: "json";
|
|
129
|
+
columnType: "PgJsonb";
|
|
130
|
+
data: PaymentPolicy | null;
|
|
131
|
+
driverParam: unknown;
|
|
132
|
+
notNull: false;
|
|
133
|
+
hasDefault: false;
|
|
134
|
+
isPrimaryKey: false;
|
|
135
|
+
isAutoincrement: false;
|
|
136
|
+
hasRuntimeDefault: false;
|
|
137
|
+
enumValues: undefined;
|
|
138
|
+
baseColumn: never;
|
|
139
|
+
identity: undefined;
|
|
140
|
+
generated: undefined;
|
|
141
|
+
}, {}, {
|
|
142
|
+
$type: PaymentPolicy | null;
|
|
143
|
+
}>;
|
|
124
144
|
createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
125
145
|
name: "created_at";
|
|
126
146
|
tableName: "shop_products";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { boolean, integer, numeric, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { boolean, integer, jsonb, numeric, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
2
2
|
import { entriesTable } from '../entry.js';
|
|
3
3
|
export const shopProductsTable = pgTable('shop_products', {
|
|
4
4
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
@@ -13,6 +13,8 @@ export const shopProductsTable = pgTable('shop_products', {
|
|
|
13
13
|
sortOrder: integer('sort_order'),
|
|
14
14
|
// Null = alert disabled. When stock decrement crosses threshold, fire-and-forget admin email.
|
|
15
15
|
lowStockThreshold: integer('low_stock_threshold'),
|
|
16
|
+
// Per-product payment policy. Null = full payment (legacy).
|
|
17
|
+
paymentPolicy: jsonb('payment_policy').$type(),
|
|
16
18
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
17
19
|
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
|
|
18
20
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { VariantAttribute } from '../../../shop/types.js';
|
|
1
2
|
export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
|
|
2
3
|
name: "shop_product_variants";
|
|
3
4
|
schema: undefined;
|
|
@@ -111,7 +112,7 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
|
|
|
111
112
|
tableName: "shop_product_variants";
|
|
112
113
|
dataType: "json";
|
|
113
114
|
columnType: "PgJsonb";
|
|
114
|
-
data: Record<string,
|
|
115
|
+
data: Record<string, unknown>;
|
|
115
116
|
driverParam: unknown;
|
|
116
117
|
notNull: false;
|
|
117
118
|
hasDefault: false;
|
|
@@ -123,7 +124,7 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
|
|
|
123
124
|
identity: undefined;
|
|
124
125
|
generated: undefined;
|
|
125
126
|
}, {}, {
|
|
126
|
-
$type: Record<string,
|
|
127
|
+
$type: Record<string, unknown>;
|
|
127
128
|
}>;
|
|
128
129
|
sortOrder: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
|
|
129
130
|
name: "sort_order";
|
|
@@ -162,3 +163,12 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
|
|
|
162
163
|
};
|
|
163
164
|
dialect: "pg";
|
|
164
165
|
}>;
|
|
166
|
+
/**
|
|
167
|
+
* Build `CREATE INDEX IF NOT EXISTS … USING gin ((attributes->'<key>'))` DDL
|
|
168
|
+
* statements — one per attribute marked `indexable: true`. Drizzle's static
|
|
169
|
+
* schema can't capture user-defined variantAttributes, so apply these at shop
|
|
170
|
+
* bootstrap (or via the migration in `src/lib/updates/0.27.0`).
|
|
171
|
+
* Index name pattern: `shop_variant_attr_<key>_gin_idx`.
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
174
|
+
export declare function createVariantAttributeIndexes(attrs: Record<string, VariantAttribute>): string[];
|
|
@@ -14,3 +14,25 @@ export const shopProductVariantsTable = pgTable('shop_product_variants', {
|
|
|
14
14
|
sortOrder: integer('sort_order'),
|
|
15
15
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull()
|
|
16
16
|
});
|
|
17
|
+
const SAFE_KEY = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
18
|
+
/**
|
|
19
|
+
* Build `CREATE INDEX IF NOT EXISTS … USING gin ((attributes->'<key>'))` DDL
|
|
20
|
+
* statements — one per attribute marked `indexable: true`. Drizzle's static
|
|
21
|
+
* schema can't capture user-defined variantAttributes, so apply these at shop
|
|
22
|
+
* bootstrap (or via the migration in `src/lib/updates/0.27.0`).
|
|
23
|
+
* Index name pattern: `shop_variant_attr_<key>_gin_idx`.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export function createVariantAttributeIndexes(attrs) {
|
|
27
|
+
const stmts = [];
|
|
28
|
+
for (const [key, attr] of Object.entries(attrs)) {
|
|
29
|
+
if (!attr.indexable)
|
|
30
|
+
continue;
|
|
31
|
+
if (!SAFE_KEY.test(key)) {
|
|
32
|
+
throw new Error(`variantAttribute key "${key}" is not a safe SQL identifier (allowed: [A-Za-z][A-Za-z0-9_]*).`);
|
|
33
|
+
}
|
|
34
|
+
stmts.push(`CREATE INDEX IF NOT EXISTS shop_variant_attr_${key}_gin_idx ` +
|
|
35
|
+
`ON shop_product_variants USING gin ((attributes->'${key}'))`);
|
|
36
|
+
}
|
|
37
|
+
return stmts;
|
|
38
|
+
}
|
|
@@ -114,6 +114,34 @@ export interface RetryPaymentResult {
|
|
|
114
114
|
requiresPaymentRedirect: boolean;
|
|
115
115
|
redirectUrl: string | null;
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Result of `orders.payBalance` — initiates a payment session for the
|
|
119
|
+
* outstanding balance on a deposit order.
|
|
120
|
+
* @public
|
|
121
|
+
*/
|
|
122
|
+
export interface PayBalanceResult {
|
|
123
|
+
status: 'redirect' | 'manual' | 'error';
|
|
124
|
+
requiresPaymentRedirect: boolean;
|
|
125
|
+
redirectUrl: string | null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Public-facing variant row returned by `client.products.listUpcoming`.
|
|
129
|
+
* Mirrors the `shop_product_variants` schema with `priceDelta` decoded as
|
|
130
|
+
* the raw numeric(20,6) string and `attributes` as the typed map declared
|
|
131
|
+
* in `defineShop({ variantAttributes })`.
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
134
|
+
export interface VariantPublic {
|
|
135
|
+
id: string;
|
|
136
|
+
productId: string;
|
|
137
|
+
sku: string | null;
|
|
138
|
+
name: Record<string, string> | null;
|
|
139
|
+
priceDelta: string;
|
|
140
|
+
stock: number | null;
|
|
141
|
+
attributes: Record<string, unknown> | null;
|
|
142
|
+
sortOrder: number | null;
|
|
143
|
+
createdAt: string;
|
|
144
|
+
}
|
|
117
145
|
/**
|
|
118
146
|
* Headless shop SDK surface returned by `createShopClient()`.
|
|
119
147
|
*
|
|
@@ -124,6 +152,21 @@ export interface RetryPaymentResult {
|
|
|
124
152
|
* @public
|
|
125
153
|
*/
|
|
126
154
|
export interface ShopClient {
|
|
155
|
+
/** Product / variant discovery. */
|
|
156
|
+
products: {
|
|
157
|
+
/**
|
|
158
|
+
* List upcoming (non-expired) variants for a product. When
|
|
159
|
+
* `defineShop({ variantExpiry })` is not configured this returns
|
|
160
|
+
* every variant; otherwise variants whose datetime attribute has
|
|
161
|
+
* already passed (per `offsetDays`) are filtered out and the
|
|
162
|
+
* remainder are sorted ascending by that attribute.
|
|
163
|
+
*
|
|
164
|
+
* @param productId - The shop product id (UUID).
|
|
165
|
+
*/
|
|
166
|
+
listUpcoming(productId: string): Promise<{
|
|
167
|
+
items: VariantPublic[];
|
|
168
|
+
}>;
|
|
169
|
+
};
|
|
127
170
|
/** Cart operations — read state and mutate items / coupon. */
|
|
128
171
|
cart: {
|
|
129
172
|
/**
|
|
@@ -201,6 +244,17 @@ export interface ShopClient {
|
|
|
201
244
|
* re-fill the checkout form.
|
|
202
245
|
*/
|
|
203
246
|
retryPayment(orderNumber: string, token?: string): Promise<RetryPaymentResult>;
|
|
247
|
+
/**
|
|
248
|
+
* Pay the outstanding balance on a deposit-policy order. `token` is
|
|
249
|
+
* the signed balance token from the admin-generated balance link;
|
|
250
|
+
* the server returns a redirect URL when the payment provider needs
|
|
251
|
+
* to take over, or `paymentStatus: 'manual'` for manual methods.
|
|
252
|
+
*
|
|
253
|
+
* @param orderNumber - The order number from the balance link.
|
|
254
|
+
* @param token - Signed balance token (query parameter on the link).
|
|
255
|
+
* @experimental
|
|
256
|
+
*/
|
|
257
|
+
payBalance(orderNumber: string, token: string): Promise<PayBalanceResult>;
|
|
204
258
|
};
|
|
205
259
|
}
|
|
206
260
|
/**
|
|
@@ -59,6 +59,9 @@ export function createShopClient(options = {}) {
|
|
|
59
59
|
return (await res.json());
|
|
60
60
|
}
|
|
61
61
|
return {
|
|
62
|
+
products: {
|
|
63
|
+
listUpcoming: (productId) => call('GET', `/api/shop/products/${encodeURIComponent(productId)}/variants/upcoming`)
|
|
64
|
+
},
|
|
62
65
|
cart: {
|
|
63
66
|
get: () => call('GET', '/api/shop/cart'),
|
|
64
67
|
add: (variantId, qty = 1) => call('POST', '/api/shop/cart', { variantId, qty }),
|
|
@@ -77,7 +80,8 @@ export function createShopClient(options = {}) {
|
|
|
77
80
|
orders: {
|
|
78
81
|
get: (orderNumber, token) => call('GET', `/api/shop/orders/${encodeURIComponent(orderNumber)}${tokenQuery(token)}`),
|
|
79
82
|
refreshPayment: (orderNumber, token) => call('POST', `/api/shop/orders/${encodeURIComponent(orderNumber)}/refresh-payment${tokenQuery(token)}`),
|
|
80
|
-
retryPayment: (orderNumber, token) => call('POST', `/api/shop/orders/${encodeURIComponent(orderNumber)}/retry-payment${tokenQuery(token)}`)
|
|
83
|
+
retryPayment: (orderNumber, token) => call('POST', `/api/shop/orders/${encodeURIComponent(orderNumber)}/retry-payment${tokenQuery(token)}`),
|
|
84
|
+
payBalance: (orderNumber, token) => call('POST', `/api/shop/orders/${encodeURIComponent(orderNumber)}/balance?token=${encodeURIComponent(token)}`, {})
|
|
81
85
|
}
|
|
82
86
|
};
|
|
83
87
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { VariantExpiryConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `createOrderFromCart` / cart-add HTTP guard when a referenced
|
|
4
|
+
* variant has already expired under the configured `variantExpiry`. The
|
|
5
|
+
* `code` is `VARIANT_EXPIRED` and `variantId` identifies the offending row.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare class VariantExpiredError extends Error {
|
|
9
|
+
readonly code = "VARIANT_EXPIRED";
|
|
10
|
+
readonly variantId: string;
|
|
11
|
+
constructor(variantId: string);
|
|
12
|
+
}
|
|
13
|
+
interface VariantLike {
|
|
14
|
+
attributes: Record<string, unknown> | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check whether a variant has expired under the given config. Fail-open by
|
|
18
|
+
* design: `null` config, missing source attribute, non-string value, or
|
|
19
|
+
* malformed datetime all return `false` — only a parseable past datetime
|
|
20
|
+
* counts as expired. Malformed datetimes emit `console.warn` so authoring
|
|
21
|
+
* issues surface in dev without blocking checkout.
|
|
22
|
+
*
|
|
23
|
+
* @param variant - Object with an `attributes` map (e.g. `shop_product_variants.attributes`).
|
|
24
|
+
* @param config - Result of `defineShop({ variantExpiry })`, or `null` when not configured.
|
|
25
|
+
* @param now - Override the current time (test seam). Defaults to `Date.now()`.
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare function isVariantExpired(variant: VariantLike, config: VariantExpiryConfig | null, now?: Date): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Return the subset of `variants` that have not yet expired. Order is
|
|
31
|
+
* preserved. `null` config = passthrough.
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export declare function filterUpcoming<T extends VariantLike>(variants: T[], config: VariantExpiryConfig | null, now?: Date): T[];
|
|
35
|
+
export {};
|