includio-cms 0.28.0 → 0.34.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.
Files changed (117) hide show
  1. package/API.md +39 -13
  2. package/CHANGELOG.md +19 -0
  3. package/DOCS.md +1 -1
  4. package/ROADMAP.md +1 -0
  5. package/dist/admin/api/handler.js +4 -0
  6. package/dist/admin/api/integrations.d.ts +13 -0
  7. package/dist/admin/api/integrations.js +61 -0
  8. package/dist/admin/api/test-email.d.ts +9 -0
  9. package/dist/admin/api/test-email.js +39 -0
  10. package/dist/admin/auth-client.d.ts +2209 -2209
  11. package/dist/admin/client/index.d.ts +10 -0
  12. package/dist/admin/client/index.js +12 -0
  13. package/dist/admin/client/maintenance/maintenance-page.svelte +210 -0
  14. package/dist/admin/client/shop/coupon-schema.d.ts +1 -1
  15. package/dist/admin/client/shop/restore-order-cell.svelte +29 -0
  16. package/dist/admin/client/shop/restore-order-cell.svelte.d.ts +8 -0
  17. package/dist/admin/client/shop/shop-order-detail-page.svelte +71 -1
  18. package/dist/admin/client/shop/shop-orders-list-page.svelte +113 -53
  19. package/dist/admin/components/layout/app-sidebar.svelte +2 -0
  20. package/dist/admin/components/layout/nav-custom.svelte +26 -0
  21. package/dist/admin/components/layout/nav-custom.svelte.d.ts +3 -0
  22. package/dist/admin/components/layout/page-header.svelte +13 -3
  23. package/dist/admin/components/layout/page-header.svelte.d.ts +13 -3
  24. package/dist/admin/remote/admin.remote.d.ts +7 -0
  25. package/dist/admin/remote/admin.remote.js +10 -0
  26. package/dist/admin/remote/entry.remote.d.ts +4 -4
  27. package/dist/admin/remote/index.d.ts +1 -0
  28. package/dist/admin/remote/index.js +1 -0
  29. package/dist/admin/remote/invite.d.ts +2 -2
  30. package/dist/admin/remote/shop.remote.d.ts +75 -48
  31. package/dist/admin/remote/shop.remote.js +41 -10
  32. package/dist/admin/types.d.ts +15 -0
  33. package/dist/admin/utils/csv-export.d.ts +45 -0
  34. package/dist/admin/utils/csv-export.js +61 -0
  35. package/dist/cli/scaffold/admin.js +1 -1
  36. package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
  37. package/dist/components/ui/command/command.svelte.d.ts +1 -1
  38. package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
  39. package/dist/components/ui/input/input.svelte.d.ts +1 -1
  40. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  41. package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
  42. package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
  43. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  44. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
  45. package/dist/core/cms.d.ts +44 -2
  46. package/dist/core/cms.js +64 -0
  47. package/dist/core/index.d.ts +1 -4
  48. package/dist/core/index.js +4 -4
  49. package/dist/core/server/index.d.ts +4 -1
  50. package/dist/core/server/index.js +4 -1
  51. package/dist/db-postgres/schema/shop/order.d.ts +34 -0
  52. package/dist/db-postgres/schema/shop/order.js +4 -0
  53. package/dist/paraglide/messages/_index.d.ts +3 -36
  54. package/dist/paraglide/messages/_index.js +3 -71
  55. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  56. package/dist/paraglide/messages/hello_world.js +33 -0
  57. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  58. package/dist/paraglide/messages/login_hello.js +34 -0
  59. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  60. package/dist/paraglide/messages/login_please_login.js +34 -0
  61. package/dist/shop/adapters/fakturownia/client.d.ts +5 -0
  62. package/dist/shop/adapters/fakturownia/client.js +20 -0
  63. package/dist/shop/adapters/fakturownia/index.js +11 -0
  64. package/dist/shop/adapters/payu/index.js +11 -0
  65. package/dist/shop/index.d.ts +1 -1
  66. package/dist/shop/server/coupons.d.ts +10 -0
  67. package/dist/shop/server/coupons.js +19 -0
  68. package/dist/shop/server/email.d.ts +7 -3
  69. package/dist/shop/server/email.js +86 -112
  70. package/dist/shop/server/emailTemplateRegistry.d.ts +47 -0
  71. package/dist/shop/server/emailTemplateRegistry.js +288 -0
  72. package/dist/shop/server/orders.d.ts +60 -1
  73. package/dist/shop/server/orders.js +145 -16
  74. package/dist/shop/templates/_partials/footer.en.html +4 -0
  75. package/dist/shop/templates/_partials/footer.pl.html +4 -0
  76. package/dist/shop/templates/_partials/header.en.html +4 -0
  77. package/dist/shop/templates/_partials/header.pl.html +4 -0
  78. package/dist/shop/templates/_partials/items.en.html +14 -0
  79. package/dist/shop/templates/_partials/items.pl.html +14 -0
  80. package/dist/shop/templates/_partials/tracking.en.html +7 -0
  81. package/dist/shop/templates/_partials/tracking.pl.html +7 -0
  82. package/dist/shop/templates/awaiting-payment.en.html +6 -0
  83. package/dist/shop/templates/awaiting-payment.pl.html +6 -0
  84. package/dist/shop/templates/cancelled.en.html +6 -0
  85. package/dist/shop/templates/cancelled.pl.html +6 -0
  86. package/dist/shop/templates/low-stock.en.html +14 -0
  87. package/dist/shop/templates/low-stock.pl.html +14 -0
  88. package/dist/shop/templates/order-completed.en.html +6 -0
  89. package/dist/shop/templates/order-completed.pl.html +6 -0
  90. package/dist/shop/templates/order-received.en.html +7 -0
  91. package/dist/shop/templates/order-received.pl.html +7 -0
  92. package/dist/shop/templates/payment-received.en.html +7 -0
  93. package/dist/shop/templates/payment-received.pl.html +7 -0
  94. package/dist/shop/templates/payment-rejected.en.html +6 -0
  95. package/dist/shop/templates/payment-rejected.pl.html +6 -0
  96. package/dist/shop/templates/preparing.en.html +7 -0
  97. package/dist/shop/templates/preparing.pl.html +7 -0
  98. package/dist/shop/templates/refunded.en.html +6 -0
  99. package/dist/shop/templates/refunded.pl.html +6 -0
  100. package/dist/shop/templates/shipped.en.html +7 -0
  101. package/dist/shop/templates/shipped.pl.html +7 -0
  102. package/dist/shop/types.d.ts +63 -0
  103. package/dist/sveltekit/index.d.ts +0 -1
  104. package/dist/sveltekit/index.js +0 -1
  105. package/dist/sveltekit/server/index.d.ts +2 -0
  106. package/dist/sveltekit/server/index.js +4 -0
  107. package/dist/types/adapters/email.d.ts +13 -0
  108. package/dist/types/cms.d.ts +30 -0
  109. package/dist/types/index.d.ts +1 -1
  110. package/dist/updates/0.34.0/index.d.ts +2 -0
  111. package/dist/updates/0.34.0/index.js +17 -0
  112. package/dist/updates/index.js +3 -1
  113. package/package.json +7 -2
  114. package/dist/paraglide/messages/en.d.ts +0 -5
  115. package/dist/paraglide/messages/en.js +0 -14
  116. package/dist/paraglide/messages/pl.d.ts +0 -5
  117. package/dist/paraglide/messages/pl.js +0 -14
