billsdk 0.0.1 → 0.1.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.
@@ -0,0 +1 @@
1
+ export { DrizzleAdapterConfig, DrizzleDB, drizzleAdapter } from '@billsdk/drizzle-adapter';
@@ -0,0 +1,3 @@
1
+ export { drizzleAdapter } from '@billsdk/drizzle-adapter';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -0,0 +1,3 @@
1
+ export { memoryAdapter } from '@billsdk/memory-adapter';
2
+ import '@billsdk/payment-adapter';
3
+ import '@billsdk/drizzle-adapter';
@@ -0,0 +1,3 @@
1
+ export { memoryAdapter } from '@billsdk/memory-adapter';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -0,0 +1 @@
1
+ export { paymentAdapter } from '@billsdk/payment-adapter';
@@ -0,0 +1,3 @@
1
+ export { paymentAdapter } from '@billsdk/payment-adapter';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
@@ -0,0 +1,133 @@
1
+ import { A as AsyncAtom, a as Atom, e as ClientConfig, S as SubscriptionResponse, C as CreateSubscriptionInput, b as CreateSubscriptionResponse, c as CancelSubscriptionInput, d as CancelSubscriptionResponse, H as HealthResponse } from '../types-Ofy1HBSd.js';
2
+ export { f as ApiResponse, g as CustomerWithSubscription } from '../types-Ofy1HBSd.js';
3
+ import { Customer, Plan } from '@billsdk/core/types';
4
+
5
+ /**
6
+ * Create a simple atom for reactive state
7
+ */
8
+ declare function atom<T>(initialValue: T): Atom<T>;
9
+ /**
10
+ * Create an async atom that fetches data
11
+ */
12
+ declare function asyncAtom<T>(fetcher: () => Promise<T>, options?: {
13
+ autoFetch?: boolean;
14
+ }): AsyncAtom<T>;
15
+ /**
16
+ * Computed atom that derives from other atoms
17
+ */
18
+ declare function computed<T, R>(sourceAtom: Atom<T>, transform: (value: T) => R): Atom<R>;
19
+
20
+ /**
21
+ * HTTP methods
22
+ */
23
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
24
+ /**
25
+ * Fetch options
26
+ */
27
+ interface FetchOptions {
28
+ method?: HttpMethod;
29
+ body?: unknown;
30
+ query?: Record<string, string | undefined>;
31
+ headers?: Record<string, string>;
32
+ }
33
+ /**
34
+ * Create a configured fetch function
35
+ */
36
+ declare function createFetch(config?: ClientConfig): <T>(path: string, options?: FetchOptions) => Promise<T>;
37
+ /**
38
+ * Create a proxy that converts method calls to API requests
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const api = createProxy($fetch);
43
+ * await api.customer.get({ query: { externalId: "123" } });
44
+ * await api.plans.list();
45
+ * ```
46
+ */
47
+ declare function createProxy<T extends ReturnType<typeof createFetch>>($fetch: T, pathMethods?: Record<string, HttpMethod>): Record<string, unknown>;
48
+
49
+ /**
50
+ * Billing client interface
51
+ */
52
+ interface BillingClient {
53
+ $customer: AsyncAtom<Customer | null>;
54
+ $subscription: AsyncAtom<SubscriptionResponse | null>;
55
+ $plans: AsyncAtom<Plan[]>;
56
+ customer: {
57
+ get(options: {
58
+ query: {
59
+ externalId: string;
60
+ };
61
+ }): Promise<{
62
+ customer: Customer | null;
63
+ }>;
64
+ create(options: {
65
+ body: {
66
+ externalId: string;
67
+ email: string;
68
+ name?: string;
69
+ };
70
+ }): Promise<{
71
+ customer: Customer;
72
+ }>;
73
+ };
74
+ plans: {
75
+ list(): Promise<{
76
+ plans: Plan[];
77
+ }>;
78
+ };
79
+ plan: {
80
+ get(options: {
81
+ query: {
82
+ id?: string;
83
+ code?: string;
84
+ };
85
+ }): Promise<{
86
+ plan: Plan | null;
87
+ prices: unknown[];
88
+ }>;
89
+ };
90
+ subscription: {
91
+ get(options: {
92
+ query: {
93
+ customerId: string;
94
+ };
95
+ }): Promise<SubscriptionResponse>;
96
+ create(options: {
97
+ body: CreateSubscriptionInput;
98
+ }): Promise<CreateSubscriptionResponse>;
99
+ cancel(options: {
100
+ body: CancelSubscriptionInput;
101
+ }): Promise<CancelSubscriptionResponse>;
102
+ };
103
+ health: {
104
+ get(): Promise<HealthResponse>;
105
+ };
106
+ setCustomerId(customerId: string): void;
107
+ refresh(): Promise<void>;
108
+ }
109
+ /**
110
+ * Create a billing client
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * import { createBillingClient } from "@billsdk/core/client";
115
+ *
116
+ * // Uses default baseURL: "/api/billing"
117
+ * const billing = createBillingClient();
118
+ *
119
+ * // Set current customer
120
+ * billing.setCustomerId("user_123");
121
+ *
122
+ * // Reactive state
123
+ * billing.$customer.subscribe((customer) => {
124
+ * console.log("Customer:", customer);
125
+ * });
126
+ *
127
+ * // Direct API calls
128
+ * const plans = await billing.plans.list();
129
+ * ```
130
+ */
131
+ declare function createBillingClient(config?: ClientConfig): BillingClient;
132
+
133
+ export { AsyncAtom, Atom, type BillingClient, CancelSubscriptionInput, CancelSubscriptionResponse, ClientConfig, CreateSubscriptionInput, CreateSubscriptionResponse, HealthResponse, SubscriptionResponse, asyncAtom, atom, computed, createBillingClient, createFetch, createProxy };
@@ -0,0 +1,257 @@
1
+ // src/client/atoms.ts
2
+ function atom(initialValue) {
3
+ let value = initialValue;
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ return {
6
+ get() {
7
+ return value;
8
+ },
9
+ set(newValue) {
10
+ value = newValue;
11
+ for (const listener of listeners) {
12
+ listener(value);
13
+ }
14
+ },
15
+ subscribe(callback) {
16
+ listeners.add(callback);
17
+ callback(value);
18
+ return () => {
19
+ listeners.delete(callback);
20
+ };
21
+ }
22
+ };
23
+ }
24
+ function asyncAtom(fetcher, options = {}) {
25
+ const valueAtom = atom(null);
26
+ const loadingAtom = atom(false);
27
+ const errorAtom = atom(null);
28
+ const refresh = async () => {
29
+ loadingAtom.set(true);
30
+ errorAtom.set(null);
31
+ try {
32
+ const data = await fetcher();
33
+ valueAtom.set(data);
34
+ } catch (err) {
35
+ errorAtom.set(err instanceof Error ? err : new Error(String(err)));
36
+ } finally {
37
+ loadingAtom.set(false);
38
+ }
39
+ };
40
+ if (options.autoFetch !== false) {
41
+ refresh();
42
+ }
43
+ return {
44
+ get() {
45
+ return valueAtom.get();
46
+ },
47
+ isLoading() {
48
+ return loadingAtom.get();
49
+ },
50
+ error() {
51
+ return errorAtom.get();
52
+ },
53
+ refresh,
54
+ subscribe(callback) {
55
+ return valueAtom.subscribe(callback);
56
+ }
57
+ };
58
+ }
59
+ function computed(sourceAtom, transform) {
60
+ const computedAtom = atom(transform(sourceAtom.get()));
61
+ sourceAtom.subscribe((value) => {
62
+ computedAtom.set(transform(value));
63
+ });
64
+ return {
65
+ get() {
66
+ return computedAtom.get();
67
+ },
68
+ set() {
69
+ throw new Error("Cannot set a computed atom directly");
70
+ },
71
+ subscribe: computedAtom.subscribe
72
+ };
73
+ }
74
+
75
+ // src/client/proxy.ts
76
+ function createFetch(config = {}) {
77
+ const baseFetch = config.fetch ?? fetch;
78
+ const baseURL = config.baseURL ?? "/api/billing";
79
+ return async (path, options = {}) => {
80
+ const method = options.method ?? "GET";
81
+ let url = `${baseURL}${path}`;
82
+ if (options.query) {
83
+ const params = new URLSearchParams();
84
+ for (const [key, value] of Object.entries(options.query)) {
85
+ if (value !== void 0) {
86
+ params.set(key, value);
87
+ }
88
+ }
89
+ const queryString = params.toString();
90
+ if (queryString) {
91
+ url += `?${queryString}`;
92
+ }
93
+ }
94
+ const headers = {
95
+ "Content-Type": "application/json",
96
+ ...config.headers,
97
+ ...options.headers
98
+ };
99
+ const fetchOptions = {
100
+ method,
101
+ headers,
102
+ credentials: config.credentials ?? "include"
103
+ };
104
+ if (options.body && ["POST", "PUT", "PATCH"].includes(method)) {
105
+ fetchOptions.body = JSON.stringify(options.body);
106
+ }
107
+ const response = await baseFetch(url, fetchOptions);
108
+ if (!response.ok) {
109
+ const errorData = await response.json().catch(() => ({ error: { message: "Unknown error" } }));
110
+ throw new Error(
111
+ errorData?.error?.message ?? `Request failed: ${response.status}`
112
+ );
113
+ }
114
+ return response.json();
115
+ };
116
+ }
117
+ function createProxy($fetch, pathMethods = {}) {
118
+ ({
119
+ ...pathMethods
120
+ });
121
+ function createNestedProxy(segments) {
122
+ return new Proxy(() => {
123
+ }, {
124
+ get(_, prop) {
125
+ if (prop === "then" || prop === "catch" || prop === "finally") {
126
+ return void 0;
127
+ }
128
+ return createNestedProxy([...segments, prop]);
129
+ },
130
+ apply(_, __, args) {
131
+ const lastSegment = segments[segments.length - 1] ?? "";
132
+ const pathSegments = segments.slice(0, -1);
133
+ let method = "GET";
134
+ if (lastSegment === "get" || lastSegment === "list") {
135
+ method = "GET";
136
+ } else if (lastSegment === "create" || lastSegment === "post") {
137
+ method = "POST";
138
+ } else if (lastSegment === "update" || lastSegment === "put") {
139
+ method = "PUT";
140
+ } else if (lastSegment === "patch") {
141
+ method = "PATCH";
142
+ } else if (lastSegment === "delete" || lastSegment === "remove") {
143
+ method = "DELETE";
144
+ } else {
145
+ pathSegments.push(lastSegment);
146
+ }
147
+ const path = "/" + pathSegments.join("/").replace(/([A-Z])/g, "-$1").toLowerCase();
148
+ const options = args[0] ?? {};
149
+ return $fetch(path, { ...options, method });
150
+ }
151
+ });
152
+ }
153
+ return createNestedProxy([]);
154
+ }
155
+
156
+ // src/client/vanilla.ts
157
+ function createBillingClient(config = {}) {
158
+ const $fetch = createFetch(config);
159
+ const customerIdAtom = atom(null);
160
+ const $customer = asyncAtom(
161
+ async () => {
162
+ const customerId = customerIdAtom.get();
163
+ if (!customerId) return null;
164
+ const response = await $fetch(
165
+ "/customer",
166
+ {
167
+ method: "GET",
168
+ query: { externalId: customerId }
169
+ }
170
+ );
171
+ return response.customer;
172
+ },
173
+ { autoFetch: false }
174
+ );
175
+ const $subscription = asyncAtom(
176
+ async () => {
177
+ const customerId = customerIdAtom.get();
178
+ if (!customerId) return null;
179
+ const response = await $fetch("/subscription", {
180
+ method: "GET",
181
+ query: { customerId }
182
+ });
183
+ return response;
184
+ },
185
+ { autoFetch: false }
186
+ );
187
+ const $plans = asyncAtom(
188
+ async () => {
189
+ const response = await $fetch("/plans", {
190
+ method: "GET"
191
+ });
192
+ return response.plans;
193
+ },
194
+ { autoFetch: true }
195
+ );
196
+ return {
197
+ // Atoms
198
+ $customer,
199
+ $subscription,
200
+ $plans,
201
+ // API methods (typed wrapper around proxy)
202
+ customer: {
203
+ async get(options) {
204
+ return $fetch("/customer", { method: "GET", query: options.query });
205
+ },
206
+ async create(options) {
207
+ return $fetch("/customer", { method: "POST", body: options.body });
208
+ }
209
+ },
210
+ plans: {
211
+ async list() {
212
+ return $fetch("/plans", { method: "GET" });
213
+ }
214
+ },
215
+ plan: {
216
+ async get(options) {
217
+ return $fetch("/plan", { method: "GET", query: options.query });
218
+ }
219
+ },
220
+ subscription: {
221
+ async get(options) {
222
+ return $fetch("/subscription", { method: "GET", query: options.query });
223
+ },
224
+ async create(options) {
225
+ return $fetch("/subscription", { method: "POST", body: options.body });
226
+ },
227
+ async cancel(options) {
228
+ return $fetch("/subscription/cancel", {
229
+ method: "POST",
230
+ body: options.body
231
+ });
232
+ }
233
+ },
234
+ health: {
235
+ async get() {
236
+ return $fetch("/health", { method: "GET" });
237
+ }
238
+ },
239
+ // Utility methods
240
+ setCustomerId(customerId) {
241
+ customerIdAtom.set(customerId);
242
+ $customer.refresh();
243
+ $subscription.refresh();
244
+ },
245
+ async refresh() {
246
+ await Promise.all([
247
+ $customer.refresh(),
248
+ $subscription.refresh(),
249
+ $plans.refresh()
250
+ ]);
251
+ }
252
+ };
253
+ }
254
+
255
+ export { asyncAtom, atom, computed, createBillingClient, createFetch, createProxy };
256
+ //# sourceMappingURL=index.js.map
257
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/atoms.ts","../../src/client/proxy.ts","../../src/client/vanilla.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AsyncAtom, Atom } from \"./types\";\n\n/**\n * Create a simple atom for reactive state\n */\nexport function atom<T>(initialValue: T): Atom<T> {\n let value = initialValue;\n const listeners = new Set<(value: T) => void>();\n\n return {\n get() {\n return value;\n },\n\n set(newValue: T) {\n value = newValue;\n for (const listener of listeners) {\n listener(value);\n }\n },\n\n subscribe(callback: (value: T) => void) {\n listeners.add(callback);\n // Call immediately with current value\n callback(value);\n // Return unsubscribe function\n return () => {\n listeners.delete(callback);\n };\n },\n };\n}\n\n/**\n * Create an async atom that fetches data\n */\nexport function asyncAtom<T>(\n fetcher: () => Promise<T>,\n options: { autoFetch?: boolean } = {},\n): AsyncAtom<T> {\n const valueAtom = atom<T | null>(null);\n const loadingAtom = atom(false);\n const errorAtom = atom<Error | null>(null);\n\n const refresh = async () => {\n loadingAtom.set(true);\n errorAtom.set(null);\n\n try {\n const data = await fetcher();\n valueAtom.set(data);\n } catch (err) {\n errorAtom.set(err instanceof Error ? err : new Error(String(err)));\n } finally {\n loadingAtom.set(false);\n }\n };\n\n // Auto-fetch on creation if enabled\n if (options.autoFetch !== false) {\n refresh();\n }\n\n return {\n get() {\n return valueAtom.get();\n },\n\n isLoading() {\n return loadingAtom.get();\n },\n\n error() {\n return errorAtom.get();\n },\n\n refresh,\n\n subscribe(callback: (value: T | null) => void) {\n return valueAtom.subscribe(callback);\n },\n };\n}\n\n/**\n * Computed atom that derives from other atoms\n */\nexport function computed<T, R>(\n sourceAtom: Atom<T>,\n transform: (value: T) => R,\n): Atom<R> {\n const computedAtom = atom(transform(sourceAtom.get()));\n\n sourceAtom.subscribe((value) => {\n computedAtom.set(transform(value));\n });\n\n return {\n get() {\n return computedAtom.get();\n },\n set() {\n throw new Error(\"Cannot set a computed atom directly\");\n },\n subscribe: computedAtom.subscribe,\n };\n}\n","import type { ClientConfig } from \"./types\";\n\n/**\n * HTTP methods\n */\ntype HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\n/**\n * Fetch options\n */\ninterface FetchOptions {\n method?: HttpMethod;\n body?: unknown;\n query?: Record<string, string | undefined>;\n headers?: Record<string, string>;\n}\n\n/**\n * Create a configured fetch function\n */\nexport function createFetch(config: ClientConfig = {}) {\n const baseFetch = config.fetch ?? fetch;\n const baseURL = config.baseURL ?? \"/api/billing\";\n\n return async <T>(path: string, options: FetchOptions = {}): Promise<T> => {\n const method = options.method ?? \"GET\";\n let url = `${baseURL}${path}`;\n\n // Add query params\n if (options.query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(options.query)) {\n if (value !== undefined) {\n params.set(key, value);\n }\n }\n const queryString = params.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n ...options.headers,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n credentials: config.credentials ?? \"include\",\n };\n\n if (options.body && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await baseFetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorData = (await response\n .json()\n .catch(() => ({ error: { message: \"Unknown error\" } }))) as {\n error?: { message?: string };\n };\n throw new Error(\n errorData?.error?.message ?? `Request failed: ${response.status}`,\n );\n }\n\n return response.json() as Promise<T>;\n };\n}\n\n/**\n * Path segments for the proxy\n */\ntype PathSegment = string;\n\n/**\n * Create a proxy that converts method calls to API requests\n *\n * @example\n * ```typescript\n * const api = createProxy($fetch);\n * await api.customer.get({ query: { externalId: \"123\" } });\n * await api.plans.list();\n * ```\n */\nexport function createProxy<T extends ReturnType<typeof createFetch>>(\n $fetch: T,\n pathMethods: Record<string, HttpMethod> = {},\n): Record<string, unknown> {\n // Default path methods\n const _methods: Record<string, HttpMethod> = {\n \"/customer:GET\": \"GET\",\n \"/customer:POST\": \"POST\",\n \"/plans:GET\": \"GET\",\n \"/plan:GET\": \"GET\",\n \"/subscription:GET\": \"GET\",\n \"/health:GET\": \"GET\",\n ...pathMethods,\n };\n\n function createNestedProxy(segments: PathSegment[]): unknown {\n return new Proxy(() => {}, {\n get(_, prop: string) {\n // Handle special methods\n if (prop === \"then\" || prop === \"catch\" || prop === \"finally\") {\n return undefined;\n }\n\n // Add segment and return nested proxy\n return createNestedProxy([...segments, prop]);\n },\n\n apply(_, __, args: unknown[]) {\n // Convert segments to path\n // e.g., [\"customer\", \"get\"] -> \"/customer\" with GET method\n const lastSegment = segments[segments.length - 1] ?? \"\";\n const pathSegments = segments.slice(0, -1);\n\n // Determine method from last segment or default\n let method: HttpMethod = \"GET\";\n if (lastSegment === \"get\" || lastSegment === \"list\") {\n method = \"GET\";\n } else if (lastSegment === \"create\" || lastSegment === \"post\") {\n method = \"POST\";\n } else if (lastSegment === \"update\" || lastSegment === \"put\") {\n method = \"PUT\";\n } else if (lastSegment === \"patch\") {\n method = \"PATCH\";\n } else if (lastSegment === \"delete\" || lastSegment === \"remove\") {\n method = \"DELETE\";\n } else {\n // If last segment isn't a method, include it in path\n pathSegments.push(lastSegment);\n }\n\n // Build path\n const path =\n \"/\" +\n pathSegments\n .join(\"/\")\n .replace(/([A-Z])/g, \"-$1\")\n .toLowerCase();\n\n // Get options from args\n const options = (args[0] as FetchOptions) ?? {};\n\n return $fetch(path, { ...options, method });\n },\n });\n }\n\n return createNestedProxy([]) as Record<string, unknown>;\n}\n","import type { Customer, Plan } from \"../types/models\";\nimport { asyncAtom, atom } from \"./atoms\";\nimport { createFetch } from \"./proxy\";\nimport type {\n AsyncAtom,\n CancelSubscriptionInput,\n CancelSubscriptionResponse,\n ClientConfig,\n CreateSubscriptionInput,\n CreateSubscriptionResponse,\n HealthResponse,\n SubscriptionResponse,\n} from \"./types\";\n\n/**\n * Billing client interface\n */\nexport interface BillingClient {\n // Reactive atoms\n $customer: AsyncAtom<Customer | null>;\n $subscription: AsyncAtom<SubscriptionResponse | null>;\n $plans: AsyncAtom<Plan[]>;\n\n // API methods\n customer: {\n get(options: {\n query: { externalId: string };\n }): Promise<{ customer: Customer | null }>;\n create(options: {\n body: { externalId: string; email: string; name?: string };\n }): Promise<{ customer: Customer }>;\n };\n\n plans: {\n list(): Promise<{ plans: Plan[] }>;\n };\n\n plan: {\n get(options: {\n query: { id?: string; code?: string };\n }): Promise<{ plan: Plan | null; prices: unknown[] }>;\n };\n\n subscription: {\n get(options: {\n query: { customerId: string };\n }): Promise<SubscriptionResponse>;\n create(options: {\n body: CreateSubscriptionInput;\n }): Promise<CreateSubscriptionResponse>;\n cancel(options: {\n body: CancelSubscriptionInput;\n }): Promise<CancelSubscriptionResponse>;\n };\n\n health: {\n get(): Promise<HealthResponse>;\n };\n\n // Utility methods\n setCustomerId(customerId: string): void;\n refresh(): Promise<void>;\n}\n\n/**\n * Create a billing client\n *\n * @example\n * ```typescript\n * import { createBillingClient } from \"@billsdk/core/client\";\n *\n * // Uses default baseURL: \"/api/billing\"\n * const billing = createBillingClient();\n *\n * // Set current customer\n * billing.setCustomerId(\"user_123\");\n *\n * // Reactive state\n * billing.$customer.subscribe((customer) => {\n * console.log(\"Customer:\", customer);\n * });\n *\n * // Direct API calls\n * const plans = await billing.plans.list();\n * ```\n */\nexport function createBillingClient(config: ClientConfig = {}): BillingClient {\n const $fetch = createFetch(config);\n\n // Current customer ID atom\n const customerIdAtom = atom<string | null>(null);\n\n // Async atoms for reactive state\n const $customer = asyncAtom<Customer | null>(\n async () => {\n const customerId = customerIdAtom.get();\n if (!customerId) return null;\n\n const response = await $fetch<{ customer: Customer | null }>(\n \"/customer\",\n {\n method: \"GET\",\n query: { externalId: customerId },\n },\n );\n return response.customer;\n },\n { autoFetch: false },\n );\n\n const $subscription = asyncAtom<SubscriptionResponse | null>(\n async () => {\n const customerId = customerIdAtom.get();\n if (!customerId) return null;\n\n const response = await $fetch<SubscriptionResponse>(\"/subscription\", {\n method: \"GET\",\n query: { customerId },\n });\n return response;\n },\n { autoFetch: false },\n );\n\n const $plans = asyncAtom<Plan[]>(\n async () => {\n const response = await $fetch<{ plans: Plan[] }>(\"/plans\", {\n method: \"GET\",\n });\n return response.plans;\n },\n { autoFetch: true },\n );\n\n return {\n // Atoms\n $customer,\n $subscription,\n $plans,\n\n // API methods (typed wrapper around proxy)\n customer: {\n async get(options) {\n return $fetch(\"/customer\", { method: \"GET\", query: options.query });\n },\n async create(options) {\n return $fetch(\"/customer\", { method: \"POST\", body: options.body });\n },\n },\n\n plans: {\n async list() {\n return $fetch(\"/plans\", { method: \"GET\" });\n },\n },\n\n plan: {\n async get(options) {\n return $fetch(\"/plan\", { method: \"GET\", query: options.query });\n },\n },\n\n subscription: {\n async get(options) {\n return $fetch(\"/subscription\", { method: \"GET\", query: options.query });\n },\n async create(options) {\n return $fetch(\"/subscription\", { method: \"POST\", body: options.body });\n },\n async cancel(options) {\n return $fetch(\"/subscription/cancel\", {\n method: \"POST\",\n body: options.body,\n });\n },\n },\n\n health: {\n async get() {\n return $fetch(\"/health\", { method: \"GET\" });\n },\n },\n\n // Utility methods\n setCustomerId(customerId: string) {\n customerIdAtom.set(customerId);\n // Refresh customer-dependent atoms\n $customer.refresh();\n $subscription.refresh();\n },\n\n async refresh() {\n await Promise.all([\n $customer.refresh(),\n $subscription.refresh(),\n $plans.refresh(),\n ]);\n },\n };\n}\n\nexport default createBillingClient;\n"]}
@@ -0,0 +1,120 @@
1
+ import { Customer, Plan } from '@billsdk/core/types';
2
+ import { A as AsyncAtom, a as Atom, S as SubscriptionResponse, C as CreateSubscriptionInput, b as CreateSubscriptionResponse, c as CancelSubscriptionInput, d as CancelSubscriptionResponse, H as HealthResponse, e as ClientConfig } from '../../types-Ofy1HBSd.js';
3
+ export { f as ApiResponse, g as CustomerWithSubscription } from '../../types-Ofy1HBSd.js';
4
+
5
+ /**
6
+ * Hook to subscribe to an atom in React
7
+ * Similar to nanostores' useStore
8
+ */
9
+ declare function useStore<T>(atom: Atom<T>): T;
10
+ /**
11
+ * Hook to subscribe to an async atom in React
12
+ * Returns { data, isLoading, error, refresh }
13
+ */
14
+ declare function useAsyncStore<T>(atom: AsyncAtom<T>): {
15
+ data: T | null;
16
+ isLoading: boolean;
17
+ error: Error | null;
18
+ refresh: () => Promise<void>;
19
+ };
20
+
21
+ /**
22
+ * React billing client interface
23
+ */
24
+ interface BillingClientReact {
25
+ useCustomer: () => {
26
+ data: Customer | null;
27
+ isLoading: boolean;
28
+ error: Error | null;
29
+ refresh: () => Promise<void>;
30
+ };
31
+ useSubscription: () => {
32
+ data: SubscriptionResponse | null;
33
+ isLoading: boolean;
34
+ error: Error | null;
35
+ refresh: () => Promise<void>;
36
+ };
37
+ usePlans: () => {
38
+ data: Plan[];
39
+ isLoading: boolean;
40
+ error: Error | null;
41
+ refresh: () => Promise<void>;
42
+ };
43
+ $customer: AsyncAtom<Customer | null>;
44
+ $subscription: AsyncAtom<SubscriptionResponse | null>;
45
+ $plans: AsyncAtom<Plan[]>;
46
+ customer: {
47
+ get(options: {
48
+ query: {
49
+ externalId: string;
50
+ };
51
+ }): Promise<{
52
+ customer: Customer | null;
53
+ }>;
54
+ create(options: {
55
+ body: {
56
+ externalId: string;
57
+ email: string;
58
+ name?: string;
59
+ };
60
+ }): Promise<{
61
+ customer: Customer;
62
+ }>;
63
+ };
64
+ plans: {
65
+ list(): Promise<{
66
+ plans: Plan[];
67
+ }>;
68
+ };
69
+ plan: {
70
+ get(options: {
71
+ query: {
72
+ id?: string;
73
+ code?: string;
74
+ };
75
+ }): Promise<{
76
+ plan: Plan | null;
77
+ prices: unknown[];
78
+ }>;
79
+ };
80
+ subscription: {
81
+ get(options: {
82
+ query: {
83
+ customerId: string;
84
+ };
85
+ }): Promise<SubscriptionResponse>;
86
+ create(options: {
87
+ body: CreateSubscriptionInput;
88
+ }): Promise<CreateSubscriptionResponse>;
89
+ cancel(options: {
90
+ body: CancelSubscriptionInput;
91
+ }): Promise<CancelSubscriptionResponse>;
92
+ };
93
+ health: {
94
+ get(): Promise<HealthResponse>;
95
+ };
96
+ setCustomerId(customerId: string): void;
97
+ refresh(): Promise<void>;
98
+ }
99
+ /**
100
+ * Create a React billing client
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * import { createBillingClient } from "@billsdk/core/react";
105
+ *
106
+ * // Uses default baseURL: "/api/billing"
107
+ * export const billing = createBillingClient();
108
+ *
109
+ * // In a component
110
+ * function Dashboard() {
111
+ * const { data: subscription, isLoading } = billing.useSubscription();
112
+ *
113
+ * if (isLoading) return <Loading />;
114
+ * return <div>Plan: {subscription?.plan?.name}</div>;
115
+ * }
116
+ * ```
117
+ */
118
+ declare function createBillingClient(config?: ClientConfig): BillingClientReact;
119
+
120
+ export { AsyncAtom, Atom, type BillingClientReact, CancelSubscriptionInput, CancelSubscriptionResponse, ClientConfig, CreateSubscriptionInput, CreateSubscriptionResponse, HealthResponse, SubscriptionResponse, createBillingClient, useAsyncStore, useStore };