krisspy-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,921 @@
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
+ HttpClient: () => HttpClient,
24
+ KrisspyAuth: () => KrisspyAuth,
25
+ KrisspyClient: () => KrisspyClient,
26
+ QueryBuilder: () => QueryBuilder,
27
+ createClient: () => createClient
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/http.ts
32
+ var HttpClient = class {
33
+ constructor(options) {
34
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
35
+ this.headers = {
36
+ "Content-Type": "application/json",
37
+ ...options.headers
38
+ };
39
+ this.debug = options.debug ?? false;
40
+ }
41
+ /**
42
+ * Set authorization header
43
+ */
44
+ setAuth(token) {
45
+ this.headers["Authorization"] = `Bearer ${token}`;
46
+ }
47
+ /**
48
+ * Remove authorization header
49
+ */
50
+ clearAuth() {
51
+ delete this.headers["Authorization"];
52
+ }
53
+ /**
54
+ * Update headers
55
+ */
56
+ setHeaders(headers) {
57
+ this.headers = { ...this.headers, ...headers };
58
+ }
59
+ /**
60
+ * Build query string from params
61
+ */
62
+ buildQueryString(params) {
63
+ const parts = [];
64
+ for (const [key, value] of Object.entries(params)) {
65
+ if (value === void 0 || value === null) continue;
66
+ if (Array.isArray(value)) {
67
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value.join(","))}`);
68
+ } else {
69
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
70
+ }
71
+ }
72
+ return parts.length > 0 ? `?${parts.join("&")}` : "";
73
+ }
74
+ /**
75
+ * Make HTTP request
76
+ */
77
+ async request(method, path, options) {
78
+ const url = `${this.baseUrl}${path}${options?.params ? this.buildQueryString(options.params) : ""}`;
79
+ const requestHeaders = {
80
+ ...this.headers,
81
+ ...options?.headers
82
+ };
83
+ if (this.debug) {
84
+ console.log(`[Krisspy SDK] ${method} ${url}`);
85
+ if (options?.body) {
86
+ console.log("[Krisspy SDK] Body:", JSON.stringify(options.body, null, 2));
87
+ }
88
+ }
89
+ try {
90
+ const response = await fetch(url, {
91
+ method,
92
+ headers: requestHeaders,
93
+ body: options?.body ? JSON.stringify(options.body) : void 0
94
+ });
95
+ const contentType = response.headers.get("content-type");
96
+ let data = null;
97
+ if (contentType?.includes("application/json")) {
98
+ data = await response.json();
99
+ } else {
100
+ data = await response.text();
101
+ }
102
+ if (this.debug) {
103
+ console.log(`[Krisspy SDK] Response ${response.status}:`, data);
104
+ }
105
+ if (!response.ok) {
106
+ const error = {
107
+ message: data?.error || data?.message || "Request failed",
108
+ code: data?.code,
109
+ details: data?.details,
110
+ hint: data?.hint,
111
+ status: response.status
112
+ };
113
+ return { data: null, error, status: response.status };
114
+ }
115
+ return { data, error: null, status: response.status };
116
+ } catch (err) {
117
+ if (this.debug) {
118
+ console.error("[Krisspy SDK] Error:", err);
119
+ }
120
+ const error = {
121
+ message: err.message || "Network error",
122
+ code: "NETWORK_ERROR",
123
+ status: 0
124
+ };
125
+ return { data: null, error, status: 0 };
126
+ }
127
+ }
128
+ /**
129
+ * GET request
130
+ */
131
+ async get(path, params) {
132
+ return this.request("GET", path, { params });
133
+ }
134
+ /**
135
+ * POST request
136
+ */
137
+ async post(path, body, params) {
138
+ return this.request("POST", path, { body, params });
139
+ }
140
+ /**
141
+ * PATCH request
142
+ */
143
+ async patch(path, body, params) {
144
+ return this.request("PATCH", path, { body, params });
145
+ }
146
+ /**
147
+ * PUT request
148
+ */
149
+ async put(path, body, params) {
150
+ return this.request("PUT", path, { body, params });
151
+ }
152
+ /**
153
+ * DELETE request
154
+ */
155
+ async delete(path, params) {
156
+ return this.request("DELETE", path, { params });
157
+ }
158
+ };
159
+
160
+ // src/auth.ts
161
+ var STORAGE_KEY = "krisspy-auth-session";
162
+ var KrisspyAuth = class {
163
+ constructor(http, backendId) {
164
+ this.currentSession = null;
165
+ this.currentUser = null;
166
+ this.listeners = [];
167
+ this.http = http;
168
+ this.backendId = backendId;
169
+ this.restoreSession();
170
+ }
171
+ /**
172
+ * Get current session from storage
173
+ */
174
+ restoreSession() {
175
+ if (typeof window === "undefined") return;
176
+ try {
177
+ const stored = localStorage.getItem(`${STORAGE_KEY}-${this.backendId}`);
178
+ if (stored) {
179
+ const session = JSON.parse(stored);
180
+ if (session.expires_at && Date.now() > session.expires_at * 1e3) {
181
+ this.clearSession();
182
+ return;
183
+ }
184
+ this.setSession(session);
185
+ }
186
+ } catch (err) {
187
+ console.warn("[Krisspy Auth] Failed to restore session:", err);
188
+ }
189
+ }
190
+ /**
191
+ * Store session
192
+ */
193
+ saveSession(session) {
194
+ if (typeof window === "undefined") return;
195
+ try {
196
+ localStorage.setItem(`${STORAGE_KEY}-${this.backendId}`, JSON.stringify(session));
197
+ } catch (err) {
198
+ console.warn("[Krisspy Auth] Failed to save session:", err);
199
+ }
200
+ }
201
+ /**
202
+ * Clear session from storage
203
+ */
204
+ clearSession() {
205
+ this.currentSession = null;
206
+ this.currentUser = null;
207
+ this.http.clearAuth();
208
+ if (this.refreshInterval) {
209
+ clearInterval(this.refreshInterval);
210
+ this.refreshInterval = void 0;
211
+ }
212
+ if (typeof window !== "undefined") {
213
+ localStorage.removeItem(`${STORAGE_KEY}-${this.backendId}`);
214
+ }
215
+ }
216
+ /**
217
+ * Set current session
218
+ */
219
+ setSession(session) {
220
+ this.currentSession = session;
221
+ this.currentUser = session.user;
222
+ this.http.setAuth(session.access_token);
223
+ this.saveSession(session);
224
+ this.setupAutoRefresh(session);
225
+ this.notifyListeners("SIGNED_IN");
226
+ }
227
+ /**
228
+ * Setup auto-refresh of token
229
+ */
230
+ setupAutoRefresh(session) {
231
+ if (this.refreshInterval) {
232
+ clearInterval(this.refreshInterval);
233
+ }
234
+ if (!session.refresh_token || !session.expires_in) return;
235
+ const refreshIn = (session.expires_in - 300) * 1e3;
236
+ if (refreshIn > 0) {
237
+ this.refreshInterval = setInterval(() => {
238
+ this.refreshSession();
239
+ }, refreshIn);
240
+ }
241
+ }
242
+ /**
243
+ * Notify auth state change listeners
244
+ */
245
+ notifyListeners(event) {
246
+ for (const listener of this.listeners) {
247
+ try {
248
+ listener(event);
249
+ } catch (err) {
250
+ console.error("[Krisspy Auth] Listener error:", err);
251
+ }
252
+ }
253
+ }
254
+ /**
255
+ * Sign up with email and password
256
+ */
257
+ async signUp(credentials) {
258
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/signup`;
259
+ const response = await this.http.post(path, {
260
+ email: credentials.email,
261
+ password: credentials.password,
262
+ metadata: credentials.metadata
263
+ });
264
+ if (response.error) {
265
+ return {
266
+ data: { user: null, session: null },
267
+ error: response.error
268
+ };
269
+ }
270
+ if (response.data?.session) {
271
+ this.setSession(response.data.session);
272
+ }
273
+ return {
274
+ data: {
275
+ user: response.data?.user ?? null,
276
+ session: response.data?.session ?? null
277
+ },
278
+ error: null
279
+ };
280
+ }
281
+ /**
282
+ * Sign in with email and password
283
+ */
284
+ async signInWithPassword(credentials) {
285
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/login`;
286
+ const response = await this.http.post(path, {
287
+ email: credentials.email,
288
+ password: credentials.password
289
+ });
290
+ if (response.error) {
291
+ return {
292
+ data: { user: null, session: null },
293
+ error: response.error
294
+ };
295
+ }
296
+ if (response.data?.session) {
297
+ this.setSession(response.data.session);
298
+ }
299
+ return {
300
+ data: {
301
+ user: response.data?.user ?? null,
302
+ session: response.data?.session ?? null
303
+ },
304
+ error: null
305
+ };
306
+ }
307
+ /**
308
+ * Sign in with OAuth provider
309
+ */
310
+ async signInWithOAuth(options) {
311
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/oauth/${options.provider}`;
312
+ const response = await this.http.post(path, {
313
+ redirect_to: options.redirectTo
314
+ });
315
+ if (response.error) {
316
+ return { data: null, error: response.error };
317
+ }
318
+ if (typeof window !== "undefined" && response.data?.url) {
319
+ window.location.href = response.data.url;
320
+ }
321
+ return { data: response.data, error: null };
322
+ }
323
+ /**
324
+ * Sign out
325
+ */
326
+ async signOut() {
327
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/logout`;
328
+ await this.http.post(path);
329
+ this.clearSession();
330
+ this.notifyListeners("SIGNED_OUT");
331
+ return { error: null };
332
+ }
333
+ /**
334
+ * Refresh the session token
335
+ */
336
+ async refreshSession() {
337
+ if (!this.currentSession?.refresh_token) {
338
+ return {
339
+ data: { user: null, session: null },
340
+ error: { message: "No refresh token available" }
341
+ };
342
+ }
343
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/refresh`;
344
+ const response = await this.http.post(path, {
345
+ refresh_token: this.currentSession.refresh_token
346
+ });
347
+ if (response.error) {
348
+ this.clearSession();
349
+ this.notifyListeners("SIGNED_OUT");
350
+ return {
351
+ data: { user: null, session: null },
352
+ error: response.error
353
+ };
354
+ }
355
+ if (response.data?.session) {
356
+ this.setSession(response.data.session);
357
+ }
358
+ return {
359
+ data: {
360
+ user: response.data?.session?.user ?? null,
361
+ session: response.data?.session ?? null
362
+ },
363
+ error: null
364
+ };
365
+ }
366
+ /**
367
+ * Get current session
368
+ */
369
+ async getSession() {
370
+ return {
371
+ data: { session: this.currentSession },
372
+ error: null
373
+ };
374
+ }
375
+ /**
376
+ * Get current user
377
+ */
378
+ async getUser() {
379
+ return {
380
+ data: { user: this.currentUser },
381
+ error: null
382
+ };
383
+ }
384
+ /**
385
+ * Get current user synchronously
386
+ */
387
+ user() {
388
+ return this.currentUser;
389
+ }
390
+ /**
391
+ * Get current session synchronously
392
+ */
393
+ session() {
394
+ return this.currentSession;
395
+ }
396
+ /**
397
+ * Update user metadata
398
+ */
399
+ async updateUser(data) {
400
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/user`;
401
+ const response = await this.http.patch(path, data);
402
+ if (response.error) {
403
+ return { data: { user: null }, error: response.error };
404
+ }
405
+ if (response.data?.user) {
406
+ this.currentUser = response.data.user;
407
+ if (this.currentSession) {
408
+ this.currentSession.user = response.data.user;
409
+ this.saveSession(this.currentSession);
410
+ }
411
+ }
412
+ return { data: { user: response.data?.user ?? null }, error: null };
413
+ }
414
+ /**
415
+ * Request password reset
416
+ */
417
+ async resetPasswordForEmail(email) {
418
+ const path = `/api/v1/cloud-backends/${this.backendId}/auth/reset-password`;
419
+ const response = await this.http.post(path, { email });
420
+ return { error: response.error };
421
+ }
422
+ /**
423
+ * Listen for auth state changes
424
+ */
425
+ onAuthStateChange(callback) {
426
+ this.listeners.push(callback);
427
+ if (this.currentSession) {
428
+ callback("SIGNED_IN");
429
+ }
430
+ return {
431
+ unsubscribe: () => {
432
+ const index = this.listeners.indexOf(callback);
433
+ if (index > -1) {
434
+ this.listeners.splice(index, 1);
435
+ }
436
+ }
437
+ };
438
+ }
439
+ /**
440
+ * Set session from external source (e.g., OAuth callback)
441
+ */
442
+ async setSessionFromUrl() {
443
+ if (typeof window === "undefined") {
444
+ return { data: { user: null, session: null }, error: { message: "Not in browser" } };
445
+ }
446
+ const hash = window.location.hash.substring(1);
447
+ const params = new URLSearchParams(hash);
448
+ const accessToken = params.get("access_token");
449
+ const refreshToken = params.get("refresh_token");
450
+ if (!accessToken) {
451
+ return { data: { user: null, session: null }, error: { message: "No access token in URL" } };
452
+ }
453
+ try {
454
+ const payload = JSON.parse(atob(accessToken.split(".")[1]));
455
+ const session = {
456
+ access_token: accessToken,
457
+ refresh_token: refreshToken ?? void 0,
458
+ expires_at: payload.exp,
459
+ expires_in: payload.exp ? payload.exp - Math.floor(Date.now() / 1e3) : 3600,
460
+ user: {
461
+ id: payload.sub,
462
+ email: payload.email,
463
+ metadata: payload.metadata
464
+ }
465
+ };
466
+ this.setSession(session);
467
+ window.history.replaceState({}, document.title, window.location.pathname);
468
+ return {
469
+ data: { user: session.user, session },
470
+ error: null
471
+ };
472
+ } catch (err) {
473
+ return {
474
+ data: { user: null, session: null },
475
+ error: { message: "Failed to parse token" }
476
+ };
477
+ }
478
+ }
479
+ };
480
+
481
+ // src/query-builder.ts
482
+ var QueryBuilder = class {
483
+ constructor(http, backendId, tableName, useRLS = true) {
484
+ this.queryParams = {};
485
+ this.selectColumns = [];
486
+ this.orderClauses = [];
487
+ this.isSingle = false;
488
+ this.http = http;
489
+ this.backendId = backendId;
490
+ this.tableName = tableName;
491
+ this.useRLS = useRLS;
492
+ }
493
+ /**
494
+ * Get the base path for data endpoints
495
+ * Uses /rls/data for RLS-enabled queries (requires auth)
496
+ * Uses /data for legacy queries (admin/owner only)
497
+ */
498
+ getBasePath() {
499
+ if (this.useRLS) {
500
+ return `/api/v1/cloud-backends/${this.backendId}/rls/data/${this.tableName}`;
501
+ }
502
+ return `/api/v1/cloud-backends/${this.backendId}/data/${this.tableName}`;
503
+ }
504
+ /**
505
+ * Select specific columns
506
+ * @example .select('id, name, price')
507
+ * @example .select('*')
508
+ */
509
+ select(columns = "*") {
510
+ this.selectColumns = columns.split(",").map((c) => c.trim());
511
+ return this;
512
+ }
513
+ /**
514
+ * Filter: equals
515
+ * @example .eq('id', 123)
516
+ */
517
+ eq(column, value) {
518
+ this.queryParams[column] = `eq.${value}`;
519
+ return this;
520
+ }
521
+ /**
522
+ * Filter: not equals
523
+ * @example .neq('status', 'deleted')
524
+ */
525
+ neq(column, value) {
526
+ this.queryParams[column] = `neq.${value}`;
527
+ return this;
528
+ }
529
+ /**
530
+ * Filter: greater than
531
+ * @example .gt('price', 100)
532
+ */
533
+ gt(column, value) {
534
+ this.queryParams[column] = `gt.${value}`;
535
+ return this;
536
+ }
537
+ /**
538
+ * Filter: greater than or equal
539
+ * @example .gte('age', 18)
540
+ */
541
+ gte(column, value) {
542
+ this.queryParams[column] = `gte.${value}`;
543
+ return this;
544
+ }
545
+ /**
546
+ * Filter: less than
547
+ * @example .lt('stock', 10)
548
+ */
549
+ lt(column, value) {
550
+ this.queryParams[column] = `lt.${value}`;
551
+ return this;
552
+ }
553
+ /**
554
+ * Filter: less than or equal
555
+ * @example .lte('price', 1000)
556
+ */
557
+ lte(column, value) {
558
+ this.queryParams[column] = `lte.${value}`;
559
+ return this;
560
+ }
561
+ /**
562
+ * Filter: pattern matching (case sensitive)
563
+ * @example .like('name', '%iPhone%')
564
+ */
565
+ like(column, pattern) {
566
+ this.queryParams[column] = `like.${pattern}`;
567
+ return this;
568
+ }
569
+ /**
570
+ * Filter: pattern matching (case insensitive)
571
+ * @example .ilike('name', '%iphone%')
572
+ */
573
+ ilike(column, pattern) {
574
+ this.queryParams[column] = `ilike.${pattern}`;
575
+ return this;
576
+ }
577
+ /**
578
+ * Filter: value in list
579
+ * @example .in('status', ['active', 'pending'])
580
+ */
581
+ in(column, values) {
582
+ this.queryParams[column] = `in.${values.join(",")}`;
583
+ return this;
584
+ }
585
+ /**
586
+ * Filter: is null/true/false
587
+ * @example .is('deleted_at', null)
588
+ */
589
+ is(column, value) {
590
+ const strValue = value === null ? "null" : value ? "true" : "false";
591
+ this.queryParams[column] = `is.${strValue}`;
592
+ return this;
593
+ }
594
+ /**
595
+ * Order by column
596
+ * @example .order('created_at', { ascending: false })
597
+ */
598
+ order(column, options) {
599
+ const direction = options?.ascending === false ? "desc" : "asc";
600
+ this.orderClauses.push(`${column}.${direction}`);
601
+ return this;
602
+ }
603
+ /**
604
+ * Limit number of rows
605
+ * @example .limit(10)
606
+ */
607
+ limit(count) {
608
+ this.limitValue = count;
609
+ return this;
610
+ }
611
+ /**
612
+ * Skip rows (for pagination)
613
+ * @example .range(0, 9) // First 10 rows
614
+ */
615
+ range(from, to) {
616
+ this.offsetValue = from;
617
+ this.limitValue = to - from + 1;
618
+ return this;
619
+ }
620
+ /**
621
+ * Return single row (throws if multiple or none)
622
+ */
623
+ single() {
624
+ this.isSingle = true;
625
+ this.limitValue = 1;
626
+ return this;
627
+ }
628
+ /**
629
+ * Return first row or null
630
+ */
631
+ maybeSingle() {
632
+ this.isSingle = true;
633
+ this.limitValue = 1;
634
+ return this;
635
+ }
636
+ /**
637
+ * Build query params for the request
638
+ */
639
+ buildParams() {
640
+ const params = { ...this.queryParams };
641
+ if (this.selectColumns.length > 0 && !this.selectColumns.includes("*")) {
642
+ params["select"] = this.selectColumns.join(",");
643
+ }
644
+ if (this.orderClauses.length > 0) {
645
+ params["order"] = this.orderClauses.join(",");
646
+ }
647
+ if (this.limitValue !== void 0) {
648
+ params["limit"] = String(this.limitValue);
649
+ }
650
+ if (this.offsetValue !== void 0) {
651
+ params["offset"] = String(this.offsetValue);
652
+ }
653
+ return params;
654
+ }
655
+ /**
656
+ * Execute SELECT query
657
+ */
658
+ async then(resolve, reject) {
659
+ try {
660
+ const result = await this.execute();
661
+ resolve(result);
662
+ } catch (err) {
663
+ if (reject) reject(err);
664
+ }
665
+ }
666
+ /**
667
+ * Execute the query
668
+ */
669
+ async execute() {
670
+ const path = this.getBasePath();
671
+ const params = this.buildParams();
672
+ const response = await this.http.get(path, params);
673
+ if (response.error) {
674
+ if (this.isSingle) {
675
+ return { data: null, error: response.error };
676
+ }
677
+ return { data: null, error: response.error, count: null };
678
+ }
679
+ if (this.isSingle) {
680
+ const item = response.data?.data?.[0] ?? null;
681
+ return { data: item, error: null };
682
+ }
683
+ return {
684
+ data: response.data?.data ?? [],
685
+ error: null,
686
+ count: response.data?.count ?? 0
687
+ };
688
+ }
689
+ /**
690
+ * Insert rows
691
+ * @example .insert({ name: 'iPhone', price: 999 })
692
+ * @example .insert([{ name: 'iPhone' }, { name: 'iPad' }])
693
+ */
694
+ async insert(data) {
695
+ const path = this.getBasePath();
696
+ const response = await this.http.post(path, data);
697
+ if (response.error) {
698
+ return { data: null, error: response.error, count: 0 };
699
+ }
700
+ return {
701
+ data: response.data?.data ?? [],
702
+ error: null,
703
+ count: response.data?.count ?? 0
704
+ };
705
+ }
706
+ /**
707
+ * Update rows (requires filters)
708
+ * @example .update({ price: 899 }).eq('id', 123)
709
+ */
710
+ async update(data) {
711
+ const path = this.getBasePath();
712
+ const params = this.buildParams();
713
+ delete params["select"];
714
+ delete params["order"];
715
+ delete params["limit"];
716
+ delete params["offset"];
717
+ const response = await this.http.patch(path, data, params);
718
+ if (response.error) {
719
+ return { data: null, error: response.error, count: 0 };
720
+ }
721
+ return {
722
+ data: response.data?.data ?? [],
723
+ error: null,
724
+ count: response.data?.count ?? 0
725
+ };
726
+ }
727
+ /**
728
+ * Delete rows (requires filters)
729
+ * @example .delete().eq('id', 123)
730
+ */
731
+ async delete() {
732
+ const path = this.getBasePath();
733
+ const params = this.buildParams();
734
+ delete params["select"];
735
+ delete params["order"];
736
+ delete params["limit"];
737
+ delete params["offset"];
738
+ const response = await this.http.delete(path, params);
739
+ if (response.error) {
740
+ return { data: null, error: response.error, count: 0 };
741
+ }
742
+ return {
743
+ data: response.data?.data ?? [],
744
+ error: null,
745
+ count: response.data?.count ?? 0
746
+ };
747
+ }
748
+ /**
749
+ * Upsert rows (insert or update on conflict)
750
+ * @example .upsert({ id: 1, name: 'iPhone' })
751
+ */
752
+ async upsert(data, options) {
753
+ return this.insert(data);
754
+ }
755
+ };
756
+
757
+ // src/client.ts
758
+ var KrisspyClient = class {
759
+ constructor(options) {
760
+ const baseUrl = options.url || "https://api.krisspy.ai";
761
+ this.backendId = options.backendId;
762
+ this.useRLS = options.useRLS !== false;
763
+ this.http = new HttpClient({
764
+ baseUrl,
765
+ headers: {
766
+ ...options.headers,
767
+ ...options.apiKey ? { "Authorization": `Bearer ${options.apiKey}` } : {}
768
+ },
769
+ debug: options.debug
770
+ });
771
+ this._auth = new KrisspyAuth(this.http, this.backendId);
772
+ }
773
+ /**
774
+ * Auth module for user authentication
775
+ *
776
+ * @example
777
+ * // Sign up
778
+ * const { data, error } = await krisspy.auth.signUp({
779
+ * email: 'user@example.com',
780
+ * password: 'secret123'
781
+ * })
782
+ *
783
+ * // Sign in
784
+ * const { data, error } = await krisspy.auth.signInWithPassword({
785
+ * email: 'user@example.com',
786
+ * password: 'secret123'
787
+ * })
788
+ *
789
+ * // Get current user
790
+ * const user = krisspy.auth.user()
791
+ *
792
+ * // Sign out
793
+ * await krisspy.auth.signOut()
794
+ */
795
+ get auth() {
796
+ return this._auth;
797
+ }
798
+ /**
799
+ * Create a query builder for a table
800
+ *
801
+ * @example
802
+ * // Select all rows
803
+ * const { data, error } = await krisspy.from('products').select('*')
804
+ *
805
+ * // Select with filters
806
+ * const { data, error } = await krisspy
807
+ * .from('products')
808
+ * .select('id, name, price')
809
+ * .eq('active', true)
810
+ * .order('created_at', { ascending: false })
811
+ * .limit(10)
812
+ *
813
+ * // Insert
814
+ * const { data, error } = await krisspy
815
+ * .from('products')
816
+ * .insert({ name: 'iPhone', price: 999 })
817
+ *
818
+ * // Update
819
+ * const { data, error } = await krisspy
820
+ * .from('products')
821
+ * .update({ price: 899 })
822
+ * .eq('id', 123)
823
+ *
824
+ * // Delete
825
+ * const { data, error } = await krisspy
826
+ * .from('products')
827
+ * .delete()
828
+ * .eq('id', 123)
829
+ */
830
+ from(table) {
831
+ return new QueryBuilder(this.http, this.backendId, table, this.useRLS);
832
+ }
833
+ /**
834
+ * Execute raw SQL query
835
+ *
836
+ * @example
837
+ * const { data, error } = await krisspy.rpc('SELECT * FROM products WHERE price > $1', [100])
838
+ */
839
+ async rpc(sql, params) {
840
+ const path = `/api/v1/cloud-backends/${this.backendId}/sql`;
841
+ const response = await this.http.post(path, { sql, params });
842
+ if (response.error) {
843
+ return { data: null, error: response.error };
844
+ }
845
+ return { data: response.data?.result ?? null, error: null };
846
+ }
847
+ /**
848
+ * Invoke a serverless function
849
+ *
850
+ * @example
851
+ * const { data, error } = await krisspy.functions.invoke('hello-world', {
852
+ * body: { name: 'John' }
853
+ * })
854
+ */
855
+ get functions() {
856
+ return {
857
+ invoke: async (functionName, options) => {
858
+ const path = `/api/v1/cloud-backends/${this.backendId}/functions/${functionName}/invoke`;
859
+ const response = await this.http.post(path, options?.body, void 0);
860
+ if (response.error) {
861
+ return { data: null, error: response.error };
862
+ }
863
+ return { data: response.data, error: null };
864
+ },
865
+ list: async () => {
866
+ const path = `/api/v1/cloud-backends/${this.backendId}/functions`;
867
+ const response = await this.http.get(path);
868
+ if (response.error) {
869
+ return { data: null, error: response.error };
870
+ }
871
+ return { data: response.data?.functions ?? [], error: null };
872
+ }
873
+ };
874
+ }
875
+ /**
876
+ * Get backend info
877
+ */
878
+ async getBackendInfo() {
879
+ const path = `/api/v1/cloud-backends/${this.backendId}`;
880
+ const response = await this.http.get(path);
881
+ if (response.error) {
882
+ return { data: null, error: response.error };
883
+ }
884
+ return { data: response.data, error: null };
885
+ }
886
+ /**
887
+ * List tables in the backend
888
+ */
889
+ async listTables() {
890
+ const path = `/api/v1/cloud-backends/${this.backendId}/tables`;
891
+ const response = await this.http.get(path);
892
+ if (response.error) {
893
+ return { data: null, error: response.error };
894
+ }
895
+ return { data: response.data?.tables ?? [], error: null };
896
+ }
897
+ /**
898
+ * Get table schema (columns)
899
+ */
900
+ async getTableSchema(table) {
901
+ const path = `/api/v1/cloud-backends/${this.backendId}/tables/${table}`;
902
+ const response = await this.http.get(path);
903
+ if (response.error) {
904
+ return { data: null, error: response.error };
905
+ }
906
+ return { data: response.data?.columns ?? [], error: null };
907
+ }
908
+ };
909
+
910
+ // src/index.ts
911
+ function createClient(options) {
912
+ return new KrisspyClient(options);
913
+ }
914
+ // Annotate the CommonJS export names for ESM import in node:
915
+ 0 && (module.exports = {
916
+ HttpClient,
917
+ KrisspyAuth,
918
+ KrisspyClient,
919
+ QueryBuilder,
920
+ createClient
921
+ });