@linabase/js 0.1.1 → 0.2.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/index.d.ts CHANGED
@@ -1,23 +1,23 @@
1
- type RequestFn$2 = (path: string, options?: RequestInit) => Promise<Response>;
1
+ type RequestFn$3 = (path: string, options?: RequestInit) => Promise<Response>;
2
+ interface PostgrestError {
3
+ message: string;
4
+ code?: string;
5
+ details?: string;
6
+ hint?: string;
7
+ }
2
8
  interface QueryResult<T = any> {
3
9
  data: T[] | null;
4
- error: {
5
- message: string;
6
- } | null;
10
+ error: PostgrestError | null;
7
11
  count: number | null;
8
12
  }
9
13
  interface SingleQueryResult<T = any> {
10
14
  data: T | null;
11
- error: {
12
- message: string;
13
- } | null;
15
+ error: PostgrestError | null;
14
16
  count: number | null;
15
17
  }
16
18
  interface CsvQueryResult {
17
19
  data: string | null;
18
- error: {
19
- message: string;
20
- } | null;
20
+ error: PostgrestError | null;
21
21
  count: number | null;
22
22
  }
23
23
  declare class DatabaseClient {
@@ -33,13 +33,17 @@ declare class DatabaseClient {
33
33
  private _csv;
34
34
  private _abortSignal;
35
35
  private _schema;
36
- constructor(request: RequestFn$2, table: string);
36
+ constructor(request: RequestFn$3, table: string);
37
37
  /** Select columns. Supports nested joins: "*, comments(*)" and aliases: "full_name:name" */
38
- select(columns?: string): this;
38
+ select(columns?: string, options?: {
39
+ count?: "exact" | "estimated" | "planned";
40
+ head?: boolean;
41
+ }): this;
39
42
  insert(data: Record<string, any> | Record<string, any>[]): this;
40
43
  /** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
41
44
  upsert(data: Record<string, any> | Record<string, any>[], options?: {
42
45
  ignoreDuplicates?: boolean;
46
+ onConflict?: string;
43
47
  }): this;
44
48
  update(data: Record<string, any>): this;
45
49
  delete(): this;
@@ -51,8 +55,8 @@ declare class DatabaseClient {
51
55
  lte(column: string, value: any): this;
52
56
  like(column: string, pattern: string): this;
53
57
  ilike(column: string, pattern: string): this;
54
- /** Regex match (~) */
55
- match(column: string, pattern: string): this;
58
+ /** Regex match (~) when called with (column, pattern). Object-based multi-column filter when called with ({ col: val }). */
59
+ match(columnOrFilter: string | Record<string, any>, pattern?: string): this;
56
60
  /** Case-insensitive regex match (~*) */
57
61
  imatch(column: string, pattern: string): this;
58
62
  in(column: string, values: any[]): this;
@@ -62,7 +66,7 @@ declare class DatabaseClient {
62
66
  containedBy(column: string, value: any): this;
63
67
  /** Overlap (&&) - ranges or arrays */
64
68
  overlaps(column: string, value: any): this;
65
- is(column: string, value: "null" | "true" | "false"): this;
69
+ is(column: string, value: "null" | "true" | "false" | null | boolean): this;
66
70
  /** IS DISTINCT FROM */
67
71
  isDistinct(column: string, value: any): this;
68
72
  /** Negate a filter: not.eq, not.in, not.is, etc. */
@@ -97,11 +101,16 @@ declare class DatabaseClient {
97
101
  schema(schemaName: string): this;
98
102
  private reset;
99
103
  execute(): Promise<QueryResult | SingleQueryResult | CsvQueryResult>;
100
- then(resolve: (value: QueryResult | SingleQueryResult | CsvQueryResult) => void, reject?: (reason: any) => void): Promise<void>;
104
+ /**
105
+ * Makes DatabaseClient thenable (await-able). Resolves to
106
+ * `{ data, error, count }` where data is permissively typed so
107
+ * callers can access properties without generated database types.
108
+ */
109
+ then<T = any, U = never>(onfulfilled?: ((value: any) => T | PromiseLike<T>) | null, onrejected?: ((reason: any) => U | PromiseLike<U>) | null): Promise<T | U>;
101
110
  }
102
111
  declare class RpcClient {
103
112
  private request;
104
- constructor(request: RequestFn$2);
113
+ constructor(request: RequestFn$3);
105
114
  /** Call a Postgres function: rpc("my_function", { arg1: "value" }, { count: "exact" }) */
106
115
  call(fn: string, args?: Record<string, any>, options?: {
107
116
  count?: "exact" | "estimated" | "planned";
@@ -109,11 +118,11 @@ declare class RpcClient {
109
118
  }): Promise<QueryResult>;
110
119
  }
111
120
 
112
- type RequestFn$1 = (path: string, options?: RequestInit) => Promise<Response>;
121
+ type RequestFn$2 = (path: string, options?: RequestInit) => Promise<Response>;
113
122
  declare class StorageClient {
114
123
  private request;
115
124
  private baseUrl;
116
- constructor(request: RequestFn$1, baseUrl?: string);
125
+ constructor(request: RequestFn$2, baseUrl?: string);
117
126
  from(bucket: string): BucketClient;
118
127
  listBuckets(): Promise<{
119
128
  data: any[];
@@ -130,9 +139,11 @@ declare class BucketClient {
130
139
  private request;
131
140
  private bucket;
132
141
  private baseUrl;
133
- constructor(request: RequestFn$1, bucket: string, baseUrl?: string);
142
+ constructor(request: RequestFn$2, bucket: string, baseUrl?: string);
134
143
  upload(path: string, file: Blob | File | ArrayBuffer, options?: {
135
144
  contentType?: string;
145
+ upsert?: boolean;
146
+ headers?: Record<string, string>;
136
147
  }): Promise<{
137
148
  data: any;
138
149
  error: any;
@@ -141,11 +152,12 @@ declare class BucketClient {
141
152
  data: Blob | null;
142
153
  error: any;
143
154
  }>;
144
- list(): Promise<{
155
+ list(prefix?: string): Promise<{
145
156
  data: any[];
146
157
  error: any;
147
158
  }>;
148
- remove(path: string): Promise<{
159
+ remove(pathOrPaths: string | string[]): Promise<{
160
+ data: any;
149
161
  error: any;
150
162
  }>;
151
163
  getPublicUrl(path: string, options?: {
@@ -189,7 +201,7 @@ declare class BucketClient {
189
201
  }>;
190
202
  }
191
203
 
192
- type RequestFn = (path: string, options?: RequestInit) => Promise<Response>;
204
+ type RequestFn$1 = (path: string, options?: RequestInit) => Promise<Response>;
193
205
  type OAuthProvider = "google" | "github" | "apple" | "microsoft" | "linkedin" | "slack" | "gitlab" | "bitbucket" | "discord" | "facebook" | "twitter" | "reddit" | "twitch" | "tiktok" | "spotify" | "telegram" | "roblox";
194
206
  interface AuthSession {
195
207
  access_token: string;
@@ -206,6 +218,8 @@ interface AuthUser {
206
218
  role: string;
207
219
  raw_user_meta_data: Record<string, unknown>;
208
220
  raw_app_meta_data: Record<string, unknown>;
221
+ /** Alias for raw_user_meta_data (Supabase compatibility) */
222
+ user_metadata: Record<string, unknown>;
209
223
  created_at: string;
210
224
  updated_at: string;
211
225
  }
@@ -218,8 +232,13 @@ declare class AuthClient {
218
232
  * header when the user signs in/out or a token is refreshed.
219
233
  */
220
234
  onSessionChange: ((session: AuthSession | null) => void) | null;
221
- constructor(request: RequestFn);
222
- private setSession;
235
+ constructor(request: RequestFn$1);
236
+ /**
237
+ * Set (or clear) the current session. Use this to restore a persisted
238
+ * session on app launch (e.g., from AsyncStorage / SecureStore).
239
+ * Emits INITIAL_SESSION to onAuthStateChange listeners.
240
+ */
241
+ setSession(session: AuthSession | null): void;
223
242
  signUp(params: {
224
243
  email: string;
225
244
  password: string;
@@ -243,6 +262,14 @@ declare class AuthClient {
243
262
  data: AuthSession | null;
244
263
  error: any;
245
264
  }>;
265
+ signInWithIdToken(params: {
266
+ provider: OAuthProvider;
267
+ token: string;
268
+ nonce?: string;
269
+ }): Promise<{
270
+ data: AuthSession | null;
271
+ error: any;
272
+ }>;
246
273
  signInWithOAuth(params: {
247
274
  provider: OAuthProvider;
248
275
  redirectTo?: string;
@@ -372,6 +399,21 @@ declare class AuthClient {
372
399
  private parseAuthResponse;
373
400
  }
374
401
 
402
+ type RequestFn = (path: string, options?: RequestInit) => Promise<Response>;
403
+ interface FunctionInvokeOptions {
404
+ body?: Record<string, any>;
405
+ method?: "GET" | "POST";
406
+ headers?: Record<string, string>;
407
+ }
408
+ declare class FunctionsClient {
409
+ private request;
410
+ constructor(request: RequestFn);
411
+ invoke<T = any>(name: string, options?: FunctionInvokeOptions): Promise<{
412
+ data: T | null;
413
+ error: any;
414
+ }>;
415
+ }
416
+
375
417
  interface LinabaseConfig {
376
418
  url: string;
377
419
  anonKey?: string;
@@ -385,8 +427,15 @@ interface LinabaseClient {
385
427
  rpc: (fn: string, args?: Record<string, any>) => ReturnType<RpcClient["call"]>;
386
428
  storage: StorageClient;
387
429
  auth: AuthClient;
430
+ functions: FunctionsClient;
431
+ /** Realtime channel (stub; not yet supported). Returns a chainable no-op. */
432
+ channel: (name: string) => any;
433
+ /** Remove a realtime channel (stub; not yet supported). */
434
+ removeChannel: (channel: any) => void;
388
435
  generateTypes: () => Promise<string>;
436
+ /** Returns a new client that targets the given branch via X-Branch header. */
437
+ branch: (slug: string) => LinabaseClient;
389
438
  }
390
439
  declare function createClient(config: LinabaseConfig): LinabaseClient;
391
440
 
392
- export { AuthClient, BucketClient, type CsvQueryResult, DatabaseClient, type LinabaseClient, type LinabaseConfig, type OAuthProvider, type QueryResult, RpcClient, type SingleQueryResult, StorageClient, createClient };
441
+ export { AuthClient, type AuthSession, type AuthUser, BucketClient, type CsvQueryResult, DatabaseClient, type FunctionInvokeOptions, FunctionsClient, type LinabaseClient, type LinabaseConfig, type OAuthProvider, type PostgrestError, type QueryResult, RpcClient, type SingleQueryResult, StorageClient, createClient };
package/dist/index.js CHANGED
@@ -19,9 +19,11 @@ var DatabaseClient = class {
19
19
  }
20
20
  // ─── Query Methods ──────────────────────────────────────
21
21
  /** Select columns. Supports nested joins: "*, comments(*)" and aliases: "full_name:name" */
22
- select(columns) {
22
+ select(columns, options) {
23
23
  this.method = "GET";
24
24
  if (columns) this.params.set("select", columns);
25
+ if (options?.count) this.preferHeaders.push(`count=${options.count}`);
26
+ if (options?.head) this.method = "GET";
25
27
  return this;
26
28
  }
27
29
  insert(data) {
@@ -38,6 +40,9 @@ var DatabaseClient = class {
38
40
  this.preferHeaders.push(
39
41
  options?.ignoreDuplicates ? "resolution=ignore-duplicates" : "resolution=merge-duplicates"
40
42
  );
43
+ if (options?.onConflict) {
44
+ this.params.set("on_conflict", options.onConflict);
45
+ }
41
46
  return this;
42
47
  }
43
48
  update(data) {
@@ -84,9 +89,15 @@ var DatabaseClient = class {
84
89
  this.params.set(column, `ilike.${pattern}`);
85
90
  return this;
86
91
  }
87
- /** Regex match (~) */
88
- match(column, pattern) {
89
- this.params.set(column, `match.${pattern}`);
92
+ /** Regex match (~) when called with (column, pattern). Object-based multi-column filter when called with ({ col: val }). */
93
+ match(columnOrFilter, pattern) {
94
+ if (typeof columnOrFilter === "object") {
95
+ for (const [key, value] of Object.entries(columnOrFilter)) {
96
+ this.eq(key, value);
97
+ }
98
+ } else if (pattern !== void 0) {
99
+ this.params.set(columnOrFilter, `match.${pattern}`);
100
+ }
90
101
  return this;
91
102
  }
92
103
  /** Case-insensitive regex match (~*) */
@@ -116,7 +127,8 @@ var DatabaseClient = class {
116
127
  }
117
128
  // ─── Null/Boolean ───────────────────────────────────────
118
129
  is(column, value) {
119
- this.params.set(column, `is.${value}`);
130
+ const v = value === null ? "null" : String(value);
131
+ this.params.set(column, `is.${v}`);
120
132
  return this;
121
133
  }
122
134
  /** IS DISTINCT FROM */
@@ -308,8 +320,13 @@ var DatabaseClient = class {
308
320
  this.reset();
309
321
  }
310
322
  }
311
- then(resolve, reject) {
312
- return this.execute().then(resolve, reject);
323
+ /**
324
+ * Makes DatabaseClient thenable (await-able). Resolves to
325
+ * `{ data, error, count }` where data is permissively typed so
326
+ * callers can access properties without generated database types.
327
+ */
328
+ then(onfulfilled, onrejected) {
329
+ return this.execute().then(onfulfilled, onrejected);
313
330
  }
314
331
  };
315
332
  var RpcClient = class {
@@ -423,7 +440,7 @@ var BucketClient = class {
423
440
  `/storage/${this.bucket}/${path}`
424
441
  );
425
442
  if (!res.ok) {
426
- const err = await res.json().catch(() => ({}));
443
+ const err = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
427
444
  return { data: null, error: err };
428
445
  }
429
446
  const blob = await res.blob();
@@ -432,30 +449,37 @@ var BucketClient = class {
432
449
  return { data: null, error: { message: err.message } };
433
450
  }
434
451
  }
435
- async list() {
452
+ async list(prefix) {
436
453
  try {
437
- const res = await this.request(
438
- `/api/storage/objects?bucketName=${this.bucket}`
439
- );
454
+ let url = `/api/storage/objects?bucketName=${this.bucket}`;
455
+ if (prefix) url += `&prefix=${encodeURIComponent(prefix)}`;
456
+ const res = await this.request(url);
440
457
  const data = await res.json();
441
458
  return { data: data.objects || [], error: null };
442
459
  } catch (err) {
443
460
  return { data: [], error: { message: err.message } };
444
461
  }
445
462
  }
446
- async remove(path) {
463
+ async remove(pathOrPaths) {
464
+ const paths = Array.isArray(pathOrPaths) ? pathOrPaths : [pathOrPaths];
447
465
  try {
448
- const res = await this.request(
449
- `/storage/${this.bucket}/${path}`,
450
- { method: "DELETE" }
466
+ const results = await Promise.all(
467
+ paths.map(async (p) => {
468
+ const res = await this.request(
469
+ `/storage/${this.bucket}/${p}`,
470
+ { method: "DELETE" }
471
+ );
472
+ if (!res.ok) {
473
+ const data = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
474
+ return { error: data };
475
+ }
476
+ return { error: null };
477
+ })
451
478
  );
452
- if (!res.ok) {
453
- const data = await res.json().catch(() => ({}));
454
- return { error: data };
455
- }
456
- return { error: null };
479
+ const firstError = results.find((r) => r.error);
480
+ return { data: firstError ? null : paths, error: firstError?.error ?? null };
457
481
  } catch (err) {
458
- return { error: { message: err.message } };
482
+ return { data: null, error: { message: err.message } };
459
483
  }
460
484
  }
461
485
  getPublicUrl(path, options) {
@@ -529,7 +553,7 @@ var BucketClient = class {
529
553
  body: JSON.stringify({ from: fromPath, to: toPath })
530
554
  });
531
555
  if (!res.ok) {
532
- const data = await res.json().catch(() => ({}));
556
+ const data = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
533
557
  return { error: data };
534
558
  }
535
559
  return { error: null };
@@ -544,7 +568,7 @@ var BucketClient = class {
544
568
  body: JSON.stringify({ from: fromPath, to: toPath })
545
569
  });
546
570
  if (!res.ok) {
547
- const data = await res.json().catch(() => ({}));
571
+ const data = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
548
572
  return { error: data };
549
573
  }
550
574
  return { error: null };
@@ -567,9 +591,15 @@ var AuthClient = class {
567
591
  constructor(request) {
568
592
  this.request = request;
569
593
  }
594
+ /**
595
+ * Set (or clear) the current session. Use this to restore a persisted
596
+ * session on app launch (e.g., from AsyncStorage / SecureStore).
597
+ * Emits INITIAL_SESSION to onAuthStateChange listeners.
598
+ */
570
599
  setSession(session) {
571
600
  this.currentSession = session;
572
601
  if (this.onSessionChange) this.onSessionChange(session);
602
+ this.emit("INITIAL_SESSION", session);
573
603
  }
574
604
  // ─── Email/Password ────────────────────────────────────────
575
605
  async signUp(params) {
@@ -608,6 +638,27 @@ var AuthClient = class {
608
638
  async signInWithPassword(params) {
609
639
  return this.signIn(params);
610
640
  }
641
+ // ─── ID Token (Mobile OAuth) ────────────────────────────────
642
+ async signInWithIdToken(params) {
643
+ try {
644
+ const res = await this.request("/auth/v1/token?grant_type=id_token", {
645
+ method: "POST",
646
+ body: JSON.stringify({
647
+ provider: params.provider,
648
+ id_token: params.token,
649
+ nonce: params.nonce
650
+ })
651
+ });
652
+ const data = await res.json();
653
+ if (!res.ok) return { data: null, error: data };
654
+ const session = this.parseAuthResponse(data);
655
+ this.setSession(session);
656
+ this.emit("SIGNED_IN", session);
657
+ return { data: session, error: null };
658
+ } catch (err) {
659
+ return { data: null, error: { message: err.message } };
660
+ }
661
+ }
611
662
  // ─── OAuth ─────────────────────────────────────────────────
612
663
  signInWithOAuth(params) {
613
664
  const queryParams = new URLSearchParams({ provider: params.provider });
@@ -804,7 +855,7 @@ var AuthClient = class {
804
855
  method: "DELETE"
805
856
  });
806
857
  if (!res.ok) {
807
- const data = await res.json().catch(() => ({}));
858
+ const data = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
808
859
  return { error: data };
809
860
  }
810
861
  return { error: null };
@@ -862,7 +913,7 @@ var AuthClient = class {
862
913
  method: "DELETE"
863
914
  });
864
915
  if (!res.ok) {
865
- const data = await res.json().catch(() => ({}));
916
+ const data = await res.json().catch(() => ({ message: `Request failed (${res.status})` }));
866
917
  return { error: data };
867
918
  }
868
919
  return { error: null };
@@ -897,17 +948,53 @@ var AuthClient = class {
897
948
  }
898
949
  }
899
950
  parseAuthResponse(data) {
951
+ const user = data.user || {};
900
952
  return {
901
953
  access_token: data.session?.access_token || data.access_token,
902
954
  refresh_token: data.session?.refresh_token || data.refresh_token,
903
955
  token_type: data.session?.token_type || data.token_type || "bearer",
904
956
  expires_in: data.session?.expires_in || data.expires_in || 3600,
905
957
  expires_at: data.session?.expires_at || data.expires_at || Math.floor(Date.now() / 1e3) + 3600,
906
- user: data.user || {}
958
+ user: {
959
+ ...user,
960
+ // Supabase-compatible alias
961
+ user_metadata: user.raw_user_meta_data || user.user_metadata || {}
962
+ }
907
963
  };
908
964
  }
909
965
  };
910
966
 
967
+ // src/functions.ts
968
+ var FunctionsClient = class {
969
+ request;
970
+ constructor(request) {
971
+ this.request = request;
972
+ }
973
+ async invoke(name, options) {
974
+ try {
975
+ const method = options?.method || "POST";
976
+ const init = { method, headers: options?.headers };
977
+ if (options?.body && method !== "GET") {
978
+ init.body = JSON.stringify(options.body);
979
+ }
980
+ let path = `/functions/v1/${name}`;
981
+ if (options?.body && method === "GET") {
982
+ const params = new URLSearchParams();
983
+ for (const [k, v] of Object.entries(options.body)) {
984
+ if (v !== void 0 && v !== null) params.set(k, String(v));
985
+ }
986
+ path += `?${params}`;
987
+ }
988
+ const res = await this.request(path, init);
989
+ const data = await res.json();
990
+ if (!res.ok) return { data: null, error: data };
991
+ return { data, error: null };
992
+ } catch (err) {
993
+ return { data: null, error: { message: err.message } };
994
+ }
995
+ }
996
+ };
997
+
911
998
  // src/client.ts
912
999
  function createClient(config) {
913
1000
  const baseUrl = config.url.replace(/\/$/, "");
@@ -931,36 +1018,67 @@ function createClient(config) {
931
1018
  headers: mergedHeaders
932
1019
  });
933
1020
  }
934
- const rpcClient = new RpcClient(request);
935
1021
  const authClient = new AuthClient(request);
936
1022
  authClient.onSessionChange = (session) => {
937
1023
  accessToken = session?.access_token || null;
938
1024
  };
939
- return {
940
- from: (table) => new DatabaseClient(request, table),
941
- schema: (schemaName) => ({
942
- from: (table) => {
943
- const client = new DatabaseClient(request, table);
944
- client._schema = schemaName;
945
- return client;
1025
+ function buildClient(reqFn, branchSlug) {
1026
+ const rc = new RpcClient(reqFn);
1027
+ const ac = new AuthClient(reqFn);
1028
+ ac.onSessionChange = (session) => {
1029
+ accessToken = session?.access_token || null;
1030
+ };
1031
+ return {
1032
+ from: (table) => new DatabaseClient(reqFn, table),
1033
+ schema: (schemaName) => ({
1034
+ from: (table) => {
1035
+ const client = new DatabaseClient(reqFn, table);
1036
+ client._schema = schemaName;
1037
+ return client;
1038
+ }
1039
+ }),
1040
+ rpc: (fn, args) => rc.call(fn, args),
1041
+ storage: new StorageClient(reqFn, baseUrl),
1042
+ auth: branchSlug ? authClient : ac,
1043
+ functions: new FunctionsClient(reqFn),
1044
+ /** Realtime channel (stub; not yet supported). Returns a chainable no-op. */
1045
+ channel: (_name) => {
1046
+ const noop = { on: () => noop, subscribe: () => noop, unsubscribe: () => {
1047
+ } };
1048
+ return noop;
1049
+ },
1050
+ /** Remove a realtime channel (stub; not yet supported). */
1051
+ removeChannel: (_channel) => {
1052
+ },
1053
+ generateTypes: async () => {
1054
+ const restUrl = baseUrl.replace(/:3100/, ":3107");
1055
+ const headers = { Authorization: `Bearer ${apiKey}` };
1056
+ if (branchSlug) headers["X-Branch"] = branchSlug;
1057
+ const res = await fetch(`${restUrl}/rest/v1/types`, { headers });
1058
+ return res.text();
1059
+ },
1060
+ branch: (slug) => {
1061
+ if (branchSlug) throw new Error("Cannot nest branch() calls");
1062
+ function branchRequest(path, options = {}) {
1063
+ return reqFn(path, {
1064
+ ...options,
1065
+ headers: {
1066
+ ...options.headers,
1067
+ "X-Branch": slug
1068
+ }
1069
+ });
1070
+ }
1071
+ return buildClient(branchRequest, slug);
946
1072
  }
947
- }),
948
- rpc: (fn, args) => rpcClient.call(fn, args),
949
- storage: new StorageClient(request, baseUrl),
950
- auth: authClient,
951
- generateTypes: async () => {
952
- const restUrl = baseUrl.replace(/:3100/, ":3107");
953
- const res = await fetch(`${restUrl}/rest/v1/types`, {
954
- headers: { Authorization: `Bearer ${apiKey}` }
955
- });
956
- return res.text();
957
- }
958
- };
1073
+ };
1074
+ }
1075
+ return buildClient(request);
959
1076
  }
960
1077
  export {
961
1078
  AuthClient,
962
1079
  BucketClient,
963
1080
  DatabaseClient,
1081
+ FunctionsClient,
964
1082
  RpcClient,
965
1083
  StorageClient,
966
1084
  createClient
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linabase/js",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "JavaScript/TypeScript client SDK for Linabase (database, storage, auth)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -47,6 +47,7 @@
47
47
  "@linabase/db": "workspace:*",
48
48
  "@linabase/rest-api": "workspace:*",
49
49
  "@types/pg": "^8.11.0",
50
+ "@vitest/coverage-v8": "^3.2.4",
50
51
  "pg": "^8.13.0",
51
52
  "tsup": "^8.3.0",
52
53
  "typescript": "^5.7.0",