@eminuckan/spine 0.3.0 → 0.3.2

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 (87) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +116 -98
  3. package/SECURITY.md +5 -15
  4. package/dist/access/index.mjs +2 -0
  5. package/dist/{access-CGrsDMwu.js → access-BHy1v5sr.mjs} +6 -8
  6. package/dist/access-BHy1v5sr.mjs.map +1 -0
  7. package/dist/api-client/index.mjs +3 -0
  8. package/dist/api-client/server.mjs +4 -0
  9. package/dist/{api-client-CgZUMukO.js → api-client-CB7XZaMg.mjs} +8 -10
  10. package/dist/api-client-CB7XZaMg.mjs.map +1 -0
  11. package/dist/auth/auth.server.d.ts +1 -0
  12. package/dist/auth/auth.server.d.ts.map +1 -1
  13. package/dist/auth/index.mjs +1 -0
  14. package/dist/auth/route-protection.server.d.ts.map +1 -1
  15. package/dist/auth/server.mjs +3 -0
  16. package/dist/{identity-C5un-xAs.js → identity/index.mjs} +24 -21
  17. package/dist/identity/index.mjs.map +1 -0
  18. package/dist/{server-Dxsww9v9.js → identity/server.mjs} +7 -8
  19. package/dist/identity/server.mjs.map +1 -0
  20. package/dist/{index.js → index.mjs} +11 -13
  21. package/dist/{logging-DviiAkLx.js → logging/index.mjs} +22 -24
  22. package/dist/logging/index.mjs.map +1 -0
  23. package/dist/{permission-service-CvGpwI0d.js → permission-service-DUyKomU3.mjs} +6 -10
  24. package/dist/permission-service-DUyKomU3.mjs.map +1 -0
  25. package/dist/permissions/index.mjs +3 -0
  26. package/dist/{permissions-_n1hIG7Q.js → permissions-C5dTP9y4.mjs} +23 -15
  27. package/dist/permissions-C5dTP9y4.mjs.map +1 -0
  28. package/dist/query-client/index.mjs +2 -0
  29. package/dist/{query-client-Bh3TyB8W.js → query-client-_xB300gc.mjs} +49 -15
  30. package/dist/query-client-_xB300gc.mjs.map +1 -0
  31. package/dist/react-router/{index.js → index.mjs} +11 -13
  32. package/dist/react-router/server.mjs +17 -0
  33. package/dist/{redis-session-storage.server-v2VcpFsQ.js → redis-session-storage.server-DGgQcJ9B.mjs} +30 -42
  34. package/dist/redis-session-storage.server-DGgQcJ9B.mjs.map +1 -0
  35. package/dist/{server-C96NMFBy.js → server-ByScGRXA.mjs} +39 -36
  36. package/dist/server-ByScGRXA.mjs.map +1 -0
  37. package/dist/{auth.server-D5oiz9aF.js → server-CqX2yCa4.mjs} +388 -119
  38. package/dist/server-CqX2yCa4.mjs.map +1 -0
  39. package/dist/server.mjs +90 -0
  40. package/dist/server.mjs.map +1 -0
  41. package/dist/signalr/index.mjs +2 -0
  42. package/dist/{signalr-k-70VHKo.js → signalr-C-TA8nEE.mjs} +11 -6
  43. package/dist/signalr-C-TA8nEE.mjs.map +1 -0
  44. package/dist/{tenant-DfLemb6n.js → tenant/index.mjs} +19 -12
  45. package/dist/tenant/index.mjs.map +1 -0
  46. package/dist/{server-Ca-3DJf2.js → tenant/server.mjs} +12 -12
  47. package/dist/tenant/server.mjs.map +1 -0
  48. package/dist/{types-BaaE6wjY.js → types-DqCXinAk.mjs} +3 -3
  49. package/dist/types-DqCXinAk.mjs.map +1 -0
  50. package/docs/codex-for-oss-application.md +14 -2
  51. package/package.json +14 -2
  52. package/dist/access/index.js +0 -4
  53. package/dist/access-CGrsDMwu.js.map +0 -1
  54. package/dist/api-client/index.js +0 -5
  55. package/dist/api-client/server.js +0 -6
  56. package/dist/api-client-CgZUMukO.js.map +0 -1
  57. package/dist/auth/index.js +0 -0
  58. package/dist/auth/server.js +0 -6
  59. package/dist/auth.server-D5oiz9aF.js.map +0 -1
  60. package/dist/auth.server-lC94lmlx.js +0 -5
  61. package/dist/identity/index.js +0 -3
  62. package/dist/identity/server.js +0 -5
  63. package/dist/identity-C5un-xAs.js.map +0 -1
  64. package/dist/logging/index.js +0 -3
  65. package/dist/logging-DviiAkLx.js.map +0 -1
  66. package/dist/permission-service-CvGpwI0d.js.map +0 -1
  67. package/dist/permissions/index.js +0 -4
  68. package/dist/permissions-_n1hIG7Q.js.map +0 -1
  69. package/dist/query-client/index.js +0 -3
  70. package/dist/query-client-Bh3TyB8W.js.map +0 -1
  71. package/dist/react-router/server.js +0 -20
  72. package/dist/redis-session-storage.server-v2VcpFsQ.js.map +0 -1
  73. package/dist/server-B6PCxc-T.js +0 -304
  74. package/dist/server-B6PCxc-T.js.map +0 -1
  75. package/dist/server-C96NMFBy.js.map +0 -1
  76. package/dist/server-Ca-3DJf2.js.map +0 -1
  77. package/dist/server-Dxsww9v9.js.map +0 -1
  78. package/dist/server-hGrElJMG.js +0 -78
  79. package/dist/server-hGrElJMG.js.map +0 -1
  80. package/dist/server.js +0 -20
  81. package/dist/signalr/index.js +0 -3
  82. package/dist/signalr-k-70VHKo.js.map +0 -1
  83. package/dist/src-B9rDUgSb.js +0 -0
  84. package/dist/tenant/index.js +0 -3
  85. package/dist/tenant/server.js +0 -5
  86. package/dist/tenant-DfLemb6n.js.map +0 -1
  87. package/dist/types-BaaE6wjY.js.map +0 -1
@@ -1,8 +1,12 @@
1
1
  import { create } from "zustand";
2
2
  import { useEffect } from "react";
3
3
  import { Fragment, jsx } from "react/jsx-runtime";
4
-
5
4
  //#region src/identity/identity-store.ts
