includio-cms 0.36.9 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +178 -3
- package/CHANGELOG.md +54 -0
- package/DOCS.md +28 -3
- package/ROADMAP.md +18 -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 +244 -0
- package/dist/admin/remote/booking.remote.js +283 -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 +39 -0
- package/dist/booking/client/index.js +44 -0
- package/dist/booking/client/use-booking.svelte.d.ts +25 -0
- package/dist/booking/client/use-booking.svelte.js +56 -0
- package/dist/booking/config.d.ts +156 -0
- package/dist/booking/config.js +36 -0
- package/dist/booking/draft.d.ts +77 -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 +136 -0
- package/dist/booking/server/bookings.d.ts +45 -0
- package/dist/booking/server/bookings.js +288 -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 +68 -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 +99 -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 +207 -0
- package/dist/booking/server/portal.js +234 -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 +307 -0
- package/dist/db-postgres/schema/booking/bookings.js +40 -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/index.js +3 -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
|
@@ -19,31 +19,51 @@ export function payuAdapter(opts) {
|
|
|
19
19
|
id,
|
|
20
20
|
label: opts.label ?? DEFAULT_LABEL,
|
|
21
21
|
async createPayment(order, ctx) {
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
|
|
22
|
+
let continueUrl;
|
|
23
|
+
const buyer = {};
|
|
24
|
+
if (ctx?.continueUrl) {
|
|
25
|
+
// Non-shop caller (e.g. booking) supplied everything — skip shop hydration.
|
|
26
|
+
if (!/^https?:\/\//i.test(ctx.continueUrl)) {
|
|
27
|
+
throw new Error('payuAdapter: ctx.continueUrl must be an absolute URL.');
|
|
28
|
+
}
|
|
29
|
+
continueUrl = ctx.continueUrl;
|
|
30
|
+
buyer.firstName = ctx.buyer?.firstName;
|
|
31
|
+
buyer.lastName = ctx.buyer?.lastName;
|
|
32
|
+
buyer.phone = ctx.buyer?.phone;
|
|
33
|
+
buyer.language = ctx.language ?? undefined;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Shop path: hydrate buyer + continueUrl from the stored shop order.
|
|
37
|
+
const shop = requireShopConfig();
|
|
38
|
+
const continueTemplate = opts.continueUrl ?? shop.orderViewUrl;
|
|
39
|
+
if (!/^https?:\/\//i.test(continueTemplate)) {
|
|
40
|
+
throw new Error('payuAdapter: continueUrl (or shop.orderViewUrl) must be an absolute URL.');
|
|
41
|
+
}
|
|
42
|
+
const full = await getOrderById(order.id);
|
|
43
|
+
const names = splitFullName(full?.customerName);
|
|
44
|
+
continueUrl = buildOrderViewUrl(continueTemplate, {
|
|
45
|
+
orderNumber: order.number,
|
|
46
|
+
orderId: order.id,
|
|
47
|
+
accessToken: full?.accessToken ?? '',
|
|
48
|
+
language: ctx?.language ?? full?.language ?? null
|
|
49
|
+
});
|
|
50
|
+
buyer.firstName = names.firstName;
|
|
51
|
+
buyer.lastName = names.lastName;
|
|
52
|
+
buyer.phone = full?.customerPhone ?? undefined;
|
|
53
|
+
buyer.language = ctx?.language ?? full?.language ?? undefined;
|
|
26
54
|
}
|
|
27
|
-
// Hydrate buyer details from stored order (customerName/phone not on OrderRef)
|
|
28
|
-
const full = await getOrderById(order.id);
|
|
29
|
-
const names = splitFullName(full?.customerName);
|
|
30
|
-
const continueUrl = buildOrderViewUrl(continueTemplate, {
|
|
31
|
-
orderNumber: order.number,
|
|
32
|
-
orderId: order.id,
|
|
33
|
-
accessToken: full?.accessToken ?? '',
|
|
34
|
-
language: ctx?.language ?? full?.language ?? null
|
|
35
|
-
});
|
|
36
55
|
const payload = buildPayuOrderPayload({
|
|
37
56
|
order,
|
|
38
57
|
posId: opts.posId,
|
|
39
58
|
notifyUrl: opts.notifyUrl,
|
|
40
59
|
continueUrl,
|
|
41
60
|
customerIp: ctx?.customerIp ?? '127.0.0.1',
|
|
61
|
+
externalId: ctx?.externalId,
|
|
42
62
|
buyer: {
|
|
43
|
-
firstName:
|
|
44
|
-
lastName:
|
|
45
|
-
phone:
|
|
46
|
-
language:
|
|
63
|
+
firstName: buyer.firstName,
|
|
64
|
+
lastName: buyer.lastName,
|
|
65
|
+
phone: buyer.phone,
|
|
66
|
+
language: buyer.language
|
|
47
67
|
}
|
|
48
68
|
});
|
|
49
69
|
const { redirectUri, orderId } = await client.createOrder(payload);
|
|
@@ -32,6 +32,12 @@ export interface BuildPayuPayloadInput {
|
|
|
32
32
|
buyer?: Omit<PayuBuyer, 'email'> & {
|
|
33
33
|
email?: string;
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Unique `extOrderId` for this attempt. PayU requires it unique per POS, so a
|
|
37
|
+
* single order/booking paying twice (deposit + balance) must vary it. Falls
|
|
38
|
+
* back to `order.number` when omitted.
|
|
39
|
+
*/
|
|
40
|
+
externalId?: string;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* Split a single "Imię Nazwisko" string into first/last name heuristically.
|
|
@@ -35,7 +35,7 @@ export function buildPayuOrderPayload(input) {
|
|
|
35
35
|
description: input.description ?? `Order ${order.number}`,
|
|
36
36
|
currencyCode: order.currency,
|
|
37
37
|
totalAmount: String(order.totalGross),
|
|
38
|
-
extOrderId: order.number,
|
|
38
|
+
extOrderId: input.externalId ?? order.number,
|
|
39
39
|
buyer,
|
|
40
40
|
products: [
|
|
41
41
|
{
|
|
@@ -63,29 +63,44 @@ export function stripeAdapter(opts) {
|
|
|
63
63
|
id,
|
|
64
64
|
label: opts.label ?? DEFAULT_LABEL,
|
|
65
65
|
async createPayment(order, ctx) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
66
|
+
let successUrl;
|
|
67
|
+
let cancelUrl;
|
|
68
|
+
let language;
|
|
69
|
+
if (ctx?.continueUrl) {
|
|
70
|
+
// Non-shop caller (e.g. booking) supplied a fully-resolved return URL —
|
|
71
|
+
// use it verbatim and skip any shop-order hydration (mirrors payuAdapter).
|
|
72
|
+
if (!/^https?:\/\//i.test(ctx.continueUrl)) {
|
|
73
|
+
throw new Error('stripeAdapter: ctx.continueUrl must be an absolute URL.');
|
|
74
|
+
}
|
|
75
|
+
successUrl = ctx.continueUrl;
|
|
76
|
+
cancelUrl = ctx.continueUrl;
|
|
77
|
+
language = ctx.language ?? null;
|
|
71
78
|
}
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
else {
|
|
80
|
+
const shop = requireShopConfig();
|
|
81
|
+
const successTemplate = opts.successUrl ?? shop.orderViewUrl;
|
|
82
|
+
const cancelTemplate = opts.cancelUrl ?? successTemplate;
|
|
83
|
+
if (!/^https?:\/\//i.test(successTemplate)) {
|
|
84
|
+
throw new Error('stripeAdapter: successUrl (or shop.orderViewUrl) must be an absolute URL.');
|
|
85
|
+
}
|
|
86
|
+
if (!/^https?:\/\//i.test(cancelTemplate)) {
|
|
87
|
+
throw new Error('stripeAdapter: cancelUrl must be an absolute URL.');
|
|
88
|
+
}
|
|
89
|
+
const full = await getOrderById(order.id);
|
|
90
|
+
language = ctx?.language ?? full?.language ?? null;
|
|
91
|
+
successUrl = buildOrderViewUrl(successTemplate, {
|
|
92
|
+
orderNumber: order.number,
|
|
93
|
+
orderId: order.id,
|
|
94
|
+
accessToken: full?.accessToken ?? '',
|
|
95
|
+
language
|
|
96
|
+
});
|
|
97
|
+
cancelUrl = buildOrderViewUrl(cancelTemplate, {
|
|
98
|
+
orderNumber: order.number,
|
|
99
|
+
orderId: order.id,
|
|
100
|
+
accessToken: full?.accessToken ?? '',
|
|
101
|
+
language
|
|
102
|
+
});
|
|
74
103
|
}
|
|
75
|
-
const full = await getOrderById(order.id);
|
|
76
|
-
const language = ctx?.language ?? full?.language ?? null;
|
|
77
|
-
const successUrl = buildOrderViewUrl(successTemplate, {
|
|
78
|
-
orderNumber: order.number,
|
|
79
|
-
orderId: order.id,
|
|
80
|
-
accessToken: full?.accessToken ?? '',
|
|
81
|
-
language
|
|
82
|
-
});
|
|
83
|
-
const cancelUrl = buildOrderViewUrl(cancelTemplate, {
|
|
84
|
-
orderNumber: order.number,
|
|
85
|
-
orderId: order.id,
|
|
86
|
-
accessToken: full?.accessToken ?? '',
|
|
87
|
-
language
|
|
88
|
-
});
|
|
89
104
|
const productNameTpl = pickI18n(opts.productName ?? DEFAULT_PRODUCT_NAME, language);
|
|
90
105
|
const productName = productNameTpl.replace('{number}', order.number);
|
|
91
106
|
const payload = buildStripeCheckoutPayload({
|
package/dist/shop/index.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import type { ShopConfig
|
|
2
|
-
|
|
1
|
+
import type { ShopConfig } from './types.js';
|
|
2
|
+
import type { CMSModule } from '../types/modules.js';
|
|
3
|
+
/**
|
|
4
|
+
* Defines the shop module. Returns a {@link CMSModule} for
|
|
5
|
+
* `defineConfig({ modules: [defineShop({...})] })`. The resolved shop config
|
|
6
|
+
* is carried on `module.config` and reachable via `getCMS().getModuleConfig('shop')`
|
|
7
|
+
* (or the back-compat `getCMS().shopConfig`).
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export declare function defineShop(config: ShopConfig): CMSModule;
|
|
3
12
|
export { InvalidVariantAttributesError } from './variant-attributes.js';
|
|
4
13
|
export { isVariantExpired, filterUpcoming, VariantExpiredError } from './expiry.js';
|
|
5
14
|
export { manualAdapter } from './adapters/manual/index.js';
|
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,
|