includio-cms 0.36.9 → 0.37.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/API.md +178 -3
- package/CHANGELOG.md +77 -0
- package/DOCS.md +28 -3
- package/ROADMAP.md +32 -0
- package/dist/admin/client/booking/booking-dashboard.svelte +40 -0
- package/dist/admin/client/booking/booking-dashboard.svelte.d.ts +3 -0
- package/dist/admin/client/booking/customer-panel.svelte +102 -0
- package/dist/admin/client/booking/customer-panel.svelte.d.ts +11 -0
- package/dist/admin/client/booking/customer-view.d.ts +52 -0
- package/dist/admin/client/booking/customer-view.js +134 -0
- package/dist/admin/client/booking/participant-data-panel.svelte +330 -0
- package/dist/admin/client/booking/participant-data-panel.svelte.d.ts +22 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte +637 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte.d.ts +3 -0
- package/dist/admin/client/booking/reservations-page.svelte +221 -0
- package/dist/admin/client/booking/reservations-page.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection-entries.svelte +1 -1
- package/dist/admin/client/collection/entry-link.svelte +6 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +3 -1
- package/dist/admin/client/collection/status-badge.svelte +39 -3
- package/dist/admin/client/collection/status-badge.svelte.d.ts +5 -3
- package/dist/admin/client/entry/entry.svelte +26 -9
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +73 -10
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte.d.ts +6 -5
- package/dist/admin/client/entry/preview-views-context.svelte.d.ts +22 -0
- package/dist/admin/client/entry/preview-views-context.svelte.js +58 -0
- package/dist/admin/client/entry/preview-views.d.ts +27 -0
- package/dist/admin/client/entry/preview-views.js +33 -0
- package/dist/admin/client/index.d.ts +3 -0
- package/dist/admin/client/index.js +3 -0
- package/dist/admin/client/modules/dashboard-registry.d.ts +7 -0
- package/dist/admin/client/modules/dashboard-registry.js +11 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte +26 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte.d.ts +6 -0
- package/dist/admin/client/modules/stat-card.svelte +22 -0
- package/dist/admin/client/modules/stat-card.svelte.d.ts +10 -0
- package/dist/admin/client/shop/shop-dashboard.svelte +29 -0
- package/dist/admin/client/shop/shop-dashboard.svelte.d.ts +3 -0
- package/dist/admin/components/fields/relation-field.svelte +11 -2
- package/dist/admin/components/icons/icon-map.js +8 -0
- package/dist/admin/components/layout/app-sidebar.svelte +45 -14
- package/dist/admin/components/layout/context-switcher.svelte +90 -0
- package/dist/admin/components/layout/context-switcher.svelte.d.ts +3 -0
- package/dist/admin/components/layout/lang.d.ts +4 -0
- package/dist/admin/components/layout/lang.js +8 -0
- package/dist/admin/components/layout/layout-renderer.svelte +2 -1
- package/dist/admin/components/layout/layout-tabs.svelte +14 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +2 -0
- package/dist/admin/components/layout/nav-collections.svelte +16 -9
- package/dist/admin/components/layout/nav-collections.svelte.d.ts +5 -1
- package/dist/admin/components/layout/nav-global.svelte +45 -0
- package/dist/admin/components/layout/nav-global.svelte.d.ts +3 -0
- package/dist/admin/components/layout/nav-main.svelte +8 -32
- package/dist/admin/components/layout/nav-main.svelte.d.ts +6 -1
- package/dist/admin/components/layout/nav-module.svelte +57 -0
- package/dist/admin/components/layout/nav-module.svelte.d.ts +7 -0
- package/dist/admin/components/layout/nav-section.svelte +1 -1
- package/dist/admin/components/layout/nav-section.svelte.d.ts +1 -1
- package/dist/admin/components/layout/nav-singletons.svelte +14 -7
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +5 -1
- package/dist/admin/remote/booking.remote.d.ts +247 -0
- package/dist/admin/remote/booking.remote.js +286 -0
- package/dist/admin/remote/index.d.ts +2 -0
- package/dist/admin/remote/index.js +2 -0
- package/dist/admin/remote/modules.remote.d.ts +10 -0
- package/dist/admin/remote/modules.remote.js +14 -0
- package/dist/admin/state/active-context-resolve.d.ts +37 -0
- package/dist/admin/state/active-context-resolve.js +66 -0
- package/dist/admin/state/active-context.svelte.d.ts +8 -0
- package/dist/admin/state/active-context.svelte.js +27 -0
- package/dist/booking/adjustments.d.ts +33 -0
- package/dist/booking/adjustments.js +26 -0
- package/dist/booking/capacity.d.ts +12 -0
- package/dist/booking/capacity.js +10 -0
- package/dist/booking/client/index.d.ts +42 -0
- package/dist/booking/client/index.js +48 -0
- package/dist/booking/client/use-booking.svelte.d.ts +24 -0
- package/dist/booking/client/use-booking.svelte.js +56 -0
- package/dist/booking/config.d.ts +176 -0
- package/dist/booking/config.js +37 -0
- package/dist/booking/draft.d.ts +96 -0
- package/dist/booking/draft.js +67 -0
- package/dist/booking/expiry-logic.d.ts +30 -0
- package/dist/booking/expiry-logic.js +33 -0
- package/dist/booking/index.d.ts +18 -0
- package/dist/booking/index.js +52 -0
- package/dist/booking/ledger.d.ts +46 -0
- package/dist/booking/ledger.js +60 -0
- package/dist/booking/number.d.ts +2 -0
- package/dist/booking/number.js +11 -0
- package/dist/booking/participant-fields/access.d.ts +10 -0
- package/dist/booking/participant-fields/access.js +14 -0
- package/dist/booking/participant-fields/age.d.ts +12 -0
- package/dist/booking/participant-fields/age.js +28 -0
- package/dist/booking/participant-fields/completeness.d.ts +8 -0
- package/dist/booking/participant-fields/completeness.js +13 -0
- package/dist/booking/participant-fields/group.d.ts +6 -0
- package/dist/booking/participant-fields/group.js +15 -0
- package/dist/booking/participant-fields/index.d.ts +6 -0
- package/dist/booking/participant-fields/index.js +6 -0
- package/dist/booking/participant-fields/types.d.ts +50 -0
- package/dist/booking/participant-fields/types.js +5 -0
- package/dist/booking/participant-fields/validate.d.ts +7 -0
- package/dist/booking/participant-fields/validate.js +44 -0
- package/dist/booking/participant-pricing.d.ts +93 -0
- package/dist/booking/participant-pricing.js +91 -0
- package/dist/booking/participants-view.d.ts +32 -0
- package/dist/booking/participants-view.js +22 -0
- package/dist/booking/payment-context.d.ts +19 -0
- package/dist/booking/payment-context.js +29 -0
- package/dist/booking/pricing-inputs.d.ts +28 -0
- package/dist/booking/pricing-inputs.js +35 -0
- package/dist/booking/pricing.d.ts +86 -0
- package/dist/booking/pricing.js +125 -0
- package/dist/booking/recompute.d.ts +22 -0
- package/dist/booking/recompute.js +31 -0
- package/dist/booking/reminders-schedule.d.ts +11 -0
- package/dist/booking/reminders-schedule.js +28 -0
- package/dist/booking/server/adjustments.d.ts +27 -0
- package/dist/booking/server/adjustments.js +139 -0
- package/dist/booking/server/bookings.d.ts +51 -0
- package/dist/booking/server/bookings.js +336 -0
- package/dist/booking/server/catalog.d.ts +9 -0
- package/dist/booking/server/catalog.js +20 -0
- package/dist/booking/server/db.d.ts +7 -0
- package/dist/booking/server/db.js +18 -0
- package/dist/booking/server/email.d.ts +23 -0
- package/dist/booking/server/email.js +59 -0
- package/dist/booking/server/emailTemplateRegistry.d.ts +29 -0
- package/dist/booking/server/emailTemplateRegistry.js +125 -0
- package/dist/booking/server/http/create-handler.d.ts +5 -0
- package/dist/booking/server/http/create-handler.js +70 -0
- package/dist/booking/server/http/index.d.ts +4 -0
- package/dist/booking/server/http/index.js +4 -0
- package/dist/booking/server/http/maintenance-handler.d.ts +9 -0
- package/dist/booking/server/http/maintenance-handler.js +36 -0
- package/dist/booking/server/http/portal-handler.d.ts +13 -0
- package/dist/booking/server/http/portal-handler.js +103 -0
- package/dist/booking/server/http/webhook-handler.d.ts +9 -0
- package/dist/booking/server/http/webhook-handler.js +39 -0
- package/dist/booking/server/index.d.ts +12 -0
- package/dist/booking/server/index.js +14 -0
- package/dist/booking/server/maintenance.d.ts +28 -0
- package/dist/booking/server/maintenance.js +134 -0
- package/dist/booking/server/participants.d.ts +26 -0
- package/dist/booking/server/participants.js +92 -0
- package/dist/booking/server/payments.d.ts +34 -0
- package/dist/booking/server/payments.js +207 -0
- package/dist/booking/server/portal-session.d.ts +16 -0
- package/dist/booking/server/portal-session.js +42 -0
- package/dist/booking/server/portal.d.ts +206 -0
- package/dist/booking/server/portal.js +236 -0
- package/dist/booking/server/price-source.d.ts +73 -0
- package/dist/booking/server/price-source.js +94 -0
- package/dist/booking/server/refunds.d.ts +7 -0
- package/dist/booking/server/refunds.js +58 -0
- package/dist/booking/server/reminders.d.ts +9 -0
- package/dist/booking/server/reminders.js +24 -0
- package/dist/booking/server/validation.d.ts +17 -0
- package/dist/booking/server/validation.js +55 -0
- package/dist/booking/state-machine.d.ts +41 -0
- package/dist/booking/state-machine.js +73 -0
- package/dist/booking/templates/_partials/footer.en.html +4 -0
- package/dist/booking/templates/_partials/footer.pl.html +4 -0
- package/dist/booking/templates/_partials/header.en.html +4 -0
- package/dist/booking/templates/_partials/header.pl.html +4 -0
- package/dist/booking/templates/balance-due.en.html +10 -0
- package/dist/booking/templates/balance-due.pl.html +10 -0
- package/dist/booking/templates/balance-overdue-cancelled.en.html +5 -0
- package/dist/booking/templates/balance-overdue-cancelled.pl.html +5 -0
- package/dist/booking/templates/booking-received.en.html +9 -0
- package/dist/booking/templates/booking-received.pl.html +9 -0
- package/dist/booking/templates/deposit-paid.en.html +6 -0
- package/dist/booking/templates/deposit-paid.pl.html +6 -0
- package/dist/booking/templates/payment-link.en.html +5 -0
- package/dist/booking/templates/payment-link.pl.html +5 -0
- package/dist/booking/templates/payment-received.en.html +10 -0
- package/dist/booking/templates/payment-received.pl.html +10 -0
- package/dist/booking/totals.d.ts +38 -0
- package/dist/booking/totals.js +61 -0
- package/dist/booking/webhook-logic.d.ts +28 -0
- package/dist/booking/webhook-logic.js +50 -0
- package/dist/cli/create-user.d.ts +7 -1
- package/dist/cli/create-user.js +23 -15
- package/dist/cli/index.js +55 -7
- package/dist/cli/scaffold/admin.d.ts +6 -0
- package/dist/cli/scaffold/admin.js +5 -3
- package/dist/cli/scaffold/booking.d.ts +12 -0
- package/dist/cli/scaffold/booking.js +103 -0
- package/dist/core/cms.d.ts +24 -9
- package/dist/core/cms.js +72 -34
- package/dist/core/config/validatePreviews.d.ts +12 -0
- package/dist/core/config/validatePreviews.js +90 -0
- package/dist/core/fields/slugPath.d.ts +9 -1
- package/dist/core/fields/slugPath.js +16 -2
- package/dist/core/server/fields/resolveRelationFields.d.ts +11 -2
- package/dist/core/server/fields/resolveRelationFields.js +12 -3
- package/dist/core/server/generator/generator.js +7 -2
- package/dist/db-postgres/schema/booking/bookingAdjustments.d.ts +186 -0
- package/dist/db-postgres/schema/booking/bookingAdjustments.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.d.ts +117 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItems.d.ts +181 -0
- package/dist/db-postgres/schema/booking/bookingItems.js +22 -0
- package/dist/db-postgres/schema/booking/bookingPayments.d.ts +204 -0
- package/dist/db-postgres/schema/booking/bookingPayments.js +25 -0
- package/dist/db-postgres/schema/booking/bookingPersons.d.ts +99 -0
- package/dist/db-postgres/schema/booking/bookingPersons.js +17 -0
- package/dist/db-postgres/schema/booking/bookingReminders.d.ts +131 -0
- package/dist/db-postgres/schema/booking/bookingReminders.js +18 -0
- package/dist/db-postgres/schema/booking/bookings.d.ts +324 -0
- package/dist/db-postgres/schema/booking/bookings.js +52 -0
- package/dist/db-postgres/schema/booking/index.d.ts +7 -0
- package/dist/db-postgres/schema/booking/index.js +7 -0
- package/dist/db-postgres/schema/index.d.ts +1 -0
- package/dist/db-postgres/schema/index.js +1 -0
- package/dist/db-postgres/schema-booking.d.ts +1 -0
- package/dist/db-postgres/schema-booking.js +1 -0
- package/dist/server/security/rate-limit-handler.d.ts +19 -0
- package/dist/server/security/rate-limit-handler.js +34 -0
- package/dist/shop/adapters/payu/client.js +3 -1
- package/dist/shop/adapters/payu/index.js +37 -17
- package/dist/shop/adapters/payu/payload.d.ts +6 -0
- package/dist/shop/adapters/payu/payload.js +1 -1
- package/dist/shop/adapters/stripe/index.js +36 -21
- package/dist/shop/index.d.ts +11 -2
- package/dist/shop/index.js +43 -1
- package/dist/shop/rate-limit.d.ts +1 -9
- package/dist/shop/rate-limit.js +3 -28
- package/dist/shop/types.d.ts +19 -0
- package/dist/sveltekit/config.d.ts +4 -0
- package/dist/sveltekit/config.js +6 -0
- package/dist/types/cms.d.ts +15 -1
- package/dist/types/cms.schema.d.ts +96 -2
- package/dist/types/cms.schema.js +84 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/layout.d.ts +6 -0
- package/dist/types/modules.d.ts +133 -0
- package/dist/types/modules.js +27 -0
- package/dist/updates/0.37.0/index.d.ts +2 -0
- package/dist/updates/0.37.0/index.js +52 -0
- package/dist/updates/0.37.1/index.d.ts +2 -0
- package/dist/updates/0.37.1/index.js +24 -0
- package/dist/updates/index.js +5 -1
- package/package.json +19 -1
- package/dist/admin/components/layout/nav-shop.svelte +0 -33
- package/dist/admin/components/layout/nav-shop.svelte.d.ts +0 -3
package/dist/shop/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/** Resolves a raw {@link ShopConfig} into a fully-defaulted {@link ResolvedShopConfig}. */
|
|
2
|
+
function resolveShopConfig(config) {
|
|
2
3
|
return {
|
|
3
4
|
...config,
|
|
4
5
|
features: {
|
|
@@ -22,6 +23,47 @@ export function defineShop(config) {
|
|
|
22
23
|
cartName: config.cartName ?? null
|
|
23
24
|
};
|
|
24
25
|
}
|
|
26
|
+
/** Server-only init for the shop module — applies GIN indexes + smoke-tests email templates. */
|
|
27
|
+
async function shopModuleInit({ drizzle, config, defaultLanguage }) {
|
|
28
|
+
const shop = config;
|
|
29
|
+
if (drizzle) {
|
|
30
|
+
const { applyVariantAttributeIndexes } = await import('./server/init.js');
|
|
31
|
+
await applyVariantAttributeIndexes(shop, drizzle);
|
|
32
|
+
}
|
|
33
|
+
// Smoke-test built-in shop email templates — fast lookup-only sweep. Catches
|
|
34
|
+
// corrupt installs (missing dist files) at boot instead of at first send.
|
|
35
|
+
const { REQUIRED_TEMPLATE_NAMES } = await import('./server/email.js');
|
|
36
|
+
const { validateBuiltinTemplates } = await import('./server/emailTemplateRegistry.js');
|
|
37
|
+
validateBuiltinTemplates([...REQUIRED_TEMPLATE_NAMES], defaultLanguage);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Defines the shop module. Returns a {@link CMSModule} for
|
|
41
|
+
* `defineConfig({ modules: [defineShop({...})] })`. The resolved shop config
|
|
42
|
+
* is carried on `module.config` and reachable via `getCMS().getModuleConfig('shop')`
|
|
43
|
+
* (or the back-compat `getCMS().shopConfig`).
|
|
44
|
+
*
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export function defineShop(config) {
|
|
48
|
+
const resolved = resolveShopConfig(config);
|
|
49
|
+
return {
|
|
50
|
+
id: 'shop',
|
|
51
|
+
label: { pl: 'Sklep', en: 'Shop' },
|
|
52
|
+
icon: 'building-store',
|
|
53
|
+
context: {
|
|
54
|
+
contextLabel: { pl: 'Sklep', en: 'Shop' },
|
|
55
|
+
landingUrl: '/admin/shop',
|
|
56
|
+
sections: [
|
|
57
|
+
{ key: 'products', title: { pl: 'Produkty', en: 'Products' }, url: '/admin/shop/products', icon: 'package' },
|
|
58
|
+
{ key: 'orders', title: { pl: 'Zamówienia', en: 'Orders' }, url: '/admin/shop/orders', icon: 'shopping-cart' },
|
|
59
|
+
{ key: 'shipping', title: { pl: 'Metody wysyłki', en: 'Shipping methods' }, url: '/admin/shop/shipping-methods', icon: 'truck' },
|
|
60
|
+
{ key: 'coupons', title: { pl: 'Kody rabatowe', en: 'Coupon codes' }, url: '/admin/shop/coupons', icon: 'ticket' }
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
config: resolved,
|
|
64
|
+
serverHooks: { init: shopModuleInit }
|
|
65
|
+
};
|
|
66
|
+
}
|
|
25
67
|
export { InvalidVariantAttributesError } from './variant-attributes.js';
|
|
26
68
|
export { isVariantExpired, filterUpcoming, VariantExpiredError } from './expiry.js';
|
|
27
69
|
export { manualAdapter } from './adapters/manual/index.js';
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export interface RateLimitResult {
|
|
3
|
-
allowed: boolean;
|
|
4
|
-
remaining: number;
|
|
5
|
-
resetAt: number;
|
|
6
|
-
}
|
|
7
|
-
export declare function checkRateLimit(key: string, rule: RateLimitRule): RateLimitResult;
|
|
8
|
-
export declare function resetRateLimit(key?: string): void;
|
|
9
|
-
export declare function clientKey(req: Request, prefix: string): string;
|
|
1
|
+
export { checkRateLimit, resetRateLimit, clientKey, type RateLimitResult } from '../server/security/rate-limit-handler.js';
|
package/dist/shop/rate-limit.js
CHANGED
|
@@ -1,28 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const windowMs = rule.windowSec * 1000;
|
|
5
|
-
const bucket = buckets.get(key);
|
|
6
|
-
if (!bucket || bucket.resetAt <= now) {
|
|
7
|
-
const fresh = { count: 1, resetAt: now + windowMs };
|
|
8
|
-
buckets.set(key, fresh);
|
|
9
|
-
return { allowed: true, remaining: rule.limit - 1, resetAt: fresh.resetAt };
|
|
10
|
-
}
|
|
11
|
-
if (bucket.count >= rule.limit) {
|
|
12
|
-
return { allowed: false, remaining: 0, resetAt: bucket.resetAt };
|
|
13
|
-
}
|
|
14
|
-
bucket.count += 1;
|
|
15
|
-
return { allowed: true, remaining: rule.limit - bucket.count, resetAt: bucket.resetAt };
|
|
16
|
-
}
|
|
17
|
-
export function resetRateLimit(key) {
|
|
18
|
-
if (key)
|
|
19
|
-
buckets.delete(key);
|
|
20
|
-
else
|
|
21
|
-
buckets.clear();
|
|
22
|
-
}
|
|
23
|
-
export function clientKey(req, prefix) {
|
|
24
|
-
const ip = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||
|
|
25
|
-
req.headers.get('x-real-ip') ||
|
|
26
|
-
'unknown';
|
|
27
|
-
return `${prefix}:${ip}`;
|
|
28
|
-
}
|
|
1
|
+
// Lifted to core (`$lib/server/security/rate-limit-handler`) so shop + booking
|
|
2
|
+
// share one generic per-handler limiter without a booking→shop dependency.
|
|
3
|
+
export { checkRateLimit, resetRateLimit, clientKey } from '../server/security/rate-limit-handler.js';
|
package/dist/shop/types.d.ts
CHANGED
|
@@ -70,6 +70,25 @@ export interface ConsentConfig {
|
|
|
70
70
|
export interface PaymentCreateContext {
|
|
71
71
|
customerIp?: string;
|
|
72
72
|
language?: string | null;
|
|
73
|
+
/**
|
|
74
|
+
* Fully-resolved absolute return URL. When set, adapters MUST use it verbatim
|
|
75
|
+
* and skip any shop-order hydration — lets non-shop callers (e.g. booking)
|
|
76
|
+
* reuse the adapter without a shop module.
|
|
77
|
+
*/
|
|
78
|
+
continueUrl?: string;
|
|
79
|
+
/** Caller-supplied buyer identity (for non-shop callers). */
|
|
80
|
+
buyer?: {
|
|
81
|
+
firstName?: string;
|
|
82
|
+
lastName?: string;
|
|
83
|
+
phone?: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Unique external id for THIS payment attempt. Adapters whose provider requires
|
|
87
|
+
* a unique-per-attempt order id (e.g. PayU's `extOrderId`, unique per POS) use
|
|
88
|
+
* it instead of `order.number`. Required when one order/booking spawns multiple
|
|
89
|
+
* provider orders (deposit + balance), otherwise the provider rejects the reuse.
|
|
90
|
+
*/
|
|
91
|
+
externalId?: string;
|
|
73
92
|
}
|
|
74
93
|
/**
|
|
75
94
|
* Result of a non-invasive integration connectivity check. Returned by an
|
|
@@ -19,6 +19,10 @@ type SingleInput = Omit<SingleConfig, 'fields'> & {
|
|
|
19
19
|
* (extends `CmsError`) listing every issue with a path and a fix hint, e.g.
|
|
20
20
|
* `languages[0].code: must be a 2-letter ISO code (e.g. 'en')`
|
|
21
21
|
*
|
|
22
|
+
* Also checks preview views: unique names, at most one `default`, `previewUrl`
|
|
23
|
+
* and `previews` are mutually exclusive, and every `tab.preview` points at a
|
|
24
|
+
* declared view.
|
|
25
|
+
*
|
|
22
26
|
* @param config - The CMSConfig (collections, singles, forms, adapters, languages, ...).
|
|
23
27
|
* @returns The same config, parsed and frozen against typos.
|
|
24
28
|
* @throws {ConfigValidationError} when validation fails — message aggregates all issues.
|
package/dist/sveltekit/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cmsConfigSchema } from '../types/cms.schema.js';
|
|
2
2
|
import { formatConfigError } from '../core/errors.js';
|
|
3
|
+
import { validatePreviews } from '../core/config/validatePreviews.js';
|
|
3
4
|
/**
|
|
4
5
|
* Defines the root CMS configuration. Pass to `includioCMS()` in `hooks.server.ts`.
|
|
5
6
|
*
|
|
@@ -7,6 +8,10 @@ import { formatConfigError } from '../core/errors.js';
|
|
|
7
8
|
* (extends `CmsError`) listing every issue with a path and a fix hint, e.g.
|
|
8
9
|
* `languages[0].code: must be a 2-letter ISO code (e.g. 'en')`
|
|
9
10
|
*
|
|
11
|
+
* Also checks preview views: unique names, at most one `default`, `previewUrl`
|
|
12
|
+
* and `previews` are mutually exclusive, and every `tab.preview` points at a
|
|
13
|
+
* declared view.
|
|
14
|
+
*
|
|
10
15
|
* @param config - The CMSConfig (collections, singles, forms, adapters, languages, ...).
|
|
11
16
|
* @returns The same config, parsed and frozen against typos.
|
|
12
17
|
* @throws {ConfigValidationError} when validation fails — message aggregates all issues.
|
|
@@ -26,6 +31,7 @@ export function defineConfig(config) {
|
|
|
26
31
|
if (!result.success) {
|
|
27
32
|
throw formatConfigError(result.error);
|
|
28
33
|
}
|
|
34
|
+
validatePreviews(config);
|
|
29
35
|
return config;
|
|
30
36
|
}
|
|
31
37
|
/**
|
package/dist/types/cms.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { AIAdapter } from './adapters/ai.js';
|
|
|
9
9
|
import type { EmailAdapter } from './adapters/email.js';
|
|
10
10
|
import type { ResolvedShopConfig } from '../shop/types.js';
|
|
11
11
|
import type { ResolvedCmpConfig } from '../cmp/types.js';
|
|
12
|
+
import type { CMSModule } from './modules.js';
|
|
12
13
|
export interface VideoTranscodeConfig {
|
|
13
14
|
/** Enable/disable auto-transcoding on upload (default: true) */
|
|
14
15
|
transcode?: boolean;
|
|
@@ -157,7 +158,12 @@ export interface CMSConfig {
|
|
|
157
158
|
apiKeys?: ApiKeyConfig[];
|
|
158
159
|
typography?: TypographyConfig;
|
|
159
160
|
sidebarHelp?: boolean;
|
|
160
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Optional modules ("overlays") layered on the CMS core — shop, booking,
|
|
163
|
+
* etc. Each is a {@link CMSModule} (typically from `defineShop()` /
|
|
164
|
+
* `defineBooking()`). Renders a context in the admin switcher.
|
|
165
|
+
*/
|
|
166
|
+
modules?: CMSModule[];
|
|
161
167
|
cmp?: ResolvedCmpConfig;
|
|
162
168
|
admin?: AdminConfig;
|
|
163
169
|
}
|
|
@@ -180,4 +186,12 @@ export interface ICMS {
|
|
|
180
186
|
shopConfig: ResolvedShopConfig | null;
|
|
181
187
|
cmpConfig: ResolvedCmpConfig | null;
|
|
182
188
|
adminConfig: AdminConfig | null;
|
|
189
|
+
/** Registered modules ("overlays"), keyed by `module.id`. */
|
|
190
|
+
modules: Map<string, CMSModule>;
|
|
191
|
+
/** Returns a registered module by id, or `undefined`. */
|
|
192
|
+
getModule(id: string): CMSModule | undefined;
|
|
193
|
+
/** Returns a registered module's `config`, narrowed to `T`, or `undefined`. */
|
|
194
|
+
getModuleConfig<T = unknown>(id: string): T | undefined;
|
|
195
|
+
/** Whether a module with the given id is registered. */
|
|
196
|
+
hasModule(id: string): boolean;
|
|
183
197
|
}
|
|
@@ -34,6 +34,12 @@ export declare const cmsConfigSchema: z.ZodObject<{
|
|
|
34
34
|
slug: z.ZodString;
|
|
35
35
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
36
36
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
37
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
38
|
+
name: z.ZodString;
|
|
39
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
40
|
+
url: z.ZodString;
|
|
41
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
}, z.core.$loose>>>;
|
|
37
43
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
38
44
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
39
45
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -44,6 +50,12 @@ export declare const cmsConfigSchema: z.ZodObject<{
|
|
|
44
50
|
slug: z.ZodString;
|
|
45
51
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
46
52
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
53
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
54
|
+
name: z.ZodString;
|
|
55
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
56
|
+
url: z.ZodString;
|
|
57
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
58
|
+
}, z.core.$loose>>>;
|
|
47
59
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
48
60
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
49
61
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -145,7 +157,26 @@ export declare const cmsConfigSchema: z.ZodObject<{
|
|
|
145
157
|
fixOrphans: z.ZodOptional<z.ZodBoolean>;
|
|
146
158
|
}, z.core.$loose>>;
|
|
147
159
|
sidebarHelp: z.ZodOptional<z.ZodBoolean>;
|
|
148
|
-
|
|
160
|
+
modules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
161
|
+
id: z.ZodString;
|
|
162
|
+
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
163
|
+
icon: z.ZodString;
|
|
164
|
+
context: z.ZodObject<{
|
|
165
|
+
contextLabel: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
166
|
+
landingUrl: z.ZodString;
|
|
167
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
168
|
+
key: z.ZodString;
|
|
169
|
+
title: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
170
|
+
url: z.ZodString;
|
|
171
|
+
icon: z.ZodString;
|
|
172
|
+
countSource: z.ZodOptional<z.ZodString>;
|
|
173
|
+
}, z.core.$loose>>;
|
|
174
|
+
surfacedCollections: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
175
|
+
surfacedSingles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
176
|
+
}, z.core.$loose>;
|
|
177
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
178
|
+
serverHooks: z.ZodOptional<z.ZodUnknown>;
|
|
179
|
+
}, z.core.$loose>>>;
|
|
149
180
|
cmp: z.ZodOptional<z.ZodUnknown>;
|
|
150
181
|
}, z.core.$loose>;
|
|
151
182
|
export type CmsConfigSchema = z.infer<typeof cmsConfigSchema>;
|
|
@@ -228,6 +259,12 @@ export declare const _internal: {
|
|
|
228
259
|
slug: z.ZodString;
|
|
229
260
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
230
261
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
262
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
263
|
+
name: z.ZodString;
|
|
264
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
265
|
+
url: z.ZodString;
|
|
266
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
267
|
+
}, z.core.$loose>>>;
|
|
231
268
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
232
269
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
233
270
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -238,6 +275,12 @@ export declare const _internal: {
|
|
|
238
275
|
slug: z.ZodString;
|
|
239
276
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
240
277
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
278
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
279
|
+
name: z.ZodString;
|
|
280
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
281
|
+
url: z.ZodString;
|
|
282
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
283
|
+
}, z.core.$loose>>>;
|
|
241
284
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
242
285
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
243
286
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -314,6 +357,26 @@ export declare const _internal: {
|
|
|
314
357
|
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
315
358
|
notificationEmailAddresses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
316
359
|
}, z.core.$loose>;
|
|
360
|
+
moduleSchema: z.ZodObject<{
|
|
361
|
+
id: z.ZodString;
|
|
362
|
+
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
363
|
+
icon: z.ZodString;
|
|
364
|
+
context: z.ZodObject<{
|
|
365
|
+
contextLabel: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
366
|
+
landingUrl: z.ZodString;
|
|
367
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
368
|
+
key: z.ZodString;
|
|
369
|
+
title: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
370
|
+
url: z.ZodString;
|
|
371
|
+
icon: z.ZodString;
|
|
372
|
+
countSource: z.ZodOptional<z.ZodString>;
|
|
373
|
+
}, z.core.$loose>>;
|
|
374
|
+
surfacedCollections: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
375
|
+
surfacedSingles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
376
|
+
}, z.core.$loose>;
|
|
377
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
378
|
+
serverHooks: z.ZodOptional<z.ZodUnknown>;
|
|
379
|
+
}, z.core.$loose>;
|
|
317
380
|
cmsConfigBaseSchema: z.ZodObject<{
|
|
318
381
|
languages: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
319
382
|
code: z.ZodString;
|
|
@@ -331,6 +394,12 @@ export declare const _internal: {
|
|
|
331
394
|
slug: z.ZodString;
|
|
332
395
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
333
396
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
397
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
398
|
+
name: z.ZodString;
|
|
399
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
400
|
+
url: z.ZodString;
|
|
401
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
402
|
+
}, z.core.$loose>>>;
|
|
334
403
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
335
404
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
336
405
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -341,6 +410,12 @@ export declare const _internal: {
|
|
|
341
410
|
slug: z.ZodString;
|
|
342
411
|
sidebarIcon: z.ZodOptional<z.ZodString>;
|
|
343
412
|
previewUrl: z.ZodOptional<z.ZodString>;
|
|
413
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
414
|
+
name: z.ZodString;
|
|
415
|
+
label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
416
|
+
url: z.ZodString;
|
|
417
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
418
|
+
}, z.core.$loose>>>;
|
|
344
419
|
fields: z.ZodArray<z.ZodType<FieldDef, unknown, z.core.$ZodTypeInternals<FieldDef, unknown>>>;
|
|
345
420
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
346
421
|
slugField: z.ZodOptional<z.ZodString>;
|
|
@@ -442,7 +517,26 @@ export declare const _internal: {
|
|
|
442
517
|
fixOrphans: z.ZodOptional<z.ZodBoolean>;
|
|
443
518
|
}, z.core.$loose>>;
|
|
444
519
|
sidebarHelp: z.ZodOptional<z.ZodBoolean>;
|
|
445
|
-
|
|
520
|
+
modules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
521
|
+
id: z.ZodString;
|
|
522
|
+
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
523
|
+
icon: z.ZodString;
|
|
524
|
+
context: z.ZodObject<{
|
|
525
|
+
contextLabel: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
526
|
+
landingUrl: z.ZodString;
|
|
527
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
528
|
+
key: z.ZodString;
|
|
529
|
+
title: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
530
|
+
url: z.ZodString;
|
|
531
|
+
icon: z.ZodString;
|
|
532
|
+
countSource: z.ZodOptional<z.ZodString>;
|
|
533
|
+
}, z.core.$loose>>;
|
|
534
|
+
surfacedCollections: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
535
|
+
surfacedSingles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
536
|
+
}, z.core.$loose>;
|
|
537
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
538
|
+
serverHooks: z.ZodOptional<z.ZodUnknown>;
|
|
539
|
+
}, z.core.$loose>>>;
|
|
446
540
|
cmp: z.ZodOptional<z.ZodUnknown>;
|
|
447
541
|
}, z.core.$loose>;
|
|
448
542
|
FIELD_TYPES: readonly ["text", "content", "number", "boolean", "date", "datetime", "file", "media", "select", "radio", "checkboxes", "relation", "object", "array", "blocks", "slug", "seo", "shop", "url", "icon", "custom"];
|
package/dist/types/cms.schema.js
CHANGED
|
@@ -344,10 +344,19 @@ const formFieldSchema = z.discriminatedUnion('type', [
|
|
|
344
344
|
/* -------------------------------------------------------------------------- */
|
|
345
345
|
/* Collections / Singles / Forms */
|
|
346
346
|
/* -------------------------------------------------------------------------- */
|
|
347
|
+
const previewViewSchema = z
|
|
348
|
+
.object({
|
|
349
|
+
name: z.string().min(1, { message: 'preview view must have a name' }),
|
|
350
|
+
label: localizedSchema.optional(),
|
|
351
|
+
url: z.string().min(1, { message: 'preview view must have a url' }),
|
|
352
|
+
default: z.boolean().optional()
|
|
353
|
+
})
|
|
354
|
+
.passthrough();
|
|
347
355
|
const configBaseShape = {
|
|
348
356
|
slug: slugSchema,
|
|
349
357
|
sidebarIcon: z.string().optional(),
|
|
350
358
|
previewUrl: z.string().optional(),
|
|
359
|
+
previews: z.array(previewViewSchema).optional(),
|
|
351
360
|
fields: z.array(fieldSchema).min(1, {
|
|
352
361
|
message: 'must declare at least one field'
|
|
353
362
|
}),
|
|
@@ -436,6 +445,39 @@ const apiKeySchema = z
|
|
|
436
445
|
})
|
|
437
446
|
.passthrough();
|
|
438
447
|
/* -------------------------------------------------------------------------- */
|
|
448
|
+
/* Modules */
|
|
449
|
+
/* -------------------------------------------------------------------------- */
|
|
450
|
+
const moduleNavSectionSchema = z
|
|
451
|
+
.object({
|
|
452
|
+
key: z.string().min(1, { message: 'module nav section.key is required' }),
|
|
453
|
+
title: localizedSchema,
|
|
454
|
+
url: z.string().min(1, { message: 'module nav section.url is required' }),
|
|
455
|
+
icon: z.string().min(1, { message: 'module nav section.icon is required' }),
|
|
456
|
+
countSource: z.string().optional()
|
|
457
|
+
})
|
|
458
|
+
.passthrough();
|
|
459
|
+
const moduleContextSchema = z
|
|
460
|
+
.object({
|
|
461
|
+
contextLabel: localizedSchema.optional(),
|
|
462
|
+
landingUrl: z.string().min(1, { message: 'module context.landingUrl is required' }),
|
|
463
|
+
sections: z.array(moduleNavSectionSchema),
|
|
464
|
+
surfacedCollections: z.array(z.string()).optional(),
|
|
465
|
+
surfacedSingles: z.array(z.string()).optional()
|
|
466
|
+
})
|
|
467
|
+
.passthrough();
|
|
468
|
+
const moduleSchema = z
|
|
469
|
+
.object({
|
|
470
|
+
id: slugSchema,
|
|
471
|
+
label: localizedSchema,
|
|
472
|
+
icon: z.string().min(1, { message: 'module.icon is required' }),
|
|
473
|
+
context: moduleContextSchema,
|
|
474
|
+
// `config` holds adapter functions / resolved module config — opaque.
|
|
475
|
+
config: z.unknown().optional(),
|
|
476
|
+
// `serverHooks` holds functions — never validated, never serialized.
|
|
477
|
+
serverHooks: z.unknown().optional()
|
|
478
|
+
})
|
|
479
|
+
.passthrough();
|
|
480
|
+
/* -------------------------------------------------------------------------- */
|
|
439
481
|
/* CMSConfig */
|
|
440
482
|
/* -------------------------------------------------------------------------- */
|
|
441
483
|
const cmsConfigBaseSchema = z
|
|
@@ -465,7 +507,7 @@ const cmsConfigBaseSchema = z
|
|
|
465
507
|
.passthrough()
|
|
466
508
|
.optional(),
|
|
467
509
|
sidebarHelp: z.boolean().optional(),
|
|
468
|
-
|
|
510
|
+
modules: z.array(moduleSchema).optional(),
|
|
469
511
|
cmp: z.unknown().optional()
|
|
470
512
|
})
|
|
471
513
|
.passthrough();
|
|
@@ -625,6 +667,46 @@ export const cmsConfigSchema = cmsConfigBaseSchema.superRefine((data, ctx) => {
|
|
|
625
667
|
}
|
|
626
668
|
}
|
|
627
669
|
});
|
|
670
|
+
// Module id uniqueness + surfaced collection/single references
|
|
671
|
+
const moduleIds = new Set();
|
|
672
|
+
(data.modules ?? []).forEach((m, i) => {
|
|
673
|
+
const mod = m;
|
|
674
|
+
const id = mod.id;
|
|
675
|
+
if (typeof id === 'string') {
|
|
676
|
+
if (moduleIds.has(id)) {
|
|
677
|
+
ctx.addIssue({
|
|
678
|
+
code: z.ZodIssueCode.custom,
|
|
679
|
+
path: ['modules', i, 'id'],
|
|
680
|
+
message: `duplicate module id '${id}'`
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
moduleIds.add(id);
|
|
684
|
+
}
|
|
685
|
+
const surfacedCollections = mod.context?.surfacedCollections;
|
|
686
|
+
if (Array.isArray(surfacedCollections)) {
|
|
687
|
+
surfacedCollections.forEach((slug, j) => {
|
|
688
|
+
if (!collectionSlugs.has(slug)) {
|
|
689
|
+
ctx.addIssue({
|
|
690
|
+
code: z.ZodIssueCode.custom,
|
|
691
|
+
path: ['modules', i, 'context', 'surfacedCollections', j],
|
|
692
|
+
message: `surfaced collection '${slug}' does not reference a declared collection`
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
const surfacedSingles = mod.context?.surfacedSingles;
|
|
698
|
+
if (Array.isArray(surfacedSingles)) {
|
|
699
|
+
surfacedSingles.forEach((slug, j) => {
|
|
700
|
+
if (!singleSlugs.has(slug)) {
|
|
701
|
+
ctx.addIssue({
|
|
702
|
+
code: z.ZodIssueCode.custom,
|
|
703
|
+
path: ['modules', i, 'context', 'surfacedSingles', j],
|
|
704
|
+
message: `surfaced single '${slug}' does not reference a declared single`
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
});
|
|
628
710
|
});
|
|
629
711
|
/** Exposed for tests only. Not part of the public API. */
|
|
630
712
|
export const _internal = {
|
|
@@ -633,6 +715,7 @@ export const _internal = {
|
|
|
633
715
|
collectionSchema,
|
|
634
716
|
singleSchema,
|
|
635
717
|
formSchema,
|
|
718
|
+
moduleSchema,
|
|
636
719
|
cmsConfigBaseSchema,
|
|
637
720
|
FIELD_TYPES,
|
|
638
721
|
FORM_FIELD_TYPES,
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
import type { Field } from './fields.js';
|
|
2
2
|
import type { IconName } from '../admin/components/icons/icon-map.js';
|
|
3
3
|
import type { Layout } from './layout.js';
|
|
4
|
+
import type { Localized } from './languages.js';
|
|
5
|
+
/**
|
|
6
|
+
* A named preview target. The same entry is often rendered in more than one way
|
|
7
|
+
* on the front end — a full page and a teaser card in a listing — and each way
|
|
8
|
+
* is a view.
|
|
9
|
+
*
|
|
10
|
+
* The admin loads `{url}?preview={entryId}&view={name}` in the preview iframe,
|
|
11
|
+
* so a project may expose one route per view, or a single route that branches
|
|
12
|
+
* on the `view` query param. Views do not change what is fetched from the
|
|
13
|
+
* database — the entry always arrives whole.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* previews: [
|
|
19
|
+
* { name: 'full', label: { pl: 'Pełny wpis' }, url: '/preview/blog-post' },
|
|
20
|
+
* { name: 'teaser', label: { pl: 'Zajawka' }, url: '/preview/blog-post/teaser' }
|
|
21
|
+
* ]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export interface PreviewView {
|
|
25
|
+
/** Stable identifier, referenced by `TabNode.preview`. */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Switcher label. Defaults to `name`. */
|
|
28
|
+
label?: Localized;
|
|
29
|
+
/** Preview route, e.g. '/preview/blog-post/teaser'. */
|
|
30
|
+
url: string;
|
|
31
|
+
/** Start view. Defaults to the first entry of the array. */
|
|
32
|
+
default?: boolean;
|
|
33
|
+
}
|
|
4
34
|
export interface ConfigBase {
|
|
5
35
|
sidebarIcon?: IconName;
|
|
6
36
|
slug: string;
|
|
37
|
+
/** Shorthand for a single preview view. Mutually exclusive with `previews`. */
|
|
7
38
|
previewUrl?: string;
|
|
39
|
+
/** Named preview views. Mutually exclusive with `previewUrl`. */
|
|
40
|
+
previews?: PreviewView[];
|
|
8
41
|
fields: Field[];
|
|
9
42
|
layout?: Layout;
|
|
10
43
|
slugField?: string;
|
package/dist/types/layout.d.ts
CHANGED
|
@@ -81,6 +81,12 @@ export interface TabsNode extends LayoutNodeBase {
|
|
|
81
81
|
export interface TabNode extends LayoutNodeBase {
|
|
82
82
|
type: 'tab';
|
|
83
83
|
label: Localized;
|
|
84
|
+
/**
|
|
85
|
+
* Name of a view from `previews[]`. Entering this tab switches the preview to
|
|
86
|
+
* that view, unless the user manually picked another view while on this tab.
|
|
87
|
+
* A tab without `preview` leaves the current view alone.
|
|
88
|
+
*/
|
|
89
|
+
preview?: string;
|
|
84
90
|
fields?: string[];
|
|
85
91
|
children?: LayoutNode[];
|
|
86
92
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module system — shop, booking, and future "overlays" on the CMS core.
|
|
3
|
+
*
|
|
4
|
+
* A module is registered via `defineConfig({ modules: [...] })`. It is split
|
|
5
|
+
* into a **serializable descriptor** (id/label/icon/context — safe to send to
|
|
6
|
+
* the admin client via a remote query) and **server-only `serverHooks`**
|
|
7
|
+
* (init logic that must never cross the wire). The module's dashboard
|
|
8
|
+
* component lives in a separate client-side registry keyed by `id`, never in
|
|
9
|
+
* the config — Svelte components are not serializable and the config is also
|
|
10
|
+
* validated server-side with Zod.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link CMSModule}
|
|
13
|
+
*/
|
|
14
|
+
/** A label that is either a plain string or a `{ lang: text }` map. */
|
|
15
|
+
export type LocalizedText = string | Record<string, string>;
|
|
16
|
+
/**
|
|
17
|
+
* One sidebar entry contributed by a module's context. Icons are referenced
|
|
18
|
+
* by **name** (resolved client-side via the admin icon-map), never as a
|
|
19
|
+
* component, so the descriptor stays serializable and userland never needs an
|
|
20
|
+
* icon library as a dependency.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export interface ModuleNavSection {
|
|
25
|
+
/** Stable key for keyed rendering and active-state checks. */
|
|
26
|
+
key: string;
|
|
27
|
+
/** Display title. */
|
|
28
|
+
title: LocalizedText;
|
|
29
|
+
/** Target route, e.g. `/admin/shop/orders`. */
|
|
30
|
+
url: string;
|
|
31
|
+
/** Icon name from the admin icon-map, e.g. `shopping-cart`. */
|
|
32
|
+
icon: string;
|
|
33
|
+
/**
|
|
34
|
+
* Optional remote-query name returning a `number`, rendered as a badge and
|
|
35
|
+
* resolved reactively on the client (same pattern as collection entry
|
|
36
|
+
* counts). Omit for sections without a count.
|
|
37
|
+
*/
|
|
38
|
+
countSource?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The curated workspace a module contributes: a landing (dashboard) target,
|
|
42
|
+
* its own nav sections, and optional **surfaced** core collections/singles
|
|
43
|
+
* pulled into the module's context (e.g. shop surfaces the `products`
|
|
44
|
+
* collection as "Products").
|
|
45
|
+
*
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export interface ModuleContext {
|
|
49
|
+
/** Switcher label for this context. Defaults to the module's `label`. */
|
|
50
|
+
contextLabel?: LocalizedText;
|
|
51
|
+
/** Where selecting this context navigates, e.g. `/admin/shop`. */
|
|
52
|
+
landingUrl: string;
|
|
53
|
+
/** Static nav sections owned by the module. */
|
|
54
|
+
sections: ModuleNavSection[];
|
|
55
|
+
/** Slugs of core collections surfaced inside this context. */
|
|
56
|
+
surfacedCollections?: string[];
|
|
57
|
+
/** Slugs of core singles surfaced inside this context. */
|
|
58
|
+
surfacedSingles?: string[];
|
|
59
|
+
}
|
|
60
|
+
/** Context passed to a module's `serverHooks.init`. */
|
|
61
|
+
export interface ModuleInitContext {
|
|
62
|
+
/** Raw drizzle handle (`databaseAdapter._drizzle`), or `undefined`. */
|
|
63
|
+
drizzle: unknown;
|
|
64
|
+
/** The module's own resolved config (same reference as `CMSModule.config`). */
|
|
65
|
+
config: unknown;
|
|
66
|
+
/** The CMS default language code (first configured language). */
|
|
67
|
+
defaultLanguage: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Server-only module hooks. NEVER serialized or sent to the admin client —
|
|
71
|
+
* stripped from the descriptor returned by `getModules()`.
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export interface ModuleServerHooks {
|
|
76
|
+
/**
|
|
77
|
+
* Idempotent boot-time init run by `initCMS` (e.g. create indexes,
|
|
78
|
+
* smoke-test templates). Non-blocking: errors are logged, not thrown.
|
|
79
|
+
*
|
|
80
|
+
* Define this ONLY in a server-only module. A module whose factory (e.g.
|
|
81
|
+
* `defineBooking`) is re-exported from a client-safe barrel MUST NOT inline a
|
|
82
|
+
* server import here — bundlers create a chunk for it and break browser builds.
|
|
83
|
+
* Use {@link initModule} instead.
|
|
84
|
+
*/
|
|
85
|
+
init?: (ctx: ModuleInitContext) => Promise<void> | void;
|
|
86
|
+
/**
|
|
87
|
+
* Bare package specifier of a SERVER-ONLY module exporting `serverInit(ctx)`,
|
|
88
|
+
* run by `initCMS` at boot. Prefer this over {@link init} when the module's
|
|
89
|
+
* factory lives in a client-safe barrel: it is a plain string (no import), so
|
|
90
|
+
* the client bundle stays free of server code. `initCMS` (server-only) resolves
|
|
91
|
+
* and imports it at runtime from node_modules. Ignored if {@link init} is set.
|
|
92
|
+
*/
|
|
93
|
+
initModule?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A CMS module ("overlay"): shop, booking, etc. Register via
|
|
97
|
+
* `defineConfig({ modules: [defineShop(...), defineBooking(...)] })`.
|
|
98
|
+
*
|
|
99
|
+
* @public
|
|
100
|
+
*/
|
|
101
|
+
export interface CMSModule {
|
|
102
|
+
/** Unique slug, e.g. `shop` | `booking`. */
|
|
103
|
+
id: string;
|
|
104
|
+
/** Display label (switcher + sidebar group label). */
|
|
105
|
+
label: LocalizedText;
|
|
106
|
+
/** Icon name from the admin icon-map, e.g. `building-store`. */
|
|
107
|
+
icon: string;
|
|
108
|
+
/** The curated workspace this module contributes. */
|
|
109
|
+
context: ModuleContext;
|
|
110
|
+
/** The module's typed resolved config — opaque to the framework. */
|
|
111
|
+
config?: unknown;
|
|
112
|
+
/** Server-only hooks (not part of the serialized descriptor). */
|
|
113
|
+
serverHooks?: ModuleServerHooks;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The serializable subset of a {@link CMSModule} sent to the admin client.
|
|
117
|
+
* Excludes `config` (may hold adapter functions) and `serverHooks`.
|
|
118
|
+
*
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
export interface CMSModuleDescriptor {
|
|
122
|
+
id: string;
|
|
123
|
+
label: LocalizedText;
|
|
124
|
+
icon: string;
|
|
125
|
+
context: ModuleContext;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Strips a {@link CMSModule} down to its serializable {@link CMSModuleDescriptor}
|
|
129
|
+
* for transport to the admin client. Drops `config` and `serverHooks`.
|
|
130
|
+
*
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
export declare function toModuleDescriptor(module: CMSModule): CMSModuleDescriptor;
|