@pol-studios/db 1.0.8 → 1.0.10

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.
Files changed (80) hide show
  1. package/dist/auth/context.js +21 -12786
  2. package/dist/auth/context.js.map +1 -1
  3. package/dist/auth/guards.js +12 -7640
  4. package/dist/auth/guards.js.map +1 -1
  5. package/dist/auth/hooks.js +25 -10591
  6. package/dist/auth/hooks.js.map +1 -1
  7. package/dist/auth/index.js +43 -13008
  8. package/dist/auth/index.js.map +1 -1
  9. package/dist/canvas-75Y7XMF3.js +1541 -0
  10. package/dist/canvas-75Y7XMF3.js.map +1 -0
  11. package/dist/chunk-2IFGILT3.js +532 -0
  12. package/dist/chunk-2IFGILT3.js.map +1 -0
  13. package/dist/chunk-3M2U6TXH.js +928 -0
  14. package/dist/chunk-3M2U6TXH.js.map +1 -0
  15. package/dist/chunk-3PJTNH2L.js +2778 -0
  16. package/dist/chunk-3PJTNH2L.js.map +1 -0
  17. package/dist/chunk-5ZYAEGCJ.js +416 -0
  18. package/dist/chunk-5ZYAEGCJ.js.map +1 -0
  19. package/dist/chunk-7HG6G25H.js +710 -0
  20. package/dist/chunk-7HG6G25H.js.map +1 -0
  21. package/dist/chunk-7XT7K4QT.js +2687 -0
  22. package/dist/chunk-7XT7K4QT.js.map +1 -0
  23. package/dist/chunk-AWFMICFV.js +158 -0
  24. package/dist/chunk-AWFMICFV.js.map +1 -0
  25. package/dist/chunk-BRTW7CO5.js +1467 -0
  26. package/dist/chunk-BRTW7CO5.js.map +1 -0
  27. package/dist/chunk-EL45Z26M.js +4194 -0
  28. package/dist/chunk-EL45Z26M.js.map +1 -0
  29. package/dist/chunk-ERGF2FCE.js +903 -0
  30. package/dist/chunk-ERGF2FCE.js.map +1 -0
  31. package/dist/chunk-GK7B66LY.js +135 -0
  32. package/dist/chunk-GK7B66LY.js.map +1 -0
  33. package/dist/chunk-GQI6WJGI.js +172 -0
  34. package/dist/chunk-GQI6WJGI.js.map +1 -0
  35. package/dist/chunk-H6365JPC.js +1858 -0
  36. package/dist/chunk-H6365JPC.js.map +1 -0
  37. package/dist/chunk-J4ZVCXZ4.js +1 -0
  38. package/dist/chunk-J4ZVCXZ4.js.map +1 -0
  39. package/dist/chunk-JUVE3DWY.js +433 -0
  40. package/dist/chunk-JUVE3DWY.js.map +1 -0
  41. package/dist/chunk-O3K7R32P.js +7555 -0
  42. package/dist/chunk-O3K7R32P.js.map +1 -0
  43. package/dist/chunk-P4UZ7IXC.js +42 -0
  44. package/dist/chunk-P4UZ7IXC.js.map +1 -0
  45. package/dist/chunk-SEY5UO2T.js +89 -0
  46. package/dist/chunk-SEY5UO2T.js.map +1 -0
  47. package/dist/chunk-USJYMRUO.js +86 -0
  48. package/dist/chunk-USJYMRUO.js.map +1 -0
  49. package/dist/chunk-XX3IWSPM.js +189 -0
  50. package/dist/chunk-XX3IWSPM.js.map +1 -0
  51. package/dist/chunk-Y3INY2CS.js +14 -0
  52. package/dist/chunk-Y3INY2CS.js.map +1 -0
  53. package/dist/chunk-ZTSBF536.js +1927 -0
  54. package/dist/chunk-ZTSBF536.js.map +1 -0
  55. package/dist/client/index.js +13 -141
  56. package/dist/client/index.js.map +1 -1
  57. package/dist/dist-NDNRSNOG.js +521 -0
  58. package/dist/dist-NDNRSNOG.js.map +1 -0
  59. package/dist/gen/index.js +186 -1280
  60. package/dist/gen/index.js.map +1 -1
  61. package/dist/hooks/index.js +21 -8694
  62. package/dist/hooks/index.js.map +1 -1
  63. package/dist/index.js +403 -47848
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.native.js +400 -25048
  66. package/dist/index.native.js.map +1 -1
  67. package/dist/index.web.js +576 -43769
  68. package/dist/index.web.js.map +1 -1
  69. package/dist/mutation/index.js +44 -4675
  70. package/dist/mutation/index.js.map +1 -1
  71. package/dist/parser/index.js +45 -3697
  72. package/dist/parser/index.js.map +1 -1
  73. package/dist/pdf-3TIGQRLA.js +20336 -0
  74. package/dist/pdf-3TIGQRLA.js.map +1 -0
  75. package/dist/query/index.js +31 -13175
  76. package/dist/query/index.js.map +1 -1
  77. package/dist/realtime/index.js +45 -12431
  78. package/dist/realtime/index.js.map +1 -1
  79. package/dist/types/index.js +9 -0
  80. package/package.json +3 -3
