@butterbase/sdk 1.0.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/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # @butterbase/sdk
2
+
3
+ Universal TypeScript SDK for Butterbase - works in browser, Node.js, and Deno environments.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @butterbase/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { createClient } from '@butterbase/sdk';
15
+
16
+ // Initialize client
17
+ const butterbase = createClient({
18
+ appId: 'app_abc123',
19
+ apiUrl: 'https://api.butterbase.com',
20
+ anonKey: 'your-anon-key' // Optional, for public access
21
+ });
22
+
23
+ // Query data
24
+ const { data, error } = await butterbase
25
+ .from('posts')
26
+ .select('*')
27
+ .eq('status', 'published')
28
+ .order('created_at', { ascending: false })
29
+ .limit(10);
30
+
31
+ // Insert data
32
+ const { data, error } = await butterbase
33
+ .from('posts')
34
+ .insert({ title: 'Hello World', content: 'My first post' });
35
+
36
+ // Update data
37
+ const { data, error } = await butterbase
38
+ .from('posts')
39
+ .update({ status: 'archived' })
40
+ .eq('id', '123');
41
+
42
+ // Delete data
43
+ const { data, error } = await butterbase
44
+ .from('posts')
45
+ .delete()
46
+ .eq('id', '123');
47
+ ```
48
+
49
+ ## Migration from 0.x to 1.0
50
+
51
+ **Breaking Change:** The `authUrl` parameter has been removed. All auth endpoints now run on the same URL as the API.
52
+
53
+ **Before (0.x):**
54
+ ```typescript
55
+ const butterbase = createClient({
56
+ appId: 'app_abc123',
57
+ apiUrl: 'https://api.butterbase.com',
58
+ authUrl: 'https://auth.butterbase.com', // ❌ No longer needed
59
+ });
60
+ ```
61
+
62
+ **After (1.0):**
63
+ ```typescript
64
+ const butterbase = createClient({
65
+ appId: 'app_abc123',
66
+ apiUrl: 'https://api.butterbase.com', // ✅ All endpoints use this URL
67
+ });
68
+ ```
69
+
70
+ ## Authentication
71
+
72
+ ```typescript
73
+ // Sign up
74
+ const { data, error } = await butterbase.auth.signUp({
75
+ email: 'user@example.com',
76
+ password: 'secure123'
77
+ });
78
+
79
+ // Sign in
80
+ const { data, error } = await butterbase.auth.signIn({
81
+ email: 'user@example.com',
82
+ password: 'secure123'
83
+ });
84
+
85
+ // Get current user
86
+ const { data: user } = await butterbase.auth.getUser();
87
+
88
+ // Sign out
89
+ await butterbase.auth.signOut();
90
+
91
+ // OAuth
92
+ const { url } = butterbase.auth.signInWithOAuth({
93
+ provider: 'google',
94
+ redirectTo: 'http://localhost:3000/callback'
95
+ });
96
+ window.location.href = url;
97
+ ```
98
+
99
+ ## Storage
100
+
101
+ ```typescript
102
+ // Upload file
103
+ const { data, error } = await butterbase.storage.upload(file);
104
+
105
+ // Get download URL
106
+ const { data } = await butterbase.storage.getDownloadUrl(objectId);
107
+
108
+ // List files
109
+ const { data: objects } = await butterbase.storage.list();
110
+
111
+ // Delete file
112
+ await butterbase.storage.delete(objectId);
113
+ ```
114
+
115
+ ## Functions
116
+
117
+ ```typescript
118
+ // Invoke serverless function
119
+ const { data, error } = await butterbase.functions.invoke('my-function', {
120
+ body: { key: 'value' },
121
+ method: 'POST'
122
+ });
123
+ ```
124
+
125
+ ## Query Builder
126
+
127
+ ### Operators
128
+
129
+ - `eq(column, value)` - Equal to
130
+ - `neq(column, value)` - Not equal to
131
+ - `gt(column, value)` - Greater than
132
+ - `gte(column, value)` - Greater than or equal to
133
+ - `lt(column, value)` - Less than
134
+ - `lte(column, value)` - Less than or equal to
135
+ - `like(column, pattern)` - Pattern matching (case-sensitive)
136
+ - `ilike(column, pattern)` - Pattern matching (case-insensitive)
137
+ - `in(column, values)` - Value in array
138
+ - `is(column, value)` - Is null/true/false
139
+
140
+ ### Modifiers
141
+
142
+ - `select(columns)` - Select specific columns
143
+ - `order(column, options)` - Order results
144
+ - `limit(count)` - Limit results
145
+ - `offset(count)` - Skip results
146
+
147
+ ## Usage in Deno
148
+
149
+ ```typescript
150
+ import { createClient } from 'npm:@butterbase/sdk';
151
+
152
+ const butterbase = createClient({
153
+ appId: Deno.env.get('BUTTERBASE_APP_ID')!,
154
+ apiUrl: Deno.env.get('BUTTERBASE_API_URL')!,
155
+ });
156
+
157
+ // Use in serverless functions
158
+ export async function handler(req: Request, ctx: any) {
159
+ const { data } = await butterbase.from('posts').select('*');
160
+ return Response.json({ data });
161
+ }
162
+ ```
163
+
164
+ ## TypeScript Support
165
+
166
+ The SDK is fully typed with TypeScript. All methods return `ButterbaseResponse<T>` with proper type inference:
167
+
168
+ ```typescript
169
+ interface Post {
170
+ id: string;
171
+ title: string;
172
+ content: string;
173
+ status: 'draft' | 'published';
174
+ }
175
+
176
+ const { data, error } = await butterbase
177
+ .from<Post>('posts')
178
+ .select('*')
179
+ .eq('status', 'published');
180
+
181
+ // data is typed as Post[] | null
182
+ // error is typed as Error | null
183
+ ```
184
+
185
+ ## License
186
+
187
+ MIT
@@ -0,0 +1,47 @@
1
+ import type { ButterbaseClient } from '../lib/butterbase-client.js';
2
+ import type { ButterbaseResponse, SignUpParams, SignInParams, LoginResponse, SignupResponse, User, OAuthParams } from '../types/index.js';
3
+ export declare class AuthClient {
4
+ private client;
5
+ constructor(client: ButterbaseClient);
6
+ /**
7
+ * Sign up a new user with email and password
8
+ * Note: API returns user and message, but no tokens (email verification required)
9
+ */
10
+ signUp(params: SignUpParams): Promise<ButterbaseResponse<SignupResponse>>;
11
+ /**
12
+ * Sign in an existing user with email and password
13
+ */
14
+ signIn(params: SignInParams): Promise<ButterbaseResponse<LoginResponse>>;
15
+ /**
16
+ * Sign out the current user
17
+ */
18
+ signOut(): Promise<ButterbaseResponse<void>>;
19
+ /**
20
+ * Get the current authenticated user
21
+ */
22
+ getUser(): Promise<ButterbaseResponse<User>>;
23
+ /**
24
+ * Initiate OAuth sign-in flow
25
+ * Returns the URL to redirect the user to
26
+ */
27
+ signInWithOAuth(params: OAuthParams): {
28
+ url: string;
29
+ };
30
+ /**
31
+ * Refresh the access token using a refresh token
32
+ */
33
+ refreshSession(refreshToken: string): Promise<ButterbaseResponse<LoginResponse>>;
34
+ /**
35
+ * Request a password reset email
36
+ */
37
+ forgotPassword(email: string): Promise<ButterbaseResponse<void>>;
38
+ /**
39
+ * Reset password with token from email
40
+ */
41
+ resetPassword(token: string, newPassword: string): Promise<ButterbaseResponse<void>>;
42
+ /**
43
+ * Verify email with verification code
44
+ */
45
+ verifyEmail(code: string): Promise<ButterbaseResponse<void>>;
46
+ }
47
+ //# sourceMappingURL=auth-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/auth/auth-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EAEZ,aAAa,EACb,cAAc,EACd,IAAI,EACJ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,UAAU;IACT,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;;OAGG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAe/E;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAiB9E;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAiBlD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAalD;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE;IAMrD;;OAEG;IACG,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAiBtF;;OAEG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IActE;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAc1F;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;CAanE"}
@@ -0,0 +1,120 @@
1
+ export class AuthClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ /**
7
+ * Sign up a new user with email and password
8
+ * Note: API returns user and message, but no tokens (email verification required)
9
+ */
10
+ async signUp(params) {
11
+ try {
12
+ const response = await this.client.request('POST', `/auth/${this.client.appId}/signup`, params);
13
+ // No token returned from signup - user must verify email first
14
+ return { data: response, error: null };
15
+ }
16
+ catch (error) {
17
+ return { data: null, error: error };
18
+ }
19
+ }
20
+ /**
21
+ * Sign in an existing user with email and password
22
+ */
23
+ async signIn(params) {
24
+ try {
25
+ const response = await this.client.request('POST', `/auth/${this.client.appId}/login`, params);
26
+ // Store access token from flat response
27
+ this.client.setAccessToken(response.access_token);
28
+ return { data: response, error: null };
29
+ }
30
+ catch (error) {
31
+ return { data: null, error: error };
32
+ }
33
+ }
34
+ /**
35
+ * Sign out the current user
36
+ */
37
+ async signOut() {
38
+ try {
39
+ await this.client.request('POST', `/auth/${this.client.appId}/logout`, {});
40
+ // Clear access token
41
+ this.client.setAccessToken(undefined);
42
+ return { data: null, error: null };
43
+ }
44
+ catch (error) {
45
+ return { data: null, error: error };
46
+ }
47
+ }
48
+ /**
49
+ * Get the current authenticated user
50
+ */
51
+ async getUser() {
52
+ try {
53
+ const user = await this.client.request('GET', `/auth/${this.client.appId}/me`);
54
+ return { data: user, error: null };
55
+ }
56
+ catch (error) {
57
+ return { data: null, error: error };
58
+ }
59
+ }
60
+ /**
61
+ * Initiate OAuth sign-in flow
62
+ * Returns the URL to redirect the user to
63
+ */
64
+ signInWithOAuth(params) {
65
+ const apiUrl = this.client['apiUrl']; // Access private property
66
+ const url = `${apiUrl}/auth/${this.client.appId}/oauth/${params.provider}?redirect_to=${encodeURIComponent(params.redirectTo)}`;
67
+ return { url };
68
+ }
69
+ /**
70
+ * Refresh the access token using a refresh token
71
+ */
72
+ async refreshSession(refreshToken) {
73
+ try {
74
+ const response = await this.client.request('POST', `/auth/${this.client.appId}/refresh`, { refresh_token: refreshToken });
75
+ // Store new access token from flat response
76
+ this.client.setAccessToken(response.access_token);
77
+ return { data: response, error: null };
78
+ }
79
+ catch (error) {
80
+ return { data: null, error: error };
81
+ }
82
+ }
83
+ /**
84
+ * Request a password reset email
85
+ */
86
+ async forgotPassword(email) {
87
+ try {
88
+ await this.client.request('POST', `/auth/${this.client.appId}/forgot-password`, { email });
89
+ return { data: null, error: null };
90
+ }
91
+ catch (error) {
92
+ return { data: null, error: error };
93
+ }
94
+ }
95
+ /**
96
+ * Reset password with token from email
97
+ */
98
+ async resetPassword(token, newPassword) {
99
+ try {
100
+ await this.client.request('POST', `/auth/${this.client.appId}/reset-password`, { token, newPassword });
101
+ return { data: null, error: null };
102
+ }
103
+ catch (error) {
104
+ return { data: null, error: error };
105
+ }
106
+ }
107
+ /**
108
+ * Verify email with verification code
109
+ */
110
+ async verifyEmail(code) {
111
+ try {
112
+ await this.client.request('POST', `/auth/${this.client.appId}/verify-email`, { code });
113
+ return { data: null, error: null };
114
+ }
115
+ catch (error) {
116
+ return { data: null, error: error };
117
+ }
118
+ }
119
+ }
120
+ //# sourceMappingURL=auth-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../src/auth/auth-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ButterbaseClient } from '../lib/butterbase-client.js';
2
+ import type { ButterbaseResponse, InvokeFunctionOptions } from '../types/index.js';
3
+ export declare class FunctionsClient {
4
+ private client;
5
+ constructor(client: ButterbaseClient);
6
+ /**
7
+ * Invoke a serverless function
8
+ */
9
+ invoke<T = any>(functionName: string, options?: InvokeFunctionOptions): Promise<ButterbaseResponse<T>>;
10
+ /**
11
+ * Invoke a serverless function that returns binary data (blob)
12
+ * Use this for functions that return files, images, or other binary content
13
+ */
14
+ invokeBlob(functionName: string, options?: InvokeFunctionOptions): Promise<ButterbaseResponse<Blob>>;
15
+ }
16
+ //# sourceMappingURL=functions-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions-client.d.ts","sourceRoot":"","sources":["../../src/functions/functions-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAEnF,qBAAa,eAAe;IACd,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,gBAAgB;IAE5C;;OAEG;IACG,MAAM,CAAC,CAAC,GAAG,GAAG,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAkBjC;;;OAGG;IACG,UAAU,CACd,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;CAiBrC"}
@@ -0,0 +1,36 @@
1
+ export class FunctionsClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ /**
7
+ * Invoke a serverless function
8
+ */
9
+ async invoke(functionName, options) {
10
+ try {
11
+ const method = options?.method || 'POST';
12
+ const path = `/v1/${this.client.appId}/fn/${functionName}`;
13
+ const data = await this.client.request(method, path, options?.body, options?.headers);
14
+ return { data, error: null };
15
+ }
16
+ catch (error) {
17
+ return { data: null, error: error };
18
+ }
19
+ }
20
+ /**
21
+ * Invoke a serverless function that returns binary data (blob)
22
+ * Use this for functions that return files, images, or other binary content
23
+ */
24
+ async invokeBlob(functionName, options) {
25
+ try {
26
+ const method = options?.method || 'POST';
27
+ const path = `/v1/${this.client.appId}/fn/${functionName}`;
28
+ const blob = await this.client.requestBlob(method, path, options?.body, options?.headers);
29
+ return { data: blob, error: null };
30
+ }
31
+ catch (error) {
32
+ return { data: null, error: error };
33
+ }
34
+ }
35
+ }
36
+ //# sourceMappingURL=functions-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions-client.js","sourceRoot":"","sources":["../../src/functions/functions-client.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;IAAG,CAAC;IAEhD;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,YAAoB,EACpB,OAA+B;QAE/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;YACzC,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,OAAO,YAAY,EAAE,CAAC;YAE3D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CACpC,MAAM,EACN,IAAI,EACJ,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,OAAO,CACjB,CAAC;YAEF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CACd,YAAoB,EACpB,OAA+B;QAE/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;YACzC,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,OAAO,YAAY,EAAE,CAAC;YAE3D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CACxC,MAAM,EACN,IAAI,EACJ,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,OAAO,CACjB,CAAC;YAEF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export { ButterbaseClient, createClient } from './lib/butterbase-client.js';
2
+ export { QueryBuilder } from './lib/query-builder.js';
3
+ export { InsertBuilder, UpdateBuilder, DeleteBuilder } from './lib/mutation-builders.js';
4
+ export { AuthClient } from './auth/auth-client.js';
5
+ export { StorageClient } from './storage/storage-client.js';
6
+ export { FunctionsClient } from './functions/functions-client.js';
7
+ export type { ButterbaseClientOptions, ButterbaseResponse, User, Session, SignUpParams, SignInParams, AuthResponse, LoginResponse, SignupResponse, OAuthParams, StorageObject, UploadResponse, DownloadUrlResponse, QueryOperator, QueryFilter, OrderByOptions, InvokeFunctionOptions, } from './types/index.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGzF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,YAAY,EACV,uBAAuB,EACvB,kBAAkB,EAClB,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,cAAc,EACd,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ // Main client
2
+ export { ButterbaseClient, createClient } from './lib/butterbase-client.js';
3
+ // Query builder
4
+ export { QueryBuilder } from './lib/query-builder.js';
5
+ // Mutation builders
6
+ export { InsertBuilder, UpdateBuilder, DeleteBuilder } from './lib/mutation-builders.js';
7
+ // Client modules
8
+ export { AuthClient } from './auth/auth-client.js';
9
+ export { StorageClient } from './storage/storage-client.js';
10
+ export { FunctionsClient } from './functions/functions-client.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE5E,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEzF,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { ButterbaseClientOptions } from '../types/index.js';
2
+ import { AuthClient } from '../auth/auth-client.js';
3
+ import { StorageClient } from '../storage/storage-client.js';
4
+ import { FunctionsClient } from '../functions/functions-client.js';
5
+ import { QueryBuilder } from './query-builder.js';
6
+ export declare class ButterbaseClient {
7
+ readonly appId: string;
8
+ private apiUrl;
9
+ private anonKey?;
10
+ private accessToken?;
11
+ private options;
12
+ readonly auth: AuthClient;
13
+ readonly storage: StorageClient;
14
+ readonly functions: FunctionsClient;
15
+ constructor(options: ButterbaseClientOptions);
16
+ /**
17
+ * Create a query builder for a table
18
+ */
19
+ from<T = any>(table: string): QueryBuilder<T>;
20
+ /**
21
+ * Set the access token for authenticated requests
22
+ */
23
+ setAccessToken(token: string | undefined): void;
24
+ /**
25
+ * Get the current access token
26
+ */
27
+ getAccessToken(): string | undefined;
28
+ /**
29
+ * Internal request method used by all clients
30
+ */
31
+ request<T>(method: string, path: string, body?: any, customHeaders?: Record<string, string>): Promise<T>;
32
+ /**
33
+ * Internal request method for blob responses (e.g., file exports)
34
+ */
35
+ requestBlob(method: string, path: string, body?: any, customHeaders?: Record<string, string>): Promise<Blob>;
36
+ }
37
+ /**
38
+ * Create a new Butterbase client instance
39
+ */
40
+ export declare function createClient(options: ButterbaseClientOptions): ButterbaseClient;
41
+ //# sourceMappingURL=butterbase-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butterbase-client.d.ts","sourceRoot":"","sources":["../../src/lib/butterbase-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,qBAAa,gBAAgB;IAC3B,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,OAAO,CAA0B;IAEzC,SAAgB,IAAI,EAAE,UAAU,CAAC;IACjC,SAAgB,OAAO,EAAE,aAAa,CAAC;IACvC,SAAgB,SAAS,EAAE,eAAe,CAAC;gBAE/B,OAAO,EAAE,uBAAuB;IAW5C;;OAEG;IACH,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAI7C;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IAIxC;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,SAAS;IAIpC;;OAEG;IACG,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,GAAG,EACV,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,OAAO,CAAC,CAAC,CAAC;IAyDb;;OAEG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,GAAG,EACV,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;CAuCjB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CAE/E"}
@@ -0,0 +1,138 @@
1
+ import { AuthClient } from '../auth/auth-client.js';
2
+ import { StorageClient } from '../storage/storage-client.js';
3
+ import { FunctionsClient } from '../functions/functions-client.js';
4
+ import { QueryBuilder } from './query-builder.js';
5
+ export class ButterbaseClient {
6
+ appId;
7
+ apiUrl;
8
+ anonKey;
9
+ accessToken;
10
+ options;
11
+ auth;
12
+ storage;
13
+ functions;
14
+ constructor(options) {
15
+ this.appId = options.appId;
16
+ this.apiUrl = options.apiUrl;
17
+ this.anonKey = options.anonKey;
18
+ this.options = options;
19
+ this.auth = new AuthClient(this);
20
+ this.storage = new StorageClient(this);
21
+ this.functions = new FunctionsClient(this);
22
+ }
23
+ /**
24
+ * Create a query builder for a table
25
+ */
26
+ from(table) {
27
+ return new QueryBuilder(table, this);
28
+ }
29
+ /**
30
+ * Set the access token for authenticated requests
31
+ */
32
+ setAccessToken(token) {
33
+ this.accessToken = token;
34
+ }
35
+ /**
36
+ * Get the current access token
37
+ */
38
+ getAccessToken() {
39
+ return this.accessToken;
40
+ }
41
+ /**
42
+ * Internal request method used by all clients
43
+ */
44
+ async request(method, path, body, customHeaders) {
45
+ const headers = {
46
+ ...customHeaders,
47
+ };
48
+ // Only set Content-Type when sending a body to avoid Fastify's FST_ERR_CTP_EMPTY_JSON_BODY
49
+ const serializedBody = body !== undefined && body !== null ? JSON.stringify(body) : undefined;
50
+ if (serializedBody !== undefined) {
51
+ headers['Content-Type'] = 'application/json';
52
+ }
53
+ // Auth priority: access token > anon key
54
+ if (this.accessToken) {
55
+ headers['Authorization'] = `Bearer ${this.accessToken}`;
56
+ }
57
+ else if (this.anonKey) {
58
+ headers['Authorization'] = `Bearer ${this.anonKey}`;
59
+ }
60
+ // All endpoints use apiUrl
61
+ const url = `${this.apiUrl}${path}`;
62
+ const response = await fetch(url, {
63
+ method,
64
+ headers,
65
+ body: serializedBody,
66
+ });
67
+ if (!response.ok) {
68
+ // Call onUnauthorized callback for 401 responses
69
+ if (response.status === 401 && this.options.onUnauthorized) {
70
+ this.options.onUnauthorized();
71
+ }
72
+ let errorMessage = response.statusText;
73
+ try {
74
+ const errorData = await response.json();
75
+ errorMessage = errorData.error || errorData.message || errorMessage;
76
+ }
77
+ catch {
78
+ // If JSON parsing fails, use statusText
79
+ }
80
+ throw new Error(errorMessage);
81
+ }
82
+ // Handle 204 No Content
83
+ if (response.status === 204) {
84
+ return undefined;
85
+ }
86
+ // Parse JSON response
87
+ const text = await response.text();
88
+ if (!text) {
89
+ return undefined;
90
+ }
91
+ return JSON.parse(text);
92
+ }
93
+ /**
94
+ * Internal request method for blob responses (e.g., file exports)
95
+ */
96
+ async requestBlob(method, path, body, customHeaders) {
97
+ const headers = {
98
+ ...customHeaders,
99
+ };
100
+ // Auth priority: access token > anon key
101
+ if (this.accessToken) {
102
+ headers['Authorization'] = `Bearer ${this.accessToken}`;
103
+ }
104
+ else if (this.anonKey) {
105
+ headers['Authorization'] = `Bearer ${this.anonKey}`;
106
+ }
107
+ // All endpoints use apiUrl
108
+ const url = `${this.apiUrl}${path}`;
109
+ const response = await fetch(url, {
110
+ method,
111
+ headers,
112
+ body: body ? JSON.stringify(body) : undefined,
113
+ });
114
+ if (!response.ok) {
115
+ // Call onUnauthorized callback for 401 responses
116
+ if (response.status === 401 && this.options.onUnauthorized) {
117
+ this.options.onUnauthorized();
118
+ }
119
+ let errorMessage = response.statusText;
120
+ try {
121
+ const errorData = await response.json();
122
+ errorMessage = errorData.error || errorData.message || errorMessage;
123
+ }
124
+ catch {
125
+ // If JSON parsing fails, use statusText
126
+ }
127
+ throw new Error(errorMessage);
128
+ }
129
+ return response.blob();
130
+ }
131
+ }
132
+ /**
133
+ * Create a new Butterbase client instance
134
+ */
135
+ export function createClient(options) {
136
+ return new ButterbaseClient(options);
137
+ }
138
+ //# sourceMappingURL=butterbase-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butterbase-client.js","sourceRoot":"","sources":["../../src/lib/butterbase-client.ts"],"names":[],"mappings":"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"}