@xiwebdesign/xicms-core 6.4.7 → 7.0.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/dist/SiteChrome.d.ts +12 -0
- package/dist/SiteChrome.js +24 -0
- package/dist/SiteChrome.js.map +1 -0
- package/dist/XiCMSProvider.d.ts +16 -8
- package/dist/XiCMSProvider.js +83 -58
- package/dist/XiCMSProvider.js.map +1 -1
- package/dist/admin/AdminApp.d.ts +1 -1
- package/dist/admin/AdminApp.js +79 -35
- package/dist/admin/AdminApp.js.map +1 -1
- package/dist/admin/AdminHelp.d.ts +8 -1
- package/dist/admin/AdminHelp.js +2 -2
- package/dist/admin/AdminHelp.js.map +1 -1
- package/dist/admin/NewsEditor.js +9 -9
- package/dist/admin/SuperadminPanel.js +5 -5
- package/dist/admin/blockEditors/GenericEditor.d.ts +2 -2
- package/dist/admin/blockEditors/GenericEditor.js +12 -11
- package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
- package/dist/admin/blockEditors/StyleEditor.d.ts +1 -1
- package/dist/admin/blockEditors/StyleEditor.js +2 -2
- package/dist/admin/blockEditors/SymbolRefEditor.d.ts +1 -1
- package/dist/admin/blockEditors/SymbolRefEditor.js +5 -5
- package/dist/admin/blockEditors/index.d.ts +1 -1
- package/dist/admin/blockEditors/index.js +10 -10
- package/dist/admin/customBlocks/CustomBlocksPanel.js +7 -7
- package/dist/admin/editors/RichTextEditor.js +8 -7
- package/dist/admin/editors/RichTextEditor.js.map +1 -1
- package/dist/admin/editors/fontSizeExtension.js +1 -1
- package/dist/admin/editors/fontSizeExtension.js.map +1 -1
- package/dist/admin/forms/FormsPanel.js +9 -9
- package/dist/admin/index.d.ts +16 -16
- package/dist/admin/index.js +16 -16
- package/dist/admin/lib/mediaUsage.js +1 -1
- package/dist/admin/lib/pagesClient.d.ts +1 -1
- package/dist/admin/lib/pagesClient.js +11 -7
- package/dist/admin/lib/pagesClient.js.map +1 -1
- package/dist/admin/lib/sanitizeDraft.d.ts +9 -0
- package/dist/admin/lib/sanitizeDraft.js +28 -0
- package/dist/admin/lib/sanitizeDraft.js.map +1 -0
- package/dist/admin/lib/symbolsClient.d.ts +1 -1
- package/dist/admin/lib/symbolsClient.js +3 -3
- package/dist/admin/lib/upload.js +3 -3
- package/dist/admin/lib/useNestedDialog.d.ts +15 -0
- package/dist/admin/lib/useNestedDialog.js +23 -0
- package/dist/admin/lib/useNestedDialog.js.map +1 -0
- package/dist/admin/lib/zodFields.d.ts +4 -18
- package/dist/admin/lib/zodFields.js +54 -35
- package/dist/admin/lib/zodFields.js.map +1 -1
- package/dist/admin/media/MediaManager.js +7 -7
- package/dist/admin/media/MediaPicker.js +7 -7
- package/dist/admin/media/MediaPicker.js.map +1 -1
- package/dist/admin/pages/PageEditor.d.ts +1 -1
- package/dist/admin/pages/PageEditor.js +13 -13
- package/dist/admin/pages/PagesPanel.js +30 -30
- package/dist/admin/pages/PagesPanel.js.map +1 -1
- package/dist/admin/panelRegistry.js +7 -7
- package/dist/admin/patterns/PatternInserter.d.ts +1 -1
- package/dist/admin/patterns/PatternInserter.js +5 -5
- package/dist/admin/patterns/PatternInserter.js.map +1 -1
- package/dist/admin/settings/MailSettings.js +5 -5
- package/dist/admin/settings/MailTemplates.d.ts +1 -1
- package/dist/admin/settings/MailTemplates.js +5 -5
- package/dist/admin/settings/SettingsPanel.js +20 -20
- package/dist/admin/settings/SettingsPanel.js.map +1 -1
- package/dist/admin/settings/SnapshotsCard.js +5 -5
- package/dist/admin/settings/moduleSettingsForm.d.ts +1 -1
- package/dist/admin/settings/moduleSettingsForm.js +4 -4
- package/dist/admin/settings/moduleSettingsForm.js.map +1 -1
- package/dist/admin/shop/CategoriesTab.js +8 -8
- package/dist/admin/shop/ConnectionsTab.js +3 -3
- package/dist/admin/shop/DiscountsTab.js +8 -8
- package/dist/admin/shop/OrdersTab.js +10 -10
- package/dist/admin/shop/OrdersTab.js.map +1 -1
- package/dist/admin/shop/ProductsTab.js +10 -10
- package/dist/admin/shop/ShopPanel.js +9 -9
- package/dist/admin/shop/ShopSettingsTab.js +4 -4
- package/dist/admin/shop/index.d.ts +2 -2
- package/dist/admin/shop/index.js +2 -2
- package/dist/admin/shop/lib.js +2 -2
- package/dist/admin/stats/StatsPanel.js +2 -2
- package/dist/admin/ui/ArrayEditor.js +1 -1
- package/dist/admin/ui/PanelIcon.d.ts +3 -0
- package/dist/admin/ui/PanelIcon.js +34 -0
- package/dist/admin/ui/PanelIcon.js.map +1 -0
- package/dist/admin/ui/dialog.d.ts +21 -6
- package/dist/admin/ui/dialog.js +55 -34
- package/dist/admin/ui/dialog.js.map +1 -1
- package/dist/admin/ui/index.d.ts +7 -7
- package/dist/admin/ui/index.js +7 -7
- package/dist/admin/ui/primitives.js +1 -1
- package/dist/admin/ui/tabs.js +1 -1
- package/dist/admin/visual/TranslationPanel.d.ts +1 -1
- package/dist/admin/visual/TranslationPanel.js +3 -3
- package/dist/admin/visual/VisualEditor.js +47 -25
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/admin.css +2 -1
- package/dist/agentFiles/catalog.d.ts +2 -2
- package/dist/agentFiles/catalog.js +6 -5
- package/dist/agentFiles/catalog.js.map +1 -1
- package/dist/agentFiles/files.d.ts +5 -5
- package/dist/agentFiles/files.js +17 -17
- package/dist/agentFiles/files.js.map +1 -1
- package/dist/all.d.ts +4 -4
- package/dist/all.js +6 -6
- package/dist/auth/AuthProvider.d.ts +2 -2
- package/dist/auth/AuthProvider.js +51 -28
- package/dist/auth/AuthProvider.js.map +1 -1
- package/dist/auth/LoginForm.js +1 -1
- package/dist/auth/roles.js +4 -1
- package/dist/auth/roles.js.map +1 -1
- package/dist/blocks/BlockRenderer.d.ts +1 -1
- package/dist/blocks/BlockRenderer.js +3 -3
- package/dist/blocks/blockStyle.d.ts +1 -1
- package/dist/blocks/builtins/Accordion.d.ts +1 -1
- package/dist/blocks/builtins/Accordion.js +13 -6
- package/dist/blocks/builtins/Accordion.js.map +1 -1
- package/dist/blocks/builtins/Agenda.d.ts +1 -1
- package/dist/blocks/builtins/Agenda.js +5 -5
- package/dist/blocks/builtins/Banner.d.ts +1 -1
- package/dist/blocks/builtins/Banner.js +2 -2
- package/dist/blocks/builtins/BeforeAfter.d.ts +1 -1
- package/dist/blocks/builtins/BeforeAfter.js +4 -4
- package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
- package/dist/blocks/builtins/Booking.d.ts +1 -1
- package/dist/blocks/builtins/Booking.js +5 -5
- package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -1
- package/dist/blocks/builtins/Breadcrumbs.js +3 -3
- package/dist/blocks/builtins/Cards.d.ts +1 -1
- package/dist/blocks/builtins/Cards.js +5 -5
- package/dist/blocks/builtins/Cards.js.map +1 -1
- package/dist/blocks/builtins/Columns.d.ts +1 -1
- package/dist/blocks/builtins/Columns.js +4 -4
- package/dist/blocks/builtins/Contact.d.ts +3 -3
- package/dist/blocks/builtins/Contact.js +4 -4
- package/dist/blocks/builtins/Countdown.d.ts +1 -1
- package/dist/blocks/builtins/Countdown.js +4 -4
- package/dist/blocks/builtins/Countdown.js.map +1 -1
- package/dist/blocks/builtins/Cta.d.ts +1 -1
- package/dist/blocks/builtins/Cta.js +3 -3
- package/dist/blocks/builtins/Downloads.d.ts +1 -1
- package/dist/blocks/builtins/Downloads.js +4 -4
- package/dist/blocks/builtins/Elements.d.ts +3 -3
- package/dist/blocks/builtins/Elements.js +3 -3
- package/dist/blocks/builtins/Embed.d.ts +1 -1
- package/dist/blocks/builtins/Embed.js +3 -3
- package/dist/blocks/builtins/Faq.d.ts +1 -1
- package/dist/blocks/builtins/Faq.js +14 -6
- package/dist/blocks/builtins/Faq.js.map +1 -1
- package/dist/blocks/builtins/FormBlock.d.ts +1 -1
- package/dist/blocks/builtins/FormBlock.js +28 -18
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/Gallery.d.ts +2 -2
- package/dist/blocks/builtins/Gallery.js +5 -5
- package/dist/blocks/builtins/Hero.d.ts +1 -1
- package/dist/blocks/builtins/Hero.js +4 -4
- package/dist/blocks/builtins/ImageBlock.d.ts +1 -1
- package/dist/blocks/builtins/ImageBlock.js +3 -3
- package/dist/blocks/builtins/Jobs.d.ts +2 -2
- package/dist/blocks/builtins/Jobs.js +5 -5
- package/dist/blocks/builtins/Layout.d.ts +2 -2
- package/dist/blocks/builtins/Layout.js +4 -4
- package/dist/blocks/builtins/MapBlock.d.ts +1 -1
- package/dist/blocks/builtins/MapBlock.js +3 -3
- package/dist/blocks/builtins/NewsListBlock.d.ts +1 -1
- package/dist/blocks/builtins/NewsListBlock.js +4 -4
- package/dist/blocks/builtins/Newsletter.d.ts +1 -1
- package/dist/blocks/builtins/Newsletter.js +7 -7
- package/dist/blocks/builtins/Newsletter.js.map +1 -1
- package/dist/blocks/builtins/OpenNowBadge.d.ts +1 -1
- package/dist/blocks/builtins/OpenNowBadge.js +8 -3
- package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
- package/dist/blocks/builtins/OpeningHours.d.ts +1 -1
- package/dist/blocks/builtins/OpeningHours.js +6 -6
- package/dist/blocks/builtins/PdfBlock.d.ts +1 -1
- package/dist/blocks/builtins/PdfBlock.js +3 -3
- package/dist/blocks/builtins/Portfolio.d.ts +1 -1
- package/dist/blocks/builtins/Portfolio.js +5 -5
- package/dist/blocks/builtins/Pricing.d.ts +2 -2
- package/dist/blocks/builtins/Pricing.js +5 -5
- package/dist/blocks/builtins/Pricing.js.map +1 -1
- package/dist/blocks/builtins/RichTextBlock.d.ts +1 -1
- package/dist/blocks/builtins/RichTextBlock.js +2 -2
- package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
- package/dist/blocks/builtins/Search.d.ts +1 -1
- package/dist/blocks/builtins/Search.js +9 -7
- package/dist/blocks/builtins/Search.js.map +1 -1
- package/dist/blocks/builtins/Sections.d.ts +4 -4
- package/dist/blocks/builtins/Sections.js +4 -4
- package/dist/blocks/builtins/Slider.d.ts +1 -1
- package/dist/blocks/builtins/Slider.js +3 -3
- package/dist/blocks/builtins/Spacer.d.ts +1 -1
- package/dist/blocks/builtins/Spacer.js +2 -2
- package/dist/blocks/builtins/SymbolRef.d.ts +1 -1
- package/dist/blocks/builtins/SymbolRef.js +31 -17
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/Team.d.ts +1 -1
- package/dist/blocks/builtins/Team.js +4 -4
- package/dist/blocks/builtins/Testimonials.d.ts +2 -2
- package/dist/blocks/builtins/Testimonials.js +4 -4
- package/dist/blocks/builtins/Video.d.ts +2 -2
- package/dist/blocks/builtins/Video.js +4 -4
- package/dist/blocks/builtins/Video.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChat.d.ts +1 -1
- package/dist/blocks/builtins/WhatsappChat.js +2 -2
- package/dist/blocks/builtins/Widgets.d.ts +12 -12
- package/dist/blocks/builtins/Widgets.js +19 -19
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/consentEmbed.js +2 -2
- package/dist/blocks/builtins/index.d.ts +40 -40
- package/dist/blocks/builtins/index.js +40 -40
- package/dist/blocks/builtins/lib/submitForm.js +5 -3
- package/dist/blocks/builtins/lib/submitForm.js.map +1 -1
- package/dist/blocks/context.d.ts +1 -1
- package/dist/blocks/customTemplate/definition.d.ts +3 -3
- package/dist/blocks/customTemplate/definition.js +6 -6
- package/dist/blocks/customTemplate/definition.js.map +1 -1
- package/dist/blocks/customTemplate/interpret.js +1 -1
- package/dist/blocks/index.d.ts +5 -5
- package/dist/blocks/index.js +5 -5
- package/dist/blocks/registry.d.ts +17 -7
- package/dist/blocks/registry.js +2 -1
- package/dist/blocks/registry.js.map +1 -1
- package/dist/components/EditBar.js +3 -3
- package/dist/components/FeedbackWidget.js +4 -4
- package/dist/components/News.d.ts +1 -1
- package/dist/components/News.js +50 -37
- package/dist/components/News.js.map +1 -1
- package/dist/components/PageView.js +11 -8
- package/dist/components/PageView.js.map +1 -1
- package/dist/components/ResponsiveImage.d.ts +1 -1
- package/dist/components/site/SiteFooter.d.ts +1 -1
- package/dist/components/site/SiteFooter.js +2 -2
- package/dist/config.d.ts +1 -1
- package/dist/demo/DemoStudio.js +3 -3
- package/dist/demo/demoStore.d.ts +3 -3
- package/dist/demo/index.d.ts +2 -2
- package/dist/demo/index.js +2 -2
- package/dist/editor/EditorProvider.js +1 -1
- package/dist/firebase/admin.d.ts +0 -2
- package/dist/firebase/admin.js +0 -6
- package/dist/firebase/admin.js.map +1 -1
- package/dist/firebase/appcheck.d.ts +1 -1
- package/dist/firebase/appcheck.js +5 -3
- package/dist/firebase/appcheck.js.map +1 -1
- package/dist/firebase/client.d.ts +2 -1
- package/dist/firebase/client.js +2 -14
- package/dist/firebase/client.js.map +1 -1
- package/dist/firebase/config.d.ts +31 -0
- package/dist/firebase/config.js +39 -0
- package/dist/firebase/config.js.map +1 -0
- package/dist/firebase/feedback.js +5 -3
- package/dist/firebase/feedback.js.map +1 -1
- package/dist/i18n/overlay.d.ts +2 -2
- package/dist/i18n/overlay.js +6 -4
- package/dist/i18n/overlay.js.map +1 -1
- package/dist/index.d.ts +45 -44
- package/dist/index.js +35 -33
- package/dist/index.js.map +1 -1
- package/dist/lock/DemoLock.js +1 -1
- package/dist/modules/builtins.d.ts +1 -1
- package/dist/modules/builtins.js +53 -55
- package/dist/modules/builtins.js.map +1 -1
- package/dist/modules/consent/ConsentBanner.js +1 -1
- package/dist/modules/consent/useConsent.js +1 -1
- package/dist/modules/context.d.ts +1 -1
- package/dist/modules/contract.d.ts +1 -1
- package/dist/modules/defineModule.d.ts +1 -1
- package/dist/modules/index.d.ts +9 -9
- package/dist/modules/index.js +8 -8
- package/dist/modules/overrides.d.ts +1 -1
- package/dist/modules/registry.d.ts +2 -7
- package/dist/modules/registry.js +2 -1
- package/dist/modules/registry.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.d.ts +1 -1
- package/dist/modules/shop/blocks/Cart.js +6 -6
- package/dist/modules/shop/blocks/Checkout.d.ts +1 -1
- package/dist/modules/shop/blocks/Checkout.js +6 -6
- package/dist/modules/shop/blocks/Donation.d.ts +1 -1
- package/dist/modules/shop/blocks/Donation.js +5 -5
- package/dist/modules/shop/blocks/OrderStatus.d.ts +1 -1
- package/dist/modules/shop/blocks/OrderStatus.js +5 -5
- package/dist/modules/shop/blocks/ProductDetail.d.ts +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +8 -8
- package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -3
- package/dist/modules/shop/blocks/ProductGrid.js +7 -7
- package/dist/modules/shop/blocks/ShopCategories.d.ts +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +6 -6
- package/dist/modules/shop/index.d.ts +5 -5
- package/dist/modules/shop/index.js +5 -5
- package/dist/modules/shop/lib.d.ts +2 -2
- package/dist/modules/shop/lib.js +18 -13
- package/dist/modules/shop/lib.js.map +1 -1
- package/dist/modules/shop/module.d.ts +1 -1
- package/dist/modules/shop/module.js +9 -9
- package/dist/modules/shop/settings.d.ts +18 -50
- package/dist/modules/shop/settings.js +16 -16
- package/dist/modules/shop/settings.js.map +1 -1
- package/dist/modules/shop/strings.js +1 -1
- package/dist/modules/shop/types.d.ts +1 -1
- package/dist/modules/types.d.ts +2 -2
- package/dist/patterns/builtins.d.ts +1 -1
- package/dist/patterns/builtins.js +1 -1
- package/dist/patterns/index.d.ts +2 -2
- package/dist/patterns/index.js +2 -2
- package/dist/render/PageRenderer.d.ts +2 -2
- package/dist/render/PageRenderer.js +1 -1
- package/dist/render/PublishedPage.d.ts +1 -1
- package/dist/render/PublishedPage.js +2 -2
- package/dist/schema/blocks.d.ts +6793 -15095
- package/dist/schema/blocks.js +335 -355
- package/dist/schema/blocks.js.map +1 -1
- package/dist/schema/customBlocks.d.ts +10 -29
- package/dist/schema/customBlocks.js +14 -13
- package/dist/schema/customBlocks.js.map +1 -1
- package/dist/schema/fields.d.ts +10 -16
- package/dist/schema/fields.js +37 -37
- package/dist/schema/fields.js.map +1 -1
- package/dist/schema/forms.d.ts +62 -111
- package/dist/schema/forms.js +17 -17
- package/dist/schema/forms.js.map +1 -1
- package/dist/schema/index.d.ts +7 -7
- package/dist/schema/index.js +7 -7
- package/dist/schema/mail.d.ts +39 -87
- package/dist/schema/mail.js +4 -4
- package/dist/schema/mail.js.map +1 -1
- package/dist/schema/pages.d.ts +152 -674
- package/dist/schema/pages.js +26 -15
- package/dist/schema/pages.js.map +1 -1
- package/dist/schema/seo.d.ts +9 -27
- package/dist/schema/seo.js +7 -7
- package/dist/schema/seo.js.map +1 -1
- package/dist/schema/settings.d.ts +218 -1074
- package/dist/schema/settings.js +55 -55
- package/dist/schema/settings.js.map +1 -1
- package/dist/schema/shop.d.ts +470 -1214
- package/dist/schema/shop.js +124 -124
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/siteConfig.d.ts +73 -597
- package/dist/schema/siteConfig.js +17 -17
- package/dist/schema/siteConfig.js.map +1 -1
- package/dist/schema/symbols.d.ts +34 -191
- package/dist/schema/symbols.js +8 -8
- package/dist/schema/symbols.js.map +1 -1
- package/dist/server/auth.d.ts +17 -0
- package/dist/server/auth.js +11 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/bundle.d.ts +15 -6
- package/dist/server/bundle.js +5 -1
- package/dist/server/bundle.js.map +1 -1
- package/dist/server/draft.d.ts +16 -0
- package/dist/server/draft.js +12 -0
- package/dist/server/draft.js.map +1 -0
- package/dist/server/env.js +8 -8
- package/dist/server/env.js.map +1 -1
- package/dist/server/index.d.ts +10 -8
- package/dist/server/index.js +12 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/pages.d.ts +14 -7
- package/dist/server/pages.js +183 -17
- package/dist/server/pages.js.map +1 -1
- package/dist/server/revalidate.d.ts +6 -0
- package/dist/server/revalidate.js +40 -0
- package/dist/server/revalidate.js.map +1 -0
- package/dist/server/seo.d.ts +3 -3
- package/dist/server/seo.js +1 -1
- package/dist/server/shop.d.ts +3 -3
- package/dist/server/shop.js +6 -3
- package/dist/server/shop.js.map +1 -1
- package/dist/settings/useSiteSettings.d.ts +2 -2
- package/dist/settings/useSiteSettings.js +48 -28
- package/dist/settings/useSiteSettings.js.map +1 -1
- package/dist/styles.css +4 -1
- package/dist/theme/presets.d.ts +1 -1
- package/package.json +35 -34
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { NavItemSchema, ThemeSchema, FormsSenderSchema, ModulesSettingsSchema } from "./settings";
|
|
3
|
-
import { SeoSchema } from "./seo";
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
import { NavItemSchema, ThemeSchema, FormsSenderSchema, ModulesSettingsSchema } from "./settings.js";
|
|
3
|
+
import { SeoSchema } from "./seo.js";
|
|
4
4
|
function defineSiteConfig(config) {
|
|
5
5
|
return config;
|
|
6
6
|
}
|
|
7
|
-
const SiteConfigSchema = z.
|
|
8
|
-
siteId: z.string().
|
|
9
|
-
name: z.string().
|
|
7
|
+
const SiteConfigSchema = z.looseObject({
|
|
8
|
+
siteId: z.string().check(z.minLength(1)).check(z.maxLength(64)).check(z.regex(/^[a-z0-9][a-z0-9-]*$/, "gebruik kleine letters/cijfers/koppeltekens (bv. 'bakkerij-jansen')")),
|
|
9
|
+
name: z.string().check(z.minLength(1)).check(z.maxLength(160)),
|
|
10
10
|
// Alleen een hostname (www.klant.nl) — géén protocol/pad: "https://…/x" glipte er eerst
|
|
11
11
|
// doorheen en werd maar half genormaliseerd in siteOrigin/buildMetadata.
|
|
12
|
-
domain: z.string().
|
|
12
|
+
domain: z.union([z.optional(z.string().check(z.maxLength(255)).check(z.regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/i, "alleen een hostname, bv. 'www.klant.nl' (zonder https:// of pad)"))), z.literal("")]),
|
|
13
13
|
mode: z.enum(["demo", "live"]),
|
|
14
|
-
demoEditing: z.
|
|
15
|
-
lang: z.string().
|
|
16
|
-
locales: z.array(z.string().
|
|
17
|
-
defaultLocale: z.string().
|
|
14
|
+
demoEditing: z.optional(z.boolean()),
|
|
15
|
+
lang: z.optional(z.string().check(z.maxLength(10))),
|
|
16
|
+
locales: z.optional(z.array(z.string().check(z.minLength(2)).check(z.maxLength(10))).check(z.maxLength(10))),
|
|
17
|
+
defaultLocale: z.optional(z.string().check(z.minLength(2)).check(z.maxLength(10))),
|
|
18
18
|
theme: ThemeSchema,
|
|
19
|
-
nav: z.array(NavItemSchema).
|
|
20
|
-
contactEmail: z.
|
|
21
|
-
seoDefaults:
|
|
22
|
-
forms:
|
|
23
|
-
modules:
|
|
24
|
-
})
|
|
19
|
+
nav: z.optional(z.array(NavItemSchema).check(z.maxLength(50))),
|
|
20
|
+
contactEmail: z.optional(z.email()),
|
|
21
|
+
seoDefaults: z.optional(SeoSchema),
|
|
22
|
+
forms: z.optional(FormsSenderSchema),
|
|
23
|
+
modules: z.optional(ModulesSettingsSchema)
|
|
24
|
+
});
|
|
25
25
|
function validateSiteConfig(config) {
|
|
26
26
|
const res = SiteConfigSchema.safeParse(config);
|
|
27
27
|
if (res.success) return [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/schema/siteConfig.ts"],"sourcesContent":["/**\n * SiteConfig — de statische basisconfig in een klantrepo (`content/site.config.ts`).\n * Dit is de fallback/identiteit van de site; bewerkbare instellingen kunnen in Firebase\n * (`sites/{siteId}/settings/site`) staan en deze waarden overschrijven.\n *\n * `@xiwebdesign/xicms-core` bevat hier nooit klantgegevens — die staan in de klantrepo.\n */\nimport
|
|
1
|
+
{"version":3,"sources":["../../src/schema/siteConfig.ts"],"sourcesContent":["/**\n * SiteConfig — de statische basisconfig in een klantrepo (`content/site.config.ts`).\n * Dit is de fallback/identiteit van de site; bewerkbare instellingen kunnen in Firebase\n * (`sites/{siteId}/settings/site`) staan en deze waarden overschrijven.\n *\n * `@xiwebdesign/xicms-core` bevat hier nooit klantgegevens — die staan in de klantrepo.\n */\nimport * as z from \"zod/mini\";\nimport { NavItemSchema, ThemeSchema, FormsSenderSchema, ModulesSettingsSchema, type NavItem, type ThemeTokens, type FormsSender } from \"./settings\";\nimport { SeoSchema, type Seo } from \"./seo\";\nimport type { ModulesSiteConfig } from \"../modules/types\";\n\nexport type SiteMode = \"demo\" | \"live\";\n\nexport interface SiteConfig {\n /** Uniek tenant-id; bepaalt het pad `sites/{siteId}/...` in Firebase. */\n siteId: string;\n /** Weergavenaam van het bedrijf. */\n name: string;\n /** Productiedomein, bv. \"www.bakkerijjansen.nl\". */\n domain?: string;\n /** \"demo\" toont de lock/CTA; \"live\" is de productiestand. */\n mode: SiteMode;\n /**\n * Demo-bewerkmodus: toont een pseudo-login zodat bezoekers het beheer (teksten + blokken) kunnen\n * uitproberen. Alle \"bewerkingen\" blijven UITSLUITEND lokaal in de browser (localStorage) — er gaat\n * niets naar Firebase. Alleen bedoeld voor een demo-site; laat dit `false`/weg op echte klantsites.\n */\n demoEditing?: boolean;\n /** Taalcode voor `<html lang>` en a11y (default \"nl\"). */\n lang?: string;\n /**\n * Extra talen naast de default (5.0), bv. `[\"de\", \"en\"]`. Vertalingen leven als overlay op\n * pagina's/symbolen; niet-default talen krijgen een URL-prefix (`/de/over-ons`). Weglaten =\n * ééntalige site (geen overhead).\n */\n locales?: string[];\n /** Default-taal van de canonieke content (default: `lang` ?? \"nl\"). */\n defaultLocale?: string;\n /** Huisstijl. */\n theme: ThemeTokens;\n /** Hoofdnavigatie. */\n nav?: NavItem[];\n /** Contact-e-mailadres voor de demo-CTA en formulieren. */\n contactEmail?: string;\n /** Standaard-SEO als een pagina niets opgeeft. */\n seoDefaults?: Seo;\n /** Afzender-instelling voor formulier-e-mail (fallback voor settings/site). */\n forms?: FormsSender;\n /**\n * Modules per site aan/uit zetten en configureren (XiCMS 3.0). Een uitgezette module verbergt\n * zowel zijn blocks als zijn beheer-paneel. Per module kun je ook `config` meegeven (gevalideerd\n * tegen het `settingsSchema` van de module) zodat de agent gedrag instelt zonder core te forken:\n *\n * modules: {\n * gallery: { enabled: true, config: { lightbox: true, columns: 3 } },\n * stats: false,\n * }\n *\n * Afwezig = de standaard van de module (`defaultEnabled`, doorgaans aan).\n */\n modules?: ModulesSiteConfig;\n}\n\n/** Helper met type-inferentie voor `site.config.ts`. */\nexport function defineSiteConfig(config: SiteConfig): SiteConfig {\n return config;\n}\n\n/**\n * Runtime-spiegel van de `SiteConfig`-interface. TypeScript vangt fouten bij compileren, maar een\n * (agent-)geschreven `site.config.ts` kan alsnog ongeldige waarden bevatten (verkeerd siteId-formaat,\n * te lange strings, kapotte nav-items). `.passthrough()` zodat extra klant-velden nooit een fout zijn.\n */\nexport const SiteConfigSchema = z.looseObject({\n siteId: z.string().check(z.minLength(1)).check(z.maxLength(64)).check(z.regex(/^[a-z0-9][a-z0-9-]*$/, \"gebruik kleine letters/cijfers/koppeltekens (bv. 'bakkerij-jansen')\")),\n name: z.string().check(z.minLength(1)).check(z.maxLength(160)),\n // Alleen een hostname (www.klant.nl) — géén protocol/pad: \"https://…/x\" glipte er eerst\n // doorheen en werd maar half genormaliseerd in siteOrigin/buildMetadata.\n domain: z.union([z.optional(z.string().check(z.maxLength(255)).check(z.regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/i, \"alleen een hostname, bv. 'www.klant.nl' (zonder https:// of pad)\"))), z.literal(\"\")]),\n mode: z.enum([\"demo\", \"live\"]),\n demoEditing: z.optional(z.boolean()),\n lang: z.optional(z.string().check(z.maxLength(10))),\n locales: z.optional(z.array(z.string().check(z.minLength(2)).check(z.maxLength(10))).check(z.maxLength(10))),\n defaultLocale: z.optional(z.string().check(z.minLength(2)).check(z.maxLength(10))),\n theme: ThemeSchema,\n nav: z.optional(z.array(NavItemSchema).check(z.maxLength(50))),\n contactEmail: z.optional(z.email()),\n seoDefaults: z.optional(SeoSchema),\n forms: z.optional(FormsSenderSchema),\n modules: z.optional(ModulesSettingsSchema),\n });\n\n/**\n * Valideert een SiteConfig en geeft leesbare issues terug (leeg = geldig). Wordt in development\n * door de provider aangeroepen zodat een agent config-fouten direct in de console ziet, in plaats\n * van een subtiel kapotte site. Gooit bewust niet — een issue mag een site nooit platleggen.\n */\nexport function validateSiteConfig(config: unknown): string[] {\n const res = SiteConfigSchema.safeParse(config);\n if (res.success) return [];\n return res.error.issues.map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`);\n}\n"],"mappings":"AAOA,YAAY,OAAO;AACnB,SAAS,eAAe,aAAa,mBAAmB,6BAA+E;AACvI,SAAS,iBAA2B;AAwD7B,SAAS,iBAAiB,QAAgC;AAC/D,SAAO;AACT;AAOO,MAAM,mBAAmB,EAAE,YAAY;AAAA,EAC1C,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,wBAAwB,qEAAqE,CAAC;AAAA,EAC5K,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,EAG7D,QAAQ,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,sEAAsE,kEAAkE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;AAAA,EACxO,MAAM,EAAE,KAAK,CAAC,QAAQ,MAAM,CAAC;AAAA,EAC7B,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,EACnC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAAA,EAClD,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAAA,EAC3G,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAAA,EACjF,OAAO;AAAA,EACP,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAAA,EAC7D,cAAc,EAAE,SAAS,EAAE,MAAM,CAAC;AAAA,EAClC,aAAa,EAAE,SAAS,SAAS;AAAA,EACjC,OAAO,EAAE,SAAS,iBAAiB;AAAA,EACnC,SAAS,EAAE,SAAS,qBAAqB;AAC3C,CAAC;AAOI,SAAS,mBAAmB,QAA2B;AAC5D,QAAM,MAAM,iBAAiB,UAAU,MAAM;AAC7C,MAAI,IAAI,QAAS,QAAO,CAAC;AACzB,SAAO,IAAI,MAAM,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE;AACpF;","names":[]}
|
package/dist/schema/symbols.d.ts
CHANGED
|
@@ -8,197 +8,40 @@
|
|
|
8
8
|
* renderen), schrijven alleen via de `saveSymbol`-callable (sanitize + validatie + audit).
|
|
9
9
|
* Een symbol mag GEEN symbolRef bevatten (geen recursie) — afgedwongen in schema én callable.
|
|
10
10
|
*/
|
|
11
|
-
import
|
|
12
|
-
export declare const SymbolSchema: z.
|
|
13
|
-
name: z.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
_type: z.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
background: z.ZodOptional<z.ZodString>;
|
|
46
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
47
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
48
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
49
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
50
|
-
}, "strip", z.ZodTypeAny, {
|
|
51
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
52
|
-
background?: string | undefined;
|
|
53
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
54
|
-
align?: "left" | "center" | "right" | undefined;
|
|
55
|
-
anchorId?: string | undefined;
|
|
56
|
-
animate?: "fade" | "up" | undefined;
|
|
57
|
-
}, {
|
|
58
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
59
|
-
background?: string | undefined;
|
|
60
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
61
|
-
align?: "left" | "center" | "right" | undefined;
|
|
62
|
-
anchorId?: string | undefined;
|
|
63
|
-
animate?: "fade" | "up" | undefined;
|
|
64
|
-
}>>;
|
|
65
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
66
|
-
_type: z.ZodString;
|
|
67
|
-
_key: z.ZodString;
|
|
68
|
-
_style: z.ZodOptional<z.ZodObject<{
|
|
69
|
-
paddingY: z.ZodOptional<z.ZodEnum<["none", "sm", "md", "lg", "xl"]>>;
|
|
70
|
-
background: z.ZodOptional<z.ZodString>;
|
|
71
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
72
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
73
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
74
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
75
|
-
}, "strip", z.ZodTypeAny, {
|
|
76
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
77
|
-
background?: string | undefined;
|
|
78
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
79
|
-
align?: "left" | "center" | "right" | undefined;
|
|
80
|
-
anchorId?: string | undefined;
|
|
81
|
-
animate?: "fade" | "up" | undefined;
|
|
82
|
-
}, {
|
|
83
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
84
|
-
background?: string | undefined;
|
|
85
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
86
|
-
align?: "left" | "center" | "right" | undefined;
|
|
87
|
-
anchorId?: string | undefined;
|
|
88
|
-
animate?: "fade" | "up" | undefined;
|
|
89
|
-
}>>;
|
|
90
|
-
}, z.ZodTypeAny, "passthrough">>, "many">>, z.objectOutputType<{
|
|
91
|
-
_type: z.ZodString;
|
|
92
|
-
_key: z.ZodString;
|
|
93
|
-
_style: z.ZodOptional<z.ZodObject<{
|
|
94
|
-
paddingY: z.ZodOptional<z.ZodEnum<["none", "sm", "md", "lg", "xl"]>>;
|
|
95
|
-
background: z.ZodOptional<z.ZodString>;
|
|
96
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
97
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
98
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
99
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
100
|
-
}, "strip", z.ZodTypeAny, {
|
|
101
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
102
|
-
background?: string | undefined;
|
|
103
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
104
|
-
align?: "left" | "center" | "right" | undefined;
|
|
105
|
-
anchorId?: string | undefined;
|
|
106
|
-
animate?: "fade" | "up" | undefined;
|
|
107
|
-
}, {
|
|
108
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
109
|
-
background?: string | undefined;
|
|
110
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
111
|
-
align?: "left" | "center" | "right" | undefined;
|
|
112
|
-
anchorId?: string | undefined;
|
|
113
|
-
animate?: "fade" | "up" | undefined;
|
|
114
|
-
}>>;
|
|
115
|
-
}, z.ZodTypeAny, "passthrough">[], z.objectInputType<{
|
|
116
|
-
_type: z.ZodString;
|
|
117
|
-
_key: z.ZodString;
|
|
118
|
-
_style: z.ZodOptional<z.ZodObject<{
|
|
119
|
-
paddingY: z.ZodOptional<z.ZodEnum<["none", "sm", "md", "lg", "xl"]>>;
|
|
120
|
-
background: z.ZodOptional<z.ZodString>;
|
|
121
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
122
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
123
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
124
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
125
|
-
}, "strip", z.ZodTypeAny, {
|
|
126
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
127
|
-
background?: string | undefined;
|
|
128
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
129
|
-
align?: "left" | "center" | "right" | undefined;
|
|
130
|
-
anchorId?: string | undefined;
|
|
131
|
-
animate?: "fade" | "up" | undefined;
|
|
132
|
-
}, {
|
|
133
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
134
|
-
background?: string | undefined;
|
|
135
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
136
|
-
align?: "left" | "center" | "right" | undefined;
|
|
137
|
-
anchorId?: string | undefined;
|
|
138
|
-
animate?: "fade" | "up" | undefined;
|
|
139
|
-
}>>;
|
|
140
|
-
}, z.ZodTypeAny, "passthrough">[] | undefined>;
|
|
141
|
-
/** Taal-overlay (5.0): per locale gepunte veldpaden → vertaalde tekst (zie i18n/overlay.ts). */
|
|
142
|
-
translations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodString>, Record<string, string>, Record<string, string>>>>;
|
|
143
|
-
}, "strip", z.ZodTypeAny, {
|
|
144
|
-
name: string;
|
|
145
|
-
blocks: z.objectOutputType<{
|
|
146
|
-
_type: z.ZodString;
|
|
147
|
-
_key: z.ZodString;
|
|
148
|
-
_style: z.ZodOptional<z.ZodObject<{
|
|
149
|
-
paddingY: z.ZodOptional<z.ZodEnum<["none", "sm", "md", "lg", "xl"]>>;
|
|
150
|
-
background: z.ZodOptional<z.ZodString>;
|
|
151
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
152
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
153
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
154
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
155
|
-
}, "strip", z.ZodTypeAny, {
|
|
156
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
157
|
-
background?: string | undefined;
|
|
158
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
159
|
-
align?: "left" | "center" | "right" | undefined;
|
|
160
|
-
anchorId?: string | undefined;
|
|
161
|
-
animate?: "fade" | "up" | undefined;
|
|
162
|
-
}, {
|
|
163
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
164
|
-
background?: string | undefined;
|
|
165
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
166
|
-
align?: "left" | "center" | "right" | undefined;
|
|
167
|
-
anchorId?: string | undefined;
|
|
168
|
-
animate?: "fade" | "up" | undefined;
|
|
169
|
-
}>>;
|
|
170
|
-
}, z.ZodTypeAny, "passthrough">[];
|
|
171
|
-
translations?: Record<string, Record<string, string>> | undefined;
|
|
172
|
-
}, {
|
|
173
|
-
name: string;
|
|
174
|
-
blocks?: z.objectInputType<{
|
|
175
|
-
_type: z.ZodString;
|
|
176
|
-
_key: z.ZodString;
|
|
177
|
-
_style: z.ZodOptional<z.ZodObject<{
|
|
178
|
-
paddingY: z.ZodOptional<z.ZodEnum<["none", "sm", "md", "lg", "xl"]>>;
|
|
179
|
-
background: z.ZodOptional<z.ZodString>;
|
|
180
|
-
width: z.ZodOptional<z.ZodEnum<["container", "full", "narrow"]>>;
|
|
181
|
-
align: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
|
|
182
|
-
anchorId: z.ZodOptional<z.ZodString>;
|
|
183
|
-
animate: z.ZodOptional<z.ZodEnum<["fade", "up"]>>;
|
|
184
|
-
}, "strip", z.ZodTypeAny, {
|
|
185
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
186
|
-
background?: string | undefined;
|
|
187
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
188
|
-
align?: "left" | "center" | "right" | undefined;
|
|
189
|
-
anchorId?: string | undefined;
|
|
190
|
-
animate?: "fade" | "up" | undefined;
|
|
191
|
-
}, {
|
|
192
|
-
paddingY?: "none" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
193
|
-
background?: string | undefined;
|
|
194
|
-
width?: "container" | "full" | "narrow" | undefined;
|
|
195
|
-
align?: "left" | "center" | "right" | undefined;
|
|
196
|
-
anchorId?: string | undefined;
|
|
197
|
-
animate?: "fade" | "up" | undefined;
|
|
198
|
-
}>>;
|
|
199
|
-
}, z.ZodTypeAny, "passthrough">[] | undefined;
|
|
200
|
-
translations?: Record<string, Record<string, string>> | undefined;
|
|
201
|
-
}>;
|
|
11
|
+
import * as z from "zod/mini";
|
|
12
|
+
export declare const SymbolSchema: z.ZodMiniObject<{
|
|
13
|
+
name: z.ZodMiniString<string>;
|
|
14
|
+
blocks: z.ZodMiniDefault<z.ZodMiniArray<z.ZodMiniObject<{
|
|
15
|
+
_key: z.ZodMiniString<string>;
|
|
16
|
+
_style: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
17
|
+
paddingY: z.ZodMiniOptional<z.ZodMiniEnum<{
|
|
18
|
+
lg: "lg";
|
|
19
|
+
md: "md";
|
|
20
|
+
none: "none";
|
|
21
|
+
sm: "sm";
|
|
22
|
+
xl: "xl";
|
|
23
|
+
}>>;
|
|
24
|
+
background: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
25
|
+
width: z.ZodMiniOptional<z.ZodMiniEnum<{
|
|
26
|
+
container: "container";
|
|
27
|
+
full: "full";
|
|
28
|
+
narrow: "narrow";
|
|
29
|
+
}>>;
|
|
30
|
+
align: z.ZodMiniOptional<z.ZodMiniEnum<{
|
|
31
|
+
center: "center";
|
|
32
|
+
left: "left";
|
|
33
|
+
right: "right";
|
|
34
|
+
}>>;
|
|
35
|
+
anchorId: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
36
|
+
animate: z.ZodMiniOptional<z.ZodMiniEnum<{
|
|
37
|
+
fade: "fade";
|
|
38
|
+
up: "up";
|
|
39
|
+
}>>;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
_type: z.ZodMiniString<string>;
|
|
42
|
+
}, z.core.$loose>>>;
|
|
43
|
+
translations: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniString<string>>>>;
|
|
44
|
+
}, z.core.$strip>;
|
|
202
45
|
export type SymbolDefinition = z.infer<typeof SymbolSchema>;
|
|
203
46
|
export type StoredSymbol = SymbolDefinition & {
|
|
204
47
|
id: string;
|
package/dist/schema/symbols.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { BlockBaseSchema } from "./blocks";
|
|
3
|
-
import { TranslationsSchema } from "../i18n/overlay";
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
import { BlockBaseSchema } from "./blocks.js";
|
|
3
|
+
import { TranslationsSchema } from "../i18n/overlay.js";
|
|
4
4
|
const SymbolSchema = z.object({
|
|
5
|
-
name: z.string().
|
|
5
|
+
name: z.string().check(z.minLength(1)).check(z.maxLength(120)).register(z.globalRegistry, { description: "Naam" }),
|
|
6
6
|
/** De blok-compositie van het symbol (zelfde vorm als page.blocks). */
|
|
7
|
-
blocks: z.array(BlockBaseSchema).
|
|
8
|
-
if (
|
|
9
|
-
ctx.
|
|
7
|
+
blocks: z._default(z.array(BlockBaseSchema).check(z.maxLength(50)), []).check((ctx) => {
|
|
8
|
+
if (ctx.value.some((b) => b._type === "symbolRef")) {
|
|
9
|
+
ctx.issues.push({ code: "custom", input: ctx.value, message: "Een symbool kan geen ander symbool bevatten." });
|
|
10
10
|
}
|
|
11
11
|
}),
|
|
12
12
|
/** Taal-overlay (5.0): per locale gepunte veldpaden → vertaalde tekst (zie i18n/overlay.ts). */
|
|
13
|
-
translations:
|
|
13
|
+
translations: z.optional(TranslationsSchema)
|
|
14
14
|
});
|
|
15
15
|
export {
|
|
16
16
|
SymbolSchema
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/schema/symbols.ts"],"sourcesContent":["/**\n * Symbols (5.0, primo-concept): een symbol is een benoemde, gedeelde sectie — een compositie van\n * gewone blokken — die op meerdere pagina's als **referentie** wordt ingevoegd (`symbolRef`-blok).\n * Wijzig het symbol → alle pagina's die ernaar verwijzen bewegen mee (i.t.t. patterns, die bij\n * invoegen worden gekloond). \"Loskoppelen\" in de editor zet een referentie om in een kloon.\n *\n * Opslag: `sites/{siteId}/symbols/{symbolId}` — publiek leesbaar (de live site leest ze bij het\n * renderen), schrijven alleen via de `saveSymbol`-callable (sanitize + validatie + audit).\n * Een symbol mag GEEN symbolRef bevatten (geen recursie) — afgedwongen in schema én callable.\n */\nimport
|
|
1
|
+
{"version":3,"sources":["../../src/schema/symbols.ts"],"sourcesContent":["/**\n * Symbols (5.0, primo-concept): een symbol is een benoemde, gedeelde sectie — een compositie van\n * gewone blokken — die op meerdere pagina's als **referentie** wordt ingevoegd (`symbolRef`-blok).\n * Wijzig het symbol → alle pagina's die ernaar verwijzen bewegen mee (i.t.t. patterns, die bij\n * invoegen worden gekloond). \"Loskoppelen\" in de editor zet een referentie om in een kloon.\n *\n * Opslag: `sites/{siteId}/symbols/{symbolId}` — publiek leesbaar (de live site leest ze bij het\n * renderen), schrijven alleen via de `saveSymbol`-callable (sanitize + validatie + audit).\n * Een symbol mag GEEN symbolRef bevatten (geen recursie) — afgedwongen in schema én callable.\n */\nimport * as z from \"zod/mini\";\nimport { BlockBaseSchema } from \"./blocks\";\nimport { TranslationsSchema } from \"../i18n/overlay\";\n\nexport const SymbolSchema = z.object({\n name: z.string().check(z.minLength(1)).check(z.maxLength(120)).register(z.globalRegistry, { description: \"Naam\" }),\n /** De blok-compositie van het symbol (zelfde vorm als page.blocks). */\n blocks: z._default(z.array(BlockBaseSchema).check(z.maxLength(50)), []).check((ctx) => {\n if (ctx.value.some((b) => b._type === \"symbolRef\")) {\n ctx.issues.push({ code: \"custom\", input: ctx.value, message: \"Een symbool kan geen ander symbool bevatten.\" });\n }\n }),\n /** Taal-overlay (5.0): per locale gepunte veldpaden → vertaalde tekst (zie i18n/overlay.ts). */\n translations: z.optional(TranslationsSchema),\n});\n// \"SymbolDefinition\", niet \"Symbol\": dat schaduwde de JS-global Symbol in elke consumer-import.\nexport type SymbolDefinition = z.infer<typeof SymbolSchema>;\nexport type StoredSymbol = SymbolDefinition & { id: string };\n"],"mappings":"AAUA,YAAY,OAAO;AACnB,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AAE5B,MAAM,eAAe,EAAE,OAAO;AAAA,EACnC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,OAAO,CAAC;AAAA;AAAA,EAEjH,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ;AACnF,QAAI,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,WAAW,GAAG;AAClD,UAAI,OAAO,KAAK,EAAE,MAAM,UAAU,OAAO,IAAI,OAAO,SAAS,+CAA+C,CAAC;AAAA,IAC/G;AAAA,EACF,CAAC;AAAA;AAAA,EAEH,cAAc,EAAE,SAAS,kBAAkB;AAC7C,CAAC;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
import { type Auth } from "firebase-admin/auth";
|
|
3
|
+
/**
|
|
4
|
+
* Server-side Firebase Auth (Admin SDK) — opt-in via de subpath
|
|
5
|
+
* `@xiwebdesign/xicms-core/server/auth`.
|
|
6
|
+
*
|
|
7
|
+
* WAAROM EEN APARTE SUBPATH EN NIET IN `/server`: `firebase-admin/auth` trekt `jwks-rsa` aan, die
|
|
8
|
+
* `require("jose")` doet terwijl jose 6 puur ESM is. Turbopack laadt externals strikt als CJS, dus
|
|
9
|
+
* zodra deze tak in een route-bundel belandt eindigt élke server-render in
|
|
10
|
+
* `ERR_REQUIRE_ESM` → HTTP 500. Dat trof publieke pagina's die niets met auth te maken hebben,
|
|
11
|
+
* puur omdat `server/pages.ts` uit hetzelfde bestand `getAdminDb` importeerde. Gemeten op de
|
|
12
|
+
* staging-deploy van groenhof: geprerenderde pagina's 200, élke on-demand render 500.
|
|
13
|
+
*
|
|
14
|
+
* Zelfde patroon als `@xiwebdesign/xicms-core/server/shop`: wie het nodig heeft importeert het
|
|
15
|
+
* expliciet, de rest draagt het niet mee.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getAdminAuth(): Auth | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
import { getAuth } from "firebase-admin/auth";
|
|
3
|
+
import { getAdminApp } from "../firebase/admin.js";
|
|
4
|
+
function getAdminAuth() {
|
|
5
|
+
const app = getAdminApp();
|
|
6
|
+
return app ? getAuth(app) : null;
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
getAdminAuth
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/auth.ts"],"sourcesContent":["import \"server-only\";\n\nimport { getAuth, type Auth } from \"firebase-admin/auth\";\nimport { getAdminApp } from \"../firebase/admin\";\n\n/**\n * Server-side Firebase Auth (Admin SDK) — opt-in via de subpath\n * `@xiwebdesign/xicms-core/server/auth`.\n *\n * WAAROM EEN APARTE SUBPATH EN NIET IN `/server`: `firebase-admin/auth` trekt `jwks-rsa` aan, die\n * `require(\"jose\")` doet terwijl jose 6 puur ESM is. Turbopack laadt externals strikt als CJS, dus\n * zodra deze tak in een route-bundel belandt eindigt élke server-render in\n * `ERR_REQUIRE_ESM` → HTTP 500. Dat trof publieke pagina's die niets met auth te maken hebben,\n * puur omdat `server/pages.ts` uit hetzelfde bestand `getAdminDb` importeerde. Gemeten op de\n * staging-deploy van groenhof: geprerenderde pagina's 200, élke on-demand render 500.\n *\n * Zelfde patroon als `@xiwebdesign/xicms-core/server/shop`: wie het nodig heeft importeert het\n * expliciet, de rest draagt het niet mee.\n */\nexport function getAdminAuth(): Auth | null {\n const app = getAdminApp();\n return app ? getAuth(app) : null;\n}\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,eAA0B;AACnC,SAAS,mBAAmB;AAgBrB,SAAS,eAA4B;AAC1C,QAAM,MAAM,YAAY;AACxB,SAAO,MAAM,QAAQ,GAAG,IAAI;AAC9B;","names":[]}
|
package/dist/server/bundle.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "server-only";
|
|
2
|
-
import type { Page } from "../schema/pages";
|
|
3
|
-
import type { StoredSymbol } from "../schema/symbols";
|
|
4
|
-
import type { CustomBlock } from "../schema/customBlocks";
|
|
5
|
-
import type { PublicSiteSettings } from "../schema/settings";
|
|
6
|
-
import type { NewsArticle } from "../content/types";
|
|
2
|
+
import type { Page } from "../schema/pages.js";
|
|
3
|
+
import type { StoredSymbol } from "../schema/symbols.js";
|
|
4
|
+
import type { CustomBlock } from "../schema/customBlocks.js";
|
|
5
|
+
import type { PublicSiteSettings } from "../schema/settings.js";
|
|
6
|
+
import type { NewsArticle } from "../content/types.js";
|
|
7
7
|
/**
|
|
8
8
|
* BUILD-TIME content-bundle READER (5.7).
|
|
9
9
|
*
|
|
@@ -54,7 +54,16 @@ export declare const getBundle: typeof readBundle;
|
|
|
54
54
|
export declare function getBundlePage(bundle: PublishedBundle, pagePath: string): (Page & {
|
|
55
55
|
id: string;
|
|
56
56
|
}) | null;
|
|
57
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Gepubliceerd nieuws uit de bundle, aflopend op datum (spiegelt de Firestore `orderBy(date,desc)`).
|
|
59
|
+
*
|
|
60
|
+
* `bodyHtml` wordt hier SERVER-SIDE gesaneerd. Nieuws is de enige publieke content die editors
|
|
61
|
+
* rechtstreeks naar Firestore schrijven — er is geen publiceer-callable die `sanitizeBlocks`
|
|
62
|
+
* draait, zoals bij pagina's. Tot nu toe was DOMPurify in de browser de enige verdediging, wat
|
|
63
|
+
* betekende dat de opmaak pas ná hydratie verscheen: een crawler zag alleen kale tekst, en de
|
|
64
|
+
* lezer een layoutverschuiving. Door hier te saneren is de bundle-inhoud te vertrouwen én direct
|
|
65
|
+
* in de SSR-HTML te renderen (zie NewsArticleView).
|
|
66
|
+
*/
|
|
58
67
|
export declare function getBundleNews(bundle: PublishedBundle): NewsArticle[];
|
|
59
68
|
/**
|
|
60
69
|
* Server-side nieuwsdata voor de publieke nieuws-routes: geef het resultaat door als
|
package/dist/server/bundle.js
CHANGED
|
@@ -2,6 +2,7 @@ import "server-only";
|
|
|
2
2
|
import { cache } from "react";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "path";
|
|
5
|
+
import { sanitizeRichText } from "./sanitize.js";
|
|
5
6
|
const BUNDLE_PATH = "content/published.bundle.json";
|
|
6
7
|
function revive(v) {
|
|
7
8
|
if (v === null || typeof v !== "object") return v;
|
|
@@ -49,7 +50,10 @@ function getBundlePage(bundle, pagePath) {
|
|
|
49
50
|
return bundle.pages.find((p) => p.path === pagePath) ?? null;
|
|
50
51
|
}
|
|
51
52
|
function getBundleNews(bundle) {
|
|
52
|
-
return [...bundle.news].filter((n) => n.published !== false).sort((a, b) => String(b.date ?? "").localeCompare(String(a.date ?? "")))
|
|
53
|
+
return [...bundle.news].filter((n) => n.published !== false).sort((a, b) => String(b.date ?? "").localeCompare(String(a.date ?? ""))).map((n) => {
|
|
54
|
+
const raw = n.bodyHtml;
|
|
55
|
+
return typeof raw === "string" ? { ...n, bodyHtml: sanitizeRichText(raw) } : n;
|
|
56
|
+
});
|
|
53
57
|
}
|
|
54
58
|
function getNewsPageData(siteId) {
|
|
55
59
|
const bundle = getBundle();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/bundle.ts"],"sourcesContent":["import \"server-only\";\n\nimport { cache } from \"react\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport type { Page } from \"../schema/pages\";\nimport type { StoredSymbol } from \"../schema/symbols\";\nimport type { CustomBlock } from \"../schema/customBlocks\";\nimport type { PublicSiteSettings } from \"../schema/settings\";\nimport type { NewsArticle } from \"../content/types\";\n\n/**\n * BUILD-TIME content-bundle READER (5.7).\n *\n * Een klantsite kan de GEPUBLICEERDE, publiek-veilige stand van zijn site lezen uit één\n * gecommit JSON-bestand (`content/published.bundle.json`, in de repo-root) i.p.v. uit Firestore.\n * De Cloud-Function-worker schrijft dat bestand bij elke publicatie en committeert het; een verse\n * build/rebuild heeft dan Firebase NOCH Firestore nodig — puur statische data.\n *\n * Contract: server/pages.ts leest bundle-first. Is er een bundle → serveer daaruit (zelfde\n * return-vormen als de Firestore-readers). Is er GEEN bundle (dev/lokaal, of een repo zonder\n * gecommit bundle) → val ongewijzigd terug op het Admin-SDK / keyless-REST-pad. De reader hier\n * gooit NOOIT: een ontbrekend/leeg/corrupt bestand levert `null` (met één regel warn), zodat de\n * Firestore-fallback het overneemt.\n *\n * De bundle-vorm moet 1-op-1 matchen met de writer (functions/src/lib/bundle.ts).\n */\n\n/** Eén bundle-item: doc-id samengevoegd met (gesaneerde) doc-data. */\nexport type BundleItem = { id: string } & Record<string, unknown>;\n\n/** Canonieke, PUBLIEKE bundle-vorm. Moet 1-op-1 matchen met de writer. */\nexport interface PublishedBundle {\n version: 1;\n siteId: string;\n generatedAt: string; // ISO\n /** = sites/{siteId}/settings/public (PublicSiteSettings-vorm), of null. */\n settings: (PublicSiteSettings & Record<string, unknown>) | null;\n /** ALLEEN gepubliceerde pagina's (status === \"published\"). */\n pages: Array<Page & { id: string }>;\n symbols: Array<StoredSymbol>;\n customBlocks: Array<CustomBlock & { id: string }>;\n /** ALLEEN gepubliceerd nieuws (published === true). */\n news: Array<{ id: string } & Record<string, unknown>>;\n}\n\n/** Pad naar het gecommit bundle-bestand, relatief aan de repo-root (process.cwd() bij build/render). */\nconst BUNDLE_PATH = \"content/published.bundle.json\";\n\n/**\n * Serialiseert nog-niet-ge-ISO'de Firestore-Timestamps ({_seconds,_nanoseconds}) alsnog naar ISO.\n * De writer doet dit al, maar de reader blijft defensief: zo kan een handmatig/ouder bundle-bestand\n * geen zod-validatie breken. Recursief, referentie-behoudend is niet nodig (eenmalige read).\n */\nfunction revive(v: unknown): unknown {\n if (v === null || typeof v !== \"object\") return v;\n if (Array.isArray(v)) return v.map(revive);\n const o = v as Record<string, unknown>;\n if (typeof o._seconds === \"number\" && typeof o._nanoseconds === \"number\") {\n return new Date(o._seconds * 1000 + Math.round(o._nanoseconds / 1e6)).toISOString();\n }\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(o)) out[k] = revive(val);\n return out;\n}\n\nfunction readBundle(): PublishedBundle | null {\n const file = path.join(process.cwd(), BUNDLE_PATH);\n let raw: string;\n try {\n raw = fs.readFileSync(file, \"utf8\");\n } catch {\n // Geen bestand = geen bundle: doodnormaal in dev/lokaal → stil de Firestore-fallback laten winnen.\n return null;\n }\n if (!raw.trim()) return null;\n try {\n const parsed = revive(JSON.parse(raw)) as Partial<PublishedBundle>;\n if (!parsed || parsed.version !== 1 || typeof parsed.siteId !== \"string\") {\n console.warn(`[xicms] ${BUNDLE_PATH} heeft een onbekende vorm (version/siteId) — Firestore-fallback wordt gebruikt.`);\n return null;\n }\n // Normaliseer de collecties naar arrays (defensief tegen een half-geschreven bestand).\n return {\n version: 1,\n siteId: parsed.siteId,\n generatedAt: typeof parsed.generatedAt === \"string\" ? parsed.generatedAt : \"\",\n settings: (parsed.settings as PublishedBundle[\"settings\"]) ?? null,\n pages: Array.isArray(parsed.pages) ? parsed.pages : [],\n symbols: Array.isArray(parsed.symbols) ? parsed.symbols : [],\n customBlocks: Array.isArray(parsed.customBlocks) ? parsed.customBlocks : [],\n news: Array.isArray(parsed.news) ? parsed.news : [],\n };\n } catch (err) {\n console.warn(`[xicms] ${BUNDLE_PATH} kon niet geparsed worden — Firestore-fallback wordt gebruikt:`, (err as Error)?.message ?? err);\n return null;\n }\n}\n\n/**\n * De gecommit content-bundle, of `null` als er geen (bruikbaar) bestand is. Per render-pass één keer\n * gelezen (React `cache()`), zodat alle bundle-first readers dezelfde in-memory kopie delen.\n */\nexport const getBundle = cache(readBundle);\n\n/** Pad-matching gelijk aan server/pages.ts (`path`-veld exact). */\nexport function getBundlePage(bundle: PublishedBundle, pagePath: string): (Page & { id: string }) | null {\n return bundle.pages.find((p) => p.path === pagePath) ?? null;\n}\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/server/bundle.ts"],"sourcesContent":["import \"server-only\";\n\nimport { cache } from \"react\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport type { Page } from \"../schema/pages\";\nimport type { StoredSymbol } from \"../schema/symbols\";\nimport type { CustomBlock } from \"../schema/customBlocks\";\nimport type { PublicSiteSettings } from \"../schema/settings\";\nimport { sanitizeRichText } from \"./sanitize\";\nimport type { NewsArticle } from \"../content/types\";\n\n/**\n * BUILD-TIME content-bundle READER (5.7).\n *\n * Een klantsite kan de GEPUBLICEERDE, publiek-veilige stand van zijn site lezen uit één\n * gecommit JSON-bestand (`content/published.bundle.json`, in de repo-root) i.p.v. uit Firestore.\n * De Cloud-Function-worker schrijft dat bestand bij elke publicatie en committeert het; een verse\n * build/rebuild heeft dan Firebase NOCH Firestore nodig — puur statische data.\n *\n * Contract: server/pages.ts leest bundle-first. Is er een bundle → serveer daaruit (zelfde\n * return-vormen als de Firestore-readers). Is er GEEN bundle (dev/lokaal, of een repo zonder\n * gecommit bundle) → val ongewijzigd terug op het Admin-SDK / keyless-REST-pad. De reader hier\n * gooit NOOIT: een ontbrekend/leeg/corrupt bestand levert `null` (met één regel warn), zodat de\n * Firestore-fallback het overneemt.\n *\n * De bundle-vorm moet 1-op-1 matchen met de writer (functions/src/lib/bundle.ts).\n */\n\n/** Eén bundle-item: doc-id samengevoegd met (gesaneerde) doc-data. */\nexport type BundleItem = { id: string } & Record<string, unknown>;\n\n/** Canonieke, PUBLIEKE bundle-vorm. Moet 1-op-1 matchen met de writer. */\nexport interface PublishedBundle {\n version: 1;\n siteId: string;\n generatedAt: string; // ISO\n /** = sites/{siteId}/settings/public (PublicSiteSettings-vorm), of null. */\n settings: (PublicSiteSettings & Record<string, unknown>) | null;\n /** ALLEEN gepubliceerde pagina's (status === \"published\"). */\n pages: Array<Page & { id: string }>;\n symbols: Array<StoredSymbol>;\n customBlocks: Array<CustomBlock & { id: string }>;\n /** ALLEEN gepubliceerd nieuws (published === true). */\n news: Array<{ id: string } & Record<string, unknown>>;\n}\n\n/** Pad naar het gecommit bundle-bestand, relatief aan de repo-root (process.cwd() bij build/render). */\nconst BUNDLE_PATH = \"content/published.bundle.json\";\n\n/**\n * Serialiseert nog-niet-ge-ISO'de Firestore-Timestamps ({_seconds,_nanoseconds}) alsnog naar ISO.\n * De writer doet dit al, maar de reader blijft defensief: zo kan een handmatig/ouder bundle-bestand\n * geen zod-validatie breken. Recursief, referentie-behoudend is niet nodig (eenmalige read).\n */\nfunction revive(v: unknown): unknown {\n if (v === null || typeof v !== \"object\") return v;\n if (Array.isArray(v)) return v.map(revive);\n const o = v as Record<string, unknown>;\n if (typeof o._seconds === \"number\" && typeof o._nanoseconds === \"number\") {\n return new Date(o._seconds * 1000 + Math.round(o._nanoseconds / 1e6)).toISOString();\n }\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(o)) out[k] = revive(val);\n return out;\n}\n\nfunction readBundle(): PublishedBundle | null {\n const file = path.join(process.cwd(), BUNDLE_PATH);\n let raw: string;\n try {\n raw = fs.readFileSync(file, \"utf8\");\n } catch {\n // Geen bestand = geen bundle: doodnormaal in dev/lokaal → stil de Firestore-fallback laten winnen.\n return null;\n }\n if (!raw.trim()) return null;\n try {\n const parsed = revive(JSON.parse(raw)) as Partial<PublishedBundle>;\n if (!parsed || parsed.version !== 1 || typeof parsed.siteId !== \"string\") {\n console.warn(`[xicms] ${BUNDLE_PATH} heeft een onbekende vorm (version/siteId) — Firestore-fallback wordt gebruikt.`);\n return null;\n }\n // Normaliseer de collecties naar arrays (defensief tegen een half-geschreven bestand).\n return {\n version: 1,\n siteId: parsed.siteId,\n generatedAt: typeof parsed.generatedAt === \"string\" ? parsed.generatedAt : \"\",\n settings: (parsed.settings as PublishedBundle[\"settings\"]) ?? null,\n pages: Array.isArray(parsed.pages) ? parsed.pages : [],\n symbols: Array.isArray(parsed.symbols) ? parsed.symbols : [],\n customBlocks: Array.isArray(parsed.customBlocks) ? parsed.customBlocks : [],\n news: Array.isArray(parsed.news) ? parsed.news : [],\n };\n } catch (err) {\n console.warn(`[xicms] ${BUNDLE_PATH} kon niet geparsed worden — Firestore-fallback wordt gebruikt:`, (err as Error)?.message ?? err);\n return null;\n }\n}\n\n/**\n * De gecommit content-bundle, of `null` als er geen (bruikbaar) bestand is. Per render-pass één keer\n * gelezen (React `cache()`), zodat alle bundle-first readers dezelfde in-memory kopie delen.\n */\nexport const getBundle = cache(readBundle);\n\n/** Pad-matching gelijk aan server/pages.ts (`path`-veld exact). */\nexport function getBundlePage(bundle: PublishedBundle, pagePath: string): (Page & { id: string }) | null {\n return bundle.pages.find((p) => p.path === pagePath) ?? null;\n}\n\n/**\n * Gepubliceerd nieuws uit de bundle, aflopend op datum (spiegelt de Firestore `orderBy(date,desc)`).\n *\n * `bodyHtml` wordt hier SERVER-SIDE gesaneerd. Nieuws is de enige publieke content die editors\n * rechtstreeks naar Firestore schrijven — er is geen publiceer-callable die `sanitizeBlocks`\n * draait, zoals bij pagina's. Tot nu toe was DOMPurify in de browser de enige verdediging, wat\n * betekende dat de opmaak pas ná hydratie verscheen: een crawler zag alleen kale tekst, en de\n * lezer een layoutverschuiving. Door hier te saneren is de bundle-inhoud te vertrouwen én direct\n * in de SSR-HTML te renderen (zie NewsArticleView).\n */\nexport function getBundleNews(bundle: PublishedBundle): NewsArticle[] {\n return [...bundle.news]\n .filter((n) => (n as { published?: unknown }).published !== false)\n .sort((a, b) => String(b.date ?? \"\").localeCompare(String(a.date ?? \"\")))\n .map((n) => {\n const raw = (n as { bodyHtml?: unknown }).bodyHtml;\n return typeof raw === \"string\" ? { ...n, bodyHtml: sanitizeRichText(raw) } : n;\n }) as unknown as NewsArticle[];\n}\n\n/**\n * Server-side nieuwsdata voor de publieke nieuws-routes: geef het resultaat door als\n * `<BlockDataProvider data={{ news }}>` zodat `useNews`/`NewsList` uit de bundle renderen (SSR,\n * geen browser-Firestore-read). Geeft `null` als er geen bundle (voor deze site) is — dan valt\n * `useNews` terug op zijn eigen Firestore-pad (admin/preview/dev, ongewijzigd gedrag).\n */\nexport function getNewsPageData(siteId: string): NewsArticle[] | null {\n const bundle = getBundle();\n if (!bundle || bundle.siteId !== siteId) return null;\n return getBundleNews(bundle);\n}\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,aAAa;AACtB,OAAO,QAAQ;AACf,OAAO,UAAU;AAMjB,SAAS,wBAAwB;AAuCjC,MAAM,cAAc;AAOpB,SAAS,OAAO,GAAqB;AACnC,MAAI,MAAM,QAAQ,OAAO,MAAM,SAAU,QAAO;AAChD,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,IAAI,MAAM;AACzC,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,aAAa,YAAY,OAAO,EAAE,iBAAiB,UAAU;AACxE,WAAO,IAAI,KAAK,EAAE,WAAW,MAAO,KAAK,MAAM,EAAE,eAAe,GAAG,CAAC,EAAE,YAAY;AAAA,EACpF;AACA,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,CAAC,EAAG,KAAI,CAAC,IAAI,OAAO,GAAG;AAC7D,SAAO;AACT;AAEA,SAAS,aAAqC;AAC5C,QAAM,OAAO,KAAK,KAAK,QAAQ,IAAI,GAAG,WAAW;AACjD,MAAI;AACJ,MAAI;AACF,UAAM,GAAG,aAAa,MAAM,MAAM;AAAA,EACpC,QAAQ;AAEN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,IAAI,KAAK,EAAG,QAAO;AACxB,MAAI;AACF,UAAM,SAAS,OAAO,KAAK,MAAM,GAAG,CAAC;AACrC,QAAI,CAAC,UAAU,OAAO,YAAY,KAAK,OAAO,OAAO,WAAW,UAAU;AACxE,cAAQ,KAAK,WAAW,WAAW,sFAAiF;AACpH,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc;AAAA,MAC3E,UAAW,OAAO,YAA4C;AAAA,MAC9D,OAAO,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC;AAAA,MACrD,SAAS,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAAA,MAC3D,cAAc,MAAM,QAAQ,OAAO,YAAY,IAAI,OAAO,eAAe,CAAC;AAAA,MAC1E,MAAM,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC;AAAA,IACpD;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,KAAK,WAAW,WAAW,uEAAmE,KAAe,WAAW,GAAG;AACnI,WAAO;AAAA,EACT;AACF;AAMO,MAAM,YAAY,MAAM,UAAU;AAGlC,SAAS,cAAc,QAAyB,UAAkD;AACvG,SAAO,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,KAAK;AAC1D;AAYO,SAAS,cAAc,QAAwC;AACpE,SAAO,CAAC,GAAG,OAAO,IAAI,EACnB,OAAO,CAAC,MAAO,EAA8B,cAAc,KAAK,EAChE,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,cAAc,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,EACvE,IAAI,CAAC,MAAM;AACV,UAAM,MAAO,EAA6B;AAC1C,WAAO,OAAO,QAAQ,WAAW,EAAE,GAAG,GAAG,UAAU,iBAAiB,GAAG,EAAE,IAAI;AAAA,EAC/E,CAAC;AACL;AAQO,SAAS,gBAAgB,QAAsC;AACpE,QAAM,SAAS,UAAU;AACzB,MAAI,CAAC,UAAU,OAAO,WAAW,OAAQ,QAAO;AAChD,SAAO,cAAc,MAAM;AAC7B;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zet Next's Draft Mode aan of uit voor de huidige browser. Aangeroepen door `PreviewDraftSync`
|
|
3
|
+
* (XiCMSProvider) zodra een editor in- of uitlogt: `POST /api/draft?aan=1` respectievelijk `?aan=0`.
|
|
4
|
+
*
|
|
5
|
+
* WAAROM DIT MOET: Draft Mode werkt via de ondertekende `__prerender_bypass`-cookie, en die kan
|
|
6
|
+
* alleen de server zetten — `document.cookie` op de client komt er niet aan. Precies dat maakt het
|
|
7
|
+
* beter dan de eigen preview-cookie die hiervoor gebruikt werd: Next controleert deze cookie VÓÓR
|
|
8
|
+
* de cache, buiten de route om, dus de pagina-route hoeft niets dynamisch te lezen en blijft voor
|
|
9
|
+
* publiek gewoon statisch geprerenderd.
|
|
10
|
+
*
|
|
11
|
+
* Draagt geen rechten: preview toont nooit meer dan de al-gepubliceerde content, dus wie deze route
|
|
12
|
+
* zelf aanroept ziet hoogstens een verse versie van iets dat toch al openbaar is. Wat het wél kost
|
|
13
|
+
* is een ongecachte render (en dus een Firestore-read) per request van die browser. Wil je dat
|
|
14
|
+
* afsluiten, verifieer dan hier een Firebase-ID-token vóór `enable()`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function draftPOST(req: Request): Promise<Response>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { draftMode } from "next/headers";
|
|
2
|
+
async function draftPOST(req) {
|
|
3
|
+
const aan = new URL(req.url).searchParams.get("aan") !== "0";
|
|
4
|
+
const dm = await draftMode();
|
|
5
|
+
if (aan) dm.enable();
|
|
6
|
+
else dm.disable();
|
|
7
|
+
return new Response(null, { status: 204 });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
draftPOST
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=draft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/draft.ts"],"sourcesContent":["import { draftMode } from \"next/headers\";\n\n/**\n * Zet Next's Draft Mode aan of uit voor de huidige browser. Aangeroepen door `PreviewDraftSync`\n * (XiCMSProvider) zodra een editor in- of uitlogt: `POST /api/draft?aan=1` respectievelijk `?aan=0`.\n *\n * WAAROM DIT MOET: Draft Mode werkt via de ondertekende `__prerender_bypass`-cookie, en die kan\n * alleen de server zetten — `document.cookie` op de client komt er niet aan. Precies dat maakt het\n * beter dan de eigen preview-cookie die hiervoor gebruikt werd: Next controleert deze cookie VÓÓR\n * de cache, buiten de route om, dus de pagina-route hoeft niets dynamisch te lezen en blijft voor\n * publiek gewoon statisch geprerenderd.\n *\n * Draagt geen rechten: preview toont nooit meer dan de al-gepubliceerde content, dus wie deze route\n * zelf aanroept ziet hoogstens een verse versie van iets dat toch al openbaar is. Wat het wél kost\n * is een ongecachte render (en dus een Firestore-read) per request van die browser. Wil je dat\n * afsluiten, verifieer dan hier een Firebase-ID-token vóór `enable()`.\n */\nexport async function draftPOST(req: Request): Promise<Response> {\n const aan = new URL(req.url).searchParams.get(\"aan\") !== \"0\";\n const dm = await draftMode();\n if (aan) dm.enable();\n else dm.disable();\n return new Response(null, { status: 204 });\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAiB1B,eAAsB,UAAU,KAAiC;AAC/D,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG,EAAE,aAAa,IAAI,KAAK,MAAM;AACzD,QAAM,KAAK,MAAM,UAAU;AAC3B,MAAI,IAAK,IAAG,OAAO;AAAA,MACd,IAAG,QAAQ;AAChB,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAC3C;","names":[]}
|
package/dist/server/env.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "server-only";
|
|
2
|
-
import
|
|
2
|
+
import * as z from "zod/mini";
|
|
3
3
|
const EnvSchema = z.object({
|
|
4
|
-
NEXT_PUBLIC_FIREBASE_API_KEY: z.string().
|
|
5
|
-
NEXT_PUBLIC_FIREBASE_PROJECT_ID: z.string().
|
|
6
|
-
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: z.
|
|
7
|
-
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: z.
|
|
8
|
-
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: z.
|
|
9
|
-
NEXT_PUBLIC_FIREBASE_APP_ID: z.
|
|
10
|
-
NEXT_PUBLIC_FIREBASE_FUNCTIONS_REGION: z.
|
|
4
|
+
NEXT_PUBLIC_FIREBASE_API_KEY: z.optional(z.string().check(z.minLength(1))),
|
|
5
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID: z.optional(z.string().check(z.minLength(1))),
|
|
6
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: z.optional(z.string()),
|
|
7
|
+
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: z.optional(z.string()),
|
|
8
|
+
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: z.optional(z.string()),
|
|
9
|
+
NEXT_PUBLIC_FIREBASE_APP_ID: z.optional(z.string()),
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_FUNCTIONS_REGION: z.optional(z.string())
|
|
11
11
|
});
|
|
12
12
|
function validateEnv(env = process.env) {
|
|
13
13
|
const problems = [];
|
package/dist/server/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/env.ts"],"sourcesContent":["import \"server-only\";\n\nimport
|
|
1
|
+
{"version":3,"sources":["../../src/server/env.ts"],"sourcesContent":["import \"server-only\";\n\nimport * as z from \"zod/mini\";\n\n/**\n * Env-validatie — vangt ontbrekende/foute Firebase-config vroeg (bij build/serverstart) i.p.v.\n * een cryptische runtime-fout later. Roep `validateEnv()` aan in een server-context (bv. de\n * sitemap-route of een instrumentation-hook). `assertEnv()` gooit; `validateEnv()` rapporteert.\n */\nconst EnvSchema = z.object({\n NEXT_PUBLIC_FIREBASE_API_KEY: z.optional(z.string().check(z.minLength(1))),\n NEXT_PUBLIC_FIREBASE_PROJECT_ID: z.optional(z.string().check(z.minLength(1))),\n NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: z.optional(z.string()),\n NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: z.optional(z.string()),\n NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: z.optional(z.string()),\n NEXT_PUBLIC_FIREBASE_APP_ID: z.optional(z.string()),\n NEXT_PUBLIC_FIREBASE_FUNCTIONS_REGION: z.optional(z.string()),\n});\n\nexport interface EnvReport {\n ok: boolean;\n /** Firebase volledig geconfigureerd (apiKey + projectId aanwezig). */\n firebaseConfigured: boolean;\n problems: string[];\n}\n\nexport function validateEnv(env: NodeJS.ProcessEnv = process.env): EnvReport {\n const problems: string[] = [];\n const parsed = EnvSchema.safeParse(env);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) problems.push(`${issue.path.join(\".\")}: ${issue.message}`);\n }\n const apiKey = env.NEXT_PUBLIC_FIREBASE_API_KEY;\n const projectId = env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;\n const firebaseConfigured = Boolean(apiKey && projectId);\n\n // Half-geconfigureerd is een veelvoorkomende, lastig te debuggen fout: meld het expliciet.\n if (apiKey && !projectId) problems.push(\"NEXT_PUBLIC_FIREBASE_PROJECT_ID ontbreekt (apiKey is wél gezet).\");\n if (!apiKey && projectId) problems.push(\"NEXT_PUBLIC_FIREBASE_API_KEY ontbreekt (projectId is wél gezet).\");\n\n return { ok: problems.length === 0, firebaseConfigured, problems };\n}\n\n/** Gooit als de env ongeldig is. Gebruik in build/serverstart om snel te falen. */\nexport function assertEnv(env: NodeJS.ProcessEnv = process.env): void {\n const report = validateEnv(env);\n if (!report.ok) {\n throw new Error(`XiCMS env-configuratie ongeldig:\\n- ${report.problems.join(\"\\n- \")}`);\n }\n}\n"],"mappings":"AAAA,OAAO;AAEP,YAAY,OAAO;AAOnB,MAAM,YAAY,EAAE,OAAO;AAAA,EACzB,8BAA8B,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAAA,EACzE,iCAAiC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAAA,EAC5E,kCAAkC,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACvD,qCAAqC,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EAC1D,0CAA0C,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EAC/D,6BAA6B,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EAClD,uCAAuC,EAAE,SAAS,EAAE,OAAO,CAAC;AAC9D,CAAC;AASM,SAAS,YAAY,MAAyB,QAAQ,KAAgB;AAC3E,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAAS,UAAU,UAAU,GAAG;AACtC,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,SAAS,OAAO,MAAM,OAAQ,UAAS,KAAK,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO,EAAE;AAAA,EACpG;AACA,QAAM,SAAS,IAAI;AACnB,QAAM,YAAY,IAAI;AACtB,QAAM,qBAAqB,QAAQ,UAAU,SAAS;AAGtD,MAAI,UAAU,CAAC,UAAW,UAAS,KAAK,qEAAkE;AAC1G,MAAI,CAAC,UAAU,UAAW,UAAS,KAAK,qEAAkE;AAE1G,SAAO,EAAE,IAAI,SAAS,WAAW,GAAG,oBAAoB,SAAS;AACnE;AAGO,SAAS,UAAU,MAAyB,QAAQ,KAAW;AACpE,QAAM,SAAS,YAAY,GAAG;AAC9B,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM;AAAA,IAAuC,OAAO,SAAS,KAAK,MAAM,CAAC,EAAE;AAAA,EACvF;AACF;","names":[]}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
* pagina-reads). NOOIT importeren in client-componenten.
|
|
4
4
|
*/
|
|
5
5
|
import "server-only";
|
|
6
|
-
export { getAdminApp,
|
|
7
|
-
export { sanitizeRichText } from "./sanitize";
|
|
8
|
-
export { jsonLdHtml } from "../blocks/builtins/jsonld";
|
|
9
|
-
export { buildMetadata, buildJsonLd, buildSitemap, buildRobots, siteOrigin, businessJsonLd, breadcrumbListJsonLd, articleJsonLd, productJsonLd, openingHoursJsonLd, galleryJsonLd, videoObjectJsonLd, type BusinessInfo, } from "./seo";
|
|
10
|
-
export { validateEnv, assertEnv, type EnvReport } from "./env";
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
6
|
+
export { getAdminApp, getAdminDb } from "../firebase/admin.js";
|
|
7
|
+
export { sanitizeRichText } from "./sanitize.js";
|
|
8
|
+
export { jsonLdHtml } from "../blocks/builtins/jsonld.js";
|
|
9
|
+
export { buildMetadata, buildJsonLd, buildSitemap, buildRobots, siteOrigin, businessJsonLd, breadcrumbListJsonLd, articleJsonLd, productJsonLd, openingHoursJsonLd, galleryJsonLd, videoObjectJsonLd, type BusinessInfo, } from "./seo.js";
|
|
10
|
+
export { validateEnv, assertEnv, type EnvReport } from "./env.js";
|
|
11
|
+
export { revalidatePOST } from "./revalidate.js";
|
|
12
|
+
export { draftPOST } from "./draft.js";
|
|
13
|
+
export { pathFromSlugs, listPublishedPages, getPublishedPageByPath, getPublishedPageByPathExpanded, getSiteSymbols, expandSymbols, getSiteCustomBlocks, getPublicSiteSettings, getDraftPageById, getDraftPageByPath, type StoredPage, } from "./pages.js";
|
|
14
|
+
export { getBundle, getBundlePage, getBundleNews, getNewsPageData, type PublishedBundle, type BundleItem, } from "./bundle.js";
|
|
15
|
+
export { siteLocales, parseLocaleSlugs, localizedPath, localizePage, localizeBlocks, pruneTranslations, TranslationsSchema, type Translations, type LocaleConfig, } from "../i18n/overlay.js";
|