@pol-studios/ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,359 @@
1
+ "use client";
2
+
3
+ // src/adapters/tanstack-router-adapter.ts
4
+ import React, { useMemo } from "react";
5
+ import {
6
+ useNavigate as useTanStackNavigate,
7
+ useLocation as useTanStackLocation,
8
+ useParams as useTanStackParams,
9
+ useRouter,
10
+ Link as TanStackLink
11
+ } from "@tanstack/react-router";
12
+ function TanStackLinkWrapper({ to, params, children, className, onClick }) {
13
+ const linkProps = {
14
+ to,
15
+ params,
16
+ className,
17
+ onClick,
18
+ children
19
+ };
20
+ return React.createElement(TanStackLink, linkProps);
21
+ }
22
+ function createTanStackRouterAdapter(navigateFn) {
23
+ return {
24
+ navigate: navigateFn ?? (() => {
25
+ console.warn("Navigate called on adapter created outside React. Use useTanStackRouterAdapter() hook instead.");
26
+ }),
27
+ useLocation: function tanStackUseLocation() {
28
+ const location = useTanStackLocation();
29
+ return {
30
+ pathname: location.pathname,
31
+ search: location.searchStr || "",
32
+ hash: location.hash || ""
33
+ };
34
+ },
35
+ useParams: function tanStackUseParams() {
36
+ return useTanStackParams({ strict: false });
37
+ },
38
+ Link: TanStackLinkWrapper
39
+ };
40
+ }
41
+ function useTanStackNavigateAdapter() {
42
+ const navigate = useTanStackNavigate();
43
+ return (options) => {
44
+ const navOptions = {
45
+ to: options.to,
46
+ params: options.params,
47
+ search: options.search,
48
+ replace: options.replace
49
+ };
50
+ navigate(navOptions);
51
+ };
52
+ }
53
+ var noopRouterAdapter = {
54
+ navigate: (_options) => {
55
+ },
56
+ useLocation: function noopUseLocation() {
57
+ return {
58
+ pathname: "/",
59
+ search: "",
60
+ hash: ""
61
+ };
62
+ },
63
+ useParams: function noopUseParams() {
64
+ return {};
65
+ },
66
+ Link: TanStackLinkWrapper
67
+ };
68
+ function useSafeRouter() {
69
+ try {
70
+ return useRouter({ warn: false });
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+ function useTanStackRouterAdapter() {
76
+ const router = useSafeRouter();
77
+ return useMemo(() => {
78
+ if (!router) {
79
+ return noopRouterAdapter;
80
+ }
81
+ return {
82
+ navigate: (options) => {
83
+ const navOptions = {
84
+ to: options.to,
85
+ params: options.params,
86
+ search: options.search,
87
+ replace: options.replace
88
+ };
89
+ router.navigate(navOptions);
90
+ },
91
+ useLocation: function tanStackUseLocation() {
92
+ const location = useTanStackLocation();
93
+ return {
94
+ pathname: location.pathname,
95
+ search: location.searchStr || "",
96
+ hash: location.hash || ""
97
+ };
98
+ },
99
+ useParams: function tanStackUseParams() {
100
+ return useTanStackParams({ strict: false });
101
+ },
102
+ Link: TanStackLinkWrapper
103
+ };
104
+ }, [router]);
105
+ }
106
+
107
+ // src/adapters/auth-adapter.ts
108
+ import { useMemo as useMemo2 } from "react";
109
+ function createPolDbHooksAuthValue(auth) {
110
+ const user = auth.user ? { id: auth.user.id, email: auth.user.email } : auth.user;
111
+ const profile = auth.profile;
112
+ const isAuthenticated = Boolean(auth.user) && !auth.isLoading;
113
+ return {
114
+ user,
115
+ profile,
116
+ isLoading: auth.isLoading,
117
+ isAuthenticated,
118
+ access: auth.access ?? [],
119
+ hasAccess: auth.hasAccess,
120
+ signInAsync: auth.signInAsync,
121
+ signOutAsync: auth.signOutAsync,
122
+ isArchived: auth.isArchived,
123
+ isSuspended: auth.isSuspended
124
+ };
125
+ }
126
+ function usePolDbHooksAuthAdapter(useSetupAuthHook) {
127
+ const auth = useSetupAuthHook();
128
+ return useMemo2(
129
+ () => createPolDbHooksAuthValue(auth),
130
+ [
131
+ auth.user,
132
+ auth.profile,
133
+ auth.isLoading,
134
+ auth.access,
135
+ auth.hasAccess,
136
+ auth.signInAsync,
137
+ auth.signOutAsync,
138
+ auth.isArchived,
139
+ auth.isSuspended
140
+ ]
141
+ );
142
+ }
143
+ function createPolDbHooksAuthAdapter(useSetupAuthHook) {
144
+ return () => usePolDbHooksAuthAdapter(useSetupAuthHook);
145
+ }
146
+
147
+ // src/adapters/supabase-data-adapter.ts
148
+ import { useMemo as useMemo3 } from "react";
149
+ function applyFilters(query, filters) {
150
+ if (!filters || filters.length === 0) return query;
151
+ for (const filter of filters) {
152
+ const { field, operator, value } = filter;
153
+ switch (operator) {
154
+ case "eq":
155
+ query = query.eq(field, value);
156
+ break;
157
+ case "neq":
158
+ query = query.neq(field, value);
159
+ break;
160
+ case "gt":
161
+ query = query.gt(field, value);
162
+ break;
163
+ case "gte":
164
+ query = query.gte(field, value);
165
+ break;
166
+ case "lt":
167
+ query = query.lt(field, value);
168
+ break;
169
+ case "lte":
170
+ query = query.lte(field, value);
171
+ break;
172
+ case "like":
173
+ query = query.like(field, value);
174
+ break;
175
+ case "ilike":
176
+ query = query.ilike(field, value);
177
+ break;
178
+ case "in":
179
+ query = query.in(field, value);
180
+ break;
181
+ case "contains":
182
+ query = query.contains(field, value);
183
+ break;
184
+ case "is":
185
+ query = query.is(field, value);
186
+ break;
187
+ default:
188
+ console.warn(`Unknown filter operator: ${operator}`);
189
+ }
190
+ }
191
+ return query;
192
+ }
193
+ function applySorting(query, sort) {
194
+ if (!sort || sort.length === 0) return query;
195
+ for (const sortItem of sort) {
196
+ query = query.order(sortItem.field, { ascending: sortItem.direction === "asc" });
197
+ }
198
+ return query;
199
+ }
200
+ function applyPagination(query, pagination) {
201
+ if (!pagination) return query;
202
+ const { page, pageSize, offset, limit } = pagination;
203
+ if (offset !== void 0 && limit !== void 0) {
204
+ return query.range(offset, offset + limit - 1);
205
+ }
206
+ if (page !== void 0 && pageSize !== void 0) {
207
+ const calculatedOffset = (page - 1) * pageSize;
208
+ return query.range(calculatedOffset, calculatedOffset + pageSize - 1);
209
+ }
210
+ if (limit !== void 0) {
211
+ return query.limit(limit);
212
+ }
213
+ return query;
214
+ }
215
+ function createSupabaseDataAdapter(client, options = {}) {
216
+ const { schema = "public", primaryKey = "id" } = options;
217
+ const adapter = {
218
+ async getById(table, id) {
219
+ const { data, error } = await client.schema(schema).from(table).select("*").eq(primaryKey, id).single();
220
+ if (error) {
221
+ if (error.code === "PGRST116") {
222
+ return null;
223
+ }
224
+ throw new Error(`Failed to fetch ${table} by id: ${error.message}`);
225
+ }
226
+ return data;
227
+ },
228
+ async getMany(table, params) {
229
+ let query = client.schema(schema).from(table).select(params?.select ?? "*");
230
+ query = applyFilters(query, params?.filters);
231
+ query = applySorting(query, params?.sort);
232
+ query = applyPagination(query, params?.pagination);
233
+ const { data, error } = await query;
234
+ if (error) {
235
+ throw new Error(`Failed to fetch ${table}: ${error.message}`);
236
+ }
237
+ return data ?? [];
238
+ },
239
+ async getManyWithCount(table, params) {
240
+ let query = client.schema(schema).from(table).select(params?.select ?? "*", { count: "exact" });
241
+ query = applyFilters(query, params?.filters);
242
+ query = applySorting(query, params?.sort);
243
+ query = applyPagination(query, params?.pagination);
244
+ const { data, count, error } = await query;
245
+ if (error) {
246
+ throw new Error(`Failed to fetch ${table} with count: ${error.message}`);
247
+ }
248
+ return {
249
+ data: data ?? [],
250
+ count: count ?? 0
251
+ };
252
+ },
253
+ async create(table, data) {
254
+ const { data: result, error } = await client.schema(schema).from(table).insert(data).select().single();
255
+ if (error) {
256
+ throw new Error(`Failed to create ${table}: ${error.message}`);
257
+ }
258
+ return result;
259
+ },
260
+ async update(table, id, data) {
261
+ const { data: result, error } = await client.schema(schema).from(table).update(data).eq(primaryKey, id).select().single();
262
+ if (error) {
263
+ throw new Error(`Failed to update ${table}: ${error.message}`);
264
+ }
265
+ return result;
266
+ },
267
+ async delete(table, id) {
268
+ const { error } = await client.schema(schema).from(table).delete().eq(primaryKey, id);
269
+ if (error) {
270
+ throw new Error(`Failed to delete ${table}: ${error.message}`);
271
+ }
272
+ },
273
+ async query(queryFn) {
274
+ return queryFn();
275
+ },
276
+ subscribe(table, callback, filter) {
277
+ let filterString;
278
+ if (filter && filter.length > 0) {
279
+ const eqFilter = filter.find((f) => f.operator === "eq");
280
+ if (eqFilter) {
281
+ filterString = `${eqFilter.field}=eq.${eqFilter.value}`;
282
+ }
283
+ }
284
+ const channelName = `${table}-${Date.now()}`;
285
+ const channel = client.channel(channelName).on(
286
+ "postgres_changes",
287
+ {
288
+ event: "*",
289
+ schema,
290
+ table,
291
+ filter: filterString
292
+ },
293
+ (payload) => {
294
+ const realtimePayload = {
295
+ eventType: payload.eventType,
296
+ new: payload.new,
297
+ old: payload.old,
298
+ table
299
+ };
300
+ callback(realtimePayload);
301
+ }
302
+ ).subscribe();
303
+ return () => {
304
+ channel.unsubscribe();
305
+ client.removeChannel(channel);
306
+ };
307
+ },
308
+ async uploadFile(bucket, path, file) {
309
+ const { data, error } = await client.storage.from(bucket).upload(path, file, {
310
+ cacheControl: "3600",
311
+ upsert: false
312
+ });
313
+ if (error) {
314
+ throw new Error(`Failed to upload file: ${error.message}`);
315
+ }
316
+ const {
317
+ data: { publicUrl }
318
+ } = client.storage.from(bucket).getPublicUrl(data.path);
319
+ return {
320
+ path: data.path,
321
+ url: publicUrl
322
+ };
323
+ },
324
+ getFileUrl(bucket, path) {
325
+ const {
326
+ data: { publicUrl }
327
+ } = client.storage.from(bucket).getPublicUrl(path);
328
+ return publicUrl;
329
+ },
330
+ async deleteFile(bucket, path) {
331
+ const { error } = await client.storage.from(bucket).remove([path]);
332
+ if (error) {
333
+ throw new Error(`Failed to delete file: ${error.message}`);
334
+ }
335
+ }
336
+ };
337
+ return adapter;
338
+ }
339
+ function useSupabaseDataAdapter(useSupabaseHook, options = {}) {
340
+ const client = useSupabaseHook();
341
+ return useMemo3(
342
+ () => createSupabaseDataAdapter(client, options),
343
+ [client, options.schema, options.primaryKey]
344
+ );
345
+ }
346
+ function createSupabaseDataAdapterHook(useSupabaseHook, options = {}) {
347
+ return () => useSupabaseDataAdapter(useSupabaseHook, options);
348
+ }
349
+ export {
350
+ createPolDbHooksAuthAdapter,
351
+ createPolDbHooksAuthValue,
352
+ createSupabaseDataAdapter,
353
+ createSupabaseDataAdapterHook,
354
+ createTanStackRouterAdapter,
355
+ usePolDbHooksAuthAdapter,
356
+ useSupabaseDataAdapter,
357
+ useTanStackNavigateAdapter,
358
+ useTanStackRouterAdapter
359
+ };