@linabase/js 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,442 @@
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
+ }
8
+ interface QueryResult<T = any> {
9
+ data: T[] | null;
10
+ error: PostgrestError | null;
11
+ count: number | null;
12
+ }
13
+ interface SingleQueryResult<T = any> {
14
+ data: T | null;
15
+ error: PostgrestError | null;
16
+ count: number | null;
17
+ }
18
+ interface CsvQueryResult {
19
+ data: string | null;
20
+ error: PostgrestError | null;
21
+ count: number | null;
22
+ }
23
+ declare class DatabaseClient {
24
+ private request;
25
+ private table;
26
+ private params;
27
+ private method;
28
+ private body;
29
+ private preferHeaders;
30
+ private _single;
31
+ private _maybeSingle;
32
+ private _throwOnError;
33
+ private _csv;
34
+ private _abortSignal;
35
+ private _schema;
36
+ constructor(request: RequestFn$3, table: string);
37
+ /** Select columns. Supports nested joins: "*, comments(*)" and aliases: "full_name:name" */
38
+ select(columns?: string, options?: {
39
+ count?: "exact" | "estimated" | "planned";
40
+ head?: boolean;
41
+ }): this;
42
+ insert(data: Record<string, any> | Record<string, any>[]): this;
43
+ /** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
44
+ upsert(data: Record<string, any> | Record<string, any>[], options?: {
45
+ ignoreDuplicates?: boolean;
46
+ onConflict?: string;
47
+ }): this;
48
+ update(data: Record<string, any>): this;
49
+ delete(): this;
50
+ eq(column: string, value: any): this;
51
+ neq(column: string, value: any): this;
52
+ gt(column: string, value: any): this;
53
+ gte(column: string, value: any): this;
54
+ lt(column: string, value: any): this;
55
+ lte(column: string, value: any): this;
56
+ like(column: string, pattern: string): this;
57
+ ilike(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;
60
+ /** Case-insensitive regex match (~*) */
61
+ imatch(column: string, pattern: string): this;
62
+ in(column: string, values: any[]): this;
63
+ /** Contains (@>) - array or JSONB containment */
64
+ contains(column: string, value: any): this;
65
+ /** Contained by (<@) */
66
+ containedBy(column: string, value: any): this;
67
+ /** Overlap (&&) - ranges or arrays */
68
+ overlaps(column: string, value: any): this;
69
+ is(column: string, value: "null" | "true" | "false" | null | boolean): this;
70
+ /** IS DISTINCT FROM */
71
+ isDistinct(column: string, value: any): this;
72
+ /** Negate a filter: not.eq, not.in, not.is, etc. */
73
+ not(column: string, operator: string, value: any): this;
74
+ /** OR filter: or("age.gt.20,name.eq.John") */
75
+ or(filters: string): this;
76
+ /** to_tsquery */
77
+ textSearch(column: string, query: string, options?: {
78
+ type?: "plain" | "phrase" | "websearch";
79
+ }): this;
80
+ order(column: string, options?: {
81
+ ascending?: boolean;
82
+ nullsFirst?: boolean;
83
+ }): this;
84
+ limit(count: number): this;
85
+ offset(count: number): this;
86
+ /** Request exact, estimated, or planned count via Prefer header */
87
+ count(type?: "exact" | "estimated" | "planned"): this;
88
+ /** Return a single object instead of an array. Errors if 0 or >1 rows. */
89
+ single(): this;
90
+ /** Return a single object or null. Errors only if >1 rows. */
91
+ maybeSingle(): this;
92
+ /** Range-based pagination: range(0, 9) fetches the first 10 rows. */
93
+ range(from: number, to: number): this;
94
+ /** Throw an error instead of returning it in the result object. */
95
+ throwOnError(): this;
96
+ /** Request CSV format. Returns raw CSV text in data instead of parsed objects. */
97
+ csv(): this;
98
+ /** Pass an AbortSignal for request cancellation. */
99
+ abortSignal(signal: AbortSignal): this;
100
+ /** Switch schema. Sets Accept-Profile (GET) or Content-Profile (POST/PATCH/DELETE). */
101
+ schema(schemaName: string): this;
102
+ private reset;
103
+ execute(): Promise<QueryResult | SingleQueryResult | CsvQueryResult>;
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>;
110
+ }
111
+ declare class RpcClient {
112
+ private request;
113
+ constructor(request: RequestFn$3);
114
+ /** Call a Postgres function: rpc("my_function", { arg1: "value" }, { count: "exact" }) */
115
+ call(fn: string, args?: Record<string, any>, options?: {
116
+ count?: "exact" | "estimated" | "planned";
117
+ throwOnError?: boolean;
118
+ }): Promise<QueryResult>;
119
+ }
120
+
121
+ type RequestFn$2 = (path: string, options?: RequestInit) => Promise<Response>;
122
+ declare class StorageClient {
123
+ private request;
124
+ private baseUrl;
125
+ constructor(request: RequestFn$2, baseUrl?: string);
126
+ from(bucket: string): BucketClient;
127
+ listBuckets(): Promise<{
128
+ data: any[];
129
+ error: any;
130
+ }>;
131
+ createBucket(name: string, options?: {
132
+ public?: boolean;
133
+ }): Promise<{
134
+ data: any;
135
+ error: any;
136
+ }>;
137
+ }
138
+ declare class BucketClient {
139
+ private request;
140
+ private bucket;
141
+ private baseUrl;
142
+ constructor(request: RequestFn$2, bucket: string, baseUrl?: string);
143
+ upload(path: string, file: Blob | File | ArrayBuffer, options?: {
144
+ contentType?: string;
145
+ upsert?: boolean;
146
+ headers?: Record<string, string>;
147
+ }): Promise<{
148
+ data: any;
149
+ error: any;
150
+ }>;
151
+ download(path: string): Promise<{
152
+ data: Blob | null;
153
+ error: any;
154
+ }>;
155
+ list(prefix?: string): Promise<{
156
+ data: any[];
157
+ error: any;
158
+ }>;
159
+ remove(pathOrPaths: string | string[]): Promise<{
160
+ data: any;
161
+ error: any;
162
+ }>;
163
+ getPublicUrl(path: string, options?: {
164
+ transform?: {
165
+ width?: number;
166
+ height?: number;
167
+ quality?: number;
168
+ format?: string;
169
+ };
170
+ }): {
171
+ data: {
172
+ publicUrl: string;
173
+ };
174
+ };
175
+ createSignedUrl(path: string, expiresIn: number): Promise<{
176
+ data: {
177
+ signedUrl: string;
178
+ } | null;
179
+ error: any;
180
+ }>;
181
+ createSignedUrls(paths: string[], expiresIn: number): Promise<{
182
+ data: Array<{
183
+ path: string;
184
+ signedUrl: string;
185
+ }> | null;
186
+ error: any;
187
+ }>;
188
+ createSignedUploadUrl(path: string): Promise<{
189
+ data: {
190
+ signedUrl: string;
191
+ token: string;
192
+ path: string;
193
+ } | null;
194
+ error: any;
195
+ }>;
196
+ move(fromPath: string, toPath: string): Promise<{
197
+ error: any;
198
+ }>;
199
+ copy(fromPath: string, toPath: string): Promise<{
200
+ error: any;
201
+ }>;
202
+ }
203
+
204
+ type RequestFn$1 = (path: string, options?: RequestInit) => Promise<Response>;
205
+ type OAuthProvider = "google" | "github" | "apple" | "microsoft" | "linkedin" | "slack" | "gitlab" | "bitbucket" | "discord" | "facebook" | "twitter" | "reddit" | "twitch" | "tiktok" | "spotify" | "telegram" | "roblox";
206
+ interface AuthSession {
207
+ access_token: string;
208
+ refresh_token: string;
209
+ token_type: string;
210
+ expires_in: number;
211
+ expires_at: number;
212
+ user: AuthUser;
213
+ }
214
+ interface AuthUser {
215
+ id: string;
216
+ email: string | null;
217
+ email_confirmed_at: string | null;
218
+ role: string;
219
+ raw_user_meta_data: Record<string, unknown>;
220
+ raw_app_meta_data: Record<string, unknown>;
221
+ /** Alias for raw_user_meta_data (Supabase compatibility) */
222
+ user_metadata: Record<string, unknown>;
223
+ created_at: string;
224
+ updated_at: string;
225
+ }
226
+ declare class AuthClient {
227
+ private request;
228
+ private listeners;
229
+ private currentSession;
230
+ /**
231
+ * Callback that the parent LinabaseClient can set to update the Authorization
232
+ * header when the user signs in/out or a token is refreshed.
233
+ */
234
+ onSessionChange: ((session: AuthSession | null) => void) | null;
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 when called externally.
240
+ * Internal callers (signIn, signUp, etc.) pass _internal=true to skip the emit.
241
+ */
242
+ setSession(session: AuthSession | null, _internal?: boolean): void;
243
+ signUp(params: {
244
+ email: string;
245
+ password: string;
246
+ data?: Record<string, unknown>;
247
+ }): Promise<{
248
+ data: AuthSession | null;
249
+ error: any;
250
+ }>;
251
+ signIn(params: {
252
+ email: string;
253
+ password: string;
254
+ }): Promise<{
255
+ data: AuthSession | null;
256
+ error: any;
257
+ }>;
258
+ /** Supabase-compatible alias for signIn */
259
+ signInWithPassword(params: {
260
+ email: string;
261
+ password: string;
262
+ }): Promise<{
263
+ data: AuthSession | null;
264
+ error: any;
265
+ }>;
266
+ signInWithIdToken(params: {
267
+ provider: OAuthProvider;
268
+ token: string;
269
+ nonce?: string;
270
+ }): Promise<{
271
+ data: AuthSession | null;
272
+ error: any;
273
+ }>;
274
+ signInWithOAuth(params: {
275
+ provider: OAuthProvider;
276
+ redirectTo?: string;
277
+ }): {
278
+ url: string;
279
+ };
280
+ signOut(): Promise<{
281
+ error: any;
282
+ }>;
283
+ getSession(): Promise<{
284
+ data: {
285
+ session: AuthSession | null;
286
+ };
287
+ error: any;
288
+ }>;
289
+ getUser(): Promise<{
290
+ data: {
291
+ user: AuthUser | null;
292
+ };
293
+ error: any;
294
+ }>;
295
+ refreshSession(): Promise<{
296
+ data: AuthSession | null;
297
+ error: any;
298
+ }>;
299
+ resetPasswordForEmail(email: string, _options?: {
300
+ redirectTo?: string;
301
+ }): Promise<{
302
+ error: any;
303
+ }>;
304
+ updatePassword(newPassword: string): Promise<{
305
+ error: any;
306
+ }>;
307
+ updateUser(attributes: {
308
+ email?: string;
309
+ password?: string;
310
+ data?: Record<string, any>;
311
+ }): Promise<{
312
+ data: {
313
+ user: AuthUser | null;
314
+ };
315
+ error: any;
316
+ }>;
317
+ signInWithOtp(params: {
318
+ email: string;
319
+ options?: {
320
+ emailRedirectTo?: string;
321
+ };
322
+ }): Promise<{
323
+ data: any;
324
+ error: any;
325
+ }>;
326
+ verifyOtp(params: {
327
+ email?: string;
328
+ phone?: string;
329
+ token: string;
330
+ type?: "email" | "sms" | "magiclink" | "signup" | "recovery";
331
+ }): Promise<{
332
+ data: any;
333
+ error: any;
334
+ }>;
335
+ get admin(): {
336
+ listUsers(params?: {
337
+ page?: number;
338
+ per_page?: number;
339
+ }): Promise<{
340
+ data: any;
341
+ error: any;
342
+ }>;
343
+ createUser(params: {
344
+ email: string;
345
+ password?: string;
346
+ user_metadata?: Record<string, any>;
347
+ email_confirm?: boolean;
348
+ }): Promise<{
349
+ data: any;
350
+ error: any;
351
+ }>;
352
+ getUserById(id: string): Promise<{
353
+ data: any;
354
+ error: any;
355
+ }>;
356
+ updateUserById(id: string, attributes: Record<string, any>): Promise<{
357
+ data: any;
358
+ error: any;
359
+ }>;
360
+ deleteUser(id: string): Promise<{
361
+ error: any;
362
+ }>;
363
+ };
364
+ get mfa(): {
365
+ enroll(params: {
366
+ factorType: "totp";
367
+ friendlyName?: string;
368
+ }): Promise<{
369
+ data: any;
370
+ error: any;
371
+ }>;
372
+ challenge(params: {
373
+ factorId: string;
374
+ }): Promise<{
375
+ data: any;
376
+ error: any;
377
+ }>;
378
+ verify(params: {
379
+ factorId: string;
380
+ challengeId: string;
381
+ code: string;
382
+ }): Promise<{
383
+ data: any;
384
+ error: any;
385
+ }>;
386
+ unenroll(params: {
387
+ factorId: string;
388
+ }): Promise<{
389
+ error: any;
390
+ }>;
391
+ listFactors(): Promise<{
392
+ data: any;
393
+ error: any;
394
+ }>;
395
+ };
396
+ onAuthStateChange(callback: (event: string, session: AuthSession | null) => void): {
397
+ unsubscribe: () => void;
398
+ };
399
+ private emit;
400
+ private parseAuthResponse;
401
+ }
402
+
403
+ type RequestFn = (path: string, options?: RequestInit) => Promise<Response>;
404
+ interface FunctionInvokeOptions {
405
+ body?: Record<string, any>;
406
+ method?: "GET" | "POST";
407
+ headers?: Record<string, string>;
408
+ }
409
+ declare class FunctionsClient {
410
+ private request;
411
+ constructor(request: RequestFn);
412
+ invoke<T = any>(name: string, options?: FunctionInvokeOptions): Promise<{
413
+ data: T | null;
414
+ error: any;
415
+ }>;
416
+ }
417
+
418
+ interface LinabaseConfig {
419
+ url: string;
420
+ anonKey?: string;
421
+ serviceRoleKey?: string;
422
+ }
423
+ interface LinabaseClient {
424
+ from: (table: string) => DatabaseClient;
425
+ schema: (schemaName: string) => {
426
+ from: (table: string) => DatabaseClient;
427
+ };
428
+ rpc: (fn: string, args?: Record<string, any>) => ReturnType<RpcClient["call"]>;
429
+ storage: StorageClient;
430
+ auth: AuthClient;
431
+ functions: FunctionsClient;
432
+ /** Realtime channel (stub; not yet supported). Returns a chainable no-op. */
433
+ channel: (name: string) => any;
434
+ /** Remove a realtime channel (stub; not yet supported). */
435
+ removeChannel: (channel: any) => void;
436
+ generateTypes: () => Promise<string>;
437
+ /** Returns a new client that targets the given branch via X-Branch header. */
438
+ branch: (slug: string) => LinabaseClient;
439
+ }
440
+ declare function createClient(config: LinabaseConfig): LinabaseClient;
441
+
442
+ 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.d.ts CHANGED
@@ -236,9 +236,10 @@ declare class AuthClient {
236
236
  /**
237
237
  * Set (or clear) the current session. Use this to restore a persisted
238
238
  * session on app launch (e.g., from AsyncStorage / SecureStore).
239
- * Emits INITIAL_SESSION to onAuthStateChange listeners.
239
+ * Emits INITIAL_SESSION to onAuthStateChange listeners when called externally.
240
+ * Internal callers (signIn, signUp, etc.) pass _internal=true to skip the emit.
240
241
  */
241
- setSession(session: AuthSession | null): void;
242
+ setSession(session: AuthSession | null, _internal?: boolean): void;
242
243
  signUp(params: {
243
244
  email: string;
244
245
  password: string;
package/dist/index.js CHANGED
@@ -159,7 +159,12 @@ var DatabaseClient = class {
159
159
  order(column, options) {
160
160
  const dir = options?.ascending === false ? "desc" : "asc";
161
161
  const nulls = options?.nullsFirst === true ? ".nullsfirst" : options?.nullsFirst === false ? ".nullslast" : "";
162
- this.params.set("order", `${column}.${dir}${nulls}`);
162
+ const existing = this.params.get("order");
163
+ if (existing) {
164
+ this.params.set("order", `${existing},${column}.${dir}${nulls}`);
165
+ } else {
166
+ this.params.set("order", `${column}.${dir}${nulls}`);
167
+ }
163
168
  return this;
164
169
  }
165
170
  limit(count) {
@@ -594,12 +599,13 @@ var AuthClient = class {
594
599
  /**
595
600
  * Set (or clear) the current session. Use this to restore a persisted
596
601
  * session on app launch (e.g., from AsyncStorage / SecureStore).
597
- * Emits INITIAL_SESSION to onAuthStateChange listeners.
602
+ * Emits INITIAL_SESSION to onAuthStateChange listeners when called externally.
603
+ * Internal callers (signIn, signUp, etc.) pass _internal=true to skip the emit.
598
604
  */
599
- setSession(session) {
605
+ setSession(session, _internal) {
600
606
  this.currentSession = session;
601
607
  if (this.onSessionChange) this.onSessionChange(session);
602
- this.emit("INITIAL_SESSION", session);
608
+ if (!_internal) this.emit("INITIAL_SESSION", session);
603
609
  }
604
610
  // ─── Email/Password ────────────────────────────────────────
605
611
  async signUp(params) {
@@ -611,7 +617,7 @@ var AuthClient = class {
611
617
  const data = await res.json();
612
618
  if (!res.ok) return { data: null, error: data };
613
619
  const session = this.parseAuthResponse(data);
614
- this.setSession(session);
620
+ this.setSession(session, true);
615
621
  this.emit("SIGNED_IN", session);
616
622
  return { data: session, error: null };
617
623
  } catch (err) {
@@ -627,7 +633,7 @@ var AuthClient = class {
627
633
  const data = await res.json();
628
634
  if (!res.ok) return { data: null, error: data };
629
635
  const session = this.parseAuthResponse(data);
630
- this.setSession(session);
636
+ this.setSession(session, true);
631
637
  this.emit("SIGNED_IN", session);
632
638
  return { data: session, error: null };
633
639
  } catch (err) {
@@ -652,7 +658,7 @@ var AuthClient = class {
652
658
  const data = await res.json();
653
659
  if (!res.ok) return { data: null, error: data };
654
660
  const session = this.parseAuthResponse(data);
655
- this.setSession(session);
661
+ this.setSession(session, true);
656
662
  this.emit("SIGNED_IN", session);
657
663
  return { data: session, error: null };
658
664
  } catch (err) {
@@ -673,7 +679,7 @@ var AuthClient = class {
673
679
  async signOut() {
674
680
  try {
675
681
  await this.request("/auth/v1/logout", { method: "POST" });
676
- this.setSession(null);
682
+ this.setSession(null, true);
677
683
  this.emit("SIGNED_OUT", null);
678
684
  return { error: null };
679
685
  } catch (err) {
@@ -713,12 +719,12 @@ var AuthClient = class {
713
719
  });
714
720
  const data = await res.json();
715
721
  if (!res.ok) {
716
- this.setSession(null);
722
+ this.setSession(null, true);
717
723
  this.emit("SIGNED_OUT", null);
718
724
  return { data: null, error: data };
719
725
  }
720
726
  const session = this.parseAuthResponse(data);
721
- this.setSession(session);
727
+ this.setSession(session, true);
722
728
  this.emit("TOKEN_REFRESHED", session);
723
729
  return { data: session, error: null };
724
730
  } catch (err) {
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@linabase/js",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "JavaScript/TypeScript client SDK for Linabase (database, storage, auth)",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
- "main": "./dist/index.js",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
8
9
  "types": "./dist/index.d.ts",
9
10
  "exports": {
10
11
  ".": {
11
12
  "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs",
12
14
  "types": "./dist/index.d.ts"
13
15
  }
14
16
  },