package/dist/core/cms.js CHANGED
@@ -23,6 +23,7 @@ export class CMS {
23
23
  sidebarHelp;
24
24
  shopConfig;
25
25
  cmpConfig;
26
+ adminConfig;
26
27
  /**
27
28
  * Resolves once the shop's variant-attribute GIN indexes have been applied
28
29
  * by `initCMS()`. `null` when the CMS is configured without a shop. Tests
@@ -47,6 +48,7 @@ export class CMS {
47
48
  this.sidebarHelp = config.sidebarHelp ?? true;
48
49
  this.shopConfig = config.shop ?? null;
49
50
  this.cmpConfig = config.cmp ?? null;
51
+ this.adminConfig = config.admin ?? null;
50
52
  this.collections = {};
51
53
  this.singles = {};
52
54
  this.forms = {};
@@ -134,6 +136,7 @@ export class CMS {
134
136
  database: drizzleAdapter(drizzleDb, { provider: 'pg', schema: authSchema }),
135
137
  secret: this.authConfig.secret,
136
138
  baseURL: this.authConfig.baseURL,
139
+ ...(this.authConfig.rateLimit ? { rateLimit: this.authConfig.rateLimit } : {}),
137
140
  emailAndPassword: {
138
141
  enabled: true,
139
142
  async sendResetPassword({ user, url }, request) {
@@ -185,6 +188,18 @@ export function initCMS(config) {
185
188
  console.warn('[shop] Failed to apply variant attribute indexes:', e);
186
189
  });
187
190
  }
191
+ // Smoke-test built-in shop email templates — fast lookup-only sweep.
192
+ // Catches corrupt installs (missing files in dist) at boot instead of
193
+ // at first email send. Dynamic import avoids loading shop server code
194
+ // when there is no shop configured.
195
+ import('../shop/server/email.js')
196
+ .then(({ REQUIRED_TEMPLATE_NAMES }) => import('../shop/server/emailTemplateRegistry.js').then(({ validateBuiltinTemplates }) => {
197
+ const defaultLang = cms.languages[0] ?? 'pl';
198
+ validateBuiltinTemplates([...REQUIRED_TEMPLATE_NAMES], defaultLang);
199
+ }))
200
+ .catch((e) => {
201
+ console.error('[shop] Built-in email template validation failed:', e);
202
+ });
188
203
  }
189
204
  return cms;
190
205
  }
@@ -210,3 +225,52 @@ export function getCMS() {
210
225
  }
211
226
  return cms;
212
227
  }
228
+ /**
229
+ * Returns the configured email adapter from the active CMS singleton, or
230
+ * `null` when no `email` was passed to `defineConfig`. Use this in userland
231
+ * hooks (e.g. `ShopConfig.onOrderPaid`) to reuse the same SMTP transport the
232
+ * CMS already opened — no second nodemailer instance, no duplicated ENV.
233
+ *
234
+ * @returns The current `EmailAdapter` or `null`.
235
+ * @throws {Error} when called before `initCMS()` has run.
236
+ * @public
237
+ * @example
238
+ * ```ts
239
+ * import { getMailer } from 'includio-cms/core';
240
+ *
241
+ * const mailer = getMailer();
242
+ * if (mailer) await mailer.sendMail({ to: 'admin@…', subject: '…', html: '…' });
243
+ * ```
244
+ */
245
+ export function getMailer() {
246
+ return getCMS().emailAdapter;
247
+ }
248
+ /**
249
+ * Send an email through the configured CMS email adapter. Thin convenience
250
+ * wrapper around `getCMS().emailAdapter.sendMail` — same options shape, same
251
+ * From address, same SMTP transport as the built-in flows (reset password,
252
+ * shop order status, form notifications).
253
+ *
254
+ * @throws {Error} when no email adapter is configured (matches
255
+ * `defineConfig({ email: ... })` not being set) or when the CMS has not
256
+ * been initialized yet.
257
+ * @public
258
+ * @example
259
+ * ```ts
260
+ * import { sendMail } from 'includio-cms/core';
261
+ *
262
+ * await sendMail({
263
+ * to: process.env.ADMIN_EMAIL!,
264
+ * subject: '[shop] New consent',
265
+ * text: 'Plain fallback for clients that prefer text.',
266
+ * html: '<p>Body…</p>'
267
+ * });
268
+ * ```
269
+ */
270
+ export async function sendMail(options) {
271
+ const mailer = getCMS().emailAdapter;
272
+ if (!mailer) {
273
+ throw new Error('[includio-cms] sendMail() called but no `email` adapter is configured in defineConfig.');
274
+ }
275
+ await mailer.sendMail(options);
276
+ }
@@ -1,5 +1,2 @@
1
- export { getCMS } from './cms.js';
2
- export { resolveMediaWithStyles, type ResolvedMedia } from './server/fields/utils/resolveMedia.js';
3
1
  export { resolveSeo, type ResolvedSeo } from './fields/resolveSeo.js';
4
- export { createEntityAPI } from '../entity/index.js';
5
- export { getAuth } from '../server/auth.js';
2
+ export type { EmailAdapter, SendMailOptions } from '../types/adapters/email.js';
@@ -1,5 +1,5 @@
1
- export { getCMS } from './cms.js';
2
- export { resolveMediaWithStyles } from './server/fields/utils/resolveMedia.js';
1
+ // `resolveSeo` is client-safe (pure). `getMailer`/`sendMail` moved to the server
2
+ // entry (`includio-cms/sveltekit/server`) so importing SEO helpers in a
3
+ // browser/component bundle no longer pulls in `cms.js` and its server graph
4
+ // ($env/dynamic/private).
3
5
  export { resolveSeo } from './fields/resolveSeo.js';
4
- export { createEntityAPI } from '../entity/index.js';
5
- export { getAuth } from '../server/auth.js';
@@ -1 +1,4 @@
1
- export {};
1
+ export { getCMS } from '../cms.js';
2
+ export { resolveMediaWithStyles, type ResolvedMedia } from './fields/utils/resolveMedia.js';
3
+ export { createEntityAPI } from '../../entity/index.js';
4
+ export { getAuth } from '../../server/auth.js';
@@ -1 +1,4 @@
1
- "use strict";
1
+ export { getCMS } from '../cms.js';
2
+ export { resolveMediaWithStyles } from './fields/utils/resolveMedia.js';
3
+ export { createEntityAPI } from '../../entity/index.js';
4
+ export { getAuth } from '../../server/auth.js';
@@ -565,6 +565,40 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
565
565
  identity: undefined;
566
566
  generated: undefined;
567
567
  }, {}, {}>;
