billsdk 0.0.1 → 0.1.0
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/dist/adapters/drizzle/index.d.ts +3 -0
- package/dist/adapters/drizzle/index.js +3 -0
- package/dist/adapters/drizzle/index.js.map +1 -0
- package/dist/adapters/memory-adapter/index.d.ts +1 -0
- package/dist/adapters/memory-adapter/index.js +3 -0
- package/dist/adapters/memory-adapter/index.js.map +1 -0
- package/dist/adapters/payment/index.d.ts +1 -0
- package/dist/adapters/payment/index.js +3 -0
- package/dist/adapters/payment/index.js.map +1 -0
- package/dist/client/index.d.ts +133 -0
- package/dist/client/index.js +257 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/react/index.d.ts +120 -0
- package/dist/client/react/index.js +248 -0
- package/dist/client/react/index.js.map +1 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.js +1293 -29
- package/dist/index.js.map +1 -1
- package/dist/integrations/next.d.ts +31 -0
- package/dist/integrations/next.js +15 -0
- package/dist/integrations/next.js.map +1 -0
- package/dist/types-Ofy1HBSd.d.ts +113 -0
- package/package.json +90 -23
- package/README.md +0 -22
- package/dist/index.d.mts +0 -8
- package/dist/index.mjs +0 -10
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { memoryAdapter } from '@billsdk/memory-adapter';
|
|
@@ -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 @@
|
|
|
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 };
|