@dodopayments/nextjs 0.3.0 → 0.3.1

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/dist/index.cjs CHANGED
@@ -9344,7 +9344,7 @@ const unknownType = ZodUnknown.create;
9344
9344
  ZodNever.create;
9345
9345
  const arrayType = ZodArray.create;
9346
9346
  const objectType = ZodObject.create;
9347
- ZodUnion.create;
9347
+ const unionType = ZodUnion.create;
9348
9348
  const discriminatedUnionType = ZodDiscriminatedUnion.create;
9349
9349
  ZodIntersection.create;
9350
9350
  ZodTuple.create;
@@ -9563,7 +9563,7 @@ const safeJSON = (text) => {
9563
9563
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
9564
9564
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
9565
9565
 
9566
- const VERSION = '2.2.0'; // x-release-please-version
9566
+ const VERSION = '2.4.6'; // x-release-please-version
9567
9567
 
9568
9568
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
9569
9569
  /**
@@ -10313,6 +10313,9 @@ class CheckoutSessions extends APIResource {
10313
10313
  create(body, options) {
10314
10314
  return this._client.post('/checkouts', { body, ...options });
10315
10315
  }
10316
+ retrieve(id, options) {
10317
+ return this._client.get(path `/checkouts/${id}`, options);
10318
+ }
10316
10319
  }
10317
10320
 
10318
10321
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
@@ -10991,1398 +10994,323 @@ let Headers$1 = class Headers extends APIResource {
10991
10994
  }
10992
10995
  };
10993
10996
 
10994
- // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
10995
- let Webhooks$1 = class Webhooks extends APIResource {
10996
- constructor() {
10997
- super(...arguments);
10998
- this.headers = new Headers$1(this._client);
10999
- }
11000
- /**
11001
- * Create a new webhook
11002
- */
11003
- create(body, options) {
11004
- return this._client.post('/webhooks', { body, ...options });
11005
- }
11006
- /**
11007
- * Get a webhook by id
11008
- */
11009
- retrieve(webhookID, options) {
11010
- return this._client.get(path `/webhooks/${webhookID}`, options);
10997
+ var dist = {};
10998
+
10999
+ var timing_safe_equal = {};
11000
+
11001
+ Object.defineProperty(timing_safe_equal, "__esModule", { value: true });
11002
+ timing_safe_equal.timingSafeEqual = void 0;
11003
+ function assert(expr, msg = "") {
11004
+ if (!expr) {
11005
+ throw new Error(msg);
11011
11006
  }
11012
- /**
11013
- * Patch a webhook by id
11014
- */
11015
- update(webhookID, body, options) {
11016
- return this._client.patch(path `/webhooks/${webhookID}`, { body, ...options });
11007
+ }
11008
+ function timingSafeEqual(a, b) {
11009
+ if (a.byteLength !== b.byteLength) {
11010
+ return false;
11017
11011
  }
11018
- /**
11019
- * List all webhooks
11020
- */
11021
- list(query = {}, options) {
11022
- return this._client.getAPIList('/webhooks', (CursorPagePagination), { query, ...options });
11012
+ if (!(a instanceof DataView)) {
11013
+ a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
11023
11014
  }
11024
- /**
11025
- * Delete a webhook by id
11026
- */
11027
- delete(webhookID, options) {
11028
- return this._client.delete(path `/webhooks/${webhookID}`, {
11029
- ...options,
11030
- headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
11031
- });
11015
+ if (!(b instanceof DataView)) {
11016
+ b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
11032
11017
  }
11033
- /**
11034
- * Get webhook secret by id
11035
- */
11036
- retrieveSecret(webhookID, options) {
11037
- return this._client.get(path `/webhooks/${webhookID}/secret`, options);
11018
+ assert(a instanceof DataView);
11019
+ assert(b instanceof DataView);
11020
+ const length = a.byteLength;
11021
+ let out = 0;
11022
+ let i = -1;
11023
+ while (++i < length) {
11024
+ out |= a.getUint8(i) ^ b.getUint8(i);
11038
11025
  }
11039
- };
11040
- Webhooks$1.Headers = Headers$1;
11026
+ return out === 0;
11027
+ }
11028
+ timing_safe_equal.timingSafeEqual = timingSafeEqual;
11041
11029
 
11042
- // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
11030
+ var base64$1 = {};
11031
+
11032
+ // Copyright (C) 2016 Dmitry Chestnykh
11033
+ // MIT License. See LICENSE file for details.
11034
+ var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () {
11035
+ var extendStatics = function (d, b) {
11036
+ extendStatics = Object.setPrototypeOf ||
11037
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
11038
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
11039
+ return extendStatics(d, b);
11040
+ };
11041
+ return function (d, b) {
11042
+ extendStatics(d, b);
11043
+ function __() { this.constructor = d; }
11044
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
11045
+ };
11046
+ })();
11047
+ Object.defineProperty(base64$1, "__esModule", { value: true });
11043
11048
  /**
11044
- * Read an environment variable.
11045
- *
11046
- * Trims beginning and trailing whitespace.
11047
- *
11048
- * Will return undefined if the environment variable doesn't exist or cannot be accessed.
11049
+ * Package base64 implements Base64 encoding and decoding.
11049
11050
  */
11050
- const readEnv = (env) => {
11051
- if (typeof globalThis.process !== 'undefined') {
11052
- return globalThis.process.env?.[env]?.trim() ?? undefined;
11053
- }
11054
- if (typeof globalThis.Deno !== 'undefined') {
11055
- return globalThis.Deno.env?.get?.(env)?.trim();
11056
- }
11057
- return undefined;
11058
- };
11059
-
11060
- // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
11061
- var _DodoPayments_instances, _a, _DodoPayments_encoder, _DodoPayments_baseURLOverridden;
11062
- const environments = {
11063
- live_mode: 'https://live.dodopayments.com',
11064
- test_mode: 'https://test.dodopayments.com',
11065
- };
11051
+ // Invalid character used in decoding to indicate
11052
+ // that the character to decode is out of range of
11053
+ // alphabet and cannot be decoded.
11054
+ var INVALID_BYTE = 256;
11066
11055
  /**
11067
- * API Client for interfacing with the Dodo Payments API.
11056
+ * Implements standard Base64 encoding.
11057
+ *
11058
+ * Operates in constant time.
11068
11059
  */
11069
- class DodoPayments {
11070
- /**
11071
- * API Client for interfacing with the Dodo Payments API.
11072
- *
11073
- * @param {string | undefined} [opts.bearerToken=process.env['DODO_PAYMENTS_API_KEY'] ?? undefined]
11074
- * @param {Environment} [opts.environment=live_mode] - Specifies the environment URL to use for the API.
11075
- * @param {string} [opts.baseURL=process.env['DODO_PAYMENTS_BASE_URL'] ?? https://live.dodopayments.com] - Override the default base URL for the API.
11076
- * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
11077
- * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
11078
- * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
11079
- * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
11080
- * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
11081
- * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
11082
- */
11083
- constructor({ baseURL = readEnv('DODO_PAYMENTS_BASE_URL'), bearerToken = readEnv('DODO_PAYMENTS_API_KEY'), ...opts } = {}) {
11084
- _DodoPayments_instances.add(this);
11085
- _DodoPayments_encoder.set(this, void 0);
11086
- this.checkoutSessions = new CheckoutSessions(this);
11087
- this.payments = new Payments(this);
11088
- this.subscriptions = new Subscriptions(this);
11089
- this.invoices = new Invoices(this);
11090
- this.licenses = new Licenses(this);
11091
- this.licenseKeys = new LicenseKeys(this);
11092
- this.licenseKeyInstances = new LicenseKeyInstances(this);
11093
- this.customers = new Customers(this);
11094
- this.refunds = new Refunds(this);
11095
- this.disputes = new Disputes(this);
11096
- this.payouts = new Payouts(this);
11097
- this.webhookEvents = new WebhookEvents(this);
11098
- this.products = new Products(this);
11099
- this.misc = new Misc(this);
11100
- this.discounts = new Discounts(this);
11101
- this.addons = new Addons(this);
11102
- this.brands = new Brands(this);
11103
- this.webhooks = new Webhooks$1(this);
11104
- this.usageEvents = new UsageEvents(this);
11105
- this.meters = new Meters(this);
11106
- if (bearerToken === undefined) {
11107
- throw new DodoPaymentsError("The DODO_PAYMENTS_API_KEY environment variable is missing or empty; either provide it, or instantiate the DodoPayments client with an bearerToken option, like new DodoPayments({ bearerToken: 'My Bearer Token' }).");
11060
+ var Coder = /** @class */ (function () {
11061
+ // TODO(dchest): methods to encode chunk-by-chunk.
11062
+ function Coder(_paddingCharacter) {
11063
+ if (_paddingCharacter === void 0) { _paddingCharacter = "="; }
11064
+ this._paddingCharacter = _paddingCharacter;
11065
+ }
11066
+ Coder.prototype.encodedLength = function (length) {
11067
+ if (!this._paddingCharacter) {
11068
+ return (length * 8 + 5) / 6 | 0;
11108
11069
  }
11109
- const options = {
11110
- bearerToken,
11111
- ...opts,
11112
- baseURL,
11113
- environment: opts.environment ?? 'live_mode',
11114
- };
11115
- if (baseURL && opts.environment) {
11116
- throw new DodoPaymentsError('Ambiguous URL; The `baseURL` option (or DODO_PAYMENTS_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null');
11070
+ return (length + 2) / 3 * 4 | 0;
11071
+ };
11072
+ Coder.prototype.encode = function (data) {
11073
+ var out = "";
11074
+ var i = 0;
11075
+ for (; i < data.length - 2; i += 3) {
11076
+ var c = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
11077
+ out += this._encodeByte((c >>> 3 * 6) & 63);
11078
+ out += this._encodeByte((c >>> 2 * 6) & 63);
11079
+ out += this._encodeByte((c >>> 1 * 6) & 63);
11080
+ out += this._encodeByte((c >>> 0 * 6) & 63);
11117
11081
  }
11118
- this.baseURL = options.baseURL || environments[options.environment || 'live_mode'];
11119
- this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT /* 1 minute */;
11120
- this.logger = options.logger ?? console;
11121
- const defaultLogLevel = 'warn';
11122
- // Set default logLevel early so that we can log a warning in parseLogLevel.
11123
- this.logLevel = defaultLogLevel;
11124
- this.logLevel =
11125
- parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
11126
- parseLogLevel(readEnv('DODO_PAYMENTS_LOG'), "process.env['DODO_PAYMENTS_LOG']", this) ??
11127
- defaultLogLevel;
11128
- this.fetchOptions = options.fetchOptions;
11129
- this.maxRetries = options.maxRetries ?? 2;
11130
- this.fetch = options.fetch ?? getDefaultFetch();
11131
- __classPrivateFieldSet(this, _DodoPayments_encoder, FallbackEncoder);
11132
- this._options = options;
11133
- this.bearerToken = bearerToken;
11134
- }
11135
- /**
11136
- * Create a new client instance re-using the same options given to the current client with optional overriding.
11137
- */
11138
- withOptions(options) {
11139
- const client = new this.constructor({
11140
- ...this._options,
11141
- environment: options.environment ? options.environment : undefined,
11142
- baseURL: options.environment ? undefined : this.baseURL,
11143
- maxRetries: this.maxRetries,
11144
- timeout: this.timeout,
11145
- logger: this.logger,
11146
- logLevel: this.logLevel,
11147
- fetch: this.fetch,
11148
- fetchOptions: this.fetchOptions,
11149
- bearerToken: this.bearerToken,
11150
- ...options,
11151
- });
11152
- return client;
11153
- }
11154
- defaultQuery() {
11155
- return this._options.defaultQuery;
11156
- }
11157
- validateHeaders({ values, nulls }) {
11158
- return;
11159
- }
11160
- async authHeaders(opts) {
11161
- return buildHeaders([{ Authorization: `Bearer ${this.bearerToken}` }]);
11162
- }
11163
- /**
11164
- * Basic re-implementation of `qs.stringify` for primitive types.
11165
- */
11166
- stringifyQuery(query) {
11167
- return Object.entries(query)
11168
- .filter(([_, value]) => typeof value !== 'undefined')
11169
- .map(([key, value]) => {
11170
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
11171
- return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
11082
+ var left = data.length - i;
11083
+ if (left > 0) {
11084
+ var c = (data[i] << 16) | (left === 2 ? data[i + 1] << 8 : 0);
11085
+ out += this._encodeByte((c >>> 3 * 6) & 63);
11086
+ out += this._encodeByte((c >>> 2 * 6) & 63);
11087
+ if (left === 2) {
11088
+ out += this._encodeByte((c >>> 1 * 6) & 63);
11172
11089
  }
11173
- if (value === null) {
11174
- return `${encodeURIComponent(key)}=`;
11090
+ else {
11091
+ out += this._paddingCharacter || "";
11175
11092
  }
11176
- throw new DodoPaymentsError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`);
11177
- })
11178
- .join('&');
11179
- }
11180
- getUserAgent() {
11181
- return `${this.constructor.name}/JS ${VERSION}`;
11182
- }
11183
- defaultIdempotencyKey() {
11184
- return `stainless-node-retry-${uuid4()}`;
11185
- }
11186
- makeStatusError(status, error, message, headers) {
11187
- return APIError.generate(status, error, message, headers);
11188
- }
11189
- buildURL(path, query, defaultBaseURL) {
11190
- const baseURL = (!__classPrivateFieldGet(this, _DodoPayments_instances, "m", _DodoPayments_baseURLOverridden).call(this) && defaultBaseURL) || this.baseURL;
11191
- const url = isAbsoluteURL(path) ?
11192
- new URL(path)
11193
- : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
11194
- const defaultQuery = this.defaultQuery();
11195
- if (!isEmptyObj(defaultQuery)) {
11196
- query = { ...defaultQuery, ...query };
11197
- }
11198
- if (typeof query === 'object' && query && !Array.isArray(query)) {
11199
- url.search = this.stringifyQuery(query);
11093
+ out += this._paddingCharacter || "";
11200
11094
  }
11201
- return url.toString();
11202
- }
11203
- /**
11204
- * Used as a callback for mutating the given `FinalRequestOptions` object.
11205
- */
11206
- async prepareOptions(options) { }
11207
- /**
11208
- * Used as a callback for mutating the given `RequestInit` object.
11209
- *
11210
- * This is useful for cases where you want to add certain headers based off of
11211
- * the request properties, e.g. `method` or `url`.
11212
- */
11213
- async prepareRequest(request, { url, options }) { }
11214
- get(path, opts) {
11215
- return this.methodRequest('get', path, opts);
11216
- }
11217
- post(path, opts) {
11218
- return this.methodRequest('post', path, opts);
11219
- }
11220
- patch(path, opts) {
11221
- return this.methodRequest('patch', path, opts);
11222
- }
11223
- put(path, opts) {
11224
- return this.methodRequest('put', path, opts);
11225
- }
11226
- delete(path, opts) {
11227
- return this.methodRequest('delete', path, opts);
11228
- }
11229
- methodRequest(method, path, opts) {
11230
- return this.request(Promise.resolve(opts).then((opts) => {
11231
- return { method, path, ...opts };
11232
- }));
11233
- }
11234
- request(options, remainingRetries = null) {
11235
- return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
11236
- }
11237
- async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {
11238
- const options = await optionsInput;
11239
- const maxRetries = options.maxRetries ?? this.maxRetries;
11240
- if (retriesRemaining == null) {
11241
- retriesRemaining = maxRetries;
11095
+ return out;
11096
+ };
11097
+ Coder.prototype.maxDecodedLength = function (length) {
11098
+ if (!this._paddingCharacter) {
11099
+ return (length * 6 + 7) / 8 | 0;
11242
11100
  }
11243
- await this.prepareOptions(options);
11244
- const { req, url, timeout } = await this.buildRequest(options, {
11245
- retryCount: maxRetries - retriesRemaining,
11246
- });
11247
- await this.prepareRequest(req, { url, options });
11248
- /** Not an API request ID, just for correlating local log entries. */
11249
- const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
11250
- const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
11251
- const startTime = Date.now();
11252
- loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({
11253
- retryOfRequestLogID,
11254
- method: options.method,
11255
- url,
11256
- options,
11257
- headers: req.headers,
11258
- }));
11259
- if (options.signal?.aborted) {
11260
- throw new APIUserAbortError();
11101
+ return length / 4 * 3 | 0;
11102
+ };
11103
+ Coder.prototype.decodedLength = function (s) {
11104
+ return this.maxDecodedLength(s.length - this._getPaddingLength(s));
11105
+ };
11106
+ Coder.prototype.decode = function (s) {
11107
+ if (s.length === 0) {
11108
+ return new Uint8Array(0);
11261
11109
  }
11262
- const controller = new AbortController();
11263
- const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
11264
- const headersTime = Date.now();
11265
- if (response instanceof globalThis.Error) {
11266
- const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
11267
- if (options.signal?.aborted) {
11268
- throw new APIUserAbortError();
11269
- }
11270
- // detect native connection timeout errors
11271
- // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
11272
- // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
11273
- // others do not provide enough information to distinguish timeouts from other connection errors
11274
- const isTimeout = isAbortError(response) ||
11275
- /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
11276
- if (retriesRemaining) {
11277
- loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`);
11278
- loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({
11279
- retryOfRequestLogID,
11280
- url,
11281
- durationMs: headersTime - startTime,
11282
- message: response.message,
11283
- }));
11284
- return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
11285
- }
11286
- loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`);
11287
- loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({
11288
- retryOfRequestLogID,
11289
- url,
11290
- durationMs: headersTime - startTime,
11291
- message: response.message,
11292
- }));
11293
- if (isTimeout) {
11294
- throw new APIConnectionTimeoutError();
11295
- }
11296
- throw new APIConnectionError({ cause: response });
11110
+ var paddingLength = this._getPaddingLength(s);
11111
+ var length = s.length - paddingLength;
11112
+ var out = new Uint8Array(this.maxDecodedLength(length));
11113
+ var op = 0;
11114
+ var i = 0;
11115
+ var haveBad = 0;
11116
+ var v0 = 0, v1 = 0, v2 = 0, v3 = 0;
11117
+ for (; i < length - 4; i += 4) {
11118
+ v0 = this._decodeChar(s.charCodeAt(i + 0));
11119
+ v1 = this._decodeChar(s.charCodeAt(i + 1));
11120
+ v2 = this._decodeChar(s.charCodeAt(i + 2));
11121
+ v3 = this._decodeChar(s.charCodeAt(i + 3));
11122
+ out[op++] = (v0 << 2) | (v1 >>> 4);
11123
+ out[op++] = (v1 << 4) | (v2 >>> 2);
11124
+ out[op++] = (v2 << 6) | v3;
11125
+ haveBad |= v0 & INVALID_BYTE;
11126
+ haveBad |= v1 & INVALID_BYTE;
11127
+ haveBad |= v2 & INVALID_BYTE;
11128
+ haveBad |= v3 & INVALID_BYTE;
11297
11129
  }
11298
- const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;
11299
- if (!response.ok) {
11300
- const shouldRetry = await this.shouldRetry(response);
11301
- if (retriesRemaining && shouldRetry) {
11302
- const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
11303
- // We don't need the body of this response.
11304
- await CancelReadableStream(response.body);
11305
- loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
11306
- loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
11307
- retryOfRequestLogID,
11308
- url: response.url,
11309
- status: response.status,
11310
- headers: response.headers,
11311
- durationMs: headersTime - startTime,
11312
- }));
11313
- return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers);
11314
- }
11315
- const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
11316
- loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
11317
- const errText = await response.text().catch((err) => castToError(err).message);
11318
- const errJSON = safeJSON(errText);
11319
- const errMessage = errJSON ? undefined : errText;
11320
- loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
11321
- retryOfRequestLogID,
11322
- url: response.url,
11323
- status: response.status,
11324
- headers: response.headers,
11325
- message: errMessage,
11326
- durationMs: Date.now() - startTime,
11327
- }));
11328
- const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
11329
- throw err;
11130
+ if (i < length - 1) {
11131
+ v0 = this._decodeChar(s.charCodeAt(i));
11132
+ v1 = this._decodeChar(s.charCodeAt(i + 1));
11133
+ out[op++] = (v0 << 2) | (v1 >>> 4);
11134
+ haveBad |= v0 & INVALID_BYTE;
11135
+ haveBad |= v1 & INVALID_BYTE;
11330
11136
  }
11331
- loggerFor(this).info(responseInfo);
11332
- loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
11333
- retryOfRequestLogID,
11334
- url: response.url,
11335
- status: response.status,
11336
- headers: response.headers,
11337
- durationMs: headersTime - startTime,
11338
- }));
11339
- return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
11340
- }
11341
- getAPIList(path, Page, opts) {
11342
- return this.requestAPIList(Page, { method: 'get', path, ...opts });
11343
- }
11344
- requestAPIList(Page, options) {
11345
- const request = this.makeRequest(options, null, undefined);
11346
- return new PagePromise(this, request, Page);
11347
- }
11348
- async fetchWithTimeout(url, init, ms, controller) {
11349
- const { signal, method, ...options } = init || {};
11350
- if (signal)
11351
- signal.addEventListener('abort', () => controller.abort());
11352
- const timeout = setTimeout(() => controller.abort(), ms);
11353
- const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) ||
11354
- (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
11355
- const fetchOptions = {
11356
- signal: controller.signal,
11357
- ...(isReadableBody ? { duplex: 'half' } : {}),
11358
- method: 'GET',
11359
- ...options,
11360
- };
11361
- if (method) {
11362
- // Custom methods like 'patch' need to be uppercased
11363
- // See https://github.com/nodejs/undici/issues/2294
11364
- fetchOptions.method = method.toUpperCase();
11137
+ if (i < length - 2) {
11138
+ v2 = this._decodeChar(s.charCodeAt(i + 2));
11139
+ out[op++] = (v1 << 4) | (v2 >>> 2);
11140
+ haveBad |= v2 & INVALID_BYTE;
11365
11141
  }
11366
- try {
11367
- // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
11368
- return await this.fetch.call(undefined, url, fetchOptions);
11142
+ if (i < length - 3) {
11143
+ v3 = this._decodeChar(s.charCodeAt(i + 3));
11144
+ out[op++] = (v2 << 6) | v3;
11145
+ haveBad |= v3 & INVALID_BYTE;
11369
11146
  }
11370
- finally {
11371
- clearTimeout(timeout);
11147
+ if (haveBad !== 0) {
11148
+ throw new Error("Base64Coder: incorrect characters for decoding");
11372
11149
  }
11373
- }
11374
- async shouldRetry(response) {
11375
- // Note this is not a standard header.
11376
- const shouldRetryHeader = response.headers.get('x-should-retry');
11377
- // If the server explicitly says whether or not to retry, obey.
11378
- if (shouldRetryHeader === 'true')
11379
- return true;
11380
- if (shouldRetryHeader === 'false')
11381
- return false;
11382
- // Retry on request timeouts.
11383
- if (response.status === 408)
11384
- return true;
11385
- // Retry on lock timeouts.
11386
- if (response.status === 409)
11387
- return true;
11388
- // Retry on rate limits.
11389
- if (response.status === 429)
11390
- return true;
11391
- // Retry internal errors.
11392
- if (response.status >= 500)
11393
- return true;
11394
- return false;
11395
- }
11396
- async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) {
11397
- let timeoutMillis;
11398
- // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.
11399
- const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');
11400
- if (retryAfterMillisHeader) {
11401
- const timeoutMs = parseFloat(retryAfterMillisHeader);
11402
- if (!Number.isNaN(timeoutMs)) {
11403
- timeoutMillis = timeoutMs;
11404
- }
11405
- }
11406
- // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
11407
- const retryAfterHeader = responseHeaders?.get('retry-after');
11408
- if (retryAfterHeader && !timeoutMillis) {
11409
- const timeoutSeconds = parseFloat(retryAfterHeader);
11410
- if (!Number.isNaN(timeoutSeconds)) {
11411
- timeoutMillis = timeoutSeconds * 1000;
11150
+ return out;
11151
+ };
11152
+ // Standard encoding have the following encoded/decoded ranges,
11153
+ // which we need to convert between.
11154
+ //
11155
+ // ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 + /
11156
+ // Index: 0 - 25 26 - 51 52 - 61 62 63
11157
+ // ASCII: 65 - 90 97 - 122 48 - 57 43 47
11158
+ //
11159
+ // Encode 6 bits in b into a new character.
11160
+ Coder.prototype._encodeByte = function (b) {
11161
+ // Encoding uses constant time operations as follows:
11162
+ //
11163
+ // 1. Define comparison of A with B using (A - B) >>> 8:
11164
+ // if A > B, then result is positive integer
11165
+ // if A <= B, then result is 0
11166
+ //
11167
+ // 2. Define selection of C or 0 using bitwise AND: X & C:
11168
+ // if X == 0, then result is 0
11169
+ // if X != 0, then result is C
11170
+ //
11171
+ // 3. Start with the smallest comparison (b >= 0), which is always
11172
+ // true, so set the result to the starting ASCII value (65).
11173
+ //
11174
+ // 4. Continue comparing b to higher ASCII values, and selecting
11175
+ // zero if comparison isn't true, otherwise selecting a value
11176
+ // to add to result, which:
11177
+ //
11178
+ // a) undoes the previous addition
11179
+ // b) provides new value to add
11180
+ //
11181
+ var result = b;
11182
+ // b >= 0
11183
+ result += 65;
11184
+ // b > 25
11185
+ result += ((25 - b) >>> 8) & ((0 - 65) - 26 + 97);
11186
+ // b > 51
11187
+ result += ((51 - b) >>> 8) & ((26 - 97) - 52 + 48);
11188
+ // b > 61
11189
+ result += ((61 - b) >>> 8) & ((52 - 48) - 62 + 43);
11190
+ // b > 62
11191
+ result += ((62 - b) >>> 8) & ((62 - 43) - 63 + 47);
11192
+ return String.fromCharCode(result);
11193
+ };
11194
+ // Decode a character code into a byte.
11195
+ // Must return 256 if character is out of alphabet range.
11196
+ Coder.prototype._decodeChar = function (c) {
11197
+ // Decoding works similar to encoding: using the same comparison
11198
+ // function, but now it works on ranges: result is always incremented
11199
+ // by value, but this value becomes zero if the range is not
11200
+ // satisfied.
11201
+ //
11202
+ // Decoding starts with invalid value, 256, which is then
11203
+ // subtracted when the range is satisfied. If none of the ranges
11204
+ // apply, the function returns 256, which is then checked by
11205
+ // the caller to throw error.
11206
+ var result = INVALID_BYTE; // start with invalid character
11207
+ // c == 43 (c > 42 and c < 44)
11208
+ result += (((42 - c) & (c - 44)) >>> 8) & (-INVALID_BYTE + c - 43 + 62);
11209
+ // c == 47 (c > 46 and c < 48)
11210
+ result += (((46 - c) & (c - 48)) >>> 8) & (-INVALID_BYTE + c - 47 + 63);
11211
+ // c > 47 and c < 58
11212
+ result += (((47 - c) & (c - 58)) >>> 8) & (-INVALID_BYTE + c - 48 + 52);
11213
+ // c > 64 and c < 91
11214
+ result += (((64 - c) & (c - 91)) >>> 8) & (-INVALID_BYTE + c - 65 + 0);
11215
+ // c > 96 and c < 123
11216
+ result += (((96 - c) & (c - 123)) >>> 8) & (-INVALID_BYTE + c - 97 + 26);
11217
+ return result;
11218
+ };
11219
+ Coder.prototype._getPaddingLength = function (s) {
11220
+ var paddingLength = 0;
11221
+ if (this._paddingCharacter) {
11222
+ for (var i = s.length - 1; i >= 0; i--) {
11223
+ if (s[i] !== this._paddingCharacter) {
11224
+ break;
11225
+ }
11226
+ paddingLength++;
11412
11227
  }
11413
- else {
11414
- timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
11228
+ if (s.length < 4 || paddingLength > 2) {
11229
+ throw new Error("Base64Coder: incorrect padding");
11415
11230
  }
11416
11231
  }
11417
- // If the API asks us to wait a certain amount of time (and it's a reasonable amount),
11418
- // just do what it says, but otherwise calculate a default
11419
- if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
11420
- const maxRetries = options.maxRetries ?? this.maxRetries;
11421
- timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
11422
- }
11423
- await sleep(timeoutMillis);
11424
- return this.makeRequest(options, retriesRemaining - 1, requestLogID);
11425
- }
11426
- calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
11427
- const initialRetryDelay = 0.5;
11428
- const maxRetryDelay = 8.0;
11429
- const numRetries = maxRetries - retriesRemaining;
11430
- // Apply exponential backoff, but not more than the max.
11431
- const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
11432
- // Apply some jitter, take up to at most 25 percent of the retry time.
11433
- const jitter = 1 - Math.random() * 0.25;
11434
- return sleepSeconds * jitter * 1000;
11435
- }
11436
- async buildRequest(inputOptions, { retryCount = 0 } = {}) {
11437
- const options = { ...inputOptions };
11438
- const { method, path, query, defaultBaseURL } = options;
11439
- const url = this.buildURL(path, query, defaultBaseURL);
11440
- if ('timeout' in options)
11441
- validatePositiveInteger('timeout', options.timeout);
11442
- options.timeout = options.timeout ?? this.timeout;
11443
- const { bodyHeaders, body } = this.buildBody({ options });
11444
- const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
11445
- const req = {
11446
- method,
11447
- headers: reqHeaders,
11448
- ...(options.signal && { signal: options.signal }),
11449
- ...(globalThis.ReadableStream &&
11450
- body instanceof globalThis.ReadableStream && { duplex: 'half' }),
11451
- ...(body && { body }),
11452
- ...(this.fetchOptions ?? {}),
11453
- ...(options.fetchOptions ?? {}),
11454
- };
11455
- return { req, url, timeout: options.timeout };
11456
- }
11457
- async buildHeaders({ options, method, bodyHeaders, retryCount, }) {
11458
- let idempotencyHeaders = {};
11459
- if (this.idempotencyHeader && method !== 'get') {
11460
- if (!options.idempotencyKey)
11461
- options.idempotencyKey = this.defaultIdempotencyKey();
11462
- idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
11463
- }
11464
- const headers = buildHeaders([
11465
- idempotencyHeaders,
11466
- {
11467
- Accept: 'application/json',
11468
- 'User-Agent': this.getUserAgent(),
11469
- 'X-Stainless-Retry-Count': String(retryCount),
11470
- ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
11471
- ...getPlatformHeaders(),
11472
- },
11473
- await this.authHeaders(options),
11474
- this._options.defaultHeaders,
11475
- bodyHeaders,
11476
- options.headers,
11477
- ]);
11478
- this.validateHeaders(headers);
11479
- return headers.values;
11480
- }
11481
- buildBody({ options: { body, headers: rawHeaders } }) {
11482
- if (!body) {
11483
- return { bodyHeaders: undefined, body: undefined };
11484
- }
11485
- const headers = buildHeaders([rawHeaders]);
11486
- if (
11487
- // Pass raw type verbatim
11488
- ArrayBuffer.isView(body) ||
11489
- body instanceof ArrayBuffer ||
11490
- body instanceof DataView ||
11491
- (typeof body === 'string' &&
11492
- // Preserve legacy string encoding behavior for now
11493
- headers.values.has('content-type')) ||
11494
- // `Blob` is superset of `File`
11495
- (globalThis.Blob && body instanceof globalThis.Blob) ||
11496
- // `FormData` -> `multipart/form-data`
11497
- body instanceof FormData ||
11498
- // `URLSearchParams` -> `application/x-www-form-urlencoded`
11499
- body instanceof URLSearchParams ||
11500
- // Send chunked stream (each chunk has own `length`)
11501
- (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) {
11502
- return { bodyHeaders: undefined, body: body };
11503
- }
11504
- else if (typeof body === 'object' &&
11505
- (Symbol.asyncIterator in body ||
11506
- (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {
11507
- return { bodyHeaders: undefined, body: ReadableStreamFrom(body) };
11508
- }
11509
- else {
11510
- return __classPrivateFieldGet(this, _DodoPayments_encoder, "f").call(this, { body, headers });
11511
- }
11232
+ return paddingLength;
11233
+ };
11234
+ return Coder;
11235
+ }());
11236
+ base64$1.Coder = Coder;
11237
+ var stdCoder = new Coder();
11238
+ function encode(data) {
11239
+ return stdCoder.encode(data);
11240
+ }
11241
+ base64$1.encode = encode;
11242
+ function decode(s) {
11243
+ return stdCoder.decode(s);
11244
+ }
11245
+ base64$1.decode = decode;
11246
+ /**
11247
+ * Implements URL-safe Base64 encoding.
11248
+ * (Same as Base64, but '+' is replaced with '-', and '/' with '_').
11249
+ *
11250
+ * Operates in constant time.
11251
+ */
11252
+ var URLSafeCoder = /** @class */ (function (_super) {
11253
+ __extends(URLSafeCoder, _super);
11254
+ function URLSafeCoder() {
11255
+ return _super !== null && _super.apply(this, arguments) || this;
11512
11256
  }
11257
+ // URL-safe encoding have the following encoded/decoded ranges:
11258
+ //
11259
+ // ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 - _
11260
+ // Index: 0 - 25 26 - 51 52 - 61 62 63
11261
+ // ASCII: 65 - 90 97 - 122 48 - 57 45 95
11262
+ //
11263
+ URLSafeCoder.prototype._encodeByte = function (b) {
11264
+ var result = b;
11265
+ // b >= 0
11266
+ result += 65;
11267
+ // b > 25
11268
+ result += ((25 - b) >>> 8) & ((0 - 65) - 26 + 97);
11269
+ // b > 51
11270
+ result += ((51 - b) >>> 8) & ((26 - 97) - 52 + 48);
11271
+ // b > 61
11272
+ result += ((61 - b) >>> 8) & ((52 - 48) - 62 + 45);
11273
+ // b > 62
11274
+ result += ((62 - b) >>> 8) & ((62 - 45) - 63 + 95);
11275
+ return String.fromCharCode(result);
11276
+ };
11277
+ URLSafeCoder.prototype._decodeChar = function (c) {
11278
+ var result = INVALID_BYTE;
11279
+ // c == 45 (c > 44 and c < 46)
11280
+ result += (((44 - c) & (c - 46)) >>> 8) & (-INVALID_BYTE + c - 45 + 62);
11281
+ // c == 95 (c > 94 and c < 96)
11282
+ result += (((94 - c) & (c - 96)) >>> 8) & (-INVALID_BYTE + c - 95 + 63);
11283
+ // c > 47 and c < 58
11284
+ result += (((47 - c) & (c - 58)) >>> 8) & (-INVALID_BYTE + c - 48 + 52);
11285
+ // c > 64 and c < 91
11286
+ result += (((64 - c) & (c - 91)) >>> 8) & (-INVALID_BYTE + c - 65 + 0);
11287
+ // c > 96 and c < 123
11288
+ result += (((96 - c) & (c - 123)) >>> 8) & (-INVALID_BYTE + c - 97 + 26);
11289
+ return result;
11290
+ };
11291
+ return URLSafeCoder;
11292
+ }(Coder));
11293
+ base64$1.URLSafeCoder = URLSafeCoder;
11294
+ var urlSafeCoder = new URLSafeCoder();
11295
+ function encodeURLSafe(data) {
11296
+ return urlSafeCoder.encode(data);
11513
11297
  }
11514
- _a = DodoPayments, _DodoPayments_encoder = new WeakMap(), _DodoPayments_instances = new WeakSet(), _DodoPayments_baseURLOverridden = function _DodoPayments_baseURLOverridden() {
11515
- return this.baseURL !== environments[this._options.environment || 'live_mode'];
11298
+ base64$1.encodeURLSafe = encodeURLSafe;
11299
+ function decodeURLSafe(s) {
11300
+ return urlSafeCoder.decode(s);
11301
+ }
11302
+ base64$1.decodeURLSafe = decodeURLSafe;
11303
+ base64$1.encodedLength = function (length) {
11304
+ return stdCoder.encodedLength(length);
11516
11305
  };
11517
- DodoPayments.DodoPayments = _a;
11518
- DodoPayments.DEFAULT_TIMEOUT = 60000; // 1 minute
11519
- DodoPayments.DodoPaymentsError = DodoPaymentsError;
11520
- DodoPayments.APIError = APIError;
11521
- DodoPayments.APIConnectionError = APIConnectionError;
11522
- DodoPayments.APIConnectionTimeoutError = APIConnectionTimeoutError;
11523
- DodoPayments.APIUserAbortError = APIUserAbortError;
11524
- DodoPayments.NotFoundError = NotFoundError;
11525
- DodoPayments.ConflictError = ConflictError;
11526
- DodoPayments.RateLimitError = RateLimitError;
11527
- DodoPayments.BadRequestError = BadRequestError;
11528
- DodoPayments.AuthenticationError = AuthenticationError;
11529
- DodoPayments.InternalServerError = InternalServerError;
11530
- DodoPayments.PermissionDeniedError = PermissionDeniedError;
11531
- DodoPayments.UnprocessableEntityError = UnprocessableEntityError;
11532
- DodoPayments.toFile = toFile;
11533
- DodoPayments.CheckoutSessions = CheckoutSessions;
11534
- DodoPayments.Payments = Payments;
11535
- DodoPayments.Subscriptions = Subscriptions;
11536
- DodoPayments.Invoices = Invoices;
11537
- DodoPayments.Licenses = Licenses;
11538
- DodoPayments.LicenseKeys = LicenseKeys;
11539
- DodoPayments.LicenseKeyInstances = LicenseKeyInstances;
11540
- DodoPayments.Customers = Customers;
11541
- DodoPayments.Refunds = Refunds;
11542
- DodoPayments.Disputes = Disputes;
11543
- DodoPayments.Payouts = Payouts;
11544
- DodoPayments.WebhookEvents = WebhookEvents;
11545
- DodoPayments.Products = Products;
11546
- DodoPayments.Misc = Misc;
11547
- DodoPayments.Discounts = Discounts;
11548
- DodoPayments.Addons = Addons;
11549
- DodoPayments.Brands = Brands;
11550
- DodoPayments.Webhooks = Webhooks$1;
11551
- DodoPayments.UsageEvents = UsageEvents;
11552
- DodoPayments.Meters = Meters;
11553
-
11554
- // src/checkout/checkout.ts
11555
- var checkoutQuerySchema = objectType({
11556
- productId: stringType(),
11557
- quantity: stringType().optional(),
11558
- // Customer fields
11559
- fullName: stringType().optional(),
11560
- firstName: stringType().optional(),
11561
- lastName: stringType().optional(),
11562
- email: stringType().optional(),
11563
- country: stringType().optional(),
11564
- addressLine: stringType().optional(),
11565
- city: stringType().optional(),
11566
- state: stringType().optional(),
11567
- zipCode: stringType().optional(),
11568
- // Disable flags
11569
- disableFullName: stringType().optional(),
11570
- disableFirstName: stringType().optional(),
11571
- disableLastName: stringType().optional(),
11572
- disableEmail: stringType().optional(),
11573
- disableCountry: stringType().optional(),
11574
- disableAddressLine: stringType().optional(),
11575
- disableCity: stringType().optional(),
11576
- disableState: stringType().optional(),
11577
- disableZipCode: stringType().optional(),
11578
- // Advanced controls
11579
- paymentCurrency: stringType().optional(),
11580
- showCurrencySelector: stringType().optional(),
11581
- paymentAmount: stringType().optional(),
11582
- showDiscounts: stringType().optional()
11583
- // Metadata (allow any key starting with metadata_)
11584
- // We'll handle metadata separately in the handler
11585
- }).catchall(unknownType());
11586
- var dynamicCheckoutBodySchema = objectType({
11587
- // For subscription
11588
- product_id: stringType().optional(),
11589
- quantity: numberType().optional(),
11590
- // For one-time payment
11591
- product_cart: arrayType(
11592
- objectType({
11593
- product_id: stringType(),
11594
- quantity: numberType()
11595
- })
11596
- ).optional(),
11597
- // Common fields
11598
- billing: objectType({
11599
- city: stringType(),
11600
- country: stringType(),
11601
- state: stringType(),
11602
- street: stringType(),
11603
- zipcode: stringType()
11604
- }),
11605
- customer: objectType({
11606
- customer_id: stringType().optional(),
11607
- email: stringType().optional(),
11608
- name: stringType().optional()
11609
- }),
11610
- discount_id: stringType().optional(),
11611
- addons: arrayType(
11612
- objectType({
11613
- addon_id: stringType(),
11614
- quantity: numberType()
11615
- })
11616
- ).optional(),
11617
- metadata: recordType(stringType(), stringType()).optional(),
11618
- currency: stringType().optional()
11619
- // Allow any additional fields (for future compatibility)
11620
- }).catchall(unknownType());
11621
- var checkoutSessionProductCartItemSchema = objectType({
11622
- product_id: stringType().min(1, "Product ID is required"),
11623
- quantity: numberType().int().positive("Quantity must be a positive integer")
11624
- });
11625
- var checkoutSessionCustomerSchema = objectType({
11626
- email: stringType().email().optional(),
11627
- name: stringType().min(1).optional(),
11628
- phone_number: stringType().optional()
11629
- }).optional();
11630
- var checkoutSessionBillingAddressSchema = objectType({
11631
- street: stringType().optional(),
11632
- city: stringType().optional(),
11633
- state: stringType().optional(),
11634
- country: stringType().length(2, "Country must be a 2-letter ISO code"),
11635
- zipcode: stringType().optional()
11636
- }).optional();
11637
- var paymentMethodTypeSchema = enumType([
11638
- "credit",
11639
- "debit",
11640
- "upi_collect",
11641
- "upi_intent",
11642
- "apple_pay",
11643
- "google_pay",
11644
- "amazon_pay",
11645
- "klarna",
11646
- "affirm",
11647
- "afterpay_clearpay",
11648
- "sepa",
11649
- "ach"
11650
- ]);
11651
- var checkoutSessionCustomizationSchema = objectType({
11652
- theme: enumType(["light", "dark", "system"]).optional(),
11653
- show_order_details: booleanType().optional(),
11654
- show_on_demand_tag: booleanType().optional()
11655
- }).optional();
11656
- var checkoutSessionFeatureFlagsSchema = objectType({
11657
- allow_currency_selection: booleanType().optional(),
11658
- allow_discount_code: booleanType().optional(),
11659
- allow_phone_number_collection: booleanType().optional(),
11660
- allow_tax_id: booleanType().optional(),
11661
- always_create_new_customer: booleanType().optional()
11662
- }).optional();
11663
- var checkoutSessionSubscriptionDataSchema = objectType({
11664
- trial_period_days: numberType().int().nonnegative().optional()
11665
- }).optional();
11666
- var checkoutSessionPayloadSchema = objectType({
11667
- // Required fields
11668
- product_cart: arrayType(checkoutSessionProductCartItemSchema).min(1, "At least one product is required"),
11669
- // Optional fields
11670
- customer: checkoutSessionCustomerSchema,
11671
- billing_address: checkoutSessionBillingAddressSchema,
11672
- return_url: stringType().url().optional(),
11673
- allowed_payment_method_types: arrayType(paymentMethodTypeSchema).optional(),
11674
- billing_currency: stringType().length(3, "Currency must be a 3-letter ISO code").optional(),
11675
- show_saved_payment_methods: booleanType().optional(),
11676
- confirm: booleanType().optional(),
11677
- discount_code: stringType().optional(),
11678
- metadata: recordType(stringType(), stringType()).optional(),
11679
- customization: checkoutSessionCustomizationSchema,
11680
- feature_flags: checkoutSessionFeatureFlagsSchema,
11681
- subscription_data: checkoutSessionSubscriptionDataSchema
11682
- });
11683
- var checkoutSessionResponseSchema = objectType({
11684
- session_id: stringType().min(1, "Session ID is required"),
11685
- checkout_url: stringType().url("Invalid checkout URL")
11686
- });
11687
- var createCheckoutSession = async (payload, config) => {
11688
- const validation = checkoutSessionPayloadSchema.safeParse(payload);
11689
- if (!validation.success) {
11690
- throw new Error(
11691
- `Invalid checkout session payload: ${validation.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ")}`
11692
- );
11693
- }
11694
- const dodopayments = new DodoPayments({
11695
- bearerToken: config.bearerToken,
11696
- environment: config.environment
11697
- });
11698
- try {
11699
- const sdkPayload = {
11700
- ...validation.data,
11701
- ...validation.data.billing_address && {
11702
- billing_address: {
11703
- ...validation.data.billing_address,
11704
- country: validation.data.billing_address.country
11705
- }
11706
- }
11707
- };
11708
- const session = await dodopayments.checkoutSessions.create(
11709
- sdkPayload
11710
- );
11711
- const responseValidation = checkoutSessionResponseSchema.safeParse(session);
11712
- if (!responseValidation.success) {
11713
- throw new Error(
11714
- `Invalid checkout session response from API: ${responseValidation.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ")}`
11715
- );
11716
- }
11717
- return responseValidation.data;
11718
- } catch (error) {
11719
- if (error instanceof Error) {
11720
- console.error("Dodo Payments Checkout Session API Error:", {
11721
- message: error.message,
11722
- payload: validation.data,
11723
- config: {
11724
- environment: config.environment,
11725
- hasBearerToken: !!config.bearerToken
11726
- }
11727
- });
11728
- throw new Error(`Failed to create checkout session: ${error.message}`);
11729
- }
11730
- console.error("Unknown error creating checkout session:", error);
11731
- throw new Error(
11732
- "Failed to create checkout session due to an unknown error"
11733
- );
11734
- }
11306
+ base64$1.maxDecodedLength = function (length) {
11307
+ return stdCoder.maxDecodedLength(length);
11735
11308
  };
11736
- var buildCheckoutUrl = async ({
11737
- queryParams,
11738
- body,
11739
- sessionPayload,
11740
- returnUrl,
11741
- bearerToken,
11742
- environment,
11743
- type = "static"
11744
- }) => {
11745
- if (type === "session") {
11746
- if (!sessionPayload) {
11747
- throw new Error("sessionPayload is required when type is 'session'");
11748
- }
11749
- const session = await createCheckoutSession(sessionPayload, {
11750
- bearerToken,
11751
- environment
11752
- });
11753
- return session.checkout_url;
11754
- }
11755
- const inputData = type === "dynamic" ? body : queryParams;
11756
- let parseResult;
11757
- if (type === "dynamic") {
11758
- parseResult = dynamicCheckoutBodySchema.safeParse(inputData);
11759
- } else {
11760
- parseResult = checkoutQuerySchema.safeParse(inputData);
11761
- }
11762
- const { success, data, error } = parseResult;
11763
- if (!success) {
11764
- throw new Error(
11765
- `Invalid ${type === "dynamic" ? "body" : "query parameters"}.
11766
- ${error.message}`
11767
- );
11768
- }
11769
- if (type !== "dynamic") {
11770
- const {
11771
- productId,
11772
- quantity: quantity2,
11773
- fullName,
11774
- firstName,
11775
- lastName,
11776
- email,
11777
- country,
11778
- addressLine,
11779
- city,
11780
- state,
11781
- zipCode,
11782
- disableFullName,
11783
- disableFirstName,
11784
- disableLastName,
11785
- disableEmail,
11786
- disableCountry,
11787
- disableAddressLine,
11788
- disableCity,
11789
- disableState,
11790
- disableZipCode,
11791
- paymentCurrency,
11792
- showCurrencySelector,
11793
- paymentAmount,
11794
- showDiscounts
11795
- // metadata handled below
11796
- } = data;
11797
- const dodopayments2 = new DodoPayments({
11798
- bearerToken,
11799
- environment
11800
- });
11801
- if (!productId) throw new Error("Missing required field: productId");
11802
- try {
11803
- await dodopayments2.products.retrieve(productId);
11804
- } catch (err) {
11805
- console.error(err);
11806
- throw new Error("Product not found");
11807
- }
11808
- const url = new URL(
11809
- `${environment === "test_mode" ? "https://test.checkout.dodopayments.com" : "https://checkout.dodopayments.com"}/buy/${productId}`
11810
- );
11811
- url.searchParams.set("quantity", quantity2 ? String(quantity2) : "1");
11812
- if (returnUrl) url.searchParams.set("redirect_url", returnUrl);
11813
- if (fullName) url.searchParams.set("fullName", String(fullName));
11814
- if (firstName) url.searchParams.set("firstName", String(firstName));
11815
- if (lastName) url.searchParams.set("lastName", String(lastName));
11816
- if (email) url.searchParams.set("email", String(email));
11817
- if (country) url.searchParams.set("country", String(country));
11818
- if (addressLine) url.searchParams.set("addressLine", String(addressLine));
11819
- if (city) url.searchParams.set("city", String(city));
11820
- if (state) url.searchParams.set("state", String(state));
11821
- if (zipCode) url.searchParams.set("zipCode", String(zipCode));
11822
- if (disableFullName === "true")
11823
- url.searchParams.set("disableFullName", "true");
11824
- if (disableFirstName === "true")
11825
- url.searchParams.set("disableFirstName", "true");
11826
- if (disableLastName === "true")
11827
- url.searchParams.set("disableLastName", "true");
11828
- if (disableEmail === "true") url.searchParams.set("disableEmail", "true");
11829
- if (disableCountry === "true")
11830
- url.searchParams.set("disableCountry", "true");
11831
- if (disableAddressLine === "true")
11832
- url.searchParams.set("disableAddressLine", "true");
11833
- if (disableCity === "true") url.searchParams.set("disableCity", "true");
11834
- if (disableState === "true") url.searchParams.set("disableState", "true");
11835
- if (disableZipCode === "true")
11836
- url.searchParams.set("disableZipCode", "true");
11837
- if (paymentCurrency)
11838
- url.searchParams.set("paymentCurrency", String(paymentCurrency));
11839
- if (showCurrencySelector)
11840
- url.searchParams.set(
11841
- "showCurrencySelector",
11842
- String(showCurrencySelector)
11843
- );
11844
- if (paymentAmount)
11845
- url.searchParams.set("paymentAmount", String(paymentAmount));
11846
- if (showDiscounts)
11847
- url.searchParams.set("showDiscounts", String(showDiscounts));
11848
- for (const [key, value] of Object.entries(queryParams || {})) {
11849
- if (key.startsWith("metadata_") && value && typeof value !== "object") {
11850
- url.searchParams.set(key, String(value));
11851
- }
11852
- }
11853
- return url.toString();
11854
- }
11855
- const dyn = data;
11856
- const {
11857
- product_id,
11858
- product_cart,
11859
- quantity,
11860
- billing,
11861
- customer,
11862
- addons,
11863
- metadata,
11864
- allowed_payment_method_types,
11865
- billing_currency,
11866
- discount_code,
11867
- on_demand,
11868
- return_url: bodyReturnUrl,
11869
- show_saved_payment_methods,
11870
- tax_id,
11871
- trial_period_days
11872
- } = dyn;
11873
- const dodopayments = new DodoPayments({
11874
- bearerToken,
11875
- environment
11876
- });
11877
- let isSubscription = false;
11878
- let productIdToFetch = product_id;
11879
- if (!product_id && product_cart && product_cart.length > 0) {
11880
- productIdToFetch = product_cart[0].product_id;
11881
- }
11882
- if (!productIdToFetch)
11883
- throw new Error(
11884
- "Missing required field: product_id or product_cart[0].product_id"
11885
- );
11886
- let product;
11887
- try {
11888
- product = await dodopayments.products.retrieve(productIdToFetch);
11889
- } catch (err) {
11890
- console.error(err);
11891
- throw new Error("Product not found");
11892
- }
11893
- isSubscription = Boolean(product.is_recurring);
11894
- if (isSubscription && !product_id)
11895
- throw new Error("Missing required field: product_id for subscription");
11896
- if (!billing) throw new Error("Missing required field: billing");
11897
- if (!customer) throw new Error("Missing required field: customer");
11898
- if (isSubscription) {
11899
- const subscriptionPayload = {
11900
- billing,
11901
- customer,
11902
- product_id,
11903
- quantity: quantity ? Number(quantity) : 1
11904
- };
11905
- if (metadata) subscriptionPayload.metadata = metadata;
11906
- if (discount_code) subscriptionPayload.discount_code = discount_code;
11907
- if (addons) subscriptionPayload.addons = addons;
11908
- if (allowed_payment_method_types)
11909
- subscriptionPayload.allowed_payment_method_types = allowed_payment_method_types;
11910
- if (billing_currency)
11911
- subscriptionPayload.billing_currency = billing_currency;
11912
- if (on_demand) subscriptionPayload.on_demand = on_demand;
11913
- subscriptionPayload.payment_link = true;
11914
- if (bodyReturnUrl) {
11915
- subscriptionPayload.return_url = bodyReturnUrl;
11916
- } else if (returnUrl) {
11917
- subscriptionPayload.return_url = returnUrl;
11918
- }
11919
- if (show_saved_payment_methods)
11920
- subscriptionPayload.show_saved_payment_methods = show_saved_payment_methods;
11921
- if (tax_id) subscriptionPayload.tax_id = tax_id;
11922
- if (trial_period_days)
11923
- subscriptionPayload.trial_period_days = trial_period_days;
11924
- let subscription;
11925
- try {
11926
- subscription = await dodopayments.subscriptions.create(subscriptionPayload);
11927
- } catch (err) {
11928
- console.error("Error when creating subscription", err);
11929
- throw new Error(err instanceof Error ? err.message : String(err));
11930
- }
11931
- if (!subscription || !subscription.payment_link) {
11932
- throw new Error(
11933
- "No payment link returned from Dodo Payments API (subscription). Make sure to set payment_link as true in payload"
11934
- );
11935
- }
11936
- return subscription.payment_link;
11937
- } else {
11938
- let cart = product_cart;
11939
- if (!cart && product_id) {
11940
- cart = [
11941
- { product_id, quantity: quantity ? Number(quantity) : 1 }
11942
- ];
11943
- }
11944
- if (!cart || cart.length === 0)
11945
- throw new Error("Missing required field: product_cart or product_id");
11946
- const paymentPayload = {
11947
- billing,
11948
- customer,
11949
- product_cart: cart
11950
- };
11951
- if (metadata) paymentPayload.metadata = metadata;
11952
- paymentPayload.payment_link = true;
11953
- if (allowed_payment_method_types)
11954
- paymentPayload.allowed_payment_method_types = allowed_payment_method_types;
11955
- if (billing_currency) paymentPayload.billing_currency = billing_currency;
11956
- if (discount_code) paymentPayload.discount_code = discount_code;
11957
- if (bodyReturnUrl) {
11958
- paymentPayload.return_url = bodyReturnUrl;
11959
- } else if (returnUrl) {
11960
- paymentPayload.return_url = returnUrl;
11961
- }
11962
- if (show_saved_payment_methods)
11963
- paymentPayload.show_saved_payment_methods = show_saved_payment_methods;
11964
- if (tax_id) paymentPayload.tax_id = tax_id;
11965
- let payment;
11966
- try {
11967
- payment = await dodopayments.payments.create(paymentPayload);
11968
- } catch (err) {
11969
- console.error("Error when creating payment link", err);
11970
- throw new Error(err instanceof Error ? err.message : String(err));
11971
- }
11972
- if (!payment || !payment.payment_link) {
11973
- throw new Error(
11974
- "No payment link returned from Dodo Payments API. Make sure to set payment_link as true in payload."
11975
- );
11976
- }
11977
- return payment.payment_link;
11978
- }
11309
+ base64$1.decodedLength = function (s) {
11310
+ return stdCoder.decodedLength(s);
11979
11311
  };
11980
11312
 
11981
- const Checkout = (config) => {
11982
- const getHandler = async (req) => {
11983
- const { searchParams } = new URL(req.url);
11984
- const queryParams = Object.fromEntries(searchParams);
11985
- if (!queryParams.productId) {
11986
- return new serverExports.NextResponse("Please provide productId query parameter", {
11987
- status: 400,
11988
- });
11989
- }
11990
- const { success, data, error } = checkoutQuerySchema.safeParse(queryParams);
11991
- if (!success) {
11992
- if (error.errors.some((e) => e.path.toString() === "productId")) {
11993
- return new serverExports.NextResponse("Please provide productId query parameter", {
11994
- status: 400,
11995
- });
11996
- }
11997
- return new serverExports.NextResponse(`Invalid query parameters.\n ${error.message}`, {
11998
- status: 400,
11999
- });
12000
- }
12001
- let url = "";
12002
- try {
12003
- url = await buildCheckoutUrl({ queryParams: data, ...config });
12004
- }
12005
- catch (error) {
12006
- return new serverExports.NextResponse(error.message, { status: 400 });
12007
- }
12008
- return serverExports.NextResponse.json({ checkout_url: url });
12009
- };
12010
- const postHandler = async (req) => {
12011
- let body;
12012
- try {
12013
- body = await req.json();
12014
- }
12015
- catch (e) {
12016
- return new serverExports.NextResponse("Invalid JSON body", { status: 400 });
12017
- }
12018
- if (config.type === "dynamic") {
12019
- // Handle dynamic checkout
12020
- const { success, data, error } = dynamicCheckoutBodySchema.safeParse(body);
12021
- if (!success) {
12022
- return new serverExports.NextResponse(`Invalid request body.\n ${error.message}`, {
12023
- status: 400,
12024
- });
12025
- }
12026
- let url = "";
12027
- try {
12028
- url = await buildCheckoutUrl({
12029
- body: data,
12030
- ...config,
12031
- type: "dynamic",
12032
- });
12033
- }
12034
- catch (error) {
12035
- return new serverExports.NextResponse(error.message, { status: 400 });
12036
- }
12037
- return serverExports.NextResponse.json({ checkout_url: url });
12038
- }
12039
- else {
12040
- // Handle checkout session
12041
- const { success, data, error } = checkoutSessionPayloadSchema.safeParse(body);
12042
- if (!success) {
12043
- return new serverExports.NextResponse(`Invalid checkout session payload.\n ${error.message}`, {
12044
- status: 400,
12045
- });
12046
- }
12047
- let url = "";
12048
- try {
12049
- url = await buildCheckoutUrl({
12050
- sessionPayload: data,
12051
- ...config,
12052
- type: "session",
12053
- });
12054
- }
12055
- catch (error) {
12056
- return new serverExports.NextResponse(error.message, { status: 400 });
12057
- }
12058
- return serverExports.NextResponse.json({ checkout_url: url });
12059
- }
12060
- };
12061
- return (req) => {
12062
- if (req.method === "POST") {
12063
- return postHandler(req);
12064
- }
12065
- return getHandler(req);
12066
- };
12067
- };
12068
-
12069
- var dist = {};
12070
-
12071
- var timing_safe_equal = {};
12072
-
12073
- Object.defineProperty(timing_safe_equal, "__esModule", { value: true });
12074
- timing_safe_equal.timingSafeEqual = void 0;
12075
- function assert(expr, msg = "") {
12076
- if (!expr) {
12077
- throw new Error(msg);
12078
- }
12079
- }
12080
- function timingSafeEqual(a, b) {
12081
- if (a.byteLength !== b.byteLength) {
12082
- return false;
12083
- }
12084
- if (!(a instanceof DataView)) {
12085
- a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
12086
- }
12087
- if (!(b instanceof DataView)) {
12088
- b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
12089
- }
12090
- assert(a instanceof DataView);
12091
- assert(b instanceof DataView);
12092
- const length = a.byteLength;
12093
- let out = 0;
12094
- let i = -1;
12095
- while (++i < length) {
12096
- out |= a.getUint8(i) ^ b.getUint8(i);
12097
- }
12098
- return out === 0;
12099
- }
12100
- timing_safe_equal.timingSafeEqual = timingSafeEqual;
12101
-
12102
- var base64$1 = {};
12103
-
12104
- // Copyright (C) 2016 Dmitry Chestnykh
12105
- // MIT License. See LICENSE file for details.
12106
- var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () {
12107
- var extendStatics = function (d, b) {
12108
- extendStatics = Object.setPrototypeOf ||
12109
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
12110
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12111
- return extendStatics(d, b);
12112
- };
12113
- return function (d, b) {
12114
- extendStatics(d, b);
12115
- function __() { this.constructor = d; }
12116
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12117
- };
12118
- })();
12119
- Object.defineProperty(base64$1, "__esModule", { value: true });
12120
- /**
12121
- * Package base64 implements Base64 encoding and decoding.
12122
- */
12123
- // Invalid character used in decoding to indicate
12124
- // that the character to decode is out of range of
12125
- // alphabet and cannot be decoded.
12126
- var INVALID_BYTE = 256;
12127
- /**
12128
- * Implements standard Base64 encoding.
12129
- *
12130
- * Operates in constant time.
12131
- */
12132
- var Coder = /** @class */ (function () {
12133
- // TODO(dchest): methods to encode chunk-by-chunk.
12134
- function Coder(_paddingCharacter) {
12135
- if (_paddingCharacter === void 0) { _paddingCharacter = "="; }
12136
- this._paddingCharacter = _paddingCharacter;
12137
- }
12138
- Coder.prototype.encodedLength = function (length) {
12139
- if (!this._paddingCharacter) {
12140
- return (length * 8 + 5) / 6 | 0;
12141
- }
12142
- return (length + 2) / 3 * 4 | 0;
12143
- };
12144
- Coder.prototype.encode = function (data) {
12145
- var out = "";
12146
- var i = 0;
12147
- for (; i < data.length - 2; i += 3) {
12148
- var c = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
12149
- out += this._encodeByte((c >>> 3 * 6) & 63);
12150
- out += this._encodeByte((c >>> 2 * 6) & 63);
12151
- out += this._encodeByte((c >>> 1 * 6) & 63);
12152
- out += this._encodeByte((c >>> 0 * 6) & 63);
12153
- }
12154
- var left = data.length - i;
12155
- if (left > 0) {
12156
- var c = (data[i] << 16) | (left === 2 ? data[i + 1] << 8 : 0);
12157
- out += this._encodeByte((c >>> 3 * 6) & 63);
12158
- out += this._encodeByte((c >>> 2 * 6) & 63);
12159
- if (left === 2) {
12160
- out += this._encodeByte((c >>> 1 * 6) & 63);
12161
- }
12162
- else {
12163
- out += this._paddingCharacter || "";
12164
- }
12165
- out += this._paddingCharacter || "";
12166
- }
12167
- return out;
12168
- };
12169
- Coder.prototype.maxDecodedLength = function (length) {
12170
- if (!this._paddingCharacter) {
12171
- return (length * 6 + 7) / 8 | 0;
12172
- }
12173
- return length / 4 * 3 | 0;
12174
- };
12175
- Coder.prototype.decodedLength = function (s) {
12176
- return this.maxDecodedLength(s.length - this._getPaddingLength(s));
12177
- };
12178
- Coder.prototype.decode = function (s) {
12179
- if (s.length === 0) {
12180
- return new Uint8Array(0);
12181
- }
12182
- var paddingLength = this._getPaddingLength(s);
12183
- var length = s.length - paddingLength;
12184
- var out = new Uint8Array(this.maxDecodedLength(length));
12185
- var op = 0;
12186
- var i = 0;
12187
- var haveBad = 0;
12188
- var v0 = 0, v1 = 0, v2 = 0, v3 = 0;
12189
- for (; i < length - 4; i += 4) {
12190
- v0 = this._decodeChar(s.charCodeAt(i + 0));
12191
- v1 = this._decodeChar(s.charCodeAt(i + 1));
12192
- v2 = this._decodeChar(s.charCodeAt(i + 2));
12193
- v3 = this._decodeChar(s.charCodeAt(i + 3));
12194
- out[op++] = (v0 << 2) | (v1 >>> 4);
12195
- out[op++] = (v1 << 4) | (v2 >>> 2);
12196
- out[op++] = (v2 << 6) | v3;
12197
- haveBad |= v0 & INVALID_BYTE;
12198
- haveBad |= v1 & INVALID_BYTE;
12199
- haveBad |= v2 & INVALID_BYTE;
12200
- haveBad |= v3 & INVALID_BYTE;
12201
- }
12202
- if (i < length - 1) {
12203
- v0 = this._decodeChar(s.charCodeAt(i));
12204
- v1 = this._decodeChar(s.charCodeAt(i + 1));
12205
- out[op++] = (v0 << 2) | (v1 >>> 4);
12206
- haveBad |= v0 & INVALID_BYTE;
12207
- haveBad |= v1 & INVALID_BYTE;
12208
- }
12209
- if (i < length - 2) {
12210
- v2 = this._decodeChar(s.charCodeAt(i + 2));
12211
- out[op++] = (v1 << 4) | (v2 >>> 2);
12212
- haveBad |= v2 & INVALID_BYTE;
12213
- }
12214
- if (i < length - 3) {
12215
- v3 = this._decodeChar(s.charCodeAt(i + 3));
12216
- out[op++] = (v2 << 6) | v3;
12217
- haveBad |= v3 & INVALID_BYTE;
12218
- }
12219
- if (haveBad !== 0) {
12220
- throw new Error("Base64Coder: incorrect characters for decoding");
12221
- }
12222
- return out;
12223
- };
12224
- // Standard encoding have the following encoded/decoded ranges,
12225
- // which we need to convert between.
12226
- //
12227
- // ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 + /
12228
- // Index: 0 - 25 26 - 51 52 - 61 62 63
12229
- // ASCII: 65 - 90 97 - 122 48 - 57 43 47
12230
- //
12231
- // Encode 6 bits in b into a new character.
12232
- Coder.prototype._encodeByte = function (b) {
12233
- // Encoding uses constant time operations as follows:
12234
- //
12235
- // 1. Define comparison of A with B using (A - B) >>> 8:
12236
- // if A > B, then result is positive integer
12237
- // if A <= B, then result is 0
12238
- //
12239
- // 2. Define selection of C or 0 using bitwise AND: X & C:
12240
- // if X == 0, then result is 0
12241
- // if X != 0, then result is C
12242
- //
12243
- // 3. Start with the smallest comparison (b >= 0), which is always
12244
- // true, so set the result to the starting ASCII value (65).
12245
- //
12246
- // 4. Continue comparing b to higher ASCII values, and selecting
12247
- // zero if comparison isn't true, otherwise selecting a value
12248
- // to add to result, which:
12249
- //
12250
- // a) undoes the previous addition
12251
- // b) provides new value to add
12252
- //
12253
- var result = b;
12254
- // b >= 0
12255
- result += 65;
12256
- // b > 25
12257
- result += ((25 - b) >>> 8) & ((0 - 65) - 26 + 97);
12258
- // b > 51
12259
- result += ((51 - b) >>> 8) & ((26 - 97) - 52 + 48);
12260
- // b > 61
12261
- result += ((61 - b) >>> 8) & ((52 - 48) - 62 + 43);
12262
- // b > 62
12263
- result += ((62 - b) >>> 8) & ((62 - 43) - 63 + 47);
12264
- return String.fromCharCode(result);
12265
- };
12266
- // Decode a character code into a byte.
12267
- // Must return 256 if character is out of alphabet range.
12268
- Coder.prototype._decodeChar = function (c) {
12269
- // Decoding works similar to encoding: using the same comparison
12270
- // function, but now it works on ranges: result is always incremented
12271
- // by value, but this value becomes zero if the range is not
12272
- // satisfied.
12273
- //
12274
- // Decoding starts with invalid value, 256, which is then
12275
- // subtracted when the range is satisfied. If none of the ranges
12276
- // apply, the function returns 256, which is then checked by
12277
- // the caller to throw error.
12278
- var result = INVALID_BYTE; // start with invalid character
12279
- // c == 43 (c > 42 and c < 44)
12280
- result += (((42 - c) & (c - 44)) >>> 8) & (-INVALID_BYTE + c - 43 + 62);
12281
- // c == 47 (c > 46 and c < 48)
12282
- result += (((46 - c) & (c - 48)) >>> 8) & (-INVALID_BYTE + c - 47 + 63);
12283
- // c > 47 and c < 58
12284
- result += (((47 - c) & (c - 58)) >>> 8) & (-INVALID_BYTE + c - 48 + 52);
12285
- // c > 64 and c < 91
12286
- result += (((64 - c) & (c - 91)) >>> 8) & (-INVALID_BYTE + c - 65 + 0);
12287
- // c > 96 and c < 123
12288
- result += (((96 - c) & (c - 123)) >>> 8) & (-INVALID_BYTE + c - 97 + 26);
12289
- return result;
12290
- };
12291
- Coder.prototype._getPaddingLength = function (s) {
12292
- var paddingLength = 0;
12293
- if (this._paddingCharacter) {
12294
- for (var i = s.length - 1; i >= 0; i--) {
12295
- if (s[i] !== this._paddingCharacter) {
12296
- break;
12297
- }
12298
- paddingLength++;
12299
- }
12300
- if (s.length < 4 || paddingLength > 2) {
12301
- throw new Error("Base64Coder: incorrect padding");
12302
- }
12303
- }
12304
- return paddingLength;
12305
- };
12306
- return Coder;
12307
- }());
12308
- base64$1.Coder = Coder;
12309
- var stdCoder = new Coder();
12310
- function encode(data) {
12311
- return stdCoder.encode(data);
12312
- }
12313
- base64$1.encode = encode;
12314
- function decode(s) {
12315
- return stdCoder.decode(s);
12316
- }
12317
- base64$1.decode = decode;
12318
- /**
12319
- * Implements URL-safe Base64 encoding.
12320
- * (Same as Base64, but '+' is replaced with '-', and '/' with '_').
12321
- *
12322
- * Operates in constant time.
12323
- */
12324
- var URLSafeCoder = /** @class */ (function (_super) {
12325
- __extends(URLSafeCoder, _super);
12326
- function URLSafeCoder() {
12327
- return _super !== null && _super.apply(this, arguments) || this;
12328
- }
12329
- // URL-safe encoding have the following encoded/decoded ranges:
12330
- //
12331
- // ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 - _
12332
- // Index: 0 - 25 26 - 51 52 - 61 62 63
12333
- // ASCII: 65 - 90 97 - 122 48 - 57 45 95
12334
- //
12335
- URLSafeCoder.prototype._encodeByte = function (b) {
12336
- var result = b;
12337
- // b >= 0
12338
- result += 65;
12339
- // b > 25
12340
- result += ((25 - b) >>> 8) & ((0 - 65) - 26 + 97);
12341
- // b > 51
12342
- result += ((51 - b) >>> 8) & ((26 - 97) - 52 + 48);
12343
- // b > 61
12344
- result += ((61 - b) >>> 8) & ((52 - 48) - 62 + 45);
12345
- // b > 62
12346
- result += ((62 - b) >>> 8) & ((62 - 45) - 63 + 95);
12347
- return String.fromCharCode(result);
12348
- };
12349
- URLSafeCoder.prototype._decodeChar = function (c) {
12350
- var result = INVALID_BYTE;
12351
- // c == 45 (c > 44 and c < 46)
12352
- result += (((44 - c) & (c - 46)) >>> 8) & (-INVALID_BYTE + c - 45 + 62);
12353
- // c == 95 (c > 94 and c < 96)
12354
- result += (((94 - c) & (c - 96)) >>> 8) & (-INVALID_BYTE + c - 95 + 63);
12355
- // c > 47 and c < 58
12356
- result += (((47 - c) & (c - 58)) >>> 8) & (-INVALID_BYTE + c - 48 + 52);
12357
- // c > 64 and c < 91
12358
- result += (((64 - c) & (c - 91)) >>> 8) & (-INVALID_BYTE + c - 65 + 0);
12359
- // c > 96 and c < 123
12360
- result += (((96 - c) & (c - 123)) >>> 8) & (-INVALID_BYTE + c - 97 + 26);
12361
- return result;
12362
- };
12363
- return URLSafeCoder;
12364
- }(Coder));
12365
- base64$1.URLSafeCoder = URLSafeCoder;
12366
- var urlSafeCoder = new URLSafeCoder();
12367
- function encodeURLSafe(data) {
12368
- return urlSafeCoder.encode(data);
12369
- }
12370
- base64$1.encodeURLSafe = encodeURLSafe;
12371
- function decodeURLSafe(s) {
12372
- return urlSafeCoder.decode(s);
12373
- }
12374
- base64$1.decodeURLSafe = decodeURLSafe;
12375
- base64$1.encodedLength = function (length) {
12376
- return stdCoder.encodedLength(length);
12377
- };
12378
- base64$1.maxDecodedLength = function (length) {
12379
- return stdCoder.maxDecodedLength(length);
12380
- };
12381
- base64$1.decodedLength = function (s) {
12382
- return stdCoder.decodedLength(s);
12383
- };
12384
-
12385
- var sha256$1 = {exports: {}};
11313
+ var sha256$1 = {exports: {}};
12386
11314
 
12387
11315
  (function (module) {
12388
11316
  (function (root, factory) {
@@ -12824,96 +11752,1219 @@ class ExtendableError extends Error {
12824
11752
  this.name = "ExtendableError";
12825
11753
  this.stack = new Error(message).stack;
12826
11754
  }
12827
- }
12828
- class WebhookVerificationError extends ExtendableError {
12829
- constructor(message) {
12830
- super(message);
12831
- Object.setPrototypeOf(this, WebhookVerificationError.prototype);
12832
- this.name = "WebhookVerificationError";
11755
+ }
11756
+ class WebhookVerificationError extends ExtendableError {
11757
+ constructor(message) {
11758
+ super(message);
11759
+ Object.setPrototypeOf(this, WebhookVerificationError.prototype);
11760
+ this.name = "WebhookVerificationError";
11761
+ }
11762
+ }
11763
+ var WebhookVerificationError_1 = dist.WebhookVerificationError = WebhookVerificationError;
11764
+ class Webhook {
11765
+ constructor(secret, options) {
11766
+ if (!secret) {
11767
+ throw new Error("Secret can't be empty.");
11768
+ }
11769
+ if ((options === null || options === void 0 ? void 0 : options.format) === "raw") {
11770
+ if (secret instanceof Uint8Array) {
11771
+ this.key = secret;
11772
+ }
11773
+ else {
11774
+ this.key = Uint8Array.from(secret, (c) => c.charCodeAt(0));
11775
+ }
11776
+ }
11777
+ else {
11778
+ if (typeof secret !== "string") {
11779
+ throw new Error("Expected secret to be of type string");
11780
+ }
11781
+ if (secret.startsWith(Webhook.prefix)) {
11782
+ secret = secret.substring(Webhook.prefix.length);
11783
+ }
11784
+ this.key = base64.decode(secret);
11785
+ }
11786
+ }
11787
+ verify(payload, headers_) {
11788
+ const headers = {};
11789
+ for (const key of Object.keys(headers_)) {
11790
+ headers[key.toLowerCase()] = headers_[key];
11791
+ }
11792
+ const msgId = headers["webhook-id"];
11793
+ const msgSignature = headers["webhook-signature"];
11794
+ const msgTimestamp = headers["webhook-timestamp"];
11795
+ if (!msgSignature || !msgId || !msgTimestamp) {
11796
+ throw new WebhookVerificationError("Missing required headers");
11797
+ }
11798
+ const timestamp = this.verifyTimestamp(msgTimestamp);
11799
+ const computedSignature = this.sign(msgId, timestamp, payload);
11800
+ const expectedSignature = computedSignature.split(",")[1];
11801
+ const passedSignatures = msgSignature.split(" ");
11802
+ const encoder = new globalThis.TextEncoder();
11803
+ for (const versionedSignature of passedSignatures) {
11804
+ const [version, signature] = versionedSignature.split(",");
11805
+ if (version !== "v1") {
11806
+ continue;
11807
+ }
11808
+ if ((0, timing_safe_equal_1.timingSafeEqual)(encoder.encode(signature), encoder.encode(expectedSignature))) {
11809
+ return JSON.parse(payload.toString());
11810
+ }
11811
+ }
11812
+ throw new WebhookVerificationError("No matching signature found");
11813
+ }
11814
+ sign(msgId, timestamp, payload) {
11815
+ if (typeof payload === "string") ;
11816
+ else if (payload.constructor.name === "Buffer") {
11817
+ payload = payload.toString();
11818
+ }
11819
+ else {
11820
+ throw new Error("Expected payload to be of type string or Buffer.");
11821
+ }
11822
+ const encoder = new TextEncoder();
11823
+ const timestampNumber = Math.floor(timestamp.getTime() / 1000);
11824
+ const toSign = encoder.encode(`${msgId}.${timestampNumber}.${payload}`);
11825
+ const expectedSignature = base64.encode(sha256.hmac(this.key, toSign));
11826
+ return `v1,${expectedSignature}`;
11827
+ }
11828
+ verifyTimestamp(timestampHeader) {
11829
+ const now = Math.floor(Date.now() / 1000);
11830
+ const timestamp = parseInt(timestampHeader, 10);
11831
+ if (isNaN(timestamp)) {
11832
+ throw new WebhookVerificationError("Invalid Signature Headers");
11833
+ }
11834
+ if (now - timestamp > WEBHOOK_TOLERANCE_IN_SECONDS) {
11835
+ throw new WebhookVerificationError("Message timestamp too old");
11836
+ }
11837
+ if (timestamp > now + WEBHOOK_TOLERANCE_IN_SECONDS) {
11838
+ throw new WebhookVerificationError("Message timestamp too new");
11839
+ }
11840
+ return new Date(timestamp * 1000);
11841
+ }
11842
+ }
11843
+ Webhook_1 = dist.Webhook = Webhook;
11844
+ Webhook.prefix = "whsec_";
11845
+
11846
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
11847
+ let Webhooks$1 = class Webhooks extends APIResource {
11848
+ constructor() {
11849
+ super(...arguments);
11850
+ this.headers = new Headers$1(this._client);
11851
+ }
11852
+ /**
11853
+ * Create a new webhook
11854
+ */
11855
+ create(body, options) {
11856
+ return this._client.post('/webhooks', { body, ...options });
11857
+ }
11858
+ /**
11859
+ * Get a webhook by id
11860
+ */
11861
+ retrieve(webhookID, options) {
11862
+ return this._client.get(path `/webhooks/${webhookID}`, options);
11863
+ }
11864
+ /**
11865
+ * Patch a webhook by id
11866
+ */
11867
+ update(webhookID, body, options) {
11868
+ return this._client.patch(path `/webhooks/${webhookID}`, { body, ...options });
11869
+ }
11870
+ /**
11871
+ * List all webhooks
11872
+ */
11873
+ list(query = {}, options) {
11874
+ return this._client.getAPIList('/webhooks', (CursorPagePagination), { query, ...options });
11875
+ }
11876
+ /**
11877
+ * Delete a webhook by id
11878
+ */
11879
+ delete(webhookID, options) {
11880
+ return this._client.delete(path `/webhooks/${webhookID}`, {
11881
+ ...options,
11882
+ headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
11883
+ });
11884
+ }
11885
+ /**
11886
+ * Get webhook secret by id
11887
+ */
11888
+ retrieveSecret(webhookID, options) {
11889
+ return this._client.get(path `/webhooks/${webhookID}/secret`, options);
11890
+ }
11891
+ unsafeUnwrap(body) {
11892
+ return JSON.parse(body);
11893
+ }
11894
+ unwrap(body, { headers, key }) {
11895
+ if (headers !== undefined) {
11896
+ const keyStr = key === undefined ? this._client.webhookKey : key;
11897
+ if (keyStr === null)
11898
+ throw new Error('Webhook key must not be null in order to unwrap');
11899
+ const wh = new Webhook_1(keyStr);
11900
+ wh.verify(body, headers);
11901
+ }
11902
+ return JSON.parse(body);
11903
+ }
11904
+ };
11905
+ Webhooks$1.Headers = Headers$1;
11906
+
11907
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
11908
+ /**
11909
+ * Read an environment variable.
11910
+ *
11911
+ * Trims beginning and trailing whitespace.
11912
+ *
11913
+ * Will return undefined if the environment variable doesn't exist or cannot be accessed.
11914
+ */
11915
+ const readEnv = (env) => {
11916
+ if (typeof globalThis.process !== 'undefined') {
11917
+ return globalThis.process.env?.[env]?.trim() ?? undefined;
11918
+ }
11919
+ if (typeof globalThis.Deno !== 'undefined') {
11920
+ return globalThis.Deno.env?.get?.(env)?.trim();
11921
+ }
11922
+ return undefined;
11923
+ };
11924
+
11925
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
11926
+ var _DodoPayments_instances, _a, _DodoPayments_encoder, _DodoPayments_baseURLOverridden;
11927
+ const environments = {
11928
+ live_mode: 'https://live.dodopayments.com',
11929
+ test_mode: 'https://test.dodopayments.com',
11930
+ };
11931
+ /**
11932
+ * API Client for interfacing with the Dodo Payments API.
11933
+ */
11934
+ class DodoPayments {
11935
+ /**
11936
+ * API Client for interfacing with the Dodo Payments API.
11937
+ *
11938
+ * @param {string | undefined} [opts.bearerToken=process.env['DODO_PAYMENTS_API_KEY'] ?? undefined]
11939
+ * @param {string | null | undefined} [opts.webhookKey=process.env['DODO_PAYMENTS_WEBHOOK_KEY'] ?? null]
11940
+ * @param {Environment} [opts.environment=live_mode] - Specifies the environment URL to use for the API.
11941
+ * @param {string} [opts.baseURL=process.env['DODO_PAYMENTS_BASE_URL'] ?? https://live.dodopayments.com] - Override the default base URL for the API.
11942
+ * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
11943
+ * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
11944
+ * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
11945
+ * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
11946
+ * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
11947
+ * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
11948
+ */
11949
+ constructor({ baseURL = readEnv('DODO_PAYMENTS_BASE_URL'), bearerToken = readEnv('DODO_PAYMENTS_API_KEY'), webhookKey = readEnv('DODO_PAYMENTS_WEBHOOK_KEY') ?? null, ...opts } = {}) {
11950
+ _DodoPayments_instances.add(this);
11951
+ _DodoPayments_encoder.set(this, void 0);
11952
+ this.checkoutSessions = new CheckoutSessions(this);
11953
+ this.payments = new Payments(this);
11954
+ this.subscriptions = new Subscriptions(this);
11955
+ this.invoices = new Invoices(this);
11956
+ this.licenses = new Licenses(this);
11957
+ this.licenseKeys = new LicenseKeys(this);
11958
+ this.licenseKeyInstances = new LicenseKeyInstances(this);
11959
+ this.customers = new Customers(this);
11960
+ this.refunds = new Refunds(this);
11961
+ this.disputes = new Disputes(this);
11962
+ this.payouts = new Payouts(this);
11963
+ this.products = new Products(this);
11964
+ this.misc = new Misc(this);
11965
+ this.discounts = new Discounts(this);
11966
+ this.addons = new Addons(this);
11967
+ this.brands = new Brands(this);
11968
+ this.webhooks = new Webhooks$1(this);
11969
+ this.webhookEvents = new WebhookEvents(this);
11970
+ this.usageEvents = new UsageEvents(this);
11971
+ this.meters = new Meters(this);
11972
+ if (bearerToken === undefined) {
11973
+ throw new DodoPaymentsError("The DODO_PAYMENTS_API_KEY environment variable is missing or empty; either provide it, or instantiate the DodoPayments client with an bearerToken option, like new DodoPayments({ bearerToken: 'My Bearer Token' }).");
11974
+ }
11975
+ const options = {
11976
+ bearerToken,
11977
+ webhookKey,
11978
+ ...opts,
11979
+ baseURL,
11980
+ environment: opts.environment ?? 'live_mode',
11981
+ };
11982
+ if (baseURL && opts.environment) {
11983
+ throw new DodoPaymentsError('Ambiguous URL; The `baseURL` option (or DODO_PAYMENTS_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null');
11984
+ }
11985
+ this.baseURL = options.baseURL || environments[options.environment || 'live_mode'];
11986
+ this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT /* 1 minute */;
11987
+ this.logger = options.logger ?? console;
11988
+ const defaultLogLevel = 'warn';
11989
+ // Set default logLevel early so that we can log a warning in parseLogLevel.
11990
+ this.logLevel = defaultLogLevel;
11991
+ this.logLevel =
11992
+ parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
11993
+ parseLogLevel(readEnv('DODO_PAYMENTS_LOG'), "process.env['DODO_PAYMENTS_LOG']", this) ??
11994
+ defaultLogLevel;
11995
+ this.fetchOptions = options.fetchOptions;
11996
+ this.maxRetries = options.maxRetries ?? 2;
11997
+ this.fetch = options.fetch ?? getDefaultFetch();
11998
+ __classPrivateFieldSet(this, _DodoPayments_encoder, FallbackEncoder);
11999
+ this._options = options;
12000
+ this.bearerToken = bearerToken;
12001
+ this.webhookKey = webhookKey;
12002
+ }
12003
+ /**
12004
+ * Create a new client instance re-using the same options given to the current client with optional overriding.
12005
+ */
12006
+ withOptions(options) {
12007
+ const client = new this.constructor({
12008
+ ...this._options,
12009
+ environment: options.environment ? options.environment : undefined,
12010
+ baseURL: options.environment ? undefined : this.baseURL,
12011
+ maxRetries: this.maxRetries,
12012
+ timeout: this.timeout,
12013
+ logger: this.logger,
12014
+ logLevel: this.logLevel,
12015
+ fetch: this.fetch,
12016
+ fetchOptions: this.fetchOptions,
12017
+ bearerToken: this.bearerToken,
12018
+ webhookKey: this.webhookKey,
12019
+ ...options,
12020
+ });
12021
+ return client;
12022
+ }
12023
+ defaultQuery() {
12024
+ return this._options.defaultQuery;
12025
+ }
12026
+ validateHeaders({ values, nulls }) {
12027
+ return;
12028
+ }
12029
+ async authHeaders(opts) {
12030
+ return buildHeaders([{ Authorization: `Bearer ${this.bearerToken}` }]);
12031
+ }
12032
+ /**
12033
+ * Basic re-implementation of `qs.stringify` for primitive types.
12034
+ */
12035
+ stringifyQuery(query) {
12036
+ return Object.entries(query)
12037
+ .filter(([_, value]) => typeof value !== 'undefined')
12038
+ .map(([key, value]) => {
12039
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
12040
+ return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
12041
+ }
12042
+ if (value === null) {
12043
+ return `${encodeURIComponent(key)}=`;
12044
+ }
12045
+ throw new DodoPaymentsError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`);
12046
+ })
12047
+ .join('&');
12048
+ }
12049
+ getUserAgent() {
12050
+ return `${this.constructor.name}/JS ${VERSION}`;
12051
+ }
12052
+ defaultIdempotencyKey() {
12053
+ return `stainless-node-retry-${uuid4()}`;
12054
+ }
12055
+ makeStatusError(status, error, message, headers) {
12056
+ return APIError.generate(status, error, message, headers);
12057
+ }
12058
+ buildURL(path, query, defaultBaseURL) {
12059
+ const baseURL = (!__classPrivateFieldGet(this, _DodoPayments_instances, "m", _DodoPayments_baseURLOverridden).call(this) && defaultBaseURL) || this.baseURL;
12060
+ const url = isAbsoluteURL(path) ?
12061
+ new URL(path)
12062
+ : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
12063
+ const defaultQuery = this.defaultQuery();
12064
+ if (!isEmptyObj(defaultQuery)) {
12065
+ query = { ...defaultQuery, ...query };
12066
+ }
12067
+ if (typeof query === 'object' && query && !Array.isArray(query)) {
12068
+ url.search = this.stringifyQuery(query);
12069
+ }
12070
+ return url.toString();
12071
+ }
12072
+ /**
12073
+ * Used as a callback for mutating the given `FinalRequestOptions` object.
12074
+ */
12075
+ async prepareOptions(options) { }
12076
+ /**
12077
+ * Used as a callback for mutating the given `RequestInit` object.
12078
+ *
12079
+ * This is useful for cases where you want to add certain headers based off of
12080
+ * the request properties, e.g. `method` or `url`.
12081
+ */
12082
+ async prepareRequest(request, { url, options }) { }
12083
+ get(path, opts) {
12084
+ return this.methodRequest('get', path, opts);
12085
+ }
12086
+ post(path, opts) {
12087
+ return this.methodRequest('post', path, opts);
12088
+ }
12089
+ patch(path, opts) {
12090
+ return this.methodRequest('patch', path, opts);
12091
+ }
12092
+ put(path, opts) {
12093
+ return this.methodRequest('put', path, opts);
12094
+ }
12095
+ delete(path, opts) {
12096
+ return this.methodRequest('delete', path, opts);
12097
+ }
12098
+ methodRequest(method, path, opts) {
12099
+ return this.request(Promise.resolve(opts).then((opts) => {
12100
+ return { method, path, ...opts };
12101
+ }));
12102
+ }
12103
+ request(options, remainingRetries = null) {
12104
+ return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
12105
+ }
12106
+ async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {
12107
+ const options = await optionsInput;
12108
+ const maxRetries = options.maxRetries ?? this.maxRetries;
12109
+ if (retriesRemaining == null) {
12110
+ retriesRemaining = maxRetries;
12111
+ }
12112
+ await this.prepareOptions(options);
12113
+ const { req, url, timeout } = await this.buildRequest(options, {
12114
+ retryCount: maxRetries - retriesRemaining,
12115
+ });
12116
+ await this.prepareRequest(req, { url, options });
12117
+ /** Not an API request ID, just for correlating local log entries. */
12118
+ const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
12119
+ const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
12120
+ const startTime = Date.now();
12121
+ loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({
12122
+ retryOfRequestLogID,
12123
+ method: options.method,
12124
+ url,
12125
+ options,
12126
+ headers: req.headers,
12127
+ }));
12128
+ if (options.signal?.aborted) {
12129
+ throw new APIUserAbortError();
12130
+ }
12131
+ const controller = new AbortController();
12132
+ const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
12133
+ const headersTime = Date.now();
12134
+ if (response instanceof globalThis.Error) {
12135
+ const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
12136
+ if (options.signal?.aborted) {
12137
+ throw new APIUserAbortError();
12138
+ }
12139
+ // detect native connection timeout errors
12140
+ // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
12141
+ // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
12142
+ // others do not provide enough information to distinguish timeouts from other connection errors
12143
+ const isTimeout = isAbortError(response) ||
12144
+ /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
12145
+ if (retriesRemaining) {
12146
+ loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`);
12147
+ loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({
12148
+ retryOfRequestLogID,
12149
+ url,
12150
+ durationMs: headersTime - startTime,
12151
+ message: response.message,
12152
+ }));
12153
+ return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
12154
+ }
12155
+ loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`);
12156
+ loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({
12157
+ retryOfRequestLogID,
12158
+ url,
12159
+ durationMs: headersTime - startTime,
12160
+ message: response.message,
12161
+ }));
12162
+ if (isTimeout) {
12163
+ throw new APIConnectionTimeoutError();
12164
+ }
12165
+ throw new APIConnectionError({ cause: response });
12166
+ }
12167
+ const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;
12168
+ if (!response.ok) {
12169
+ const shouldRetry = await this.shouldRetry(response);
12170
+ if (retriesRemaining && shouldRetry) {
12171
+ const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
12172
+ // We don't need the body of this response.
12173
+ await CancelReadableStream(response.body);
12174
+ loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
12175
+ loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
12176
+ retryOfRequestLogID,
12177
+ url: response.url,
12178
+ status: response.status,
12179
+ headers: response.headers,
12180
+ durationMs: headersTime - startTime,
12181
+ }));
12182
+ return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers);
12183
+ }
12184
+ const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
12185
+ loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
12186
+ const errText = await response.text().catch((err) => castToError(err).message);
12187
+ const errJSON = safeJSON(errText);
12188
+ const errMessage = errJSON ? undefined : errText;
12189
+ loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
12190
+ retryOfRequestLogID,
12191
+ url: response.url,
12192
+ status: response.status,
12193
+ headers: response.headers,
12194
+ message: errMessage,
12195
+ durationMs: Date.now() - startTime,
12196
+ }));
12197
+ const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
12198
+ throw err;
12199
+ }
12200
+ loggerFor(this).info(responseInfo);
12201
+ loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
12202
+ retryOfRequestLogID,
12203
+ url: response.url,
12204
+ status: response.status,
12205
+ headers: response.headers,
12206
+ durationMs: headersTime - startTime,
12207
+ }));
12208
+ return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
12209
+ }
12210
+ getAPIList(path, Page, opts) {
12211
+ return this.requestAPIList(Page, { method: 'get', path, ...opts });
12212
+ }
12213
+ requestAPIList(Page, options) {
12214
+ const request = this.makeRequest(options, null, undefined);
12215
+ return new PagePromise(this, request, Page);
12216
+ }
12217
+ async fetchWithTimeout(url, init, ms, controller) {
12218
+ const { signal, method, ...options } = init || {};
12219
+ if (signal)
12220
+ signal.addEventListener('abort', () => controller.abort());
12221
+ const timeout = setTimeout(() => controller.abort(), ms);
12222
+ const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) ||
12223
+ (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
12224
+ const fetchOptions = {
12225
+ signal: controller.signal,
12226
+ ...(isReadableBody ? { duplex: 'half' } : {}),
12227
+ method: 'GET',
12228
+ ...options,
12229
+ };
12230
+ if (method) {
12231
+ // Custom methods like 'patch' need to be uppercased
12232
+ // See https://github.com/nodejs/undici/issues/2294
12233
+ fetchOptions.method = method.toUpperCase();
12234
+ }
12235
+ try {
12236
+ // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
12237
+ return await this.fetch.call(undefined, url, fetchOptions);
12238
+ }
12239
+ finally {
12240
+ clearTimeout(timeout);
12241
+ }
12242
+ }
12243
+ async shouldRetry(response) {
12244
+ // Note this is not a standard header.
12245
+ const shouldRetryHeader = response.headers.get('x-should-retry');
12246
+ // If the server explicitly says whether or not to retry, obey.
12247
+ if (shouldRetryHeader === 'true')
12248
+ return true;
12249
+ if (shouldRetryHeader === 'false')
12250
+ return false;
12251
+ // Retry on request timeouts.
12252
+ if (response.status === 408)
12253
+ return true;
12254
+ // Retry on lock timeouts.
12255
+ if (response.status === 409)
12256
+ return true;
12257
+ // Retry on rate limits.
12258
+ if (response.status === 429)
12259
+ return true;
12260
+ // Retry internal errors.
12261
+ if (response.status >= 500)
12262
+ return true;
12263
+ return false;
12264
+ }
12265
+ async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) {
12266
+ let timeoutMillis;
12267
+ // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.
12268
+ const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');
12269
+ if (retryAfterMillisHeader) {
12270
+ const timeoutMs = parseFloat(retryAfterMillisHeader);
12271
+ if (!Number.isNaN(timeoutMs)) {
12272
+ timeoutMillis = timeoutMs;
12273
+ }
12274
+ }
12275
+ // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
12276
+ const retryAfterHeader = responseHeaders?.get('retry-after');
12277
+ if (retryAfterHeader && !timeoutMillis) {
12278
+ const timeoutSeconds = parseFloat(retryAfterHeader);
12279
+ if (!Number.isNaN(timeoutSeconds)) {
12280
+ timeoutMillis = timeoutSeconds * 1000;
12281
+ }
12282
+ else {
12283
+ timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
12284
+ }
12285
+ }
12286
+ // If the API asks us to wait a certain amount of time (and it's a reasonable amount),
12287
+ // just do what it says, but otherwise calculate a default
12288
+ if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
12289
+ const maxRetries = options.maxRetries ?? this.maxRetries;
12290
+ timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
12291
+ }
12292
+ await sleep(timeoutMillis);
12293
+ return this.makeRequest(options, retriesRemaining - 1, requestLogID);
12294
+ }
12295
+ calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
12296
+ const initialRetryDelay = 0.5;
12297
+ const maxRetryDelay = 8.0;
12298
+ const numRetries = maxRetries - retriesRemaining;
12299
+ // Apply exponential backoff, but not more than the max.
12300
+ const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
12301
+ // Apply some jitter, take up to at most 25 percent of the retry time.
12302
+ const jitter = 1 - Math.random() * 0.25;
12303
+ return sleepSeconds * jitter * 1000;
12304
+ }
12305
+ async buildRequest(inputOptions, { retryCount = 0 } = {}) {
12306
+ const options = { ...inputOptions };
12307
+ const { method, path, query, defaultBaseURL } = options;
12308
+ const url = this.buildURL(path, query, defaultBaseURL);
12309
+ if ('timeout' in options)
12310
+ validatePositiveInteger('timeout', options.timeout);
12311
+ options.timeout = options.timeout ?? this.timeout;
12312
+ const { bodyHeaders, body } = this.buildBody({ options });
12313
+ const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
12314
+ const req = {
12315
+ method,
12316
+ headers: reqHeaders,
12317
+ ...(options.signal && { signal: options.signal }),
12318
+ ...(globalThis.ReadableStream &&
12319
+ body instanceof globalThis.ReadableStream && { duplex: 'half' }),
12320
+ ...(body && { body }),
12321
+ ...(this.fetchOptions ?? {}),
12322
+ ...(options.fetchOptions ?? {}),
12323
+ };
12324
+ return { req, url, timeout: options.timeout };
12325
+ }
12326
+ async buildHeaders({ options, method, bodyHeaders, retryCount, }) {
12327
+ let idempotencyHeaders = {};
12328
+ if (this.idempotencyHeader && method !== 'get') {
12329
+ if (!options.idempotencyKey)
12330
+ options.idempotencyKey = this.defaultIdempotencyKey();
12331
+ idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
12332
+ }
12333
+ const headers = buildHeaders([
12334
+ idempotencyHeaders,
12335
+ {
12336
+ Accept: 'application/json',
12337
+ 'User-Agent': this.getUserAgent(),
12338
+ 'X-Stainless-Retry-Count': String(retryCount),
12339
+ ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
12340
+ ...getPlatformHeaders(),
12341
+ },
12342
+ await this.authHeaders(options),
12343
+ this._options.defaultHeaders,
12344
+ bodyHeaders,
12345
+ options.headers,
12346
+ ]);
12347
+ this.validateHeaders(headers);
12348
+ return headers.values;
12349
+ }
12350
+ buildBody({ options: { body, headers: rawHeaders } }) {
12351
+ if (!body) {
12352
+ return { bodyHeaders: undefined, body: undefined };
12353
+ }
12354
+ const headers = buildHeaders([rawHeaders]);
12355
+ if (
12356
+ // Pass raw type verbatim
12357
+ ArrayBuffer.isView(body) ||
12358
+ body instanceof ArrayBuffer ||
12359
+ body instanceof DataView ||
12360
+ (typeof body === 'string' &&
12361
+ // Preserve legacy string encoding behavior for now
12362
+ headers.values.has('content-type')) ||
12363
+ // `Blob` is superset of `File`
12364
+ (globalThis.Blob && body instanceof globalThis.Blob) ||
12365
+ // `FormData` -> `multipart/form-data`
12366
+ body instanceof FormData ||
12367
+ // `URLSearchParams` -> `application/x-www-form-urlencoded`
12368
+ body instanceof URLSearchParams ||
12369
+ // Send chunked stream (each chunk has own `length`)
12370
+ (globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) {
12371
+ return { bodyHeaders: undefined, body: body };
12372
+ }
12373
+ else if (typeof body === 'object' &&
12374
+ (Symbol.asyncIterator in body ||
12375
+ (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {
12376
+ return { bodyHeaders: undefined, body: ReadableStreamFrom(body) };
12377
+ }
12378
+ else {
12379
+ return __classPrivateFieldGet(this, _DodoPayments_encoder, "f").call(this, { body, headers });
12380
+ }
12381
+ }
12382
+ }
12383
+ _a = DodoPayments, _DodoPayments_encoder = new WeakMap(), _DodoPayments_instances = new WeakSet(), _DodoPayments_baseURLOverridden = function _DodoPayments_baseURLOverridden() {
12384
+ return this.baseURL !== environments[this._options.environment || 'live_mode'];
12385
+ };
12386
+ DodoPayments.DodoPayments = _a;
12387
+ DodoPayments.DEFAULT_TIMEOUT = 60000; // 1 minute
12388
+ DodoPayments.DodoPaymentsError = DodoPaymentsError;
12389
+ DodoPayments.APIError = APIError;
12390
+ DodoPayments.APIConnectionError = APIConnectionError;
12391
+ DodoPayments.APIConnectionTimeoutError = APIConnectionTimeoutError;
12392
+ DodoPayments.APIUserAbortError = APIUserAbortError;
12393
+ DodoPayments.NotFoundError = NotFoundError;
12394
+ DodoPayments.ConflictError = ConflictError;
12395
+ DodoPayments.RateLimitError = RateLimitError;
12396
+ DodoPayments.BadRequestError = BadRequestError;
12397
+ DodoPayments.AuthenticationError = AuthenticationError;
12398
+ DodoPayments.InternalServerError = InternalServerError;
12399
+ DodoPayments.PermissionDeniedError = PermissionDeniedError;
12400
+ DodoPayments.UnprocessableEntityError = UnprocessableEntityError;
12401
+ DodoPayments.toFile = toFile;
12402
+ DodoPayments.CheckoutSessions = CheckoutSessions;
12403
+ DodoPayments.Payments = Payments;
12404
+ DodoPayments.Subscriptions = Subscriptions;
12405
+ DodoPayments.Invoices = Invoices;
12406
+ DodoPayments.Licenses = Licenses;
12407
+ DodoPayments.LicenseKeys = LicenseKeys;
12408
+ DodoPayments.LicenseKeyInstances = LicenseKeyInstances;
12409
+ DodoPayments.Customers = Customers;
12410
+ DodoPayments.Refunds = Refunds;
12411
+ DodoPayments.Disputes = Disputes;
12412
+ DodoPayments.Payouts = Payouts;
12413
+ DodoPayments.Products = Products;
12414
+ DodoPayments.Misc = Misc;
12415
+ DodoPayments.Discounts = Discounts;
12416
+ DodoPayments.Addons = Addons;
12417
+ DodoPayments.Brands = Brands;
12418
+ DodoPayments.Webhooks = Webhooks$1;
12419
+ DodoPayments.WebhookEvents = WebhookEvents;
12420
+ DodoPayments.UsageEvents = UsageEvents;
12421
+ DodoPayments.Meters = Meters;
12422
+
12423
+ // src/checkout/checkout.ts
12424
+ var checkoutQuerySchema = objectType({
12425
+ productId: stringType(),
12426
+ quantity: stringType().optional(),
12427
+ // Customer fields
12428
+ fullName: stringType().optional(),
12429
+ firstName: stringType().optional(),
12430
+ lastName: stringType().optional(),
12431
+ email: stringType().optional(),
12432
+ country: stringType().optional(),
12433
+ addressLine: stringType().optional(),
12434
+ city: stringType().optional(),
12435
+ state: stringType().optional(),
12436
+ zipCode: stringType().optional(),
12437
+ // Disable flags
12438
+ disableFullName: stringType().optional(),
12439
+ disableFirstName: stringType().optional(),
12440
+ disableLastName: stringType().optional(),
12441
+ disableEmail: stringType().optional(),
12442
+ disableCountry: stringType().optional(),
12443
+ disableAddressLine: stringType().optional(),
12444
+ disableCity: stringType().optional(),
12445
+ disableState: stringType().optional(),
12446
+ disableZipCode: stringType().optional(),
12447
+ // Advanced controls
12448
+ paymentCurrency: stringType().optional(),
12449
+ showCurrencySelector: stringType().optional(),
12450
+ paymentAmount: stringType().optional(),
12451
+ showDiscounts: stringType().optional()
12452
+ // Metadata (allow any key starting with metadata_)
12453
+ // We'll handle metadata separately in the handler
12454
+ }).catchall(unknownType());
12455
+ var dynamicCheckoutBodySchema = objectType({
12456
+ // For subscription
12457
+ product_id: stringType().optional(),
12458
+ quantity: numberType().optional(),
12459
+ // For one-time payment
12460
+ product_cart: arrayType(
12461
+ objectType({
12462
+ product_id: stringType(),
12463
+ quantity: numberType()
12464
+ })
12465
+ ).optional(),
12466
+ // Common fields
12467
+ billing: objectType({
12468
+ city: stringType(),
12469
+ country: stringType(),
12470
+ state: stringType(),
12471
+ street: stringType(),
12472
+ zipcode: stringType()
12473
+ }),
12474
+ customer: objectType({
12475
+ customer_id: stringType().optional(),
12476
+ email: stringType().optional(),
12477
+ name: stringType().optional()
12478
+ }),
12479
+ discount_id: stringType().optional(),
12480
+ addons: arrayType(
12481
+ objectType({
12482
+ addon_id: stringType(),
12483
+ quantity: numberType()
12484
+ })
12485
+ ).optional(),
12486
+ metadata: recordType(stringType(), stringType()).optional(),
12487
+ currency: stringType().optional()
12488
+ // Allow any additional fields (for future compatibility)
12489
+ }).catchall(unknownType());
12490
+ var checkoutSessionProductCartItemSchema = objectType({
12491
+ product_id: stringType().min(1, "Product ID is required"),
12492
+ quantity: numberType().int().positive("Quantity must be a positive integer"),
12493
+ addons: arrayType(
12494
+ objectType({
12495
+ addon_id: stringType(),
12496
+ quantity: numberType().int().nonnegative()
12497
+ })
12498
+ ).optional(),
12499
+ amount: numberType().int().nonnegative(
12500
+ "Amount must be a non-negative integer (for pay-what-you-want products)"
12501
+ ).optional()
12502
+ });
12503
+ var checkoutSessionCustomerSchema = unionType([
12504
+ objectType({
12505
+ email: stringType().email(),
12506
+ name: stringType().min(1).optional(),
12507
+ phone_number: stringType().optional()
12508
+ }),
12509
+ objectType({
12510
+ customer_id: stringType()
12511
+ })
12512
+ ]).optional();
12513
+ var checkoutSessionBillingAddressSchema = objectType({
12514
+ street: stringType().optional(),
12515
+ city: stringType().optional(),
12516
+ state: stringType().optional(),
12517
+ country: stringType().length(2, "Country must be a 2-letter ISO code"),
12518
+ zipcode: stringType().optional()
12519
+ }).optional();
12520
+ var paymentMethodTypeSchema = enumType([
12521
+ "credit",
12522
+ "debit",
12523
+ "upi_collect",
12524
+ "upi_intent",
12525
+ "apple_pay",
12526
+ "cashapp",
12527
+ "google_pay",
12528
+ "multibanco",
12529
+ "bancontact_card",
12530
+ "eps",
12531
+ "ideal",
12532
+ "przelewy24",
12533
+ "paypal",
12534
+ "affirm",
12535
+ "klarna",
12536
+ "sepa",
12537
+ "ach",
12538
+ "amazon_pay",
12539
+ "afterpay_clearpay"
12540
+ ]);
12541
+ var checkoutSessionCustomizationSchema = objectType({
12542
+ theme: enumType(["light", "dark", "system"]).optional(),
12543
+ show_order_details: booleanType().optional(),
12544
+ show_on_demand_tag: booleanType().optional(),
12545
+ force_language: stringType().optional()
12546
+ }).optional();
12547
+ var checkoutSessionFeatureFlagsSchema = objectType({
12548
+ allow_currency_selection: booleanType().optional(),
12549
+ allow_discount_code: booleanType().optional(),
12550
+ allow_phone_number_collection: booleanType().optional(),
12551
+ allow_tax_id: booleanType().optional(),
12552
+ always_create_new_customer: booleanType().optional()
12553
+ }).optional();
12554
+ var checkoutSessionOnDemandSchema = objectType({
12555
+ mandate_only: booleanType(),
12556
+ product_price: numberType().int().optional(),
12557
+ product_currency: stringType().length(3).optional(),
12558
+ product_description: stringType().optional(),
12559
+ adaptive_currency_fees_inclusive: booleanType().optional()
12560
+ }).optional();
12561
+ var checkoutSessionSubscriptionDataSchema = objectType({
12562
+ trial_period_days: numberType().int().nonnegative().optional(),
12563
+ on_demand: checkoutSessionOnDemandSchema
12564
+ }).optional();
12565
+ var checkoutSessionPayloadSchema = objectType({
12566
+ // Required fields
12567
+ product_cart: arrayType(checkoutSessionProductCartItemSchema).min(1, "At least one product is required"),
12568
+ // Optional fields
12569
+ customer: checkoutSessionCustomerSchema,
12570
+ billing_address: checkoutSessionBillingAddressSchema,
12571
+ return_url: stringType().url().optional(),
12572
+ allowed_payment_method_types: arrayType(paymentMethodTypeSchema).optional(),
12573
+ billing_currency: stringType().length(3, "Currency must be a 3-letter ISO code").optional(),
12574
+ show_saved_payment_methods: booleanType().optional(),
12575
+ confirm: booleanType().optional(),
12576
+ discount_code: stringType().optional(),
12577
+ metadata: recordType(stringType(), stringType()).optional(),
12578
+ customization: checkoutSessionCustomizationSchema,
12579
+ feature_flags: checkoutSessionFeatureFlagsSchema,
12580
+ subscription_data: checkoutSessionSubscriptionDataSchema,
12581
+ force_3ds: booleanType().optional()
12582
+ });
12583
+ var checkoutSessionResponseSchema = objectType({
12584
+ session_id: stringType().min(1, "Session ID is required"),
12585
+ checkout_url: stringType().url("Invalid checkout URL")
12586
+ });
12587
+ var createCheckoutSession = async (payload, config) => {
12588
+ const validation = checkoutSessionPayloadSchema.safeParse(payload);
12589
+ if (!validation.success) {
12590
+ throw new Error(
12591
+ `Invalid checkout session payload: ${validation.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ")}`
12592
+ );
12593
+ }
12594
+ const dodopayments = new DodoPayments({
12595
+ bearerToken: config.bearerToken,
12596
+ environment: config.environment
12597
+ });
12598
+ try {
12599
+ const sdkPayload = {
12600
+ ...validation.data,
12601
+ ...validation.data.billing_address && {
12602
+ billing_address: {
12603
+ ...validation.data.billing_address,
12604
+ country: validation.data.billing_address.country
12605
+ }
12606
+ }
12607
+ };
12608
+ const session = await dodopayments.checkoutSessions.create(
12609
+ sdkPayload
12610
+ );
12611
+ const responseValidation = checkoutSessionResponseSchema.safeParse(session);
12612
+ if (!responseValidation.success) {
12613
+ throw new Error(
12614
+ `Invalid checkout session response from API: ${responseValidation.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join(", ")}`
12615
+ );
12616
+ }
12617
+ return responseValidation.data;
12618
+ } catch (error) {
12619
+ if (error instanceof Error) {
12620
+ console.error("Dodo Payments Checkout Session API Error:", {
12621
+ message: error.message,
12622
+ payload: validation.data,
12623
+ config: {
12624
+ environment: config.environment,
12625
+ hasBearerToken: !!config.bearerToken
12626
+ }
12627
+ });
12628
+ throw new Error(`Failed to create checkout session: ${error.message}`);
12629
+ }
12630
+ console.error("Unknown error creating checkout session:", error);
12631
+ throw new Error(
12632
+ "Failed to create checkout session due to an unknown error"
12633
+ );
12634
+ }
12635
+ };
12636
+ var buildCheckoutUrl = async ({
12637
+ queryParams,
12638
+ body,
12639
+ sessionPayload,
12640
+ returnUrl,
12641
+ bearerToken,
12642
+ environment,
12643
+ type = "static"
12644
+ }) => {
12645
+ if (type === "session") {
12646
+ if (!sessionPayload) {
12647
+ throw new Error("sessionPayload is required when type is 'session'");
12648
+ }
12649
+ const session = await createCheckoutSession(sessionPayload, {
12650
+ bearerToken,
12651
+ environment
12652
+ });
12653
+ return session.checkout_url;
12654
+ }
12655
+ const inputData = type === "dynamic" ? body : queryParams;
12656
+ let parseResult;
12657
+ if (type === "dynamic") {
12658
+ parseResult = dynamicCheckoutBodySchema.safeParse(inputData);
12659
+ } else {
12660
+ parseResult = checkoutQuerySchema.safeParse(inputData);
12661
+ }
12662
+ const { success, data, error } = parseResult;
12663
+ if (!success) {
12664
+ throw new Error(
12665
+ `Invalid ${type === "dynamic" ? "body" : "query parameters"}.
12666
+ ${error.message}`
12667
+ );
12668
+ }
12669
+ if (type !== "dynamic") {
12670
+ const {
12671
+ productId,
12672
+ quantity: quantity2,
12673
+ fullName,
12674
+ firstName,
12675
+ lastName,
12676
+ email,
12677
+ country,
12678
+ addressLine,
12679
+ city,
12680
+ state,
12681
+ zipCode,
12682
+ disableFullName,
12683
+ disableFirstName,
12684
+ disableLastName,
12685
+ disableEmail,
12686
+ disableCountry,
12687
+ disableAddressLine,
12688
+ disableCity,
12689
+ disableState,
12690
+ disableZipCode,
12691
+ paymentCurrency,
12692
+ showCurrencySelector,
12693
+ paymentAmount,
12694
+ showDiscounts
12695
+ // metadata handled below
12696
+ } = data;
12697
+ const dodopayments2 = new DodoPayments({
12698
+ bearerToken,
12699
+ environment
12700
+ });
12701
+ if (!productId) throw new Error("Missing required field: productId");
12702
+ try {
12703
+ await dodopayments2.products.retrieve(productId);
12704
+ } catch (err) {
12705
+ console.error(err);
12706
+ throw new Error("Product not found");
12707
+ }
12708
+ const url = new URL(
12709
+ `${environment === "test_mode" ? "https://test.checkout.dodopayments.com" : "https://checkout.dodopayments.com"}/buy/${productId}`
12710
+ );
12711
+ url.searchParams.set("quantity", quantity2 ? String(quantity2) : "1");
12712
+ if (returnUrl) url.searchParams.set("redirect_url", returnUrl);
12713
+ if (fullName) url.searchParams.set("fullName", String(fullName));
12714
+ if (firstName) url.searchParams.set("firstName", String(firstName));
12715
+ if (lastName) url.searchParams.set("lastName", String(lastName));
12716
+ if (email) url.searchParams.set("email", String(email));
12717
+ if (country) url.searchParams.set("country", String(country));
12718
+ if (addressLine) url.searchParams.set("addressLine", String(addressLine));
12719
+ if (city) url.searchParams.set("city", String(city));
12720
+ if (state) url.searchParams.set("state", String(state));
12721
+ if (zipCode) url.searchParams.set("zipCode", String(zipCode));
12722
+ if (disableFullName === "true")
12723
+ url.searchParams.set("disableFullName", "true");
12724
+ if (disableFirstName === "true")
12725
+ url.searchParams.set("disableFirstName", "true");
12726
+ if (disableLastName === "true")
12727
+ url.searchParams.set("disableLastName", "true");
12728
+ if (disableEmail === "true") url.searchParams.set("disableEmail", "true");
12729
+ if (disableCountry === "true")
12730
+ url.searchParams.set("disableCountry", "true");
12731
+ if (disableAddressLine === "true")
12732
+ url.searchParams.set("disableAddressLine", "true");
12733
+ if (disableCity === "true") url.searchParams.set("disableCity", "true");
12734
+ if (disableState === "true") url.searchParams.set("disableState", "true");
12735
+ if (disableZipCode === "true")
12736
+ url.searchParams.set("disableZipCode", "true");
12737
+ if (paymentCurrency)
12738
+ url.searchParams.set("paymentCurrency", String(paymentCurrency));
12739
+ if (showCurrencySelector)
12740
+ url.searchParams.set(
12741
+ "showCurrencySelector",
12742
+ String(showCurrencySelector)
12743
+ );
12744
+ if (paymentAmount)
12745
+ url.searchParams.set("paymentAmount", String(paymentAmount));
12746
+ if (showDiscounts)
12747
+ url.searchParams.set("showDiscounts", String(showDiscounts));
12748
+ for (const [key, value] of Object.entries(queryParams || {})) {
12749
+ if (key.startsWith("metadata_") && value && typeof value !== "object") {
12750
+ url.searchParams.set(key, String(value));
12751
+ }
12752
+ }
12753
+ return url.toString();
12754
+ }
12755
+ const dyn = data;
12756
+ const {
12757
+ product_id,
12758
+ product_cart,
12759
+ quantity,
12760
+ billing,
12761
+ customer,
12762
+ addons,
12763
+ metadata,
12764
+ allowed_payment_method_types,
12765
+ billing_currency,
12766
+ discount_code,
12767
+ on_demand,
12768
+ return_url: bodyReturnUrl,
12769
+ show_saved_payment_methods,
12770
+ tax_id,
12771
+ trial_period_days
12772
+ } = dyn;
12773
+ const dodopayments = new DodoPayments({
12774
+ bearerToken,
12775
+ environment
12776
+ });
12777
+ let isSubscription = false;
12778
+ let productIdToFetch = product_id;
12779
+ if (!product_id && product_cart && product_cart.length > 0) {
12780
+ productIdToFetch = product_cart[0].product_id;
12781
+ }
12782
+ if (!productIdToFetch)
12783
+ throw new Error(
12784
+ "Missing required field: product_id or product_cart[0].product_id"
12785
+ );
12786
+ let product;
12787
+ try {
12788
+ product = await dodopayments.products.retrieve(productIdToFetch);
12789
+ } catch (err) {
12790
+ console.error(err);
12791
+ throw new Error("Product not found");
12792
+ }
12793
+ isSubscription = Boolean(product.is_recurring);
12794
+ if (isSubscription && !product_id)
12795
+ throw new Error("Missing required field: product_id for subscription");
12796
+ if (!billing) throw new Error("Missing required field: billing");
12797
+ if (!customer) throw new Error("Missing required field: customer");
12798
+ if (isSubscription) {
12799
+ const subscriptionPayload = {
12800
+ billing,
12801
+ customer,
12802
+ product_id,
12803
+ quantity: quantity ? Number(quantity) : 1
12804
+ };
12805
+ if (metadata) subscriptionPayload.metadata = metadata;
12806
+ if (discount_code) subscriptionPayload.discount_code = discount_code;
12807
+ if (addons) subscriptionPayload.addons = addons;
12808
+ if (allowed_payment_method_types)
12809
+ subscriptionPayload.allowed_payment_method_types = allowed_payment_method_types;
12810
+ if (billing_currency)
12811
+ subscriptionPayload.billing_currency = billing_currency;
12812
+ if (on_demand) subscriptionPayload.on_demand = on_demand;
12813
+ subscriptionPayload.payment_link = true;
12814
+ if (bodyReturnUrl) {
12815
+ subscriptionPayload.return_url = bodyReturnUrl;
12816
+ } else if (returnUrl) {
12817
+ subscriptionPayload.return_url = returnUrl;
12818
+ }
12819
+ if (show_saved_payment_methods)
12820
+ subscriptionPayload.show_saved_payment_methods = show_saved_payment_methods;
12821
+ if (tax_id) subscriptionPayload.tax_id = tax_id;
12822
+ if (trial_period_days)
12823
+ subscriptionPayload.trial_period_days = trial_period_days;
12824
+ let subscription;
12825
+ try {
12826
+ subscription = await dodopayments.subscriptions.create(subscriptionPayload);
12827
+ } catch (err) {
12828
+ console.error("Error when creating subscription", err);
12829
+ throw new Error(err instanceof Error ? err.message : String(err));
12833
12830
  }
12834
- }
12835
- var WebhookVerificationError_1 = dist.WebhookVerificationError = WebhookVerificationError;
12836
- class Webhook {
12837
- constructor(secret, options) {
12838
- if (!secret) {
12839
- throw new Error("Secret can't be empty.");
12831
+ if (!subscription || !subscription.payment_link) {
12832
+ throw new Error(
12833
+ "No payment link returned from Dodo Payments API (subscription). Make sure to set payment_link as true in payload"
12834
+ );
12835
+ }
12836
+ return subscription.payment_link;
12837
+ } else {
12838
+ let cart = product_cart;
12839
+ if (!cart && product_id) {
12840
+ cart = [
12841
+ { product_id, quantity: quantity ? Number(quantity) : 1 }
12842
+ ];
12843
+ }
12844
+ if (!cart || cart.length === 0)
12845
+ throw new Error("Missing required field: product_cart or product_id");
12846
+ const paymentPayload = {
12847
+ billing,
12848
+ customer,
12849
+ product_cart: cart
12850
+ };
12851
+ if (metadata) paymentPayload.metadata = metadata;
12852
+ paymentPayload.payment_link = true;
12853
+ if (allowed_payment_method_types)
12854
+ paymentPayload.allowed_payment_method_types = allowed_payment_method_types;
12855
+ if (billing_currency) paymentPayload.billing_currency = billing_currency;
12856
+ if (discount_code) paymentPayload.discount_code = discount_code;
12857
+ if (bodyReturnUrl) {
12858
+ paymentPayload.return_url = bodyReturnUrl;
12859
+ } else if (returnUrl) {
12860
+ paymentPayload.return_url = returnUrl;
12861
+ }
12862
+ if (show_saved_payment_methods)
12863
+ paymentPayload.show_saved_payment_methods = show_saved_payment_methods;
12864
+ if (tax_id) paymentPayload.tax_id = tax_id;
12865
+ let payment;
12866
+ try {
12867
+ payment = await dodopayments.payments.create(paymentPayload);
12868
+ } catch (err) {
12869
+ console.error("Error when creating payment link", err);
12870
+ throw new Error(err instanceof Error ? err.message : String(err));
12871
+ }
12872
+ if (!payment || !payment.payment_link) {
12873
+ throw new Error(
12874
+ "No payment link returned from Dodo Payments API. Make sure to set payment_link as true in payload."
12875
+ );
12876
+ }
12877
+ return payment.payment_link;
12878
+ }
12879
+ };
12880
+
12881
+ const Checkout = (config) => {
12882
+ const getHandler = async (req) => {
12883
+ const { searchParams } = new URL(req.url);
12884
+ const queryParams = Object.fromEntries(searchParams);
12885
+ if (!queryParams.productId) {
12886
+ return new serverExports.NextResponse("Please provide productId query parameter", {
12887
+ status: 400,
12888
+ });
12840
12889
  }
12841
- if ((options === null || options === void 0 ? void 0 : options.format) === "raw") {
12842
- if (secret instanceof Uint8Array) {
12843
- this.key = secret;
12844
- }
12845
- else {
12846
- this.key = Uint8Array.from(secret, (c) => c.charCodeAt(0));
12890
+ const { success, data, error } = checkoutQuerySchema.safeParse(queryParams);
12891
+ if (!success) {
12892
+ if (error.errors.some((e) => e.path.toString() === "productId")) {
12893
+ return new serverExports.NextResponse("Please provide productId query parameter", {
12894
+ status: 400,
12895
+ });
12847
12896
  }
12897
+ return new serverExports.NextResponse(`Invalid query parameters.\n ${error.message}`, {
12898
+ status: 400,
12899
+ });
12848
12900
  }
12849
- else {
12850
- if (typeof secret !== "string") {
12851
- throw new Error("Expected secret to be of type string");
12852
- }
12853
- if (secret.startsWith(Webhook.prefix)) {
12854
- secret = secret.substring(Webhook.prefix.length);
12855
- }
12856
- this.key = base64.decode(secret);
12901
+ let url = "";
12902
+ try {
12903
+ url = await buildCheckoutUrl({ queryParams: data, ...config });
12857
12904
  }
12858
- }
12859
- verify(payload, headers_) {
12860
- const headers = {};
12861
- for (const key of Object.keys(headers_)) {
12862
- headers[key.toLowerCase()] = headers_[key];
12905
+ catch (error) {
12906
+ return new serverExports.NextResponse(error.message, { status: 400 });
12863
12907
  }
12864
- const msgId = headers["webhook-id"];
12865
- const msgSignature = headers["webhook-signature"];
12866
- const msgTimestamp = headers["webhook-timestamp"];
12867
- if (!msgSignature || !msgId || !msgTimestamp) {
12868
- throw new WebhookVerificationError("Missing required headers");
12908
+ return serverExports.NextResponse.json({ checkout_url: url });
12909
+ };
12910
+ const postHandler = async (req) => {
12911
+ let body;
12912
+ try {
12913
+ body = await req.json();
12869
12914
  }
12870
- const timestamp = this.verifyTimestamp(msgTimestamp);
12871
- const computedSignature = this.sign(msgId, timestamp, payload);
12872
- const expectedSignature = computedSignature.split(",")[1];
12873
- const passedSignatures = msgSignature.split(" ");
12874
- const encoder = new globalThis.TextEncoder();
12875
- for (const versionedSignature of passedSignatures) {
12876
- const [version, signature] = versionedSignature.split(",");
12877
- if (version !== "v1") {
12878
- continue;
12915
+ catch (e) {
12916
+ return new serverExports.NextResponse("Invalid JSON body", { status: 400 });
12917
+ }
12918
+ if (config.type === "dynamic") {
12919
+ // Handle dynamic checkout
12920
+ const { success, data, error } = dynamicCheckoutBodySchema.safeParse(body);
12921
+ if (!success) {
12922
+ return new serverExports.NextResponse(`Invalid request body.\n ${error.message}`, {
12923
+ status: 400,
12924
+ });
12879
12925
  }
12880
- if ((0, timing_safe_equal_1.timingSafeEqual)(encoder.encode(signature), encoder.encode(expectedSignature))) {
12881
- return JSON.parse(payload.toString());
12926
+ let url = "";
12927
+ try {
12928
+ url = await buildCheckoutUrl({
12929
+ body: data,
12930
+ ...config,
12931
+ type: "dynamic",
12932
+ });
12882
12933
  }
12883
- }
12884
- throw new WebhookVerificationError("No matching signature found");
12885
- }
12886
- sign(msgId, timestamp, payload) {
12887
- if (typeof payload === "string") ;
12888
- else if (payload.constructor.name === "Buffer") {
12889
- payload = payload.toString();
12934
+ catch (error) {
12935
+ return new serverExports.NextResponse(error.message, { status: 400 });
12936
+ }
12937
+ return serverExports.NextResponse.json({ checkout_url: url });
12890
12938
  }
12891
12939
  else {
12892
- throw new Error("Expected payload to be of type string or Buffer.");
12893
- }
12894
- const encoder = new TextEncoder();
12895
- const timestampNumber = Math.floor(timestamp.getTime() / 1000);
12896
- const toSign = encoder.encode(`${msgId}.${timestampNumber}.${payload}`);
12897
- const expectedSignature = base64.encode(sha256.hmac(this.key, toSign));
12898
- return `v1,${expectedSignature}`;
12899
- }
12900
- verifyTimestamp(timestampHeader) {
12901
- const now = Math.floor(Date.now() / 1000);
12902
- const timestamp = parseInt(timestampHeader, 10);
12903
- if (isNaN(timestamp)) {
12904
- throw new WebhookVerificationError("Invalid Signature Headers");
12905
- }
12906
- if (now - timestamp > WEBHOOK_TOLERANCE_IN_SECONDS) {
12907
- throw new WebhookVerificationError("Message timestamp too old");
12940
+ // Handle checkout session
12941
+ const { success, data, error } = checkoutSessionPayloadSchema.safeParse(body);
12942
+ if (!success) {
12943
+ return new serverExports.NextResponse(`Invalid checkout session payload.\n ${error.message}`, {
12944
+ status: 400,
12945
+ });
12946
+ }
12947
+ let url = "";
12948
+ try {
12949
+ url = await buildCheckoutUrl({
12950
+ sessionPayload: data,
12951
+ ...config,
12952
+ type: "session",
12953
+ });
12954
+ }
12955
+ catch (error) {
12956
+ return new serverExports.NextResponse(error.message, { status: 400 });
12957
+ }
12958
+ return serverExports.NextResponse.json({ checkout_url: url });
12908
12959
  }
12909
- if (timestamp > now + WEBHOOK_TOLERANCE_IN_SECONDS) {
12910
- throw new WebhookVerificationError("Message timestamp too new");
12960
+ };
12961
+ return (req) => {
12962
+ if (req.method === "POST") {
12963
+ return postHandler(req);
12911
12964
  }
12912
- return new Date(timestamp * 1000);
12913
- }
12914
- }
12915
- Webhook_1 = dist.Webhook = Webhook;
12916
- Webhook.prefix = "whsec_";
12965
+ return getHandler(req);
12966
+ };
12967
+ };
12917
12968
 
12918
12969
  // src/schemas/webhook.ts
12919
12970
  var PaymentSchema = objectType({