@proxy-checkout/server-js 0.0.4-pr-76.21.1 → 0.0.4-pr-76.22.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.
Files changed (50) hide show
  1. package/dist/cjs/cart.js +26 -0
  2. package/dist/cjs/client.js +41 -0
  3. package/dist/cjs/consistency.js +36 -0
  4. package/dist/cjs/errors.js +59 -0
  5. package/dist/cjs/events.js +151 -0
  6. package/dist/cjs/http-client.js +84 -0
  7. package/dist/cjs/index.js +55 -0
  8. package/dist/cjs/lifecycle.js +109 -0
  9. package/dist/cjs/package.json +3 -0
  10. package/dist/cjs/response-validators.js +60 -0
  11. package/dist/cjs/sessions.js +303 -0
  12. package/dist/cjs/subscriptions.js +59 -0
  13. package/dist/cjs/types.js +2 -0
  14. package/dist/cjs/version.js +6 -0
  15. package/dist/cjs/webhook-events.js +69 -0
  16. package/dist/cjs/webhook-handler.js +177 -0
  17. package/dist/cjs/webhooks.js +182 -0
  18. package/dist/{version.d.ts → esm/version.d.ts} +2 -2
  19. package/dist/{version.js → esm/version.js} +1 -1
  20. package/package.json +8 -6
  21. /package/dist/{cart.d.ts → esm/cart.d.ts} +0 -0
  22. /package/dist/{cart.js → esm/cart.js} +0 -0
  23. /package/dist/{client.d.ts → esm/client.d.ts} +0 -0
  24. /package/dist/{client.js → esm/client.js} +0 -0
  25. /package/dist/{consistency.d.ts → esm/consistency.d.ts} +0 -0
  26. /package/dist/{consistency.js → esm/consistency.js} +0 -0
  27. /package/dist/{errors.d.ts → esm/errors.d.ts} +0 -0
  28. /package/dist/{errors.js → esm/errors.js} +0 -0
  29. /package/dist/{events.d.ts → esm/events.d.ts} +0 -0
  30. /package/dist/{events.js → esm/events.js} +0 -0
  31. /package/dist/{http-client.d.ts → esm/http-client.d.ts} +0 -0
  32. /package/dist/{http-client.js → esm/http-client.js} +0 -0
  33. /package/dist/{index.d.ts → esm/index.d.ts} +0 -0
  34. /package/dist/{index.js → esm/index.js} +0 -0
  35. /package/dist/{lifecycle.d.ts → esm/lifecycle.d.ts} +0 -0
  36. /package/dist/{lifecycle.js → esm/lifecycle.js} +0 -0
  37. /package/dist/{response-validators.d.ts → esm/response-validators.d.ts} +0 -0
  38. /package/dist/{response-validators.js → esm/response-validators.js} +0 -0
  39. /package/dist/{sessions.d.ts → esm/sessions.d.ts} +0 -0
  40. /package/dist/{sessions.js → esm/sessions.js} +0 -0
  41. /package/dist/{subscriptions.d.ts → esm/subscriptions.d.ts} +0 -0
  42. /package/dist/{subscriptions.js → esm/subscriptions.js} +0 -0
  43. /package/dist/{types.d.ts → esm/types.d.ts} +0 -0
  44. /package/dist/{types.js → esm/types.js} +0 -0
  45. /package/dist/{webhook-events.d.ts → esm/webhook-events.d.ts} +0 -0
  46. /package/dist/{webhook-events.js → esm/webhook-events.js} +0 -0
  47. /package/dist/{webhook-handler.d.ts → esm/webhook-handler.d.ts} +0 -0
  48. /package/dist/{webhook-handler.js → esm/webhook-handler.js} +0 -0
  49. /package/dist/{webhooks.d.ts → esm/webhooks.d.ts} +0 -0
  50. /package/dist/{webhooks.js → esm/webhooks.js} +0 -0
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /**
3
+ * Typed cart-snapshot validation.
4
+ *
5
+ * The cart snapshot is merchant-defined and opaque to Proxy, so the SDK keeps
6
+ * the shape app-owned but standardizes the parse step: pass a zod-style schema
7
+ * (or a plain validator function) and get a typed cart or a structured error.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.parseProxyCart = parseProxyCart;
11
+ const errors_js_1 = require("./errors.js");
12
+ /** Run a cart snapshot through a validator, wrapping failures in a structured SDK error. */
13
+ function parseProxyCart(cartSnapshot, validator) {
14
+ try {
15
+ return typeof validator === "function"
16
+ ? validator(cartSnapshot)
17
+ : validator.parse(cartSnapshot);
18
+ }
19
+ catch (cause) {
20
+ throw new errors_js_1.ProxyCheckoutValidationError("Proxy cart snapshot failed validation.", {
21
+ cause,
22
+ code: "cart_invalid",
23
+ field: "cart_snapshot",
24
+ });
25
+ }
26
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProxyCheckoutServerClient = void 0;
4
+ exports.createProxyCheckoutServerClient = createProxyCheckoutServerClient;
5
+ const events_js_1 = require("./events.js");
6
+ const http_client_js_1 = require("./http-client.js");
7
+ const sessions_js_1 = require("./sessions.js");
8
+ const subscriptions_js_1 = require("./subscriptions.js");
9
+ const webhook_handler_js_1 = require("./webhook-handler.js");
10
+ const webhooks_js_1 = require("./webhooks.js");
11
+ class ProxyCheckoutServerClient {
12
+ apiHost;
13
+ sessions;
14
+ subscriptions;
15
+ /** Current-state lifecycle resolver for signed webhook events. */
16
+ events;
17
+ /** Webhook delivery handling: `handle`, `process`, `constructEvent`. */
18
+ webhooks;
19
+ /** Webhook endpoint management API (create/list/rotate). */
20
+ webhookEndpoints;
21
+ constructor(options) {
22
+ const httpClient = new http_client_js_1.ProxyCheckoutHttpClient({
23
+ apiHost: options.apiHost,
24
+ apiKey: options.apiKey,
25
+ fetchImpl: options.fetch,
26
+ });
27
+ this.apiHost = httpClient.apiHost;
28
+ this.sessions = new sessions_js_1.ProxySessionsResource(httpClient, {
29
+ payHost: options.payHost,
30
+ publishableKey: options.publishableKey,
31
+ });
32
+ this.subscriptions = new subscriptions_js_1.ProxySubscriptionsResource(httpClient, this.sessions);
33
+ this.events = new events_js_1.ProxyEventsResource(this.sessions, this.subscriptions);
34
+ this.webhooks = new webhook_handler_js_1.ProxyWebhooksResource(this.events);
35
+ this.webhookEndpoints = new webhooks_js_1.ProxyWebhookEndpointsResource(httpClient);
36
+ }
37
+ }
38
+ exports.ProxyCheckoutServerClient = ProxyCheckoutServerClient;
39
+ function createProxyCheckoutServerClient(options) {
40
+ return new ProxyCheckoutServerClient(options);
41
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * Buyer-reference and session linkage consistency checks.
4
+ *
5
+ * Proxy current-state retrieval is the source of truth, but the SDK still
6
+ * guards that the records it stitches together actually belong to the same
7
+ * buyer and session before a merchant acts on them.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.assertSubscriptionMatchesSession = assertSubscriptionMatchesSession;
11
+ exports.assertCartBuyerReference = assertCartBuyerReference;
12
+ const errors_js_1 = require("./errors.js");
13
+ /**
14
+ * Assert that a subscription belongs to the given original session and that the
15
+ * buyer references agree. Throws {@link ProxyCheckoutValidationError} otherwise.
16
+ */
17
+ function assertSubscriptionMatchesSession(subscription, session) {
18
+ if (subscription.originalProxySessionId !== session.id) {
19
+ throw new errors_js_1.ProxyCheckoutValidationError(`Proxy subscription ${subscription.id} is not linked to session ${session.id}.`, { code: "subscription_session_mismatch", field: "original_proxy_session_id" });
20
+ }
21
+ if (subscription.buyerReference !== session.buyerReference) {
22
+ throw new errors_js_1.ProxyCheckoutValidationError(`Proxy subscription ${subscription.id} buyer reference does not match session ${session.id}.`, { code: "buyer_reference_mismatch", field: "buyer_reference" });
23
+ }
24
+ }
25
+ /**
26
+ * Assert that a cart-embedded buyer reference, when present, matches the session
27
+ * buyer reference. A `null`/`undefined` cart buyer reference is allowed (the
28
+ * cart simply does not carry one).
29
+ */
30
+ function assertCartBuyerReference(cartBuyerReference, session) {
31
+ if (cartBuyerReference !== null &&
32
+ cartBuyerReference !== undefined &&
33
+ cartBuyerReference !== session.buyerReference) {
34
+ throw new errors_js_1.ProxyCheckoutValidationError(`Proxy session ${session.id} cart buyer reference does not match the session buyer reference.`, { code: "buyer_reference_mismatch", field: "cart.buyerReference" });
35
+ }
36
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProxyCheckoutApiError = exports.ProxyCheckoutValidationError = void 0;
4
+ exports.toApiError = toApiError;
5
+ /**
6
+ * Raised when the SDK receives Proxy data it cannot safely normalize, for
7
+ * example an invalid date string, a cart snapshot that fails the merchant
8
+ * schema, or a buyer-reference / provider-binding consistency violation.
9
+ */
10
+ class ProxyCheckoutValidationError extends Error {
11
+ name = "ProxyCheckoutValidationError";
12
+ code;
13
+ field;
14
+ cause;
15
+ constructor(message, details) {
16
+ super(message);
17
+ this.code = details.code;
18
+ this.field = details.field;
19
+ this.cause = details.cause;
20
+ }
21
+ }
22
+ exports.ProxyCheckoutValidationError = ProxyCheckoutValidationError;
23
+ class ProxyCheckoutApiError extends Error {
24
+ name = "ProxyCheckoutApiError";
25
+ code;
26
+ requestId;
27
+ responseBody;
28
+ statusCode;
29
+ constructor(message, details) {
30
+ super(message);
31
+ this.code = details.code;
32
+ this.requestId = details.requestId;
33
+ this.responseBody = details.responseBody;
34
+ this.statusCode = details.statusCode;
35
+ }
36
+ }
37
+ exports.ProxyCheckoutApiError = ProxyCheckoutApiError;
38
+ function toApiError(statusCode, responseBody, headerRequestId) {
39
+ const error = readApiError(responseBody);
40
+ const message = error.message ?? `Proxy API request failed with status ${statusCode}.`;
41
+ return new ProxyCheckoutApiError(message, {
42
+ code: error.code,
43
+ requestId: error.requestId ?? headerRequestId,
44
+ responseBody,
45
+ statusCode,
46
+ });
47
+ }
48
+ function readApiError(responseBody) {
49
+ const body = isRecord(responseBody) ? responseBody : undefined;
50
+ const error = body && isRecord(body.error) ? body.error : undefined;
51
+ return {
52
+ code: typeof error?.code === "string" ? error.code : undefined,
53
+ message: typeof error?.message === "string" ? error.message : undefined,
54
+ requestId: typeof error?.request_id === "string" ? error.request_id : undefined,
55
+ };
56
+ }
57
+ function isRecord(value) {
58
+ return typeof value === "object" && value !== null && !Array.isArray(value);
59
+ }
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * Current-state lifecycle resolver for signed Proxy webhook events.
4
+ *
5
+ * A webhook is only a wakeup: this resolver re-reads the authoritative session
6
+ * and subscription state with the merchant secret key and returns a typed
7
+ * lifecycle decision. It never grants from webhook payload fields, and it
8
+ * classifies subscription events from current state rather than event order.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ProxyEventsResource = void 0;
12
+ const consistency_js_1 = require("./consistency.js");
13
+ const lifecycle_js_1 = require("./lifecycle.js");
14
+ const webhook_events_js_1 = require("./webhook-events.js");
15
+ class ProxyEventsResource {
16
+ sessions;
17
+ subscriptions;
18
+ constructor(sessions, subscriptions) {
19
+ this.sessions = sessions;
20
+ this.subscriptions = subscriptions;
21
+ }
22
+ /**
23
+ * Resolve a signed webhook event into a current-state lifecycle decision by
24
+ * re-reading the authoritative session/subscription with the secret key.
25
+ */
26
+ async resolveCurrentState(event, options = {}) {
27
+ if ((0, webhook_events_js_1.isProxySubscriptionEvent)(event.type)) {
28
+ return this.resolveSubscriptionEvent(event, options);
29
+ }
30
+ if ((0, webhook_events_js_1.isProxySessionEvent)(event.type)) {
31
+ return this.resolveSessionEvent(event, options);
32
+ }
33
+ return ignored(event, `Event type ${event.type} is not a lifecycle event.`, {
34
+ sessionId: readEventString(event.data.proxy_session_id),
35
+ subscriptionId: readEventString(event.data.subscription_id),
36
+ });
37
+ }
38
+ async resolveSessionEvent(event, options) {
39
+ const sessionId = extractSessionId(event);
40
+ if (sessionId === null) {
41
+ return ignored(event, "Session event is missing proxy_session_id.", {
42
+ sessionId: null,
43
+ subscriptionId: readEventString(event.data.subscription_id),
44
+ });
45
+ }
46
+ const session = await this.sessions.retrieve(sessionId, options);
47
+ if ((0, lifecycle_js_1.isSessionProvisionable)(session)) {
48
+ const subscriptionId = readEventString(event.data.subscription_id);
49
+ let subscription = null;
50
+ if (subscriptionId !== null) {
51
+ subscription = await this.subscriptions.retrieve(subscriptionId, options);
52
+ (0, consistency_js_1.assertSubscriptionMatchesSession)(subscription, session);
53
+ }
54
+ return {
55
+ accessEndsAt: subscription === null ? null : (0, lifecycle_js_1.subscriptionAccessEndsAt)(subscription),
56
+ event,
57
+ kind: "initial_provision",
58
+ session,
59
+ subscription,
60
+ willRenew: subscription === null ? null : (0, lifecycle_js_1.subscriptionWillRenew)(subscription),
61
+ };
62
+ }
63
+ if ((0, lifecycle_js_1.isSessionTerminal)(session)) {
64
+ return { event, kind: "terminal_session", session };
65
+ }
66
+ return ignored(event, `Session ${session.id} status ${session.status} is not yet actionable.`, {
67
+ sessionId: session.id,
68
+ subscriptionId: null,
69
+ });
70
+ }
71
+ async resolveSubscriptionEvent(event, options) {
72
+ const subscriptionId = readEventString(event.data.subscription_id);
73
+ if (subscriptionId === null) {
74
+ return ignored(event, "Subscription event is missing subscription_id.", {
75
+ sessionId: readEventString(event.data.proxy_session_id),
76
+ subscriptionId: null,
77
+ });
78
+ }
79
+ const subscription = await this.subscriptions.retrieve(subscriptionId, options);
80
+ const session = await this.sessions.retrieve(subscription.originalProxySessionId, options);
81
+ (0, consistency_js_1.assertSubscriptionMatchesSession)(subscription, session);
82
+ const accessEndsAt = (0, lifecycle_js_1.subscriptionAccessEndsAt)(subscription);
83
+ if ((0, lifecycle_js_1.isSubscriptionEnded)(subscription)) {
84
+ return {
85
+ accessEndsAt,
86
+ event,
87
+ kind: "subscription_cancelled",
88
+ session,
89
+ subscription,
90
+ willRenew: false,
91
+ };
92
+ }
93
+ if (subscription.cancelAtPeriodEnd) {
94
+ return {
95
+ accessEndsAt,
96
+ event,
97
+ kind: "subscription_cancel_scheduled",
98
+ session,
99
+ subscription,
100
+ willRenew: false,
101
+ };
102
+ }
103
+ if ((0, lifecycle_js_1.isSubscriptionPaymentAtRisk)(subscription)) {
104
+ return {
105
+ accessEndsAt,
106
+ event,
107
+ kind: "payment_risk",
108
+ latestPaymentStatus: subscription.latestPaymentStatus,
109
+ session,
110
+ subscription,
111
+ willRenew: (0, lifecycle_js_1.subscriptionWillRenew)(subscription),
112
+ };
113
+ }
114
+ return {
115
+ accessEndsAt,
116
+ event,
117
+ kind: "subscription_renewed",
118
+ session,
119
+ subscription,
120
+ willRenew: (0, lifecycle_js_1.subscriptionWillRenew)(subscription),
121
+ };
122
+ }
123
+ }
124
+ exports.ProxyEventsResource = ProxyEventsResource;
125
+ function ignored(event, reason, ids) {
126
+ return {
127
+ event,
128
+ kind: "ignored",
129
+ reason,
130
+ sessionId: ids.sessionId,
131
+ subscriptionId: ids.subscriptionId,
132
+ };
133
+ }
134
+ /** Read the session id from an event, handling the nested `proxy_session.expired` payload. */
135
+ function extractSessionId(event) {
136
+ const direct = readEventString(event.data.proxy_session_id);
137
+ if (direct !== null) {
138
+ return direct;
139
+ }
140
+ const nested = event.data.proxy_session;
141
+ if (isRecord(nested)) {
142
+ return readEventString(nested.id);
143
+ }
144
+ return null;
145
+ }
146
+ function readEventString(value) {
147
+ return typeof value === "string" && value.length > 0 ? value : null;
148
+ }
149
+ function isRecord(value) {
150
+ return typeof value === "object" && value !== null && !Array.isArray(value);
151
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProxyCheckoutHttpClient = void 0;
4
+ const errors_js_1 = require("./errors.js");
5
+ const version_js_1 = require("./version.js");
6
+ class ProxyCheckoutHttpClient {
7
+ apiHost;
8
+ apiKey;
9
+ fetchImpl;
10
+ constructor({ apiHost, apiKey, fetchImpl, }) {
11
+ assertSecretKey(apiKey);
12
+ const resolvedFetch = fetchImpl ?? globalThis.fetch;
13
+ if (typeof resolvedFetch !== "function") {
14
+ throw new Error("Proxy Checkout server SDK requires a fetch implementation.");
15
+ }
16
+ this.apiHost = normalizeApiHost(apiHost);
17
+ this.apiKey = apiKey;
18
+ this.fetchImpl = resolvedFetch;
19
+ }
20
+ async request(method, path, body, options = {}) {
21
+ const response = await this.fetchImpl(`${this.apiHost}${path}`, {
22
+ ...(body === undefined ? {} : { body: JSON.stringify(body) }),
23
+ headers: buildHeaders(this.apiKey, options, body !== undefined),
24
+ method,
25
+ });
26
+ const responseBody = await readResponseBody(response);
27
+ if (!response.ok) {
28
+ const headerRequestId = response.headers.get("x-request-id") || undefined;
29
+ throw (0, errors_js_1.toApiError)(response.status, responseBody, headerRequestId);
30
+ }
31
+ return responseBody;
32
+ }
33
+ }
34
+ exports.ProxyCheckoutHttpClient = ProxyCheckoutHttpClient;
35
+ function buildHeaders(apiKey, options, hasJsonBody) {
36
+ const headers = {
37
+ accept: "application/json",
38
+ authorization: `Bearer ${apiKey}`,
39
+ "user-agent": version_js_1.proxyCheckoutServerSdkUserAgent,
40
+ };
41
+ if (hasJsonBody) {
42
+ headers["content-type"] = "application/json";
43
+ }
44
+ if (options.idempotencyKey !== undefined) {
45
+ headers["idempotency-key"] = options.idempotencyKey;
46
+ }
47
+ if (options.requestId !== undefined) {
48
+ headers["x-request-id"] = options.requestId;
49
+ }
50
+ return headers;
51
+ }
52
+ async function readResponseBody(response) {
53
+ const text = await response.text();
54
+ if (!text) {
55
+ return undefined;
56
+ }
57
+ try {
58
+ return JSON.parse(text);
59
+ }
60
+ catch {
61
+ return text;
62
+ }
63
+ }
64
+ function assertSecretKey(apiKey) {
65
+ if (!apiKey.startsWith("sk_test_") && !apiKey.startsWith("sk_live_")) {
66
+ throw new Error("Proxy Checkout secret key must start with sk_test_ or sk_live_.");
67
+ }
68
+ }
69
+ function normalizeApiHost(apiHost) {
70
+ if (apiHost === undefined) {
71
+ return "https://api.proxycheckout.com";
72
+ }
73
+ let url;
74
+ try {
75
+ url = new URL(apiHost);
76
+ }
77
+ catch {
78
+ throw new Error(`Invalid apiHost URL: ${apiHost}. Make sure it is an absolute HTTP or HTTPS URL.`);
79
+ }
80
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
81
+ throw new Error(`Invalid apiHost URL: ${apiHost}. Make sure it is an absolute HTTP or HTTPS URL.`);
82
+ }
83
+ return `${url.origin}${url.pathname}`.replace(/\/$/, "");
84
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyProxyWebhookSignature = exports.proxyCheckoutWebhookEndpointEndpoints = exports.ProxyWebhookSignatureVerificationError = exports.ProxyWebhookEndpointsResource = exports.PROXY_SIGNATURE_HEADER = exports.constructProxyWebhookEvent = exports.ProxyWebhooksResource = exports.PROXY_WEBHOOK_RETRY_AFTER_SECONDS = exports.PROXY_WEBHOOK_EVENT_TYPES = exports.isProxySubscriptionEvent = exports.isProxySessionEvent = exports.isProxyPaymentAttemptEvent = exports.proxyCheckoutServerSdkVersion = exports.proxyCheckoutServerSdkUserAgent = exports.proxyCheckoutServerSdkName = exports.proxyCheckoutSubscriptionEndpoints = exports.ProxySubscriptionsResource = exports.proxyCheckoutServerEndpoints = exports.ProxySessionsResource = exports.ProxySessionCartResource = exports.TERMINAL_SESSION_STATUSES = exports.subscriptionWillRenew = exports.subscriptionAccessEndsAt = exports.requireProxyDate = exports.parseOptionalProxyDate = exports.PROVISIONABLE_SESSION_STATUSES = exports.isSubscriptionPaymentAtRisk = exports.isSubscriptionEnded = exports.isSessionTerminal = exports.isSessionProvisionable = exports.ENDED_SUBSCRIPTION_STATUSES = exports.AT_RISK_SUBSCRIPTION_STATUSES = exports.ProxyEventsResource = exports.ProxyCheckoutValidationError = exports.ProxyCheckoutApiError = exports.assertSubscriptionMatchesSession = exports.assertCartBuyerReference = exports.ProxyCheckoutServerClient = exports.createProxyCheckoutServerClient = exports.parseProxyCart = void 0;
4
+ var cart_js_1 = require("./cart.js");
5
+ Object.defineProperty(exports, "parseProxyCart", { enumerable: true, get: function () { return cart_js_1.parseProxyCart; } });
6
+ var client_js_1 = require("./client.js");
7
+ Object.defineProperty(exports, "createProxyCheckoutServerClient", { enumerable: true, get: function () { return client_js_1.createProxyCheckoutServerClient; } });
8
+ Object.defineProperty(exports, "ProxyCheckoutServerClient", { enumerable: true, get: function () { return client_js_1.ProxyCheckoutServerClient; } });
9
+ var consistency_js_1 = require("./consistency.js");
10
+ Object.defineProperty(exports, "assertCartBuyerReference", { enumerable: true, get: function () { return consistency_js_1.assertCartBuyerReference; } });
11
+ Object.defineProperty(exports, "assertSubscriptionMatchesSession", { enumerable: true, get: function () { return consistency_js_1.assertSubscriptionMatchesSession; } });
12
+ var errors_js_1 = require("./errors.js");
13
+ Object.defineProperty(exports, "ProxyCheckoutApiError", { enumerable: true, get: function () { return errors_js_1.ProxyCheckoutApiError; } });
14
+ Object.defineProperty(exports, "ProxyCheckoutValidationError", { enumerable: true, get: function () { return errors_js_1.ProxyCheckoutValidationError; } });
15
+ var events_js_1 = require("./events.js");
16
+ Object.defineProperty(exports, "ProxyEventsResource", { enumerable: true, get: function () { return events_js_1.ProxyEventsResource; } });
17
+ var lifecycle_js_1 = require("./lifecycle.js");
18
+ Object.defineProperty(exports, "AT_RISK_SUBSCRIPTION_STATUSES", { enumerable: true, get: function () { return lifecycle_js_1.AT_RISK_SUBSCRIPTION_STATUSES; } });
19
+ Object.defineProperty(exports, "ENDED_SUBSCRIPTION_STATUSES", { enumerable: true, get: function () { return lifecycle_js_1.ENDED_SUBSCRIPTION_STATUSES; } });
20
+ Object.defineProperty(exports, "isSessionProvisionable", { enumerable: true, get: function () { return lifecycle_js_1.isSessionProvisionable; } });
21
+ Object.defineProperty(exports, "isSessionTerminal", { enumerable: true, get: function () { return lifecycle_js_1.isSessionTerminal; } });
22
+ Object.defineProperty(exports, "isSubscriptionEnded", { enumerable: true, get: function () { return lifecycle_js_1.isSubscriptionEnded; } });
23
+ Object.defineProperty(exports, "isSubscriptionPaymentAtRisk", { enumerable: true, get: function () { return lifecycle_js_1.isSubscriptionPaymentAtRisk; } });
24
+ Object.defineProperty(exports, "PROVISIONABLE_SESSION_STATUSES", { enumerable: true, get: function () { return lifecycle_js_1.PROVISIONABLE_SESSION_STATUSES; } });
25
+ Object.defineProperty(exports, "parseOptionalProxyDate", { enumerable: true, get: function () { return lifecycle_js_1.parseOptionalProxyDate; } });
26
+ Object.defineProperty(exports, "requireProxyDate", { enumerable: true, get: function () { return lifecycle_js_1.requireProxyDate; } });
27
+ Object.defineProperty(exports, "subscriptionAccessEndsAt", { enumerable: true, get: function () { return lifecycle_js_1.subscriptionAccessEndsAt; } });
28
+ Object.defineProperty(exports, "subscriptionWillRenew", { enumerable: true, get: function () { return lifecycle_js_1.subscriptionWillRenew; } });
29
+ Object.defineProperty(exports, "TERMINAL_SESSION_STATUSES", { enumerable: true, get: function () { return lifecycle_js_1.TERMINAL_SESSION_STATUSES; } });
30
+ var sessions_js_1 = require("./sessions.js");
31
+ Object.defineProperty(exports, "ProxySessionCartResource", { enumerable: true, get: function () { return sessions_js_1.ProxySessionCartResource; } });
32
+ Object.defineProperty(exports, "ProxySessionsResource", { enumerable: true, get: function () { return sessions_js_1.ProxySessionsResource; } });
33
+ Object.defineProperty(exports, "proxyCheckoutServerEndpoints", { enumerable: true, get: function () { return sessions_js_1.proxyCheckoutServerEndpoints; } });
34
+ var subscriptions_js_1 = require("./subscriptions.js");
35
+ Object.defineProperty(exports, "ProxySubscriptionsResource", { enumerable: true, get: function () { return subscriptions_js_1.ProxySubscriptionsResource; } });
36
+ Object.defineProperty(exports, "proxyCheckoutSubscriptionEndpoints", { enumerable: true, get: function () { return subscriptions_js_1.proxyCheckoutSubscriptionEndpoints; } });
37
+ var version_js_1 = require("./version.js");
38
+ Object.defineProperty(exports, "proxyCheckoutServerSdkName", { enumerable: true, get: function () { return version_js_1.proxyCheckoutServerSdkName; } });
39
+ Object.defineProperty(exports, "proxyCheckoutServerSdkUserAgent", { enumerable: true, get: function () { return version_js_1.proxyCheckoutServerSdkUserAgent; } });
40
+ Object.defineProperty(exports, "proxyCheckoutServerSdkVersion", { enumerable: true, get: function () { return version_js_1.proxyCheckoutServerSdkVersion; } });
41
+ var webhook_events_js_1 = require("./webhook-events.js");
42
+ Object.defineProperty(exports, "isProxyPaymentAttemptEvent", { enumerable: true, get: function () { return webhook_events_js_1.isProxyPaymentAttemptEvent; } });
43
+ Object.defineProperty(exports, "isProxySessionEvent", { enumerable: true, get: function () { return webhook_events_js_1.isProxySessionEvent; } });
44
+ Object.defineProperty(exports, "isProxySubscriptionEvent", { enumerable: true, get: function () { return webhook_events_js_1.isProxySubscriptionEvent; } });
45
+ Object.defineProperty(exports, "PROXY_WEBHOOK_EVENT_TYPES", { enumerable: true, get: function () { return webhook_events_js_1.PROXY_WEBHOOK_EVENT_TYPES; } });
46
+ var webhook_handler_js_1 = require("./webhook-handler.js");
47
+ Object.defineProperty(exports, "PROXY_WEBHOOK_RETRY_AFTER_SECONDS", { enumerable: true, get: function () { return webhook_handler_js_1.PROXY_WEBHOOK_RETRY_AFTER_SECONDS; } });
48
+ Object.defineProperty(exports, "ProxyWebhooksResource", { enumerable: true, get: function () { return webhook_handler_js_1.ProxyWebhooksResource; } });
49
+ var webhooks_js_1 = require("./webhooks.js");
50
+ Object.defineProperty(exports, "constructProxyWebhookEvent", { enumerable: true, get: function () { return webhooks_js_1.constructProxyWebhookEvent; } });
51
+ Object.defineProperty(exports, "PROXY_SIGNATURE_HEADER", { enumerable: true, get: function () { return webhooks_js_1.PROXY_SIGNATURE_HEADER; } });
52
+ Object.defineProperty(exports, "ProxyWebhookEndpointsResource", { enumerable: true, get: function () { return webhooks_js_1.ProxyWebhookEndpointsResource; } });
53
+ Object.defineProperty(exports, "ProxyWebhookSignatureVerificationError", { enumerable: true, get: function () { return webhooks_js_1.ProxyWebhookSignatureVerificationError; } });
54
+ Object.defineProperty(exports, "proxyCheckoutWebhookEndpointEndpoints", { enumerable: true, get: function () { return webhooks_js_1.proxyCheckoutWebhookEndpointEndpoints; } });
55
+ Object.defineProperty(exports, "verifyProxyWebhookSignature", { enumerable: true, get: function () { return webhooks_js_1.verifyProxyWebhookSignature; } });
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ /**
3
+ * SDK-owned normalization of Proxy session and subscription lifecycle.
4
+ *
5
+ * These helpers turn raw Proxy state into the small set of derived facts a
6
+ * merchant entitlement layer actually needs (`willRenew`, `accessEndsAt`,
7
+ * terminal/provisionable predicates) so every customer does not re-encode
8
+ * Proxy lifecycle semantics by hand.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.AT_RISK_SUBSCRIPTION_STATUSES = exports.ENDED_SUBSCRIPTION_STATUSES = exports.TERMINAL_SESSION_STATUSES = exports.PROVISIONABLE_SESSION_STATUSES = void 0;
12
+ exports.requireProxyDate = requireProxyDate;
13
+ exports.parseOptionalProxyDate = parseOptionalProxyDate;
14
+ exports.isSessionProvisionable = isSessionProvisionable;
15
+ exports.isSessionTerminal = isSessionTerminal;
16
+ exports.subscriptionWillRenew = subscriptionWillRenew;
17
+ exports.subscriptionAccessEndsAt = subscriptionAccessEndsAt;
18
+ exports.isSubscriptionEnded = isSubscriptionEnded;
19
+ exports.isSubscriptionPaymentAtRisk = isSubscriptionPaymentAtRisk;
20
+ const errors_js_1 = require("./errors.js");
21
+ /** Session statuses that mean the payer has paid and entitlement may be granted. */
22
+ exports.PROVISIONABLE_SESSION_STATUSES = new Set(["paid", "provisionable"]);
23
+ /**
24
+ * Session statuses that are terminal from the SDK's lifecycle perspective — the
25
+ * automatic flow has stopped and the merchant must observe the outcome. This
26
+ * includes `merchant_action_required`, which halts the session pending merchant
27
+ * intervention; classifying it here keeps a `proxy_session.merchant_action_required`
28
+ * event from silently resolving to `ignored` and being marked processed.
29
+ */
30
+ exports.TERMINAL_SESSION_STATUSES = new Set([
31
+ "cancelled",
32
+ "expired",
33
+ "failed",
34
+ "merchant_action_required",
35
+ "provisioned",
36
+ "provisioning_failed",
37
+ ]);
38
+ /** Subscription statuses that mean the subscription is no longer active. */
39
+ exports.ENDED_SUBSCRIPTION_STATUSES = new Set([
40
+ "canceled",
41
+ "ended",
42
+ "incomplete_expired",
43
+ ]);
44
+ /** Subscription statuses that indicate a payment problem on an otherwise live subscription. */
45
+ exports.AT_RISK_SUBSCRIPTION_STATUSES = new Set(["past_due", "unpaid"]);
46
+ /** Parse a required ISO date from Proxy, throwing a structured error when missing/invalid. */
47
+ function requireProxyDate(value, field) {
48
+ const date = parseOptionalProxyDate(value, field);
49
+ if (date === null) {
50
+ throw new errors_js_1.ProxyCheckoutValidationError(`Proxy date field ${field} is required.`, {
51
+ code: "invalid_date",
52
+ field,
53
+ });
54
+ }
55
+ return date;
56
+ }
57
+ /** Parse an optional ISO date from Proxy, returning null when absent and throwing when invalid. */
58
+ function parseOptionalProxyDate(value, field = "date") {
59
+ if (value === null || value === undefined || value === "") {
60
+ return null;
61
+ }
62
+ const date = new Date(value);
63
+ if (Number.isNaN(date.getTime())) {
64
+ throw new errors_js_1.ProxyCheckoutValidationError(`Proxy date field ${field} is not a valid date.`, {
65
+ code: "invalid_date",
66
+ field,
67
+ });
68
+ }
69
+ return date;
70
+ }
71
+ /** True once the payer has paid / the session is provisionable for entitlement. */
72
+ function isSessionProvisionable(session) {
73
+ return exports.PROVISIONABLE_SESSION_STATUSES.has(session.status);
74
+ }
75
+ /** True once the session has reached a terminal state. */
76
+ function isSessionTerminal(session) {
77
+ return exports.TERMINAL_SESSION_STATUSES.has(session.status);
78
+ }
79
+ /**
80
+ * Whether the subscription is expected to renew at the end of the current period.
81
+ * A subscription will not renew once it is scheduled to cancel or has ended.
82
+ */
83
+ function subscriptionWillRenew(subscription) {
84
+ if (subscription.cancelAtPeriodEnd) {
85
+ return false;
86
+ }
87
+ if (subscription.endedAt !== null) {
88
+ return false;
89
+ }
90
+ return !exports.ENDED_SUBSCRIPTION_STATUSES.has(subscription.status);
91
+ }
92
+ /**
93
+ * The instant at which paid access should end given current subscription state.
94
+ * Prefers an explicit `endedAt` (hard stop) over the current period boundary.
95
+ * Returns null when neither is known.
96
+ */
97
+ function subscriptionAccessEndsAt(subscription) {
98
+ return (parseOptionalProxyDate(subscription.endedAt, "subscription.endedAt") ??
99
+ parseOptionalProxyDate(subscription.currentPeriodEnd, "subscription.currentPeriodEnd"));
100
+ }
101
+ /** True when the subscription has ended (cancelled / expired / explicitly ended). */
102
+ function isSubscriptionEnded(subscription) {
103
+ return subscription.endedAt !== null || exports.ENDED_SUBSCRIPTION_STATUSES.has(subscription.status);
104
+ }
105
+ /** True when the subscription is live but has a payment problem (past_due / unpaid / failed). */
106
+ function isSubscriptionPaymentAtRisk(subscription) {
107
+ return (exports.AT_RISK_SUBSCRIPTION_STATUSES.has(subscription.status) ||
108
+ subscription.latestPaymentStatus === "failed");
109
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireJsonObject = requireJsonObject;
4
+ exports.requireString = requireString;
5
+ exports.requireNullableString = requireNullableString;
6
+ exports.requireInteger = requireInteger;
7
+ exports.requireNullableInteger = requireNullableInteger;
8
+ exports.requireBoolean = requireBoolean;
9
+ exports.requireStringArrayOrNull = requireStringArrayOrNull;
10
+ function requireJsonObject(value, operation) {
11
+ if (!isRecord(value)) {
12
+ throw new Error(`Proxy API response for ${operation} must be a JSON object.`);
13
+ }
14
+ return value;
15
+ }
16
+ function requireString(value, field) {
17
+ if (typeof value !== "string") {
18
+ throw new Error(`Proxy API response field ${field} must be a string.`);
19
+ }
20
+ return value;
21
+ }
22
+ function requireNullableString(value, field) {
23
+ if (value === null) {
24
+ return null;
25
+ }
26
+ return requireString(value, field);
27
+ }
28
+ function requireInteger(value, field) {
29
+ if (typeof value !== "number" || !Number.isInteger(value)) {
30
+ throw new Error(`Proxy API response field ${field} must be an integer.`);
31
+ }
32
+ return value;
33
+ }
34
+ function requireNullableInteger(value, field) {
35
+ if (value === null) {
36
+ return null;
37
+ }
38
+ if (typeof value !== "number" || !Number.isInteger(value)) {
39
+ throw new Error(`Proxy API response field ${field} must be an integer or null.`);
40
+ }
41
+ return value;
42
+ }
43
+ function requireBoolean(value, field) {
44
+ if (typeof value !== "boolean") {
45
+ throw new Error(`Proxy API response field ${field} must be a boolean.`);
46
+ }
47
+ return value;
48
+ }
49
+ function requireStringArrayOrNull(value, field) {
50
+ if (value === null) {
51
+ return null;
52
+ }
53
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
54
+ throw new Error(`Proxy API response field ${field} must be an array or null.`);
55
+ }
56
+ return value;
57
+ }
58
+ function isRecord(value) {
59
+ return typeof value === "object" && value !== null && !Array.isArray(value);
60
+ }