@ghostly-solutions/auth 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -84
- package/dist/{auth-client-CAHMjodm.d.ts → auth-client-Cdkp07ii.d.ts} +14 -6
- package/dist/{auth-sdk-error-DKM7PyKC.d.ts → auth-sdk-error-D3gsfK9d.d.ts} +0 -3
- package/dist/extension.d.ts +16 -0
- package/dist/extension.js +502 -0
- package/dist/extension.js.map +1 -0
- package/dist/index.d.ts +12 -19
- package/dist/index.js +105 -119
- package/dist/index.js.map +1 -1
- package/dist/next.d.ts +4 -27
- package/dist/next.js +125 -383
- package/dist/next.js.map +1 -1
- package/dist/react.d.ts +4 -20
- package/dist/react.js +129 -176
- package/dist/react.js.map +1 -1
- package/docs/api-reference.md +65 -89
- package/docs/architecture.md +28 -46
- package/docs/development-and-ci.md +15 -19
- package/docs/index.md +1 -15
- package/docs/integration-guide.md +46 -81
- package/docs/overview.md +24 -30
- package/package.json +11 -4
- package/react-client.js +3 -0
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/auth-endpoints.ts","../src/constants/http-status.ts","../src/errors/auth-sdk-error.ts","../src/types/auth-error-code.ts","../src/constants/auth-keys.ts","../src/core/object-guards.ts","../src/core/session-parser.ts","../src/core/broadcast-sync.ts","../src/core/callback-url.ts","../src/core/http-client.ts","../src/core/runtime.ts","../src/core/return-to-storage.ts","../src/core/session-store.ts","../src/core/auth-client.ts","../src/adapters/react/auth-callback-handler.tsx","../src/adapters/react/auth-context.tsx","../src/adapters/react/auth-provider.tsx","../src/adapters/react/use-auth.ts","../src/adapters/react/auth-session-gate.tsx"],"names":["useMemo","useState","useEffect","jsx","Fragment"],"mappings":"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","file":"react.js","sourcesContent":["const authApiPrefix = \"/v1/auth\";\n\nexport const authEndpoints = {\n loginStart: `${authApiPrefix}/keycloak/login`,\n validateKeycloakToken: `${authApiPrefix}/keycloak/validate`,\n session: `${authApiPrefix}/me`,\n logout: `${authApiPrefix}/logout`,\n} as const;\n","export const httpStatus = {\n ok: 200,\n found: 302,\n noContent: 204,\n badRequest: 400,\n unauthorized: 401,\n} as const;\n","import type { AuthErrorCode } from \"../types/auth-error-code\";\n\nexport interface AuthSdkErrorPayload {\n code: AuthErrorCode;\n details: unknown;\n message: string;\n status: number | null;\n}\n\nexport class AuthSdkError extends Error {\n readonly code: AuthErrorCode;\n readonly details: unknown;\n readonly status: number | null;\n\n constructor(payload: AuthSdkErrorPayload) {\n super(payload.message);\n this.name = \"AuthSdkError\";\n this.code = payload.code;\n this.details = payload.details;\n this.status = payload.status;\n }\n}\n","export const authErrorCode = {\n callbackMissingToken: \"callback_missing_token\",\n callbackInvalidToken: \"callback_invalid_token\",\n callbackValidationFailed: \"callback_validation_failed\",\n unauthorized: \"unauthorized\",\n networkError: \"network_error\",\n apiError: \"api_error\",\n broadcastChannelUnsupported: \"broadcast_channel_unsupported\",\n serverOriginResolutionFailed: \"server_origin_resolution_failed\",\n} as const;\n\nexport type AuthErrorCode = (typeof authErrorCode)[keyof typeof authErrorCode];\n","export const authQueryKeys = {\n token: \"token\",\n} as const;\n\nexport const authStorageKeys = {\n returnTo: \"ghostly-auth:return-to\",\n} as const;\n\nexport const authBroadcast = {\n channelName: \"ghostly-auth-channel\",\n sessionUpdatedEvent: \"session-updated\",\n} as const;\n\nexport const authRoutes = {\n root: \"/\",\n callback: \"/auth/callback\",\n} as const;\n","export function isObjectRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isStringValue(value: unknown): value is string {\n return typeof value === \"string\";\n}\n","import type { GhostlySession } from \"../types/ghostly-session\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\n\nexport function isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => isStringValue(entry));\n}\n\nexport function isGhostlySession(value: unknown): value is GhostlySession {\n if (!isObjectRecord(value)) {\n return false;\n }\n\n return (\n isStringValue(value.id) &&\n isStringValue(value.username) &&\n (value.firstName === null || isStringValue(value.firstName)) &&\n (value.lastName === null || isStringValue(value.lastName)) &&\n isStringValue(value.email) &&\n isStringValue(value.role) &&\n isStringArray(value.permissions)\n );\n}\n","import { authBroadcast } from \"../constants/auth-keys\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\nimport { isGhostlySession } from \"./session-parser\";\n\ninterface SessionUpdatedMessage {\n session: GhostlySession | null;\n type: typeof authBroadcast.sessionUpdatedEvent;\n}\n\nexport interface BroadcastSync {\n close(): void;\n publishSession(session: GhostlySession | null): void;\n}\n\ninterface CreateBroadcastSyncOptions {\n onSessionUpdated: (session: GhostlySession | null) => void;\n}\n\nfunction isSessionUpdatedMessage(value: unknown): value is SessionUpdatedMessage {\n if (!isObjectRecord(value)) {\n return false;\n }\n\n if (!isStringValue(value.type)) {\n return false;\n }\n\n if (value.type !== authBroadcast.sessionUpdatedEvent) {\n return false;\n }\n\n return value.session === null || isGhostlySession(value.session);\n}\n\nfunction createUnsupportedBroadcastChannelError(): AuthSdkError {\n return new AuthSdkError({\n code: authErrorCode.broadcastChannelUnsupported,\n details: null,\n message: \"BroadcastChannel is unavailable in this runtime.\",\n status: null,\n });\n}\n\nexport function createBroadcastSync(options: CreateBroadcastSyncOptions): BroadcastSync {\n if (typeof BroadcastChannel === \"undefined\") {\n throw createUnsupportedBroadcastChannelError();\n }\n\n const channel = new BroadcastChannel(authBroadcast.channelName);\n\n const onMessage: EventListener = (event) => {\n const messageEvent = event as MessageEvent<unknown>;\n\n if (!isSessionUpdatedMessage(messageEvent.data)) {\n return;\n }\n\n options.onSessionUpdated(messageEvent.data.session);\n };\n\n channel.addEventListener(\"message\", onMessage);\n\n return {\n close() {\n channel.removeEventListener(\"message\", onMessage);\n channel.close();\n },\n publishSession(session) {\n const payload: SessionUpdatedMessage = {\n session,\n type: authBroadcast.sessionUpdatedEvent,\n };\n\n channel.postMessage(payload);\n },\n };\n}\n","import { authQueryKeys } from \"../constants/auth-keys\";\n\nexport function readCallbackToken(url: URL): string | null {\n return url.searchParams.get(authQueryKeys.token);\n}\n\nexport function removeCallbackToken(url: URL): URL {\n const nextUrl = new URL(url.toString());\n nextUrl.searchParams.delete(authQueryKeys.token);\n return nextUrl;\n}\n\nexport function replaceBrowserHistory(url: URL): void {\n window.history.replaceState(null, \"\", url.toString());\n}\n","import { httpStatus } from \"../constants/http-status\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\n\nconst jsonContentType = \"application/json\";\nconst jsonHeaderName = \"content-type\";\nconst includeCredentials: RequestCredentials = \"include\";\nconst noStoreCache: RequestCache = \"no-store\";\n\ninterface RequestOptions<TBody> {\n body?: TBody;\n expectedStatus?: number;\n method: \"GET\" | \"POST\";\n path: string;\n}\n\ninterface ParsedErrorPayload {\n code: string | null;\n details: unknown;\n message: string | null;\n}\n\nfunction toTypedValue<TValue>(value: unknown): TValue {\n return value as TValue;\n}\n\nfunction mapHttpStatusToAuthErrorCode(status: number) {\n if (status === httpStatus.unauthorized) {\n return authErrorCode.unauthorized;\n }\n\n return authErrorCode.apiError;\n}\n\nasync function parseJsonPayload(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nasync function parseErrorPayload(response: Response): Promise<ParsedErrorPayload> {\n const payload = await parseJsonPayload(response);\n\n if (!isObjectRecord(payload)) {\n return {\n code: null,\n details: null,\n message: null,\n };\n }\n\n const maybeCode = payload.code;\n const maybeMessage = payload.message;\n\n return {\n code: isStringValue(maybeCode) ? maybeCode : null,\n details: \"details\" in payload ? payload.details : null,\n message: isStringValue(maybeMessage) ? maybeMessage : null,\n };\n}\n\nfunction buildApiErrorMessage(method: RequestOptions<unknown>[\"method\"], path: string): string {\n return `Auth API request failed: ${method} ${path}`;\n}\n\nfunction buildNetworkErrorMessage(method: RequestOptions<unknown>[\"method\"], path: string): string {\n return `Auth API network failure: ${method} ${path}`;\n}\n\nasync function request<TResponse, TBody = undefined>(\n options: RequestOptions<TBody>,\n): Promise<TResponse> {\n const expectedStatus = options.expectedStatus ?? httpStatus.ok;\n const headers = new Headers();\n const hasBody = typeof options.body !== \"undefined\";\n\n if (hasBody) {\n headers.set(jsonHeaderName, jsonContentType);\n }\n\n const requestInit: RequestInit = {\n cache: noStoreCache,\n credentials: includeCredentials,\n headers,\n method: options.method,\n };\n\n if (hasBody) {\n requestInit.body = JSON.stringify(options.body);\n }\n\n let response: Response;\n\n try {\n response = await fetch(options.path, requestInit);\n } catch (error) {\n throw new AuthSdkError({\n code: authErrorCode.networkError,\n details: error,\n message: buildNetworkErrorMessage(options.method, options.path),\n status: null,\n });\n }\n\n if (response.status !== expectedStatus) {\n const parsed = await parseErrorPayload(response);\n\n throw new AuthSdkError({\n code: mapHttpStatusToAuthErrorCode(response.status),\n details: {\n apiCode: parsed.code,\n apiDetails: parsed.details,\n },\n message: parsed.message ?? buildApiErrorMessage(options.method, options.path),\n status: response.status,\n });\n }\n\n if (response.status === httpStatus.noContent) {\n return toTypedValue<TResponse>(null);\n }\n\n const payload = await parseJsonPayload(response);\n return toTypedValue<TResponse>(payload);\n}\n\nexport function getJson<TResponse>(path: string): Promise<TResponse> {\n return request<TResponse>({\n method: \"GET\",\n path,\n });\n}\n\nexport function postJson<TResponse, TBody>(path: string, body: TBody): Promise<TResponse> {\n return request<TResponse, TBody>({\n body,\n method: \"POST\",\n path,\n });\n}\n\nexport function postEmpty(path: string): Promise<null> {\n return request<null>({\n expectedStatus: httpStatus.noContent,\n method: \"POST\",\n path,\n });\n}\n","import { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\n\nconst browserRuntimeErrorMessage = \"Browser runtime is required for this auth operation.\";\n\nexport function isBrowserRuntime(): boolean {\n return typeof window !== \"undefined\";\n}\n\nexport function assertBrowserRuntime(): void {\n if (isBrowserRuntime()) {\n return;\n }\n\n throw new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: browserRuntimeErrorMessage,\n status: null,\n });\n}\n","import { authRoutes, authStorageKeys } from \"../constants/auth-keys\";\nimport { assertBrowserRuntime } from \"./runtime\";\n\nfunction sanitizeReturnTo(value: string | null | undefined): string {\n if (!value) {\n return authRoutes.root;\n }\n\n if (!value.startsWith(authRoutes.root)) {\n return authRoutes.root;\n }\n\n const protocolRelativePrefix = \"//\";\n\n if (value.startsWith(protocolRelativePrefix)) {\n return authRoutes.root;\n }\n\n return value;\n}\n\nfunction getCurrentBrowserPath(): string {\n return `${window.location.pathname}${window.location.search}${window.location.hash}`;\n}\n\nexport function saveReturnToPath(returnTo: string | undefined): string {\n assertBrowserRuntime();\n\n const fallbackPath = getCurrentBrowserPath();\n const sanitized = sanitizeReturnTo(returnTo ?? fallbackPath);\n window.sessionStorage.setItem(authStorageKeys.returnTo, sanitized);\n return sanitized;\n}\n\nexport function consumeReturnToPath(): string {\n assertBrowserRuntime();\n\n const value = window.sessionStorage.getItem(authStorageKeys.returnTo);\n window.sessionStorage.removeItem(authStorageKeys.returnTo);\n return sanitizeReturnTo(value);\n}\n","import type { SessionListener } from \"../types/auth-client\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\n\ntype SessionResolveState = \"pending\" | \"resolved\";\n\nexport class SessionStore {\n private listeners = new Set<SessionListener>();\n private resolvedSession: GhostlySession | null = null;\n private resolveState: SessionResolveState = \"pending\";\n\n getSessionIfResolved(): GhostlySession | null {\n if (this.resolveState === \"pending\") {\n return null;\n }\n\n return this.resolvedSession;\n }\n\n hasResolvedSession(): boolean {\n return this.resolveState === \"resolved\";\n }\n\n setSession(session: GhostlySession | null): void {\n this.resolveState = \"resolved\";\n this.resolvedSession = session;\n\n for (const listener of this.listeners) {\n listener(session);\n }\n }\n\n subscribe(listener: SessionListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n}\n","import { authEndpoints } from \"../constants/auth-endpoints\";\nimport { httpStatus } from \"../constants/http-status\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport type {\n AuthClient,\n LoginOptions,\n ProcessCallbackResult,\n SessionRequestOptions,\n} from \"../types/auth-client\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\nimport type { BroadcastSync } from \"./broadcast-sync\";\nimport { createBroadcastSync } from \"./broadcast-sync\";\nimport { readCallbackToken, removeCallbackToken, replaceBrowserHistory } from \"./callback-url\";\nimport { getJson, postEmpty, postJson } from \"./http-client\";\nimport { consumeReturnToPath, saveReturnToPath } from \"./return-to-storage\";\nimport { assertBrowserRuntime } from \"./runtime\";\nimport { isGhostlySession } from \"./session-parser\";\nimport { SessionStore } from \"./session-store\";\n\ninterface ValidateTokenRequest {\n token: string;\n}\n\ninterface ValidateTokenResponse {\n session: unknown;\n}\n\nfunction createPendingRedirectPromise<TValue>(): Promise<TValue> {\n return new Promise(() => {\n // Location redirect never resolves within current runtime execution.\n });\n}\n\nfunction createInvalidSessionPayloadError(path: string): AuthSdkError {\n return new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: `Auth API response has invalid session shape: ${path}`,\n status: null,\n });\n}\n\nfunction toValidatedSession(payload: unknown, path: string): GhostlySession {\n if (!isGhostlySession(payload)) {\n throw createInvalidSessionPayloadError(path);\n }\n\n return payload;\n}\n\nfunction toCallbackFailure(error: unknown): AuthSdkError {\n if (error instanceof AuthSdkError) {\n if (error.status === httpStatus.unauthorized) {\n return new AuthSdkError({\n code: authErrorCode.callbackInvalidToken,\n details: error.details,\n message: \"Callback JWT is invalid or expired.\",\n status: error.status,\n });\n }\n\n return new AuthSdkError({\n code: authErrorCode.callbackValidationFailed,\n details: error.details,\n message: \"Keycloak callback validation failed.\",\n status: error.status,\n });\n }\n\n return new AuthSdkError({\n code: authErrorCode.callbackValidationFailed,\n details: error,\n message: \"Keycloak callback validation failed.\",\n status: null,\n });\n}\n\nfunction createNoopBroadcastSync(): BroadcastSync {\n return {\n close() {},\n publishSession() {},\n };\n}\n\nfunction createSafeBroadcastSync(\n onSessionUpdated: (session: GhostlySession | null) => void,\n): BroadcastSync {\n try {\n return createBroadcastSync({\n onSessionUpdated,\n });\n } catch (error) {\n if (error instanceof AuthSdkError && error.code === authErrorCode.broadcastChannelUnsupported) {\n return createNoopBroadcastSync();\n }\n\n throw error;\n }\n}\n\nasync function fetchCurrentSessionFromApi(): Promise<GhostlySession | null> {\n const payload = await getJson<unknown>(authEndpoints.session);\n\n if (payload === null) {\n return null;\n }\n\n return toValidatedSession(payload, authEndpoints.session);\n}\n\nexport function createAuthClient(): AuthClient {\n assertBrowserRuntime();\n\n const sessionStore = new SessionStore();\n const broadcastSync = createSafeBroadcastSync((session) => {\n sessionStore.setSession(session);\n });\n\n const getSession = async (options?: SessionRequestOptions): Promise<GhostlySession | null> => {\n const forceRefresh = options?.forceRefresh ?? false;\n\n if (sessionStore.hasResolvedSession() && !forceRefresh) {\n return sessionStore.getSessionIfResolved();\n }\n\n const session = await fetchCurrentSessionFromApi();\n sessionStore.setSession(session);\n broadcastSync.publishSession(session);\n\n return session;\n };\n\n const requireSession = async (): Promise<GhostlySession> => {\n const session = await getSession();\n\n if (session) {\n return session;\n }\n\n throw new AuthSdkError({\n code: authErrorCode.unauthorized,\n details: null,\n message: \"Authenticated session is required.\",\n status: httpStatus.unauthorized,\n });\n };\n\n const login = (options?: LoginOptions): void => {\n saveReturnToPath(options?.returnTo);\n window.location.assign(authEndpoints.loginStart);\n };\n\n const processCallback = async (): Promise<ProcessCallbackResult> => {\n const currentUrl = new URL(window.location.href);\n const token = readCallbackToken(currentUrl);\n\n if (!token) {\n throw new AuthSdkError({\n code: authErrorCode.callbackMissingToken,\n details: null,\n message: \"Missing callback token query parameter.\",\n status: httpStatus.badRequest,\n });\n }\n\n const cleanedUrl = removeCallbackToken(currentUrl);\n replaceBrowserHistory(cleanedUrl);\n\n try {\n const payload = await postJson<ValidateTokenResponse, ValidateTokenRequest>(\n authEndpoints.validateKeycloakToken,\n { token },\n );\n\n const session = toValidatedSession(payload.session, authEndpoints.validateKeycloakToken);\n sessionStore.setSession(session);\n broadcastSync.publishSession(session);\n\n return {\n redirectTo: consumeReturnToPath(),\n session,\n };\n } catch (error) {\n throw toCallbackFailure(error);\n }\n };\n\n const completeCallbackRedirect = async (): Promise<never> => {\n const result = await processCallback();\n window.location.replace(result.redirectTo);\n return createPendingRedirectPromise<never>();\n };\n\n const logout = async (): Promise<void> => {\n await postEmpty(authEndpoints.logout);\n sessionStore.setSession(null);\n broadcastSync.publishSession(null);\n };\n\n const subscribe = sessionStore.subscribe.bind(sessionStore);\n\n return {\n completeCallbackRedirect,\n getSession,\n login,\n logout,\n processCallback,\n requireSession,\n subscribe,\n };\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { createAuthClient } from \"../../core/auth-client\";\nimport { AuthSdkError } from \"../../errors/auth-sdk-error\";\nimport type { AuthClient } from \"../../types/auth-client\";\n\nexport type AuthCallbackStatus = \"processing\" | \"failed\";\n\nexport interface UseAuthCallbackRedirectOptions {\n client?: AuthClient;\n}\n\nexport interface UseAuthCallbackRedirectResult {\n error: AuthSdkError | null;\n status: AuthCallbackStatus;\n}\n\nfunction normalizeAuthError(error: unknown): AuthSdkError {\n if (error instanceof AuthSdkError) {\n return error;\n }\n\n return new AuthSdkError({\n code: \"callback_validation_failed\",\n details: error,\n message: \"Auth callback redirect failed.\",\n status: null,\n });\n}\n\nexport function useAuthCallbackRedirect(\n options: UseAuthCallbackRedirectOptions = {},\n): UseAuthCallbackRedirectResult {\n const client = useMemo(() => options.client ?? createAuthClient(), [options.client]);\n const [error, setError] = useState<AuthSdkError | null>(null);\n\n useEffect(() => {\n let isActive = true;\n\n void client.completeCallbackRedirect().catch((caughtError) => {\n if (!isActive) {\n return;\n }\n\n setError(normalizeAuthError(caughtError));\n });\n\n return () => {\n isActive = false;\n };\n }, [client]);\n\n if (error) {\n return {\n error,\n status: \"failed\",\n };\n }\n\n return {\n error: null,\n status: \"processing\",\n };\n}\n\nexport interface AuthCallbackHandlerProps {\n client?: AuthClient;\n processing: ReactNode;\n renderError: (error: AuthSdkError) => ReactNode;\n}\n\nexport function AuthCallbackHandler(props: AuthCallbackHandlerProps) {\n const state = useAuthCallbackRedirect({\n client: props.client,\n });\n\n if (state.status === \"failed\" && state.error) {\n return props.renderError(state.error);\n }\n\n return <>{props.processing}</>;\n}\n","\"use client\";\n\nimport { createContext } from \"react\";\nimport type { AuthSdkError } from \"../../errors/auth-sdk-error\";\nimport type { LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\n\nexport interface AuthContextValue {\n error: AuthSdkError | null;\n isLoading: boolean;\n login: (options?: LoginOptions) => void;\n logout: () => Promise<void>;\n refresh: () => Promise<GhostlySession | null>;\n session: GhostlySession | null;\n}\n\nexport const AuthContext = createContext<AuthContextValue | null>(null);\n","\"use client\";\n\nimport { type ReactNode, useCallback, useEffect, useMemo, useState } from \"react\";\nimport { createAuthClient } from \"../../core/auth-client\";\nimport { AuthSdkError } from \"../../errors/auth-sdk-error\";\nimport type { AuthClient, LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\nimport { AuthContext } from \"./auth-context\";\n\nconst initialLoadingState = true;\n\nfunction toAuthError(error: unknown): AuthSdkError {\n if (error instanceof AuthSdkError) {\n return error;\n }\n\n return new AuthSdkError({\n code: \"api_error\",\n details: error,\n message: \"Unexpected auth adapter error.\",\n status: null,\n });\n}\n\nfunction createDeferredAuthClient(): AuthClient {\n let authClient: AuthClient | null = null;\n\n const resolveClient = (): AuthClient => {\n authClient ??= createAuthClient();\n return authClient;\n };\n\n return {\n completeCallbackRedirect() {\n return resolveClient().completeCallbackRedirect();\n },\n getSession(options) {\n return resolveClient().getSession(options);\n },\n login(options?: LoginOptions) {\n resolveClient().login(options);\n },\n logout() {\n return resolveClient().logout();\n },\n processCallback() {\n return resolveClient().processCallback();\n },\n requireSession() {\n return resolveClient().requireSession();\n },\n subscribe(listener) {\n if (typeof window === \"undefined\") {\n return () => {};\n }\n\n return resolveClient().subscribe(listener);\n },\n };\n}\n\nexport interface AuthProviderProps {\n children: ReactNode;\n client?: AuthClient;\n}\n\nexport function AuthProvider(props: AuthProviderProps) {\n const authClient = useMemo(() => props.client ?? createDeferredAuthClient(), [props.client]);\n const [session, setSession] = useState<GhostlySession | null>(null);\n const [error, setError] = useState<AuthSdkError | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(initialLoadingState);\n\n useEffect(() => {\n let isActive = true;\n\n const unsubscribe = authClient.subscribe((nextSession) => {\n if (!isActive) {\n return;\n }\n\n setSession(nextSession);\n setIsLoading(false);\n });\n\n void authClient\n .getSession()\n .then((nextSession) => {\n if (!isActive) {\n return;\n }\n\n setSession(nextSession);\n })\n .catch((caughtError: unknown) => {\n if (!isActive) {\n return;\n }\n\n setError(toAuthError(caughtError));\n })\n .finally(() => {\n if (!isActive) {\n return;\n }\n\n setIsLoading(false);\n });\n\n return () => {\n isActive = false;\n unsubscribe();\n };\n }, [authClient]);\n\n const login = useCallback(\n (options?: LoginOptions) => {\n setError(null);\n authClient.login(options);\n },\n [authClient],\n );\n\n const logout = useCallback(async () => {\n setError(null);\n\n try {\n await authClient.logout();\n setSession(null);\n } catch (caughtError) {\n const normalizedError = toAuthError(caughtError);\n setError(normalizedError);\n throw normalizedError;\n }\n }, [authClient]);\n\n const refresh = useCallback(async () => {\n setError(null);\n\n try {\n const nextSession = await authClient.getSession({ forceRefresh: true });\n setSession(nextSession);\n return nextSession;\n } catch (caughtError) {\n const normalizedError = toAuthError(caughtError);\n setError(normalizedError);\n throw normalizedError;\n }\n }, [authClient]);\n\n const contextValue = useMemo(\n () => ({\n error,\n isLoading,\n login,\n logout,\n refresh,\n session,\n }),\n [error, isLoading, login, logout, refresh, session],\n );\n\n return <AuthContext.Provider value={contextValue}>{props.children}</AuthContext.Provider>;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { AuthContext } from \"./auth-context\";\n\nconst missingProviderErrorMessage = \"useAuth must be used inside AuthProvider.\";\n\nexport function useAuth() {\n const context = useContext(AuthContext);\n\n if (context) {\n return context;\n }\n\n throw new Error(missingProviderErrorMessage);\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\nimport { useAuth } from \"./use-auth\";\n\ninterface UnauthorizedRenderProps {\n login: (options?: LoginOptions) => void;\n}\n\nexport interface AuthSessionGateProps {\n authorized: (session: GhostlySession) => ReactNode;\n loading?: ReactNode;\n unauthorized: ReactNode | ((props: UnauthorizedRenderProps) => ReactNode);\n}\n\nfunction resolveUnauthorizedContent(\n input: AuthSessionGateProps[\"unauthorized\"],\n props: UnauthorizedRenderProps,\n): ReactNode {\n if (typeof input === \"function\") {\n return input(props);\n }\n\n return input;\n}\n\nexport function AuthSessionGate(props: AuthSessionGateProps) {\n const auth = useAuth();\n\n if (auth.isLoading) {\n return <>{props.loading ?? null}</>;\n }\n\n if (!auth.session) {\n return (\n <>\n {resolveUnauthorizedContent(props.unauthorized, {\n login: auth.login,\n })}\n </>\n );\n }\n\n return <>{props.authorized(auth.session)}</>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/auth-endpoints.ts","../src/constants/http-status.ts","../src/errors/auth-sdk-error.ts","../src/types/auth-error-code.ts","../src/core/api-origin.ts","../src/constants/auth-keys.ts","../src/core/object-guards.ts","../src/core/session-parser.ts","../src/core/broadcast-sync.ts","../src/core/http-client.ts","../src/core/runtime.ts","../src/core/return-to-storage.ts","../src/core/session-store.ts","../src/core/auth-client.ts","../src/adapters/react/auth-context.tsx","../src/adapters/react/auth-provider.tsx","../src/adapters/react/use-auth.ts","../src/adapters/react/auth-session-gate.tsx"],"names":["jsx"],"mappings":"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","file":"react.js","sourcesContent":["const authApiPrefix = \"/oauth\";\n\nexport const authEndpoints = {\n authorize: `${authApiPrefix}/authorize`,\n providerCallback: `${authApiPrefix}/callback/provider`,\n session: `${authApiPrefix}/session`,\n refresh: `${authApiPrefix}/refresh`,\n logout: `${authApiPrefix}/logout`,\n} as const;\n","export const httpStatus = {\n ok: 200,\n found: 302,\n noContent: 204,\n badRequest: 400,\n unauthorized: 401,\n} as const;\n","import type { AuthErrorCode } from \"../types/auth-error-code\";\n\nexport interface AuthSdkErrorPayload {\n code: AuthErrorCode;\n details: unknown;\n message: string;\n status: number | null;\n}\n\nexport class AuthSdkError extends Error {\n readonly code: AuthErrorCode;\n readonly details: unknown;\n readonly status: number | null;\n\n constructor(payload: AuthSdkErrorPayload) {\n super(payload.message);\n this.name = \"AuthSdkError\";\n this.code = payload.code;\n this.details = payload.details;\n this.status = payload.status;\n }\n}\n","export const authErrorCode = {\n unauthorized: \"unauthorized\",\n networkError: \"network_error\",\n apiError: \"api_error\",\n broadcastChannelUnsupported: \"broadcast_channel_unsupported\",\n serverOriginResolutionFailed: \"server_origin_resolution_failed\",\n} as const;\n\nexport type AuthErrorCode = (typeof authErrorCode)[keyof typeof authErrorCode];\n","import { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\n\nconst slash = \"/\";\n\nfunction normalizeApiOrigin(apiOrigin: string): string {\n const trimmed = apiOrigin.trim();\n\n if (!trimmed) {\n throw new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: \"Auth API origin must be a non-empty absolute URL.\",\n status: null,\n });\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(trimmed);\n } catch (error) {\n throw new AuthSdkError({\n code: authErrorCode.apiError,\n details: error,\n message: \"Auth API origin must be a valid absolute URL.\",\n status: null,\n });\n }\n\n if (parsed.pathname !== slash || parsed.search || parsed.hash) {\n throw new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: \"Auth API origin must not include path, query, or hash.\",\n status: null,\n });\n }\n\n return parsed.origin;\n}\n\nexport function resolveApiEndpoint(path: string, apiOrigin?: string): string {\n if (!apiOrigin) {\n return path;\n }\n\n return `${normalizeApiOrigin(apiOrigin)}${path}`;\n}\n","export const authBroadcast = {\n channelName: \"ghostly-auth-channel\",\n sessionUpdatedEvent: \"session-updated\",\n} as const;\n\nexport const authRoutes = {\n root: \"/\",\n} as const;\n","export function isObjectRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isStringValue(value: unknown): value is string {\n return typeof value === \"string\";\n}\n","import type { GhostlySession } from \"../types/ghostly-session\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\n\nexport function isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => isStringValue(entry));\n}\n\nexport function isGhostlySession(value: unknown): value is GhostlySession {\n if (!isObjectRecord(value)) {\n return false;\n }\n\n return (\n isStringValue(value.id) &&\n isStringValue(value.username) &&\n (value.firstName === null || isStringValue(value.firstName)) &&\n (value.lastName === null || isStringValue(value.lastName)) &&\n isStringValue(value.email) &&\n isStringValue(value.role) &&\n isStringArray(value.permissions)\n );\n}\n","import { authBroadcast } from \"../constants/auth-keys\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\nimport { isGhostlySession } from \"./session-parser\";\n\ninterface SessionUpdatedMessage {\n session: GhostlySession | null;\n type: typeof authBroadcast.sessionUpdatedEvent;\n}\n\nexport interface BroadcastSync {\n close(): void;\n publishSession(session: GhostlySession | null): void;\n}\n\ninterface CreateBroadcastSyncOptions {\n onSessionUpdated: (session: GhostlySession | null) => void;\n}\n\nfunction isSessionUpdatedMessage(value: unknown): value is SessionUpdatedMessage {\n if (!isObjectRecord(value)) {\n return false;\n }\n\n if (!isStringValue(value.type)) {\n return false;\n }\n\n if (value.type !== authBroadcast.sessionUpdatedEvent) {\n return false;\n }\n\n return value.session === null || isGhostlySession(value.session);\n}\n\nfunction createUnsupportedBroadcastChannelError(): AuthSdkError {\n return new AuthSdkError({\n code: authErrorCode.broadcastChannelUnsupported,\n details: null,\n message: \"BroadcastChannel is unavailable in this runtime.\",\n status: null,\n });\n}\n\nexport function createBroadcastSync(options: CreateBroadcastSyncOptions): BroadcastSync {\n if (typeof BroadcastChannel === \"undefined\") {\n throw createUnsupportedBroadcastChannelError();\n }\n\n const channel = new BroadcastChannel(authBroadcast.channelName);\n\n const onMessage: EventListener = (event) => {\n const messageEvent = event as MessageEvent<unknown>;\n\n if (!isSessionUpdatedMessage(messageEvent.data)) {\n return;\n }\n\n options.onSessionUpdated(messageEvent.data.session);\n };\n\n channel.addEventListener(\"message\", onMessage);\n\n return {\n close() {\n channel.removeEventListener(\"message\", onMessage);\n channel.close();\n },\n publishSession(session) {\n const payload: SessionUpdatedMessage = {\n session,\n type: authBroadcast.sessionUpdatedEvent,\n };\n\n channel.postMessage(payload);\n },\n };\n}\n","import { httpStatus } from \"../constants/http-status\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport { isObjectRecord, isStringValue } from \"./object-guards\";\n\nconst jsonContentType = \"application/json\";\nconst jsonHeaderName = \"content-type\";\nconst includeCredentials: RequestCredentials = \"include\";\nconst noStoreCache: RequestCache = \"no-store\";\n\ninterface RequestOptions<TBody> {\n body?: TBody;\n expectedStatus?: number;\n method: \"GET\" | \"POST\";\n path: string;\n}\n\ninterface ParsedErrorPayload {\n code: string | null;\n details: unknown;\n message: string | null;\n}\n\nfunction toTypedValue<TValue>(value: unknown): TValue {\n return value as TValue;\n}\n\nfunction mapHttpStatusToAuthErrorCode(status: number) {\n if (status === httpStatus.unauthorized) {\n return authErrorCode.unauthorized;\n }\n\n return authErrorCode.apiError;\n}\n\nasync function parseJsonPayload(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nasync function parseErrorPayload(response: Response): Promise<ParsedErrorPayload> {\n const payload = await parseJsonPayload(response);\n\n if (!isObjectRecord(payload)) {\n return {\n code: null,\n details: null,\n message: null,\n };\n }\n\n const maybeCode = payload.code;\n const maybeMessage = payload.message;\n\n return {\n code: isStringValue(maybeCode) ? maybeCode : null,\n details: \"details\" in payload ? payload.details : null,\n message: isStringValue(maybeMessage) ? maybeMessage : null,\n };\n}\n\nfunction buildApiErrorMessage(method: RequestOptions<unknown>[\"method\"], path: string): string {\n return `Auth API request failed: ${method} ${path}`;\n}\n\nfunction buildNetworkErrorMessage(method: RequestOptions<unknown>[\"method\"], path: string): string {\n return `Auth API network failure: ${method} ${path}`;\n}\n\nasync function request<TResponse, TBody = undefined>(\n options: RequestOptions<TBody>,\n): Promise<TResponse> {\n const expectedStatus = options.expectedStatus ?? httpStatus.ok;\n const headers = new Headers();\n const hasBody = typeof options.body !== \"undefined\";\n\n if (hasBody) {\n headers.set(jsonHeaderName, jsonContentType);\n }\n\n const requestInit: RequestInit = {\n cache: noStoreCache,\n credentials: includeCredentials,\n headers,\n method: options.method,\n };\n\n if (hasBody) {\n requestInit.body = JSON.stringify(options.body);\n }\n\n let response: Response;\n\n try {\n response = await fetch(options.path, requestInit);\n } catch (error) {\n throw new AuthSdkError({\n code: authErrorCode.networkError,\n details: error,\n message: buildNetworkErrorMessage(options.method, options.path),\n status: null,\n });\n }\n\n if (response.status !== expectedStatus) {\n const parsed = await parseErrorPayload(response);\n\n throw new AuthSdkError({\n code: mapHttpStatusToAuthErrorCode(response.status),\n details: {\n apiCode: parsed.code,\n apiDetails: parsed.details,\n },\n message: parsed.message ?? buildApiErrorMessage(options.method, options.path),\n status: response.status,\n });\n }\n\n if (response.status === httpStatus.noContent) {\n return toTypedValue<TResponse>(null);\n }\n\n const payload = await parseJsonPayload(response);\n return toTypedValue<TResponse>(payload);\n}\n\nexport function getJson<TResponse>(path: string): Promise<TResponse> {\n return request<TResponse>({\n method: \"GET\",\n path,\n });\n}\n\nexport function postJson<TResponse, TBody>(path: string, body: TBody): Promise<TResponse> {\n return request<TResponse, TBody>({\n body,\n method: \"POST\",\n path,\n });\n}\n\nexport function postJsonWithoutBody<TResponse>(path: string): Promise<TResponse> {\n return request<TResponse>({\n method: \"POST\",\n path,\n });\n}\n\nexport function postEmpty(path: string): Promise<null> {\n return request<null>({\n expectedStatus: httpStatus.noContent,\n method: \"POST\",\n path,\n });\n}\n","import { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport { authErrorCode } from \"../types/auth-error-code\";\n\nconst browserRuntimeErrorMessage = \"Browser runtime is required for this auth operation.\";\n\nexport function isBrowserRuntime(): boolean {\n return typeof window !== \"undefined\";\n}\n\nexport function assertBrowserRuntime(): void {\n if (isBrowserRuntime()) {\n return;\n }\n\n throw new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: browserRuntimeErrorMessage,\n status: null,\n });\n}\n","import { authRoutes } from \"../constants/auth-keys\";\nimport { assertBrowserRuntime } from \"./runtime\";\n\nfunction sanitizeReturnTo(value: string | null | undefined): string {\n if (!value) {\n return authRoutes.root;\n }\n\n if (!value.startsWith(authRoutes.root)) {\n return authRoutes.root;\n }\n\n const protocolRelativePrefix = \"//\";\n\n if (value.startsWith(protocolRelativePrefix)) {\n return authRoutes.root;\n }\n\n return value;\n}\n\nfunction getCurrentBrowserPath(): string {\n return `${window.location.pathname}${window.location.search}${window.location.hash}`;\n}\n\nexport function resolveReturnToPath(returnTo: string | undefined): string {\n assertBrowserRuntime();\n\n const fallbackPath = getCurrentBrowserPath();\n return sanitizeReturnTo(returnTo ?? fallbackPath);\n}\n","import type { SessionListener } from \"../types/auth-client\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\n\ntype SessionResolveState = \"pending\" | \"resolved\";\n\nexport class SessionStore {\n private listeners = new Set<SessionListener>();\n private resolvedSession: GhostlySession | null = null;\n private resolveState: SessionResolveState = \"pending\";\n\n getSessionIfResolved(): GhostlySession | null {\n if (this.resolveState === \"pending\") {\n return null;\n }\n\n return this.resolvedSession;\n }\n\n hasResolvedSession(): boolean {\n return this.resolveState === \"resolved\";\n }\n\n setSession(session: GhostlySession | null): void {\n this.resolveState = \"resolved\";\n this.resolvedSession = session;\n\n for (const listener of this.listeners) {\n listener(session);\n }\n }\n\n subscribe(listener: SessionListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n}\n","import { authEndpoints } from \"../constants/auth-endpoints\";\nimport { httpStatus } from \"../constants/http-status\";\nimport { AuthSdkError } from \"../errors/auth-sdk-error\";\nimport type {\n AuthClient,\n AuthClientOptions,\n AuthInitOptions,\n AuthInitResult,\n LoginOptions,\n SessionRequestOptions,\n} from \"../types/auth-client\";\nimport { authErrorCode } from \"../types/auth-error-code\";\nimport type { GhostlySession } from \"../types/ghostly-session\";\nimport { resolveApiEndpoint } from \"./api-origin\";\nimport type { BroadcastSync } from \"./broadcast-sync\";\nimport { createBroadcastSync } from \"./broadcast-sync\";\nimport { getJson, postEmpty, postJsonWithoutBody } from \"./http-client\";\nimport { resolveReturnToPath } from \"./return-to-storage\";\nimport { isGhostlySession } from \"./session-parser\";\nimport { SessionStore } from \"./session-store\";\n\nfunction createInvalidSessionPayloadError(path: string): AuthSdkError {\n return new AuthSdkError({\n code: authErrorCode.apiError,\n details: null,\n message: `Auth API response has invalid session shape: ${path}`,\n status: null,\n });\n}\n\nfunction toValidatedSession(payload: unknown, path: string): GhostlySession {\n if (!isGhostlySession(payload)) {\n throw createInvalidSessionPayloadError(path);\n }\n\n return payload;\n}\n\nfunction toSessionPayload(payload: unknown, path: string): GhostlySession | null {\n if (payload === null) {\n return null;\n }\n\n return toValidatedSession(payload, path);\n}\n\nfunction createNoopBroadcastSync(): BroadcastSync {\n return {\n close() {},\n publishSession() {},\n };\n}\n\nfunction createSafeBroadcastSync(\n onSessionUpdated: (session: GhostlySession | null) => void,\n): BroadcastSync {\n try {\n return createBroadcastSync({\n onSessionUpdated,\n });\n } catch (error) {\n if (error instanceof AuthSdkError && error.code === authErrorCode.broadcastChannelUnsupported) {\n return createNoopBroadcastSync();\n }\n\n throw error;\n }\n}\n\nfunction toInitResult(session: GhostlySession | null): AuthInitResult {\n return {\n session,\n status: session ? \"authenticated\" : \"unauthenticated\",\n };\n}\n\nexport function createAuthClient(options: AuthClientOptions = {}): AuthClient {\n let initPromise: Promise<AuthInitResult> | null = null;\n const defaultApplication = options.application?.trim() || \"\";\n\n const sessionStore = new SessionStore();\n const broadcastSync = createSafeBroadcastSync((session) => {\n sessionStore.setSession(session);\n });\n\n const resolveEndpoint = (path: string): string => resolveApiEndpoint(path, options.apiOrigin);\n\n const loadSession = async (): Promise<GhostlySession | null> => {\n const payload = await getJson<unknown>(resolveEndpoint(authEndpoints.session));\n return toSessionPayload(payload, authEndpoints.session);\n };\n\n const init = async (initOptions?: AuthInitOptions): Promise<AuthInitResult> => {\n const forceRefresh = initOptions?.forceRefresh ?? false;\n\n if (sessionStore.hasResolvedSession() && !forceRefresh) {\n return toInitResult(sessionStore.getSessionIfResolved());\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n const session = await loadSession();\n sessionStore.setSession(session);\n broadcastSync.publishSession(session);\n return toInitResult(session);\n })();\n\n try {\n return await initPromise;\n } finally {\n initPromise = null;\n }\n };\n\n const getSession = async (\n requestOptions?: SessionRequestOptions,\n ): Promise<GhostlySession | null> => {\n const result = await init({\n forceRefresh: requestOptions?.forceRefresh ?? false,\n });\n\n return result.session;\n };\n\n const refresh = async (): Promise<GhostlySession | null> => {\n const payload = await postJsonWithoutBody<unknown>(resolveEndpoint(authEndpoints.refresh));\n const session = toSessionPayload(payload, authEndpoints.refresh);\n sessionStore.setSession(session);\n broadcastSync.publishSession(session);\n return session;\n };\n\n const requireSession = async (): Promise<GhostlySession> => {\n const session = await getSession();\n\n if (session) {\n return session;\n }\n\n throw new AuthSdkError({\n code: authErrorCode.unauthorized,\n details: null,\n message: \"Authenticated session is required.\",\n status: httpStatus.unauthorized,\n });\n };\n\n const login = (loginOptions?: LoginOptions): void => {\n const returnTo = resolveReturnToPath(loginOptions?.returnTo);\n const authorizeUrl = new URL(resolveEndpoint(authEndpoints.authorize), window.location.origin);\n authorizeUrl.searchParams.set(\"return_to\", returnTo);\n const application = loginOptions?.application?.trim() || defaultApplication;\n if (application) {\n authorizeUrl.searchParams.set(\"app\", application);\n }\n window.location.assign(authorizeUrl.toString());\n };\n\n const logout = async (): Promise<void> => {\n await postEmpty(resolveEndpoint(authEndpoints.logout));\n sessionStore.setSession(null);\n broadcastSync.publishSession(null);\n };\n\n const subscribe = sessionStore.subscribe.bind(sessionStore);\n\n return {\n init,\n getSession,\n login,\n logout,\n refresh,\n requireSession,\n subscribe,\n };\n}\n","\"use client\";\n\nimport { createContext } from \"react\";\nimport type { AuthSdkError } from \"../../errors/auth-sdk-error\";\nimport type { LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\n\nexport interface AuthContextValue {\n error: AuthSdkError | null;\n isLoading: boolean;\n login: (options?: LoginOptions) => void;\n logout: () => Promise<void>;\n refresh: () => Promise<GhostlySession | null>;\n session: GhostlySession | null;\n}\n\nexport const AuthContext = createContext<AuthContextValue | null>(null);\n","\"use client\";\n\nimport { type ReactNode, useCallback, useEffect, useMemo, useState } from \"react\";\nimport { createAuthClient } from \"../../core/auth-client\";\nimport { AuthSdkError } from \"../../errors/auth-sdk-error\";\nimport type { AuthClient, LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\nimport { AuthContext } from \"./auth-context\";\n\nconst initialLoadingState = true;\n\nfunction toAuthError(error: unknown): AuthSdkError {\n if (error instanceof AuthSdkError) {\n return error;\n }\n\n return new AuthSdkError({\n code: \"api_error\",\n details: error,\n message: \"Unexpected auth adapter error.\",\n status: null,\n });\n}\n\nfunction createDeferredAuthClient(): AuthClient {\n let authClient: AuthClient | null = null;\n\n const resolveClient = (): AuthClient => {\n authClient ??= createAuthClient();\n return authClient;\n };\n\n return {\n init(options) {\n return resolveClient().init(options);\n },\n getSession(options) {\n return resolveClient().getSession(options);\n },\n login(options?: LoginOptions) {\n resolveClient().login(options);\n },\n logout() {\n return resolveClient().logout();\n },\n refresh() {\n return resolveClient().refresh();\n },\n requireSession() {\n return resolveClient().requireSession();\n },\n subscribe(listener) {\n if (typeof window === \"undefined\") {\n return () => {};\n }\n\n return resolveClient().subscribe(listener);\n },\n };\n}\n\nexport interface AuthProviderProps {\n children: ReactNode;\n client?: AuthClient;\n initialSession?: GhostlySession | null;\n}\n\nexport function AuthProvider(props: AuthProviderProps) {\n const authClient = useMemo(() => props.client ?? createDeferredAuthClient(), [props.client]);\n const [session, setSession] = useState<GhostlySession | null>(props.initialSession ?? null);\n const [error, setError] = useState<AuthSdkError | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(\n props.initialSession === undefined ? initialLoadingState : false,\n );\n\n useEffect(() => {\n let isActive = true;\n const requiresBootstrap = props.initialSession === undefined;\n\n if (!requiresBootstrap) {\n setSession(props.initialSession ?? null);\n setIsLoading(false);\n }\n\n const unsubscribe = authClient.subscribe((nextSession) => {\n if (!isActive) {\n return;\n }\n\n setSession(nextSession);\n });\n\n if (!requiresBootstrap) {\n return () => {\n isActive = false;\n unsubscribe();\n };\n }\n\n void authClient\n .init()\n .then((result) => {\n if (!isActive) {\n return;\n }\n\n setSession(result.session);\n })\n .catch((caughtError: unknown) => {\n if (!isActive) {\n return;\n }\n\n setError(toAuthError(caughtError));\n })\n .finally(() => {\n if (!isActive) {\n return;\n }\n\n setIsLoading(false);\n });\n\n return () => {\n isActive = false;\n unsubscribe();\n };\n }, [authClient, props.initialSession]);\n\n const login = useCallback(\n (options?: LoginOptions) => {\n setError(null);\n authClient.login(options);\n },\n [authClient],\n );\n\n const logout = useCallback(async () => {\n setError(null);\n\n try {\n await authClient.logout();\n setSession(null);\n } catch (caughtError) {\n const normalizedError = toAuthError(caughtError);\n setError(normalizedError);\n throw normalizedError;\n }\n }, [authClient]);\n\n const refresh = useCallback(async () => {\n setError(null);\n\n try {\n const nextSession = await authClient.refresh();\n setSession(nextSession);\n return nextSession;\n } catch (caughtError) {\n const normalizedError = toAuthError(caughtError);\n setError(normalizedError);\n throw normalizedError;\n }\n }, [authClient]);\n\n const contextValue = useMemo(\n () => ({\n error,\n isLoading,\n login,\n logout,\n refresh,\n session,\n }),\n [error, isLoading, login, logout, refresh, session],\n );\n\n return <AuthContext.Provider value={contextValue}>{props.children}</AuthContext.Provider>;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { AuthContext } from \"./auth-context\";\n\nconst missingProviderErrorMessage = \"useAuth must be used inside AuthProvider.\";\n\nexport function useAuth() {\n const context = useContext(AuthContext);\n\n if (context) {\n return context;\n }\n\n throw new Error(missingProviderErrorMessage);\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { LoginOptions } from \"../../types/auth-client\";\nimport type { GhostlySession } from \"../../types/ghostly-session\";\nimport { useAuth } from \"./use-auth\";\n\ninterface UnauthorizedRenderProps {\n login: (options?: LoginOptions) => void;\n}\n\nexport interface AuthSessionGateProps {\n authorized: (session: GhostlySession) => ReactNode;\n loading?: ReactNode;\n unauthorized: ReactNode | ((props: UnauthorizedRenderProps) => ReactNode);\n}\n\nfunction resolveUnauthorizedContent(\n input: AuthSessionGateProps[\"unauthorized\"],\n props: UnauthorizedRenderProps,\n): ReactNode {\n if (typeof input === \"function\") {\n return input(props);\n }\n\n return input;\n}\n\nexport function AuthSessionGate(props: AuthSessionGateProps) {\n const auth = useAuth();\n\n if (auth.isLoading) {\n return <>{props.loading ?? null}</>;\n }\n\n if (!auth.session) {\n return (\n <>\n {resolveUnauthorizedContent(props.unauthorized, {\n login: auth.login,\n })}\n </>\n );\n }\n\n return <>{props.authorized(auth.session)}</>;\n}\n"]}
|
package/docs/api-reference.md
CHANGED
|
@@ -15,131 +15,107 @@ export interface GhostlySession {
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
-
export interface
|
|
19
|
-
|
|
18
|
+
export interface AuthClientOptions {
|
|
19
|
+
apiOrigin?: string;
|
|
20
|
+
application?: string;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export interface
|
|
23
|
-
|
|
23
|
+
export interface AuthInitOptions {
|
|
24
|
+
forceRefresh?: boolean;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
export interface
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
details: unknown;
|
|
27
|
+
export interface AuthInitResult {
|
|
28
|
+
session: GhostlySession | null;
|
|
29
|
+
status: "authenticated" | "unauthenticated";
|
|
30
30
|
}
|
|
31
|
-
```
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
callbackInvalidToken: "callback_invalid_token",
|
|
37
|
-
callbackValidationFailed: "callback_validation_failed",
|
|
38
|
-
unauthorized: "unauthorized",
|
|
39
|
-
networkError: "network_error",
|
|
40
|
-
apiError: "api_error",
|
|
41
|
-
broadcastChannelUnsupported: "broadcast_channel_unsupported",
|
|
42
|
-
serverOriginResolutionFailed: "server_origin_resolution_failed",
|
|
43
|
-
} as const;
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
export class AuthSdkError extends Error {
|
|
48
|
-
readonly code: AuthErrorCode;
|
|
49
|
-
readonly status: number | null;
|
|
50
|
-
readonly details: unknown;
|
|
32
|
+
export interface LoginOptions {
|
|
33
|
+
returnTo?: string;
|
|
34
|
+
application?: string;
|
|
51
35
|
}
|
|
52
36
|
```
|
|
53
37
|
|
|
54
|
-
## Core Client
|
|
55
|
-
|
|
56
38
|
```ts
|
|
57
39
|
export interface AuthClient {
|
|
58
|
-
|
|
59
|
-
processCallback(): Promise<{ session: GhostlySession; redirectTo: string }>;
|
|
60
|
-
completeCallbackRedirect(): Promise<never>;
|
|
40
|
+
init(options?: AuthInitOptions): Promise<AuthInitResult>;
|
|
61
41
|
getSession(options?: { forceRefresh?: boolean }): Promise<GhostlySession | null>;
|
|
62
|
-
|
|
42
|
+
login(options?: LoginOptions): void;
|
|
43
|
+
refresh(): Promise<GhostlySession | null>;
|
|
63
44
|
logout(): Promise<void>;
|
|
45
|
+
requireSession(): Promise<GhostlySession>;
|
|
64
46
|
subscribe(listener: (session: GhostlySession | null) => void): () => void;
|
|
65
47
|
}
|
|
66
48
|
```
|
|
67
49
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Creates a browser runtime client. Throws `AuthSdkError` when browser requirements are not met.
|
|
71
|
-
|
|
72
|
-
### `login(options?)`
|
|
73
|
-
|
|
74
|
-
- Stores `returnTo` in `sessionStorage`.
|
|
75
|
-
- Redirects to `GET /v1/auth/keycloak/login`.
|
|
76
|
-
|
|
77
|
-
### `processCallback()`
|
|
50
|
+
## Core Entry (`@ghostly-solutions/auth`)
|
|
78
51
|
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
52
|
+
- `createAuthClient(options?)`
|
|
53
|
+
- `authEndpoints`
|
|
54
|
+
- `authRoutes`
|
|
55
|
+
- `authErrorCode`
|
|
56
|
+
- `AuthSdkError`
|
|
83
57
|
|
|
84
|
-
|
|
58
|
+
`createAuthClient()` must run in browser runtime.
|
|
85
59
|
|
|
86
|
-
|
|
60
|
+
## React Entry (`@ghostly-solutions/auth/react`)
|
|
87
61
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
- With `forceRefresh: true`: re-fetches `GET /v1/auth/me`.
|
|
92
|
-
|
|
93
|
-
### `requireSession()`
|
|
94
|
-
|
|
95
|
-
Returns session or throws `AuthSdkError` with `code = "unauthorized"`.
|
|
96
|
-
|
|
97
|
-
### `logout()`
|
|
98
|
-
|
|
99
|
-
Calls `POST /v1/auth/logout`, clears session state, and broadcasts update.
|
|
100
|
-
|
|
101
|
-
### `subscribe(listener)`
|
|
62
|
+
- `AuthProvider`
|
|
63
|
+
- `AuthSessionGate`
|
|
64
|
+
- `useAuth`
|
|
102
65
|
|
|
103
|
-
|
|
66
|
+
`AuthProvider` props:
|
|
104
67
|
|
|
105
|
-
|
|
68
|
+
- `children: ReactNode`
|
|
69
|
+
- `client?: AuthClient`
|
|
70
|
+
- `initialSession?: GhostlySession | null`
|
|
106
71
|
|
|
107
|
-
|
|
72
|
+
`initialSession` semantics:
|
|
108
73
|
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `useAuthCallbackRedirect`
|
|
113
|
-
- `AuthSessionGate`
|
|
74
|
+
- `undefined` => provider bootstraps with `init()` and keeps `isLoading=true` until resolved.
|
|
75
|
+
- `null` => provider starts as resolved unauthenticated (`isLoading=false`).
|
|
76
|
+
- `GhostlySession` => provider starts as resolved authenticated (`isLoading=false`).
|
|
114
77
|
|
|
115
78
|
`useAuth()` returns:
|
|
116
79
|
|
|
117
|
-
- `session
|
|
118
|
-
- `isLoading
|
|
119
|
-
- `error
|
|
120
|
-
- `login(
|
|
80
|
+
- `session`
|
|
81
|
+
- `isLoading`
|
|
82
|
+
- `error`
|
|
83
|
+
- `login()`
|
|
121
84
|
- `logout()`
|
|
122
85
|
- `refresh()`
|
|
123
86
|
|
|
124
|
-
`
|
|
125
|
-
|
|
126
|
-
- `status: "processing" | "failed"`
|
|
127
|
-
- `error: AuthSdkError | null`
|
|
128
|
-
|
|
129
|
-
## Next Adapter
|
|
130
|
-
|
|
131
|
-
Entry: `@ghostly-solutions/auth/next`
|
|
87
|
+
## Next Entry (`@ghostly-solutions/auth/next`)
|
|
132
88
|
|
|
133
89
|
- `getServerSession(options)`
|
|
134
90
|
- `requireServerSession(options)`
|
|
135
|
-
- `ensureClientAuthenticated(client?)`
|
|
136
91
|
- `getNextServerSession(options?)`
|
|
92
|
+
- `tryGetNextServerSession(options?)`
|
|
137
93
|
- `requireNextServerSession(options?)`
|
|
138
|
-
- `
|
|
94
|
+
- `ensureClientAuthenticated(client?)`
|
|
95
|
+
|
|
96
|
+
## Extension Entry (`@ghostly-solutions/auth/extension`)
|
|
97
|
+
|
|
98
|
+
- `createExtensionAuthClient(options)`
|
|
99
|
+
- `ExtensionAuthClient.loginWithWebAuthFlow(options?)`
|
|
139
100
|
|
|
140
|
-
`
|
|
101
|
+
`ExtensionAuthClient` extends `AuthClient`.
|
|
141
102
|
|
|
142
|
-
|
|
103
|
+
## Errors
|
|
143
104
|
|
|
144
|
-
|
|
145
|
-
|
|
105
|
+
```ts
|
|
106
|
+
export const authErrorCode = {
|
|
107
|
+
unauthorized: "unauthorized",
|
|
108
|
+
networkError: "network_error",
|
|
109
|
+
apiError: "api_error",
|
|
110
|
+
broadcastChannelUnsupported: "broadcast_channel_unsupported",
|
|
111
|
+
serverOriginResolutionFailed: "server_origin_resolution_failed",
|
|
112
|
+
} as const;
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
export class AuthSdkError extends Error {
|
|
117
|
+
readonly code: AuthErrorCode;
|
|
118
|
+
readonly status: number | null;
|
|
119
|
+
readonly details: unknown;
|
|
120
|
+
}
|
|
121
|
+
```
|
package/docs/architecture.md
CHANGED
|
@@ -1,62 +1,44 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Layers
|
|
4
4
|
|
|
5
|
-
- `src/constants`: fixed
|
|
6
|
-
- `src/types`: public
|
|
7
|
-
- `src/errors`:
|
|
8
|
-
- `src/core`:
|
|
9
|
-
- `src/adapters/react`:
|
|
10
|
-
- `src/adapters/next`:
|
|
5
|
+
- `src/constants`: fixed routes and protocol constants.
|
|
6
|
+
- `src/types`: public contracts.
|
|
7
|
+
- `src/errors`: typed SDK errors.
|
|
8
|
+
- `src/core`: browser auth client, state store, transport, broadcast sync.
|
|
9
|
+
- `src/adapters/react`: provider/hook/session gate.
|
|
10
|
+
- `src/adapters/next`: server helpers for Next runtime.
|
|
11
|
+
- `src/adapters/extension`: extension-specific login orchestration.
|
|
11
12
|
|
|
12
|
-
##
|
|
13
|
+
## Session Model
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
- Session is stored server-side.
|
|
16
|
+
- Browser keeps only `HttpOnly` cookie.
|
|
17
|
+
- SDK keeps in-memory snapshot of `GhostlySession | null`.
|
|
18
|
+
- `BroadcastChannel` syncs updates across tabs.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
## Request Model
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
- Resolved state: `GhostlySession | null`.
|
|
20
|
-
- Updates notify subscribers.
|
|
21
|
-
|
|
22
|
-
### HTTP Layer
|
|
23
|
-
|
|
24
|
-
`http-client.ts` standardizes API calls:
|
|
22
|
+
Transport defaults:
|
|
25
23
|
|
|
26
24
|
- `credentials: "include"`
|
|
27
25
|
- `cache: "no-store"`
|
|
28
|
-
- normalized error mapping to `AuthSdkError`
|
|
29
|
-
|
|
30
|
-
### Callback Processing
|
|
31
|
-
|
|
32
|
-
`auth-client.ts` callback sequence:
|
|
33
|
-
|
|
34
|
-
1. Parse `token` from URL.
|
|
35
|
-
2. Remove `token` from browser URL immediately.
|
|
36
|
-
3. Validate token via API.
|
|
37
|
-
4. Save session in memory.
|
|
38
|
-
5. Resolve `returnTo` and return result.
|
|
39
|
-
|
|
40
|
-
### Cross-tab Sync
|
|
41
|
-
|
|
42
|
-
`broadcast-sync.ts` sends `session-updated` events through `BroadcastChannel`.
|
|
43
|
-
|
|
44
|
-
- Login/session refresh and logout publish updates.
|
|
45
|
-
- Other tabs update in-memory state in reaction to events.
|
|
46
26
|
|
|
47
|
-
|
|
27
|
+
SDK calls:
|
|
48
28
|
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- `
|
|
52
|
-
- Unauthorized state is explicit and typed.
|
|
29
|
+
- `GET /oauth/session` in `init()` and `getSession({ forceRefresh: true })`
|
|
30
|
+
- `POST /oauth/refresh` in `refresh()`
|
|
31
|
+
- `POST /oauth/logout` in `logout()`
|
|
53
32
|
|
|
54
|
-
##
|
|
33
|
+
## Redirect Model
|
|
55
34
|
|
|
56
|
-
|
|
35
|
+
- `login()` builds `GET /oauth/authorize?return_to=...` and may append logical `app`.
|
|
36
|
+
- `return_to` is sanitized to in-app absolute path (`/path`).
|
|
37
|
+
- OAuth callback processing is server-side; SDK does not process callback token URLs.
|
|
57
38
|
|
|
58
|
-
|
|
59
|
-
- `@ghostly-solutions/auth/react`
|
|
60
|
-
- `@ghostly-solutions/auth/next`
|
|
39
|
+
## Security Notes
|
|
61
40
|
|
|
62
|
-
|
|
41
|
+
- No token persistence in local/session storage.
|
|
42
|
+
- No callback token in browser URL contract.
|
|
43
|
+
- Unauthorized state is explicit (`null` session or typed error).
|
|
44
|
+
- IdP client selection belongs to the auth gateway, not to the SDK.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- Node.js 22+
|
|
6
6
|
- npm 11+
|
|
7
7
|
|
|
8
|
-
Bun
|
|
8
|
+
Bun can be used locally as an optional runner.
|
|
9
9
|
|
|
10
10
|
## Local Commands
|
|
11
11
|
|
|
@@ -17,37 +17,33 @@ npm run build
|
|
|
17
17
|
npm run check
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Optional Bun aliases are defined in `bun.json`.
|
|
23
|
-
|
|
24
|
-
Examples:
|
|
20
|
+
Optional Bun shortcuts:
|
|
25
21
|
|
|
26
22
|
```bash
|
|
27
23
|
bun run lint
|
|
24
|
+
bun run typecheck
|
|
28
25
|
bun run test
|
|
29
26
|
bun run build
|
|
30
27
|
```
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## CI (`.gitlab-ci.yml`)
|
|
35
|
-
|
|
36
|
-
Pipeline stages:
|
|
29
|
+
## CI
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
2. `test`: unit test run.
|
|
40
|
-
3. `build`: package build and `npm pack --dry-run` verification.
|
|
31
|
+
`.gitlab-ci.yml` runs:
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
1. `lint`
|
|
34
|
+
2. `typecheck`
|
|
35
|
+
3. `test`
|
|
36
|
+
4. `build` + `npm pack --dry-run`
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
- Uses `npm ci` with lockfile-based cache.
|
|
46
|
-
- Produces `dist/` as build artifact.
|
|
38
|
+
CI image: `node:22-bookworm`.
|
|
47
39
|
|
|
48
40
|
## Release Checklist
|
|
49
41
|
|
|
50
42
|
1. `npm run check`
|
|
51
43
|
2. `npm run build`
|
|
52
44
|
3. `npm pack --dry-run`
|
|
53
|
-
4. Verify
|
|
45
|
+
4. Verify exports in package tarball:
|
|
46
|
+
- `@ghostly-solutions/auth`
|
|
47
|
+
- `@ghostly-solutions/auth/react`
|
|
48
|
+
- `@ghostly-solutions/auth/next`
|
|
49
|
+
- `@ghostly-solutions/auth/extension`
|
package/docs/index.md
CHANGED
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
# Ghostly Auth SDK Documentation
|
|
2
2
|
|
|
3
|
-
## Documents
|
|
4
|
-
|
|
5
3
|
- [Overview](./overview.md)
|
|
6
4
|
- [API Reference](./api-reference.md)
|
|
7
5
|
- [Integration Guide](./integration-guide.md)
|
|
8
6
|
- [Architecture](./architecture.md)
|
|
9
7
|
- [Development and CI](./development-and-ci.md)
|
|
10
|
-
- [
|
|
11
|
-
|
|
12
|
-
## Scope
|
|
13
|
-
|
|
14
|
-
This SDK provides a fixed authentication flow for Ghostly Solutions products:
|
|
15
|
-
|
|
16
|
-
1. Redirect user to Ghostly API login start endpoint.
|
|
17
|
-
2. Receive JWT on a dedicated callback page.
|
|
18
|
-
3. Validate JWT through Ghostly API.
|
|
19
|
-
4. Resolve and expose a typed session.
|
|
20
|
-
5. Keep tabs synchronized and support logout.
|
|
21
|
-
|
|
22
|
-
The SDK intentionally avoids runtime endpoint configuration and fallback logic.
|
|
8
|
+
- [Demo](../demo/README.md)
|