includio-cms 0.26.0 → 0.28.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 +58 -2
- package/CHANGELOG.md +105 -0
- package/DOCS.md +1 -1
- package/ROADMAP.md +8 -0
- package/dist/admin/auth-client.d.ts +42 -42
- package/dist/admin/client/admin/admin-layout.svelte +12 -2
- package/dist/admin/client/admin/admin-layout.svelte.d.ts +2 -1
- package/dist/admin/client/collection/data-table.svelte +0 -39
- package/dist/admin/client/collection/data-table.svelte.d.ts +0 -2
- package/dist/admin/client/shop/coupon-schema.d.ts +1 -1
- package/dist/admin/client/shop/refund-dialog.svelte +37 -1
- package/dist/admin/client/shop/refund-dialog.svelte.d.ts +3 -0
- package/dist/admin/client/shop/shop-order-detail-page.svelte +192 -0
- package/dist/admin/components/fields/field-renderer.svelte +6 -1
- package/dist/admin/components/fields/icon-field.svelte +86 -0
- package/dist/admin/components/fields/icon-field.svelte.d.ts +8 -0
- package/dist/admin/components/fields/icon-picker-dialog.svelte +174 -0
- package/dist/admin/components/fields/icon-picker-dialog.svelte.d.ts +11 -0
- package/dist/admin/components/fields/object-field.svelte +27 -7
- package/dist/admin/components/fields/shop-field.svelte +210 -20
- package/dist/admin/components/layout/layout-tabs.svelte +1 -0
- package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte +109 -0
- package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte.d.ts +9 -0
- package/dist/admin/helpers/build-icon-set-map.d.ts +8 -0
- package/dist/admin/helpers/build-icon-set-map.js +16 -0
- package/dist/admin/helpers/index.d.ts +2 -0
- package/dist/admin/helpers/index.js +2 -0
- package/dist/admin/remote/shop.remote.d.ts +116 -24
- package/dist/admin/remote/shop.remote.js +79 -6
- package/dist/admin/state/icon-sets.svelte.d.ts +9 -0
- package/dist/admin/state/icon-sets.svelte.js +20 -0
- package/dist/cli/scaffold/admin.js +2 -2
- package/dist/components/ui/checkbox/checkbox.svelte +3 -3
- package/dist/core/cms.d.ts +11 -2
- package/dist/core/cms.js +29 -0
- package/dist/core/fields/fieldSchemaToTs.js +7 -0
- package/dist/core/server/generator/fields.d.ts +2 -0
- package/dist/core/server/generator/fields.js +34 -1
- package/dist/core/server/generator/generator.js +2 -1
- package/dist/db-postgres/schema/shop/index.d.ts +1 -0
- package/dist/db-postgres/schema/shop/index.js +1 -0
- package/dist/db-postgres/schema/shop/invoice.d.ts +254 -0
- package/dist/db-postgres/schema/shop/invoice.js +27 -0
- package/dist/db-postgres/schema/shop/order.d.ts +107 -1
- package/dist/db-postgres/schema/shop/order.js +7 -1
- package/dist/db-postgres/schema/shop/payment.d.ts +20 -0
- package/dist/db-postgres/schema/shop/payment.js +4 -1
- package/dist/db-postgres/schema/shop/product.d.ts +20 -0
- package/dist/db-postgres/schema/shop/product.js +3 -1
- package/dist/db-postgres/schema/shop/productVariant.d.ts +12 -2
- package/dist/db-postgres/schema/shop/productVariant.js +22 -0
- package/dist/paraglide/messages/_index.d.ts +36 -3
- package/dist/paraglide/messages/_index.js +71 -3
- package/dist/paraglide/messages/en.d.ts +5 -0
- package/dist/paraglide/messages/en.js +14 -0
- package/dist/paraglide/messages/pl.d.ts +5 -0
- package/dist/paraglide/messages/pl.js +14 -0
- package/dist/shop/adapters/fakturownia/client.d.ts +28 -0
- package/dist/shop/adapters/fakturownia/client.js +67 -0
- package/dist/shop/adapters/fakturownia/index.d.ts +27 -0
- package/dist/shop/adapters/fakturownia/index.js +36 -0
- package/dist/shop/adapters/fakturownia/payload.d.ts +35 -0
- package/dist/shop/adapters/fakturownia/payload.js +45 -0
- package/dist/shop/cart/types.d.ts +1 -0
- package/dist/shop/client/index.d.ts +61 -0
- package/dist/shop/client/index.js +5 -1
- package/dist/shop/expiry.d.ts +35 -0
- package/dist/shop/expiry.js +68 -0
- package/dist/shop/http/balance-handler.d.ts +20 -0
- package/dist/shop/http/balance-handler.js +91 -0
- package/dist/shop/http/cart-handler.js +19 -0
- package/dist/shop/http/checkout-handler.js +30 -1
- package/dist/shop/http/index.d.ts +2 -0
- package/dist/shop/http/index.js +2 -0
- package/dist/shop/http/upcoming-handler.d.ts +16 -0
- package/dist/shop/http/upcoming-handler.js +65 -0
- package/dist/shop/http/webhook-handler.js +46 -9
- package/dist/shop/index.d.ts +7 -1
- package/dist/shop/index.js +10 -1
- package/dist/shop/nip.d.ts +12 -0
- package/dist/shop/nip.js +23 -0
- package/dist/shop/server/balance-payment.d.ts +40 -0
- package/dist/shop/server/balance-payment.js +140 -0
- package/dist/shop/server/cart-hydrate.js +2 -0
- package/dist/shop/server/init.d.ts +14 -0
- package/dist/shop/server/init.js +35 -0
- package/dist/shop/server/invoices.d.ts +64 -0
- package/dist/shop/server/invoices.js +237 -0
- package/dist/shop/server/orders.d.ts +38 -0
- package/dist/shop/server/orders.js +152 -2
- package/dist/shop/server/payment-policy.d.ts +35 -0
- package/dist/shop/server/payment-policy.js +55 -0
- package/dist/shop/server/payments.d.ts +29 -0
- package/dist/shop/server/payments.js +64 -0
- package/dist/shop/server/populate.d.ts +1 -1
- package/dist/shop/server/refund.d.ts +17 -12
- package/dist/shop/server/refund.js +96 -13
- package/dist/shop/server/shop-data.d.ts +4 -1
- package/dist/shop/server/shop-data.js +24 -2
- package/dist/shop/template.d.ts +13 -0
- package/dist/shop/template.js +98 -0
- package/dist/shop/types.d.ts +208 -1
- package/dist/shop/variant-attributes.d.ts +28 -0
- package/dist/shop/variant-attributes.js +69 -0
- package/dist/sveltekit/server/index.d.ts +1 -0
- package/dist/sveltekit/server/index.js +2 -0
- package/dist/types/cms.d.ts +4 -3
- package/dist/types/cms.schema.d.ts +1 -1
- package/dist/types/cms.schema.js +9 -0
- package/dist/types/fields.d.ts +21 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/plugins.d.ts +40 -0
- package/dist/types/plugins.js +4 -1
- package/dist/updates/0.26.1/index.d.ts +2 -0
- package/dist/updates/0.26.1/index.js +19 -0
- package/dist/updates/0.27.0/index.d.ts +2 -0
- package/dist/updates/0.27.0/index.js +50 -0
- package/dist/updates/0.28.0/index.d.ts +2 -0
- package/dist/updates/0.28.0/index.js +38 -0
- package/dist/updates/index.js +7 -1
- package/package.json +1 -1
- package/dist/paraglide/messages/hello_world.d.ts +0 -5
- package/dist/paraglide/messages/hello_world.js +0 -33
- package/dist/paraglide/messages/login_hello.d.ts +0 -16
- package/dist/paraglide/messages/login_hello.js +0 -34
- package/dist/paraglide/messages/login_please_login.d.ts +0 -16
- package/dist/paraglide/messages/login_please_login.js +0 -34
|
@@ -8,6 +8,9 @@ export declare const getShopConfig: import("@sveltejs/kit").RemoteQueryFunction<
|
|
|
8
8
|
id: string;
|
|
9
9
|
label: import("../../shop/types.js").I18nText;
|
|
10
10
|
}[];
|
|
11
|
+
variantAttributes: Record<string, import("../../shop/types.js").VariantAttribute>;
|
|
12
|
+
variantLabel: import("../../shop/types.js").VariantLabelConfig | null;
|
|
13
|
+
variantExpiry: import("../../shop/types.js").VariantExpiryConfig | null;
|
|
11
14
|
} | null>;
|
|
12
15
|
export declare const listShopProductEntries: import("@sveltejs/kit").RemoteQueryFunction<void, import("../../shop/server/shop-data.js").ShopEntryListItem[]>;
|
|
13
16
|
export declare const getShopDataForEntry: import("@sveltejs/kit").RemoteQueryFunction<string, import("../../shop/server/shop-data.js").ShopDataWithVariants | null>;
|
|
@@ -18,6 +21,18 @@ export declare const upsertShopDataForEntry: import("@sveltejs/kit").RemoteComma
|
|
|
18
21
|
vatRate: number;
|
|
19
22
|
isActive?: boolean | undefined;
|
|
20
23
|
sortOrder?: number | null | undefined;
|
|
24
|
+
paymentPolicy?: {
|
|
25
|
+
type: "full";
|
|
26
|
+
} | {
|
|
27
|
+
type: "deposit";
|
|
28
|
+
depositAmount: {
|
|
29
|
+
type: "percent";
|
|
30
|
+
value: number;
|
|
31
|
+
} | {
|
|
32
|
+
type: "amount";
|
|
33
|
+
value: number;
|
|
34
|
+
};
|
|
35
|
+
} | null | undefined;
|
|
21
36
|
};
|
|
22
37
|
variants?: {
|
|
23
38
|
id?: string | undefined;
|
|
@@ -25,7 +40,7 @@ export declare const upsertShopDataForEntry: import("@sveltejs/kit").RemoteComma
|
|
|
25
40
|
name?: Record<string, string> | null | undefined;
|
|
26
41
|
priceDelta?: number | undefined;
|
|
27
42
|
stock?: number | null | undefined;
|
|
28
|
-
attributes?: Record<string,
|
|
43
|
+
attributes?: Record<string, unknown> | null | undefined;
|
|
29
44
|
}[] | undefined;
|
|
30
45
|
}, Promise<import("../../shop/server/shop-data.js").ShopDataWithVariants>>;
|
|
31
46
|
export declare const deleteShopDataForEntry: import("@sveltejs/kit").RemoteCommand<string, Promise<{
|
|
@@ -84,17 +99,26 @@ export declare const listOrdersAdmin: import("@sveltejs/kit").RemoteQueryFunctio
|
|
|
84
99
|
} | undefined, {
|
|
85
100
|
items: {
|
|
86
101
|
number: string;
|
|
102
|
+
currency: string;
|
|
103
|
+
consents: {
|
|
104
|
+
id: string;
|
|
105
|
+
accepted: boolean;
|
|
106
|
+
label: string;
|
|
107
|
+
}[] | null;
|
|
87
108
|
id: string;
|
|
88
109
|
status: import("../../shop/types.js").OrderStatus;
|
|
89
110
|
createdAt: Date;
|
|
90
111
|
updatedAt: Date;
|
|
91
112
|
language: string | null;
|
|
92
113
|
carrierType: string | null;
|
|
93
|
-
currency: string;
|
|
94
114
|
customerEmail: string;
|
|
95
115
|
customerName: string | null;
|
|
96
116
|
customerPhone: string | null;
|
|
117
|
+
customerNip: string | null;
|
|
118
|
+
customerCompanyName: string | null;
|
|
97
119
|
shippingAddress: Record<string, string> | null;
|
|
120
|
+
billingAddress: Record<string, string> | null;
|
|
121
|
+
invoiceRequested: boolean;
|
|
98
122
|
totalNet: number;
|
|
99
123
|
totalGross: number;
|
|
100
124
|
vatAmount: number;
|
|
@@ -108,13 +132,10 @@ export declare const listOrdersAdmin: import("@sveltejs/kit").RemoteQueryFunctio
|
|
|
108
132
|
shipmentCreatedAt: Date | null;
|
|
109
133
|
paymentMethod: string | null;
|
|
110
134
|
paymentProviderRef: string | null;
|
|
111
|
-
consents: {
|
|
112
|
-
id: string;
|
|
113
|
-
accepted: boolean;
|
|
114
|
-
label: string;
|
|
115
|
-
}[] | null;
|
|
116
135
|
notes: string | null;
|
|
117
136
|
accessToken: string;
|
|
137
|
+
partialPayment: import("../../shop/types.js").PartialPayment | null;
|
|
138
|
+
balanceOwed: boolean;
|
|
118
139
|
}[];
|
|
119
140
|
total: number;
|
|
120
141
|
limit: number;
|
|
@@ -123,17 +144,26 @@ export declare const listOrdersAdmin: import("@sveltejs/kit").RemoteQueryFunctio
|
|
|
123
144
|
export declare const getOrderForAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
|
|
124
145
|
order: {
|
|
125
146
|
number: string;
|
|
147
|
+
currency: string;
|
|
148
|
+
consents: {
|
|
149
|
+
id: string;
|
|
150
|
+
accepted: boolean;
|
|
151
|
+
label: string;
|
|
152
|
+
}[] | null;
|
|
126
153
|
id: string;
|
|
127
154
|
status: import("../../shop/types.js").OrderStatus;
|
|
128
155
|
createdAt: Date;
|
|
129
156
|
updatedAt: Date;
|
|
130
157
|
language: string | null;
|
|
131
158
|
carrierType: string | null;
|
|
132
|
-
currency: string;
|
|
133
159
|
customerEmail: string;
|
|
134
160
|
customerName: string | null;
|
|
135
161
|
customerPhone: string | null;
|
|
162
|
+
customerNip: string | null;
|
|
163
|
+
customerCompanyName: string | null;
|
|
136
164
|
shippingAddress: Record<string, string> | null;
|
|
165
|
+
billingAddress: Record<string, string> | null;
|
|
166
|
+
invoiceRequested: boolean;
|
|
137
167
|
totalNet: number;
|
|
138
168
|
totalGross: number;
|
|
139
169
|
vatAmount: number;
|
|
@@ -147,13 +177,10 @@ export declare const getOrderForAdmin: import("@sveltejs/kit").RemoteQueryFuncti
|
|
|
147
177
|
shipmentCreatedAt: Date | null;
|
|
148
178
|
paymentMethod: string | null;
|
|
149
179
|
paymentProviderRef: string | null;
|
|
150
|
-
consents: {
|
|
151
|
-
id: string;
|
|
152
|
-
accepted: boolean;
|
|
153
|
-
label: string;
|
|
154
|
-
}[] | null;
|
|
155
180
|
notes: string | null;
|
|
156
181
|
accessToken: string;
|
|
182
|
+
partialPayment: import("../../shop/types.js").PartialPayment | null;
|
|
183
|
+
balanceOwed: boolean;
|
|
157
184
|
};
|
|
158
185
|
items: {
|
|
159
186
|
id: string;
|
|
@@ -182,17 +209,26 @@ export declare const updateOrderStatusCmd: import("@sveltejs/kit").RemoteCommand
|
|
|
182
209
|
note?: string | undefined;
|
|
183
210
|
}, Promise<{
|
|
184
211
|
number: string;
|
|
212
|
+
currency: string;
|
|
213
|
+
consents: {
|
|
214
|
+
id: string;
|
|
215
|
+
accepted: boolean;
|
|
216
|
+
label: string;
|
|
217
|
+
}[] | null;
|
|
185
218
|
id: string;
|
|
186
219
|
status: import("../../shop/types.js").OrderStatus;
|
|
187
220
|
createdAt: Date;
|
|
188
221
|
updatedAt: Date;
|
|
189
222
|
language: string | null;
|
|
190
223
|
carrierType: string | null;
|
|
191
|
-
currency: string;
|
|
192
224
|
customerEmail: string;
|
|
193
225
|
customerName: string | null;
|
|
194
226
|
customerPhone: string | null;
|
|
227
|
+
customerNip: string | null;
|
|
228
|
+
customerCompanyName: string | null;
|
|
195
229
|
shippingAddress: Record<string, string> | null;
|
|
230
|
+
billingAddress: Record<string, string> | null;
|
|
231
|
+
invoiceRequested: boolean;
|
|
196
232
|
totalNet: number;
|
|
197
233
|
totalGross: number;
|
|
198
234
|
vatAmount: number;
|
|
@@ -206,13 +242,10 @@ export declare const updateOrderStatusCmd: import("@sveltejs/kit").RemoteCommand
|
|
|
206
242
|
shipmentCreatedAt: Date | null;
|
|
207
243
|
paymentMethod: string | null;
|
|
208
244
|
paymentProviderRef: string | null;
|
|
209
|
-
consents: {
|
|
210
|
-
id: string;
|
|
211
|
-
accepted: boolean;
|
|
212
|
-
label: string;
|
|
213
|
-
}[] | null;
|
|
214
245
|
notes: string | null;
|
|
215
246
|
accessToken: string;
|
|
247
|
+
partialPayment: import("../../shop/types.js").PartialPayment | null;
|
|
248
|
+
balanceOwed: boolean;
|
|
216
249
|
}>>;
|
|
217
250
|
export declare const resendOrderEmailCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
218
251
|
orderId: string;
|
|
@@ -253,15 +286,15 @@ export declare const listShopableCollections: import("@sveltejs/kit").RemoteQuer
|
|
|
253
286
|
}[]>;
|
|
254
287
|
export declare const getOrderRefundsAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
|
|
255
288
|
refunds: {
|
|
289
|
+
amount: number;
|
|
290
|
+
currency: string;
|
|
256
291
|
id: string;
|
|
257
292
|
status: import("../../db-postgres/schema/shop/index.js").ShopRefundStatus;
|
|
258
293
|
createdAt: Date;
|
|
259
294
|
updatedAt: Date;
|
|
260
|
-
currency: string;
|
|
261
295
|
orderId: string;
|
|
262
296
|
provider: string;
|
|
263
297
|
providerRef: string | null;
|
|
264
|
-
amount: number;
|
|
265
298
|
paymentId: string | null;
|
|
266
299
|
reason: string | null;
|
|
267
300
|
createdBy: string | null;
|
|
@@ -277,6 +310,8 @@ export declare const refundOrderCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
|
277
310
|
orderId: string;
|
|
278
311
|
amount?: number | undefined;
|
|
279
312
|
reason?: string | undefined;
|
|
313
|
+
kind?: "full" | "deposit" | "balance" | undefined;
|
|
314
|
+
releaseStock?: boolean | undefined;
|
|
280
315
|
}, Promise<{
|
|
281
316
|
refund: import("../../shop/server/refund.js").ShopRefundRow;
|
|
282
317
|
remainingRefundable: number;
|
|
@@ -286,9 +321,66 @@ export declare const refundOrderCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
|
286
321
|
error?: undefined;
|
|
287
322
|
} | {
|
|
288
323
|
success: false;
|
|
289
|
-
code: "order_not_found" | "order_not_paid" | "no_provider_ref" | "unknown_provider" | "refund_unsupported" | "invalid_amount" | "amount_exceeds_remaining" | "provider_error";
|
|
324
|
+
code: "order_not_found" | "order_not_paid" | "no_provider_ref" | "unknown_provider" | "refund_unsupported" | "invalid_amount" | "amount_exceeds_remaining" | "provider_error" | "no_payment_kind";
|
|
290
325
|
error: string;
|
|
291
326
|
}>>;
|
|
327
|
+
export declare const getOrderInvoiceAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
|
|
328
|
+
invoice: {
|
|
329
|
+
number: string | null;
|
|
330
|
+
raw: unknown;
|
|
331
|
+
id: string;
|
|
332
|
+
status: import("../../db-postgres/schema/shop/index.js").ShopInvoiceStatus;
|
|
333
|
+
createdAt: Date;
|
|
334
|
+
updatedAt: Date;
|
|
335
|
+
orderId: string;
|
|
336
|
+
provider: string;
|
|
337
|
+
kind: string;
|
|
338
|
+
externalId: string | null;
|
|
339
|
+
pdfUrl: string | null;
|
|
340
|
+
attempts: number;
|
|
341
|
+
nextRetryAt: Date | null;
|
|
342
|
+
lastError: string | null;
|
|
343
|
+
} | null;
|
|
344
|
+
invoicingEnabled: boolean;
|
|
345
|
+
}>;
|
|
346
|
+
export declare const issueInvoiceCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
347
|
+
orderId: string;
|
|
348
|
+
force?: boolean | undefined;
|
|
349
|
+
}, Promise<{
|
|
350
|
+
success: true;
|
|
351
|
+
invoice: {
|
|
352
|
+
number: string | null;
|
|
353
|
+
raw: unknown;
|
|
354
|
+
id: string;
|
|
355
|
+
status: import("../../db-postgres/schema/shop/index.js").ShopInvoiceStatus;
|
|
356
|
+
createdAt: Date;
|
|
357
|
+
updatedAt: Date;
|
|
358
|
+
orderId: string;
|
|
359
|
+
provider: string;
|
|
360
|
+
kind: string;
|
|
361
|
+
externalId: string | null;
|
|
362
|
+
pdfUrl: string | null;
|
|
363
|
+
attempts: number;
|
|
364
|
+
nextRetryAt: Date | null;
|
|
365
|
+
lastError: string | null;
|
|
366
|
+
} | null;
|
|
367
|
+
error?: undefined;
|
|
368
|
+
} | {
|
|
369
|
+
success: false;
|
|
370
|
+
error: string;
|
|
371
|
+
invoice?: undefined;
|
|
372
|
+
}>>;
|
|
373
|
+
export declare const generateBalanceLinkForOrder: import("@sveltejs/kit").RemoteCommand<string, Promise<{
|
|
374
|
+
success: false;
|
|
375
|
+
error: string;
|
|
376
|
+
url?: undefined;
|
|
377
|
+
balanceAmount?: undefined;
|
|
378
|
+
} | {
|
|
379
|
+
success: true;
|
|
380
|
+
url: string;
|
|
381
|
+
balanceAmount: number;
|
|
382
|
+
error?: undefined;
|
|
383
|
+
}>>;
|
|
292
384
|
export declare const listCouponsAdmin: import("@sveltejs/kit").RemoteQueryFunction<void, {
|
|
293
385
|
id: string;
|
|
294
386
|
code: string;
|
|
@@ -317,7 +409,7 @@ export declare const getCouponAdmin: import("@sveltejs/kit").RemoteQueryFunction
|
|
|
317
409
|
}>;
|
|
318
410
|
export declare const createCouponCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
319
411
|
code: string;
|
|
320
|
-
type: "
|
|
412
|
+
type: "percent" | "fixed";
|
|
321
413
|
value: number;
|
|
322
414
|
minOrderAmount?: number | null | undefined;
|
|
323
415
|
maxUses?: number | null | undefined;
|
|
@@ -340,7 +432,7 @@ export declare const updateCouponCmd: import("@sveltejs/kit").RemoteCommand<{
|
|
|
340
432
|
id: string;
|
|
341
433
|
input: {
|
|
342
434
|
code?: string | undefined;
|
|
343
|
-
type?: "
|
|
435
|
+
type?: "percent" | "fixed" | undefined;
|
|
344
436
|
value?: number | undefined;
|
|
345
437
|
minOrderAmount?: number | null | undefined;
|
|
346
438
|
maxUses?: number | null | undefined;
|
|
@@ -6,6 +6,7 @@ import { createShippingMethod, deleteShippingMethod, getShippingMethod, listShip
|
|
|
6
6
|
import { countOrders, getOrderById, getOrderItems, getOrderStatusHistory, listOrders, updateOrderStatus } from '../../shop/server/orders.js';
|
|
7
7
|
import { cancelShipmentForOrder, createShipmentForOrder } from '../../shop/server/shipments.js';
|
|
8
8
|
import { sendOrderStatusEmail } from '../../shop/server/email.js';
|
|
9
|
+
import { getInvoiceByOrderId, issueInvoiceForOrder } from '../../shop/server/invoices.js';
|
|
9
10
|
import { getRefundedAmount, listRefunds, refundOrder, RefundError } from '../../shop/server/refund.js';
|
|
10
11
|
import { getShopDb } from '../../shop/server/db.js';
|
|
11
12
|
import { shopCouponsTable } from '../../db-postgres/schema/shop/index.js';
|
|
@@ -24,7 +25,10 @@ export const getShopConfig = query(async () => {
|
|
|
24
25
|
vatRates: shop.vatRates,
|
|
25
26
|
features: shop.features,
|
|
26
27
|
languages: getCMS().languages,
|
|
27
|
-
paymentMethods: shop.payment.map((p) => ({ id: p.id, label: p.label }))
|
|
28
|
+
paymentMethods: shop.payment.map((p) => ({ id: p.id, label: p.label })),
|
|
29
|
+
variantAttributes: shop.variantAttributes,
|
|
30
|
+
variantLabel: shop.variantLabel,
|
|
31
|
+
variantExpiry: shop.variantExpiry
|
|
28
32
|
};
|
|
29
33
|
});
|
|
30
34
|
export const listShopProductEntries = query(async () => {
|
|
@@ -35,11 +39,20 @@ export const getShopDataForEntry = query(z.string(), async (entryId) => {
|
|
|
35
39
|
requireAuth();
|
|
36
40
|
return getShopDataByEntry(entryId);
|
|
37
41
|
});
|
|
42
|
+
const depositAmountSchema = z.discriminatedUnion('type', [
|
|
43
|
+
z.object({ type: z.literal('percent'), value: z.number().positive().max(100) }),
|
|
44
|
+
z.object({ type: z.literal('amount'), value: z.number().int().positive() })
|
|
45
|
+
]);
|
|
46
|
+
const paymentPolicySchema = z.discriminatedUnion('type', [
|
|
47
|
+
z.object({ type: z.literal('full') }),
|
|
48
|
+
z.object({ type: z.literal('deposit'), depositAmount: depositAmountSchema })
|
|
49
|
+
]);
|
|
38
50
|
const shopDataInputSchema = z.object({
|
|
39
51
|
basePrice: z.number().nonnegative().max(1e9), // PLN (≤6dp)
|
|
40
52
|
vatRate: z.number().int().min(0).max(100),
|
|
41
53
|
isActive: z.boolean().optional(),
|
|
42
|
-
sortOrder: z.number().int().nullable().optional()
|
|
54
|
+
sortOrder: z.number().int().nullable().optional(),
|
|
55
|
+
paymentPolicy: paymentPolicySchema.nullable().optional()
|
|
43
56
|
});
|
|
44
57
|
const variantInputSchema = z.object({
|
|
45
58
|
id: z.string().optional(),
|
|
@@ -47,7 +60,9 @@ const variantInputSchema = z.object({
|
|
|
47
60
|
name: z.record(z.string(), z.string()).nullable().optional(),
|
|
48
61
|
priceDelta: z.number().optional(), // PLN
|
|
49
62
|
stock: z.number().int().nullable().optional(),
|
|
50
|
-
|
|
63
|
+
// unknown — variantAttributes can be string|number|boolean|datetime;
|
|
64
|
+
// validateVariantAttributes (server) enforces the typed shape from shop config.
|
|
65
|
+
attributes: z.record(z.string(), z.unknown()).nullable().optional()
|
|
51
66
|
});
|
|
52
67
|
export const upsertShopDataForEntry = command(z.object({
|
|
53
68
|
entryId: z.string(),
|
|
@@ -223,11 +238,20 @@ export const getOrderRefundsAdmin = query(z.string(), async (orderId) => {
|
|
|
223
238
|
export const refundOrderCmd = command(z.object({
|
|
224
239
|
orderId: z.string(),
|
|
225
240
|
amount: z.number().int().positive().optional(),
|
|
226
|
-
reason: z.string().max(500).optional()
|
|
227
|
-
|
|
241
|
+
reason: z.string().max(500).optional(),
|
|
242
|
+
kind: z.enum(['full', 'deposit', 'balance']).optional(),
|
|
243
|
+
releaseStock: z.boolean().optional()
|
|
244
|
+
}), async ({ orderId, amount, reason, kind, releaseStock }) => {
|
|
228
245
|
requireAuth();
|
|
229
246
|
try {
|
|
230
|
-
const result = await refundOrder({
|
|
247
|
+
const result = await refundOrder({
|
|
248
|
+
orderId,
|
|
249
|
+
amount,
|
|
250
|
+
reason,
|
|
251
|
+
kind,
|
|
252
|
+
releaseStock,
|
|
253
|
+
createdBy: 'admin'
|
|
254
|
+
});
|
|
231
255
|
return { success: true, ...result };
|
|
232
256
|
}
|
|
233
257
|
catch (err) {
|
|
@@ -238,6 +262,55 @@ export const refundOrderCmd = command(z.object({
|
|
|
238
262
|
return { success: false, code: 'provider_error', error: message };
|
|
239
263
|
}
|
|
240
264
|
});
|
|
265
|
+
export const getOrderInvoiceAdmin = query(z.string(), async (orderId) => {
|
|
266
|
+
requireAuth();
|
|
267
|
+
const invoice = await getInvoiceByOrderId(orderId);
|
|
268
|
+
const invoicingEnabled = !!getCMS().shopConfig?.invoicing;
|
|
269
|
+
return { invoice, invoicingEnabled };
|
|
270
|
+
});
|
|
271
|
+
export const issueInvoiceCmd = command(z.object({ orderId: z.string(), force: z.boolean().optional() }), async ({ orderId, force }) => {
|
|
272
|
+
requireAuth();
|
|
273
|
+
try {
|
|
274
|
+
const invoice = await issueInvoiceForOrder(orderId, { force });
|
|
275
|
+
return { success: true, invoice };
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
const message = err instanceof Error ? err.message : 'Invoice issuance failed';
|
|
279
|
+
return { success: false, error: message };
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
export const generateBalanceLinkForOrder = command(z.string(), async (orderId) => {
|
|
283
|
+
requireAuth();
|
|
284
|
+
const { generateBalanceToken, requireBalanceTokenSecret } = await import('../../shop/server/balance-payment.js');
|
|
285
|
+
const { getOrderById } = await import('../../shop/server/orders.js');
|
|
286
|
+
const order = await getOrderById(orderId);
|
|
287
|
+
if (!order)
|
|
288
|
+
return { success: false, error: 'Order not found' };
|
|
289
|
+
if (!order.balanceOwed) {
|
|
290
|
+
return { success: false, error: 'Order has no outstanding balance' };
|
|
291
|
+
}
|
|
292
|
+
let secret;
|
|
293
|
+
try {
|
|
294
|
+
secret = requireBalanceTokenSecret();
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
const message = err instanceof Error ? err.message : 'Token secret not configured';
|
|
298
|
+
return { success: false, error: message };
|
|
299
|
+
}
|
|
300
|
+
const token = generateBalanceToken(order.id, secret);
|
|
301
|
+
// Mirror orderViewUrl template — build the customer-facing URL by
|
|
302
|
+
// extending the configured base with the balance path + token.
|
|
303
|
+
const cms = (await import('../../core/cms.js')).getCMS();
|
|
304
|
+
const orderViewUrl = cms.shopConfig?.orderViewUrl ?? '/shop/order/{orderNumber}?token={accessToken}';
|
|
305
|
+
const base = orderViewUrl
|
|
306
|
+
.replace('{orderNumber}', encodeURIComponent(order.number))
|
|
307
|
+
.replace('{orderId}', encodeURIComponent(order.id))
|
|
308
|
+
.replace('{accessToken}', encodeURIComponent(order.accessToken))
|
|
309
|
+
.replace('{language}', encodeURIComponent(order.language ?? ''));
|
|
310
|
+
const sep = base.includes('?') ? '&' : '?';
|
|
311
|
+
const url = `${base}${sep}balance=1&balanceToken=${encodeURIComponent(token)}`;
|
|
312
|
+
return { success: true, url, balanceAmount: order.partialPayment?.balanceAmount ?? 0 };
|
|
313
|
+
});
|
|
241
314
|
// Coupons ────────────────────────────────────────────────────────────────────
|
|
242
315
|
const couponInputSchema = z.object({
|
|
243
316
|
code: z.string().min(1).max(64),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IconSetPlugin } from '../../types/plugins.js';
|
|
2
|
+
export declare function setIconSets(sets: Map<string, IconSetPlugin>): void;
|
|
3
|
+
export declare function getIconSets(): Map<string, IconSetPlugin>;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a single icon set: explicit `slug` (from {@link IconField.set}) takes
|
|
6
|
+
* precedence; otherwise returns the first registered set (predictable order
|
|
7
|
+
* matches Map insertion). Returns `null` when none are registered.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveIconSet(slug?: string): IconSetPlugin | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const contextKey = Symbol('iconSets');
|
|
3
|
+
export function setIconSets(sets) {
|
|
4
|
+
setContext(contextKey, sets);
|
|
5
|
+
}
|
|
6
|
+
export function getIconSets() {
|
|
7
|
+
return getContext(contextKey) ?? new Map();
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a single icon set: explicit `slug` (from {@link IconField.set}) takes
|
|
11
|
+
* precedence; otherwise returns the first registered set (predictable order
|
|
12
|
+
* matches Map insertion). Returns `null` when none are registered.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveIconSet(slug) {
|
|
15
|
+
const sets = getIconSets();
|
|
16
|
+
if (slug)
|
|
17
|
+
return sets.get(slug) ?? null;
|
|
18
|
+
const first = sets.values().next();
|
|
19
|
+
return first.done ? null : first.value;
|
|
20
|
+
}
|
|
@@ -329,7 +329,7 @@ export const { POST } = createRetryPaymentHandler();
|
|
|
329
329
|
{
|
|
330
330
|
path: 'admin/api/[...path]/+server.ts',
|
|
331
331
|
content: `${GENERATED_COMMENT_TS}
|
|
332
|
-
import { createAdminApiHandler } from 'includio-cms/
|
|
332
|
+
import { createAdminApiHandler } from 'includio-cms/sveltekit/server';
|
|
333
333
|
|
|
334
334
|
export const { GET, POST, PATCH, PUT, DELETE } = createAdminApiHandler();
|
|
335
335
|
`
|
|
@@ -337,7 +337,7 @@ export const { GET, POST, PATCH, PUT, DELETE } = createAdminApiHandler();
|
|
|
337
337
|
{
|
|
338
338
|
path: 'admin/api/rest/[...restPath]/+server.ts',
|
|
339
339
|
content: `${GENERATED_COMMENT_TS}
|
|
340
|
-
import { createRestApiHandler } from 'includio-cms/
|
|
340
|
+
import { createRestApiHandler } from 'includio-cms/sveltekit/server';
|
|
341
341
|
|
|
342
342
|
export const { GET, POST, PUT, DELETE } = createRestApiHandler();
|
|
343
343
|
`
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
bind:ref
|
|
18
18
|
data-slot="checkbox"
|
|
19
19
|
class={cn(
|
|
20
|
-
"border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shadow-xs peer flex size-
|
|
20
|
+
"border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shadow-xs peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border outline-none transition-shadow focus-visible:ring-[3px] after:absolute after:-inset-1 after:content-[''] disabled:cursor-not-allowed disabled:opacity-50",
|
|
21
21
|
className
|
|
22
22
|
)}
|
|
23
23
|
bind:checked
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
{#snippet children({ checked, indeterminate })}
|
|
28
28
|
<div data-slot="checkbox-indicator" class="text-current transition-none">
|
|
29
29
|
{#if checked}
|
|
30
|
-
<CheckIcon class="size-
|
|
30
|
+
<CheckIcon class="size-3.5" />
|
|
31
31
|
{:else if indeterminate}
|
|
32
|
-
<MinusIcon class="size-
|
|
32
|
+
<MinusIcon class="size-3.5" />
|
|
33
33
|
{/if}
|
|
34
34
|
</div>
|
|
35
35
|
{/snippet}
|
package/dist/core/cms.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { ApiKeyConfig, AuthConfig, CMSConfig, ICMS, MediaConfig, Typography
|
|
|
4
4
|
import type { CollectionConfigWithType } from '../types/collections.js';
|
|
5
5
|
import type { Language } from '../types/languages.js';
|
|
6
6
|
import type { SingleConfigWithType } from '../types/singles.js';
|
|
7
|
-
import type { CustomFieldDefinition,
|
|
7
|
+
import type { CustomFieldDefinition, IconSetPlugin, Plugin } from '../types/plugins.js';
|
|
8
8
|
import type { FormConfig } from '../types/forms.js';
|
|
9
9
|
import type { AIAdapter } from '../types/adapters/ai.js';
|
|
10
10
|
import type { EmailAdapter } from '../types/adapters/email.js';
|
|
@@ -28,8 +28,17 @@ export declare class CMS implements ICMS {
|
|
|
28
28
|
sidebarHelp: boolean;
|
|
29
29
|
shopConfig: ResolvedShopConfig | null;
|
|
30
30
|
cmpConfig: ResolvedCmpConfig | null;
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Resolves once the shop's variant-attribute GIN indexes have been applied
|
|
33
|
+
* by `initCMS()`. `null` when the CMS is configured without a shop. Tests
|
|
34
|
+
* can `await` this to gate on init completion; production callers don't
|
|
35
|
+
* need to — index application is idempotent and non-blocking.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
shopInitPromise: Promise<void> | null;
|
|
39
|
+
plugins: Plugin[];
|
|
32
40
|
customFields: Map<string, CustomFieldDefinition>;
|
|
41
|
+
iconSets: Map<string, IconSetPlugin>;
|
|
33
42
|
apiKeys: ApiKeyConfig[];
|
|
34
43
|
constructor(config: CMSConfig);
|
|
35
44
|
private validateFieldSlugs;
|
package/dist/core/cms.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { isIconSetPlugin } from '../types/plugins.js';
|
|
1
2
|
import { setSchemaGetCMS } from './fields/fieldSchemaToTs.js';
|
|
2
3
|
import { betterAuth } from 'better-auth';
|
|
3
4
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
|
|
4
5
|
import { admin } from 'better-auth/plugins';
|
|
5
6
|
import { resetPasswordEmailTemplate } from '../admin/email/reset-password-template.js';
|
|
6
7
|
import * as authSchema from '../server/db/schema/auth-schema.js';
|
|
8
|
+
import { applyVariantAttributeIndexes } from '../shop/server/init.js';
|
|
7
9
|
export class CMS {
|
|
8
10
|
config;
|
|
9
11
|
databaseAdapter;
|
|
@@ -21,8 +23,17 @@ export class CMS {
|
|
|
21
23
|
sidebarHelp;
|
|
22
24
|
shopConfig;
|
|
23
25
|
cmpConfig;
|
|
26
|
+
/**
|
|
27
|
+
* Resolves once the shop's variant-attribute GIN indexes have been applied
|
|
28
|
+
* by `initCMS()`. `null` when the CMS is configured without a shop. Tests
|
|
29
|
+
* can `await` this to gate on init completion; production callers don't
|
|
30
|
+
* need to — index application is idempotent and non-blocking.
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
shopInitPromise = null;
|
|
24
34
|
plugins = [];
|
|
25
35
|
customFields = new Map();
|
|
36
|
+
iconSets = new Map();
|
|
26
37
|
apiKeys = [];
|
|
27
38
|
constructor(config) {
|
|
28
39
|
this.config = config;
|
|
@@ -64,6 +75,13 @@ export class CMS {
|
|
|
64
75
|
if (config.plugins) {
|
|
65
76
|
this.plugins = config.plugins;
|
|
66
77
|
for (const plugin of this.plugins) {
|
|
78
|
+
if (isIconSetPlugin(plugin)) {
|
|
79
|
+
if (this.iconSets.has(plugin.slug)) {
|
|
80
|
+
throw new Error(`Duplicate icon-set plugin slug: "${plugin.slug}"`);
|
|
81
|
+
}
|
|
82
|
+
this.iconSets.set(plugin.slug, plugin);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
67
85
|
for (const def of plugin.fields ?? []) {
|
|
68
86
|
if (this.customFields.has(def.fieldType)) {
|
|
69
87
|
throw new Error(`Duplicate custom field type: "${def.fieldType}" (plugin: "${plugin.slug}")`);
|
|
@@ -157,6 +175,17 @@ export function initCMS(config) {
|
|
|
157
175
|
import('./server/media/operations/backgroundMaintenance.js')
|
|
158
176
|
.then((m) => m.startBackgroundMaintenance())
|
|
159
177
|
.catch((e) => console.warn('[cms] Failed to start background maintenance:', e));
|
|
178
|
+
// Apply shop variantAttribute GIN indexes (idempotent CREATE INDEX IF NOT EXISTS).
|
|
179
|
+
// Pass shop + drizzle explicitly so the dynamic import doesn't depend on a
|
|
180
|
+
// shared CMS singleton (vitest can give the dynamic module a fresh instance).
|
|
181
|
+
if (cms.shopConfig) {
|
|
182
|
+
const drizzle = cms.databaseAdapter._drizzle;
|
|
183
|
+
if (drizzle) {
|
|
184
|
+
cms.shopInitPromise = applyVariantAttributeIndexes(cms.shopConfig, drizzle).catch((e) => {
|
|
185
|
+
console.warn('[shop] Failed to apply variant attribute indexes:', e);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
160
189
|
return cms;
|
|
161
190
|
}
|
|
162
191
|
/**
|
|
@@ -444,6 +444,13 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
444
444
|
localizedDefault.text = emptyLangMap;
|
|
445
445
|
return localizedSchema.optional().default(localizedDefault);
|
|
446
446
|
}
|
|
447
|
+
case 'icon': {
|
|
448
|
+
// Value is a plain string key referencing an icon registered by an
|
|
449
|
+
// IconSetPlugin. Validation matches `slug` field semantics.
|
|
450
|
+
if (field.required)
|
|
451
|
+
return z.string().min(1, { message: msg.required });
|
|
452
|
+
return z.string().optional().default('');
|
|
453
|
+
}
|
|
447
454
|
case 'custom': {
|
|
448
455
|
const customDef = getCustomFieldDef(field.fieldType);
|
|
449
456
|
if (!customDef)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Field } from '../../../types/fields.js';
|
|
2
2
|
import type { CustomFieldDefinition } from '../../../types/plugins.js';
|
|
3
|
+
import type { VariantAttribute } from '../../../shop/types.js';
|
|
3
4
|
export declare function setGeneratorCustomFields(customFields: Map<string, CustomFieldDefinition>): void;
|
|
5
|
+
export declare function setGeneratorShopVariantAttributes(attrs: Record<string, VariantAttribute>): void;
|
|
4
6
|
export declare function generateTsTypeFromFields(fields: Field[]): string;
|
|
5
7
|
export declare function generateFlatTsTypeFromFields(fields: Field[]): string;
|
|
6
8
|
export interface InlineBlockTypeDef {
|
|
@@ -1,12 +1,44 @@
|
|
|
1
1
|
import { toPascalCase, quoteKey } from './utils.js';
|
|
2
2
|
import { buildSeoTsType } from '../../fields/seoFieldDescriptor.js';
|
|
3
3
|
let _customFields = new Map();
|
|
4
|
+
let _shopVariantAttributes = {};
|
|
4
5
|
function isGuaranteed(f) {
|
|
5
6
|
return !!(f.required || f.type === 'seo' || f.defaultValue !== undefined);
|
|
6
7
|
}
|
|
7
8
|
export function setGeneratorCustomFields(customFields) {
|
|
8
9
|
_customFields = customFields;
|
|
9
10
|
}
|
|
11
|
+
export function setGeneratorShopVariantAttributes(attrs) {
|
|
12
|
+
_shopVariantAttributes = attrs;
|
|
13
|
+
}
|
|
14
|
+
function variantAttributeTsType(attr) {
|
|
15
|
+
switch (attr.type) {
|
|
16
|
+
case 'text':
|
|
17
|
+
case 'datetime':
|
|
18
|
+
case 'image':
|
|
19
|
+
case 'entry':
|
|
20
|
+
case 'slug':
|
|
21
|
+
return 'string';
|
|
22
|
+
case 'number':
|
|
23
|
+
return 'number';
|
|
24
|
+
case 'boolean':
|
|
25
|
+
return 'boolean';
|
|
26
|
+
case 'select':
|
|
27
|
+
return attr.options.map((o) => `'${o.value}'`).join(' | ');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function buildShopAttributesType() {
|
|
31
|
+
const entries = Object.entries(_shopVariantAttributes);
|
|
32
|
+
if (entries.length === 0)
|
|
33
|
+
return 'Record<string, string> | null';
|
|
34
|
+
const fields = entries
|
|
35
|
+
.map(([key, attr]) => {
|
|
36
|
+
const opt = attr.required ? '' : '?';
|
|
37
|
+
return `${quoteKey(key)}${opt}: ${variantAttributeTsType(attr)}`;
|
|
38
|
+
})
|
|
39
|
+
.join('; ');
|
|
40
|
+
return `{ ${fields} }`;
|
|
41
|
+
}
|
|
10
42
|
function getFieldTypeAsString(field) {
|
|
11
43
|
switch (field.type) {
|
|
12
44
|
case 'text':
|
|
@@ -68,6 +100,7 @@ function getFieldTypeAsString(field) {
|
|
|
68
100
|
return 'UrlFieldData[]';
|
|
69
101
|
}
|
|
70
102
|
case 'slug':
|
|
103
|
+
case 'icon':
|
|
71
104
|
return 'string';
|
|
72
105
|
case 'seo':
|
|
73
106
|
return buildSeoTsType();
|
|
@@ -82,7 +115,7 @@ function getFieldTypeAsString(field) {
|
|
|
82
115
|
name: Record<string, string> | null;
|
|
83
116
|
priceDelta: number;
|
|
84
117
|
stock: number | null;
|
|
85
|
-
attributes:
|
|
118
|
+
attributes: ${buildShopAttributesType()};
|
|
86
119
|
}>;
|
|
87
120
|
} | null`;
|
|
88
121
|
case 'url': {
|