@ezcoder.dev/sdk 1.5.0 → 1.6.1
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/{DatabaseProvider-BtYMJRqh.d.ts → DatabaseProvider-ByBXGNfV.d.ts} +13 -0
- package/dist/analytics/index.js +2 -2
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +2 -2
- package/dist/{chunk-HX7IFB7C.js → chunk-JDXWUBZC.js} +35 -5
- package/dist/chunk-JDXWUBZC.js.map +1 -0
- package/dist/chunk-PAIK6GOS.js +124 -0
- package/dist/chunk-PAIK6GOS.js.map +1 -0
- package/dist/{chunk-RU2GHN7O.js → chunk-QTUXMBBU.js} +456 -124
- package/dist/chunk-QTUXMBBU.js.map +1 -0
- package/dist/database/index.d.ts +1 -1
- package/dist/database/index.js +9 -8
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7 -7
- package/dist/notifications/index.js +2 -2
- package/dist/payments/index.d.ts +1 -1
- package/dist/payments/index.js +2 -2
- package/dist/roles/index.js +34 -11
- package/dist/roles/index.js.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +2 -2
- package/dist/{types-1uP3V_pe.d.ts → types-BET19sj2.d.ts} +1 -0
- package/package.json +1 -1
- package/dist/chunk-HX7IFB7C.js.map +0 -1
- package/dist/chunk-OIAKVQGD.js +0 -389
- package/dist/chunk-OIAKVQGD.js.map +0 -1
- package/dist/chunk-RU2GHN7O.js.map +0 -1
package/dist/chunk-OIAKVQGD.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
env
|
|
3
|
-
} from "./chunk-KWR4PA5I.js";
|
|
4
|
-
|
|
5
|
-
// src/core/platform.ts
|
|
6
|
-
var isConfigured = () => Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID);
|
|
7
|
-
function getSessionId() {
|
|
8
|
-
if (typeof sessionStorage === "undefined") return "server";
|
|
9
|
-
let sessionId = sessionStorage.getItem("ezcoder_session_id");
|
|
10
|
-
if (!sessionId) {
|
|
11
|
-
sessionId = `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
12
|
-
sessionStorage.setItem("ezcoder_session_id", sessionId);
|
|
13
|
-
}
|
|
14
|
-
return sessionId;
|
|
15
|
-
}
|
|
16
|
-
function getVisitorId() {
|
|
17
|
-
if (typeof localStorage === "undefined") return "server";
|
|
18
|
-
let visitorId = localStorage.getItem("ezcoder_visitor_id");
|
|
19
|
-
if (!visitorId) {
|
|
20
|
-
visitorId = `vis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
21
|
-
localStorage.setItem("ezcoder_visitor_id", visitorId);
|
|
22
|
-
}
|
|
23
|
-
return visitorId;
|
|
24
|
-
}
|
|
25
|
-
var pageEntryTime = typeof window !== "undefined" ? Date.now() : 0;
|
|
26
|
-
var currentPath = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
27
|
-
var maxScrollDepth = 0;
|
|
28
|
-
var trackPageEntry = () => {
|
|
29
|
-
pageEntryTime = Date.now();
|
|
30
|
-
currentPath = window.location.pathname;
|
|
31
|
-
maxScrollDepth = 0;
|
|
32
|
-
};
|
|
33
|
-
var getTimeOnPage = () => Date.now() - pageEntryTime;
|
|
34
|
-
var throttle = (fn, wait) => {
|
|
35
|
-
let lastTime = 0;
|
|
36
|
-
return (...args) => {
|
|
37
|
-
const now = Date.now();
|
|
38
|
-
if (now - lastTime >= wait) {
|
|
39
|
-
lastTime = now;
|
|
40
|
-
fn(...args);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
var trackScrollDepth = () => {
|
|
45
|
-
if (typeof window === "undefined") return;
|
|
46
|
-
const scrollTop = window.scrollY;
|
|
47
|
-
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
48
|
-
if (docHeight > 0) {
|
|
49
|
-
const scrollPercent = Math.round(scrollTop / docHeight * 100);
|
|
50
|
-
if (scrollPercent > maxScrollDepth) {
|
|
51
|
-
maxScrollDepth = Math.min(scrollPercent, 100);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var analyticsPost = async (endpoint, body) => {
|
|
56
|
-
if (!isConfigured()) {
|
|
57
|
-
return { success: false, error: "Platform not configured" };
|
|
58
|
-
}
|
|
59
|
-
try {
|
|
60
|
-
const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {
|
|
61
|
-
method: "POST",
|
|
62
|
-
headers: { "Content-Type": "application/json" },
|
|
63
|
-
body: JSON.stringify(body)
|
|
64
|
-
});
|
|
65
|
-
if (!response.ok) {
|
|
66
|
-
const error = await response.text();
|
|
67
|
-
return { success: false, error };
|
|
68
|
-
}
|
|
69
|
-
return await response.json();
|
|
70
|
-
} catch (error) {
|
|
71
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
72
|
-
return { success: false, error: message };
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
var stripePost = async (endpoint, body) => {
|
|
76
|
-
if (!env.EZCODER_API_URL) {
|
|
77
|
-
return { success: false, error: "Platform not configured" };
|
|
78
|
-
}
|
|
79
|
-
if (!env.EZC_SECRET_KEY) {
|
|
80
|
-
return {
|
|
81
|
-
success: false,
|
|
82
|
-
error: "Payment configuration incomplete. The site owner needs to redeploy from EzCoder to enable checkout."
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
try {
|
|
86
|
-
const headers = {
|
|
87
|
-
"Content-Type": "application/json",
|
|
88
|
-
"Authorization": `Bearer ${env.EZC_SECRET_KEY}`
|
|
89
|
-
};
|
|
90
|
-
const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {
|
|
91
|
-
method: "POST",
|
|
92
|
-
headers,
|
|
93
|
-
body: JSON.stringify(body)
|
|
94
|
-
});
|
|
95
|
-
if (!response.ok) {
|
|
96
|
-
const error = await response.text();
|
|
97
|
-
return { success: false, error };
|
|
98
|
-
}
|
|
99
|
-
return await response.json();
|
|
100
|
-
} catch (error) {
|
|
101
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
102
|
-
return { success: false, error: message };
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
var stripeGet = async (endpoint) => {
|
|
106
|
-
if (!env.EZCODER_API_URL) {
|
|
107
|
-
return { success: false, error: "Platform not configured" };
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
const headers = { "Content-Type": "application/json" };
|
|
111
|
-
if (env.EZC_SECRET_KEY) {
|
|
112
|
-
headers["Authorization"] = `Bearer ${env.EZC_SECRET_KEY}`;
|
|
113
|
-
}
|
|
114
|
-
const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {
|
|
115
|
-
method: "GET",
|
|
116
|
-
headers
|
|
117
|
-
});
|
|
118
|
-
if (!response.ok) {
|
|
119
|
-
const error = await response.text();
|
|
120
|
-
return { success: false, error };
|
|
121
|
-
}
|
|
122
|
-
return await response.json();
|
|
123
|
-
} catch (error) {
|
|
124
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
125
|
-
return { success: false, error: message };
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
var sendPageExit = () => {
|
|
129
|
-
if (!isConfigured() || typeof navigator === "undefined") return;
|
|
130
|
-
const payload = JSON.stringify({
|
|
131
|
-
type: "page_exit",
|
|
132
|
-
projectId: env.EZC_PROJECT_ID,
|
|
133
|
-
sessionId: getSessionId(),
|
|
134
|
-
visitorId: getVisitorId(),
|
|
135
|
-
pathname: currentPath,
|
|
136
|
-
timeOnPage: getTimeOnPage(),
|
|
137
|
-
scrollDepth: maxScrollDepth,
|
|
138
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
139
|
-
});
|
|
140
|
-
if (navigator.sendBeacon) {
|
|
141
|
-
navigator.sendBeacon(`${env.EZCODER_API_URL}/api/analytics/collect`, payload);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
var ezcoder = {
|
|
145
|
-
isConfigured,
|
|
146
|
-
analytics: {
|
|
147
|
-
track: (eventType, properties = {}) => {
|
|
148
|
-
return analyticsPost("/api/analytics/collect", {
|
|
149
|
-
type: eventType,
|
|
150
|
-
projectId: env.EZC_PROJECT_ID,
|
|
151
|
-
sessionId: getSessionId(),
|
|
152
|
-
visitorId: getVisitorId(),
|
|
153
|
-
url: typeof window !== "undefined" ? window.location.href : "",
|
|
154
|
-
pathname: typeof window !== "undefined" ? window.location.pathname : "/",
|
|
155
|
-
referrer: typeof document !== "undefined" ? document.referrer : "",
|
|
156
|
-
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "",
|
|
157
|
-
screenResolution: typeof window !== "undefined" ? `${window.screen.width}x${window.screen.height}` : "",
|
|
158
|
-
viewport: typeof window !== "undefined" ? `${window.innerWidth}x${window.innerHeight}` : "",
|
|
159
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
160
|
-
metadata: properties
|
|
161
|
-
});
|
|
162
|
-
},
|
|
163
|
-
pageView: (path) => {
|
|
164
|
-
trackPageEntry();
|
|
165
|
-
return ezcoder.analytics.track("page_view", {
|
|
166
|
-
path: path || (typeof window !== "undefined" ? window.location.pathname : "/"),
|
|
167
|
-
title: typeof document !== "undefined" ? document.title : ""
|
|
168
|
-
});
|
|
169
|
-
},
|
|
170
|
-
identify: (userId, traits = {}) => {
|
|
171
|
-
return ezcoder.analytics.track("identify", { userId, ...traits });
|
|
172
|
-
},
|
|
173
|
-
error: (message, context = {}) => {
|
|
174
|
-
return ezcoder.analytics.track("error", {
|
|
175
|
-
message,
|
|
176
|
-
...context,
|
|
177
|
-
stack: context.stack || new Error().stack
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
stripe: {
|
|
182
|
-
createCheckout: async (priceId, options = {}) => {
|
|
183
|
-
const result = await stripePost("/api/stripe/create-checkout", {
|
|
184
|
-
priceId,
|
|
185
|
-
projectId: env.EZC_PROJECT_ID,
|
|
186
|
-
successUrl: options.successUrl || `${typeof window !== "undefined" ? window.location.origin : ""}/payment/success`,
|
|
187
|
-
cancelUrl: options.cancelUrl || `${typeof window !== "undefined" ? window.location.origin : ""}/payment/cancel`,
|
|
188
|
-
customerEmail: options.customerEmail,
|
|
189
|
-
quantity: options.quantity || 1
|
|
190
|
-
});
|
|
191
|
-
if (result.url && options.redirect !== false && typeof window !== "undefined") {
|
|
192
|
-
window.location.href = result.url;
|
|
193
|
-
}
|
|
194
|
-
return result;
|
|
195
|
-
},
|
|
196
|
-
getProducts: async () => {
|
|
197
|
-
return { products: [], message: "Products managed via EzCoder dashboard" };
|
|
198
|
-
},
|
|
199
|
-
verifySession: async (sessionId) => {
|
|
200
|
-
if (!sessionId) {
|
|
201
|
-
return { success: false, error: "Session ID is required" };
|
|
202
|
-
}
|
|
203
|
-
return stripeGet(`/api/stripe/verify-session?session_id=${encodeURIComponent(sessionId)}`);
|
|
204
|
-
},
|
|
205
|
-
getCustomerStatus: async (options = {}) => {
|
|
206
|
-
const params = new URLSearchParams();
|
|
207
|
-
if (options.customerId) params.set("customer_id", options.customerId);
|
|
208
|
-
if (options.email) params.set("email", options.email);
|
|
209
|
-
if (!options.customerId && !options.email) {
|
|
210
|
-
return { success: false, error: "Either customerId or email is required" };
|
|
211
|
-
}
|
|
212
|
-
return stripeGet(`/api/stripe/customer-status?${params.toString()}`);
|
|
213
|
-
},
|
|
214
|
-
createPortalSession: async (customerId, options = {}) => {
|
|
215
|
-
const result = await stripePost("/api/stripe/customer-portal", {
|
|
216
|
-
customerId,
|
|
217
|
-
returnUrl: options.returnUrl || window.location.href
|
|
218
|
-
});
|
|
219
|
-
if (result.url && options.redirect !== false && typeof window !== "undefined") {
|
|
220
|
-
window.location.href = result.url;
|
|
221
|
-
}
|
|
222
|
-
return result;
|
|
223
|
-
},
|
|
224
|
-
getInvoices: async (customerId, options = {}) => {
|
|
225
|
-
const params = new URLSearchParams();
|
|
226
|
-
params.set("customer_id", customerId);
|
|
227
|
-
if (options.limit) params.set("limit", String(options.limit));
|
|
228
|
-
return stripeGet(`/api/stripe/invoices?${params.toString()}`);
|
|
229
|
-
}
|
|
230
|
-
},
|
|
231
|
-
users: {
|
|
232
|
-
trackSignup: (userId, email, role = null) => {
|
|
233
|
-
return ezcoder.analytics.track("user_signup", { userId, email, role, signupMethod: "email" });
|
|
234
|
-
},
|
|
235
|
-
trackLogin: (userId) => {
|
|
236
|
-
return ezcoder.analytics.track("user_login", { userId });
|
|
237
|
-
},
|
|
238
|
-
trackLogout: (userId) => {
|
|
239
|
-
return ezcoder.analytics.track("user_logout", { userId });
|
|
240
|
-
},
|
|
241
|
-
trackRoleChange: (userId, oldRole, newRole) => {
|
|
242
|
-
return ezcoder.analytics.track("role_change", { userId, oldRole, newRole });
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
var ezcoderAuthIntegration = {
|
|
247
|
-
onLogin: (user) => {
|
|
248
|
-
if (user?.id) {
|
|
249
|
-
ezcoder.analytics.identify(user.id, {
|
|
250
|
-
email: user.email,
|
|
251
|
-
name: user.user_metadata?.full_name
|
|
252
|
-
});
|
|
253
|
-
ezcoder.users.trackLogin(user.id);
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
onSignup: (user) => {
|
|
257
|
-
if (user?.id) {
|
|
258
|
-
ezcoder.analytics.identify(user.id, { email: user.email });
|
|
259
|
-
ezcoder.users.trackSignup(user.id, user.email || "");
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
onLogout: (userId) => {
|
|
263
|
-
if (userId) {
|
|
264
|
-
ezcoder.users.trackLogout(userId);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
var trackWebVitals = () => {
|
|
269
|
-
if (typeof window === "undefined" || !("PerformanceObserver" in window)) return;
|
|
270
|
-
try {
|
|
271
|
-
new PerformanceObserver((list) => {
|
|
272
|
-
const entries = list.getEntries();
|
|
273
|
-
const lastEntry = entries[entries.length - 1];
|
|
274
|
-
if (lastEntry) {
|
|
275
|
-
ezcoder.analytics.track("web_vital", {
|
|
276
|
-
metric: "LCP",
|
|
277
|
-
value: Math.round(lastEntry.startTime),
|
|
278
|
-
pathname: window.location.pathname
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
}).observe({ type: "largest-contentful-paint", buffered: true });
|
|
282
|
-
} catch {
|
|
283
|
-
}
|
|
284
|
-
try {
|
|
285
|
-
new PerformanceObserver((list) => {
|
|
286
|
-
const entry = list.getEntries()[0];
|
|
287
|
-
if (entry) {
|
|
288
|
-
ezcoder.analytics.track("web_vital", {
|
|
289
|
-
metric: "FID",
|
|
290
|
-
value: Math.round(entry.processingStart - entry.startTime),
|
|
291
|
-
pathname: window.location.pathname
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}).observe({ type: "first-input", buffered: true });
|
|
295
|
-
} catch {
|
|
296
|
-
}
|
|
297
|
-
try {
|
|
298
|
-
let clsValue = 0;
|
|
299
|
-
new PerformanceObserver((list) => {
|
|
300
|
-
for (const entry of list.getEntries()) {
|
|
301
|
-
if (!entry.hadRecentInput) {
|
|
302
|
-
clsValue += entry.value;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}).observe({ type: "layout-shift", buffered: true });
|
|
306
|
-
document.addEventListener("visibilitychange", () => {
|
|
307
|
-
if (document.hidden && clsValue > 0) {
|
|
308
|
-
ezcoder.analytics.track("web_vital", {
|
|
309
|
-
metric: "CLS",
|
|
310
|
-
value: Math.round(clsValue * 1e3) / 1e3,
|
|
311
|
-
pathname: window.location.pathname
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
} catch {
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
var setupErrorTracking = () => {
|
|
319
|
-
if (typeof window === "undefined") return;
|
|
320
|
-
window.onerror = (message, source, lineno, colno, error) => {
|
|
321
|
-
ezcoder.analytics.track("js_error", {
|
|
322
|
-
message: String(message),
|
|
323
|
-
source,
|
|
324
|
-
lineno,
|
|
325
|
-
colno,
|
|
326
|
-
stack: error?.stack,
|
|
327
|
-
pathname: window.location.pathname
|
|
328
|
-
});
|
|
329
|
-
return false;
|
|
330
|
-
};
|
|
331
|
-
window.addEventListener("unhandledrejection", (event) => {
|
|
332
|
-
ezcoder.analytics.track("promise_rejection", {
|
|
333
|
-
reason: event.reason?.message || String(event.reason),
|
|
334
|
-
stack: event.reason?.stack,
|
|
335
|
-
pathname: window.location.pathname
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
};
|
|
339
|
-
if (typeof window !== "undefined") {
|
|
340
|
-
window.addEventListener("scroll", throttle(trackScrollDepth, 500), { passive: true });
|
|
341
|
-
window.addEventListener("beforeunload", sendPageExit);
|
|
342
|
-
document.addEventListener("visibilitychange", () => {
|
|
343
|
-
if (!isConfigured()) return;
|
|
344
|
-
if (document.hidden) {
|
|
345
|
-
ezcoder.analytics.track("page_blur", {
|
|
346
|
-
timeOnPage: getTimeOnPage(),
|
|
347
|
-
scrollDepth: maxScrollDepth,
|
|
348
|
-
pathname: currentPath
|
|
349
|
-
});
|
|
350
|
-
} else {
|
|
351
|
-
ezcoder.analytics.track("page_focus", { pathname: window.location.pathname });
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
const originalPushState = history.pushState;
|
|
355
|
-
history.pushState = function(...args) {
|
|
356
|
-
sendPageExit();
|
|
357
|
-
originalPushState.apply(this, args);
|
|
358
|
-
trackPageEntry();
|
|
359
|
-
if (isConfigured()) ezcoder.analytics.pageView();
|
|
360
|
-
};
|
|
361
|
-
const originalReplaceState = history.replaceState;
|
|
362
|
-
history.replaceState = function(...args) {
|
|
363
|
-
originalReplaceState.apply(this, args);
|
|
364
|
-
trackPageEntry();
|
|
365
|
-
};
|
|
366
|
-
window.addEventListener("popstate", () => {
|
|
367
|
-
sendPageExit();
|
|
368
|
-
trackPageEntry();
|
|
369
|
-
if (isConfigured()) ezcoder.analytics.pageView();
|
|
370
|
-
});
|
|
371
|
-
if (isConfigured()) {
|
|
372
|
-
setTimeout(() => {
|
|
373
|
-
ezcoder.analytics.pageView();
|
|
374
|
-
trackWebVitals();
|
|
375
|
-
setupErrorTracking();
|
|
376
|
-
}, 100);
|
|
377
|
-
}
|
|
378
|
-
if (env.EZCODER_API_URL && !env.EZC_SECRET_KEY) {
|
|
379
|
-
console.warn(
|
|
380
|
-
"[EzCoder SDK] EZCODER_SECRET_KEY is not set \u2014 Stripe checkout and authenticated API calls will fail. Redeploy your project from the EzCoder editor to auto-provision keys."
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export {
|
|
386
|
-
ezcoder,
|
|
387
|
-
ezcoderAuthIntegration
|
|
388
|
-
};
|
|
389
|
-
//# sourceMappingURL=chunk-OIAKVQGD.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/platform.ts"],"sourcesContent":["import { env } from './config';\r\nimport type { AnalyticsResult, CheckoutOptions, EzcoderClient, AuthIntegration, AuthUser } from './types';\r\n\r\nconst isConfigured = (): boolean => Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID);\r\n\r\nfunction getSessionId(): string {\r\n if (typeof sessionStorage === 'undefined') return 'server';\r\n let sessionId = sessionStorage.getItem('ezcoder_session_id');\r\n if (!sessionId) {\r\n sessionId = `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n sessionStorage.setItem('ezcoder_session_id', sessionId);\r\n }\r\n return sessionId;\r\n}\r\n\r\nfunction getVisitorId(): string {\r\n if (typeof localStorage === 'undefined') return 'server';\r\n let visitorId = localStorage.getItem('ezcoder_visitor_id');\r\n if (!visitorId) {\r\n visitorId = `vis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n localStorage.setItem('ezcoder_visitor_id', visitorId);\r\n }\r\n return visitorId;\r\n}\r\n\r\nlet pageEntryTime: number = typeof window !== 'undefined' ? Date.now() : 0;\r\nlet currentPath: string = typeof window !== 'undefined' ? window.location.pathname : '/';\r\nlet maxScrollDepth: number = 0;\r\n\r\nconst trackPageEntry = (): void => {\r\n pageEntryTime = Date.now();\r\n currentPath = window.location.pathname;\r\n maxScrollDepth = 0;\r\n};\r\n\r\nconst getTimeOnPage = (): number => Date.now() - pageEntryTime;\r\n\r\nconst throttle = <T extends (...args: never[]) => void>(fn: T, wait: number): ((...args: Parameters<T>) => void) => {\r\n let lastTime = 0;\r\n return (...args: Parameters<T>) => {\r\n const now = Date.now();\r\n if (now - lastTime >= wait) {\r\n lastTime = now;\r\n fn(...args);\r\n }\r\n };\r\n};\r\n\r\nconst trackScrollDepth = (): void => {\r\n if (typeof window === 'undefined') return;\r\n const scrollTop = window.scrollY;\r\n const docHeight = document.documentElement.scrollHeight - window.innerHeight;\r\n if (docHeight > 0) {\r\n const scrollPercent = Math.round((scrollTop / docHeight) * 100);\r\n if (scrollPercent > maxScrollDepth) {\r\n maxScrollDepth = Math.min(scrollPercent, 100);\r\n }\r\n }\r\n};\r\n\r\nconst analyticsPost = async (endpoint: string, body: Record<string, unknown>): Promise<AnalyticsResult> => {\r\n if (!isConfigured()) {\r\n return { success: false, error: 'Platform not configured' };\r\n }\r\n\r\n try {\r\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.text();\r\n return { success: false, error };\r\n }\r\n\r\n return await response.json();\r\n } catch (error: unknown) {\r\n const message = error instanceof Error ? error.message : 'Unknown error';\r\n return { success: false, error: message };\r\n }\r\n};\r\n\r\nconst stripePost = async (endpoint: string, body: Record<string, unknown>): Promise<AnalyticsResult & Record<string, unknown>> => {\r\n if (!env.EZCODER_API_URL) {\r\n return { success: false, error: 'Platform not configured' };\r\n }\r\n\r\n if (!env.EZC_SECRET_KEY) {\r\n return {\r\n success: false,\r\n error: 'Payment configuration incomplete. The site owner needs to redeploy from EzCoder to enable checkout.',\r\n };\r\n }\r\n\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${env.EZC_SECRET_KEY}`,\r\n };\r\n\r\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.text();\r\n return { success: false, error };\r\n }\r\n\r\n return await response.json();\r\n } catch (error: unknown) {\r\n const message = error instanceof Error ? error.message : 'Unknown error';\r\n return { success: false, error: message };\r\n }\r\n};\r\n\r\nconst stripeGet = async (endpoint: string): Promise<AnalyticsResult & Record<string, unknown>> => {\r\n if (!env.EZCODER_API_URL) {\r\n return { success: false, error: 'Platform not configured' };\r\n }\r\n\r\n try {\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n if (env.EZC_SECRET_KEY) {\r\n headers['Authorization'] = `Bearer ${env.EZC_SECRET_KEY}`;\r\n }\r\n\r\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\r\n method: 'GET',\r\n headers,\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.text();\r\n return { success: false, error };\r\n }\r\n\r\n return await response.json();\r\n } catch (error: unknown) {\r\n const message = error instanceof Error ? error.message : 'Unknown error';\r\n return { success: false, error: message };\r\n }\r\n};\r\n\r\nconst sendPageExit = (): void => {\r\n if (!isConfigured() || typeof navigator === 'undefined') return;\r\n\r\n const payload = JSON.stringify({\r\n type: 'page_exit',\r\n projectId: env.EZC_PROJECT_ID,\r\n sessionId: getSessionId(),\r\n visitorId: getVisitorId(),\r\n pathname: currentPath,\r\n timeOnPage: getTimeOnPage(),\r\n scrollDepth: maxScrollDepth,\r\n timestamp: new Date().toISOString(),\r\n });\r\n\r\n if (navigator.sendBeacon) {\r\n navigator.sendBeacon(`${env.EZCODER_API_URL}/api/analytics/collect`, payload);\r\n }\r\n};\r\n\r\nexport const ezcoder: EzcoderClient = {\r\n isConfigured,\r\n\r\n analytics: {\r\n track: (eventType: string, properties: Record<string, unknown> = {}) => {\r\n return analyticsPost('/api/analytics/collect', {\r\n type: eventType,\r\n projectId: env.EZC_PROJECT_ID,\r\n sessionId: getSessionId(),\r\n visitorId: getVisitorId(),\r\n url: typeof window !== 'undefined' ? window.location.href : '',\r\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\r\n referrer: typeof document !== 'undefined' ? document.referrer : '',\r\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\r\n screenResolution: typeof window !== 'undefined'\r\n ? `${window.screen.width}x${window.screen.height}`\r\n : '',\r\n viewport: typeof window !== 'undefined'\r\n ? `${window.innerWidth}x${window.innerHeight}`\r\n : '',\r\n timestamp: new Date().toISOString(),\r\n metadata: properties,\r\n });\r\n },\r\n\r\n pageView: (path?: string) => {\r\n trackPageEntry();\r\n return ezcoder.analytics.track('page_view', {\r\n path: path || (typeof window !== 'undefined' ? window.location.pathname : '/'),\r\n title: typeof document !== 'undefined' ? document.title : '',\r\n });\r\n },\r\n\r\n identify: (userId: string, traits: Record<string, unknown> = {}) => {\r\n return ezcoder.analytics.track('identify', { userId, ...traits });\r\n },\r\n\r\n error: (message: string, context: Record<string, unknown> = {}) => {\r\n return ezcoder.analytics.track('error', {\r\n message,\r\n ...context,\r\n stack: (context.stack as string) || new Error().stack,\r\n });\r\n },\r\n },\r\n\r\n stripe: {\r\n createCheckout: async (priceId: string, options: CheckoutOptions = {}) => {\r\n const result = await stripePost('/api/stripe/create-checkout', {\r\n priceId,\r\n projectId: env.EZC_PROJECT_ID,\r\n successUrl: options.successUrl || `${typeof window !== 'undefined' ? window.location.origin : ''}/payment/success`,\r\n cancelUrl: options.cancelUrl || `${typeof window !== 'undefined' ? window.location.origin : ''}/payment/cancel`,\r\n customerEmail: options.customerEmail,\r\n quantity: options.quantity || 1,\r\n });\r\n\r\n if (result.url && options.redirect !== false && typeof window !== 'undefined') {\r\n window.location.href = result.url as string;\r\n }\r\n\r\n return result;\r\n },\r\n\r\n getProducts: async () => {\r\n return { products: [], message: 'Products managed via EzCoder dashboard' };\r\n },\r\n\r\n verifySession: async (sessionId: string) => {\r\n if (!sessionId) {\r\n return { success: false, error: 'Session ID is required' };\r\n }\r\n return stripeGet(`/api/stripe/verify-session?session_id=${encodeURIComponent(sessionId)}`);\r\n },\r\n\r\n getCustomerStatus: async (options: { customerId?: string; email?: string } = {}) => {\r\n const params = new URLSearchParams();\r\n if (options.customerId) params.set('customer_id', options.customerId);\r\n if (options.email) params.set('email', options.email);\r\n\r\n if (!options.customerId && !options.email) {\r\n return { success: false, error: 'Either customerId or email is required' };\r\n }\r\n\r\n return stripeGet(`/api/stripe/customer-status?${params.toString()}`);\r\n },\r\n\r\n createPortalSession: async (customerId: string, options: { returnUrl?: string; redirect?: boolean } = {}) => {\r\n const result = await stripePost('/api/stripe/customer-portal', {\r\n customerId,\r\n returnUrl: options.returnUrl || window.location.href,\r\n });\r\n\r\n if (result.url && options.redirect !== false && typeof window !== 'undefined') {\r\n window.location.href = result.url as string;\r\n }\r\n\r\n return result;\r\n },\r\n\r\n getInvoices: async (customerId: string, options: { limit?: number } = {}) => {\r\n const params = new URLSearchParams();\r\n params.set('customer_id', customerId);\r\n if (options.limit) params.set('limit', String(options.limit));\r\n return stripeGet(`/api/stripe/invoices?${params.toString()}`);\r\n },\r\n },\r\n\r\n users: {\r\n trackSignup: (userId: string, email: string, role: string | null = null) => {\r\n return ezcoder.analytics.track('user_signup', { userId, email, role, signupMethod: 'email' });\r\n },\r\n\r\n trackLogin: (userId: string) => {\r\n return ezcoder.analytics.track('user_login', { userId });\r\n },\r\n\r\n trackLogout: (userId: string) => {\r\n return ezcoder.analytics.track('user_logout', { userId });\r\n },\r\n\r\n trackRoleChange: (userId: string, oldRole: string, newRole: string) => {\r\n return ezcoder.analytics.track('role_change', { userId, oldRole, newRole });\r\n },\r\n },\r\n};\r\n\r\nexport const ezcoderAuthIntegration: AuthIntegration = {\r\n onLogin: (user: AuthUser) => {\r\n if (user?.id) {\r\n ezcoder.analytics.identify(user.id, {\r\n email: user.email,\r\n name: user.user_metadata?.full_name,\r\n });\r\n ezcoder.users.trackLogin(user.id);\r\n }\r\n },\r\n onSignup: (user: AuthUser) => {\r\n if (user?.id) {\r\n ezcoder.analytics.identify(user.id, { email: user.email });\r\n ezcoder.users.trackSignup(user.id, user.email || '');\r\n }\r\n },\r\n onLogout: (userId: string) => {\r\n if (userId) {\r\n ezcoder.users.trackLogout(userId);\r\n }\r\n },\r\n};\r\n\r\ninterface LayoutShift extends PerformanceEntry {\r\n hadRecentInput: boolean;\r\n value: number;\r\n}\r\n\r\ninterface PerformanceEventTiming extends PerformanceEntry {\r\n processingStart: number;\r\n}\r\n\r\nconst trackWebVitals = (): void => {\r\n if (typeof window === 'undefined' || !('PerformanceObserver' in window)) return;\r\n\r\n try {\r\n new PerformanceObserver((list) => {\r\n const entries = list.getEntries();\r\n const lastEntry = entries[entries.length - 1];\r\n if (lastEntry) {\r\n ezcoder.analytics.track('web_vital', {\r\n metric: 'LCP',\r\n value: Math.round(lastEntry.startTime),\r\n pathname: window.location.pathname,\r\n });\r\n }\r\n }).observe({ type: 'largest-contentful-paint', buffered: true });\r\n } catch { /* LCP not supported */ }\r\n\r\n try {\r\n new PerformanceObserver((list) => {\r\n const entry = list.getEntries()[0] as PerformanceEventTiming;\r\n if (entry) {\r\n ezcoder.analytics.track('web_vital', {\r\n metric: 'FID',\r\n value: Math.round(entry.processingStart - entry.startTime),\r\n pathname: window.location.pathname,\r\n });\r\n }\r\n }).observe({ type: 'first-input', buffered: true });\r\n } catch { /* FID not supported */ }\r\n\r\n try {\r\n let clsValue = 0;\r\n new PerformanceObserver((list) => {\r\n for (const entry of list.getEntries()) {\r\n if (!(entry as LayoutShift).hadRecentInput) {\r\n clsValue += (entry as LayoutShift).value;\r\n }\r\n }\r\n }).observe({ type: 'layout-shift', buffered: true });\r\n\r\n document.addEventListener('visibilitychange', () => {\r\n if (document.hidden && clsValue > 0) {\r\n ezcoder.analytics.track('web_vital', {\r\n metric: 'CLS',\r\n value: Math.round(clsValue * 1000) / 1000,\r\n pathname: window.location.pathname,\r\n });\r\n }\r\n });\r\n } catch { /* CLS not supported */ }\r\n};\r\n\r\nconst setupErrorTracking = (): void => {\r\n if (typeof window === 'undefined') return;\r\n\r\n window.onerror = (message, source, lineno, colno, error) => {\r\n ezcoder.analytics.track('js_error', {\r\n message: String(message),\r\n source,\r\n lineno,\r\n colno,\r\n stack: error?.stack,\r\n pathname: window.location.pathname,\r\n });\r\n return false;\r\n };\r\n\r\n window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {\r\n ezcoder.analytics.track('promise_rejection', {\r\n reason: event.reason?.message || String(event.reason),\r\n stack: event.reason?.stack,\r\n pathname: window.location.pathname,\r\n });\r\n });\r\n};\r\n\r\nif (typeof window !== 'undefined') {\r\n window.addEventListener('scroll', throttle(trackScrollDepth, 500), { passive: true });\r\n window.addEventListener('beforeunload', sendPageExit);\r\n\r\n document.addEventListener('visibilitychange', () => {\r\n if (!isConfigured()) return;\r\n if (document.hidden) {\r\n ezcoder.analytics.track('page_blur', {\r\n timeOnPage: getTimeOnPage(),\r\n scrollDepth: maxScrollDepth,\r\n pathname: currentPath,\r\n });\r\n } else {\r\n ezcoder.analytics.track('page_focus', { pathname: window.location.pathname });\r\n }\r\n });\r\n\r\n const originalPushState = history.pushState;\r\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\r\n sendPageExit();\r\n originalPushState.apply(this, args);\r\n trackPageEntry();\r\n if (isConfigured()) ezcoder.analytics.pageView();\r\n };\r\n\r\n const originalReplaceState = history.replaceState;\r\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\r\n originalReplaceState.apply(this, args);\r\n trackPageEntry();\r\n };\r\n\r\n window.addEventListener('popstate', () => {\r\n sendPageExit();\r\n trackPageEntry();\r\n if (isConfigured()) ezcoder.analytics.pageView();\r\n });\r\n\r\n if (isConfigured()) {\r\n setTimeout(() => {\r\n ezcoder.analytics.pageView();\r\n trackWebVitals();\r\n setupErrorTracking();\r\n }, 100);\r\n }\r\n\r\n if (env.EZCODER_API_URL && !env.EZC_SECRET_KEY) {\r\n console.warn(\r\n '[EzCoder SDK] EZCODER_SECRET_KEY is not set — Stripe checkout and authenticated API calls will fail. ' +\r\n 'Redeploy your project from the EzCoder editor to auto-provision keys.'\r\n );\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/database/DatabaseProvider.tsx","../src/core/bootstrap.ts","../src/database/errors.ts","../src/database/QueryBuilder.ts","../src/database/DatabaseClient.ts","../src/database/useRealtime.ts"],"sourcesContent":["import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';\nimport { supabase } from '../core/supabase';\nimport { env } from '../core/config';\nimport { loadBootstrap, getRuntimeConfig } from '../core/bootstrap';\nimport { DatabaseClient } from './DatabaseClient';\n\ninterface DatabaseContextValue {\n db: DatabaseClient | null;\n isConfigured: boolean;\n}\n\nconst DatabaseContext = createContext<DatabaseContextValue>({\n db: null,\n isConfigured: false,\n});\n\ninterface DatabaseProviderProps {\n children: ReactNode;\n projectId?: string;\n}\n\n/**\n * Parity Doctrine W2: the database is configured as soon as we know the\n * projectId — from the prop, the build-time env, OR the runtime bootstrap.\n * Crucially, a build that baked NO env (the herdmark \"useDatabase must be used\n * within <DatabaseProvider>\" boot crash) is no longer broken: we fetch the\n * config live and resolve the projectId at runtime. The DatabaseClient reaches\n * the DB through the platform proxy, so a configured Supabase client is NOT\n * required for data access — anonymous reads authorize by deployment origin.\n */\nexport function DatabaseProvider({ children, projectId }: DatabaseProviderProps) {\n const bakedProjectId = projectId || env.EZC_PROJECT_ID || '';\n const [runtimeProjectId, setRuntimeProjectId] = useState<string>(getRuntimeConfig()?.projectId || '');\n const [bootstrapAttempted, setBootstrapAttempted] = useState<boolean>(Boolean(getRuntimeConfig()));\n\n useEffect(() => {\n if (bakedProjectId) return; // already configured from build-time env/prop\n let cancelled = false;\n loadBootstrap().then((rc) => {\n if (cancelled) return;\n if (rc?.projectId) setRuntimeProjectId(rc.projectId);\n setBootstrapAttempted(true);\n });\n return () => { cancelled = true; };\n }, [bakedProjectId]);\n\n const resolvedProjectId = bakedProjectId || runtimeProjectId;\n const configured = Boolean(resolvedProjectId);\n\n const db = useMemo(\n () => (configured ? new DatabaseClient(supabase, resolvedProjectId) : null),\n [configured, resolvedProjectId],\n );\n\n const value = useMemo(() => ({ db, isConfigured: configured }), [db, configured]);\n\n // Env-less build ONLY: hold render until the runtime bootstrap resolves the\n // projectId, converting the old hard crash into a sub-second gate. A normally\n // configured build (projectId baked) never enters this branch.\n if (!bakedProjectId && !bootstrapAttempted && !runtimeProjectId) {\n return null;\n }\n\n return <DatabaseContext.Provider value={value}>{children}</DatabaseContext.Provider>;\n}\n\nexport function useDatabase(): DatabaseClient {\n const { db } = useContext(DatabaseContext);\n if (!db) {\n throw new Error(\n 'useDatabase() must be used within <DatabaseProvider>. ' +\n 'Ensure the app is wrapped in <DatabaseProvider> and the project has a deployment origin or EZC_PROJECT_ID.',\n );\n }\n return db;\n}\n\nexport function useDatabaseOptional(): DatabaseClient | null {\n const { db } = useContext(DatabaseContext);\n return db;\n}\n\nexport function useIsDatabaseConfigured(): boolean {\n const { isConfigured } = useContext(DatabaseContext);\n return isConfigured;\n}\n","/**\n * Runtime config bootstrap (Parity Doctrine W2).\n *\n * The SDK fetches /api/sdk/bootstrap ONCE at startup and overlays the result on\n * the build-time-baked `env`. This means a bundle that baked NO env (the\n * herdmark \"loads but crashes on boot\" class) still works — it learns its\n * config live — and preview and deployed take the identical path.\n *\n * Resolution order for any config value: runtime bootstrap → baked env. The\n * baked env is the OFFLINE FALLBACK, never the primary source. Secrets never\n * appear here — the endpoint returns public config only.\n */\n\nimport { env } from './config';\n\nexport interface RuntimeConfig {\n projectId: string;\n apiUrl: string;\n authUrl: string | null;\n authAnonKey: string | null;\n supabaseUrl: string | null;\n supabaseAnonKey: string | null;\n stripePublishableKey: string | null;\n storageBucketPublic: string | null;\n storageBucketPrivate: string | null;\n publicToken: string | null;\n manifest: unknown | null;\n}\n\nlet cached: RuntimeConfig | null = null;\nlet inflight: Promise<RuntimeConfig | null> | null = null;\n\n/** The base URL of the platform API. Baked value is the offline fallback. */\nfunction apiBase(): string {\n return (env.EZCODER_API_URL || 'https://ezcoder.dev').replace(/\\/$/, '');\n}\n\n/**\n * Fetch the runtime config once (coalesced). Safe to call from multiple\n * providers — only one network request is made. Never throws: on failure it\n * returns null and the SDK falls back to baked env.\n *\n * @param opts.force re-fetch even if cached\n */\nexport async function loadBootstrap(opts: { force?: boolean } = {}): Promise<RuntimeConfig | null> {\n if (cached && !opts.force) return cached;\n if (inflight && !opts.force) return inflight;\n if (typeof fetch === 'undefined') return null;\n\n inflight = (async () => {\n try {\n const headers: Record<string, string> = {};\n // If a token IS baked, send it so the endpoint resolves the project even\n // off a non-deployment origin (e.g. preview). Otherwise the endpoint\n // resolves by origin — no baked config required.\n const tok = env.EZC_PROJECT_TOKEN_PUBLIC || env.EZC_PROJECT_TOKEN_LEGACY || '';\n if (tok) headers['X-EzCoder-Public-Token'] = tok;\n // Pass the baked projectId as a preview fallback (honored only for trusted origins server-side).\n const qs = env.EZC_PROJECT_ID ? `?projectId=${encodeURIComponent(env.EZC_PROJECT_ID)}` : '';\n const res = await fetch(`${apiBase()}/api/sdk/bootstrap${qs}`, { method: 'GET', headers });\n if (!res.ok) return null;\n const body = await res.json().catch(() => null);\n if (!body?.success || !body.config?.projectId) return null;\n cached = body.config as RuntimeConfig;\n return cached;\n } catch {\n return null;\n } finally {\n inflight = null;\n }\n })();\n return inflight;\n}\n\n/** The loaded runtime config, or null if not yet loaded / unavailable. */\nexport function getRuntimeConfig(): RuntimeConfig | null {\n return cached;\n}\n\n/** Test seam. */\nexport function _resetBootstrap(): void {\n cached = null;\n inflight = null;\n}\n\n/**\n * Resolve a config value preferring runtime bootstrap over baked env. Use this\n * for any SDK-critical value so an env-less build still resolves it at runtime.\n */\nexport function configValue<K extends keyof RuntimeConfig>(key: K, bakedFallback: string): string {\n const rc = cached;\n const v = rc ? rc[key] : null;\n return (typeof v === 'string' && v) ? v : bakedFallback;\n}\n","export class DatabaseError extends Error {\r\n readonly code: string;\r\n readonly statusCode: number;\r\n\r\n constructor(message: string, code = 'DATABASE_ERROR', statusCode = 500) {\r\n super(message);\r\n this.name = 'DatabaseError';\r\n this.code = code;\r\n this.statusCode = statusCode;\r\n }\r\n}\r\n\r\nexport class QueryError extends DatabaseError {\r\n readonly sql?: string;\r\n\r\n constructor(message: string, sql?: string) {\r\n super(message, 'QUERY_ERROR', 400);\r\n this.name = 'QueryError';\r\n this.sql = sql;\r\n }\r\n}\r\n\r\nexport class ValidationError extends DatabaseError {\r\n constructor(message: string) {\r\n super(message, 'VALIDATION_ERROR', 422);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport class ConnectionError extends DatabaseError {\r\n constructor(message: string) {\r\n super(message, 'CONNECTION_ERROR', 503);\r\n this.name = 'ConnectionError';\r\n }\r\n}\r\n\r\nexport class NotFoundError extends DatabaseError {\r\n constructor(message = 'Record not found') {\r\n super(message, 'NOT_FOUND', 404);\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\nexport function mapRpcError(rpcResult: { success: boolean; error?: string; code?: string }): DatabaseError | null {\r\n if (rpcResult.success) return null;\r\n const msg = rpcResult.error || 'Unknown database error';\r\n if (msg.includes('No database schema exists')) return new NotFoundError(msg);\r\n if (msg.includes('Authentication required')) return new ConnectionError(msg);\r\n if (msg.includes('blocked') || msg.includes('forbidden')) return new ValidationError(msg);\r\n return new QueryError(msg);\r\n}\r\n","import type { SupabaseClient } from '@supabase/supabase-js';\r\nimport type { DatabaseResult, SingleResult, MutationResult, FilterValue, OrderOption } from './types';\r\nimport { QueryError, ValidationError, mapRpcError } from './errors';\r\n\r\nfunction escapeSqlValue(value: FilterValue): string {\r\n if (value === null) return 'NULL';\r\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';\r\n if (typeof value === 'number') {\r\n if (!Number.isFinite(value)) throw new ValidationError('Non-finite numbers are not allowed');\r\n return String(value);\r\n }\r\n return `'${String(value).replace(/'/g, \"''\")}'`;\r\n}\r\n\r\nfunction escapeIdentifier(name: string): string {\r\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {\r\n throw new ValidationError(`Invalid identifier: ${name}`);\r\n }\r\n return `\"${name}\"`;\r\n}\r\n\r\n/**\r\n * Validate a .select() column list. The list is concatenated into the SELECT\r\n * clause, so it must not be able to break out of the column position. We allow\r\n * the shapes generated apps actually use — column names, dotted refs, double-\r\n * quoted idents, `AS` aliases, commas, `*`, and simple function calls like\r\n * count(*) — but reject statement terminators, comment markers, and nested\r\n * sub-SELECTs that would change the query's meaning (security review finding 3).\r\n */\r\nfunction assertSafeSelectColumns(columns: string): void {\r\n if (columns === '*') return;\r\n if (/[;]|--|\\/\\*|\\*\\//.test(columns)) {\r\n throw new ValidationError('select() columns may not contain statement separators or comments');\r\n }\r\n if (/\\bselect\\b/i.test(columns)) {\r\n throw new ValidationError('select() columns may not contain a sub-SELECT');\r\n }\r\n // Allowed character set: identifiers, dots, commas, whitespace, parens, star,\r\n // quotes (for quoted idents / string-literal aliases). No operators that\r\n // enable injection (e.g. semicolons handled above).\r\n if (!/^[A-Za-z0-9_.,*()\\s\"']+$/.test(columns)) {\r\n throw new ValidationError('select() columns contain unsupported characters');\r\n }\r\n}\r\n\r\ntype Operation = 'select' | 'insert' | 'update' | 'delete' | 'count' | 'upsert';\r\n\r\ninterface Filter {\r\n column: string;\r\n op: string;\r\n value: FilterValue | FilterValue[];\r\n}\r\n\r\nexport interface ServerProxy {\r\n serverQuery?: (sql: string) => Promise<{ success: boolean; data?: unknown[]; rowCount?: number; error?: string; schema?: string }>;\r\n serverExec?: (sql: string) => Promise<{ success: boolean; data?: unknown[]; rowCount?: number; error?: string; schema?: string }>;\r\n}\r\n\r\nexport class QueryBuilder<T = Record<string, unknown>> {\r\n private readonly supabase: SupabaseClient;\r\n private readonly projectId: string;\r\n private readonly table: string;\r\n private readonly serverProxy?: ServerProxy;\r\n\r\n private operation: Operation = 'select';\r\n private selectColumns = '*';\r\n private filters: Filter[] = [];\r\n private orderClauses: string[] = [];\r\n private limitValue: number | null = null;\r\n private offsetValue: number | null = null;\r\n private insertData: Record<string, FilterValue>[] | null = null;\r\n private updateData: Record<string, FilterValue> | null = null;\r\n private upsertConflict: string | null = null;\r\n private singleMode = false;\r\n private maybeSingleMode = false;\r\n\r\n constructor(supabase: SupabaseClient, projectId: string, table: string, serverProxy?: ServerProxy) {\r\n this.supabase = supabase;\r\n this.projectId = projectId;\r\n this.table = table;\r\n this.serverProxy = serverProxy;\r\n }\r\n\r\n select(columns = '*'): this {\r\n assertSafeSelectColumns(columns);\r\n this.operation = 'select';\r\n this.selectColumns = columns;\r\n return this;\r\n }\r\n\r\n // --- Filters ---\r\n\r\n eq(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '=', value });\r\n return this;\r\n }\r\n\r\n neq(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '!=', value });\r\n return this;\r\n }\r\n\r\n gt(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '>', value });\r\n return this;\r\n }\r\n\r\n lt(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '<', value });\r\n return this;\r\n }\r\n\r\n gte(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '>=', value });\r\n return this;\r\n }\r\n\r\n lte(column: string, value: FilterValue): this {\r\n this.filters.push({ column, op: '<=', value });\r\n return this;\r\n }\r\n\r\n like(column: string, pattern: string): this {\r\n this.filters.push({ column, op: 'LIKE', value: pattern });\r\n return this;\r\n }\r\n\r\n ilike(column: string, pattern: string): this {\r\n this.filters.push({ column, op: 'ILIKE', value: pattern });\r\n return this;\r\n }\r\n\r\n in(column: string, values: FilterValue[]): this {\r\n this.filters.push({ column, op: 'IN', value: values });\r\n return this;\r\n }\r\n\r\n is(column: string, value: null | boolean): this {\r\n this.filters.push({ column, op: 'IS', value });\r\n return this;\r\n }\r\n\r\n // --- Ordering & Pagination ---\r\n\r\n order(column: string, options: OrderOption = {}): this {\r\n const dir = options.ascending === false ? 'DESC' : 'ASC';\r\n const nulls = options.nullsFirst ? 'NULLS FIRST' : 'NULLS LAST';\r\n this.orderClauses.push(`${escapeIdentifier(column)} ${dir} ${nulls}`);\r\n return this;\r\n }\r\n\r\n limit(count: number): this {\r\n this.limitValue = count;\r\n return this;\r\n }\r\n\r\n offset(count: number): this {\r\n this.offsetValue = count;\r\n return this;\r\n }\r\n\r\n // --- Mutations ---\r\n\r\n insert(records: Record<string, FilterValue> | Record<string, FilterValue>[]): this {\r\n this.operation = 'insert';\r\n this.insertData = Array.isArray(records) ? records : [records];\r\n return this;\r\n }\r\n\r\n update(values: Record<string, FilterValue>): this {\r\n this.operation = 'update';\r\n this.updateData = values;\r\n return this;\r\n }\r\n\r\n delete(): this {\r\n this.operation = 'delete';\r\n return this;\r\n }\r\n\r\n upsert(records: Record<string, FilterValue> | Record<string, FilterValue>[], options?: { onConflict?: string }): this {\r\n this.operation = 'upsert';\r\n this.insertData = Array.isArray(records) ? records : [records];\r\n this.upsertConflict = options?.onConflict || null;\r\n return this;\r\n }\r\n\r\n // --- Result Helpers ---\r\n\r\n count(): QueryBuilder<{ count: number }> {\r\n this.operation = 'count';\r\n return this as unknown as QueryBuilder<{ count: number }>;\r\n }\r\n\r\n single(): QueryBuilder<T> {\r\n this.singleMode = true;\r\n this.limitValue = 1;\r\n return this;\r\n }\r\n\r\n maybeSingle(): QueryBuilder<T> {\r\n this.maybeSingleMode = true;\r\n this.limitValue = 1;\r\n return this;\r\n }\r\n\r\n // --- SQL Building ---\r\n\r\n private buildWhereClause(): string {\r\n if (this.filters.length === 0) return '';\r\n const conditions = this.filters.map((f) => {\r\n const col = escapeIdentifier(f.column);\r\n if (f.op === 'IS') {\r\n const val = f.value === null ? 'NULL' : f.value ? 'TRUE' : 'FALSE';\r\n return `${col} IS ${val}`;\r\n }\r\n if (f.op === 'IN') {\r\n const vals = (f.value as FilterValue[]).map(escapeSqlValue).join(', ');\r\n return `${col} IN (${vals})`;\r\n }\r\n return `${col} ${f.op} ${escapeSqlValue(f.value as FilterValue)}`;\r\n });\r\n return ` WHERE ${conditions.join(' AND ')}`;\r\n }\r\n\r\n private buildSelectSql(): string {\r\n let sql = `SELECT ${this.selectColumns} FROM \"${this.table}\"`;\r\n sql += this.buildWhereClause();\r\n if (this.orderClauses.length > 0) sql += ` ORDER BY ${this.orderClauses.join(', ')}`;\r\n if (this.limitValue !== null) sql += ` LIMIT ${this.limitValue}`;\r\n if (this.offsetValue !== null && this.offsetValue > 0) sql += ` OFFSET ${this.offsetValue}`;\r\n return sql;\r\n }\r\n\r\n private buildCountSql(): string {\r\n let sql = `SELECT COUNT(*) as count FROM \"${this.table}\"`;\r\n sql += this.buildWhereClause();\r\n return sql;\r\n }\r\n\r\n private buildInsertSql(): string {\r\n if (!this.insertData || this.insertData.length === 0) {\r\n throw new ValidationError('No data provided for insert');\r\n }\r\n const columns = Object.keys(this.insertData[0]);\r\n const colList = columns.map(escapeIdentifier).join(', ');\r\n const rows = this.insertData.map(\r\n (row) => `(${columns.map((c) => escapeSqlValue(row[c] ?? null)).join(', ')})`\r\n );\r\n return `INSERT INTO \"${this.table}\" (${colList}) VALUES ${rows.join(', ')}`;\r\n }\r\n\r\n private buildUpsertSql(): string {\r\n let sql = this.buildInsertSql();\r\n const conflict = this.upsertConflict || 'id';\r\n const columns = Object.keys(this.insertData![0]);\r\n const updateCols = columns\r\n .filter((c) => c !== conflict)\r\n .map((c) => `${escapeIdentifier(c)} = EXCLUDED.${escapeIdentifier(c)}`)\r\n .join(', ');\r\n sql += ` ON CONFLICT (${escapeIdentifier(conflict)}) DO UPDATE SET ${updateCols}`;\r\n return sql;\r\n }\r\n\r\n private buildUpdateSql(): string {\r\n if (!this.updateData || Object.keys(this.updateData).length === 0) {\r\n throw new ValidationError('No data provided for update');\r\n }\r\n if (this.filters.length === 0) {\r\n throw new ValidationError('UPDATE without filters is not allowed — add .eq() or other filters');\r\n }\r\n const setClauses = Object.entries(this.updateData)\r\n .map(([col, val]) => `${escapeIdentifier(col)} = ${escapeSqlValue(val)}`)\r\n .join(', ');\r\n return `UPDATE \"${this.table}\" SET ${setClauses}${this.buildWhereClause()}`;\r\n }\r\n\r\n private buildDeleteSql(): string {\r\n if (this.filters.length === 0) {\r\n throw new ValidationError('DELETE without filters is not allowed — add .eq() or other filters');\r\n }\r\n return `DELETE FROM \"${this.table}\"${this.buildWhereClause()}`;\r\n }\r\n\r\n // --- Execution ---\r\n\r\n private async executeQuery(): Promise<DatabaseResult<T>> {\r\n const isRead = this.operation === 'select' || this.operation === 'count';\r\n\r\n let sql: string;\r\n switch (this.operation) {\r\n case 'select': sql = this.buildSelectSql(); break;\r\n case 'count': sql = this.buildCountSql(); break;\r\n case 'insert': sql = this.buildInsertSql(); break;\r\n case 'upsert': sql = this.buildUpsertSql(); break;\r\n case 'update': sql = this.buildUpdateSql(); break;\r\n case 'delete': sql = this.buildDeleteSql(); break;\r\n default: throw new QueryError(`Unknown operation: ${this.operation}`);\r\n }\r\n\r\n // ONE path (Parity Doctrine W1): every read/write goes through the platform\r\n // proxy. The DatabaseClient supplies serverQuery/serverExec, which attach the\r\n // right credential (end-user JWT → token → origin) — identical in preview and\r\n // deployed, so there is no environment branching here.\r\n const fn = isRead ? this.serverProxy?.serverQuery : this.serverProxy?.serverExec;\r\n if (!fn) throw new QueryError('Database client is not configured', sql);\r\n const data = await fn(sql);\r\n if (!data.success) {\r\n const dbError = mapRpcError(data);\r\n if (dbError) throw dbError;\r\n throw new QueryError(data.error || 'Query failed', sql);\r\n }\r\n return {\r\n success: true,\r\n data: (isRead ? data.data || [] : []) as T[],\r\n rowCount: data.rowCount ?? (isRead ? (data.data?.length || 0) : 0),\r\n schema: data.schema,\r\n };\r\n }\r\n\r\n then<TResult1 = DatabaseResult<T> | SingleResult<T>, TResult2 = never>(\r\n onfulfilled?: ((value: DatabaseResult<T> | SingleResult<T>) => TResult1 | PromiseLike<TResult1>) | null,\r\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\r\n ): Promise<TResult1 | TResult2> {\r\n const promise = this.executeQuery().then((result) => {\r\n if (this.singleMode) {\r\n if (result.data.length === 0) {\r\n throw new QueryError('Expected exactly one row, got 0');\r\n }\r\n return { success: true, data: result.data[0], error: undefined } as SingleResult<T>;\r\n }\r\n if (this.maybeSingleMode) {\r\n return {\r\n success: true,\r\n data: result.data.length > 0 ? result.data[0] : null,\r\n error: undefined,\r\n } as SingleResult<T>;\r\n }\r\n return result;\r\n });\r\n return promise.then(onfulfilled, onrejected);\r\n }\r\n}\r\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { DatabaseResult, MutationResult, SchemaInfo } from './types';\nimport { QueryBuilder } from './QueryBuilder';\nimport { QueryError, ConnectionError } from './errors';\nimport { ezcoder } from '../core/platform';\nimport { features, env } from '../core/config';\nimport { getRuntimeConfig } from '../core/bootstrap';\n\nfunction trackDbEvent(event: string, props: Record<string, unknown>) {\n if (!features.analytics) return;\n try { ezcoder.analytics.track(event, props); } catch { /* non-critical */ }\n}\n\ninterface ProxyResult {\n success: boolean;\n data?: unknown[];\n rowCount?: number;\n error?: string;\n schema?: string;\n exists?: boolean;\n tables?: unknown[];\n tablesCount?: number;\n createdAt?: string;\n lastAccessedAt?: string;\n executed_sql?: string;\n}\n\nconst MAX_RETRIES = 3;\nconst SERVER_TIMEOUT_MS = 8000;\n\n/**\n * ONE data path (Parity Doctrine W1). Every database call — preview & deployed,\n * read & write, anonymous & authenticated, browser & server — goes through the\n * platform proxy `/api/platform/db/{projectId}/{query|execute|schema}`. The\n * ONLY thing that varies is the credential attached:\n *\n * - server mode → Authorization: Bearer <server API key>\n * - logged-in user → Authorization: Bearer <tenant session JWT> (RLS applies)\n * - anonymous + token → X-EzCoder-Public-Token: <public/legacy token>\n * - anonymous, no tok → nothing; the server authorizes by deployment origin\n *\n * No environment branching, no RPC-vs-proxy fork, no preview-only fallback —\n * preview and deployed take byte-identical paths, which is the whole point.\n */\nexport class DatabaseClient {\n private readonly supabase: SupabaseClient | null;\n private readonly projectId: string;\n private apiKey?: string;\n private platformUrl: string;\n private serverMode: boolean = false;\n\n constructor(supabase: SupabaseClient | null, projectId: string) {\n this.supabase = supabase;\n this.projectId = projectId;\n this.platformUrl = env.EZCODER_API_URL || 'https://ezcoder.dev';\n }\n\n static createServerClient(\n projectId: string,\n apiKey: string,\n platformUrl?: string\n ): DatabaseClient {\n const client = new DatabaseClient(null, projectId);\n client.apiKey = apiKey;\n client.platformUrl = platformUrl\n || (typeof process !== 'undefined' && process.env?.EZCODER_API_URL)\n || env.EZCODER_API_URL\n || 'https://ezcoder.dev';\n client.serverMode = true;\n return client;\n }\n\n from<T = Record<string, unknown>>(table: string): QueryBuilder<T> {\n return new QueryBuilder<T>(null as unknown as SupabaseClient, this.projectId, table, {\n serverQuery: (sql: string) => this._proxy('/query', sql),\n serverExec: (sql: string) => this._proxy('/execute', sql),\n });\n }\n\n async sql<T = Record<string, unknown>>(query: string): Promise<DatabaseResult<T>> {\n const trimmed = query.trim().toLowerCase();\n if (!trimmed.startsWith('select')) {\n throw new QueryError('sql() is for read-only queries. Use execute() for mutations.');\n }\n const start = Date.now();\n const result = await this._proxy('/query', query);\n const latencyMs = Date.now() - start;\n if (!result.success) {\n trackDbEvent('db_query', { projectId: this.projectId, latencyMs, success: false, error: result.error });\n throw new QueryError(result.error || 'Query failed', query);\n }\n trackDbEvent('db_query', { projectId: this.projectId, latencyMs, success: true, rowCount: result.rowCount ?? 0 });\n return {\n success: true,\n data: (result.data || []) as T[],\n rowCount: result.rowCount ?? (result.data?.length || 0),\n schema: result.schema,\n };\n }\n\n async execute(sql: string): Promise<MutationResult> {\n const start = Date.now();\n const result = await this._proxy('/execute', sql);\n const latencyMs = Date.now() - start;\n if (!result.success) {\n trackDbEvent('db_mutation', { projectId: this.projectId, latencyMs, success: false, error: result.error });\n throw new QueryError(result.error || 'Execution failed', sql);\n }\n trackDbEvent('db_mutation', { projectId: this.projectId, latencyMs, success: true, rowCount: result.rowCount ?? 0 });\n return {\n success: true,\n rowCount: result.rowCount ?? 0,\n schema: result.schema,\n executed_sql: result.executed_sql,\n };\n }\n\n async getSchema(): Promise<SchemaInfo> {\n const result = await this._proxy('/schema', null);\n if (!result.success) throw new ConnectionError(result.error || 'Schema fetch failed');\n return {\n exists: result.exists ?? false,\n schema: result.schema,\n tables: (result.tables || []) as SchemaInfo['tables'],\n tablesCount: result.tablesCount ?? 0,\n createdAt: result.createdAt,\n lastAccessedAt: result.lastAccessedAt,\n };\n }\n\n /**\n * Resolve the credential for this call. Order mirrors the server's auth tiers:\n * server key → end-user session JWT → public/legacy token → none (origin).\n */\n private async _authHeaders(): Promise<Record<string, string>> {\n if (this.serverMode && this.apiKey) {\n return { Authorization: `Bearer ${this.apiKey}` };\n }\n // Browser: prefer the logged-in user's session so the server runs the query\n // under their identity and RLS applies.\n if (this.supabase?.auth?.getSession) {\n let sessionResult: { data?: { session?: { access_token?: string } | null } } | undefined;\n try {\n sessionResult = await this.supabase.auth.getSession();\n } catch {\n // getSession THREW (network/refresh race). Do NOT silently fall through\n // to the public/origin path — that runs without per-user RLS and would\n // leak other users' rows to a logged-in user. Send no credential so the\n // server rejects (401) and the app re-authenticates. A NULL session\n // (logged out) is different and DOES fall through below.\n return {};\n }\n const token = sessionResult?.data?.session?.access_token;\n if (token) return { Authorization: `Bearer ${token}` };\n }\n // Anonymous (no session): send the browser-safe project token. Prefer the\n // runtime-bootstrapped token (works even when the build baked none); fall\n // back to the baked token; otherwise send nothing and let the server\n // authorize by origin.\n const pub = getRuntimeConfig()?.publicToken\n || env.EZC_PROJECT_TOKEN_PUBLIC || env.EZC_PROJECT_TOKEN_LEGACY || '';\n if (pub) return { 'X-EzCoder-Public-Token': pub };\n return {};\n }\n\n /** Platform API base — runtime bootstrap wins over the baked value so an\n * env-less build still reaches the right host. */\n private baseUrl(): string {\n return (getRuntimeConfig()?.apiUrl || this.platformUrl).replace(/\\/$/, '');\n }\n\n private async _proxy(endpoint: '/query' | '/execute' | '/schema', sql: string | null): Promise<ProxyResult> {\n const url = `${this.baseUrl()}/api/platform/db/${this.projectId}${endpoint}`;\n const method = endpoint === '/schema' ? 'GET' : 'POST';\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const headers: Record<string, string> = { ...(await this._authHeaders()) };\n if (method === 'POST') headers['Content-Type'] = 'application/json';\n const res = await fetch(url, {\n method,\n headers,\n body: method === 'POST' ? JSON.stringify({ sql }) : undefined,\n signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),\n });\n\n if (res.status === 429) {\n const retryAfter = parseInt(res.headers.get('retry-after') || '60', 10);\n await new Promise(r => setTimeout(r, Math.min(retryAfter, 5) * 1000));\n continue;\n }\n if (res.status === 503) {\n await new Promise(r => setTimeout(r, (attempt + 1) * 2000));\n continue;\n }\n return await res.json() as ProxyResult;\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n // A thrown error (timeout / connection drop) on /execute may mean the\n // write already committed server-side — retrying could double-insert.\n // Reads and schema are idempotent and safe to retry. (429/503 above are\n // explicit \"not processed\" signals and DO retry for all endpoints.)\n if (endpoint === '/execute') break;\n }\n }\n return { success: false, error: lastError?.message || 'Request failed after retries' };\n }\n}\n","import { useEffect, useState, useRef } from 'react';\r\nimport { supabase, isSupabaseConfigured } from '../core/supabase';\r\nimport { env } from '../core/config';\r\n\r\ntype RealtimeEvent = 'INSERT' | 'UPDATE' | 'DELETE' | '*';\r\n\r\ninterface RealtimeOptions {\r\n event?: RealtimeEvent;\r\n filter?: string;\r\n}\r\n\r\ninterface UseRealtimeReturn<T> {\r\n data: T[];\r\n status: 'connecting' | 'connected' | 'error' | 'disabled';\r\n setData: React.Dispatch<React.SetStateAction<T[]>>;\r\n}\r\n\r\nexport function useRealtime<T extends Record<string, unknown> = Record<string, unknown>>(\r\n table: string,\r\n options: RealtimeOptions = {},\r\n): UseRealtimeReturn<T> {\r\n const [data, setData] = useState<T[]>([]);\r\n const [status, setStatus] = useState<UseRealtimeReturn<T>['status']>('connecting');\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n\r\n const projectId = env.EZC_PROJECT_ID;\r\n\r\n useEffect(() => {\r\n if (!isSupabaseConfigured || !projectId) {\r\n setStatus('disabled');\r\n return;\r\n }\r\n\r\n const schemaName = `proj_${projectId.replace(/-/g, '_')}`;\r\n const channelName = `${schemaName}_${table}_${optionsRef.current.event || 'all'}`;\r\n\r\n const channel = supabase\r\n .channel(channelName)\r\n .on(\r\n 'postgres_changes' as never,\r\n {\r\n event: optionsRef.current.event || '*',\r\n schema: schemaName,\r\n table,\r\n filter: optionsRef.current.filter,\r\n } as never,\r\n (payload: { eventType: string; new: Record<string, unknown>; old: Record<string, unknown> }) => {\r\n if (payload.eventType === 'INSERT') {\r\n setData((prev) => [...prev, payload.new as T]);\r\n } else if (payload.eventType === 'UPDATE') {\r\n setData((prev) =>\r\n prev.map((item) =>\r\n (item as Record<string, unknown>).id === (payload.new as Record<string, unknown>).id\r\n ? (payload.new as T)\r\n : item,\r\n ),\r\n );\r\n } else if (payload.eventType === 'DELETE') {\r\n setData((prev) =>\r\n prev.filter(\r\n (item) =>\r\n (item as Record<string, unknown>).id !== (payload.old as Record<string, unknown>).id,\r\n ),\r\n );\r\n }\r\n },\r\n )\r\n .subscribe((subStatus: string) => {\r\n setStatus(subStatus === 'SUBSCRIBED' ? 'connected' : 'connecting');\r\n });\r\n\r\n return () => {\r\n supabase.removeChannel(channel);\r\n };\r\n }, [projectId, table]);\r\n\r\n return { data, status, setData };\r\n}\r\n"],"mappings":"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","names":["supabase","supabase","useEffect","useState","useState","useEffect"]}
|