@pol-studios/db 1.0.31 → 1.0.34
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/{DataLayerContext-Dc7nF2IG.d.ts → DataLayerContext-BwMk4VpG.d.ts} +92 -8
- package/dist/UserMetadataContext-QLIv-mfF.d.ts +171 -0
- package/dist/{UserMetadataContext-B8gVWGMl.d.ts → UserMetadataContext-pQb3A8_Q.d.ts} +1 -1
- package/dist/auth/context.d.ts +53 -5
- package/dist/auth/context.js +30 -8
- package/dist/auth/guards.d.ts +9 -9
- package/dist/auth/guards.js +2 -3
- package/dist/auth/hooks.d.ts +108 -4
- package/dist/auth/hooks.js +13 -9
- package/dist/auth/index.d.ts +6 -6
- package/dist/auth/index.js +45 -17
- package/dist/chunk-5HJLTYRA.js +355 -0
- package/dist/chunk-5HJLTYRA.js.map +1 -0
- package/dist/{chunk-WX4ABYIF.js → chunk-67HMVGV7.js} +292 -94
- package/dist/chunk-67HMVGV7.js.map +1 -0
- package/dist/chunk-6KN7KLEG.js +1 -0
- package/dist/{chunk-FZF26ZRB.js → chunk-7BGDQT5X.js} +29 -16
- package/dist/{chunk-FZF26ZRB.js.map → chunk-7BGDQT5X.js.map} +1 -1
- package/dist/{chunk-P4UZ7IXC.js → chunk-7D4SUZUM.js} +1 -5
- package/dist/{chunk-3PJTNH2L.js → chunk-AKIRHA4Q.js} +2 -2
- package/dist/{chunk-OQ7U6EQ3.js → chunk-AML2TLXJ.js} +3801 -3424
- package/dist/chunk-AML2TLXJ.js.map +1 -0
- package/dist/{chunk-5EFDS7SR.js → chunk-DMVUEJG2.js} +7 -2
- package/dist/chunk-DMVUEJG2.js.map +1 -0
- package/dist/{chunk-ADD5MIMK.js → chunk-FESQS4S5.js} +15 -15
- package/dist/{chunk-ADD5MIMK.js.map → chunk-FESQS4S5.js.map} +1 -1
- package/dist/{chunk-U5UNPBKB.js → chunk-FI6JAD5G.js} +3 -3
- package/dist/{chunk-TKWR5AAY.js → chunk-JOULSXOI.js} +2 -2
- package/dist/{chunk-HTJ2FQW5.js → chunk-LF3V3ERS.js} +13 -15
- package/dist/{chunk-HTJ2FQW5.js.map → chunk-LF3V3ERS.js.map} +1 -1
- package/dist/{chunk-5BLKZUKM.js → chunk-MREERKQU.js} +45 -14
- package/dist/chunk-MREERKQU.js.map +1 -0
- package/dist/{chunk-VGEMLNNM.js → chunk-NP34C3O3.js} +306 -704
- package/dist/chunk-NP34C3O3.js.map +1 -0
- package/dist/{chunk-CNIGRBRE.js → chunk-QJZUIAHA.js} +43 -19
- package/dist/{chunk-CNIGRBRE.js.map → chunk-QJZUIAHA.js.map} +1 -1
- package/dist/{chunk-HAWJTZCK.js → chunk-RT4O5H2E.js} +5 -7
- package/dist/chunk-RT4O5H2E.js.map +1 -0
- package/dist/{chunk-2NVSXZKQ.js → chunk-TN7QINPK.js} +74 -309
- package/dist/chunk-TN7QINPK.js.map +1 -0
- package/dist/chunk-UBHORKBS.js +215 -0
- package/dist/chunk-UBHORKBS.js.map +1 -0
- package/dist/{chunk-WVF7RUW5.js → chunk-WM25QE7E.js} +3 -3
- package/dist/{chunk-H6365JPC.js → chunk-YUX6RGLZ.js} +3 -3
- package/dist/{chunk-H6365JPC.js.map → chunk-YUX6RGLZ.js.map} +1 -1
- package/dist/{chunk-H3LNH2NT.js → chunk-Z456IHCB.js} +5 -9
- package/dist/{chunk-H3LNH2NT.js.map → chunk-Z456IHCB.js.map} +1 -1
- package/dist/{chunk-JAATANS3.js → chunk-ZCOFRJQD.js} +3 -3
- package/dist/{chunk-JAATANS3.js.map → chunk-ZCOFRJQD.js.map} +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +2 -2
- package/dist/core/index.d.ts +54 -31
- package/dist/{executor-Br27YZvl.d.ts → executor-YJw4m7Q7.d.ts} +9 -1
- package/dist/gen/index.js +1 -1
- package/dist/hooks/index.d.ts +3 -22
- package/dist/hooks/index.js +12 -9
- package/dist/{index-CYFdO0iB.d.ts → index-lveh8qb0.d.ts} +1 -1
- package/dist/index.d.ts +38 -10
- package/dist/index.js +57 -36
- package/dist/index.native.d.ts +19 -13
- package/dist/index.native.js +64 -35
- package/dist/index.web.d.ts +18 -45
- package/dist/index.web.js +58 -49
- package/dist/index.web.js.map +1 -1
- package/dist/mutation/index.d.ts +2 -2
- package/dist/mutation/index.js +5 -5
- package/dist/parser/index.js +4 -4
- package/dist/powersync-bridge/index.d.ts +18 -3
- package/dist/powersync-bridge/index.js +2 -2
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +7 -8
- package/dist/realtime/index.js +7 -9
- package/dist/realtime/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +6 -7
- package/dist/{useBatchUpsert-9OYjibLh.d.ts → useBatchUpsert-DAkiCNo3.d.ts} +1 -1
- package/dist/{useDbCount-Dk0yCKlT.d.ts → useDbCount-DWfYB2iu.d.ts} +16 -2
- package/dist/{useResolveFeedback-C1KucfdQ.d.ts → useResolveFeedback-CxLccZKK.d.ts} +197 -93
- package/dist/{useSupabase-DvWVuHHE.d.ts → useSupabase-DSZNeXnF.d.ts} +1 -1
- package/dist/with-auth/index.d.ts +2 -2
- package/dist/with-auth/index.js +46 -33
- package/dist/with-auth/index.js.map +1 -1
- package/package.json +18 -8
- package/dist/UserMetadataContext-DntmpK41.d.ts +0 -33
- package/dist/canvas-C4TBBDUL.node +0 -0
- package/dist/canvas-ZQNCL7JL.js +0 -1541
- package/dist/canvas-ZQNCL7JL.js.map +0 -1
- package/dist/chunk-2NVSXZKQ.js.map +0 -1
- package/dist/chunk-5BLKZUKM.js.map +0 -1
- package/dist/chunk-5EFDS7SR.js.map +0 -1
- package/dist/chunk-HAWJTZCK.js.map +0 -1
- package/dist/chunk-NSIAAYW3.js +0 -1
- package/dist/chunk-O7SETNGD.js +0 -3391
- package/dist/chunk-O7SETNGD.js.map +0 -1
- package/dist/chunk-OQ7U6EQ3.js.map +0 -1
- package/dist/chunk-VGEMLNNM.js.map +0 -1
- package/dist/chunk-WX4ABYIF.js.map +0 -1
- package/dist/dist-NDNRSNOG.js +0 -521
- package/dist/dist-NDNRSNOG.js.map +0 -1
- package/dist/pdf-PHXP7RHD.js +0 -20336
- package/dist/pdf-PHXP7RHD.js.map +0 -1
- /package/dist/{chunk-NSIAAYW3.js.map → chunk-6KN7KLEG.js.map} +0 -0
- /package/dist/{chunk-P4UZ7IXC.js.map → chunk-7D4SUZUM.js.map} +0 -0
- /package/dist/{chunk-3PJTNH2L.js.map → chunk-AKIRHA4Q.js.map} +0 -0
- /package/dist/{chunk-U5UNPBKB.js.map → chunk-FI6JAD5G.js.map} +0 -0
- /package/dist/{chunk-TKWR5AAY.js.map → chunk-JOULSXOI.js.map} +0 -0
- /package/dist/{chunk-WVF7RUW5.js.map → chunk-WM25QE7E.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/hooks/useAuth.ts","../src/auth/hooks/usePermission.ts"],"sourcesContent":["import { isUsable } from \"@pol-studios/utils\";\nimport { useCallback, useContext, useMemo } from \"react\";\nimport { User } from \"@supabase/supabase-js\";\nimport { SetupAuthContext, setupAuthContext, type EffectivePermission } from \"../context/AuthProvider\";\nimport { permissionContext } from \"../context/PermissionContext\";\nimport { EntityAction, EntityType } from \"../types/EntityPermissions\";\n\n// Re-export EffectivePermission type for consumers\nexport type { EffectivePermission };\n\n/**\n * Hook for authenticated users only.\n * Throws an error if the user is not authenticated.\n * Use useSetupAuth() if you need to handle unauthenticated users.\n *\n * @returns Auth context with guaranteed non-null user and hasAccess helper\n * @throws Error if user is not authenticated\n *\n * @example\n * ```tsx\n * function AuthenticatedComponent() {\n * const { user, hasAccess, profile } = useAuth();\n *\n * // user is guaranteed to be non-null\n * console.log(user.id);\n *\n * if (hasAccess('admin')) {\n * return <AdminDashboard />;\n * }\n *\n * return <UserDashboard />;\n * }\n * ```\n */\nexport function useAuth() {\n const auth = useContext(setupAuthContext);\n if (isUsable(auth.user) === false) {\n console.log({\n auth\n });\n throw new Error(\"User must not be null, use useSetupAuth() to use a nullable user.\");\n } else {\n return auth as any;\n }\n}\n\n/**\n * Hook for handling both authenticated and unauthenticated states.\n * Does not throw if user is not authenticated.\n *\n * @returns Auth context with possibly null user, hasAccess, and hasEntityAccess helpers\n *\n * @example\n * ```tsx\n * function FlexibleComponent() {\n * const { user, hasAccess, hasEntityAccess, isLoading } = useSetupAuth();\n *\n * if (isLoading) {\n * return <Spinner />;\n * }\n *\n * if (!user) {\n * return <LoginPrompt />;\n * }\n *\n * // Check global access\n * const isAdmin = hasAccess('admin');\n *\n * // Check entity-level access\n * const canEditProject = hasEntityAccess('Project', 123, 'edit');\n *\n * return <Dashboard />;\n * }\n * ```\n */\nexport function useSetupAuth(): SetupAuthContext & {\n hasAccess: (access: string) => boolean;\n hasEntityAccess: (entityType: EntityType, entityId: number, action: EntityAction) => boolean;\n effectivePermissions: EffectivePermission[];\n} {\n const auth = useContext(setupAuthContext);\n const entityPermissions = useContext(permissionContext);\n\n // Use the context's hasAccess which now includes effective permissions checking\n const hasAccess = useCallback((key: string) => {\n // Delegate to context hasAccess if available (includes effective permissions)\n if (auth.hasAccess) {\n return auth.hasAccess(key);\n }\n\n // Fallback for backward compatibility\n // Archived/suspended users have no access\n if (auth.isArchived || auth.isSuspended) {\n return false;\n }\n const accessGiven = auth.access;\n if (isUsable(accessGiven) === false) return false;\n if (accessGiven.includes(\"owner\")) return true;\n if (accessGiven.includes(key)) return true;\n if (isUsable(key) === false) return true;\n return false;\n }, [auth.hasAccess, auth.access, auth.isArchived, auth.isSuspended]);\n\n /**\n * Check if the current user has access to a specific entity.\n * Owners (users with 'owner' access key) bypass entity permissions entirely.\n * Otherwise, delegates to the PermissionContext for granular permission checks.\n *\n * @param entityType - 'Project' | 'Client' | 'ProjectDatabase'\n * @param entityId - The ID of the entity to check\n * @param action - 'view' | 'adminView' | 'edit' | 'create' | 'delete' | 'share'\n * @returns boolean - true if user has permission for the action on the entity\n */\n const hasEntityAccess = useCallback((entityType: EntityType, entityId: number, action: EntityAction): boolean => {\n // Archived/suspended users have no entity access\n if (auth.isArchived || auth.isSuspended) {\n return false;\n }\n\n // Validate entityId is a valid positive integer\n if (!entityId || entityId <= 0 || !Number.isInteger(entityId)) {\n return false;\n }\n\n // Owners bypass all entity permission checks\n const accessGiven_0 = auth.access;\n if (isUsable(accessGiven_0) && accessGiven_0.includes(\"owner\")) {\n return true;\n }\n\n // If PermissionContext is not available, deny access\n if (!entityPermissions || typeof entityPermissions.checkPermission !== \"function\") {\n return false;\n }\n\n // Delegate to PermissionContext\n return entityPermissions.checkPermission(entityType, entityId, action);\n }, [auth.access, auth.isArchived, auth.isSuspended, entityPermissions]);\n return useMemo(() => ({\n hasAccess,\n hasEntityAccess,\n ...auth,\n user: auth.user,\n effectivePermissions: auth.effectivePermissions || []\n }), [hasAccess, hasEntityAccess, auth]);\n}","import { c as _c } from \"react/compiler-runtime\";\nimport { useContext, useEffect, useMemo } from \"react\";\nimport { permissionContext } from \"../context/PermissionContext\";\nimport { EntityType, EntityAction, EntityPermissionCheck } from \"../types/EntityPermissions\";\n\n// Re-export types for convenience\nexport type { EntityType, EntityAction, EntityPermissionCheck };\n\n/**\n * Hook to get the full PermissionContext\n * @throws Error if used outside of PermissionProvider\n */\nfunction usePermissionContext() {\n const context = useContext(permissionContext);\n if (!context || Object.keys(context).length === 0) {\n throw new Error(\"usePermission hooks must be used within a PermissionProvider\");\n }\n return context;\n}\n\n/**\n * Hook to get full permission info for a single entity\n * @param entityType - 'Project' | 'Client' | 'ProjectDatabase'\n * @param entityId - The ID of the entity (can be undefined for loading states)\n * @returns EntityPermissionCheck with canView, canEdit, etc. and isLoading\n *\n * @example\n * ```tsx\n * function ProjectHeader({ projectId }: { projectId: number }) {\n * const permission = usePermission('Project', projectId);\n *\n * if (permission.isLoading) {\n * return <Spinner />;\n * }\n *\n * return (\n * <div>\n * {permission.canEdit && <EditButton />}\n * {permission.canDelete && <DeleteButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermission(entityType, entityId) {\n const $ = _c(5);\n const {\n getPermission\n } = usePermissionContext();\n let t0;\n bb0: {\n if (entityId === undefined) {\n let t1;\n if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t1 = {\n canView: false,\n canAdminView: false,\n canEdit: false,\n canCreate: false,\n canDelete: false,\n canShare: false,\n permissionLevel: null,\n isLoading: true\n };\n $[0] = t1;\n } else {\n t1 = $[0];\n }\n t0 = t1;\n break bb0;\n }\n let t1;\n if ($[1] !== entityId || $[2] !== entityType || $[3] !== getPermission) {\n t1 = getPermission(entityType, entityId);\n $[1] = entityId;\n $[2] = entityType;\n $[3] = getPermission;\n $[4] = t1;\n } else {\n t1 = $[4];\n }\n t0 = t1;\n }\n return t0;\n}\n\n/**\n * Hook to check a single action permission\n * @param entityType - Entity type\n * @param entityId - Entity ID\n * @param action - 'view' | 'adminView' | 'edit' | 'create' | 'delete' | 'share'\n * @returns boolean - true if user has permission for action\n *\n * @example\n * ```tsx\n * function ProjectActions({ projectId }: { projectId: number }) {\n * const canEdit = usePermissionCheck('Project', projectId, 'edit');\n * const canDelete = usePermissionCheck('Project', projectId, 'delete');\n *\n * return (\n * <div>\n * <Button disabled={!canEdit}>Edit</Button>\n * <Button disabled={!canDelete}>Delete</Button>\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissionCheck(entityType, entityId, action) {\n const $ = _c(5);\n const {\n checkPermission\n } = usePermissionContext();\n let t0;\n bb0: {\n if (entityId === undefined) {\n t0 = false;\n break bb0;\n }\n let t1;\n if ($[0] !== action || $[1] !== checkPermission || $[2] !== entityId || $[3] !== entityType) {\n t1 = checkPermission(entityType, entityId, action);\n $[0] = action;\n $[1] = checkPermission;\n $[2] = entityId;\n $[3] = entityType;\n $[4] = t1;\n } else {\n t1 = $[4];\n }\n t0 = t1;\n }\n return t0;\n}\n\n/**\n * Result type for usePermissions batch hook\n */\nexport interface EntityWithPermission {\n type: EntityType;\n id: number;\n permission: EntityPermissionCheck;\n}\n\n/**\n * Hook for batch permission lookup - useful for lists\n * @param entities - Array of { type, id } objects\n * @returns Array of entities with their permissions attached\n *\n * This hook:\n * - Calls prefetchPermissions on mount and when entities change\n * - Returns memoized results\n * - Handles empty arrays gracefully\n *\n * @example\n * ```tsx\n * function ProjectList({ projects }: { projects: Array<{ id: number; name: string }> }) {\n * const entities = projects.map(p => ({ type: 'Project' as const, id: p.id }));\n * const entitiesWithPermissions = usePermissionsBatch(entities);\n *\n * return (\n * <ul>\n * {entitiesWithPermissions.map(({ id, permission }) => {\n * const project = projects.find(p => p.id === id);\n * return (\n * <li key={id}>\n * {project?.name}\n * {permission.canEdit && <EditIcon />}\n * </li>\n * );\n * })}\n * </ul>\n * );\n * }\n * ```\n */\nexport function usePermissionsBatch(entities: Array<{\n type: EntityType;\n id: number;\n}>): EntityWithPermission[] {\n const {\n getPermission,\n prefetchPermissions\n } = usePermissionContext();\n\n // Memoize the entities array to prevent unnecessary re-renders\n const entitiesKey = useMemo(() => entities.map(e => `${e.type}:${e.id}`).sort().join(\",\"), [entities]);\n\n // Prefetch permissions when entities change\n useEffect(() => {\n if (entities.length === 0) {\n return;\n }\n\n // Convert to the format expected by prefetchPermissions\n const entitiesToPrefetch = entities.map(e_0 => ({\n entityType: e_0.type,\n entityId: e_0.id\n }));\n prefetchPermissions(entitiesToPrefetch);\n }, [entities, entitiesKey, prefetchPermissions]);\n\n // Return memoized results\n return useMemo(() => {\n if (entities.length === 0) {\n return [];\n }\n return entities.map(entity => ({\n type: entity.type,\n id: entity.id,\n permission: getPermission(entity.type, entity.id)\n }));\n }, [getPermission, entitiesKey]);\n}\n\n/**\n * Simple boolean hook to check if user can view an entity\n * @param entityType - Entity type\n * @param entityId - Entity ID (can be undefined for loading states)\n * @returns boolean - true if user can view the entity\n *\n * @example\n * ```tsx\n * function ProjectPage({ projectId }: { projectId: number }) {\n * const canView = useCanView('Project', projectId);\n *\n * if (!canView) {\n * return <AccessDenied />;\n * }\n *\n * return <ProjectContent projectId={projectId} />;\n * }\n * ```\n */\nexport function useCanView(entityType, entityId) {\n return usePermissionCheck(entityType, entityId, \"view\");\n}\n\n/**\n * Simple boolean hook to check if user can edit an entity\n * @param entityType - Entity type\n * @param entityId - Entity ID (can be undefined for loading states)\n * @returns boolean - true if user can edit the entity\n *\n * @example\n * ```tsx\n * function ProjectEditor({ projectId }: { projectId: number }) {\n * const canEdit = useCanEdit('Project', projectId);\n *\n * return (\n * <form>\n * <input disabled={!canEdit} />\n * <button disabled={!canEdit}>Save</button>\n * </form>\n * );\n * }\n * ```\n */\nexport function useCanEdit(entityType, entityId) {\n return usePermissionCheck(entityType, entityId, \"edit\");\n}\n\n/**\n * Simple boolean hook to check if user can delete an entity\n * @param entityType - Entity type\n * @param entityId - Entity ID (can be undefined for loading states)\n * @returns boolean - true if user can delete the entity\n *\n * @example\n * ```tsx\n * function ProjectActions({ projectId }: { projectId: number }) {\n * const canDelete = useCanDelete('Project', projectId);\n *\n * return (\n * <Button\n * variant=\"destructive\"\n * disabled={!canDelete}\n * onClick={handleDelete}\n * >\n * Delete Project\n * </Button>\n * );\n * }\n * ```\n */\nexport function useCanDelete(entityType, entityId) {\n return usePermissionCheck(entityType, entityId, \"delete\");\n}\n\n/**\n * Simple boolean hook to check if user can share an entity\n * @param entityType - Entity type\n * @param entityId - Entity ID (can be undefined for loading states)\n * @returns boolean - true if user can share the entity\n *\n * @example\n * ```tsx\n * function ShareButton({ projectId }: { projectId: number }) {\n * const canShare = useCanShare('Project', projectId);\n *\n * if (!canShare) {\n * return null;\n * }\n *\n * return <Button onClick={openShareModal}>Share</Button>;\n * }\n * ```\n */\nexport function useCanShare(entityType, entityId) {\n return usePermissionCheck(entityType, entityId, \"share\");\n}\n\n/**\n * Simple boolean hook to check if user can create entities of a type\n * Note: For create permission, the entityId should be the parent entity ID\n * (e.g., for creating a ProjectDatabase, pass the Project ID)\n *\n * @param entityType - Entity type\n * @param entityId - Parent entity ID (can be undefined for loading states)\n * @returns boolean - true if user can create entities\n *\n * @example\n * ```tsx\n * function AddDatabaseButton({ projectId }: { projectId: number }) {\n * const canCreate = useCanCreate('ProjectDatabase', projectId);\n *\n * return (\n * <Button disabled={!canCreate} onClick={handleCreate}>\n * Add Database\n * </Button>\n * );\n * }\n * ```\n */\nexport function useCanCreate(entityType, entityId) {\n return usePermissionCheck(entityType, entityId, \"create\");\n}\n\n/**\n * Hook to invalidate permission cache for a specific entity\n * Useful after permission changes (e.g., after sharing an entity)\n *\n * @returns Function to invalidate permission for an entity\n *\n * @example\n * ```tsx\n * function ShareModal({ projectId }: { projectId: number }) {\n * const invalidatePermission = useInvalidatePermission();\n *\n * const handleShare = async (userId: string) => {\n * await shareProject(projectId, userId);\n * invalidatePermission('Project', projectId);\n * };\n *\n * return <ShareForm onShare={handleShare} />;\n * }\n * ```\n */\nexport function useInvalidatePermission() {\n const {\n invalidatePermission\n } = usePermissionContext();\n return invalidatePermission;\n}\n\n/**\n * Hook to get the loading state of the permission context\n * @returns boolean - true if permissions are being fetched\n *\n * @example\n * ```tsx\n * function PermissionAwareComponent() {\n * const isLoadingPermissions = usePermissionLoading();\n *\n * if (isLoadingPermissions) {\n * return <LoadingSpinner />;\n * }\n *\n * return <Content />;\n * }\n * ```\n */\nexport function usePermissionLoading() {\n const {\n isLoading\n } = usePermissionContext();\n return isLoading;\n}"],"mappings":"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","names":["useContext","useMemo","useContext","t1","useMemo"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/config.ts","../src/client/useSupabase.tsx","../src/utils/uuid.ts"],"sourcesContent":["let supabaseUrl = process.env.SUPABASE_URL;\nlet supabaseKey = process.env.SUPABASE_ANON_KEY ?? \"\";\nexport function setSupabaseUrl(url: string) {\n supabaseUrl = url;\n}\nexport function getSupabaseUrl() {\n return supabaseUrl;\n}\nexport function setSupabaseKey(key: string) {\n supabaseKey = key;\n}\nexport function getSupabaseKey() {\n return supabaseKey;\n}","import { c as _c } from \"react/compiler-runtime\";\nimport { createContext, ReactNode, useContext, useEffect, useMemo, useState } from \"react\";\nimport { createClient, SupabaseClient, SupabaseClientOptions } from \"@supabase/supabase-js\";\nimport { getSupabaseUrl, getSupabaseKey } from \"./config\";\nimport { generateUUID } from \"../utils/uuid\";\n\n// This interface is augmented by consumers to provide their database types\n// Example: declare module '@pol-studios/db' { interface SupabaseDatabaseTypes { Database: MyDatabaseType } }\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface SupabaseDatabaseTypes {}\nexport type Database = SupabaseDatabaseTypes extends {\n Database: infer D;\n} ? D : any;\nexport type TypedSupabaseClient = SupabaseClient<Database>;\nfunction newUuid(): string {\n return generateUUID();\n}\nfunction isUsable<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\nfunction delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n// Client instance ID - for self-change detection and cache keys (static per app instance)\n// NOT the database session ID - just identifies this browser tab/app instance\nexport const ClientInstanceId = newUuid();\n\n// DEPRECATED: Alias for backward compatibility - use ClientInstanceId instead\nexport const UserSessionId = ClientInstanceId;\nlet defaultOptions: any = {\n auth: {\n autoRefreshToken: true,\n persistSession: true,\n detectSessionInUrl: true\n },\n global: {},\n realtime: {}\n};\nexport function createNewSupabaseClient<SchemaName extends string & keyof Database = (\"public\" extends keyof Database ? \"public\" : string & keyof Database)>(options?: SupabaseClientOptions<SchemaName>) {\n const client = createClient<Database, SchemaName>(getSupabaseUrl()!, getSupabaseKey()!, {\n ...defaultOptions,\n ...options\n });\n onSupabaseInitializedAction && onSupabaseInitializedAction(client as any);\n return client;\n}\nlet onSupabaseInitializedAction: ((supabase: SupabaseClient) => any) | undefined = undefined;\nexport function onSupabaseInitialized(afterInitialize: (supabase: SupabaseClient) => any) {\n onSupabaseInitializedAction = afterInitialize;\n}\nexport function setDefaultOptions(options: SupabaseClientOptions<string & keyof Database>) {\n defaultOptions = options;\n}\nexport let typedSupabase: SupabaseClient<Database> = null as SupabaseClient<Database>;\nconst context = createContext({\n supabaseClient: typedSupabase as SupabaseClient<Database> | null\n});\nexport default function useSupabase() {\n const supabaseContext = useContext(context);\n if (isUsable(supabaseContext?.supabaseClient) === false) {\n throw new Error(\"Hook not inside a supabase context provider.\");\n }\n return supabaseContext.supabaseClient;\n}\nexport function SupabaseProvider(t0) {\n const $ = _c(16);\n const {\n children,\n options,\n afterInitialize,\n supabaseClient: supabaseClientProp\n } = t0;\n let t1;\n if ($[0] !== options || $[1] !== supabaseClientProp) {\n t1 = () => supabaseClientProp ?? createNewSupabaseClient({\n ...defaultOptions,\n ...(options ? options : {})\n }) as unknown as SupabaseClient<Database>;\n $[0] = options;\n $[1] = supabaseClientProp;\n $[2] = t1;\n } else {\n t1 = $[2];\n }\n const [supabaseClient] = useState(t1);\n const [wasHidden, setWasHidden] = useState(false);\n const [, setConnected] = useState(true);\n let t2;\n if ($[3] !== afterInitialize || $[4] !== supabaseClient) {\n t2 = () => {\n afterInitialize && afterInitialize(supabaseClient);\n };\n $[3] = afterInitialize;\n $[4] = supabaseClient;\n $[5] = t2;\n } else {\n t2 = $[5];\n }\n let t3;\n if ($[6] !== supabaseClient) {\n t3 = [supabaseClient];\n $[6] = supabaseClient;\n $[7] = t3;\n } else {\n t3 = $[7];\n }\n useEffect(t2, t3);\n let t4;\n let t5;\n if ($[8] !== wasHidden) {\n t4 = () => {\n const checkVisibility = async () => {\n if (typeof window.document === \"undefined\") {\n return;\n }\n if (document?.hidden) {\n await delay(60000).then(x => {\n if (document.hidden) {\n setWasHidden(true);\n }\n });\n } else {\n if (wasHidden) {\n setWasHidden(false);\n ;\n try {\n setConnected(true);\n } catch (t6) {\n const error = t6;\n console.error(\"Reconnection failed:\", error);\n setConnected(false);\n }\n }\n }\n };\n const intervalId = setInterval(checkVisibility, 1000);\n return () => {\n clearInterval(intervalId);\n };\n };\n t5 = [wasHidden];\n $[8] = wasHidden;\n $[9] = t4;\n $[10] = t5;\n } else {\n t4 = $[9];\n t5 = $[10];\n }\n useEffect(t4, t5);\n let t6;\n if ($[11] !== supabaseClient) {\n t6 = {\n supabaseClient\n };\n $[11] = supabaseClient;\n $[12] = t6;\n } else {\n t6 = $[12];\n }\n const t7 = t6;\n let t8;\n if ($[13] !== children || $[14] !== t7) {\n t8 = <context.Provider value={t7}>{children}</context.Provider>;\n $[13] = children;\n $[14] = t7;\n $[15] = t8;\n } else {\n t8 = $[15];\n }\n return t8;\n}","/**\n * Generate a UUID that works across all environments\n * (Browser, React Native, Node.js)\n */\nexport function generateUUID(): string {\n // Try Web Crypto API first (browsers, modern Node.js)\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for React Native and older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : r & 0x3 | 0x8;\n return v.toString(16);\n });\n}"],"mappings":"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","names":["t6"]}
|
|
@@ -1 +0,0 @@
|
|
|
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(accessKeys: string[] | undefined | null, key: string, options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\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 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(accessKeys: string[] | undefined | null, keys: string[], options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\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(accessKeys: string[] | undefined | null, keys: string[], options?: {\n isArchived?: boolean;\n isSuspended?: boolean;\n}): boolean {\n // Check each key, return true only if all match\n return keys.every(key => hasAccess(accessKeys, key, options));\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(permission: EntityPermissionCheck | null | undefined, action: EntityAction, options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\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(permission: EntityPermissionCheck | null | undefined, actions: EntityAction[], options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\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(permission: EntityPermissionCheck | null | undefined, actions: EntityAction[], options?: {\n accessKeys?: string[] | null;\n isArchived?: boolean;\n isSuspended?: boolean;\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(permission: EntityPermissionCheck | null | undefined): 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(permission: EntityPermissionCheck | null | undefined): permission is EntityPermissionCheck & {\n isLoading: false;\n} {\n return permission !== null && permission !== undefined && !permission.isLoading;\n}"],"mappings":";;;;;AA6BO,SAAS,UAAU,YAAyC,KAAa,SAGpE;AAEV,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;AACA,SAAO;AACT;AAgBO,SAAS,aAAa,YAAyC,MAAgB,SAG1E;AAEV,SAAO,KAAK,KAAK,SAAO,UAAU,YAAY,KAAK,OAAO,CAAC;AAC7D;AAgBO,SAAS,aAAa,YAAyC,MAAgB,SAG1E;AAEV,SAAO,KAAK,MAAM,SAAO,UAAU,YAAY,KAAK,OAAO,CAAC;AAC9D;;;ACtEO,SAAS,gBAAgB,YAAsD,QAAsB,SAIhG;AAEV,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,mBAAmB,YAAsD,SAAyB,SAItG;AACV,SAAO,QAAQ,KAAK,YAAU,gBAAgB,YAAY,QAAQ,OAAO,CAAC;AAC5E;AAgBO,SAAS,mBAAmB,YAAsD,SAAyB,SAItG;AACV,SAAO,QAAQ,MAAM,YAAU,gBAAgB,YAAY,QAAQ,OAAO,CAAC;AAC7E;AAiBO,SAAS,qBAAqB,YAA+D;AAClG,SAAO,YAAY,aAAa;AAClC;AAoBO,SAAS,mBAAmB,YAEjC;AACA,SAAO,eAAe,QAAQ,eAAe,UAAa,CAAC,WAAW;AACxE;","names":[]}
|
package/dist/chunk-NSIAAYW3.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=chunk-NSIAAYW3.js.map
|