5
+ /**
6
+ * Identity Store (Zustand)
7
+ *
8
+ * Centralized state management for identity context.
9
+ */
6
10
  const initialIdentityContext = {
7
11
  hasAnyMembership: false,
8
12
  hasEntitlement: false,
@@ -33,6 +37,8 @@ const DEFAULT_IDENTITY_STORE_CONFIG = {
33
37
  };
34
38
  let identityStoreConfig = { ...DEFAULT_IDENTITY_STORE_CONFIG };
35
39
  var IdentityUnauthorizedError = class extends Error {
40
+ reason;
41
+ response;
36
42
  constructor(reason, response) {
37
43
  super(reason);
38
44
  this.reason = reason;
@@ -51,8 +57,7 @@ function isRecord(value) {
51
57
  }
52
58
  function appendRefreshParam(endpoint, forceRefresh) {
53
59
  if (!forceRefresh) return endpoint;
54
- const separator = endpoint.includes("?") ? "&" : "?";
55
- return `${endpoint}${separator}refresh=true`;
60
+ return `${endpoint}${endpoint.includes("?") ? "&" : "?"}refresh=true`;
56
61
  }
57
62
  async function readJsonResponse(response) {
58
63
  const text = await response.text();
@@ -135,7 +140,7 @@ const useIdentityStore = create((set, get) => ({
135
140
  ...state.context,
136
141
  ...newContext,
137
142
  isLoading: false,
138
- lastUpdated: new Date()
143
+ lastUpdated: /* @__PURE__ */ new Date()
139
144
  } }));
140
145
  },
141
146
  refreshContext: async () => {
@@ -145,8 +150,7 @@ const useIdentityStore = create((set, get) => ({
145
150
  ...state.context,
146
151
  isLoading: true
147
152
  } }));
148
- const fetchContext = config.fetchContext ?? defaultFetchIdentityContext;
149
- const newContext = await fetchContext({
153
+ const newContext = await (config.fetchContext ?? defaultFetchIdentityContext)({
150
154
  endpoint: config.contextEndpoint,
151
155
  fetch: config.fetcher,
152
156
  forceRefresh: true,
@@ -157,7 +161,7 @@ const useIdentityStore = create((set, get) => ({
157
161
  ...get().context,
158
162
  ...newContext,
159
163
  isLoading: false,
160
- lastUpdated: new Date()
164
+ lastUpdated: /* @__PURE__ */ new Date()
161
165
  } });
162
166
  console.log("Identity context refreshed:", newContext);
163
167
  } else set((state) => ({ context: {
@@ -183,8 +187,7 @@ const useIdentityStore = create((set, get) => ({
183
187
  try {
184
188
  const config = getIdentityStoreConfig();
185
189
  console.log("Refreshing permissions...");
186
- const fetchPermissions = config.fetchPermissions ?? defaultFetchIdentityPermissions;
187
- const permissions = await fetchPermissions({
190
+ const permissions = await (config.fetchPermissions ?? defaultFetchIdentityPermissions)({
188
191
  endpoint: config.permissionsEndpoint,
189
192
  fetch: config.fetcher,
190
193
  currentContext: get().context
@@ -192,7 +195,7 @@ const useIdentityStore = create((set, get) => ({
192
195
  set((state) => ({ context: {
193
196
  ...state.context,
194
197
  permissions,
195
- lastUpdated: new Date()
198
+ lastUpdated: /* @__PURE__ */ new Date()
196
199
  } }));
197
200
  console.log("Permissions refreshed:", { count: permissions.length });
198
201
  } catch (error) {
@@ -220,18 +223,19 @@ const useUserTenants = () => useIdentityStore((state) => ({
220
223
  }));
221
224
  const useUserPermissions = () => useIdentityStore((state) => state.context.permissions);
222
225
  const useIdentityContext = () => {
223
- const context = useIdentityStore((state) => state.context);
224
- const refreshContext = useIdentityStore((state) => state.refreshContext);
225
- const refreshPermissions = useIdentityStore((state) => state.refreshPermissions);
226
226
  return {
227
- context,
228
- refreshContext,
229
- refreshPermissions
227
+ context: useIdentityStore((state) => state.context),
228
+ refreshContext: useIdentityStore((state) => state.refreshContext),
229
+ refreshPermissions: useIdentityStore((state) => state.refreshPermissions)
230
230
  };
231
231
  };
232
-
233
232
  //#endregion
234
233
  //#region src/identity/identity-context-provider.tsx
234
+ /**
235
+ * Identity Context Provider
236
+ *
237
+ * Initializes the identity store and listens to SignalR events.
238
+ */
235
239
  function IdentityContextProvider({ children, initialContext, accessToken, signalRClient }) {
236
240
  const setContext = useIdentityStore((state) => state.setContext);
237
241
  const refreshContext = useIdentityStore((state) => state.refreshContext);
@@ -252,8 +256,7 @@ function IdentityContextProvider({ children, initialContext, accessToken, signal
252
256
  } else refreshContext();
253
257
  }
254
258
  };
255
- const unsubscribe = signalRClient.onIdentityContextChanged(handleContextChange);
256
- return unsubscribe;
259
+ return signalRClient.onIdentityContextChanged(handleContextChange);
257
260
  }, [
258
261
  accessToken,
259
262
  contextVersion,
@@ -273,7 +276,7 @@ function IdentityContextProvider({ children, initialContext, accessToken, signal
273
276
  }, [signalRClient]);
274
277
  return /* @__PURE__ */ jsx(Fragment, { children });
275
278
  }
276
-
277
279
  //#endregion
278
280
  export { IdentityContextProvider, configureIdentityEndpoints, configureIdentityStore, initialIdentityContext, normalizeIdentityContextPayload, normalizeIdentityPermissionsPayload, resetIdentityStoreConfig, useHasEntitlement, useHasSubscription, useIdentityContext, useIdentityStore, useIsOnboarded, useUserPermissions, useUserTenants };
279
- //# sourceMappingURL=identity-C5un-xAs.js.map
281
+
282
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/identity/identity-store.ts","../../src/identity/identity-context-provider.tsx"],"sourcesContent":["/**\n * Identity Store (Zustand)\n * \n * Centralized state management for identity context.\n */\n\nimport { create } from 'zustand';\nimport type { IdentityContextData } from './types';\n\nexport const initialIdentityContext: IdentityContextData = {\n hasAnyMembership: false,\n hasEntitlement: false,\n hasSubscription: false,\n isOnboarded: false,\n tenants: [],\n currentTenant: undefined,\n permissions: [],\n contextVersion: 0,\n isLoading: true,\n userId: undefined,\n email: undefined,\n firstName: undefined,\n lastName: undefined,\n displayName: undefined,\n profileImageUrl: undefined,\n phoneNumber: undefined,\n timeZone: undefined,\n addresses: undefined,\n hasOwnerMembership: false,\n memberships: undefined,\n};\n\nexport interface IdentityContextFetchContext {\n endpoint: string;\n fetch: typeof fetch;\n forceRefresh: boolean;\n currentContext: IdentityContextData;\n}\n\nexport interface IdentityPermissionsFetchContext {\n endpoint: string;\n fetch: typeof fetch;\n currentContext: IdentityContextData;\n}\n\nexport interface IdentityState {\n context: IdentityContextData;\n\n // Actions\n setContext: (context: Partial<IdentityContextData>) => void;\n refreshContext: () => Promise<void>;\n refreshPermissions: () => Promise<void>;\n reset: () => void;\n}\n\nexport interface IdentityUnauthorizedDetails {\n reason: 'current-user-missing' | 'unauthorized';\n logoutPath: string;\n response?: Response;\n}\n\nexport interface IdentityStoreConfig {\n contextEndpoint?: string;\n permissionsEndpoint?: string;\n logoutPath?: string;\n fetcher?: typeof fetch;\n fetchContext?: (context: IdentityContextFetchContext) => Promise<Partial<IdentityContextData> | null>;\n fetchPermissions?: (context: IdentityPermissionsFetchContext) => Promise<string[]>;\n onUnauthorized?: (details: IdentityUnauthorizedDetails) => void;\n}\n\nconst DEFAULT_IDENTITY_STORE_CONFIG: Required<\n Pick<IdentityStoreConfig, 'contextEndpoint' | 'permissionsEndpoint' | 'logoutPath' | 'fetcher'>\n> = {\n contextEndpoint: '/api/identity/context',\n permissionsEndpoint: '/api/identity/permissions',\n logoutPath: '/auth/logout',\n fetcher: (input, init) => fetch(input, init),\n};\n\nlet identityStoreConfig: IdentityStoreConfig = {\n ...DEFAULT_IDENTITY_STORE_CONFIG,\n};\n\nclass IdentityUnauthorizedError extends Error {\n constructor(\n readonly reason: IdentityUnauthorizedDetails['reason'],\n readonly response?: Response\n ) {\n super(reason);\n this.name = 'IdentityUnauthorizedError';\n }\n}\n\nfunction getIdentityStoreConfig(): IdentityStoreConfig & typeof DEFAULT_IDENTITY_STORE_CONFIG {\n return {\n ...DEFAULT_IDENTITY_STORE_CONFIG,\n ...identityStoreConfig,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction appendRefreshParam(endpoint: string, forceRefresh: boolean): string {\n if (!forceRefresh) {\n return endpoint;\n }\n\n const separator = endpoint.includes('?') ? '&' : '?';\n return `${endpoint}${separator}refresh=true`;\n}\n\nasync function readJsonResponse(response: Response): Promise<unknown> {\n const text = await response.text();\n return text.trim().length > 0 ? JSON.parse(text) : null;\n}\n\nexport function normalizeIdentityContextPayload(payload: unknown): Partial<IdentityContextData> | null {\n if (!isRecord(payload)) {\n return null;\n }\n\n if (payload.success === false) {\n return null;\n }\n\n const nestedContext = payload.context ?? payload.data ?? payload.identity ?? payload.user;\n if (isRecord(nestedContext)) {\n return nestedContext as Partial<IdentityContextData>;\n }\n\n return payload as Partial<IdentityContextData>;\n}\n\nexport function normalizeIdentityPermissionsPayload(payload: unknown): string[] {\n if (Array.isArray(payload)) {\n return payload.filter((permission): permission is string => typeof permission === 'string');\n }\n\n if (!isRecord(payload)) {\n return [];\n }\n\n const nestedPermissions =\n payload.permissions ??\n (isRecord(payload.data) ? payload.data.permissions : payload.data) ??\n (isRecord(payload.context) ? payload.context.permissions : undefined);\n\n return Array.isArray(nestedPermissions)\n ? nestedPermissions.filter((permission): permission is string => typeof permission === 'string')\n : [];\n}\n\nasync function defaultFetchIdentityContext({\n endpoint,\n fetch: fetchFn,\n forceRefresh,\n}: IdentityContextFetchContext): Promise<Partial<IdentityContextData> | null> {\n const response = await fetchFn(appendRefreshParam(endpoint, forceRefresh), {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (response.ok) {\n return normalizeIdentityContextPayload(await readJsonResponse(response));\n }\n\n if (response.status === 404) {\n const errorData = await readJsonResponse(response).catch(() => ({}));\n if (\n isRecord(errorData) &&\n (errorData.code === 'CurrentUserMissing' || errorData.title === 'CurrentUserMissing')\n ) {\n throw new IdentityUnauthorizedError('current-user-missing', response);\n }\n }\n\n if (response.status === 401) {\n throw new IdentityUnauthorizedError('unauthorized', response);\n }\n\n console.error('Failed to refresh identity context:', response.status);\n return null;\n}\n\nasync function defaultFetchIdentityPermissions({\n endpoint,\n fetch: fetchFn,\n}: IdentityPermissionsFetchContext): Promise<string[]> {\n const response = await fetchFn(endpoint, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (response.ok) {\n return normalizeIdentityPermissionsPayload(await readJsonResponse(response));\n }\n\n if (response.status === 401) {\n throw new IdentityUnauthorizedError('unauthorized', response);\n }\n\n console.error('Failed to refresh permissions:', response.status);\n return [];\n}\n\nfunction handleUnauthorized(details: Omit<IdentityUnauthorizedDetails, 'logoutPath'>): void {\n const config = getIdentityStoreConfig();\n const unauthorizedDetails: IdentityUnauthorizedDetails = {\n ...details,\n logoutPath: config.logoutPath,\n };\n\n if (config.onUnauthorized) {\n config.onUnauthorized(unauthorizedDetails);\n return;\n }\n\n if (typeof window !== 'undefined') {\n window.location.href = config.logoutPath;\n }\n}\n\n/**\n * Configure the identity store for different app/back-end conventions.\n */\nexport function configureIdentityStore(config: IdentityStoreConfig): void {\n identityStoreConfig = {\n ...identityStoreConfig,\n ...config,\n };\n}\n\n/**\n * Reset identity store configuration to the built-in defaults.\n */\nexport function resetIdentityStoreConfig(): void {\n identityStoreConfig = {\n ...DEFAULT_IDENTITY_STORE_CONFIG,\n };\n}\n\n/**\n * Backward-compatible endpoint-only configuration helper.\n */\nexport function configureIdentityEndpoints(config: {\n contextEndpoint?: string;\n permissionsEndpoint?: string;\n}): void {\n configureIdentityStore(config);\n}\n\nexport const useIdentityStore = create<IdentityState>((set, get) => ({\n context: initialIdentityContext,\n\n setContext: (newContext) => {\n set((state) => ({\n context: {\n ...state.context,\n ...newContext,\n isLoading: false,\n lastUpdated: new Date(),\n },\n }));\n },\n\n refreshContext: async () => {\n try {\n const config = getIdentityStoreConfig();\n\n set((state) => ({\n context: { ...state.context, isLoading: true },\n }));\n\n const fetchContext = config.fetchContext ?? defaultFetchIdentityContext;\n const newContext = await fetchContext({\n endpoint: config.contextEndpoint,\n fetch: config.fetcher,\n forceRefresh: true,\n currentContext: get().context,\n });\n\n if (newContext) {\n set({\n context: {\n ...get().context,\n ...newContext,\n isLoading: false,\n lastUpdated: new Date(),\n },\n });\n console.log('Identity context refreshed:', newContext);\n } else {\n set((state) => ({\n context: { ...state.context, isLoading: false },\n }));\n }\n } catch (error) {\n if (error instanceof IdentityUnauthorizedError) {\n handleUnauthorized({\n reason: error.reason,\n response: error.response,\n });\n return;\n }\n\n console.error('Error refreshing identity context:', error);\n set((state) => ({\n context: { ...state.context, isLoading: false },\n }));\n }\n },\n\n refreshPermissions: async () => {\n try {\n const config = getIdentityStoreConfig();\n\n console.log('Refreshing permissions...');\n\n const fetchPermissions = config.fetchPermissions ?? defaultFetchIdentityPermissions;\n const permissions = await fetchPermissions({\n endpoint: config.permissionsEndpoint,\n fetch: config.fetcher,\n currentContext: get().context,\n });\n\n set((state) => ({\n context: {\n ...state.context,\n permissions,\n lastUpdated: new Date(),\n },\n }));\n\n console.log('Permissions refreshed:', {\n count: permissions.length,\n });\n } catch (error) {\n if (error instanceof IdentityUnauthorizedError) {\n handleUnauthorized({\n reason: error.reason,\n response: error.response,\n });\n return;\n }\n\n console.error('Error refreshing permissions:', error);\n }\n },\n\n reset: () => {\n set({ context: initialIdentityContext });\n },\n}));\n\n// Convenience selectors\nexport const useIsOnboarded = () => useIdentityStore((state) => state.context.isOnboarded);\nexport const useHasEntitlement = () => useIdentityStore((state) => state.context.hasEntitlement ?? state.context.hasSubscription);\n/** @deprecated Use useHasEntitlement or an app-specific selector instead. */\nexport const useHasSubscription = () => useIdentityStore((state) => state.context.hasSubscription);\nexport const useUserTenants = () =>\n useIdentityStore((state) => ({\n tenants: state.context.tenants,\n currentTenant: state.context.currentTenant,\n }));\nexport const useUserPermissions = () => useIdentityStore((state) => state.context.permissions);\nexport const useIdentityContext = () => {\n const context = useIdentityStore((state) => state.context);\n const refreshContext = useIdentityStore((state) => state.refreshContext);\n const refreshPermissions = useIdentityStore((state) => state.refreshPermissions);\n\n return { context, refreshContext, refreshPermissions };\n};\n","/**\n * Identity Context Provider\n * \n * Initializes the identity store and listens to SignalR events.\n */\n\nimport { useEffect, type ReactNode } from 'react';\nimport { useIdentityStore } from './identity-store';\nimport type { IdentityContextData, IdentityContextChangedEvent } from './types';\n\ninterface IdentityContextProviderProps {\n children: ReactNode;\n initialContext?: Partial<IdentityContextData>;\n accessToken?: string | null;\n signalRClient?: {\n onIdentityContextChanged: (handler: (event: IdentityContextChangedEvent) => void) => () => void;\n disconnect: () => Promise<void>;\n };\n}\n\nexport function IdentityContextProvider({\n children,\n initialContext,\n accessToken,\n signalRClient,\n}: IdentityContextProviderProps) {\n const setContext = useIdentityStore((state) => state.setContext);\n const refreshContext = useIdentityStore((state) => state.refreshContext);\n const refreshPermissions = useIdentityStore((state) => state.refreshPermissions);\n const contextVersion = useIdentityStore((state) => state.context.contextVersion);\n\n // Initialize store with initial context from server\n useEffect(() => {\n if (initialContext) {\n setContext(initialContext);\n }\n }, [initialContext, setContext]);\n\n // Handle SignalR identity context changes\n useEffect(() => {\n if (!signalRClient) return;\n\n const handleContextChange = (event: IdentityContextChangedEvent) => {\n console.log('Identity context changed via SignalR:', event);\n\n if (event.contextVersion > (contextVersion ?? 0)) {\n console.log('Refreshing context due to SignalR event...');\n\n if (event.reason === 'PermissionsChanged' || event.reason === 'RoleAssignmentChanged') {\n console.log('Permission-specific change detected, refreshing permissions only...');\n refreshPermissions();\n } else {\n refreshContext();\n }\n }\n };\n\n const unsubscribe = signalRClient.onIdentityContextChanged(handleContextChange);\n\n return unsubscribe;\n }, [accessToken, contextVersion, refreshContext, refreshPermissions, signalRClient]);\n\n // Initial context load if not provided\n useEffect(() => {\n if (!initialContext) {\n refreshContext();\n }\n }, [initialContext, refreshContext]);\n\n // Cleanup SignalR on unmount\n useEffect(() => {\n return () => {\n if (signalRClient) {\n signalRClient.disconnect().catch((error) => {\n console.error('Error disconnecting SignalR:', error);\n });\n }\n };\n }, [signalRClient]);\n\n return <>{children}</>;\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { logger } from "./logging-DviiAkLx.js";
2
- import { isApiClientError } from "./types-BaaE6wjY.js";
3
-
1
+ import { logger } from "../logging/index.mjs";
2
+ import { t as isApiClientError } from "../types-DqCXinAk.mjs";
4
3
  //#region src/identity/identity-context.server.ts
5
4
  let identityAPIFetcher = null;
6
5
  /**
@@ -9,8 +8,8 @@ let identityAPIFetcher = null;
9
8
  function configureIdentityAPIFetcher(fetcher) {
10
9
  identityAPIFetcher = fetcher;
11
10
  }
12
- const contextCache = new Map();
13
- const CONTEXT_CACHE_TTL = 5 * 60 * 1e3;
11
+ const contextCache = /* @__PURE__ */ new Map();
12
+ const CONTEXT_CACHE_TTL = 300 * 1e3;
14
13
  /**
15
14
  * Fetch identity context from backend
16
15
  */
@@ -30,7 +29,7 @@ async function fetchIdentityContext(request) {
30
29
  logger.error("Failed to fetch identity context", error instanceof Error ? error : void 0);
31
30
  if (isApiClientError(error) && error.response?.status === 404 && error.problemDetails?.title === "CurrentUserMissing") {
32
31
  logger.error("CurrentUserMissing error detected - session is invalid");
33
- const invalidSessionError = new Error("INVALID_SESSION");
32
+ const invalidSessionError = /* @__PURE__ */ new Error("INVALID_SESSION");
34
33
  invalidSessionError.isInvalidSession = true;
35
34
  throw invalidSessionError;
36
35
  }
@@ -141,7 +140,7 @@ function updateContextVersion(userId, newVersion) {
141
140
  version: newVersion
142
141
  });
143
142
  }
144
-
145
143
  //#endregion
146
144
  export { clearIdentityContextCache, configureIdentityAPIFetcher, configurePermissionFetcher, contextToUserInfo, fetchIdentityContext, fetchUserPermissions, getIdentityContext, hasContextVersionChanged, updateContextVersion };
147
- //# sourceMappingURL=server-Dxsww9v9.js.map
145
+
146
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../../src/identity/identity-context.server.ts"],"sourcesContent":["/**\n * Identity Context Server Module\n * \n * Server-side identity context management.\n */\n\nimport type { AddressData, IdentityContextData, TenantMembership } from './types';\nimport { isApiClientError } from '../api-client/types';\nimport { logger } from '../logging';\n\n/**\n * Identity API fetcher type (to avoid coupling with specific API client)\n */\nexport type IdentityAPIFetcher = (request: Request) => Promise<IdentityContextData>;\n\nlet identityAPIFetcher: IdentityAPIFetcher | null = null;\n\n/**\n * Configure identity API fetcher\n */\nexport function configureIdentityAPIFetcher(fetcher: IdentityAPIFetcher): void {\n identityAPIFetcher = fetcher;\n}\n\n// In-memory cache for identity context\nconst contextCache = new Map<\n string,\n {\n context: IdentityContextData;\n timestamp: number;\n version: number;\n }\n>();\n\nconst CONTEXT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetch identity context from backend\n */\nexport async function fetchIdentityContext(request: Request): Promise<IdentityContextData> {\n if (!identityAPIFetcher) {\n throw new Error('Identity API fetcher not configured. Call configureIdentityAPIFetcher first.');\n }\n\n try {\n logger.info('Fetching identity context');\n const context = await identityAPIFetcher(request);\n \n logger.debug('Identity context fetched', {\n hasAnyMembership: context.hasAnyMembership,\n hasEntitlement: context.hasEntitlement ?? context.hasSubscription,\n isOnboarded: context.isOnboarded,\n membershipCount: context.memberships?.length || 0,\n });\n\n return context;\n } catch (error: unknown) {\n logger.error('Failed to fetch identity context', error instanceof Error ? error : undefined);\n\n // Check if this is a CurrentUserMissing error\n if (isApiClientError(error) && error.response?.status === 404 && error.problemDetails?.title === 'CurrentUserMissing') {\n logger.error('CurrentUserMissing error detected - session is invalid');\n const invalidSessionError = new Error('INVALID_SESSION');\n (invalidSessionError as Error & { isInvalidSession: boolean }).isInvalidSession = true;\n throw invalidSessionError;\n }\n\n throw error;\n }\n}\n\n/**\n * Get cached identity context or fetch fresh if needed\n */\nexport async function getIdentityContext(\n request: Request,\n userId: string,\n forceRefresh = false\n): Promise<IdentityContextData> {\n const cacheKey = userId;\n const cached = contextCache.get(cacheKey);\n const now = Date.now();\n\n // Return cached if valid and not forcing refresh\n if (!forceRefresh && cached && now - cached.timestamp < CONTEXT_CACHE_TTL) {\n logger.debug('Using cached identity context for user', { userId });\n return cached.context;\n }\n\n // Fetch fresh context\n const context = await fetchIdentityContext(request);\n\n // Cache the result\n contextCache.set(cacheKey, {\n context,\n timestamp: now,\n version: context.contextVersion ?? 0,\n });\n\n logger.debug('Cached fresh identity context for user', { userId });\n return context;\n}\n\n/**\n * Clear identity context cache for user\n */\nexport function clearIdentityContextCache(userId?: string): void {\n if (userId) {\n contextCache.delete(userId);\n logger.debug('Cleared identity context cache for user', { userId });\n } else {\n contextCache.clear();\n logger.debug('Cleared all identity context cache');\n }\n}\n\n/**\n * Permission fetcher type\n */\nexport type PermissionFetcher = (request: Request, tenantId: string) => Promise<string[]>;\n\nlet permissionFetcher: PermissionFetcher | null = null;\n\n/**\n * Configure permission fetcher\n */\nexport function configurePermissionFetcher(fetcher: PermissionFetcher): void {\n permissionFetcher = fetcher;\n}\n\n/**\n * Fetch user permissions for a specific tenant\n */\nexport async function fetchUserPermissions(request: Request, tenantId: string): Promise<string[]> {\n if (!tenantId) {\n logger.warn('No tenant ID provided, skipping permission fetch');\n return [];\n }\n\n if (!permissionFetcher) {\n throw new Error('Permission fetcher not configured. Call configurePermissionFetcher first.');\n }\n\n try {\n return await permissionFetcher(request, tenantId);\n } catch (error) {\n logger.error('Failed to fetch user permissions', error instanceof Error ? error : undefined);\n return [];\n }\n}\n\nexport interface UserContextInfo {\n tenants: string[];\n memberships: TenantMembership[];\n currentTenant?: string;\n isOnboarded: boolean;\n permissions: string[];\n hasEntitlement: boolean;\n /** @deprecated Use hasEntitlement or app-specific fields instead. */\n hasSubscription: boolean;\n userId?: string;\n email?: string;\n firstName?: string | null;\n lastName?: string | null;\n displayName?: string | null;\n profileImageUrl?: string | null;\n phoneNumber?: string | null;\n timeZone?: string;\n addresses?: AddressData[];\n hasOwnerMembership: boolean;\n}\n\nexport interface ContextToUserInfoOptions {\n currentTenant?: string | null;\n request?: Request;\n}\n\n/**\n * Convert raw identity context into a tenant-aware user info shape.\n */\nexport async function contextToUserInfo(\n context: IdentityContextData,\n options: ContextToUserInfoOptions = {}\n): Promise<UserContextInfo> {\n const memberships = context.memberships || [];\n const tenants = memberships.map((membership) => membership.tenantId);\n const resolvedCurrentTenant =\n options.currentTenant && tenants.includes(options.currentTenant)\n ? options.currentTenant\n : tenants[0] || undefined;\n\n let permissions: string[] = [];\n if (resolvedCurrentTenant && options.request) {\n permissions = await fetchUserPermissions(options.request, resolvedCurrentTenant);\n }\n\n return {\n tenants,\n memberships,\n currentTenant: resolvedCurrentTenant,\n isOnboarded: context.isOnboarded ?? false,\n permissions,\n hasEntitlement: context.hasEntitlement ?? context.hasSubscription ?? false,\n hasSubscription: context.hasSubscription ?? context.hasEntitlement ?? false,\n userId: context.userId,\n email: context.email,\n firstName: context.firstName,\n lastName: context.lastName,\n displayName: context.displayName,\n profileImageUrl: context.profileImageUrl,\n phoneNumber: context.phoneNumber,\n timeZone: context.timeZone,\n addresses: context.addresses,\n hasOwnerMembership: context.hasOwnerMembership ?? false,\n };\n}\n\n/**\n * Check if a cached context version differs from the latest version.\n */\nexport function hasContextVersionChanged(userId: string, newVersion: number): boolean {\n const cached = contextCache.get(userId);\n return !cached || cached.version !== newVersion;\n}\n\n/**\n * Mark a cached identity context as stale after a version change.\n */\nexport function updateContextVersion(userId: string, newVersion: number): void {\n const cached = contextCache.get(userId);\n if (!cached) return;\n\n cached.version = newVersion;\n cached.timestamp = 0;\n logger.debug('Marked identity context as stale for user', {\n userId,\n version: newVersion,\n });\n}\n"],"mappings":";;;AAeA,IAAI,qBAAgD;;;;AAKpD,SAAgB,4BAA4B,SAAmC;CAC7E,qBAAqB;AACvB;AAGA,MAAM,+BAAe,IAAI,IAOvB;AAEF,MAAM,oBAAoB,MAAS;;;;AAKnC,eAAsB,qBAAqB,SAAgD;CACzF,IAAI,CAAC,oBACH,MAAM,IAAI,MAAM,8EAA8E;CAGhG,IAAI;EACF,OAAO,KAAK,2BAA2B;EACvC,MAAM,UAAU,MAAM,mBAAmB,OAAO;EAEhD,OAAO,MAAM,4BAA4B;GACvC,kBAAkB,QAAQ;GAC1B,gBAAgB,QAAQ,kBAAkB,QAAQ;GAClD,aAAa,QAAQ;GACrB,iBAAiB,QAAQ,aAAa,UAAU;EAClD,CAAC;EAED,OAAO;CACT,SAAS,OAAgB;EACvB,OAAO,MAAM,oCAAoC,iBAAiB,QAAQ,QAAQ,KAAA,CAAS;EAG3F,IAAI,iBAAiB,KAAK,KAAK,MAAM,UAAU,WAAW,OAAO,MAAM,gBAAgB,UAAU,sBAAsB;GACrH,OAAO,MAAM,wDAAwD;GACrE,MAAM,sCAAsB,IAAI,MAAM,iBAAiB;GACvD,oBAA+D,mBAAmB;GAClF,MAAM;EACR;EAEA,MAAM;CACR;AACF;;;;AAKA,eAAsB,mBACpB,SACA,QACA,eAAe,OACe;CAC9B,MAAM,WAAW;CACjB,MAAM,SAAS,aAAa,IAAI,QAAQ;CACxC,MAAM,MAAM,KAAK,IAAI;CAGrB,IAAI,CAAC,gBAAgB,UAAU,MAAM,OAAO,YAAY,mBAAmB;EACzE,OAAO,MAAM,0CAA0C,EAAE,OAAO,CAAC;EACjE,OAAO,OAAO;CAChB;CAGA,MAAM,UAAU,MAAM,qBAAqB,OAAO;CAGlD,aAAa,IAAI,UAAU;EACzB;EACA,WAAW;EACX,SAAS,QAAQ,kBAAkB;CACrC,CAAC;CAED,OAAO,MAAM,0CAA0C,EAAE,OAAO,CAAC;CACjE,OAAO;AACT;;;;AAKA,SAAgB,0BAA0B,QAAuB;CAC/D,IAAI,QAAQ;EACV,aAAa,OAAO,MAAM;EAC1B,OAAO,MAAM,2CAA2C,EAAE,OAAO,CAAC;CACpE,OAAO;EACL,aAAa,MAAM;EACnB,OAAO,MAAM,oCAAoC;CACnD;AACF;AAOA,IAAI,oBAA8C;;;;AAKlD,SAAgB,2BAA2B,SAAkC;CAC3E,oBAAoB;AACtB;;;;AAKA,eAAsB,qBAAqB,SAAkB,UAAqC;CAChG,IAAI,CAAC,UAAU;EACb,OAAO,KAAK,kDAAkD;EAC9D,OAAO,CAAC;CACV;CAEA,IAAI,CAAC,mBACH,MAAM,IAAI,MAAM,2EAA2E;CAG7F,IAAI;EACF,OAAO,MAAM,kBAAkB,SAAS,QAAQ;CAClD,SAAS,OAAO;EACd,OAAO,MAAM,oCAAoC,iBAAiB,QAAQ,QAAQ,KAAA,CAAS;EAC3F,OAAO,CAAC;CACV;AACF;;;;AA+BA,eAAsB,kBACpB,SACA,UAAoC,CAAC,GACX;CAC1B,MAAM,cAAc,QAAQ,eAAe,CAAC;CAC5C,MAAM,UAAU,YAAY,KAAK,eAAe,WAAW,QAAQ;CACnE,MAAM,wBACJ,QAAQ,iBAAiB,QAAQ,SAAS,QAAQ,aAAa,IAC3D,QAAQ,gBACR,QAAQ,MAAM,KAAA;CAEpB,IAAI,cAAwB,CAAC;CAC7B,IAAI,yBAAyB,QAAQ,SACnC,cAAc,MAAM,qBAAqB,QAAQ,SAAS,qBAAqB;CAGjF,OAAO;EACL;EACA;EACA,eAAe;EACf,aAAa,QAAQ,eAAe;EACpC;EACA,gBAAgB,QAAQ,kBAAkB,QAAQ,mBAAmB;EACrE,iBAAiB,QAAQ,mBAAmB,QAAQ,kBAAkB;EACtE,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,WAAW,QAAQ;EACnB,UAAU,QAAQ;EAClB,aAAa,QAAQ;EACrB,iBAAiB,QAAQ;EACzB,aAAa,QAAQ;EACrB,UAAU,QAAQ;EAClB,WAAW,QAAQ;EACnB,oBAAoB,QAAQ,sBAAsB;CACpD;AACF;;;;AAKA,SAAgB,yBAAyB,QAAgB,YAA6B;CACpF,MAAM,SAAS,aAAa,IAAI,MAAM;CACtC,OAAO,CAAC,UAAU,OAAO,YAAY;AACvC;;;;AAKA,SAAgB,qBAAqB,QAAgB,YAA0B;CAC7E,MAAM,SAAS,aAAa,IAAI,MAAM;CACtC,IAAI,CAAC,QAAQ;CAEb,OAAO,UAAU;CACjB,OAAO,YAAY;CACnB,OAAO,MAAM,6CAA6C;EACxD;EACA,SAAS;CACX,CAAC;AACH"}
@@ -1,13 +1,11 @@
1
- import { LOG_LEVEL_PRIORITY, LogLevel, Logger, createLogger, defaultLoggerConfig, logger } from "./logging-DviiAkLx.js";
2
- import { PermissionChecker } from "./permission-service-CvGpwI0d.js";
3
- import { PERMISSION_MODULES, PermissionInitializer, ProtectedAction, ProtectedButton, ProtectedLink, ProtectedSection, getPermissionChecker, getPermissions, initializePermissions, useAllPermissions, useHasModulePermission, useHasPermission, useHasPermissions, useModulePermission, usePermission, usePermissionChecker, usePermissionStore, usePermissions } from "./permissions-_n1hIG7Q.js";
4
- import { evaluateAccessRequirement } from "./access-CGrsDMwu.js";
5
- import { TenantProvider, configureTenantClient, configureTenantEndpoints, getTenantCookieName, initializeTenantStore, normalizeTenantDataPayload, normalizeTenantSwitchPayload, resetTenantClientConfig, useCurrentOrganization, useCurrentTenant, useCurrentTenantData, useOrganization, useTenant, useTenantData, useTenantStore, useTenantSwitcher } from "./tenant-DfLemb6n.js";
6
- import { IdentityContextProvider, configureIdentityEndpoints, configureIdentityStore, initialIdentityContext, normalizeIdentityContextPayload, normalizeIdentityPermissionsPayload, resetIdentityStoreConfig, useHasEntitlement, useHasSubscription, useIdentityContext, useIdentityStore, useIsOnboarded, useUserPermissions, useUserTenants } from "./identity-C5un-xAs.js";
7
- import { isApiClientError } from "./types-BaaE6wjY.js";
8
- import { ApiError, ErrorCodes, ErrorHandler, calculateBackoffDelay, createRetryFetch, fetchWithTimeout, handleApiError, isRetryableError, withRetry } from "./api-client-CgZUMukO.js";
9
- import { IdentitySignalRClient, SignalRClient, cleanupSignalR, createIdentitySignalRClient, getIdentitySignalRClient, initializeSignalR } from "./signalr-k-70VHKo.js";
10
- import { cachePresets, createQueryClient, createQueryKeyFactory, invalidationHelpers } from "./query-client-Bh3TyB8W.js";
11
- import "./src-B9rDUgSb.js";
12
-
13
- export { ApiError, ErrorCodes, ErrorHandler, IdentityContextProvider, IdentitySignalRClient, LOG_LEVEL_PRIORITY, LogLevel, Logger, PERMISSION_MODULES, PermissionChecker, PermissionInitializer, ProtectedAction, ProtectedButton, ProtectedLink, ProtectedSection, SignalRClient, TenantProvider, cachePresets, calculateBackoffDelay, cleanupSignalR, configureIdentityEndpoints, configureIdentityStore, configureTenantClient, configureTenantEndpoints, createIdentitySignalRClient, createLogger, createQueryClient, createQueryKeyFactory, createRetryFetch, defaultLoggerConfig, evaluateAccessRequirement, fetchWithTimeout, getIdentitySignalRClient, getPermissionChecker, getPermissions, getTenantCookieName, handleApiError, initialIdentityContext, initializePermissions, initializeSignalR, initializeTenantStore, invalidationHelpers, isApiClientError, isRetryableError, logger, normalizeIdentityContextPayload, normalizeIdentityPermissionsPayload, normalizeTenantDataPayload, normalizeTenantSwitchPayload, resetIdentityStoreConfig, resetTenantClientConfig, useAllPermissions, useCurrentOrganization, useCurrentTenant, useCurrentTenantData, useHasEntitlement, useHasModulePermission, useHasPermission, useHasPermissions, useHasSubscription, useIdentityContext, useIdentityStore, useIsOnboarded, useModulePermission, useOrganization, usePermission, usePermissionChecker, usePermissionStore, usePermissions, useTenant, useTenantData, useTenantStore, useTenantSwitcher, useUserPermissions, useUserTenants, withRetry };
1
+ import { LOG_LEVEL_PRIORITY, LogLevel, Logger, createLogger, defaultLoggerConfig, logger } from "./logging/index.mjs";
2
+ import { t as PermissionChecker } from "./permission-service-DUyKomU3.mjs";
3
+ import { _ as initializePermissions, a as ProtectedSection, c as useHasPermission, d as usePermission, f as usePermissionChecker, g as getPermissions, h as getPermissionChecker, i as ProtectedLink, l as useHasPermissions, m as PermissionInitializer, n as ProtectedAction, o as useAllPermissions, p as usePermissions, r as ProtectedButton, s as useHasModulePermission, t as PERMISSION_MODULES, u as useModulePermission, v as usePermissionStore } from "./permissions-C5dTP9y4.mjs";
4
+ import { t as evaluateAccessRequirement } from "./access-BHy1v5sr.mjs";
5
+ import { TenantProvider, configureTenantClient, configureTenantEndpoints, getTenantCookieName, initializeTenantStore, normalizeTenantDataPayload, normalizeTenantSwitchPayload, resetTenantClientConfig, useCurrentOrganization, useCurrentTenant, useCurrentTenantData, useOrganization, useTenant, useTenantData, useTenantStore, useTenantSwitcher } from "./tenant/index.mjs";
6
+ import { IdentityContextProvider, configureIdentityEndpoints, configureIdentityStore, initialIdentityContext, normalizeIdentityContextPayload, normalizeIdentityPermissionsPayload, resetIdentityStoreConfig, useHasEntitlement, useHasSubscription, useIdentityContext, useIdentityStore, useIsOnboarded, useUserPermissions, useUserTenants } from "./identity/index.mjs";
7
+ import { t as isApiClientError } from "./types-DqCXinAk.mjs";
8
+ import { a as withRetry, c as handleApiError, i as isRetryableError, l as ErrorCodes, n as createRetryFetch, o as ApiError, r as fetchWithTimeout, s as ErrorHandler, t as calculateBackoffDelay } from "./api-client-CB7XZaMg.mjs";
9
+ import { a as getIdentitySignalRClient, i as createIdentitySignalRClient, n as SignalRClient, o as initializeSignalR, r as cleanupSignalR, t as IdentitySignalRClient } from "./signalr-C-TA8nEE.mjs";
10
+ import { i as invalidationHelpers, n as createQueryClient, r as createQueryKeyFactory, t as cachePresets } from "./query-client-_xB300gc.mjs";
11
+ export { ApiError, ErrorCodes, ErrorHandler, IdentityContextProvider, IdentitySignalRClient, LOG_LEVEL_PRIORITY, LogLevel, Logger, PERMISSION_MODULES, PermissionChecker, PermissionInitializer, ProtectedAction, ProtectedButton, ProtectedLink, ProtectedSection, SignalRClient, TenantProvider, cachePresets, calculateBackoffDelay, cleanupSignalR, configureIdentityEndpoints, configureIdentityStore, configureTenantClient, configureTenantEndpoints, createIdentitySignalRClient, createLogger, createQueryClient, createQueryKeyFactory, createRetryFetch, defaultLoggerConfig, evaluateAccessRequirement, fetchWithTimeout, getIdentitySignalRClient, getPermissionChecker, getPermissions, getTenantCookieName, handleApiError, initialIdentityContext, initializePermissions, initializeSignalR, initializeTenantStore, invalidationHelpers, isApiClientError, isRetryableError, logger, normalizeIdentityContextPayload, normalizeIdentityPermissionsPayload, normalizeTenantDataPayload, normalizeTenantSwitchPayload, resetIdentityStoreConfig, resetTenantClientConfig, useAllPermissions, useCurrentOrganization, useCurrentTenant, useCurrentTenantData, useHasEntitlement, useHasModulePermission, useHasPermission, useHasPermissions, useHasSubscription, useIdentityContext, useIdentityStore, useIsOnboarded, useModulePermission, useOrganization, usePermission, usePermissionChecker, usePermissionStore, usePermissions, useTenant, useTenantData, useTenantStore, useTenantSwitcher, useUserPermissions, useUserTenants, withRetry };
@@ -2,29 +2,27 @@
2
2
  /**
3
3
  * Logging Types
4
4
  */
5
- let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
6
- LogLevel$1["DEBUG"] = "debug";
7
- LogLevel$1["INFO"] = "info";
8
- LogLevel$1["WARN"] = "warn";
9
- LogLevel$1["ERROR"] = "error";
10
- return LogLevel$1;
5
+ let LogLevel = /* @__PURE__ */ function(LogLevel) {
6
+ LogLevel["DEBUG"] = "debug";
7
+ LogLevel["INFO"] = "info";
8
+ LogLevel["WARN"] = "warn";
9
+ LogLevel["ERROR"] = "error";
10
+ return LogLevel;
11
11
  }({});
12
-
13
12
  //#endregion
14
13
  //#region src/logging/config.ts
15
14
  const LOG_LEVEL_PRIORITY = {
16
- [LogLevel.DEBUG]: 0,
17
- [LogLevel.INFO]: 1,
18
- [LogLevel.WARN]: 2,
19
- [LogLevel.ERROR]: 3
15
+ ["debug"]: 0,
16
+ ["info"]: 1,
17
+ ["warn"]: 2,
18
+ ["error"]: 3
20
19
  };
21
20
  const defaultLoggerConfig = {
22
- minLevel: process.env.NODE_ENV === "production" ? LogLevel.INFO : LogLevel.DEBUG,
21
+ minLevel: process.env.NODE_ENV === "production" ? "info" : "debug",
23
22
  enableConsole: true,
24
23
  enableRemote: false,
25
24
  serviceName: "spine"
26
25
  };
27
-
28
26
  //#endregion
29
27
  //#region src/logging/logger.ts
30
28
  var Logger = class {
@@ -36,21 +34,21 @@ var Logger = class {
36
34
  };
37
35
  }
38
36
  debug(message, context) {
39
- this.log(LogLevel.DEBUG, message, context);
37
+ this.log("debug", message, context);
40
38
  }
41
39
  info(message, context) {
42
- this.log(LogLevel.INFO, message, context);
40
+ this.log("info", message, context);
43
41
  }
44
42
  warn(message, context) {
45
- this.log(LogLevel.WARN, message, context);
43
+ this.log("warn", message, context);
46
44
  }
47
45
  error(message, error, context) {
48
- this.log(LogLevel.ERROR, message, context, error);
46
+ this.log("error", message, context, error);
49
47
  }
50
48
  log(level, message, context, error) {
51
49
  if (!this.shouldLog(level)) return;
52
50
  const entry = {
53
- timestamp: new Date().toISOString(),
51
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
54
52
  level,
55
53
  message,
56
54
  context,
@@ -67,16 +65,16 @@ var Logger = class {
67
65
  logToConsole(entry) {
68
66
  const formatted = this.formatEntry(entry);
69
67
  switch (entry.level) {
70
- case LogLevel.DEBUG:
68
+ case "debug":
71
69
  console.debug(formatted);
72
70
  break;
73
- case LogLevel.INFO:
71
+ case "info":
74
72
  console.info(formatted);
75
73
  break;
76
- case LogLevel.WARN:
74
+ case "warn":
77
75
  console.warn(formatted);
78
76
  break;
79
- case LogLevel.ERROR:
77
+ case "error":
80
78
  console.error(formatted);
81
79
  if (entry.error) console.error(entry.error);
82
80
  break;
@@ -112,7 +110,7 @@ const logger = new Logger();
112
110
  function createLogger(config) {
113
111
  return new Logger(config);
114
112
  }
115
-
116
113
  //#endregion
117
114
  export { LOG_LEVEL_PRIORITY, LogLevel, Logger, createLogger, defaultLoggerConfig, logger };
118
- //# sourceMappingURL=logging-DviiAkLx.js.map
115
+
116
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/logging/types.ts","../../src/logging/config.ts","../../src/logging/logger.ts"],"sourcesContent":["/**\n * Logging Types\n */\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nexport interface LogContext {\n [key: string]: unknown;\n}\n\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n context?: LogContext;\n error?: Error;\n}\n\nexport interface LoggerConfig {\n minLevel: LogLevel;\n enableConsole: boolean;\n enableRemote: boolean;\n remoteEndpoint?: string;\n serviceName?: string;\n}\n","/**\n * Logger Configuration\n */\n\nimport { LogLevel, type LoggerConfig } from './types';\n\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n [LogLevel.DEBUG]: 0,\n [LogLevel.INFO]: 1,\n [LogLevel.WARN]: 2,\n [LogLevel.ERROR]: 3,\n};\n\nexport const defaultLoggerConfig: LoggerConfig = {\n minLevel: process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG,\n enableConsole: true,\n enableRemote: false,\n serviceName: 'spine',\n};\n","/**\n * Logger Service\n * \n * Centralized logging implementation with structured logging format.\n */\n\nimport { LogLevel, type LogContext, type LogEntry, type LoggerConfig } from './types';\nimport { defaultLoggerConfig, LOG_LEVEL_PRIORITY } from './config';\n\nexport class Logger {\n private config: LoggerConfig;\n\n constructor(config?: Partial<LoggerConfig>) {\n this.config = {\n ...defaultLoggerConfig,\n ...config,\n };\n }\n\n debug(message: string, context?: LogContext): void {\n this.log(LogLevel.DEBUG, message, context);\n }\n\n info(message: string, context?: LogContext): void {\n this.log(LogLevel.INFO, message, context);\n }\n\n warn(message: string, context?: LogContext): void {\n this.log(LogLevel.WARN, message, context);\n }\n\n error(message: string, error?: Error, context?: LogContext): void {\n this.log(LogLevel.ERROR, message, context, error);\n }\n\n private log(\n level: LogLevel,\n message: string,\n context?: LogContext,\n error?: Error\n ): void {\n if (!this.shouldLog(level)) {\n return;\n }\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n context,\n error,\n };\n\n if (this.config.enableConsole) {\n this.logToConsole(entry);\n }\n\n if (this.config.enableRemote && this.config.remoteEndpoint) {\n this.sendToRemote(entry).catch((err) => {\n console.error('Failed to send log to remote endpoint:', err);\n });\n }\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.config.minLevel];\n }\n\n private logToConsole(entry: LogEntry): void {\n const formatted = this.formatEntry(entry);\n\n switch (entry.level) {\n case LogLevel.DEBUG:\n console.debug(formatted);\n break;\n case LogLevel.INFO:\n console.info(formatted);\n break;\n case LogLevel.WARN:\n console.warn(formatted);\n break;\n case LogLevel.ERROR:\n console.error(formatted);\n if (entry.error) {\n console.error(entry.error);\n }\n break;\n }\n }\n\n private formatEntry(entry: LogEntry): string {\n const parts = [\n `[${entry.timestamp}]`,\n `[${entry.level.toUpperCase()}]`,\n entry.message,\n ];\n\n if (entry.context && Object.keys(entry.context).length > 0) {\n parts.push(JSON.stringify(entry.context));\n }\n\n return parts.join(' ');\n }\n\n private async sendToRemote(entry: LogEntry): Promise<void> {\n if (!this.config.remoteEndpoint) return;\n\n await fetch(this.config.remoteEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...entry,\n serviceName: this.config.serviceName,\n error: entry.error\n ? {\n name: entry.error.name,\n message: entry.error.message,\n stack: entry.error.stack,\n }\n : undefined,\n }),\n });\n }\n}\n\n// Default logger instance\nexport const logger = new Logger();\n\n// Create logger with custom config\nexport function createLogger(config?: Partial<LoggerConfig>): Logger {\n return new Logger(config);\n}\n"],"mappings":";;;;AAIA,IAAY,WAAL,yBAAA,UAAA;CACL,SAAA,WAAA;CACA,SAAA,UAAA;CACA,SAAA,UAAA;CACA,SAAA,WAAA;;AACF,EAAA,CAAA,CAAA;;;ACHA,MAAa,qBAA+C;YACxC;WACD;WACA;YACC;AACpB;AAEA,MAAa,sBAAoC;CAC/C,UAAU,QAAQ,IAAI,aAAa,eAAA,SAAA;CACnC,eAAe;CACf,cAAc;CACd,aAAa;AACf;;;ACTA,IAAa,SAAb,MAAoB;CAClB;CAEA,YAAY,QAAgC;EAC1C,KAAK,SAAS;GACZ,GAAG;GACH,GAAG;EACL;CACF;CAEA,MAAM,SAAiB,SAA4B;EACjD,KAAK,IAAA,SAAoB,SAAS,OAAO;CAC3C;CAEA,KAAK,SAAiB,SAA4B;EAChD,KAAK,IAAA,QAAmB,SAAS,OAAO;CAC1C;CAEA,KAAK,SAAiB,SAA4B;EAChD,KAAK,IAAA,QAAmB,SAAS,OAAO;CAC1C;CAEA,MAAM,SAAiB,OAAe,SAA4B;EAChE,KAAK,IAAA,SAAoB,SAAS,SAAS,KAAK;CAClD;CAEA,IACE,OACA,SACA,SACA,OACM;EACN,IAAI,CAAC,KAAK,UAAU,KAAK,GACvB;EAGF,MAAM,QAAkB;GACtB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;GAClC;GACA;GACA;GACA;EACF;EAEA,IAAI,KAAK,OAAO,eACd,KAAK,aAAa,KAAK;EAGzB,IAAI,KAAK,OAAO,gBAAgB,KAAK,OAAO,gBAC1C,KAAK,aAAa,KAAK,CAAC,CAAC,OAAO,QAAQ;GACtC,QAAQ,MAAM,0CAA0C,GAAG;EAC7D,CAAC;CAEL;CAEA,UAAkB,OAA0B;EAC1C,OAAO,mBAAmB,UAAU,mBAAmB,KAAK,OAAO;CACrE;CAEA,aAAqB,OAAuB;EAC1C,MAAM,YAAY,KAAK,YAAY,KAAK;EAExC,QAAQ,MAAM,OAAd;GACE,KAAA;IACE,QAAQ,MAAM,SAAS;IACvB;GACF,KAAA;IACE,QAAQ,KAAK,SAAS;IACtB;GACF,KAAA;IACE,QAAQ,KAAK,SAAS;IACtB;GACF,KAAA;IACE,QAAQ,MAAM,SAAS;IACvB,IAAI,MAAM,OACR,QAAQ,MAAM,MAAM,KAAK;IAE3B;EACJ;CACF;CAEA,YAAoB,OAAyB;EAC3C,MAAM,QAAQ;GACZ,IAAI,MAAM,UAAU;GACpB,IAAI,MAAM,MAAM,YAAY,EAAE;GAC9B,MAAM;EACR;EAEA,IAAI,MAAM,WAAW,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,SAAS,GACvD,MAAM,KAAK,KAAK,UAAU,MAAM,OAAO,CAAC;EAG1C,OAAO,MAAM,KAAK,GAAG;CACvB;CAEA,MAAc,aAAa,OAAgC;EACzD,IAAI,CAAC,KAAK,OAAO,gBAAgB;EAEjC,MAAM,MAAM,KAAK,OAAO,gBAAgB;GACtC,QAAQ;GACR,SAAS,EAAE,gBAAgB,mBAAmB;GAC9C,MAAM,KAAK,UAAU;IACnB,GAAG;IACH,aAAa,KAAK,OAAO;IACzB,OAAO,MAAM,QACT;KACE,MAAM,MAAM,MAAM;KAClB,SAAS,MAAM,MAAM;KACrB,OAAO,MAAM,MAAM;IACrB,IACA,KAAA;GACN,CAAC;EACH,CAAC;CACH;AACF;AAGA,MAAa,SAAS,IAAI,OAAO;AAGjC,SAAgB,aAAa,QAAwC;CACnE,OAAO,IAAI,OAAO,MAAM;AAC1B"}
@@ -24,14 +24,10 @@ var PermissionChecker = class {
24
24
  const { operator = "OR", wildcard = false } = options;
25
25
  const matchedPermissions = [];
26
26
  const missingPermissions = [];
27
- for (const permission of permissions) {
28
- const hasIt = wildcard ? this.hasWildcardPermission(permission) : this.hasPermission(permission);
29
- if (hasIt) matchedPermissions.push(permission);
30
- else missingPermissions.push(permission);
31
- }
32
- const hasPermission = operator === "AND" ? missingPermissions.length === 0 : matchedPermissions.length > 0;
27
+ for (const permission of permissions) if (wildcard ? this.hasWildcardPermission(permission) : this.hasPermission(permission)) matchedPermissions.push(permission);
28
+ else missingPermissions.push(permission);
33
29
  return {
34
- hasPermission,
30
+ hasPermission: operator === "AND" ? missingPermissions.length === 0 : matchedPermissions.length > 0,
35
31
  matchedPermissions,
36
32
  missingPermissions
37
33
  };
@@ -89,7 +85,7 @@ var PermissionChecker = class {
89
85
  return this.permissionArray.length;
90
86
  }
91
87
  };
92
-
93
88
  //#endregion
94
- export { PermissionChecker };
95
- //# sourceMappingURL=permission-service-CvGpwI0d.js.map
89
+ export { PermissionChecker as t };
90
+
91
+ //# sourceMappingURL=permission-service-DUyKomU3.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-service-DUyKomU3.mjs","names":[],"sources":["../src/permissions/permission-service.ts"],"sourcesContent":["/**\n * Permission Service\n * \n * Core permission checking logic.\n */\n\nimport type {\n PermissionCode,\n PermissionModule,\n PermissionCheckOptions,\n PermissionCheckResult,\n FieldPermissionResult,\n} from './types';\n\n/**\n * Permission Checker Class\n * \n * Provides methods for checking user permissions.\n */\nexport class PermissionChecker {\n private permissions: Set<PermissionCode>;\n private permissionArray: PermissionCode[];\n\n constructor(permissions: PermissionCode[]) {\n this.permissionArray = permissions;\n this.permissions = new Set(permissions);\n }\n\n /**\n * Check if user has a single permission\n */\n hasPermission(permission: PermissionCode): boolean {\n return this.permissions.has(permission);\n }\n\n /**\n * Check multiple permissions with AND/OR logic\n */\n hasPermissions(\n permissions: PermissionCode[],\n options: PermissionCheckOptions = {}\n ): PermissionCheckResult {\n const { operator = 'OR', wildcard = false } = options;\n\n const matchedPermissions: PermissionCode[] = [];\n const missingPermissions: PermissionCode[] = [];\n\n for (const permission of permissions) {\n const hasIt = wildcard\n ? this.hasWildcardPermission(permission)\n : this.hasPermission(permission);\n\n if (hasIt) {\n matchedPermissions.push(permission);\n } else {\n missingPermissions.push(permission);\n }\n }\n\n const hasPermission =\n operator === 'AND'\n ? missingPermissions.length === 0\n : matchedPermissions.length > 0;\n\n return {\n hasPermission,\n matchedPermissions,\n missingPermissions,\n };\n }\n\n /**\n * Check wildcard permission pattern\n */\n private hasWildcardPermission(pattern: PermissionCode): boolean {\n if (!pattern.includes('*')) {\n return this.hasPermission(pattern);\n }\n\n const regex = new RegExp(\n '^' + pattern.replace(/\\./g, '\\\\.').replace(/\\*/g, '.*') + '$'\n );\n\n return this.permissionArray.some((p) => regex.test(p));\n }\n\n /**\n * Check if user has any permission in a module\n */\n hasModulePermission(module: PermissionModule): boolean {\n const prefix = `${module}.`;\n return this.permissionArray.some((p) => p.startsWith(prefix));\n }\n\n /**\n * Get field-level permissions for an entity\n */\n getFieldPermissions(\n module: PermissionModule,\n entity: string\n ): FieldPermissionResult {\n const base = `${module}.${entity}`;\n\n return {\n canView: this.hasPermission(`${base}.View`),\n canEdit: this.hasPermission(`${base}.Edit`),\n canCreate: this.hasPermission(`${base}.Create`),\n canDelete: this.hasPermission(`${base}.Delete`),\n };\n }\n\n /**\n * Get all permissions\n */\n getAllPermissions(): readonly PermissionCode[] {\n return Object.freeze([...this.permissionArray]);\n }\n\n /**\n * Get permissions for a specific module\n */\n getModulePermissions(module: PermissionModule): PermissionCode[] {\n const prefix = `${module}.`;\n return this.permissionArray.filter((p) => p.startsWith(prefix));\n }\n\n /**\n * Check if user has any permissions\n */\n hasAnyPermissions(): boolean {\n return this.permissionArray.length > 0;\n }\n\n /**\n * Get permission count\n */\n getPermissionCount(): number {\n return this.permissionArray.length;\n }\n}\n"],"mappings":";;;;;;AAmBA,IAAa,oBAAb,MAA+B;CAC7B;CACA;CAEA,YAAY,aAA+B;EACzC,KAAK,kBAAkB;EACvB,KAAK,cAAc,IAAI,IAAI,WAAW;CACxC;;;;CAKA,cAAc,YAAqC;EACjD,OAAO,KAAK,YAAY,IAAI,UAAU;CACxC;;;;CAKA,eACE,aACA,UAAkC,CAAC,GACZ;EACvB,MAAM,EAAE,WAAW,MAAM,WAAW,UAAU;EAE9C,MAAM,qBAAuC,CAAC;EAC9C,MAAM,qBAAuC,CAAC;EAE9C,KAAK,MAAM,cAAc,aAKvB,IAJc,WACV,KAAK,sBAAsB,UAAU,IACrC,KAAK,cAAc,UAAU,GAG/B,mBAAmB,KAAK,UAAU;OAElC,mBAAmB,KAAK,UAAU;EAStC,OAAO;GACL,eALA,aAAa,QACT,mBAAmB,WAAW,IAC9B,mBAAmB,SAAS;GAIhC;GACA;EACF;CACF;;;;CAKA,sBAA8B,SAAkC;EAC9D,IAAI,CAAC,QAAQ,SAAS,GAAG,GACvB,OAAO,KAAK,cAAc,OAAO;EAGnC,MAAM,QAAQ,IAAI,OAChB,MAAM,QAAQ,QAAQ,OAAO,KAAK,CAAC,CAAC,QAAQ,OAAO,IAAI,IAAI,GAC7D;EAEA,OAAO,KAAK,gBAAgB,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC;CACvD;;;;CAKA,oBAAoB,QAAmC;EACrD,MAAM,SAAS,GAAG,OAAO;EACzB,OAAO,KAAK,gBAAgB,MAAM,MAAM,EAAE,WAAW,MAAM,CAAC;CAC9D;;;;CAKA,oBACE,QACA,QACuB;EACvB,MAAM,OAAO,GAAG,OAAO,GAAG;EAE1B,OAAO;GACL,SAAS,KAAK,cAAc,GAAG,KAAK,MAAM;GAC1C,SAAS,KAAK,cAAc,GAAG,KAAK,MAAM;GAC1C,WAAW,KAAK,cAAc,GAAG,KAAK,QAAQ;GAC9C,WAAW,KAAK,cAAc,GAAG,KAAK,QAAQ;EAChD;CACF;;;;CAKA,oBAA+C;EAC7C,OAAO,OAAO,OAAO,CAAC,GAAG,KAAK,eAAe,CAAC;CAChD;;;;CAKA,qBAAqB,QAA4C;EAC/D,MAAM,SAAS,GAAG,OAAO;EACzB,OAAO,KAAK,gBAAgB,QAAQ,MAAM,EAAE,WAAW,MAAM,CAAC;CAChE;;;;CAKA,oBAA6B;EAC3B,OAAO,KAAK,gBAAgB,SAAS;CACvC;;;;CAKA,qBAA6B;EAC3B,OAAO,KAAK,gBAAgB;CAC9B;AACF"}
@@ -0,0 +1,3 @@
1
+ import { t as PermissionChecker } from "../permission-service-DUyKomU3.mjs";
2
+ import { _ as initializePermissions, a as ProtectedSection, c as useHasPermission, d as usePermission, f as usePermissionChecker, g as getPermissions, h as getPermissionChecker, i as ProtectedLink, l as useHasPermissions, m as PermissionInitializer, n as ProtectedAction, o as useAllPermissions, p as usePermissions, r as ProtectedButton, s as useHasModulePermission, t as PERMISSION_MODULES, u as useModulePermission, v as usePermissionStore } from "../permissions-C5dTP9y4.mjs";
3
+ export { PERMISSION_MODULES, PermissionChecker, PermissionInitializer, ProtectedAction, ProtectedButton, ProtectedLink, ProtectedSection, getPermissionChecker, getPermissions, initializePermissions, useAllPermissions, useHasModulePermission, useHasPermission, useHasPermissions, useModulePermission, usePermission, usePermissionChecker, usePermissionStore, usePermissions };
@@ -1,10 +1,14 @@
1
- import { PermissionChecker } from "./permission-service-CvGpwI0d.js";
1
+ import { t as PermissionChecker } from "./permission-service-DUyKomU3.mjs";
2
2
  import { create } from "zustand";
3
3
  import { useCallback, useEffect, useMemo } from "react";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
-
6
5
  //#region src/permissions/permission-store.ts
7
6
  /**
7
+ * Permission Store (Zustand)
8
+ *
9
+ * State management for permissions.
10
+ */
11
+ /**
8
12
  * Selectors for focused store reads
9
13
  */
10
14
  const selectChecker = (state) => state.checker;
@@ -53,10 +57,14 @@ function getPermissionChecker() {
53
57
  function getPermissions() {
54
58
  return usePermissionStore.getState().permissions;
55
59
  }
56
-
57
60
  //#endregion
58
61
  //#region src/permissions/permission-initializer.tsx
59
62
  /**
63
+ * Permission Initializer Component
64
+ *
65
+ * Initializes permission store from identity context.
66
+ */
67
+ /**
60
68
  * Component that initializes permissions from props
61
69
  */
62
70
  function PermissionInitializer({ permissions, isLoading = false, children }) {
@@ -65,10 +73,14 @@ function PermissionInitializer({ permissions, isLoading = false, children }) {
65
73
  }, [permissions, isLoading]);
66
74
  return /* @__PURE__ */ jsx(Fragment, { children });
67
75
  }
68
-
69
76
  //#endregion
70
77
  //#region src/permissions/hooks.ts
71
78
  /**
79
+ * Permission Hooks
80
+ *
81
+ * React hooks for permission checks.
82
+ */
83
+ /**
72
84
  * Hook for checking a single permission
73
85
  */
74
86
  function usePermission(permission) {
@@ -119,15 +131,13 @@ function useAllPermissions() {
119
131
  const checker = usePermissionStore(selectChecker);
120
132
  return useMemo(() => checker.getAllPermissions(), [checker]);
121
133
  }
122
-
123
134
  //#endregion
124
135
  //#region src/permissions/components.tsx
125
136
  /**
126
137
  * Button that only renders if user has the required permission
127
138
  */
128
- function ProtectedButton({ permission, fallback = null, children,...props }) {
129
- const hasPermission = usePermission(permission);
130
- if (!hasPermission) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
139
+ function ProtectedButton({ permission, fallback = null, children, ...props }) {
140
+ if (!usePermission(permission)) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
131
141
  return /* @__PURE__ */ jsx("button", {
132
142
  ...props,
133
143
  children
@@ -136,9 +146,8 @@ function ProtectedButton({ permission, fallback = null, children,...props }) {
136
146
  /**
137
147
  * Link that only renders if user has the required permission
138
148
  */
139
- function ProtectedLink({ permission, fallback = null, children,...props }) {
140
- const hasPermission = usePermission(permission);
141
- if (!hasPermission) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
149
+ function ProtectedLink({ permission, fallback = null, children, ...props }) {
150
+ if (!usePermission(permission)) return /* @__PURE__ */ jsx(Fragment, { children: fallback });
142
151
  return /* @__PURE__ */ jsx("a", {
143
152
  ...props,
144
153
  children
@@ -167,7 +176,6 @@ function ProtectedAction({ permission, onAction, children }) {
167
176
  disabled: !hasPermission
168
177
  }) });
169
178
  }
170
-
171
179
  //#endregion
172
180
  //#region src/permissions/constants.ts
173
181
  /**
@@ -177,7 +185,7 @@ function ProtectedAction({ permission, onAction, children }) {
177
185
  * module constants in the consuming app instead.
178
186
  */
179
187
  const PERMISSION_MODULES = [];
180
-
181
188
  //#endregion
182
- export { PERMISSION_MODULES, PermissionInitializer, ProtectedAction, ProtectedButton, ProtectedLink, ProtectedSection, getPermissionChecker, getPermissions, initializePermissions, useAllPermissions, useHasModulePermission, useHasPermission, useHasPermissions, useModulePermission, usePermission, usePermissionChecker, usePermissionStore, usePermissions };
183
- //# sourceMappingURL=permissions-_n1hIG7Q.js.map
189
+ export { initializePermissions as _, ProtectedSection as a, useHasPermission as c, usePermission as d, usePermissionChecker as f, getPermissions as g, getPermissionChecker as h, ProtectedLink as i, useHasPermissions as l, PermissionInitializer as m, ProtectedAction as n, useAllPermissions as o, usePermissions as p, ProtectedButton as r, useHasModulePermission as s, PERMISSION_MODULES as t, useModulePermission as u, usePermissionStore as v };
190
+
191
+ //# sourceMappingURL=permissions-C5dTP9y4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-C5dTP9y4.mjs","names":[],"sources":["../src/permissions/permission-store.ts","../src/permissions/permission-initializer.tsx","../src/permissions/hooks.ts","../src/permissions/components.tsx","../src/permissions/constants.ts"],"sourcesContent":["/**\n * Permission Store (Zustand)\n * \n * State management for permissions.\n */\n\nimport { create } from 'zustand';\nimport { PermissionChecker } from './permission-service';\nimport type { PermissionCode } from './types';\n\n/**\n * Permission store state interface\n */\ninterface PermissionState {\n checker: PermissionChecker;\n permissions: PermissionCode[];\n isLoading: boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setLoading: (isLoading: boolean) => void;\n reset: () => void;\n}\n\n/**\n * Selectors for focused store reads\n */\nexport const selectChecker = (state: PermissionState) => state.checker;\nexport const selectPermissions = (state: PermissionState) => state.permissions;\nexport const selectIsLoading = (state: PermissionState) => state.isLoading;\n\n/**\n * Initial state\n */\nconst initialState = {\n checker: new PermissionChecker([]),\n permissions: [] as PermissionCode[],\n isLoading: false,\n};\n\n/**\n * Permission store\n */\nexport const usePermissionStore = create<PermissionState>((set) => ({\n ...initialState,\n\n setPermissions: (permissions: PermissionCode[]) => {\n set({\n permissions,\n checker: new PermissionChecker(permissions),\n });\n },\n\n setLoading: (isLoading: boolean) => {\n set({ isLoading });\n },\n\n reset: () => {\n set(initialState);\n },\n}));\n\n/**\n * Initialize permission store\n */\nexport function initializePermissions(\n permissions: PermissionCode[],\n isLoading: boolean = false\n): void {\n usePermissionStore.getState().setPermissions(permissions);\n usePermissionStore.getState().setLoading(isLoading);\n}\n\n/**\n * Get permission checker outside React components\n */\nexport function getPermissionChecker(): PermissionChecker {\n return usePermissionStore.getState().checker;\n}\n\n/**\n * Get all permissions outside React components\n */\nexport function getPermissions(): PermissionCode[] {\n return usePermissionStore.getState().permissions;\n}\n","/**\n * Permission Initializer Component\n * \n * Initializes permission store from identity context.\n */\n\nimport { useEffect, type ReactNode } from 'react';\nimport { initializePermissions } from './permission-store';\nimport type { PermissionCode } from './types';\n\ninterface PermissionInitializerProps {\n permissions: PermissionCode[];\n isLoading?: boolean;\n children: ReactNode;\n}\n\n/**\n * Component that initializes permissions from props\n */\nexport function PermissionInitializer({\n permissions,\n isLoading = false,\n children,\n}: PermissionInitializerProps) {\n useEffect(() => {\n initializePermissions(permissions, isLoading);\n }, [permissions, isLoading]);\n\n return <>{children}</>;\n}\n","/**\n * Permission Hooks\n * \n * React hooks for permission checks.\n */\n\nimport { useMemo, useCallback } from 'react';\nimport { usePermissionStore, selectChecker } from './permission-store';\nimport type { PermissionCode, PermissionCheckOptions, PermissionModule } from './types';\n\n/**\n * Hook for checking a single permission\n */\nexport function usePermission(permission: PermissionCode): boolean {\n const checker = usePermissionStore(selectChecker);\n return useMemo(() => checker.hasPermission(permission), [checker, permission]);\n}\n\n/**\n * Alias for usePermission\n */\nexport const useHasPermission = usePermission;\n\n/**\n * Hook for checking multiple permissions\n */\nexport function usePermissions(\n permissions: PermissionCode[],\n options?: PermissionCheckOptions\n) {\n const checker = usePermissionStore(selectChecker);\n return useMemo(\n () => checker.hasPermissions(permissions, options),\n [checker, permissions, options]\n );\n}\n\n/**\n * Alias for usePermissions\n */\nexport const useHasPermissions = usePermissions;\n\n/**\n * Hook for checking module-level permissions\n */\nexport function useModulePermission(module: PermissionModule): boolean {\n const checker = usePermissionStore(selectChecker);\n return useMemo(() => checker.hasModulePermission(module), [checker, module]);\n}\n\n/**\n * Alias for useModulePermission\n */\nexport const useHasModulePermission = useModulePermission;\n\n/**\n * Hook for getting a memoized permission checker function\n */\nexport function usePermissionChecker() {\n const checker = usePermissionStore(selectChecker);\n return useCallback(\n (permission: PermissionCode) => checker.hasPermission(permission),\n [checker]\n );\n}\n\n/**\n * Hook for getting all user permissions\n */\nexport function useAllPermissions(): readonly PermissionCode[] {\n const checker = usePermissionStore(selectChecker);\n return useMemo(() => checker.getAllPermissions(), [checker]);\n}\n\n/**\n * Hook for field-level permissions\n */\nexport function useFieldPermissions(module: PermissionModule, entity: string) {\n const checker = usePermissionStore(selectChecker);\n return useMemo(\n () => checker.getFieldPermissions(module, entity),\n [checker, module, entity]\n );\n}\n\n/**\n * Hook for permission loading state\n */\nexport function usePermissionLoading(): boolean {\n return usePermissionStore((state) => state.isLoading);\n}\n","/**\n * Permission Components\n * \n * Protected UI components that conditionally render based on permissions.\n */\n\nimport React, { type ReactNode, type ComponentProps } from 'react';\nimport { usePermission, usePermissions } from './hooks';\nimport type { PermissionCode, PermissionCheckOptions } from './types';\n\n// ============================================================================\n// ProtectedButton\n// ============================================================================\n\ninterface ProtectedButtonProps extends ComponentProps<'button'> {\n permission: PermissionCode;\n fallback?: ReactNode;\n}\n\n/**\n * Button that only renders if user has the required permission\n */\nexport function ProtectedButton({\n permission,\n fallback = null,\n children,\n ...props\n}: ProtectedButtonProps) {\n const hasPermission = usePermission(permission);\n\n if (!hasPermission) {\n return <>{fallback}</>;\n }\n\n return <button {...props}>{children}</button>;\n}\n\n// ============================================================================\n// ProtectedLink\n// ============================================================================\n\ninterface ProtectedLinkProps extends ComponentProps<'a'> {\n permission: PermissionCode;\n fallback?: ReactNode;\n}\n\n/**\n * Link that only renders if user has the required permission\n */\nexport function ProtectedLink({\n permission,\n fallback = null,\n children,\n ...props\n}: ProtectedLinkProps) {\n const hasPermission = usePermission(permission);\n\n if (!hasPermission) {\n return <>{fallback}</>;\n }\n\n return <a {...props}>{children}</a>;\n}\n\n// ============================================================================\n// ProtectedSection\n// ============================================================================\n\ninterface ProtectedSectionProps {\n permission?: PermissionCode;\n permissions?: PermissionCode[];\n options?: PermissionCheckOptions;\n fallback?: ReactNode;\n children: ReactNode;\n}\n\n/**\n * Section that only renders if user has the required permission(s)\n */\nexport function ProtectedSection({\n permission,\n permissions,\n options,\n fallback = null,\n children,\n}: ProtectedSectionProps) {\n // Single permission check\n const singlePermissionResult = usePermission(permission || '');\n \n // Multiple permissions check\n const multiplePermissionsResult = usePermissions(permissions || [], options);\n\n // Determine if we should render\n let hasPermission = false;\n \n if (permission) {\n hasPermission = singlePermissionResult;\n } else if (permissions && permissions.length > 0) {\n hasPermission = multiplePermissionsResult.hasPermission;\n } else {\n // No permission specified, render by default\n hasPermission = true;\n }\n\n if (!hasPermission) {\n return <>{fallback}</>;\n }\n\n return <>{children}</>;\n}\n\n// ============================================================================\n// ProtectedAction\n// ============================================================================\n\ninterface ProtectedActionProps {\n permission: PermissionCode;\n onAction: () => void;\n children: (props: { onClick: () => void; disabled: boolean }) => ReactNode;\n}\n\n/**\n * Render prop component for protected actions\n */\nexport function ProtectedAction({\n permission,\n onAction,\n children,\n}: ProtectedActionProps) {\n const hasPermission = usePermission(permission);\n\n return (\n <>\n {children({\n onClick: hasPermission ? onAction : () => {},\n disabled: !hasPermission,\n })}\n </>\n );\n}\n","/**\n * Permission Constants\n */\n\nimport type { PermissionModule } from './types';\n\n/**\n * Available permission modules\n *\n * @deprecated Spine does not own an application's permission taxonomy. Define\n * module constants in the consuming app instead.\n */\nexport const PERMISSION_MODULES: PermissionModule[] = [];\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { i as invalidationHelpers, n as createQueryClient, r as createQueryKeyFactory, t as cachePresets } from "../query-client-_xB300gc.mjs";
2
+ export { cachePresets, createQueryClient, createQueryKeyFactory, invalidationHelpers };