@stewardhq/sdk 0.5.0 → 0.7.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/LICENSE +201 -0
- package/README.md +247 -200
- package/dist/_chunks/errors.js +1 -1
- package/dist/_chunks/events.d.ts +133 -122
- package/dist/_chunks/events.js +45 -7
- package/dist/_chunks/index.d.ts +1308 -594
- package/dist/_chunks/locale.d.ts +42 -3
- package/dist/_chunks/src.js +379 -26
- package/dist/_chunks/validators.d.ts +2 -2
- package/dist/_chunks/webhook-core.d.ts +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/contract.js +3 -3
- package/dist/index.d.ts +24 -24
- package/dist/index.js +66 -5
- package/dist/server.d.ts +32 -20
- package/dist/server.js +7 -3
- package/package.json +14 -8
package/dist/_chunks/src.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $t as MeteredPriceSchema, A as SubscriptionStatusSchema, Bn as EntitlementsSchema, C as AccountSchema, D as BillingProfileKindSchema, Et as MAX_METER_UNITS, Fn as CodeSchema, H as EmailSettingsSchema, Ht as MeterCreditPropertiesSchema, In as CurrencySchema, Jn as InvoiceBillingReasonSchema, Kn as IdSchema, L as EMAIL_TEMPLATES, Ln as DateTimeSchema, Nn as ActorRefSchema, O as BillingProfileSchema, Pn as AmountMinorSchema, Qt as MeteredPriceDefSchema, Un as ExternalRefSchema, Ut as MeterDefSchema, V as EmailSettingsPatchSchema, Vt as MeterCreditEntrySchema, X as PriceChangeNoticeMeteredRateSchema, Yn as InvoicePaymentStatusSchema, Z as applyEmailSettingsPatch, a as EVENT_TYPES, bt as AccountMetersSchema, ct as BenefitDefSchema, ft as CatalogBenefitSchema, gt as featureValueMatchesType, ln as plainDecimalOf, o as EventIdSchema, on as isMicroPrecise, qn as IntervalSchema, rn as MICRO_UNITS_PER_UNIT, tn as meterFilterClauseOf, un as toMicroUnits, w as AccountStateSchema, wt as DecimalUnitsStringSchema, xt as CatalogMeterSchema } from "./events.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region ../contract/src/catalog.ts
|
|
4
4
|
const FeatureTypeSchema = z.enum([
|
|
@@ -346,17 +346,34 @@ const BrandingSchema = z.object({
|
|
|
346
346
|
});
|
|
347
347
|
const DEFAULT_PAYMENT_DUE_DAYS = 7;
|
|
348
348
|
const DEFAULT_MIN_INVOICE_MINOR = 1e3;
|
|
349
|
+
const DEFAULT_BANK_TRANSFER_PAYMENT_DAYS = 5;
|
|
349
350
|
const PaymentDueDaysSchema = z.number().int().min(1).max(60);
|
|
351
|
+
const BankTransferPaymentDaysSchema = z.number().int().min(1).max(14);
|
|
352
|
+
const BankTransferSettingsSchema = z.object({
|
|
353
|
+
enabled: z.boolean().default(false),
|
|
354
|
+
paymentDays: BankTransferPaymentDaysSchema.default(5)
|
|
355
|
+
});
|
|
350
356
|
const BillingSettingsSchema = z.object({
|
|
351
357
|
paymentDueDays: PaymentDueDaysSchema.default(7),
|
|
352
358
|
minInvoiceMinor: AmountMinorSchema.default(DEFAULT_MIN_INVOICE_MINOR),
|
|
353
|
-
allowMultipleSubscriptions: z.boolean().default(false)
|
|
359
|
+
allowMultipleSubscriptions: z.boolean().default(false),
|
|
360
|
+
bankTransfer: BankTransferSettingsSchema.default({
|
|
361
|
+
enabled: false,
|
|
362
|
+
paymentDays: 5
|
|
363
|
+
})
|
|
354
364
|
});
|
|
365
|
+
/** Patch of `settings.billing.bankTransfer`: an omitted field is unchanged, `null` restores its default. */
|
|
366
|
+
const BankTransferSettingsPatchSchema = z.object({
|
|
367
|
+
enabled: z.boolean().nullable().optional(),
|
|
368
|
+
paymentDays: BankTransferPaymentDaysSchema.nullable().optional()
|
|
369
|
+
}).strict();
|
|
355
370
|
/** Patch of `settings.billing`: an omitted field is unchanged, `null` restores its default. */
|
|
356
371
|
const BillingSettingsPatchSchema = z.object({
|
|
357
372
|
paymentDueDays: PaymentDueDaysSchema.nullable().optional(),
|
|
358
373
|
minInvoiceMinor: AmountMinorSchema.nullable().optional(),
|
|
359
|
-
allowMultipleSubscriptions: z.boolean().nullable().optional()
|
|
374
|
+
allowMultipleSubscriptions: z.boolean().nullable().optional(),
|
|
375
|
+
/** Merges per field; `bankTransfer: null` restores its defaults (off). */
|
|
376
|
+
bankTransfer: BankTransferSettingsPatchSchema.nullable().optional()
|
|
360
377
|
}).strict();
|
|
361
378
|
const DEFAULT_EVENT_RETENTION_DAYS = 120;
|
|
362
379
|
const DEFAULT_LATE_GRACE_MINUTES = 60;
|
|
@@ -423,6 +440,12 @@ const BrandingPatchSchema = z.object({
|
|
|
423
440
|
}).strict();
|
|
424
441
|
/** `PATCH /v1/admin/settings` gövdesi. */
|
|
425
442
|
const ProductSettingsPatchSchema = z.object({
|
|
443
|
+
/**
|
|
444
|
+
* The payment provider for NEW checkouts and payment sessions (issue #57 decision 2; an open
|
|
445
|
+
* session keeps the provider it was opened with). Steward refuses a provider this deployment
|
|
446
|
+
* has not configured (422 `provider_not_available`).
|
|
447
|
+
*/
|
|
448
|
+
provider: z.string().regex(/^[a-z][a-z0-9_-]{0,39}$/, "a provider id (lowercase)").optional(),
|
|
426
449
|
appUrl: WebUrlSchema.nullable().optional(),
|
|
427
450
|
defaultCurrency: CurrencySchema.optional(),
|
|
428
451
|
defaultLocale: SettingsLocaleSchema.optional(),
|
|
@@ -446,6 +469,17 @@ const MERGED_SECTIONS = /* @__PURE__ */ new Set([
|
|
|
446
469
|
"events",
|
|
447
470
|
"metering"
|
|
448
471
|
]);
|
|
472
|
+
/** Objects inside a merged section that merge one level deeper (`billing.bankTransfer`). */
|
|
473
|
+
const NESTED_MERGED_FIELDS = /* @__PURE__ */ new Set(["bankTransfer"]);
|
|
474
|
+
/** Field-by-field merge: `null` deletes a field (its default comes back), `undefined` keeps it. */
|
|
475
|
+
function mergeFields(current, patch, nested = /* @__PURE__ */ new Set()) {
|
|
476
|
+
const merged = { ...current };
|
|
477
|
+
for (const [field, value] of Object.entries(patch)) if (value === null) delete merged[field];
|
|
478
|
+
else if (value === void 0) continue;
|
|
479
|
+
else if (nested.has(field)) merged[field] = mergeFields(current[field] ?? {}, value);
|
|
480
|
+
else merged[field] = value;
|
|
481
|
+
return merged;
|
|
482
|
+
}
|
|
449
483
|
/**
|
|
450
484
|
* Doğrulanmış yamayı ayarlara uygular (saf). Sonuç şemadan geçer; alan kuralları
|
|
451
485
|
* yamada zaten denetlendiği için yalnızca programlama hatasında fırlatır.
|
|
@@ -464,12 +498,7 @@ function applySettingsPatch(current, patch) {
|
|
|
464
498
|
} else if (key === "emails") next.emails = applyEmailSettingsPatch(current.emails, value);
|
|
465
499
|
else if (MERGED_SECTIONS.has(key)) {
|
|
466
500
|
if (value === null) delete next[key];
|
|
467
|
-
else {
|
|
468
|
-
const section = { ...current[key] ?? {} };
|
|
469
|
-
for (const [field, fieldValue] of Object.entries(value)) if (fieldValue === null) delete section[field];
|
|
470
|
-
else if (fieldValue !== void 0) section[field] = fieldValue;
|
|
471
|
-
next[key] = section;
|
|
472
|
-
}
|
|
501
|
+
else next[key] = mergeFields(current[key] ?? {}, value, NESTED_MERGED_FIELDS);
|
|
473
502
|
} else if (value === null) delete next[key];
|
|
474
503
|
else next[key] = value;
|
|
475
504
|
}
|
|
@@ -540,7 +569,15 @@ const CheckoutSessionCreateInputSchema = z.object({
|
|
|
540
569
|
/** Opens the account with this name if it does not exist; never renames an existing account. */
|
|
541
570
|
displayName: z.string().min(1).max(200).optional(),
|
|
542
571
|
prefill: CheckoutPrefillSchema.optional(),
|
|
543
|
-
consents: z.array(CheckoutConsentInputSchema).max(20).optional()
|
|
572
|
+
consents: z.array(CheckoutConsentInputSchema).max(20).optional(),
|
|
573
|
+
/**
|
|
574
|
+
* Upgrade (bank transfer plan H16): a live subscription of the account this checkout replaces.
|
|
575
|
+
* It does not block the session (`already_subscribed`) and keeps running until the payment is
|
|
576
|
+
* recorded; in the transaction that records it (card or bank transfer) it is canceled
|
|
577
|
+
* immediately and the new subscription starts. An abandoned, expired or canceled session leaves
|
|
578
|
+
* it untouched. Not a live subscription of the account → 422 `replaces_subscription_invalid`.
|
|
579
|
+
*/
|
|
580
|
+
replacesSubscriptionId: IdSchema.optional()
|
|
544
581
|
}).superRefine((body, ctx) => {
|
|
545
582
|
const seen = /* @__PURE__ */ new Set();
|
|
546
583
|
body.consents?.forEach((consent, i) => {
|
|
@@ -567,7 +604,18 @@ const CheckoutStatusSchema = z.enum([
|
|
|
567
604
|
"expired",
|
|
568
605
|
"canceled"
|
|
569
606
|
]);
|
|
570
|
-
/**
|
|
607
|
+
/**
|
|
608
|
+
* How the customer chose to pay on the hosted page (bank transfer plan H5): `card` (the provider's
|
|
609
|
+
* form) or `bank_transfer` (the session stays `open` until an operator records the transfer).
|
|
610
|
+
* Absent/null: not chosen yet. The session status set does not change for it.
|
|
611
|
+
*/
|
|
612
|
+
const PAYMENT_METHODS = ["card", "bank_transfer"];
|
|
613
|
+
const PaymentMethodSchema = z.enum(PAYMENT_METHODS);
|
|
614
|
+
/**
|
|
615
|
+
* Provider form shown on steward's hosted checkout page (never returned to the product).
|
|
616
|
+
* @deprecated Ürün yüzeyinde kullanılmıyor; yalnızca servis içi. Bir sonraki minor sürümde paketin
|
|
617
|
+
* dış yüzeyinden çıkarılacak (temizlik planı C9).
|
|
618
|
+
*/
|
|
571
619
|
const ProviderPayloadSchema = z.discriminatedUnion("type", [z.object({
|
|
572
620
|
type: z.literal("html_snippet"),
|
|
573
621
|
html: z.string()
|
|
@@ -595,7 +643,11 @@ const CheckoutSessionSchema = z.object({
|
|
|
595
643
|
subscriptionId: IdSchema.nullable(),
|
|
596
644
|
expiresAt: DateTimeSchema,
|
|
597
645
|
createdAt: DateTimeSchema,
|
|
598
|
-
completedAt: DateTimeSchema.nullable()
|
|
646
|
+
completedAt: DateTimeSchema.nullable(),
|
|
647
|
+
/** Payment method chosen on the page (H6); absent (or null): not chosen yet, or an older steward. */
|
|
648
|
+
paymentMethod: PaymentMethodSchema.nullable().optional(),
|
|
649
|
+
/** The subscription this checkout replaces (H16); absent (or null): none, or an older steward. */
|
|
650
|
+
replacesSubscriptionId: IdSchema.nullable().optional()
|
|
599
651
|
});
|
|
600
652
|
/**
|
|
601
653
|
* `POST /v1/accounts/{ref}/checkout-sessions` response: `url` is steward's checkout page
|
|
@@ -640,9 +692,227 @@ const CHECKOUT_ERRORS = [
|
|
|
640
692
|
"provider_not_configured",
|
|
641
693
|
"provider_error",
|
|
642
694
|
"account_deleted",
|
|
643
|
-
"meter_already_billed"
|
|
695
|
+
"meter_already_billed",
|
|
696
|
+
"replaces_subscription_invalid"
|
|
644
697
|
];
|
|
645
698
|
//#endregion
|
|
699
|
+
//#region ../contract/src/bank-transfers.ts
|
|
700
|
+
const BankTransferRecordInputSchema = z.object({
|
|
701
|
+
/** The account's order code as written in the transfer description (`K7M2-QX9D-4`; case and separators are forgiven). */
|
|
702
|
+
code: z.string().min(1).max(40),
|
|
703
|
+
/** The amount received, minor units (kuruş, cent); must equal what the item waits for. */
|
|
704
|
+
amountMinor: z.number().int().positive(),
|
|
705
|
+
currency: CurrencySchema,
|
|
706
|
+
/** When the money reached the account. */
|
|
707
|
+
receivedAt: DateTimeSchema,
|
|
708
|
+
/** The bank's transaction / receipt number; one payment per reference. */
|
|
709
|
+
bankRef: z.string().trim().min(1).max(100),
|
|
710
|
+
/** Settle this checkout (required when several items match, and with `acceptExpired`). */
|
|
711
|
+
checkoutSessionId: IdSchema.optional(),
|
|
712
|
+
/** Pay this invoice (a checkout matches too, or a written-off invoice the transfer pays). */
|
|
713
|
+
invoiceId: IdSchema.optional(),
|
|
714
|
+
/** H10: settle the named checkout although it expired (a late transfer the operator accepts). */
|
|
715
|
+
acceptExpired: z.boolean().optional()
|
|
716
|
+
}).strict().refine((input) => !input.acceptExpired || input.checkoutSessionId !== void 0, {
|
|
717
|
+
path: ["checkoutSessionId"],
|
|
718
|
+
message: "acceptExpired needs checkoutSessionId"
|
|
719
|
+
}).refine((input) => input.checkoutSessionId === void 0 || input.invoiceId === void 0, {
|
|
720
|
+
path: ["invoiceId"],
|
|
721
|
+
message: "name either checkoutSessionId or invoiceId"
|
|
722
|
+
});
|
|
723
|
+
const BankTransferRecordedSchema = z.object({
|
|
724
|
+
accountRef: ExternalRefSchema,
|
|
725
|
+
code: z.string(),
|
|
726
|
+
/** The checkout the transfer completed; null when it paid an invoice. */
|
|
727
|
+
checkoutSessionId: IdSchema.nullable(),
|
|
728
|
+
/** The invoice the transfer paid; null when it completed a checkout. */
|
|
729
|
+
invoiceId: IdSchema.nullable(),
|
|
730
|
+
subscriptionId: IdSchema,
|
|
731
|
+
paymentId: IdSchema,
|
|
732
|
+
/** The subscription the upgrade replaced (canceled in the same transaction, H16); null: none. */
|
|
733
|
+
replacedSubscriptionId: IdSchema.nullable(),
|
|
734
|
+
/** The checkout had expired and the operator accepted the transfer (H10). */
|
|
735
|
+
acceptedAfterExpiry: z.boolean(),
|
|
736
|
+
/** The paid invoice had been written off (waived / uncollectible). */
|
|
737
|
+
paidAfterWriteoff: z.boolean(),
|
|
738
|
+
/** The account's state after the recording. */
|
|
739
|
+
account: AccountStateSchema.optional()
|
|
740
|
+
});
|
|
741
|
+
//#endregion
|
|
742
|
+
//#region ../contract/src/admin.ts
|
|
743
|
+
const API_KEY_SCOPES = [
|
|
744
|
+
"product",
|
|
745
|
+
"admin",
|
|
746
|
+
"checkout"
|
|
747
|
+
];
|
|
748
|
+
const ApiKeyScopeSchema = z.enum(API_KEY_SCOPES);
|
|
749
|
+
/** The public part of a key: the 12 hex characters after `stw_` (in logs, audit rows and `doctor`). */
|
|
750
|
+
const ApiKeyPrefixSchema = z.string().regex(/^[0-9a-f]{12}$/, "12 lowercase hex characters");
|
|
751
|
+
/**
|
|
752
|
+
* `stw_<prefix: 12 hex>_<secret: 43 base64url>`. A low-variety secret (e.g. one character
|
|
753
|
+
* repeated) is refused; `generateApiKeyToken` draws 32 random bytes.
|
|
754
|
+
*/
|
|
755
|
+
const ApiKeyTokenSchema = z.string().regex(/^stw_[0-9a-f]{12}_[A-Za-z0-9_-]{43}$/, "stw_ + 12 hex + _ + 43 base64url characters").refine((token) => new Set(token.slice(17)).size >= 16, "the secret is not random enough");
|
|
756
|
+
/** Longest expiry a key can be given, in days (about ten years). */
|
|
757
|
+
const MAX_API_KEY_TTL_DAYS = 3650;
|
|
758
|
+
const ApiKeyCreateInputSchema = z.object({
|
|
759
|
+
/** Generated by the client (`generateApiKeyToken`); never echoed back. */
|
|
760
|
+
token: ApiKeyTokenSchema,
|
|
761
|
+
name: z.string().trim().min(1).max(100),
|
|
762
|
+
scope: ApiKeyScopeSchema,
|
|
763
|
+
/**
|
|
764
|
+
* Whole days until the key expires. Omitted: the scope's default (admin 90 days, others never).
|
|
765
|
+
* null: never expires, refused for an admin key (issue #57 decision 1).
|
|
766
|
+
*/
|
|
767
|
+
expiresInDays: z.number().int().min(1).max(MAX_API_KEY_TTL_DAYS).nullable().optional()
|
|
768
|
+
}).strict().refine((input) => !(input.scope === "admin" && input.expiresInDays === null), {
|
|
769
|
+
path: ["expiresInDays"],
|
|
770
|
+
message: "an admin key must expire"
|
|
771
|
+
});
|
|
772
|
+
const ApiKeySchema = z.object({
|
|
773
|
+
prefix: ApiKeyPrefixSchema,
|
|
774
|
+
name: z.string(),
|
|
775
|
+
scope: ApiKeyScopeSchema,
|
|
776
|
+
createdAt: DateTimeSchema,
|
|
777
|
+
/** Updated at most once a minute. */
|
|
778
|
+
lastUsedAt: DateTimeSchema.nullable(),
|
|
779
|
+
expiresAt: DateTimeSchema.nullable(),
|
|
780
|
+
revokedAt: DateTimeSchema.nullable()
|
|
781
|
+
});
|
|
782
|
+
/** `GET /v1/admin/api-keys`: the product's keys, revoked and expired ones included, oldest first. */
|
|
783
|
+
const ApiKeyListSchema = z.object({ items: z.array(ApiKeySchema) });
|
|
784
|
+
/** A new API key token (`stw_…`), Web Crypto; Node ≥22, edge and workerd. Store it once, send it once. */
|
|
785
|
+
function generateApiKeyToken() {
|
|
786
|
+
const random = (n) => globalThis.crypto.getRandomValues(new Uint8Array(n));
|
|
787
|
+
return `stw_${[...random(6)].map((b) => b.toString(16).padStart(2, "0")).join("")}_${btoa(String.fromCharCode(...random(32))).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "")}`;
|
|
788
|
+
}
|
|
789
|
+
const DUNNING_ACTIONS = [
|
|
790
|
+
"retry_payment",
|
|
791
|
+
"suspend",
|
|
792
|
+
"terminate"
|
|
793
|
+
];
|
|
794
|
+
/**
|
|
795
|
+
* `products.dunning_policy`: steps by days after the first failed payment; `dryRun` only audits.
|
|
796
|
+
* Not strict: stored policies are read through it too (an unknown field must not turn a stored
|
|
797
|
+
* policy into the default).
|
|
798
|
+
*/
|
|
799
|
+
const DunningPolicySchema = z.object({
|
|
800
|
+
steps: z.array(z.object({
|
|
801
|
+
afterDays: z.number().min(0).max(365),
|
|
802
|
+
action: z.enum(DUNNING_ACTIONS)
|
|
803
|
+
})).refine((steps) => steps.every((s, i) => i === 0 || s.afterDays >= steps[i - 1].afterDays), "steps must be in order of days"),
|
|
804
|
+
dryRun: z.boolean().default(true)
|
|
805
|
+
});
|
|
806
|
+
/** `POST /v1/admin/events/:id/redeliver`: every delivery of the event requeued, attempts reset. */
|
|
807
|
+
const RedeliveredEventSchema = z.object({
|
|
808
|
+
eventId: EventIdSchema,
|
|
809
|
+
type: z.string(),
|
|
810
|
+
deliveries: z.array(z.object({
|
|
811
|
+
endpointId: IdSchema,
|
|
812
|
+
status: z.enum([
|
|
813
|
+
"pending",
|
|
814
|
+
"delivered",
|
|
815
|
+
"dead"
|
|
816
|
+
]),
|
|
817
|
+
attempts: z.number().int().nonnegative(),
|
|
818
|
+
nextAttemptAt: DateTimeSchema
|
|
819
|
+
}))
|
|
820
|
+
});
|
|
821
|
+
const MAX_NOTICE_DAYS = 3650;
|
|
822
|
+
const RepriceInputSchema = z.object({
|
|
823
|
+
planCode: CodeSchema,
|
|
824
|
+
/** The move takes effect from the first period boundary at least this many days away. */
|
|
825
|
+
noticeDays: z.number().int().min(0).max(MAX_NOTICE_DAYS),
|
|
826
|
+
/** true: the same list, nothing written and no e-mail. Required so a real run is never implicit. */
|
|
827
|
+
dryRun: z.boolean()
|
|
828
|
+
}).strict();
|
|
829
|
+
const RepriceItemSchema = z.object({
|
|
830
|
+
subscriptionId: IdSchema,
|
|
831
|
+
accountRef: ExternalRefSchema,
|
|
832
|
+
interval: IntervalSchema,
|
|
833
|
+
currency: CurrencySchema,
|
|
834
|
+
oldAmountMinor: z.number().int(),
|
|
835
|
+
newAmountMinor: z.number().int(),
|
|
836
|
+
taxInclusive: z.boolean(),
|
|
837
|
+
/** The boundary the current amount applies from; null for a skipped subscription. */
|
|
838
|
+
effectiveAt: DateTimeSchema.nullable(),
|
|
839
|
+
action: z.enum([
|
|
840
|
+
"schedule",
|
|
841
|
+
"already_scheduled",
|
|
842
|
+
"skip"
|
|
843
|
+
]),
|
|
844
|
+
reason: z.enum([
|
|
845
|
+
"cancel_scheduled",
|
|
846
|
+
"change_scheduled",
|
|
847
|
+
"legacy_provider",
|
|
848
|
+
"no_period"
|
|
849
|
+
]).optional(),
|
|
850
|
+
/** The metered rates that change (locked → current); absent when none does. */
|
|
851
|
+
meteredRates: z.array(PriceChangeNoticeMeteredRateSchema).optional()
|
|
852
|
+
});
|
|
853
|
+
const RepriceResultSchema = z.object({
|
|
854
|
+
dryRun: z.boolean(),
|
|
855
|
+
/** The earliest boundary a move can take effect at (now + notice days). */
|
|
856
|
+
effectiveNotBefore: DateTimeSchema,
|
|
857
|
+
/** Subscriptions scheduled by this run (one notice e-mail each); 0 on a dry run. */
|
|
858
|
+
scheduled: z.number().int().nonnegative(),
|
|
859
|
+
items: z.array(RepriceItemSchema)
|
|
860
|
+
});
|
|
861
|
+
/** `POST /v1/admin/accounts/:ref/meters/recompute`: every meter, or one. */
|
|
862
|
+
const MeterRecomputeInputSchema = z.object({ meter: CodeSchema.optional() }).strict();
|
|
863
|
+
const MeterRecomputeResultSchema = z.object({ items: z.array(z.object({
|
|
864
|
+
meter: CodeSchema,
|
|
865
|
+
/** The open period rebuilt; null when the account has no open period of the meter. */
|
|
866
|
+
periodStart: DateTimeSchema.nullable(),
|
|
867
|
+
periodEnd: DateTimeSchema.nullable(),
|
|
868
|
+
/** Consumption before and after (decimal strings). */
|
|
869
|
+
before: z.string().nullable(),
|
|
870
|
+
after: z.string().nullable()
|
|
871
|
+
})) });
|
|
872
|
+
/** `POST /v1/admin/accounts/:ref/meters/close-periods`: `force` does not wait for unrolled events. */
|
|
873
|
+
const MeterClosePeriodsInputSchema = z.object({
|
|
874
|
+
meter: CodeSchema.optional(),
|
|
875
|
+
force: z.boolean().optional()
|
|
876
|
+
}).strict();
|
|
877
|
+
const MeterClosePeriodsResultSchema = z.object({
|
|
878
|
+
closed: z.number().int().nonnegative(),
|
|
879
|
+
/** `meter.period_closed` events written. */
|
|
880
|
+
events: z.number().int().nonnegative(),
|
|
881
|
+
/** Closing periods left (not ended yet, or waiting for the rollup). */
|
|
882
|
+
pending: z.number().int().nonnegative()
|
|
883
|
+
});
|
|
884
|
+
/**
|
|
885
|
+
* `POST /v1/admin/accounts/:ref/credits`: positive units = `manual_grant` (as the product route),
|
|
886
|
+
* negative = `adjustment` (a correction; admin only, issue #57 decision 3). Response:
|
|
887
|
+
* `CreditGrantResponseSchema`.
|
|
888
|
+
*/
|
|
889
|
+
const CreditAdjustmentInputSchema = z.object({
|
|
890
|
+
meter: CodeSchema,
|
|
891
|
+
units: z.number().min(-MAX_METER_UNITS).max(MAX_METER_UNITS).refine((value) => value !== 0, "must not be zero").refine((value) => isMicroPrecise(value), "at most 6 decimal places"),
|
|
892
|
+
reason: z.string().trim().min(3).max(500)
|
|
893
|
+
}).strict();
|
|
894
|
+
const BANK_TRANSFER_LIST_STATUSES = ["pending", "expired"];
|
|
895
|
+
const BankTransferListStatusSchema = z.enum(BANK_TRANSFER_LIST_STATUSES);
|
|
896
|
+
const BankTransferListItemSchema = z.object({
|
|
897
|
+
kind: z.enum(["checkout", "invoice"]),
|
|
898
|
+
id: IdSchema,
|
|
899
|
+
/** The session status, or the invoice's payment status. */
|
|
900
|
+
status: z.string(),
|
|
901
|
+
/** The checkout's plan, or the invoice's subscription plan (null: none). */
|
|
902
|
+
planCode: z.string().nullable(),
|
|
903
|
+
totalMinor: z.number().int(),
|
|
904
|
+
currency: CurrencySchema,
|
|
905
|
+
/** The session's expiry, or the invoice's due date (null: none). */
|
|
906
|
+
deadline: DateTimeSchema.nullable(),
|
|
907
|
+
/** The account's order code (in the transfer description). */
|
|
908
|
+
code: z.string().nullable(),
|
|
909
|
+
accountRef: ExternalRefSchema,
|
|
910
|
+
/** When bank transfer was chosen (checkouts); null for invoices. */
|
|
911
|
+
selectedAt: DateTimeSchema.nullable()
|
|
912
|
+
});
|
|
913
|
+
/** `GET /v1/admin/bank-transfers`: `pending` by deadline; `expired`: expired in the last 30 days. */
|
|
914
|
+
const BankTransferListSchema = z.object({ items: z.array(BankTransferListItemSchema) });
|
|
915
|
+
//#endregion
|
|
646
916
|
//#region ../contract/src/portal.ts
|
|
647
917
|
const PortalSessionCreateInputSchema = z.object({
|
|
648
918
|
/** Sayfa dili; verilmezse ürün ayarı `defaultLocale`. */
|
|
@@ -1034,6 +1304,11 @@ const ERROR_CODES = Object.freeze({
|
|
|
1034
1304
|
actor_ref_required: spec(400, "validation"),
|
|
1035
1305
|
idempotency_key_required: spec(400, "validation"),
|
|
1036
1306
|
invalid_idempotency_key: spec(400, "validation"),
|
|
1307
|
+
/**
|
|
1308
|
+
* The request body is over the route's limit (`/v1`: 64 KiB; catalog sync 1 MiB; invoice issue
|
|
1309
|
+
* 10 MiB). Event ingest keeps its own code (`batch_too_large`).
|
|
1310
|
+
*/
|
|
1311
|
+
payload_too_large: spec(413, "validation"),
|
|
1037
1312
|
/** Anahtar yok / iptal / yanlış — neden ayrıştırılmaz. */
|
|
1038
1313
|
unauthorized: spec(401, "config"),
|
|
1039
1314
|
/** Admin kapsamı gereken uç. */
|
|
@@ -1052,6 +1327,22 @@ const ERROR_CODES = Object.freeze({
|
|
|
1052
1327
|
checkout_session_not_found: spec(404, "not_found"),
|
|
1053
1328
|
/** Yönetim ucu: endpoint yok ya da başka ürünün. */
|
|
1054
1329
|
webhook_endpoint_not_found: spec(404, "not_found"),
|
|
1330
|
+
/** Admin endpoint (issue #57): no API key of the product has this prefix. */
|
|
1331
|
+
api_key_not_found: spec(404, "not_found"),
|
|
1332
|
+
/** Admin endpoint (issue #57): no event of the product has this id. */
|
|
1333
|
+
event_not_found: spec(404, "not_found"),
|
|
1334
|
+
/**
|
|
1335
|
+
* `POST /v1/admin/webhook-endpoints`: the URL fails the SSRF policy (through the Ingress only public
|
|
1336
|
+
* `https://` names resolving to public addresses; cluster addresses only from inside the cluster).
|
|
1337
|
+
* The message says which rule.
|
|
1338
|
+
*/
|
|
1339
|
+
webhook_url_not_allowed: spec(422, "validation"),
|
|
1340
|
+
/** `POST /v1/admin/api-keys`: a key with this prefix already exists (generate a new token). */
|
|
1341
|
+
api_key_exists: spec(409, "conflict"),
|
|
1342
|
+
/** `POST /v1/admin/api-keys/:prefix/revoke`: a key cannot revoke itself (revoke it with another admin key). */
|
|
1343
|
+
api_key_self_revoke: spec(409, "conflict"),
|
|
1344
|
+
/** `PATCH /v1/admin/settings`: the `provider` is not configured in this deployment. */
|
|
1345
|
+
provider_not_available: spec(422, "validation"),
|
|
1055
1346
|
/** Ürün için henüz katalog senkronlanmadı (404 ama kurulum eksiği). */
|
|
1056
1347
|
catalog_not_configured: spec(404, "config"),
|
|
1057
1348
|
plan_missing_feature: spec(422, "validation"),
|
|
@@ -1065,12 +1356,14 @@ const ERROR_CODES = Object.freeze({
|
|
|
1065
1356
|
already_subscribed: spec(409, "conflict"),
|
|
1066
1357
|
already_canceled: spec(409, "conflict"),
|
|
1067
1358
|
/**
|
|
1068
|
-
* LEGACY — no longer produced (billing core, M35: no plan rank). Steward before the billing core
|
|
1359
|
+
* @deprecated LEGACY — no longer produced (billing core, M35: no plan rank). Steward before the billing core
|
|
1069
1360
|
* answered `PUT …/plan` `mode: "strict"` with it when a live subscription's plan outranked the
|
|
1070
1361
|
* target. Kept so clients that handle it keep compiling.
|
|
1071
1362
|
*/
|
|
1072
1363
|
subscription_plan_higher: spec(409, "conflict"),
|
|
1073
1364
|
plan_not_sellable: spec(422, "validation"),
|
|
1365
|
+
/** Checkout `replacesSubscriptionId` (bank transfer plan H16): not a live subscription of the account. */
|
|
1366
|
+
replaces_subscription_invalid: spec(422, "validation"),
|
|
1074
1367
|
/**
|
|
1075
1368
|
* F4e: hesap silinmiş (anonimleştirilmiş). `/v1/accounts/:ref` altındaki her uç (tekrar
|
|
1076
1369
|
* `DELETE` ve aynı ref'le `PUT` dahil) 410 döner; hesap geri açılmaz.
|
|
@@ -1078,13 +1371,26 @@ const ERROR_CODES = Object.freeze({
|
|
|
1078
1371
|
account_deleted: spec(410, "not_found"),
|
|
1079
1372
|
/** `DELETE /v1/accounts/:ref`: canlı abonelik (dönem sonunda iptali planlı dahil) var; önce hemen iptal. */
|
|
1080
1373
|
subscription_active: spec(409, "conflict"),
|
|
1081
|
-
/**
|
|
1374
|
+
/**
|
|
1375
|
+
* `DELETE /v1/accounts/:ref`: sağlayıcı formu açık ya da havale bekleyen (bank transfer plan H5) checkout
|
|
1376
|
+
* oturumu var; kapanınca (süre dolumu, ödeme kaydı) tekrar dene.
|
|
1377
|
+
*/
|
|
1082
1378
|
checkout_in_progress: spec(409, "conflict", true),
|
|
1083
1379
|
/** `successUrl`, `cancelUrl` or portal `returnUrl` is not in the product's allowed origins: product misconfiguration. */
|
|
1084
1380
|
return_url_not_allowed: spec(422, "config"),
|
|
1085
1381
|
/** Bu deployment'ta sağlayıcı yapılandırılmamış (503 ama beklemekle düzelmez). */
|
|
1086
1382
|
provider_not_configured: spec(503, "config"),
|
|
1087
1383
|
provider_error: spec(502, "provider"),
|
|
1384
|
+
/** Not an order code, or its check symbol does not match (a typo in the transfer description). */
|
|
1385
|
+
bank_transfer_code_invalid: spec(422, "validation"),
|
|
1386
|
+
/** No account of the product has this order code. */
|
|
1387
|
+
bank_transfer_code_not_found: spec(404, "not_found"),
|
|
1388
|
+
/** This bank reference is already recorded. */
|
|
1389
|
+
bank_transfer_duplicate: spec(409, "conflict"),
|
|
1390
|
+
/** Nothing of the account waits for exactly this amount, or several items do (name one), or the named checkout is not one. */
|
|
1391
|
+
bank_transfer_unmatched: spec(422, "conflict"),
|
|
1392
|
+
/** The checkout expired (only `acceptExpired` settles it), is closed or cannot be completed: refund the transfer. */
|
|
1393
|
+
bank_transfer_rejected: spec(409, "conflict"),
|
|
1088
1394
|
already_issued: spec(409, "conflict"),
|
|
1089
1395
|
number_taken: spec(409, "conflict"),
|
|
1090
1396
|
invalid_document: spec(422, "validation"),
|
|
@@ -1126,14 +1432,21 @@ const ERROR_CODES = Object.freeze({
|
|
|
1126
1432
|
internal_error: spec(500, "unavailable", true),
|
|
1127
1433
|
/** `/health`: veritabanına ulaşılamıyor. */
|
|
1128
1434
|
database_unavailable: spec(503, "unavailable", true),
|
|
1129
|
-
/**
|
|
1435
|
+
/**
|
|
1436
|
+
* Always with `Retry-After` (seconds). `/v1`: the key's budget for the route is spent, or the client
|
|
1437
|
+
* IP is blocked after too many rejected keys (`service/src/http/rate-limit.ts`, issue #43). Hosted
|
|
1438
|
+
* pages: wrong page key / action limit (`hosted/routes.ts`, `hosted/portal-routes.ts`).
|
|
1439
|
+
*/
|
|
1130
1440
|
rate_limited: spec(429, "unavailable", true),
|
|
1131
1441
|
unknown_provider: spec(404, "not_found"),
|
|
1132
1442
|
bad_signature: spec(401, "config"),
|
|
1133
1443
|
invalid_payload: spec(400, "validation"),
|
|
1134
1444
|
stale_event: spec(400, "validation"),
|
|
1135
1445
|
not_configured: spec(503, "config"),
|
|
1136
|
-
/**
|
|
1446
|
+
/**
|
|
1447
|
+
* @deprecated Üretilmiyor: sağlayıcı abonelik yolu silindi (M30) ve sahte sağlayıcı da bu kodu
|
|
1448
|
+
* döndürmüyor. Eski istemciler derlensin diye duruyor; bir sonraki minor sürümde kaldırılacak.
|
|
1449
|
+
*/
|
|
1137
1450
|
unknown_subscription: spec(404, "not_found")
|
|
1138
1451
|
});
|
|
1139
1452
|
function isKnownErrorCode(code) {
|
|
@@ -1502,25 +1815,26 @@ const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
|
1502
1815
|
]);
|
|
1503
1816
|
const CLUSTER_SUFFIX = ".svc.cluster.local";
|
|
1504
1817
|
/**
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1818
|
+
* Address SYNTAX policy; null when acceptable, otherwise the reason. `allowLoopback` is false in
|
|
1819
|
+
* production. Separate from the schema: only the service knows whether it runs in production. The
|
|
1820
|
+
* service adds the SSRF rules on top (who may register a cluster address, public names only, DNS
|
|
1821
|
+
* resolving to public addresses; `service/src/domain/webhook-url-policy.ts`).
|
|
1508
1822
|
*/
|
|
1509
1823
|
function webhookEndpointUrlProblem(value, options) {
|
|
1510
1824
|
let url;
|
|
1511
1825
|
try {
|
|
1512
1826
|
url = new URL(value);
|
|
1513
1827
|
} catch {
|
|
1514
|
-
return "
|
|
1828
|
+
return "not a valid url";
|
|
1515
1829
|
}
|
|
1516
|
-
if (url.username !== "" || url.password !== "") return "
|
|
1830
|
+
if (url.username !== "" || url.password !== "") return "url must not contain credentials";
|
|
1517
1831
|
if (url.protocol === "https:") return null;
|
|
1518
1832
|
const host = url.hostname.toLowerCase();
|
|
1519
1833
|
if (url.protocol === "http:") {
|
|
1520
1834
|
if (host.endsWith(CLUSTER_SUFFIX) && host.length > 18) return null;
|
|
1521
1835
|
if (options.allowLoopback && LOOPBACK_HOSTS.has(host)) return null;
|
|
1522
1836
|
}
|
|
1523
|
-
return options.allowLoopback ? "https://, cluster
|
|
1837
|
+
return options.allowLoopback ? "must be https://, cluster-internal http://*.svc.cluster.local or http://localhost" : "must be https:// or cluster-internal http://*.svc.cluster.local";
|
|
1524
1838
|
}
|
|
1525
1839
|
const EndpointUrlSchema = z.url({ protocol: /^https?$/ }).max(2e3).refine((value) => !hasSecretMarker(value), "adres sır içeremez");
|
|
1526
1840
|
const DescriptionSchema = z.string().trim().min(1).max(200).refine((value) => !hasSecretMarker(value), "açıklama sır içeremez");
|
|
@@ -1546,7 +1860,10 @@ const WebhookLastDeliverySchema = z.object({
|
|
|
1546
1860
|
"dead"
|
|
1547
1861
|
]),
|
|
1548
1862
|
httpStatus: z.number().int().nullable(),
|
|
1549
|
-
/**
|
|
1863
|
+
/**
|
|
1864
|
+
* `http_<kod>`, `timeout`, `network_error`, `endpoint_inactive`, `url_not_allowed` (the URL or the
|
|
1865
|
+
* address it resolves to fails the SSRF policy at send time); başarıda null.
|
|
1866
|
+
*/
|
|
1550
1867
|
error: z.string().nullable(),
|
|
1551
1868
|
attempts: z.number().int().nonnegative(),
|
|
1552
1869
|
at: DateTimeSchema
|
|
@@ -1559,6 +1876,11 @@ const WebhookEndpointSchema = z.object({
|
|
|
1559
1876
|
/** null: filtre yok, yalnızca 0.1'in 15 eski tipi (`LEGACY_EVENT_TYPES`). */
|
|
1560
1877
|
eventTypes: z.array(EventTypeSchema).nullable(),
|
|
1561
1878
|
description: z.string().nullable(),
|
|
1879
|
+
/**
|
|
1880
|
+
* A cluster address registered from inside the cluster (`*.svc.cluster.local`); every other
|
|
1881
|
+
* endpoint must be public `https://`. Absent from stewards before issue #43.
|
|
1882
|
+
*/
|
|
1883
|
+
internal: z.boolean().optional(),
|
|
1562
1884
|
createdAt: DateTimeSchema,
|
|
1563
1885
|
rotatedAt: DateTimeSchema.nullable(),
|
|
1564
1886
|
lastDelivery: WebhookLastDeliverySchema.nullable()
|
|
@@ -1740,6 +2062,23 @@ const DoctorEmailsSchema = z.object({
|
|
|
1740
2062
|
/** Emails are sent: transport and sender configured, at least one template on. */
|
|
1741
2063
|
ready: z.boolean()
|
|
1742
2064
|
});
|
|
2065
|
+
/** An active `api_keys` row (not revoked, not expired); issue #43. Never the secret. */
|
|
2066
|
+
const DoctorApiKeySchema = z.object({
|
|
2067
|
+
name: z.string(),
|
|
2068
|
+
/** Public prefix (`stw_<prefix>_…`): what `revoke-api-key` takes. */
|
|
2069
|
+
prefix: z.string(),
|
|
2070
|
+
/** `product` | `admin` | `checkout`; open set. */
|
|
2071
|
+
scope: z.string(),
|
|
2072
|
+
createdAt: DateTimeSchema,
|
|
2073
|
+
/** Updated at most once a minute. */
|
|
2074
|
+
lastUsedAt: DateTimeSchema.nullable(),
|
|
2075
|
+
/** null: never expires. */
|
|
2076
|
+
expiresAt: DateTimeSchema.nullable(),
|
|
2077
|
+
/** Whole days since creation. */
|
|
2078
|
+
ageDays: z.number().int().nonnegative()
|
|
2079
|
+
});
|
|
2080
|
+
/** A key expiring within this many days is a warning. */
|
|
2081
|
+
const DOCTOR_KEY_EXPIRY_WARN_DAYS = 14;
|
|
1743
2082
|
const DoctorReportSchema = z.object({
|
|
1744
2083
|
/** `error` önemde uyarı yok. */
|
|
1745
2084
|
ok: z.boolean(),
|
|
@@ -1765,6 +2104,8 @@ dryRun: z.boolean() }),
|
|
|
1765
2104
|
events: DoctorEventsSchema.optional(),
|
|
1766
2105
|
/** Metering MF5; absent without metered prices and from older steward. */
|
|
1767
2106
|
overage: DoctorOverageSchema.optional(),
|
|
2107
|
+
/** The product's active API keys, oldest first; absent from steward versions before issue #43. */
|
|
2108
|
+
apiKeys: z.array(DoctorApiKeySchema).optional(),
|
|
1768
2109
|
warnings: z.array(DoctorWarningSchema)
|
|
1769
2110
|
});
|
|
1770
2111
|
/** Email readiness from settings and the deployment's transport (pure). */
|
|
@@ -1846,7 +2187,9 @@ function buildDoctorReport(facts) {
|
|
|
1846
2187
|
if (drift > 0) warn("info", "price_drift", `${drift} live subscription(s) keep a locked amount that differs from the current price; moving them to the current price is an explicit operation`);
|
|
1847
2188
|
const legacy = facts.billing?.legacyProviderSubscriptions ?? 0;
|
|
1848
2189
|
if (legacy > 0) warn("error", "legacy_provider_subscription", `${legacy} live subscription(s) still have a provider subscription: steward never invoices them and the provider may still charge them; cancel each in the provider panel, then immediately in steward`);
|
|
1849
|
-
|
|
2190
|
+
const transferCurrencies = facts.bankTransfer?.currencies ?? [];
|
|
2191
|
+
if (!provider.configured && transferCurrencies.length > 0) warn("warning", "card_payments_unavailable", `payment provider ${provider.id} is not configured in this deployment: card payments are off, checkout offers bank transfer only (${transferCurrencies.join(", ")})`);
|
|
2192
|
+
else if (!provider.configured) warn("error", "provider_not_configured", `ödeme sağlayıcısı ${provider.id} bu deployment'ta yapılandırılmamış`);
|
|
1850
2193
|
else if (provider.healthy === false) warn("warning", "provider_unhealthy", `ödeme sağlayıcısı ${provider.id} art arda erişilemedi (yanıtı veren pod'un gözlemi)`);
|
|
1851
2194
|
const returnOrigins = returnOriginsOf(settings);
|
|
1852
2195
|
if (returnOrigins.length === 0) warn("error", "no_return_origin", "checkout dönüşüne izinli origin yok: `appUrl` ayarlanmalı (her checkout return_url_not_allowed alır)");
|
|
@@ -1888,6 +2231,15 @@ function buildDoctorReport(facts) {
|
|
|
1888
2231
|
else if (overage.chargeMode === "dry_run") warn("info", "overage_dry_run", "metering.chargeMode is dry_run: overage is priced into meter charges (GET /v1/accounts/:ref/meter-charges) but not invoiced; switch to live after one full cycle");
|
|
1889
2232
|
}
|
|
1890
2233
|
if (overage && overage.unratedSubscriptions > 0) warn("info", "overage_unrated_subscriptions", `${overage.unratedSubscriptions} live subscription(s) have no locked rate for a metered price of their plan (added after they started, M20): their overage is not billed until they move to the current terms`);
|
|
2234
|
+
const DAY_MS = 864e5;
|
|
2235
|
+
const apiKeys = facts.apiKeys?.map((key) => ({
|
|
2236
|
+
...key,
|
|
2237
|
+
ageDays: Math.max(0, Math.floor((facts.checkedAt.getTime() - Date.parse(key.createdAt)) / DAY_MS))
|
|
2238
|
+
}));
|
|
2239
|
+
for (const key of apiKeys ?? []) if (key.expiresAt !== null) {
|
|
2240
|
+
const daysLeft = (Date.parse(key.expiresAt) - facts.checkedAt.getTime()) / DAY_MS;
|
|
2241
|
+
if (daysLeft <= 14) warn("warning", "api_key_expiring", `${key.scope} key "${key.name}" (${key.prefix}) expires in ${Math.max(0, Math.ceil(daysLeft))} day(s): create a new key and revoke this one`);
|
|
2242
|
+
} else if (key.scope === "admin") warn("info", "admin_key_without_expiry", `admin key "${key.name}" (${key.prefix}) never expires: replace it with a key created with an expiry`);
|
|
1891
2243
|
return {
|
|
1892
2244
|
ok: !warnings.some((w) => w.severity === "error"),
|
|
1893
2245
|
checkedAt: facts.checkedAt.toISOString(),
|
|
@@ -1905,8 +2257,9 @@ function buildDoctorReport(facts) {
|
|
|
1905
2257
|
...facts.billing ? { billing: facts.billing } : {},
|
|
1906
2258
|
...facts.events ? { events: facts.events } : {},
|
|
1907
2259
|
...overage ? { overage } : {},
|
|
2260
|
+
...apiKeys ? { apiKeys } : {},
|
|
1908
2261
|
warnings
|
|
1909
2262
|
};
|
|
1910
2263
|
}
|
|
1911
2264
|
//#endregion
|
|
1912
|
-
export {
|
|
2265
|
+
export { periodBoundsOf as $, EventsSettingsSchema as $n, ApiKeySchema as $t, WebhookEndpointCreateInputSchema as A, INDIVIDUAL_IDENTITY_PLACEHOLDER as An, METERED_PRICE_TAX_MISMATCH as Ar, InvoiceStatusSchema as At, PlanSetInputSchema as B, BillingSettingsSchema as Bn, GrantSchema as Bt, emailReadinessOf as C, CheckoutConsentInputSchema as Cn, CatalogSyncResultSchema as Cr, STEWARD_CAPABILITIES as Ct, EventTypeSchema as D, CheckoutSessionSchema as Dn, MAX_CATALOG_METERED_PRICES as Dr, InvoicePaymentSessionCreateInputSchema as Dt, DEFAULT_ENDPOINT_EVENT_TYPES as E, CheckoutSessionCreatedSchema as En, MAX_CATALOG_BENEFITS as Er, InvoiceLineSchema as Et, WebhookLastDeliverySchema as F, checkoutRedirectUrl as Fn, ManualInvoiceLineInputSchema as Ft, addUtcMonths as G, DEFAULT_EVENT_RETENTION_DAYS as Gn, SubscriptionSchema as Gt, PlanSetResponseSchema as H, BrandingSchema as Hn, PaymentSchema as Ht, WebhookSecretSchema as I, BankTransferPaymentDaysSchema as In, manualInvoiceTotals as It, matchesFilter as J, DEFAULT_MIN_INVOICE_MINOR as Jn, PortalSessionSchema as Jt, consumptionOf as K, DEFAULT_LATE_GRACE_MINUTES as Kn, PORTAL_SESSION_ERRORS as Kt, generateWebhookSecret as L, BankTransferSettingsPatchSchema as Ln, splitInclusiveTax as Lt, WebhookEndpointRotateInputSchema as M, PAYMENT_METHODS as Mn, PriceDefSchema as Mr, InvoiceWaiveInputSchema as Mt, WebhookEndpointSchema as N, PaymentMethodSchema as Nn, PriceSchema as Nr, MANUAL_INVOICE_MAX_AMOUNT_MINOR as Nt, WEBHOOK_ENDPOINT_STATUSES as O, CheckoutStatusSchema as On, MAX_CATALOG_METERS as Or, InvoicePaymentSessionSchema as Ot, WebhookEndpointStatusSchema as P, ProviderPayloadSchema as Pn, ManualInvoiceInputSchema as Pt, overageOf as Q, EventsSettingsPatchSchema as Qn, ApiKeyPrefixSchema as Qt, webhookEndpointUrlProblem as R, BankTransferSettingsSchema as Rn, CancelSubscriptionInputSchema as Rt, buildDoctorReport as S, CHECKOUT_ERRORS as Sn, CatalogSyncInputSchema as Sr, MeResponseSchema as St, hostedReadinessOf as T, CheckoutSessionCreateInputSchema as Tn, FeatureTypeSchema as Tr, InvoiceIssueInputSchema as Tt, PlanSetWarningSchema as U, DEFAULT_BANK_TRANSFER_PAYMENT_DAYS as Un, StatsSchema as Ut, PlanSetModeSchema as V, BrandingPatchSchema as Vn, MAX_GRANT_BENEFITS as Vt, ResyncResultSchema as W, DEFAULT_CHECKOUT_TTL_MINUTES as Wn, SubscriptionChangeInputSchema as Wt, meterCreditsOf as X, DEFAULT_PORTAL_TTL_MINUTES as Xn, ApiKeyCreateInputSchema as Xt, meterChargeTotals as Y, DEFAULT_PAYMENT_DUE_DAYS as Yn, API_KEY_SCOPES as Yt, overageCapReached as Z, EventRetentionDaysSchema as Zn, ApiKeyListSchema as Zt, DoctorReportSchema as _, RepriceItemSchema as _n, meteringSettingsOf as _r, HEADER_SDK as _t, DOCTOR_REQUIRED_LEGAL_LINKS as a, BankTransferListStatusSchema as an, PaymentDueDaysSchema as ar, isKnownErrorCode as at, DoctorUnsellablePriceSchema as b, BankTransferRecordInputSchema as bn, CatalogPlanSchema as br, InvoiceWaiveResponseSchema as bt, DoctorApiKeySchema as c, DunningPolicySchema as cn, ReturnOriginSchema as cr, CancelSubscriptionResponseSchema as ct, DoctorEmailsSchema as d, MeterClosePeriodsInputSchema as dn, TtlMinutesSchema as dr, CreditGrantResponseSchema as dt, ApiKeyScopeSchema as en, LateGraceMinutesSchema as er, rateOverage as et, DoctorEndpointSchema as f, MeterClosePeriodsResultSchema as fn, WebUrlSchema as fr, GrantCreateResponseSchema as ft, DoctorProviderSchema as g, RepriceInputSchema as gn, isReturnUrlAllowed as gr, HEADER_REQUEST_ID as gt, DoctorOverageSchema as h, RedeliveredEventSchema as hn, eventsSettingsOf as hr, HEADER_IDEMPOTENCY_KEY as ht, DOCTOR_REQUIRED_BRANDING as i, BankTransferListSchema as in, MeteringSettingsSchema as ir, errorCodeSpec as it, WebhookEndpointListSchema as j, MAX_CHECKOUT_CONSENT_DOCS as jn, PlanDefSchema as jr, InvoiceVoidInputSchema as jt, WEBHOOK_SECRET_PREFIX as k, ConsentSchema as kn, MAX_PLAN_BENEFITS as kr, InvoiceSchema as kt, DoctorBillingSchema as l, MAX_API_KEY_TTL_DAYS as ln, SETTINGS_LOCALES as lr, ChangeSubscriptionResponseSchema as lt, DoctorHostedSchema as m, MeterRecomputeResultSchema as mn, billingSettingsOf as mr, HEADER_API_VERSION as mt, DOCTOR_PENDING_BACKLOG_MS as n, BANK_TRANSFER_LIST_STATUSES as nn, MeterChargeModeSchema as nr, standingOf as nt, DOCTOR_ROLLUP_LAG_WARN_SECONDS as o, CreditAdjustmentInputSchema as on, ProductSettingsPatchSchema as or, AccountDetailSchema as ot, DoctorEventsSchema as p, MeterRecomputeInputSchema as pn, applySettingsPatch as pr, HEADER_ACTOR_REF as pt, contributionOf as q, DEFAULT_METER_CHARGE_MODE as qn, PortalSessionCreateInputSchema as qt, DOCTOR_PROVIDER_ENVIRONMENTS as r, BankTransferListItemSchema as rn, MeteringSettingsPatchSchema as rr, ERROR_CODES as rt, DOCTOR_SEVERITIES as s, DUNNING_ACTIONS as sn, ProductSettingsSchema as sr, AccountUpsertResponseSchema as st, DOCTOR_KEY_EXPIRY_WARN_DAYS as t, ApiKeyTokenSchema as tn, METER_CHARGE_MODES as tr, rolloverOf as tt, DoctorCatalogSchema as u, MAX_NOTICE_DAYS as un, SettingsLocaleSchema as ur, CheckoutSessionResponseSchema as ut, DoctorSettingsSchema as v, RepriceResultSchema as vn, returnOriginsOf as vr, InvoiceIssueResponseSchema as vt, endpointDiagnosisOf as w, CheckoutPrefillSchema as wn, FeatureDefSchema as wr, UncancelSubscriptionResponseSchema as wt, DoctorWarningSchema as x, BankTransferRecordedSchema as xn, CatalogSchema as xr, ManualInvoiceResponseSchema as xt, DoctorSeveritySchema as y, generateApiKeyToken as yn, AccountsRefreshResultSchema as yr, InvoiceVoidResponseSchema as yt, PLAN_SET_MODES as z, BillingSettingsPatchSchema as zn, GrantCreateInputSchema as zt };
|
|
@@ -5,7 +5,7 @@ declare const UNIT_DECIMALS = 6;
|
|
|
5
5
|
declare const MICRO_UNITS_PER_UNIT = 1000000n;
|
|
6
6
|
/** A unit value that is not a finite, non-negative decimal (M4 `invalid_value`). */
|
|
7
7
|
declare class InvalidUnitValueError extends RangeError {
|
|
8
|
-
readonly code:
|
|
8
|
+
readonly code: 'invalid_value';
|
|
9
9
|
constructor(value: unknown);
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -61,7 +61,7 @@ declare function isValidVkn(value: unknown): boolean;
|
|
|
61
61
|
* (iyzico'nun istediği biçim).
|
|
62
62
|
*/
|
|
63
63
|
declare function isE164(value: unknown, options?: {
|
|
64
|
-
country?:
|
|
64
|
+
country?: 'TR';
|
|
65
65
|
}): boolean;
|
|
66
66
|
//#endregion
|
|
67
67
|
export { MICRO_UNITS_PER_UNIT as a, isMicroPrecise as c, plainDecimalOf as d, toMicroUnits as f, InvalidUnitValueError as i, microToDecimalString as l, isValidTckn as n, UNIT_DECIMALS as o, isValidVkn as r, fromMicroUnits as s, isE164 as t, parseMicroUnits as u };
|