@velobaseai/billing 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Velobase
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,282 @@
1
+ # @velobaseai/billing
2
+
3
+ Official Velobase Billing SDK for JavaScript and TypeScript.
4
+
5
+ - Zero runtime dependencies — uses native `fetch`
6
+ - Works with Node.js 18+, Deno, Bun, and Cloudflare Workers
7
+ - ESM and CommonJS dual build with full TypeScript declarations
8
+ - Automatic retries with exponential backoff
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @velobaseai/billing
14
+ # or
15
+ pnpm add @velobaseai/billing
16
+ # or
17
+ yarn add @velobaseai/billing
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import Velobase from '@velobaseai/billing';
24
+
25
+ const vb = new Velobase({ apiKey: 'vb_live_xxx' });
26
+
27
+ // 1. Deposit credits to a customer (creates the customer if new)
28
+ const deposit = await vb.customers.deposit({
29
+ customerId: 'user_123',
30
+ amount: 1000,
31
+ });
32
+
33
+ // 2. Check balance
34
+ const customer = await vb.customers.get('user_123');
35
+ console.log(customer.balance.available); // 1000
36
+
37
+ // 3. Freeze credits before doing work
38
+ const freeze = await vb.billing.freeze({
39
+ customerId: 'user_123',
40
+ amount: 50,
41
+ businessId: 'job_abc',
42
+ });
43
+
44
+ // 4a. Job succeeded — consume (supports partial)
45
+ const consume = await vb.billing.consume({
46
+ businessId: 'job_abc',
47
+ actualAmount: 32, // only charge 32, return 18
48
+ });
49
+
50
+ // 4b. Or if the job failed — unfreeze to return all
51
+ const unfreeze = await vb.billing.unfreeze({
52
+ businessId: 'job_abc',
53
+ });
54
+ ```
55
+
56
+ ## How It Works
57
+
58
+ Velobase Billing uses a **freeze-then-consume** pattern to safely manage credits:
59
+
60
+ ```
61
+ deposit → freeze → consume (normal flow)
62
+ → unfreeze (failure/cancellation)
63
+ ```
64
+
65
+ 1. **Deposit** — Add credits to a customer's account. Creates the customer automatically on first deposit.
66
+ 2. **Freeze** — Pre-authorize an amount before performing work. The frozen credits are deducted from `available` but not yet `used`. Each freeze is identified by a unique `businessId` you provide.
67
+ 3. **Consume** — After the work is done, settle the frozen amount. You can pass `actualAmount` to charge less than what was frozen; the difference is automatically returned.
68
+ 4. **Unfreeze** — If the work fails or is cancelled, release the full frozen amount back to the customer.
69
+
70
+ All write operations are **idempotent** — repeating the same `businessId` (freeze/consume/unfreeze) or `idempotencyKey` (deposit) returns the original result without double-charging.
71
+
72
+ ## Configuration
73
+
74
+ ```typescript
75
+ const vb = new Velobase({
76
+ apiKey: 'vb_live_xxx', // Required. Your Velobase API key.
77
+ baseUrl: 'https://api.velobase.io', // Optional. Override the API endpoint.
78
+ timeout: 30000, // Optional. Request timeout in ms (default: 30s).
79
+ maxRetries: 2, // Optional. Retry count on 5xx/network errors (default: 2).
80
+ });
81
+ ```
82
+
83
+ ## Usage Examples
84
+
85
+ ### Deposit with idempotency
86
+
87
+ ```typescript
88
+ // Safe to retry — the second call returns the same result without double-charging
89
+ const result = await vb.customers.deposit({
90
+ customerId: 'user_123',
91
+ amount: 500,
92
+ idempotencyKey: 'order_abc_payment',
93
+ description: 'Purchase of 500 credits',
94
+ });
95
+
96
+ console.log(result.addedAmount); // 500
97
+ console.log(result.isIdempotentReplay); // false on first call, true on retries
98
+ ```
99
+
100
+ ### Deposit with customer metadata
101
+
102
+ ```typescript
103
+ const result = await vb.customers.deposit({
104
+ customerId: 'user_123',
105
+ amount: 1000,
106
+ name: 'Alice',
107
+ email: 'alice@example.com',
108
+ metadata: { plan: 'pro', source: 'stripe' },
109
+ });
110
+ ```
111
+
112
+ ### Full billing flow
113
+
114
+ ```typescript
115
+ const CUSTOMER = 'user_123';
116
+ const JOB_ID = 'video_gen_001';
117
+
118
+ // Check balance before starting
119
+ const before = await vb.customers.get(CUSTOMER);
120
+ console.log('Available:', before.balance.available);
121
+
122
+ // Freeze the estimated cost
123
+ await vb.billing.freeze({
124
+ customerId: CUSTOMER,
125
+ amount: 100,
126
+ businessId: JOB_ID,
127
+ businessType: 'video_generation',
128
+ description: '1080p video, ~60s',
129
+ });
130
+
131
+ // ... do the work ...
132
+
133
+ // Settle with the actual cost (partial consumption)
134
+ const result = await vb.billing.consume({
135
+ businessId: JOB_ID,
136
+ actualAmount: 73,
137
+ });
138
+ console.log('Charged:', result.consumedAmount); // 73
139
+ console.log('Returned:', result.returnedAmount); // 27
140
+
141
+ // Verify final balance
142
+ const after = await vb.customers.get(CUSTOMER);
143
+ console.log('Available:', after.balance.available);
144
+ ```
145
+
146
+ ### Customer balance structure
147
+
148
+ ```typescript
149
+ const customer = await vb.customers.get('user_123');
150
+
151
+ // Aggregate balance across all accounts
152
+ customer.balance.total; // total deposited
153
+ customer.balance.used; // total consumed
154
+ customer.balance.frozen; // currently frozen (pending)
155
+ customer.balance.available; // total - used - frozen
156
+
157
+ // Individual accounts (e.g., different credit types/expiry)
158
+ for (const account of customer.accounts) {
159
+ console.log(account.accountType); // 'CREDIT'
160
+ console.log(account.subAccountType); // 'DEFAULT'
161
+ console.log(account.available);
162
+ console.log(account.expiresAt); // null or ISO date string
163
+ }
164
+ ```
165
+
166
+ ## API Reference
167
+
168
+ ### `vb.customers.deposit(params): Promise<DepositResponse>`
169
+
170
+ Deposit credits. Creates the customer if they don't exist.
171
+
172
+ | Parameter | Type | Required | Description |
173
+ |---|---|---|---|
174
+ | `customerId` | `string` | Yes | Your unique customer identifier |
175
+ | `amount` | `number` | Yes | Amount to deposit (must be > 0) |
176
+ | `idempotencyKey` | `string` | No | Prevents duplicate deposits on retry |
177
+ | `name` | `string \| null` | No | Customer display name |
178
+ | `email` | `string \| null` | No | Customer email |
179
+ | `metadata` | `object` | No | Arbitrary key-value metadata |
180
+ | `description` | `string` | No | Description for the deposit |
181
+
182
+ **Returns:** `{ customerId, accountId, totalAmount, addedAmount, recordId, isIdempotentReplay }`
183
+
184
+ ### `vb.customers.get(customerId): Promise<CustomerResponse>`
185
+
186
+ Retrieve a customer's balance and account details.
187
+
188
+ **Returns:** `{ id, name, email, metadata, balance, accounts, createdAt }`
189
+
190
+ ### `vb.billing.freeze(params): Promise<FreezeResponse>`
191
+
192
+ Freeze credits before performing work.
193
+
194
+ | Parameter | Type | Required | Description |
195
+ |---|---|---|---|
196
+ | `customerId` | `string` | Yes | Customer identifier |
197
+ | `amount` | `number` | Yes | Amount to freeze (must be > 0) |
198
+ | `businessId` | `string` | Yes | Your unique ID for this operation (idempotency key) |
199
+ | `businessType` | `string` | No | Category label (e.g., `'video_generation'`) |
200
+ | `description` | `string` | No | Human-readable description |
201
+
202
+ **Returns:** `{ businessId, frozenAmount, freezeDetails, isIdempotentReplay }`
203
+
204
+ ### `vb.billing.consume(params): Promise<ConsumeResponse>`
205
+
206
+ Settle a frozen amount. Supports partial consumption.
207
+
208
+ | Parameter | Type | Required | Description |
209
+ |---|---|---|---|
210
+ | `businessId` | `string` | Yes | The `businessId` from the freeze |
211
+ | `actualAmount` | `number` | No | Actual amount to charge. Defaults to full frozen amount. |
212
+
213
+ **Returns:** `{ businessId, consumedAmount, returnedAmount, consumeDetails, consumedAt, isIdempotentReplay }`
214
+
215
+ ### `vb.billing.unfreeze(params): Promise<UnfreezeResponse>`
216
+
217
+ Release a frozen amount back to the customer.
218
+
219
+ | Parameter | Type | Required | Description |
220
+ |---|---|---|---|
221
+ | `businessId` | `string` | Yes | The `businessId` from the freeze |
222
+
223
+ **Returns:** `{ businessId, unfrozenAmount, unfreezeDetails, unfrozenAt, isIdempotentReplay }`
224
+
225
+ ## Error Handling
226
+
227
+ All API errors throw typed exceptions that extend `VelobaseError`:
228
+
229
+ ```typescript
230
+ import {
231
+ VelobaseError,
232
+ VelobaseAuthenticationError,
233
+ VelobaseValidationError,
234
+ VelobaseNotFoundError,
235
+ } from '@velobaseai/billing';
236
+
237
+ try {
238
+ await vb.billing.freeze({
239
+ customerId: 'user_123',
240
+ amount: 999999,
241
+ businessId: 'job_xyz',
242
+ });
243
+ } catch (err) {
244
+ if (err instanceof VelobaseValidationError) {
245
+ // 400 — bad request or insufficient balance
246
+ console.error(err.message); // "insufficient balance"
247
+ } else if (err instanceof VelobaseAuthenticationError) {
248
+ // 401 — invalid or missing API key
249
+ } else if (err instanceof VelobaseNotFoundError) {
250
+ // 404 — customer not found
251
+ } else if (err instanceof VelobaseError) {
252
+ // catch-all for other API errors
253
+ console.error(err.status, err.type, err.message);
254
+ }
255
+ }
256
+ ```
257
+
258
+ | Error Class | HTTP Status | When |
259
+ |---|---|---|
260
+ | `VelobaseAuthenticationError` | 401 | Invalid or missing API key |
261
+ | `VelobaseValidationError` | 400 | Bad params, insufficient balance |
262
+ | `VelobaseNotFoundError` | 404 | Customer or resource not found |
263
+ | `VelobaseConflictError` | 409 | Conflicting operation |
264
+ | `VelobaseInternalError` | 500 | Server-side error (auto-retried) |
265
+
266
+ ## Retries
267
+
268
+ The SDK automatically retries on 5xx errors and network failures with exponential backoff (500ms, 1s, 2s..., capped at 5s). Retries are safe because all Velobase write operations are idempotent.
269
+
270
+ 4xx errors (validation, auth, not found) are never retried.
271
+
272
+ ## CommonJS
273
+
274
+ ```javascript
275
+ const { Velobase } = require('@velobaseai/billing');
276
+
277
+ const vb = new Velobase({ apiKey: 'vb_live_xxx' });
278
+ ```
279
+
280
+ ## License
281
+
282
+ MIT
@@ -0,0 +1,140 @@
1
+ interface HttpClientOptions {
2
+ baseUrl: string;
3
+ apiKey: string;
4
+ timeout: number;
5
+ maxRetries: number;
6
+ }
7
+ declare class HttpClient {
8
+ private baseUrl;
9
+ private apiKey;
10
+ private timeout;
11
+ private maxRetries;
12
+ constructor(opts: HttpClientOptions);
13
+ request<T>(method: string, path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
14
+ }
15
+
16
+ interface FreezeParams {
17
+ customerId: string;
18
+ amount: number;
19
+ businessId: string;
20
+ businessType?: string;
21
+ description?: string;
22
+ }
23
+ interface FreezeResponse {
24
+ businessId: string;
25
+ frozenAmount: number;
26
+ freezeDetails: unknown[];
27
+ isIdempotentReplay: boolean;
28
+ }
29
+ interface ConsumeParams {
30
+ businessId: string;
31
+ actualAmount?: number;
32
+ }
33
+ interface ConsumeResponse {
34
+ businessId: string;
35
+ consumedAmount: number;
36
+ returnedAmount?: number;
37
+ consumeDetails: unknown[];
38
+ consumedAt: string;
39
+ isIdempotentReplay: boolean;
40
+ }
41
+ interface UnfreezeParams {
42
+ businessId: string;
43
+ }
44
+ interface UnfreezeResponse {
45
+ businessId: string;
46
+ unfrozenAmount: number;
47
+ unfreezeDetails: unknown[];
48
+ unfrozenAt: string;
49
+ isIdempotentReplay: boolean;
50
+ }
51
+ interface DepositParams {
52
+ customerId: string;
53
+ amount: number;
54
+ idempotencyKey?: string;
55
+ name?: string | null;
56
+ email?: string | null;
57
+ metadata?: Record<string, unknown>;
58
+ description?: string;
59
+ }
60
+ interface DepositResponse {
61
+ customerId: string;
62
+ accountId: string;
63
+ totalAmount: number;
64
+ addedAmount: number;
65
+ recordId: string;
66
+ isIdempotentReplay: boolean;
67
+ }
68
+ interface CustomerBalance {
69
+ total: number;
70
+ used: number;
71
+ frozen: number;
72
+ available: number;
73
+ }
74
+ interface CustomerAccount {
75
+ accountType: string;
76
+ subAccountType: string;
77
+ total: number;
78
+ used: number;
79
+ frozen: number;
80
+ available: number;
81
+ startsAt: string | null;
82
+ expiresAt: string | null;
83
+ }
84
+ interface CustomerResponse {
85
+ id: string;
86
+ name: string | null;
87
+ email: string | null;
88
+ metadata: Record<string, unknown> | null;
89
+ balance: CustomerBalance;
90
+ accounts: CustomerAccount[];
91
+ createdAt: string;
92
+ }
93
+ interface VelobaseOptions {
94
+ apiKey: string;
95
+ baseUrl?: string;
96
+ timeout?: number;
97
+ maxRetries?: number;
98
+ }
99
+
100
+ declare class BillingResource {
101
+ private http;
102
+ constructor(http: HttpClient);
103
+ freeze(params: FreezeParams): Promise<FreezeResponse>;
104
+ consume(params: ConsumeParams): Promise<ConsumeResponse>;
105
+ unfreeze(params: UnfreezeParams): Promise<UnfreezeResponse>;
106
+ }
107
+ declare class CustomersResource {
108
+ private http;
109
+ constructor(http: HttpClient);
110
+ deposit(params: DepositParams): Promise<DepositResponse>;
111
+ get(customerId: string): Promise<CustomerResponse>;
112
+ }
113
+ declare class Velobase {
114
+ readonly billing: BillingResource;
115
+ readonly customers: CustomersResource;
116
+ constructor(opts: VelobaseOptions);
117
+ }
118
+
119
+ declare class VelobaseError extends Error {
120
+ status: number;
121
+ type: string;
122
+ constructor(message: string, status: number, type: string);
123
+ }
124
+ declare class VelobaseAuthenticationError extends VelobaseError {
125
+ constructor(message: string);
126
+ }
127
+ declare class VelobaseValidationError extends VelobaseError {
128
+ constructor(message: string);
129
+ }
130
+ declare class VelobaseNotFoundError extends VelobaseError {
131
+ constructor(message: string);
132
+ }
133
+ declare class VelobaseConflictError extends VelobaseError {
134
+ constructor(message: string);
135
+ }
136
+ declare class VelobaseInternalError extends VelobaseError {
137
+ constructor(message: string);
138
+ }
139
+
140
+ export { type ConsumeParams, type ConsumeResponse, type CustomerAccount, type CustomerBalance, type CustomerResponse, type DepositParams, type DepositResponse, type FreezeParams, type FreezeResponse, type UnfreezeParams, type UnfreezeResponse, Velobase, VelobaseAuthenticationError, VelobaseConflictError, VelobaseError, VelobaseInternalError, VelobaseNotFoundError, type VelobaseOptions, VelobaseValidationError, Velobase as default };
@@ -0,0 +1,140 @@
1
+ interface HttpClientOptions {
2
+ baseUrl: string;
3
+ apiKey: string;
4
+ timeout: number;
5
+ maxRetries: number;
6
+ }
7
+ declare class HttpClient {
8
+ private baseUrl;
9
+ private apiKey;
10
+ private timeout;
11
+ private maxRetries;
12
+ constructor(opts: HttpClientOptions);
13
+ request<T>(method: string, path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
14
+ }
15
+
16
+ interface FreezeParams {
17
+ customerId: string;
18
+ amount: number;
19
+ businessId: string;
20
+ businessType?: string;
21
+ description?: string;
22
+ }
23
+ interface FreezeResponse {
24
+ businessId: string;
25
+ frozenAmount: number;
26
+ freezeDetails: unknown[];
27
+ isIdempotentReplay: boolean;
28
+ }
29
+ interface ConsumeParams {
30
+ businessId: string;
31
+ actualAmount?: number;
32
+ }
33
+ interface ConsumeResponse {
34
+ businessId: string;
35
+ consumedAmount: number;
36
+ returnedAmount?: number;
37
+ consumeDetails: unknown[];
38
+ consumedAt: string;
39
+ isIdempotentReplay: boolean;
40
+ }
41
+ interface UnfreezeParams {
42
+ businessId: string;
43
+ }
44
+ interface UnfreezeResponse {
45
+ businessId: string;
46
+ unfrozenAmount: number;
47
+ unfreezeDetails: unknown[];
48
+ unfrozenAt: string;
49
+ isIdempotentReplay: boolean;
50
+ }
51
+ interface DepositParams {
52
+ customerId: string;
53
+ amount: number;
54
+ idempotencyKey?: string;
55
+ name?: string | null;
56
+ email?: string | null;
57
+ metadata?: Record<string, unknown>;
58
+ description?: string;
59
+ }
60
+ interface DepositResponse {
61
+ customerId: string;
62
+ accountId: string;
63
+ totalAmount: number;
64
+ addedAmount: number;
65
+ recordId: string;
66
+ isIdempotentReplay: boolean;
67
+ }
68
+ interface CustomerBalance {
69
+ total: number;
70
+ used: number;
71
+ frozen: number;
72
+ available: number;
73
+ }
74
+ interface CustomerAccount {
75
+ accountType: string;
76
+ subAccountType: string;
77
+ total: number;
78
+ used: number;
79
+ frozen: number;
80
+ available: number;
81
+ startsAt: string | null;
82
+ expiresAt: string | null;
83
+ }
84
+ interface CustomerResponse {
85
+ id: string;
86
+ name: string | null;
87
+ email: string | null;
88
+ metadata: Record<string, unknown> | null;
89
+ balance: CustomerBalance;
90
+ accounts: CustomerAccount[];
91
+ createdAt: string;
92
+ }
93
+ interface VelobaseOptions {
94
+ apiKey: string;
95
+ baseUrl?: string;
96
+ timeout?: number;
97
+ maxRetries?: number;
98
+ }
99
+
100
+ declare class BillingResource {
101
+ private http;
102
+ constructor(http: HttpClient);
103
+ freeze(params: FreezeParams): Promise<FreezeResponse>;
104
+ consume(params: ConsumeParams): Promise<ConsumeResponse>;
105
+ unfreeze(params: UnfreezeParams): Promise<UnfreezeResponse>;
106
+ }
107
+ declare class CustomersResource {
108
+ private http;
109
+ constructor(http: HttpClient);
110
+ deposit(params: DepositParams): Promise<DepositResponse>;
111
+ get(customerId: string): Promise<CustomerResponse>;
112
+ }
113
+ declare class Velobase {
114
+ readonly billing: BillingResource;
115
+ readonly customers: CustomersResource;
116
+ constructor(opts: VelobaseOptions);
117
+ }
118
+
119
+ declare class VelobaseError extends Error {
120
+ status: number;
121
+ type: string;
122
+ constructor(message: string, status: number, type: string);
123
+ }
124
+ declare class VelobaseAuthenticationError extends VelobaseError {
125
+ constructor(message: string);
126
+ }
127
+ declare class VelobaseValidationError extends VelobaseError {
128
+ constructor(message: string);
129
+ }
130
+ declare class VelobaseNotFoundError extends VelobaseError {
131
+ constructor(message: string);
132
+ }
133
+ declare class VelobaseConflictError extends VelobaseError {
134
+ constructor(message: string);
135
+ }
136
+ declare class VelobaseInternalError extends VelobaseError {
137
+ constructor(message: string);
138
+ }
139
+
140
+ export { type ConsumeParams, type ConsumeResponse, type CustomerAccount, type CustomerBalance, type CustomerResponse, type DepositParams, type DepositResponse, type FreezeParams, type FreezeResponse, type UnfreezeParams, type UnfreezeResponse, Velobase, VelobaseAuthenticationError, VelobaseConflictError, VelobaseError, VelobaseInternalError, VelobaseNotFoundError, type VelobaseOptions, VelobaseValidationError, Velobase as default };
package/dist/index.js ADDED
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Velobase: () => Velobase,
24
+ VelobaseAuthenticationError: () => VelobaseAuthenticationError,
25
+ VelobaseConflictError: () => VelobaseConflictError,
26
+ VelobaseError: () => VelobaseError,
27
+ VelobaseInternalError: () => VelobaseInternalError,
28
+ VelobaseNotFoundError: () => VelobaseNotFoundError,
29
+ VelobaseValidationError: () => VelobaseValidationError,
30
+ default: () => Velobase
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/errors.ts
35
+ var VelobaseError = class extends Error {
36
+ status;
37
+ type;
38
+ constructor(message, status, type) {
39
+ super(message);
40
+ this.name = "VelobaseError";
41
+ this.status = status;
42
+ this.type = type;
43
+ }
44
+ };
45
+ var VelobaseAuthenticationError = class extends VelobaseError {
46
+ constructor(message) {
47
+ super(message, 401, "auth_error");
48
+ this.name = "VelobaseAuthenticationError";
49
+ }
50
+ };
51
+ var VelobaseValidationError = class extends VelobaseError {
52
+ constructor(message) {
53
+ super(message, 400, "validation_error");
54
+ this.name = "VelobaseValidationError";
55
+ }
56
+ };
57
+ var VelobaseNotFoundError = class extends VelobaseError {
58
+ constructor(message) {
59
+ super(message, 404, "not_found");
60
+ this.name = "VelobaseNotFoundError";
61
+ }
62
+ };
63
+ var VelobaseConflictError = class extends VelobaseError {
64
+ constructor(message) {
65
+ super(message, 409, "conflict");
66
+ this.name = "VelobaseConflictError";
67
+ }
68
+ };
69
+ var VelobaseInternalError = class extends VelobaseError {
70
+ constructor(message) {
71
+ super(message, 500, "server_error");
72
+ this.name = "VelobaseInternalError";
73
+ }
74
+ };
75
+
76
+ // src/http.ts
77
+ function toSnakeCase(str) {
78
+ return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
79
+ }
80
+ function toCamelCase(str) {
81
+ return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
82
+ }
83
+ function convertKeys(obj, converter) {
84
+ if (Array.isArray(obj)) {
85
+ return obj.map((item) => convertKeys(item, converter));
86
+ }
87
+ if (obj !== null && typeof obj === "object") {
88
+ const result = {};
89
+ for (const [key, value] of Object.entries(obj)) {
90
+ result[converter(key)] = convertKeys(value, converter);
91
+ }
92
+ return result;
93
+ }
94
+ return obj;
95
+ }
96
+ function toSnakeCaseKeys(obj) {
97
+ return convertKeys(obj, toSnakeCase);
98
+ }
99
+ function toCamelCaseKeys(obj) {
100
+ return convertKeys(obj, toCamelCase);
101
+ }
102
+ function isRetryable(status) {
103
+ return status >= 500 || status === 429;
104
+ }
105
+ function throwForStatus(status, message, type) {
106
+ switch (status) {
107
+ case 400:
108
+ throw new VelobaseValidationError(message);
109
+ case 401:
110
+ throw new VelobaseAuthenticationError(message);
111
+ case 404:
112
+ throw new VelobaseNotFoundError(message);
113
+ case 409:
114
+ throw new VelobaseConflictError(message);
115
+ case 500:
116
+ throw new VelobaseInternalError(message);
117
+ default:
118
+ throw new VelobaseError(message, status, type);
119
+ }
120
+ }
121
+ var HttpClient = class {
122
+ baseUrl;
123
+ apiKey;
124
+ timeout;
125
+ maxRetries;
126
+ constructor(opts) {
127
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
128
+ this.apiKey = opts.apiKey;
129
+ this.timeout = opts.timeout;
130
+ this.maxRetries = opts.maxRetries;
131
+ }
132
+ async request(method, path, body, headers) {
133
+ const url = `${this.baseUrl}${path}`;
134
+ let lastError;
135
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
136
+ if (attempt > 0) {
137
+ const delay = Math.min(500 * 2 ** (attempt - 1), 5e3);
138
+ await new Promise((r) => setTimeout(r, delay));
139
+ }
140
+ const controller = new AbortController();
141
+ const timer = setTimeout(() => controller.abort(), this.timeout);
142
+ try {
143
+ const res = await fetch(url, {
144
+ method,
145
+ headers: {
146
+ "Authorization": `Bearer ${this.apiKey}`,
147
+ "Content-Type": "application/json",
148
+ ...headers
149
+ },
150
+ body: body ? JSON.stringify(toSnakeCaseKeys(body)) : void 0,
151
+ signal: controller.signal
152
+ });
153
+ clearTimeout(timer);
154
+ if (!res.ok) {
155
+ const json2 = await res.json().catch(() => ({}));
156
+ const msg = json2.error?.message ?? `HTTP ${res.status}`;
157
+ const type = json2.error?.type ?? "unknown_error";
158
+ if (isRetryable(res.status) && attempt < this.maxRetries) {
159
+ lastError = new VelobaseError(msg, res.status, type);
160
+ continue;
161
+ }
162
+ throwForStatus(res.status, msg, type);
163
+ }
164
+ const json = await res.json();
165
+ return toCamelCaseKeys(json);
166
+ } catch (err) {
167
+ clearTimeout(timer);
168
+ if (err instanceof VelobaseError) {
169
+ throw err;
170
+ }
171
+ lastError = err;
172
+ if (attempt < this.maxRetries) {
173
+ continue;
174
+ }
175
+ throw new VelobaseError(
176
+ `Request failed: ${lastError.message}`,
177
+ 0,
178
+ "network_error"
179
+ );
180
+ }
181
+ }
182
+ throw lastError;
183
+ }
184
+ };
185
+
186
+ // src/client.ts
187
+ var DEFAULT_BASE_URL = "https://api.velobase.io";
188
+ var DEFAULT_TIMEOUT = 3e4;
189
+ var DEFAULT_MAX_RETRIES = 2;
190
+ var BillingResource = class {
191
+ constructor(http) {
192
+ this.http = http;
193
+ }
194
+ async freeze(params) {
195
+ return this.http.request(
196
+ "POST",
197
+ "/v1/billing/freeze",
198
+ params
199
+ );
200
+ }
201
+ async consume(params) {
202
+ return this.http.request(
203
+ "POST",
204
+ "/v1/billing/consume",
205
+ params
206
+ );
207
+ }
208
+ async unfreeze(params) {
209
+ return this.http.request(
210
+ "POST",
211
+ "/v1/billing/unfreeze",
212
+ params
213
+ );
214
+ }
215
+ };
216
+ var CustomersResource = class {
217
+ constructor(http) {
218
+ this.http = http;
219
+ }
220
+ async deposit(params) {
221
+ const headers = {};
222
+ if (params.idempotencyKey) {
223
+ headers["Idempotency-Key"] = params.idempotencyKey;
224
+ }
225
+ return this.http.request(
226
+ "POST",
227
+ "/v1/customers/deposit",
228
+ params,
229
+ headers
230
+ );
231
+ }
232
+ async get(customerId) {
233
+ return this.http.request(
234
+ "GET",
235
+ `/v1/customers/${encodeURIComponent(customerId)}`
236
+ );
237
+ }
238
+ };
239
+ var Velobase = class {
240
+ billing;
241
+ customers;
242
+ constructor(opts) {
243
+ if (!opts.apiKey) {
244
+ throw new Error(
245
+ "apiKey is required. Get your API key at https://velobase.io"
246
+ );
247
+ }
248
+ const http = new HttpClient({
249
+ baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,
250
+ apiKey: opts.apiKey,
251
+ timeout: opts.timeout ?? DEFAULT_TIMEOUT,
252
+ maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES
253
+ });
254
+ this.billing = new BillingResource(http);
255
+ this.customers = new CustomersResource(http);
256
+ }
257
+ };
258
+ // Annotate the CommonJS export names for ESM import in node:
259
+ 0 && (module.exports = {
260
+ Velobase,
261
+ VelobaseAuthenticationError,
262
+ VelobaseConflictError,
263
+ VelobaseError,
264
+ VelobaseInternalError,
265
+ VelobaseNotFoundError,
266
+ VelobaseValidationError
267
+ });
268
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["export { Velobase } from \"./client\";\nexport {\n VelobaseError,\n VelobaseAuthenticationError,\n VelobaseValidationError,\n VelobaseNotFoundError,\n VelobaseConflictError,\n VelobaseInternalError,\n} from \"./errors\";\nexport type {\n VelobaseOptions,\n FreezeParams,\n FreezeResponse,\n ConsumeParams,\n ConsumeResponse,\n UnfreezeParams,\n UnfreezeResponse,\n DepositParams,\n DepositResponse,\n CustomerBalance,\n CustomerAccount,\n CustomerResponse,\n} from \"./types\";\n\n// default export for convenience\nexport { Velobase as default } from \"./client\";\n","export class VelobaseError extends Error {\n status: number;\n type: string;\n\n constructor(message: string, status: number, type: string) {\n super(message);\n this.name = \"VelobaseError\";\n this.status = status;\n this.type = type;\n }\n}\n\nexport class VelobaseAuthenticationError extends VelobaseError {\n constructor(message: string) {\n super(message, 401, \"auth_error\");\n this.name = \"VelobaseAuthenticationError\";\n }\n}\n\nexport class VelobaseValidationError extends VelobaseError {\n constructor(message: string) {\n super(message, 400, \"validation_error\");\n this.name = \"VelobaseValidationError\";\n }\n}\n\nexport class VelobaseNotFoundError extends VelobaseError {\n constructor(message: string) {\n super(message, 404, \"not_found\");\n this.name = \"VelobaseNotFoundError\";\n }\n}\n\nexport class VelobaseConflictError extends VelobaseError {\n constructor(message: string) {\n super(message, 409, \"conflict\");\n this.name = \"VelobaseConflictError\";\n }\n}\n\nexport class VelobaseInternalError extends VelobaseError {\n constructor(message: string) {\n super(message, 500, \"server_error\");\n this.name = \"VelobaseInternalError\";\n }\n}\n","import {\n VelobaseAuthenticationError,\n VelobaseConflictError,\n VelobaseError,\n VelobaseInternalError,\n VelobaseNotFoundError,\n VelobaseValidationError,\n} from \"./errors\";\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries: number;\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction convertKeys(\n obj: unknown,\n converter: (key: string) => string,\n): unknown {\n if (Array.isArray(obj)) {\n return obj.map((item) => convertKeys(item, converter));\n }\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[converter(key)] = convertKeys(value, converter);\n }\n return result;\n }\n return obj;\n}\n\nexport function toSnakeCaseKeys<T>(obj: T): unknown {\n return convertKeys(obj, toSnakeCase);\n}\n\nexport function toCamelCaseKeys<T>(obj: T): unknown {\n return convertKeys(obj, toCamelCase);\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 429;\n}\n\nfunction throwForStatus(\n status: number,\n message: string,\n type: string,\n): never {\n switch (status) {\n case 400:\n throw new VelobaseValidationError(message);\n case 401:\n throw new VelobaseAuthenticationError(message);\n case 404:\n throw new VelobaseNotFoundError(message);\n case 409:\n throw new VelobaseConflictError(message);\n case 500:\n throw new VelobaseInternalError(message);\n default:\n throw new VelobaseError(message, status, type);\n }\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(opts: HttpClientOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n this.timeout = opts.timeout;\n this.maxRetries = opts.maxRetries;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const delay = Math.min(500 * 2 ** (attempt - 1), 5000);\n await new Promise((r) => setTimeout(r, delay));\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n method,\n headers: {\n \"Authorization\": `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(toSnakeCaseKeys(body)) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n if (!res.ok) {\n const json = (await res.json().catch(() => ({}))) as {\n error?: { message?: string; type?: string };\n };\n const msg =\n json.error?.message ?? `HTTP ${res.status}`;\n const type = json.error?.type ?? \"unknown_error\";\n\n if (isRetryable(res.status) && attempt < this.maxRetries) {\n lastError = new VelobaseError(msg, res.status, type);\n continue;\n }\n\n throwForStatus(res.status, msg, type);\n }\n\n const json = await res.json();\n return toCamelCaseKeys(json) as T;\n } catch (err) {\n clearTimeout(timer);\n\n if (err instanceof VelobaseError) {\n throw err;\n }\n\n lastError = err as Error;\n\n if (attempt < this.maxRetries) {\n continue;\n }\n\n throw new VelobaseError(\n `Request failed: ${lastError.message}`,\n 0,\n \"network_error\",\n );\n }\n }\n\n throw lastError;\n }\n}\n","import { HttpClient } from \"./http\";\nimport type {\n ConsumeParams,\n ConsumeResponse,\n CustomerResponse,\n DepositParams,\n DepositResponse,\n FreezeParams,\n FreezeResponse,\n UnfreezeParams,\n UnfreezeResponse,\n VelobaseOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.velobase.io\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nclass BillingResource {\n constructor(private http: HttpClient) {}\n\n async freeze(params: FreezeParams): Promise<FreezeResponse> {\n return this.http.request<FreezeResponse>(\n \"POST\",\n \"/v1/billing/freeze\",\n params,\n );\n }\n\n async consume(params: ConsumeParams): Promise<ConsumeResponse> {\n return this.http.request<ConsumeResponse>(\n \"POST\",\n \"/v1/billing/consume\",\n params,\n );\n }\n\n async unfreeze(params: UnfreezeParams): Promise<UnfreezeResponse> {\n return this.http.request<UnfreezeResponse>(\n \"POST\",\n \"/v1/billing/unfreeze\",\n params,\n );\n }\n}\n\nclass CustomersResource {\n constructor(private http: HttpClient) {}\n\n async deposit(params: DepositParams): Promise<DepositResponse> {\n const headers: Record<string, string> = {};\n if (params.idempotencyKey) {\n headers[\"Idempotency-Key\"] = params.idempotencyKey;\n }\n return this.http.request<DepositResponse>(\n \"POST\",\n \"/v1/customers/deposit\",\n params,\n headers,\n );\n }\n\n async get(customerId: string): Promise<CustomerResponse> {\n return this.http.request<CustomerResponse>(\n \"GET\",\n `/v1/customers/${encodeURIComponent(customerId)}`,\n );\n }\n}\n\nexport class Velobase {\n readonly billing: BillingResource;\n readonly customers: CustomersResource;\n\n constructor(opts: VelobaseOptions) {\n if (!opts.apiKey) {\n throw new Error(\n \"apiKey is required. Get your API key at https://velobase.io\",\n );\n }\n\n const http = new HttpClient({\n baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: opts.apiKey,\n timeout: opts.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES,\n });\n\n this.billing = new BillingResource(http);\n this.customers = new CustomersResource(http);\n }\n}\n"],"mappings":"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","names":["json"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,235 @@
1
+ // src/errors.ts
2
+ var VelobaseError = class extends Error {
3
+ status;
4
+ type;
5
+ constructor(message, status, type) {
6
+ super(message);
7
+ this.name = "VelobaseError";
8
+ this.status = status;
9
+ this.type = type;
10
+ }
11
+ };
12
+ var VelobaseAuthenticationError = class extends VelobaseError {
13
+ constructor(message) {
14
+ super(message, 401, "auth_error");
15
+ this.name = "VelobaseAuthenticationError";
16
+ }
17
+ };
18
+ var VelobaseValidationError = class extends VelobaseError {
19
+ constructor(message) {
20
+ super(message, 400, "validation_error");
21
+ this.name = "VelobaseValidationError";
22
+ }
23
+ };
24
+ var VelobaseNotFoundError = class extends VelobaseError {
25
+ constructor(message) {
26
+ super(message, 404, "not_found");
27
+ this.name = "VelobaseNotFoundError";
28
+ }
29
+ };
30
+ var VelobaseConflictError = class extends VelobaseError {
31
+ constructor(message) {
32
+ super(message, 409, "conflict");
33
+ this.name = "VelobaseConflictError";
34
+ }
35
+ };
36
+ var VelobaseInternalError = class extends VelobaseError {
37
+ constructor(message) {
38
+ super(message, 500, "server_error");
39
+ this.name = "VelobaseInternalError";
40
+ }
41
+ };
42
+
43
+ // src/http.ts
44
+ function toSnakeCase(str) {
45
+ return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
46
+ }
47
+ function toCamelCase(str) {
48
+ return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
49
+ }
50
+ function convertKeys(obj, converter) {
51
+ if (Array.isArray(obj)) {
52
+ return obj.map((item) => convertKeys(item, converter));
53
+ }
54
+ if (obj !== null && typeof obj === "object") {
55
+ const result = {};
56
+ for (const [key, value] of Object.entries(obj)) {
57
+ result[converter(key)] = convertKeys(value, converter);
58
+ }
59
+ return result;
60
+ }
61
+ return obj;
62
+ }
63
+ function toSnakeCaseKeys(obj) {
64
+ return convertKeys(obj, toSnakeCase);
65
+ }
66
+ function toCamelCaseKeys(obj) {
67
+ return convertKeys(obj, toCamelCase);
68
+ }
69
+ function isRetryable(status) {
70
+ return status >= 500 || status === 429;
71
+ }
72
+ function throwForStatus(status, message, type) {
73
+ switch (status) {
74
+ case 400:
75
+ throw new VelobaseValidationError(message);
76
+ case 401:
77
+ throw new VelobaseAuthenticationError(message);
78
+ case 404:
79
+ throw new VelobaseNotFoundError(message);
80
+ case 409:
81
+ throw new VelobaseConflictError(message);
82
+ case 500:
83
+ throw new VelobaseInternalError(message);
84
+ default:
85
+ throw new VelobaseError(message, status, type);
86
+ }
87
+ }
88
+ var HttpClient = class {
89
+ baseUrl;
90
+ apiKey;
91
+ timeout;
92
+ maxRetries;
93
+ constructor(opts) {
94
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
95
+ this.apiKey = opts.apiKey;
96
+ this.timeout = opts.timeout;
97
+ this.maxRetries = opts.maxRetries;
98
+ }
99
+ async request(method, path, body, headers) {
100
+ const url = `${this.baseUrl}${path}`;
101
+ let lastError;
102
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
103
+ if (attempt > 0) {
104
+ const delay = Math.min(500 * 2 ** (attempt - 1), 5e3);
105
+ await new Promise((r) => setTimeout(r, delay));
106
+ }
107
+ const controller = new AbortController();
108
+ const timer = setTimeout(() => controller.abort(), this.timeout);
109
+ try {
110
+ const res = await fetch(url, {
111
+ method,
112
+ headers: {
113
+ "Authorization": `Bearer ${this.apiKey}`,
114
+ "Content-Type": "application/json",
115
+ ...headers
116
+ },
117
+ body: body ? JSON.stringify(toSnakeCaseKeys(body)) : void 0,
118
+ signal: controller.signal
119
+ });
120
+ clearTimeout(timer);
121
+ if (!res.ok) {
122
+ const json2 = await res.json().catch(() => ({}));
123
+ const msg = json2.error?.message ?? `HTTP ${res.status}`;
124
+ const type = json2.error?.type ?? "unknown_error";
125
+ if (isRetryable(res.status) && attempt < this.maxRetries) {
126
+ lastError = new VelobaseError(msg, res.status, type);
127
+ continue;
128
+ }
129
+ throwForStatus(res.status, msg, type);
130
+ }
131
+ const json = await res.json();
132
+ return toCamelCaseKeys(json);
133
+ } catch (err) {
134
+ clearTimeout(timer);
135
+ if (err instanceof VelobaseError) {
136
+ throw err;
137
+ }
138
+ lastError = err;
139
+ if (attempt < this.maxRetries) {
140
+ continue;
141
+ }
142
+ throw new VelobaseError(
143
+ `Request failed: ${lastError.message}`,
144
+ 0,
145
+ "network_error"
146
+ );
147
+ }
148
+ }
149
+ throw lastError;
150
+ }
151
+ };
152
+
153
+ // src/client.ts
154
+ var DEFAULT_BASE_URL = "https://api.velobase.io";
155
+ var DEFAULT_TIMEOUT = 3e4;
156
+ var DEFAULT_MAX_RETRIES = 2;
157
+ var BillingResource = class {
158
+ constructor(http) {
159
+ this.http = http;
160
+ }
161
+ async freeze(params) {
162
+ return this.http.request(
163
+ "POST",
164
+ "/v1/billing/freeze",
165
+ params
166
+ );
167
+ }
168
+ async consume(params) {
169
+ return this.http.request(
170
+ "POST",
171
+ "/v1/billing/consume",
172
+ params
173
+ );
174
+ }
175
+ async unfreeze(params) {
176
+ return this.http.request(
177
+ "POST",
178
+ "/v1/billing/unfreeze",
179
+ params
180
+ );
181
+ }
182
+ };
183
+ var CustomersResource = class {
184
+ constructor(http) {
185
+ this.http = http;
186
+ }
187
+ async deposit(params) {
188
+ const headers = {};
189
+ if (params.idempotencyKey) {
190
+ headers["Idempotency-Key"] = params.idempotencyKey;
191
+ }
192
+ return this.http.request(
193
+ "POST",
194
+ "/v1/customers/deposit",
195
+ params,
196
+ headers
197
+ );
198
+ }
199
+ async get(customerId) {
200
+ return this.http.request(
201
+ "GET",
202
+ `/v1/customers/${encodeURIComponent(customerId)}`
203
+ );
204
+ }
205
+ };
206
+ var Velobase = class {
207
+ billing;
208
+ customers;
209
+ constructor(opts) {
210
+ if (!opts.apiKey) {
211
+ throw new Error(
212
+ "apiKey is required. Get your API key at https://velobase.io"
213
+ );
214
+ }
215
+ const http = new HttpClient({
216
+ baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,
217
+ apiKey: opts.apiKey,
218
+ timeout: opts.timeout ?? DEFAULT_TIMEOUT,
219
+ maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES
220
+ });
221
+ this.billing = new BillingResource(http);
222
+ this.customers = new CustomersResource(http);
223
+ }
224
+ };
225
+ export {
226
+ Velobase,
227
+ VelobaseAuthenticationError,
228
+ VelobaseConflictError,
229
+ VelobaseError,
230
+ VelobaseInternalError,
231
+ VelobaseNotFoundError,
232
+ VelobaseValidationError,
233
+ Velobase as default
234
+ };
235
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["export class VelobaseError extends Error {\n status: number;\n type: string;\n\n constructor(message: string, status: number, type: string) {\n super(message);\n this.name = \"VelobaseError\";\n this.status = status;\n this.type = type;\n }\n}\n\nexport class VelobaseAuthenticationError extends VelobaseError {\n constructor(message: string) {\n super(message, 401, \"auth_error\");\n this.name = \"VelobaseAuthenticationError\";\n }\n}\n\nexport class VelobaseValidationError extends VelobaseError {\n constructor(message: string) {\n super(message, 400, \"validation_error\");\n this.name = \"VelobaseValidationError\";\n }\n}\n\nexport class VelobaseNotFoundError extends VelobaseError {\n constructor(message: string) {\n super(message, 404, \"not_found\");\n this.name = \"VelobaseNotFoundError\";\n }\n}\n\nexport class VelobaseConflictError extends VelobaseError {\n constructor(message: string) {\n super(message, 409, \"conflict\");\n this.name = \"VelobaseConflictError\";\n }\n}\n\nexport class VelobaseInternalError extends VelobaseError {\n constructor(message: string) {\n super(message, 500, \"server_error\");\n this.name = \"VelobaseInternalError\";\n }\n}\n","import {\n VelobaseAuthenticationError,\n VelobaseConflictError,\n VelobaseError,\n VelobaseInternalError,\n VelobaseNotFoundError,\n VelobaseValidationError,\n} from \"./errors\";\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n maxRetries: number;\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction convertKeys(\n obj: unknown,\n converter: (key: string) => string,\n): unknown {\n if (Array.isArray(obj)) {\n return obj.map((item) => convertKeys(item, converter));\n }\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[converter(key)] = convertKeys(value, converter);\n }\n return result;\n }\n return obj;\n}\n\nexport function toSnakeCaseKeys<T>(obj: T): unknown {\n return convertKeys(obj, toSnakeCase);\n}\n\nexport function toCamelCaseKeys<T>(obj: T): unknown {\n return convertKeys(obj, toCamelCase);\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 429;\n}\n\nfunction throwForStatus(\n status: number,\n message: string,\n type: string,\n): never {\n switch (status) {\n case 400:\n throw new VelobaseValidationError(message);\n case 401:\n throw new VelobaseAuthenticationError(message);\n case 404:\n throw new VelobaseNotFoundError(message);\n case 409:\n throw new VelobaseConflictError(message);\n case 500:\n throw new VelobaseInternalError(message);\n default:\n throw new VelobaseError(message, status, type);\n }\n}\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n private maxRetries: number;\n\n constructor(opts: HttpClientOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n this.timeout = opts.timeout;\n this.maxRetries = opts.maxRetries;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n headers?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const delay = Math.min(500 * 2 ** (attempt - 1), 5000);\n await new Promise((r) => setTimeout(r, delay));\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n method,\n headers: {\n \"Authorization\": `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(toSnakeCaseKeys(body)) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n if (!res.ok) {\n const json = (await res.json().catch(() => ({}))) as {\n error?: { message?: string; type?: string };\n };\n const msg =\n json.error?.message ?? `HTTP ${res.status}`;\n const type = json.error?.type ?? \"unknown_error\";\n\n if (isRetryable(res.status) && attempt < this.maxRetries) {\n lastError = new VelobaseError(msg, res.status, type);\n continue;\n }\n\n throwForStatus(res.status, msg, type);\n }\n\n const json = await res.json();\n return toCamelCaseKeys(json) as T;\n } catch (err) {\n clearTimeout(timer);\n\n if (err instanceof VelobaseError) {\n throw err;\n }\n\n lastError = err as Error;\n\n if (attempt < this.maxRetries) {\n continue;\n }\n\n throw new VelobaseError(\n `Request failed: ${lastError.message}`,\n 0,\n \"network_error\",\n );\n }\n }\n\n throw lastError;\n }\n}\n","import { HttpClient } from \"./http\";\nimport type {\n ConsumeParams,\n ConsumeResponse,\n CustomerResponse,\n DepositParams,\n DepositResponse,\n FreezeParams,\n FreezeResponse,\n UnfreezeParams,\n UnfreezeResponse,\n VelobaseOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.velobase.io\";\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nclass BillingResource {\n constructor(private http: HttpClient) {}\n\n async freeze(params: FreezeParams): Promise<FreezeResponse> {\n return this.http.request<FreezeResponse>(\n \"POST\",\n \"/v1/billing/freeze\",\n params,\n );\n }\n\n async consume(params: ConsumeParams): Promise<ConsumeResponse> {\n return this.http.request<ConsumeResponse>(\n \"POST\",\n \"/v1/billing/consume\",\n params,\n );\n }\n\n async unfreeze(params: UnfreezeParams): Promise<UnfreezeResponse> {\n return this.http.request<UnfreezeResponse>(\n \"POST\",\n \"/v1/billing/unfreeze\",\n params,\n );\n }\n}\n\nclass CustomersResource {\n constructor(private http: HttpClient) {}\n\n async deposit(params: DepositParams): Promise<DepositResponse> {\n const headers: Record<string, string> = {};\n if (params.idempotencyKey) {\n headers[\"Idempotency-Key\"] = params.idempotencyKey;\n }\n return this.http.request<DepositResponse>(\n \"POST\",\n \"/v1/customers/deposit\",\n params,\n headers,\n );\n }\n\n async get(customerId: string): Promise<CustomerResponse> {\n return this.http.request<CustomerResponse>(\n \"GET\",\n `/v1/customers/${encodeURIComponent(customerId)}`,\n );\n }\n}\n\nexport class Velobase {\n readonly billing: BillingResource;\n readonly customers: CustomersResource;\n\n constructor(opts: VelobaseOptions) {\n if (!opts.apiKey) {\n throw new Error(\n \"apiKey is required. Get your API key at https://velobase.io\",\n );\n }\n\n const http = new HttpClient({\n baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: opts.apiKey,\n timeout: opts.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES,\n });\n\n this.billing = new BillingResource(http);\n this.customers = new CustomersResource(http);\n }\n}\n"],"mappings":"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","names":["json"]}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@velobaseai/billing",
3
+ "version": "0.1.0",
4
+ "description": "Velobase Billing SDK for JavaScript/TypeScript",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "typecheck": "tsc --noEmit",
26
+ "clean": "rm -rf dist"
27
+ },
28
+ "keywords": [
29
+ "velobase",
30
+ "billing",
31
+ "credits",
32
+ "api",
33
+ "sdk"
34
+ ],
35
+ "author": "Velobase",
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/velobase/billing-sdk-js.git"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "devDependencies": {
45
+ "tsup": "^8.0.0",
46
+ "typescript": "^5.5.0"
47
+ }
48
+ }