@cosmicdrift/kumiko-bundled-features 0.374.0 → 0.377.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/account-security/constants.d.ts +1 -0
- package/dist/account-security/constants.js +1 -0
- package/dist/account-security/index.d.ts +1 -1
- package/dist/account-security/index.js +1 -1
- package/dist/admin-shell/web/client-plugin.d.ts +1 -1
- package/dist/audit/web/client-plugin.d.ts +1 -1
- package/dist/auth-email-password/mail-notifications.js +1 -1
- package/dist/auth-email-password/web/auth-client.js +1 -1
- package/dist/auth-email-password/web/auth-form-primitives.js +1 -1
- package/dist/auth-email-password/web/default-topbar-actions.js +1 -1
- package/dist/auth-email-password/web/index.js +1 -1
- package/dist/auth-email-password/web/session.js +1 -1
- package/dist/auth-email-password/web/tenant-menu-items.js +1 -1
- package/dist/auth-email-password/web/tenant-switcher.js +1 -1
- package/dist/auth-email-password/web/user-menu.js +1 -1
- package/dist/auth-foundation/env.d.ts +9 -0
- package/dist/auth-foundation/env.js +21 -0
- package/dist/auth-foundation/index.d.ts +1 -0
- package/dist/auth-foundation/index.js +1 -0
- package/dist/auth-mfa/schema/user-mfa.d.ts +6 -6
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +1 -1
- package/dist/billing-foundation/consumer-protection/termination-pages.js +1 -1
- package/dist/billing-foundation/contact-card.d.ts +2 -0
- package/dist/billing-foundation/contact-card.js +16 -0
- package/dist/billing-foundation/entities.d.ts +8 -8
- package/dist/billing-foundation/handlers/billing-plans.query.js +1 -1
- package/dist/billing-foundation/index.d.ts +1 -1
- package/dist/billing-foundation/plan-catalog.js +1 -0
- package/dist/billing-foundation/projection.d.ts +8 -8
- package/dist/billing-foundation/types.d.ts +11 -0
- package/dist/billing-foundation/validate-options.js +13 -0
- package/dist/billing-foundation/web/billing-contact-plan.d.ts +5 -0
- package/dist/billing-foundation/web/billing-contact-plan.js +17 -0
- package/dist/billing-foundation/web/billing-plans-panel.js +5 -13
- package/dist/billing-foundation/web/cancel-contract-dialog.js +2 -2
- package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +1 -1
- package/dist/billing-foundation/web/checkout-consent-dialog.js +1 -0
- package/dist/billing-foundation/web/client-plugin.d.ts +1 -1
- package/dist/billing-foundation/web/localized-params.d.ts +1 -0
- package/dist/billing-foundation/web/localized-params.js +11 -0
- package/dist/cap-counter/entity.d.ts +1 -1
- package/dist/cap-overview/web/cap-cards-panel.js +3 -3
- package/dist/cap-overview/web/client-plugin.d.ts +1 -1
- package/dist/channel-email/email-channel.d.ts +2 -1
- package/dist/compliance-profiles/web/client-plugin.d.ts +1 -1
- package/dist/config/feature.js +2 -2
- package/dist/config/table.d.ts +6 -6
- package/dist/custom-fields/entity.d.ts +4 -4
- package/dist/custom-fields/web/client-plugin.d.ts +1 -1
- package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -4
- package/dist/delivery/tables.d.ts +6 -6
- package/dist/delivery/unsubscribe-page.js +1 -1
- package/dist/delivery/web/client-plugin.d.ts +1 -1
- package/dist/delivery/web/delivery-status-cell.js +1 -1
- package/dist/document-ingest-foundation/entity.d.ts +4 -4
- package/dist/feature-toggles/web/client-plugin.d.ts +1 -1
- package/dist/file-provider-s3/env-named-feature.d.ts +17 -0
- package/dist/file-provider-s3/env-named-feature.js +23 -0
- package/dist/file-provider-s3/env-schema.d.ts +7 -0
- package/dist/file-provider-s3/env-schema.js +15 -10
- package/dist/file-provider-s3/index.d.ts +1 -0
- package/dist/file-provider-s3/index.js +1 -0
- package/dist/folders/entity.d.ts +8 -8
- package/dist/folders/web/client-plugin.d.ts +1 -1
- package/dist/form-draft/entity.d.ts +2 -2
- package/dist/host-routing/constants.d.ts +2 -0
- package/dist/host-routing/constants.js +3 -0
- package/dist/host-routing/dispatch.d.ts +1 -1
- package/dist/host-routing/dispatch.js +35 -25
- package/dist/host-routing/feature.js +100 -27
- package/dist/host-routing/host.d.ts +9 -0
- package/dist/host-routing/host.js +24 -2
- package/dist/host-routing/index.d.ts +2 -1
- package/dist/host-routing/index.js +1 -0
- package/dist/host-routing/options.d.ts +14 -0
- package/dist/host-routing/redirects.d.ts +6 -0
- package/dist/host-routing/redirects.js +27 -0
- package/dist/host-routing/tenant-lookup.d.ts +7 -0
- package/dist/host-routing/tenant-lookup.js +39 -0
- package/dist/host-routing/validate-options.js +34 -1
- package/dist/inbound-mail-foundation/entities.d.ts +25 -25
- package/dist/inbound-mail-foundation/feature.js +7 -0
- package/dist/inbound-mail-foundation/i18n.d.ts +3 -0
- package/dist/inbound-mail-foundation/i18n.js +35 -0
- package/dist/inbound-mail-foundation/index.d.ts +1 -0
- package/dist/inbound-mail-foundation/index.js +1 -0
- package/dist/inbound-mail-foundation/projection.d.ts +20 -20
- package/dist/inbound-mail-foundation/screens.d.ts +7 -0
- package/dist/inbound-mail-foundation/screens.js +86 -0
- package/dist/inbound-mail-foundation/types.d.ts +2 -2
- package/dist/jobs/job-run-table.d.ts +6 -6
- package/dist/jobs/web/client-plugin.d.ts +1 -1
- package/dist/ledger/entity.d.ts +13 -13
- package/dist/legal-pages/feature.js +11 -1
- package/dist/legal-pages/layout.d.ts +2 -2
- package/dist/legal-pages/layout.js +4 -4
- package/dist/legal-pages/web/client-plugin.d.ts +1 -1
- package/dist/mail-foundation/feature.d.ts +20 -21
- package/dist/mail-foundation/feature.js +1 -1
- package/dist/managed-pages/table.d.ts +12 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/notes-history/entity.d.ts +12 -12
- package/dist/notes-history/web/client-plugin.d.ts +1 -1
- package/dist/page-render/branding.js +1 -1
- package/dist/page-render/layout.d.ts +1 -1
- package/dist/page-render/layout.js +2 -2
- package/dist/page-render/markdown.js +1 -1
- package/dist/personal-access-tokens/i18n.js +1 -1
- package/dist/personal-access-tokens/schema/api-token.d.ts +6 -6
- package/dist/personal-access-tokens/screens.js +1 -1
- package/dist/secrets/feature.d.ts +1 -1
- package/dist/secrets/feature.js +3 -3
- package/dist/secrets/table.d.ts +1 -1
- package/dist/seo/sitemap.js +1 -1
- package/dist/sessions/schema/user-session.d.ts +4 -4
- package/dist/shared/mail-template-body.js +1 -1
- package/dist/shared/purge-files-reaching-subject.js +98 -3
- package/dist/tags/entity.d.ts +9 -9
- package/dist/tags/web/client-plugin.d.ts +1 -1
- package/dist/template-resolver/document-blocks.d.ts +5 -0
- package/dist/template-resolver/document-blocks.js +21 -0
- package/dist/template-resolver/document-ops.d.ts +167 -0
- package/dist/template-resolver/document-ops.js +390 -0
- package/dist/template-resolver/document-sanitizer.d.ts +3 -0
- package/dist/template-resolver/document-sanitizer.js +6 -0
- package/dist/template-resolver/feature.d.ts +2 -0
- package/dist/template-resolver/feature.js +4 -0
- package/dist/template-resolver/handlers/bundle-import.js +1 -0
- package/dist/template-resolver/handlers/document-base.d.ts +23 -0
- package/dist/template-resolver/handlers/document-base.js +55 -0
- package/dist/template-resolver/handlers/document-blocks.query.d.ts +22 -0
- package/dist/template-resolver/handlers/document-blocks.query.js +46 -0
- package/dist/template-resolver/handlers/export-bundle.query.d.ts +1 -0
- package/dist/template-resolver/handlers/export-bundle.query.js +9 -2
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +1 -0
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +1 -0
- package/dist/template-resolver/handlers/patch-draft.write.d.ts +66 -0
- package/dist/template-resolver/handlers/patch-draft.write.js +105 -0
- package/dist/template-resolver/handlers/preview.query.d.ts +1 -0
- package/dist/template-resolver/handlers/preview.query.js +2 -1
- package/dist/template-resolver/handlers/send-test.write.d.ts +1 -0
- package/dist/template-resolver/handlers/send-test.write.js +2 -1
- package/dist/template-resolver/handlers/template-write.d.ts +2 -0
- package/dist/template-resolver/handlers/template-write.js +14 -2
- package/dist/template-resolver/handlers/validate.query.d.ts +10 -4
- package/dist/template-resolver/handlers/validate.query.js +12 -7
- package/dist/template-resolver/{web/placeholder-text.js → placeholder-text.js} +1 -1
- package/dist/template-resolver/qualified-names.d.ts +2 -0
- package/dist/template-resolver/qualified-names.js +2 -0
- package/dist/template-resolver/seeding.d.ts +1 -0
- package/dist/template-resolver/seeding.js +2 -1
- package/dist/template-resolver/table.d.ts +10 -10
- package/dist/template-resolver/template-bundle.d.ts +1 -0
- package/dist/template-resolver/template-bundle.js +6 -1
- package/dist/template-resolver/template-preview.d.ts +4 -1
- package/dist/template-resolver/template-preview.js +16 -3
- package/dist/template-resolver/template-validation.d.ts +2 -1
- package/dist/template-resolver/template-validation.js +1 -1
- package/dist/template-resolver/user-content-table.d.ts +10 -10
- package/dist/template-resolver/web/client-plugin.d.ts +1 -1
- package/dist/template-resolver/web/client-plugin.js +3 -3
- package/dist/template-resolver/web/document-tiptap-editor.js +1 -1
- package/dist/template-resolver/web/document-toolbar-blocks.d.ts +2 -5
- package/dist/template-resolver/web/document-toolbar-blocks.js +1 -21
- package/dist/template-resolver/web/i18n.js +14 -0
- package/dist/template-resolver/web/placeholder-line-editor.js +2 -2
- package/dist/tenant/invitation-table.d.ts +6 -6
- package/dist/tenant/membership-table.d.ts +4 -4
- package/dist/tenant/schema/tenant.d.ts +6 -6
- package/dist/tenant/web/client-plugin.d.ts +1 -1
- package/dist/tenant/web/member-status-cell.js +1 -1
- package/dist/tier-engine/entity.d.ts +1 -1
- package/dist/tier-engine/tier-resolver.d.ts +1 -1
- package/dist/tier-engine/web/client-plugin.d.ts +1 -1
- package/dist/user/schema/user.d.ts +12 -12
- package/dist/user-data-rights/env.d.ts +5 -0
- package/dist/user-data-rights/env.js +11 -0
- package/dist/user-data-rights/feature.js +4 -2
- package/dist/user-data-rights/index.d.ts +1 -0
- package/dist/user-data-rights/index.js +1 -0
- package/dist/user-data-rights/lib/mail-transport-resolver.js +1 -1
- package/dist/user-data-rights/lib/storage-provider-resolver.js +1 -1
- package/dist/user-data-rights/mail-notifications.js +1 -1
- package/dist/user-data-rights/schema/download-attempt.d.ts +14 -14
- package/dist/user-data-rights/schema/download-token.d.ts +8 -8
- package/dist/user-data-rights/schema/export-job.d.ts +6 -6
- package/dist/user-data-rights/web/client-plugin.d.ts +1 -1
- package/dist/user-data-rights/web/privacy-center-screen.js +2 -2
- package/dist/waitlist/entity.d.ts +14 -14
- package/dist/waitlist/legacy-migrate.d.ts +2 -0
- package/dist/waitlist/legacy-migrate.js +38 -3
- package/package.json +16 -11
- package/src/account-security/changes.json +6 -0
- package/src/auth-foundation/changes.json +6 -0
- package/src/billing-foundation/changes.json +6 -0
- package/src/channel-email/changes.json +6 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/file-provider-s3/changes.json +6 -0
- package/src/host-routing/changes.json +6 -0
- package/src/inbound-mail-foundation/changes.json +7 -0
- package/src/legal-pages/changes.json +6 -0
- package/src/template-resolver/changes.json +18 -0
- package/src/user-data-rights/changes.json +6 -0
- package/src/waitlist/changes.json +6 -0
- /package/dist/template-resolver/{web/placeholder-text.d.ts → placeholder-text.d.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const ACCOUNT_SECURITY_FEATURE = "account-security";
|
|
2
2
|
export declare const ACCOUNT_SECURITY_SCREEN_ID = "account-security";
|
|
3
3
|
export declare const ACCOUNT_SECURITY_SCREEN_QN = "account-security:screen:account-security";
|
|
4
|
+
export declare const ACCOUNT_SECURITY_SCREEN_TITLE_KEY = "screen:account-security.title";
|
|
4
5
|
export declare const ACCOUNT_SECURITY_NAV_LABEL = "account-security:nav.accountSecurity";
|
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
export const ACCOUNT_SECURITY_FEATURE = "account-security";
|
|
3
3
|
export const ACCOUNT_SECURITY_SCREEN_ID = "account-security";
|
|
4
4
|
export const ACCOUNT_SECURITY_SCREEN_QN = `${ACCOUNT_SECURITY_FEATURE}:screen:${ACCOUNT_SECURITY_SCREEN_ID}`;
|
|
5
|
+
export const ACCOUNT_SECURITY_SCREEN_TITLE_KEY = `screen:${ACCOUNT_SECURITY_SCREEN_ID}.title`;
|
|
5
6
|
export const ACCOUNT_SECURITY_NAV_LABEL = `${ACCOUNT_SECURITY_FEATURE}:nav.accountSecurity`;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ACCOUNT_SECURITY_FEATURE, ACCOUNT_SECURITY_NAV_LABEL, ACCOUNT_SECURITY_SCREEN_ID, ACCOUNT_SECURITY_SCREEN_QN, } from "./constants.ts";
|
|
1
|
+
export { ACCOUNT_SECURITY_FEATURE, ACCOUNT_SECURITY_NAV_LABEL, ACCOUNT_SECURITY_SCREEN_ID, ACCOUNT_SECURITY_SCREEN_QN, ACCOUNT_SECURITY_SCREEN_TITLE_KEY, } from "./constants.ts";
|
|
2
2
|
export { type AccountSecurityFeatureOptions, type AccountSecurityNavOptions, accountSecurityMfaStatusVisibility, createAccountSecurityFeature, } from "./feature.ts";
|
|
3
3
|
export { ACCOUNT_SECURITY_I18N } from "./i18n.ts";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ACCOUNT_SECURITY_FEATURE, ACCOUNT_SECURITY_NAV_LABEL, ACCOUNT_SECURITY_SCREEN_ID, ACCOUNT_SECURITY_SCREEN_QN, } from "./constants.js";
|
|
1
|
+
export { ACCOUNT_SECURITY_FEATURE, ACCOUNT_SECURITY_NAV_LABEL, ACCOUNT_SECURITY_SCREEN_ID, ACCOUNT_SECURITY_SCREEN_QN, ACCOUNT_SECURITY_SCREEN_TITLE_KEY, } from "./constants.js";
|
|
2
2
|
export { accountSecurityMfaStatusVisibility, createAccountSecurityFeature, } from "./feature.js";
|
|
3
3
|
export { ACCOUNT_SECURITY_I18N } from "./i18n.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
2
|
-
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer
|
|
2
|
+
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
3
3
|
export type AdminShellClientOptions = {
|
|
4
4
|
readonly translations?: TranslationsByLocale;
|
|
5
5
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
2
|
-
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer
|
|
2
|
+
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
3
3
|
export type AuditClientOptions = {
|
|
4
4
|
readonly translations?: TranslationsByLocale;
|
|
5
5
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QnTypes, qn, templateVariable, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { hasMailTranslationKey, listMailLocales, mailT, resolveMailLocale, } from "@cosmicdrift/kumiko-framework/i18n";
|
|
3
|
-
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
3
|
+
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-renderer/headless";
|
|
4
4
|
import { AUTH_EMAIL_PASSWORD_FEATURE } from "./constants.js";
|
|
5
5
|
export const AUTH_MAIL_KINDS = {
|
|
6
6
|
passwordReset: { name: "password-reset", translationKey: "reset" },
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// Die dispatcher-live nutzt denselben readCsrfToken-Helper; wir
|
|
9
9
|
// reuse'n ihn hier, damit die Konstanten (Cookie-Name, Header-Name)
|
|
10
10
|
// nicht divergieren.
|
|
11
|
-
import { CSRF_HEADER_NAME, readCsrfToken } from "@cosmicdrift/kumiko-dispatcher-live";
|
|
12
11
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
12
|
+
import { CSRF_HEADER_NAME, readCsrfToken } from "@cosmicdrift/kumiko-renderer/live";
|
|
13
13
|
export function csrfHeader() {
|
|
14
14
|
const token = readCsrfToken();
|
|
15
15
|
return token !== undefined ? { [CSRF_HEADER_NAME]: token } : {};
|
|
@@ -15,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
// Link-Styles laufen über das Link-Primitive (variant="button"/"muted") —
|
|
16
16
|
// die früheren authButtonClass/authMutedLinkClass sind dorthin gewandert.
|
|
17
17
|
import { usePrimitives } from "@cosmicdrift/kumiko-renderer";
|
|
18
|
-
import { BareFormProvider, cn } from "@cosmicdrift/kumiko-renderer
|
|
18
|
+
import { BareFormProvider, cn } from "@cosmicdrift/kumiko-renderer/web";
|
|
19
19
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
20
20
|
const defaultAuthShell = (card) => (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background px-4", children: card }));
|
|
21
21
|
const AuthShellContext = createContext(null);
|
|
@@ -6,7 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
// ThemeToggle → UserMenu (rechts). Apps mit eigener Anordnung
|
|
7
7
|
// importieren weiter die Einzelkomponenten direkt — DefaultTopbarActions
|
|
8
8
|
// ist Convenience, kein Muss.
|
|
9
|
-
import { ThemeToggle } from "@cosmicdrift/kumiko-renderer
|
|
9
|
+
import { ThemeToggle } from "@cosmicdrift/kumiko-renderer/web";
|
|
10
10
|
import { TenantSwitcher } from "./tenant-switcher.js";
|
|
11
11
|
import { UserMenu } from "./user-menu.js";
|
|
12
12
|
export function DefaultTopbarActions({ tenantName, extras, lightIcon, darkIcon, } = {}) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Wird über den Sub-Path-Export `@cosmicdrift/kumiko-bundled-features/auth-email-
|
|
4
4
|
// password/web` konsumiert — die Server-Seite (defineFeature) lebt in
|
|
5
5
|
// `@cosmicdrift/kumiko-bundled-features/auth-email-password` und hat keine
|
|
6
|
-
// React-/DOM-Deps. Trennung bleibt sauber so wie renderer vs renderer
|
|
6
|
+
// React-/DOM-Deps. Trennung bleibt sauber so wie renderer vs renderer/web.
|
|
7
7
|
export { defaultTranslations, mergeTranslations } from "../i18n.js";
|
|
8
8
|
export { AuthRequestError, confirmAccountUnlock, confirmSignup, requestAccountUnlock, requestEmailVerification, requestPasswordReset, requestSignup, resetPassword, toLoginResponse, verifyEmail, } from "./auth-client.js";
|
|
9
9
|
export { AuthCard, AuthShellProvider, useAuthShell } from "./auth-form-primitives.js";
|
|
@@ -9,8 +9,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
// eine Dependency weniger im Browser-Bundle haben. Die Consumer leben
|
|
10
10
|
// unter `<SessionProvider>`; der `useSession()`-Hook liefert den State
|
|
11
11
|
// und die Transitions.
|
|
12
|
-
import { readCsrfToken } from "@cosmicdrift/kumiko-dispatcher-live";
|
|
13
12
|
import { CurrentUserProvider, useSessionEndedSignal, } from "@cosmicdrift/kumiko-renderer";
|
|
13
|
+
import { readCsrfToken } from "@cosmicdrift/kumiko-renderer/live";
|
|
14
14
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
15
15
|
import { AuthRequestError, fetchCurrentUser, fetchTenants, login as loginApi, logout as logoutApi, switchTenant as switchTenantApi, } from "./auth-client.js";
|
|
16
16
|
// Exported so screens that render on BOTH authenticated and anonymous public
|
|
@@ -3,7 +3,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
// Tenant choices as dropdown entries — the TenantSwitcher's list for a user
|
|
4
4
|
// menu that carries the shell controls. Renders nothing for a single tenant.
|
|
5
5
|
import { useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
6
|
-
import { DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator, } from "@cosmicdrift/kumiko-renderer
|
|
6
|
+
import { DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator, } from "@cosmicdrift/kumiko-renderer/web";
|
|
7
7
|
import { useSession } from "./session.js";
|
|
8
8
|
export function TenantMenuItems({ tenantName }) {
|
|
9
9
|
const t = useTranslation();
|
|
@@ -15,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
// der Host den Resolver rein (kommt z.B. aus einer useTenantNames()-
|
|
16
16
|
// Hook die einmalig am App-Boot geladen wird).
|
|
17
17
|
import { useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
18
|
-
import { cn, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger, } from "@cosmicdrift/kumiko-renderer
|
|
18
|
+
import { cn, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger, } from "@cosmicdrift/kumiko-renderer/web";
|
|
19
19
|
import { Building2, ChevronDown } from "lucide-react";
|
|
20
20
|
import { useCallback, useState } from "react";
|
|
21
21
|
import { useSession } from "./session.js";
|
|
@@ -10,7 +10,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
10
10
|
// Component außerhalb des AuthGate einhängen ohne dass ein harter
|
|
11
11
|
// Fehler entsteht.
|
|
12
12
|
import { useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
13
|
-
import { cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from "@cosmicdrift/kumiko-renderer
|
|
13
|
+
import { cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from "@cosmicdrift/kumiko-renderer/web";
|
|
14
14
|
import { ChevronDown, ChevronsUpDown, LogOut } from "lucide-react";
|
|
15
15
|
import { useSession } from "./session.js";
|
|
16
16
|
function initials(value) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
/** Env block behind `auth.admin` and `auth.mail`: the first admin login and the public app URL
|
|
3
|
+
* the mail links and the Origin guard derive from. Unset keys leave the matching option to
|
|
4
|
+
* explicit values; an app spreads `.shape` into its env schema and passes the parsed values on. */
|
|
5
|
+
export declare const authEnvSchema: z.ZodObject<{
|
|
6
|
+
APP_BASE_URL: z.ZodOptional<z.ZodURL>;
|
|
7
|
+
AUTH_ADMIN_EMAIL: z.ZodOptional<z.ZodEmail>;
|
|
8
|
+
AUTH_ADMIN_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
const ADMIN_PASSWORD_MIN_LENGTH = 16;
|
|
3
|
+
/** Env block behind `auth.admin` and `auth.mail`: the first admin login and the public app URL
|
|
4
|
+
* the mail links and the Origin guard derive from. Unset keys leave the matching option to
|
|
5
|
+
* explicit values; an app spreads `.shape` into its env schema and passes the parsed values on. */
|
|
6
|
+
export const authEnvSchema = z.object({
|
|
7
|
+
APP_BASE_URL: z
|
|
8
|
+
.url()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Public https URL of the app; auth mail links, the Origin guard and unsubscribe links use it."),
|
|
11
|
+
AUTH_ADMIN_EMAIL: z
|
|
12
|
+
.email()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Login of the admin seeded through `auth.admin`."),
|
|
15
|
+
AUTH_ADMIN_PASSWORD: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(ADMIN_PASSWORD_MIN_LENGTH)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Password of the admin seeded through `auth.admin`. Generate with: openssl rand -hex 24")
|
|
20
|
+
.meta({ kumiko: { pulumi: { generator: "openssl rand -hex 24", secret: true } } }),
|
|
21
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { authEnvSchema } from "./env.ts";
|
|
1
2
|
export { createAuthFoundationFeature, type ResolvedTenantResolver, resolveSessionStore, resolveTenantExistence, resolveTenantResolver, resolveTokenVerifier, } from "./feature.ts";
|
|
2
3
|
export { resolveAnonymousAccessFromRegistry } from "./resolve-anonymous-access.ts";
|
|
3
4
|
export { type AuthProviderBuildDeps, type AuthProviderPlugin, type AuthVerifier, EXT_SESSION_STORE, EXT_TENANT_EXISTENCE, EXT_TENANT_RESOLVER, EXT_TOKEN_VERIFIER, isAuthProviderPlugin, isSessionStoreProvider, isTenantExistenceProvider, isTenantResolverProvider, isTenantResolverTrust, isValidTokenShape, type SessionMassRevoker, type SessionStore, type SessionStoreProvider, type TenantExistenceProvider, type TenantExistsFn, type TenantResolverFn, type TenantResolverProvider, type TenantResolverTrust, type TokenShape, tokenShapeKey, tokenShapeMatches, } from "./types.ts";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Public API of the auth-foundation bundled-feature.
|
|
2
|
+
export { authEnvSchema } from "./env.js";
|
|
2
3
|
export { createAuthFoundationFeature, resolveSessionStore, resolveTenantExistence, resolveTenantResolver, resolveTokenVerifier, } from "./feature.js";
|
|
3
4
|
export { resolveAnonymousAccessFromRegistry } from "./resolve-anonymous-access.js";
|
|
4
5
|
export { EXT_SESSION_STORE, EXT_TENANT_EXISTENCE, EXT_TENANT_RESOLVER, EXT_TOKEN_VERIFIER, isAuthProviderPlugin, isSessionStoreProvider, isTenantExistenceProvider, isTenantResolverProvider, isTenantResolverTrust, isValidTokenShape, tokenShapeKey, tokenShapeMatches, } from "./types.js";
|
|
@@ -13,7 +13,7 @@ export declare const userMfaEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
13
13
|
readonly sensitive?: boolean;
|
|
14
14
|
readonly writeOnly?: boolean;
|
|
15
15
|
readonly readAsInstruction?: boolean;
|
|
16
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
16
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
17
17
|
readonly default?: string;
|
|
18
18
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
19
19
|
readonly multiline?: boolean | {
|
|
@@ -36,7 +36,7 @@ export declare const userMfaEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
36
36
|
readonly sensitive?: boolean;
|
|
37
37
|
readonly writeOnly?: boolean;
|
|
38
38
|
readonly readAsInstruction?: boolean;
|
|
39
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
39
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
40
40
|
readonly default?: string;
|
|
41
41
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
42
42
|
readonly multiline?: boolean | {
|
|
@@ -59,7 +59,7 @@ export declare const userMfaEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
59
59
|
readonly sensitive?: boolean;
|
|
60
60
|
readonly writeOnly?: boolean;
|
|
61
61
|
readonly readAsInstruction?: boolean;
|
|
62
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
62
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
63
63
|
readonly default?: string;
|
|
64
64
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
65
65
|
readonly multiline?: boolean | {
|
|
@@ -114,7 +114,7 @@ export declare const userMfaTable: import("@cosmicdrift/kumiko-framework/db").En
|
|
|
114
114
|
readonly sensitive?: boolean;
|
|
115
115
|
readonly writeOnly?: boolean;
|
|
116
116
|
readonly readAsInstruction?: boolean;
|
|
117
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
117
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
118
118
|
readonly default?: string;
|
|
119
119
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
120
120
|
readonly multiline?: boolean | {
|
|
@@ -137,7 +137,7 @@ export declare const userMfaTable: import("@cosmicdrift/kumiko-framework/db").En
|
|
|
137
137
|
readonly sensitive?: boolean;
|
|
138
138
|
readonly writeOnly?: boolean;
|
|
139
139
|
readonly readAsInstruction?: boolean;
|
|
140
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
140
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
141
141
|
readonly default?: string;
|
|
142
142
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
143
143
|
readonly multiline?: boolean | {
|
|
@@ -160,7 +160,7 @@ export declare const userMfaTable: import("@cosmicdrift/kumiko-framework/db").En
|
|
|
160
160
|
readonly sensitive?: boolean;
|
|
161
161
|
readonly writeOnly?: boolean;
|
|
162
162
|
readonly readAsInstruction?: boolean;
|
|
163
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
163
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
164
164
|
readonly default?: string;
|
|
165
165
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
166
166
|
readonly multiline?: boolean | {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
1
|
+
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-renderer/headless";
|
|
2
2
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
3
|
import { Marked } from "marked";
|
|
4
4
|
import { isAllowedDocumentLinkHref, isDocumentPlaceholderHref, } from "../../template-resolver/index.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Public § 312k pages (/legal/kuendigen, /legal/cancel): form → review → confirm,
|
|
2
2
|
// no JavaScript. Every echoed value goes through escapeHtml/escapeHtmlAttr.
|
|
3
3
|
import { getSessionCookies } from "@cosmicdrift/kumiko-framework/api";
|
|
4
|
-
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
4
|
+
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-renderer/headless";
|
|
5
5
|
import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
6
6
|
import { getCookie } from "hono/cookie";
|
|
7
7
|
import { redirectToCanonicalPath, securePageHeaders, slashVariantOf, wrapInLayout, } from "../../page-render/index.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @runtime client
|
|
2
|
+
/** Shared by boot validation and the panel (defense in depth); keep free of server imports. */
|
|
3
|
+
export function isContactCardHref(href) {
|
|
4
|
+
if (href !== href.trim())
|
|
5
|
+
return false;
|
|
6
|
+
let url;
|
|
7
|
+
try {
|
|
8
|
+
url = new URL(href);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (url.protocol === "https:")
|
|
14
|
+
return true;
|
|
15
|
+
return url.protocol === "mailto:" && url.pathname !== "";
|
|
16
|
+
}
|
|
@@ -13,7 +13,7 @@ export declare const subscriptionEntity: import("@cosmicdrift/kumiko-types/field
|
|
|
13
13
|
readonly sensitive?: boolean;
|
|
14
14
|
readonly writeOnly?: boolean;
|
|
15
15
|
readonly readAsInstruction?: boolean;
|
|
16
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
16
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
17
17
|
readonly default?: string;
|
|
18
18
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
19
19
|
readonly multiline?: boolean | {
|
|
@@ -36,7 +36,7 @@ export declare const subscriptionEntity: import("@cosmicdrift/kumiko-types/field
|
|
|
36
36
|
readonly sensitive?: boolean;
|
|
37
37
|
readonly writeOnly?: boolean;
|
|
38
38
|
readonly readAsInstruction?: boolean;
|
|
39
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
39
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
40
40
|
readonly default?: string;
|
|
41
41
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
42
42
|
readonly multiline?: boolean | {
|
|
@@ -59,7 +59,7 @@ export declare const subscriptionEntity: import("@cosmicdrift/kumiko-types/field
|
|
|
59
59
|
readonly sensitive?: boolean;
|
|
60
60
|
readonly writeOnly?: boolean;
|
|
61
61
|
readonly readAsInstruction?: boolean;
|
|
62
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
62
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
63
63
|
readonly default?: string;
|
|
64
64
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
65
65
|
readonly multiline?: boolean | {
|
|
@@ -82,7 +82,7 @@ export declare const subscriptionEntity: import("@cosmicdrift/kumiko-types/field
|
|
|
82
82
|
readonly sensitive?: boolean;
|
|
83
83
|
readonly writeOnly?: boolean;
|
|
84
84
|
readonly readAsInstruction?: boolean;
|
|
85
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
85
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
86
86
|
readonly default?: string;
|
|
87
87
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
88
88
|
readonly multiline?: boolean | {
|
|
@@ -105,7 +105,7 @@ export declare const subscriptionEntity: import("@cosmicdrift/kumiko-types/field
|
|
|
105
105
|
readonly sensitive?: boolean;
|
|
106
106
|
readonly writeOnly?: boolean;
|
|
107
107
|
readonly readAsInstruction?: boolean;
|
|
108
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
108
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
109
109
|
readonly default?: string;
|
|
110
110
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
111
111
|
readonly multiline?: boolean | {
|
|
@@ -161,7 +161,7 @@ export declare const paymentEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
161
161
|
readonly sensitive?: boolean;
|
|
162
162
|
readonly writeOnly?: boolean;
|
|
163
163
|
readonly readAsInstruction?: boolean;
|
|
164
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
164
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
165
165
|
readonly default?: string;
|
|
166
166
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
167
167
|
readonly multiline?: boolean | {
|
|
@@ -184,7 +184,7 @@ export declare const paymentEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
184
184
|
readonly sensitive?: boolean;
|
|
185
185
|
readonly writeOnly?: boolean;
|
|
186
186
|
readonly readAsInstruction?: boolean;
|
|
187
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
187
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
188
188
|
readonly default?: string;
|
|
189
189
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
190
190
|
readonly multiline?: boolean | {
|
|
@@ -207,7 +207,7 @@ export declare const paymentEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
207
207
|
readonly sensitive?: boolean;
|
|
208
208
|
readonly writeOnly?: boolean;
|
|
209
209
|
readonly readAsInstruction?: boolean;
|
|
210
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
210
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
211
211
|
readonly default?: string;
|
|
212
212
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
213
213
|
readonly multiline?: boolean | {
|
|
@@ -10,7 +10,7 @@ const billingPlansSchema = z.object({}).strict();
|
|
|
10
10
|
export function createBillingPlansQuery(options, catalog) {
|
|
11
11
|
return {
|
|
12
12
|
name: "billing-plans",
|
|
13
|
-
description: "Lists the purchasable plans with live price, benefits, the caller's current tier and which action (checkout | switch | current | unavailable | paymentPending) each plan offers.",
|
|
13
|
+
description: "Lists the purchasable plans with live price, benefits, the caller's current tier and which action (checkout | switch | current | unavailable | paymentPending) each plan offers, plus the optional price-less contact card.",
|
|
14
14
|
schema: billingPlansSchema,
|
|
15
15
|
access: { roles: catalog.viewRoles },
|
|
16
16
|
handler: async (_query, ctx) => {
|
|
@@ -12,5 +12,5 @@ export { getSubscriptionForTenant, type SubscriptionView } from "./get-subscript
|
|
|
12
12
|
export { paymentsProjectionTable, subscriptionsProjectionTable } from "./projection.ts";
|
|
13
13
|
export { billingPlansPanel, createBillingPlansScreen } from "./screens.ts";
|
|
14
14
|
export { createSubscriptionTierSync, effectiveTierFromSubscription, SUBSCRIPTION_WEBHOOK_PATH, type SubscriptionTierSyncDeps, type TierSyncResult, } from "./subscription-tier-sync.ts";
|
|
15
|
-
export { type BillingFoundationOptions, type BillingPlanBenefit, type BillingPlanCatalog, type BillingPlanPrice, type BillingPlansResult, type BillingPlanView, type ConsumerProtectionOptions, KNOWN_RECURRING_INTERVALS, type LegalLinkSet, type PaymentEvent, type ProviderPrice, type ProviderSubscriptionSnapshot, type RecurringInterval, type SubscriptionEvent, type SubscriptionProviderPlugin, } from "./types.ts";
|
|
15
|
+
export { type BillingFoundationOptions, type BillingPlanBenefit, type BillingPlanCatalog, type BillingPlanContactCard, type BillingPlanPrice, type BillingPlansResult, type BillingPlanView, type ConsumerProtectionOptions, KNOWN_RECURRING_INTERVALS, type LegalLinkSet, type PaymentEvent, type ProviderPrice, type ProviderSubscriptionSnapshot, type RecurringInterval, type SubscriptionEvent, type SubscriptionProviderPlugin, } from "./types.ts";
|
|
16
16
|
export { createSubscriptionWebhookRoute, type SubscriptionWebhookRouteOptions, } from "./webhook-handler.ts";
|
|
@@ -13,7 +13,7 @@ export declare const subscriptionsProjectionTable: import("@cosmicdrift/kumiko-f
|
|
|
13
13
|
readonly sensitive?: boolean;
|
|
14
14
|
readonly writeOnly?: boolean;
|
|
15
15
|
readonly readAsInstruction?: boolean;
|
|
16
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
16
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
17
17
|
readonly default?: string;
|
|
18
18
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
19
19
|
readonly multiline?: boolean | {
|
|
@@ -36,7 +36,7 @@ export declare const subscriptionsProjectionTable: import("@cosmicdrift/kumiko-f
|
|
|
36
36
|
readonly sensitive?: boolean;
|
|
37
37
|
readonly writeOnly?: boolean;
|
|
38
38
|
readonly readAsInstruction?: boolean;
|
|
39
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
39
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
40
40
|
readonly default?: string;
|
|
41
41
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
42
42
|
readonly multiline?: boolean | {
|
|
@@ -59,7 +59,7 @@ export declare const subscriptionsProjectionTable: import("@cosmicdrift/kumiko-f
|
|
|
59
59
|
readonly sensitive?: boolean;
|
|
60
60
|
readonly writeOnly?: boolean;
|
|
61
61
|
readonly readAsInstruction?: boolean;
|
|
62
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
62
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
63
63
|
readonly default?: string;
|
|
64
64
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
65
65
|
readonly multiline?: boolean | {
|
|
@@ -82,7 +82,7 @@ export declare const subscriptionsProjectionTable: import("@cosmicdrift/kumiko-f
|
|
|
82
82
|
readonly sensitive?: boolean;
|
|
83
83
|
readonly writeOnly?: boolean;
|
|
84
84
|
readonly readAsInstruction?: boolean;
|
|
85
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
85
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
86
86
|
readonly default?: string;
|
|
87
87
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
88
88
|
readonly multiline?: boolean | {
|
|
@@ -105,7 +105,7 @@ export declare const subscriptionsProjectionTable: import("@cosmicdrift/kumiko-f
|
|
|
105
105
|
readonly sensitive?: boolean;
|
|
106
106
|
readonly writeOnly?: boolean;
|
|
107
107
|
readonly readAsInstruction?: boolean;
|
|
108
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
108
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
109
109
|
readonly default?: string;
|
|
110
110
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
111
111
|
readonly multiline?: boolean | {
|
|
@@ -160,7 +160,7 @@ export declare const paymentsProjectionTable: import("@cosmicdrift/kumiko-framew
|
|
|
160
160
|
readonly sensitive?: boolean;
|
|
161
161
|
readonly writeOnly?: boolean;
|
|
162
162
|
readonly readAsInstruction?: boolean;
|
|
163
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
163
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
164
164
|
readonly default?: string;
|
|
165
165
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
166
166
|
readonly multiline?: boolean | {
|
|
@@ -183,7 +183,7 @@ export declare const paymentsProjectionTable: import("@cosmicdrift/kumiko-framew
|
|
|
183
183
|
readonly sensitive?: boolean;
|
|
184
184
|
readonly writeOnly?: boolean;
|
|
185
185
|
readonly readAsInstruction?: boolean;
|
|
186
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
186
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
187
187
|
readonly default?: string;
|
|
188
188
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
189
189
|
readonly multiline?: boolean | {
|
|
@@ -206,7 +206,7 @@ export declare const paymentsProjectionTable: import("@cosmicdrift/kumiko-framew
|
|
|
206
206
|
readonly sensitive?: boolean;
|
|
207
207
|
readonly writeOnly?: boolean;
|
|
208
208
|
readonly readAsInstruction?: boolean;
|
|
209
|
-
readonly format?: "email" | "url" | "phone" | "password";
|
|
209
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
210
210
|
readonly default?: string;
|
|
211
211
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
212
212
|
readonly multiline?: boolean | {
|
|
@@ -259,6 +259,13 @@ export type BillingPlanBenefit = {
|
|
|
259
259
|
readonly labelKey: string;
|
|
260
260
|
readonly params?: Readonly<Record<string, string | number>>;
|
|
261
261
|
};
|
|
262
|
+
/** Price-less card (e.g. "Enterprise · Contact us"); `href` must be an absolute https: or mailto: URL. */
|
|
263
|
+
export type BillingPlanContactCard = {
|
|
264
|
+
readonly labelKey: string;
|
|
265
|
+
readonly benefits: readonly BillingPlanBenefit[];
|
|
266
|
+
readonly actionLabelKey: string;
|
|
267
|
+
readonly href: string;
|
|
268
|
+
};
|
|
262
269
|
export type BillingPlanCatalog<TTier extends string = string> = {
|
|
263
270
|
/** Purchasable tiers, in display order. */
|
|
264
271
|
readonly plans: readonly TTier[];
|
|
@@ -280,6 +287,8 @@ export type BillingPlanCatalog<TTier extends string = string> = {
|
|
|
280
287
|
readonly returnPath?: string;
|
|
281
288
|
/** Defaults to the only registered provider exposing `priceToTier`. */
|
|
282
289
|
readonly providerName?: string;
|
|
290
|
+
/** Rendered as the last card, no price, visible to `viewRoles` regardless of `purchaseRoles`. */
|
|
291
|
+
readonly contact?: BillingPlanContactCard;
|
|
283
292
|
};
|
|
284
293
|
export type LegalLinkSet = {
|
|
285
294
|
readonly terms: string;
|
|
@@ -368,6 +377,8 @@ export type BillingPlansResult = {
|
|
|
368
377
|
} | null;
|
|
369
378
|
readonly canPurchase: boolean;
|
|
370
379
|
readonly plans: readonly BillingPlanView[];
|
|
380
|
+
/** Present only when `catalog.contact` is configured. */
|
|
381
|
+
readonly contact?: BillingPlanContactCard;
|
|
371
382
|
/** Present only when `consumerProtection` is configured. */
|
|
372
383
|
readonly consumerProtection?: {
|
|
373
384
|
readonly consentTexts: Readonly<Record<"de" | "en", {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as z from "zod";
|
|
6
6
|
import { isTerminationScope, TERMINATION_SCOPES } from "./constants.js";
|
|
7
7
|
import { CONSENT_LOCALES } from "./consumer-protection/consent-locale.js";
|
|
8
|
+
import { isContactCardHref } from "./contact-card.js";
|
|
8
9
|
import { isLegalLinkSet, } from "./types.js";
|
|
9
10
|
function isRootRelativePath(path) {
|
|
10
11
|
return path.startsWith("/") && !path.startsWith("//");
|
|
@@ -60,6 +61,16 @@ function validateLegalLinkSet(set, path) {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
function validateContactCard(contact) {
|
|
65
|
+
for (const key of ["labelKey", "actionLabelKey"]) {
|
|
66
|
+
if (contact[key].trim() === "") {
|
|
67
|
+
throw new Error(`createBillingFoundationFeature: catalog.contact.${key} must not be empty.`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!isContactCardHref(contact.href)) {
|
|
71
|
+
throw new Error(`createBillingFoundationFeature: catalog.contact.href "${contact.href}" must be an absolute https: or mailto: URL.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
63
74
|
function validateBaseUrl(baseUrl) {
|
|
64
75
|
let parsed;
|
|
65
76
|
try {
|
|
@@ -114,4 +125,6 @@ export function validateOptions(options) {
|
|
|
114
125
|
if (catalog.viewRoles.length === 0) {
|
|
115
126
|
throw new Error("createBillingFoundationFeature: catalog.viewRoles must not be empty.");
|
|
116
127
|
}
|
|
128
|
+
if (catalog.contact !== undefined)
|
|
129
|
+
validateContactCard(catalog.contact);
|
|
117
130
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @runtime client
|
|
3
|
+
import { useLocale, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
4
|
+
import { PlanCard } from "@cosmicdrift/kumiko-renderer/web";
|
|
5
|
+
import { isContactCardHref } from "../contact-card.js";
|
|
6
|
+
import { localizedParams } from "./localized-params.js";
|
|
7
|
+
export function BillingContactPlan({ contact, }) {
|
|
8
|
+
const t = useTranslation();
|
|
9
|
+
const locale = useLocale().locale();
|
|
10
|
+
if (!isContactCardHref(contact.href))
|
|
11
|
+
return null;
|
|
12
|
+
return (_jsx(PlanCard, { title: t(contact.labelKey), features: contact.benefits.map((benefit) => t(benefit.labelKey, localizedParams(benefit.params, locale))), ctaLink: {
|
|
13
|
+
label: t(contact.actionLabelKey),
|
|
14
|
+
href: contact.href,
|
|
15
|
+
target: new URL(contact.href).protocol === "https:" ? "_blank" : undefined,
|
|
16
|
+
}, testId: "billing-plan-card-contact" }));
|
|
17
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// @runtime client
|
|
3
|
-
import { toInstant } from "@cosmicdrift/kumiko-headless";
|
|
4
3
|
import { useLocale, useMutation, usePrimitives, useQuery, useTranslation, } from "@cosmicdrift/kumiko-renderer";
|
|
5
|
-
import {
|
|
4
|
+
import { toInstant } from "@cosmicdrift/kumiko-renderer/headless";
|
|
5
|
+
import { formatMoney, PlanCard, PlanGrid, } from "@cosmicdrift/kumiko-renderer/web";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { BillingPlanActions, SubscriptionFoundationHandlers, SubscriptionFoundationQueries, SubscriptionStatuses, } from "../constants.js";
|
|
8
|
+
import { BillingContactPlan } from "./billing-contact-plan.js";
|
|
8
9
|
import { CancelContractDialog } from "./cancel-contract-dialog.js";
|
|
9
10
|
import { CheckoutConsentDialog } from "./checkout-consent-dialog.js";
|
|
11
|
+
import { localizedParams } from "./localized-params.js";
|
|
10
12
|
function intervalKey(price) {
|
|
11
13
|
if (price === null || price.interval === null)
|
|
12
14
|
return undefined;
|
|
@@ -21,16 +23,6 @@ function renewalKey(price) {
|
|
|
21
23
|
? `billing-foundation.consent.renewsEvery.${price.interval}`
|
|
22
24
|
: `billing-foundation.consent.renews.${price.interval}`;
|
|
23
25
|
}
|
|
24
|
-
function localizedParams(params, locale) {
|
|
25
|
-
if (params === undefined)
|
|
26
|
-
return undefined;
|
|
27
|
-
const localized = {};
|
|
28
|
-
for (const [key, value] of Object.entries(params)) {
|
|
29
|
-
localized[key] =
|
|
30
|
-
typeof value === "number" ? new Intl.NumberFormat(locale).format(value) : value;
|
|
31
|
-
}
|
|
32
|
-
return localized;
|
|
33
|
-
}
|
|
34
26
|
/** Which action the plan "would" offer if it weren't blocked — mirrors
|
|
35
27
|
* plan-catalog.ts's own decision tree, since `unavailable` collapses both
|
|
36
28
|
* "would checkout" and "would switch" into one action and the disabled CTA
|
|
@@ -189,7 +181,7 @@ export function BillingPlansPanel(_props) {
|
|
|
189
181
|
date: toInstant(result.subscription.cancelAt).toLocaleString(locale, {
|
|
190
182
|
dateStyle: "medium",
|
|
191
183
|
}),
|
|
192
|
-
}), " ", t("billing-foundation.plans.switchRequiresReactivation")] })), consumerProtection !== undefined && canManage && result.subscription?.cancelAt == null && (_jsx("div", { children: _jsx(Button, { variant: "secondary", onClick: () => setCancelOpen(true), testId: "billing-plans-cancel-contract", children: t("billing-foundation.cancel.open") }) })), _jsxs(PlanGrid, { testId: "billing-plans-grid", children: [!currentTierInPlans && (_jsx(PlanCard, { title: t(result.currentTier.labelKey), current: true, testId: "billing-plan-card-current", features: result.currentTier.benefits.map((benefit) => t(benefit.labelKey, localizedParams(benefit.params, locale))), secondaryAction: manageOrReactivateAction(canManage, result.subscription, t, handleManage, redirecting) })), visiblePlans.map((plan) => (_jsx(PlanCard, { testId: `billing-plan-card-${plan.tier}`, ...toCardProps(plan) }, plan.tier)))] }), consumerProtection !== undefined &&
|
|
184
|
+
}), " ", t("billing-foundation.plans.switchRequiresReactivation")] })), consumerProtection !== undefined && canManage && result.subscription?.cancelAt == null && (_jsx("div", { children: _jsx(Button, { variant: "secondary", onClick: () => setCancelOpen(true), testId: "billing-plans-cancel-contract", children: t("billing-foundation.cancel.open") }) })), _jsxs(PlanGrid, { testId: "billing-plans-grid", children: [!currentTierInPlans && (_jsx(PlanCard, { title: t(result.currentTier.labelKey), current: true, testId: "billing-plan-card-current", features: result.currentTier.benefits.map((benefit) => t(benefit.labelKey, localizedParams(benefit.params, locale))), secondaryAction: manageOrReactivateAction(canManage, result.subscription, t, handleManage, redirecting) })), visiblePlans.map((plan) => (_jsx(PlanCard, { testId: `billing-plan-card-${plan.tier}`, ...toCardProps(plan) }, plan.tier))), result.contact !== undefined && _jsx(BillingContactPlan, { contact: result.contact })] }), consumerProtection !== undefined &&
|
|
193
185
|
consentPlan !== undefined &&
|
|
194
186
|
consentPlan.price !== null && (_jsx(CheckoutConsentDialog, { open: true, onOpenChange: (open) => {
|
|
195
187
|
if (!open)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// @runtime client
|
|
3
|
-
import { toInstant } from "@cosmicdrift/kumiko-headless";
|
|
4
3
|
import { useLocale, useMutation, usePrimitives, useTranslation, } from "@cosmicdrift/kumiko-renderer";
|
|
5
|
-
import {
|
|
4
|
+
import { toInstant } from "@cosmicdrift/kumiko-renderer/headless";
|
|
5
|
+
import { ModeSwitch } from "@cosmicdrift/kumiko-renderer/web";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { SubscriptionFoundationHandlers } from "../constants.js";
|
|
8
8
|
const DECLARATION_TYPES = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WriteResult } from "@cosmicdrift/kumiko-headless";
|
|
1
|
+
import type { WriteResult } from "@cosmicdrift/kumiko-renderer/headless";
|
|
2
2
|
import { type ReactNode } from "react";
|
|
3
3
|
import type { BillingPlansResult } from "../types.ts";
|
|
4
4
|
export declare const CONSENT_TEXT_OUTDATED_CODE = "consent_text_outdated";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// @runtime client
|
|
2
3
|
import { useLocale, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
3
4
|
import { useState } from "react";
|
|
4
5
|
import { resolveConsentLocale } from "../consumer-protection/consent-locale.js";
|