568
+ deletedAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
569
+ name: "deleted_at";
570
+ tableName: "shop_orders";
571
+ dataType: "date";
572
+ columnType: "PgTimestamp";
573
+ data: Date;
574
+ driverParam: string;
575
+ notNull: false;
576
+ hasDefault: false;
577
+ isPrimaryKey: false;
578
+ isAutoincrement: false;
579
+ hasRuntimeDefault: false;
580
+ enumValues: undefined;
581
+ baseColumn: never;
582
+ identity: undefined;
583
+ generated: undefined;
584
+ }, {}, {}>;
585
+ deletedBy: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
586
+ name: "deleted_by";
587
+ tableName: "shop_orders";
588
+ dataType: "string";
589
+ columnType: "PgText";
590
+ data: string;
591
+ driverParam: string;
592
+ notNull: false;
593
+ hasDefault: false;
594
+ isPrimaryKey: false;
595
+ isAutoincrement: false;
596
+ hasRuntimeDefault: false;
597
+ enumValues: [string, ...string[]];
598
+ baseColumn: never;
599
+ identity: undefined;
600
+ generated: undefined;
601
+ }, {}, {}>;
568
602
  createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
569
603
  name: "created_at";
570
604
  tableName: "shop_orders";
@@ -35,6 +35,10 @@ export const shopOrdersTable = pgTable('shop_orders', {
35
35
  accessToken: uuid('access_token').defaultRandom().notNull(),
36
36
  partialPayment: jsonb('partial_payment').$type(),
37
37
  balanceOwed: boolean('balance_owed').default(false).notNull(),
38
+ // Soft-delete: admin can hide an order from the admin list without losing
39
+ // the row (accounting/audit safety). NULL = visible. See softDeleteOrder.
40
+ deletedAt: timestamp('deleted_at', { withTimezone: true }),
41
+ deletedBy: text('deleted_by'),
38
42
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
39
43
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
40
44
  });
