@casfa/client 0.0.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/claim.d.ts +21 -0
- package/dist/api/claim.d.ts.map +1 -0
- package/dist/api/delegates.d.ts +39 -0
- package/dist/api/delegates.d.ts.map +1 -0
- package/dist/api/depots.d.ts +68 -0
- package/dist/api/depots.d.ts.map +1 -0
- package/dist/api/filesystem.d.ts +55 -0
- package/dist/api/filesystem.d.ts.map +1 -0
- package/dist/api/index.d.ts +13 -3
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +355 -207
- package/dist/api/index.js.map +19 -1
- package/dist/api/info.d.ts +16 -0
- package/dist/api/info.d.ts.map +1 -0
- package/dist/api/nodes.d.ts +42 -0
- package/dist/api/nodes.d.ts.map +1 -0
- package/dist/api/oauth.d.ts +54 -0
- package/dist/api/oauth.d.ts.map +1 -0
- package/dist/api/requests.d.ts +33 -0
- package/dist/api/requests.d.ts.map +1 -0
- package/dist/api/tokens.d.ts +19 -0
- package/dist/api/tokens.d.ts.map +1 -0
- package/dist/client/delegates.d.ts +26 -0
- package/dist/client/delegates.d.ts.map +1 -0
- package/dist/client/depots.d.ts +28 -0
- package/dist/client/depots.d.ts.map +1 -0
- package/dist/client/filesystem.d.ts +39 -0
- package/dist/client/filesystem.d.ts.map +1 -0
- package/dist/client/helpers.d.ts +27 -0
- package/dist/client/helpers.d.ts.map +1 -0
- package/dist/client/index.d.ts +49 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/nodes.d.ts +30 -0
- package/dist/client/nodes.d.ts.map +1 -0
- package/dist/client/oauth.d.ts +24 -0
- package/dist/client/oauth.d.ts.map +1 -0
- package/dist/client/tokens.d.ts +23 -0
- package/dist/client/tokens.d.ts.map +1 -0
- package/dist/index.d.ts +14 -294
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +414 -515
- package/dist/index.js.map +32 -1
- package/dist/store/index.d.ts +8 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/jwt-refresh.d.ts +31 -0
- package/dist/store/jwt-refresh.d.ts.map +1 -0
- package/dist/store/token-checks.d.ts +33 -0
- package/dist/store/token-checks.d.ts.map +1 -0
- package/dist/store/token-selector.d.ts +29 -0
- package/dist/store/token-selector.d.ts.map +1 -0
- package/dist/store/token-store.d.ts +30 -0
- package/dist/store/token-store.d.ts.map +1 -0
- package/dist/types/client.d.ts +64 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -142
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -3
- package/dist/types/index.js.map +10 -1
- package/dist/types/tokens.d.ts +86 -0
- package/dist/types/tokens.d.ts.map +1 -0
- package/dist/utils/http.d.ts +32 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/package.json +7 -3
- package/dist/index-cPO-6GxE.d.ts +0 -338
package/dist/index.js.map
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/index.ts","../src/utils/http.ts","../src/api/depots.ts","../src/api/info.ts","../src/api/nodes.ts","../src/api/oauth.ts","../src/api/requests.ts","../src/api/tickets.ts","../src/api/tokens.ts","../src/store/token-checks.ts","../src/store/jwt-refresh.ts","../src/store/token-selector.ts","../src/types/tokens.ts","../src/store/token-store.ts","../src/client/helpers.ts","../src/client/depots.ts","../src/client/nodes.ts","../src/client/oauth.ts","../src/client/tickets.ts","../src/client/tokens.ts","../src/client/index.ts"],"sourcesContent":["/**\n * API module exports for @casfa/client\n */\n\n// Depot API\nexport {\n type CommitDepotResponse,\n commitDepot,\n createDepot,\n deleteDepot,\n getDepot,\n type ListDepotsResponse,\n listDepots,\n updateDepot,\n} from \"./depots.ts\";\n// Info API\nexport { fetchServiceInfo, healthCheck } from \"./info.ts\";\n// Node API\nexport { getNode, getNodeMetadata, type NodeUploadResult, prepareNodes, putNode } from \"./nodes.ts\";\n// OAuth API\nexport {\n type CognitoConfig,\n exchangeCode,\n getMe,\n getOAuthConfig,\n login,\n refresh,\n type TokenResponse,\n tokenResponseToStoredUserToken,\n type UserInfo,\n} from \"./oauth.ts\";\n// Client Authorization Request API\nexport {\n approveAuthRequest,\n createAuthRequest,\n getAuthRequest,\n pollAuthRequest,\n rejectAuthRequest,\n} from \"./requests.ts\";\n// Ticket API\nexport {\n createTicket,\n getTicket,\n type ListTicketsResponse,\n listTickets,\n type SubmitTicketResponse,\n submitTicket,\n} from \"./tickets.ts\";\n// Token management API\nexport {\n createToken,\n type DelegateTokenParams,\n delegateToken,\n getToken,\n type ListTokensParams,\n type ListTokensResponse,\n listTokens,\n revokeToken,\n} from \"./tokens.ts\";\n","/**\n * Fetch utilities for the stateful client.\n */\n\nimport type { ClientError, FetchResult } from \"../types/client.ts\";\n\n// ============================================================================\n// Error Handling\n// ============================================================================\n\n/**\n * Map HTTP status to error code.\n */\nexport const statusToErrorCode = (status: number): string => {\n switch (status) {\n case 401:\n return \"UNAUTHORIZED\";\n case 403:\n return \"FORBIDDEN\";\n case 404:\n return \"NOT_FOUND\";\n case 409:\n return \"CONFLICT\";\n case 400:\n case 422:\n return \"VALIDATION_ERROR\";\n case 429:\n return \"RATE_LIMITED\";\n default:\n return \"UNKNOWN\";\n }\n};\n\n/**\n * Create error from HTTP response.\n */\nexport const createErrorFromResponse = async (response: Response): Promise<ClientError> => {\n const code = statusToErrorCode(response.status);\n let message = response.statusText;\n let details: unknown;\n\n try {\n const body = (await response.json()) as Record<string, unknown>;\n if (typeof body.message === \"string\") {\n message = body.message;\n }\n if (typeof body.error === \"string\") {\n message = body.error;\n }\n details = body;\n } catch {\n // Response body is not JSON, use status text\n }\n\n return { code, message, status: response.status, details };\n};\n\n/**\n * Create a network error.\n */\nexport const createNetworkError = (err: unknown): ClientError => ({\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network request failed\",\n details: err,\n});\n\n// ============================================================================\n// Fetch Function\n// ============================================================================\n\nexport type FetchOptions = {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n headers?: Record<string, string>;\n body?: unknown;\n /** Expected response type */\n responseType?: \"json\" | \"blob\" | \"text\" | \"none\";\n};\n\n/**\n * Make a fetch request with error handling.\n */\nexport const fetchApi = async <T>(\n url: string,\n options: FetchOptions = {}\n): Promise<FetchResult<T>> => {\n const { method = \"GET\", headers = {}, body, responseType = \"json\" } = options;\n\n const requestHeaders: Record<string, string> = { ...headers };\n\n // Add content-type for JSON body\n if (body !== undefined && !requestHeaders[\"Content-Type\"]) {\n requestHeaders[\"Content-Type\"] = \"application/json\";\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers: requestHeaders,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const error = await createErrorFromResponse(response);\n return { ok: false, error };\n }\n\n // Parse response based on type\n let data: T;\n switch (responseType) {\n case \"json\":\n data = (await response.json()) as T;\n break;\n case \"blob\":\n data = (await response.blob()) as T;\n break;\n case \"text\":\n data = (await response.text()) as T;\n break;\n case \"none\":\n data = undefined as T;\n break;\n }\n\n return { ok: true, data, status: response.status };\n } catch (err) {\n return { ok: false, error: createNetworkError(err) };\n }\n};\n\n/**\n * Make an authenticated fetch request.\n */\nexport const fetchWithAuth = async <T>(\n url: string,\n authHeader: string | null,\n options: FetchOptions = {}\n): Promise<FetchResult<T>> => {\n const headers = { ...options.headers };\n\n if (authHeader) {\n headers.Authorization = authHeader;\n }\n\n return fetchApi<T>(url, { ...options, headers });\n};\n","/**\n * Depot API functions.\n *\n * Token Requirement:\n * - All depot operations require Access Token with canManageDepot permission.\n */\n\nimport type {\n CreateDepot,\n CreateDepotResponse,\n DepotCommit,\n DepotDetail,\n DepotListItem,\n ListDepotsQuery,\n UpdateDepot,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ListDepotsResponse = {\n depots: DepotListItem[];\n nextCursor?: string;\n};\n\nexport type CommitDepotResponse = {\n depotId: string;\n root: string;\n updatedAt: number;\n};\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Create a new depot.\n * Requires Access Token with canManageDepot.\n */\nexport const createDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: CreateDepot\n): Promise<FetchResult<CreateDepotResponse>> => {\n return fetchWithAuth<CreateDepotResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * List depots.\n * Requires Access Token.\n */\nexport const listDepots = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params?: ListDepotsQuery\n): Promise<FetchResult<ListDepotsResponse>> => {\n const query = new URLSearchParams();\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n\n const queryString = query.toString();\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots${queryString ? `?${queryString}` : \"\"}`;\n\n return fetchWithAuth<ListDepotsResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * Get depot details.\n * Requires Access Token.\n */\nexport const getDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string\n): Promise<FetchResult<DepotDetail>> => {\n return fetchWithAuth<DepotDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`\n );\n};\n\n/**\n * Update depot metadata.\n * Requires Access Token with canManageDepot.\n */\nexport const updateDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string,\n params: UpdateDepot\n): Promise<FetchResult<DepotDetail>> => {\n return fetchWithAuth<DepotDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"PATCH\",\n body: params,\n }\n );\n};\n\n/**\n * Delete a depot.\n * Requires Access Token with canManageDepot.\n */\nexport const deleteDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string\n): Promise<FetchResult<void>> => {\n return fetchWithAuth<void>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"DELETE\",\n responseType: \"none\",\n }\n );\n};\n\n/**\n * Commit new root to depot.\n * Requires Access Token with canManageDepot.\n */\nexport const commitDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string,\n params: DepotCommit\n): Promise<FetchResult<CommitDepotResponse>> => {\n return fetchWithAuth<CommitDepotResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}/commit`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n","/**\n * Service info API.\n */\n\nimport type { ServiceInfo } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchApi } from \"../utils/http.ts\";\n\n/**\n * Fetch service info from /api/info.\n */\nexport const fetchServiceInfo = async (baseUrl: string): Promise<FetchResult<ServiceInfo>> => {\n return fetchApi<ServiceInfo>(`${baseUrl}/api/info`);\n};\n\n/**\n * Health check.\n */\nexport const healthCheck = async (baseUrl: string): Promise<FetchResult<{ status: string }>> => {\n return fetchApi<{ status: string }>(`${baseUrl}/api/health`);\n};\n","/**\n * Node API functions.\n *\n * Token Requirement:\n * - GET /nodes/:nodeKey: Access Token (with X-CAS-Index-Path header)\n * - POST /nodes/prepare: Access Token with canUpload\n * - PUT /nodes/:nodeKey: Access Token with canUpload\n */\n\nimport type { NodeMetadata, PrepareNodes, PrepareNodesResponse } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type NodeUploadResult = {\n nodeKey: string;\n status: \"created\" | \"exists\";\n};\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Get node content.\n * Requires Access Token with scope covering the index path.\n *\n * @param indexPath - The CAS index path for scope verification (e.g., \"depot:MAIN:0:1\")\n */\nexport const getNode = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n indexPath: string\n): Promise<FetchResult<Uint8Array>> => {\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}`;\n\n try {\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${accessTokenBase64}`,\n \"X-CAS-Index-Path\": indexPath,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n return {\n ok: false,\n error: {\n code: String(response.status),\n message: (error as { message?: string }).message ?? response.statusText,\n status: response.status,\n },\n };\n }\n\n const data = new Uint8Array(await response.arrayBuffer());\n return { ok: true, data, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n\n/**\n * Get node metadata.\n * Requires Access Token with scope covering the index path.\n */\nexport const getNodeMetadata = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n indexPath: string\n): Promise<FetchResult<NodeMetadata>> => {\n return fetchWithAuth<NodeMetadata>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}/metadata`,\n `Bearer ${accessTokenBase64}`,\n {\n headers: {\n \"X-CAS-Index-Path\": indexPath,\n },\n }\n );\n};\n\n/**\n * Prepare nodes for upload.\n * Returns which nodes need to be uploaded vs already exist.\n * Requires Access Token with canUpload.\n */\nexport const prepareNodes = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: PrepareNodes\n): Promise<FetchResult<PrepareNodesResponse>> => {\n return fetchWithAuth<PrepareNodesResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/prepare`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * Upload a node.\n * Requires Access Token with canUpload.\n */\nexport const putNode = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n content: Uint8Array\n): Promise<FetchResult<NodeUploadResult>> => {\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}`;\n\n try {\n const response = await fetch(url, {\n method: \"PUT\",\n headers: {\n Authorization: `Bearer ${accessTokenBase64}`,\n \"Content-Type\": \"application/octet-stream\",\n },\n body: content,\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n return {\n ok: false,\n error: {\n code: String(response.status),\n message: (error as { message?: string }).message ?? response.statusText,\n status: response.status,\n },\n };\n }\n\n const data = (await response.json()) as NodeUploadResult;\n return { ok: true, data, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n","/**\n * OAuth API functions.\n */\n\nimport type { Login, Refresh, TokenExchange } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport type { StoredUserToken } from \"../types/tokens.ts\";\nimport { fetchApi, fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type CognitoConfig = {\n region: string;\n userPoolId: string;\n clientId: string;\n domain: string;\n};\n\nexport type TokenResponse = {\n accessToken: string;\n refreshToken: string;\n expiresIn: number;\n idToken?: string;\n};\n\nexport type UserInfo = {\n userId: string;\n email: string;\n role: string;\n};\n\n// ============================================================================\n// Public OAuth API\n// ============================================================================\n\n/**\n * Get Cognito configuration.\n */\nexport const getOAuthConfig = async (baseUrl: string): Promise<FetchResult<CognitoConfig>> => {\n return fetchApi<CognitoConfig>(`${baseUrl}/api/oauth/config`);\n};\n\n/**\n * Exchange authorization code for tokens.\n */\nexport const exchangeCode = async (\n baseUrl: string,\n params: TokenExchange\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/token`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Login with email and password.\n */\nexport const login = async (\n baseUrl: string,\n params: Login\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/login`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Refresh access token.\n */\nexport const refresh = async (\n baseUrl: string,\n params: Refresh\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/refresh`, {\n method: \"POST\",\n body: params,\n });\n};\n\n// ============================================================================\n// Authenticated OAuth API\n// ============================================================================\n\n/**\n * Get current user info.\n * Requires User JWT.\n */\nexport const getMe = async (\n baseUrl: string,\n userAccessToken: string\n): Promise<FetchResult<UserInfo>> => {\n return fetchWithAuth<UserInfo>(`${baseUrl}/api/oauth/me`, `Bearer ${userAccessToken}`);\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Convert token response to stored user token.\n */\nexport const tokenResponseToStoredUserToken = (\n response: TokenResponse,\n userId: string\n): StoredUserToken => ({\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n userId,\n expiresAt: Date.now() + response.expiresIn * 1000,\n});\n","/**\n * Client Authorization Request API functions.\n *\n * For CLI/desktop apps to request tokens through user approval.\n */\n\nimport type {\n ApproveRequest,\n ApproveRequestResponse,\n CreateAuthRequest,\n CreateAuthRequestResponse,\n DenyRequest,\n DenyRequestResponse,\n PollRequestResponse,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchApi, fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Public APIs (No auth required)\n// ============================================================================\n\n/**\n * Create an authorization request.\n * No auth required - called by CLI/desktop clients.\n */\nexport const createAuthRequest = async (\n baseUrl: string,\n params: CreateAuthRequest\n): Promise<FetchResult<CreateAuthRequestResponse>> => {\n return fetchApi<CreateAuthRequestResponse>(`${baseUrl}/api/tokens/requests`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Poll authorization request status.\n * No auth required - called by CLI/desktop clients.\n */\nexport const pollAuthRequest = async (\n baseUrl: string,\n requestId: string\n): Promise<FetchResult<PollRequestResponse>> => {\n return fetchApi<PollRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/poll`\n );\n};\n\n// ============================================================================\n// User JWT APIs (For approving/rejecting requests)\n// ============================================================================\n\n/**\n * Get authorization request details.\n * Requires User JWT.\n */\nexport const getAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string\n): Promise<FetchResult<PollRequestResponse>> => {\n return fetchWithAuth<PollRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}`,\n `Bearer ${userAccessToken}`\n );\n};\n\n/**\n * Approve an authorization request.\n * Requires User JWT.\n */\nexport const approveAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string,\n params?: ApproveRequest\n): Promise<FetchResult<ApproveRequestResponse>> => {\n return fetchWithAuth<ApproveRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/approve`,\n `Bearer ${userAccessToken}`,\n {\n method: \"POST\",\n body: params ?? {},\n }\n );\n};\n\n/**\n * Reject an authorization request.\n * Requires User JWT.\n */\nexport const rejectAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string,\n params?: DenyRequest\n): Promise<FetchResult<DenyRequestResponse>> => {\n return fetchWithAuth<DenyRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/reject`,\n `Bearer ${userAccessToken}`,\n {\n method: \"POST\",\n body: params ?? {},\n }\n );\n};\n","/**\n * Ticket API functions.\n *\n * Token Requirement:\n * - POST /api/realm/{realmId}/tickets: Access Token (create ticket, bind pre-issued token)\n * - GET /api/realm/{realmId}/tickets: Access Token (list)\n * - GET /api/realm/{realmId}/tickets/:ticketId: Access Token (get detail)\n * - POST /api/realm/{realmId}/tickets/:ticketId/submit: Access Token (submit)\n *\n * Design Principle: All Realm data operations use Access Token.\n * Delegate Token is only for issuing tokens.\n *\n * Two-step Ticket creation flow:\n * 1. Issue Access Token using Delegate Token (POST /api/tokens/delegate)\n * 2. Create Ticket and bind the token (POST /api/realm/{realmId}/tickets)\n */\n\nimport type {\n CreateTicket,\n CreateTicketResponse,\n ListTicketsQuery,\n TicketDetail,\n TicketListItem,\n TicketSubmit,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ListTicketsResponse = {\n tickets: TicketListItem[];\n nextCursor?: string;\n};\n\nexport type SubmitTicketResponse = {\n ticketId: string;\n status: \"submitted\";\n root: string;\n submittedAt: number;\n};\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Create a new ticket and bind a pre-issued Access Token.\n * Requires Access Token.\n *\n * @param accessTokenBase64 - Caller's Access Token (for authentication)\n * @param params.accessTokenId - Pre-issued Access Token ID to bind (for Tool use)\n */\nexport const createTicket = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: CreateTicket\n): Promise<FetchResult<CreateTicketResponse>> => {\n return fetchWithAuth<CreateTicketResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * List tickets.\n * Requires Access Token.\n */\nexport const listTickets = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params?: ListTicketsQuery\n): Promise<FetchResult<ListTicketsResponse>> => {\n const query = new URLSearchParams();\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n if (params?.status) query.set(\"status\", params.status);\n\n const queryString = query.toString();\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets${queryString ? `?${queryString}` : \"\"}`;\n\n return fetchWithAuth<ListTicketsResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * Get ticket details.\n * Requires Access Token.\n */\nexport const getTicket = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n ticketId: string\n): Promise<FetchResult<TicketDetail>> => {\n return fetchWithAuth<TicketDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets/${encodeURIComponent(ticketId)}`,\n `Bearer ${accessTokenBase64}`\n );\n};\n\n/**\n * Submit a ticket.\n * Requires Access Token.\n */\nexport const submitTicket = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n ticketId: string,\n params: TicketSubmit\n): Promise<FetchResult<SubmitTicketResponse>> => {\n return fetchWithAuth<SubmitTicketResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets/${encodeURIComponent(ticketId)}/submit`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n","/**\n * Token management API functions.\n *\n * Token Requirement:\n * - POST /api/tokens: User JWT\n * - GET /api/tokens: User JWT\n * - GET /api/tokens/:tokenId: User JWT\n * - POST /api/tokens/:tokenId/revoke: User JWT\n * - POST /api/tokens/delegate: Delegate Token\n */\n\nimport type {\n CreateToken,\n CreateTokenResponse,\n RevokeTokenResponse,\n TokenDetail,\n TokenListItem,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ListTokensParams = {\n limit?: number;\n cursor?: string;\n type?: \"delegate\" | \"access\";\n};\n\nexport type ListTokensResponse = {\n tokens: TokenListItem[];\n nextCursor?: string;\n};\n\n// ============================================================================\n// User JWT APIs\n// ============================================================================\n\n/**\n * Create a new Delegate Token.\n * Requires User JWT.\n */\nexport const createToken = async (\n baseUrl: string,\n userAccessToken: string,\n params: CreateToken\n): Promise<FetchResult<CreateTokenResponse>> => {\n return fetchWithAuth<CreateTokenResponse>(`${baseUrl}/api/tokens`, `Bearer ${userAccessToken}`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * List Delegate Tokens.\n * Requires User JWT.\n */\nexport const listTokens = async (\n baseUrl: string,\n userAccessToken: string,\n params?: ListTokensParams\n): Promise<FetchResult<ListTokensResponse>> => {\n const query = new URLSearchParams();\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n if (params?.type) query.set(\"type\", params.type);\n\n const queryString = query.toString();\n const url = `${baseUrl}/api/tokens${queryString ? `?${queryString}` : \"\"}`;\n\n return fetchWithAuth<ListTokensResponse>(url, `Bearer ${userAccessToken}`);\n};\n\n/**\n * Get token details.\n * Requires User JWT.\n */\nexport const getToken = async (\n baseUrl: string,\n userAccessToken: string,\n tokenId: string\n): Promise<FetchResult<TokenDetail>> => {\n return fetchWithAuth<TokenDetail>(\n `${baseUrl}/api/tokens/${encodeURIComponent(tokenId)}`,\n `Bearer ${userAccessToken}`\n );\n};\n\n/**\n * Revoke a token.\n * Requires User JWT.\n */\nexport const revokeToken = async (\n baseUrl: string,\n userAccessToken: string,\n tokenId: string\n): Promise<FetchResult<RevokeTokenResponse>> => {\n return fetchWithAuth<RevokeTokenResponse>(\n `${baseUrl}/api/tokens/${encodeURIComponent(tokenId)}/revoke`,\n `Bearer ${userAccessToken}`,\n { method: \"POST\" }\n );\n};\n\n// ============================================================================\n// Delegate Token APIs\n// ============================================================================\n\nexport type DelegateTokenParams = {\n name: string;\n type: \"delegate\" | \"access\";\n expiresIn?: number;\n canUpload?: boolean;\n canManageDepot?: boolean;\n scope?: string[];\n};\n\n/**\n * Delegate (re-issue) a token using existing Delegate Token.\n * Requires Delegate Token.\n */\nexport const delegateToken = async (\n baseUrl: string,\n delegateTokenBase64: string,\n params: DelegateTokenParams\n): Promise<FetchResult<CreateTokenResponse>> => {\n return fetchWithAuth<CreateTokenResponse>(\n `${baseUrl}/api/tokens/delegate`,\n `Bearer ${delegateTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n","/**\n * Token validity and issuer consistency checks.\n */\n\nimport type {\n StoredAccessToken,\n StoredDelegateToken,\n StoredUserToken,\n TokenState,\n} from \"../types/tokens.ts\";\n\n// ============================================================================\n// Validity Checks\n// ============================================================================\n\n/**\n * Default buffer time before expiration (60 seconds).\n */\nexport const DEFAULT_EXPIRY_BUFFER_MS = 60_000;\n\n/**\n * Check if a token is valid (not expired with buffer).\n */\nexport const isTokenValid = (\n token: { expiresAt: number } | null,\n bufferMs: number = DEFAULT_EXPIRY_BUFFER_MS\n): boolean => {\n if (!token) return false;\n return Date.now() + bufferMs < token.expiresAt;\n};\n\n/**\n * Check if token is expiring soon and should be refreshed proactively.\n * Used for JWT refresh scheduling.\n */\nexport const isTokenExpiringSoon = (\n token: { expiresAt: number } | null,\n windowMs: number = 5 * 60_000 // 5 minutes\n): boolean => {\n if (!token) return false;\n return Date.now() + windowMs >= token.expiresAt;\n};\n\n/**\n * Check if user JWT is valid.\n */\nexport const isUserTokenValid = (userToken: StoredUserToken | null, bufferMs?: number): boolean => {\n return isTokenValid(userToken, bufferMs);\n};\n\n/**\n * Check if delegate token is valid.\n */\nexport const isDelegateTokenValid = (\n delegateToken: StoredDelegateToken | null,\n bufferMs?: number\n): boolean => {\n return isTokenValid(delegateToken, bufferMs);\n};\n\n/**\n * Check if access token is valid.\n */\nexport const isAccessTokenValid = (\n accessToken: StoredAccessToken | null,\n bufferMs?: number\n): boolean => {\n return isTokenValid(accessToken, bufferMs);\n};\n\n// ============================================================================\n// Issuer Consistency Checks\n// ============================================================================\n\n/**\n * Get the current max issuer ID.\n * Priority: User JWT (userId) > Delegate Token (tokenId)\n */\nexport const getMaxIssuerId = (state: TokenState): string | null => {\n if (state.user && isUserTokenValid(state.user)) {\n return state.user.userId;\n }\n if (state.delegate && isDelegateTokenValid(state.delegate)) {\n return state.delegate.tokenId;\n }\n return null;\n};\n\n/**\n * Check if access token is issued by the current max issuer.\n * If not, the access token should be re-issued.\n */\nexport const isAccessTokenFromMaxIssuer = (state: TokenState): boolean => {\n const accessToken = state.access;\n if (!accessToken || !isAccessTokenValid(accessToken)) {\n return false;\n }\n\n const maxIssuerId = getMaxIssuerId(state);\n if (!maxIssuerId) {\n // No valid issuer, access token is orphaned but still usable\n return true;\n }\n\n return accessToken.issuerId === maxIssuerId;\n};\n\n/**\n * Check if delegate token is issued by current user.\n * If user JWT exists but delegate token is from a different user,\n * we may want to re-issue the delegate token.\n */\nexport const isDelegateTokenFromCurrentUser = (state: TokenState): boolean => {\n const delegateToken = state.delegate;\n const userToken = state.user;\n\n if (!delegateToken || !isDelegateTokenValid(delegateToken)) {\n return false;\n }\n\n if (!userToken || !isUserTokenValid(userToken)) {\n // No user token, delegate token is the top-level authority\n return true;\n }\n\n return delegateToken.issuerId === userToken.userId;\n};\n\n/**\n * Determine if access token needs re-issue.\n * Returns true if:\n * - Access token is invalid/expired\n * - Access token's issuer is not the current max issuer\n */\nexport const shouldReissueAccessToken = (state: TokenState): boolean => {\n if (!isAccessTokenValid(state.access)) {\n return true;\n }\n if (!isAccessTokenFromMaxIssuer(state)) {\n return true;\n }\n return false;\n};\n\n/**\n * Determine if delegate token needs re-issue.\n * Returns true if:\n * - Delegate token is invalid/expired\n * - User token exists but delegate token is not from current user\n */\nexport const shouldReissueDelegateToken = (state: TokenState): boolean => {\n if (!isDelegateTokenValid(state.delegate)) {\n return true;\n }\n if (state.user && !isDelegateTokenFromCurrentUser(state)) {\n return true;\n }\n return false;\n};\n","/**\n * JWT refresh management with promise deduplication.\n */\n\nimport type { OnAuthRequiredCallback } from \"../types/client.ts\";\nimport type { StoredUserToken } from \"../types/tokens.ts\";\nimport { isUserTokenValid } from \"./token-checks.ts\";\nimport type { TokenStore } from \"./token-store.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RefreshManager = {\n /**\n * Ensure user token is valid, refreshing if needed.\n * Returns the valid user token or null if refresh failed.\n */\n ensureValidUserToken: () => Promise<StoredUserToken | null>;\n\n /**\n * Schedule proactive refresh before expiration.\n */\n scheduleProactiveRefresh: () => void;\n\n /**\n * Cancel any scheduled refresh.\n */\n cancelScheduledRefresh: () => void;\n};\n\nexport type RefreshManagerConfig = {\n store: TokenStore;\n baseUrl: string;\n onAuthRequired?: OnAuthRequiredCallback;\n};\n\n// ============================================================================\n// Refresh API Call\n// ============================================================================\n\ntype RefreshResponse = {\n accessToken: string;\n refreshToken?: string;\n expiresIn: number;\n};\n\nconst callRefreshApi = async (\n baseUrl: string,\n refreshToken: string\n): Promise<RefreshResponse | null> => {\n try {\n const response = await fetch(`${baseUrl}/api/oauth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as RefreshResponse;\n } catch {\n return null;\n }\n};\n\n// ============================================================================\n// Refresh Manager Factory\n// ============================================================================\n\n/**\n * Create a refresh manager for JWT token refresh.\n */\nexport const createRefreshManager = (config: RefreshManagerConfig): RefreshManager => {\n const { store, baseUrl, onAuthRequired } = config;\n\n // Promise deduplication: only one refresh in flight at a time\n let refreshPromise: Promise<StoredUserToken | null> | null = null;\n\n // Scheduled refresh timer\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n\n const doRefresh = async (): Promise<StoredUserToken | null> => {\n const state = store.getState();\n const userToken = state.user;\n\n if (!userToken?.refreshToken) {\n onAuthRequired?.();\n return null;\n }\n\n const result = await callRefreshApi(baseUrl, userToken.refreshToken);\n\n if (!result) {\n // Refresh failed, require re-auth\n store.setUser(null);\n onAuthRequired?.();\n return null;\n }\n\n const newUserToken: StoredUserToken = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken ?? userToken.refreshToken,\n userId: userToken.userId,\n expiresAt: Date.now() + result.expiresIn * 1000,\n };\n\n store.setUser(newUserToken);\n return newUserToken;\n };\n\n const ensureValidUserToken = async (): Promise<StoredUserToken | null> => {\n const state = store.getState();\n const userToken = state.user;\n\n // Check if current token is valid\n if (isUserTokenValid(userToken)) {\n return userToken;\n }\n\n // No user token at all\n if (!userToken) {\n return null;\n }\n\n // Need to refresh - use deduplication\n if (!refreshPromise) {\n refreshPromise = doRefresh().finally(() => {\n refreshPromise = null;\n });\n }\n\n return refreshPromise;\n };\n\n const scheduleProactiveRefresh = () => {\n cancelScheduledRefresh();\n\n const state = store.getState();\n const userToken = state.user;\n\n if (!userToken) return;\n\n // Schedule refresh 5 minutes before expiration\n const refreshTime = userToken.expiresAt - Date.now() - 5 * 60_000;\n\n if (refreshTime <= 0) {\n // Already expiring soon, refresh immediately\n ensureValidUserToken();\n return;\n }\n\n refreshTimer = setTimeout(() => {\n ensureValidUserToken().then((newToken) => {\n if (newToken) {\n // Schedule next refresh\n scheduleProactiveRefresh();\n }\n });\n }, refreshTime);\n };\n\n const cancelScheduledRefresh = () => {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n };\n\n return {\n ensureValidUserToken,\n scheduleProactiveRefresh,\n cancelScheduledRefresh,\n };\n};\n","/**\n * Token selector and auto-issuer.\n *\n * Implements the \"maximum authority\" principle:\n * - When issuing tokens, prefer User JWT (depth=0) over Delegate Token\n * - Check issuer consistency before using existing tokens\n * - Re-issue tokens when issuer is not maximized\n */\n\nimport type { ServiceInfo } from \"@casfa/protocol\";\nimport type { StoredAccessToken, StoredDelegateToken } from \"../types/tokens.ts\";\nimport {\n isDelegateTokenValid,\n isUserTokenValid,\n shouldReissueAccessToken,\n} from \"./token-checks.ts\";\nimport type { TokenStore } from \"./token-store.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TokenSelectorConfig = {\n store: TokenStore;\n baseUrl: string;\n realm: string;\n serverInfo: ServiceInfo | null;\n defaultTokenTtl?: number;\n};\n\nexport type TokenSelector = {\n /**\n * Get or issue an Access Token.\n * - If valid Access Token exists and is from max issuer, return it\n * - Otherwise, issue a new one using User JWT or Delegate Token\n */\n ensureAccessToken: () => Promise<StoredAccessToken | null>;\n\n /**\n * Get or issue a Delegate Token.\n * - If valid Delegate Token exists, return it\n * - If User JWT exists, issue a new one\n */\n ensureDelegateToken: () => Promise<StoredDelegateToken | null>;\n};\n\n// ============================================================================\n// API Calls for Token Issuance\n// ============================================================================\n\ntype CreateTokenRequest = {\n realm: string;\n name: string;\n type: \"delegate\" | \"access\";\n expiresIn?: number;\n canUpload?: boolean;\n canManageDepot?: boolean;\n scope?: string[];\n};\n\ntype CreateTokenResponse = {\n tokenId: string;\n tokenBase64: string;\n type: \"delegate\" | \"access\";\n issuerId: string;\n expiresAt: number;\n canUpload: boolean;\n canManageDepot: boolean;\n};\n\n/**\n * Issue a token using User JWT.\n */\nconst issueTokenWithUserJwt = async (\n baseUrl: string,\n userAccessToken: string,\n request: CreateTokenRequest\n): Promise<CreateTokenResponse | null> => {\n try {\n const response = await fetch(`${baseUrl}/api/tokens`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${userAccessToken}`,\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n console.error(\"[TokenSelector] Failed to issue token with User JWT:\", response.status);\n return null;\n }\n\n return (await response.json()) as CreateTokenResponse;\n } catch (err) {\n console.error(\"[TokenSelector] Error issuing token with User JWT:\", err);\n return null;\n }\n};\n\n/**\n * Delegate a token using existing Delegate Token.\n */\nconst delegateToken = async (\n baseUrl: string,\n delegateTokenBase64: string,\n request: Omit<CreateTokenRequest, \"realm\">\n): Promise<CreateTokenResponse | null> => {\n try {\n const response = await fetch(`${baseUrl}/api/tokens/delegate`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${delegateTokenBase64}`,\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n console.error(\"[TokenSelector] Failed to delegate token:\", response.status);\n return null;\n }\n\n return (await response.json()) as CreateTokenResponse;\n } catch (err) {\n console.error(\"[TokenSelector] Error delegating token:\", err);\n return null;\n }\n};\n\n// ============================================================================\n// Token Selector Factory\n// ============================================================================\n\n/**\n * Create a token selector instance.\n */\nexport const createTokenSelector = (config: TokenSelectorConfig): TokenSelector => {\n const { store, baseUrl, realm, serverInfo, defaultTokenTtl } = config;\n\n /**\n * Get token TTL in seconds.\n * Priority: defaultTokenTtl > server max > fallback\n */\n const getTokenTtl = (type: \"delegate\" | \"access\"): number => {\n if (defaultTokenTtl) return defaultTokenTtl;\n\n if (serverInfo?.limits) {\n if (type === \"delegate\" && serverInfo.limits.maxDelegateTokenTtl) {\n return serverInfo.limits.maxDelegateTokenTtl;\n }\n if (type === \"access\" && serverInfo.limits.maxAccessTokenTtl) {\n return serverInfo.limits.maxAccessTokenTtl;\n }\n }\n\n // Fallback: 1 hour for access, 30 days for delegate\n return type === \"access\" ? 3600 : 30 * 24 * 3600;\n };\n\n const ensureAccessToken = async (): Promise<StoredAccessToken | null> => {\n const state = store.getState();\n\n // Check if existing access token is valid and from max issuer\n if (!shouldReissueAccessToken(state)) {\n return state.access;\n }\n\n // Need to issue a new access token\n // Priority: User JWT > Delegate Token\n const userToken = state.user;\n const delegateToken_ = state.delegate;\n\n if (isUserTokenValid(userToken)) {\n // Issue with User JWT (max authority)\n const result = await issueTokenWithUserJwt(baseUrl, userToken!.accessToken, {\n realm,\n name: \"auto-issued-access\",\n type: \"access\",\n expiresIn: getTokenTtl(\"access\"),\n canUpload: true,\n canManageDepot: true,\n });\n\n if (result) {\n const newToken: StoredAccessToken = {\n tokenId: result.tokenId,\n tokenBase64: result.tokenBase64,\n type: \"access\",\n issuerId: result.issuerId,\n expiresAt: result.expiresAt,\n canUpload: result.canUpload,\n canManageDepot: result.canManageDepot,\n };\n store.setAccess(newToken);\n return newToken;\n }\n }\n\n if (isDelegateTokenValid(delegateToken_)) {\n // Issue with Delegate Token (fallback)\n const result = await delegateToken(baseUrl, delegateToken_!.tokenBase64, {\n name: \"auto-issued-access\",\n type: \"access\",\n expiresIn: getTokenTtl(\"access\"),\n canUpload: delegateToken_!.canUpload,\n canManageDepot: delegateToken_!.canManageDepot,\n });\n\n if (result) {\n const newToken: StoredAccessToken = {\n tokenId: result.tokenId,\n tokenBase64: result.tokenBase64,\n type: \"access\",\n issuerId: result.issuerId,\n expiresAt: result.expiresAt,\n canUpload: result.canUpload,\n canManageDepot: result.canManageDepot,\n };\n store.setAccess(newToken);\n return newToken;\n }\n }\n\n // No way to issue access token\n return null;\n };\n\n const ensureDelegateToken = async (): Promise<StoredDelegateToken | null> => {\n const state = store.getState();\n\n // Check if existing delegate token is valid\n if (isDelegateTokenValid(state.delegate)) {\n return state.delegate;\n }\n\n // Need to issue a new delegate token\n // Only User JWT can issue delegate tokens\n const userToken = state.user;\n\n if (!isUserTokenValid(userToken)) {\n return null;\n }\n\n const result = await issueTokenWithUserJwt(baseUrl, userToken!.accessToken, {\n realm,\n name: \"auto-issued-delegate\",\n type: \"delegate\",\n expiresIn: getTokenTtl(\"delegate\"),\n canUpload: true,\n canManageDepot: true,\n });\n\n if (result) {\n const newToken: StoredDelegateToken = {\n tokenId: result.tokenId,\n tokenBase64: result.tokenBase64,\n type: \"delegate\",\n issuerId: result.issuerId,\n expiresAt: result.expiresAt,\n canUpload: result.canUpload,\n canManageDepot: result.canManageDepot,\n };\n store.setDelegate(newToken);\n return newToken;\n }\n\n return null;\n };\n\n return {\n ensureAccessToken,\n ensureDelegateToken,\n };\n};\n","/**\n * Token types for the stateful client.\n *\n * Three-tier token hierarchy:\n * - User JWT: OAuth login token, highest authority\n * - Delegate Token: Re-delegation token, can issue child tokens\n * - Access Token: Data access token, used for CAS operations\n */\n\n// ============================================================================\n// Stored Token Types\n// ============================================================================\n\n/**\n * User JWT token with refresh capability.\n */\nexport type StoredUserToken = {\n /** JWT access token */\n accessToken: string;\n /** Refresh token for token renewal */\n refreshToken: string;\n /** User ID (usr_xxx format) */\n userId: string;\n /** Token expiration time (epoch ms) */\n expiresAt: number;\n};\n\n/**\n * Delegate Token (re-delegation token).\n */\nexport type StoredDelegateToken = {\n /** Token ID (dlt1_xxx format) */\n tokenId: string;\n /** Token binary as Base64 */\n tokenBase64: string;\n /** Token type: always \"delegate\" */\n type: \"delegate\";\n /** Issuer ID (usr_xxx or dlt1_xxx) */\n issuerId: string;\n /** Token expiration time (epoch ms) */\n expiresAt: number;\n /** Whether the token can upload nodes */\n canUpload: boolean;\n /** Whether the token can manage depots */\n canManageDepot: boolean;\n};\n\n/**\n * Access Token (data access token).\n */\nexport type StoredAccessToken = {\n /** Token ID (dlt1_xxx format) */\n tokenId: string;\n /** Token binary as Base64 */\n tokenBase64: string;\n /** Token type: always \"access\" */\n type: \"access\";\n /** Issuer ID (usr_xxx or dlt1_xxx) */\n issuerId: string;\n /** Token expiration time (epoch ms) */\n expiresAt: number;\n /** Whether the token can upload nodes */\n canUpload: boolean;\n /** Whether the token can manage depots */\n canManageDepot: boolean;\n};\n\n/**\n * Complete token state held by the client.\n */\nexport type TokenState = {\n /** User JWT (optional) */\n user: StoredUserToken | null;\n /** Delegate Token (optional) */\n delegate: StoredDelegateToken | null;\n /** Access Token (optional) */\n access: StoredAccessToken | null;\n};\n\n/**\n * Empty token state.\n */\nexport const emptyTokenState = (): TokenState => ({\n user: null,\n delegate: null,\n access: null,\n});\n\n// ============================================================================\n// Token Requirement Types\n// ============================================================================\n\n/**\n * Token requirement for API calls.\n */\nexport type TokenRequirement = \"none\" | \"user\" | \"delegate\" | \"access\";\n\n/**\n * Auth header format.\n */\nexport type AuthHeader = {\n Authorization: string;\n};\n\n/**\n * Get issuer ID from current state (for signing new tokens).\n * Priority: User JWT > Delegate Token\n */\nexport const getMaxIssuerId = (state: TokenState): string | null => {\n if (state.user) {\n return state.user.userId;\n }\n if (state.delegate) {\n return state.delegate.tokenId;\n }\n return null;\n};\n\n/**\n * Check if Access Token was issued by the current max issuer.\n */\nexport const isAccessTokenFromMaxIssuer = (state: TokenState): boolean => {\n if (!state.access) return false;\n\n const maxIssuerId = getMaxIssuerId(state);\n if (!maxIssuerId) return false;\n\n return state.access.issuerId === maxIssuerId;\n};\n\n/**\n * Check if Delegate Token was issued by current user.\n */\nexport const isDelegateTokenFromCurrentUser = (state: TokenState): boolean => {\n if (!state.delegate || !state.user) return false;\n return state.delegate.issuerId === state.user.userId;\n};\n","/**\n * Token store - manages the three-tier token state.\n *\n * Provides a closure-based store for token state management with\n * automatic persistence and change notifications.\n */\n\nimport type {\n OnAuthRequiredCallback,\n OnTokenChangeCallback,\n TokenStorageProvider,\n} from \"../types/client.ts\";\nimport type {\n StoredAccessToken,\n StoredDelegateToken,\n StoredUserToken,\n TokenState,\n} from \"../types/tokens.ts\";\nimport { emptyTokenState } from \"../types/tokens.ts\";\n\n// ============================================================================\n// Store Types\n// ============================================================================\n\nexport type TokenStore = {\n /** Get current token state (immutable snapshot) */\n getState: () => TokenState;\n\n /** Set user JWT token */\n setUser: (token: StoredUserToken | null) => void;\n\n /** Set delegate token */\n setDelegate: (token: StoredDelegateToken | null) => void;\n\n /** Set access token */\n setAccess: (token: StoredAccessToken | null) => void;\n\n /** Clear all tokens */\n clear: () => void;\n\n /** Initialize from storage provider */\n initialize: () => Promise<void>;\n};\n\nexport type TokenStoreConfig = {\n storage?: TokenStorageProvider;\n onTokenChange?: OnTokenChangeCallback;\n onAuthRequired?: OnAuthRequiredCallback;\n};\n\n// ============================================================================\n// Store Factory\n// ============================================================================\n\n/**\n * Create a token store instance.\n */\nexport const createTokenStore = (config: TokenStoreConfig = {}): TokenStore => {\n const { storage, onTokenChange } = config;\n\n // Internal mutable state\n let state: TokenState = emptyTokenState();\n\n // Notify change and persist\n const notifyAndPersist = () => {\n onTokenChange?.(state);\n storage?.save(state).catch((err) => {\n console.error(\"[TokenStore] Failed to persist state:\", err);\n });\n };\n\n return {\n getState: () => ({ ...state }),\n\n setUser: (token) => {\n state = { ...state, user: token };\n notifyAndPersist();\n },\n\n setDelegate: (token) => {\n state = { ...state, delegate: token };\n notifyAndPersist();\n },\n\n setAccess: (token) => {\n state = { ...state, access: token };\n notifyAndPersist();\n },\n\n clear: () => {\n state = emptyTokenState();\n notifyAndPersist();\n storage?.clear().catch((err) => {\n console.error(\"[TokenStore] Failed to clear storage:\", err);\n });\n },\n\n initialize: async () => {\n if (!storage) return;\n\n try {\n const loaded = await storage.load();\n if (loaded) {\n state = loaded;\n // Don't notify on initial load to avoid side effects\n }\n } catch (err) {\n console.error(\"[TokenStore] Failed to load from storage:\", err);\n }\n },\n };\n};\n","/**\n * Client helper functions for reducing boilerplate.\n */\n\nimport type { FetchResult } from \"../types/client.ts\";\nimport type { StoredAccessToken, StoredDelegateToken, StoredUserToken } from \"../types/tokens.ts\";\n\n// ============================================================================\n// Error Constants\n// ============================================================================\n\nexport const ERRORS = {\n USER_REQUIRED: { code: \"UNAUTHORIZED\", message: \"User login required\" },\n DELEGATE_REQUIRED: { code: \"FORBIDDEN\", message: \"Delegate token required\" },\n ACCESS_REQUIRED: { code: \"FORBIDDEN\", message: \"Access token required\" },\n} as const;\n\n// ============================================================================\n// Token Guards\n// ============================================================================\n\nexport type TokenGetter<T> = () => Promise<T | null>;\n\n/**\n * Higher-order function for token-required operations.\n * Reduces repetitive null checks and error returns.\n */\nexport const withToken = <T>(\n getToken: TokenGetter<T>,\n error: { code: string; message: string }\n) => {\n return <R>(fn: (token: T) => Promise<FetchResult<R>>): Promise<FetchResult<R>> =>\n getToken().then((token) =>\n token ? fn(token) : Promise.resolve({ ok: false as const, error })\n );\n};\n\nexport const withUserToken = (getToken: TokenGetter<StoredUserToken>) =>\n withToken(getToken, ERRORS.USER_REQUIRED);\n\nexport const withDelegateToken = (getToken: TokenGetter<StoredDelegateToken>) =>\n withToken(getToken, ERRORS.DELEGATE_REQUIRED);\n\nexport const withAccessToken = (getToken: TokenGetter<StoredAccessToken>) =>\n withToken(getToken, ERRORS.ACCESS_REQUIRED);\n","/**\n * Depot methods for the stateful client.\n */\n\nimport type {\n CreateDepot,\n CreateDepotResponse,\n DepotCommit,\n DepotDetail,\n ListDepotsQuery,\n UpdateDepot,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DepotMethods = {\n /** Create a new depot */\n create: (params: CreateDepot) => Promise<FetchResult<CreateDepotResponse>>;\n /** List depots */\n list: (params?: ListDepotsQuery) => Promise<FetchResult<api.ListDepotsResponse>>;\n /** Get depot details */\n get: (depotId: string) => Promise<FetchResult<DepotDetail>>;\n /** Update depot */\n update: (depotId: string, params: UpdateDepot) => Promise<FetchResult<DepotDetail>>;\n /** Delete depot */\n delete: (depotId: string) => Promise<FetchResult<void>>;\n /** Commit new root */\n commit: (depotId: string, params: DepotCommit) => Promise<FetchResult<api.CommitDepotResponse>>;\n};\n\nexport type DepotDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createDepotMethods = ({ baseUrl, realm, tokenSelector }: DepotDeps): DepotMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n create: (params) =>\n requireAccess((t) => api.createDepot(baseUrl, realm, t.tokenBase64, params)),\n\n list: (params) => requireAccess((t) => api.listDepots(baseUrl, realm, t.tokenBase64, params)),\n\n get: (depotId) => requireAccess((t) => api.getDepot(baseUrl, realm, t.tokenBase64, depotId)),\n\n update: (depotId, params) =>\n requireAccess((t) => api.updateDepot(baseUrl, realm, t.tokenBase64, depotId, params)),\n\n delete: (depotId) =>\n requireAccess((t) => api.deleteDepot(baseUrl, realm, t.tokenBase64, depotId)),\n\n commit: (depotId, params) =>\n requireAccess((t) => api.commitDepot(baseUrl, realm, t.tokenBase64, depotId, params)),\n };\n};\n","/**\n * Node methods for the stateful client.\n */\n\nimport type { NodeMetadata, PrepareNodes, PrepareNodesResponse } from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type NodeMethods = {\n /** Get node content */\n get: (nodeKey: string, indexPath: string) => Promise<FetchResult<Uint8Array>>;\n /** Get node metadata */\n getMetadata: (nodeKey: string, indexPath: string) => Promise<FetchResult<NodeMetadata>>;\n /** Prepare nodes for upload */\n prepare: (params: PrepareNodes) => Promise<FetchResult<PrepareNodesResponse>>;\n /** Upload a node */\n put: (nodeKey: string, content: Uint8Array) => Promise<FetchResult<api.NodeUploadResult>>;\n};\n\nexport type NodeDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createNodeMethods = ({ baseUrl, realm, tokenSelector }: NodeDeps): NodeMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n get: (nodeKey, indexPath) =>\n requireAccess((t) => api.getNode(baseUrl, realm, t.tokenBase64, nodeKey, indexPath)),\n\n getMetadata: (nodeKey, indexPath) =>\n requireAccess((t) => api.getNodeMetadata(baseUrl, realm, t.tokenBase64, nodeKey, indexPath)),\n\n prepare: (params) =>\n requireAccess((t) => api.prepareNodes(baseUrl, realm, t.tokenBase64, params)),\n\n put: (nodeKey, content) =>\n requireAccess((t) => api.putNode(baseUrl, realm, t.tokenBase64, nodeKey, content)),\n };\n};\n","/**\n * OAuth methods for the stateful client.\n */\n\nimport * as api from \"../api/index.ts\";\nimport type { RefreshManager } from \"../store/jwt-refresh.ts\";\nimport type { TokenStore } from \"../store/token-store.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { ERRORS } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type OAuthMethods = {\n /** Get Cognito configuration */\n getConfig: () => Promise<FetchResult<api.CognitoConfig>>;\n /** Login with email and password */\n login: (email: string, password: string) => Promise<FetchResult<api.UserInfo>>;\n /** Exchange authorization code for tokens */\n exchangeCode: (\n code: string,\n redirectUri: string,\n codeVerifier?: string\n ) => Promise<FetchResult<api.UserInfo>>;\n /** Get current user info */\n getMe: () => Promise<FetchResult<api.UserInfo>>;\n};\n\nexport type OAuthDeps = {\n baseUrl: string;\n store: TokenStore;\n refreshManager: RefreshManager;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createOAuthMethods = ({\n baseUrl,\n store,\n refreshManager,\n}: OAuthDeps): OAuthMethods => ({\n getConfig: () => api.getOAuthConfig(baseUrl),\n\n login: async (email, password) => {\n const result = await api.login(baseUrl, { email, password });\n if (!result.ok) return result;\n\n const meResult = await api.getMe(baseUrl, result.data.accessToken);\n if (!meResult.ok) return meResult;\n\n store.setUser(api.tokenResponseToStoredUserToken(result.data, meResult.data.userId));\n refreshManager.scheduleProactiveRefresh();\n return meResult;\n },\n\n exchangeCode: async (code, redirectUri, codeVerifier) => {\n const result = await api.exchangeCode(baseUrl, {\n code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n if (!result.ok) return result;\n\n const meResult = await api.getMe(baseUrl, result.data.accessToken);\n if (!meResult.ok) return meResult;\n\n store.setUser(api.tokenResponseToStoredUserToken(result.data, meResult.data.userId));\n refreshManager.scheduleProactiveRefresh();\n return meResult;\n },\n\n getMe: async () => {\n const user = await refreshManager.ensureValidUserToken();\n if (!user) {\n return { ok: false, error: ERRORS.USER_REQUIRED };\n }\n return api.getMe(baseUrl, user.accessToken);\n },\n});\n","/**\n * Ticket methods for the stateful client.\n *\n * Design Principle: All Realm data operations use Access Token.\n * Delegate Token is only for issuing tokens.\n *\n * Two-step Ticket creation flow:\n * 1. Issue Access Token using tokens.delegate() (requires Delegate Token)\n * 2. Create Ticket using tickets.create() (requires Access Token)\n */\n\nimport type {\n CreateTicket,\n CreateTicketResponse,\n ListTicketsQuery,\n TicketDetail,\n TicketSubmit,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TicketMethods = {\n /**\n * Create a new ticket and bind a pre-issued Access Token.\n * Requires Access Token.\n *\n * Note: The Access Token to bind must be issued first using tokens.delegate().\n *\n * @param params.accessTokenId - Pre-issued Access Token ID to bind (for Tool use)\n */\n create: (params: CreateTicket) => Promise<FetchResult<CreateTicketResponse>>;\n /** List tickets */\n list: (params?: ListTicketsQuery) => Promise<FetchResult<api.ListTicketsResponse>>;\n /** Get ticket details */\n get: (ticketId: string) => Promise<FetchResult<TicketDetail>>;\n /** Submit ticket */\n submit: (\n ticketId: string,\n params: TicketSubmit\n ) => Promise<FetchResult<api.SubmitTicketResponse>>;\n};\n\nexport type TicketDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createTicketMethods = ({\n baseUrl,\n realm,\n tokenSelector,\n}: TicketDeps): TicketMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n create: (params) =>\n requireAccess((access) => api.createTicket(baseUrl, realm, access.tokenBase64, params)),\n\n list: (params) =>\n requireAccess((access) => api.listTickets(baseUrl, realm, access.tokenBase64, params)),\n\n get: (ticketId) =>\n requireAccess((access) => api.getTicket(baseUrl, realm, access.tokenBase64, ticketId)),\n\n submit: (ticketId, params) =>\n requireAccess((access) =>\n api.submitTicket(baseUrl, realm, access.tokenBase64, ticketId, params)\n ),\n };\n};\n","/**\n * Token management methods for the stateful client.\n */\n\nimport type { CreateToken, CreateTokenResponse } from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { RefreshManager } from \"../store/jwt-refresh.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { TokenStore } from \"../store/token-store.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport type { StoredAccessToken, StoredDelegateToken } from \"../types/tokens.ts\";\nimport { withDelegateToken, withUserToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TokenMethods = {\n /** Create a new token (User JWT required) */\n create: (params: CreateToken) => Promise<FetchResult<StoredDelegateToken | StoredAccessToken>>;\n /** List tokens (User JWT required) */\n list: (params?: api.ListTokensParams) => Promise<FetchResult<api.ListTokensResponse>>;\n /** Revoke a token (User JWT required) */\n revoke: (tokenId: string) => Promise<FetchResult<void>>;\n /** Delegate a token using current Delegate Token */\n delegate: (\n params: api.DelegateTokenParams\n ) => Promise<FetchResult<StoredDelegateToken | StoredAccessToken>>;\n};\n\nexport type TokenDeps = {\n baseUrl: string;\n realm: string;\n store: TokenStore;\n refreshManager: RefreshManager;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createTokenMethods = ({\n baseUrl,\n realm,\n store,\n refreshManager,\n tokenSelector,\n}: TokenDeps): TokenMethods => {\n const requireUser = withUserToken(() => refreshManager.ensureValidUserToken());\n const requireDelegate = withDelegateToken(() => tokenSelector.ensureDelegateToken());\n\n return {\n create: (params) =>\n requireUser(async (user) => {\n const result = await api.createToken(baseUrl, user.accessToken, params);\n if (!result.ok) return result;\n\n const newToken = toStoredToken(result.data);\n\n // Auto-store if for current realm\n if (params.realm === realm) {\n if (params.type === \"delegate\") {\n store.setDelegate(newToken as StoredDelegateToken);\n } else {\n store.setAccess(newToken as StoredAccessToken);\n }\n }\n\n return { ok: true, data: newToken, status: result.status };\n }),\n\n list: (params) => requireUser((user) => api.listTokens(baseUrl, user.accessToken, params)),\n\n revoke: (tokenId) =>\n requireUser(async (user) => {\n const result = await api.revokeToken(baseUrl, user.accessToken, tokenId);\n if (!result.ok) return { ok: false, error: result.error };\n\n // Clear local token if it matches\n const state = store.getState();\n if (state.delegate?.tokenId === tokenId) store.setDelegate(null);\n if (state.access?.tokenId === tokenId) store.setAccess(null);\n\n return { ok: true, data: undefined, status: result.status };\n }),\n\n delegate: (params) =>\n requireDelegate(async (delegate) => {\n const result = await api.delegateToken(baseUrl, delegate.tokenBase64, params);\n if (!result.ok) return result;\n return { ok: true, data: toStoredToken(result.data), status: result.status };\n }),\n };\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst toStoredToken = (response: CreateTokenResponse): StoredDelegateToken | StoredAccessToken => ({\n tokenId: response.tokenId,\n tokenBase64: response.tokenBase64,\n type: (response as { type?: \"delegate\" | \"access\" }).type ?? \"delegate\",\n issuerId: (response as { issuerId?: string }).issuerId ?? \"\",\n expiresAt: response.expiresAt,\n canUpload: (response as { canUpload?: boolean }).canUpload ?? false,\n canManageDepot: (response as { canManageDepot?: boolean }).canManageDepot ?? false,\n});\n","/**\n * Stateful CASFA Client\n *\n * A closure-based client that manages three-tier token hierarchy:\n * - User JWT: OAuth login token, highest authority\n * - Delegate Token: Re-delegation token, can issue child tokens\n * - Access Token: Data access token, used for CAS operations\n */\n\nimport type { ServiceInfo } from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport { createRefreshManager } from \"../store/jwt-refresh.ts\";\nimport { createTokenSelector } from \"../store/token-selector.ts\";\nimport { createTokenStore } from \"../store/token-store.ts\";\nimport type {\n ClientConfig,\n OnAuthRequiredCallback,\n OnTokenChangeCallback,\n TokenStorageProvider,\n} from \"../types/client.ts\";\nimport type { StoredAccessToken, StoredDelegateToken, TokenState } from \"../types/tokens.ts\";\nimport { createDepotMethods, type DepotMethods } from \"./depots.ts\";\nimport { createNodeMethods, type NodeMethods } from \"./nodes.ts\";\nimport { createOAuthMethods, type OAuthMethods } from \"./oauth.ts\";\nimport { createTicketMethods, type TicketMethods } from \"./tickets.ts\";\nimport { createTokenMethods, type TokenMethods } from \"./tokens.ts\";\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport type { DepotMethods, NodeMethods, OAuthMethods, TicketMethods, TokenMethods };\n\nexport type { ClientConfig, OnAuthRequiredCallback, OnTokenChangeCallback, TokenStorageProvider };\n\n// ============================================================================\n// Client Type\n// ============================================================================\n\n/**\n * The stateful CASFA client.\n */\nexport type CasfaClient = {\n /** Get current token state */\n getState: () => TokenState;\n /** Get server info */\n getServerInfo: () => ServiceInfo | null;\n\n /** Set delegate token (e.g., from external source) */\n setDelegateToken: (token: StoredDelegateToken) => void;\n /** Set access token (e.g., from external source) */\n setAccessToken: (token: StoredAccessToken) => void;\n /** Clear all tokens and logout */\n logout: () => void;\n\n /** OAuth methods */\n oauth: OAuthMethods;\n /** Token management methods */\n tokens: TokenMethods;\n /** Ticket methods */\n tickets: TicketMethods;\n /** Depot methods */\n depots: DepotMethods;\n /** Node methods */\n nodes: NodeMethods;\n};\n\n// ============================================================================\n// Client Factory\n// ============================================================================\n\n/**\n * Create a stateful CASFA client.\n */\nexport const createClient = async (config: ClientConfig): Promise<CasfaClient> => {\n const { baseUrl, realm, tokenStorage, onTokenChange, onAuthRequired, defaultTokenTtl } = config;\n\n // Initialize token store\n const store = createTokenStore({\n storage: tokenStorage,\n onTokenChange,\n onAuthRequired,\n });\n await store.initialize();\n\n // Initialize refresh manager\n const refreshManager = createRefreshManager({\n store,\n baseUrl,\n onAuthRequired,\n });\n\n // Fetch server info\n let serverInfo: ServiceInfo | null = null;\n const infoResult = await api.fetchServiceInfo(baseUrl);\n if (infoResult.ok) {\n serverInfo = infoResult.data;\n }\n\n // Initialize token selector\n const tokenSelector = createTokenSelector({\n store,\n baseUrl,\n realm,\n serverInfo,\n defaultTokenTtl,\n });\n\n // Shared dependencies\n const deps = { baseUrl, realm, store, refreshManager, tokenSelector };\n\n // Build client\n return {\n getState: () => store.getState(),\n getServerInfo: () => serverInfo,\n\n setDelegateToken: (token) => store.setDelegate(token),\n setAccessToken: (token) => store.setAccess(token),\n\n logout: () => {\n refreshManager.cancelScheduledRefresh();\n store.clear();\n },\n\n oauth: createOAuthMethods(deps),\n tokens: createTokenMethods(deps),\n tickets: createTicketMethods(deps),\n depots: createDepotMethods(deps),\n nodes: createNodeMethods(deps),\n };\n};\n"],"mappings":"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","names":["delegateToken","delegateToken","getToken"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/utils/http.ts", "../src/api/claim.ts", "../src/api/delegates.ts", "../src/api/depots.ts", "../src/api/filesystem.ts", "../src/api/info.ts", "../src/api/nodes.ts", "../src/api/oauth.ts", "../src/api/requests.ts", "../src/api/tokens.ts", "../src/store/token-checks.ts", "../src/store/jwt-refresh.ts", "../src/store/token-selector.ts", "../src/types/tokens.ts", "../src/store/token-store.ts", "../src/client/helpers.ts", "../src/client/delegates.ts", "../src/client/depots.ts", "../src/client/filesystem.ts", "../src/client/nodes.ts", "../src/client/oauth.ts", "../src/client/tokens.ts", "../src/client/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Fetch utilities for the stateful client.\n */\n\nimport type { ClientError, FetchResult } from \"../types/client.ts\";\n\n// ============================================================================\n// Error Handling\n// ============================================================================\n\n/**\n * Map HTTP status to error code.\n */\nexport const statusToErrorCode = (status: number): string => {\n switch (status) {\n case 401:\n return \"UNAUTHORIZED\";\n case 403:\n return \"FORBIDDEN\";\n case 404:\n return \"NOT_FOUND\";\n case 409:\n return \"CONFLICT\";\n case 400:\n case 422:\n return \"VALIDATION_ERROR\";\n case 429:\n return \"RATE_LIMITED\";\n default:\n return \"UNKNOWN\";\n }\n};\n\n/**\n * Create error from HTTP response.\n */\nexport const createErrorFromResponse = async (response: Response): Promise<ClientError> => {\n const code = statusToErrorCode(response.status);\n let message = response.statusText;\n let details: unknown = null;\n\n try {\n const body = (await response.json()) as Record<string, unknown>;\n // Prefer body.message (descriptive) over body.error (may be a code like \"validation_error\")\n if (typeof body.message === \"string\") {\n message = body.message;\n } else if (typeof body.error === \"string\") {\n // Only use body.error as message if body.message is absent\n message = body.error;\n }\n // Handle Zod validation error objects (from @hono/zod-validator default hook)\n if (body.error && typeof body.error === \"object\" && \"issues\" in (body.error as object)) {\n const issues = (\n body.error as { issues: Array<{ message: string; path?: Array<string | number> }> }\n ).issues;\n if (Array.isArray(issues) && issues.length > 0) {\n message = issues\n .map((i) => (i.path?.length ? `${i.path.join(\".\")}: ${i.message}` : i.message))\n .join(\"; \");\n }\n }\n details = body;\n } catch {\n // Response body is not JSON, use status text\n }\n\n return { code, message, status: response.status, details };\n};\n\n/**\n * Create a network error.\n */\nexport const createNetworkError = (err: unknown): ClientError => ({\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network request failed\",\n details: err,\n});\n\n// ============================================================================\n// Fetch Function\n// ============================================================================\n\nexport type FetchOptions = {\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n headers?: Record<string, string>;\n body?: unknown;\n /** Expected response type */\n responseType?: \"json\" | \"blob\" | \"text\" | \"none\";\n};\n\n/**\n * Make a fetch request with error handling.\n */\nexport const fetchApi = async <T>(\n url: string,\n options: FetchOptions = {}\n): Promise<FetchResult<T>> => {\n const { method = \"GET\", headers = {}, body, responseType = \"json\" } = options;\n\n const requestHeaders: Record<string, string> = { ...headers };\n\n // Add content-type for JSON body\n if (body !== undefined && !requestHeaders[\"Content-Type\"]) {\n requestHeaders[\"Content-Type\"] = \"application/json\";\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers: requestHeaders,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const error = await createErrorFromResponse(response);\n return { ok: false, error };\n }\n\n // Parse response based on type\n let data: T;\n switch (responseType) {\n case \"json\":\n data = (await response.json()) as T;\n break;\n case \"blob\":\n data = (await response.blob()) as T;\n break;\n case \"text\":\n data = (await response.text()) as T;\n break;\n case \"none\":\n data = undefined as T;\n break;\n }\n\n return { ok: true, data, status: response.status };\n } catch (err) {\n return { ok: false, error: createNetworkError(err) };\n }\n};\n\n/**\n * Make an authenticated fetch request.\n */\nexport const fetchWithAuth = async <T>(\n url: string,\n authHeader: string | null,\n options: FetchOptions = {}\n): Promise<FetchResult<T>> => {\n const headers = { ...options.headers };\n\n if (authHeader) {\n headers.Authorization = authHeader;\n }\n\n return fetchApi<T>(url, { ...options, headers });\n};\n",
|
|
6
|
+
"/**\n * Claim API functions.\n *\n * Token Requirement:\n * - POST /api/realm/{realmId}/nodes/{key}/claim: Access Token with canUpload (legacy)\n * - POST /api/realm/{realmId}/nodes/claim: Access Token with canUpload (batch)\n */\n\nimport type {\n BatchClaimRequest,\n BatchClaimResponse,\n ClaimNodeRequest,\n ClaimNodeResponse,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n/**\n * Claim ownership of a CAS node via Proof-of-Possession (legacy single claim).\n * Requires Access Token with canUpload permission.\n */\nexport const claimNode = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n params: ClaimNodeRequest\n): Promise<FetchResult<ClaimNodeResponse>> => {\n return fetchWithAuth<ClaimNodeResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}/claim`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * Batch claim ownership of CAS nodes.\n * Supports PoP and path-based claims in a single request.\n * Requires Access Token with canUpload permission.\n */\nexport const batchClaimNodes = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: BatchClaimRequest\n): Promise<FetchResult<BatchClaimResponse>> => {\n return fetchWithAuth<BatchClaimResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/claim`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n",
|
|
7
|
+
"/**\n * Delegate management API functions.\n *\n * Token Requirement:\n * - All delegate operations require Access Token.\n *\n * Routes:\n * - POST /api/realm/{realmId}/delegates — create child delegate\n * - GET /api/realm/{realmId}/delegates — list delegates\n * - GET /api/realm/{realmId}/delegates/:delegateId — get delegate detail\n * - POST /api/realm/{realmId}/delegates/:delegateId/revoke — revoke delegate\n */\n\nimport type {\n CreateDelegateRequest,\n CreateDelegateResponse,\n DelegateDetail,\n DelegateListItem,\n ListDelegatesQuery,\n RevokeDelegateResponse,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ListDelegatesResponse = {\n delegates: DelegateListItem[];\n nextCursor: string | null;\n};\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Create a child delegate.\n * Requires Access Token from parent delegate.\n */\nexport const createDelegate = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: CreateDelegateRequest\n): Promise<FetchResult<CreateDelegateResponse>> => {\n return fetchWithAuth<CreateDelegateResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/delegates`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * List child delegates.\n * Requires Access Token.\n */\nexport const listDelegates = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params?: ListDelegatesQuery\n): Promise<FetchResult<ListDelegatesResponse>> => {\n const query = new URLSearchParams();\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n if (params?.includeRevoked) query.set(\"includeRevoked\", \"true\");\n\n const queryString = query.toString();\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/delegates${queryString ? `?${queryString}` : \"\"}`;\n\n return fetchWithAuth<ListDelegatesResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * Get delegate details.\n * Requires Access Token.\n */\nexport const getDelegate = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n delegateId: string\n): Promise<FetchResult<DelegateDetail>> => {\n return fetchWithAuth<DelegateDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/delegates/${encodeURIComponent(delegateId)}`,\n `Bearer ${accessTokenBase64}`\n );\n};\n\n/**\n * Revoke a delegate.\n * Requires Access Token.\n */\nexport const revokeDelegate = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n delegateId: string\n): Promise<FetchResult<RevokeDelegateResponse>> => {\n return fetchWithAuth<RevokeDelegateResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/delegates/${encodeURIComponent(delegateId)}/revoke`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n }\n );\n};\n",
|
|
8
|
+
"/**\n * Depot API functions.\n *\n * Token Requirement:\n * - All depot operations require Access Token with canManageDepot permission.\n */\n\nimport type {\n CreateDepot,\n CreateDepotResponse,\n DepotCommit,\n DepotDetail,\n DepotListItem,\n ListDepotsQuery,\n UpdateDepot,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ListDepotsResponse = {\n depots: DepotListItem[];\n nextCursor: string | null;\n};\n\nexport type CommitDiffEntry = {\n type: \"added\" | \"removed\" | \"modified\" | \"moved\";\n path: string;\n kind: \"file\" | \"dir\" | null;\n /** Destination path for moved entries */\n pathTo: string | null;\n};\n\nexport type CommitDepotResponse = {\n depotId: string;\n root: string;\n updatedAt: number;\n /** Previous root before this commit (null if first commit) */\n previousRoot: string | null;\n};\n\n// ============================================================================\n// Conflict Types\n// ============================================================================\n\n/** 409 Conflict error body returned when expectedRoot doesn't match server root */\nexport type CommitConflictInfo = {\n code: \"CONFLICT\";\n message: string;\n /** Current server root that doesn't match expectedRoot */\n currentRoot: string;\n /** The expectedRoot the client sent */\n expectedRoot: string | null;\n};\n\n/** Type guard for commit conflict errors */\nexport function isCommitConflict(error: unknown): error is CommitConflictInfo {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code: unknown }).code === \"CONFLICT\" &&\n \"currentRoot\" in error\n );\n}\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Create a new depot.\n * Requires Access Token with canManageDepot.\n */\nexport const createDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: CreateDepot\n): Promise<FetchResult<CreateDepotResponse>> => {\n return fetchWithAuth<CreateDepotResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * List depots.\n * Requires Access Token.\n */\nexport const listDepots = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params?: ListDepotsQuery\n): Promise<FetchResult<ListDepotsResponse>> => {\n const query = new URLSearchParams();\n if (params?.limit) query.set(\"limit\", String(params.limit));\n if (params?.cursor) query.set(\"cursor\", params.cursor);\n\n const queryString = query.toString();\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots${queryString ? `?${queryString}` : \"\"}`;\n\n return fetchWithAuth<ListDepotsResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * Get depot details.\n * Requires Access Token.\n */\nexport const getDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string\n): Promise<FetchResult<DepotDetail>> => {\n return fetchWithAuth<DepotDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`\n );\n};\n\n/**\n * Update depot metadata.\n * Requires Access Token with canManageDepot.\n */\nexport const updateDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string,\n params: UpdateDepot\n): Promise<FetchResult<DepotDetail>> => {\n return fetchWithAuth<DepotDetail>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"PATCH\",\n body: params,\n }\n );\n};\n\n/**\n * Delete a depot.\n * Requires Access Token with canManageDepot.\n */\nexport const deleteDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string\n): Promise<FetchResult<void>> => {\n return fetchWithAuth<void>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"DELETE\",\n responseType: \"none\",\n }\n );\n};\n\n/**\n * Commit new root to depot.\n * Requires Access Token with canManageDepot.\n */\nexport const commitDepot = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n depotId: string,\n params: DepotCommit\n): Promise<FetchResult<CommitDepotResponse>> => {\n return fetchWithAuth<CommitDepotResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}/commit`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n",
|
|
9
|
+
"/**\n * Filesystem API functions for @casfa/client.\n *\n * All filesystem operations are mounted under:\n * /api/realm/{realmId}/nodes/fs/{nodeKey}/{op}\n *\n * Where nodeKey is the depot's current root node.\n *\n * Token Requirements:\n * - Read ops (stat, ls, read): Access Token (nodeKey must pass Direct Authorization Check)\n * - Write ops (write, mkdir, rm, mv, cp, rewrite): Access Token with canUpload\n */\n\nimport type {\n FsCpResponse,\n FsLsResponse,\n FsMkdirResponse,\n FsMvResponse,\n FsRewriteEntry,\n FsRewriteResponse,\n FsRmResponse,\n FsStatResponse,\n FsWriteResponse,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction buildFsUrl(baseUrl: string, realm: string, rootKey: string, op: string): string {\n return `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/fs/${encodeURIComponent(rootKey)}/${op}`;\n}\n\n// ============================================================================\n// Read Operations\n// ============================================================================\n\n/**\n * GET /fs/stat — Get file/directory metadata.\n */\nexport const fsStat = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path?: string\n): Promise<FetchResult<FsStatResponse>> => {\n const params = new URLSearchParams();\n if (path) params.set(\"path\", path);\n const qs = params.toString();\n const url = `${buildFsUrl(baseUrl, realm, rootKey, \"stat\")}${qs ? `?${qs}` : \"\"}`;\n\n return fetchWithAuth<FsStatResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * GET /fs/ls — List directory contents with pagination.\n */\nexport const fsLs = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path?: string,\n opts?: { limit?: number; cursor?: string }\n): Promise<FetchResult<FsLsResponse>> => {\n const params = new URLSearchParams();\n if (path) params.set(\"path\", path);\n if (opts?.limit) params.set(\"limit\", String(opts.limit));\n if (opts?.cursor) params.set(\"cursor\", opts.cursor);\n const qs = params.toString();\n const url = `${buildFsUrl(baseUrl, realm, rootKey, \"ls\")}${qs ? `?${qs}` : \"\"}`;\n\n return fetchWithAuth<FsLsResponse>(url, `Bearer ${accessTokenBase64}`);\n};\n\n/**\n * GET /fs/read — Read file content as Blob.\n */\nexport const fsRead = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path: string\n): Promise<FetchResult<Blob>> => {\n const params = new URLSearchParams({ path });\n const url = `${buildFsUrl(baseUrl, realm, rootKey, \"read\")}?${params}`;\n\n // Custom fetch — need Blob response, fetchWithAuth only does JSON\n try {\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${accessTokenBase64}` },\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as Record<string, unknown>;\n if (typeof body.message === \"string\") message = body.message;\n } catch {\n // ignore\n }\n return {\n ok: false,\n error: { code: String(response.status), message, status: response.status },\n };\n }\n\n const blob = await response.blob();\n return { ok: true, data: blob, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n\n// ============================================================================\n// Write Operations\n// ============================================================================\n\n/**\n * POST /fs/write — Create or overwrite a file.\n * Body is raw binary. Path via query param, content-type via header.\n */\nexport const fsWrite = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path: string,\n data: Blob | ArrayBuffer | Uint8Array,\n contentType = \"application/octet-stream\"\n): Promise<FetchResult<FsWriteResponse>> => {\n const params = new URLSearchParams({ path });\n const url = `${buildFsUrl(baseUrl, realm, rootKey, \"write\")}?${params}`;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Blob accepts Uint8Array at runtime\n const body: Blob = data instanceof Blob ? data : new Blob([data as any], { type: contentType });\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessTokenBase64}`,\n \"Content-Type\": contentType,\n \"Content-Length\": String(body.size),\n },\n body,\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as Record<string, unknown>;\n if (typeof body.message === \"string\") message = body.message;\n } catch {\n // ignore\n }\n return {\n ok: false,\n error: { code: String(response.status), message, status: response.status },\n };\n }\n\n const result = (await response.json()) as FsWriteResponse;\n return { ok: true, data: result, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n\n/**\n * POST /fs/mkdir — Create a directory.\n */\nexport const fsMkdir = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path: string\n): Promise<FetchResult<FsMkdirResponse>> => {\n const url = buildFsUrl(baseUrl, realm, rootKey, \"mkdir\");\n\n return fetchWithAuth<FsMkdirResponse>(url, `Bearer ${accessTokenBase64}`, {\n method: \"POST\",\n body: { path },\n });\n};\n\n/**\n * POST /fs/rm — Remove a file or directory.\n */\nexport const fsRm = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n path: string\n): Promise<FetchResult<FsRmResponse>> => {\n const url = buildFsUrl(baseUrl, realm, rootKey, \"rm\");\n\n return fetchWithAuth<FsRmResponse>(url, `Bearer ${accessTokenBase64}`, {\n method: \"POST\",\n body: { path },\n });\n};\n\n/**\n * POST /fs/mv — Move or rename a file/directory.\n */\nexport const fsMv = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n from: string,\n to: string\n): Promise<FetchResult<FsMvResponse>> => {\n const url = buildFsUrl(baseUrl, realm, rootKey, \"mv\");\n\n return fetchWithAuth<FsMvResponse>(url, `Bearer ${accessTokenBase64}`, {\n method: \"POST\",\n body: { from, to },\n });\n};\n\n/**\n * POST /fs/cp — Copy a file or directory.\n */\nexport const fsCp = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n from: string,\n to: string\n): Promise<FetchResult<FsCpResponse>> => {\n const url = buildFsUrl(baseUrl, realm, rootKey, \"cp\");\n\n return fetchWithAuth<FsCpResponse>(url, `Bearer ${accessTokenBase64}`, {\n method: \"POST\",\n body: { from, to },\n });\n};\n\n/**\n * POST /fs/rewrite — Batch rewrite directory tree.\n */\nexport const fsRewrite = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n rootKey: string,\n entries?: Record<string, FsRewriteEntry>,\n deletes?: string[]\n): Promise<FetchResult<FsRewriteResponse>> => {\n const url = buildFsUrl(baseUrl, realm, rootKey, \"rewrite\");\n\n return fetchWithAuth<FsRewriteResponse>(url, `Bearer ${accessTokenBase64}`, {\n method: \"POST\",\n body: { entries, deletes },\n });\n};\n",
|
|
10
|
+
"/**\n * Service info API.\n */\n\nimport type { ServiceInfo } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchApi } from \"../utils/http.ts\";\n\n/**\n * Fetch service info from /api/info.\n */\nexport const fetchServiceInfo = async (baseUrl: string): Promise<FetchResult<ServiceInfo>> => {\n return fetchApi<ServiceInfo>(`${baseUrl}/api/info`);\n};\n\n/**\n * Health check.\n */\nexport const healthCheck = async (baseUrl: string): Promise<FetchResult<{ status: string }>> => {\n return fetchApi<{ status: string }>(`${baseUrl}/api/health`);\n};\n",
|
|
11
|
+
"/**\n * Node API functions.\n *\n * Token Requirement:\n * - GET /nodes/raw/:nodeKey: Access Token (Direct Authorization Check)\n * - GET /nodes/metadata/:nodeKey: Access Token (Direct Authorization Check)\n * - POST /nodes/check: Access Token\n * - PUT /nodes/raw/:nodeKey: Access Token with canUpload\n */\n\nimport type { CheckNodes, CheckNodesResponse, NodeMetadata } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type NodeUploadResult = {\n nodeKey: string;\n status: \"created\" | \"exists\";\n};\n\n// ============================================================================\n// Access Token APIs\n// ============================================================================\n\n/**\n * Get node content.\n * Requires Access Token with Direct Authorization on the nodeKey.\n */\nexport const getNode = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string\n): Promise<FetchResult<Uint8Array>> => {\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/raw/${encodeURIComponent(nodeKey)}`;\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${accessTokenBase64}`,\n };\n\n const response = await fetch(url, { headers });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n return {\n ok: false,\n error: {\n code: String(response.status),\n message: (error as { message?: string }).message ?? response.statusText,\n status: response.status,\n },\n };\n }\n\n const data = new Uint8Array(await response.arrayBuffer());\n return { ok: true, data, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n\n/**\n * Get node content via navigation path (GET /nodes/raw/:key/~0/~1/...).\n * Requires Access Token with Direct Authorization on the starting nodeKey.\n */\nexport const getNodeNavigated = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n indexPath: string\n): Promise<FetchResult<Uint8Array>> => {\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/raw/${encodeURIComponent(nodeKey)}/${indexPath}`;\n\n try {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${accessTokenBase64}`,\n };\n\n const response = await fetch(url, { headers });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n return {\n ok: false,\n error: {\n code: String(response.status),\n message: (error as { message?: string }).message ?? response.statusText,\n status: response.status,\n },\n };\n }\n\n const data = new Uint8Array(await response.arrayBuffer());\n return { ok: true, data, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n\n/**\n * Get node metadata.\n * Requires Access Token with Direct Authorization on the nodeKey.\n */\nexport const getNodeMetadata = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string\n): Promise<FetchResult<NodeMetadata>> => {\n return fetchWithAuth<NodeMetadata>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/metadata/${encodeURIComponent(nodeKey)}`,\n `Bearer ${accessTokenBase64}`\n );\n};\n\n/**\n * Check nodes status on the server.\n * Returns three-way classification: missing, owned, unowned.\n * Requires Access Token.\n */\nexport const checkNodes = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n params: CheckNodes\n): Promise<FetchResult<CheckNodesResponse>> => {\n return fetchWithAuth<CheckNodesResponse>(\n `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/check`,\n `Bearer ${accessTokenBase64}`,\n {\n method: \"POST\",\n body: params,\n }\n );\n};\n\n/**\n * Upload a node.\n * Requires Access Token with canUpload.\n */\nexport const putNode = async (\n baseUrl: string,\n realm: string,\n accessTokenBase64: string,\n nodeKey: string,\n content: Uint8Array\n): Promise<FetchResult<NodeUploadResult>> => {\n const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/raw/${encodeURIComponent(nodeKey)}`;\n\n try {\n const response = await fetch(url, {\n method: \"PUT\",\n headers: {\n Authorization: `Bearer ${accessTokenBase64}`,\n \"Content-Type\": \"application/octet-stream\",\n },\n // Uint8Array is valid as fetch body in all runtimes, but TS lib\n // variations (DOM vs Node vs ESNext) disagree on the exact type.\n body: content as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }));\n return {\n ok: false,\n error: {\n code: String(response.status),\n message: (error as { message?: string }).message ?? response.statusText,\n status: response.status,\n },\n };\n }\n\n const data = (await response.json()) as NodeUploadResult;\n return { ok: true, data, status: response.status };\n } catch (err) {\n return {\n ok: false,\n error: {\n code: \"NETWORK_ERROR\",\n message: err instanceof Error ? err.message : \"Network error\",\n },\n };\n }\n};\n",
|
|
12
|
+
"/**\n * OAuth API functions.\n */\n\nimport type { Login, Refresh, TokenExchange } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport type { StoredUserToken } from \"../types/tokens.ts\";\nimport { fetchApi, fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type CognitoConfig = {\n region: string;\n userPoolId: string;\n clientId: string;\n domain: string;\n};\n\nexport type TokenResponse = {\n accessToken: string;\n refreshToken: string;\n expiresIn: number;\n idToken?: string;\n};\n\nexport type UserInfo = {\n userId: string;\n email: string;\n role: string;\n /** Root delegate ID for this user (null if none created yet) */\n rootDelegateId: string | null;\n};\n\n// ============================================================================\n// Public OAuth API\n// ============================================================================\n\n/**\n * Get Cognito configuration.\n */\nexport const getOAuthConfig = async (baseUrl: string): Promise<FetchResult<CognitoConfig>> => {\n return fetchApi<CognitoConfig>(`${baseUrl}/api/oauth/config`);\n};\n\n/**\n * Exchange authorization code for tokens.\n */\nexport const exchangeCode = async (\n baseUrl: string,\n params: TokenExchange\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/token`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Login with email and password.\n */\nexport const login = async (\n baseUrl: string,\n params: Login\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/login`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Refresh access token.\n */\nexport const refresh = async (\n baseUrl: string,\n params: Refresh\n): Promise<FetchResult<TokenResponse>> => {\n return fetchApi<TokenResponse>(`${baseUrl}/api/oauth/refresh`, {\n method: \"POST\",\n body: params,\n });\n};\n\n// ============================================================================\n// Authenticated OAuth API\n// ============================================================================\n\n/**\n * Get current user info.\n * Requires User JWT.\n */\nexport const getMe = async (\n baseUrl: string,\n userAccessToken: string\n): Promise<FetchResult<UserInfo>> => {\n return fetchWithAuth<UserInfo>(`${baseUrl}/api/oauth/me`, `Bearer ${userAccessToken}`);\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Convert token response to stored user token.\n *\n * Prefers idToken over accessToken for Bearer auth because\n * Cognito access tokens do not contain email/name claims.\n */\nexport const tokenResponseToStoredUserToken = (\n response: TokenResponse,\n userId: string\n): StoredUserToken => ({\n accessToken: response.idToken ?? response.accessToken,\n refreshToken: response.refreshToken,\n userId,\n expiresAt: Date.now() + response.expiresIn * 1000,\n});\n",
|
|
13
|
+
"/**\n * Client Authorization Request API functions.\n *\n * For CLI/desktop apps to request tokens through user approval.\n */\n\nimport type {\n ApproveRequest,\n ApproveRequestResponse,\n CreateAuthRequest,\n CreateAuthRequestResponse,\n DenyRequest,\n DenyRequestResponse,\n PollRequestResponse,\n} from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchApi, fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Public APIs (No auth required)\n// ============================================================================\n\n/**\n * Create an authorization request.\n * No auth required - called by CLI/desktop clients.\n */\nexport const createAuthRequest = async (\n baseUrl: string,\n params: CreateAuthRequest\n): Promise<FetchResult<CreateAuthRequestResponse>> => {\n return fetchApi<CreateAuthRequestResponse>(`${baseUrl}/api/tokens/requests`, {\n method: \"POST\",\n body: params,\n });\n};\n\n/**\n * Poll authorization request status.\n * No auth required - called by CLI/desktop clients.\n */\nexport const pollAuthRequest = async (\n baseUrl: string,\n requestId: string\n): Promise<FetchResult<PollRequestResponse>> => {\n return fetchApi<PollRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/poll`\n );\n};\n\n// ============================================================================\n// User JWT APIs (For approving/rejecting requests)\n// ============================================================================\n\n/**\n * Get authorization request details.\n * Requires User JWT.\n */\nexport const getAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string\n): Promise<FetchResult<PollRequestResponse>> => {\n return fetchWithAuth<PollRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}`,\n `Bearer ${userAccessToken}`\n );\n};\n\n/**\n * Approve an authorization request.\n * Requires User JWT.\n */\nexport const approveAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string,\n params?: ApproveRequest\n): Promise<FetchResult<ApproveRequestResponse>> => {\n return fetchWithAuth<ApproveRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/approve`,\n `Bearer ${userAccessToken}`,\n {\n method: \"POST\",\n body: params ?? {},\n }\n );\n};\n\n/**\n * Reject an authorization request.\n * Requires User JWT.\n */\nexport const rejectAuthRequest = async (\n baseUrl: string,\n userAccessToken: string,\n requestId: string,\n params?: DenyRequest\n): Promise<FetchResult<DenyRequestResponse>> => {\n return fetchWithAuth<DenyRequestResponse>(\n `${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/reject`,\n `Bearer ${userAccessToken}`,\n {\n method: \"POST\",\n body: params ?? {},\n }\n );\n};\n",
|
|
14
|
+
"/**\n * Token API functions (new 2-tier model).\n *\n * Token Endpoint:\n * - POST /api/auth/refresh: Bearer RT → new RT + AT (child delegates only)\n *\n * Root delegates no longer need a dedicated endpoint — the server's\n * access-token-auth middleware auto-creates the root delegate on first\n * JWT-authenticated request.\n */\n\nimport type { RefreshTokenResponse } from \"@casfa/protocol\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { fetchWithAuth } from \"../utils/http.ts\";\n\n// ============================================================================\n// Refresh Token API (RT → new RT + AT, child delegates only)\n// ============================================================================\n\n/**\n * Rotate refresh token to get new RT + AT pair.\n * Uses Bearer auth with the refresh token.\n * Only valid for child delegates (depth > 0).\n */\nexport const refreshToken = async (\n baseUrl: string,\n refreshTokenBase64: string\n): Promise<FetchResult<RefreshTokenResponse>> => {\n return fetchWithAuth<RefreshTokenResponse>(\n `${baseUrl}/api/auth/refresh`,\n `Bearer ${refreshTokenBase64}`,\n {\n method: \"POST\",\n }\n );\n};\n",
|
|
15
|
+
"/**\n * Token validity checks for the two-tier model.\n *\n * Root delegates use JWT directly (no AT/RT), so root-specific\n * AT validity checks have been removed.\n */\n\nimport type { StoredAccessToken, StoredUserToken } from \"../types/tokens.ts\";\n\n// ============================================================================\n// Validity Checks\n// ============================================================================\n\n/**\n * Default buffer time before expiration (60 seconds).\n */\nexport const DEFAULT_EXPIRY_BUFFER_MS = 60_000;\n\n/**\n * Check if a token is valid (not expired with buffer).\n */\nexport const isTokenValid = (\n token: { expiresAt: number } | null,\n bufferMs: number = DEFAULT_EXPIRY_BUFFER_MS\n): boolean => {\n if (!token) return false;\n return Date.now() + bufferMs < token.expiresAt;\n};\n\n/**\n * Check if token is expiring soon and should be refreshed proactively.\n * Used for JWT refresh scheduling.\n */\nexport const isTokenExpiringSoon = (\n token: { expiresAt: number } | null,\n windowMs: number = 5 * 60_000 // 5 minutes\n): boolean => {\n if (!token) return false;\n return Date.now() + windowMs >= token.expiresAt;\n};\n\n/**\n * Check if user JWT is valid.\n */\nexport const isUserTokenValid = (userToken: StoredUserToken | null, bufferMs?: number): boolean => {\n return isTokenValid(userToken, bufferMs);\n};\n\n/**\n * Check if a StoredAccessToken (view) is valid.\n */\nexport const isStoredAccessTokenValid = (\n accessToken: StoredAccessToken | null,\n bufferMs?: number\n): boolean => {\n return isTokenValid(accessToken, bufferMs);\n};\n",
|
|
16
|
+
"/**\n * JWT refresh management with promise deduplication.\n */\n\nimport type { OnAuthRequiredCallback } from \"../types/client.ts\";\nimport type { StoredUserToken } from \"../types/tokens.ts\";\nimport { isUserTokenValid } from \"./token-checks.ts\";\nimport type { TokenStore } from \"./token-store.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RefreshManager = {\n /**\n * Ensure user token is valid, refreshing if needed.\n * Returns the valid user token or null if refresh failed.\n */\n ensureValidUserToken: () => Promise<StoredUserToken | null>;\n\n /**\n * Schedule proactive refresh before expiration.\n */\n scheduleProactiveRefresh: () => void;\n\n /**\n * Cancel any scheduled refresh.\n */\n cancelScheduledRefresh: () => void;\n};\n\nexport type RefreshManagerConfig = {\n store: TokenStore;\n baseUrl: string;\n onAuthRequired?: OnAuthRequiredCallback;\n};\n\n// ============================================================================\n// Refresh API Call\n// ============================================================================\n\ntype RefreshResponse = {\n accessToken: string;\n idToken?: string;\n refreshToken?: string;\n expiresIn: number;\n};\n\nconst callRefreshApi = async (\n baseUrl: string,\n refreshToken: string\n): Promise<RefreshResponse | null> => {\n try {\n const response = await fetch(`${baseUrl}/api/oauth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as RefreshResponse;\n } catch {\n return null;\n }\n};\n\n// ============================================================================\n// Refresh Manager Factory\n// ============================================================================\n\n/**\n * Create a refresh manager for JWT token refresh.\n */\nexport const createRefreshManager = (config: RefreshManagerConfig): RefreshManager => {\n const { store, baseUrl, onAuthRequired } = config;\n\n // Promise deduplication: only one refresh in flight at a time\n let refreshPromise: Promise<StoredUserToken | null> | null = null;\n\n // Scheduled refresh timer\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n\n const doRefresh = async (): Promise<StoredUserToken | null> => {\n const state = store.getState();\n const userToken = state.user;\n\n if (!userToken?.refreshToken) {\n onAuthRequired?.();\n return null;\n }\n\n const result = await callRefreshApi(baseUrl, userToken.refreshToken);\n\n if (!result) {\n // Refresh failed, require re-auth\n store.setUser(null);\n onAuthRequired?.();\n return null;\n }\n\n const newUserToken: StoredUserToken = {\n accessToken: result.idToken ?? result.accessToken,\n refreshToken: result.refreshToken ?? userToken.refreshToken,\n userId: userToken.userId,\n expiresAt: Date.now() + result.expiresIn * 1000,\n };\n\n store.setUser(newUserToken);\n return newUserToken;\n };\n\n const ensureValidUserToken = async (): Promise<StoredUserToken | null> => {\n const state = store.getState();\n const userToken = state.user;\n\n // Check if current token is valid\n if (isUserTokenValid(userToken)) {\n return userToken;\n }\n\n // No user token at all\n if (!userToken) {\n return null;\n }\n\n // Need to refresh - use deduplication\n if (!refreshPromise) {\n refreshPromise = doRefresh().finally(() => {\n refreshPromise = null;\n });\n }\n\n return refreshPromise;\n };\n\n const scheduleProactiveRefresh = () => {\n cancelScheduledRefresh();\n\n const state = store.getState();\n const userToken = state.user;\n\n if (!userToken) return;\n\n // Schedule refresh 5 minutes before expiration\n const refreshTime = userToken.expiresAt - Date.now() - 5 * 60_000;\n\n if (refreshTime <= 0) {\n // Already expiring soon, refresh immediately\n ensureValidUserToken();\n return;\n }\n\n refreshTimer = setTimeout(() => {\n ensureValidUserToken().then((newToken) => {\n if (newToken) {\n // Schedule next refresh\n scheduleProactiveRefresh();\n }\n });\n }, refreshTime);\n };\n\n const cancelScheduledRefresh = () => {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = null;\n }\n };\n\n return {\n ensureValidUserToken,\n scheduleProactiveRefresh,\n cancelScheduledRefresh,\n };\n};\n",
|
|
17
|
+
"/**\n * Token selector — ensures the client has valid auth for API calls.\n *\n * The server auto-creates the root delegate on first JWT request,\n * so the client just needs a valid user JWT. No explicit root delegate\n * creation step is required.\n */\n\nimport type { StoredAccessToken } from \"../types/tokens.ts\";\nimport { isUserTokenValid } from \"./token-checks.ts\";\nimport type { TokenStore } from \"./token-store.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TokenSelectorConfig = {\n store: TokenStore;\n baseUrl: string;\n realm: string;\n};\n\nexport type TokenSelector = {\n /**\n * Get an auth token for realm API calls.\n *\n * Returns a StoredAccessToken where `tokenBase64` is the user's JWT.\n * The server's unified auth middleware detects JWT (contains '.') and\n * auto-creates the root delegate if needed.\n */\n ensureAccessToken: () => Promise<StoredAccessToken | null>;\n};\n\n// ============================================================================\n// Token Selector Factory\n// ============================================================================\n\n/**\n * Create a token selector instance.\n */\nexport const createTokenSelector = (config: TokenSelectorConfig): TokenSelector => {\n const { store } = config;\n\n const ensureAccessToken = async (): Promise<StoredAccessToken | null> => {\n const state = store.getState();\n const userToken = state.user;\n if (!isUserTokenValid(userToken)) {\n return null;\n }\n\n // Use JWT directly — server auto-creates root delegate on first request\n return {\n tokenBase64: userToken!.accessToken,\n tokenBytes: new Uint8Array(0), // JWT has no raw token bytes\n expiresAt: userToken!.expiresAt,\n canUpload: true, // Root delegate always has full permissions\n canManageDepot: true,\n };\n };\n\n return {\n ensureAccessToken,\n };\n};\n",
|
|
18
|
+
"/**\n * Token types for the stateful client.\n *\n * Two-tier hierarchy:\n * - User JWT: OAuth login token, highest authority, used for all root operations\n * - Root Delegate: metadata-only entity (no RT/AT), anchor of the delegate tree\n *\n * Root operations use JWT directly via the server's unified auth middleware.\n * Child delegates (created via Delegate API) use their own AT/RT pairs.\n */\n\n// ============================================================================\n// Stored Token Types\n// ============================================================================\n\n/**\n * User JWT token with refresh capability.\n */\nexport type StoredUserToken = {\n /** JWT access token */\n accessToken: string;\n /** Refresh token for token renewal */\n refreshToken: string;\n /** User ID (usr_xxx format) */\n userId: string;\n /** Token expiration time (epoch ms) */\n expiresAt: number;\n};\n\n/**\n * Root Delegate metadata (no RT/AT — root uses JWT directly).\n *\n * Auto-created by the server's auth middleware on first JWT request.\n * All root realm operations use the user's JWT as the Bearer token;\n * the server's unified auth middleware resolves the root delegate automatically.\n */\nexport type StoredRootDelegate = {\n /** Delegate entity ID */\n delegateId: string;\n /** Realm this delegate belongs to */\n realm: string;\n /** Delegate depth (0 = root) */\n depth: number;\n /** Whether the delegate can upload nodes */\n canUpload: boolean;\n /** Whether the delegate can manage depots */\n canManageDepot: boolean;\n};\n\n/**\n * Complete token state held by the client.\n */\nexport type TokenState = {\n /** User JWT (optional) */\n user: StoredUserToken | null;\n /** Root Delegate metadata (optional) */\n rootDelegate: StoredRootDelegate | null;\n};\n\n/**\n * Empty token state.\n */\nexport const emptyTokenState = (): TokenState => ({\n user: null,\n rootDelegate: null,\n});\n\n// ============================================================================\n// Token Requirement Types\n// ============================================================================\n\n/**\n * Token requirement for API calls.\n */\nexport type TokenRequirement = \"none\" | \"user\" | \"access\";\n\n/**\n * Auth header format.\n */\nexport type AuthHeader = {\n Authorization: string;\n};\n\n// ============================================================================\n// Access Token View (for client module API surface)\n// ============================================================================\n\n/**\n * Stored Access Token — used by client methods for API calls.\n *\n * In root mode: `tokenBase64` is the user's JWT string, `tokenBytes` is empty.\n * In child delegate mode: `tokenBase64` is AT base64, `tokenBytes` is raw AT bytes.\n *\n * The server's unified auth middleware detects JWT vs AT automatically.\n */\nexport type StoredAccessToken = {\n /** Token string (JWT or AT base64) to use in Authorization: Bearer header */\n tokenBase64: string;\n /** Raw token bytes (empty for JWT mode, 32 bytes for AT mode) */\n tokenBytes: Uint8Array;\n /** Token expiration time (epoch ms) */\n expiresAt: number;\n /** Whether the delegate can upload nodes */\n canUpload: boolean;\n /** Whether the delegate can manage depots */\n canManageDepot: boolean;\n};\n",
|
|
19
|
+
"/**\n * Token store - manages the two-tier token state.\n *\n * Provides a closure-based store for token state management with\n * automatic persistence and change notifications.\n */\n\nimport type {\n OnAuthRequiredCallback,\n OnTokenChangeCallback,\n TokenStorageProvider,\n} from \"../types/client.ts\";\nimport type { StoredRootDelegate, StoredUserToken, TokenState } from \"../types/tokens.ts\";\nimport { emptyTokenState } from \"../types/tokens.ts\";\n\n// ============================================================================\n// Store Types\n// ============================================================================\n\nexport type TokenStore = {\n /** Get current token state (immutable snapshot) */\n getState: () => TokenState;\n\n /** Set user JWT token */\n setUser: (token: StoredUserToken | null) => void;\n\n /** Set root delegate (RT + AT pair) */\n setRootDelegate: (delegate: StoredRootDelegate | null) => void;\n\n /** Clear all tokens */\n clear: () => void;\n\n /** Initialize from storage provider */\n initialize: () => Promise<void>;\n};\n\nexport type TokenStoreConfig = {\n storage?: TokenStorageProvider;\n onTokenChange?: OnTokenChangeCallback;\n onAuthRequired?: OnAuthRequiredCallback;\n};\n\n// ============================================================================\n// Store Factory\n// ============================================================================\n\n/**\n * Create a token store instance.\n */\nexport const createTokenStore = (config: TokenStoreConfig = {}): TokenStore => {\n const { storage, onTokenChange } = config;\n\n // Internal mutable state\n let state: TokenState = emptyTokenState();\n\n // Notify change and persist\n const notifyAndPersist = () => {\n onTokenChange?.(state);\n storage?.save(state).catch((err) => {\n console.error(\"[TokenStore] Failed to persist state:\", err);\n });\n };\n\n return {\n getState: () => ({ ...state }),\n\n setUser: (token) => {\n state = { ...state, user: token };\n notifyAndPersist();\n },\n\n setRootDelegate: (delegate) => {\n state = { ...state, rootDelegate: delegate };\n notifyAndPersist();\n },\n\n clear: () => {\n state = emptyTokenState();\n notifyAndPersist();\n storage?.clear().catch((err) => {\n console.error(\"[TokenStore] Failed to clear storage:\", err);\n });\n },\n\n initialize: async () => {\n if (!storage) return;\n\n try {\n const loaded = await storage.load();\n if (loaded) {\n state = loaded;\n // Don't notify on initial load to avoid side effects\n }\n } catch (err) {\n console.error(\"[TokenStore] Failed to load from storage:\", err);\n }\n },\n };\n};\n",
|
|
20
|
+
"/**\n * Client helper functions for reducing boilerplate.\n */\n\nimport type { FetchResult } from \"../types/client.ts\";\nimport type { StoredAccessToken, StoredUserToken } from \"../types/tokens.ts\";\n\n// ============================================================================\n// Error Constants\n// ============================================================================\n\nexport const ERRORS = {\n USER_REQUIRED: { code: \"UNAUTHORIZED\", message: \"User login required\" },\n ACCESS_REQUIRED: { code: \"FORBIDDEN\", message: \"Access token required\" },\n} as const;\n\n// ============================================================================\n// Token Guards\n// ============================================================================\n\nexport type TokenGetter<T> = () => Promise<T | null>;\n\n/**\n * Higher-order function for token-required operations.\n * Reduces repetitive null checks and error returns.\n */\nexport const withToken = <T>(\n getToken: TokenGetter<T>,\n error: { code: string; message: string }\n) => {\n return <R>(fn: (token: T) => Promise<FetchResult<R>>): Promise<FetchResult<R>> =>\n getToken().then((token) =>\n token ? fn(token) : Promise.resolve({ ok: false as const, error })\n );\n};\n\nexport const withUserToken = (getToken: TokenGetter<StoredUserToken>) =>\n withToken(getToken, ERRORS.USER_REQUIRED);\n\nexport const withAccessToken = (getToken: TokenGetter<StoredAccessToken>) =>\n withToken(getToken, ERRORS.ACCESS_REQUIRED);\n",
|
|
21
|
+
"/**\n * Delegate management methods for the stateful client.\n */\n\nimport type {\n ClaimNodeResponse,\n CreateDelegateRequest,\n CreateDelegateResponse,\n DelegateDetail,\n ListDelegatesQuery,\n RevokeDelegateResponse,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DelegateMethods = {\n /** Create a child delegate */\n create: (params: CreateDelegateRequest) => Promise<FetchResult<CreateDelegateResponse>>;\n /** List child delegates */\n list: (params?: ListDelegatesQuery) => Promise<FetchResult<api.ListDelegatesResponse>>;\n /** Get delegate details */\n get: (delegateId: string) => Promise<FetchResult<DelegateDetail>>;\n /** Revoke a delegate */\n revoke: (delegateId: string) => Promise<FetchResult<RevokeDelegateResponse>>;\n /** Claim ownership of a CAS node via PoP */\n claimNode: (nodeKey: string, pop: string) => Promise<FetchResult<ClaimNodeResponse>>;\n};\n\nexport type DelegateDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createDelegateMethods = ({\n baseUrl,\n realm,\n tokenSelector,\n}: DelegateDeps): DelegateMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n create: (params) =>\n requireAccess((t) => api.createDelegate(baseUrl, realm, t.tokenBase64, params)),\n\n list: (params) =>\n requireAccess((t) => api.listDelegates(baseUrl, realm, t.tokenBase64, params)),\n\n get: (delegateId) =>\n requireAccess((t) => api.getDelegate(baseUrl, realm, t.tokenBase64, delegateId)),\n\n revoke: (delegateId) =>\n requireAccess((t) => api.revokeDelegate(baseUrl, realm, t.tokenBase64, delegateId)),\n\n claimNode: (nodeKey, pop) =>\n requireAccess((t) => api.claimNode(baseUrl, realm, t.tokenBase64, nodeKey, { pop })),\n };\n};\n",
|
|
22
|
+
"/**\n * Depot methods for the stateful client.\n */\n\nimport type {\n CreateDepot,\n CreateDepotResponse,\n DepotCommit,\n DepotDetail,\n ListDepotsQuery,\n UpdateDepot,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DepotMethods = {\n /** Create a new depot */\n create: (params: CreateDepot) => Promise<FetchResult<CreateDepotResponse>>;\n /** List depots */\n list: (params?: ListDepotsQuery) => Promise<FetchResult<api.ListDepotsResponse>>;\n /** Get depot details */\n get: (depotId: string) => Promise<FetchResult<DepotDetail>>;\n /** Update depot */\n update: (depotId: string, params: UpdateDepot) => Promise<FetchResult<DepotDetail>>;\n /** Delete depot */\n delete: (depotId: string) => Promise<FetchResult<void>>;\n /** Commit new root */\n commit: (depotId: string, params: DepotCommit) => Promise<FetchResult<api.CommitDepotResponse>>;\n};\n\nexport type DepotDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createDepotMethods = ({ baseUrl, realm, tokenSelector }: DepotDeps): DepotMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n create: (params) =>\n requireAccess((t) => api.createDepot(baseUrl, realm, t.tokenBase64, params)),\n\n list: (params) => requireAccess((t) => api.listDepots(baseUrl, realm, t.tokenBase64, params)),\n\n get: (depotId) => requireAccess((t) => api.getDepot(baseUrl, realm, t.tokenBase64, depotId)),\n\n update: (depotId, params) =>\n requireAccess((t) => api.updateDepot(baseUrl, realm, t.tokenBase64, depotId, params)),\n\n delete: (depotId) =>\n requireAccess((t) => api.deleteDepot(baseUrl, realm, t.tokenBase64, depotId)),\n\n commit: (depotId, params) =>\n requireAccess((t) => api.commitDepot(baseUrl, realm, t.tokenBase64, depotId, params)),\n };\n};\n",
|
|
23
|
+
"/**\n * Filesystem methods for the stateful client.\n *\n * Provides high-level fs operations that automatically handle\n * token management and root node resolution via depot.\n */\n\nimport type {\n FsCpResponse,\n FsLsResponse,\n FsMkdirResponse,\n FsMvResponse,\n FsRewriteEntry,\n FsRewriteResponse,\n FsRmResponse,\n FsStatResponse,\n FsWriteResponse,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type FsMethods = {\n /** Get file/directory metadata */\n stat: (rootKey: string, path?: string) => Promise<FetchResult<FsStatResponse>>;\n /** List directory contents with pagination */\n ls: (\n rootKey: string,\n path?: string,\n opts?: { limit?: number; cursor?: string }\n ) => Promise<FetchResult<FsLsResponse>>;\n /** Read file content as Blob */\n read: (rootKey: string, path: string) => Promise<FetchResult<Blob>>;\n /** Write (create/overwrite) a file */\n write: (\n rootKey: string,\n path: string,\n data: Blob | ArrayBuffer | Uint8Array,\n contentType?: string\n ) => Promise<FetchResult<FsWriteResponse>>;\n /** Create a directory */\n mkdir: (rootKey: string, path: string) => Promise<FetchResult<FsMkdirResponse>>;\n /** Remove a file or directory */\n rm: (rootKey: string, path: string) => Promise<FetchResult<FsRmResponse>>;\n /** Move or rename */\n mv: (rootKey: string, from: string, to: string) => Promise<FetchResult<FsMvResponse>>;\n /** Copy */\n cp: (rootKey: string, from: string, to: string) => Promise<FetchResult<FsCpResponse>>;\n /** Batch rewrite directory tree */\n rewrite: (\n rootKey: string,\n entries?: Record<string, FsRewriteEntry>,\n deletes?: string[]\n ) => Promise<FetchResult<FsRewriteResponse>>;\n};\n\nexport type FsDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createFsMethods = ({ baseUrl, realm, tokenSelector }: FsDeps): FsMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n stat: (rootKey, path?) =>\n requireAccess((t) => api.fsStat(baseUrl, realm, t.tokenBase64, rootKey, path)),\n\n ls: (rootKey, path?, opts?) =>\n requireAccess((t) => api.fsLs(baseUrl, realm, t.tokenBase64, rootKey, path, opts)),\n\n read: (rootKey, path) =>\n requireAccess((t) => api.fsRead(baseUrl, realm, t.tokenBase64, rootKey, path)),\n\n write: (rootKey, path, data, contentType?) =>\n requireAccess((t) =>\n api.fsWrite(baseUrl, realm, t.tokenBase64, rootKey, path, data, contentType)\n ),\n\n mkdir: (rootKey, path) =>\n requireAccess((t) => api.fsMkdir(baseUrl, realm, t.tokenBase64, rootKey, path)),\n\n rm: (rootKey, path) =>\n requireAccess((t) => api.fsRm(baseUrl, realm, t.tokenBase64, rootKey, path)),\n\n mv: (rootKey, from, to) =>\n requireAccess((t) => api.fsMv(baseUrl, realm, t.tokenBase64, rootKey, from, to)),\n\n cp: (rootKey, from, to) =>\n requireAccess((t) => api.fsCp(baseUrl, realm, t.tokenBase64, rootKey, from, to)),\n\n rewrite: (rootKey, entries?, deletes?) =>\n requireAccess((t) => api.fsRewrite(baseUrl, realm, t.tokenBase64, rootKey, entries, deletes)),\n };\n};\n",
|
|
24
|
+
"/**\n * Node methods for the stateful client.\n */\n\nimport type {\n BatchClaimRequest,\n BatchClaimResponse,\n CheckNodes,\n CheckNodesResponse,\n ClaimNodeResponse,\n NodeMetadata,\n} from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { withAccessToken } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type NodeMethods = {\n /** Get node content */\n get: (nodeKey: string) => Promise<FetchResult<Uint8Array>>;\n /** Get node content via navigation path (~0/~1/...) */\n getNavigated: (nodeKey: string, indexPath: string) => Promise<FetchResult<Uint8Array>>;\n /** Get node metadata */\n getMetadata: (nodeKey: string) => Promise<FetchResult<NodeMetadata>>;\n /** Check nodes status on the server */\n check: (params: CheckNodes) => Promise<FetchResult<CheckNodesResponse>>;\n /** Upload a node */\n put: (nodeKey: string, content: Uint8Array) => Promise<FetchResult<api.NodeUploadResult>>;\n /** Claim ownership of a node via PoP (legacy single claim) */\n claim: (nodeKey: string, pop: string) => Promise<FetchResult<ClaimNodeResponse>>;\n /** Batch claim ownership of nodes (PoP + path-based) */\n batchClaim: (params: BatchClaimRequest) => Promise<FetchResult<BatchClaimResponse>>;\n};\n\nexport type NodeDeps = {\n baseUrl: string;\n realm: string;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createNodeMethods = ({ baseUrl, realm, tokenSelector }: NodeDeps): NodeMethods => {\n const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());\n\n return {\n get: (nodeKey) => requireAccess((t) => api.getNode(baseUrl, realm, t.tokenBase64, nodeKey)),\n\n getNavigated: (nodeKey, indexPath) =>\n requireAccess((t) => api.getNodeNavigated(baseUrl, realm, t.tokenBase64, nodeKey, indexPath)),\n\n getMetadata: (nodeKey) =>\n requireAccess((t) => api.getNodeMetadata(baseUrl, realm, t.tokenBase64, nodeKey)),\n\n check: (params) => requireAccess((t) => api.checkNodes(baseUrl, realm, t.tokenBase64, params)),\n\n put: (nodeKey, content) =>\n requireAccess((t) => api.putNode(baseUrl, realm, t.tokenBase64, nodeKey, content)),\n\n claim: (nodeKey, pop) =>\n requireAccess((t) => api.claimNode(baseUrl, realm, t.tokenBase64, nodeKey, { pop })),\n\n batchClaim: (params) =>\n requireAccess((t) => api.batchClaimNodes(baseUrl, realm, t.tokenBase64, params)),\n };\n};\n",
|
|
25
|
+
"/**\n * OAuth methods for the stateful client.\n */\n\nimport * as api from \"../api/index.ts\";\nimport type { RefreshManager } from \"../store/jwt-refresh.ts\";\nimport type { TokenStore } from \"../store/token-store.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\nimport { ERRORS } from \"./helpers.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type OAuthMethods = {\n /** Get Cognito configuration */\n getConfig: () => Promise<FetchResult<api.CognitoConfig>>;\n /** Login with email and password */\n login: (email: string, password: string) => Promise<FetchResult<api.UserInfo>>;\n /** Exchange authorization code for tokens */\n exchangeCode: (\n code: string,\n redirectUri: string,\n codeVerifier?: string\n ) => Promise<FetchResult<api.UserInfo>>;\n /** Get current user info */\n getMe: () => Promise<FetchResult<api.UserInfo>>;\n};\n\nexport type OAuthDeps = {\n baseUrl: string;\n store: TokenStore;\n refreshManager: RefreshManager;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createOAuthMethods = ({\n baseUrl,\n store,\n refreshManager,\n}: OAuthDeps): OAuthMethods => ({\n getConfig: () => api.getOAuthConfig(baseUrl),\n\n login: async (email, password) => {\n const result = await api.login(baseUrl, { email, password });\n if (!result.ok) return result;\n\n const meResult = await api.getMe(baseUrl, result.data.accessToken);\n if (!meResult.ok) return meResult;\n\n store.setUser(api.tokenResponseToStoredUserToken(result.data, meResult.data.userId));\n refreshManager.scheduleProactiveRefresh();\n return meResult;\n },\n\n exchangeCode: async (code, redirectUri, codeVerifier) => {\n const result = await api.exchangeCode(baseUrl, {\n code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n if (!result.ok) return result;\n\n const meResult = await api.getMe(baseUrl, result.data.accessToken);\n if (!meResult.ok) return meResult;\n\n store.setUser(api.tokenResponseToStoredUserToken(result.data, meResult.data.userId));\n refreshManager.scheduleProactiveRefresh();\n return meResult;\n },\n\n getMe: async () => {\n const user = await refreshManager.ensureValidUserToken();\n if (!user) {\n return { ok: false, error: ERRORS.USER_REQUIRED };\n }\n return api.getMe(baseUrl, user.accessToken);\n },\n});\n",
|
|
26
|
+
"/**\n * Token management methods for the stateful client.\n *\n * Root delegates are auto-created by the server's auth middleware on\n * first JWT request. This module provides token refresh operations.\n */\n\nimport type { RefreshManager } from \"../store/jwt-refresh.ts\";\nimport type { TokenSelector } from \"../store/token-selector.ts\";\nimport type { TokenStore } from \"../store/token-store.ts\";\nimport type { FetchResult } from \"../types/client.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TokenMethods = {\n /** Refresh the user's JWT (OAuth token refresh). */\n refresh: () => Promise<FetchResult<void>>;\n};\n\nexport type TokenDeps = {\n baseUrl: string;\n realm: string;\n store: TokenStore;\n refreshManager: RefreshManager;\n tokenSelector: TokenSelector;\n};\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport const createTokenMethods = ({ refreshManager }: TokenDeps): TokenMethods => {\n return {\n refresh: async () => {\n try {\n await refreshManager.ensureValidUserToken();\n return { ok: true, data: undefined, status: 200 };\n } catch (err) {\n return {\n ok: false,\n error: {\n message: (err as Error).message,\n code: \"REFRESH_FAILED\",\n },\n status: 0,\n };\n }\n },\n };\n};\n",
|
|
27
|
+
"/**\n * Stateful CASFA Client\n *\n * A closure-based client that manages JWT auth.\n * Root delegate is auto-created by the server on first JWT request.\n */\n\nimport type { ServiceInfo } from \"@casfa/protocol\";\nimport * as api from \"../api/index.ts\";\nimport { createRefreshManager } from \"../store/jwt-refresh.ts\";\nimport { createTokenSelector } from \"../store/token-selector.ts\";\nimport { createTokenStore } from \"../store/token-store.ts\";\nimport type {\n ClientConfig,\n OnAuthRequiredCallback,\n OnTokenChangeCallback,\n TokenStorageProvider,\n} from \"../types/client.ts\";\nimport type { StoredAccessToken, StoredRootDelegate, TokenState } from \"../types/tokens.ts\";\nimport { createDelegateMethods, type DelegateMethods } from \"./delegates.ts\";\nimport { createDepotMethods, type DepotMethods } from \"./depots.ts\";\nimport { createFsMethods, type FsMethods } from \"./filesystem.ts\";\nimport { createNodeMethods, type NodeMethods } from \"./nodes.ts\";\nimport { createOAuthMethods, type OAuthMethods } from \"./oauth.ts\";\nimport { createTokenMethods, type TokenMethods } from \"./tokens.ts\";\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport type { DelegateMethods, DepotMethods, FsMethods, NodeMethods, OAuthMethods, TokenMethods };\n\nexport type { ClientConfig, OnAuthRequiredCallback, OnTokenChangeCallback, TokenStorageProvider };\n\n// ============================================================================\n// Client Type\n// ============================================================================\n\n/**\n * The stateful CASFA client.\n */\nexport type CasfaClient = {\n /** Get current token state */\n getState: () => TokenState;\n /** Get server info */\n getServerInfo: () => ServiceInfo | null;\n\n /** Set root delegate metadata (e.g., from external source) */\n setRootDelegate: (delegate: StoredRootDelegate) => void;\n /** Get current auth token (JWT — server auto-creates root delegate) */\n getAccessToken: () => Promise<StoredAccessToken | null>;\n /** Clear all tokens and logout */\n logout: () => void;\n\n /** OAuth methods */\n oauth: OAuthMethods;\n /** Token management methods */\n tokens: TokenMethods;\n /** Delegate management methods */\n delegates: DelegateMethods;\n /** Depot methods */\n depots: DepotMethods;\n /** Filesystem methods */\n fs: FsMethods;\n /** Node methods */\n nodes: NodeMethods;\n};\n\n// ============================================================================\n// Client Factory\n// ============================================================================\n\n/**\n * Create a stateful CASFA client.\n */\nexport const createClient = async (config: ClientConfig): Promise<CasfaClient> => {\n const { baseUrl, realm, tokenStorage, onTokenChange, onAuthRequired } = config;\n\n // Initialize token store\n const store = createTokenStore({\n storage: tokenStorage,\n onTokenChange,\n onAuthRequired,\n });\n await store.initialize();\n\n // Initialize refresh manager (for JWT OAuth refresh)\n const refreshManager = createRefreshManager({\n store,\n baseUrl,\n onAuthRequired,\n });\n\n // Fetch server info\n let serverInfo: ServiceInfo | null = null;\n const infoResult = await api.fetchServiceInfo(baseUrl);\n if (infoResult.ok) {\n serverInfo = infoResult.data;\n }\n\n // Initialize token selector (JWT auth)\n const tokenSelector = createTokenSelector({\n store,\n baseUrl,\n realm,\n });\n\n // Shared dependencies\n const deps = { baseUrl, realm, store, refreshManager, tokenSelector };\n\n // Build client\n return {\n getState: () => store.getState(),\n getServerInfo: () => serverInfo,\n\n setRootDelegate: (delegate) => store.setRootDelegate(delegate),\n getAccessToken: () => tokenSelector.ensureAccessToken(),\n\n logout: () => {\n refreshManager.cancelScheduledRefresh();\n store.clear();\n },\n\n oauth: createOAuthMethods(deps),\n tokens: createTokenMethods(deps),\n delegates: createDelegateMethods(deps),\n depots: createDepotMethods(deps),\n fs: createFsMethods(deps),\n nodes: createNodeMethods(deps),\n };\n};\n"
|
|
28
|
+
],
|
|
29
|
+
"mappings": "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",
|
|
30
|
+
"debugId": "5038FC2C1365EC6364756E2164756E21",
|
|
31
|
+
"names": []
|
|
32
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store module exports.
|
|
3
|
+
*/
|
|
4
|
+
export { createRefreshManager, type RefreshManager, type RefreshManagerConfig, } from "./jwt-refresh.ts";
|
|
5
|
+
export { DEFAULT_EXPIRY_BUFFER_MS, isStoredAccessTokenValid, isTokenExpiringSoon, isTokenValid, isUserTokenValid, } from "./token-checks.ts";
|
|
6
|
+
export { createTokenSelector, type TokenSelector, type TokenSelectorConfig, } from "./token-selector.ts";
|
|
7
|
+
export { createTokenStore, type TokenStore, type TokenStoreConfig, } from "./token-store.ts";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT refresh management with promise deduplication.
|
|
3
|
+
*/
|
|
4
|
+
import type { OnAuthRequiredCallback } from "../types/client.ts";
|
|
5
|
+
import type { StoredUserToken } from "../types/tokens.ts";
|
|
6
|
+
import type { TokenStore } from "./token-store.ts";
|
|
7
|
+
export type RefreshManager = {
|
|
8
|
+
/**
|
|
9
|
+
* Ensure user token is valid, refreshing if needed.
|
|
10
|
+
* Returns the valid user token or null if refresh failed.
|
|
11
|
+
*/
|
|
12
|
+
ensureValidUserToken: () => Promise<StoredUserToken | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Schedule proactive refresh before expiration.
|
|
15
|
+
*/
|
|
16
|
+
scheduleProactiveRefresh: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Cancel any scheduled refresh.
|
|
19
|
+
*/
|
|
20
|
+
cancelScheduledRefresh: () => void;
|
|
21
|
+
};
|
|
22
|
+
export type RefreshManagerConfig = {
|
|
23
|
+
store: TokenStore;
|
|
24
|
+
baseUrl: string;
|
|
25
|
+
onAuthRequired?: OnAuthRequiredCallback;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Create a refresh manager for JWT token refresh.
|
|
29
|
+
*/
|
|
30
|
+
export declare const createRefreshManager: (config: RefreshManagerConfig) => RefreshManager;
|
|
31
|
+
//# sourceMappingURL=jwt-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-refresh.d.ts","sourceRoot":"","sources":["../../src/store/jwt-refresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,oBAAoB,EAAE,MAAM,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE5D;;OAEG;IACH,wBAAwB,EAAE,MAAM,IAAI,CAAC;IAErC;;OAEG;IACH,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC,CAAC;AAsCF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,oBAAoB,KAAG,cAqGnE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token validity checks for the two-tier model.
|
|
3
|
+
*
|
|
4
|
+
* Root delegates use JWT directly (no AT/RT), so root-specific
|
|
5
|
+
* AT validity checks have been removed.
|
|
6
|
+
*/
|
|
7
|
+
import type { StoredAccessToken, StoredUserToken } from "../types/tokens.ts";
|
|
8
|
+
/**
|
|
9
|
+
* Default buffer time before expiration (60 seconds).
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_EXPIRY_BUFFER_MS = 60000;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a token is valid (not expired with buffer).
|
|
14
|
+
*/
|
|
15
|
+
export declare const isTokenValid: (token: {
|
|
16
|
+
expiresAt: number;
|
|
17
|
+
} | null, bufferMs?: number) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Check if token is expiring soon and should be refreshed proactively.
|
|
20
|
+
* Used for JWT refresh scheduling.
|
|
21
|
+
*/
|
|
22
|
+
export declare const isTokenExpiringSoon: (token: {
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
} | null, windowMs?: number) => boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if user JWT is valid.
|
|
27
|
+
*/
|
|
28
|
+
export declare const isUserTokenValid: (userToken: StoredUserToken | null, bufferMs?: number) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Check if a StoredAccessToken (view) is valid.
|
|
31
|
+
*/
|
|
32
|
+
export declare const isStoredAccessTokenValid: (accessToken: StoredAccessToken | null, bufferMs?: number) => boolean;
|
|
33
|
+
//# sourceMappingURL=token-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-checks.d.ts","sourceRoot":"","sources":["../../src/store/token-checks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAM7E;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACnC,WAAU,MAAiC,KAC1C,OAGF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACnC,WAAU,MAAmB,KAC5B,OAGF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,WAAW,eAAe,GAAG,IAAI,EAAE,WAAW,MAAM,KAAG,OAEvF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GACnC,aAAa,iBAAiB,GAAG,IAAI,EACrC,WAAW,MAAM,KAChB,OAEF,CAAC"}
|