@usethrottle/discounts 0.4.0 → 0.5.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 CHANGED
@@ -68,7 +68,7 @@ await discounts.create({
68
68
 
69
69
  await discounts.create({
70
70
  code: 'FIVE-OFF',
71
- name: '$5 off',
71
+ name: 'Spring discount',
72
72
  type: 'fixed_amount',
73
73
  value: 500,
74
74
  });
@@ -82,6 +82,15 @@ amount discounts.
82
82
  repeat customer use, or `null` for unlimited customer redemptions. Redemption
83
83
  usage is counted when a discounted cart becomes an order.
84
84
 
85
+ ## Money
86
+
87
+ Amounts are integers in the currency's minor unit. `validate` and `preview`
88
+ answer `minimum` and `shortfall` money values (`{ amount, currency, display }`)
89
+ when the order is under a code's minimum. Show them with
90
+ `formatMoney(amount, currency)`: this package re-exports `@usethrottle/money`
91
+ as `money` and `formatMoney` by name, plus the `CurrencyCode` and `MoneyValue`
92
+ types.
93
+
85
94
  ## API Key Safety
86
95
 
87
96
  This package sends `X-API-Key` to the Throttle API. Use it from a trusted server
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,16 +17,35 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
33
+ CURRENCIES: () => import_money.CURRENCIES,
23
34
  DiscountsClient: () => DiscountsClient,
24
35
  ThrottleDiscountsError: () => ThrottleDiscountsError,
25
36
  ThrottleError: () => import_errors2.ThrottleError,
37
+ UnknownCurrencyError: () => import_money.UnknownCurrencyError,
26
38
  createDiscountsClient: () => createDiscountsClient,
27
- isThrottleError: () => import_errors2.isThrottleError
39
+ currencySymbol: () => import_money.currencySymbol,
40
+ formatMoney: () => import_money.formatMoney,
41
+ isKnownCurrency: () => import_money.isKnownCurrency,
42
+ isThrottleError: () => import_errors2.isThrottleError,
43
+ minorUnitsOf: () => import_money.minorUnitsOf,
44
+ money: () => money,
45
+ moneyValue: () => import_money.moneyValue,
46
+ parseMoney: () => import_money.parseMoney,
47
+ toDecimalString: () => import_money.toDecimalString,
48
+ toMinor: () => import_money.toMinor
28
49
  });
29
50
  module.exports = __toCommonJS(index_exports);
30
51
 
@@ -77,7 +98,8 @@ var DiscountsClient = class {
77
98
  code: json?.error?.code ?? "unknown_error",
78
99
  message: json?.error?.message ?? `HTTP ${res.status}`,
79
100
  statusCode: res.status,
80
- details: json?.error?.details
101
+ details: json?.error?.details,
102
+ responseHeaders: res.headers
81
103
  });
82
104
  }
83
105
  return {
@@ -154,11 +176,26 @@ function serializeDates(input) {
154
176
  }
155
177
  return out;
156
178
  }
179
+
180
+ // src/index.ts
181
+ var money = __toESM(require("@usethrottle/money"), 1);
182
+ var import_money = require("@usethrottle/money");
157
183
  // Annotate the CommonJS export names for ESM import in node:
158
184
  0 && (module.exports = {
185
+ CURRENCIES,
159
186
  DiscountsClient,
160
187
  ThrottleDiscountsError,
161
188
  ThrottleError,
189
+ UnknownCurrencyError,
162
190
  createDiscountsClient,
163
- isThrottleError
191
+ currencySymbol,
192
+ formatMoney,
193
+ isKnownCurrency,
194
+ isThrottleError,
195
+ minorUnitsOf,
196
+ money,
197
+ moneyValue,
198
+ parseMoney,
199
+ toDecimalString,
200
+ toMinor
164
201
  });