@@ -1,36 +1,3 @@
1
- export function hello_world(inputs: {
2
- name: NonNullable<unknown>;
3
- }, options?: {
4
- locale?: "en" | "pl";
5
- }): string;
6
- /**
7
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
8
- *
9
- * - Changing this function will be over-written by the next build.
10
- *
11
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
12
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
13
- *
14
- * @param {{}} inputs
15
- * @param {{ locale?: "en" | "pl" }} options
16
- * @returns {string}
17
- */
18
- declare function login_hello(inputs?: {}, options?: {
19
- locale?: "en" | "pl";
20
- }): string;
21
- /**
22
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
23
- *
24
- * - Changing this function will be over-written by the next build.
25
- *
26
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
27
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
28
- *
29
- * @param {{}} inputs
30
- * @param {{ locale?: "en" | "pl" }} options
31
- * @returns {string}
32
- */
33
- declare function login_please_login(inputs?: {}, options?: {
34
- locale?: "en" | "pl";
35
- }): string;
36
- export { login_hello as login.hello, login_please_login as login.please_login };
1
+ export * from "./hello_world.js";
2
+ export * from "./login_hello.js";
3
+ export * from "./login_please_login.js";
@@ -1,72 +1,4 @@
1
1
  /* eslint-disable */
2
- import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from "../runtime.js"
3
- import * as en from "./en.js"
4
- import * as pl from "./pl.js"
5
- /**
6
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
7
- *
8
- * - Changing this function will be over-written by the next build.
9
- *
10
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
11
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
12
- *
13
- * @param {{ name: NonNullable<unknown> }} inputs
14
- * @param {{ locale?: "en" | "pl" }} options
15
- * @returns {string}
16
- */
17
- /* @__NO_SIDE_EFFECTS__ */
18
- export const hello_world = (inputs, options = {}) => {
19
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
20
- return /** @type {any} */ (globalThis).__paraglide_ssr.hello_world(inputs)
21
- }
22
- const locale = options.locale ?? getLocale()
23
- trackMessageCall("hello_world", locale)
24
- if (locale === "en") return en.hello_world(inputs)
25
- return pl.hello_world(inputs)
26
- };
27
- /**
28
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
29
- *
30
- * - Changing this function will be over-written by the next build.
31
- *
32
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
33
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
34
- *
35
- * @param {{}} inputs
36
- * @param {{ locale?: "en" | "pl" }} options
37
- * @returns {string}
38
- */
39
- /* @__NO_SIDE_EFFECTS__ */
40
- const login_hello = (inputs = {}, options = {}) => {
41
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
42
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_hello(inputs)
43
- }
44
- const locale = options.locale ?? getLocale()
45
- trackMessageCall("login_hello", locale)
46
- if (locale === "en") return en.login_hello(inputs)
47
- return pl.login_hello(inputs)
48
- };
49
- export { login_hello as "login.hello" }
50
- /**
51
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
52
- *
53
- * - Changing this function will be over-written by the next build.
54
- *
55
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
56
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
57
- *
58
- * @param {{}} inputs
59
- * @param {{ locale?: "en" | "pl" }} options
60
- * @returns {string}
61
- */
62
- /* @__NO_SIDE_EFFECTS__ */
63
- const login_please_login = (inputs = {}, options = {}) => {
64
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
65
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_please_login(inputs)
66
- }
67
- const locale = options.locale ?? getLocale()
68
- trackMessageCall("login_please_login", locale)
69
- if (locale === "en") return en.login_please_login(inputs)
70
- return pl.login_please_login(inputs)
71
- };
72
- export { login_please_login as "login.please_login" }
2
+ export * from './hello_world.js'
3
+ export * from './login_hello.js'
4
+ export * from './login_please_login.js'
@@ -0,0 +1,5 @@
1
+ export function hello_world(inputs: {
2
+ name: NonNullable<unknown>;
3
+ }, options?: {
4
+ locale?: "en" | "pl";
5
+ }): string;
@@ -0,0 +1,33 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
5
+ return `Hello, ${i.name} from en!`
6
+ };
7
+
8
+ const pl_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
9
+ return `Hello, ${i.name} from pl!`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{ name: NonNullable<unknown> }} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ export const hello_world = (inputs, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.hello_world(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("hello_world", locale)
31
+ if (locale === "en") return en_hello_world(inputs)
32
+ return pl_hello_world(inputs)
33
+ };
@@ -0,0 +1,16 @@
1
+ export { login_hello as login.hello };
2
+ /**
3
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
+ *
5
+ * - Changing this function will be over-written by the next build.
6
+ *
7
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
+ *
10
+ * @param {{}} inputs
11
+ * @param {{ locale?: "en" | "pl" }} options
12
+ * @returns {string}
13
+ */
14
+ declare function login_hello(inputs?: {}, options?: {
15
+ locale?: "en" | "pl";
16
+ }): string;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_login_hello = /** @type {(inputs: {}) => string} */ () => {
5
+ return `Welcome back`
6
+ };
7
+
8
+ const pl_login_hello = /** @type {(inputs: {}) => string} */ () => {
9
+ return `Witaj ponownie`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{}} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ const login_hello = (inputs = {}, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.login_hello(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("login_hello", locale)
31
+ if (locale === "en") return en_login_hello(inputs)
32
+ return pl_login_hello(inputs)
33
+ };
34
+ export { login_hello as "login.hello" }
@@ -0,0 +1,16 @@
1
+ export { login_please_login as login.please_login };
2
+ /**
3
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
+ *
5
+ * - Changing this function will be over-written by the next build.
6
+ *
7
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
+ *
10
+ * @param {{}} inputs
11
+ * @param {{ locale?: "en" | "pl" }} options
12
+ * @returns {string}
13
+ */
14
+ declare function login_please_login(inputs?: {}, options?: {
15
+ locale?: "en" | "pl";
16
+ }): string;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_login_please_login = /** @type {(inputs: {}) => string} */ () => {
5
+ return `Login to your account`
6
+ };
7
+
8
+ const pl_login_please_login = /** @type {(inputs: {}) => string} */ () => {
9
+ return `Zaloguj się na swoje konto`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{}} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ const login_please_login = (inputs = {}, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.login_please_login(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("login_please_login", locale)
31
+ if (locale === "en") return en_login_please_login(inputs)
32
+ return pl_login_please_login(inputs)
33
+ };
34
+ export { login_please_login as "login.please_login" }
@@ -23,6 +23,11 @@ export declare class FakturowniaClient {
23
23
  constructor(opts: FakturowniaClientOptions);
24
24
  createInvoice(invoice: FakturowniaInvoiceBody): Promise<FakturowniaInvoice>;
25
25
  sendByEmail(id: number | string): Promise<void>;
26
+ /**
27
+ * Read-only account lookup — used for connectivity/auth health checks.
28
+ * Does NOT create or modify anything. A 200 means domain + token are valid.
29
+ */
30
+ getAccount(): Promise<unknown>;
26
31
  private postRaw;
27
32
  private post;
28
33
  }
@@ -40,6 +40,26 @@ export class FakturowniaClient {
40
40
  api_token: this.apiToken
41
41
  });
42
42
  }
43
+ /**
44
+ * Read-only account lookup — used for connectivity/auth health checks.
45
+ * Does NOT create or modify anything. A 200 means domain + token are valid.
46
+ */
47
+ async getAccount() {
48
+ const res = await this.fetchFn(`${this.base}/account.json?api_token=${encodeURIComponent(this.apiToken)}`, { headers: { Accept: 'application/json' } });
49
+ if (!res.ok) {
50
+ let body;
51
+ try {
52
+ body = await res.json();
53
+ }
54
+ catch {
55
+ body = await res.text().catch(() => undefined);
56
+ }
57
+ const raw = body == null ? '' : typeof body === 'string' ? body : JSON.stringify(body);
58
+ const detail = raw ? `: ${raw.slice(0, 400)}` : '';
59
+ throw new FakturowniaApiError(`Fakturownia /account.json → ${res.status}${detail}`, res.status, body);
60
+ }
61
+ return res.json();
62
+ }
43
63
  async postRaw(path, payload) {
44
64
  const res = await this.fetchFn(`${this.base}${path}`, {
45
65
  method: 'POST',
@@ -32,5 +32,16 @@ export function fakturowniaAdapter(opts) {
32
32
  await client.sendByEmail(externalId);
33
33
  };
34
34
  }
35
+ adapter.healthCheck = async () => {
36
+ // Read-only /account.json lookup — verifies domain + token without
37
+ // issuing an invoice.
38
+ try {
39
+ await client.getAccount();
40
+ return { ok: true };
41
+ }
42
+ catch (e) {
43
+ return { ok: false, message: e instanceof Error ? e.message : String(e) };
44
+ }
45
+ };
35
46
  return adapter;
36
47
  }
@@ -99,6 +99,17 @@ export function payuAdapter(opts) {
99
99
  amount: input.amount ?? 0,
100
100
  raw: result.raw
101
101
  };
102
+ },
103
+ async healthCheck() {
104
+ // OAuth client_credentials token fetch — reaches PayU and verifies
105
+ // posId/clientId/clientSecret without creating an order.
106
+ try {
107
+ await client.getAccessToken();
108
+ return { ok: true };
109
+ }
110
+ catch (e) {
111
+ return { ok: false, message: e instanceof Error ? e.message : String(e) };
112
+ }
102
113
  }
103
114
  };