@@ -0,0 +1,42 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __esm = (fn, res) => function __init() {
14
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ };
16
+ var __commonJS = (cb, mod) => function __require2() {
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
28
+ // If the importer is in node compatibility mode or this is not an ESM
29
+ // file that has been converted to a CommonJS file using a Babel-
30
+ // compatible transform (i.e. "__esModule" has not been set), then set
31
+ // "default" to the CommonJS "module.exports" for node compatibility.
32
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
33
+ mod
34
+ ));
35
+
36
+ export {
37
+ __require,
38
+ __esm,
39
+ __commonJS,
40
+ __toESM
41
+ };
42
+ //# sourceMappingURL=chunk-P4UZ7IXC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,89 @@
1
+ import {
2
+ useDeleteManyMutation,
3
+ useUpsertItem
4
+ } from "./chunk-H6365JPC.js";
5
+ import {
6
+ useSupabase
7
+ } from "./chunk-AWFMICFV.js";
8
+
9
+ // src/mutation/useBatchDelete.ts
10
+ import { useMutation } from "@tanstack/react-query";
11
+ function useBatchDelete(relation, primaryKeys = ["id"]) {
12
+ const tableName = typeof relation === "object" ? relation.table : relation;
13
+ const schemaName = typeof relation === "object" ? String(relation.schema) : "public";
14
+ const supabase = useSupabase();
15
+ const primaryKeysAsStrings = primaryKeys.map((k) => String(k));
16
+ const deleteManyMutation = useDeleteManyMutation(
17
+ supabase.schema(schemaName).from(tableName),
18
+ primaryKeysAsStrings
19
+ );
20
+ const deleteMutation = useMutation({
21
+ mutationFn: async (item) => {
22
+ if (Array.isArray(item)) {
23
+ const response = await deleteManyMutation.mutateAsync(item);
24
+ return response;
25
+ } else {
26
+ throw new Error("Item must be an array.");
27
+ }
28
+ }
29
+ });
30
+ return deleteMutation;
31
+ }
32
+
33
+ // src/mutation/useBatchUpsert.ts
34
+ import { useMutation as useMutation2 } from "@tanstack/react-query";
35
+ function isUsable(value) {
36
+ return value !== null && value !== void 0;
37
+ }
38
+ function omit(obj, keys) {
39
+ const result = { ...obj };
40
+ for (const key of keys) {
41
+ delete result[key];
42
+ }
43
+ return result;
44
+ }
45
+ function useBatchUpsert(relation, primaryKeys = ["id"], query = "*") {
46
+ const supabase = useSupabase();
47
+ const tableName = typeof relation === "object" ? relation.table : relation;
48
+ const schemaName = typeof relation === "object" ? String(relation.schema) : "public";
49
+ const upsertItem = useUpsertItem({
50
+ primaryKeys,
51
+ table: relation,
52
+ schema: "public"
53
+ });
54
+ const primaryKeysAsStrings = primaryKeys.map((k) => String(k));
55
+ async function upsertItemAction(item) {
56
+ let task;
57
+ if (Object.keys(item).length !== primaryKeys.length && primaryKeys.every((key) => key in item && isUsable(item[key]))) {
58
+ const updateObject = omit(item, primaryKeysAsStrings);
59
+ task = supabase.schema(schemaName).from(tableName).update(updateObject);
60
+ primaryKeys.forEach((key) => {
61
+ task = task.eq(String(key), item[key]);
62
+ });
63
+ } else {
64
+ task = supabase.schema(schemaName).from(tableName).insert(omit(item, primaryKeysAsStrings));
65
+ }
66
+ const response = await task.select(query);
67
+ if (response.error) {
68
+ throw response.error;
69
+ }
70
+ return response.data[0];
71
+ }
72
+ const updateMutation = useMutation2({
73
+ mutationFn: async (item) => {
74
+ if (Array.isArray(item)) {
75
+ const data = await Promise.all(item.map((x) => upsertItemAction(x)));
76
+ data.filter((x) => isUsable(x)).forEach((x) => upsertItem(x));
77
+ return data;
78
+ }
79
+ throw new Error("Item must be an array.");
80
+ }
81
+ });
82
+ return updateMutation;
83
+ }
84
+
85
+ export {
86
+ useBatchDelete,
87
+ useBatchUpsert
88
+ };
89
+ //# sourceMappingURL=chunk-SEY5UO2T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mutation/useBatchDelete.ts","../src/mutation/useBatchUpsert.ts"],"sourcesContent":["import { useMutation } from \"@tanstack/react-query\";\nimport useSupabase, { Database } from \"../client/useSupabase\";\nimport { GetResult } from \"../parser/select-query-parser\";\nimport { GenericSchema } from \"../parser/types\";\nimport {\n useDeleteManyMutation,\n} from \"@supabase-cache-helpers/postgrest-react-query\";\n\ntype ItemType<T> = T extends Array<infer U> ? U : T;\n\nexport function useBatchDelete<\n TableName extends string & keyof PublicSchema[\"Tables\"],\n Table extends PublicSchema[\"Tables\"][TableName],\n Schema extends keyof Database = \"public\",\n PublicSchema extends GenericSchema =\n Database[Extract<keyof Database, Schema>],\n Query extends string = \"*\",\n RelationName = unknown,\n Relationships = Table extends { Relationships: infer R } ? R : unknown,\n RowResult extends object = Omit<\n GetResult<\n PublicSchema,\n Table[\"Update\"],\n RelationName,\n Relationships,\n Query\n >,\n \"id\"\n >,\n>(\n relation: TableName | { table: TableName; schema: Schema },\n primaryKeys: (keyof ItemType<RowResult> & string)[] = [\"id\" as any],\n) {\n const tableName = typeof relation === \"object\" ? relation.table : relation;\n const schemaName: string = typeof relation === \"object\"\n ? String(relation.schema)\n : \"public\";\n\n const supabase = useSupabase();\n const primaryKeysAsStrings = primaryKeys.map((k) => String(k)) as string[];\n const deleteManyMutation = useDeleteManyMutation(\n supabase.schema(schemaName as \"public\").from(tableName as any) as any,\n primaryKeysAsStrings as any,\n );\n\n const deleteMutation = useMutation<\n RowResult | null,\n Error,\n RowResult | RowResult[]\n >({\n mutationFn: async (item) => {\n if (Array.isArray(item)) {\n const response = await deleteManyMutation.mutateAsync(item);\n return response as any;\n } else {\n throw new Error(\"Item must be an array.\");\n }\n },\n });\n\n return deleteMutation;\n}\n","import { useMutation } from \"@tanstack/react-query\";\nimport useSupabase, { Database } from \"../client/useSupabase\";\nimport { useUpsertItem } from \"@supabase-cache-helpers/postgrest-react-query\";\nimport { GetResult } from \"../parser/select-query-parser\";\nimport { GenericSchema } from \"../parser/types\";\n\nfunction isUsable<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\nfunction omit<T extends Record<string, any>, K extends keyof T>(\n obj: T,\n keys: K[]\n): Omit<T, K> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result;\n}\n\ntype ItemType<T> = T extends Array<infer U> ? U : T;\n\nexport function useBatchUpsert<\n TableName extends string & keyof PublicSchema[\"Tables\"],\n Table extends PublicSchema[\"Tables\"][TableName],\n Schema extends keyof Database = \"public\",\n PublicSchema extends GenericSchema =\n Database[Extract<keyof Database, Schema>],\n Query extends string = \"*\",\n RelationName = unknown,\n Relationships = Table extends { Relationships: infer R } ? R : unknown,\n RowResult extends object = GetResult<\n PublicSchema,\n Table[\"Row\"],\n RelationName,\n Relationships,\n Query\n >,\n ResultInsert extends object = GetResult<\n PublicSchema,\n Table[\"Insert\"],\n RelationName,\n Relationships,\n Query\n >,\n ResultUpdate extends object =\n & Omit<\n GetResult<\n PublicSchema,\n Table[\"Update\"],\n RelationName,\n Relationships,\n Query\n >,\n \"id\"\n >\n & { id: any },\n>(\n relation: TableName | { table: TableName; schema: Schema },\n primaryKeys: (keyof (ItemType<RowResult> | any) & string)[] = [\"id\"],\n query: string = \"*\",\n) {\n const supabase = useSupabase();\n const tableName = typeof relation === \"object\" ? relation.table : relation;\n const schemaName: string = typeof relation === \"object\"\n ? String(relation.schema)\n : \"public\";\n\n const upsertItem = useUpsertItem({\n primaryKeys: primaryKeys,\n table: relation as any,\n schema: \"public\",\n });\n\n const primaryKeysAsStrings = primaryKeys.map((k) => String(k)) as string[];\n\n async function upsertItemAction(item: any) {\n let task: any;\n\n if (\n Object.keys(item).length !== primaryKeys.length &&\n primaryKeys.every((key) => key in item && isUsable(item[key]))\n ) {\n const updateObject = omit(item as any, primaryKeysAsStrings as any) as any;\n task = supabase\n .schema(schemaName as \"public\")\n .from(tableName as any).update(updateObject);\n\n primaryKeys.forEach((key) => {\n task = task.eq(String(key), item[key]);\n });\n } else {\n task = supabase\n .schema(schemaName as \"public\")\n .from(tableName as any)\n .insert(omit(item as any, primaryKeysAsStrings as any) as any);\n }\n\n const response = await task.select(query);\n if (response.error) {\n throw response.error;\n }\n return response.data[0];\n }\n\n const updateMutation = useMutation<\n (RowResult[] | null),\n Error,\n (ResultUpdate | ResultInsert)[]\n >({\n mutationFn: async (item) => {\n if (Array.isArray(item)) {\n const data = await Promise.all(item.map((x) => upsertItemAction(x)));\n data.filter((x) => isUsable(x)).forEach((x) => upsertItem(x as any));\n return data as RowResult[];\n }\n throw new Error(\"Item must be an array.\");\n },\n });\n\n return updateMutation;\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,mBAAmB;AAUrB,SAAS,eAoBd,UACA,cAAsD,CAAC,IAAW,GAClE;AACA,QAAM,YAAY,OAAO,aAAa,WAAW,SAAS,QAAQ;AAClE,QAAM,aAAqB,OAAO,aAAa,WAC3C,OAAO,SAAS,MAAM,IACtB;AAEJ,QAAM,WAAW,YAAY;AAC7B,QAAM,uBAAuB,YAAY,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAC7D,QAAM,qBAAqB;AAAA,IACzB,SAAS,OAAO,UAAsB,EAAE,KAAK,SAAgB;AAAA,IAC7D;AAAA,EACF;AAEA,QAAM,iBAAiB,YAIrB;AAAA,IACA,YAAY,OAAO,SAAS;AAC1B,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,cAAM,WAAW,MAAM,mBAAmB,YAAY,IAAI;AAC1D,eAAO;AAAA,MACT,OAAO;AACL,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;AC7DA,SAAS,eAAAA,oBAAmB;AAM5B,SAAS,SAAY,OAAyC;AAC5D,SAAO,UAAU,QAAQ,UAAU;AACrC;AAEA,SAAS,KACP,KACA,MACY;AACZ,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,aAAW,OAAO,MAAM;AACtB,WAAO,OAAO,GAAG;AAAA,EACnB;AACA,SAAO;AACT;AAIO,SAAS,eAoCd,UACA,cAA8D,CAAC,IAAI,GACnE,QAAgB,KAChB;AACA,QAAM,WAAW,YAAY;AAC7B,QAAM,YAAY,OAAO,aAAa,WAAW,SAAS,QAAQ;AAClE,QAAM,aAAqB,OAAO,aAAa,WAC3C,OAAO,SAAS,MAAM,IACtB;AAEJ,QAAM,aAAa,cAAc;AAAA,IAC/B;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,EACV,CAAC;AAED,QAAM,uBAAuB,YAAY,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAE7D,iBAAe,iBAAiB,MAAW;AACzC,QAAI;AAEJ,QACE,OAAO,KAAK,IAAI,EAAE,WAAW,YAAY,UACzC,YAAY,MAAM,CAAC,QAAQ,OAAO,QAAQ,SAAS,KAAK,GAAG,CAAC,CAAC,GAC7D;AACA,YAAM,eAAe,KAAK,MAAa,oBAA2B;AAClE,aAAO,SACJ,OAAO,UAAsB,EAC7B,KAAK,SAAgB,EAAE,OAAO,YAAY;AAE7C,kBAAY,QAAQ,CAAC,QAAQ;AAC3B,eAAO,KAAK,GAAG,OAAO,GAAG,GAAG,KAAK,GAAG,CAAC;AAAA,MACvC,CAAC;AAAA,IACH,OAAO;AACL,aAAO,SACJ,OAAO,UAAsB,EAC7B,KAAK,SAAgB,EACrB,OAAO,KAAK,MAAa,oBAA2B,CAAQ;AAAA,IACjE;AAEA,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK;AACxC,QAAI,SAAS,OAAO;AAClB,YAAM,SAAS;AAAA,IACjB;AACA,WAAO,SAAS,KAAK,CAAC;AAAA,EACxB;AAEA,QAAM,iBAAiBC,aAIrB;AAAA,IACA,YAAY,OAAO,SAAS;AAC1B,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,cAAM,OAAO,MAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC;AACnE,aAAK,OAAO,CAAC,MAAM,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,WAAW,CAAQ,CAAC;AACnE,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":["useMutation","useMutation"]}
@@ -0,0 +1,86 @@
1
+ import {
2
+ isUsable
3
+ } from "./chunk-O3K7R32P.js";
4
+
5
+ // src/auth/guards/hasAccess.ts
6
+ function hasAccess(accessKeys, key, options) {
7
+ if (options?.isArchived || options?.isSuspended) {
8
+ return false;
9
+ }
10
+ if (isUsable(accessKeys) === false) {
11
+ return false;
12
+ }
13
+ if (accessKeys.includes("owner")) {
14
+ return true;
15
+ }
16
+ if (accessKeys.includes(key)) {
17
+ return true;
18
+ }
19
+ if (isUsable(key) === false) {
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ function hasAnyAccess(accessKeys, keys, options) {
25
+ return keys.some((key) => hasAccess(accessKeys, key, options));
26
+ }
27
+ function hasAllAccess(accessKeys, keys, options) {
28
+ return keys.every((key) => hasAccess(accessKeys, key, options));
29
+ }
30
+
31
+ // src/auth/guards/hasEntityAccess.ts
32
+ function hasEntityAccess(permission, action, options) {
33
+ if (options?.isArchived || options?.isSuspended) {
34
+ return false;
35
+ }
36
+ const accessKeys = options?.accessKeys;
37
+ if (isUsable(accessKeys) && accessKeys.includes("owner")) {
38
+ return true;
39
+ }
40
+ if (!permission) {
41
+ return false;
42
+ }
43
+ if (permission.isLoading) {
44
+ return false;
45
+ }
46
+ switch (action) {
47
+ case "view":
48
+ return permission.canView;
49
+ case "adminView":
50
+ return permission.canAdminView;
51
+ case "edit":
52
+ return permission.canEdit;
53
+ case "create":
54
+ return permission.canCreate;
55
+ case "delete":
56
+ return permission.canDelete;
57
+ case "share":
58
+ return permission.canShare;
59
+ default:
60
+ return false;
61
+ }
62
+ }
63
+ function hasAnyEntityAccess(permission, actions, options) {
64
+ return actions.some((action) => hasEntityAccess(permission, action, options));
65
+ }
66
+ function hasAllEntityAccess(permission, actions, options) {
67
+ return actions.every((action) => hasEntityAccess(permission, action, options));
68
+ }
69
+ function isEntityAccessDenied(permission) {
70
+ return permission?.isDenied === true;
71
+ }
72
+ function isPermissionLoaded(permission) {
73
+ return permission !== null && permission !== void 0 && !permission.isLoading;
74
+ }
75
+
76
+ export {
77
+ hasAccess,
78
+ hasAnyAccess,
79
+ hasAllAccess,
80
+ hasEntityAccess,
81
+ hasAnyEntityAccess,
82
+ hasAllEntityAccess,
83
+ isEntityAccessDenied,
84
+ isPermissionLoaded
85
+ };
86
+ //# sourceMappingURL=chunk-USJYMRUO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth/guards/hasAccess.ts","../src/auth/guards/hasEntityAccess.ts"],"sourcesContent":["import { isUsable } from \"@pol-studios/utils\";\n\n/**\n * Check if a user has access to a specific permission key.\n * Owners bypass all permission checks.\n *\n * @param accessKeys - Array of access keys the user has\n * @param key - The access key to check for\n * @param options - Additional options for the check\n * @param options.isArchived - Whether the user is archived\n * @param options.isSuspended - Whether the user is suspended\n * @returns boolean - true if user has the specified access\n *\n * @example\n * ```ts\n * // Basic usage\n * const canAccess = hasAccess(['admin', 'viewer'], 'admin'); // true\n * const cannotAccess = hasAccess(['viewer'], 'admin'); // false\n *\n * // Owner bypasses all checks\n * const ownerAccess = hasAccess(['owner'], 'any-key'); // true\n *\n * // Empty key always returns true (no permission required)\n * const noKeyRequired = hasAccess(['viewer'], ''); // true\n *\n * // Archived/suspended users have no access\n * const archivedUser = hasAccess(['admin'], 'admin', { isArchived: true }); // false\n * ```\n */\nexport function hasAccess(\n accessKeys: string[] | undefined | null,\n key: string,\n options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n // Archived/suspended users have no access\n if (options?.isArchived || options?.isSuspended) {\n return false;\n }\n\n // No access keys means no access\n if (isUsable(accessKeys) === false) {\n return false;\n }\n\n // Owners bypass all permission checks\n if (accessKeys.includes(\"owner\")) {\n return true;\n }\n\n // Check if the specific key is present\n if (accessKeys.includes(key)) {\n return true;\n }\n\n // Empty/undefined key means no specific permission required\n if (isUsable(key) === false) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if a user has any of the specified access keys.\n *\n * @param accessKeys - Array of access keys the user has\n * @param keys - Array of access keys to check for (OR logic)\n * @param options - Additional options for the check\n * @returns boolean - true if user has any of the specified keys\n *\n * @example\n * ```ts\n * const hasAny = hasAnyAccess(['viewer'], ['admin', 'editor', 'viewer']); // true\n * const hasNone = hasAnyAccess(['viewer'], ['admin', 'editor']); // false\n * ```\n */\nexport function hasAnyAccess(\n accessKeys: string[] | undefined | null,\n keys: string[],\n options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n // Check each key, return true if any match\n return keys.some((key) => hasAccess(accessKeys, key, options));\n}\n\n/**\n * Check if a user has all of the specified access keys.\n *\n * @param accessKeys - Array of access keys the user has\n * @param keys - Array of access keys to check for (AND logic)\n * @param options - Additional options for the check\n * @returns boolean - true if user has all of the specified keys\n *\n * @example\n * ```ts\n * const hasAll = hasAllAccess(['admin', 'editor'], ['admin', 'editor']); // true\n * const hasPartial = hasAllAccess(['admin'], ['admin', 'editor']); // false\n * ```\n */\nexport function hasAllAccess(\n accessKeys: string[] | undefined | null,\n keys: string[],\n options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n // Check each key, return true only if all match\n return keys.every((key) => hasAccess(accessKeys, key, options));\n}\n","import { isUsable } from \"@pol-studios/utils\";\nimport { EntityType, EntityAction, EntityPermissionCheck } from \"../types/EntityPermissions\";\n\n/**\n * Check if a user has entity-level access based on permission check result.\n * Owners (users with 'owner' access key) bypass entity permissions entirely.\n *\n * @param permission - The permission check result from getPermission/usePermission\n * @param action - The action to check for\n * @param options - Additional options for the check\n * @param options.accessKeys - User's access keys (for owner check)\n * @param options.isArchived - Whether the user is archived\n * @param options.isSuspended - Whether the user is suspended\n * @returns boolean - true if user has permission for the action\n *\n * @example\n * ```ts\n * // Basic usage\n * const permission = await getPermission('Project', 123);\n * const canEdit = hasEntityAccess(permission, 'edit');\n *\n * // With owner bypass\n * const canEditAsOwner = hasEntityAccess(permission, 'edit', {\n * accessKeys: ['owner'],\n * }); // true, owners bypass all checks\n *\n * // Check loading state\n * if (permission.isLoading) {\n * return false; // Wait for permission to load\n * }\n * ```\n */\nexport function hasEntityAccess(\n permission: EntityPermissionCheck | null | undefined,\n action: EntityAction,\n options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n // Archived/suspended users have no entity access\n if (options?.isArchived || options?.isSuspended) {\n return false;\n }\n\n // Owners bypass all entity permission checks\n const accessKeys = options?.accessKeys;\n if (isUsable(accessKeys) && accessKeys.includes(\"owner\")) {\n return true;\n }\n\n // No permission data means no access\n if (!permission) {\n return false;\n }\n\n // Still loading means no access (yet)\n if (permission.isLoading) {\n return false;\n }\n\n // Check the specific action\n switch (action) {\n case \"view\":\n return permission.canView;\n case \"adminView\":\n return permission.canAdminView;\n case \"edit\":\n return permission.canEdit;\n case \"create\":\n return permission.canCreate;\n case \"delete\":\n return permission.canDelete;\n case \"share\":\n return permission.canShare;\n default:\n return false;\n }\n}\n\n/**\n * Check if a user has any of the specified entity actions.\n *\n * @param permission - The permission check result\n * @param actions - Array of actions to check for (OR logic)\n * @param options - Additional options for the check\n * @returns boolean - true if user has permission for any of the actions\n *\n * @example\n * ```ts\n * const canEditOrDelete = hasAnyEntityAccess(permission, ['edit', 'delete']);\n * ```\n */\nexport function hasAnyEntityAccess(\n permission: EntityPermissionCheck | null | undefined,\n actions: EntityAction[],\n options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n return actions.some((action) => hasEntityAccess(permission, action, options));\n}\n\n/**\n * Check if a user has all of the specified entity actions.\n *\n * @param permission - The permission check result\n * @param actions - Array of actions to check for (AND logic)\n * @param options - Additional options for the check\n * @returns boolean - true if user has permission for all of the actions\n *\n * @example\n * ```ts\n * // Check if user can edit AND delete (admin-like permissions)\n * const isAdmin = hasAllEntityAccess(permission, ['edit', 'delete', 'share']);\n * ```\n */\nexport function hasAllEntityAccess(\n permission: EntityPermissionCheck | null | undefined,\n actions: EntityAction[],\n options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\n }\n): boolean {\n return actions.every((action) => hasEntityAccess(permission, action, options));\n}\n\n/**\n * Check if entity access was explicitly denied.\n * Useful for distinguishing between \"no permission\" and \"explicitly blocked\".\n *\n * @param permission - The permission check result\n * @returns boolean - true if access was explicitly denied\n *\n * @example\n * ```ts\n * const permission = await getPermission('Project', 123);\n * if (isEntityAccessDenied(permission)) {\n * showBlockedMessage('You have been explicitly denied access to this project');\n * }\n * ```\n */\nexport function isEntityAccessDenied(\n permission: EntityPermissionCheck | null | undefined\n): boolean {\n return permission?.isDenied === true;\n}\n\n/**\n * Type guard to check if permission data is loaded and available.\n *\n * @param permission - The permission check result\n * @returns boolean - true if permission data is loaded\n *\n * @example\n * ```ts\n * const permission = usePermission('Project', projectId);\n *\n * if (!isPermissionLoaded(permission)) {\n * return <Spinner />;\n * }\n *\n * // TypeScript knows permission is fully loaded here\n * return permission.canEdit ? <Editor /> : <Viewer />;\n * ```\n */\nexport function isPermissionLoaded(\n permission: EntityPermissionCheck | null | undefined\n): permission is EntityPermissionCheck & { isLoading: false } {\n return permission !== null && permission !== undefined && !permission.isLoading;\n}\n"],"mappings":";;;;;AA6BO,SAAS,UACd,YACA,KACA,SAIS;AAET,MAAI,SAAS,cAAc,SAAS,aAAa;AAC/C,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,UAAU,MAAM,OAAO;AAClC,WAAO;AAAA,EACT;AAGA,MAAI,WAAW,SAAS,OAAO,GAAG;AAChC,WAAO;AAAA,EACT;AAGA,MAAI,WAAW,SAAS,GAAG,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,GAAG,MAAM,OAAO;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAgBO,SAAS,aACd,YACA,MACA,SAIS;AAET,SAAO,KAAK,KAAK,CAAC,QAAQ,UAAU,YAAY,KAAK,OAAO,CAAC;AAC/D;AAgBO,SAAS,aACd,YACA,MACA,SAIS;AAET,SAAO,KAAK,MAAM,CAAC,QAAQ,UAAU,YAAY,KAAK,OAAO,CAAC;AAChE;;;ACnFO,SAAS,gBACd,YACA,QACA,SAKS;AAET,MAAI,SAAS,cAAc,SAAS,aAAa;AAC/C,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,SAAS;AAC5B,MAAI,SAAS,UAAU,KAAK,WAAW,SAAS,OAAO,GAAG;AACxD,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAGA,MAAI,WAAW,WAAW;AACxB,WAAO;AAAA,EACT;AAGA,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB,KAAK;AACH,aAAO,WAAW;AAAA,IACpB;AACE,aAAO;AAAA,EACX;AACF;AAeO,SAAS,mBACd,YACA,SACA,SAKS;AACT,SAAO,QAAQ,KAAK,CAAC,WAAW,gBAAgB,YAAY,QAAQ,OAAO,CAAC;AAC9E;AAgBO,SAAS,mBACd,YACA,SACA,SAKS;AACT,SAAO,QAAQ,MAAM,CAAC,WAAW,gBAAgB,YAAY,QAAQ,OAAO,CAAC;AAC/E;AAiBO,SAAS,qBACd,YACS;AACT,SAAO,YAAY,aAAa;AAClC;AAoBO,SAAS,mBACd,YAC4D;AAC5D,SAAO,eAAe,QAAQ,eAAe,UAAa,CAAC,WAAW;AACxE;","names":[]}
@@ -0,0 +1,189 @@
1
+ import {
2
+ useDataLayer
3
+ } from "./chunk-3M2U6TXH.js";
4
+
5
+ // src/hooks/useSyncStatus.ts
6
+ import { useState, useEffect } from "react";
7
+ var defaultSyncStatus = {
8
+ isConnected: true,
9
+ // Supabase-only mode is always "connected" when online
10
+ isSyncing: false,
11
+ lastSyncedAt: null,
12
+ pendingUploads: 0,
13
+ error: null
14
+ };
15
+ function useSyncStatus() {
16
+ const { syncStatus, status, powerSync } = useDataLayer();
17
+ const [currentStatus, setCurrentStatus] = useState(syncStatus);
18
+ useEffect(() => {
19
+ if (powerSync && status.currentBackend === "powersync") {
20
+ setCurrentStatus(syncStatus);
21
+ } else {
22
+ setCurrentStatus({
23
+ ...defaultSyncStatus,
24
+ isConnected: status.isOnline
25
+ });
26
+ }
27
+ }, [syncStatus, status.currentBackend, status.isOnline, powerSync]);
28
+ return currentStatus;
29
+ }
30
+
31
+ // src/hooks/useSyncControl.ts
32
+ import { useMemo } from "react";
33
+ function useSyncControl() {
34
+ const { syncControl, status, powerSync } = useDataLayer();
35
+ const noOpControls = useMemo(
36
+ () => ({
37
+ triggerSync: async () => {
38
+ console.warn(
39
+ "[useSyncControl] triggerSync called but PowerSync is not available"
40
+ );
41
+ },
42
+ startLiveSync: async () => {
43
+ console.warn(
44
+ "[useSyncControl] startLiveSync called but PowerSync is not available"
45
+ );
46
+ },
47
+ stopLiveSync: () => {
48
+ console.warn(
49
+ "[useSyncControl] stopLiveSync called but PowerSync is not available"
50
+ );
51
+ },
52
+ setScope: async (_scopeName, _values) => {
53
+ console.warn(
54
+ "[useSyncControl] setScope called but PowerSync is not available"
55
+ );
56
+ }
57
+ }),
58
+ []
59
+ );
60
+ const controls = useMemo(() => {
61
+ if (powerSync && status.currentBackend === "powersync") {
62
+ return syncControl;
63
+ }
64
+ return noOpControls;
65
+ }, [powerSync, status.currentBackend, syncControl, noOpControls]);
66
+ return controls;
67
+ }
68
+
69
+ // src/hooks/useOnlineStatus.ts
70
+ import { useState as useState2, useEffect as useEffect2 } from "react";
71
+
72
+ // src/utils/network.ts
73
+ var netInfoModule = null;
74
+ var netInfoChecked = false;
75
+ function isReactNative() {
76
+ return typeof navigator !== "undefined" && navigator.product === "ReactNative";
77
+ }
78
+ async function getNetInfo() {
79
+ if (netInfoChecked) {
80
+ return netInfoModule;
81
+ }
82
+ netInfoChecked = true;
83
+ if (!isReactNative()) {
84
+ return null;
85
+ }
86
+ try {
87
+ const module = await import("@react-native-community/netinfo");
88
+ netInfoModule = module.default || module;
89
+ return netInfoModule;
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+ async function getOnlineStatus() {
95
+ const netInfo = await getNetInfo();
96
+ if (netInfo) {
97
+ const state = await netInfo.fetch();
98
+ return state.isConnected ?? true;
99
+ }
100
+ if (typeof navigator !== "undefined" && "onLine" in navigator) {
101
+ return navigator.onLine;
102
+ }
103
+ return true;
104
+ }
105
+ function getOnlineStatusSync() {
106
+ if (typeof window !== "undefined" && typeof navigator !== "undefined") {
107
+ return navigator.onLine;
108
+ }
109
+ return true;
110
+ }
111
+ function subscribeToNetworkChanges(callback) {
112
+ if (isReactNative()) {
113
+ let unsubscribe = null;
114
+ getNetInfo().then((netInfo) => {
115
+ if (netInfo) {
116
+ unsubscribe = netInfo.addEventListener((state) => {
117
+ callback(state.isConnected ?? true);
118
+ });
119
+ }
120
+ });
121
+ return () => {
122
+ if (unsubscribe) {
123
+ unsubscribe();
124
+ }
125
+ };
126
+ }
127
+ const isBrowser = typeof window !== "undefined" && typeof window.addEventListener === "function";
128
+ if (isBrowser) {
129
+ const handleOnline = () => callback(true);
130
+ const handleOffline = () => callback(false);
131
+ window.addEventListener("online", handleOnline);
132
+ window.addEventListener("offline", handleOffline);
133
+ return () => {
134
+ window.removeEventListener("online", handleOnline);
135
+ window.removeEventListener("offline", handleOffline);
136
+ };
137
+ }
138
+ return () => {
139
+ };
140
+ }
141
+ async function initializeNetworkMonitoring() {
142
+ await getNetInfo();
143
+ }
144
+
145
+ // src/hooks/useOnlineStatus.ts
146
+ function useOnlineStatus() {
147
+ const { status, powerSync } = useDataLayer();
148
+ const [onlineStatus, setOnlineStatus] = useState2({
149
+ isOnline: status.isOnline,
150
+ isConnected: status.powerSyncStatus === "available",
151
+ backend: status.currentBackend
152
+ });
153
+ useEffect2(() => {
154
+ setOnlineStatus({
155
+ isOnline: status.isOnline,
156
+ isConnected: powerSync !== null && status.powerSyncStatus === "available",
157
+ backend: status.currentBackend
158
+ });
159
+ }, [status.isOnline, status.powerSyncStatus, status.currentBackend, powerSync]);
160
+ useEffect2(() => {
161
+ getOnlineStatus().then((isOnline) => {
162
+ setOnlineStatus((prev) => {
163
+ if (prev.isOnline !== isOnline) {
164
+ return { ...prev, isOnline };
165
+ }
166
+ return prev;
167
+ });
168
+ });
169
+ }, []);
170
+ useEffect2(() => {
171
+ const unsubscribe = subscribeToNetworkChanges((isOnline) => {
172
+ setOnlineStatus((prev) => ({ ...prev, isOnline }));
173
+ });
174
+ return unsubscribe;
175
+ }, []);
176
+ return onlineStatus;
177
+ }
178
+
179
+ export {
180
+ useSyncStatus,
181
+ useSyncControl,
182
+ isReactNative,
183
+ getOnlineStatus,
184
+ getOnlineStatusSync,
185
+ subscribeToNetworkChanges,
186
+ initializeNetworkMonitoring,
187
+ useOnlineStatus
188
+ };
189
+ //# sourceMappingURL=chunk-XX3IWSPM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useSyncStatus.ts","../src/hooks/useSyncControl.ts","../src/hooks/useOnlineStatus.ts","../src/utils/network.ts"],"sourcesContent":["/**\n * V3 useSyncStatus Hook\n *\n * Provides sync status information from the data layer.\n * Returns default \"always synced\" status when PowerSync is not available.\n */\n\nimport { useState, useEffect } from \"react\";\nimport { useDataLayer } from \"./useDataLayer\";\nimport type { SyncStatus } from \"../core/types\";\n\n/**\n * Default sync status when PowerSync is not available\n */\nconst defaultSyncStatus: SyncStatus = {\n isConnected: true, // Supabase-only mode is always \"connected\" when online\n isSyncing: false,\n lastSyncedAt: null,\n pendingUploads: 0,\n error: null,\n};\n\n/**\n * Hook to get the current sync status\n *\n * When PowerSync is not available, returns a default \"always synced\" status.\n *\n * @example\n * const { isSyncing, pendingUploads, isConnected } = useSyncStatus();\n *\n * if (pendingUploads > 0) {\n * console.log(`${pendingUploads} changes waiting to sync`);\n * }\n */\nexport function useSyncStatus(): SyncStatus {\n const { syncStatus, status, powerSync } = useDataLayer();\n const [currentStatus, setCurrentStatus] = useState<SyncStatus>(syncStatus);\n\n // Update status when context changes\n useEffect(() => {\n // If PowerSync is available, use actual sync status\n if (powerSync && status.currentBackend === \"powersync\") {\n setCurrentStatus(syncStatus);\n } else {\n // Supabase-only mode - return default status based on online state\n setCurrentStatus({\n ...defaultSyncStatus,\n isConnected: status.isOnline,\n });\n }\n }, [syncStatus, status.currentBackend, status.isOnline, powerSync]);\n\n return currentStatus;\n}\n\nexport default useSyncStatus;\n","/**\n * V3 useSyncControl Hook\n *\n * Provides sync control functions from the data layer.\n * Returns no-op functions when PowerSync is not available.\n */\n\nimport { useMemo } from \"react\";\nimport { useDataLayer } from \"./useDataLayer\";\nimport type { SyncControl } from \"../core/types\";\n\n/**\n * Hook to get sync controls for PowerSync\n *\n * When PowerSync is not available, all methods are no-ops that log a warning.\n *\n * @example\n * const { triggerSync, startLiveSync, stopLiveSync } = useSyncControl();\n *\n * // Manually trigger a sync\n * await triggerSync();\n *\n * // Start/stop live sync\n * await startLiveSync();\n * stopLiveSync();\n */\nexport function useSyncControl(): SyncControl {\n const { syncControl, status, powerSync } = useDataLayer();\n\n // Create no-op controls for when PowerSync is not available\n const noOpControls = useMemo<SyncControl>(\n () => ({\n triggerSync: async () => {\n console.warn(\n \"[useSyncControl] triggerSync called but PowerSync is not available\"\n );\n },\n startLiveSync: async () => {\n console.warn(\n \"[useSyncControl] startLiveSync called but PowerSync is not available\"\n );\n },\n stopLiveSync: () => {\n console.warn(\n \"[useSyncControl] stopLiveSync called but PowerSync is not available\"\n );\n },\n setScope: async (_scopeName: string, _values: string[]) => {\n console.warn(\n \"[useSyncControl] setScope called but PowerSync is not available\"\n );\n },\n }),\n []\n );\n\n // Return actual controls if PowerSync is available, otherwise no-ops\n const controls = useMemo<SyncControl>(() => {\n if (powerSync && status.currentBackend === \"powersync\") {\n return syncControl;\n }\n return noOpControls;\n }, [powerSync, status.currentBackend, syncControl, noOpControls]);\n\n return controls;\n}\n\nexport default useSyncControl;\n","/**\n * V3 useOnlineStatus Hook\n *\n * Provides online/connection status information.\n * Combines data layer status with platform-specific online/offline events.\n * Works on both web (browser events) and React Native (NetInfo).\n */\n\nimport { useState, useEffect } from \"react\";\nimport { useDataLayer } from \"./useDataLayer\";\nimport { subscribeToNetworkChanges, getOnlineStatus } from \"../utils/network\";\n\n/**\n * Online status information\n */\nexport interface OnlineStatus {\n /** Whether the device has network connectivity */\n isOnline: boolean;\n /** Whether PowerSync is connected (false if using Supabase-only) */\n isConnected: boolean;\n /** Current backend being used */\n backend: \"powersync\" | \"supabase\" | null;\n}\n\n/**\n * Hook to get online/connection status\n *\n * @example\n * const { isOnline, isConnected, backend } = useOnlineStatus();\n *\n * if (!isOnline) {\n * return <OfflineBanner />;\n * }\n */\nexport function useOnlineStatus(): OnlineStatus {\n const { status, powerSync } = useDataLayer();\n\n const [onlineStatus, setOnlineStatus] = useState<OnlineStatus>({\n isOnline: status.isOnline,\n isConnected: status.powerSyncStatus === \"available\",\n backend: status.currentBackend,\n });\n\n // Update status when context changes\n useEffect(() => {\n setOnlineStatus({\n isOnline: status.isOnline,\n isConnected:\n powerSync !== null && status.powerSyncStatus === \"available\",\n backend: status.currentBackend,\n });\n }, [status.isOnline, status.powerSyncStatus, status.currentBackend, powerSync]);\n\n // Check actual network status on mount (especially important for React Native\n // where the auto-detector doesn't check NetInfo and always returns true)\n useEffect(() => {\n getOnlineStatus().then((isOnline) => {\n setOnlineStatus((prev) => {\n if (prev.isOnline !== isOnline) {\n return { ...prev, isOnline };\n }\n return prev;\n });\n });\n }, []);\n\n // Listen to platform-specific online/offline events for immediate updates\n // Works on both web (browser events) and React Native (NetInfo)\n useEffect(() => {\n const unsubscribe = subscribeToNetworkChanges((isOnline) => {\n setOnlineStatus((prev) => ({ ...prev, isOnline }));\n });\n\n return unsubscribe;\n }, []);\n\n return onlineStatus;\n}\n\nexport default useOnlineStatus;\n","/**\n * Platform-aware network status utility\n *\n * Provides unified network connectivity detection for both web (browser)\n * and React Native environments.\n *\n * - On React Native: Uses @react-native-community/netinfo\n * - On Web: Uses navigator.onLine and window online/offline events\n */\n\n// Type for NetInfo to avoid hard dependency\ninterface NetInfoState {\n isConnected: boolean | null;\n isInternetReachable: boolean | null;\n}\n\ntype NetInfoSubscription = () => void;\n\ninterface NetInfoModule {\n fetch: () => Promise<NetInfoState>;\n addEventListener: (\n callback: (state: NetInfoState) => void\n ) => NetInfoSubscription;\n}\n\n// Cached NetInfo module reference\nlet netInfoModule: NetInfoModule | null = null;\nlet netInfoChecked = false;\n\n/**\n * Check if we're running in React Native environment\n */\nexport function isReactNative(): boolean {\n return (\n typeof navigator !== \"undefined\" && navigator.product === \"ReactNative\"\n );\n}\n\n/**\n * Try to load NetInfo module (React Native only)\n * Returns null if not available\n */\nasync function getNetInfo(): Promise<NetInfoModule | null> {\n if (netInfoChecked) {\n return netInfoModule;\n }\n\n netInfoChecked = true;\n\n if (!isReactNative()) {\n return null;\n }\n\n try {\n // Dynamic import to avoid bundling issues on web\n const module = await import(\"@react-native-community/netinfo\");\n netInfoModule = module.default || module;\n return netInfoModule;\n } catch {\n // NetInfo not available\n return null;\n }\n}\n\n/**\n * Get current online status\n *\n * @returns Promise resolving to true if online, false if offline\n */\nexport async function getOnlineStatus(): Promise<boolean> {\n const netInfo = await getNetInfo();\n\n if (netInfo) {\n // React Native with NetInfo\n const state = await netInfo.fetch();\n return state.isConnected ?? true;\n }\n\n // Browser environment\n if (typeof navigator !== \"undefined\" && \"onLine\" in navigator) {\n return navigator.onLine;\n }\n\n // SSR or unknown environment - assume online\n return true;\n}\n\n/**\n * Get current online status synchronously (browser only, RN returns cached/default)\n * Use getOnlineStatus() for accurate cross-platform results\n *\n * @returns true if online (or unknown), false if offline\n */\nexport function getOnlineStatusSync(): boolean {\n // Browser environment\n if (typeof window !== \"undefined\" && typeof navigator !== \"undefined\") {\n return navigator.onLine;\n }\n\n // SSR, React Native, or unknown - assume online\n // For RN, use getOnlineStatus() async version for accuracy\n return true;\n}\n\n/**\n * Subscribe to network status changes\n *\n * @param callback - Function called when online status changes\n * @returns Unsubscribe function\n */\nexport function subscribeToNetworkChanges(\n callback: (isOnline: boolean) => void\n): () => void {\n // Try React Native NetInfo first\n if (isReactNative()) {\n let unsubscribe: NetInfoSubscription | null = null;\n\n // Async setup for NetInfo\n getNetInfo().then((netInfo) => {\n if (netInfo) {\n unsubscribe = netInfo.addEventListener((state) => {\n callback(state.isConnected ?? true);\n });\n }\n });\n\n return () => {\n if (unsubscribe) {\n unsubscribe();\n }\n };\n }\n\n // Browser environment (not React Native or SSR)\n const isBrowser = typeof window !== \"undefined\" && typeof window.addEventListener === \"function\";\n if (isBrowser) {\n const handleOnline = () => callback(true);\n const handleOffline = () => callback(false);\n\n window.addEventListener(\"online\", handleOnline);\n window.addEventListener(\"offline\", handleOffline);\n\n return () => {\n window.removeEventListener(\"online\", handleOnline);\n window.removeEventListener(\"offline\", handleOffline);\n };\n }\n\n // SSR or unknown - no-op\n return () => {};\n}\n\n/**\n * Initialize network monitoring (call early in app lifecycle)\n * This pre-loads NetInfo on React Native for faster subsequent calls\n */\nexport async function initializeNetworkMonitoring(): Promise<void> {\n await getNetInfo();\n}\n"],"mappings":"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","names":["useState","useEffect","useState","useEffect"]}
@@ -0,0 +1,14 @@
1
+ // src/config.ts
2
+ var supabaseUrl = process.env.SUPABASE_URL;
3
+ function setSupabaseUrl(url) {
4
+ supabaseUrl = url;
5
+ }
6
+ function getSupabaseUrl() {
7
+ return supabaseUrl;
8
+ }
9
+
10
+ export {
11
+ setSupabaseUrl,
12
+ getSupabaseUrl
13
+ };
14
+ //# sourceMappingURL=chunk-Y3INY2CS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["let supabaseUrl = process.env.SUPABASE_URL;\n\nexport function setSupabaseUrl(url: string) {\n supabaseUrl = url;\n}\n\nexport function getSupabaseUrl() {\n return supabaseUrl;\n}\n"],"mappings":";AAAA,IAAI,cAAc,QAAQ,IAAI;AAEvB,SAAS,eAAe,KAAa;AACxC,gBAAc;AAClB;AAEO,SAAS,iBAAiB;AAC7B,SAAO;AACX;","names":[]}