@softure-ai/billing 0.0.0-stage → 0.1.6
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/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +695 -2
- package/dist/calendar.d.ts +26 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +81 -0
- package/dist/calendar.js.map +1 -0
- package/dist/contract.d.ts +187 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +6 -0
- package/dist/contract.js.map +1 -0
- package/dist/currency-digits.d.ts +3 -0
- package/dist/currency-digits.d.ts.map +1 -0
- package/dist/currency-digits.js +32 -0
- package/dist/currency-digits.js.map +1 -0
- package/dist/entitlement.d.ts +25 -0
- package/dist/entitlement.d.ts.map +1 -0
- package/dist/entitlement.js +75 -0
- package/dist/entitlement.js.map +1 -0
- package/dist/fields.d.ts +25 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +27 -0
- package/dist/fields.js.map +1 -0
- package/dist/index.d.ts +274 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/invoice.d.ts +29 -0
- package/dist/invoice.d.ts.map +1 -0
- package/dist/invoice.js +35 -0
- package/dist/invoice.js.map +1 -0
- package/dist/mailing/index.d.ts +2 -0
- package/dist/mailing/index.d.ts.map +1 -0
- package/dist/mailing/index.js +4 -0
- package/dist/mailing/index.js.map +1 -0
- package/dist/mailing/reminder-mail.d.ts +50 -0
- package/dist/mailing/reminder-mail.d.ts.map +1 -0
- package/dist/mailing/reminder-mail.js +71 -0
- package/dist/mailing/reminder-mail.js.map +1 -0
- package/dist/manual.d.ts +12 -0
- package/dist/manual.d.ts.map +1 -0
- package/dist/manual.js +22 -0
- package/dist/manual.js.map +1 -0
- package/dist/messages/en.d.ts +176 -0
- package/dist/messages/en.d.ts.map +1 -0
- package/dist/messages/en.js +151 -0
- package/dist/messages/en.js.map +1 -0
- package/dist/messages/index.d.ts +359 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +14 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/pl.d.ts +3 -0
- package/dist/messages/pl.d.ts.map +1 -0
- package/dist/messages/pl.js +151 -0
- package/dist/messages/pl.js.map +1 -0
- package/dist/next/access.d.ts +16 -0
- package/dist/next/access.d.ts.map +1 -0
- package/dist/next/access.js +24 -0
- package/dist/next/access.js.map +1 -0
- package/dist/next/actions.d.ts +24 -0
- package/dist/next/actions.d.ts.map +1 -0
- package/dist/next/actions.js +158 -0
- package/dist/next/actions.js.map +1 -0
- package/dist/next/context.d.ts +4 -0
- package/dist/next/context.d.ts.map +1 -0
- package/dist/next/context.js +17 -0
- package/dist/next/context.js.map +1 -0
- package/dist/next/current-entitlement.d.ts +18 -0
- package/dist/next/current-entitlement.d.ts.map +1 -0
- package/dist/next/current-entitlement.js +26 -0
- package/dist/next/current-entitlement.js.map +1 -0
- package/dist/next/index.d.ts +8 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +12 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/pages.d.ts +24 -0
- package/dist/next/pages.d.ts.map +1 -0
- package/dist/next/pages.js +166 -0
- package/dist/next/pages.js.map +1 -0
- package/dist/next/pricing.d.ts +12 -0
- package/dist/next/pricing.d.ts.map +1 -0
- package/dist/next/pricing.js +20 -0
- package/dist/next/pricing.js.map +1 -0
- package/dist/next/route.d.ts +11 -0
- package/dist/next/route.d.ts.map +1 -0
- package/dist/next/route.js +56 -0
- package/dist/next/route.js.map +1 -0
- package/dist/options.d.ts +85 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +121 -0
- package/dist/options.js.map +1 -0
- package/dist/payment.d.ts +61 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +12 -0
- package/dist/payment.js.map +1 -0
- package/dist/plans.d.ts +20 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +53 -0
- package/dist/plans.js.map +1 -0
- package/dist/price.d.ts +12 -0
- package/dist/price.d.ts.map +1 -0
- package/dist/price.js +37 -0
- package/dist/price.js.map +1 -0
- package/dist/refund.d.ts +70 -0
- package/dist/refund.d.ts.map +1 -0
- package/dist/refund.js +109 -0
- package/dist/refund.js.map +1 -0
- package/dist/reminder.d.ts +30 -0
- package/dist/reminder.d.ts.map +1 -0
- package/dist/reminder.js +34 -0
- package/dist/reminder.js.map +1 -0
- package/dist/schema.d.ts +1023 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +77 -0
- package/dist/schema.js.map +1 -0
- package/dist/scripts/entitlement-scripts.d.ts +17 -0
- package/dist/scripts/entitlement-scripts.d.ts.map +1 -0
- package/dist/scripts/entitlement-scripts.js +167 -0
- package/dist/scripts/entitlement-scripts.js.map +1 -0
- package/dist/scripts/index.d.ts +3 -0
- package/dist/scripts/index.d.ts.map +1 -0
- package/dist/scripts/index.js +5 -0
- package/dist/scripts/index.js.map +1 -0
- package/dist/scripts/plan-scripts.d.ts +19 -0
- package/dist/scripts/plan-scripts.d.ts.map +1 -0
- package/dist/scripts/plan-scripts.js +106 -0
- package/dist/scripts/plan-scripts.js.map +1 -0
- package/dist/server/entitlements.d.ts +69 -0
- package/dist/server/entitlements.d.ts.map +1 -0
- package/dist/server/entitlements.js +202 -0
- package/dist/server/entitlements.js.map +1 -0
- package/dist/server/grants.d.ts +74 -0
- package/dist/server/grants.d.ts.map +1 -0
- package/dist/server/grants.js +174 -0
- package/dist/server/grants.js.map +1 -0
- package/dist/server/health.d.ts +3 -0
- package/dist/server/health.d.ts.map +1 -0
- package/dist/server/health.js +17 -0
- package/dist/server/health.js.map +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +14 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/options.d.ts +20 -0
- package/dist/server/options.d.ts.map +1 -0
- package/dist/server/options.js +38 -0
- package/dist/server/options.js.map +1 -0
- package/dist/server/payments.d.ts +140 -0
- package/dist/server/payments.d.ts.map +1 -0
- package/dist/server/payments.js +339 -0
- package/dist/server/payments.js.map +1 -0
- package/dist/server/plans.d.ts +50 -0
- package/dist/server/plans.d.ts.map +1 -0
- package/dist/server/plans.js +129 -0
- package/dist/server/plans.js.map +1 -0
- package/dist/server/privacy.d.ts +77 -0
- package/dist/server/privacy.d.ts.map +1 -0
- package/dist/server/privacy.js +110 -0
- package/dist/server/privacy.js.map +1 -0
- package/dist/server/reminders.d.ts +20 -0
- package/dist/server/reminders.d.ts.map +1 -0
- package/dist/server/reminders.js +85 -0
- package/dist/server/reminders.js.map +1 -0
- package/dist/server/requests.d.ts +80 -0
- package/dist/server/requests.d.ts.map +1 -0
- package/dist/server/requests.js +155 -0
- package/dist/server/requests.js.map +1 -0
- package/dist/server/setup.d.ts +9 -0
- package/dist/server/setup.d.ts.map +1 -0
- package/dist/server/setup.js +34 -0
- package/dist/server/setup.js.map +1 -0
- package/dist/server/take-back.d.ts +80 -0
- package/dist/server/take-back.d.ts.map +1 -0
- package/dist/server/take-back.js +138 -0
- package/dist/server/take-back.js.map +1 -0
- package/dist/server/user-id.d.ts +4 -0
- package/dist/server/user-id.d.ts.map +1 -0
- package/dist/server/user-id.js +11 -0
- package/dist/server/user-id.js.map +1 -0
- package/dist/stripe-currency.d.ts +27 -0
- package/dist/stripe-currency.d.ts.map +1 -0
- package/dist/stripe-currency.js +57 -0
- package/dist/stripe-currency.js.map +1 -0
- package/dist/stripe-webhook.d.ts +101 -0
- package/dist/stripe-webhook.d.ts.map +1 -0
- package/dist/stripe-webhook.js +209 -0
- package/dist/stripe-webhook.js.map +1 -0
- package/dist/stripe.d.ts +25 -0
- package/dist/stripe.d.ts.map +1 -0
- package/dist/stripe.js +116 -0
- package/dist/stripe.js.map +1 -0
- package/dist/ui/access-badge.d.ts +16 -0
- package/dist/ui/access-badge.d.ts.map +1 -0
- package/dist/ui/access-badge.js +43 -0
- package/dist/ui/access-badge.js.map +1 -0
- package/dist/ui/access-notice.d.ts +20 -0
- package/dist/ui/access-notice.d.ts.map +1 -0
- package/dist/ui/access-notice.js +41 -0
- package/dist/ui/access-notice.js.map +1 -0
- package/dist/ui/format.d.ts +11 -0
- package/dist/ui/format.d.ts.map +1 -0
- package/dist/ui/format.js +21 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/grant-form.d.ts +18 -0
- package/dist/ui/grant-form.d.ts.map +1 -0
- package/dist/ui/grant-form.js +23 -0
- package/dist/ui/grant-form.js.map +1 -0
- package/dist/ui/grant-history.d.ts +39 -0
- package/dist/ui/grant-history.d.ts.map +1 -0
- package/dist/ui/grant-history.js +36 -0
- package/dist/ui/grant-history.js.map +1 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +12 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/payment-form.d.ts +23 -0
- package/dist/ui/payment-form.d.ts.map +1 -0
- package/dist/ui/payment-form.js +34 -0
- package/dist/ui/payment-form.js.map +1 -0
- package/dist/ui/payment-requests.d.ts +30 -0
- package/dist/ui/payment-requests.d.ts.map +1 -0
- package/dist/ui/payment-requests.js +31 -0
- package/dist/ui/payment-requests.js.map +1 -0
- package/dist/ui/pricing-tiles.d.ts +22 -0
- package/dist/ui/pricing-tiles.d.ts.map +1 -0
- package/dist/ui/pricing-tiles.js +40 -0
- package/dist/ui/pricing-tiles.js.map +1 -0
- package/migrations/0001_create_entitlements.sql +16 -0
- package/migrations/0002_create_payments.sql +30 -0
- package/migrations/0003_record_payment_grants.sql +25 -0
- package/migrations/0004_create_requests_and_grants.sql +58 -0
- package/migrations/0005_record_refunded_amounts.sql +18 -0
- package/migrations/0006_record_request_handover_and_prices.sql +38 -0
- package/migrations/0007_record_failed_refunds.sql +27 -0
- package/migrations/0008_record_request_handover_claims.sql +9 -0
- package/migrations/0009_record_pending_charge_states.sql +16 -0
- package/module.json +23 -0
- package/package.json +85 -4
- package/src/calendar.ts +90 -0
- package/src/contract.ts +181 -0
- package/src/currency-digits.ts +37 -0
- package/src/entitlement.ts +84 -0
- package/src/fields.ts +37 -0
- package/src/index.ts +163 -0
- package/src/invoice.ts +58 -0
- package/src/mailing/index.ts +11 -0
- package/src/mailing/reminder-mail.ts +108 -0
- package/src/manual.ts +31 -0
- package/src/messages/en.ts +150 -0
- package/src/messages/index.ts +18 -0
- package/src/messages/pl.ts +152 -0
- package/src/next/access.tsx +55 -0
- package/src/next/actions.ts +176 -0
- package/src/next/context.ts +18 -0
- package/src/next/current-entitlement.ts +36 -0
- package/src/next/index.ts +11 -0
- package/src/next/next-modules.d.ts +21 -0
- package/src/next/pages.tsx +267 -0
- package/src/next/pricing.tsx +39 -0
- package/src/next/route.ts +57 -0
- package/src/options.ts +128 -0
- package/src/payment.ts +77 -0
- package/src/plans.ts +63 -0
- package/src/price.ts +50 -0
- package/src/refund.ts +135 -0
- package/src/reminder.ts +52 -0
- package/src/schema.ts +86 -0
- package/src/scripts/entitlement-scripts.ts +188 -0
- package/src/scripts/index.ts +11 -0
- package/src/scripts/plan-scripts.ts +143 -0
- package/src/server/entitlements.ts +227 -0
- package/src/server/grants.ts +227 -0
- package/src/server/health.ts +18 -0
- package/src/server/index.ts +83 -0
- package/src/server/options.ts +52 -0
- package/src/server/payments.ts +434 -0
- package/src/server/plans.ts +143 -0
- package/src/server/privacy.ts +189 -0
- package/src/server/reminders.ts +113 -0
- package/src/server/requests.ts +201 -0
- package/src/server/setup.ts +37 -0
- package/src/server/take-back.ts +190 -0
- package/src/server/user-id.ts +12 -0
- package/src/stripe-currency.ts +65 -0
- package/src/stripe-webhook.ts +278 -0
- package/src/stripe.ts +130 -0
- package/src/ui/access-badge.tsx +64 -0
- package/src/ui/access-notice.tsx +73 -0
- package/src/ui/format.ts +25 -0
- package/src/ui/grant-form.tsx +69 -0
- package/src/ui/grant-history.tsx +127 -0
- package/src/ui/index.ts +25 -0
- package/src/ui/payment-form.tsx +111 -0
- package/src/ui/payment-requests.tsx +126 -0
- package/src/ui/pricing-tiles.tsx +105 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { en } from "./en.js";
|
|
2
|
+
import { pl } from "./pl.js";
|
|
3
|
+
/** Complete default dictionaries; apps pass partial overrides per locale. */
|
|
4
|
+
export const billingMessages = { en, pl };
|
|
5
|
+
/** The copy for an error code; an unknown code gets the generic failure. */
|
|
6
|
+
export function getBillingErrorMessage(messages, code) {
|
|
7
|
+
const separator = code.lastIndexOf(".");
|
|
8
|
+
const namespace = code.slice(0, separator);
|
|
9
|
+
const name = code.slice(separator + 1);
|
|
10
|
+
const groups = messages.errors;
|
|
11
|
+
const group = Object.hasOwn(groups, namespace) ? groups[namespace] : undefined;
|
|
12
|
+
return (group !== undefined && Object.hasOwn(group, name) ? group[name] : undefined) ?? messages.errors.core.unexpected;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAI7B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAE1C,4EAA4E;AAC5E,MAAM,UAAU,sBAAsB,CAAC,QAAyB,EAAE,IAA6F;IAC7J,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAoE,CAAC;IAC7F,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;AAC1H,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pl.d.ts","sourceRoot":"","sources":["../../src/messages/pl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElC,eAAO,MAAM,EAAE,EAAE,OAAO,EAqJvB,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
export const pl = {
|
|
2
|
+
badge: {
|
|
3
|
+
trial: "Okres próbny",
|
|
4
|
+
paid: "Opłacone",
|
|
5
|
+
lifetime: "Dostęp dożywotni",
|
|
6
|
+
readOnly: "Tylko odczyt",
|
|
7
|
+
daysLeft: { one: "został {count} dzień", few: "zostały {count} dni", many: "zostało {count} dni", other: "zostało {count} dnia" },
|
|
8
|
+
until: "do {date}",
|
|
9
|
+
},
|
|
10
|
+
notice: {
|
|
11
|
+
trialEnding: "Okres próbny kończy się {date}. Wybierz plan, żeby potem dalej wprowadzać zmiany.",
|
|
12
|
+
paidEnding: "Dostęp kończy się {date}. Przedłuż go, żeby potem dalej wprowadzać zmiany.",
|
|
13
|
+
trialEnded: "Okres próbny się skończył. Twoje dane są bezpieczne i nadal możesz je przeglądać; wybierz plan, żeby znów wprowadzać zmiany.",
|
|
14
|
+
paidEnded: "Dostęp się skończył. Twoje dane są bezpieczne i nadal możesz je przeglądać; przedłuż go, żeby znów wprowadzać zmiany.",
|
|
15
|
+
choosePlan: "Wybierz plan",
|
|
16
|
+
renew: "Przedłuż dostęp",
|
|
17
|
+
},
|
|
18
|
+
reminderMail: {
|
|
19
|
+
trialEnding: {
|
|
20
|
+
subject: "Okres próbny kończy się {date}",
|
|
21
|
+
body: "Okres próbny kończy się {date}. Wybierz plan, żeby potem dalej wprowadzać zmiany; Twoje dane i tak pozostaną bezpieczne.",
|
|
22
|
+
},
|
|
23
|
+
paidEnding: {
|
|
24
|
+
subject: "Dostęp kończy się {date}",
|
|
25
|
+
body: "Dostęp kończy się {date}. Przedłuż go, żeby potem dalej wprowadzać zmiany; Twoje dane i tak pozostaną bezpieczne.",
|
|
26
|
+
},
|
|
27
|
+
trialEnded: {
|
|
28
|
+
subject: "Okres próbny się skończył",
|
|
29
|
+
body: "Okres próbny się skończył. Twoje dane są bezpieczne i nadal możesz je przeglądać; wybierz plan, żeby znów wprowadzać zmiany.",
|
|
30
|
+
},
|
|
31
|
+
paidEnded: {
|
|
32
|
+
subject: "Dostęp się skończył",
|
|
33
|
+
body: "Dostęp się skończył. Twoje dane są bezpieczne i nadal możesz je przeglądać; przedłuż go, żeby znów wprowadzać zmiany.",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
pricing: {
|
|
37
|
+
period: {
|
|
38
|
+
day: { one: "za dzień", few: "za {count} dni", many: "za {count} dni", other: "za {count} dnia" },
|
|
39
|
+
week: { one: "za tydzień", few: "za {count} tygodnie", many: "za {count} tygodni", other: "za {count} tygodnia" },
|
|
40
|
+
month: { one: "za miesiąc", few: "za {count} miesiące", many: "za {count} miesięcy", other: "za {count} miesiąca" },
|
|
41
|
+
year: { one: "za rok", few: "za {count} lata", many: "za {count} lat", other: "za {count} roku" },
|
|
42
|
+
lifetime: "płatność jednorazowa",
|
|
43
|
+
},
|
|
44
|
+
featured: "Polecany",
|
|
45
|
+
choose: "Wybierz {plan}",
|
|
46
|
+
empty: "Nie ma jeszcze dostępnych planów.",
|
|
47
|
+
},
|
|
48
|
+
payment: {
|
|
49
|
+
title: "Wybierz plan",
|
|
50
|
+
lead: "Wybierz plan dla siebie. Płatny dostęp zaczyna się, gdy skończy się obecny.",
|
|
51
|
+
plansLabel: "Plany",
|
|
52
|
+
orderTitle: "Twoje zamówienie",
|
|
53
|
+
orderLead: "{plan}, {price} {period}",
|
|
54
|
+
changePlan: "Wybierz inny plan",
|
|
55
|
+
invoiceLead: "Fakturę wyślemy na adres {email}. Dostęp zacznie się po jej opłaceniu.",
|
|
56
|
+
fields: {
|
|
57
|
+
name: "Imię i nazwisko lub firma",
|
|
58
|
+
taxId: "NIP (opcjonalnie)",
|
|
59
|
+
address: "Adres do faktury",
|
|
60
|
+
},
|
|
61
|
+
requestInvoice: "Poproś o fakturę",
|
|
62
|
+
checkout: "Przejdź do płatności",
|
|
63
|
+
pending: "Wysyłanie…",
|
|
64
|
+
requested: "Dziękujemy! Prośba o fakturę za {plan} została wysłana. Fakturę wyślemy na adres {email}; dostęp zacznie się po jej opłaceniu.",
|
|
65
|
+
checkoutSuccess: "Dziękujemy za płatność! Dostęp zaktualizujemy, gdy płatność zostanie potwierdzona, zwykle w ciągu minuty.",
|
|
66
|
+
checkoutCancelled: "Płatność została anulowana i nic nie pobrano. Możesz spróbować ponownie albo wybrać inny plan.",
|
|
67
|
+
lifetime: "Masz dostęp dożywotni: nie ma już za co płacić.",
|
|
68
|
+
},
|
|
69
|
+
admin: {
|
|
70
|
+
title: "Nadaj dostęp",
|
|
71
|
+
lead: "Nadaj plan kontu, gdy wpłynie płatność. Płatny okres zaczyna się, gdy skończy się obecny dostęp konta.",
|
|
72
|
+
email: "E-mail konta",
|
|
73
|
+
plan: "Plan",
|
|
74
|
+
submit: "Nadaj plan",
|
|
75
|
+
pending: "Nadawanie…",
|
|
76
|
+
granted: "{email} ma teraz {plan}.",
|
|
77
|
+
grantedUntil: "{email} ma teraz {plan}, z dostępem do {date}.",
|
|
78
|
+
noPlans: "Nie ma planów do nadania: dodaj je w billing({ plans }).",
|
|
79
|
+
requests: {
|
|
80
|
+
title: "Prośby o fakturę",
|
|
81
|
+
lead: "Prośby wysłane ze strony płatności. Nadaj plan, gdy faktura zostanie opłacona, albo odrzuć prośbę.",
|
|
82
|
+
empty: "Brak otwartych próśb.",
|
|
83
|
+
line: "{email} – {plan}",
|
|
84
|
+
requestedOn: "Wysłana {date}",
|
|
85
|
+
price: "Cena: {price}",
|
|
86
|
+
invoice: "Faktura na: {name}, {address}",
|
|
87
|
+
taxId: "NIP: {taxId}",
|
|
88
|
+
noInvoice: "Bez danych do faktury",
|
|
89
|
+
grant: "Nadaj",
|
|
90
|
+
granting: "Nadawanie…",
|
|
91
|
+
dismiss: "Odrzuć",
|
|
92
|
+
dismissing: "Odrzucanie…",
|
|
93
|
+
history: "Historia",
|
|
94
|
+
grantLabel: "Nadaj {plan} dla {email}",
|
|
95
|
+
dismissLabel: "Odrzuć prośbę {email} o {plan}",
|
|
96
|
+
},
|
|
97
|
+
history: {
|
|
98
|
+
title: "Historia konta",
|
|
99
|
+
lead: "Znajdź konto, żeby zobaczyć jego dostęp, plany nadane ręcznie i płatności.",
|
|
100
|
+
email: "Znajdź konto po e-mailu",
|
|
101
|
+
submit: "Pokaż historię",
|
|
102
|
+
pending: "Szukanie…",
|
|
103
|
+
accountTitle: "Historia konta {email}",
|
|
104
|
+
empty: "Brak nadań i płatności.",
|
|
105
|
+
manual: "{plan}, nadany ręcznie",
|
|
106
|
+
fromRequest: "{plan}, nadany z prośby",
|
|
107
|
+
provider: "{plan}, opłacony przez {provider}",
|
|
108
|
+
grantedOn: "Nadany {date}",
|
|
109
|
+
grantedFor: "Nadany {date} za {amount}",
|
|
110
|
+
paidOn: "Zapłacono {amount}, {date}",
|
|
111
|
+
period: "Dostęp od {from} do {to}",
|
|
112
|
+
lifetime: "Dostęp dożywotni",
|
|
113
|
+
noGrant: "Zapisana, zanim zaczęliśmy zapisywać nadania",
|
|
114
|
+
active: "Aktywny",
|
|
115
|
+
revokedOn: "Cofnięty {date}",
|
|
116
|
+
paid: "Opłacona",
|
|
117
|
+
refundedOn: "Zwrócona {date}",
|
|
118
|
+
partlyRefunded: "Opłacona, zwrócono {amount}",
|
|
119
|
+
revoke: "Cofnij",
|
|
120
|
+
revoking: "Cofanie…",
|
|
121
|
+
revokeLabel: "Cofnij {plan} nadany {date}",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
errors: {
|
|
125
|
+
billing: {
|
|
126
|
+
read_only: "Konto jest w trybie tylko do odczytu. Wybierz plan, żeby wprowadzać zmiany.",
|
|
127
|
+
account_unknown: "Żadne konto nie ma tego adresu e-mail.",
|
|
128
|
+
end_not_in_future: "Data końca musi być w przyszłości.",
|
|
129
|
+
plan_unknown: "Ten plan nie jest już dostępny. Wybierz inny.",
|
|
130
|
+
invoice_details_invalid: "Sprawdź dane do faktury poniżej.",
|
|
131
|
+
invoice_field_required: "Wypełnij to pole.",
|
|
132
|
+
invoice_field_too_long: "Użyj najwyżej {max} znaków.",
|
|
133
|
+
invoice_field_control_characters: "Usuń znaki nowej linii, tabulatory i inne znaki sterujące.",
|
|
134
|
+
payment_failed: "Nie udało się rozpocząć płatności. Spróbuj za chwilę.",
|
|
135
|
+
lifetime_active: "To konto ma już dostęp dożywotni: nie ma za co płacić ani czego nadawać.",
|
|
136
|
+
request_closed: "Ta prośba została już obsłużona lub odrzucona.",
|
|
137
|
+
grant_revoked: "Ten dostęp został już cofnięty.",
|
|
138
|
+
},
|
|
139
|
+
security: {
|
|
140
|
+
rate_limited: "Zbyt wiele prób. Spróbuj później.",
|
|
141
|
+
},
|
|
142
|
+
auth: {
|
|
143
|
+
forbidden: "Nie masz uprawnień do tej operacji.",
|
|
144
|
+
},
|
|
145
|
+
core: {
|
|
146
|
+
database_failed: "Coś poszło nie tak po naszej stronie. Spróbuj za chwilę.",
|
|
147
|
+
unexpected: "Coś poszło nie tak po naszej stronie. Spróbuj za chwilę.",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=pl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pl.js","sourceRoot":"","sources":["../../src/messages/pl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ClassNames, LinkComponentType } from "@softure-ai/ui";
|
|
2
|
+
import { type AccessBadgeSlot } from "../ui/access-badge.js";
|
|
3
|
+
import { type AccessNoticeSlot } from "../ui/access-notice.js";
|
|
4
|
+
export interface CurrentAccessBadgeProps {
|
|
5
|
+
readonly classNames?: ClassNames<AccessBadgeSlot>;
|
|
6
|
+
readonly unstyled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function CurrentAccessBadge({ classNames, unstyled }: CurrentAccessBadgeProps): Promise<import("react").JSX.Element | null>;
|
|
9
|
+
export interface CurrentAccessNoticeProps {
|
|
10
|
+
/** The app's link component, e.g. Next's `Link`; a plain `<a>` when omitted. */
|
|
11
|
+
readonly LinkComponent?: LinkComponentType;
|
|
12
|
+
readonly classNames?: ClassNames<AccessNoticeSlot>;
|
|
13
|
+
readonly unstyled?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function CurrentAccessNotice({ LinkComponent, classNames, unstyled }: CurrentAccessNoticeProps): Promise<import("react").JSX.Element | null>;
|
|
16
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/next/access.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG7E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,kBAAkB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,uBAAuB,+CAczF;AAED,MAAM,WAAW,wBAAwB;IACvC,gFAAgF;IAChF,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,mBAAmB,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,wBAAwB,+CAgB1G"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// The badge and the notice for the signed-in account, wired to the registered config: one line in
|
|
3
|
+
// any server component (`<CurrentAccessBadge />`, `<CurrentAccessNotice />`). Without a session
|
|
4
|
+
// they render nothing.
|
|
5
|
+
import { getSoftureConfig } from "@softure-ai/core/next";
|
|
6
|
+
import { getBillingMessages, getBillingRoutes } from "../server/options.js";
|
|
7
|
+
import { AccessBadge } from "../ui/access-badge.js";
|
|
8
|
+
import { AccessNotice } from "../ui/access-notice.js";
|
|
9
|
+
import { getCurrentEntitlement } from "./current-entitlement.js";
|
|
10
|
+
export async function CurrentAccessBadge({ classNames, unstyled }) {
|
|
11
|
+
const entitlement = await getCurrentEntitlement();
|
|
12
|
+
if (entitlement === null)
|
|
13
|
+
return null;
|
|
14
|
+
const config = getSoftureConfig();
|
|
15
|
+
return (_jsx(AccessBadge, { entitlement: entitlement, messages: getBillingMessages(config), locale: config.locale, timezone: config.timezone, classNames: classNames, unstyled: unstyled }));
|
|
16
|
+
}
|
|
17
|
+
export async function CurrentAccessNotice({ LinkComponent, classNames, unstyled }) {
|
|
18
|
+
const entitlement = await getCurrentEntitlement();
|
|
19
|
+
if (entitlement === null)
|
|
20
|
+
return null;
|
|
21
|
+
const config = getSoftureConfig();
|
|
22
|
+
return (_jsx(AccessNotice, { entitlement: entitlement, messages: getBillingMessages(config), locale: config.locale, timezone: config.timezone, paymentHref: getBillingRoutes(config).payment, LinkComponent: LinkComponent, classNames: classNames, unstyled: unstyled }));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.js","sourceRoot":"","sources":["../../src/next/access.tsx"],"names":[],"mappings":";AAAA,kGAAkG;AAClG,gGAAgG;AAChG,uBAAuB;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAwB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAyB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAOjE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAA2B;IACxF,MAAM,WAAW,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAClD,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,OAAO,CACL,KAAC,WAAW,IACV,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,EACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,GAClB,CACH,CAAC;AACJ,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAA4B;IACzG,MAAM,WAAW,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAClD,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,OAAO,CACL,KAAC,YAAY,IACX,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,EACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAC7C,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,GAClB,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AdminActionState, GrantFormState, PaymentFormState } from "../contract.js";
|
|
2
|
+
/**
|
|
3
|
+
* Starts paying for the plan of the form. Without a session it redirects to the login page and
|
|
4
|
+
* back to the payment page. A hosted checkout is a redirect; a manual request answers `requested`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function startPaymentAction(_previous: PaymentFormState, formData: FormData): Promise<PaymentFormState>;
|
|
7
|
+
/**
|
|
8
|
+
* Grants one payment of a plan to the account with the form's email and records it in the
|
|
9
|
+
* account's history. Only for the role of `billing({ adminRole })`, checked from the session
|
|
10
|
+
* before the form is read. An account with lifetime access is refused.
|
|
11
|
+
*/
|
|
12
|
+
export declare function grantPlanAction(_previous: GrantFormState, formData: FormData): Promise<GrantFormState>;
|
|
13
|
+
/** Grants the plan of the form's open request and closes it (admin role). */
|
|
14
|
+
export declare function grantRequestAction(_previous: AdminActionState, formData: FormData): Promise<AdminActionState>;
|
|
15
|
+
/** Closes the form's open request without a grant (admin role). */
|
|
16
|
+
export declare function dismissRequestAction(_previous: AdminActionState, formData: FormData): Promise<AdminActionState>;
|
|
17
|
+
/** Revokes the form's manual grant, taking back only what it added (admin role). */
|
|
18
|
+
export declare function revokeGrantAction(_previous: AdminActionState, formData: FormData): Promise<AdminActionState>;
|
|
19
|
+
/**
|
|
20
|
+
* Finds the account with the form's email and sends the admin to its history on the admin page,
|
|
21
|
+
* by the account's id: an email address never lands in a URL (admin role).
|
|
22
|
+
*/
|
|
23
|
+
export declare function findAccountAction(_previous: AdminActionState, formData: FormData): Promise<AdminActionState>;
|
|
24
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAwB,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAwB/G;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiBnH;AAWD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAiC5G;AAyBD,6EAA6E;AAC7E,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAMnH;AAED,mEAAmE;AACnE,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAErH;AAED,oFAAoF;AACpF,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAMlH;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAelH"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { authorizeRole, requireUser } from "@softure-ai/auth/next";
|
|
3
|
+
import { errorLogLabel, formatMessage, safeError } from "@softure-ai/core";
|
|
4
|
+
import { getSoftureConfig } from "@softure-ai/core/next";
|
|
5
|
+
import { revalidatePath } from "next/cache";
|
|
6
|
+
import { redirect } from "next/navigation";
|
|
7
|
+
import { ACCOUNT_PARAM, EMAIL_FIELD, GRANT_FIELD, INVOICE_FIELDS, PLAN_FIELD, REQUEST_FIELD } from "../fields.js";
|
|
8
|
+
import { findPlan, getLocalizedText } from "../plans.js";
|
|
9
|
+
import { grantPaymentRequest, grantPlanManually, revokeManualGrant } from "../server/grants.js";
|
|
10
|
+
import { getBillingMessages, getBillingOptions, getBillingRoutes } from "../server/options.js";
|
|
11
|
+
import { findAccountByEmail, getBillingPlans, startPayment } from "../server/plans.js";
|
|
12
|
+
import { dismissPaymentRequest } from "../server/requests.js";
|
|
13
|
+
import { formatLastDay } from "../ui/format.js";
|
|
14
|
+
import { getBillingContext } from "./context.js";
|
|
15
|
+
/** Longer values are cut: the server functions refuse them anyway, and nothing huge is echoed back. */
|
|
16
|
+
const MAX_FIELD_LENGTH = 1024;
|
|
17
|
+
function readText(formData, name) {
|
|
18
|
+
const value = formData.get(name);
|
|
19
|
+
return typeof value === "string" ? value.slice(0, MAX_FIELD_LENGTH) : "";
|
|
20
|
+
}
|
|
21
|
+
function reportFailure(operation, error) {
|
|
22
|
+
console.error(`@softure-ai/billing: ${operation} failed: ${errorLogLabel(error)}`);
|
|
23
|
+
return safeError(error).error;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Starts paying for the plan of the form. Without a session it redirects to the login page and
|
|
27
|
+
* back to the payment page. A hosted checkout is a redirect; a manual request answers `requested`.
|
|
28
|
+
*/
|
|
29
|
+
export async function startPaymentAction(_previous, formData) {
|
|
30
|
+
const config = getSoftureConfig();
|
|
31
|
+
const user = await requireUser({ next: getBillingRoutes(config).payment });
|
|
32
|
+
const planId = readText(formData, PLAN_FIELD);
|
|
33
|
+
const invoice = { name: readText(formData, INVOICE_FIELDS.name), taxId: readText(formData, INVOICE_FIELDS.taxId), address: readText(formData, INVOICE_FIELDS.address) };
|
|
34
|
+
const values = { [INVOICE_FIELDS.name]: invoice.name, [INVOICE_FIELDS.taxId]: invoice.taxId, [INVOICE_FIELDS.address]: invoice.address };
|
|
35
|
+
let result;
|
|
36
|
+
try {
|
|
37
|
+
result = await startPayment(await getBillingContext(config), { account: { id: user.id, email: user.email }, planId, invoice });
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return { status: "error", error: reportFailure("starting a payment", error), values };
|
|
41
|
+
}
|
|
42
|
+
if (!result.ok)
|
|
43
|
+
return { status: "error", error: result.error, ...("fieldErrors" in result ? { fieldErrors: result.fieldErrors } : {}), values };
|
|
44
|
+
// Outside the try: Next's redirect works by throwing.
|
|
45
|
+
if (result.value.type === "redirect")
|
|
46
|
+
redirect(result.value.url);
|
|
47
|
+
return { status: "requested" };
|
|
48
|
+
}
|
|
49
|
+
function refreshAdminPage(config) {
|
|
50
|
+
revalidatePath(getBillingRoutes(config).admin);
|
|
51
|
+
}
|
|
52
|
+
/** The signed-in admin, or the refusal: the role of `billing({ adminRole })`, from the session. */
|
|
53
|
+
async function authorizeAdmin(config) {
|
|
54
|
+
return authorizeRole(getBillingOptions(config).adminRole);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Grants one payment of a plan to the account with the form's email and records it in the
|
|
58
|
+
* account's history. Only for the role of `billing({ adminRole })`, checked from the session
|
|
59
|
+
* before the form is read. An account with lifetime access is refused.
|
|
60
|
+
*/
|
|
61
|
+
export async function grantPlanAction(_previous, formData) {
|
|
62
|
+
const config = getSoftureConfig();
|
|
63
|
+
const admin = await authorizeAdmin(config);
|
|
64
|
+
if (!admin.ok)
|
|
65
|
+
return { status: "error", error: admin.error };
|
|
66
|
+
const email = readText(formData, EMAIL_FIELD).trim();
|
|
67
|
+
const planId = readText(formData, PLAN_FIELD);
|
|
68
|
+
const echo = { email, planId };
|
|
69
|
+
const plan = findPlan(getBillingPlans(config), planId);
|
|
70
|
+
if (plan === undefined)
|
|
71
|
+
return { status: "error", error: "billing.plan_unknown", ...echo };
|
|
72
|
+
let result;
|
|
73
|
+
try {
|
|
74
|
+
const ctx = await getBillingContext(config);
|
|
75
|
+
const account = await findAccountByEmail(ctx, email);
|
|
76
|
+
if (account === null)
|
|
77
|
+
return { status: "error", error: "billing.account_unknown", ...echo };
|
|
78
|
+
result = await grantPlanManually(ctx, { userId: account.id, planId: plan.id, adminId: admin.value.id });
|
|
79
|
+
if (result.ok) {
|
|
80
|
+
refreshAdminPage(config);
|
|
81
|
+
const messages = getBillingMessages(config).admin;
|
|
82
|
+
const { entitlement } = result.value;
|
|
83
|
+
const values = { email: account.email, plan: getLocalizedText(plan.name, config.locale) };
|
|
84
|
+
const notice = entitlement.status === "paid" && entitlement.endsAt !== null
|
|
85
|
+
? formatMessage(messages.grantedUntil, { ...values, date: formatLastDay(entitlement.endsAt, config.locale, config.timezone) })
|
|
86
|
+
: formatMessage(messages.granted, values);
|
|
87
|
+
return { status: "granted", notice, planId };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return { status: "error", error: reportFailure("granting a plan", error), ...echo };
|
|
92
|
+
}
|
|
93
|
+
// No request was given, so it is never closed; an account deleted meanwhile is unknown.
|
|
94
|
+
const error = result.error === "billing.request_closed" ? "billing.account_unknown" : result.error;
|
|
95
|
+
return { status: "error", error, ...echo };
|
|
96
|
+
}
|
|
97
|
+
/** Runs one admin change on the row the form names: role first, then the change, then a refresh. */
|
|
98
|
+
async function runAdminChange(formData, { operation, field, change }) {
|
|
99
|
+
const config = getSoftureConfig();
|
|
100
|
+
const admin = await authorizeAdmin(config);
|
|
101
|
+
if (!admin.ok)
|
|
102
|
+
return { status: "error", error: admin.error };
|
|
103
|
+
const id = readText(formData, field);
|
|
104
|
+
try {
|
|
105
|
+
const result = await change(await getBillingContext(config), id, admin.value.id);
|
|
106
|
+
if (!result.ok)
|
|
107
|
+
return { status: "error", error: result.error };
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return { status: "error", error: reportFailure(operation, error) };
|
|
111
|
+
}
|
|
112
|
+
refreshAdminPage(config);
|
|
113
|
+
return { status: "done" };
|
|
114
|
+
}
|
|
115
|
+
/** Grants the plan of the form's open request and closes it (admin role). */
|
|
116
|
+
export async function grantRequestAction(_previous, formData) {
|
|
117
|
+
return runAdminChange(formData, {
|
|
118
|
+
operation: "granting a payment request",
|
|
119
|
+
field: REQUEST_FIELD,
|
|
120
|
+
change: (ctx, requestId, adminId) => grantPaymentRequest(ctx, { requestId, adminId }),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/** Closes the form's open request without a grant (admin role). */
|
|
124
|
+
export async function dismissRequestAction(_previous, formData) {
|
|
125
|
+
return runAdminChange(formData, { operation: "dismissing a payment request", field: REQUEST_FIELD, change: (ctx, requestId) => dismissPaymentRequest(ctx, requestId) });
|
|
126
|
+
}
|
|
127
|
+
/** Revokes the form's manual grant, taking back only what it added (admin role). */
|
|
128
|
+
export async function revokeGrantAction(_previous, formData) {
|
|
129
|
+
return runAdminChange(formData, {
|
|
130
|
+
operation: "revoking a manual grant",
|
|
131
|
+
field: GRANT_FIELD,
|
|
132
|
+
change: (ctx, grantId, adminId) => revokeManualGrant(ctx, { grantId, adminId }),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Finds the account with the form's email and sends the admin to its history on the admin page,
|
|
137
|
+
* by the account's id: an email address never lands in a URL (admin role).
|
|
138
|
+
*/
|
|
139
|
+
export async function findAccountAction(_previous, formData) {
|
|
140
|
+
const config = getSoftureConfig();
|
|
141
|
+
const admin = await authorizeAdmin(config);
|
|
142
|
+
if (!admin.ok)
|
|
143
|
+
return { status: "error", error: admin.error };
|
|
144
|
+
const email = readText(formData, EMAIL_FIELD).trim();
|
|
145
|
+
let accountId;
|
|
146
|
+
try {
|
|
147
|
+
const account = await findAccountByEmail(await getBillingContext(config), email);
|
|
148
|
+
if (account === null)
|
|
149
|
+
return { status: "error", error: "billing.account_unknown", email };
|
|
150
|
+
accountId = account.id;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return { status: "error", error: reportFailure("finding an account", error), email };
|
|
154
|
+
}
|
|
155
|
+
// Outside the try: Next's redirect works by throwing.
|
|
156
|
+
redirect(`${getBillingRoutes(config).admin}?${new URLSearchParams({ [ACCOUNT_PARAM]: accountId }).toString()}`);
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,aAAkC,GAAG,OAAO,CAAC,cAAc,CAAC,CAQ3G"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// What the adapter hands the server functions: the registered config, the process-wide database
|
|
2
|
+
// handle and the wall clock. Every billing request comes through here, so a broken setup (an
|
|
3
|
+
// undeclared `adminRole`) fails on the first one.
|
|
4
|
+
import { systemClock } from "@softure-ai/core";
|
|
5
|
+
import { getSoftureConfig } from "@softure-ai/core/next";
|
|
6
|
+
import { getConfiguredDatabase } from "@softure-ai/db";
|
|
7
|
+
import { assertAdminRoleDeclared } from "../server/setup.js";
|
|
8
|
+
export async function getBillingContext(config = getSoftureConfig()) {
|
|
9
|
+
assertAdminRoleDeclared(config);
|
|
10
|
+
if (config.database === null) {
|
|
11
|
+
// Unreachable for a validated config: the module has a database schema.
|
|
12
|
+
throw new Error("@softure-ai/billing: softure.config.ts has no database; billing needs one");
|
|
13
|
+
}
|
|
14
|
+
const { db } = await getConfiguredDatabase(config.database);
|
|
15
|
+
return { db, clock: systemClock, config };
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6FAA6F;AAC7F,kDAAkD;AAClD,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAwB,gBAAgB,EAAE;IAChF,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC7B,wEAAwE;QACxE,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AuthUser } from "@softure-ai/auth";
|
|
2
|
+
import { type RequireUserOptions } from "@softure-ai/auth/next";
|
|
3
|
+
import { type Err, type Ok } from "@softure-ai/core";
|
|
4
|
+
import type { Entitlement } from "../contract.js";
|
|
5
|
+
/** The entitlement of the request's account, or null without a session. Database failures propagate. */
|
|
6
|
+
export declare const getCurrentEntitlement: () => Promise<Entitlement | null>;
|
|
7
|
+
/** What a write may go ahead with. */
|
|
8
|
+
export interface WriteAccess {
|
|
9
|
+
readonly user: AuthUser;
|
|
10
|
+
readonly entitlement: Entitlement;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The guard for an app's write actions; call it before reading any input. Without a session it
|
|
14
|
+
* redirects to the login page (as `requireUser`); a read-only account gets `billing.read_only` for
|
|
15
|
+
* the action to return to its form. Never a reason to skip the action's own authorization.
|
|
16
|
+
*/
|
|
17
|
+
export declare function requireWriteAccess(options?: RequireUserOptions): Promise<Ok<WriteAccess> | Err<"billing.read_only">>;
|
|
18
|
+
//# sourceMappingURL=current-entitlement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-entitlement.d.ts","sourceRoot":"","sources":["../../src/next/current-entitlement.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAA+B,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAW,KAAK,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,wGAAwG;AACxG,eAAO,MAAM,qBAAqB,QAAmB,OAAO,CAAC,WAAW,GAAG,IAAI,CAI7E,CAAC;AAEH,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAM9H"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getCurrentUser, requireUser } from "@softure-ai/auth/next";
|
|
2
|
+
import { err, ok } from "@softure-ai/core";
|
|
3
|
+
import { cache } from "react";
|
|
4
|
+
import { getEntitlement } from "../server/entitlements.js";
|
|
5
|
+
import { getBillingContext } from "./context.js";
|
|
6
|
+
/** The entitlement of the request's account, or null without a session. Database failures propagate. */
|
|
7
|
+
export const getCurrentEntitlement = cache(async () => {
|
|
8
|
+
const user = await getCurrentUser();
|
|
9
|
+
if (user === null)
|
|
10
|
+
return null;
|
|
11
|
+
return getEntitlement(await getBillingContext(), user.id);
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* The guard for an app's write actions; call it before reading any input. Without a session it
|
|
15
|
+
* redirects to the login page (as `requireUser`); a read-only account gets `billing.read_only` for
|
|
16
|
+
* the action to return to its form. Never a reason to skip the action's own authorization.
|
|
17
|
+
*/
|
|
18
|
+
export async function requireWriteAccess(options = {}) {
|
|
19
|
+
const user = await requireUser(options);
|
|
20
|
+
const entitlement = await getCurrentEntitlement();
|
|
21
|
+
// The session's account exists, so it has an entitlement; null would mean it vanished mid-request.
|
|
22
|
+
if (entitlement === null || entitlement.status === "read_only")
|
|
23
|
+
return err("billing.read_only");
|
|
24
|
+
return ok({ user, entitlement });
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=current-entitlement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-entitlement.js","sourceRoot":"","sources":["../../src/next/current-entitlement.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,WAAW,EAA2B,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,GAAG,EAAE,EAAE,EAAqB,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,wGAAwG;AACxG,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,KAAK,IAAiC,EAAE;IACjF,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;IACpC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,cAAc,CAAC,MAAM,iBAAiB,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,CAAC,CAAC;AAQH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAA8B,EAAE;IACvE,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAClD,mGAAmG;IACnG,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAChG,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CurrentAccessBadge, type CurrentAccessBadgeProps, CurrentAccessNotice, type CurrentAccessNoticeProps } from "./access.js";
|
|
2
|
+
export { dismissRequestAction, findAccountAction, grantPlanAction, grantRequestAction, revokeGrantAction, startPaymentAction } from "./actions.js";
|
|
3
|
+
export { getBillingContext } from "./context.js";
|
|
4
|
+
export { getCurrentEntitlement, requireWriteAccess, type WriteAccess } from "./current-entitlement.js";
|
|
5
|
+
export { BillingAdminPage, type BillingAdminPageProps, PaymentPage, type PaymentPageProps } from "./pages.js";
|
|
6
|
+
export { getPlanPaymentHref, Pricing, type PricingProps } from "./pricing.js";
|
|
7
|
+
export { STRIPE_WEBHOOK_MAX_BYTES, STRIPE_WEBHOOK_SECRET_ENV, stripeWebhookRoute } from "./route.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACnI,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9G,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// The Next.js adapter of @softure-ai/billing: the signed-in account's entitlement, the write guard
|
|
2
|
+
// for server actions, the badge and notice, the pricing tiles, the payment and admin pages and
|
|
3
|
+
// their actions, and the Stripe webhook route, wired to the registered configuration
|
|
4
|
+
// (docs/02-module-standard.md §8).
|
|
5
|
+
export { CurrentAccessBadge, CurrentAccessNotice } from "./access.js";
|
|
6
|
+
export { dismissRequestAction, findAccountAction, grantPlanAction, grantRequestAction, revokeGrantAction, startPaymentAction } from "./actions.js";
|
|
7
|
+
export { getBillingContext } from "./context.js";
|
|
8
|
+
export { getCurrentEntitlement, requireWriteAccess } from "./current-entitlement.js";
|
|
9
|
+
export { BillingAdminPage, PaymentPage } from "./pages.js";
|
|
10
|
+
export { getPlanPaymentHref, Pricing } from "./pricing.js";
|
|
11
|
+
export { STRIPE_WEBHOOK_MAX_BYTES, STRIPE_WEBHOOK_SECRET_ENV, stripeWebhookRoute } from "./route.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,+FAA+F;AAC/F,qFAAqF;AACrF,mCAAmC;AACnC,OAAO,EAAE,kBAAkB,EAAgC,mBAAmB,EAAiC,MAAM,aAAa,CAAC;AACnI,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAoB,MAAM,0BAA0B,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAA8B,WAAW,EAAyB,MAAM,YAAY,CAAC;AAC9G,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAqB,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type SearchParams = Promise<Record<string, string | string[] | undefined>>;
|
|
2
|
+
export interface PaymentPageProps {
|
|
3
|
+
readonly searchParams?: SearchParams;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The plans and, with `?plan=<id>`, the order: the plan's price and the provider's form (the
|
|
7
|
+
* invoice request of the manual adapter, a checkout button of a hosted provider). Without a session
|
|
8
|
+
* it sends the visitor to log in and back. A read-only account reaches it too: it is where to pay.
|
|
9
|
+
* A hosted checkout comes back with `?checkout=success` or `?checkout=cancelled`, shown as a notice
|
|
10
|
+
* (the access itself changes when the provider's webhook confirms the payment).
|
|
11
|
+
*/
|
|
12
|
+
export declare function PaymentPage({ searchParams }: PaymentPageProps): Promise<import("react").JSX.Element>;
|
|
13
|
+
export interface BillingAdminPageProps {
|
|
14
|
+
readonly searchParams?: SearchParams;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The admin page of manual payments: the open invoice requests (grant or dismiss each), the grant
|
|
18
|
+
* form, and an account's history (`?account=<id>`, reached by the email lookup or a request's
|
|
19
|
+
* link) with its access and a revoke button on each active manual grant. Anyone without the role
|
|
20
|
+
* of `billing({ adminRole })`, signed in or not, gets Next's "not found".
|
|
21
|
+
*/
|
|
22
|
+
export declare function BillingAdminPage({ searchParams }: BillingAdminPageProps): Promise<import("react").JSX.Element>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/next/pages.tsx"],"names":[],"mappings":"AA+BA,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAiBD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,EAAE,YAAY,EAAE,EAAE,gBAAgB,wCAqEnE;AAqFD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,YAAY,EAAE,EAAE,qBAAqB,wCA2C7E"}
|