@withwiz/coupon 0.1.0 → 0.3.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/README.md +67 -2
- package/dist/index.cjs +238 -52
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.mjs +238 -53
- package/package.json +7 -6
package/dist/index.d.cts
CHANGED
|
@@ -68,6 +68,24 @@ declare const LIMITS: {
|
|
|
68
68
|
readonly PAGINATION_MAX_LIMIT: 200;
|
|
69
69
|
readonly NAME_MAX_LENGTH: 200;
|
|
70
70
|
readonly CURRENCY_LENGTH: 3;
|
|
71
|
+
/**
|
|
72
|
+
* [L] Caller-supplied identifier caps. Ids (coupon / campaign / cursor) are
|
|
73
|
+
* bounded by the audit log's `resourceId VarChar(64)`; `orderRef` by the
|
|
74
|
+
* redemption table's `VarChar(128)`. User / actor ids share the same bound
|
|
75
|
+
* so an unbounded string can never reach a Json or text column unchecked.
|
|
76
|
+
*/
|
|
77
|
+
readonly ID_MAX_LENGTH: 64;
|
|
78
|
+
readonly USER_ID_MAX_LENGTH: 128;
|
|
79
|
+
readonly ORDER_REF_MAX_LENGTH: 128;
|
|
80
|
+
/** [L] Upper bound on serialized `metadata` (bytes of JSON text). */
|
|
81
|
+
readonly METADATA_MAX_BYTES: 16384;
|
|
82
|
+
/** [L] Per-list entry cap and per-entry length cap for eligibility rules. */
|
|
83
|
+
readonly ELIGIBILITY_MAX_ENTRIES: 1000;
|
|
84
|
+
readonly ELIGIBILITY_ENTRY_MAX_LENGTH: 128;
|
|
85
|
+
/** [L] Length cap for `context.plan / productId / categoryId`. */
|
|
86
|
+
readonly CONTEXT_VALUE_MAX_LENGTH: 128;
|
|
87
|
+
/** Upper bound for `duration.months` on a REPEATING discount. */
|
|
88
|
+
readonly DURATION_MAX_MONTHS: 36;
|
|
71
89
|
};
|
|
72
90
|
/**
|
|
73
91
|
* Audit log action strings (stable identifiers).
|
|
@@ -91,17 +109,32 @@ type AuditAction = (typeof AUDIT_ACTION)[keyof typeof AUDIT_ACTION];
|
|
|
91
109
|
* No Prisma generated types imported here (see contract §10 PrismaLike rule).
|
|
92
110
|
*/
|
|
93
111
|
|
|
112
|
+
/**
|
|
113
|
+
* How many billing cycles a discount applies to. Absent = ONCE.
|
|
114
|
+
* The package records it; applying it to recurring charges is the consumer's job
|
|
115
|
+
* (re-run `calculateDiscount` per cycle with the stored policy).
|
|
116
|
+
*/
|
|
117
|
+
type DiscountDuration = {
|
|
118
|
+
kind: "ONCE";
|
|
119
|
+
} | {
|
|
120
|
+
kind: "REPEATING";
|
|
121
|
+
months: number;
|
|
122
|
+
} | {
|
|
123
|
+
kind: "FOREVER";
|
|
124
|
+
};
|
|
94
125
|
type DiscountPolicy = {
|
|
95
126
|
kind: "PERCENT";
|
|
96
127
|
percent: number;
|
|
97
128
|
maxDiscount?: number;
|
|
98
129
|
minOrder?: number;
|
|
99
130
|
currency?: string;
|
|
131
|
+
duration?: DiscountDuration;
|
|
100
132
|
} | {
|
|
101
133
|
kind: "FIXED";
|
|
102
134
|
amount: number;
|
|
103
135
|
currency: string;
|
|
104
136
|
minOrder?: number;
|
|
137
|
+
duration?: DiscountDuration;
|
|
105
138
|
};
|
|
106
139
|
type EligibilityRules = {
|
|
107
140
|
allowedUserIds?: string[];
|
|
@@ -325,6 +358,13 @@ type CampaignIssueArgs = {
|
|
|
325
358
|
codeLength?: number;
|
|
326
359
|
maxAttempts?: number;
|
|
327
360
|
actorId?: string;
|
|
361
|
+
/**
|
|
362
|
+
* Redemption limits stamped on each issued code. Unset = unlimited, which
|
|
363
|
+
* is rarely what a batch of unique codes wants: pass `maxRedemptions: 1`
|
|
364
|
+
* for single-use codes.
|
|
365
|
+
*/
|
|
366
|
+
maxRedemptions?: number | null;
|
|
367
|
+
maxRedemptionsPerUser?: number | null;
|
|
328
368
|
};
|
|
329
369
|
type CampaignSummary = {
|
|
330
370
|
id: string;
|
|
@@ -557,6 +597,15 @@ type CouponClientConfig = {
|
|
|
557
597
|
* @example { coupon: "coupons" }
|
|
558
598
|
*/
|
|
559
599
|
tables?: Partial<TableNameMap>;
|
|
600
|
+
/**
|
|
601
|
+
* Postgres schema that holds the coupon tables, used to qualify the
|
|
602
|
+
* `SELECT ... FOR UPDATE` row lock. Needed when the tables live outside
|
|
603
|
+
* `public` and the client uses a driver adapter (Prisma 7), whose raw
|
|
604
|
+
* queries resolve unqualified names through the connection's `search_path`.
|
|
605
|
+
*
|
|
606
|
+
* @example "billing"
|
|
607
|
+
*/
|
|
608
|
+
schema?: string;
|
|
560
609
|
};
|
|
561
610
|
interface CouponClient {
|
|
562
611
|
coupons: {
|
|
@@ -638,6 +687,8 @@ declare function validateDiscountPolicy(policy: DiscountPolicy): void;
|
|
|
638
687
|
* Throws MinimumOrderNotMetError if subtotal < policy.minOrder.
|
|
639
688
|
*/
|
|
640
689
|
declare function calculate(input: DiscountInput): DiscountBreakdown;
|
|
690
|
+
/** The effective duration of a policy. Policies without one apply ONCE. */
|
|
691
|
+
declare function resolveDuration(policy: DiscountPolicy): DiscountDuration;
|
|
641
692
|
|
|
642
693
|
/**
|
|
643
694
|
* Error taxonomy for @withwiz/coupon.
|
|
@@ -752,4 +803,4 @@ declare class TenantMismatchError extends CouponError {
|
|
|
752
803
|
constructor(message?: string, ctx?: CouponErrorContext);
|
|
753
804
|
}
|
|
754
805
|
|
|
755
|
-
export { AUDIT_ACTION, type AuditAction, type AuditLog, type BulkIssuanceResult, CAMPAIGN_STATUS, COUPON_REJECT_REASON, COUPON_STATUS, type Campaign, CampaignCapacityExceededError, CampaignClosedError, type CampaignIssueArgs, type CampaignStatus, type CampaignSummary, type Coupon, CouponAlreadyRedeemedError, CouponArchivedError, type CouponClient, type CouponClientConfig, CouponError, type CouponEvent, type CouponEventHandler, CouponExhaustedError, CouponExpiredError, CouponInactiveError, type CouponLogger, type CouponModelKey, CouponNotFoundError, type CouponRejectReason, type CouponStatus, type CreateCampaignInput, type CreateCouponInput, CurrencyMismatchError, DEFAULT_MODEL_NAMES, type DiscountBreakdown, type DiscountInput, type DiscountPolicy, type EligibilityRules, IneligibleCategoryError, IneligiblePlanError, IneligibleProductError, IneligibleUserError, InvalidDateRangeError, InvalidDiscountPolicyError, InvalidModelNameError, type Issuance, type IssueBulkInput, type IssueCouponInput, LIMITS, type ListAuditLogsArgs, type ListCampaignsArgs, type ListCouponsArgs, type ListIssuancesArgs, type ListRedemptionsArgs, MinimumOrderNotMetError, type ModelNameMap, type Paged, PerUserLimitExceededError, type PrismaLike, type PrismaTxLike, type RedeemInput, type Redemption, type RedemptionResult, type TableNameMap, TenantMismatchError, type ValidateContext, type ValidateInput, ValidationError, type ValidationResult, calculate as calculateDiscount, createCouponClient, validateDiscountPolicy };
|
|
806
|
+
export { AUDIT_ACTION, type AuditAction, type AuditLog, type BulkIssuanceResult, CAMPAIGN_STATUS, COUPON_REJECT_REASON, COUPON_STATUS, type Campaign, CampaignCapacityExceededError, CampaignClosedError, type CampaignIssueArgs, type CampaignStatus, type CampaignSummary, type Coupon, CouponAlreadyRedeemedError, CouponArchivedError, type CouponClient, type CouponClientConfig, CouponError, type CouponEvent, type CouponEventHandler, CouponExhaustedError, CouponExpiredError, CouponInactiveError, type CouponLogger, type CouponModelKey, CouponNotFoundError, type CouponRejectReason, type CouponStatus, type CreateCampaignInput, type CreateCouponInput, CurrencyMismatchError, DEFAULT_MODEL_NAMES, type DiscountBreakdown, type DiscountDuration, type DiscountInput, type DiscountPolicy, type EligibilityRules, IneligibleCategoryError, IneligiblePlanError, IneligibleProductError, IneligibleUserError, InvalidDateRangeError, InvalidDiscountPolicyError, InvalidModelNameError, type Issuance, type IssueBulkInput, type IssueCouponInput, LIMITS, type ListAuditLogsArgs, type ListCampaignsArgs, type ListCouponsArgs, type ListIssuancesArgs, type ListRedemptionsArgs, MinimumOrderNotMetError, type ModelNameMap, type Paged, PerUserLimitExceededError, type PrismaLike, type PrismaTxLike, type RedeemInput, type Redemption, type RedemptionResult, type TableNameMap, TenantMismatchError, type ValidateContext, type ValidateInput, ValidationError, type ValidationResult, calculate as calculateDiscount, createCouponClient, resolveDuration, validateDiscountPolicy };
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,24 @@ declare const LIMITS: {
|
|
|
68
68
|
readonly PAGINATION_MAX_LIMIT: 200;
|
|
69
69
|
readonly NAME_MAX_LENGTH: 200;
|
|
70
70
|
readonly CURRENCY_LENGTH: 3;
|
|
71
|
+
/**
|
|
72
|
+
* [L] Caller-supplied identifier caps. Ids (coupon / campaign / cursor) are
|
|
73
|
+
* bounded by the audit log's `resourceId VarChar(64)`; `orderRef` by the
|
|
74
|
+
* redemption table's `VarChar(128)`. User / actor ids share the same bound
|
|
75
|
+
* so an unbounded string can never reach a Json or text column unchecked.
|
|
76
|
+
*/
|
|
77
|
+
readonly ID_MAX_LENGTH: 64;
|
|
78
|
+
readonly USER_ID_MAX_LENGTH: 128;
|
|
79
|
+
readonly ORDER_REF_MAX_LENGTH: 128;
|
|
80
|
+
/** [L] Upper bound on serialized `metadata` (bytes of JSON text). */
|
|
81
|
+
readonly METADATA_MAX_BYTES: 16384;
|
|
82
|
+
/** [L] Per-list entry cap and per-entry length cap for eligibility rules. */
|
|
83
|
+
readonly ELIGIBILITY_MAX_ENTRIES: 1000;
|
|
84
|
+
readonly ELIGIBILITY_ENTRY_MAX_LENGTH: 128;
|
|
85
|
+
/** [L] Length cap for `context.plan / productId / categoryId`. */
|
|
86
|
+
readonly CONTEXT_VALUE_MAX_LENGTH: 128;
|
|
87
|
+
/** Upper bound for `duration.months` on a REPEATING discount. */
|
|
88
|
+
readonly DURATION_MAX_MONTHS: 36;
|
|
71
89
|
};
|
|
72
90
|
/**
|
|
73
91
|
* Audit log action strings (stable identifiers).
|
|
@@ -91,17 +109,32 @@ type AuditAction = (typeof AUDIT_ACTION)[keyof typeof AUDIT_ACTION];
|
|
|
91
109
|
* No Prisma generated types imported here (see contract §10 PrismaLike rule).
|
|
92
110
|
*/
|
|
93
111
|
|
|
112
|
+
/**
|
|
113
|
+
* How many billing cycles a discount applies to. Absent = ONCE.
|
|
114
|
+
* The package records it; applying it to recurring charges is the consumer's job
|
|
115
|
+
* (re-run `calculateDiscount` per cycle with the stored policy).
|
|
116
|
+
*/
|
|
117
|
+
type DiscountDuration = {
|
|
118
|
+
kind: "ONCE";
|
|
119
|
+
} | {
|
|
120
|
+
kind: "REPEATING";
|
|
121
|
+
months: number;
|
|
122
|
+
} | {
|
|
123
|
+
kind: "FOREVER";
|
|
124
|
+
};
|
|
94
125
|
type DiscountPolicy = {
|
|
95
126
|
kind: "PERCENT";
|
|
96
127
|
percent: number;
|
|
97
128
|
maxDiscount?: number;
|
|
98
129
|
minOrder?: number;
|
|
99
130
|
currency?: string;
|
|
131
|
+
duration?: DiscountDuration;
|
|
100
132
|
} | {
|
|
101
133
|
kind: "FIXED";
|
|
102
134
|
amount: number;
|
|
103
135
|
currency: string;
|
|
104
136
|
minOrder?: number;
|
|
137
|
+
duration?: DiscountDuration;
|
|
105
138
|
};
|
|
106
139
|
type EligibilityRules = {
|
|
107
140
|
allowedUserIds?: string[];
|
|
@@ -325,6 +358,13 @@ type CampaignIssueArgs = {
|
|
|
325
358
|
codeLength?: number;
|
|
326
359
|
maxAttempts?: number;
|
|
327
360
|
actorId?: string;
|
|
361
|
+
/**
|
|
362
|
+
* Redemption limits stamped on each issued code. Unset = unlimited, which
|
|
363
|
+
* is rarely what a batch of unique codes wants: pass `maxRedemptions: 1`
|
|
364
|
+
* for single-use codes.
|
|
365
|
+
*/
|
|
366
|
+
maxRedemptions?: number | null;
|
|
367
|
+
maxRedemptionsPerUser?: number | null;
|
|
328
368
|
};
|
|
329
369
|
type CampaignSummary = {
|
|
330
370
|
id: string;
|
|
@@ -557,6 +597,15 @@ type CouponClientConfig = {
|
|
|
557
597
|
* @example { coupon: "coupons" }
|
|
558
598
|
*/
|
|
559
599
|
tables?: Partial<TableNameMap>;
|
|
600
|
+
/**
|
|
601
|
+
* Postgres schema that holds the coupon tables, used to qualify the
|
|
602
|
+
* `SELECT ... FOR UPDATE` row lock. Needed when the tables live outside
|
|
603
|
+
* `public` and the client uses a driver adapter (Prisma 7), whose raw
|
|
604
|
+
* queries resolve unqualified names through the connection's `search_path`.
|
|
605
|
+
*
|
|
606
|
+
* @example "billing"
|
|
607
|
+
*/
|
|
608
|
+
schema?: string;
|
|
560
609
|
};
|
|
561
610
|
interface CouponClient {
|
|
562
611
|
coupons: {
|
|
@@ -638,6 +687,8 @@ declare function validateDiscountPolicy(policy: DiscountPolicy): void;
|
|
|
638
687
|
* Throws MinimumOrderNotMetError if subtotal < policy.minOrder.
|
|
639
688
|
*/
|
|
640
689
|
declare function calculate(input: DiscountInput): DiscountBreakdown;
|
|
690
|
+
/** The effective duration of a policy. Policies without one apply ONCE. */
|
|
691
|
+
declare function resolveDuration(policy: DiscountPolicy): DiscountDuration;
|
|
641
692
|
|
|
642
693
|
/**
|
|
643
694
|
* Error taxonomy for @withwiz/coupon.
|
|
@@ -752,4 +803,4 @@ declare class TenantMismatchError extends CouponError {
|
|
|
752
803
|
constructor(message?: string, ctx?: CouponErrorContext);
|
|
753
804
|
}
|
|
754
805
|
|
|
755
|
-
export { AUDIT_ACTION, type AuditAction, type AuditLog, type BulkIssuanceResult, CAMPAIGN_STATUS, COUPON_REJECT_REASON, COUPON_STATUS, type Campaign, CampaignCapacityExceededError, CampaignClosedError, type CampaignIssueArgs, type CampaignStatus, type CampaignSummary, type Coupon, CouponAlreadyRedeemedError, CouponArchivedError, type CouponClient, type CouponClientConfig, CouponError, type CouponEvent, type CouponEventHandler, CouponExhaustedError, CouponExpiredError, CouponInactiveError, type CouponLogger, type CouponModelKey, CouponNotFoundError, type CouponRejectReason, type CouponStatus, type CreateCampaignInput, type CreateCouponInput, CurrencyMismatchError, DEFAULT_MODEL_NAMES, type DiscountBreakdown, type DiscountInput, type DiscountPolicy, type EligibilityRules, IneligibleCategoryError, IneligiblePlanError, IneligibleProductError, IneligibleUserError, InvalidDateRangeError, InvalidDiscountPolicyError, InvalidModelNameError, type Issuance, type IssueBulkInput, type IssueCouponInput, LIMITS, type ListAuditLogsArgs, type ListCampaignsArgs, type ListCouponsArgs, type ListIssuancesArgs, type ListRedemptionsArgs, MinimumOrderNotMetError, type ModelNameMap, type Paged, PerUserLimitExceededError, type PrismaLike, type PrismaTxLike, type RedeemInput, type Redemption, type RedemptionResult, type TableNameMap, TenantMismatchError, type ValidateContext, type ValidateInput, ValidationError, type ValidationResult, calculate as calculateDiscount, createCouponClient, validateDiscountPolicy };
|
|
806
|
+
export { AUDIT_ACTION, type AuditAction, type AuditLog, type BulkIssuanceResult, CAMPAIGN_STATUS, COUPON_REJECT_REASON, COUPON_STATUS, type Campaign, CampaignCapacityExceededError, CampaignClosedError, type CampaignIssueArgs, type CampaignStatus, type CampaignSummary, type Coupon, CouponAlreadyRedeemedError, CouponArchivedError, type CouponClient, type CouponClientConfig, CouponError, type CouponEvent, type CouponEventHandler, CouponExhaustedError, CouponExpiredError, CouponInactiveError, type CouponLogger, type CouponModelKey, CouponNotFoundError, type CouponRejectReason, type CouponStatus, type CreateCampaignInput, type CreateCouponInput, CurrencyMismatchError, DEFAULT_MODEL_NAMES, type DiscountBreakdown, type DiscountDuration, type DiscountInput, type DiscountPolicy, type EligibilityRules, IneligibleCategoryError, IneligiblePlanError, IneligibleProductError, IneligibleUserError, InvalidDateRangeError, InvalidDiscountPolicyError, InvalidModelNameError, type Issuance, type IssueBulkInput, type IssueCouponInput, LIMITS, type ListAuditLogsArgs, type ListCampaignsArgs, type ListCouponsArgs, type ListIssuancesArgs, type ListRedemptionsArgs, MinimumOrderNotMetError, type ModelNameMap, type Paged, PerUserLimitExceededError, type PrismaLike, type PrismaTxLike, type RedeemInput, type Redemption, type RedemptionResult, type TableNameMap, TenantMismatchError, type ValidateContext, type ValidateInput, ValidationError, type ValidationResult, calculate as calculateDiscount, createCouponClient, resolveDuration, validateDiscountPolicy };
|