UNPKG

autumn-js

Version:
256 lines (252 loc) 6.64 kB
"use client"; import { createEntityMethod, deleteEntityMethod, getEntityMethod } from "./chunk-OYBOLAL5.mjs"; import { attachMethod, cancelMethod, checkMethod, checkoutMethod, openBillingPortalMethod, queryMethod, setupPaymentMethod, trackMethod } from "./chunk-6EXNYWJX.mjs"; import { listProductsMethod } from "./chunk-V575SGOW.mjs"; import { createCode, redeemCode } from "./chunk-SUENW2KS.mjs"; import { logAuthError } from "./chunk-JVCOY7ZL.mjs"; import { logFetchError } from "./chunk-CIBQ4BJU.mjs"; import { AutumnError, toContainerResult } from "./chunk-QN2ALOVD.mjs"; import { eventAggregateMethod, eventListMethod } from "./chunk-XDQLJ7QR.mjs"; import { createCustomerMethod } from "./chunk-WFFVOEUG.mjs"; // src/libraries/react/client/ReactAutumnClient.tsx var AutumnClient = class { backendUrl; getBearerToken; customerData; includeCredentials; prefix; camelCase; headers; framework; defaultReturnUrl; suppressLogs; constructor({ backendUrl, getBearerToken, customerData, includeCredentials, betterAuthUrl, headers, pathPrefix, defaultReturnUrl, suppressLogs }) { this.backendUrl = backendUrl; this.getBearerToken = getBearerToken; this.customerData = customerData; this.includeCredentials = includeCredentials; this.prefix = "/api/autumn"; let camelCase = false; if (betterAuthUrl) { this.prefix = "/api/auth/autumn"; this.backendUrl = betterAuthUrl; camelCase = true; } const providedPrefix = pathPrefix; if (providedPrefix) { const normalized = `/${providedPrefix}`.replace(/\/+/g, "/").replace(/\/$/, ""); this.prefix = normalized; } this.headers = headers; if (betterAuthUrl) camelCase = true; this.camelCase = camelCase; this.defaultReturnUrl = defaultReturnUrl; this.suppressLogs = suppressLogs ?? false; } /** * Detects if the backend supports CORS credentials by making an OPTIONS request */ async detectCors() { if (this.prefix?.includes("/api/auth")) { return { valid: true, includeCredentials: true }; } const testEndpoint = `${this.backendUrl}${this.prefix}/cors`; try { await fetch(testEndpoint, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({}) }); return { valid: true, includeCredentials: true }; } catch (_) { try { await fetch(testEndpoint, { method: "POST", credentials: "omit", headers: { "Content-Type": "application/json" }, body: JSON.stringify({}) }); return { valid: true, includeCredentials: false }; } catch (_2) { return { valid: false, includeCredentials: void 0 }; } } } /** * Automatically determines whether to include credentials based on CORS detection */ async shouldIncludeCredentials() { if (this.includeCredentials !== void 0) { return this.includeCredentials; } try { const corsResult = await this.detectCors(); if (corsResult.valid) { console.warn( `[Autumn] Detected CORS credentials: ${corsResult.includeCredentials}` ); console.warn( `[Autumn] To disable this warning, you can set includeCredentials={${corsResult.includeCredentials ? "true" : "false"}} in <AutumnProvider />` ); this.includeCredentials = corsResult.includeCredentials; return corsResult.includeCredentials || false; } console.warn(`[Autumn] CORS detection failed, defaulting to false`); return false; } catch (error) { console.error(`[Autumn] Error detecting CORS: ${error.message}`); return false; } } async getHeaders() { let headers = { "Content-Type": "application/json" }; if (this.getBearerToken) { try { const token = await this.getBearerToken(); headers.Authorization = `Bearer ${token}`; } catch (_) { console.error(`Failed to call getToken() in AutumnProvider`); } } if (this.headers) { headers = { ...headers, ...this.headers }; } return headers; } async handleFetch({ path, method, body }) { body = method === "POST" ? { ...body, [this.camelCase ? "customerData" : "customer_data"]: this.customerData || void 0 } : void 0; const includeCredentials = await this.shouldIncludeCredentials(); try { const response = await fetch(`${this.backendUrl}${path}`, { method, body: body ? JSON.stringify(body) : void 0, headers: await this.getHeaders(), credentials: includeCredentials ? "include" : "omit" }); const loggedError = this.suppressLogs ? false : await logAuthError(response); return await toContainerResult({ response, logger: console, logError: !this.suppressLogs && !loggedError }); } catch (error) { if (!this.suppressLogs) { logFetchError({ method, backendUrl: this.backendUrl || "", path, error }); } return { data: null, error: new AutumnError({ message: error instanceof Error ? error.message : JSON.stringify(error), code: "fetch_failed" }) }; } } async post(path, body) { return await this.handleFetch({ path, method: "POST", body }); } async get(path) { return await this.handleFetch({ path, method: "GET" }); } async delete(path) { return await this.handleFetch({ path, method: "DELETE" }); } async createCustomer(params) { return await createCustomerMethod({ client: this, params }); } attach = attachMethod.bind(this); checkout = checkoutMethod.bind(this); cancel = cancelMethod.bind(this); check = checkMethod.bind(this); track = trackMethod.bind(this); openBillingPortal = openBillingPortalMethod.bind(this); setupPayment = setupPaymentMethod.bind(this); query = queryMethod.bind(this); entities = { create: createEntityMethod.bind(this), get: getEntityMethod.bind(this), delete: deleteEntityMethod.bind(this) }; referrals = { createCode: createCode.bind(this), redeemCode: redeemCode.bind(this) }; products = { list: listProductsMethod.bind(this) }; events = { list: eventListMethod.bind(this), aggregate: eventAggregateMethod.bind(this) }; }; export { AutumnClient };