package/dist/index.d.cts CHANGED
@@ -1,7 +1,21 @@
1
- import { ThrottleError } from '@usethrottle/errors';
1
+ import { CurrencyCode, MoneyValue } from '@usethrottle/money';
2
+ import * as money from '@usethrottle/money';
3
+ export { money };
4
+ export { CURRENCIES, CurrencyCode, MoneyValue, UnknownCurrencyError, currencySymbol, formatMoney, isKnownCurrency, minorUnitsOf, moneyValue, parseMoney, toDecimalString, toMinor } from '@usethrottle/money';
5
+ import { ThrottleError, ThrottleErrorArgs } from '@usethrottle/errors';
2
6
  export { ThrottleError, isThrottleError } from '@usethrottle/errors';
3
7
 
4
8
  type DiscountType = 'percentage' | 'fixed_amount';
9
+ /**
10
+ * Per-currency amounts in minor units, keyed by currency code:
11
+ * `{ EUR: { value: 900, minOrder: 4500 } }`. A currency with no entry is not
12
+ * offered; amounts are never converted. `Partial` because `CurrencyCode` lists
13
+ * every ISO code as a literal: a plain `Record` would require all of them.
14
+ */
15
+ type DiscountAmounts = Partial<Record<CurrencyCode, {
16
+ value?: number;
17
+ minOrder?: number;
18
+ }>>;
5
19
  interface Discount {
6
20
  id: string;
7
21
  code: string | null;
@@ -17,6 +31,8 @@ interface Discount {
17
31
  endsAt?: string | null;
18
32
  metadata: Record<string, unknown>;
19
33
  createdAt: string;
34
+ /** Per-currency amounts; the main-currency entry mirrors `value`. */
35
+ amounts?: DiscountAmounts;
20
36
  }
21
37
  interface CreateDiscountInput {
22
38
  code?: string;
@@ -54,6 +70,11 @@ interface DiscountValidationResult {
54
70
  valid: boolean;
55
71
  discount?: Discount;
56
72
  error?: string;
73
+ currency?: CurrencyCode;
74
+ /** The code's minimum order total, when the order is under it. */
75
+ minimum?: MoneyValue;
76
+ /** How much more the order needs to reach the minimum. */
77
+ shortfall?: MoneyValue;
57
78
  }
58
79
  interface DiscountPreviewInput {
59
80
  code: string;
@@ -71,16 +92,20 @@ interface DiscountPreviewResult {
71
92
  code: string;
72
93
  type?: DiscountType;
73
94
  value?: number;
74
- currency: string;
95
+ currency: CurrencyCode;
75
96
  subtotal: number;
76
97
  discountTotal: number;
77
98
  total: number;
78
99
  discount?: Discount;
79
100
  message: string | null;
101
+ /** The code's minimum order total, when the subtotal is under it. */
102
+ minimum?: MoneyValue;
103
+ /** How much more the subtotal needs to reach the minimum. */
104
+ shortfall?: MoneyValue;
80
105
  }
81
106
  interface Cart {
82
107
  id: string;
83
- currency: string;
108
+ currency: CurrencyCode;
84
109
  subtotal: number;
85
110
  discountTotal: number;
86
111
  shippingTotal: number;
@@ -92,7 +117,7 @@ interface Cart {
92
117
  code: string;
93
118
  type: DiscountType;
94
119
  amount: number;
95
- currency: string;
120
+ currency: CurrencyCode;
96
121
  freeShipping: boolean;
97
122
  validUntil: string | null;
98
123
  snapshotHash: string;
@@ -146,7 +171,8 @@ declare class ThrottleDiscountsError extends ThrottleError {
146
171
  message: string;
147
172
  statusCode: number;
148
173
  details?: unknown;
174
+ responseHeaders?: ThrottleErrorArgs['responseHeaders'];
149
175
  });
150
176
  }
151
177
 
152
- export { type Cart, type CreateDiscountInput, type Discount, type DiscountListParams, type DiscountPreviewInput, type DiscountPreviewResult, type DiscountType, type DiscountValidationResult, DiscountsClient, type DiscountsClientOptions, type PaginatedDiscounts, ThrottleDiscountsError, type UpdateDiscountInput, createDiscountsClient };
178
+ export { type Cart, type CreateDiscountInput, type Discount, type DiscountAmounts, type DiscountListParams, type DiscountPreviewInput, type DiscountPreviewResult, type DiscountType, type DiscountValidationResult, DiscountsClient, type DiscountsClientOptions, type PaginatedDiscounts, ThrottleDiscountsError, type UpdateDiscountInput, createDiscountsClient };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,21 @@
1
- import { ThrottleError } from '@usethrottle/errors';
1
+ import { CurrencyCode, MoneyValue } from '@usethrottle/money';
2
+ import * as money from '@usethrottle/money';
3
+ export { money };
4
+ export { CURRENCIES, CurrencyCode, MoneyValue, UnknownCurrencyError, currencySymbol, formatMoney, isKnownCurrency, minorUnitsOf, moneyValue, parseMoney, toDecimalString, toMinor } from '@usethrottle/money';
5
+ import { ThrottleError, ThrottleErrorArgs } from '@usethrottle/errors';
2
6
  export { ThrottleError, isThrottleError } from '@usethrottle/errors';
3
7
 
4
8
  type DiscountType = 'percentage' | 'fixed_amount';
9
+ /**
10
+ * Per-currency amounts in minor units, keyed by currency code:
11
+ * `{ EUR: { value: 900, minOrder: 4500 } }`. A currency with no entry is not
12
+ * offered; amounts are never converted. `Partial` because `CurrencyCode` lists
13
+ * every ISO code as a literal: a plain `Record` would require all of them.
14
+ */
15
+ type DiscountAmounts = Partial<Record<CurrencyCode, {
16
+ value?: number;
17
+ minOrder?: number;
18
+ }>>;
5
19
  interface Discount {
6
20
  id: string;
7
21
  code: string | null;
@@ -17,6 +31,8 @@ interface Discount {
17
31
  endsAt?: string | null;
18
32
  metadata: Record<string, unknown>;
19
33
  createdAt: string;
34
+ /** Per-currency amounts; the main-currency entry mirrors `value`. */
35
+ amounts?: DiscountAmounts;
20
36
  }
21
37
  interface CreateDiscountInput {
22
38
  code?: string;
@@ -54,6 +70,11 @@ interface DiscountValidationResult {
54
70
  valid: boolean;
55
71
  discount?: Discount;
56
72
  error?: string;
73
+ currency?: CurrencyCode;
74
+ /** The code's minimum order total, when the order is under it. */
75
+ minimum?: MoneyValue;
76
+ /** How much more the order needs to reach the minimum. */
77
+ shortfall?: MoneyValue;
57
78
  }
58
79
  interface DiscountPreviewInput {
59
80
  code: string;
@@ -71,16 +92,20 @@ interface DiscountPreviewResult {
71
92
  code: string;
72
93
  type?: DiscountType;
73
94
  value?: number;
74
- currency: string;
95
+ currency: CurrencyCode;
75
96
  subtotal: number;
76
97
  discountTotal: number;
77
98
  total: number;
78
99
  discount?: Discount;
79
100
  message: string | null;
101
+ /** The code's minimum order total, when the subtotal is under it. */
102
+ minimum?: MoneyValue;
103
+ /** How much more the subtotal needs to reach the minimum. */
104
+ shortfall?: MoneyValue;
80
105
  }
81
106
  interface Cart {
82
107
  id: string;
83
- currency: string;
108
+ currency: CurrencyCode;
84
109
  subtotal: number;
85
110
  discountTotal: number;
86
111
  shippingTotal: number;
@@ -92,7 +117,7 @@ interface Cart {
92
117
  code: string;
93
118
  type: DiscountType;
94
119
  amount: number;
95
- currency: string;
120
+ currency: CurrencyCode;
96
121
  freeShipping: boolean;
97
122
  validUntil: string | null;
98
123
  snapshotHash: string;
@@ -146,7 +171,8 @@ declare class ThrottleDiscountsError extends ThrottleError {
146
171
  message: string;
147
172
  statusCode: number;
148
173
  details?: unknown;
174
+ responseHeaders?: ThrottleErrorArgs['responseHeaders'];
149
175
  });
150
176
  }
151
177
 
152
- export { type Cart, type CreateDiscountInput, type Discount, type DiscountListParams, type DiscountPreviewInput, type DiscountPreviewResult, type DiscountType, type DiscountValidationResult, DiscountsClient, type DiscountsClientOptions, type PaginatedDiscounts, ThrottleDiscountsError, type UpdateDiscountInput, createDiscountsClient };
178
+ export { type Cart, type CreateDiscountInput, type Discount, type DiscountAmounts, type DiscountListParams, type DiscountPreviewInput, type DiscountPreviewResult, type DiscountType, type DiscountValidationResult, DiscountsClient, type DiscountsClientOptions, type PaginatedDiscounts, ThrottleDiscountsError, type UpdateDiscountInput, createDiscountsClient };
package/dist/index.js CHANGED
@@ -47,7 +47,8 @@ var DiscountsClient = class {
47
47
  code: json?.error?.code ?? "unknown_error",
48
48
  message: json?.error?.message ?? `HTTP ${res.status}`,
49
49
  statusCode: res.status,
50
- details: json?.error?.details
50
+ details: json?.error?.details,
51
+ responseHeaders: res.headers
51
52
  });
52
53
  }
53
54
  return {
@@ -124,10 +125,36 @@ function serializeDates(input) {
124
125
  }
125
126
  return out;
126
127
  }
128
+
129
+ // src/index.ts
130
+ import * as money from "@usethrottle/money";
131
+ import {
132
+ formatMoney,
133
+ currencySymbol,
134
+ minorUnitsOf,
135
+ toDecimalString,
136
+ toMinor,
137
+ parseMoney,
138
+ moneyValue,
139
+ CURRENCIES,
140
+ isKnownCurrency,
141
+ UnknownCurrencyError
142
+ } from "@usethrottle/money";
127
143
  export {
144
+ CURRENCIES,
128
145
  DiscountsClient,
129
146
  ThrottleDiscountsError,
130
147
  ThrottleError2 as ThrottleError,
148
+ UnknownCurrencyError,
131
149
  createDiscountsClient,
132
- isThrottleError
150
+ currencySymbol,
151
+ formatMoney,
152
+ isKnownCurrency,
153
+ isThrottleError,
154
+ minorUnitsOf,
155
+ money,
156
+ moneyValue,
157
+ parseMoney,
158
+ toDecimalString,
159
+ toMinor
133
160
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usethrottle/discounts",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Headless TypeScript client for Throttle discount and promotion code APIs.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -19,7 +19,8 @@
19
19
  "CLAUDE.md"
20
20
  ],
21
21
  "dependencies": {
22
- "@usethrottle/errors": "^1.0.0"
22
+ "@usethrottle/errors": "^1.1.0",
23
+ "@usethrottle/money": "^1.0.0"
23
24
  },
24
25
  "devDependencies": {
25
26
  "tsup": "^8.0.0",
@@ -34,7 +35,7 @@
34
35
  },
35
36
  "scripts": {
36
37
  "build": "tsup",
37
- "test": "vitest run",
38
+ "test": "tsc --noEmit --strict --skipLibCheck --target es2022 --lib es2022,dom --module esnext --moduleResolution bundler __tests__/currency-types.check.ts && vitest run",
38
39
  "typecheck": "tsc --noEmit"
39
40
  }
40
41
  }