@kywi-software/core 0.14.0 → 0.15.1
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/AGENT-PATTERNS.md +200 -17
- package/README.md +38 -12
- package/dist/admin/audience-editor.d.ts +2 -0
- package/dist/admin/audience-editor.d.ts.map +1 -1
- package/dist/admin/audience-editor.js +4 -2
- package/dist/admin/audience-editor.js.map +1 -1
- package/dist/admin/chrome.d.ts.map +1 -1
- package/dist/admin/chrome.js +6 -7
- package/dist/admin/chrome.js.map +1 -1
- package/dist/admin/condition-builder.d.ts.map +1 -1
- package/dist/admin/condition-builder.js +16 -3
- package/dist/admin/condition-builder.js.map +1 -1
- package/dist/admin/field-components.d.ts.map +1 -1
- package/dist/admin/field-components.js +27 -1
- package/dist/admin/field-components.js.map +1 -1
- package/dist/admin/form-helpers.d.ts.map +1 -1
- package/dist/admin/form-helpers.js +6 -1
- package/dist/admin/form-helpers.js.map +1 -1
- package/dist/admin/layout-editor/chrome-env.d.ts +35 -0
- package/dist/admin/layout-editor/chrome-env.d.ts.map +1 -0
- package/dist/admin/layout-editor/chrome-env.js +13 -0
- package/dist/admin/layout-editor/chrome-env.js.map +1 -0
- package/dist/admin/layout-editor/component-actions.d.ts +58 -7
- package/dist/admin/layout-editor/component-actions.d.ts.map +1 -1
- package/dist/admin/layout-editor/component-actions.js +131 -5
- package/dist/admin/layout-editor/component-actions.js.map +1 -1
- package/dist/admin/layout-editor/component-fork.d.ts +4 -4
- package/dist/admin/layout-editor/component-fork.d.ts.map +1 -1
- package/dist/admin/layout-editor/component-fork.js +76 -10
- package/dist/admin/layout-editor/component-fork.js.map +1 -1
- package/dist/admin/layout-editor/component-picker-field.d.ts +17 -3
- package/dist/admin/layout-editor/component-picker-field.d.ts.map +1 -1
- package/dist/admin/layout-editor/component-picker-field.js +5 -2
- package/dist/admin/layout-editor/component-picker-field.js.map +1 -1
- package/dist/admin/layout-editor/drag-feedback.d.ts +25 -1
- package/dist/admin/layout-editor/drag-feedback.d.ts.map +1 -1
- package/dist/admin/layout-editor/drag-feedback.js +9 -0
- package/dist/admin/layout-editor/drag-feedback.js.map +1 -1
- package/dist/admin/layout-editor/drag-utils.d.ts +103 -5
- package/dist/admin/layout-editor/drag-utils.d.ts.map +1 -1
- package/dist/admin/layout-editor/drag-utils.js +131 -4
- package/dist/admin/layout-editor/drag-utils.js.map +1 -1
- package/dist/admin/layout-editor/editor-canvas.d.ts +11 -0
- package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-canvas.js +134 -20
- package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
- package/dist/admin/layout-editor/editor-dialog.d.ts +58 -3
- package/dist/admin/layout-editor/editor-dialog.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-dialog.js +71 -9
- package/dist/admin/layout-editor/editor-dialog.js.map +1 -1
- package/dist/admin/layout-editor/editor-state.d.ts +119 -0
- package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-state.js +188 -6
- package/dist/admin/layout-editor/editor-state.js.map +1 -1
- package/dist/admin/layout-editor/editor-toolbar.d.ts +10 -1
- package/dist/admin/layout-editor/editor-toolbar.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-toolbar.js +2 -2
- package/dist/admin/layout-editor/editor-toolbar.js.map +1 -1
- package/dist/admin/layout-editor/editor.css +216 -8
- package/dist/admin/layout-editor/inline-text.d.ts +15 -1
- package/dist/admin/layout-editor/inline-text.d.ts.map +1 -1
- package/dist/admin/layout-editor/inline-text.js +30 -2
- package/dist/admin/layout-editor/inline-text.js.map +1 -1
- package/dist/admin/layout-editor/layout-editor.d.ts +21 -16
- package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
- package/dist/admin/layout-editor/layout-editor.js +40 -17
- package/dist/admin/layout-editor/layout-editor.js.map +1 -1
- package/dist/admin/layout-editor/linked-component-notes.d.ts +88 -0
- package/dist/admin/layout-editor/linked-component-notes.d.ts.map +1 -0
- package/dist/admin/layout-editor/linked-component-notes.js +88 -0
- package/dist/admin/layout-editor/linked-component-notes.js.map +1 -0
- package/dist/admin/layout-editor/module-overlay.d.ts +23 -4
- package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
- package/dist/admin/layout-editor/module-overlay.js +56 -10
- package/dist/admin/layout-editor/module-overlay.js.map +1 -1
- package/dist/admin/layout-editor/module-variant-container-config.d.ts.map +1 -1
- package/dist/admin/layout-editor/module-variant-container-config.js +9 -2
- package/dist/admin/layout-editor/module-variant-container-config.js.map +1 -1
- package/dist/admin/layout-editor/module-variant-container-panel.d.ts +75 -0
- package/dist/admin/layout-editor/module-variant-container-panel.d.ts.map +1 -0
- package/dist/admin/layout-editor/module-variant-container-panel.js +29 -0
- package/dist/admin/layout-editor/module-variant-container-panel.js.map +1 -0
- package/dist/admin/layout-editor/node-lookup.d.ts.map +1 -1
- package/dist/admin/layout-editor/node-lookup.js +33 -3
- package/dist/admin/layout-editor/node-lookup.js.map +1 -1
- package/dist/admin/layout-editor/overlay-shell.d.ts.map +1 -1
- package/dist/admin/layout-editor/overlay-shell.js +19 -4
- package/dist/admin/layout-editor/overlay-shell.js.map +1 -1
- package/dist/admin/layout-editor/props-panel.d.ts +28 -11
- package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
- package/dist/admin/layout-editor/props-panel.js +75 -125
- package/dist/admin/layout-editor/props-panel.js.map +1 -1
- package/dist/admin/layout-editor/section-variant-container-config.d.ts.map +1 -1
- package/dist/admin/layout-editor/section-variant-container-config.js +11 -2
- package/dist/admin/layout-editor/section-variant-container-config.js.map +1 -1
- package/dist/admin/layout-editor/use-chrome-flip.d.ts +99 -11
- package/dist/admin/layout-editor/use-chrome-flip.d.ts.map +1 -1
- package/dist/admin/layout-editor/use-chrome-flip.js +268 -97
- package/dist/admin/layout-editor/use-chrome-flip.js.map +1 -1
- package/dist/admin/layout-editor/use-component-connect.d.ts +13 -0
- package/dist/admin/layout-editor/use-component-connect.d.ts.map +1 -1
- package/dist/admin/layout-editor/use-component-connect.js +116 -20
- package/dist/admin/layout-editor/use-component-connect.js.map +1 -1
- package/dist/admin/layout-editor/use-component-fork.d.ts +49 -19
- package/dist/admin/layout-editor/use-component-fork.d.ts.map +1 -1
- package/dist/admin/layout-editor/use-component-fork.js +28 -19
- package/dist/admin/layout-editor/use-component-fork.js.map +1 -1
- package/dist/admin/layout-editor/use-component-library.d.ts +4 -4
- package/dist/admin/layout-editor/use-component-library.d.ts.map +1 -1
- package/dist/admin/layout-editor/use-component-library.js +1 -1
- package/dist/admin/layout-editor/use-component-library.js.map +1 -1
- package/dist/admin/layout-editor/use-editor-dnd.d.ts +10 -0
- package/dist/admin/layout-editor/use-editor-dnd.d.ts.map +1 -1
- package/dist/admin/layout-editor/use-editor-dnd.js +234 -14
- package/dist/admin/layout-editor/use-editor-dnd.js.map +1 -1
- package/dist/admin/layout-editor/variant-container-config.d.ts.map +1 -1
- package/dist/admin/layout-editor/variant-container-config.js +1 -1
- package/dist/admin/layout-editor/variant-container-config.js.map +1 -1
- package/dist/admin/layout-editor/variant-editor.d.ts +16 -15
- package/dist/admin/layout-editor/variant-editor.d.ts.map +1 -1
- package/dist/admin/layout-editor/variant-editor.js +16 -5
- package/dist/admin/layout-editor/variant-editor.js.map +1 -1
- package/dist/admin/primitives.d.ts.map +1 -1
- package/dist/admin/primitives.js +1 -1
- package/dist/admin/primitives.js.map +1 -1
- package/dist/admin/registry.d.ts +12 -0
- package/dist/admin/registry.d.ts.map +1 -1
- package/dist/admin/registry.js +12 -0
- package/dist/admin/registry.js.map +1 -1
- package/dist/admin/rule-tester.d.ts +1 -0
- package/dist/admin/rule-tester.d.ts.map +1 -1
- package/dist/admin/rule-tester.js +7 -4
- package/dist/admin/rule-tester.js.map +1 -1
- package/dist/admin/server.d.ts +10 -1
- package/dist/admin/server.d.ts.map +1 -1
- package/dist/admin/server.js +4 -1
- package/dist/admin/server.js.map +1 -1
- package/dist/admin/signal-options.d.ts +17 -0
- package/dist/admin/signal-options.d.ts.map +1 -1
- package/dist/admin/signal-options.js +28 -0
- package/dist/admin/signal-options.js.map +1 -1
- package/dist/admin/site-switcher.d.ts +16 -3
- package/dist/admin/site-switcher.d.ts.map +1 -1
- package/dist/admin/site-switcher.js +18 -3
- package/dist/admin/site-switcher.js.map +1 -1
- package/dist/admin/styles/admin.css +0 -3
- package/dist/admin/surface-matcher.d.ts +6 -2
- package/dist/admin/surface-matcher.d.ts.map +1 -1
- package/dist/admin/surface-matcher.js +42 -5
- package/dist/admin/surface-matcher.js.map +1 -1
- package/dist/admin/surfaces/audiences/audiences-data.d.ts +5 -0
- package/dist/admin/surfaces/audiences/audiences-data.d.ts.map +1 -1
- package/dist/admin/surfaces/audiences/audiences-data.js +3 -0
- package/dist/admin/surfaces/audiences/audiences-data.js.map +1 -1
- package/dist/admin/surfaces/components/components-data.d.ts +31 -11
- package/dist/admin/surfaces/components/components-data.d.ts.map +1 -1
- package/dist/admin/surfaces/components/components-data.js +17 -4
- package/dist/admin/surfaces/components/components-data.js.map +1 -1
- package/dist/admin/surfaces/components/components-list.d.ts.map +1 -1
- package/dist/admin/surfaces/components/components-list.js +20 -7
- package/dist/admin/surfaces/components/components-list.js.map +1 -1
- package/dist/admin/surfaces/components/definition-canvas.d.ts +11 -3
- package/dist/admin/surfaces/components/definition-canvas.d.ts.map +1 -1
- package/dist/admin/surfaces/components/definition-canvas.js +138 -17
- package/dist/admin/surfaces/components/definition-canvas.js.map +1 -1
- package/dist/admin/surfaces/dashboard/dashboard-index.d.ts.map +1 -1
- package/dist/admin/surfaces/dashboard/dashboard-index.js +2 -2
- package/dist/admin/surfaces/dashboard/dashboard-index.js.map +1 -1
- package/dist/admin/surfaces/layouts/layout-editor-client.d.ts.map +1 -1
- package/dist/admin/surfaces/layouts/layout-editor-client.js +12 -11
- package/dist/admin/surfaces/layouts/layout-editor-client.js.map +1 -1
- package/dist/admin/surfaces/menus/menu-editor.d.ts.map +1 -1
- package/dist/admin/surfaces/menus/menu-editor.js +17 -4
- package/dist/admin/surfaces/menus/menu-editor.js.map +1 -1
- package/dist/admin/surfaces/menus/menu-tree.d.ts +18 -4
- package/dist/admin/surfaces/menus/menu-tree.d.ts.map +1 -1
- package/dist/admin/surfaces/menus/menu-tree.js +18 -3
- package/dist/admin/surfaces/menus/menu-tree.js.map +1 -1
- package/dist/admin/surfaces/menus/menus-data.d.ts +18 -0
- package/dist/admin/surfaces/menus/menus-data.d.ts.map +1 -1
- package/dist/admin/surfaces/menus/menus-data.js +4 -0
- package/dist/admin/surfaces/menus/menus-data.js.map +1 -1
- package/dist/admin/surfaces/menus/menus-list.d.ts.map +1 -1
- package/dist/admin/surfaces/menus/menus-list.js +2 -12
- package/dist/admin/surfaces/menus/menus-list.js.map +1 -1
- package/dist/admin/surfaces/users/users-data.d.ts +14 -0
- package/dist/admin/surfaces/users/users-data.d.ts.map +1 -1
- package/dist/admin/surfaces/users/users-data.js +19 -0
- package/dist/admin/surfaces/users/users-data.js.map +1 -1
- package/dist/admin/surfaces/users/users-detail.d.ts.map +1 -1
- package/dist/admin/surfaces/users/users-detail.js +40 -4
- package/dist/admin/surfaces/users/users-detail.js.map +1 -1
- package/dist/admin/surfaces/users/users-new.d.ts.map +1 -1
- package/dist/admin/surfaces/users/users-new.js +8 -5
- package/dist/admin/surfaces/users/users-new.js.map +1 -1
- package/dist/admin/user-form.d.ts +10 -1
- package/dist/admin/user-form.d.ts.map +1 -1
- package/dist/admin/user-form.js +2 -2
- package/dist/admin/user-form.js.map +1 -1
- package/dist/api/admin-features-routes.js +2 -2
- package/dist/api/admin-features-routes.js.map +1 -1
- package/dist/api/api-key-routes.js +2 -2
- package/dist/api/api-key-routes.js.map +1 -1
- package/dist/api/audience-preview-routes.d.ts +7 -0
- package/dist/api/audience-preview-routes.d.ts.map +1 -1
- package/dist/api/audience-preview-routes.js +4 -4
- package/dist/api/audience-preview-routes.js.map +1 -1
- package/dist/api/audience-routes.d.ts +7 -0
- package/dist/api/audience-routes.d.ts.map +1 -1
- package/dist/api/audience-routes.js +31 -19
- package/dist/api/audience-routes.js.map +1 -1
- package/dist/api/audience-runtime-routes.d.ts +23 -0
- package/dist/api/audience-runtime-routes.d.ts.map +1 -1
- package/dist/api/audience-runtime-routes.js +511 -25
- package/dist/api/audience-runtime-routes.js.map +1 -1
- package/dist/api/auth-routes.d.ts.map +1 -1
- package/dist/api/auth-routes.js +10 -4
- package/dist/api/auth-routes.js.map +1 -1
- package/dist/api/auth.d.ts +1 -0
- package/dist/api/auth.d.ts.map +1 -1
- package/dist/api/auth.js +43 -3
- package/dist/api/auth.js.map +1 -1
- package/dist/api/ax-routes.d.ts.map +1 -1
- package/dist/api/ax-routes.js +7 -3
- package/dist/api/ax-routes.js.map +1 -1
- package/dist/api/bulk-routes.d.ts.map +1 -1
- package/dist/api/bulk-routes.js +7 -7
- package/dist/api/bulk-routes.js.map +1 -1
- package/dist/api/category-routes.js +6 -6
- package/dist/api/category-routes.js.map +1 -1
- package/dist/api/changeset-routes.js +2 -2
- package/dist/api/changeset-routes.js.map +1 -1
- package/dist/api/comment-routes.js +12 -12
- package/dist/api/comment-routes.js.map +1 -1
- package/dist/api/component-routes.d.ts +25 -0
- package/dist/api/component-routes.d.ts.map +1 -1
- package/dist/api/component-routes.js +44 -19
- package/dist/api/component-routes.js.map +1 -1
- package/dist/api/config-routes.js +4 -4
- package/dist/api/config-routes.js.map +1 -1
- package/dist/api/content-permission-routes.js +2 -2
- package/dist/api/content-permission-routes.js.map +1 -1
- package/dist/api/content-routes.d.ts.map +1 -1
- package/dist/api/content-routes.js +21 -16
- package/dist/api/content-routes.js.map +1 -1
- package/dist/api/content-type-routes.js +3 -3
- package/dist/api/content-type-routes.js.map +1 -1
- package/dist/api/dashboard-routes.js +1 -1
- package/dist/api/dashboard-routes.js.map +1 -1
- package/dist/api/experiment-routes.d.ts +7 -0
- package/dist/api/experiment-routes.d.ts.map +1 -1
- package/dist/api/experiment-routes.js +10 -10
- package/dist/api/experiment-routes.js.map +1 -1
- package/dist/api/experiment-runtime-routes.d.ts +6 -0
- package/dist/api/experiment-runtime-routes.d.ts.map +1 -1
- package/dist/api/experiment-runtime-routes.js +47 -11
- package/dist/api/experiment-runtime-routes.js.map +1 -1
- package/dist/api/extension-routes.js +4 -4
- package/dist/api/extension-routes.js.map +1 -1
- package/dist/api/feed-routes.d.ts +2 -2
- package/dist/api/feed-routes.js +5 -5
- package/dist/api/feed-routes.js.map +1 -1
- package/dist/api/form-routes.js +6 -6
- package/dist/api/form-routes.js.map +1 -1
- package/dist/api/graphql/resolvers.d.ts +1 -1
- package/dist/api/graphql/resolvers.d.ts.map +1 -1
- package/dist/api/graphql/resolvers.js +68 -33
- package/dist/api/graphql/resolvers.js.map +1 -1
- package/dist/api/group-routes.js +9 -9
- package/dist/api/group-routes.js.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +43 -7
- package/dist/api/index.js.map +1 -1
- package/dist/api/layout-routes.d.ts +19 -1
- package/dist/api/layout-routes.d.ts.map +1 -1
- package/dist/api/layout-routes.js +92 -8
- package/dist/api/layout-routes.js.map +1 -1
- package/dist/api/layout-write-guard.d.ts +3 -2
- package/dist/api/layout-write-guard.d.ts.map +1 -1
- package/dist/api/layout-write-guard.js +12 -4
- package/dist/api/layout-write-guard.js.map +1 -1
- package/dist/api/media-routes.d.ts.map +1 -1
- package/dist/api/media-routes.js +100 -35
- package/dist/api/media-routes.js.map +1 -1
- package/dist/api/menu-routes.d.ts +9 -1
- package/dist/api/menu-routes.d.ts.map +1 -1
- package/dist/api/menu-routes.js +46 -12
- package/dist/api/menu-routes.js.map +1 -1
- package/dist/api/nav-routes.d.ts +6 -0
- package/dist/api/nav-routes.d.ts.map +1 -1
- package/dist/api/nav-routes.js +25 -4
- package/dist/api/nav-routes.js.map +1 -1
- package/dist/api/oauth-routes.js +2 -2
- package/dist/api/oauth-routes.js.map +1 -1
- package/dist/api/openapi.d.ts.map +1 -1
- package/dist/api/openapi.js +82 -34
- package/dist/api/openapi.js.map +1 -1
- package/dist/api/pagination.d.ts +10 -0
- package/dist/api/pagination.d.ts.map +1 -1
- package/dist/api/pagination.js +7 -1
- package/dist/api/pagination.js.map +1 -1
- package/dist/api/response.d.ts +29 -0
- package/dist/api/response.d.ts.map +1 -1
- package/dist/api/response.js +23 -3
- package/dist/api/response.js.map +1 -1
- package/dist/api/search-routes.d.ts.map +1 -1
- package/dist/api/search-routes.js +19 -5
- package/dist/api/search-routes.js.map +1 -1
- package/dist/api/section-template-routes.d.ts.map +1 -1
- package/dist/api/section-template-routes.js +37 -20
- package/dist/api/section-template-routes.js.map +1 -1
- package/dist/api/site-admin-routes.d.ts +10 -1
- package/dist/api/site-admin-routes.d.ts.map +1 -1
- package/dist/api/site-admin-routes.js +21 -1
- package/dist/api/site-admin-routes.js.map +1 -1
- package/dist/api/site-context.d.ts +35 -5
- package/dist/api/site-context.d.ts.map +1 -1
- package/dist/api/site-context.js +21 -6
- package/dist/api/site-context.js.map +1 -1
- package/dist/api/site-routes.js +2 -2
- package/dist/api/site-routes.js.map +1 -1
- package/dist/api/tag-routes.d.ts.map +1 -1
- package/dist/api/tag-routes.js +5 -5
- package/dist/api/tag-routes.js.map +1 -1
- package/dist/api/translation-routes.js +5 -5
- package/dist/api/translation-routes.js.map +1 -1
- package/dist/api/user-routes.d.ts.map +1 -1
- package/dist/api/user-routes.js +136 -21
- package/dist/api/user-routes.js.map +1 -1
- package/dist/api/version-routes.js +2 -2
- package/dist/api/version-routes.js.map +1 -1
- package/dist/api/webhook-routes.js +8 -8
- package/dist/api/webhook-routes.js.map +1 -1
- package/dist/api/workflow-routes.d.ts.map +1 -1
- package/dist/api/workflow-routes.js +23 -14
- package/dist/api/workflow-routes.js.map +1 -1
- package/dist/audiences/collectors/identity.d.ts +14 -1
- package/dist/audiences/collectors/identity.d.ts.map +1 -1
- package/dist/audiences/collectors/identity.js +16 -3
- package/dist/audiences/collectors/identity.js.map +1 -1
- package/dist/audiences/collectors/index.d.ts +16 -2
- package/dist/audiences/collectors/index.d.ts.map +1 -1
- package/dist/audiences/collectors/index.js +29 -5
- package/dist/audiences/collectors/index.js.map +1 -1
- package/dist/audiences/collectors/pinned-audience.d.ts +28 -2
- package/dist/audiences/collectors/pinned-audience.d.ts.map +1 -1
- package/dist/audiences/collectors/pinned-audience.js +35 -5
- package/dist/audiences/collectors/pinned-audience.js.map +1 -1
- package/dist/audiences/collectors/selfid.d.ts +25 -0
- package/dist/audiences/collectors/selfid.d.ts.map +1 -0
- package/dist/audiences/collectors/selfid.js +46 -0
- package/dist/audiences/collectors/selfid.js.map +1 -0
- package/dist/audiences/collectors/session.d.ts +41 -0
- package/dist/audiences/collectors/session.d.ts.map +1 -0
- package/dist/audiences/collectors/session.js +50 -0
- package/dist/audiences/collectors/session.js.map +1 -0
- package/dist/audiences/collectors/utm.d.ts +15 -1
- package/dist/audiences/collectors/utm.d.ts.map +1 -1
- package/dist/audiences/collectors/utm.js +16 -2
- package/dist/audiences/collectors/utm.js.map +1 -1
- package/dist/audiences/consent-config.d.ts +21 -0
- package/dist/audiences/consent-config.d.ts.map +1 -0
- package/dist/audiences/consent-config.js +15 -0
- package/dist/audiences/consent-config.js.map +1 -0
- package/dist/audiences/consent-startup.d.ts +39 -0
- package/dist/audiences/consent-startup.d.ts.map +1 -0
- package/dist/audiences/consent-startup.js +105 -0
- package/dist/audiences/consent-startup.js.map +1 -0
- package/dist/audiences/consent.d.ts +205 -0
- package/dist/audiences/consent.d.ts.map +1 -0
- package/dist/audiences/consent.js +335 -0
- package/dist/audiences/consent.js.map +1 -0
- package/dist/audiences/cookies.d.ts +21 -0
- package/dist/audiences/cookies.d.ts.map +1 -1
- package/dist/audiences/cookies.js +26 -0
- package/dist/audiences/cookies.js.map +1 -1
- package/dist/audiences/engine.d.ts +7 -0
- package/dist/audiences/engine.d.ts.map +1 -1
- package/dist/audiences/engine.js +7 -2
- package/dist/audiences/engine.js.map +1 -1
- package/dist/audiences/entry-page.d.ts +89 -0
- package/dist/audiences/entry-page.d.ts.map +1 -0
- package/dist/audiences/entry-page.js +116 -0
- package/dist/audiences/entry-page.js.map +1 -0
- package/dist/audiences/evaluator/instant-match.d.ts.map +1 -1
- package/dist/audiences/evaluator/instant-match.js +7 -0
- package/dist/audiences/evaluator/instant-match.js.map +1 -1
- package/dist/audiences/index.d.ts +6 -2
- package/dist/audiences/index.d.ts.map +1 -1
- package/dist/audiences/index.js +12 -2
- package/dist/audiences/index.js.map +1 -1
- package/dist/audiences/queries.d.ts +16 -0
- package/dist/audiences/queries.d.ts.map +1 -1
- package/dist/audiences/queries.js +28 -1
- package/dist/audiences/queries.js.map +1 -1
- package/dist/audiences/schema.d.ts +17 -0
- package/dist/audiences/schema.d.ts.map +1 -1
- package/dist/audiences/schema.js +7 -0
- package/dist/audiences/schema.js.map +1 -1
- package/dist/audiences/server-eval.d.ts +32 -1
- package/dist/audiences/server-eval.d.ts.map +1 -1
- package/dist/audiences/server-eval.js +35 -3
- package/dist/audiences/server-eval.js.map +1 -1
- package/dist/audiences/ssr.d.ts +18 -1
- package/dist/audiences/ssr.d.ts.map +1 -1
- package/dist/audiences/ssr.js +18 -1
- package/dist/audiences/ssr.js.map +1 -1
- package/dist/audiences/types.d.ts +22 -1
- package/dist/audiences/types.d.ts.map +1 -1
- package/dist/audiences/types.js +1 -0
- package/dist/audiences/types.js.map +1 -1
- package/dist/audiences/utm-persistence.d.ts +20 -7
- package/dist/audiences/utm-persistence.d.ts.map +1 -1
- package/dist/audiences/utm-persistence.js +20 -7
- package/dist/audiences/utm-persistence.js.map +1 -1
- package/dist/auth/roles.d.ts +11 -0
- package/dist/auth/roles.d.ts.map +1 -1
- package/dist/auth/roles.js +13 -0
- package/dist/auth/roles.js.map +1 -1
- package/dist/auth/tokens.d.ts +7 -0
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +24 -2
- package/dist/auth/tokens.js.map +1 -1
- package/dist/ax/content-source.d.ts +10 -2
- package/dist/ax/content-source.d.ts.map +1 -1
- package/dist/ax/content-source.js +81 -5
- package/dist/ax/content-source.js.map +1 -1
- package/dist/ax/effective-body.d.ts +28 -0
- package/dist/ax/effective-body.d.ts.map +1 -0
- package/dist/ax/effective-body.js +47 -0
- package/dist/ax/effective-body.js.map +1 -0
- package/dist/ax/index.d.ts +3 -1
- package/dist/ax/index.d.ts.map +1 -1
- package/dist/ax/index.js +2 -0
- package/dist/ax/index.js.map +1 -1
- package/dist/ax/jsonld.d.ts +31 -1
- package/dist/ax/jsonld.d.ts.map +1 -1
- package/dist/ax/jsonld.js +35 -22
- package/dist/ax/jsonld.js.map +1 -1
- package/dist/ax/layout-to-html.d.ts +127 -0
- package/dist/ax/layout-to-html.d.ts.map +1 -0
- package/dist/ax/layout-to-html.js +545 -0
- package/dist/ax/layout-to-html.js.map +1 -0
- package/dist/ax/llms-full-txt.d.ts +3 -1
- package/dist/ax/llms-full-txt.d.ts.map +1 -1
- package/dist/ax/llms-full-txt.js +5 -2
- package/dist/ax/llms-full-txt.js.map +1 -1
- package/dist/ax/page-markdown.d.ts +10 -2
- package/dist/ax/page-markdown.d.ts.map +1 -1
- package/dist/ax/page-markdown.js +16 -3
- package/dist/ax/page-markdown.js.map +1 -1
- package/dist/ax/summary.d.ts +4 -0
- package/dist/ax/summary.d.ts.map +1 -1
- package/dist/ax/summary.js +6 -1
- package/dist/ax/summary.js.map +1 -1
- package/dist/ax/types.d.ts +24 -0
- package/dist/ax/types.d.ts.map +1 -1
- package/dist/cache/content-invalidation.d.ts.map +1 -1
- package/dist/cache/content-invalidation.js +11 -0
- package/dist/cache/content-invalidation.js.map +1 -1
- package/dist/config/types.d.ts +43 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/config/validate.d.ts.map +1 -1
- package/dist/config/validate.js +3 -0
- package/dist/config/validate.js.map +1 -1
- package/dist/db/apply-snapshot.d.ts +25 -0
- package/dist/db/apply-snapshot.d.ts.map +1 -1
- package/dist/db/apply-snapshot.js +48 -16
- package/dist/db/apply-snapshot.js.map +1 -1
- package/dist/db/ax-queries.d.ts +6 -0
- package/dist/db/ax-queries.d.ts.map +1 -1
- package/dist/db/ax-queries.js +6 -0
- package/dist/db/ax-queries.js.map +1 -1
- package/dist/db/component-instance-queries.d.ts +79 -19
- package/dist/db/component-instance-queries.d.ts.map +1 -1
- package/dist/db/component-instance-queries.js +266 -83
- package/dist/db/component-instance-queries.js.map +1 -1
- package/dist/db/component-queries.d.ts +1 -16
- package/dist/db/component-queries.d.ts.map +1 -1
- package/dist/db/component-queries.js +7 -56
- package/dist/db/component-queries.js.map +1 -1
- package/dist/db/content-queries.d.ts.map +1 -1
- package/dist/db/content-queries.js +9 -2
- package/dist/db/content-queries.js.map +1 -1
- package/dist/db/extension-queries.d.ts +2 -2
- package/dist/db/feed-queries.d.ts +3 -3
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/layout-queries.d.ts +21 -3
- package/dist/db/layout-queries.d.ts.map +1 -1
- package/dist/db/layout-queries.js +14 -6
- package/dist/db/layout-queries.js.map +1 -1
- package/dist/db/menu-queries.d.ts +69 -5
- package/dist/db/menu-queries.d.ts.map +1 -1
- package/dist/db/menu-queries.js +120 -13
- package/dist/db/menu-queries.js.map +1 -1
- package/dist/db/search-queries.d.ts.map +1 -1
- package/dist/db/search-queries.js +24 -1
- package/dist/db/search-queries.js.map +1 -1
- package/dist/db/section-template-queries.d.ts +62 -0
- package/dist/db/section-template-queries.d.ts.map +1 -0
- package/dist/db/section-template-queries.js +178 -0
- package/dist/db/section-template-queries.js.map +1 -0
- package/dist/db/site-plugin-queries.d.ts +2 -2
- package/dist/db/tree-queries.d.ts.map +1 -1
- package/dist/db/tree-queries.js +5 -0
- package/dist/db/tree-queries.js.map +1 -1
- package/dist/db/webhook-queries.d.ts +3 -3
- package/dist/db/workflow-queries.d.ts.map +1 -1
- package/dist/db/workflow-queries.js +5 -20
- package/dist/db/workflow-queries.js.map +1 -1
- package/dist/experiments/runtime.d.ts +21 -3
- package/dist/experiments/runtime.d.ts.map +1 -1
- package/dist/experiments/runtime.js +21 -3
- package/dist/experiments/runtime.js.map +1 -1
- package/dist/hooks/ax-invalidation.d.ts.map +1 -1
- package/dist/hooks/ax-invalidation.js +4 -0
- package/dist/hooks/ax-invalidation.js.map +1 -1
- package/dist/layout/component-refs.d.ts +90 -2
- package/dist/layout/component-refs.d.ts.map +1 -1
- package/dist/layout/component-refs.js +293 -16
- package/dist/layout/component-refs.js.map +1 -1
- package/dist/layout/index.d.ts +7 -4
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +6 -3
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/legacy-variant-container.d.ts +123 -0
- package/dist/layout/legacy-variant-container.d.ts.map +1 -0
- package/dist/layout/legacy-variant-container.js +397 -0
- package/dist/layout/legacy-variant-container.js.map +1 -0
- package/dist/layout/module-permissions.d.ts.map +1 -1
- package/dist/layout/module-permissions.js +26 -38
- package/dist/layout/module-permissions.js.map +1 -1
- package/dist/layout/modules-extended.d.ts +28 -1
- package/dist/layout/modules-extended.d.ts.map +1 -1
- package/dist/layout/modules-extended.js +73 -1
- package/dist/layout/modules-extended.js.map +1 -1
- package/dist/layout/modules.d.ts.map +1 -1
- package/dist/layout/modules.js +9 -1
- package/dist/layout/modules.js.map +1 -1
- package/dist/layout/personalization.d.ts +83 -0
- package/dist/layout/personalization.d.ts.map +1 -1
- package/dist/layout/personalization.js +250 -4
- package/dist/layout/personalization.js.map +1 -1
- package/dist/layout/registry.d.ts.map +1 -1
- package/dist/layout/registry.js +20 -0
- package/dist/layout/registry.js.map +1 -1
- package/dist/layout/renderer.d.ts +29 -2
- package/dist/layout/renderer.d.ts.map +1 -1
- package/dist/layout/renderer.js +23 -6
- package/dist/layout/renderer.js.map +1 -1
- package/dist/layout/seed-defaults.d.ts +45 -0
- package/dist/layout/seed-defaults.d.ts.map +1 -0
- package/dist/layout/seed-defaults.js +75 -0
- package/dist/layout/seed-defaults.js.map +1 -0
- package/dist/layout/types.d.ts +17 -0
- package/dist/layout/types.d.ts.map +1 -1
- package/dist/layout/types.js +7 -0
- package/dist/layout/types.js.map +1 -1
- package/dist/layout/walk.d.ts +14 -0
- package/dist/layout/walk.d.ts.map +1 -0
- package/dist/layout/walk.js +49 -0
- package/dist/layout/walk.js.map +1 -0
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/inline-risk.d.ts +26 -0
- package/dist/media/inline-risk.d.ts.map +1 -0
- package/dist/media/inline-risk.js +142 -0
- package/dist/media/inline-risk.js.map +1 -0
- package/dist/media/upload-allowlist.d.ts +23 -0
- package/dist/media/upload-allowlist.d.ts.map +1 -1
- package/dist/media/upload-allowlist.js +29 -0
- package/dist/media/upload-allowlist.js.map +1 -1
- package/dist/nav/builder.d.ts.map +1 -1
- package/dist/nav/builder.js +15 -3
- package/dist/nav/builder.js.map +1 -1
- package/dist/nav/index.d.ts +1 -1
- package/dist/nav/index.d.ts.map +1 -1
- package/dist/nav/index.js +1 -1
- package/dist/nav/index.js.map +1 -1
- package/dist/nav/menu-resolver.d.ts +11 -0
- package/dist/nav/menu-resolver.d.ts.map +1 -1
- package/dist/nav/menu-resolver.js +49 -9
- package/dist/nav/menu-resolver.js.map +1 -1
- package/dist/nav/paths.d.ts +37 -0
- package/dist/nav/paths.d.ts.map +1 -0
- package/dist/nav/paths.js +48 -0
- package/dist/nav/paths.js.map +1 -0
- package/dist/nav/types.d.ts +6 -0
- package/dist/nav/types.d.ts.map +1 -1
- package/dist/nav/url-resolver.d.ts +1 -5
- package/dist/nav/url-resolver.d.ts.map +1 -1
- package/dist/nav/url-resolver.js +6 -12
- package/dist/nav/url-resolver.js.map +1 -1
- package/dist/schema/base.d.ts +24 -4
- package/dist/schema/base.d.ts.map +1 -1
- package/dist/schema/base.js +17 -4
- package/dist/schema/base.js.map +1 -1
- package/dist/schema/components.d.ts +90 -9
- package/dist/schema/components.d.ts.map +1 -1
- package/dist/schema/components.js +113 -22
- package/dist/schema/components.js.map +1 -1
- package/dist/schema/mysql-tables.d.ts +5775 -48
- package/dist/schema/mysql-tables.d.ts.map +1 -1
- package/dist/schema/mysql-tables.js +622 -46
- package/dist/schema/mysql-tables.js.map +1 -1
- package/dist/scope/jsonld.d.ts +18 -3
- package/dist/scope/jsonld.d.ts.map +1 -1
- package/dist/scope/jsonld.js +6 -4
- package/dist/scope/jsonld.js.map +1 -1
- package/dist/scope/kywi-form.d.ts +11 -0
- package/dist/scope/kywi-form.d.ts.map +1 -1
- package/dist/scope/kywi-form.js +11 -1
- package/dist/scope/kywi-form.js.map +1 -1
- package/dist/scope/kywi-wizard-form.d.ts.map +1 -1
- package/dist/scope/kywi-wizard-form.js +76 -2
- package/dist/scope/kywi-wizard-form.js.map +1 -1
- package/dist/scope/sticky-offset.d.ts +34 -13
- package/dist/scope/sticky-offset.d.ts.map +1 -1
- package/dist/scope/sticky-offset.js +236 -43
- package/dist/scope/sticky-offset.js.map +1 -1
- package/dist/site/styles.css +61 -15
- package/dist/versioning/scheduler.d.ts +28 -0
- package/dist/versioning/scheduler.d.ts.map +1 -1
- package/dist/versioning/scheduler.js +50 -3
- package/dist/versioning/scheduler.js.map +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/audiences/collectors/session.ts"],"names":[],"mappings":"AACA,OAAO,EAA8C,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAGnG;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,GAAE,kBAAkB,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC/D,cAAc,CAMhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYjE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { COOKIE_NAMES } from '../cookies.js';
|
|
2
|
+
import { cookieAllowed, readConsentFromCookieHeader } from '../consent.js';
|
|
3
|
+
import { entryPagePath } from '../entry-page.js';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the visitor's entry page: the `kywi_entry` cookie recorded on the
|
|
6
|
+
* first request of the session, falling back to THIS request's path + query.
|
|
7
|
+
*
|
|
8
|
+
* The cookie is a `personalization` cookie, so it is treated as absent unless
|
|
9
|
+
* the visitor consents (kywi-cms#91) — a stored entry page from an earlier
|
|
10
|
+
* "accept" must stop resolving a visitor who has since rejected.
|
|
11
|
+
*
|
|
12
|
+
* The fallback is not a degraded mode, it is the mechanism: a `Set-Cookie` only
|
|
13
|
+
* takes effect on the NEXT request, so the landing request — the one carrying
|
|
14
|
+
* `?from=marketer` — has no cookie to read and must evaluate against its own
|
|
15
|
+
* path. That is what lets a campaign link personalize the page it links to
|
|
16
|
+
* without a reload, consent or no consent.
|
|
17
|
+
*/
|
|
18
|
+
export function collectSession(req, cookies, gate = {}) {
|
|
19
|
+
const consent = readConsentFromCookieHeader(gate.cookieHeader ?? req.headers.get('cookie'));
|
|
20
|
+
const stored = cookieAllowed(COOKIE_NAMES.ENTRY, consent, gate)
|
|
21
|
+
? cookies.get(COOKIE_NAMES.ENTRY)
|
|
22
|
+
: undefined;
|
|
23
|
+
return { entryPage: stored || entryPagePath(req.url) || '/' };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Every query parameter on this request, as the `query.<param>` signal family
|
|
27
|
+
* (kywi-cms#196) — so a campaign link like `/developers?from=marketer` is a
|
|
28
|
+
* one-line audience rule (`query.from equals marketer`) instead of a substring
|
|
29
|
+
* match against the entry page.
|
|
30
|
+
*
|
|
31
|
+
* Never gated: like the URL's own `utm_*` params, these are the content of the
|
|
32
|
+
* request being served, not tracking carried into it from an earlier visit.
|
|
33
|
+
* Repeated params keep the FIRST value, matching `URLSearchParams.get`.
|
|
34
|
+
*/
|
|
35
|
+
export function collectQuery(req) {
|
|
36
|
+
const out = {};
|
|
37
|
+
let params;
|
|
38
|
+
try {
|
|
39
|
+
params = new URL(req.url).searchParams;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
for (const [key, value] of params) {
|
|
45
|
+
if (key !== '' && !(key in out))
|
|
46
|
+
out[key] = value;
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/audiences/collectors/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAA2B,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAchD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAY,EACZ,OAA4B,EAC5B,OAA8D,EAAE;IAEhE,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,YAAY,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC3F,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;QAC7D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC;QACjC,CAAC,CAAC,SAAS,CAAA;IACb,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAA;AAC/D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,IAAI,MAAuB,CAAA;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACnD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ConsentGateOptions } from '../consent.js';
|
|
1
2
|
export interface UtmSignals {
|
|
2
3
|
source: string | null;
|
|
3
4
|
medium: string | null;
|
|
@@ -5,5 +6,18 @@ export interface UtmSignals {
|
|
|
5
6
|
term: string | null;
|
|
6
7
|
content: string | null;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the visitor's UTM attribution: this request's `utm_*` query params,
|
|
11
|
+
* falling back to the persisted `kywi_utm` cookie.
|
|
12
|
+
*
|
|
13
|
+
* The cookie fallback is IGNORED unless the visitor consents to personalization
|
|
14
|
+
* (kywi-cms#91). Blocking the write alone would not be enough — a visitor who
|
|
15
|
+
* accepted last month and rejects today still carries the cookie, and reading it
|
|
16
|
+
* would keep them in a campaign audience they just opted out of. The URL's own
|
|
17
|
+
* `utm_*` params are always honoured: they are this request's content, not
|
|
18
|
+
* stored tracking.
|
|
19
|
+
*/
|
|
20
|
+
export declare function collectUtm(req: Request, cookies: Map<string, string>, gate?: ConsentGateOptions & {
|
|
21
|
+
cookieHeader?: string | null;
|
|
22
|
+
}): UtmSignals;
|
|
9
23
|
//# sourceMappingURL=utm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utm.d.ts","sourceRoot":"","sources":["../../../src/audiences/collectors/utm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utm.d.ts","sourceRoot":"","sources":["../../../src/audiences/collectors/utm.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAE9E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,GAAE,kBAAkB,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC/D,UAAU,CAgBZ"}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { COOKIE_NAMES } from '../cookies.js';
|
|
2
|
-
|
|
2
|
+
import { cookieAllowedByHeader } from '../consent.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the visitor's UTM attribution: this request's `utm_*` query params,
|
|
5
|
+
* falling back to the persisted `kywi_utm` cookie.
|
|
6
|
+
*
|
|
7
|
+
* The cookie fallback is IGNORED unless the visitor consents to personalization
|
|
8
|
+
* (kywi-cms#91). Blocking the write alone would not be enough — a visitor who
|
|
9
|
+
* accepted last month and rejects today still carries the cookie, and reading it
|
|
10
|
+
* would keep them in a campaign audience they just opted out of. The URL's own
|
|
11
|
+
* `utm_*` params are always honoured: they are this request's content, not
|
|
12
|
+
* stored tracking.
|
|
13
|
+
*/
|
|
14
|
+
export function collectUtm(req, cookies, gate = {}) {
|
|
3
15
|
const url = new URL(req.url);
|
|
4
16
|
let cookieUtm = {};
|
|
5
|
-
const raw =
|
|
17
|
+
const raw = cookieAllowedByHeader(COOKIE_NAMES.UTM, gate.cookieHeader ?? req.headers.get('cookie'), gate)
|
|
18
|
+
? cookies.get(COOKIE_NAMES.UTM)
|
|
19
|
+
: undefined;
|
|
6
20
|
if (raw) {
|
|
7
21
|
try {
|
|
8
22
|
cookieUtm = JSON.parse(raw);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utm.js","sourceRoot":"","sources":["../../../src/audiences/collectors/utm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"utm.js","sourceRoot":"","sources":["../../../src/audiences/collectors/utm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,qBAAqB,EAA2B,MAAM,eAAe,CAAA;AAU9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACxB,GAAY,EACZ,OAA4B,EAC5B,OAA8D,EAAE;IAEhE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,SAAS,GAAwB,EAAE,CAAA;IACvC,MAAM,GAAG,GAAG,qBAAqB,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;QACvG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC;QAC/B,CAAC,CAAC,SAAS,CAAA;IACb,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC;YAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACnF,CAAC;IACD,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI;QACtE,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI;QACtE,QAAQ,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC,QAAQ,IAAI,IAAI;QAC5E,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,IAAI,IAAI,IAAI;QAChE,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,SAAS,CAAC,OAAO,IAAI,IAAI;KAC1E,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve `theme.personalization.requireConsent` from a `KywiConfig`
|
|
3
|
+
* (kywi-cms#91).
|
|
4
|
+
*
|
|
5
|
+
* Kept out of `./consent.ts` because that module must import nothing at all —
|
|
6
|
+
* it is pulled into Next.js edge middleware. This file's only import is a TYPE,
|
|
7
|
+
* which erases at compile time, but it lives next door rather than inside the
|
|
8
|
+
* gate so the edge entry stays obviously dependency-free.
|
|
9
|
+
*/
|
|
10
|
+
import type { KywiConfig } from '../config/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Does this site require consent before personalization cookies are written?
|
|
13
|
+
*
|
|
14
|
+
* **True unless a theme explicitly opts out.** The flag lives on the theme, so
|
|
15
|
+
* it resolves the same way `clientRuntimeEnabled` / `transparencyNoticeEnabled`
|
|
16
|
+
* do in the reference app: the named site's theme, falling back to the first
|
|
17
|
+
* site's theme and then the first theme declared. A site with no theme at all
|
|
18
|
+
* requires consent — the safe answer is the default answer.
|
|
19
|
+
*/
|
|
20
|
+
export declare function personalizationRequiresConsent(config: KywiConfig, siteId?: string): boolean;
|
|
21
|
+
//# sourceMappingURL=consent-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-config.d.ts","sourceRoot":"","sources":["../../src/audiences/consent-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAI3F"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does this site require consent before personalization cookies are written?
|
|
3
|
+
*
|
|
4
|
+
* **True unless a theme explicitly opts out.** The flag lives on the theme, so
|
|
5
|
+
* it resolves the same way `clientRuntimeEnabled` / `transparencyNoticeEnabled`
|
|
6
|
+
* do in the reference app: the named site's theme, falling back to the first
|
|
7
|
+
* site's theme and then the first theme declared. A site with no theme at all
|
|
8
|
+
* requires consent — the safe answer is the default answer.
|
|
9
|
+
*/
|
|
10
|
+
export function personalizationRequiresConsent(config, siteId) {
|
|
11
|
+
const site = (siteId ? config.sites.find((s) => s.id === siteId) : undefined) ?? config.sites[0];
|
|
12
|
+
const theme = config.themes.find((t) => t.name === site?.theme) ?? config.themes[0];
|
|
13
|
+
return theme?.personalization?.requireConsent !== false;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=consent-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-config.js","sourceRoot":"","sources":["../../src/audiences/consent-config.ts"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH,MAAM,UAAU,8BAA8B,CAAC,MAAkB,EAAE,MAAe;IAChF,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAChG,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACnF,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,KAAK,KAAK,CAAA;AACzD,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { KywiDb } from '../db/client.js';
|
|
2
|
+
/** The env var mirroring `theme.personalization.requireConsent` for edge middleware. */
|
|
3
|
+
export declare const REQUIRE_CONSENT_ENV = "KYWI_REQUIRE_CONSENT";
|
|
4
|
+
/** How `middleware.ts` reads the mirror: anything but the literal "false" is true. */
|
|
5
|
+
export declare function requireConsentFromEnv(env?: Record<string, string | undefined>): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Fail startup when the config flag and its edge mirror disagree.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately a throw and not a warning: the two halves of one setting pointing
|
|
10
|
+
* opposite ways is never intentional, and the resulting behaviour (cookies
|
|
11
|
+
* written by the edge that the API then declines to read, or vice versa) is
|
|
12
|
+
* exactly the kind of bug that survives to production because nothing is
|
|
13
|
+
* visibly broken.
|
|
14
|
+
*/
|
|
15
|
+
export declare function assertConsentEnvAgreement(requireConsentFromConfig: boolean, env?: Record<string, string | undefined>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Build the once-only "consent required, but nothing asks for it" check.
|
|
18
|
+
*
|
|
19
|
+
* Returns a function safe to call on every request: it runs at most once, never
|
|
20
|
+
* awaits (the first request does not pay for it), and swallows every error. A
|
|
21
|
+
* warning that could break a page, or add latency to the hot path, would not be
|
|
22
|
+
* worth having.
|
|
23
|
+
*
|
|
24
|
+
* The check is a `::text LIKE` prefilter — the same shape
|
|
25
|
+
* `checkAudienceDeletionSafety` uses — looking for anything that mentions the
|
|
26
|
+
* module type at all. Over-matching is fine here: a false negative (staying
|
|
27
|
+
* quiet) is the safe direction for an advisory warning.
|
|
28
|
+
*
|
|
29
|
+
* It reads BOTH places a module can be placed: `kywi_content.layout` and
|
|
30
|
+
* `kywi_section_templates.definition`. A banner composed from a blueprint is a
|
|
31
|
+
* banner, and scanning pages alone told a site that builds every page that way
|
|
32
|
+
* that consent could never be granted — while the banner was on screen.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createConsentBannerCheck(deps: {
|
|
35
|
+
db: KywiDb;
|
|
36
|
+
requireConsent: boolean;
|
|
37
|
+
warn?: (message: string) => void;
|
|
38
|
+
}): () => void;
|
|
39
|
+
//# sourceMappingURL=consent-startup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-startup.d.ts","sourceRoot":"","sources":["../../src/audiences/consent-startup.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C,wFAAwF;AACxF,eAAO,MAAM,mBAAmB,yBAAyB,CAAA;AAEzD,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO,CAEpG;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,wBAAwB,EAAE,OAAO,EACjC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,IAAI,CAcN;AASD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,EAAE,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC,GAAG,MAAM,IAAI,CA8Bb"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup checks for the cookie-consent gate (kywi-cms#91).
|
|
3
|
+
*
|
|
4
|
+
* Two failure modes are invisible at runtime and expensive to discover later:
|
|
5
|
+
*
|
|
6
|
+
* 1. The config flag and its edge mirror disagree. `middleware.ts` runs on the
|
|
7
|
+
* edge and cannot read `kywi.config.ts`, so `requireConsent` is mirrored as
|
|
8
|
+
* `KYWI_REQUIRE_CONSENT`. If the two drift, the middleware and the API
|
|
9
|
+
* disagree about whether a visitor may be tracked — one writes
|
|
10
|
+
* `kywi_visitor`, the other refuses to read it — and nothing anywhere says
|
|
11
|
+
* so. That is a misconfiguration, and it fails the deploy.
|
|
12
|
+
*
|
|
13
|
+
* 2. Consent is required and no page offers a way to give it. Every
|
|
14
|
+
* personalization cookie is then permanently suppressed: audiences,
|
|
15
|
+
* experiments and UTM attribution quietly do nothing, and the site looks
|
|
16
|
+
* broken rather than gated. That is a WARNING, not an error — a site may
|
|
17
|
+
* legitimately have no personalization at all — but it must be said out
|
|
18
|
+
* loud, once, rather than left for someone to debug.
|
|
19
|
+
*/
|
|
20
|
+
import { sql } from 'drizzle-orm';
|
|
21
|
+
/** The env var mirroring `theme.personalization.requireConsent` for edge middleware. */
|
|
22
|
+
export const REQUIRE_CONSENT_ENV = 'KYWI_REQUIRE_CONSENT';
|
|
23
|
+
/** How `middleware.ts` reads the mirror: anything but the literal "false" is true. */
|
|
24
|
+
export function requireConsentFromEnv(env = process.env) {
|
|
25
|
+
return env[REQUIRE_CONSENT_ENV] !== 'false';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Fail startup when the config flag and its edge mirror disagree.
|
|
29
|
+
*
|
|
30
|
+
* Deliberately a throw and not a warning: the two halves of one setting pointing
|
|
31
|
+
* opposite ways is never intentional, and the resulting behaviour (cookies
|
|
32
|
+
* written by the edge that the API then declines to read, or vice versa) is
|
|
33
|
+
* exactly the kind of bug that survives to production because nothing is
|
|
34
|
+
* visibly broken.
|
|
35
|
+
*/
|
|
36
|
+
export function assertConsentEnvAgreement(requireConsentFromConfig, env = process.env) {
|
|
37
|
+
const fromEnv = requireConsentFromEnv(env);
|
|
38
|
+
if (fromEnv === requireConsentFromConfig)
|
|
39
|
+
return;
|
|
40
|
+
const raw = env[REQUIRE_CONSENT_ENV];
|
|
41
|
+
throw new Error(`Cookie-consent misconfiguration: theme.personalization.requireConsent is ` +
|
|
42
|
+
`${requireConsentFromConfig} but ${REQUIRE_CONSENT_ENV} is ` +
|
|
43
|
+
`${raw === undefined ? 'unset (which means true)' : JSON.stringify(raw)}.\n` +
|
|
44
|
+
` Next.js edge middleware cannot read kywi.config.ts, so it mirrors that flag ` +
|
|
45
|
+
`through ${REQUIRE_CONSENT_ENV}. While they disagree, the middleware and the API ` +
|
|
46
|
+
`disagree about whether a visitor may be tracked.\n` +
|
|
47
|
+
` Set both, or neither: ${REQUIRE_CONSENT_ENV}=false alongside ` +
|
|
48
|
+
`personalization: { requireConsent: false }, or remove both.`);
|
|
49
|
+
}
|
|
50
|
+
const NO_BANNER_WARNING = '[kywi] Cookie consent is required (theme.personalization.requireConsent) but no ' +
|
|
51
|
+
'page or layout places the `cookieConsent` module, so no visitor can ever grant it. ' +
|
|
52
|
+
'Every personalization cookie stays suppressed: audiences, A/B bucketing and UTM ' +
|
|
53
|
+
'attribution will resolve to default content for everyone. Place the module, or set ' +
|
|
54
|
+
'personalization: { requireConsent: false } if consent is collected by external tooling.';
|
|
55
|
+
/**
|
|
56
|
+
* Build the once-only "consent required, but nothing asks for it" check.
|
|
57
|
+
*
|
|
58
|
+
* Returns a function safe to call on every request: it runs at most once, never
|
|
59
|
+
* awaits (the first request does not pay for it), and swallows every error. A
|
|
60
|
+
* warning that could break a page, or add latency to the hot path, would not be
|
|
61
|
+
* worth having.
|
|
62
|
+
*
|
|
63
|
+
* The check is a `::text LIKE` prefilter — the same shape
|
|
64
|
+
* `checkAudienceDeletionSafety` uses — looking for anything that mentions the
|
|
65
|
+
* module type at all. Over-matching is fine here: a false negative (staying
|
|
66
|
+
* quiet) is the safe direction for an advisory warning.
|
|
67
|
+
*
|
|
68
|
+
* It reads BOTH places a module can be placed: `kywi_content.layout` and
|
|
69
|
+
* `kywi_section_templates.definition`. A banner composed from a blueprint is a
|
|
70
|
+
* banner, and scanning pages alone told a site that builds every page that way
|
|
71
|
+
* that consent could never be granted — while the banner was on screen.
|
|
72
|
+
*/
|
|
73
|
+
export function createConsentBannerCheck(deps) {
|
|
74
|
+
const warn = deps.warn ?? ((m) => console.warn(m));
|
|
75
|
+
let started = false;
|
|
76
|
+
return () => {
|
|
77
|
+
if (started || !deps.requireConsent)
|
|
78
|
+
return;
|
|
79
|
+
started = true;
|
|
80
|
+
void (async () => {
|
|
81
|
+
try {
|
|
82
|
+
const rows = await deps.db.execute(sql `
|
|
83
|
+
SELECT 1 AS found
|
|
84
|
+
FROM kywi_content
|
|
85
|
+
WHERE layout IS NOT NULL
|
|
86
|
+
AND layout::text LIKE ${'%"cookieConsent"%'}
|
|
87
|
+
UNION ALL
|
|
88
|
+
SELECT 1 AS found
|
|
89
|
+
FROM kywi_section_templates
|
|
90
|
+
WHERE definition IS NOT NULL
|
|
91
|
+
AND definition::text LIKE ${'%"cookieConsent"%'}
|
|
92
|
+
LIMIT 1
|
|
93
|
+
`);
|
|
94
|
+
if (rows.length === 0)
|
|
95
|
+
warn(NO_BANNER_WARNING);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// No content table yet (a fresh install mid-migration), a dialect that
|
|
99
|
+
// cannot cast, a transient connection failure — none of that is worth
|
|
100
|
+
// failing or logging a request over. Silence is the safe direction.
|
|
101
|
+
}
|
|
102
|
+
})();
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=consent-startup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-startup.js","sourceRoot":"","sources":["../../src/audiences/consent-startup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,wFAAwF;AACxF,MAAM,CAAC,MAAM,mBAAmB,GAAG,sBAAsB,CAAA;AAEzD,sFAAsF;AACtF,MAAM,UAAU,qBAAqB,CAAC,MAA0C,OAAO,CAAC,GAAG;IACzF,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,OAAO,CAAA;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,wBAAiC,EACjC,MAA0C,OAAO,CAAC,GAAG;IAErD,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,OAAO,KAAK,wBAAwB;QAAE,OAAM;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAA;IACpC,MAAM,IAAI,KAAK,CACb,2EAA2E;QACzE,GAAG,wBAAwB,QAAQ,mBAAmB,MAAM;QAC5D,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK;QAC5E,gFAAgF;QAChF,WAAW,mBAAmB,oDAAoD;QAClF,oDAAoD;QACpD,2BAA2B,mBAAmB,mBAAmB;QACjE,6DAA6D,CAChE,CAAA;AACH,CAAC;AAED,MAAM,iBAAiB,GACrB,kFAAkF;IAClF,qFAAqF;IACrF,kFAAkF;IAClF,qFAAqF;IACrF,yFAAyF,CAAA;AAE3F;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAIxC;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1D,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO,GAAG,EAAE;QACV,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAM;QAC3C,OAAO,GAAG,IAAI,CAAA;QACd,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAChC,GAAG,CAAA;;;;sCAIyB,mBAAmB;;;;;0CAKf,mBAAmB;;WAElD,CACF,CAAA;gBACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,iBAAiB,CAAC,CAAA;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,uEAAuE;gBACvE,sEAAsE;gBACtE,oEAAoE;YACtE,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;IACN,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie consent — the category map, and the gate every optional cookie write
|
|
3
|
+
* passes through (kywi-cms#91).
|
|
4
|
+
*
|
|
5
|
+
* Before this module the `cookieConsent` layout module and the `kywi_consent`
|
|
6
|
+
* cookie were two halves of a feature that never met: the banner's buttons had
|
|
7
|
+
* no handlers, and no cookie-writing code path ever asked whether the visitor
|
|
8
|
+
* had consented. This file is the join. It owns three things:
|
|
9
|
+
*
|
|
10
|
+
* 1. `COOKIE_CONSENT_CATEGORY` — the SINGLE SOURCE OF TRUTH mapping every
|
|
11
|
+
* cookie the engine writes to the consent category it needs. Nothing else
|
|
12
|
+
* in the codebase may decide a cookie's category.
|
|
13
|
+
* 2. `cookieAllowed()` / `consentAllows()` — the gate. Every optional cookie
|
|
14
|
+
* write calls one of these first.
|
|
15
|
+
* 3. The browser-side read/write of the `kywi_consent` cookie itself, used by
|
|
16
|
+
* the `cookieConsent` layout module's buttons.
|
|
17
|
+
*
|
|
18
|
+
* ── Category decisions (owner-set) ──────────────────────────────────────────
|
|
19
|
+
*
|
|
20
|
+
* necessary / `essential` — always allowed, never gated:
|
|
21
|
+
* `kywi_consent` the consent record itself
|
|
22
|
+
* `kywi_optout` the personalization opt-out flag: a *suppression*
|
|
23
|
+
* preference. Blocking a visitor from recording "stop
|
|
24
|
+
* personalizing me" until they consent to cookies would
|
|
25
|
+
* be perverse, so this is necessary by construction.
|
|
26
|
+
* `kywi_preview_init` admin preview hand-off, not visitor tracking.
|
|
27
|
+
*
|
|
28
|
+
* `personalization` — gated:
|
|
29
|
+
* `kywi_visitor` visitor id, incl. experiment bucketing / exposure
|
|
30
|
+
* `kywi_signals` the signed server-resolved audience signals
|
|
31
|
+
* `kywi_utm` campaign attribution carried across navigation
|
|
32
|
+
* `kywi_audience` the audience the RUNTIME resolved and remembered. A pin
|
|
33
|
+
* the visitor chose by hand in the transparency panel is
|
|
34
|
+
* `essential` instead — see the `source` discussion in
|
|
35
|
+
* `api/audience-runtime-routes.ts`
|
|
36
|
+
* `kywi_known` adapter-pushed known-identity flag
|
|
37
|
+
* `kywi_entry` the first page of the session (kywi-cms#196). Carried
|
|
38
|
+
* across navigation, so it is exactly the kind of stored
|
|
39
|
+
* signal the gate governs — the landing request's own path
|
|
40
|
+
* is read straight off the URL either way, so a campaign
|
|
41
|
+
* link still personalizes the page it points at.
|
|
42
|
+
* `kywi_selfid` the visitor's self-ID answers, kept server-readable so a
|
|
43
|
+
* server-pruned variant arm can be chosen from them
|
|
44
|
+
* (kywi-cms#200). The audience PIN that a self-ID submit
|
|
45
|
+
* produces is `essential` under the `switcher:` rule
|
|
46
|
+
* below — a control the visitor operated by hand — but the
|
|
47
|
+
* stored attribute bag itself is tracking and is gated.
|
|
48
|
+
*
|
|
49
|
+
* Auth/session cookies (the admin's access + refresh cookies, CSRF) are
|
|
50
|
+
* `essential` by definition and deliberately never routed through this gate —
|
|
51
|
+
* they carry no tracking and the admin cannot function without them.
|
|
52
|
+
*
|
|
53
|
+
* ── Undecided means not consented ───────────────────────────────────────────
|
|
54
|
+
*
|
|
55
|
+
* A visitor who has not answered the banner has a null `ConsentState`, and
|
|
56
|
+
* `consentAllows(null, 'personalization')` is FALSE. This matches `hasConsent()`
|
|
57
|
+
* in `@kywi-software/js` and is the compliance-correct default. The consequence
|
|
58
|
+
* is deliberate: until a visitor accepts, personalization cookies are not
|
|
59
|
+
* written and pages degrade to their default (unpersonalized) content. Nothing
|
|
60
|
+
* fails — the request still resolves, the visitor id is still minted for the
|
|
61
|
+
* duration of that request, it just is not persisted.
|
|
62
|
+
*
|
|
63
|
+
* An unmapped cookie name is denied rather than allowed, so adding a new cookie
|
|
64
|
+
* without classifying it here fails closed. A core test asserts every name in
|
|
65
|
+
* `COOKIE_NAMES` appears in the map, so that failure surfaces at test time.
|
|
66
|
+
*
|
|
67
|
+
* ── The escape hatch: personalization.requireConsent ────────────────────────
|
|
68
|
+
*
|
|
69
|
+
* `theme.personalization.requireConsent` (kywi.config.ts) DEFAULTS TO TRUE — the
|
|
70
|
+
* compliant behaviour above. Setting it to `false` turns this gate off entirely:
|
|
71
|
+
* every category reads as allowed, decided or not, and the cookie writes behave
|
|
72
|
+
* as they did before kywi-cms#91. That is for a site whose consent is collected
|
|
73
|
+
* by external tooling (a third-party CMP) which suppresses cookies its own way;
|
|
74
|
+
* the site takes responsibility for compliance, and Kywi stops second-guessing
|
|
75
|
+
* it. It is NOT a way to opt out of consent — turning it off on a site with no
|
|
76
|
+
* other consent mechanism is the non-compliant configuration this issue existed
|
|
77
|
+
* to fix.
|
|
78
|
+
*
|
|
79
|
+
* Every gate function takes the flag through a `ConsentGateOptions` bag rather
|
|
80
|
+
* than reading config itself, because this module must stay dependency-free
|
|
81
|
+
* (see below). `personalizationRequiresConsent()` in `./consent-config.ts`
|
|
82
|
+
* resolves it from a `KywiConfig`; the edge middleware, which cannot import an
|
|
83
|
+
* app's config at all, mirrors it with `KYWI_REQUIRE_CONSENT=false`.
|
|
84
|
+
*
|
|
85
|
+
* EDGE-SAFE LEAF MODULE: this file imports nothing, so it can be pulled into
|
|
86
|
+
* Next.js edge middleware (where core's DB-backed code cannot run) and into
|
|
87
|
+
* `audiences/utm-persistence.ts`, which has the same constraint. It is
|
|
88
|
+
* published as its own export entry (`@kywi-software/core/audiences/consent`).
|
|
89
|
+
* Keep it dependency-free. The browser-only helpers guard on `document`, so
|
|
90
|
+
* importing this on the server or the edge is safe.
|
|
91
|
+
*/
|
|
92
|
+
/** The cookie the visitor's consent decision is stored in. */
|
|
93
|
+
export declare const CONSENT_COOKIE = "kywi_consent";
|
|
94
|
+
/** 1 year, in seconds — how long a consent decision is remembered. */
|
|
95
|
+
export declare const CONSENT_MAX_AGE: number;
|
|
96
|
+
/** The cookie an audience pin lives in. */
|
|
97
|
+
export declare const AUDIENCE_PIN_COOKIE = "kywi_audience";
|
|
98
|
+
/**
|
|
99
|
+
* The `kywi_audience` value prefix marking a pin the visitor chose BY HAND in
|
|
100
|
+
* the transparency panel, as opposed to one the runtime remembered on its own.
|
|
101
|
+
*
|
|
102
|
+
* Owned here, in the zero-import leaf, because both halves of the feature need
|
|
103
|
+
* it and neither can import the other: `collectors/pinned-audience.ts` encodes
|
|
104
|
+
* and decodes with it, and `clearDeniedCookies` below must recognise it to avoid
|
|
105
|
+
* sweeping away a preference it is supposed to honour.
|
|
106
|
+
*/
|
|
107
|
+
export declare const SWITCHER_PIN_PREFIX = "switcher:";
|
|
108
|
+
export type ConsentCategory = 'essential' | 'analytics' | 'marketing' | 'personalization';
|
|
109
|
+
/** Shared tail argument of every gate function. */
|
|
110
|
+
export interface ConsentGateOptions {
|
|
111
|
+
/**
|
|
112
|
+
* `theme.personalization.requireConsent`. Defaults to true. When explicitly
|
|
113
|
+
* `false` the gate is off and every category reads as allowed — the
|
|
114
|
+
* external-CMP escape hatch described in the file header.
|
|
115
|
+
*/
|
|
116
|
+
requireConsent?: boolean;
|
|
117
|
+
}
|
|
118
|
+
export interface ConsentState {
|
|
119
|
+
essential: boolean;
|
|
120
|
+
analytics: boolean;
|
|
121
|
+
marketing: boolean;
|
|
122
|
+
personalization: boolean;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Every cookie the engine writes → the consent category it requires.
|
|
126
|
+
* The single source of truth; see the file header for the reasoning behind
|
|
127
|
+
* each classification.
|
|
128
|
+
*/
|
|
129
|
+
export declare const COOKIE_CONSENT_CATEGORY: {
|
|
130
|
+
readonly kywi_consent: "essential";
|
|
131
|
+
readonly kywi_optout: "essential";
|
|
132
|
+
readonly kywi_preview_init: "essential";
|
|
133
|
+
readonly kywi_signals: "personalization";
|
|
134
|
+
readonly kywi_visitor: "personalization";
|
|
135
|
+
readonly kywi_utm: "personalization";
|
|
136
|
+
readonly kywi_audience: "personalization";
|
|
137
|
+
readonly kywi_known: "personalization";
|
|
138
|
+
readonly kywi_entry: "personalization";
|
|
139
|
+
readonly kywi_selfid: "personalization";
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* The consent category `cookieName` requires, or `null` when the name is not
|
|
143
|
+
* classified. An unclassified cookie is denied by `cookieAllowed`.
|
|
144
|
+
*/
|
|
145
|
+
export declare function consentCategoryFor(cookieName: string): ConsentCategory | null;
|
|
146
|
+
/** Parse a raw `kywi_consent` cookie value. Returns null when absent/malformed. */
|
|
147
|
+
export declare function parseConsentValue(raw: string | null | undefined): ConsentState | null;
|
|
148
|
+
/**
|
|
149
|
+
* Read the consent decision out of a request's `Cookie` header.
|
|
150
|
+
* Returns null when the header is absent or carries no usable decision.
|
|
151
|
+
*
|
|
152
|
+
* A header can legitimately carry the same cookie name twice — most often a
|
|
153
|
+
* `Path=/` cookie shadowed by a narrower one from an earlier deploy. Taking the
|
|
154
|
+
* first match and giving up if it will not parse would throw away a perfectly
|
|
155
|
+
* good decision sitting right behind a corrupt one, so keep looking.
|
|
156
|
+
*/
|
|
157
|
+
export declare function readConsentFromCookieHeader(header: string | null | undefined): ConsentState | null;
|
|
158
|
+
/**
|
|
159
|
+
* Is `category` granted by `state`? `essential` is always granted — necessary
|
|
160
|
+
* cookies need no consent. Every other category requires an explicit `true`,
|
|
161
|
+
* so an undecided visitor (null state) grants nothing.
|
|
162
|
+
*/
|
|
163
|
+
export declare function consentAllows(state: ConsentState | null, category: ConsentCategory, options?: ConsentGateOptions): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* The gate: may `cookieName` be written given `state`? Unclassified cookie
|
|
166
|
+
* names fail closed — unless the gate itself is off.
|
|
167
|
+
*/
|
|
168
|
+
export declare function cookieAllowed(cookieName: string, state: ConsentState | null, options?: ConsentGateOptions): boolean;
|
|
169
|
+
/** Convenience for request handlers: gate `cookieName` against a `Cookie` header. */
|
|
170
|
+
export declare function cookieAllowedByHeader(cookieName: string, header: string | null | undefined, options?: ConsentGateOptions): boolean;
|
|
171
|
+
/** Every cookie name classified into `category`. */
|
|
172
|
+
export declare function cookiesInCategory(category: ConsentCategory): string[];
|
|
173
|
+
/**
|
|
174
|
+
* Delete every cookie whose category `state` does not grant, and return the
|
|
175
|
+
* names deleted.
|
|
176
|
+
*
|
|
177
|
+
* Refusing to WRITE new cookies is only half of "Reject All" — a visitor who
|
|
178
|
+
* accepted last month and rejects today is still carrying a `kywi_visitor` id,
|
|
179
|
+
* and a gate that only blocks writes would keep reading it forever. So a
|
|
180
|
+
* decision revokes as well as denies (kywi-cms#91).
|
|
181
|
+
*
|
|
182
|
+
* `kywi_signals` is HttpOnly and cannot be removed from script; the attempt is
|
|
183
|
+
* harmless and the server stops writing it, after which it expires on its own
|
|
184
|
+
* 60-second horizon. The server-side read paths ALSO ignore personalization
|
|
185
|
+
* cookies whenever the gate denies, so a cookie script cannot clear is inert
|
|
186
|
+
* either way.
|
|
187
|
+
*
|
|
188
|
+
* No-op off the browser.
|
|
189
|
+
*/
|
|
190
|
+
export declare function clearDeniedCookies(state: ConsentState | null): string[];
|
|
191
|
+
/** Read the visitor's consent decision from `document.cookie`, or null. */
|
|
192
|
+
export declare function getConsentState(): ConsentState | null;
|
|
193
|
+
/**
|
|
194
|
+
* Record a consent decision. `essential` is always forced true — the visitor
|
|
195
|
+
* cannot decline necessary cookies, and the banner renders that checkbox
|
|
196
|
+
* checked and disabled to say so. Returns the state written.
|
|
197
|
+
*
|
|
198
|
+
* Any category the decision denies is REVOKED at the same time: see
|
|
199
|
+
* `clearDeniedCookies`. Rejecting is not just "stop writing", it is "and delete
|
|
200
|
+
* what you already wrote".
|
|
201
|
+
*/
|
|
202
|
+
export declare function setConsent(prefs: Partial<Omit<ConsentState, 'essential'>>): ConsentState;
|
|
203
|
+
/** Has the visitor granted `category`? See `consentAllows` for the semantics. */
|
|
204
|
+
export declare function hasConsent(category: ConsentCategory, options?: ConsentGateOptions): boolean;
|
|
205
|
+
//# sourceMappingURL=consent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/audiences/consent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,cAAc,iBAAiB,CAAA;AAE5C,sEAAsE;AACtE,eAAO,MAAM,eAAe,QAAkB,CAAA;AAE9C,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,kBAAkB,CAAA;AAElD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAA;AAE9C,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAA;AAEzF,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;CAWgB,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAE7E;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAsBrF;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAWlG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAKT;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAOT;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAET;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,EAAE,CAIrE;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,EAAE,CAUvE;AAsCD,2EAA2E;AAC3E,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAGrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,GAAG,YAAY,CAiBxF;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAE/F"}
|