@proxy-checkout/stripe-server-js 0.0.0-pr-76.17.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Linus Labs, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @proxy-checkout/stripe-server-js
2
+
3
+ Server-side Stripe adapter for Proxy Checkout. It owns the Stripe-specific integration protocol so merchant backends never hand-roll it:
4
+
5
+ - **`requiredMetadata(proxySession)`** — the `proxy_session_id` metadata Proxy needs on the Checkout Session, Subscription, and PaymentIntent.
6
+ - **`assertCheckoutSessionBelongsToProxy` / `assertSubscriptionBelongsToProxy` / `assertPaymentIntentBelongsToProxy`** — provider-object ownership checks.
7
+ - **`openCheckout(...)`** — records payer-opened, validates the typed cart, supplies required metadata, records the Proxy provider binding, and returns the client secret. The merchant only supplies an app-specific Stripe-session builder.
8
+ - **`syncCheckoutCart(...)`** — validates the stored Proxy provider binding, then updates the Proxy cart and the Stripe Checkout `line_items` in the safest order with deterministic rollback/reconciliation (`ProxyStripeCartSyncError`).
9
+
10
+ PSP-agnostic primitives (sessions, subscriptions, webhooks, lifecycle) live in [`@proxy-checkout/server-js`](https://www.npmjs.com/package/@proxy-checkout/server-js). This package is an additive adapter on top and is dependency-free: you inject your own `Stripe` instance and your `@proxy-checkout/server-js` client.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install --save-exact @proxy-checkout/stripe-server-js @proxy-checkout/server-js stripe
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```ts
21
+ import Stripe from "stripe";
22
+ import { createProxyCheckoutServerClient } from "@proxy-checkout/server-js";
23
+ import { openCheckout, syncCheckoutCart } from "@proxy-checkout/stripe-server-js";
24
+
25
+ const proxy = createProxyCheckoutServerClient({ apiKey: process.env.PROXY_SECRET_KEY! });
26
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: "2025-12-15.clover" });
27
+
28
+ // Create the merchant-owned Stripe checkout, correctly linked to the Proxy session.
29
+ const checkout = await openCheckout({
30
+ proxy,
31
+ stripe,
32
+ proxySessionId,
33
+ cartSchema, // a zod-style schema, or any (value) => Cart validator
34
+ validateCart: ({ cart }) => buildMerchantOffer(cart),
35
+ createCheckoutSession: ({ stripe, cart, metadata }) =>
36
+ stripe.checkout.sessions.create({
37
+ ...buildMerchantStripeParams(cart),
38
+ ui_mode: "embedded",
39
+ metadata: { ...metadata.checkoutSession },
40
+ subscription_data: { metadata: metadata.subscriptionData.metadata },
41
+ }),
42
+ });
43
+ // checkout.clientSecret -> render Stripe Elements
44
+
45
+ // Cart edits go through the binding-validated sync helper.
46
+ await syncCheckoutCart({
47
+ proxy,
48
+ stripe,
49
+ proxySessionId,
50
+ checkoutSessionId: checkout.checkoutSession.id,
51
+ cartSchema,
52
+ input: { interval: "year" },
53
+ buildNextCart: ({ currentCart, input }) => buildMerchantCart(currentCart, input),
54
+ buildStripeLineItems: (cart) => cart.lineItems,
55
+ });
56
+ ```
57
+
58
+ See the [agentic delegated-checkout guide](https://github.com/linuslabs/proxy/blob/main/docs/integration/agentic-delegated-checkout-guide.md) for the full four-route integration recipe.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Adapter-specific error raised when a Stripe/Proxy cart synchronization cannot
3
+ * complete cleanly. The `reconciled` flag states whether the Proxy cart was
4
+ * restored to its prior state, so callers can react deterministically.
5
+ */
6
+ export type ProxyStripeCartSyncCode = "reconciliation_failed" | "stripe_update_failed";
7
+ export declare class ProxyStripeCartSyncError extends Error {
8
+ readonly name = "ProxyStripeCartSyncError";
9
+ readonly code: ProxyStripeCartSyncCode;
10
+ /** True when the Proxy cart was rolled back to its prior state after the failure. */
11
+ readonly reconciled: boolean;
12
+ readonly cause: unknown;
13
+ readonly rollbackCause: unknown;
14
+ constructor(message: string, details: {
15
+ code: ProxyStripeCartSyncCode;
16
+ reconciled: boolean;
17
+ cause: unknown;
18
+ rollbackCause?: unknown;
19
+ });
20
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,15 @@
1
+ export class ProxyStripeCartSyncError extends Error {
2
+ name = "ProxyStripeCartSyncError";
3
+ code;
4
+ /** True when the Proxy cart was rolled back to its prior state after the failure. */
5
+ reconciled;
6
+ cause;
7
+ rollbackCause;
8
+ constructor(message, details) {
9
+ super(message);
10
+ this.code = details.code;
11
+ this.reconciled = details.reconciled;
12
+ this.cause = details.cause;
13
+ this.rollbackCause = details.rollbackCause;
14
+ }
15
+ }
@@ -0,0 +1,6 @@
1
+ export { type ProxyStripeCartSyncCode, ProxyStripeCartSyncError, } from "./errors.js";
2
+ export { assertCheckoutSessionBelongsToProxy, assertPaymentIntentBelongsToProxy, assertSubscriptionBelongsToProxy, PROXY_SESSION_METADATA_KEY, type ProxySessionMetadata, type ProxyStripeRequiredMetadata, requiredMetadata, } from "./metadata.js";
3
+ export { type OpenCheckoutOptions, type OpenCheckoutResult, openCheckout, } from "./open-checkout.js";
4
+ export { type SyncCheckoutCartOptions, type SyncCheckoutCartResult, type SyncedCart, syncCheckoutCart, } from "./sync-checkout-cart.js";
5
+ export type { StripeCheckoutSessionLike, StripeCheckoutSessionsApiLike, StripeCheckoutSessionUpdateParams, StripeClientLike, StripeMetadata, StripePaymentIntentLike, StripeSubscriptionLike, } from "./types.js";
6
+ export { proxyCheckoutStripeServerSdkName, proxyCheckoutStripeServerSdkVersion, } from "./version.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { ProxyStripeCartSyncError, } from "./errors.js";
2
+ export { assertCheckoutSessionBelongsToProxy, assertPaymentIntentBelongsToProxy, assertSubscriptionBelongsToProxy, PROXY_SESSION_METADATA_KEY, requiredMetadata, } from "./metadata.js";
3
+ export { openCheckout, } from "./open-checkout.js";
4
+ export { syncCheckoutCart, } from "./sync-checkout-cart.js";
5
+ export { proxyCheckoutStripeServerSdkName, proxyCheckoutStripeServerSdkVersion, } from "./version.js";
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Required Stripe metadata placement + provider-object ownership assertions.
3
+ *
4
+ * Proxy correlates Stripe objects to a session solely through
5
+ * `metadata.proxy_session_id`. This module centralizes that placement so
6
+ * customers never have to remember which Stripe objects need the key, and
7
+ * provides assertions that a Stripe object actually belongs to a Proxy session.
8
+ */
9
+ import type { StripeCheckoutSessionLike, StripePaymentIntentLike, StripeSubscriptionLike } from "./types.js";
10
+ /** The single metadata key Proxy reads to correlate a Stripe object to a session. */
11
+ export declare const PROXY_SESSION_METADATA_KEY = "proxy_session_id";
12
+ export type ProxySessionMetadata = Readonly<Record<"proxy_session_id", string>>;
13
+ /**
14
+ * The metadata each Stripe object must carry, ready to spread into Stripe params.
15
+ *
16
+ * - `checkoutSession` → `metadata` on `checkout.sessions.create`
17
+ * - `subscriptionData` → `subscription_data` for subscription-mode Checkout
18
+ * - `paymentIntentData` → `payment_intent_data` for payment-mode Checkout / PaymentIntents
19
+ */
20
+ export interface ProxyStripeRequiredMetadata {
21
+ readonly checkoutSession: ProxySessionMetadata;
22
+ readonly paymentIntent: ProxySessionMetadata;
23
+ readonly paymentIntentData: {
24
+ readonly metadata: ProxySessionMetadata;
25
+ };
26
+ readonly subscription: ProxySessionMetadata;
27
+ readonly subscriptionData: {
28
+ readonly metadata: ProxySessionMetadata;
29
+ };
30
+ }
31
+ /** Build the required Stripe metadata placements for a Proxy session. */
32
+ export declare function requiredMetadata(proxySession: {
33
+ id: string;
34
+ }): ProxyStripeRequiredMetadata;
35
+ /** Assert a Stripe Checkout Session carries the expected `proxy_session_id` metadata. */
36
+ export declare function assertCheckoutSessionBelongsToProxy(checkoutSession: Pick<StripeCheckoutSessionLike, "metadata">, proxySessionId: string): void;
37
+ /** Assert a Stripe Subscription carries the expected `proxy_session_id` metadata. */
38
+ export declare function assertSubscriptionBelongsToProxy(subscription: Pick<StripeSubscriptionLike, "metadata">, proxySessionId: string): void;
39
+ /** Assert a Stripe PaymentIntent carries the expected `proxy_session_id` metadata. */
40
+ export declare function assertPaymentIntentBelongsToProxy(paymentIntent: Pick<StripePaymentIntentLike, "metadata">, proxySessionId: string): void;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Required Stripe metadata placement + provider-object ownership assertions.
3
+ *
4
+ * Proxy correlates Stripe objects to a session solely through
5
+ * `metadata.proxy_session_id`. This module centralizes that placement so
6
+ * customers never have to remember which Stripe objects need the key, and
7
+ * provides assertions that a Stripe object actually belongs to a Proxy session.
8
+ */
9
+ import { ProxyCheckoutValidationError } from "@proxy-checkout/server-js";
10
+ /** The single metadata key Proxy reads to correlate a Stripe object to a session. */
11
+ export const PROXY_SESSION_METADATA_KEY = "proxy_session_id";
12
+ /** Build the required Stripe metadata placements for a Proxy session. */
13
+ export function requiredMetadata(proxySession) {
14
+ const metadata = { proxy_session_id: proxySession.id };
15
+ return {
16
+ checkoutSession: metadata,
17
+ paymentIntent: metadata,
18
+ paymentIntentData: { metadata },
19
+ subscription: metadata,
20
+ subscriptionData: { metadata },
21
+ };
22
+ }
23
+ /** Assert a Stripe Checkout Session carries the expected `proxy_session_id` metadata. */
24
+ export function assertCheckoutSessionBelongsToProxy(checkoutSession, proxySessionId) {
25
+ assertProxyMetadata(checkoutSession.metadata, proxySessionId, "Stripe checkout session");
26
+ }
27
+ /** Assert a Stripe Subscription carries the expected `proxy_session_id` metadata. */
28
+ export function assertSubscriptionBelongsToProxy(subscription, proxySessionId) {
29
+ assertProxyMetadata(subscription.metadata, proxySessionId, "Stripe subscription");
30
+ }
31
+ /** Assert a Stripe PaymentIntent carries the expected `proxy_session_id` metadata. */
32
+ export function assertPaymentIntentBelongsToProxy(paymentIntent, proxySessionId) {
33
+ assertProxyMetadata(paymentIntent.metadata, proxySessionId, "Stripe payment intent");
34
+ }
35
+ function assertProxyMetadata(metadata, proxySessionId, objectLabel) {
36
+ const value = metadata?.[PROXY_SESSION_METADATA_KEY];
37
+ if (value !== proxySessionId) {
38
+ throw new ProxyCheckoutValidationError(`${objectLabel} metadata.${PROXY_SESSION_METADATA_KEY} (${value ?? "missing"}) does not match Proxy session ${proxySessionId}.`, { code: "provider_binding_mismatch", field: `metadata.${PROXY_SESSION_METADATA_KEY}` });
39
+ }
40
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `openCheckout` — the payer-opened + provider-object creation workflow.
3
+ *
4
+ * It performs the Proxy protocol steps (record payer-opened, validate the cart,
5
+ * supply required metadata, record the provider binding) and delegates only the
6
+ * app-specific Stripe object creation to the merchant callback. This makes it
7
+ * hard to create a Stripe checkout that is not correctly linked to a session.
8
+ */
9
+ import type { PayerOpenedResult, ProxyCartValidator, ProxyCheckoutServerClient } from "@proxy-checkout/server-js";
10
+ import type { ProxyStripeRequiredMetadata } from "./metadata.js";
11
+ import type { StripeCheckoutSessionLike } from "./types.js";
12
+ export interface OpenCheckoutOptions<TStripe, TCart, TOffer, TSession> {
13
+ /** Optional schema validating the session cart snapshot into a typed cart. */
14
+ readonly cartSchema?: ProxyCartValidator<TCart>;
15
+ /** Builds the Stripe checkout object. Must place `metadata.checkoutSession` (and subscription/payment-intent metadata) on the created object. */
16
+ readonly createCheckoutSession: (input: {
17
+ cart: TCart;
18
+ metadata: ProxyStripeRequiredMetadata;
19
+ offer: TOffer;
20
+ proxySession: PayerOpenedResult;
21
+ stripe: TStripe;
22
+ }) => Promise<TSession> | TSession;
23
+ /** Optional extractor used to assert the cart buyer reference matches the session. */
24
+ readonly getCartBuyerReference?: (cart: TCart) => string | null | undefined;
25
+ /** A Proxy server SDK client. */
26
+ readonly proxy: ProxyCheckoutServerClient;
27
+ readonly proxySessionId: string;
28
+ /** Provider identifier recorded with the binding. Defaults to "stripe". */
29
+ readonly psp?: string;
30
+ readonly requestId?: string;
31
+ /** The merchant's Stripe instance, forwarded to `createCheckoutSession`. */
32
+ readonly stripe: TStripe;
33
+ /** Optional merchant cart validation that derives an app-specific offer. */
34
+ readonly validateCart?: (input: {
35
+ cart: TCart;
36
+ session: PayerOpenedResult;
37
+ }) => Promise<TOffer> | TOffer;
38
+ }
39
+ export interface OpenCheckoutResult<TCart, TOffer, TSession> {
40
+ readonly binding: Awaited<ReturnType<ProxyCheckoutServerClient["sessions"]["recordProviderBinding"]>>;
41
+ readonly cart: TCart;
42
+ readonly checkoutSession: TSession;
43
+ readonly clientSecret: string | null;
44
+ readonly offer: TOffer;
45
+ readonly proxySession: PayerOpenedResult;
46
+ readonly proxySessionId: string;
47
+ }
48
+ export declare function openCheckout<TStripe, TCart = unknown, TOffer = undefined, TSession extends StripeCheckoutSessionLike = StripeCheckoutSessionLike>(options: OpenCheckoutOptions<TStripe, TCart, TOffer, TSession>): Promise<OpenCheckoutResult<TCart, TOffer, TSession>>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `openCheckout` — the payer-opened + provider-object creation workflow.
3
+ *
4
+ * It performs the Proxy protocol steps (record payer-opened, validate the cart,
5
+ * supply required metadata, record the provider binding) and delegates only the
6
+ * app-specific Stripe object creation to the merchant callback. This makes it
7
+ * hard to create a Stripe checkout that is not correctly linked to a session.
8
+ */
9
+ import { assertCheckoutSessionBelongsToProxy, requiredMetadata } from "./metadata.js";
10
+ export async function openCheckout(options) {
11
+ const psp = options.psp ?? "stripe";
12
+ const proxySession = await options.proxy.sessions.payerOpened(options.proxySessionId, {
13
+ requestId: options.requestId,
14
+ });
15
+ // Parse the cart (and run the buyer-reference check) whenever a schema OR a
16
+ // buyer-reference extractor is provided, so the consistency check is never
17
+ // silently skipped just because no custom schema was passed.
18
+ const cart = options.cartSchema || options.getCartBuyerReference
19
+ ? options.proxy.sessions.parseCart(proxySession, options.cartSchema ?? ((value) => value), { getBuyerReference: options.getCartBuyerReference })
20
+ : proxySession.cartSnapshot;
21
+ const offer = options.validateCart
22
+ ? await options.validateCart({ cart, session: proxySession })
23
+ : undefined;
24
+ const metadata = requiredMetadata(proxySession);
25
+ const checkoutSession = await options.createCheckoutSession({
26
+ cart,
27
+ metadata,
28
+ offer,
29
+ proxySession,
30
+ stripe: options.stripe,
31
+ });
32
+ // Fail closed if the merchant forgot to place proxy_session_id metadata.
33
+ assertCheckoutSessionBelongsToProxy(checkoutSession, proxySession.id);
34
+ const binding = await options.proxy.sessions.recordProviderBinding(proxySession.id, {
35
+ providerCheckoutSessionId: checkoutSession.id,
36
+ psp,
37
+ requestId: options.requestId,
38
+ });
39
+ return {
40
+ binding,
41
+ cart,
42
+ checkoutSession,
43
+ clientSecret: checkoutSession.client_secret ?? null,
44
+ offer,
45
+ proxySession,
46
+ proxySessionId: proxySession.id,
47
+ };
48
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `syncCheckoutCart` — coordinated Proxy + Stripe cart update.
3
+ *
4
+ * Validates ownership against the first-class Proxy provider binding (not just
5
+ * Stripe metadata), then updates the Proxy cart and the Stripe checkout in the
6
+ * safest order with deterministic rollback/reconciliation on failure.
7
+ */
8
+ import { type JsonObject, type MerchantProxySession, type ProxyCartValidator, type ProxyCheckoutServerClient } from "@proxy-checkout/server-js";
9
+ import type { StripeCheckoutSessionLike, StripeClientLike } from "./types.js";
10
+ /** The next cart, expressed both as Proxy state and the typed merchant cart. */
11
+ export interface SyncedCart<TCart> {
12
+ readonly amountMinor: number;
13
+ readonly cart: TCart;
14
+ readonly cartSnapshot: JsonObject;
15
+ readonly currency: string;
16
+ }
17
+ export interface SyncCheckoutCartOptions<TStripe extends StripeClientLike, TCart, TInput> {
18
+ /** Compute the next cart from current state and the merchant input. */
19
+ readonly buildNextCart: (input: {
20
+ currentCart: TCart;
21
+ currentSession: MerchantProxySession;
22
+ input: TInput;
23
+ }) => Promise<SyncedCart<TCart>> | SyncedCart<TCart>;
24
+ /** Derive the Stripe `line_items` update from the next typed cart. */
25
+ readonly buildStripeLineItems: (cart: TCart) => unknown;
26
+ /** Optional schema validating the current cart snapshot into a typed cart. */
27
+ readonly cartSchema?: ProxyCartValidator<TCart>;
28
+ readonly checkoutSessionId: string;
29
+ /** Merchant-supplied change request (e.g. new interval/quantity). */
30
+ readonly input: TInput;
31
+ readonly proxy: ProxyCheckoutServerClient;
32
+ readonly proxySessionId: string;
33
+ /** Provider identifier the session must be bound under. Defaults to "stripe". */
34
+ readonly psp?: string;
35
+ readonly requestId?: string;
36
+ readonly stripe: TStripe;
37
+ }
38
+ export interface SyncCheckoutCartResult<TCart> {
39
+ readonly amountMinor: number;
40
+ readonly cart: TCart;
41
+ readonly cartSnapshot: JsonObject;
42
+ readonly checkoutSession: StripeCheckoutSessionLike;
43
+ readonly currency: string;
44
+ }
45
+ export declare function syncCheckoutCart<TStripe extends StripeClientLike, TCart, TInput>(options: SyncCheckoutCartOptions<TStripe, TCart, TInput>): Promise<SyncCheckoutCartResult<TCart>>;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `syncCheckoutCart` — coordinated Proxy + Stripe cart update.
3
+ *
4
+ * Validates ownership against the first-class Proxy provider binding (not just
5
+ * Stripe metadata), then updates the Proxy cart and the Stripe checkout in the
6
+ * safest order with deterministic rollback/reconciliation on failure.
7
+ */
8
+ import { ProxyCheckoutValidationError, } from "@proxy-checkout/server-js";
9
+ import { ProxyStripeCartSyncError } from "./errors.js";
10
+ import { assertCheckoutSessionBelongsToProxy } from "./metadata.js";
11
+ export async function syncCheckoutCart(options) {
12
+ const psp = options.psp ?? "stripe";
13
+ const session = await options.proxy.sessions.retrieve(options.proxySessionId, {
14
+ requestId: options.requestId,
15
+ });
16
+ // Ownership: validate against the stored binding first, then defensively
17
+ // against the Stripe object's own metadata.
18
+ assertSessionBoundTo(session, options.checkoutSessionId, psp);
19
+ const stripeSession = await options.stripe.checkout.sessions.retrieve(options.checkoutSessionId);
20
+ assertCheckoutSessionBelongsToProxy(stripeSession, options.proxySessionId);
21
+ const currentCart = options.cartSchema
22
+ ? options.proxy.sessions.parseCart(session, options.cartSchema)
23
+ : session.cartSnapshot;
24
+ const next = await options.buildNextCart({
25
+ currentCart,
26
+ currentSession: session,
27
+ input: options.input,
28
+ });
29
+ const prior = {
30
+ amountMinor: session.amountMinor,
31
+ cartSnapshot: session.cartSnapshot,
32
+ currency: session.currency,
33
+ };
34
+ // Update Proxy first; the API rejects a non-editable session before Stripe is touched.
35
+ await options.proxy.sessions.cart.set(options.proxySessionId, {
36
+ amountMinor: next.amountMinor,
37
+ cartSnapshot: next.cartSnapshot,
38
+ currency: next.currency,
39
+ requestId: options.requestId,
40
+ });
41
+ let updatedCheckout;
42
+ try {
43
+ updatedCheckout = await options.stripe.checkout.sessions.update(options.checkoutSessionId, {
44
+ line_items: options.buildStripeLineItems(next.cart),
45
+ });
46
+ }
47
+ catch (cause) {
48
+ try {
49
+ await options.proxy.sessions.cart.set(options.proxySessionId, {
50
+ amountMinor: prior.amountMinor,
51
+ cartSnapshot: prior.cartSnapshot,
52
+ currency: prior.currency,
53
+ requestId: options.requestId,
54
+ });
55
+ }
56
+ catch (rollbackCause) {
57
+ throw new ProxyStripeCartSyncError("Stripe checkout update failed and the Proxy cart rollback failed; carts may be out of sync.", { cause, code: "reconciliation_failed", reconciled: false, rollbackCause });
58
+ }
59
+ throw new ProxyStripeCartSyncError("Stripe checkout update failed; the Proxy cart was rolled back to its prior state.", { cause, code: "stripe_update_failed", reconciled: true });
60
+ }
61
+ return {
62
+ amountMinor: next.amountMinor,
63
+ cart: next.cart,
64
+ cartSnapshot: next.cartSnapshot,
65
+ checkoutSession: updatedCheckout,
66
+ currency: next.currency,
67
+ };
68
+ }
69
+ function assertSessionBoundTo(session, checkoutSessionId, psp) {
70
+ if (session.providerCheckoutSessionId !== checkoutSessionId ||
71
+ session.providerCheckoutSessionPsp !== psp) {
72
+ throw new ProxyCheckoutValidationError(`Proxy session ${session.id} is not bound to provider checkout session ${checkoutSessionId}.`, { code: "provider_binding_mismatch", field: "provider_checkout_session_id" });
73
+ }
74
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Minimal structural Stripe types.
3
+ *
4
+ * The adapter is dependency-free: merchants inject their own `Stripe` instance
5
+ * and objects, which are structurally compatible with these narrow interfaces.
6
+ * This avoids a runtime/build dependency on the `stripe` package while keeping
7
+ * the bits the adapter actually touches type-safe.
8
+ */
9
+ export type StripeMetadata = Record<string, string | null> | null | undefined;
10
+ export interface StripeCheckoutSessionLike {
11
+ readonly client_secret?: string | null;
12
+ readonly id: string;
13
+ readonly metadata?: StripeMetadata;
14
+ }
15
+ export interface StripeSubscriptionLike {
16
+ readonly id: string;
17
+ readonly metadata?: StripeMetadata;
18
+ }
19
+ export interface StripePaymentIntentLike {
20
+ readonly id: string;
21
+ readonly metadata?: StripeMetadata;
22
+ }
23
+ export interface StripeCheckoutSessionUpdateParams {
24
+ readonly line_items?: unknown;
25
+ readonly metadata?: Record<string, string>;
26
+ }
27
+ export interface StripeCheckoutSessionsApiLike {
28
+ retrieve(id: string, params?: unknown, options?: unknown): Promise<StripeCheckoutSessionLike>;
29
+ update(id: string, params: StripeCheckoutSessionUpdateParams, options?: unknown): Promise<StripeCheckoutSessionLike>;
30
+ }
31
+ export interface StripeClientLike {
32
+ readonly checkout: {
33
+ readonly sessions: StripeCheckoutSessionsApiLike;
34
+ };
35
+ }
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Minimal structural Stripe types.
3
+ *
4
+ * The adapter is dependency-free: merchants inject their own `Stripe` instance
5
+ * and objects, which are structurally compatible with these narrow interfaces.
6
+ * This avoids a runtime/build dependency on the `stripe` package while keeping
7
+ * the bits the adapter actually touches type-safe.
8
+ */
9
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const proxyCheckoutStripeServerSdkName = "@proxy-checkout/stripe-server-js";
2
+ export declare const proxyCheckoutStripeServerSdkVersion = "0.0.0-pr-76.17.1";
@@ -0,0 +1,2 @@
1
+ export const proxyCheckoutStripeServerSdkName = "@proxy-checkout/stripe-server-js";
2
+ export const proxyCheckoutStripeServerSdkVersion = "0.0.0-pr-76.17.1";
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "description": "Server-side Stripe adapter for Proxy Checkout: required metadata, provider binding, openCheckout, and cart sync.",
3
+ "license": "MIT",
4
+ "module": "./dist/index.js",
5
+ "name": "@proxy-checkout/stripe-server-js",
6
+ "private": false,
7
+ "sideEffects": false,
8
+ "type": "module",
9
+ "types": "./dist/index.d.ts",
10
+ "version": "0.0.0-pr-76.17.1",
11
+ "devDependencies": {
12
+ "@types/node": "^24.12.4",
13
+ "@vitest/coverage-v8": "4.1.7",
14
+ "typescript": "^6.0.3",
15
+ "vitest": "4.1.7",
16
+ "@proxy-checkout/server-js": "0.0.4-pr-76.17.1"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.js",
21
+ "types": "./dist/index.d.ts"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "LICENSE",
27
+ "README.md"
28
+ ],
29
+ "keywords": [
30
+ "proxy-checkout",
31
+ "stripe",
32
+ "checkout",
33
+ "payments",
34
+ "sdk"
35
+ ],
36
+ "peerDependencies": {
37
+ "@proxy-checkout/server-js": "0.0.4"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "repository": {
43
+ "directory": "sdks/stripe-server-js",
44
+ "type": "git",
45
+ "url": "git+https://github.com/linuslabs/proxy.git"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc -p tsconfig.build.json",
49
+ "test:all": "vitest run",
50
+ "test:coverage": "vitest run --coverage.enabled --coverage.reportsDirectory=coverage/all",
51
+ "test:coverage:changed": "vitest run --coverage.enabled --coverage.reportsDirectory=coverage/changed",
52
+ "test:coverage:integration": "vitest run --project integration --coverage.enabled --coverage.reportsDirectory=coverage/integration",
53
+ "test:coverage:unit": "vitest run --project unit --coverage.enabled --coverage.reportsDirectory=coverage/unit",
54
+ "test:integration": "vitest run --project integration",
55
+ "test:unit": "vitest run --project unit",
56
+ "typecheck": "tsc --noEmit -p tsconfig.json"
57
+ }
58
+ }