104
115
  }
@@ -12,5 +12,5 @@ export type { InpostAdapterOptions, InpostSenderAddress, GeowidgetConfigPreset,
12
12
  export { fakturowniaAdapter } from './adapters/fakturownia/index.js';
13
13
  export type { FakturowniaAdapterOptions } from './adapters/fakturownia/index.js';
14
14
  export { isValidNip } from './nip.js';
15
- export type { ShopConfig, ResolvedShopConfig, Currency, OrderStatus, PaymentAdapter, PaymentCreateContext, PaymentRefundInput, PaymentRefundResult, CarrierAdapter, CarrierEvent, ShipmentCreateInput, ShipmentCreateResult, ShipmentLabel, ConsentConfig, ShopFeatures, PaymentCreateResult, PaymentEvent, OrderRef, CouponRef, I18nText, VariantAttribute, VariantAttributeText, VariantAttributeNumber, VariantAttributeDatetime, VariantAttributeSelect, VariantAttributeBoolean, VariantAttributeImage, VariantAttributeEntry, VariantAttributeSlug, VariantLabelConfig, VariantExpiryConfig, PaymentPolicy, DepositAmount, PartialPayment, InvoicingAdapter, InvoiceIssuePolicy, InvoiceBuyer, InvoiceLineItem, InvoicePayload, InvoiceCreateResult, InvoiceContext } from './types.js';
15
+ export type { ShopConfig, ResolvedShopConfig, Currency, Order, OrderStatus, PaymentAdapter, PaymentCreateContext, PaymentRefundInput, PaymentRefundResult, CarrierAdapter, CarrierEvent, ShipmentCreateInput, ShipmentCreateResult, ShipmentLabel, ConsentConfig, ShopFeatures, PaymentCreateResult, PaymentEvent, OrderRef, CouponRef, I18nText, VariantAttribute, VariantAttributeText, VariantAttributeNumber, VariantAttributeDatetime, VariantAttributeSelect, VariantAttributeBoolean, VariantAttributeImage, VariantAttributeEntry, VariantAttributeSlug, VariantLabelConfig, VariantExpiryConfig, PaymentPolicy, DepositAmount, PartialPayment, InvoicingAdapter, InvoiceIssuePolicy, InvoiceBuyer, InvoiceLineItem, InvoicePayload, InvoiceCreateResult, InvoiceContext } from './types.js';
16
16
  export { interpolateTemplate } from './template.js';
@@ -51,3 +51,13 @@ export declare function recordCouponRedemption(input: {
51
51
  * row commits.
52
52
  */
53
53
  export declare function releaseCouponSlot(couponId: string): Promise<void>;
54
+ /**
55
+ * Read the coupon applied to an order (if any), via the redemption row.
56
+ * Returns `null` when the order had no coupon or the redemption row is missing.
57
+ * Safe to call from email/admin/storefront — uses the same authoritative
58
+ * `shop_coupon_redemptions` table that `recordCouponRedemption` writes to.
59
+ */
60
+ export declare function getOrderCoupon(orderId: string): Promise<{
61
+ code: string;
62
+ discountAmount: number;
63
+ } | null>;
@@ -115,3 +115,22 @@ export async function releaseCouponSlot(couponId) {
115
115
  })
116
116
  .where(eq(shopCouponsTable.id, couponId));
117
117
  }
118
+ /**
119
+ * Read the coupon applied to an order (if any), via the redemption row.
120
+ * Returns `null` when the order had no coupon or the redemption row is missing.
121
+ * Safe to call from email/admin/storefront — uses the same authoritative
122
+ * `shop_coupon_redemptions` table that `recordCouponRedemption` writes to.
123
+ */
124
+ export async function getOrderCoupon(orderId) {
125
+ const db = getShopDb();
126
+ const [row] = await db
127
+ .select({
128
+ code: shopCouponsTable.code,
129
+ discountAmount: shopCouponRedemptionsTable.discountAmount
130
+ })
131
+ .from(shopCouponRedemptionsTable)
132
+ .innerJoin(shopCouponsTable, eq(shopCouponRedemptionsTable.couponId, shopCouponsTable.id))
133
+ .where(eq(shopCouponRedemptionsTable.orderId, orderId))
134
+ .limit(1);
135
+ return row ?? null;
136
+ }
@@ -1,11 +1,15 @@
1
1
  import type { OrderStatus } from '../types.js';
2
+ /**
3
+ * List of template names a shop install must ship in `dist/shop/templates/`.
4
+ * Consumed by `validateBuiltinTemplates` at CMS bootstrap.
5
+ * @internal
6
+ */
7
+ export declare const REQUIRED_TEMPLATE_NAMES: readonly string[];
2
8
  export declare function sendOrderStatusEmail(orderId: string, status: OrderStatus): Promise<void>;
3
9
  /**
4
10
  * Notify the shop admin that a product crossed its low-stock threshold.
5
11
  * Fire-and-forget — silently no-ops when no `shop.adminEmail` or no email
6
- * adapter is configured. Stays inside email.ts to keep the adapter call
7
- * site centralised (HTML, escaping, logging behaviour identical to status
8
- * emails).
12
+ * adapter is configured.
9
13
  *
10
14
  * @internal
11
15
  */