UNPKG

autumn-js

Version:
978 lines (961 loc) 28.5 kB
import queryString from 'query-string'; import { z } from 'zod/v4'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/sdk/error.ts var AutumnError = class _AutumnError extends Error { constructor(response) { super(response.message); __publicField(this, "message"); __publicField(this, "code"); this.message = response.message; this.code = response.code; } static fromError(error) { return new _AutumnError({ message: error.message || "Unknown error", code: error.code || "unknown_error" }); } toString() { return `${this.message} (code: ${this.code})`; } toJSON() { return { message: this.message, code: this.code }; } }; // src/sdk/general/genMethods.ts var handleCheckout = async ({ instance, params }) => { return instance.post("/checkout", params); }; var handleAttach = async ({ instance, params }) => { return instance.post("/attach", params); }; var handleSetupPayment = async ({ instance, params }) => { return instance.post("/setup_payment", params); }; var handleCancel = async ({ instance, params }) => { return instance.post("/cancel", params); }; var handleTrack = async ({ instance, params }) => { return instance.post("/track", params); }; var handleUsage = async ({ instance, params }) => { return instance.post("/usage", params); }; var handleCheck = async ({ instance, params }) => { return instance.post("/check", params); }; var handleQuery = async ({ instance, params }) => { return instance.post("/query", params); }; // src/libraries/backend/constants.ts var autumnApiUrl = "https://api.useautumn.com/v1"; var staticWrapper = (callback, instance, args) => { if (!instance) { instance = new Autumn(); } return callback({ instance, ...args }); }; var buildQueryString = (params) => { if (!params) return ""; return queryString.stringify(params, { skipNull: true, skipEmptyString: true }); }; var buildPathWithQuery = (basePath, params) => { const query = buildQueryString(params); return query ? `${basePath}?${query}` : basePath; }; // src/sdk/customers/cusMethods.ts var customerMethods = (instance) => { return { list: (params) => staticWrapper(listCustomers, instance, { params }), get: (id, params) => staticWrapper(getCustomer, instance, { id, params }), create: (params) => staticWrapper(createCustomer, instance, { params }), update: (id, params) => staticWrapper(updateCustomer, instance, { id, params }), delete: (id, params) => staticWrapper(deleteCustomer, instance, { id, params }), billingPortal: (id, params) => staticWrapper(billingPortal, instance, { id, params }), updateBalances: (id, params) => staticWrapper(updateBalances, instance, { id, params }) }; }; var getExpandStr = (expand) => { if (!expand) { return ""; } return `expand=${expand.join(",")}`; }; var listCustomers = async ({ instance, params }) => { const path = buildPathWithQuery("/customers", params); return instance.get(path); }; var getCustomer = async ({ instance, id, params }) => { if (!id) { return { data: null, error: new AutumnError({ message: "Customer ID is required", code: "CUSTOMER_ID_REQUIRED" }) }; } return instance.get(`/customers/${id}?${getExpandStr(params?.expand)}`); }; var createCustomer = async ({ instance, params }) => { return instance.post(`/customers?${getExpandStr(params?.expand)}`, params); }; var updateCustomer = async ({ instance, id, params }) => { return instance.post(`/customers/${id}`, params); }; var deleteCustomer = async ({ instance, id, params }) => { return instance.delete(`/customers/${id}${params?.delete_in_stripe ? "?delete_in_stripe=true" : ""}`); }; var billingPortal = async ({ instance, id, params }) => { return instance.post(`/customers/${id}/billing_portal`, params); }; var updateBalances = async ({ instance, id, params }) => { return instance.post(`/customers/${id}/balances`, { balances: Array.isArray(params) ? params : [params] }); }; // src/sdk/customers/entities/entMethods.ts var entityMethods = (instance) => { return { get: (customer_id, entity_id, params) => staticWrapper(getEntity, instance, { customer_id, entity_id, params }), create: (customer_id, params) => staticWrapper(createEntity, instance, { customer_id, params }), transfer: (customer_id, params) => staticWrapper(transferProduct, instance, { customer_id, params }), delete: (customer_id, entity_id) => staticWrapper(deleteEntity, instance, { customer_id, entity_id }) }; }; var getExpandStr2 = (expand) => { if (!expand) { return ""; } return `expand=${expand.join(",")}`; }; var getEntity = async ({ instance, customer_id, entity_id, params }) => { return instance.get( `/customers/${customer_id}/entities/${entity_id}?${getExpandStr2( params?.expand )}` ); }; var createEntity = async ({ instance, customer_id, params }) => { return instance.post(`/customers/${customer_id}/entities`, params); }; var deleteEntity = async ({ instance, customer_id, entity_id }) => { return instance.delete(`/customers/${customer_id}/entities/${entity_id}`); }; var transferProduct = async ({ instance, customer_id, params }) => { return instance.post(`/customers/${customer_id}/transfer`, params); }; // src/sdk/products/prodMethods.ts var productMethods = (instance) => { return { get: (id) => staticWrapper(getProduct, instance, { id }), create: (params) => staticWrapper(createProduct, instance, { params }), list: (params) => staticWrapper(listProducts, instance, { params }), delete: (id) => staticWrapper(deleteProduct, instance, { id }) }; }; var listProducts = async ({ instance, params }) => { let path = "/products_beta"; if (params) { const queryParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== void 0) { queryParams.append(key, String(value)); } } const queryString2 = queryParams.toString(); if (queryString2) { path += `?${queryString2}`; } } return instance.get(path); }; var getProduct = async ({ instance, id }) => { return instance.get(`/products/${id}`); }; var createProduct = async ({ instance, params }) => { return instance.post("/products", params); }; var deleteProduct = async ({ instance, id, params }) => { const path = buildPathWithQuery(`/products/${id}`, params); return instance.delete(path); }; // src/sdk/referrals/referralMethods.ts var referralMethods = (instance) => { return { createCode: (params) => staticWrapper(createReferralCode, instance, { params }), redeemCode: (params) => staticWrapper(redeemReferralCode, instance, { params }) }; }; var createReferralCode = async ({ instance, params }) => { return instance.post("/referrals/code", params); }; var redeemReferralCode = async ({ instance, params }) => { return instance.post("/referrals/redeem", params); }; // src/sdk/response.ts var toContainerResult = async ({ response, logger: logger2, logError = true }) => { if (response.status < 200 || response.status >= 300) { let error; try { error = await response.json(); if (logError) { logger2.error(`[Autumn] ${error.message}`); } } catch (error2) { throw error2; } return { data: null, error: new AutumnError({ message: error.message, code: error.code }), statusCode: response.status }; } try { const data = await response.json(); return { data, error: null, statusCode: response?.status }; } catch (error) { throw error; } }; // src/utils/logger.ts var getTime = () => { let timeString = (/* @__PURE__ */ new Date()).toISOString(); return `[${timeString.split("T")[1].split(".")[0]}]`; }; var greaterThanLevel = (level) => { return levels.indexOf(level) >= levels.indexOf(logger.level); }; var levels = ["debug", "info", "warn", "error", "fatal"]; var logger = { ...console, level: "info", debug: (...args) => { if (greaterThanLevel("debug")) { console.log(getTime(), "DEBUG", ...args); } }, log: (...args) => { console.log(getTime(), "INFO", ...args); }, info: (...args) => { if (greaterThanLevel("info")) { console.log(getTime(), "INFO", ...args); } }, warn: (...args) => { if (greaterThanLevel("warn")) { console.log(getTime(), "WARN", ...args); } }, error: (...args) => { if (greaterThanLevel("error")) { console.log(getTime(), "ERROR", ...args); } } }; // src/sdk/features/featureMethods.ts var featureMethods = (instance) => { return { list: () => staticWrapper(listFeatures, instance, {}), get: (id) => staticWrapper(getFeature, instance, { id }) }; }; var listFeatures = async ({ instance, params }) => { let path = "/features"; if (params) { const queryParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== void 0) { queryParams.append(key, String(value)); } } const queryString2 = queryParams.toString(); if (queryString2) { path += `?${queryString2}`; } } return instance.get(path); }; var getFeature = async ({ instance, id }) => { return instance.get(`/features/${id}`); }; // src/sdk/client.ts var LATEST_API_VERSION = "1.2"; var Autumn = class { constructor(options) { __publicField(this, "secretKey"); __publicField(this, "publishableKey"); __publicField(this, "headers"); __publicField(this, "url"); __publicField(this, "logger", console); __publicField(this, "customers", customerMethods(this)); __publicField(this, "products", productMethods(this)); __publicField(this, "entities", entityMethods(this)); __publicField(this, "referrals", referralMethods(this)); __publicField(this, "features", featureMethods(this)); try { this.secretKey = options?.secretKey || process.env.AUTUMN_SECRET_KEY; this.publishableKey = options?.publishableKey || process.env.AUTUMN_PUBLISHABLE_KEY; } catch (error) { } if (!this.secretKey && !this.publishableKey && !options?.headers) { throw new Error("Autumn secret key or publishable key is required"); } this.headers = options?.headers || { Authorization: `Bearer ${this.secretKey || this.publishableKey}`, "Content-Type": "application/json" }; let version = options?.version || LATEST_API_VERSION; this.headers["x-api-version"] = version; this.url = options?.url || autumnApiUrl; this.logger = logger; this.logger.level = options?.logLevel || "info"; } async get(path) { const response = await fetch(`${this.url}${path}`, { headers: this.headers }); return toContainerResult({ response, logger: this.logger }); } async post(path, body) { try { const response = await fetch(`${this.url}${path}`, { method: "POST", headers: this.headers, body: JSON.stringify(body) }); return toContainerResult({ response, logger: this.logger }); } catch (error) { console.error("Error sending request:", error); throw error; } } async delete(path) { const response = await fetch(`${this.url}${path}`, { method: "DELETE", headers: this.headers }); return toContainerResult({ response, logger: this.logger }); } /** * Initiates a checkout flow for a product purchase. * * The checkout function handles the purchase process for products with pricing. * It determines whether to show a dialog for user input or redirect directly * to Stripe based on the customer's state and product requirements. * * @param params - Checkout parameters including product ID, customer data, and options * @returns Promise resolving to checkout details including pricing, prorations, and URLs * * @example * ```typescript * const result = await autumn.checkout({ * customer_id: "user_123", * product_id: "pro", * success_url: "https://myapp.com/success" * }); * * if (result.url) { * // Redirect to Stripe checkout * window.location.href = result.url; * } * ``` */ async checkout(params) { return handleCheckout({ instance: this, params }); } /** * Attaches a product to a customer, enabling access and handling billing. * * The attach function activates a product for a customer and applies all product items. * When you attach a product: * - The customer gains access to all features in the product * - If the product has prices, the customer will be billed accordingly * - If there's no existing payment method, a checkout URL will be generated * * @param params - Attach parameters including customer ID, product ID, and options * @returns Promise resolving to attachment result with checkout URL if needed * * @example * ```typescript * const result = await autumn.attach({ * customer_id: "user_123", * product_id: "pro", * success_url: "https://myapp.com/success" * }); * * if (result.checkout_url) { * // Payment required - redirect to checkout * window.location.href = result.checkout_url; * } else { * // Product successfully attached * console.log("Access granted:", result.message); * } * ``` */ async attach(params) { return handleAttach({ instance: this, params }); } /** * Sets up a payment method for a customer. * * This method allows you to set up payment methods for customers without * immediately charging them. Useful for collecting payment information * before product attachment or for updating existing payment methods. * * @param params - Setup payment parameters including customer information * @returns Promise resolving to setup payment result * * @example * ```typescript * const result = await autumn.setupPayment({ * customer_id: "user_123" * }); * ``` */ async setupPayment(params) { return handleSetupPayment({ instance: this, params }); } /** * Cancels a customer's subscription or product attachment. * * This method allows you to cancel a customer's subscription to a specific product. * You can choose to cancel immediately or at the end of the billing cycle. * * @param params - Cancel parameters including customer ID and product ID * @returns Promise resolving to cancellation result * * @example * ```typescript * const result = await autumn.cancel({ * customer_id: "user_123", * product_id: "pro", * cancel_immediately: false // Cancel at end of billing cycle * }); * ``` */ async cancel(params) { return handleCancel({ instance: this, params }); } /** * Checks if a customer has access to a specific feature. * * This method verifies whether a customer has permission to use a feature * and checks their remaining balance/usage limits. It can be used to gate * features and determine when to show upgrade prompts. * * @param params - Check parameters including customer ID and feature ID * @returns Promise resolving to access check result with allowed status and balance info * * @example * ```typescript * const result = await autumn.check({ * customer_id: "user_123", * feature_id: "messages", * required_balance: 1 * }); * * if (!result.allowed) { * console.log("Feature access denied - upgrade required"); * } * ``` */ async check(params) { return handleCheck({ instance: this, params }); } /** * Tracks usage events for features or analytics. * * This method records usage events for metered features, updating the customer's * balance and usage statistics. It's typically used server-side to ensure * accurate tracking that cannot be manipulated by users. * * @param params - Track parameters including customer ID, feature ID, and usage value * @returns Promise resolving to tracking result * * @example * ```typescript * const result = await autumn.track({ * customer_id: "user_123", * feature_id: "messages", * value: 1 // Track 1 message sent * }); * ``` */ async track(params) { return handleTrack({ instance: this, params }); } /** * Retrieves usage statistics and analytics for a customer. * * This method fetches detailed usage information for a customer's features, * including current balances, usage history, and analytics data. Useful * for displaying usage dashboards or generating reports. * * @param params - Usage parameters including customer ID and optional filters * @returns Promise resolving to usage statistics and analytics data * * @example * ```typescript * const result = await autumn.usage({ * customer_id: "user_123", * feature_id: "messages" * value: 20 // Usage value * }); * ``` */ async usage(params) { return handleUsage({ instance: this, params }); } /** * Performs advanced queries on customer data and analytics. * * This method allows you to run complex queries against customer data, * usage patterns, and billing information. Useful for generating reports, * analytics, and custom data insights. * * @param params - Query parameters including customer ID and query specifications * @returns Promise resolving to query results with requested data * * @example * ```typescript * const result = await autumn.query({ * customer_id: "user_123", * feature_id: "messages" // feature id to fetch for query, can also be an array * }); * * ``` */ async query(params) { return handleQuery({ instance: this, params }); } }; __publicField(Autumn, "customers", customerMethods()); __publicField(Autumn, "products", productMethods()); __publicField(Autumn, "entities", entityMethods()); __publicField(Autumn, "referrals", referralMethods()); __publicField(Autumn, "features", featureMethods()); __publicField(Autumn, "checkout", (params) => staticWrapper(handleCheckout, void 0, { params })); __publicField(Autumn, "usage", (params) => staticWrapper(handleUsage, void 0, { params })); __publicField(Autumn, "attach", (params) => staticWrapper(handleAttach, void 0, { params })); __publicField(Autumn, "setupPayment", (params) => staticWrapper(handleSetupPayment, void 0, { params })); __publicField(Autumn, "cancel", (params) => staticWrapper(handleCancel, void 0, { params })); __publicField(Autumn, "check", (params) => staticWrapper(handleCheck, void 0, { params })); __publicField(Autumn, "track", (params) => staticWrapper(handleTrack, void 0, { params })); __publicField(Autumn, "query", (params) => staticWrapper(handleQuery, void 0, { params })); // src/sdk/products/prodEnums.ts var Infinite = "inf"; var FreeTrialDuration = /* @__PURE__ */ ((FreeTrialDuration2) => { FreeTrialDuration2["Day"] = "day"; return FreeTrialDuration2; })(FreeTrialDuration || {}); var UsageModel = /* @__PURE__ */ ((UsageModel2) => { UsageModel2["Prepaid"] = "prepaid"; UsageModel2["PayPerUse"] = "pay_per_use"; return UsageModel2; })(UsageModel || {}); var ProductItemInterval = /* @__PURE__ */ ((ProductItemInterval2) => { ProductItemInterval2["Minute"] = "minute"; ProductItemInterval2["Hour"] = "hour"; ProductItemInterval2["Day"] = "day"; ProductItemInterval2["Week"] = "week"; ProductItemInterval2["Month"] = "month"; ProductItemInterval2["Quarter"] = "quarter"; ProductItemInterval2["SemiAnnual"] = "semi_annual"; ProductItemInterval2["Year"] = "year"; ProductItemInterval2["Multiple"] = "multiple"; return ProductItemInterval2; })(ProductItemInterval || {}); var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => { ProductStatus2["Active"] = "active"; ProductStatus2["Expired"] = "expired"; ProductStatus2["Trialing"] = "trialing"; ProductStatus2["Scheduled"] = "scheduled"; ProductStatus2["PastDue"] = "past_due"; return ProductStatus2; })(ProductStatus || {}); var CustomerExpandEnum = z.enum([ "invoices", "rewards", "trials_used", "entities", "referrals", "payment_method" ]); var CoreCusFeatureSchema = z.object({ unlimited: z.boolean().optional(), interval: z.enum(ProductItemInterval).optional(), balance: z.number().nullish(), usage: z.number().optional(), included_usage: z.number().optional(), next_reset_at: z.number().nullish(), overage_allowed: z.boolean().optional(), usage_limit: z.number().optional(), rollovers: z.object({ balance: z.number(), expires_at: z.number() }).optional(), breakdown: z.array( z.object({ interval: z.enum(ProductItemInterval), balance: z.number().optional(), usage: z.number().optional(), included_usage: z.number().optional(), next_reset_at: z.number().optional() }) ).optional(), credit_schema: z.array( z.object({ feature_id: z.string(), credit_amount: z.number() }) ).optional() }); var CustomerDataSchema = z.object({ name: z.string().nullish(), email: z.string().nullish(), fingerprint: z.string().nullish() }); var CreateCustomerParamsSchema = z.object({ id: z.string().nullish(), email: z.string().nullish(), name: z.string().nullish(), fingerprint: z.string().nullish(), metadata: z.record(z.string(), z.any()).optional(), expand: z.array(CustomerExpandEnum).optional(), stripe_id: z.string().nullish() }); var BillingPortalParamsSchema = z.object({ return_url: z.string().optional() }); var UpdateBalancesParamsSchema = z.object({ feature_id: z.string(), balance: z.number() }).or( z.array( z.object({ feature_id: z.string(), balance: z.number() }) ) ); var DeleteCustomerParamsSchema = z.object({ delete_in_stripe: z.boolean().optional() }); var ListCustomersParamsSchema = z.object({ limit: z.number().optional(), offset: z.number().optional() }); var CheckFeatureResultSchema = z.object({ allowed: z.boolean(), feature_id: z.string(), customer_id: z.string(), entity_id: z.string().optional(), required_balance: z.number() }).extend(CoreCusFeatureSchema.shape); var EntityDataSchema = z.object({ name: z.string().optional(), feature_id: z.string() }); var TransferProductParamsSchema = z.object({ from_entity_id: z.string(), to_entity_id: z.string(), product_id: z.string() }); var CancelParamsSchema = z.object({ customer_id: z.string(), product_id: z.string(), entity_id: z.string().optional(), cancel_immediately: z.boolean().optional() }); var CancelResultSchema = z.object({ success: z.boolean(), customer_id: z.string(), product_id: z.string() }); var TrackParamsSchema = z.object({ customer_id: z.string(), value: z.number().optional(), feature_id: z.string().optional(), event_name: z.string().optional(), entity_id: z.string().optional(), customer_data: z.any().optional(), idempotency_key: z.string().optional(), entity_data: z.any().optional(), properties: z.record(z.string(), z.any()).optional() }); var TrackResultSchema = z.object({ id: z.string(), code: z.string(), customer_id: z.string(), feature_id: z.string().optional(), event_name: z.string().optional() }); var CheckParamsSchema = z.object({ customer_id: z.string(), feature_id: z.string().optional(), product_id: z.string().optional(), entity_id: z.string().optional(), customer_data: z.any().optional(), required_balance: z.number().optional(), send_event: z.boolean().optional(), with_preview: z.boolean().optional(), entity_data: EntityDataSchema.optional() }); var QueryRangeEnum = z.enum(["24h", "7d", "30d", "90d", "last_cycle"]); var QueryParamsSchema = z.object({ customer_id: z.string(), feature_id: z.string().or(z.array(z.string())), range: QueryRangeEnum.optional() }); // src/sdk/general/genEnums.ts var AppEnv = /* @__PURE__ */ ((AppEnv2) => { AppEnv2["Sandbox"] = "sandbox"; AppEnv2["Live"] = "live"; return AppEnv2; })(AppEnv || {}); // src/sdk/components/componentMethods.ts var fetchPricingTable = async ({ instance, params }) => { let path = "/components/pricing_table"; if (params) { const queryParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (key === "products") { continue; } if (value !== void 0) { queryParams.append(key, String(value)); } } const queryString2 = queryParams.toString(); if (queryString2) { path += `?${queryString2}`; } } return await instance.get(path); }; var CreateReferralCodeParamsSchema = z.object({ customer_id: z.string(), program_id: z.string() }); var RedeemReferralCodeParamsSchema = z.object({ code: z.string(), customer_id: z.string() }); var AttachFeatureOptionsSchema = z.object({ feature_id: z.string(), quantity: z.number() }); var AttachParamsSchema = z.object({ customer_id: z.string(), product_id: z.string().optional(), entity_id: z.string().optional(), options: z.array(AttachFeatureOptionsSchema).optional(), product_ids: z.array(z.string()).optional(), free_trial: z.boolean().optional(), success_url: z.string().optional(), metadata: z.record(z.string(), z.string()).optional(), force_checkout: z.boolean().optional(), customer_data: CustomerDataSchema.optional(), entity_data: z.any().optional(), checkout_session_params: z.record(z.string(), z.any()).optional(), reward: z.string().optional(), invoice: z.boolean().optional() }); var AttachResultSchema = z.object({ checkout_url: z.string().optional(), customer_id: z.string(), product_ids: z.array(z.string()), code: z.string(), message: z.string(), customer_data: z.any().optional(), invoice: z.object({ status: z.string(), stripe_id: z.string(), hosted_invoice_url: z.string().nullable(), total: z.number(), currency: z.string() }).optional() }); var CheckoutParamsSchema = z.object({ customer_id: z.string(), product_id: z.string(), product_ids: z.array(z.string()).optional(), entity_id: z.string().optional(), options: z.array(AttachFeatureOptionsSchema).optional(), force_checkout: z.boolean().optional(), invoice: z.boolean().optional(), success_url: z.string().optional(), customer_data: CustomerDataSchema.optional(), entity_data: z.any().optional(), checkout_session_params: z.record(z.string(), z.any()).optional(), reward: z.string().optional() }); var FeatureType = /* @__PURE__ */ ((FeatureType2) => { FeatureType2["Boolean"] = "boolean"; FeatureType2["SingleUse"] = "single_use"; FeatureType2["ContinuousUse"] = "continuous_use"; FeatureType2["CreditSystem"] = "credit_system"; return FeatureType2; })(FeatureType || {}); var FeatureSchema = z.object({ id: z.string(), name: z.string(), type: z.enum(FeatureType), display: z.object({ singular: z.string(), plural: z.string() }).nullish(), credit_schema: z.array( z.object({ metered_feature_id: z.string(), credit_cost: z.number() }) ).nullish(), archived: z.boolean() }); export { AppEnv, AttachFeatureOptionsSchema, AttachParamsSchema, AttachResultSchema, Autumn, AutumnError, BillingPortalParamsSchema, CancelParamsSchema, CancelResultSchema, CheckFeatureResultSchema, CheckParamsSchema, CheckoutParamsSchema, CoreCusFeatureSchema, CreateCustomerParamsSchema, CreateReferralCodeParamsSchema, CustomerDataSchema, CustomerExpandEnum, DeleteCustomerParamsSchema, EntityDataSchema, FeatureSchema, FreeTrialDuration, Infinite, ListCustomersParamsSchema, ProductItemInterval, ProductStatus, QueryParamsSchema, QueryRangeEnum, RedeemReferralCodeParamsSchema, TrackParamsSchema, TrackResultSchema, TransferProductParamsSchema, UpdateBalancesParamsSchema, UsageModel, fetchPricingTable, toContainerResult };