@singi-labs/sifa-sdk 0.18.12 → 0.18.13

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/query/client.ts","../../../src/query/fetchers/profile.ts","../../../src/query/fetchers/get-profile-view.ts","../../../src/query/fetchers/profile-mutations.ts","../../../src/query/fetchers/positions.ts","../../../src/query/fetchers/education.ts","../../../src/query/fetchers/skills.ts","../../../src/query/fetchers/records.ts","../../../src/query/fetchers/profile-locations.ts","../../../src/query/fetchers/external-accounts.ts","../../../src/query/fetchers/endorsements.ts","../../../src/query/fetchers/received-endorsements.ts","../../../src/query/fetchers/reciprocity.ts","../../../src/query/fetchers/endorsement-inbox.ts","../../../src/query/fetchers/confirmations.ts","../../../src/query/fetchers/inbox.ts","../../../src/query/fetchers/unlinked-positions.ts","../../../src/query/fetchers/profile-completeness.ts","../../../src/query/fetchers/keytrace-claims.ts","../../../src/query/fetchers/marque-domains.ts","../../../src/query/fetchers/publications.ts","../../../src/query/fetchers/profile-items-hide.ts","../../../src/query/fetchers/activity-items-hide.ts","../../../src/query/fetchers/stats.ts","../../../src/query/fetchers/apps.ts","../../../src/query/fetchers/accounts.ts","../../../src/query/fetchers/search.ts","../../../src/query/fetchers/speakers.ts","../../../src/query/fetchers/discovery.ts","../../../src/query/fetchers/follow.ts","../../../src/query/fetchers/follow-extras.ts","../../../src/query/fetchers/admin-feature-allowlists.ts","../../../src/query/fetchers/admin-review-queues.ts","../../../src/query/fetchers/activity.ts","../../../src/query/fetchers/github-prs.ts","../../../src/query/fetchers/endorsement.ts","../../../src/query/fetchers/stream.ts","../../../src/query/fetchers/reactions.ts","../../../src/query/fetchers/quoted-posts.ts","../../../src/query/fetchers/roadmap.ts","../../../src/query/fetchers/destructive.ts","../../../src/query/fetchers/repo-inventory.ts","../../../src/query/fetchers/network-map.ts","../../../src/schemas/entity.ts","../../../src/query/fetchers/entities.ts","../../../src/query/fetchers/org.ts","../../../src/logic/primary-position.ts","../../../src/logic/profile-summary.ts","../../../src/query/fetchers/profile-summary.ts","../../../src/query/keys.ts","../../../src/schemas/shared.ts","../../../src/schemas/profile-project.ts","../../../src/schemas/profile-involvement.ts","../../../src/schemas/profile-investment.ts","../../../src/query/fetchers/investments.ts"],"names":["buildListPath","z","EMPTY_SEARCH"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Foundation HTTP client for talking to the Sifa AppView.\n *\n * Stateless. Consumers supply a {@link SifaApiConfig} per call (the React\n * hooks read it from context; non-React consumers pass it explicitly). No\n * singletons, no module-level state.\n */\n\n/** Configuration passed to every fetcher. */\nexport interface SifaApiConfig {\n /** Base URL of the sifa-api AppView, e.g. `https://api.sifa.id`. No trailing slash. */\n baseUrl: string;\n /**\n * Optional fetch implementation. Defaults to {@link globalThis.fetch}.\n * Lets Next.js consumers pass their cache-enhanced fetch; node/Expo\n * consumers can leave this unset.\n */\n fetch?: typeof fetch;\n}\n\n/** Options accepted by {@link apiFetch}. */\nexport interface ApiFetchOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n /** Request body. Serialized to JSON automatically. */\n body?: unknown;\n /** AbortSignal. Defaults to `AbortSignal.timeout(timeoutMs)` if `timeoutMs` is set. */\n signal?: AbortSignal;\n /** Per-call timeout in milliseconds. Default: 10_000. Ignored if `signal` is provided. */\n timeoutMs?: number;\n /** Retry on HTTP 429 up to 3 times with the server's `Retry-After` delay (capped at 3s). */\n retryOn429?: boolean;\n /** Additional headers. `Content-Type: application/json` is set automatically when `body` is present. */\n headers?: Record<string, string>;\n credentials?: RequestCredentials;\n cache?: RequestCache;\n /**\n * Next.js-specific cache hints. Ignored on non-Next runtimes. Passed\n * through transparently as part of {@link RequestInit}.\n */\n next?: { revalidate?: number | false; tags?: string[] };\n}\n\n/** Error thrown by {@link apiFetch} on non-2xx responses. */\nexport class ApiError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.name = 'ApiError';\n this.status = status;\n this.body = body;\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_RATE_LIMIT_RETRIES = 3;\nconst RATE_LIMIT_RETRY_CAP_SECONDS = 3;\n\n/**\n * Encode a handle or DID for safe interpolation into a request path,\n * idempotently.\n *\n * Plain {@link encodeURIComponent} double-encodes an already-encoded\n * identifier: Next.js hands route params to RSC pages percent-encoded on a\n * hard navigation (`did%3Aplc%3A...`) but decoded on client-side navigation\n * (`did:plc:...`). Encoding the former again turns `%` into `%25`, so the\n * AppView reads `did%3A...` as a literal handle, finds no match, and 404s —\n * which is why DID profile links broke on direct visits but worked when\n * clicked within the app.\n *\n * AT identifiers (handles are domain names, DIDs are `did:method:...`) never\n * contain a literal `%`, so decoding a decoded value is a no-op. A malformed\n * percent sequence (lone `%`) makes {@link decodeURIComponent} throw; in that\n * case we keep the original value so behaviour matches the prior bare\n * `encodeURIComponent`.\n */\nexport function encodeIdentifier(value: string): string {\n let decoded = value;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n // Malformed percent-encoding — fall back to the raw value.\n }\n return encodeURIComponent(decoded);\n}\n\n/**\n * Generic fetcher used by all SDK query and mutation functions.\n *\n * Returns parsed JSON typed as `T`. Throws {@link ApiError} on non-2xx\n * responses. Use {@link apiFetchOrNull} when 404 should resolve to `null`\n * instead.\n */\nexport async function apiFetch<T = unknown>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}${path}`;\n const maxRetries = options.retryOn429 ? MAX_RATE_LIMIT_RETRIES : 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n let body: BodyInit | undefined;\n if (options.body !== undefined) {\n headers['Content-Type'] ??= 'application/json';\n body = JSON.stringify(options.body);\n }\n\n // `next` is a Next.js extension to RequestInit; cast through.\n const init = {\n method: options.method ?? 'GET',\n headers,\n body,\n signal,\n credentials: options.credentials,\n cache: options.cache,\n ...(options.next ? { next: options.next } : {}),\n } as RequestInit;\n\n const res = await fetchFn(url, init);\n\n if (res.status === 429 && attempt < maxRetries) {\n const retryAfterRaw = res.headers.get('retry-after');\n const retryAfter = retryAfterRaw ? Number.parseInt(retryAfterRaw, 10) : 2;\n const waitSeconds = Math.min(\n Number.isFinite(retryAfter) ? retryAfter : 2,\n RATE_LIMIT_RETRY_CAP_SECONDS,\n );\n await new Promise((r) => setTimeout(r, waitSeconds * 1000));\n continue;\n }\n\n if (!res.ok) {\n let errBody: unknown;\n try {\n errBody = (await res.json()) as unknown;\n } catch {\n try {\n errBody = await res.text();\n } catch {\n errBody = undefined;\n }\n }\n throw new ApiError(`Sifa API ${res.status} on ${path}`, res.status, errBody);\n }\n\n // 204 and 205 are defined to carry no body, so res.json() throws on them.\n // apiWrite treats that throw as a failed write, which turned every\n // successful no-content response (roadmap unvote, remove reaction,\n // dismiss endorsement) into a reported error.\n if (res.status === 204 || res.status === 205) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n\n throw new ApiError(`Sifa API exhausted retries on ${path}`, 429);\n}\n\n/**\n * Variant of {@link apiFetch} that resolves to `null` on HTTP 404 instead\n * of throwing. Useful for \"fetch by handle\" reads where missing is\n * expected (e.g. unknown profile).\n */\nexport async function apiFetchOrNull<T>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T | null> {\n try {\n return await apiFetch<T>(config, path, options);\n } catch (e) {\n if (e instanceof ApiError && e.status === 404) return null;\n throw e;\n }\n}\n\n/**\n * Result returned by record-write mutations (create / update / delete).\n *\n * Never throws -- writes against the user's PDS can fail in many ways\n * (network, PDS unreachable, rate limit) and the UI needs structured\n * results to render appropriate messages.\n */\nexport interface WriteResult {\n success: boolean;\n error?: string;\n /**\n * PDS hostname returned by sifa-api when a write failed at the user's\n * Personal Data Server (issue #167). Lets the UI render\n * \"Your data server (eurosky.social) isn't responding\" instead of a\n * generic \"Request failed (500)\".\n */\n pdsHost?: string;\n}\n\n/** Result returned by create mutations. Includes the newly created `rkey`. */\nexport interface CreateResult extends WriteResult {\n rkey?: string;\n}\n\ninterface ApiErrorBody {\n message?: string;\n pdsHost?: string;\n}\n\nfunction extractWriteError(data: unknown, status: number): { error: string; pdsHost?: string } {\n const body = (data ?? {}) as ApiErrorBody;\n return {\n error: body.message ?? `Request failed (${status})`,\n ...(body.pdsHost ? { pdsHost: body.pdsHost } : {}),\n };\n}\n\n/**\n * Write mutation against the Sifa AppView. Wraps {@link apiFetch} with the\n * never-throws contract used by all sifa-web mutations: returns a\n * structured {@link WriteResult} on both success and failure, and\n * preserves the `pdsHost` field when the AppView reports a PDS-side\n * failure (issue #167).\n *\n * On success: returns `{ success: true, ...payload }` where `payload` is\n * whatever the server returned in JSON (or `{}` for 204).\n *\n * On failure: returns `{ success: false, error, pdsHost? }`. Never throws.\n *\n * Use {@link apiWriteCreate} when you specifically need the `rkey` from a\n * create response folded into the result shape.\n */\nexport async function apiWrite<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n method: 'POST' | 'PUT' | 'DELETE' | 'PATCH',\n options: Omit<ApiFetchOptions, 'method'> = {},\n): Promise<WriteResult & TExtra> {\n try {\n const data = await apiFetch<TExtra>(config, path, {\n method,\n credentials: 'include',\n ...options,\n });\n return { success: true, ...(data ?? ({} as TExtra)) };\n } catch (e) {\n if (e instanceof ApiError) {\n return { success: false, ...extractWriteError(e.body, e.status) } as WriteResult & TExtra;\n }\n return { success: false, error: 'Network error' } as WriteResult & TExtra;\n }\n}\n\n/**\n * Write mutation that expects the server to return a record key (`rkey`)\n * in its response body. Wraps {@link apiWrite} and folds the `rkey` into\n * the result shape so consumers get `{ success, rkey?, error?, pdsHost? }`.\n *\n * If the server returns additional fields (e.g. `feedUrl` from external\n * account creation), pass them via the `TExtra` generic to keep them\n * typed.\n */\nexport function apiWriteCreate<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n body: unknown,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<CreateResult & TExtra> {\n return apiWrite<{ rkey?: string } & TExtra>(config, path, 'POST', {\n body,\n ...options,\n });\n}\n","import type { Profile } from '../../types/index.js';\nimport {\n encodeIdentifier,\n apiFetch,\n apiFetchOrNull,\n type ApiFetchOptions,\n type SifaApiConfig,\n} from '../client.js';\n\n/**\n * Read the aggregated profile for a handle or DID.\n *\n * Returns `null` when the AppView has no profile for the given identifier\n * (HTTP 404). Throws {@link ApiError} on other non-2xx responses.\n *\n * Server-callable (Next.js RSC) and client-callable (Expo, browser).\n */\nexport function fetchProfile(\n config: SifaApiConfig,\n handleOrDid: string,\n options: ApiFetchOptions = {},\n): Promise<Profile | null> {\n const path = `/api/profile/${encodeIdentifier(handleOrDid)}`;\n return apiFetchOrNull<Profile>(config, path, {\n retryOn429: true,\n ...options,\n });\n}\n\n/**\n * Public AT Fund link for a profile, if one is configured. Returns `null`\n * on any error or when the response payload's `url` field is missing or\n * non-string.\n */\nexport async function fetchAtFundLink(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<string | null> {\n const path = `/api/profiles/${encodeIdentifier(did)}/at-fund-link`;\n try {\n const data = await apiFetch<{ url?: unknown }>(config, path, {\n next: { revalidate: 3600 },\n timeoutMs: 5000,\n ...options,\n });\n return typeof data.url === 'string' ? data.url : null;\n } catch {\n return null;\n }\n}\n","import type { ProfileView } from '../../types/profile-view.js';\nimport {\n ApiError,\n apiFetch,\n encodeIdentifier,\n type ApiFetchOptions,\n type SifaApiConfig,\n} from '../client.js';\n\n/**\n * Read the aggregated public profile view via the `id.sifa.getProfileView`\n * XRPC query. This is the AppView-only join (positions, education, skills,\n * endorsements, and more) exposed as a standard lexicon method, distinct from\n * the internal `/api/profile/*` REST surface.\n *\n * Returns `null` when the AppView has no profile for the actor\n * (`ProfileNotFound`). Throws {@link ApiError} on other non-2xx responses.\n *\n * Server-callable (Next.js RSC) and client-callable (Expo, browser).\n */\nexport async function fetchGetProfileView(\n config: SifaApiConfig,\n actor: string,\n options: ApiFetchOptions = {},\n): Promise<ProfileView | null> {\n const path = `/xrpc/id.sifa.getProfileView?actor=${encodeIdentifier(actor)}`;\n try {\n return await apiFetch<ProfileView>(config, path, { retryOn429: true, ...options });\n } catch (e) {\n if (\n e instanceof ApiError &&\n e.status === 400 &&\n typeof e.body === 'object' &&\n e.body !== null &&\n (e.body as { error?: unknown }).error === 'ProfileNotFound'\n ) {\n return null;\n }\n throw e;\n }\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Industry/domain entry on the profile self record. */\nexport interface ProfileIndustryInput {\n industry: string;\n domain?: string;\n}\n\n/**\n * Location payload accepted by `updateProfileSelf`.\n *\n * Accepts both shapes during the community.lexicon.location.address\n * migration. Prefer `locality` (new) over `city` (legacy) when sending.\n * The API's locationSchema is a Zod union that resolves either input.\n */\nexport interface ProfileSelfLocation {\n country: string;\n countryCode?: string;\n region?: string;\n city?: string;\n locality?: string;\n}\n\n/** Body accepted by {@link updateProfileSelf}. */\nexport interface UpdateProfileSelfInput {\n headline?: string;\n about?: string;\n /** Schema.org Person.givenName from id.sifa.profile.self.givenName. */\n givenName?: string;\n /** Schema.org Person.familyName from id.sifa.profile.self.familyName. */\n familyName?: string;\n /** Free-form phonetic respelling of the name from id.sifa.profile.self.namePronunciation. */\n namePronunciation?: string;\n industries?: ProfileIndustryInput[];\n location?: ProfileSelfLocation;\n website?: string;\n openTo?: string[];\n preferredWorkplace?: string[];\n availableFromUtc?: number;\n availableToUtc?: number;\n}\n\n/** Update the authenticated user's `id.sifa.profile.self` record. */\nexport function updateProfileSelf(\n config: SifaApiConfig,\n data: UpdateProfileSelfInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/self', 'PUT', { body: data, ...options });\n}\n\n/** Body accepted by {@link updateProfileOverride}. */\nexport interface UpdateProfileOverrideInput {\n headline?: string | null;\n about?: string | null;\n displayName?: string | null;\n pronouns?: string | null;\n}\n\n/**\n * Override aggregated profile fields with sifa-specific values. `null`\n * clears the override and falls back to the upstream PDS value.\n */\nexport function updateProfileOverride(\n config: SifaApiConfig,\n data: UpdateProfileOverrideInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/override', 'PUT', { body: data, ...options });\n}\n\n/** Extended result for {@link refreshPds}. */\nexport interface RefreshPdsResult extends WriteResult {\n displayName?: string | null;\n avatar?: string | null;\n}\n\n/**\n * Re-pull the authenticated user's `app.bsky.actor.profile` from their\n * PDS. Returns the freshly resolved `displayName` and `avatar` on\n * success so the UI can update without a full profile refetch.\n */\nexport function refreshPds(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RefreshPdsResult> {\n return apiWrite<{ displayName?: string | null; avatar?: string | null }>(\n config,\n '/api/profile/refresh-pds',\n 'POST',\n options,\n );\n}\n\n/** Extended result for {@link uploadAvatar}. */\nexport interface UploadAvatarResult extends WriteResult {\n /** Publicly accessible URL of the newly uploaded avatar. */\n url?: string;\n}\n\n/**\n * Upload a new avatar via `multipart/form-data`. Pass either a `File`\n * (browser) or any `Blob` (Expo, node). The SDK leaves `Content-Type`\n * unset so the runtime can set the multipart boundary automatically.\n *\n * Never throws -- inspect `result.success` and `result.url`.\n */\nexport async function uploadAvatar(\n config: SifaApiConfig,\n file: Blob,\n options: ApiFetchOptions = {},\n): Promise<UploadAvatarResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/profile/avatar`;\n const formData = new FormData();\n formData.append('file', file);\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n credentials: options.credentials ?? 'include',\n body: formData,\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 30_000),\n headers: options.headers,\n });\n if (!res.ok) {\n const errBody = (await res.json().catch(() => ({}))) as {\n message?: string;\n pdsHost?: string;\n };\n const msg = errBody.message ?? `Request failed (${res.status})`;\n const pdsHost = errBody.pdsHost;\n return { success: false, error: msg, ...(pdsHost ? { pdsHost } : {}) };\n }\n const data = (await res.json()) as { url: string };\n return { success: true, url: data.url };\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n/** Delete the authenticated user's avatar override (revert to PDS avatar). */\nexport function deleteAvatarOverride(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/avatar', 'DELETE', options);\n}\n\n/** Extended result for {@link uploadNamePronunciationAudio}. */\nexport interface UploadPronunciationAudioResult extends WriteResult {\n /** Publicly accessible URL of the newly uploaded audio clip. */\n url?: string;\n}\n\n/**\n * Upload a name-pronunciation audio clip via `multipart/form-data`. Pass a\n * `File` (browser) or any `Blob` (Expo, node). The SDK leaves `Content-Type`\n * unset so the runtime sets the multipart boundary automatically.\n *\n * Never throws -- inspect `result.success` and `result.url`.\n */\nexport async function uploadNamePronunciationAudio(\n config: SifaApiConfig,\n file: Blob,\n options: ApiFetchOptions = {},\n): Promise<UploadPronunciationAudioResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/profile/pronunciation-audio`;\n const formData = new FormData();\n formData.append('file', file);\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n credentials: options.credentials ?? 'include',\n body: formData,\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 30_000),\n headers: options.headers,\n });\n if (!res.ok) {\n const errBody = (await res.json().catch(() => ({}))) as {\n message?: string;\n pdsHost?: string;\n };\n const msg = errBody.message ?? `Request failed (${res.status})`;\n const pdsHost = errBody.pdsHost;\n return { success: false, error: msg, ...(pdsHost ? { pdsHost } : {}) };\n }\n const data = (await res.json()) as { url: string };\n return { success: true, url: data.url };\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n/** Delete the name-pronunciation audio clip from the user's profile. */\nexport function deleteNamePronunciationAudio(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/pronunciation-audio', 'DELETE', options);\n}\n","import type { ProfilePosition, SkillRef } from '../../types/index.js';\nimport {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\nexport type { CreateResult, WriteResult } from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.position` record on the authenticated\n * user's PDS. The AppView signs and writes via the user's OAuth session.\n *\n * `data` should be a lexicon-shaped position record (without `createdAt`\n * or `rkey`; the AppView fills both). Validate with\n * `ProfilePositionRecordSchema.omit({ createdAt: true })` before calling\n * if you want client-side guarantees.\n *\n * Never throws -- inspect `result.success` and use `result.error` /\n * `result.pdsHost` for UI messaging.\n */\nexport function createPosition(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/position', data, options);\n}\n\n/** Update an existing position by `rkey`. */\nexport function updatePosition(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/position/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete a position by `rkey`. */\nexport function deletePosition(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/position/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n\n/** Mark a position as the user's primary (current) role. */\nexport function setPositionPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/position/${encodeURIComponent(rkey)}/primary`,\n 'PUT',\n options,\n );\n}\n\n/** Clear the \"primary\" flag on a position. */\nexport function unsetPositionPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/position/${encodeURIComponent(rkey)}/primary`,\n 'DELETE',\n options,\n );\n}\n\n/**\n * Build the PUT-body for a position update. Strips `null` `location`\n * (so JSON.stringify drops it) and includes the provided `skills` list.\n */\nfunction buildPositionPayload(\n position: ProfilePosition,\n skills: SkillRef[],\n): Record<string, unknown> {\n return {\n company: position.company,\n title: position.title,\n description: position.description,\n startedAt: position.startedAt,\n endedAt: position.endedAt,\n location: position.location ?? undefined,\n // Carry the form-controlled optional fields the AppView merge would\n // otherwise clear when absent from the PUT body. Omitting them here made\n // every link/unlink strip employmentType, workplaceType, and entityRef\n // off the position (id.sifa.profile.position#skills round-trip).\n employmentType: position.employmentType,\n workplaceType: position.workplaceType,\n entityRef: position.entityRef,\n skills,\n };\n}\n\n/**\n * Add a skill link to a position. Idempotent: if the skill is already\n * linked, resolves to `{ success: true }` without a network call.\n *\n * Implementation note: the AppView only exposes whole-record PUTs, so\n * this helper rebuilds the position body with the new skills list.\n */\nexport function linkSkillToPosition(\n config: SifaApiConfig,\n position: ProfilePosition,\n skillRef: SkillRef,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const currentSkills = position.skills ?? [];\n if (currentSkills.some((s) => s.uri === skillRef.uri)) {\n return Promise.resolve({ success: true });\n }\n return updatePosition(\n config,\n position.rkey,\n buildPositionPayload(position, [...currentSkills, skillRef]),\n options,\n );\n}\n\n/** Remove a skill link from a position. */\nexport function unlinkSkillFromPosition(\n config: SifaApiConfig,\n position: ProfilePosition,\n skillRef: SkillRef,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const remaining = (position.skills ?? []).filter((s) => s.uri !== skillRef.uri);\n return updatePosition(config, position.rkey, buildPositionPayload(position, remaining), options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.education` record on the authenticated\n * user's PDS.\n */\nexport function createEducation(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/education', data, options);\n}\n\n/** Update an existing education record by `rkey`. */\nexport function updateEducation(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/education/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete an education record by `rkey`. */\nexport function deleteEducation(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/education/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.skill` record on the authenticated\n * user's PDS.\n */\nexport function createSkill(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/skill', data, options);\n}\n\n/** Update an existing skill record by `rkey`. */\nexport function updateSkill(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/skill/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Outcome of a bulk sub-category assign. */\nexport interface SubCategoryBulkResult {\n /** Records written. */\n updated: number;\n /** Records that already carried the label, so no write was needed. */\n unchanged: number;\n /** Requested rkeys with no matching record on the PDS. */\n skipped: string[];\n}\n\n/**\n * Set (or clear) the sub-category on many skills in one request.\n *\n * A single call replaces one PUT per skill, which tripped the AppView's\n * per-IP rate limit on any sizeable profile (#324). An empty `subCategory`\n * clears the field.\n */\nexport function updateSkillSubCategories(\n config: SifaApiConfig,\n rkeys: string[],\n subCategory: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult & SubCategoryBulkResult> {\n return apiWrite<SubCategoryBulkResult>(config, '/api/profile/skills/subcategory', 'POST', {\n body: { rkeys, subCategory },\n ...options,\n });\n}\n\n/** Delete a skill record by `rkey`. */\nexport function deleteSkill(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/skill/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Generic record-create escape hatch. Most callers should prefer the\n * dedicated section helpers (`createPosition`, `createEducation`, etc.)\n * which take typed payloads and ship matching hooks. Use this when the\n * lexicon doesn't yet have a dedicated endpoint (certifications,\n * projects, publications, volunteering, honors, languages, courses).\n *\n * `collection` is a `id.sifa.profile.*` collection NSID. Routes to\n * `POST /api/profile/records/<collection>`.\n */\nexport function createRecord(\n config: SifaApiConfig,\n collection: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(\n config,\n `/api/profile/records/${encodeURIComponent(collection)}`,\n data,\n options,\n );\n}\n\n/** Generic record-update escape hatch. See {@link createRecord}. */\nexport function updateRecord(\n config: SifaApiConfig,\n collection: string,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const path = `/api/profile/records/${encodeURIComponent(collection)}/${encodeURIComponent(rkey)}`;\n return apiWrite(config, path, 'PUT', { body: data, ...options });\n}\n\n/** Generic record-delete escape hatch. See {@link createRecord}. */\nexport function deleteRecord(\n config: SifaApiConfig,\n collection: string,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const path = `/api/profile/records/${encodeURIComponent(collection)}/${encodeURIComponent(rkey)}`;\n return apiWrite(config, path, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Address payload accepted by `/api/profile/location` endpoints.\n *\n * Accepts both shapes during the community.lexicon.location.address\n * migration. Prefer `country` + `locality` (new) over `countryCode` +\n * `city` (legacy). The API's `locationSchema` is a Zod union that\n * accepts either pair.\n */\nexport interface ProfileLocationAddress {\n /** Legacy alias for `country` (alpha-2). */\n countryCode?: string;\n /** community.lexicon.location.address field -- prefer over `countryCode`. */\n country?: string;\n region?: string;\n /** Legacy alias for `locality`. */\n city?: string;\n /** community.lexicon.location.address field -- prefer over `city`. */\n locality?: string;\n}\n\n/** Body accepted by {@link createProfileLocation} / {@link updateProfileLocation}. */\nexport interface ProfileLocationInput {\n address: ProfileLocationAddress;\n type: string;\n label?: string;\n isPrimary?: boolean;\n}\n\n/** Create a new profile location entry. */\nexport function createProfileLocation(\n config: SifaApiConfig,\n data: ProfileLocationInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/location', data, options);\n}\n\n/** Update an existing profile location by `rkey`. */\nexport function updateProfileLocation(\n config: SifaApiConfig,\n rkey: string,\n data: ProfileLocationInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/location/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete a profile location by `rkey`. */\nexport function deleteProfileLocation(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/location/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import type { ExternalAccount } from '../../types/index.js';\nimport {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Body accepted by {@link createExternalAccount} / {@link updateExternalAccount}. */\nexport interface ExternalAccountInput {\n platform: string;\n url: string;\n label?: string;\n feedUrl?: string;\n}\n\n/** Extended create result for {@link createExternalAccount}. */\nexport interface CreateExternalAccountResult extends WriteResult {\n rkey?: string;\n feedUrl?: string | null;\n}\n\n/** Extended write result for {@link verifyExternalAccount}. */\nexport interface VerifyExternalAccountResult extends WriteResult {\n verified?: boolean;\n verifiedVia?: string;\n}\n\n/** List external accounts attached to a profile. Returns `[]` on error. */\nexport async function fetchExternalAccounts(\n config: SifaApiConfig,\n handleOrDid: string,\n options: ApiFetchOptions = {},\n): Promise<ExternalAccount[]> {\n const path = `/api/profile/${encodeIdentifier(handleOrDid)}/external-accounts`;\n try {\n const data = await apiFetch<{ accounts?: ExternalAccount[] }>(config, path, {\n credentials: 'include',\n ...options,\n });\n return data.accounts ?? [];\n } catch {\n return [];\n }\n}\n\n/**\n * Create a new external account record. Returns the newly-created `rkey`\n * and the server-resolved `feedUrl` (sifa-api inspects the target for\n * RSS feeds on platforms that publish them).\n */\nexport function createExternalAccount(\n config: SifaApiConfig,\n data: ExternalAccountInput,\n options: ApiFetchOptions = {},\n): Promise<CreateExternalAccountResult> {\n return apiWrite<{ rkey?: string; feedUrl?: string | null }>(\n config,\n '/api/profile/external-accounts',\n 'POST',\n { body: data, ...options },\n );\n}\n\n/** Update an existing external account by `rkey`. */\nexport function updateExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n data: ExternalAccountInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/external-accounts/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete an external account by `rkey`. */\nexport function deleteExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}`,\n 'DELETE',\n options,\n );\n}\n\n/** Mark an external account as the user's primary. */\nexport function setExternalAccountPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/primary`,\n 'PUT',\n options,\n );\n}\n\n/** Clear the \"primary\" flag on an external account. */\nexport function unsetExternalAccountPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/primary`,\n 'DELETE',\n options,\n );\n}\n\n/**\n * Run server-side verification on an external account (e.g. inspect\n * the target for a keytrace claim). Returns `{ verified, verifiedVia }`\n * on success.\n */\nexport function verifyExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<VerifyExternalAccountResult> {\n return apiWrite<{ verified?: boolean; verifiedVia?: string }>(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/verify`,\n 'POST',\n { body: {}, ...options },\n );\n}\n","import {\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n} from '../client.js';\n\n/** Body accepted by {@link createEndorsement}. */\nexport interface EndorsementInput {\n /** DID of the person being endorsed. */\n subjectDid: string;\n /**\n * AT-URI of the subject's `id.sifa.profile.skill` record. Omit to propose a\n * skill they have not listed; `skillName` then names what is proposed, and\n * the record is created when they accept.\n */\n skillUri?: string;\n /**\n * CID of that skill record, pinning the endorsement to the version endorsed.\n * Optional: the AppView resolves it when omitted, which is the common case\n * since only the firehose carries a CID. Never substitute another record's.\n */\n skillCid?: string;\n /**\n * Snapshot of the skill's name at endorsement time. Acts as the validity\n * anchor: if the subject later renames the skill, the mismatch is detectable.\n */\n skillName: string;\n comment?: string;\n}\n\n/** Body accepted by {@link confirmEndorsement}. */\nexport interface ConfirmEndorsementResult {\n /** Skill the endorsement resolved to, created if it was a proposal. */\n skillUri?: string;\n /** True when accepting added a new skill to the profile. */\n skillCreated?: boolean;\n}\n\nexport interface ConfirmEndorsementInput {\n endorsementUri: string;\n /**\n * Optional. When omitted the AppView resolves the CID itself, reading the\n * record from the endorser's PDS if it has none stored. Callers working from\n * the pending inbox should pass `cid` through when it is there and leave it\n * out when it is not, rather than substituting another record's CID.\n */\n endorsementCid?: string;\n}\n\n/**\n * Create an endorsement of another user's skill. The endorsed user\n * must confirm before the endorsement appears on their profile (the\n * endorsement record is on the endorser's PDS; a separate confirmation\n * record on the endorsed user's PDS gates display).\n */\nexport function createEndorsement(\n config: SifaApiConfig,\n data: EndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/endorsement', data, options);\n}\n\n/**\n * Confirm a received endorsement, writing a confirmation record to the\n * signed-in user's PDS. This is what makes the endorsement public: until the\n * confirmation exists, the endorsement is indexed but displays nowhere.\n */\nexport function confirmEndorsement(\n config: SifaApiConfig,\n data: ConfirmEndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult & ConfirmEndorsementResult> {\n return apiWriteCreate<ConfirmEndorsementResult>(\n config,\n '/api/endorsement/confirm',\n data,\n options,\n );\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface ReceivedEndorsement {\n endorserDid: string;\n /** Absent when the endorser has no Sifa profile yet. */\n endorserHandle?: string;\n endorserDisplayName?: string;\n endorserAvatar?: string;\n skillUri?: string;\n skillCid?: string;\n skillName: string;\n comment?: string;\n createdAt: string;\n}\n\nexport interface ReceivedEndorsementsPage {\n endorsements: ReceivedEndorsement[];\n cursor?: string;\n}\n\n/**\n * Confirmed endorsements a DID has received, newest first.\n *\n * Only confirmed ones exist here: the AppView inner-joins against the\n * confirmation records, so an endorsement the subject has not accepted is\n * absent rather than pending. Public -- no credentials needed.\n *\n * Returns an empty page on failure so a surface that merely decorates a page\n * cannot break it.\n */\nexport async function fetchReceivedEndorsements(\n config: SifaApiConfig,\n did: string,\n options: { limit?: number } & ApiFetchOptions = {},\n): Promise<ReceivedEndorsementsPage> {\n const { limit, ...fetchOptions } = options;\n const qs = limit ? `?limit=${limit}` : '';\n try {\n const data = await apiFetch<ReceivedEndorsementsPage>(\n config,\n `/api/endorsement/${encodeIdentifier(did)}${qs}`,\n { cache: 'no-store', timeoutMs: 5000, ...fetchOptions },\n );\n return { endorsements: data?.endorsements ?? [], cursor: data?.cursor };\n } catch {\n return { endorsements: [] };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface ReciprocitySkill {\n name: string;\n uri: string;\n /** Absent until the firehose indexes the skill; the AppView resolves it. */\n cid?: string;\n}\n\nexport interface ReciprocityCandidate {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n skills: ReciprocitySkill[];\n}\n\n/**\n * Someone the signed-in user follows on Sifa whose skills they could endorse.\n *\n * The AppView picks: it filters people already dismissed and anyone blocked,\n * requires at least one skill, and rotates the choice every twelve hours so\n * the same person is not offered indefinitely.\n *\n * `null` means there is nobody left to suggest -- a real state, not an error.\n * Failures also yield `null` so a broken suggestion never breaks the homepage.\n */\nexport async function fetchReciprocityCandidate(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<ReciprocityCandidate | null> {\n try {\n const data = await apiFetch<{ candidate: ReciprocityCandidate | null }>(\n config,\n '/api/endorsements/reciprocity-candidate',\n {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...options,\n },\n );\n return data?.candidate ?? null;\n } catch {\n return null;\n }\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** A received endorsement the subject has neither confirmed nor dismissed. */\nexport interface PendingEndorsement {\n endorserDid: string;\n /**\n * Endorser's handle, when the AppView has resolved one. Absent when the\n * endorser has no Sifa profile yet -- an endorsement can come from any AT\n * Protocol app -- so the UI needs a fallback for having no name to show.\n */\n endorserHandle?: string;\n rkey: string;\n /**\n * AT-URI of the endorsement record. The confirm mutation needs a strongRef,\n * so the AppView hands this back rather than making callers rebuild it.\n */\n uri: string;\n /**\n * CID of the endorsement record, when the AppView has it. Often absent:\n * an endorsement written by another AT Protocol app can be indexed without\n * its CID ever reaching us. Pass it through to confirm when present; the\n * AppView resolves it from the endorser's PDS when it is not.\n */\n cid?: string;\n /** Absent when this endorsement proposes a skill the subject does not have. */\n skillUri?: string;\n skillCid?: string;\n /**\n * True when accepting this will add `skillName` to the profile as well as\n * publishing the endorsement. The UI must say so: it is a bigger action than\n * confirming an endorsement of a skill already listed.\n */\n proposesNewSkill?: boolean;\n skillName: string;\n comment?: string;\n createdAt: string;\n}\n\nexport interface PendingEndorsementsPage {\n endorsements: PendingEndorsement[];\n cursor?: string;\n}\n\n/** Body accepted by {@link dismissEndorsement}. */\nexport interface DismissEndorsementInput {\n endorserDid: string;\n rkey: string;\n}\n\n/** Options for {@link fetchPendingEndorsements}, adding RSC cookie forwarding. */\nexport interface FetchPendingEndorsementsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Endorsements awaiting the signed-in user's decision. Requires credentials --\n * the AppView reads the subject DID from the session, not from a parameter, so\n * there is no way to read someone else's inbox.\n *\n * Returns an empty page on failure so a broken inbox degrades to \"nothing\n * pending\" rather than breaking the surface hosting it.\n */\nexport async function fetchPendingEndorsements(\n config: SifaApiConfig,\n options: FetchPendingEndorsementsOptions = {},\n): Promise<PendingEndorsementsPage> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<PendingEndorsementsPage>(config, '/api/endorsements/pending', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { endorsements: data?.endorsements ?? [], cursor: data?.cursor };\n } catch {\n return { endorsements: [] };\n }\n}\n\n/**\n * Take a received endorsement out of the inbox.\n *\n * This writes nothing to any PDS. An endorsement only displays once the subject\n * has confirmed it, so declining is already the default state -- the dismissal\n * is a local flag that stops it reappearing, not a published rejection.\n */\nexport function dismissEndorsement(\n config: SifaApiConfig,\n data: DismissEndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/endorsement/dismiss', 'POST', { body: data, ...options });\n}\n","import {\n apiFetch,\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** A claim naming the signed-in user that they have neither confirmed nor dismissed. */\nexport interface PendingConfirmation {\n /** DID of the person who wrote the claim. */\n claimerDid: string;\n /**\n * Claimer's handle, when the AppView has resolved one. Absent when they have\n * no Sifa profile: a claim can be written by any AT Protocol app, so the UI\n * needs a fallback for having no name to show.\n */\n claimerHandle?: string;\n claimerDisplayName?: string;\n claimerAvatar?: string;\n /** AT-URI of the record that names you. The confirm mutation needs a strongRef. */\n subjectUri: string;\n /**\n * CID of that record, when the AppView has it. Often absent, since a record\n * indexed from another app can arrive without one. Pass it through when\n * present; the AppView resolves it from the claimer's PDS when it is not.\n * Never substitute a different record's CID.\n */\n subjectCid?: string;\n relation: string;\n /** Name or title the subject record carries right now, for display and snapshotting. */\n subjectName: string;\n /** Role the claimer assigned you, for `projectMember`. Display only. */\n role?: string;\n title?: string;\n createdAt: string;\n}\n\nexport interface PendingConfirmationsPage {\n confirmations: PendingConfirmation[];\n cursor?: string;\n}\n\n/** A confirmation the signed-in user has already given. */\nexport interface GivenConfirmation {\n subjectUri: string;\n claimerDid: string;\n claimerHandle?: string;\n relation: string;\n /** The name as it stood when confirmed, so a rename shows as a difference. */\n subjectName: string;\n /** The name the record carries now. Absent when the claim no longer exists. */\n currentName?: string;\n /** The record changed materially after it was confirmed. */\n confirmedStale: boolean;\n /** They removed you from the record, or deleted it. Nothing left to withdraw. */\n claimWithdrawn: boolean;\n createdAt: string;\n}\n\n/** Body accepted by {@link createConfirmation}. */\nexport interface ConfirmationInput {\n subjectUri: string;\n subjectCid?: string;\n relation: string;\n /**\n * Snapshot of the subject's name at confirmation time. Stored in your own\n * repo, out of the claimer's reach, so a later rename is detectable.\n */\n subjectName?: string;\n}\n\n/** Body accepted by {@link dismissConfirmation} and {@link revokeConfirmation}. */\nexport interface ConfirmationSubjectInput {\n subjectUri: string;\n}\n\n/** Options for the read fetchers, adding the RSC cookie-forwarding escape hatch. */\nexport interface FetchConfirmationsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Claims awaiting the signed-in user's decision. Requires credentials -- the\n * AppView reads the subject DID from the session, not from a parameter, so\n * there is no way to read someone else's inbox.\n *\n * Returns an empty page on failure so a broken inbox degrades to \"nothing\n * pending\" rather than breaking the surface hosting it.\n */\nexport async function fetchPendingConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<PendingConfirmationsPage> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<PendingConfirmationsPage>(config, '/api/confirmations/pending', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { confirmations: data?.confirmations ?? [], cursor: data?.cursor };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Confirmations the signed-in user has already given.\n *\n * The surface for changing your mind. Without it a confirmation is one-way in\n * practice: the inbox lists only claims you have not answered, so once answered\n * there is nowhere to see it, let alone withdraw it.\n *\n * Returns an empty list on failure, matching the pending inbox: a broken list\n * should not break the page hosting it.\n */\nexport async function fetchGivenConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<{ confirmations: GivenConfirmation[] }> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<{ confirmations: GivenConfirmation[] }>(\n config,\n '/api/confirmations/mine',\n { cache: 'no-store', credentials: 'include', timeoutMs: 5000, ...rest, headers },\n );\n return { confirmations: data?.confirmations ?? [] };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Affirm that a record naming you is accurate, writing an `id.sifa.confirmation`\n * to your own PDS. Until this exists the claim renders as a bare handle with no\n * display name, avatar, or link back to you.\n *\n * Confirming does not put the claimer's record on your profile. That record\n * lives in their repository and they can rename it at will; keeping your own\n * entry is a separate, deliberate step.\n */\nexport function createConfirmation(\n config: SifaApiConfig,\n data: ConfirmationInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/confirmation', data, options);\n}\n\n/**\n * Take a claim out of the inbox without confirming it.\n *\n * This writes nothing to any PDS. A claim only gains your identity once you\n * have confirmed it, so declining is already the default state -- the dismissal\n * is a local flag that stops it reappearing, not a published rejection the\n * claimer can read.\n */\nexport function dismissConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/dismiss', 'POST', { body: data, ...options });\n}\n\n/**\n * Withdraw a confirmation you previously gave, deleting the record from your\n * PDS. The claim reverts to rendering as a bare handle.\n *\n * The usual reason is drift: the claimer renamed the project or changed the\n * role after you confirmed, so what you affirmed is no longer what is shown.\n * Also writes a dismissal, or the still-live claim returns to your inbox.\n */\nexport function revokeConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/revoke', 'POST', { body: data, ...options });\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Counts that drive the unified Inbox badge on the header bell.\n *\n * Both numbers are computed server-side and are DISJOINT, so summing them never\n * double-counts a single event:\n *\n * - `tasks` — open items that need the signed-in user's decision or attention.\n * As of this release it counts: pending confirmations, pending endorsement\n * requests, confirmation drift/withdrawn, positions with an unlinked company,\n * and (as 1) an incomplete profile. This set is defined by the AppView and MAY\n * GROW in future without an SDK release, so treat `tasks` as \"how many things\n * need attention\", not as a fixed sum of specific sources.\n * - `unreadNotifications` — unread passive notifications, EXCLUDING the actionable\n * types already counted in `tasks` (e.g. `confirmation_requested`,\n * `endorsement_received`). Computed as the residual of total unread minus\n * task-owned types, so a new/unknown actionable type still surfaces somewhere\n * rather than vanishing.\n */\nexport interface InboxCounts {\n tasks: number;\n unreadNotifications: number;\n}\n\nexport interface FetchInboxCountsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Combined inbox counts for the signed-in user, for the header bell badge.\n *\n * Requires credentials -- the AppView reads the subject from the session, not a\n * parameter. Returns `{ tasks: 0, unreadNotifications: 0 }` on ANY failure,\n * including the unauthenticated case, so the badge degrades to \"nothing waiting\"\n * rather than breaking the header. As a consequence the hook never surfaces an\n * error (`isError` stays false); a persistently-down endpoint is indistinguishable\n * from a genuine zero. That trade-off is deliberate for a poll-driven badge.\n */\n/** Coerce a server-supplied count to a safe non-negative integer. */\nfunction toCount(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;\n}\n\nexport async function fetchInboxCounts(\n config: SifaApiConfig,\n options: FetchInboxCountsOptions = {},\n): Promise<InboxCounts> {\n // Destructure cookieHeader out before spreading so the raw Cookie header (a\n // session token) never lands as a top-level property on the fetch init.\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n try {\n const data = await apiFetch<InboxCounts>(config, '/api/inbox/counts', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return {\n tasks: toCount(data?.tasks),\n unreadNotifications: toCount(data?.unreadNotifications),\n };\n } catch {\n return { tasks: 0, unreadNotifications: 0 };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * A position on the signed-in user's own profile whose free-text company is not\n * yet linked to a canonical company entity. Linking it makes the position roll\n * up under the company's `/c/` page and appear on the company roster.\n */\nexport interface UnlinkedPosition {\n /** rkey of the `id.sifa.profile.position` record, for deep-linking to the editor. */\n rkey: string;\n /** AT-URI of the position record. */\n uri: string;\n /** The free-text company label the user entered. */\n company: string;\n /** The position title, for display. Absent when the record has none. */\n title?: string;\n}\n\nexport interface UnlinkedPositionsResult {\n positions: UnlinkedPosition[];\n}\n\nexport interface FetchUnlinkedPositionsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Positions on the signed-in user's profile with an unlinked company, an \"open\n * task\" surfaced in the unified Inbox. Requires credentials -- the AppView reads\n * the owner from the session. Returns an empty list on any failure so a broken\n * list degrades to \"nothing to link\" rather than breaking the hosting surface.\n */\nexport async function fetchUnlinkedPositions(\n config: SifaApiConfig,\n options: FetchUnlinkedPositionsOptions = {},\n): Promise<UnlinkedPositionsResult> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n try {\n const data = await apiFetch<UnlinkedPositionsResult>(config, '/api/positions/unlinked', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { positions: Array.isArray(data?.positions) ? data.positions : [] };\n } catch {\n return { positions: [] };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * The binary profile-completeness signals the AppView tracks. Each maps to a\n * concrete \"add this to your profile\" step in the unified Inbox checklist.\n */\nexport const PROFILE_COMPLETENESS_SIGNALS = [\n 'headline',\n 'about',\n 'position',\n 'education',\n 'skill',\n 'certification',\n] as const;\n\nexport type ProfileCompletenessSignal = (typeof PROFILE_COMPLETENESS_SIGNALS)[number];\n\n/**\n * Completeness of the signed-in user's own profile: which of the tracked signals\n * are still missing. `missing.length === 0` means complete.\n */\nexport interface ProfileCompleteness {\n /** True when no tracked signal is missing. */\n complete: boolean;\n /** Signals present (of {@link PROFILE_COMPLETENESS_SIGNALS}). */\n score: number;\n /** Total tracked signals. */\n total: number;\n /** The signals still missing, for the checklist. */\n missing: ProfileCompletenessSignal[];\n}\n\nexport interface FetchProfileCompletenessOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Completeness of the signed-in user's own profile, an \"open task\" surfaced in\n * the unified Inbox as a checklist. Requires credentials -- the AppView reads\n * the owner from the session. Returns a complete-looking result on any failure\n * (no missing signals) so a broken call degrades to \"nothing to do\" rather than\n * nagging the user with a phantom checklist.\n */\nexport async function fetchProfileCompleteness(\n config: SifaApiConfig,\n options: FetchProfileCompletenessOptions = {},\n): Promise<ProfileCompleteness> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n const empty: ProfileCompleteness = {\n complete: true,\n score: PROFILE_COMPLETENESS_SIGNALS.length,\n total: PROFILE_COMPLETENESS_SIGNALS.length,\n missing: [],\n };\n\n try {\n const data = await apiFetch<ProfileCompleteness>(config, '/api/profile/completeness', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n if (!data) return empty;\n const missing = Array.isArray(data.missing) ? data.missing : [];\n return {\n complete: data.complete ?? missing.length === 0,\n score: data.score ?? PROFILE_COMPLETENESS_SIGNALS.length - missing.length,\n total: data.total ?? PROFILE_COMPLETENESS_SIGNALS.length,\n missing,\n };\n } catch {\n return empty;\n }\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/**\n * Hide a keytrace claim (verified-account claim discovered on the\n * user's external accounts) from the user's profile. The claim itself\n * stays in the index; only its display is suppressed.\n */\nexport function hideKeytraceClaim(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/keytrace-claims/${encodeURIComponent(rkey)}/hide`,\n 'POST',\n options,\n );\n}\n\n/** Restore a previously-hidden keytrace claim. */\nexport function unhideKeytraceClaim(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/keytrace-claims/${encodeURIComponent(rkey)}/hide`,\n 'DELETE',\n options,\n );\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/**\n * Make a Marque-registered domain public in the owner's Links section. Marque\n * domains are owner-only by default; this reveals one. `domain` is the\n * at.marque.domain rkey (the domain name itself).\n */\nexport function revealMarqueDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/marque-domains/${encodeURIComponent(domain)}/reveal`,\n 'POST',\n options,\n );\n}\n\n/** Make a previously-revealed Marque domain owner-only again. */\nexport function unrevealMarqueDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/marque-domains/${encodeURIComponent(domain)}/reveal`,\n 'DELETE',\n options,\n );\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Extended result for {@link refreshOrcidPublications}. */\nexport interface RefreshOrcidPublicationsResult extends WriteResult {\n added?: number;\n removed?: number;\n}\n\n/**\n * Hide an ORCID-imported publication from the user's profile. The\n * `putCode` is the ORCID-side identifier; the underlying record stays\n * in the index, only its display is suppressed.\n */\nexport function hideOrcidPublication(\n config: SifaApiConfig,\n putCode: number,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/orcid-publications/${putCode}/hide`, 'POST', options);\n}\n\n/** Restore a previously-hidden ORCID publication. */\nexport function unhideOrcidPublication(\n config: SifaApiConfig,\n putCode: number,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/orcid-publications/${putCode}/hide`, 'DELETE', options);\n}\n\n/** Hide a standard (auto-imported) publication by its AT URI. */\nexport function hideStandardPublication(\n config: SifaApiConfig,\n uri: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/standard-publications/${encodeURIComponent(uri)}/hide`,\n 'POST',\n options,\n );\n}\n\n/** Restore a previously-hidden standard publication. */\nexport function unhideStandardPublication(\n config: SifaApiConfig,\n uri: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/standard-publications/${encodeURIComponent(uri)}/hide`,\n 'DELETE',\n options,\n );\n}\n\n/** Bulk-hide standard publications by AT URI list. */\nexport function bulkHideStandardPublications(\n config: SifaApiConfig,\n uris: string[],\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/standard-publications/bulk-hide', 'POST', {\n body: { uris },\n ...options,\n });\n}\n\n/** Bulk-unhide standard publications by AT URI list. */\nexport function bulkUnhideStandardPublications(\n config: SifaApiConfig,\n uris: string[],\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/standard-publications/bulk-hide', 'DELETE', {\n body: { uris },\n ...options,\n });\n}\n\n/** Hide an `id.sifa.profile.publication` (user-authored publication record). */\nexport function hideSifaPublication(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/publications/${rkey}/hide`, 'POST', options);\n}\n\n/** Restore a previously-hidden Sifa publication. */\nexport function unhideSifaPublication(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/publications/${rkey}/hide`, 'DELETE', options);\n}\n\n/**\n * Re-pull the authenticated user's ORCID publications. Returns counts\n * of added and removed records. The server returns `{ error: '...' }`\n * inline (not via HTTP status) on quota / linkage failures; the SDK\n * folds that into `{ success: false, error }` to keep the contract\n * consistent with other mutations.\n */\nexport async function refreshOrcidPublications(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RefreshOrcidPublicationsResult> {\n const result = await apiWrite<{ added?: number; removed?: number; error?: string }>(\n config,\n '/api/profile/orcid-publications/refresh',\n 'POST',\n { body: {}, ...options },\n );\n if (result.success && result.error) {\n return { success: false, error: result.error };\n }\n return result;\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Item types that can be hidden on the authenticated user's profile. */\nexport const HIDDEN_ITEM_TYPES = [\n 'position',\n 'education',\n 'certification',\n 'project',\n 'volunteering',\n 'publication',\n 'course',\n 'honor',\n 'language',\n 'externalAccount',\n] as const;\nexport type HiddenItemType = (typeof HIDDEN_ITEM_TYPES)[number];\n\n/** Source from which an item originates; disambiguates `item_id`. */\nexport const HIDDEN_ITEM_SOURCES = ['pds', 'standard', 'orcid'] as const;\nexport type HiddenItemSource = (typeof HIDDEN_ITEM_SOURCES)[number];\n\nexport interface HideProfileItemInput {\n itemType: HiddenItemType;\n source: HiddenItemSource;\n /** rkey for `pds`, AT-URI for `standard`, ORCID putCode as text for `orcid`. */\n itemId: string;\n}\n\nexport interface BulkHideProfileItemInput {\n itemType: HiddenItemType;\n source: HiddenItemSource;\n itemIds: string[];\n}\n\n/**\n * Hide one profile item. The underlying record stays on the user's PDS;\n * only its display on sifa.id is suppressed.\n */\nexport function hideProfileItem(\n config: SifaApiConfig,\n input: HideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/hide', 'POST', { ...options, body: input });\n}\n\n/** Restore a previously-hidden profile item. */\nexport function unhideProfileItem(\n config: SifaApiConfig,\n input: HideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/hide', 'DELETE', { ...options, body: input });\n}\n\n/** Bulk-hide profile items sharing the same `itemType` + `source`. */\nexport function bulkHideProfileItems(\n config: SifaApiConfig,\n input: BulkHideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/bulk-hide', 'POST', { ...options, body: input });\n}\n\n/** Bulk-unhide profile items sharing the same `itemType` + `source`. */\nexport function bulkUnhideProfileItems(\n config: SifaApiConfig,\n input: BulkHideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/bulk-hide', 'DELETE', { ...options, body: input });\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\nexport interface HideActivityItemInput {\n /** AT-URI of the record, or the item URL for externally-sourced items. */\n uri: string;\n /** Collection NSID (or synthetic collection, e.g. `fediverse.post`). */\n collection: string;\n /**\n * Registry app id the item belongs to. Optional, and used only to take the\n * item out of the owner's OG-image activity spine, which is computed from\n * per-(day, app) counts and never sees a URI.\n */\n appId?: string;\n /** UTC day the item was created (`YYYY-MM-DD`), for the same reason. */\n activityDate?: string;\n}\n\nexport interface UnhideActivityItemInput {\n uri: string;\n}\n\n/** One activity item the authenticated user has hidden from their profile. */\nexport interface HiddenActivityItem {\n uri: string;\n collection: string;\n appId: string | null;\n activityDate: string | null;\n hiddenAt: string;\n}\n\nexport interface FetchHiddenActivityItemsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Hide one activity item from the authenticated user's profile. The record\n * stays on their PDS and stays readable by every other app; only its\n * appearance on sifa.id is suppressed.\n */\nexport function hideActivityItem(\n config: SifaApiConfig,\n input: HideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'POST', { ...options, body: input });\n}\n\n/** Restore a previously-hidden activity item. */\nexport function unhideActivityItem(\n config: SifaApiConfig,\n input: UnhideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'DELETE', { ...options, body: input });\n}\n\n/**\n * Everything the authenticated user has hidden, newest hide first. Returns\n * `[]` on any error so a settings page can still render.\n */\nexport async function fetchHiddenActivityItems(\n config: SifaApiConfig,\n options: FetchHiddenActivityItemsOptions = {},\n): Promise<HiddenActivityItem[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ items: HiddenActivityItem[] }>(\n config,\n '/api/activity/hidden-items',\n { credentials: 'include', ...options, headers },\n );\n return data.items;\n } catch {\n return [];\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Public, aggregate stats shown on the homepage and similar surfaces. */\nexport interface StatsResponse {\n profileCount: number;\n avatars: string[];\n atproto: {\n userCount: number;\n growthPerSecond: number;\n timestamp: number;\n } | null;\n}\n\n/**\n * Homepage stats (profile count, avatar samples, ATproto growth). Public\n * endpoint -- safe to cache. Returns `null` on any error so callers can\n * render a graceful empty state.\n */\nexport async function fetchStats(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<StatsResponse | null> {\n try {\n return await apiFetch<StatsResponse>(config, '/api/stats', {\n next: { revalidate: 900 },\n ...options,\n });\n } catch {\n return null;\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Catalog entry describing an ATproto app that Sifa surfaces activity for. */\nexport interface AppRegistryEntry {\n id: string;\n name: string;\n category: string;\n collectionPrefixes: string[];\n scanCollections: string[];\n urlPattern?: string;\n color: string;\n}\n\n/** Compact app representation returned by the hidden-apps endpoint. */\nexport interface HiddenApp {\n id: string;\n name: string;\n category: string;\n}\n\nexport interface FetchHiddenAppsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Public app registry shown across discovery surfaces. Heavily cached.\n * Returns `[]` on any error.\n */\nexport async function fetchAppsRegistry(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<AppRegistryEntry[]> {\n try {\n return await apiFetch<AppRegistryEntry[]>(config, '/api/apps/registry', {\n next: { revalidate: 86400 },\n ...options,\n });\n } catch {\n return [];\n }\n}\n\n/**\n * Apps the authenticated user has chosen to hide from their activity feed.\n * Requires an authenticated session. Returns `[]` on any error (including\n * the unauthenticated case).\n */\nexport async function fetchHiddenApps(\n config: SifaApiConfig,\n options: FetchHiddenAppsOptions = {},\n): Promise<HiddenApp[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ apps: HiddenApp[] }>(config, '/api/profile/hidden-apps', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.apps;\n } catch {\n return [];\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** One account attached to the current browser, for the account switcher. */\nexport interface AccountSummary {\n did: string;\n handle: string | null;\n displayName: string | null;\n avatarUrl: string | null;\n /**\n * The org's uploaded logo blob CID, for a company account that set one on its\n * `/c/` page; null otherwise. The switcher resolves it to the same logo `/c/`\n * shows (via the shared company-logo resolution), so an uploaded logo appears\n * in the menu rather than the atproto avatar. Omitted by older api responses.\n */\n orgLogoBlob?: string | null;\n /** Whether this is the currently-active account. */\n active: boolean;\n}\n\nexport interface FetchAccountsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Accounts attached to this browser (the account switcher). Requires an\n * authenticated session. Returns `[]` on any error, including the\n * unauthenticated case.\n */\nexport async function fetchAccounts(\n config: SifaApiConfig,\n options: FetchAccountsOptions = {},\n): Promise<AccountSummary[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ accounts: AccountSummary[] }>(config, '/api/auth/accounts', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.accounts;\n } catch {\n return [];\n }\n}\n\n/**\n * Make an already-attached account the active one. Keyed by DID (public); the\n * server maps it to the browser's session id. Browser-only: the endpoint\n * requires an Origin header, which browsers set automatically on POST. Callers\n * typically reload the app afterwards to reset session-seeded state.\n */\nexport async function switchAccount(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<void> {\n await apiFetch(config, '/oauth/switch', {\n method: 'POST',\n body: { did },\n credentials: 'include',\n ...options,\n });\n}\n","import type { SkillSuggestion } from '../../types/index.js';\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Profile entry returned by the search endpoint. */\nexport interface ProfileSearchResult {\n did?: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatar?: string;\n about?: string;\n currentRole?: string;\n currentCompany?: string;\n industry?: string;\n domain?: string;\n countryCode?: string;\n locationCountry?: string;\n preferredWorkplace?: string[];\n claimed?: boolean;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n}\n\nexport interface SearchFilters {\n q?: string;\n skill?: string;\n country?: string;\n industry?: string;\n domain?: string;\n workplace?: string;\n app?: string;\n /**\n * Open-to filter. Values are short tokens (e.g. \"fullTime\", \"mentor\",\n * \"collab\") matching `OPEN_TO_OPTIONS[].token` from the taxonomy. The\n * API expands tokens to lex values server-side. Multiple tokens are\n * OR-combined (profile matches if any selected token is set).\n */\n openTo?: string[];\n limit?: number;\n}\n\nexport interface SearchResponse {\n profiles: ProfileSearchResult[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Skill typeahead suggestion. */\nexport interface SkillSearchResult {\n name: string;\n slug: string;\n category: string;\n userCount: number;\n}\n\nexport interface FilterOptions {\n countries: { countryCode: string; country: string; count: number }[];\n industries: { industry: string; count: number }[];\n apps: { appId: string; count: number }[];\n /**\n * Distribution of openTo selections across indexed profiles. Each entry\n * maps a short token (see {@link SearchFilters.openTo}) to the number of\n * profiles that have it set. Omitted from older API responses; treat\n * absence as \"no data\" rather than \"all zero\".\n */\n openTo?: { token: string; count: number }[];\n}\n\n/** Company entry returned by company search (workspace#299). */\nexport interface CompanySearchResult {\n /** Immutable catalogue id; the durable `/c/{publicId}` link. */\n publicId: string;\n name: string;\n domain: string | null;\n country: string | null;\n industry: string | null;\n logoUrl: string | null;\n employeeCount: number | null;\n}\n\nexport interface CompanySearchFilters {\n q?: string;\n /** ISO 3166-1 alpha-2. */\n country?: string;\n industry?: string;\n limit?: number;\n}\n\nexport interface CompanySearchResponse {\n results: CompanySearchResult[];\n hasMore: boolean;\n}\n\nconst EMPTY_SEARCH: SearchResponse = { profiles: [], total: 0, limit: 20, offset: 0 };\nconst EMPTY_FILTERS: FilterOptions = { countries: [], industries: [], apps: [], openTo: [] };\nconst EMPTY_COMPANY_SEARCH: CompanySearchResponse = { results: [], hasMore: false };\n\n/**\n * Search profiles by free-text query and optional filters. Returns an\n * empty result set when no filters are provided (matching sifa-web's\n * \"no input, no fetch\" behavior).\n */\nexport async function fetchSearchProfiles(\n config: SifaApiConfig,\n filters: SearchFilters,\n options: ApiFetchOptions = {},\n): Promise<SearchResponse> {\n const params = new URLSearchParams();\n if (filters.q) params.set('q', filters.q);\n if (filters.skill) params.set('skill', filters.skill);\n if (filters.country) params.set('country', filters.country);\n if (filters.industry) params.set('industry', filters.industry);\n if (filters.domain) params.set('domain', filters.domain);\n if (filters.workplace) params.set('workplace', filters.workplace);\n if (filters.app) params.set('app', filters.app);\n if (filters.openTo && filters.openTo.length > 0) {\n for (const token of filters.openTo) {\n if (token) params.append('openTo', token);\n }\n }\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n\n if (params.size === 0) return EMPTY_SEARCH;\n\n return apiFetch<SearchResponse>(config, `/api/search/profiles?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n}\n\n/**\n * Company search over the entity catalogue (workspace#299).\n *\n * A category of its own rather than part of profile search: the two rank\n * differently and carry different filters, and a slow category should not hold\n * up the rest of a blended results page.\n *\n * An empty query returns nothing without a network call. The API rejects a\n * blank `q` rather than scanning ~200k rows, so asking would only spend a round\n * trip to be told no.\n */\nexport async function fetchSearchCompanies(\n config: SifaApiConfig,\n filters: CompanySearchFilters,\n options: ApiFetchOptions = {},\n): Promise<CompanySearchResponse> {\n const q = filters.q?.trim();\n if (!q) return EMPTY_COMPANY_SEARCH;\n\n const params = new URLSearchParams({ q });\n if (filters.country) params.set('country', filters.country);\n if (filters.industry) params.set('industry', filters.industry);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n\n return apiFetch<CompanySearchResponse>(config, `/api/search/companies?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n}\n\n/**\n * Skill typeahead. Returns up to 8 matches for the given prefix. Empty\n * input returns an empty array without hitting the server.\n */\nexport async function fetchSkillSuggestions(\n config: SifaApiConfig,\n query: string,\n options: ApiFetchOptions = {},\n): Promise<SkillSearchResult[]> {\n if (!query.trim()) return [];\n const path = `/api/search/skills?q=${encodeURIComponent(query)}&limit=8`;\n const data = await apiFetch<{ skills?: SkillSearchResult[] }>(config, path, {\n cache: 'no-store',\n ...options,\n });\n return data.skills ?? [];\n}\n\n/** Available filter facets (countries, industries, apps) for search UI. */\nexport async function fetchSearchFilters(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<FilterOptions> {\n try {\n return await apiFetch<FilterOptions>(config, '/api/search/filters', {\n next: { revalidate: 300 },\n ...options,\n });\n } catch {\n return EMPTY_FILTERS;\n }\n}\n\n/**\n * Canonical-skill search backing the position-editor and similar\n * skill-pickers. Hits `/api/skills/search` (the canonical-skills DB\n * lookup) which is distinct from {@link fetchSkillSuggestions}'s\n * `/api/search/skills` (the profile-skill typeahead).\n *\n * Returns `[]` on empty input (no network call) or any error.\n */\nexport async function searchSkills(\n config: SifaApiConfig,\n query: string,\n limit = 10,\n options: ApiFetchOptions = {},\n): Promise<SkillSuggestion[]> {\n if (!query.trim()) return [];\n const path = `/api/skills/search?q=${encodeURIComponent(query)}&limit=${limit}`;\n try {\n const data = await apiFetch<{ skills?: SkillSuggestion[] }>(config, path, {\n cache: 'no-store',\n ...options,\n });\n return data.skills ?? [];\n } catch {\n return [];\n }\n}\n","import type { PresentationLinkView } from '../../types/index.js';\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Which claim a listed speaker makes about a topic. Phase 1 has no confirmed\n * data, so groups are named by the CLAIM, never a \"proven\" label:\n * - `spoke_about_it` — has a topic-matching delivery (or, with a topic set,\n * a matching presentation plus at least one delivery)\n * - `skilled` — holds the matching canonical skill but has no matching talk\n * (only appears when a topic is supplied)\n * - `open_to_speaking` — opted in but has never delivered (only appears when\n * no topic is supplied)\n */\nexport type SpeakerGroup = 'spoke_about_it' | 'skilled' | 'open_to_speaking';\n\n/** One person in the speaker directory. Everyone listed has opted in. */\nexport interface SpeakerCard {\n did: string;\n handle: string;\n displayName: string | null;\n avatar: string | null;\n headline: string | null;\n currentRole: string | null;\n currentCompany: string | null;\n deliveryCount: number;\n group: SpeakerGroup;\n matchedTopics: string[];\n /**\n * Self-reported event names from the speaker's own presentationDelivery\n * records — unconfirmed in Phase 1. `eventsSelfReported` is always true;\n * the web layer labels these as such.\n */\n recentEvents: string[];\n eventsSelfReported: boolean;\n /**\n * Up to 3 of the speaker's most-recent talks (self-reported), newest first.\n * `rkey` builds the talk-page URL via `buildTalkSlug(title, rkey)`. Optional:\n * absent from responses served before this field shipped, so consumers should\n * default to an empty list.\n */\n recentTalks?: { title: string; rkey: string }[];\n}\n\nexport interface SpeakersResponse {\n speakers: SpeakerCard[];\n}\n\n/** The reusable talk, or a standalone delivery when it has no parent talk. */\nexport interface TalkEvent {\n eventName: string | null;\n date: string | null;\n}\n\n/** Compact speaker card embedded in a talk row. */\nexport interface TalkSpeaker {\n did: string;\n handle: string;\n displayName: string | null;\n avatar: string | null;\n headline: string | null;\n currentRole: string | null;\n currentCompany: string | null;\n}\n\nexport interface TalkRow {\n /**\n * `presentation` = a reusable `id.sifa.profile.presentation` record.\n * `delivery` = a standalone presentationDelivery with no parent presentation.\n */\n kind: 'presentation' | 'delivery';\n rkey: string;\n title: string | null;\n snippet: string | null;\n links: PresentationLinkView[];\n writeupUri: string | null;\n speaker: TalkSpeaker;\n events: TalkEvent[];\n eventsSelfReported: boolean;\n deliveryCount: number;\n matchedTopics: string[];\n}\n\nexport interface TalksResponse {\n talks: TalkRow[];\n}\n\nexport interface SpeakerDirectoryFilters {\n /** Free-text topic (canonical skill name/slug/alias, talk title, or event). */\n topic?: string;\n /** Max rows to return; the API caps this at 50. */\n limit?: number;\n}\n\nconst EMPTY_SPEAKERS: SpeakersResponse = { speakers: [] };\nconst EMPTY_TALKS: TalksResponse = { talks: [] };\n\nfunction buildParams(filters: SpeakerDirectoryFilters): URLSearchParams {\n const params = new URLSearchParams();\n const topic = filters.topic?.trim();\n if (topic) params.set('topic', topic);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n return params;\n}\n\n/**\n * Speaker directory (Phase 1, read-only POC). Everyone returned has opted in to\n * speaking; past deliveries are a ranking signal, not an inclusion path. An\n * optional `topic` filters to people who hold the matching canonical skill,\n * have a matching presentation, or have a matching delivery. Results come\n * grouped and ordered by the API.\n *\n * Returns an empty list on any error so callers can render a graceful state.\n */\nexport async function fetchSpeakers(\n config: SifaApiConfig,\n filters: SpeakerDirectoryFilters = {},\n options: ApiFetchOptions = {},\n): Promise<SpeakersResponse> {\n const params = buildParams(filters);\n const query = params.toString();\n const path = query ? `/api/speakers?${query}` : '/api/speakers';\n try {\n return await apiFetch<SpeakersResponse>(config, path, {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return EMPTY_SPEAKERS;\n }\n}\n\n/**\n * Talk directory (Phase 1, read-only POC). Lists talks by opted-in speakers,\n * delivered-first, then latest delivery date. Same optional `topic` filter as\n * {@link fetchSpeakers}. Returns an empty list on any error.\n */\nexport async function fetchTalks(\n config: SifaApiConfig,\n filters: SpeakerDirectoryFilters = {},\n options: ApiFetchOptions = {},\n): Promise<TalksResponse> {\n const params = buildParams(filters);\n const query = params.toString();\n const path = query ? `/api/talks?${query}` : '/api/talks';\n try {\n return await apiFetch<TalksResponse>(config, path, {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return EMPTY_TALKS;\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Lightweight profile representation used by discovery endpoints. */\nexport interface SimilarProfile {\n did: string;\n handle: string;\n displayName?: string | null;\n avatar?: string | null;\n headline?: string | null;\n currentRole?: string | null;\n currentCompany?: string | null;\n industry?: string | null;\n domain?: string | null;\n}\n\nexport interface SuggestionProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n dismissed: boolean;\n blueskyVerified?: boolean;\n}\n\nexport interface SuggestionsResponse {\n onSifa: SuggestionProfile[];\n notOnSifa: SuggestionProfile[];\n cursor?: string;\n}\n\nexport interface FeaturedProfile {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n pronouns?: string;\n headline?: string;\n about?: string;\n currentRole?: string;\n currentCompany?: string;\n locationCountry?: string;\n locationRegion?: string;\n /** Legacy alias for `locationLocality`; emitted by sifa-api during the additive response window. */\n locationCity?: string;\n /** community.lexicon.location.address field name -- prefer over `locationCity`. */\n locationLocality?: string;\n countryCode?: string;\n location?: string;\n website?: string;\n openTo?: string[];\n preferredWorkplace?: string[];\n availableFromUtc?: number;\n availableToUtc?: number;\n followersCount?: number;\n atprotoFollowersCount?: number;\n pdsProvider?: { name: string; host: string } | null;\n claimed: boolean;\n featuredDate: string;\n}\n\n/** Profiles similar to the given DID (matchmaking). Returns `[]` on error. */\nexport async function fetchSimilarProfiles(\n config: SifaApiConfig,\n did: string,\n opts: { limit?: number } & ApiFetchOptions = {},\n): Promise<SimilarProfile[]> {\n const limit = opts.limit ?? 5;\n const path = `/api/discover/similar/${encodeIdentifier(did)}?limit=${limit}`;\n try {\n const data = await apiFetch<{ profiles?: SimilarProfile[] }>(config, path, {\n next: { revalidate: 300 },\n timeoutMs: 5000,\n ...opts,\n });\n return data.profiles ?? [];\n } catch {\n return [];\n }\n}\n\nexport interface FetchSuggestionsOptions extends ApiFetchOptions {\n source?: string;\n includeDismissed?: boolean;\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/** Discovery suggestions feed. Resolves to empty arrays on error. */\nexport async function fetchSuggestions(\n config: SifaApiConfig,\n opts: FetchSuggestionsOptions = {},\n): Promise<SuggestionsResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.includeDismissed) params.set('include_dismissed', 'true');\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n\n const qs = params.toString();\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n try {\n return await apiFetch<SuggestionsResponse>(config, `/api/suggestions${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n timeoutMs: 8000,\n ...opts,\n headers,\n });\n } catch {\n return { onSifa: [], notOnSifa: [] };\n }\n}\n\n/** Count of pending suggestions since an optional timestamp. */\nexport async function fetchSuggestionCount(\n config: SifaApiConfig,\n since?: string,\n options: ApiFetchOptions = {},\n): Promise<number> {\n const params = since ? `?since=${encodeURIComponent(since)}` : '';\n try {\n const data = await apiFetch<{ count?: number }>(config, `/api/suggestions/count${params}`, {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n });\n return data.count ?? 0;\n } catch {\n return 0;\n }\n}\n\n/** Featured profile (rotated by sifa-api). Returns `null` when none. */\nexport async function fetchFeaturedProfile(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<FeaturedProfile | null> {\n try {\n return await apiFetch<FeaturedProfile>(config, '/api/featured-profile', {\n next: { revalidate: 900 },\n ...options,\n });\n } catch {\n return null;\n }\n}\n","import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { FollowFeedPage } from '../../schemas/feed.js';\n\nexport interface FollowProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n claimed: boolean;\n followedAt: string;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n}\n\nexport interface FollowingResponse {\n follows: FollowProfile[];\n cursor?: string;\n}\n\n/** People the authenticated user follows. Empty on error. */\nexport async function fetchFollowing(\n config: SifaApiConfig,\n opts: { source?: string; cursor?: string; limit?: number } & ApiFetchOptions = {},\n): Promise<FollowingResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n\n try {\n return await apiFetch<FollowingResponse>(config, `/api/following${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n });\n } catch {\n return { follows: [] };\n }\n}\n\n/**\n * Result of {@link followUser}. Extends {@link WriteResult} with the\n * follow `rkey` returned by sifa-api on success. Self-follow + invalid\n * handle surface as `success: false` with the server-provided message;\n * dup-follow is idempotent (sifa-api E7) and resolves as `success: true`.\n */\nexport interface FollowUserResult extends WriteResult {\n rkey?: string;\n /** DID of the followed subject (server-resolved from the handle). */\n subjectDid?: string;\n}\n\n/**\n * Create an `id.sifa.graph.follow` record on the caller's PDS via the\n * AppView. Idempotent on duplicate (server catches the unique-violation\n * and returns 200, per sifa-api#673 E7).\n */\nexport function followUser(\n config: SifaApiConfig,\n handle: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<FollowUserResult> {\n const { note, ...rest } = opts;\n return apiWrite<{ rkey?: string; subjectDid?: string }>(\n config,\n `/api/follow/${encodeIdentifier(handle)}`,\n 'POST',\n {\n body: note !== undefined ? { note } : undefined,\n ...rest,\n },\n );\n}\n\n/** Delete the authenticated viewer's `id.sifa.graph.follow` for `handle`. */\nexport function unfollowUser(\n config: SifaApiConfig,\n handle: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/follow/${encodeIdentifier(handle)}`, 'DELETE', opts);\n}\n\nexport interface FollowListPage {\n follows: FollowProfile[];\n cursor: string | null;\n}\n\nexport interface FetchFollowListOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors {@link FetchActivityFeedOptions}; required for authenticated\n * server fetches because `credentials: 'include'` does not propagate\n * cookies from RSC).\n */\n cookieHeader?: string;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowListOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\n/**\n * Paginated list of `handle`'s followers. Returns an empty page on error\n * so the UI can render a graceful \"no followers yet\" state.\n */\nexport async function getFollowers(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/followers`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** Paginated list of who `handle` follows. */\nexport async function getFollowing(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/following`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/**\n * @deprecated The `/api/following/feed` surface was reverted (sifa-api#674).\n * Per `decisions/activity-data-strategy.md` the Sifa Timeline + ATmosphere\n * Stream are two distinct surfaces with different data paths (Barazo API\n * for Timeline, live PDS reads + Valkey for Stream). These collapsed feed\n * types are no longer consumed. Scheduled for removal in next major bump.\n */\nexport interface FetchFollowingFeedOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Comma-separated category filter (per sifa-api#673 TR10). Forwarded\n * as-is; the server validates allowed values.\n */\n categories?: string[];\n cookieHeader?: string;\n}\n\n/**\n * V5 home feed: Sifa events + curated ATmosphere creation events filtered\n * by the authenticated viewer's followees. Composite cursor (per E5/TR4).\n * Returns an empty page on error.\n *\n * @deprecated The `/api/following/feed` surface was reverted (sifa-api#674).\n * Per `decisions/activity-data-strategy.md` the Sifa Timeline + ATmosphere\n * Stream are two distinct surfaces with different data paths (Barazo API\n * for Timeline, live PDS reads + Valkey for Stream). This fetcher is no\n * longer consumed. Scheduled for removal in next major bump.\n */\nexport async function getFollowingFeed(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowFeedPage> {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n if (opts.categories && opts.categories.length > 0) {\n params.set('categories', opts.categories.join(','));\n }\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n try {\n const res = await apiFetch<{ items: FollowFeedPage['items']; cursor?: string | null }>(\n config,\n `/api/following/feed${qs ? `?${qs}` : ''}`,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [], cursor: res.cursor ?? null };\n } catch {\n return { items: [], cursor: null };\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { FollowProfileItem } from '../../schemas/follow-profile.js';\n\n/**\n * Options shared by the cursor-paginated follow-graph endpoints introduced in\n * `sifa-api#674` (mutuals + bluesky-suggestions). Mirrors\n * `FetchFollowListOptions` in `./follow.ts` but the response wrapper here uses\n * the `{ items, cursor }` shape (not `{ follows, cursor }`).\n */\nexport interface FetchFollowProfilePageOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors `FetchFollowListOptions`; required for authenticated server\n * fetches because `credentials: 'include'` does not propagate cookies from\n * RSC).\n */\n cookieHeader?: string;\n}\n\n/** Page of {@link FollowProfileItem} rows with an opaque next-page cursor. */\nexport interface FollowProfilePageResponse {\n items: FollowProfileItem[];\n cursor: string | null;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowProfilePageOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\nasync function fetchFollowProfilePage(\n config: SifaApiConfig,\n path: string,\n opts: FetchFollowProfilePageOptions,\n): Promise<FollowProfilePageResponse> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ items?: FollowProfileItem[]; cursor?: string | null }>(\n config,\n path,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [], cursor: res.cursor ?? null };\n } catch {\n return { items: [], cursor: null };\n }\n}\n\n/**\n * Cursor-paginated list of mutual sifa-source follows for `handleOrDid`\n * (X↔Y both follow each other on Sifa). Backed by\n * `GET /api/profile/{handleOrDid}/mutuals` from `sifa-api#674`. Public —\n * does not require auth. Returns an empty page on error.\n */\nexport async function getMutuals(\n config: SifaApiConfig,\n handleOrDid: string,\n opts: FetchFollowProfilePageOptions = {},\n): Promise<FollowProfilePageResponse> {\n return fetchFollowProfilePage(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handleOrDid)}/mutuals`, opts),\n opts,\n );\n}\n\n/**\n * Cursor-paginated list of Sifa users the viewer follows on Bluesky but NOT\n * on Sifa, filtered to people active on Sifa. Backed by\n * `GET /api/me/bluesky-suggestions` from `sifa-api#674`. Auth-required.\n * Returns an empty page on error.\n */\nexport async function getBlueskySuggestions(\n config: SifaApiConfig,\n opts: FetchFollowProfilePageOptions = {},\n): Promise<FollowProfilePageResponse> {\n return fetchFollowProfilePage(config, buildListPath('/api/me/bluesky-suggestions', opts), opts);\n}\n","import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { FeatureAllowlistEntry, FeatureFlag } from '../../schemas/follow-profile.js';\n\n/**\n * Options for {@link listFeatureAllowlist}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface ListFeatureAllowlistOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/feature-allowlists/:flag`. */\nexport interface FeatureAllowlistResponse {\n items: FeatureAllowlistEntry[];\n}\n\n/**\n * List all DIDs on the given feature flag's allowlist. Admin-gated server-\n * side (caller must be an admin). Returns an empty list on error so the UI\n * can render a graceful empty state.\n */\nexport async function listFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n opts: ListFeatureAllowlistOptions = {},\n): Promise<FeatureAllowlistResponse> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ items?: FeatureAllowlistEntry[] }>(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [] };\n } catch {\n return { items: [] };\n }\n}\n\n/**\n * Add (or upsert the note for) a DID on the given flag's allowlist. Maps to\n * `POST /api/admin/feature-allowlists/{flag}`. Returns a {@link WriteResult};\n * never throws.\n */\nexport function addFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n const { note, ...rest } = opts;\n return apiWrite(config, `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`, 'POST', {\n body: note !== undefined ? { did, note } : { did },\n ...rest,\n });\n}\n\n/**\n * Remove a DID from the given flag's allowlist. Maps to\n * `DELETE /api/admin/feature-allowlists/{flag}/{did}`. Returns a\n * {@link WriteResult}; never throws.\n */\nexport function removeFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}/${encodeIdentifier(did)}`,\n 'DELETE',\n opts,\n );\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Options for {@link getAdminReviewQueues}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface GetAdminReviewQueuesOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/stats/review-queues`. */\nexport interface AdminReviewQueues {\n ideas: number;\n nameCorrections: number;\n pendingCompanies: number;\n /** Sum of the three queues. */\n total: number;\n generatedAt: string;\n}\n\n/**\n * Open counts for the three admin review queues (ideas, pending companies,\n * name corrections) plus their total.\n *\n * Unlike {@link listFeatureAllowlist} this does NOT swallow errors: a zeroed\n * payload would render as \"all queues clear\" in the admin nav, which is worse\n * than rendering nothing. Callers decide how to degrade.\n */\nexport async function getAdminReviewQueues(\n config: SifaApiConfig,\n opts: GetAdminReviewQueuesOptions = {},\n): Promise<AdminReviewQueues> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n const res = await apiFetch<Partial<AdminReviewQueues>>(config, '/api/admin/stats/review-queues', {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n\n const ideas = res.ideas ?? 0;\n const nameCorrections = res.nameCorrections ?? 0;\n const pendingCompanies = res.pendingCompanies ?? 0;\n\n return {\n ideas,\n nameCorrections,\n pendingCompanies,\n // Derived rather than trusted so an API that predates the field still\n // yields a usable pill count.\n total: res.total ?? ideas + nameCorrections + pendingCompanies,\n generatedAt: res.generatedAt ?? '',\n };\n}\n","import type { ActivityLabel } from '../../cards/adult-content.js';\nimport { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { QuotedPostResult } from './quoted-posts.js';\n\n/**\n * Liveness of an activity card's destination, as reported by sifa-api's\n * `/api/activity` enrichment (see sifa-api `url-health-checker`). How liveness\n * is measured depends on the card's health strategy (see `resolveCardHealth`):\n * first-party permalinks (`record`) are checked by record existence on the PDS;\n * foreign/derived targets (`url`) by HTTP reachability (HEAD, then GET).\n *\n * ok -- record exists, or the URL returned 2xx/3xx\n * broken -- confirmed dead (record deleted, or >=2 consecutive 4xx / >=5 consecutive 5xx)\n * unverifiable -- 403/429, PDS unreachable, or network error; NOT dead\n * unknown -- newly seen, not yet checked\n *\n * Consumers should only suppress UI on `'broken'`. All other values\n * (including missing) mean \"render normally\".\n */\nexport type ActivityItemLinkHealth = 'ok' | 'broken' | 'unverifiable' | 'unknown';\n\nexport interface HeatmapDay {\n date: string;\n total: number;\n apps: { appId: string; count: number }[];\n}\n\nexport interface HeatmapResponse {\n days: HeatmapDay[];\n appTotals: { appId: string; appName: string; total: number }[];\n thresholds: [number, number, number, number];\n}\n\nexport interface ActivityItem {\n uri: string;\n cid: string;\n collection: string;\n rkey: string;\n record: Record<string, unknown>;\n appId: string;\n appName: string;\n category: string;\n indexedAt: string;\n /**\n * Set by the server when an `app.bsky.embed.record` quote was already\n * resolved upstream (AppView path). Mutually exclusive with `quotedPostUri`.\n */\n quotedPost?: QuotedPostResult;\n /**\n * Set by the server when an `app.bsky.embed.record` quote needs client-side\n * resolution (PDS path). Pass batches to {@link resolveQuotedPosts}.\n * Mutually exclusive with `quotedPost`.\n */\n quotedPostUri?: string;\n /**\n * Reachability of the card's external destination as last checked by\n * sifa-api. Undefined for legacy responses; treat as 'unknown'.\n * See {@link ActivityItemLinkHealth}.\n */\n linkHealth?: ActivityItemLinkHealth;\n /**\n * Content labels from `app.bsky.feed.defs#postView.labels`. Set by\n * sifa-api for Bluesky posts; undefined for other sources and legacy\n * responses. Pass items to {@link hasAdultContent} to decide whether to\n * gate media. See {@link ActivityLabel}.\n */\n labels?: ActivityLabel[];\n /**\n * The owner has hidden this item from their profile. Only ever set on the\n * owner's own view of their feed -- every other surface omits hidden items\n * rather than flagging them -- so a card can offer an unhide in place.\n */\n hidden?: boolean;\n}\n\nexport interface ActivityTeaserResponse {\n items: ActivityItem[];\n blueskyGated?: boolean;\n backfillPending?: boolean;\n failedApps?: string[];\n}\n\nexport interface ActivityFeedResponse {\n items: ActivityItem[];\n cursor: string | null;\n hasMore: boolean;\n availableCategories?: string[];\n blueskyGated?: boolean;\n failedApps?: string[];\n}\n\n/**\n * Per-day activity counts for a profile across all ATproto apps. Returns\n * `null` on any error so callers can render a graceful empty state.\n */\nexport async function fetchHeatmapData(\n config: SifaApiConfig,\n handleOrDid: string,\n days: number,\n options: ApiFetchOptions = {},\n): Promise<HeatmapResponse | null> {\n const path = `/api/activity/${encodeIdentifier(handleOrDid)}/heatmap?days=${days}`;\n try {\n return await apiFetch<HeatmapResponse>(config, path, {\n next: { revalidate: 900, tags: [`heatmap-${handleOrDid}`] },\n ...options,\n });\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityTeaserOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Recent activity teaser for a profile (homepage-sized slice). Caps the\n * upstream wait so the SSR path cannot hang. Returns `null` on any error.\n */\nexport async function fetchActivityTeaser(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityTeaserOptions = {},\n): Promise<ActivityTeaserResponse | null> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityTeaserResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}/teaser`,\n {\n credentials: 'include',\n timeoutMs: 8000,\n next: { revalidate: 300, tags: [`activity-teaser-${handleOrDid}`] },\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityFeedOptions extends ApiFetchOptions {\n category?: string;\n limit?: number;\n cursor?: string;\n cookieHeader?: string;\n}\n\n/**\n * Paginated activity feed for a profile. Always fresh (`cache: 'no-store'`).\n * Returns `null` on any error.\n */\nexport async function fetchActivityFeed(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityFeedOptions = {},\n): Promise<ActivityFeedResponse | null> {\n const params = new URLSearchParams();\n if (options.category) params.set('category', options.category);\n if (options.limit) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityFeedResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}${qs ? `?${qs}` : ''}`,\n {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n","import { z } from 'zod';\n\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * A single merged pull request ingested from GitHub, as served by sifa-api's\n * `GET /api/me/github/pull-requests`. Mirrors the `github_contributions` row.\n */\nexport const GithubPullRequestSchema = z.object({\n prNumber: z.number(),\n repoOwner: z.string(),\n repoName: z.string(),\n title: z.string(),\n url: z.string(),\n language: z.string().nullable(),\n additions: z.number(),\n deletions: z.number(),\n /** ISO 8601 merge timestamp. */\n mergedAt: z.string(),\n});\nexport type GithubPullRequest = z.infer<typeof GithubPullRequestSchema>;\n\nexport const MyGithubPullRequestsResponseSchema = z.object({\n items: z.array(GithubPullRequestSchema),\n hasMore: z.boolean(),\n});\nexport type MyGithubPullRequestsResponse = z.infer<typeof MyGithubPullRequestsResponseSchema>;\n\nexport interface FetchMyGithubPullRequestsOptions extends ApiFetchOptions {\n limit?: number;\n offset?: number;\n /** Forwarded as the `cookie` header for server-side (SSR) calls. */\n cookieHeader?: string;\n}\n\n/**\n * Fetch the authenticated viewer's own ingested merged PRs (newest first).\n * Auth-scoped: relies on the session cookie (`credentials: 'include'`), so it\n * returns the caller's PRs, not a public handle's. Backs the GitHub importer.\n */\nexport async function fetchMyGithubPullRequests(\n config: SifaApiConfig,\n options: FetchMyGithubPullRequestsOptions = {},\n): Promise<MyGithubPullRequestsResponse> {\n const { limit, offset, cookieHeader, ...fetchOptions } = options;\n\n const params = new URLSearchParams();\n if (limit !== undefined) params.set('limit', String(limit));\n if (offset !== undefined) params.set('offset', String(offset));\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n const data = await apiFetch<unknown>(\n config,\n `/api/me/github/pull-requests${qs ? `?${qs}` : ''}`,\n {\n credentials: 'include',\n cache: 'no-store',\n ...fetchOptions,\n headers,\n },\n );\n\n return MyGithubPullRequestsResponseSchema.parse(data);\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Counts confirmed endorsements received by a DID. The backend's\n * `GET /api/endorsement/:did` already returns only confirmed endorsements\n * (via inner join with `endorsementConfirmations`), so this helper just\n * returns the array length. Failures return 0 so callers can route safely.\n *\n * Public endpoint -- no credentials needed.\n */\nexport async function fetchEndorsementCount(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<number> {\n const path = `/api/endorsement/${encodeIdentifier(did)}`;\n try {\n const data = await apiFetch<unknown>(config, path, {\n cache: 'no-store',\n timeoutMs: 5000,\n ...options,\n });\n if (typeof data !== 'object' || data === null || !('endorsements' in data)) {\n return 0;\n }\n const endorsements = data.endorsements;\n return Array.isArray(endorsements) ? endorsements.length : 0;\n } catch {\n return 0;\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface FetchNetworkStreamCountOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n *\n * When omitted, the request falls back to `credentials: 'include'` so\n * client-side calls work without extra plumbing.\n */\n cookieHeader?: string;\n}\n\n/**\n * Counts items in the authenticated user's network stream digest. The\n * underlying `GET /api/stream/network` endpoint may 404 while the feature\n * is in development; in that case (and on any other error) this returns\n * 0 so callers can route safely to a fallback experience.\n */\nexport async function fetchNetworkStreamCount(\n config: SifaApiConfig,\n did: string,\n options: FetchNetworkStreamCountOptions = {},\n): Promise<number> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<unknown>(\n config,\n `/api/stream/network?did=${encodeIdentifier(did)}`,\n {\n cache: 'no-store',\n timeoutMs: 5000,\n ...(options.cookieHeader ? {} : { credentials: 'include' }),\n ...options,\n headers,\n },\n );\n if (typeof data !== 'object' || data === null || !('items' in data)) {\n return 0;\n }\n const items = data.items;\n return Array.isArray(items) ? items.length : 0;\n } catch {\n return 0;\n }\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Per-URI reaction state for the authenticated viewer. */\nexport interface ReactionStatus {\n reacted: boolean;\n rkey?: string;\n collection?: string;\n}\n\n/** Result of checking whether the authenticated viewer has an account on a given app. */\nexport interface AccountCheckResult {\n hasAccount: boolean;\n appName: string;\n appUrl: string;\n}\n\nexport interface FetchReactionStatusOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Batch-look up reaction status for multiple URIs. Returns `{}` for an\n * empty input list (no network call) and `null` on any error.\n */\nexport async function fetchReactionStatus(\n config: SifaApiConfig,\n uris: string[],\n options: FetchReactionStatusOptions = {},\n): Promise<Record<string, ReactionStatus> | null> {\n if (uris.length === 0) return {};\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<Record<string, ReactionStatus>>(\n config,\n `/api/reactions/status?uris=${encodeURIComponent(uris.join(','))}`,\n {\n credentials: 'include',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\nexport interface CheckAppAccountOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/**\n * Check whether the authenticated viewer has an account on a given app.\n * Returns `null` on any error.\n */\nexport async function checkAppAccount(\n config: SifaApiConfig,\n appId: string,\n options: CheckAppAccountOptions = {},\n): Promise<AccountCheckResult | null> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<AccountCheckResult>(\n config,\n `/api/reactions/account-check/${encodeURIComponent(appId)}`,\n {\n credentials: 'include',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\n/** Result of a successful {@link createReaction}. */\nexport interface ReactionResult {\n uri: string;\n rkey: string;\n}\n\n/** Structured error returned by {@link createReaction} on failure. */\nexport interface ReactionError {\n type: 'scope_insufficient' | 'error';\n /** When `type === 'scope_insufficient'`, the lexicon scope the user must re-authorize for. */\n requiredScope?: string;\n}\n\n/**\n * Create a reaction (like / star) on a target ATproto record.\n *\n * Returns a discriminated-union result instead of the generic\n * {@link WriteResult} shape because reactions have a distinct\n * \"scope insufficient\" failure that callers handle differently from\n * other errors (it triggers an OAuth scope-upgrade flow rather than\n * an error toast).\n *\n * Never throws.\n */\nexport async function createReaction(\n config: SifaApiConfig,\n targetUri: string,\n appId: string,\n targetCid?: string,\n options: ApiFetchOptions = {},\n): Promise<{ ok: true; data: ReactionResult } | { ok: false; error: ReactionError }> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/reactions`;\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(options.headers ?? {}) },\n credentials: options.credentials ?? 'include',\n body: JSON.stringify({ targetUri, appId, targetCid }),\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 10_000),\n });\n\n if (!res.ok) {\n if (res.status === 403) {\n try {\n const body = (await res.json()) as { error?: string; requiredScope?: string };\n if (body.error === 'ScopeInsufficient') {\n return {\n ok: false,\n error: { type: 'scope_insufficient', requiredScope: body.requiredScope },\n };\n }\n } catch {\n // Fall through to generic error\n }\n }\n return { ok: false, error: { type: 'error' } };\n }\n\n const data = (await res.json()) as ReactionResult;\n return { ok: true, data };\n } catch {\n return { ok: false, error: { type: 'error' } };\n }\n}\n\n/**\n * Delete a reaction (like / star) on a target ATproto record. Returns\n * `{ success: true }` on 2xx, `{ success: false, error }` on failure.\n */\nexport function deleteReaction(\n config: SifaApiConfig,\n targetUri: string,\n appId: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/reactions', 'DELETE', {\n body: { targetUri, appId },\n ...options,\n });\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface QuotedPostAuthor {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n}\n\nexport interface QuotedPostImage {\n thumb: string;\n fullsize: string;\n alt?: string;\n}\n\nexport interface QuotedPostView {\n uri: string;\n cid: string;\n author: QuotedPostAuthor;\n text: string;\n createdAt: string;\n images?: QuotedPostImage[];\n}\n\nexport type QuotedPostResult =\n | { status: 'ok'; record: QuotedPostView }\n | { status: 'deleted'; uri: string }\n | { status: 'unavailable'; uri: string };\n\n/** Max URIs per request to `POST /api/quoted-posts/resolve` (mirrors server cap). */\nexport const QUOTED_POSTS_BATCH_MAX = 20;\n\nexport interface ResolveQuotedPostsOptions extends ApiFetchOptions {\n /** Cookie header for Next.js RSC server-side calls; ignored in browsers. */\n cookieHeader?: string;\n}\n\n/**\n * Resolve a batch of AT-URIs to their quoted-post snapshots via the Sifa AppView.\n *\n * Auto-deduplicates input URIs and splits requests into chunks of\n * {@link QUOTED_POSTS_BATCH_MAX} so callers can pass an arbitrary-length array.\n * Each chunk is fired in parallel. The server caches results in Valkey, so\n * repeated calls for the same URI are cheap.\n *\n * Returns a map of `uri -> QuotedPostResult`. URIs that fail (network error,\n * non-2xx, or the server omitting them) are absent from the map; the caller\n * should render a skeleton or tombstone for those.\n */\nexport async function resolveQuotedPosts(\n config: SifaApiConfig,\n uris: string[],\n options: ResolveQuotedPostsOptions = {},\n): Promise<Record<string, QuotedPostResult>> {\n if (uris.length === 0) return {};\n\n const unique = [...new Set(uris)];\n const batches: string[][] = [];\n for (let i = 0; i < unique.length; i += QUOTED_POSTS_BATCH_MAX) {\n batches.push(unique.slice(i, i + QUOTED_POSTS_BATCH_MAX));\n }\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n const results: Record<string, QuotedPostResult> = {};\n await Promise.all(\n batches.map(async (batch) => {\n try {\n const data = await apiFetch<Record<string, QuotedPostResult>>(\n config,\n '/api/quoted-posts/resolve',\n {\n method: 'POST',\n body: { uris: batch },\n credentials: 'include',\n timeoutMs: 8000,\n ...options,\n headers,\n },\n );\n Object.assign(results, data);\n } catch {\n // Leave failed URIs absent so the consumer can render a fallback.\n }\n }),\n );\n\n return results;\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Voter on a roadmap item. */\nexport interface RoadmapVoter {\n did: string;\n avatarUrl?: string;\n}\n\n/** Map of item key -> vote tally and voter list. */\nexport type RoadmapVotesResponse = Record<string, { count: number; voters: RoadmapVoter[] }>;\n\n/**\n * Public roadmap vote tallies, keyed by item. Returns `{}` on any error.\n */\nexport async function fetchRoadmapVotes(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RoadmapVotesResponse> {\n try {\n return await apiFetch<RoadmapVotesResponse>(config, '/api/roadmap/votes', {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return {};\n }\n}\n\nexport interface FetchMyRoadmapVotesOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Roadmap items the authenticated user has voted on. Returns `[]` on any\n * error or when the response payload is shaped unexpectedly.\n */\nexport async function fetchMyRoadmapVotes(\n config: SifaApiConfig,\n options: FetchMyRoadmapVotesOptions = {},\n): Promise<string[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ voted?: string[] }>(config, '/api/roadmap/votes/me', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.voted ?? [];\n } catch {\n return [];\n }\n}\n\n/** Result of a successful {@link castRoadmapVote} -- the created upvote record. */\nexport interface RoadmapVoteResult {\n uri: string;\n rkey: string;\n}\n\n/** Structured error returned by {@link castRoadmapVote} on failure. */\nexport interface RoadmapVoteError {\n type: 'scope_insufficient' | 'error';\n /**\n * When `type === 'scope_insufficient'`, the lexicon collection the user must\n * re-authorize for (e.g. `app.userinput.upvote`). sifa-web maps this to an\n * OAuth scope-upgrade flow (`/oauth/reauth?scope=repo:<collection>`).\n */\n requiredScope?: string;\n}\n\n/**\n * Discriminated-union result of {@link castRoadmapVote}. Exported so the\n * `useCastRoadmapVote` hook and SDK consumers can type mutation handlers\n * against a single source of truth.\n */\nexport type CastRoadmapVoteResult =\n { ok: true; data: RoadmapVoteResult } | { ok: false; error: RoadmapVoteError };\n\n/**\n * Cast a vote on a roadmap item by its key.\n *\n * Writes an `app.userinput.upvote` record into the viewer's PDS (server-side,\n * via their OAuth session). Returns a discriminated-union result rather than\n * the generic {@link WriteResult} because a first-time voter's PDS grant may\n * not yet include the `app.userinput.upvote` collection: the AppView responds\n * 403 `ScopeInsufficient`, which the caller handles by triggering an OAuth\n * scope upgrade rather than showing an error. Mirrors {@link createReaction}.\n *\n * Never throws.\n */\nexport async function castRoadmapVote(\n config: SifaApiConfig,\n key: string,\n options: ApiFetchOptions = {},\n): Promise<CastRoadmapVoteResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/roadmap/votes/${encodeURIComponent(key)}`;\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n // No body: the item key is in the URL. Do NOT declare a JSON content-type\n // for an empty body — Fastify rejects that with a 400 before the handler\n // runs. Only forward caller-provided headers.\n ...(options.headers ? { headers: options.headers } : {}),\n credentials: options.credentials ?? 'include',\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 10_000),\n });\n\n if (!res.ok) {\n if (res.status === 403) {\n try {\n const body = (await res.json()) as { error?: string; requiredScope?: string };\n if (body.error === 'ScopeInsufficient') {\n return {\n ok: false,\n error: { type: 'scope_insufficient', requiredScope: body.requiredScope },\n };\n }\n } catch {\n // Fall through to generic error.\n }\n }\n return { ok: false, error: { type: 'error' } };\n }\n\n const data = (await res.json()) as RoadmapVoteResult;\n return { ok: true, data };\n } catch {\n return { ok: false, error: { type: 'error' } };\n }\n}\n\n/** Retract a previously-cast roadmap vote. */\nexport function retractRoadmapVote(\n config: SifaApiConfig,\n key: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/roadmap/votes/${encodeURIComponent(key)}`, 'DELETE', options);\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * What the server managed to remove from the user's PDS.\n *\n * The wipe runs per collection, so it can partly succeed: `success: true` means\n * the account action completed, NOT that the PDS is clean. A UI that ignores\n * this can tell someone their data is gone while it is still on their data\n * server, so treat a non-empty `remaining` as \"not deleted\".\n *\n * Absent when the PDS was not touched (`deletePdsData: false`).\n */\nexport interface PdsWipeOutcome {\n /** Collections whose records were removed. */\n deleted: string[];\n /** Collections whose records are still on the PDS. Non-empty means not done. */\n remaining: string[];\n /**\n * The server could not enumerate the repo, so it does not know what survived.\n * Without this, that case is indistinguishable from \"nothing to delete\".\n */\n unknown: boolean;\n}\n\n/**\n * What a PDS wipe could not remove with the grant the session holds today.\n *\n * Read this BEFORE the destructive step. Deleting an account destroys the\n * session, so a missing scope cannot be granted afterwards -- there is nobody\n * left to ask. A non-empty `needsScopeFor` means the wipe would strand those\n * records on the user's data server.\n */\nexport interface WipePreview {\n /** id.sifa.* collections the current grant cannot delete. */\n needsScopeFor: string[];\n /**\n * The server could not enumerate the repo, so the gap list is not\n * authoritative. Distinct from an empty list, which means \"nothing to ask for\".\n */\n unknown?: boolean;\n}\n\n/**\n * Ask which id.sifa.* collections the current grant cannot delete.\n *\n * Unlike most read fetchers in this file's neighbourhood, a failure is NOT\n * flattened into an empty result: an empty gap list reads as \"a wipe will be\n * clean\", and a caller must not promise that on the strength of a request that\n * never arrived. Let it throw and warn.\n */\nexport function fetchWipePreview(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WipePreview> {\n return apiFetch<WipePreview>(config, '/api/profile/wipe-preview', {\n credentials: 'include',\n ...options,\n });\n}\n\n/** Extended write result for {@link resetProfile}. */\nexport interface ResetProfileResult extends WriteResult {\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/** Extended write result for {@link deleteAccount}. */\nexport interface DeleteAccountResult extends WriteResult {\n /** The deleted handle, returned by the server for confirmation UIs. */\n handle?: string;\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/**\n * Reset the authenticated user's Sifa profile.\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS. `deletePdsData: false` only removes the AppView's\n * indexed state -- the records on the PDS are left intact and could be\n * re-indexed later.\n *\n * Destructive. Server enforces session check + attestation; the SDK\n * does not gate on additional confirmation. Wrap call sites in your\n * own modal if you want a UX confirmation step.\n */\nexport function resetProfile(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<ResetProfileResult> {\n return apiWrite<{ ok?: boolean; pds?: PdsWipeOutcome }>(config, '/api/profile/reset', 'DELETE', {\n body: { deletePdsData },\n ...options,\n });\n}\n\n/**\n * Delete the authenticated user's account. Returns the deleted handle\n * on success (used by the post-delete confirmation screen).\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS; `false` leaves the PDS records intact.\n *\n * Destructive. Same caveat as {@link resetProfile}.\n */\nexport function deleteAccount(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<DeleteAccountResult> {\n return apiWrite<{ ok?: boolean; handle?: string; pds?: PdsWipeOutcome }>(\n config,\n '/api/profile/account',\n 'DELETE',\n {\n body: { deletePdsData },\n ...options,\n },\n );\n}\n","import type { RepoDeleteResult, RepoInventory } from '../../repo/types.js';\nimport { apiFetch, apiWrite, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Read what the user's PDS actually holds under id.sifa.*.\n *\n * A failure is not flattened into an empty inventory. Zero records reads as\n * \"Sifa has stored nothing about you\", and a request that never arrived must\n * not be allowed to say that. Let it throw.\n */\nexport function fetchRepoInventory(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RepoInventory> {\n return apiFetch<RepoInventory>(config, '/api/me/repo-inventory', {\n credentials: 'include',\n ...options,\n });\n}\n\nexport interface RepoDeleteInput {\n collection: string;\n /** The records to remove. Omit and set `all` to remove the whole collection. */\n rkeys?: string[];\n /**\n * Remove every record in the collection, including ones written between the\n * inventory read and this call. A UI offering \"delete all of X\" must send\n * this rather than the rkeys it happened to see, or a record created in\n * between silently survives a delete the user believes was complete.\n */\n all?: boolean;\n}\n\n/**\n * Delete records from the user's own repo.\n *\n * The returned `success` means the request was accepted, NOT that the records\n * are gone: read `results` for that, per record. `needsScopeUpgrade` means\n * nothing was attempted and the user has to grant the scope first.\n *\n * Destructive and not undoable -- a deleted record's CID cannot be restored.\n * The server enforces the id.sifa.* boundary and the session check; the SDK\n * adds no confirmation step, so wrap call sites in one.\n */\nexport function deleteRepoRecords(\n config: SifaApiConfig,\n input: RepoDeleteInput,\n options: ApiFetchOptions = {},\n): Promise<RepoDeleteResult & { success: boolean; error?: string }> {\n return apiWrite<RepoDeleteResult>(config, '/api/me/repo-delete', 'POST', {\n body: input,\n ...options,\n });\n}\n\n/**\n * URL of the raw-record download.\n *\n * A URL rather than a fetcher: the response is a file the browser saves, and\n * routing it through fetch would buffer the whole repo in memory to hand it\n * straight back to a download anchor.\n */\nexport function repoExportUrl(config: SifaApiConfig): string {\n return `${config.baseUrl}/api/me/repo-export`;\n}\n","import { apiFetch, apiFetchOrNull, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** A node in the personal network graph. */\nexport interface NetworkMapNode {\n did: string;\n handle: string;\n displayName: string;\n avatar: string | null;\n /** Number of edges this node participates in within the rendered graph. */\n degree: number;\n /** Phase 2: community detection cluster id. */\n cluster?: number;\n /** Phase 2: pre-computed layout coordinates. */\n x?: number;\n y?: number;\n}\n\n/** A directed edge in the personal network graph. */\nexport interface NetworkMapEdge {\n source: string;\n target: string;\n mutual: boolean;\n /** Networks this edge was observed in, e.g. `['sifa', 'bluesky']`. */\n sources: string[];\n}\n\n/** The graph payload itself, decoupled from response metadata. */\nexport interface NetworkMapGraphData {\n nodes: NetworkMapNode[];\n edges: NetworkMapEdge[];\n /** Phase 2: cluster metadata for legend rendering. */\n clusters?: Array<{ id: number; label: string; color: string }>;\n}\n\n/** Cached graph response. */\nexport interface NetworkMapResponse {\n generatedAt: string;\n expiresAt: string;\n graph: NetworkMapGraphData;\n stats: {\n totalNodes: number;\n totalEdges: number;\n mutualCount: number;\n sources: Record<string, number>;\n };\n}\n\n/** Async job tracking generation progress. */\nexport interface NetworkMapGenerationJob {\n jobId: string;\n did: string;\n status: 'pending' | 'complete' | 'failed';\n /** 0..100 */\n progress: number;\n createdAt: string;\n completedAt?: string;\n error?: string;\n /**\n * Queue position when the job is still pending and not yet picked up\n * by the worker. 0 = next to run. Absent for in-flight or terminal\n * jobs (and for any backend that doesn't yet report position).\n */\n position?: number;\n /**\n * Estimated remaining seconds, derived server-side from the median\n * historical duration for the user's follow-count bucket multiplied\n * by `position + 1`. Absent when no historical data exists yet.\n */\n etaSeconds?: number;\n}\n\n/** Returned by `initiateNetworkMapGeneration` when a new job was started or one was already running. */\nexport interface NetworkMapPendingJob {\n jobId: string;\n status: 'pending' | 'cached';\n}\n\n/** Discriminate the union returned by `initiateNetworkMapGeneration`. */\nexport function isNetworkMapResponse(\n value: NetworkMapPendingJob | NetworkMapResponse,\n): value is NetworkMapResponse {\n return 'graph' in value;\n}\n\n/**\n * Kick off a personal network-map computation. The backend returns the\n * cached map immediately when fresh, otherwise it returns a job id that\n * the caller polls via `checkNetworkMapJobStatus`.\n */\nexport async function initiateNetworkMapGeneration(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapPendingJob | NetworkMapResponse> {\n return apiFetch<NetworkMapPendingJob | NetworkMapResponse>(config, '/api/network-map/generate', {\n method: 'POST',\n credentials: 'include',\n ...options,\n });\n}\n\n/**\n * Poll the status of an in-flight generation job. Throws on 404 (unknown\n * or expired job) — callers may want to treat that as terminal failure.\n */\nexport async function checkNetworkMapJobStatus(\n config: SifaApiConfig,\n jobId: string,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapGenerationJob> {\n return apiFetch<NetworkMapGenerationJob>(\n config,\n `/api/network-map/status/${encodeURIComponent(jobId)}`,\n {\n credentials: 'include',\n ...options,\n },\n );\n}\n\n/**\n * Fetch the most recent cached network map for the authenticated user.\n * Returns `null` when no map has ever been generated (404).\n */\nexport async function fetchNetworkMap(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapResponse | null> {\n return apiFetchOrNull<NetworkMapResponse>(config, '/api/network-map', {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n });\n}\n","import { z } from 'zod';\n\n/**\n * Organization entity-resolution payloads (#159). Shared by the typeahead,\n * selection, and grow-on-demand import-search endpoints on sifa-api.\n */\n\n/**\n * A nullable string constrained to an http(s) URL. Rejects `javascript:` and\n * other script-bearing schemes at the SDK boundary so a hostile API response\n * cannot smuggle an XSS payload into a rendered `href`/`src`. Note: Wikidata\n * entity URIs are canonically `http://`, so both http and https are allowed.\n */\nconst httpUrlNullable = z\n .string()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'must be an http(s) URL' })\n .nullable();\n\nconst searchResultCommon = {\n kind: z.string(),\n name: z.string(),\n domain: z.string().nullable(),\n country: z.string().nullable(),\n logoUrl: httpUrlNullable,\n parentName: z.string().nullable(),\n};\n\n/**\n * A single typeahead row. Discriminated on `source`: a curated `entity` row\n * carries `entityId`, a `pdl` staging row carries `pdlId`. The union guarantees\n * the identifier for the row's source is always present, so a stable React key\n * can never be `entity:undefined`. The disambiguation fields\n * (domain/country/parentName) drive the dropdown display.\n */\nexport const EntitySearchResultSchema = z.discriminatedUnion('source', [\n z.object({\n source: z.literal('entity'),\n entityId: z.number().int().positive(),\n ...searchResultCommon,\n }),\n z.object({\n source: z.literal('pdl'),\n pdlId: z.string().min(1),\n ...searchResultCommon,\n }),\n]);\nexport type EntitySearchResult = z.infer<typeof EntitySearchResultSchema>;\n\n/** Response of `GET /api/entities/search`. */\nexport const EntitySearchResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n hasMore: z.boolean(),\n});\nexport type EntitySearchResponse = z.infer<typeof EntitySearchResponseSchema>;\n\n/**\n * Body of `POST /api/entities/select`: promote a PDL row OR bump an entity.\n * Exactly one of `entityId`/`pdlId` must be present -- supplying both is\n * ambiguous (the server would have to silently pick one) and is rejected.\n */\nexport const EntitySelectRequestSchema = z\n .object({\n entityId: z.number().int().positive().optional(),\n pdlId: z.string().min(1).optional(),\n })\n .refine((v) => (v.entityId != null) !== (v.pdlId != null), {\n message: 'exactly one of entityId or pdlId is required',\n });\nexport type EntitySelectRequest = z.infer<typeof EntitySelectRequestSchema>;\n\n/** Response of `POST /api/entities/select`. `entityRef` is the portable\n * Wikidata/ROR/LEI URI to write to the position record, or null for a\n * PDL-only entity (its resolution stays AppView-side). */\nexport const EntitySelectResponseSchema = z.object({\n entityId: z.number().int().positive(),\n slug: z.string(),\n kind: z.string(),\n canonicalName: z.string(),\n domain: z.string().nullable(),\n /**\n * The entity's website, gated to sources trustworthy enough to prefill into a\n * record the user signs. Narrower than `domain`, which is a display value and\n * may come from a crawl. Null when the entity has no such source.\n */\n website: httpUrlNullable.default(null),\n /** Which tier `website` came from. Crawled is never an accepted source. */\n websiteTier: z.enum(['org', 'curated']).nullable().default(null),\n entityRef: httpUrlNullable,\n});\nexport type EntitySelectResponse = z.infer<typeof EntitySelectResponseSchema>;\n\n/** Response of `POST /api/entities/import-search`. */\nexport const EntityImportSearchResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n});\nexport type EntityImportSearchResponse = z.infer<typeof EntityImportSearchResponseSchema>;\n\n/**\n * Body of the domain grow-on-demand endpoints (`POST /api/entities/resolve-domain`\n * and `POST /api/entities/mint-domain`). The server re-validates the value as a\n * registrable domain; 253 is the max DNS name length.\n */\nexport const EntityResolveDomainRequestSchema = z.object({\n domain: z.string().min(1).max(253),\n});\nexport type EntityResolveDomainRequest = z.infer<typeof EntityResolveDomainRequestSchema>;\n\n/**\n * Response of `POST /api/entities/resolve-domain` (grow-on-demand Branch 1). Any\n * notable companies whose official website is the domain, imported from Wikidata.\n * `canMint` is true when nothing notable matched AND the domain is eligible for\n * the user-initiated mint-from-domain path -- it drives the \"Add <domain>\"\n * affordance.\n */\nexport const EntityResolveDomainResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n canMint: z.boolean(),\n});\nexport type EntityResolveDomainResponse = z.infer<typeof EntityResolveDomainResponseSchema>;\n\n/**\n * Response of `POST /api/entities/mint-domain` (grow-on-demand Branch 2). The\n * linkable entity minted from (or already resolved for) the domain. A non-2xx\n * status (e.g. the domain is not mintable, a confusable look-alike, or the site\n * yielded nothing usable) surfaces as a thrown error, not a null result.\n *\n * `pending` is true when the entity is a fresh hidden-pending mint: the\n * requesting user's own link resolves to it immediately, but it stays out of\n * other users' typeahead + aggregation until an admin approves it. Clients should\n * reflect this (\"added -- pending review\") rather than \"added & live\".\n */\nexport const EntityMintDomainResponseSchema = z.object({\n result: EntitySearchResultSchema,\n pending: z.boolean(),\n});\nexport type EntityMintDomainResponse = z.infer<typeof EntityMintDomainResponseSchema>;\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport {\n EntitySearchResponseSchema,\n EntitySelectResponseSchema,\n EntityImportSearchResponseSchema,\n EntityResolveDomainResponseSchema,\n EntityMintDomainResponseSchema,\n type EntitySearchResponse,\n type EntitySearchResult,\n type EntitySelectRequest,\n type EntitySelectResponse,\n type EntityResolveDomainResponse,\n type EntityMintDomainResponse,\n} from '../../schemas/entity.js';\n\nconst EMPTY_SEARCH: EntitySearchResponse = { results: [], hasMore: false };\n\n/**\n * Organization typeahead. Returns curated entities first, then the PDL crawl,\n * deduped by domain. Empty input returns an empty result without a network call.\n */\nexport async function fetchEntitySearch(\n config: SifaApiConfig,\n query: string,\n limit?: number,\n options: ApiFetchOptions = {},\n): Promise<EntitySearchResponse> {\n if (!query.trim()) return EMPTY_SEARCH;\n const params = new URLSearchParams({ q: query });\n if (limit !== undefined) params.set('limit', String(limit));\n const data = await apiFetch<unknown>(config, `/api/entities/search?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n return EntitySearchResponseSchema.parse(data);\n}\n\n/**\n * Record a selection: promote a PDL row into a canonical entity (dedupe by\n * domain) or bump an existing entity's usage counter. Returns the entity plus\n * its portable `entityRef` (null for PDL-only entities). Requires a session.\n */\nexport async function selectEntity(\n config: SifaApiConfig,\n body: EntitySelectRequest,\n options: ApiFetchOptions = {},\n): Promise<EntitySelectResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/select', {\n method: 'POST',\n body,\n credentials: 'include',\n ...options,\n });\n return EntitySelectResponseSchema.parse(data);\n}\n\n/**\n * Grow-on-demand: when the local typeahead misses, resolve the query live via\n * Wikidata, import the org-class matches, and return them. Requires a session.\n * Empty input returns an empty array without a network call.\n */\nexport async function importSearchEntities(\n config: SifaApiConfig,\n query: string,\n options: ApiFetchOptions = {},\n): Promise<EntitySearchResult[]> {\n if (!query.trim()) return [];\n const data = await apiFetch<unknown>(config, '/api/entities/import-search', {\n method: 'POST',\n body: { q: query },\n credentials: 'include',\n ...options,\n });\n return EntityImportSearchResponseSchema.parse(data).results;\n}\n\n/**\n * Grow-on-demand by domain, Branch 1: when a domain-shaped typeahead query\n * misses locally, resolve any notable company whose official website is that\n * domain (Wikidata reverse P856), importing the matches. Read-only w.r.t.\n * minting. `canMint` tells the caller whether to offer the user-initiated\n * \"Add <domain>\" affordance. Requires a session.\n */\nexport async function resolveEntityDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<EntityResolveDomainResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/resolve-domain', {\n method: 'POST',\n body: { domain },\n credentials: 'include',\n ...options,\n });\n return EntityResolveDomainResponseSchema.parse(data);\n}\n\n/**\n * Grow-on-demand by domain, Branch 2 (user-initiated): mint a crawled-tier\n * entity from the domain's own homepage (or resolve it to a notable company if\n * one exists). Throws on a non-2xx response (domain not mintable, or the site\n * yielded nothing usable). Requires a session.\n */\nexport async function mintEntityDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<EntityMintDomainResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/mint-domain', {\n method: 'POST',\n body: { domain },\n credentials: 'include',\n ...options,\n });\n return EntityMintDomainResponseSchema.parse(data);\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\nimport type { OrgClaimRequestInput } from '../../schemas/write/org-claim.js';\nimport type {\n OrgDomainChallengeRequestInput,\n OrgDomainVerifyRequestInput,\n OrgNotificationEmailRequestInput,\n OrgProfileUpdateRequestInput,\n} from '../../schemas/write/org-settings.js';\n\n/** How a single entity binding was resolved during a claim. */\nexport interface OrgClaimBinding {\n entityId: number;\n entityRef: string;\n validatedBy: string | null;\n status: 'active' | 'pending';\n dissolved: boolean;\n}\n\n/** The public org-profile echo returned by claim / update endpoints (no `contact`). */\nexport interface OrgProfileEcho {\n name: string;\n description: string | null;\n website: string | null;\n entityRefs: string[];\n}\n\n/** Response body of `POST /api/org/claim`. */\nexport interface OrgClaimResult {\n orgDid: string;\n status: 'active' | 'review';\n bindings: OrgClaimBinding[];\n orgProfile: OrgProfileEcho;\n}\n\n/** Response body of `PUT /api/org/profile`. */\nexport interface OrgProfileUpdateResult {\n ok: boolean;\n orgProfile: OrgProfileEcho;\n}\n\n/** Response body of `POST /api/org/domains/challenge`. */\nexport interface OrgDomainChallengeResult {\n domain: string;\n txtRecordName: string;\n txtRecordValue: string;\n}\n\n/** Response body of `POST /api/org/domains/verify` (happy path). */\nexport interface OrgDomainVerifyResult {\n status: 'verified' | 'pending';\n domain: string;\n}\n\n/** Response body of `POST /api/org/notification-emails`. */\nexport interface OrgNotificationEmailAddResult {\n ok: boolean;\n status: string;\n}\n\n/** Response body of `DELETE /api/org/notification-emails`. */\nexport interface OrgNotificationEmailRemoveResult {\n ok: boolean;\n removed: number;\n}\n\n/**\n * Finalize an org profile claim (`POST /api/org/claim`). Auth-gated (org-claim\n * JIT scope) and floor-checked server-side. Never throws -- returns the\n * structured {@link OrgClaimResult} folded into a {@link WriteResult} on success,\n * or `{ success: false, error, pdsHost? }` on failure.\n */\nexport function submitOrgClaim(\n config: SifaApiConfig,\n body: OrgClaimRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgClaimResult>> {\n return apiWrite<Partial<OrgClaimResult>>(config, '/api/org/claim', 'POST', { body, ...options });\n}\n\n/**\n * Edit the org record (`PUT /api/org/profile`). Fresh-from-body server-side PUT\n * (a cleared optional field is dropped, no spread-merge). Never throws.\n */\nexport function updateOrgProfile(\n config: SifaApiConfig,\n body: OrgProfileUpdateRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgProfileUpdateResult>> {\n return apiWrite<Partial<OrgProfileUpdateResult>>(config, '/api/org/profile', 'PUT', {\n body,\n ...options,\n });\n}\n\n/**\n * Issue a one-time DNS TXT domain challenge (`POST /api/org/domains/challenge`).\n * Returns the TXT record name + value the org must publish. Never throws.\n */\nexport function requestOrgDomainChallenge(\n config: SifaApiConfig,\n body: OrgDomainChallengeRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgDomainChallengeResult>> {\n return apiWrite<Partial<OrgDomainChallengeResult>>(config, '/api/org/domains/challenge', 'POST', {\n body,\n ...options,\n });\n}\n\n/**\n * Verify a DNS TXT domain challenge (`POST /api/org/domains/verify`). On success\n * `status` is `verified` or `pending`. Expired / confusable / not-found map to\n * non-2xx server responses and surface as `{ success: false, error }`. Never\n * throws.\n */\nexport function verifyOrgDomain(\n config: SifaApiConfig,\n body: OrgDomainVerifyRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgDomainVerifyResult>> {\n return apiWrite<Partial<OrgDomainVerifyResult>>(config, '/api/org/domains/verify', 'POST', {\n body,\n ...options,\n });\n}\n\n/**\n * Add an org notification email (`POST /api/org/notification-emails`). The\n * address must use a domain the org controls (checked server-side). An\n * individual verification email is enqueued through the (dormant) sending\n * pipeline. Never throws.\n */\nexport function addOrgNotificationEmail(\n config: SifaApiConfig,\n body: OrgNotificationEmailRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgNotificationEmailAddResult>> {\n return apiWrite<Partial<OrgNotificationEmailAddResult>>(\n config,\n '/api/org/notification-emails',\n 'POST',\n { body, ...options },\n );\n}\n\n/**\n * Remove an org notification email (`DELETE /api/org/notification-emails`).\n * Never throws.\n */\nexport function removeOrgNotificationEmail(\n config: SifaApiConfig,\n body: OrgNotificationEmailRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgNotificationEmailRemoveResult>> {\n return apiWrite<Partial<OrgNotificationEmailRemoveResult>>(\n config,\n '/api/org/notification-emails',\n 'DELETE',\n { body, ...options },\n );\n}\n","/**\n * Canonical rule for picking the \"primary\" position to surface on profile cards,\n * social previews, and structured-data outputs.\n *\n * Without this shared helper, different surfaces (visible hero, OG image,\n * <meta description>, JSON-LD) re-derived \"primary\" inconsistently and diverged\n * for users with multiple concurrent roles.\n *\n * A `hidden` position is one the user chose not to show on their public profile.\n * It is never surfaced as the featured role — hidden wins over `primary`, so a\n * role flagged both hidden and primary is excluded rather than featured.\n *\n * Rules (in order):\n * 1. A position the user explicitly flagged `primary` AND that is still active AND not hidden.\n * 2. Otherwise, the active, non-hidden position with the most recent `startedAt`.\n * 3. Otherwise, undefined (no eligible position).\n */\n\nexport interface PrimaryPositionCandidate {\n startedAt?: string;\n endedAt?: string;\n primary?: boolean;\n hidden?: boolean;\n}\n\nexport function pickPrimaryPosition<T extends PrimaryPositionCandidate>(\n positions: readonly T[] | undefined,\n): T | undefined {\n if (!positions || positions.length === 0) return undefined;\n\n const active = positions.filter((p) => !p.endedAt && !p.hidden);\n if (active.length === 0) return undefined;\n\n const flagged = active.find((p) => p.primary === true);\n if (flagged) return flagged;\n\n return [...active].sort((a, b) => (b.startedAt ?? '').localeCompare(a.startedAt ?? ''))[0];\n}\n","/**\n * Compact professional summary derived from a {@link ProfileView}.\n *\n * The full `id.sifa.getProfileView` payload carries every section (all\n * positions, education, skills, publications, talks, and more). Third-party\n * surfaces that only want to show \"who is this, what do they do now\" — a badge,\n * a maintainer card, a byline — need a much smaller shape. This is that shape,\n * derived with the same canonical rules the Sifa web app uses (see\n * {@link pickPrimaryPosition}) so an embedded summary matches the profile page.\n *\n * Pure and I/O-free: pass it a view you already fetched. For the fetch +\n * summarize convenience, use `fetchProfileSummary` from `@singi-labs/sifa-sdk`.\n */\n\nimport type { ProfileView } from '../types/profile-view.js';\nimport { pickPrimaryPosition } from './primary-position.js';\n\nexport interface ProfileSummary {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n pronouns?: string;\n headline?: string;\n /** Title of the current primary role, if the person has an active position. */\n currentTitle?: string;\n /** Current employer: the resolved entity name when linked, else the free-text company. */\n currentCompany?: string;\n /** Skill names in the order the AppView returns them, capped by `maxSkills`. */\n topSkills: string[];\n /** Whether the profile is claimed by its owner (vs an unclaimed placeholder). */\n claimed: boolean;\n}\n\nexport interface SummarizeProfileViewOptions {\n /** Maximum number of skills to include in `topSkills`. Default 5; negatives clamp to 0. */\n maxSkills?: number;\n}\n\nconst DEFAULT_MAX_SKILLS = 5;\n\nexport function summarizeProfileView(\n view: ProfileView,\n options: SummarizeProfileViewOptions = {},\n): ProfileSummary {\n const limit = Math.max(0, options.maxSkills ?? DEFAULT_MAX_SKILLS);\n const primary = pickPrimaryPosition(view.positions);\n\n return {\n did: view.did,\n handle: view.handle,\n displayName: view.displayName,\n avatar: view.avatar,\n pronouns: view.pronouns,\n headline: view.headline,\n currentTitle: primary?.title,\n currentCompany: primary ? (primary.entityName ?? primary.company) : undefined,\n topSkills: (view.skills ?? []).slice(0, limit).map((s) => s.name),\n claimed: view.claimed ?? false,\n };\n}\n","import {\n summarizeProfileView,\n type ProfileSummary,\n type SummarizeProfileViewOptions,\n} from '../../logic/profile-summary.js';\nimport { fetchGetProfileView } from './get-profile-view.js';\nimport type { ApiFetchOptions, SifaApiConfig } from '../client.js';\n\n/**\n * Fetch the aggregated public profile via `id.sifa.getProfileView` and reduce it\n * to a compact {@link ProfileSummary} (identity, headline, current role/employer,\n * top skills). Convenience over `fetchGetProfileView` + `summarizeProfileView`,\n * for third-party surfaces that only want the headline facts.\n *\n * Returns `null` when the AppView has no profile for the actor. Server-callable\n * (Next.js RSC) and client-callable (Expo, browser).\n */\nexport async function fetchProfileSummary(\n config: SifaApiConfig,\n actor: string,\n options: SummarizeProfileViewOptions & ApiFetchOptions = {},\n): Promise<ProfileSummary | null> {\n const { maxSkills, ...fetchOptions } = options;\n const view = await fetchGetProfileView(config, actor, fetchOptions);\n return view ? summarizeProfileView(view, { maxSkills }) : null;\n}\n","/**\n * Query key factory for TanStack Query.\n *\n * Keys are read-only tuples; the hierarchy matches the SDK's fetcher\n * grouping. Use these instead of inline arrays so consumers can target\n * `queryClient.invalidateQueries({ queryKey: keys.profile.all() })` and\n * similar patterns without typos.\n *\n * Convention: every leaf key starts with the namespace ('sifa') so\n * consumers can invalidate everything Sifa-related in one call.\n */\nexport const sifaQueryKeys = {\n all: () => ['sifa'] as const,\n\n profile: {\n all: () => ['sifa', 'profile'] as const,\n byHandle: (handleOrDid: string) => ['sifa', 'profile', handleOrDid] as const,\n atFundLink: (did: string) => ['sifa', 'profile', 'at-fund-link', did] as const,\n view: (actor: string) => ['sifa', 'profile', 'view', actor] as const,\n externalAccounts: (handleOrDid: string) =>\n ['sifa', 'profile', 'external-accounts', handleOrDid] as const,\n // Session-scoped: the AppView reads the owner from the session cookie, so\n // there is only ever one completeness result per client.\n completeness: () => ['sifa', 'profile', 'completeness'] as const,\n },\n\n position: {\n all: () => ['sifa', 'position'] as const,\n byOwner: (did: string) => ['sifa', 'position', 'by-owner', did] as const,\n // Session-scoped: the AppView reads the owner from the session cookie.\n unlinked: () => ['sifa', 'position', 'unlinked'] as const,\n },\n\n // Aggregate inbox counts for the header bell badge (session-scoped). The first\n // aggregate namespace: it fans in across confirmations, endorsements, drift,\n // unlinked positions and profile completeness on the server.\n inbox: {\n all: () => ['sifa', 'inbox'] as const,\n counts: () => ['sifa', 'inbox', 'counts'] as const,\n },\n\n search: {\n all: () => ['sifa', 'search'] as const,\n profiles: (filters: Record<string, unknown>) =>\n ['sifa', 'search', 'profiles', filters] as const,\n companies: (filters: Record<string, unknown>) =>\n ['sifa', 'search', 'companies', filters] as const,\n skills: (query: string) => ['sifa', 'search', 'skills', query] as const,\n canonicalSkills: (query: string, limit: number) =>\n ['sifa', 'search', 'canonical-skills', query, limit] as const,\n filters: () => ['sifa', 'search', 'filters'] as const,\n },\n\n entity: {\n all: () => ['sifa', 'entity'] as const,\n search: (query: string, limit: number) => ['sifa', 'entity', 'search', query, limit] as const,\n },\n\n discovery: {\n all: () => ['sifa', 'discovery'] as const,\n similar: (did: string, limit: number) => ['sifa', 'discovery', 'similar', did, limit] as const,\n suggestions: (opts: Record<string, unknown>) =>\n ['sifa', 'discovery', 'suggestions', opts] as const,\n suggestionCount: (since: string | undefined) =>\n ['sifa', 'discovery', 'suggestion-count', since ?? null] as const,\n featured: () => ['sifa', 'discovery', 'featured'] as const,\n },\n\n follow: {\n all: () => ['sifa', 'follow'] as const,\n following: (opts: Record<string, unknown>) => ['sifa', 'follow', 'following', opts] as const,\n followers: (handle: string) => ['sifa', 'follow', 'followers', handle] as const,\n followingOf: (handle: string) => ['sifa', 'follow', 'following-of', handle] as const,\n feed: (opts: Record<string, unknown>) => ['sifa', 'follow', 'feed', opts] as const,\n mutuals: (handle: string) => ['sifa', 'follow', 'mutuals', handle] as const,\n blueskySuggestions: () => ['sifa', 'follow', 'bluesky-suggestions'] as const,\n },\n\n admin: {\n all: () => ['sifa', 'admin'] as const,\n featureAllowlist: (flag: string) => ['sifa', 'admin', 'feature-allowlist', flag] as const,\n reviewQueues: () => ['sifa', 'admin', 'review-queues'] as const,\n },\n\n stats: {\n all: () => ['sifa', 'stats'] as const,\n homepage: () => ['sifa', 'stats', 'homepage'] as const,\n },\n\n apps: {\n all: () => ['sifa', 'apps'] as const,\n registry: () => ['sifa', 'apps', 'registry'] as const,\n hidden: () => ['sifa', 'apps', 'hidden'] as const,\n },\n\n auth: {\n all: () => ['sifa', 'auth'] as const,\n // Session-scoped: the AppView reads the account list from the browser's\n // cookies, so there is only ever one list per client.\n accounts: () => ['sifa', 'auth', 'accounts'] as const,\n },\n\n activity: {\n all: () => ['sifa', 'activity'] as const,\n heatmap: (handleOrDid: string, days: number) =>\n ['sifa', 'activity', 'heatmap', handleOrDid, days] as const,\n teaser: (handleOrDid: string) => ['sifa', 'activity', 'teaser', handleOrDid] as const,\n feed: (handleOrDid: string, opts: Record<string, unknown>) =>\n ['sifa', 'activity', 'feed', handleOrDid, opts] as const,\n // Session-scoped: the AppView reads the caller's own hides from their\n // cookie, so there is only ever one list per client.\n hiddenItems: () => ['sifa', 'activity', 'hidden-items'] as const,\n },\n\n github: {\n all: () => ['sifa', 'github'] as const,\n myPullRequests: (opts: { limit?: number; offset?: number }) =>\n ['sifa', 'github', 'my-pull-requests', opts] as const,\n },\n\n endorsement: {\n all: () => ['sifa', 'endorsement'] as const,\n count: (did: string) => ['sifa', 'endorsement', 'count', did] as const,\n // Scoped to the session rather than a DID -- the AppView reads the subject\n // from the session cookie, so there is only ever one inbox per client.\n pending: () => ['sifa', 'endorsement', 'pending'] as const,\n // Also session-scoped: the AppView picks the candidate from the viewer's\n // own follows, dismissals and blocks.\n reciprocity: () => ['sifa', 'endorsement', 'reciprocity'] as const,\n received: (did: string) => ['sifa', 'endorsement', 'received', did] as const,\n },\n\n confirmation: {\n all: () => ['sifa', 'confirmation'] as const,\n // Scoped to the session for the same reason as the endorsement inbox: the\n // AppView reads the subject from the session cookie, so there is only ever\n // one inbox per client.\n pending: () => ['sifa', 'confirmation', 'pending'] as const,\n /** Confirmations this session has given, for the withdraw surface. */\n given: () => ['sifa', 'confirmation', 'given'] as const,\n },\n\n stream: {\n all: () => ['sifa', 'stream'] as const,\n networkCount: (did: string) => ['sifa', 'stream', 'network-count', did] as const,\n },\n\n reactions: {\n all: () => ['sifa', 'reactions'] as const,\n status: (uris: string[]) => ['sifa', 'reactions', 'status', uris] as const,\n accountCheck: (appId: string) => ['sifa', 'reactions', 'account-check', appId] as const,\n },\n\n roadmap: {\n all: () => ['sifa', 'roadmap'] as const,\n votes: () => ['sifa', 'roadmap', 'votes'] as const,\n myVotes: () => ['sifa', 'roadmap', 'my-votes'] as const,\n },\n\n bskyPreferences: {\n all: () => ['sifa', 'bsky-preferences'] as const,\n contentLabels: () => ['sifa', 'bsky-preferences', 'content-labels'] as const,\n },\n\n repoInventory: {\n all: () => ['sifa', 'repo-inventory'] as const,\n list: () => ['sifa', 'repo-inventory', 'list'] as const,\n },\n destructive: {\n all: () => ['sifa', 'destructive'] as const,\n wipePreview: () => ['sifa', 'destructive', 'wipe-preview'] as const,\n },\n} as const;\n\nexport type SifaQueryKey =\n | ReturnType<typeof sifaQueryKeys.all>\n | ReturnType<typeof sifaQueryKeys.profile.all>\n | ReturnType<typeof sifaQueryKeys.profile.byHandle>\n | ReturnType<typeof sifaQueryKeys.profile.atFundLink>\n | ReturnType<typeof sifaQueryKeys.profile.externalAccounts>\n | ReturnType<typeof sifaQueryKeys.profile.completeness>\n | ReturnType<typeof sifaQueryKeys.position.all>\n | ReturnType<typeof sifaQueryKeys.position.byOwner>\n | ReturnType<typeof sifaQueryKeys.position.unlinked>\n | ReturnType<typeof sifaQueryKeys.inbox.all>\n | ReturnType<typeof sifaQueryKeys.inbox.counts>\n | ReturnType<typeof sifaQueryKeys.search.all>\n | ReturnType<typeof sifaQueryKeys.search.profiles>\n | ReturnType<typeof sifaQueryKeys.search.canonicalSkills>\n | ReturnType<typeof sifaQueryKeys.search.skills>\n | ReturnType<typeof sifaQueryKeys.search.filters>\n | ReturnType<typeof sifaQueryKeys.entity.all>\n | ReturnType<typeof sifaQueryKeys.entity.search>\n | ReturnType<typeof sifaQueryKeys.discovery.all>\n | ReturnType<typeof sifaQueryKeys.discovery.similar>\n | ReturnType<typeof sifaQueryKeys.discovery.suggestions>\n | ReturnType<typeof sifaQueryKeys.discovery.suggestionCount>\n | ReturnType<typeof sifaQueryKeys.discovery.featured>\n | ReturnType<typeof sifaQueryKeys.follow.all>\n | ReturnType<typeof sifaQueryKeys.follow.following>\n | ReturnType<typeof sifaQueryKeys.follow.followers>\n | ReturnType<typeof sifaQueryKeys.follow.followingOf>\n | ReturnType<typeof sifaQueryKeys.follow.feed>\n | ReturnType<typeof sifaQueryKeys.follow.mutuals>\n | ReturnType<typeof sifaQueryKeys.follow.blueskySuggestions>\n | ReturnType<typeof sifaQueryKeys.admin.all>\n | ReturnType<typeof sifaQueryKeys.admin.featureAllowlist>\n | ReturnType<typeof sifaQueryKeys.admin.reviewQueues>\n | ReturnType<typeof sifaQueryKeys.stats.all>\n | ReturnType<typeof sifaQueryKeys.stats.homepage>\n | ReturnType<typeof sifaQueryKeys.apps.all>\n | ReturnType<typeof sifaQueryKeys.apps.registry>\n | ReturnType<typeof sifaQueryKeys.apps.hidden>\n | ReturnType<typeof sifaQueryKeys.activity.all>\n | ReturnType<typeof sifaQueryKeys.activity.heatmap>\n | ReturnType<typeof sifaQueryKeys.activity.teaser>\n | ReturnType<typeof sifaQueryKeys.activity.feed>\n | ReturnType<typeof sifaQueryKeys.activity.hiddenItems>\n | ReturnType<typeof sifaQueryKeys.endorsement.all>\n | ReturnType<typeof sifaQueryKeys.endorsement.count>\n | ReturnType<typeof sifaQueryKeys.endorsement.pending>\n | ReturnType<typeof sifaQueryKeys.endorsement.reciprocity>\n | ReturnType<typeof sifaQueryKeys.endorsement.received>\n | ReturnType<typeof sifaQueryKeys.confirmation.all>\n | ReturnType<typeof sifaQueryKeys.confirmation.pending>\n | ReturnType<typeof sifaQueryKeys.confirmation.given>\n | ReturnType<typeof sifaQueryKeys.stream.all>\n | ReturnType<typeof sifaQueryKeys.stream.networkCount>\n | ReturnType<typeof sifaQueryKeys.reactions.all>\n | ReturnType<typeof sifaQueryKeys.reactions.status>\n | ReturnType<typeof sifaQueryKeys.reactions.accountCheck>\n | ReturnType<typeof sifaQueryKeys.roadmap.all>\n | ReturnType<typeof sifaQueryKeys.roadmap.votes>\n | ReturnType<typeof sifaQueryKeys.roadmap.myVotes>\n | ReturnType<typeof sifaQueryKeys.bskyPreferences.all>\n | ReturnType<typeof sifaQueryKeys.bskyPreferences.contentLabels>\n | ReturnType<typeof sifaQueryKeys.destructive.all>\n | ReturnType<typeof sifaQueryKeys.destructive.wipePreview>\n | ReturnType<typeof sifaQueryKeys.repoInventory.all>\n | ReturnType<typeof sifaQueryKeys.repoInventory.list>;\n","import { z } from 'zod';\n\n/**\n * Grapheme-aware refinement matching the AT Protocol lexicon `maxGraphemes`\n * constraint. JS strings are sequences of UTF-16 code units, but lexicon\n * `maxGraphemes` counts user-perceived characters (grapheme clusters), so\n * emoji sequences, regional indicators, ZWJ joins, and combining marks all\n * count as one unit each. We use `Intl.Segmenter` to enforce this correctly.\n */\nexport function maxGraphemes(max: number) {\n return (value: string): boolean => {\n const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n let count = 0;\n for (const _ of segmenter.segment(value)) {\n count++;\n if (count > max) return false;\n }\n return true;\n };\n}\n\n/** Decentralized identifier, AT Protocol `format: did`. */\nexport const didSchema = z.string().regex(/^did:[a-z]+:[a-zA-Z0-9._:%-]+$/, 'Invalid DID');\n\n/** RFC 3339 datetime with timezone offset, AT Protocol `format: datetime`. */\nexport const datetimeSchema = z.string().datetime({ offset: true });\n\n/**\n * Freeform calendar date for user-facing profile dates (start/end, issued,\n * completed, awarded, published, etc.). Accepts a bare year, year-month,\n * year-month-day, or a full datetime (so a legacy record's RFC-3339 date maps\n * through on backfill without loss). NOT strict `datetime` -- users typically\n * remember only month/year, and LinkedIn-importer writes carry partial dates,\n * so the lexicons document these as freeform `YYYY-MM` / `YYYY-MM-DD`. Record\n * metadata like `createdAt` stays on `datetimeSchema`.\n */\nexport const partialDateSchema = z\n .string()\n .regex(/^\\d{4}(-\\d{2}(-\\d{2}(T.+)?)?)?$/, 'Expected YYYY, YYYY-MM, YYYY-MM-DD, or a datetime');\n\n/** Generic AT-URI, AT Protocol `format: at-uri`. */\nexport const atUriSchema = z.string().regex(/^at:\\/\\/[^\\s]+$/, 'Invalid AT-URI');\n\n/** Content identifier, AT Protocol `format: cid`. Loose validation -- accepts CIDv0 and CIDv1. */\nexport const cidSchema = z\n .string()\n .regex(/^(Qm[1-9A-HJ-NP-Za-km-z]{44}|b[A-Za-z0-9+/=]+)$/, 'Invalid CID');\n\n/** BCP 47 language tag, AT Protocol `format: language`. */\nexport const languageTagSchema = z\n .string()\n .regex(/^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/, 'Invalid BCP 47 language tag');\n\n/** Generic URI, AT Protocol `format: uri`. */\nexport const uriSchema = z.string().url();\n\n/**\n * StrongRef shape from `com.atproto.repo.strongRef` -- pins a record by both\n * AT-URI (identity) and CID (version).\n */\nexport const strongRefSchema = z.object({\n uri: atUriSchema,\n cid: cidSchema,\n});\n\n/**\n * Reference to an `id.sifa.profile.skill` record by AT-URI. Mirrors\n * `id.sifa.defs#skillRef`, which carries no CID at all: skills are mutable\n * records in the same user's repo, so the reference resolves live and tracks\n * edits to the target.\n */\nexport const skillRefSchema = z.object({\n uri: atUriSchema,\n});\n\n/**\n * Reference to a record by AT-URI, with an optional CID. Mirrors\n * `id.sifa.defs#externalRecordRef`. Unlike a strongRef the CID is optional:\n * consumers resolve the AT-URI live so the reference tracks edits to the\n * target, and the CID is a best-effort integrity hint only.\n */\nexport const externalRecordRefSchema = z.object({\n uri: atUriSchema,\n cid: cidSchema.optional(),\n});\n\n/**\n * Self-labels shape from `com.atproto.label.defs#selfLabels`. Modelled\n * permissively because clients rarely construct this directly; the AppView\n * handles label validation.\n */\nexport const selfLabelsSchema = z.object({\n $type: z.literal('com.atproto.label.defs#selfLabels').optional(),\n values: z.array(z.object({ val: z.string() })),\n});\n","import { z } from 'zod';\n\nimport {\n datetimeSchema,\n didSchema,\n maxGraphemes,\n partialDateSchema,\n externalRecordRefSchema,\n selfLabelsSchema,\n strongRefSchema,\n uriSchema,\n} from './shared.js';\n\n/**\n * A person named as a member of a project. Mirrors `id.sifa.defs#projectMemberRef`.\n *\n * A claim by the record author, not a fact: the named person carries a display\n * name, avatar, and profile link only once they publish a matching\n * `id.sifa.confirmation`. `role` is display only, since a record living in\n * someone else's repository cannot grant write access to anything.\n */\nexport const projectMemberRefSchema = z.object({\n did: didSchema,\n role: z.string().optional(),\n title: z.string().refine(maxGraphemes(128)).max(1280).optional(),\n});\n\nexport type ProjectMemberRef = z.infer<typeof projectMemberRefSchema>;\n\n/** Zod schema for `id.sifa.profile.project` records. */\nexport const ProfileProjectRecordSchema = z.object({\n name: z.string().min(1).refine(maxGraphemes(256)).max(2560),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n url: uriSchema.optional(),\n members: z.array(projectMemberRefSchema).max(50).optional(),\n /**\n * The canonical `id.sifa.project.self` this personal entry corresponds to.\n * A composition link. For the same project recorded on someone else's\n * profile, see `sameAs`.\n */\n projectRef: strongRefSchema.optional(),\n /**\n * The same project as recorded on another person's profile. Each side stays\n * its own record; this only says the two describe one thing. Resolves by\n * AT-URI, since they will keep editing their copy.\n */\n sameAs: externalRecordRefSchema.optional(),\n position: strongRefSchema.optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n labels: selfLabelsSchema.optional(),\n createdAt: datetimeSchema,\n});\n\nexport type ProfileProjectRecord = z.infer<typeof ProfileProjectRecordSchema>;\n","import { z } from 'zod';\n\nimport {\n datetimeSchema,\n didSchema,\n externalRecordRefSchema,\n maxGraphemes,\n partialDateSchema,\n selfLabelsSchema,\n uriSchema,\n} from './shared.js';\nimport { projectMemberRefSchema } from './profile-project.js';\n\n/** Collection NSID for involvement records. Pass to the generic record helpers. */\nexport const PROFILE_INVOLVEMENT_NSID = 'id.sifa.profile.involvement';\n\n/**\n * A public artifact proving a piece of work. Mirrors `id.sifa.defs#artifactLink`.\n * `kind` is an open enum (bare-string knownValues), so any string is accepted.\n * `.passthrough()` keeps unknown fields a newer client or co-writer may emit.\n */\nexport const ArtifactLinkSchema = z\n .object({\n url: uriSchema,\n kind: z.string().optional(),\n label: z.string().refine(maxGraphemes(200)).max(2000).optional(),\n })\n .passthrough();\n\nexport type ArtifactLink = z.infer<typeof ArtifactLinkSchema>;\n\n/**\n * Zod schema for `id.sifa.profile.involvement` records.\n *\n * `.passthrough()` (not `.strict()`): external apps (Verak, weareonhire)\n * co-write `id.sifa.*`, so an older SDK must not reject a record carrying a\n * field it doesn't know yet. `kind` is an open enum matching the lexicon's\n * knownValues but accepting any string for the same forward-compat reason.\n */\nexport const ProfileInvolvementRecordSchema = z\n .object({\n kind: z.string(),\n upstream: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n upstreamDid: didSchema.optional(),\n upstreamUrl: uriSchema.optional(),\n role: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n links: z.array(ArtifactLinkSchema).max(50).optional(),\n // Portable org entity identifier (Wikidata/ROR/LEI URI) from the resolver\n // typeahead, constrained to http(s) so a script scheme is never a valid ref.\n entityRef: z\n .string()\n .url()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'entityRef must be an http(s) URL' })\n .max(2048)\n .optional(),\n // community.lexicon.location.address — validated at the app layer.\n location: z.unknown().optional(),\n // id.sifa.defs#skillRef references (at-uri to a skill record in the same repo).\n skills: z\n .array(z.object({ uri: z.string() }))\n .max(50)\n .optional(),\n labels: selfLabelsSchema.optional(),\n collaborators: z.array(projectMemberRefSchema).max(50).optional(),\n sameAs: externalRecordRefSchema.optional(),\n createdAt: datetimeSchema,\n })\n .passthrough();\n\nexport type ProfileInvolvementRecord = z.infer<typeof ProfileInvolvementRecordSchema>;\n","import { z } from 'zod';\n\nimport { ArtifactLinkSchema } from './profile-involvement.js';\nimport {\n datetimeSchema,\n didSchema,\n maxGraphemes,\n partialDateSchema,\n selfLabelsSchema,\n} from './shared.js';\n\n// Portable entity identifier (Wikidata/ROR/LEI URI) from the typeahead. Constrained\n// to http(s) so a script-bearing scheme is never a valid ref (#159). An investment\n// carries two of these -- the company and the vehicle -- so the check is shared.\nconst entityRefField = z\n .string()\n .url()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'entityRef must be an http(s) URL' })\n .max(2048)\n .optional();\n\n/**\n * A deliberately structured amount. Free text was rejected here: an unparseable\n * money string is worse than no amount at all, and cannot be repaired once people\n * have written them.\n */\nexport const InvestmentAmountSchema = z.object({\n /** Whole major currency units (euros, not cents). Cheque sizes are round numbers. */\n value: z.number().int().min(0),\n /** ISO 4217 three-letter code, uppercase. */\n currency: z.string().length(3),\n});\n\n/** Collection NSID for investment records. */\nexport const PROFILE_INVESTMENT_NSID = 'id.sifa.profile.investment';\n\n/** Zod schema for `id.sifa.profile.investment` records. */\nexport const ProfileInvestmentRecordSchema = z\n .object({\n /** For a limited-partner entry this names the fund, not a portfolio company. */\n company: z.string().min(1).refine(maxGraphemes(256)).max(2560),\n companyDid: didSchema.optional(),\n entityRef: entityRefField,\n role: z.string().optional(),\n stage: z.string().optional(),\n status: z.string().optional(),\n /** The vehicle the capital went through. Absent for a cheque in the person's own name. */\n via: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n viaDid: didSchema.optional(),\n viaEntityRef: entityRefField,\n /**\n * Optional and empty by default. Cheque size is a personal financial disclosure,\n * and clients must not prompt for it.\n */\n amount: InvestmentAmountSchema.optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n links: z.array(ArtifactLinkSchema).max(50).optional(),\n labels: selfLabelsSchema.optional(),\n createdAt: datetimeSchema,\n })\n .passthrough();\n\nexport type ProfileInvestmentRecord = z.infer<typeof ProfileInvestmentRecordSchema>;\n","import { PROFILE_INVESTMENT_NSID } from '../../schemas/profile-investment.js';\nimport { createRecord, updateRecord, deleteRecord } from './records.js';\nimport type { ApiFetchOptions, CreateResult, SifaApiConfig, WriteResult } from '../client.js';\n\nexport type { CreateResult, WriteResult } from '../client.js';\n\n/**\n * Typed wrappers over the generic record routes for\n * `id.sifa.profile.investment`. sifa-api serves every collection without a\n * bespoke handler through `POST|PUT|DELETE /api/profile/records/<collection>`,\n * so these exist for call-site readability, not for a different endpoint.\n *\n * Never throw -- inspect `result.success` and use `result.error` /\n * `result.pdsHost` for UI messaging.\n */\nexport function createInvestment(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return createRecord(config, PROFILE_INVESTMENT_NSID, data, options);\n}\n\n/** Update an existing investment by `rkey`. */\nexport function updateInvestment(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return updateRecord(config, PROFILE_INVESTMENT_NSID, rkey, data, options);\n}\n\n/** Delete an investment by `rkey`. */\nexport function deleteInvestment(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return deleteRecord(config, PROFILE_INVESTMENT_NSID, rkey, options);\n}\n"]}
1
+ {"version":3,"sources":["../../../src/query/client.ts","../../../src/query/fetchers/profile.ts","../../../src/query/fetchers/get-profile-view.ts","../../../src/query/fetchers/profile-mutations.ts","../../../src/query/fetchers/positions.ts","../../../src/query/fetchers/education.ts","../../../src/query/fetchers/skills.ts","../../../src/query/fetchers/records.ts","../../../src/query/fetchers/profile-locations.ts","../../../src/query/fetchers/external-accounts.ts","../../../src/query/fetchers/endorsements.ts","../../../src/query/fetchers/received-endorsements.ts","../../../src/query/fetchers/reciprocity.ts","../../../src/query/fetchers/endorsement-inbox.ts","../../../src/query/fetchers/confirmations.ts","../../../src/query/fetchers/inbox.ts","../../../src/query/fetchers/unlinked-positions.ts","../../../src/query/fetchers/profile-completeness.ts","../../../src/query/fetchers/keytrace-claims.ts","../../../src/query/fetchers/marque-domains.ts","../../../src/query/fetchers/publications.ts","../../../src/query/fetchers/profile-items-hide.ts","../../../src/query/fetchers/activity-items-hide.ts","../../../src/query/fetchers/stats.ts","../../../src/query/fetchers/apps.ts","../../../src/query/fetchers/accounts.ts","../../../src/query/fetchers/search.ts","../../../src/query/fetchers/speakers.ts","../../../src/query/fetchers/discovery.ts","../../../src/query/fetchers/follow.ts","../../../src/query/fetchers/follow-extras.ts","../../../src/query/fetchers/admin-feature-allowlists.ts","../../../src/query/fetchers/admin-review-queues.ts","../../../src/query/fetchers/activity.ts","../../../src/query/fetchers/github-prs.ts","../../../src/query/fetchers/endorsement.ts","../../../src/query/fetchers/stream.ts","../../../src/query/fetchers/reactions.ts","../../../src/query/fetchers/quoted-posts.ts","../../../src/query/fetchers/roadmap.ts","../../../src/query/fetchers/destructive.ts","../../../src/query/fetchers/repo-inventory.ts","../../../src/query/fetchers/network-map.ts","../../../src/schemas/entity.ts","../../../src/query/fetchers/entities.ts","../../../src/query/fetchers/org.ts","../../../src/logic/primary-position.ts","../../../src/logic/profile-summary.ts","../../../src/query/fetchers/profile-summary.ts","../../../src/query/keys.ts","../../../src/schemas/shared.ts","../../../src/schemas/profile-project.ts","../../../src/schemas/profile-involvement.ts","../../../src/schemas/profile-investment.ts","../../../src/query/fetchers/investments.ts"],"names":["buildListPath","z","EMPTY_SEARCH"],"mappings":";;;;;AA2CO,IAAM,QAAA,GAAN,cAAuB,KAAA,CAAM;AAAA,EACzB,MAAA;AAAA,EACA,IAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,IAAA,EAAgB;AAC3D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEA,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,sBAAA,GAAyB,CAAA;AAC/B,IAAM,4BAAA,GAA+B,CAAA;AAoB9B,SAAS,iBAAiB,KAAA,EAAuB;AACtD,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,mBAAmB,KAAK,CAAA;AAAA,EACpC,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,mBAAmB,OAAO,CAAA;AACnC;AASA,eAAsB,QAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EAChB;AACZ,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,OAAO,GAAG,IAAI,CAAA,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,GAAa,sBAAA,GAAyB,CAAA;AAEjE,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,OAAA,EAAA,EAAW;AACtD,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,IAAU,YAAY,OAAA,CAAQ,OAAA,CAAQ,aAAa,kBAAkB,CAAA;AAE5F,IAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC9B,MAAA,OAAA,CAAQ,cAAc,CAAA,KAAM,kBAAA;AAC5B,MAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,MAC1B,OAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,GAAI,QAAQ,IAAA,GAAO,EAAE,MAAM,OAAA,CAAQ,IAAA,KAAS;AAAC,KAC/C;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,EAAK,IAAI,CAAA;AAEnC,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,IAAO,OAAA,GAAU,UAAA,EAAY;AAC9C,MAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AACnD,MAAA,MAAM,aAAa,aAAA,GAAgB,MAAA,CAAO,QAAA,CAAS,aAAA,EAAe,EAAE,CAAA,GAAI,CAAA;AACxE,MAAA,MAAM,cAAc,IAAA,CAAK,GAAA;AAAA,QACvB,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,GAAI,UAAA,GAAa,CAAA;AAAA,QAC3C;AAAA,OACF;AACA,MAAA,MAAM,IAAI,QAAQ,CAAC,CAAA,KAAM,WAAW,CAAA,EAAG,WAAA,GAAc,GAAI,CAAC,CAAA;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,OAAA,GAAW,MAAM,IAAI,IAAA,EAAK;AAAA,MAC5B,CAAA,CAAA,MAAQ;AACN,QAAA,IAAI;AACF,UAAA,OAAA,GAAU,MAAM,IAAI,IAAA,EAAK;AAAA,QAC3B,CAAA,CAAA,MAAQ;AACN,UAAA,OAAA,GAAU,MAAA;AAAA,QACZ;AAAA,MACF;AACA,MAAA,MAAM,IAAI,QAAA,CAAS,CAAA,SAAA,EAAY,GAAA,CAAI,MAAM,OAAO,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC7E;AAMA,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,IAAO,GAAA,CAAI,WAAW,GAAA,EAAK;AAC5C,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,OAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB;AAEA,EAAA,MAAM,IAAI,QAAA,CAAS,CAAA,8BAAA,EAAiC,IAAI,IAAI,GAAG,CAAA;AACjE;AAOA,eAAsB,cAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACT;AACnB,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAAY,MAAA,EAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,EAChD,SAAS,CAAA,EAAG;AACV,IAAA,IAAI,CAAA,YAAa,QAAA,IAAY,CAAA,CAAE,MAAA,KAAW,KAAK,OAAO,IAAA;AACtD,IAAA,MAAM,CAAA;AAAA,EACR;AACF;AA+BA,SAAS,iBAAA,CAAkB,MAAe,MAAA,EAAqD;AAC7F,EAAA,MAAM,IAAA,GAAQ,QAAQ,EAAC;AACvB,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,IAAA,CAAK,OAAA,IAAW,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAA,CAAA;AAAA,IAChD,GAAI,KAAK,OAAA,GAAU,EAAE,SAAS,IAAA,CAAK,OAAA,KAAY;AAAC,GAClD;AACF;AAiBA,eAAsB,SACpB,MAAA,EACA,IAAA,EACA,MAAA,EACA,OAAA,GAA2C,EAAC,EACb;AAC/B,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAiB,MAAA,EAAQ,IAAA,EAAM;AAAA,MAChD,MAAA;AAAA,MACA,WAAA,EAAa,SAAA;AAAA,MACb,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,GAAI,IAAA,IAAS,EAAC,EAAc;AAAA,EACtD,SAAS,CAAA,EAAG;AACV,IAAA,IAAI,aAAa,QAAA,EAAU;AACzB,MAAA,OAAO,EAAE,SAAS,KAAA,EAAO,GAAG,kBAAkB,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,MAAM,CAAA,EAAE;AAAA,IAClE;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,eAAA,EAAgB;AAAA,EAClD;AACF;AAWO,SAAS,eACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACrB;AAChC,EAAA,OAAO,QAAA,CAAqC,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ;AAAA,IAChE,IAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;;;AClQO,SAAS,YAAA,CACd,MAAA,EACA,WAAA,EACA,OAAA,GAA2B,EAAC,EACH;AACzB,EAAA,MAAM,IAAA,GAAO,CAAA,aAAA,EAAgB,gBAAA,CAAiB,WAAW,CAAC,CAAA,CAAA;AAC1D,EAAA,OAAO,cAAA,CAAwB,QAAQ,IAAA,EAAM;AAAA,IAC3C,UAAA,EAAY,IAAA;AAAA,IACZ,GAAG;AAAA,GACJ,CAAA;AACH;AAOA,eAAsB,eAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACJ;AACxB,EAAA,MAAM,IAAA,GAAO,CAAA,cAAA,EAAiB,gBAAA,CAAiB,GAAG,CAAC,CAAA,aAAA,CAAA;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA4B,MAAA,EAAQ,IAAA,EAAM;AAAA,MAC3D,IAAA,EAAM,EAAE,UAAA,EAAY,IAAA,EAAK;AAAA,MACzB,SAAA,EAAW,GAAA;AAAA,MACX,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,OAAO,IAAA,CAAK,GAAA,KAAQ,QAAA,GAAW,KAAK,GAAA,GAAM,IAAA;AAAA,EACnD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC9BA,eAAsB,mBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACC;AAC7B,EAAA,MAAM,IAAA,GAAO,CAAA,mCAAA,EAAsC,gBAAA,CAAiB,KAAK,CAAC,CAAA,CAAA;AAC1E,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,SAAsB,MAAA,EAAQ,IAAA,EAAM,EAAE,UAAA,EAAY,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AAAA,EACnF,SAAS,CAAA,EAAG;AACV,IAAA,IACE,CAAA,YAAa,QAAA,IACb,CAAA,CAAE,MAAA,KAAW,OACb,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAClB,EAAE,IAAA,KAAS,IAAA,IACV,CAAA,CAAE,IAAA,CAA6B,UAAU,iBAAA,EAC1C;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,CAAA;AAAA,EACR;AACF;;;ACGO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,mBAAA,EAAqB,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AAChF;AAcO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,uBAAA,EAAyB,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACpF;AAaO,SAAS,UAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACD;AAC3B,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,0BAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAeA,eAAsB,YAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACC;AAC7B,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,mBAAA,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,EAAA,QAAA,CAAS,MAAA,CAAO,QAAQ,IAAI,CAAA;AAE5B,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,EAAK;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,WAAA,EAAa,QAAQ,WAAA,IAAe,SAAA;AAAA,MACpC,IAAA,EAAM,QAAA;AAAA,MACN,QAAQ,OAAA,CAAQ,MAAA,IAAU,YAAY,OAAA,CAAQ,OAAA,CAAQ,aAAa,GAAM,CAAA;AAAA,MACzE,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,OAAA,GAAW,MAAM,GAAA,CAAI,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AAIlD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,IAAW,CAAA,gBAAA,EAAmB,IAAI,MAAM,CAAA,CAAA,CAAA;AAC5D,MAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,GAAA,EAAK,GAAI,OAAA,GAAU,EAAE,OAAA,EAAQ,GAAI,EAAC,EAAG;AAAA,IACvE;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,GAAA,EAAK,KAAK,GAAA,EAAI;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,eAAA,EAAgB;AAAA,EAClD;AACF;AAGO,SAAS,oBAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,qBAAA,EAAuB,QAAA,EAAU,OAAO,CAAA;AAClE;AAeA,eAAsB,4BAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACa;AACzC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,gCAAA,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,EAAA,QAAA,CAAS,MAAA,CAAO,QAAQ,IAAI,CAAA;AAE5B,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,EAAK;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,WAAA,EAAa,QAAQ,WAAA,IAAe,SAAA;AAAA,MACpC,IAAA,EAAM,QAAA;AAAA,MACN,QAAQ,OAAA,CAAQ,MAAA,IAAU,YAAY,OAAA,CAAQ,OAAA,CAAQ,aAAa,GAAM,CAAA;AAAA,MACzE,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,OAAA,GAAW,MAAM,GAAA,CAAI,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AAIlD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,IAAW,CAAA,gBAAA,EAAmB,IAAI,MAAM,CAAA,CAAA,CAAA;AAC5D,MAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,GAAA,EAAK,GAAI,OAAA,GAAU,EAAE,OAAA,EAAQ,GAAI,EAAC,EAAG;AAAA,IACvE;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,GAAA,EAAK,KAAK,GAAA,EAAI;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,eAAA,EAAgB;AAAA,EAClD;AACF;AAGO,SAAS,4BAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,kCAAA,EAAoC,QAAA,EAAU,OAAO,CAAA;AAC/E;;;AClLO,SAAS,cAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,uBAAA,EAAyB,IAAA,EAAM,OAAO,CAAA;AACtE;AAGO,SAAS,eACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,sBAAA,EAAyB,mBAAmB,IAAI,CAAC,IAAI,KAAA,EAAO;AAAA,IAClF,IAAA,EAAM,IAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,cAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA,EAAI,UAAU,OAAO,CAAA;AAChG;AAGO,SAAS,kBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,IAAI,CAAC,CAAA,QAAA,CAAA;AAAA,IACjD,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,oBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,IAAI,CAAC,CAAA,QAAA,CAAA;AAAA,IACjD,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,SAAS,oBAAA,CACP,UACA,MAAA,EACyB;AACzB,EAAA,OAAO;AAAA,IACL,SAAS,QAAA,CAAS,OAAA;AAAA,IAClB,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,aAAa,QAAA,CAAS,WAAA;AAAA,IACtB,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB,SAAS,QAAA,CAAS,OAAA;AAAA,IAClB,QAAA,EAAU,SAAS,QAAA,IAAY,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAK/B,gBAAgB,QAAA,CAAS,cAAA;AAAA,IACzB,eAAe,QAAA,CAAS,aAAA;AAAA,IACxB,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB;AAAA,GACF;AACF;AASO,SAAS,oBACd,MAAA,EACA,QAAA,EACA,QAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,MAAA,IAAU,EAAC;AAC1C,EAAA,IAAI,aAAA,CAAc,KAAK,CAAC,CAAA,KAAM,EAAE,GAAA,KAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACrD,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,EAC1C;AACA,EAAA,OAAO,cAAA;AAAA,IACL,MAAA;AAAA,IACA,QAAA,CAAS,IAAA;AAAA,IACT,qBAAqB,QAAA,EAAU,CAAC,GAAG,aAAA,EAAe,QAAQ,CAAC,CAAA;AAAA,IAC3D;AAAA,GACF;AACF;AAGO,SAAS,wBACd,MAAA,EACA,QAAA,EACA,QAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,MAAM,SAAA,GAAA,CAAa,QAAA,CAAS,MAAA,IAAU,EAAC,EAAG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,QAAA,CAAS,GAAG,CAAA;AAC9E,EAAA,OAAO,cAAA,CAAe,QAAQ,QAAA,CAAS,IAAA,EAAM,qBAAqB,QAAA,EAAU,SAAS,GAAG,OAAO,CAAA;AACjG;;;ACjIO,SAAS,eAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,wBAAA,EAA0B,IAAA,EAAM,OAAO,CAAA;AACvE;AAGO,SAAS,gBACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,uBAAA,EAA0B,mBAAmB,IAAI,CAAC,IAAI,KAAA,EAAO;AAAA,IACnF,IAAA,EAAM,IAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,eAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,uBAAA,EAA0B,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA,EAAI,UAAU,OAAO,CAAA;AACjG;;;AC5BO,SAAS,WAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,oBAAA,EAAsB,IAAA,EAAM,OAAO,CAAA;AACnE;AAGO,SAAS,YACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,mBAAA,EAAsB,mBAAmB,IAAI,CAAC,IAAI,KAAA,EAAO;AAAA,IAC/E,IAAA,EAAM,IAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AAgCO,SAAS,WAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,mBAAA,EAAsB,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA,EAAI,UAAU,OAAO,CAAA;AAC7F;;;ACnDO,SAAS,aACd,MAAA,EACA,UAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,qBAAA,EAAwB,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA;AAAA,IACtD,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,aACd,MAAA,EACA,UAAA,EACA,MACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,MAAM,IAAA,GAAO,wBAAwB,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA,EAAI,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA;AAC/F,EAAA,OAAO,QAAA,CAAS,QAAQ,IAAA,EAAM,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACjE;AAGO,SAAS,aACd,MAAA,EACA,UAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,MAAM,IAAA,GAAO,wBAAwB,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA,EAAI,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA;AAC/F,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,IAAA,EAAM,QAAA,EAAU,OAAO,CAAA;AACjD;;;AChBO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,uBAAA,EAAyB,IAAA,EAAM,OAAO,CAAA;AACtE;AAGO,SAAS,sBACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,sBAAA,EAAyB,mBAAmB,IAAI,CAAC,IAAI,KAAA,EAAO;AAAA,IAClF,IAAA,EAAM,IAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA,EAAI,UAAU,OAAO,CAAA;AAChG;;;ACnCA,eAAsB,qBAAA,CACpB,MAAA,EACA,WAAA,EACA,OAAA,GAA2B,EAAC,EACA;AAC5B,EAAA,MAAM,IAAA,GAAO,CAAA,aAAA,EAAgB,gBAAA,CAAiB,WAAW,CAAC,CAAA,kBAAA,CAAA;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA2C,MAAA,EAAQ,IAAA,EAAM;AAAA,MAC1E,WAAA,EAAa,SAAA;AAAA,MACb,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,YAAY,EAAC;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAOO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACU;AACtC,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,gCAAA;AAAA,IACA,MAAA;AAAA,IACA,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA;AAAQ,GAC3B;AACF;AAGO,SAAS,sBACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,+BAAA,EAAkC,mBAAmB,IAAI,CAAC,IAAI,KAAA,EAAO;AAAA,IAC3F,IAAA,EAAM,IAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,+BAAA,EAAkC,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA;AAAA,IAC1D,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,yBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,+BAAA,EAAkC,kBAAA,CAAmB,IAAI,CAAC,CAAA,QAAA,CAAA;AAAA,IAC1D,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,2BAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,+BAAA,EAAkC,kBAAA,CAAmB,IAAI,CAAC,CAAA,QAAA,CAAA;AAAA,IAC1D,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAOO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACU;AACtC,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,+BAAA,EAAkC,kBAAA,CAAmB,IAAI,CAAC,CAAA,OAAA,CAAA;AAAA,IAC1D,MAAA;AAAA,IACA,EAAE,IAAA,EAAM,EAAC,EAAG,GAAG,OAAA;AAAQ,GACzB;AACF;;;ACjFO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,kBAAA,EAAoB,IAAA,EAAM,OAAO,CAAA;AACjE;AAOO,SAAS,kBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACsB;AAClD,EAAA,OAAO,cAAA;AAAA,IACL,MAAA;AAAA,IACA,0BAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;;;AClDA,eAAsB,yBAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAAgD,EAAC,EACd;AACnC,EAAA,MAAM,EAAE,KAAA,EAAO,GAAG,YAAA,EAAa,GAAI,OAAA;AACnC,EAAA,MAAM,EAAA,GAAK,KAAA,GAAQ,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,GAAK,EAAA;AACvC,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA;AAAA,MACjB,MAAA;AAAA,MACA,CAAA,iBAAA,EAAoB,gBAAA,CAAiB,GAAG,CAAC,GAAG,EAAE,CAAA,CAAA;AAAA,MAC9C,EAAE,KAAA,EAAO,UAAA,EAAY,SAAA,EAAW,GAAA,EAAM,GAAG,YAAA;AAAa,KACxD;AACA,IAAA,OAAO,EAAE,cAAc,IAAA,EAAM,YAAA,IAAgB,EAAC,EAAG,MAAA,EAAQ,MAAM,MAAA,EAAO;AAAA,EACxE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,YAAA,EAAc,EAAC,EAAE;AAAA,EAC5B;AACF;;;ACpBA,eAAsB,yBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACU;AACtC,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA;AAAA,MACjB,MAAA;AAAA,MACA,yCAAA;AAAA,MACA;AAAA,QACE,KAAA,EAAO,UAAA;AAAA,QACP,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW,GAAA;AAAA,QACX,GAAG;AAAA;AACL,KACF;AACA,IAAA,OAAO,MAAM,SAAA,IAAa,IAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC2BA,eAAsB,wBAAA,CACpB,MAAA,EACA,OAAA,GAA2C,EAAC,EACV;AAClC,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkC,MAAA,EAAQ,2BAAA,EAA6B;AAAA,MACxF,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,EAAE,cAAc,IAAA,EAAM,YAAA,IAAgB,EAAC,EAAG,MAAA,EAAQ,MAAM,MAAA,EAAO;AAAA,EACxE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,YAAA,EAAc,EAAC,EAAE;AAAA,EAC5B;AACF;AASO,SAAS,kBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,0BAAA,EAA4B,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACxF;;;ACVA,eAAsB,yBAAA,CACpB,MAAA,EACA,OAAA,GAAqC,EAAC,EACH;AACnC,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAmC,MAAA,EAAQ,4BAAA,EAA8B;AAAA,MAC1F,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,EAAE,eAAe,IAAA,EAAM,aAAA,IAAiB,EAAC,EAAG,MAAA,EAAQ,MAAM,MAAA,EAAO;AAAA,EAC1E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,aAAA,EAAe,EAAC,EAAE;AAAA,EAC7B;AACF;AAYA,eAAsB,uBAAA,CACpB,MAAA,EACA,OAAA,GAAqC,EAAC,EACW;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA;AAAA,MACjB,MAAA;AAAA,MACA,yBAAA;AAAA,MACA,EAAE,OAAO,UAAA,EAAY,WAAA,EAAa,WAAW,SAAA,EAAW,GAAA,EAAM,GAAG,IAAA,EAAM,OAAA;AAAQ,KACjF;AACA,IAAA,OAAO,EAAE,aAAA,EAAe,IAAA,EAAM,aAAA,IAAiB,EAAC,EAAE;AAAA,EACpD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,aAAA,EAAe,EAAC,EAAE;AAAA,EAC7B;AACF;AAWO,SAAS,kBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,cAAA,CAAe,MAAA,EAAQ,mBAAA,EAAqB,IAAA,EAAM,OAAO,CAAA;AAClE;AAUO,SAAS,mBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,2BAAA,EAA6B,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACzF;AAUO,SAAS,kBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,0BAAA,EAA4B,MAAA,EAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACxF;;;ACrJA,SAAS,QAAQ,KAAA,EAAwB;AACvC,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,KAAA,IAAS,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,GAAI,CAAA;AACjG;AAEA,eAAsB,gBAAA,CACpB,MAAA,EACA,OAAA,GAAmC,EAAC,EACd;AAGtB,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AAEnC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAsB,MAAA,EAAQ,mBAAA,EAAqB;AAAA,MACpE,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,OAAA,CAAQ,IAAA,EAAM,KAAK,CAAA;AAAA,MAC1B,mBAAA,EAAqB,OAAA,CAAQ,IAAA,EAAM,mBAAmB;AAAA,KACxD;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,CAAA,EAAG,mBAAA,EAAqB,CAAA,EAAE;AAAA,EAC5C;AACF;;;ACrCA,eAAsB,sBAAA,CACpB,MAAA,EACA,OAAA,GAAyC,EAAC,EACR;AAClC,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AAEnC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkC,MAAA,EAAQ,yBAAA,EAA2B;AAAA,MACtF,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,EAAE,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,SAAS,CAAA,GAAI,IAAA,CAAK,SAAA,GAAY,EAAC,EAAE;AAAA,EAC3E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,SAAA,EAAW,EAAC,EAAE;AAAA,EACzB;AACF;;;ACnDO,IAAM,4BAAA,GAA+B;AAAA,EAC1C,UAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF;AAmCA,eAAsB,wBAAA,CACpB,MAAA,EACA,OAAA,GAA2C,EAAC,EACd;AAC9B,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,OAAA;AAClC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AAEnC,EAAA,MAAM,KAAA,GAA6B;AAAA,IACjC,QAAA,EAAU,IAAA;AAAA,IACV,OAAO,4BAAA,CAA6B,MAAA;AAAA,IACpC,OAAO,4BAAA,CAA6B,MAAA;AAAA,IACpC,SAAS;AAAC,GACZ;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA8B,MAAA,EAAQ,2BAAA,EAA6B;AAAA,MACpF,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAClB,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA,CAAK,UAAU,EAAC;AAC9D,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,IAAA,CAAK,QAAA,IAAY,OAAA,CAAQ,MAAA,KAAW,CAAA;AAAA,MAC9C,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,4BAAA,CAA6B,SAAS,OAAA,CAAQ,MAAA;AAAA,MACnE,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,4BAAA,CAA6B,MAAA;AAAA,MAClD;AAAA,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;;;AC3EO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,IAAI,CAAC,CAAA,KAAA,CAAA;AAAA,IACxD,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,IAAI,CAAC,CAAA,KAAA,CAAA;AAAA,IACxD,QAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACzBO,SAAS,kBAAA,CACd,MAAA,EACA,MAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,4BAAA,EAA+B,kBAAA,CAAmB,MAAM,CAAC,CAAA,OAAA,CAAA;AAAA,IACzD,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,oBAAA,CACd,MAAA,EACA,MAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,4BAAA,EAA+B,kBAAA,CAAmB,MAAM,CAAC,CAAA,OAAA,CAAA;AAAA,IACzD,QAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACnBO,SAAS,oBAAA,CACd,MAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,gCAAA,EAAmC,OAAO,CAAA,KAAA,CAAA,EAAS,QAAQ,OAAO,CAAA;AAC5F;AAGO,SAAS,sBAAA,CACd,MAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,gCAAA,EAAmC,OAAO,CAAA,KAAA,CAAA,EAAS,UAAU,OAAO,CAAA;AAC9F;AAGO,SAAS,uBAAA,CACd,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,mCAAA,EAAsC,kBAAA,CAAmB,GAAG,CAAC,CAAA,KAAA,CAAA;AAAA,IAC7D,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,yBAAA,CACd,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,mCAAA,EAAsC,kBAAA,CAAmB,GAAG,CAAC,CAAA,KAAA,CAAA;AAAA,IAC7D,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,4BAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,8CAAA,EAAgD,MAAA,EAAQ;AAAA,IAC9E,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,8BAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,8CAAA,EAAgD,QAAA,EAAU;AAAA,IAChF,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,0BAAA,EAA6B,IAAI,CAAA,KAAA,CAAA,EAAS,QAAQ,OAAO,CAAA;AACnF;AAGO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,0BAAA,EAA6B,IAAI,CAAA,KAAA,CAAA,EAAS,UAAU,OAAO,CAAA;AACrF;AASA,eAAsB,wBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACa;AACzC,EAAA,MAAM,SAAS,MAAM,QAAA;AAAA,IACnB,MAAA;AAAA,IACA,yCAAA;AAAA,IACA,MAAA;AAAA,IACA,EAAE,IAAA,EAAM,EAAC,EAAG,GAAG,OAAA;AAAQ,GACzB;AACA,EAAA,IAAI,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,KAAA,EAAO;AAClC,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EAC/C;AACA,EAAA,OAAO,MAAA;AACT;;;ACtHO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,UAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF;AAIO,IAAM,mBAAA,GAAsB,CAAC,KAAA,EAAO,UAAA,EAAY,OAAO;AAoBvD,SAAS,eAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,yBAAA,EAA2B,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AACxF;AAGO,SAAS,iBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,yBAAA,EAA2B,QAAA,EAAU,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AAC1F;AAGO,SAAS,oBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,8BAAA,EAAgC,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AAC7F;AAGO,SAAS,sBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,8BAAA,EAAgC,QAAA,EAAU,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AAC/F;;;ACtBO,SAAS,gBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,0BAAA,EAA4B,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AACzF;AAGO,SAAS,kBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,0BAAA,EAA4B,QAAA,EAAU,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,CAAA;AAC3F;AAMA,eAAsB,wBAAA,CACpB,MAAA,EACA,OAAA,GAA2C,EAAC,EACb;AAC/B,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA;AAAA,MACjB,MAAA;AAAA,MACA,4BAAA;AAAA,MACA,EAAE,WAAA,EAAa,SAAA,EAAW,GAAG,SAAS,OAAA;AAAQ,KAChD;AACA,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;ACrEA,eAAsB,UAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAC/B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAAwB,MAAA,EAAQ,YAAA,EAAc;AAAA,MACzD,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAI;AAAA,MACxB,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;ACGA,eAAsB,iBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACC;AAC7B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAA6B,MAAA,EAAQ,oBAAA,EAAsB;AAAA,MACtE,IAAA,EAAM,EAAE,UAAA,EAAY,KAAA,EAAM;AAAA,MAC1B,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAOA,eAAsB,eAAA,CACpB,MAAA,EACA,OAAA,GAAkC,EAAC,EACb;AACtB,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAgC,MAAA,EAAQ,0BAAA,EAA4B;AAAA,MACrF,WAAA,EAAa,SAAA;AAAA,MACb,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;ACpCA,eAAsB,aAAA,CACpB,MAAA,EACA,OAAA,GAAgC,EAAC,EACN;AAC3B,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAyC,MAAA,EAAQ,oBAAA,EAAsB;AAAA,MACxF,WAAA,EAAa,SAAA;AAAA,MACb,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAQA,eAAsB,aAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACb;AACf,EAAA,MAAM,QAAA,CAAS,QAAQ,eAAA,EAAiB;AAAA,IACtC,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EAAM,EAAE,GAAA,EAAI;AAAA,IACZ,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;;;ACyBA,IAAM,YAAA,GAA+B,EAAE,QAAA,EAAU,EAAC,EAAG,OAAO,CAAA,EAAG,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,CAAA,EAAE;AACpF,IAAM,aAAA,GAA+B,EAAE,SAAA,EAAW,EAAC,EAAG,UAAA,EAAY,EAAC,EAAG,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AAC3F,IAAM,uBAA8C,EAAE,OAAA,EAAS,EAAC,EAAG,SAAS,KAAA,EAAM;AAOlF,eAAsB,mBAAA,CACpB,MAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACH;AACzB,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,QAAQ,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,QAAQ,CAAC,CAAA;AACxC,EAAA,IAAI,QAAQ,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,QAAQ,KAAK,CAAA;AACpD,EAAA,IAAI,QAAQ,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,QAAQ,OAAO,CAAA;AAC1D,EAAA,IAAI,QAAQ,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC7D,EAAA,IAAI,QAAQ,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACvD,EAAA,IAAI,QAAQ,SAAA,EAAW,MAAA,CAAO,GAAA,CAAI,WAAA,EAAa,QAAQ,SAAS,CAAA;AAChE,EAAA,IAAI,QAAQ,GAAA,EAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,QAAQ,GAAG,CAAA;AAC9C,EAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,EAAG;AAC/C,IAAA,KAAA,MAAW,KAAA,IAAS,QAAQ,MAAA,EAAQ;AAClC,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,MAAA,CAAO,QAAA,EAAU,KAAK,CAAA;AAAA,IAC1C;AAAA,EACF;AACA,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAE1E,EAAA,IAAI,MAAA,CAAO,IAAA,KAAS,CAAA,EAAG,OAAO,YAAA;AAE9B,EAAA,OAAO,SAAyB,MAAA,EAAQ,CAAA,qBAAA,EAAwB,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,EAAI;AAAA,IACnF,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACH;AAaA,eAAsB,oBAAA,CACpB,MAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACI;AAChC,EAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,CAAA,EAAG,IAAA,EAAK;AAC1B,EAAA,IAAI,CAAC,GAAG,OAAO,oBAAA;AAEf,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB,EAAE,GAAG,CAAA;AACxC,EAAA,IAAI,QAAQ,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,QAAQ,OAAO,CAAA;AAC1D,EAAA,IAAI,QAAQ,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC7D,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAE1E,EAAA,OAAO,SAAgC,MAAA,EAAQ,CAAA,sBAAA,EAAyB,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,EAAI;AAAA,IAC3F,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACH;AAMA,eAAsB,qBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACE;AAC9B,EAAA,IAAI,CAAC,KAAA,CAAM,IAAA,EAAK,SAAU,EAAC;AAC3B,EAAA,MAAM,IAAA,GAAO,CAAA,qBAAA,EAAwB,kBAAA,CAAmB,KAAK,CAAC,CAAA,QAAA,CAAA;AAC9D,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA2C,MAAA,EAAQ,IAAA,EAAM;AAAA,IAC1E,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,OAAO,IAAA,CAAK,UAAU,EAAC;AACzB;AAGA,eAAsB,kBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACJ;AACxB,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAAwB,MAAA,EAAQ,qBAAA,EAAuB;AAAA,MAClE,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAI;AAAA,MACxB,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,aAAA;AAAA,EACT;AACF;AAUA,eAAsB,aACpB,MAAA,EACA,KAAA,EACA,QAAQ,EAAA,EACR,OAAA,GAA2B,EAAC,EACA;AAC5B,EAAA,IAAI,CAAC,KAAA,CAAM,IAAA,EAAK,SAAU,EAAC;AAC3B,EAAA,MAAM,OAAO,CAAA,qBAAA,EAAwB,kBAAA,CAAmB,KAAK,CAAC,UAAU,KAAK,CAAA,CAAA;AAC7E,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAyC,MAAA,EAAQ,IAAA,EAAM;AAAA,MACxE,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,UAAU,EAAC;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;AC9HA,IAAM,cAAA,GAAmC,EAAE,QAAA,EAAU,EAAC,EAAE;AACxD,IAAM,WAAA,GAA6B,EAAE,KAAA,EAAO,EAAC,EAAE;AAE/C,SAAS,YAAY,OAAA,EAAmD;AACtE,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,IAAA,EAAK;AAClC,EAAA,IAAI,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,KAAK,CAAA;AACpC,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC1E,EAAA,OAAO,MAAA;AACT;AAWA,eAAsB,cACpB,MAAA,EACA,OAAA,GAAmC,EAAC,EACpC,OAAA,GAA2B,EAAC,EACD;AAC3B,EAAA,MAAM,MAAA,GAAS,YAAY,OAAO,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,EAAS;AAC9B,EAAA,MAAM,IAAA,GAAO,KAAA,GAAQ,CAAA,cAAA,EAAiB,KAAK,CAAA,CAAA,GAAK,eAAA;AAChD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAA2B,MAAA,EAAQ,IAAA,EAAM;AAAA,MACpD,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,cAAA;AAAA,EACT;AACF;AAOA,eAAsB,WACpB,MAAA,EACA,OAAA,GAAmC,EAAC,EACpC,OAAA,GAA2B,EAAC,EACJ;AACxB,EAAA,MAAM,MAAA,GAAS,YAAY,OAAO,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,EAAS;AAC9B,EAAA,MAAM,IAAA,GAAO,KAAA,GAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAA,GAAK,YAAA;AAC7C,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAAwB,MAAA,EAAQ,IAAA,EAAM;AAAA,MACjD,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,WAAA;AAAA,EACT;AACF;;;ACzFA,eAAsB,oBAAA,CACpB,MAAA,EACA,GAAA,EACA,IAAA,GAA6C,EAAC,EACnB;AAC3B,EAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,IAAS,CAAA;AAC5B,EAAA,MAAM,OAAO,CAAA,sBAAA,EAAyB,gBAAA,CAAiB,GAAG,CAAC,UAAU,KAAK,CAAA,CAAA;AAC1E,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA0C,MAAA,EAAQ,IAAA,EAAM;AAAA,MACzE,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAI;AAAA,MACxB,SAAA,EAAW,GAAA;AAAA,MACX,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,YAAY,EAAC;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAgBA,eAAsB,gBAAA,CACpB,MAAA,EACA,IAAA,GAAgC,EAAC,EACH;AAC9B,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,gBAAA,EAAkB,MAAA,CAAO,GAAA,CAAI,qBAAqB,MAAM,CAAA;AACjE,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AAEtD,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAC3B,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAE7C,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,SAA8B,MAAA,EAAQ,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,EAAI;AAAA,MAC1F,WAAA,EAAa,SAAA;AAAA,MACb,KAAA,EAAO,UAAA;AAAA,MACP,SAAA,EAAW,GAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,MAAA,EAAQ,EAAC,EAAG,SAAA,EAAW,EAAC,EAAE;AAAA,EACrC;AACF;AAGA,eAAsB,oBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACX;AACjB,EAAA,MAAM,SAAS,KAAA,GAAQ,CAAA,OAAA,EAAU,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA,GAAK,EAAA;AAC/D,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA,CAA6B,MAAA,EAAQ,CAAA,sBAAA,EAAyB,MAAM,CAAA,CAAA,EAAI;AAAA,MACzF,WAAA,EAAa,SAAA;AAAA,MACb,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,OAAO,KAAK,KAAA,IAAS,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,CAAA;AAAA,EACT;AACF;AAGA,eAAsB,oBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACK;AACjC,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAA0B,MAAA,EAAQ,uBAAA,EAAyB;AAAA,MACtE,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAI;AAAA,MACxB,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC9HA,eAAsB,cAAA,CACpB,MAAA,EACA,IAAA,GAA+E,EAAC,EACpD;AAC5B,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACtD,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAE3B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,SAA4B,MAAA,EAAQ,CAAA,cAAA,EAAiB,KAAK,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,EAAI;AAAA,MACtF,WAAA,EAAa,SAAA;AAAA,MACb,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,EAAC,EAAE;AAAA,EACvB;AACF;AAmBO,SAAS,UAAA,CACd,MAAA,EACA,MAAA,EACA,IAAA,GAAqE,EAAC,EAC3C;AAC3B,EAAA,MAAM,EAAE,IAAA,EAAM,GAAG,IAAA,EAAK,GAAI,IAAA;AAC1B,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,YAAA,EAAe,gBAAA,CAAiB,MAAM,CAAC,CAAA,CAAA;AAAA,IACvC,MAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,IAAA,KAAS,MAAA,GAAY,EAAE,MAAK,GAAI,MAAA;AAAA,MACtC,GAAG;AAAA;AACL,GACF;AACF;AAGO,SAAS,YAAA,CACd,MAAA,EACA,MAAA,EACA,IAAA,GAAiD,EAAC,EAC5B;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,YAAA,EAAe,gBAAA,CAAiB,MAAM,CAAC,CAAA,CAAA,EAAI,UAAU,IAAI,CAAA;AACnF;AAmBA,SAAS,aAAA,CAAc,QAAgB,IAAA,EAAsC;AAC3E,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACtD,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAC3B,EAAA,OAAO,GAAG,MAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AACvC;AAMA,eAAsB,YAAA,CACpB,MAAA,EACA,MAAA,EACA,IAAA,GAA+B,EAAC,EACP;AACzB,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,QAAA;AAAA,MAChB,MAAA;AAAA,MACA,cAAc,CAAA,aAAA,EAAgB,gBAAA,CAAiB,MAAM,CAAC,cAAc,IAAI,CAAA;AAAA,MACxE,EAAE,WAAA,EAAa,SAAA,EAAW,OAAO,UAAA,EAAY,GAAG,MAAM,OAAA;AAAQ,KAChE;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,GAAA,CAAI,SAAS,MAAA,EAAQ,GAAA,CAAI,UAAU,IAAA,EAAK;AAAA,EAC5D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,EAAC,EAAG,QAAQ,IAAA,EAAK;AAAA,EACrC;AACF;AAGA,eAAsB,YAAA,CACpB,MAAA,EACA,MAAA,EACA,IAAA,GAA+B,EAAC,EACP;AACzB,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,QAAA;AAAA,MAChB,MAAA;AAAA,MACA,cAAc,CAAA,aAAA,EAAgB,gBAAA,CAAiB,MAAM,CAAC,cAAc,IAAI,CAAA;AAAA,MACxE,EAAE,WAAA,EAAa,SAAA,EAAW,OAAO,UAAA,EAAY,GAAG,MAAM,OAAA;AAAQ,KAChE;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,GAAA,CAAI,SAAS,MAAA,EAAQ,GAAA,CAAI,UAAU,IAAA,EAAK;AAAA,EAC5D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,OAAA,EAAS,EAAC,EAAG,QAAQ,IAAA,EAAK;AAAA,EACrC;AACF;AA+BA,eAAsB,gBAAA,CACpB,MAAA,EACA,IAAA,GAAkC,EAAC,EACV;AACzB,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACtD,EAAA,IAAI,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,IAAI,YAAA,EAAc,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,EACpD;AACA,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAE3B,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAE7C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,QAAA;AAAA,MAChB,MAAA;AAAA,MACA,CAAA,mBAAA,EAAsB,EAAA,GAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AAAA,MACxC,EAAE,WAAA,EAAa,SAAA,EAAW,OAAO,UAAA,EAAY,GAAG,MAAM,OAAA;AAAQ,KAChE;AACA,IAAA,OAAO,EAAE,OAAO,GAAA,CAAI,KAAA,IAAS,EAAC,EAAG,MAAA,EAAQ,GAAA,CAAI,MAAA,IAAU,IAAA,EAAK;AAAA,EAC9D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,QAAQ,IAAA,EAAK;AAAA,EACnC;AACF;;;AC5LA,SAASA,cAAAA,CAAc,QAAgB,IAAA,EAA6C;AAClF,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,KAAK,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,KAAK,MAAM,CAAA;AACjD,EAAA,IAAI,IAAA,CAAK,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACtD,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAC3B,EAAA,OAAO,GAAG,MAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AACvC;AAEA,eAAe,sBAAA,CACb,MAAA,EACA,IAAA,EACA,IAAA,EACoC;AACpC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,QAAA;AAAA,MAChB,MAAA;AAAA,MACA,IAAA;AAAA,MACA,EAAE,WAAA,EAAa,SAAA,EAAW,OAAO,UAAA,EAAY,GAAG,MAAM,OAAA;AAAQ,KAChE;AACA,IAAA,OAAO,EAAE,OAAO,GAAA,CAAI,KAAA,IAAS,EAAC,EAAG,MAAA,EAAQ,GAAA,CAAI,MAAA,IAAU,IAAA,EAAK;AAAA,EAC9D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,QAAQ,IAAA,EAAK;AAAA,EACnC;AACF;AAQA,eAAsB,UAAA,CACpB,MAAA,EACA,WAAA,EACA,IAAA,GAAsC,EAAC,EACH;AACpC,EAAA,OAAO,sBAAA;AAAA,IACL,MAAA;AAAA,IACAA,eAAc,CAAA,aAAA,EAAgB,gBAAA,CAAiB,WAAW,CAAC,YAAY,IAAI,CAAA;AAAA,IAC3E;AAAA,GACF;AACF;AAQA,eAAsB,qBAAA,CACpB,MAAA,EACA,IAAA,GAAsC,EAAC,EACH;AACpC,EAAA,OAAO,uBAAuB,MAAA,EAAQA,cAAAA,CAAc,6BAAA,EAA+B,IAAI,GAAG,IAAI,CAAA;AAChG;;;ACvDA,eAAsB,oBAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,GAAoC,EAAC,EACF;AACnC,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,QAAA;AAAA,MAChB,MAAA;AAAA,MACA,CAAA,8BAAA,EAAiC,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA;AAAA,MACzD,EAAE,WAAA,EAAa,SAAA,EAAW,OAAO,UAAA,EAAY,GAAG,MAAM,OAAA;AAAQ,KAChE;AACA,IAAA,OAAO,EAAE,KAAA,EAAO,GAAA,CAAI,KAAA,IAAS,EAAC,EAAE;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAE;AAAA,EACrB;AACF;AAOO,SAAS,oBACd,MAAA,EACA,IAAA,EACA,GAAA,EACA,IAAA,GAAqE,EAAC,EAChD;AACtB,EAAA,MAAM,EAAE,IAAA,EAAM,GAAG,IAAA,EAAK,GAAI,IAAA;AAC1B,EAAA,OAAO,SAAS,MAAA,EAAQ,CAAA,8BAAA,EAAiC,mBAAmB,IAAI,CAAC,IAAI,MAAA,EAAQ;AAAA,IAC3F,IAAA,EAAM,SAAS,MAAA,GAAY,EAAE,KAAK,IAAA,EAAK,GAAI,EAAE,GAAA,EAAI;AAAA,IACjD,GAAG;AAAA,GACJ,CAAA;AACH;AAOO,SAAS,uBACd,MAAA,EACA,IAAA,EACA,GAAA,EACA,IAAA,GAAiD,EAAC,EAC5B;AACtB,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,iCAAiC,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA,EAAI,gBAAA,CAAiB,GAAG,CAAC,CAAA,CAAA;AAAA,IAClF,QAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACtDA,eAAsB,oBAAA,CACpB,MAAA,EACA,IAAA,GAAoC,EAAC,EACT;AAC5B,EAAA,MAAM,UAAkC,EAAE,GAAI,IAAA,CAAK,OAAA,IAAW,EAAC,EAAG;AAClE,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,IAAA,CAAK,YAAA;AAE7C,EAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAqC,MAAA,EAAQ,gCAAA,EAAkC;AAAA,IAC/F,WAAA,EAAa,SAAA;AAAA,IACb,KAAA,EAAO,UAAA;AAAA,IACP,GAAG,IAAA;AAAA,IACH;AAAA,GACD,CAAA;AAED,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,IAAS,CAAA;AAC3B,EAAA,MAAM,eAAA,GAAkB,IAAI,eAAA,IAAmB,CAAA;AAC/C,EAAA,MAAM,gBAAA,GAAmB,IAAI,gBAAA,IAAoB,CAAA;AAEjD,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA;AAAA;AAAA,IAGA,KAAA,EAAO,GAAA,CAAI,KAAA,IAAS,KAAA,GAAQ,eAAA,GAAkB,gBAAA;AAAA,IAC9C,WAAA,EAAa,IAAI,WAAA,IAAe;AAAA,GAClC;AACF;;;ACwCA,eAAsB,iBACpB,MAAA,EACA,WAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACK;AACjC,EAAA,MAAM,OAAO,CAAA,cAAA,EAAiB,gBAAA,CAAiB,WAAW,CAAC,iBAAiB,IAAI,CAAA,CAAA;AAChF,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAA0B,MAAA,EAAQ,IAAA,EAAM;AAAA,MACnD,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAK,MAAM,CAAC,CAAA,QAAA,EAAW,WAAW,CAAA,CAAE,CAAA,EAAE;AAAA,MAC1D,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAeA,eAAsB,mBAAA,CACpB,MAAA,EACA,WAAA,EACA,OAAA,GAAsC,EAAC,EACC;AACxC,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA;AAAA,MACX,MAAA;AAAA,MACA,CAAA,cAAA,EAAiB,gBAAA,CAAiB,WAAW,CAAC,CAAA,OAAA,CAAA;AAAA,MAC9C;AAAA,QACE,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW,GAAA;AAAA,QACX,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAK,MAAM,CAAC,CAAA,gBAAA,EAAmB,WAAW,CAAA,CAAE,CAAA,EAAE;AAAA,QAClE,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAaA,eAAsB,iBAAA,CACpB,MAAA,EACA,WAAA,EACA,OAAA,GAAoC,EAAC,EACC;AACtC,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,QAAQ,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC7D,EAAA,IAAI,OAAA,CAAQ,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC5D,EAAA,IAAI,QAAQ,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACvD,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAE3B,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA;AAAA,MACX,MAAA;AAAA,MACA,CAAA,cAAA,EAAiB,iBAAiB,WAAW,CAAC,GAAG,EAAA,GAAK,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAAA,MACnE;AAAA,QACE,WAAA,EAAa,SAAA;AAAA,QACb,KAAA,EAAO,UAAA;AAAA,QACP,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;ACrLO,IAAM,uBAAA,GAA0BC,MAAE,MAAA,CAAO;AAAA,EAC9C,QAAA,EAAUA,MAAE,MAAA,EAAO;AAAA,EACnB,SAAA,EAAWA,MAAE,MAAA,EAAO;AAAA,EACpB,QAAA,EAAUA,MAAE,MAAA,EAAO;AAAA,EACnB,KAAA,EAAOA,MAAE,MAAA,EAAO;AAAA,EAChB,GAAA,EAAKA,MAAE,MAAA,EAAO;AAAA,EACd,QAAA,EAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,SAAA,EAAWA,MAAE,MAAA,EAAO;AAAA,EACpB,SAAA,EAAWA,MAAE,MAAA,EAAO;AAAA;AAAA,EAEpB,QAAA,EAAUA,MAAE,MAAA;AACd,CAAC,CAAA;AAGM,IAAM,kCAAA,GAAqCA,MAAE,MAAA,CAAO;AAAA,EACzD,KAAA,EAAOA,KAAA,CAAE,KAAA,CAAM,uBAAuB,CAAA;AAAA,EACtC,OAAA,EAASA,MAAE,OAAA;AACb,CAAC,CAAA;AAeD,eAAsB,yBAAA,CACpB,MAAA,EACA,OAAA,GAA4C,EAAC,EACN;AACvC,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,YAAA,EAAc,GAAG,cAAa,GAAI,OAAA;AAEzD,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,EAAA,IAAI,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AAC1D,EAAA,IAAI,WAAW,MAAA,EAAW,MAAA,CAAO,IAAI,QAAA,EAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AAC7D,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,EAAS;AAE3B,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,YAAA,UAAsB,MAAA,GAAS,YAAA;AAEnC,EAAA,MAAM,OAAO,MAAM,QAAA;AAAA,IACjB,MAAA;AAAA,IACA,CAAA,4BAAA,EAA+B,EAAA,GAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AAAA,IACjD;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,KAAA,EAAO,UAAA;AAAA,MACP,GAAG,YAAA;AAAA,MACH;AAAA;AACF,GACF;AAEA,EAAA,OAAO,kCAAA,CAAmC,MAAM,IAAI,CAAA;AACtD;;;ACxDA,eAAsB,qBAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACX;AACjB,EAAA,MAAM,IAAA,GAAO,CAAA,iBAAA,EAAoB,gBAAA,CAAiB,GAAG,CAAC,CAAA,CAAA;AACtD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkB,MAAA,EAAQ,IAAA,EAAM;AAAA,MACjD,KAAA,EAAO,UAAA;AAAA,MACP,SAAA,EAAW,GAAA;AAAA,MACX,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,IAAQ,EAAE,kBAAkB,IAAA,CAAA,EAAO;AAC1E,MAAA,OAAO,CAAA;AAAA,IACT;AACA,IAAA,MAAM,eAAe,IAAA,CAAK,YAAA;AAC1B,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA,GAAI,aAAa,MAAA,GAAS,CAAA;AAAA,EAC7D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,CAAA;AAAA,EACT;AACF;;;ACVA,eAAsB,uBAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAA0C,EAAC,EAC1B;AACjB,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAM,QAAA;AAAA,MACjB,MAAA;AAAA,MACA,CAAA,wBAAA,EAA2B,gBAAA,CAAiB,GAAG,CAAC,CAAA,CAAA;AAAA,MAChD;AAAA,QACE,KAAA,EAAO,UAAA;AAAA,QACP,SAAA,EAAW,GAAA;AAAA,QACX,GAAI,OAAA,CAAQ,YAAA,GAAe,EAAC,GAAI,EAAE,aAAa,SAAA,EAAU;AAAA,QACzD,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACF;AACA,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,SAAS,IAAA,IAAQ,EAAE,WAAW,IAAA,CAAA,EAAO;AACnE,MAAA,OAAO,CAAA;AAAA,IACT;AACA,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAM,MAAA,GAAS,CAAA;AAAA,EAC/C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,CAAA;AAAA,EACT;AACF;;;ACbA,eAAsB,mBAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAAsC,EAAC,EACS;AAChD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAE/B,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA;AAAA,MACX,MAAA;AAAA,MACA,8BAA8B,kBAAA,CAAmB,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAC,CAAA,CAAA;AAAA,MAChE;AAAA,QACE,WAAA,EAAa,SAAA;AAAA,QACb,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAUA,eAAsB,eAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAAkC,EAAC,EACC;AACpC,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA;AAAA,MACX,MAAA;AAAA,MACA,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAAA,MACzD;AAAA,QACE,WAAA,EAAa,SAAA;AAAA,QACb,GAAG,OAAA;AAAA,QACH;AAAA;AACF,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AA0BA,eAAsB,eACpB,MAAA,EACA,SAAA,EACA,OACA,SAAA,EACA,OAAA,GAA2B,EAAC,EACuD;AACnF,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA;AAC3C,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,cAAA,CAAA;AAE7B,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,EAAK;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AAAA,MAC1E,WAAA,EAAa,QAAQ,WAAA,IAAe,SAAA;AAAA,MACpC,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,SAAA,EAAW,KAAA,EAAO,WAAW,CAAA;AAAA,MACpD,QAAQ,OAAA,CAAQ,MAAA,IAAU,YAAY,OAAA,CAAQ,OAAA,CAAQ,aAAa,GAAM;AAAA,KAC1E,CAAA;AAED,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,UAAA,IAAI,IAAA,CAAK,UAAU,mBAAA,EAAqB;AACtC,YAAA,OAAO;AAAA,cACL,EAAA,EAAI,KAAA;AAAA,cACJ,OAAO,EAAE,IAAA,EAAM,oBAAA,EAAsB,aAAA,EAAe,KAAK,aAAA;AAAc,aACzE;AAAA,UACF;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,EAAE,IAAA,EAAM,SAAQ,EAAE;AAAA,IAC/C;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAK;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,EAAE,IAAA,EAAM,SAAQ,EAAE;AAAA,EAC/C;AACF;AAMO,SAAS,eACd,MAAA,EACA,SAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,gBAAA,EAAkB,QAAA,EAAU;AAAA,IAClD,IAAA,EAAM,EAAE,SAAA,EAAW,KAAA,EAAM;AAAA,IACzB,GAAG;AAAA,GACJ,CAAA;AACH;;;AC9IO,IAAM,sBAAA,GAAyB;AAmBtC,eAAsB,kBAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAAqC,EAAC,EACK;AAC3C,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAE/B,EAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,IAAI,CAAC,CAAA;AAChC,EAAA,MAAM,UAAsB,EAAC;AAC7B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,KAAK,sBAAA,EAAwB;AAC9D,IAAA,OAAA,CAAQ,KAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAA,GAAI,sBAAsB,CAAC,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,MAAM,UAA4C,EAAC;AACnD,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,OAAA,CAAQ,GAAA,CAAI,OAAO,KAAA,KAAU;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,OAAO,MAAM,QAAA;AAAA,UACjB,MAAA;AAAA,UACA,2BAAA;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,MAAA;AAAA,YACR,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,EAAM;AAAA,YACpB,WAAA,EAAa,SAAA;AAAA,YACb,SAAA,EAAW,GAAA;AAAA,YACX,GAAG,OAAA;AAAA,YACH;AAAA;AACF,SACF;AACA,QAAA,MAAA,CAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,GACH;AAEA,EAAA,OAAO,OAAA;AACT;;;ACrEA,eAAsB,iBAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAC/B,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,QAAA,CAA+B,MAAA,EAAQ,oBAAA,EAAsB;AAAA,MACxE,KAAA,EAAO,UAAA;AAAA,MACP,GAAG;AAAA,KACJ,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAeA,eAAsB,mBAAA,CACpB,MAAA,EACA,OAAA,GAAsC,EAAC,EACpB;AACnB,EAAA,MAAM,UAAkC,EAAE,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AACrE,EAAA,IAAI,OAAA,CAAQ,YAAA,EAAc,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,YAAA;AAEnD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAA+B,MAAA,EAAQ,uBAAA,EAAyB;AAAA,MACjF,WAAA,EAAa,SAAA;AAAA,MACb,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,SAAS,EAAC;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAuCA,eAAsB,eAAA,CACpB,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACI;AAChC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,IAAS,UAAA,CAAW,KAAA;AAC3C,EAAA,MAAM,MAAM,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,mBAAA,EAAsB,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA;AAE1E,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,EAAK;AAAA,MAC7B,MAAA,EAAQ,MAAA;AAAA;AAAA;AAAA;AAAA,MAIR,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY,EAAC;AAAA,MACtD,WAAA,EAAa,QAAQ,WAAA,IAAe,SAAA;AAAA,MACpC,QAAQ,OAAA,CAAQ,MAAA,IAAU,YAAY,OAAA,CAAQ,OAAA,CAAQ,aAAa,GAAM;AAAA,KAC1E,CAAA;AAED,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACtB,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,UAAA,IAAI,IAAA,CAAK,UAAU,mBAAA,EAAqB;AACtC,YAAA,OAAO;AAAA,cACL,EAAA,EAAI,KAAA;AAAA,cACJ,OAAO,EAAE,IAAA,EAAM,oBAAA,EAAsB,aAAA,EAAe,KAAK,aAAA;AAAc,aACzE;AAAA,UACF;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,EAAE,IAAA,EAAM,SAAQ,EAAE;AAAA,IAC/C;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAK;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,EAAE,IAAA,EAAM,SAAQ,EAAE;AAAA,EAC/C;AACF;AAGO,SAAS,kBAAA,CACd,MAAA,EACA,GAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAS,QAAQ,CAAA,mBAAA,EAAsB,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA,EAAI,UAAU,OAAO,CAAA;AAC5F;;;ACjGO,SAAS,gBAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,QAAA,CAAsB,QAAQ,2BAAA,EAA6B;AAAA,IAChE,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;AA4BO,SAAS,YAAA,CACd,MAAA,EACA,aAAA,EACA,OAAA,GAA2B,EAAC,EACC;AAC7B,EAAA,OAAO,QAAA,CAAiD,MAAA,EAAQ,oBAAA,EAAsB,QAAA,EAAU;AAAA,IAC9F,IAAA,EAAM,EAAE,aAAA,EAAc;AAAA,IACtB,GAAG;AAAA,GACJ,CAAA;AACH;AAWO,SAAS,aAAA,CACd,MAAA,EACA,aAAA,EACA,OAAA,GAA2B,EAAC,EACE;AAC9B,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,sBAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,EAAE,aAAA,EAAc;AAAA,MACtB,GAAG;AAAA;AACL,GACF;AACF;;;ACpHO,SAAS,kBAAA,CACd,MAAA,EACA,OAAA,GAA2B,EAAC,EACJ;AACxB,EAAA,OAAO,QAAA,CAAwB,QAAQ,wBAAA,EAA0B;AAAA,IAC/D,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;AA0BO,SAAS,iBAAA,CACd,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACsC;AAClE,EAAA,OAAO,QAAA,CAA2B,MAAA,EAAQ,qBAAA,EAAuB,MAAA,EAAQ;AAAA,IACvE,IAAA,EAAM,KAAA;AAAA,IACN,GAAG;AAAA,GACJ,CAAA;AACH;AASO,SAAS,cAAc,MAAA,EAA+B;AAC3D,EAAA,OAAO,CAAA,EAAG,OAAO,OAAO,CAAA,mBAAA,CAAA;AAC1B;;;ACcO,SAAS,qBACd,KAAA,EAC6B;AAC7B,EAAA,OAAO,OAAA,IAAW,KAAA;AACpB;AAOA,eAAsB,4BAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACwB;AACpD,EAAA,OAAO,QAAA,CAAoD,QAAQ,2BAAA,EAA6B;AAAA,IAC9F,MAAA,EAAQ,MAAA;AAAA,IACR,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACH;AAMA,eAAsB,wBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACM;AAClC,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,CAAA,wBAAA,EAA2B,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAAA,IACpD;AAAA,MACE,WAAA,EAAa,SAAA;AAAA,MACb,GAAG;AAAA;AACL,GACF;AACF;AAMA,eAAsB,eAAA,CACpB,MAAA,EACA,OAAA,GAA2B,EAAC,EACQ;AACpC,EAAA,OAAO,cAAA,CAAmC,QAAQ,kBAAA,EAAoB;AAAA,IACpE,WAAA,EAAa,SAAA;AAAA,IACb,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACH;ACvHA,IAAM,kBAAkBA,KAAAA,CACrB,MAAA,EAAO,CACP,MAAA,CAAO,CAAC,CAAA,KAAM,eAAA,CAAgB,IAAA,CAAK,CAAC,GAAG,EAAE,OAAA,EAAS,wBAAA,EAA0B,EAC5E,QAAA,EAAS;AAEZ,IAAM,kBAAA,GAAqB;AAAA,EACzB,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,MAAA,EAAQA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC5B,OAAA,EAASA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC7B,OAAA,EAAS,eAAA;AAAA,EACT,UAAA,EAAYA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACzB,CAAA;AASO,IAAM,wBAAA,GAA2BA,KAAAA,CAAE,kBAAA,CAAmB,QAAA,EAAU;AAAA,EACrEA,MAAE,MAAA,CAAO;AAAA,IACP,MAAA,EAAQA,KAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC1B,UAAUA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA,IACpC,GAAG;AAAA,GACJ,CAAA;AAAA,EACDA,MAAE,MAAA,CAAO;AAAA,IACP,MAAA,EAAQA,KAAAA,CAAE,OAAA,CAAQ,KAAK,CAAA;AAAA,IACvB,KAAA,EAAOA,KAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,IACvB,GAAG;AAAA,GACJ;AACH,CAAC,CAAA;AAIM,IAAM,0BAAA,GAA6BA,MAAE,MAAA,CAAO;AAAA,EACjD,OAAA,EAASA,KAAAA,CAAE,KAAA,CAAM,wBAAwB,CAAA;AAAA,EACzC,OAAA,EAASA,MAAE,OAAA;AACb,CAAC,CAAA;AAQwCA,MACtC,MAAA,CAAO;AAAA,EACN,QAAA,EAAUA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,QAAA,GAAW,QAAA,EAAS;AAAA,EAC/C,OAAOA,KAAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,QAAA;AAC3B,CAAC,CAAA,CACA,OAAO,CAAC,CAAA,KAAO,EAAE,QAAA,IAAY,IAAA,MAAW,CAAA,CAAE,KAAA,IAAS,IAAA,CAAA,EAAO;AAAA,EACzD,OAAA,EAAS;AACX,CAAC;AAMI,IAAM,0BAAA,GAA6BA,MAAE,MAAA,CAAO;AAAA,EACjD,UAAUA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA,EACpC,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,aAAA,EAAeA,MAAE,MAAA,EAAO;AAAA,EACxB,MAAA,EAAQA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5B,OAAA,EAAS,eAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA;AAAA;AAAA,EAErC,WAAA,EAAaA,KAAAA,CAAE,IAAA,CAAK,CAAC,KAAA,EAAO,SAAS,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,IAAI,CAAA;AAAA,EAC/D,SAAA,EAAW;AACb,CAAC,CAAA;AAIM,IAAM,gCAAA,GAAmCA,MAAE,MAAA,CAAO;AAAA,EACvD,OAAA,EAASA,KAAAA,CAAE,KAAA,CAAM,wBAAwB;AAC3C,CAAC,CAAA;AAQ+CA,MAAE,MAAA,CAAO;AAAA,EACvD,MAAA,EAAQA,MAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,GAAG;AACnC,CAAC;AAUgDA,MAAE,MAAA,CAAO;AAAA,EACxD,OAAA,EAASA,KAAAA,CAAE,KAAA,CAAM,wBAAwB,CAAA;AAAA,EACzC,OAAA,EAASA,MAAE,OAAA;AACb,CAAC;AAc6CA,MAAE,MAAA,CAAO;AAAA,EACrD,MAAA,EAAQ,wBAAA;AAAA,EACR,OAAA,EAASA,MAAE,OAAA;AACb,CAAC;;;ACvHD,IAAMC,gBAAqC,EAAE,OAAA,EAAS,EAAC,EAAG,SAAS,KAAA,EAAM;AAMzE,eAAsB,kBACpB,MAAA,EACA,KAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAC/B,EAAA,IAAI,CAAC,KAAA,CAAM,IAAA,EAAK,EAAG,OAAOA,aAAAA;AAC1B,EAAA,MAAM,SAAS,IAAI,eAAA,CAAgB,EAAE,CAAA,EAAG,OAAO,CAAA;AAC/C,EAAA,IAAI,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkB,MAAA,EAAQ,wBAAwB,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,EAAI;AAAA,IACxF,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,OAAO,0BAAA,CAA2B,MAAM,IAAI,CAAA;AAC9C;AAOA,eAAsB,YAAA,CACpB,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAC/B,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkB,MAAA,EAAQ,sBAAA,EAAwB;AAAA,IACnE,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA;AAAA,IACA,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,OAAO,0BAAA,CAA2B,MAAM,IAAI,CAAA;AAC9C;AAOA,eAAsB,oBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAA2B,EAAC,EACG;AAC/B,EAAA,IAAI,CAAC,KAAA,CAAM,IAAA,EAAK,SAAU,EAAC;AAC3B,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAkB,MAAA,EAAQ,6BAAA,EAA+B;AAAA,IAC1E,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EAAM,EAAE,CAAA,EAAG,KAAA,EAAM;AAAA,IACjB,WAAA,EAAa,SAAA;AAAA,IACb,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,OAAO,gCAAA,CAAiC,KAAA,CAAM,IAAI,CAAA,CAAE,OAAA;AACtD;;;ACHO,SAAS,cAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACL;AAChD,EAAA,OAAO,QAAA,CAAkC,QAAQ,gBAAA,EAAkB,MAAA,EAAQ,EAAE,IAAA,EAAM,GAAG,SAAS,CAAA;AACjG;AAMO,SAAS,gBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACG;AACxD,EAAA,OAAO,QAAA,CAA0C,MAAA,EAAQ,kBAAA,EAAoB,KAAA,EAAO;AAAA,IAClF,IAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,yBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACK;AAC1D,EAAA,OAAO,QAAA,CAA4C,MAAA,EAAQ,4BAAA,EAA8B,MAAA,EAAQ;AAAA,IAC/F,IAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAQO,SAAS,eAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACE;AACvD,EAAA,OAAO,QAAA,CAAyC,MAAA,EAAQ,yBAAA,EAA2B,MAAA,EAAQ;AAAA,IACzF,IAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAQO,SAAS,uBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACU;AAC/D,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,8BAAA;AAAA,IACA,MAAA;AAAA,IACA,EAAE,IAAA,EAAM,GAAG,OAAA;AAAQ,GACrB;AACF;AAMO,SAAS,0BAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAAoD,EAAC,EACa;AAClE,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,8BAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAE,IAAA,EAAM,GAAG,OAAA;AAAQ,GACrB;AACF;;;ACvIO,SAAS,oBACd,SAAA,EACe;AACf,EAAA,IAAI,CAAC,SAAA,IAAa,SAAA,CAAU,MAAA,KAAW,GAAG,OAAO,MAAA;AAEjD,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,CAAA,CAAE,MAAM,CAAA;AAC9D,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAEhC,EAAA,MAAM,UAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,IAAI,CAAA;AACrD,EAAA,IAAI,SAAS,OAAO,OAAA;AAEpB,EAAA,OAAO,CAAC,GAAG,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAA,CAAO,CAAA,CAAE,SAAA,IAAa,IAAI,aAAA,CAAc,CAAA,CAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAA;AAC3F;;;ACEA,IAAM,kBAAA,GAAqB,CAAA;AAEpB,SAAS,oBAAA,CACd,IAAA,EACA,OAAA,GAAuC,EAAC,EACxB;AAChB,EAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,aAAa,kBAAkB,CAAA;AACjE,EAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,IAAA,CAAK,SAAS,CAAA;AAElD,EAAA,OAAO;AAAA,IACL,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,cAAc,OAAA,EAAS,KAAA;AAAA,IACvB,cAAA,EAAgB,OAAA,GAAW,OAAA,CAAQ,UAAA,IAAc,QAAQ,OAAA,GAAW,MAAA;AAAA,IACpE,SAAA,EAAA,CAAY,IAAA,CAAK,MAAA,IAAU,EAAC,EAAG,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAAA,IAChE,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,GAC3B;AACF;;;AC3CA,eAAsB,mBAAA,CACpB,MAAA,EACA,KAAA,EACA,OAAA,GAAyD,EAAC,EAC1B;AAChC,EAAA,MAAM,EAAE,SAAA,EAAW,GAAG,YAAA,EAAa,GAAI,OAAA;AACvC,EAAA,MAAM,IAAA,GAAO,MAAM,mBAAA,CAAoB,MAAA,EAAQ,OAAO,YAAY,CAAA;AAClE,EAAA,OAAO,OAAO,oBAAA,CAAqB,IAAA,EAAM,EAAE,SAAA,EAAW,CAAA,GAAI,IAAA;AAC5D;;;ACdO,IAAM,aAAA,GAAgB;AAAA,EAC3B,GAAA,EAAK,MAAM,CAAC,MAAM,CAAA;AAAA,EAElB,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,IAC7B,UAAU,CAAC,WAAA,KAAwB,CAAC,MAAA,EAAQ,WAAW,WAAW,CAAA;AAAA,IAClE,YAAY,CAAC,GAAA,KAAgB,CAAC,MAAA,EAAQ,SAAA,EAAW,gBAAgB,GAAG,CAAA;AAAA,IACpE,MAAM,CAAC,KAAA,KAAkB,CAAC,MAAA,EAAQ,SAAA,EAAW,QAAQ,KAAK,CAAA;AAAA,IAC1D,kBAAkB,CAAC,WAAA,KACjB,CAAC,MAAA,EAAQ,SAAA,EAAW,qBAAqB,WAAW,CAAA;AAAA;AAAA;AAAA,IAGtD,YAAA,EAAc,MAAM,CAAC,MAAA,EAAQ,WAAW,cAAc;AAAA,GACxD;AAAA,EAEA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,IAC9B,SAAS,CAAC,GAAA,KAAgB,CAAC,MAAA,EAAQ,UAAA,EAAY,YAAY,GAAG,CAAA;AAAA;AAAA,IAE9D,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,YAAY,UAAU;AAAA,GACjD;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,EAAO;AAAA,IACL,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC3B,MAAA,EAAQ,MAAM,CAAC,MAAA,EAAQ,SAAS,QAAQ;AAAA,GAC1C;AAAA,EAEA,MAAA,EAAQ;AAAA,IACN,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5B,UAAU,CAAC,OAAA,KACT,CAAC,MAAA,EAAQ,QAAA,EAAU,YAAY,OAAO,CAAA;AAAA,IACxC,WAAW,CAAC,OAAA,KACV,CAAC,MAAA,EAAQ,QAAA,EAAU,aAAa,OAAO,CAAA;AAAA,IACzC,QAAQ,CAAC,KAAA,KAAkB,CAAC,MAAA,EAAQ,QAAA,EAAU,UAAU,KAAK,CAAA;AAAA,IAC7D,eAAA,EAAiB,CAAC,KAAA,EAAe,KAAA,KAC/B,CAAC,MAAA,EAAQ,QAAA,EAAU,kBAAA,EAAoB,KAAA,EAAO,KAAK,CAAA;AAAA,IACrD,OAAA,EAAS,MAAM,CAAC,MAAA,EAAQ,UAAU,SAAS;AAAA,GAC7C;AAAA,EAEA,MAAA,EAAQ;AAAA,IACN,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5B,MAAA,EAAQ,CAAC,KAAA,EAAe,KAAA,KAAkB,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,KAAK;AAAA,GACrF;AAAA,EAEA,SAAA,EAAW;AAAA,IACT,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,WAAW,CAAA;AAAA,IAC/B,OAAA,EAAS,CAAC,GAAA,EAAa,KAAA,KAAkB,CAAC,MAAA,EAAQ,WAAA,EAAa,SAAA,EAAW,GAAA,EAAK,KAAK,CAAA;AAAA,IACpF,aAAa,CAAC,IAAA,KACZ,CAAC,MAAA,EAAQ,WAAA,EAAa,eAAe,IAAI,CAAA;AAAA,IAC3C,eAAA,EAAiB,CAAC,KAAA,KAChB,CAAC,QAAQ,WAAA,EAAa,kBAAA,EAAoB,SAAS,IAAI,CAAA;AAAA,IACzD,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,aAAa,UAAU;AAAA,GAClD;AAAA,EAEA,MAAA,EAAQ;AAAA,IACN,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5B,WAAW,CAAC,IAAA,KAAkC,CAAC,MAAA,EAAQ,QAAA,EAAU,aAAa,IAAI,CAAA;AAAA,IAClF,WAAW,CAAC,MAAA,KAAmB,CAAC,MAAA,EAAQ,QAAA,EAAU,aAAa,MAAM,CAAA;AAAA,IACrE,aAAa,CAAC,MAAA,KAAmB,CAAC,MAAA,EAAQ,QAAA,EAAU,gBAAgB,MAAM,CAAA;AAAA,IAC1E,MAAM,CAAC,IAAA,KAAkC,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAQ,IAAI,CAAA;AAAA,IACxE,SAAS,CAAC,MAAA,KAAmB,CAAC,MAAA,EAAQ,QAAA,EAAU,WAAW,MAAM,CAAA;AAAA,IACjE,kBAAA,EAAoB,MAAM,CAAC,MAAA,EAAQ,UAAU,qBAAqB;AAAA,GACpE;AAAA,EAEA,KAAA,EAAO;AAAA,IACL,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC3B,kBAAkB,CAAC,IAAA,KAAiB,CAAC,MAAA,EAAQ,OAAA,EAAS,qBAAqB,IAAI,CAAA;AAAA,IAC/E,YAAA,EAAc,MAAM,CAAC,MAAA,EAAQ,SAAS,eAAe;AAAA,GACvD;AAAA,EAEA,KAAA,EAAO;AAAA,IACL,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC3B,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,SAAS,UAAU;AAAA,GAC9C;AAAA,EAEA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC1B,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,QAAQ,UAAU,CAAA;AAAA,IAC3C,MAAA,EAAQ,MAAM,CAAC,MAAA,EAAQ,QAAQ,QAAQ;AAAA,GACzC;AAAA,EAEA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA;AAAA;AAAA;AAAA,IAG1B,QAAA,EAAU,MAAM,CAAC,MAAA,EAAQ,QAAQ,UAAU;AAAA,GAC7C;AAAA,EAEA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,IAC9B,OAAA,EAAS,CAAC,WAAA,EAAqB,IAAA,KAC7B,CAAC,MAAA,EAAQ,UAAA,EAAY,SAAA,EAAW,WAAA,EAAa,IAAI,CAAA;AAAA,IACnD,QAAQ,CAAC,WAAA,KAAwB,CAAC,MAAA,EAAQ,UAAA,EAAY,UAAU,WAAW,CAAA;AAAA,IAC3E,IAAA,EAAM,CAAC,WAAA,EAAqB,IAAA,KAC1B,CAAC,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,WAAA,EAAa,IAAI,CAAA;AAAA;AAAA;AAAA,IAGhD,WAAA,EAAa,MAAM,CAAC,MAAA,EAAQ,YAAY,cAAc;AAAA,GACxD;AAAA,EAEA,MAAA,EAAQ;AAAA,IACN,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5B,gBAAgB,CAAC,IAAA,KACf,CAAC,MAAA,EAAQ,QAAA,EAAU,oBAAoB,IAAI;AAAA,GAC/C;AAAA,EAEA,WAAA,EAAa;AAAA,IACX,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,aAAa,CAAA;AAAA,IACjC,OAAO,CAAC,GAAA,KAAgB,CAAC,MAAA,EAAQ,aAAA,EAAe,SAAS,GAAG,CAAA;AAAA;AAAA;AAAA,IAG5D,OAAA,EAAS,MAAM,CAAC,MAAA,EAAQ,eAAe,SAAS,CAAA;AAAA;AAAA;AAAA,IAGhD,WAAA,EAAa,MAAM,CAAC,MAAA,EAAQ,eAAe,aAAa,CAAA;AAAA,IACxD,UAAU,CAAC,GAAA,KAAgB,CAAC,MAAA,EAAQ,aAAA,EAAe,YAAY,GAAG;AAAA,GACpE;AAAA,EAEA,YAAA,EAAc;AAAA,IACZ,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA,IAIlC,OAAA,EAAS,MAAM,CAAC,MAAA,EAAQ,gBAAgB,SAAS,CAAA;AAAA;AAAA,IAEjD,KAAA,EAAO,MAAM,CAAC,MAAA,EAAQ,gBAAgB,OAAO;AAAA,GAC/C;AAAA,EAEA,MAAA,EAAQ;AAAA,IACN,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5B,cAAc,CAAC,GAAA,KAAgB,CAAC,MAAA,EAAQ,QAAA,EAAU,iBAAiB,GAAG;AAAA,GACxE;AAAA,EAEA,SAAA,EAAW;AAAA,IACT,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,WAAW,CAAA;AAAA,IAC/B,QAAQ,CAAC,IAAA,KAAmB,CAAC,MAAA,EAAQ,WAAA,EAAa,UAAU,IAAI,CAAA;AAAA,IAChE,cAAc,CAAC,KAAA,KAAkB,CAAC,MAAA,EAAQ,WAAA,EAAa,iBAAiB,KAAK;AAAA,GAC/E;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,IAC7B,KAAA,EAAO,MAAM,CAAC,MAAA,EAAQ,WAAW,OAAO,CAAA;AAAA,IACxC,OAAA,EAAS,MAAM,CAAC,MAAA,EAAQ,WAAW,UAAU;AAAA,GAC/C;AAAA,EAEA,eAAA,EAAiB;AAAA,IACf,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,kBAAkB,CAAA;AAAA,IACtC,aAAA,EAAe,MAAM,CAAC,MAAA,EAAQ,oBAAoB,gBAAgB;AAAA,GACpE;AAAA,EAEA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,gBAAgB,CAAA;AAAA,IACpC,IAAA,EAAM,MAAM,CAAC,MAAA,EAAQ,kBAAkB,MAAM;AAAA,GAC/C;AAAA,EACA,WAAA,EAAa;AAAA,IACX,GAAA,EAAK,MAAM,CAAC,MAAA,EAAQ,aAAa,CAAA;AAAA,IACjC,WAAA,EAAa,MAAM,CAAC,MAAA,EAAQ,eAAe,cAAc;AAAA;AAE7D;ACnKO,SAAS,aAAa,GAAA,EAAa;AACxC,EAAA,OAAO,CAAC,KAAA,KAA2B;AACjC,IAAA,MAAM,SAAA,GAAY,IAAI,IAAA,CAAK,SAAA,CAAU,QAAW,EAAE,WAAA,EAAa,YAAY,CAAA;AAC3E,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,CAAA,IAAK,SAAA,CAAU,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxC,MAAA,KAAA,EAAA;AACA,MAAA,IAAI,KAAA,GAAQ,KAAK,OAAO,KAAA;AAAA,IAC1B;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF;AAGO,IAAM,YAAYD,KAAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,kCAAkC,aAAa,CAAA;AAGlF,IAAM,cAAA,GAAiBA,MAAE,MAAA,EAAO,CAAE,SAAS,EAAE,MAAA,EAAQ,MAAM,CAAA;AAW3D,IAAM,oBAAoBA,KAAAA,CAC9B,MAAA,EAAO,CACP,KAAA,CAAM,mCAAmC,mDAAmD,CAAA;AAGxF,IAAM,cAAcA,KAAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,mBAAmB,gBAAgB,CAAA;AAGxE,IAAM,YAAYA,KAAAA,CACtB,MAAA,EAAO,CACP,KAAA,CAAM,mDAAmD,aAAa,CAAA;AAGxCA,KAAAA,CAC9B,MAAA,EAAO,CACP,KAAA,CAAM,uCAAuC,6BAA6B;AAGtE,IAAM,SAAA,GAAYA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI;AAMjC,IAAM,eAAA,GAAkBA,MAAE,MAAA,CAAO;AAAA,EACtC,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAC,CAAA;AAQ6BA,MAAE,MAAA,CAAO;AAAA,EACrC,GAAA,EAAK;AACP,CAAC;AAQM,IAAM,uBAAA,GAA0BA,MAAE,MAAA,CAAO;AAAA,EAC9C,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK,UAAU,QAAA;AACjB,CAAC,CAAA;AAW6BA,MAC3B,MAAA,CAAO;AAAA,EACN,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,IAAI,IAAI,CAAA;AAAA,EAC1D,GAAA,EAAK,UAAU,QAAA,EAAS;AAAA,EACxB,SAAA,EAAW,UAAU,QAAA;AACvB,CAAC,EACA,WAAA;AASI,IAAM,gBAAA,GAAmBA,MAAE,MAAA,CAAO;AAAA,EACvC,KAAA,EAAOA,KAAAA,CAAE,OAAA,CAAQ,mCAAmC,EAAE,QAAA,EAAS;AAAA,EAC/D,MAAA,EAAQA,KAAAA,CAAE,KAAA,CAAMA,KAAAA,CAAE,MAAA,CAAO,EAAE,GAAA,EAAKA,KAAAA,CAAE,MAAA,EAAO,EAAG,CAAC;AAC/C,CAAC,CAAA;AC5FM,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA,EAC7C,GAAA,EAAK,SAAA;AAAA,EACL,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,KAAA,EAAOA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,IAAI,CAAA,CAAE,QAAA;AACxD,CAAC,CAAA;AAKyCA,MAAE,MAAA,CAAO;AAAA,EACjD,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,IAAI,IAAI,CAAA;AAAA,EAC1D,WAAA,EAAaA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAK,CAAA,CAAE,QAAA,EAAS;AAAA,EACvE,GAAA,EAAK,UAAU,QAAA,EAAS;AAAA,EACxB,OAAA,EAASA,MAAE,KAAA,CAAM,sBAAsB,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1D,UAAA,EAAY,gBAAgB,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrC,MAAA,EAAQ,wBAAwB,QAAA,EAAS;AAAA,EACzC,QAAA,EAAU,gBAAgB,QAAA,EAAS;AAAA,EACnC,SAAA,EAAW,kBAAkB,QAAA,EAAS;AAAA,EACtC,OAAA,EAAS,kBAAkB,QAAA,EAAS;AAAA,EACpC,MAAA,EAAQ,iBAAiB,QAAA,EAAS;AAAA,EAClC,SAAA,EAAW;AACb,CAAC;;;AC/BM,IAAM,kBAAA,GAAqBA,MAC/B,MAAA,CAAO;AAAA,EACN,GAAA,EAAK,SAAA;AAAA,EACL,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,KAAA,EAAOA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,GAAI,CAAA,CAAE,QAAA;AACxD,CAAC,EACA,WAAA,EAAY;AAY+BA,MAC3C,MAAA,CAAO;AAAA,EACN,IAAA,EAAMA,MAAE,MAAA,EAAO;AAAA,EACf,QAAA,EAAUA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,IAAI,CAAA,CAAE,QAAA,EAAS;AAAA,EAClE,WAAA,EAAa,UAAU,QAAA,EAAS;AAAA,EAChC,WAAA,EAAa,UAAU,QAAA,EAAS;AAAA,EAChC,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,IAAI,CAAA,CAAE,QAAA,EAAS;AAAA,EAC9D,WAAA,EAAaA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAK,CAAA,CAAE,QAAA,EAAS;AAAA,EACvE,SAAA,EAAW,kBAAkB,QAAA,EAAS;AAAA,EACtC,OAAA,EAAS,kBAAkB,QAAA,EAAS;AAAA,EACpC,KAAA,EAAOA,MAAE,KAAA,CAAM,kBAAkB,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA;AAAA;AAAA,EAGpD,SAAA,EAAWA,MACR,MAAA,EAAO,CACP,KAAI,CACJ,MAAA,CAAO,CAAC,CAAA,KAAM,eAAA,CAAgB,KAAK,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,kCAAA,EAAoC,CAAA,CACtF,GAAA,CAAI,IAAI,CAAA,CACR,QAAA,EAAS;AAAA;AAAA,EAEZ,QAAA,EAAUA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA;AAAA,EAE/B,QAAQA,KAAAA,CACL,KAAA,CAAMA,KAAAA,CAAE,MAAA,CAAO,EAAE,GAAA,EAAKA,KAAAA,CAAE,MAAA,EAAO,EAAG,CAAC,CAAA,CACnC,GAAA,CAAI,EAAE,EACN,QAAA,EAAS;AAAA,EACZ,MAAA,EAAQ,iBAAiB,QAAA,EAAS;AAAA,EAClC,aAAA,EAAeA,MAAE,KAAA,CAAM,sBAAsB,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA,EAChE,MAAA,EAAQ,wBAAwB,QAAA,EAAS;AAAA,EACzC,SAAA,EAAW;AACb,CAAC,EACA,WAAA;;;ACxDH,IAAM,cAAA,GAAiBA,MACpB,MAAA,EAAO,CACP,KAAI,CACJ,MAAA,CAAO,CAAC,CAAA,KAAM,eAAA,CAAgB,KAAK,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,kCAAA,EAAoC,CAAA,CACtF,GAAA,CAAI,IAAI,CAAA,CACR,QAAA,EAAS;AAOL,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA;AAAA,EAE7C,OAAOA,KAAAA,CAAE,MAAA,GAAS,GAAA,EAAI,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAE7B,QAAA,EAAUA,KAAAA,CAAE,MAAA,EAAO,CAAE,OAAO,CAAC;AAC/B,CAAC,CAAA;AAGM,IAAM,uBAAA,GAA0B,4BAAA;AAGMA,MAC1C,MAAA,CAAO;AAAA;AAAA,EAEN,OAAA,EAASA,KAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,IAAI,IAAI,CAAA;AAAA,EAC7D,UAAA,EAAY,UAAU,QAAA,EAAS;AAAA,EAC/B,SAAA,EAAW,cAAA;AAAA,EACX,IAAA,EAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,KAAA,EAAOA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3B,MAAA,EAAQA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA,EAE5B,GAAA,EAAKA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,IAAI,CAAA,CAAE,QAAA,EAAS;AAAA,EAC7D,MAAA,EAAQ,UAAU,QAAA,EAAS;AAAA,EAC3B,YAAA,EAAc,cAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,MAAA,EAAQ,uBAAuB,QAAA,EAAS;AAAA,EACxC,SAAA,EAAW,kBAAkB,QAAA,EAAS;AAAA,EACtC,OAAA,EAAS,kBAAkB,QAAA,EAAS;AAAA,EACpC,WAAA,EAAaA,KAAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,YAAA,CAAa,GAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAK,CAAA,CAAE,QAAA,EAAS;AAAA,EACvE,KAAA,EAAOA,MAAE,KAAA,CAAM,kBAAkB,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA,EACpD,MAAA,EAAQ,iBAAiB,QAAA,EAAS;AAAA,EAClC,SAAA,EAAW;AACb,CAAC,EACA,WAAA;;;AC/CI,SAAS,gBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACL;AACvB,EAAA,OAAO,YAAA,CAAa,MAAA,EAAQ,uBAAA,EAAyB,IAAA,EAAM,OAAO,CAAA;AACpE;AAGO,SAAS,iBACd,MAAA,EACA,IAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,YAAA,CAAa,MAAA,EAAQ,uBAAA,EAAyB,IAAA,EAAM,MAAM,OAAO,CAAA;AAC1E;AAGO,SAAS,gBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,GAA2B,EAAC,EACN;AACtB,EAAA,OAAO,YAAA,CAAa,MAAA,EAAQ,uBAAA,EAAyB,IAAA,EAAM,OAAO,CAAA;AACpE","file":"index.cjs","sourcesContent":["/**\n * Foundation HTTP client for talking to the Sifa AppView.\n *\n * Stateless. Consumers supply a {@link SifaApiConfig} per call (the React\n * hooks read it from context; non-React consumers pass it explicitly). No\n * singletons, no module-level state.\n */\n\n/** Configuration passed to every fetcher. */\nexport interface SifaApiConfig {\n /** Base URL of the sifa-api AppView, e.g. `https://api.sifa.id`. No trailing slash. */\n baseUrl: string;\n /**\n * Optional fetch implementation. Defaults to {@link globalThis.fetch}.\n * Lets Next.js consumers pass their cache-enhanced fetch; node/Expo\n * consumers can leave this unset.\n */\n fetch?: typeof fetch;\n}\n\n/** Options accepted by {@link apiFetch}. */\nexport interface ApiFetchOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n /** Request body. Serialized to JSON automatically. */\n body?: unknown;\n /** AbortSignal. Defaults to `AbortSignal.timeout(timeoutMs)` if `timeoutMs` is set. */\n signal?: AbortSignal;\n /** Per-call timeout in milliseconds. Default: 10_000. Ignored if `signal` is provided. */\n timeoutMs?: number;\n /** Retry on HTTP 429 up to 3 times with the server's `Retry-After` delay (capped at 3s). */\n retryOn429?: boolean;\n /** Additional headers. `Content-Type: application/json` is set automatically when `body` is present. */\n headers?: Record<string, string>;\n credentials?: RequestCredentials;\n cache?: RequestCache;\n /**\n * Next.js-specific cache hints. Ignored on non-Next runtimes. Passed\n * through transparently as part of {@link RequestInit}.\n */\n next?: { revalidate?: number | false; tags?: string[] };\n}\n\n/** Error thrown by {@link apiFetch} on non-2xx responses. */\nexport class ApiError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.name = 'ApiError';\n this.status = status;\n this.body = body;\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_RATE_LIMIT_RETRIES = 3;\nconst RATE_LIMIT_RETRY_CAP_SECONDS = 3;\n\n/**\n * Encode a handle or DID for safe interpolation into a request path,\n * idempotently.\n *\n * Plain {@link encodeURIComponent} double-encodes an already-encoded\n * identifier: Next.js hands route params to RSC pages percent-encoded on a\n * hard navigation (`did%3Aplc%3A...`) but decoded on client-side navigation\n * (`did:plc:...`). Encoding the former again turns `%` into `%25`, so the\n * AppView reads `did%3A...` as a literal handle, finds no match, and 404s —\n * which is why DID profile links broke on direct visits but worked when\n * clicked within the app.\n *\n * AT identifiers (handles are domain names, DIDs are `did:method:...`) never\n * contain a literal `%`, so decoding a decoded value is a no-op. A malformed\n * percent sequence (lone `%`) makes {@link decodeURIComponent} throw; in that\n * case we keep the original value so behaviour matches the prior bare\n * `encodeURIComponent`.\n */\nexport function encodeIdentifier(value: string): string {\n let decoded = value;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n // Malformed percent-encoding — fall back to the raw value.\n }\n return encodeURIComponent(decoded);\n}\n\n/**\n * Generic fetcher used by all SDK query and mutation functions.\n *\n * Returns parsed JSON typed as `T`. Throws {@link ApiError} on non-2xx\n * responses. Use {@link apiFetchOrNull} when 404 should resolve to `null`\n * instead.\n */\nexport async function apiFetch<T = unknown>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}${path}`;\n const maxRetries = options.retryOn429 ? MAX_RATE_LIMIT_RETRIES : 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n let body: BodyInit | undefined;\n if (options.body !== undefined) {\n headers['Content-Type'] ??= 'application/json';\n body = JSON.stringify(options.body);\n }\n\n // `next` is a Next.js extension to RequestInit; cast through.\n const init = {\n method: options.method ?? 'GET',\n headers,\n body,\n signal,\n credentials: options.credentials,\n cache: options.cache,\n ...(options.next ? { next: options.next } : {}),\n } as RequestInit;\n\n const res = await fetchFn(url, init);\n\n if (res.status === 429 && attempt < maxRetries) {\n const retryAfterRaw = res.headers.get('retry-after');\n const retryAfter = retryAfterRaw ? Number.parseInt(retryAfterRaw, 10) : 2;\n const waitSeconds = Math.min(\n Number.isFinite(retryAfter) ? retryAfter : 2,\n RATE_LIMIT_RETRY_CAP_SECONDS,\n );\n await new Promise((r) => setTimeout(r, waitSeconds * 1000));\n continue;\n }\n\n if (!res.ok) {\n let errBody: unknown;\n try {\n errBody = (await res.json()) as unknown;\n } catch {\n try {\n errBody = await res.text();\n } catch {\n errBody = undefined;\n }\n }\n throw new ApiError(`Sifa API ${res.status} on ${path}`, res.status, errBody);\n }\n\n // 204 and 205 are defined to carry no body, so res.json() throws on them.\n // apiWrite treats that throw as a failed write, which turned every\n // successful no-content response (roadmap unvote, remove reaction,\n // dismiss endorsement) into a reported error.\n if (res.status === 204 || res.status === 205) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n\n throw new ApiError(`Sifa API exhausted retries on ${path}`, 429);\n}\n\n/**\n * Variant of {@link apiFetch} that resolves to `null` on HTTP 404 instead\n * of throwing. Useful for \"fetch by handle\" reads where missing is\n * expected (e.g. unknown profile).\n */\nexport async function apiFetchOrNull<T>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T | null> {\n try {\n return await apiFetch<T>(config, path, options);\n } catch (e) {\n if (e instanceof ApiError && e.status === 404) return null;\n throw e;\n }\n}\n\n/**\n * Result returned by record-write mutations (create / update / delete).\n *\n * Never throws -- writes against the user's PDS can fail in many ways\n * (network, PDS unreachable, rate limit) and the UI needs structured\n * results to render appropriate messages.\n */\nexport interface WriteResult {\n success: boolean;\n error?: string;\n /**\n * PDS hostname returned by sifa-api when a write failed at the user's\n * Personal Data Server (issue #167). Lets the UI render\n * \"Your data server (eurosky.social) isn't responding\" instead of a\n * generic \"Request failed (500)\".\n */\n pdsHost?: string;\n}\n\n/** Result returned by create mutations. Includes the newly created `rkey`. */\nexport interface CreateResult extends WriteResult {\n rkey?: string;\n}\n\ninterface ApiErrorBody {\n message?: string;\n pdsHost?: string;\n}\n\nfunction extractWriteError(data: unknown, status: number): { error: string; pdsHost?: string } {\n const body = (data ?? {}) as ApiErrorBody;\n return {\n error: body.message ?? `Request failed (${status})`,\n ...(body.pdsHost ? { pdsHost: body.pdsHost } : {}),\n };\n}\n\n/**\n * Write mutation against the Sifa AppView. Wraps {@link apiFetch} with the\n * never-throws contract used by all sifa-web mutations: returns a\n * structured {@link WriteResult} on both success and failure, and\n * preserves the `pdsHost` field when the AppView reports a PDS-side\n * failure (issue #167).\n *\n * On success: returns `{ success: true, ...payload }` where `payload` is\n * whatever the server returned in JSON (or `{}` for 204).\n *\n * On failure: returns `{ success: false, error, pdsHost? }`. Never throws.\n *\n * Use {@link apiWriteCreate} when you specifically need the `rkey` from a\n * create response folded into the result shape.\n */\nexport async function apiWrite<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n method: 'POST' | 'PUT' | 'DELETE' | 'PATCH',\n options: Omit<ApiFetchOptions, 'method'> = {},\n): Promise<WriteResult & TExtra> {\n try {\n const data = await apiFetch<TExtra>(config, path, {\n method,\n credentials: 'include',\n ...options,\n });\n return { success: true, ...(data ?? ({} as TExtra)) };\n } catch (e) {\n if (e instanceof ApiError) {\n return { success: false, ...extractWriteError(e.body, e.status) } as WriteResult & TExtra;\n }\n return { success: false, error: 'Network error' } as WriteResult & TExtra;\n }\n}\n\n/**\n * Write mutation that expects the server to return a record key (`rkey`)\n * in its response body. Wraps {@link apiWrite} and folds the `rkey` into\n * the result shape so consumers get `{ success, rkey?, error?, pdsHost? }`.\n *\n * If the server returns additional fields (e.g. `feedUrl` from external\n * account creation), pass them via the `TExtra` generic to keep them\n * typed.\n */\nexport function apiWriteCreate<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n body: unknown,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<CreateResult & TExtra> {\n return apiWrite<{ rkey?: string } & TExtra>(config, path, 'POST', {\n body,\n ...options,\n });\n}\n","import type { Profile } from '../../types/index.js';\nimport {\n encodeIdentifier,\n apiFetch,\n apiFetchOrNull,\n type ApiFetchOptions,\n type SifaApiConfig,\n} from '../client.js';\n\n/**\n * Read the aggregated profile for a handle or DID.\n *\n * Returns `null` when the AppView has no profile for the given identifier\n * (HTTP 404). Throws {@link ApiError} on other non-2xx responses.\n *\n * Server-callable (Next.js RSC) and client-callable (Expo, browser).\n */\nexport function fetchProfile(\n config: SifaApiConfig,\n handleOrDid: string,\n options: ApiFetchOptions = {},\n): Promise<Profile | null> {\n const path = `/api/profile/${encodeIdentifier(handleOrDid)}`;\n return apiFetchOrNull<Profile>(config, path, {\n retryOn429: true,\n ...options,\n });\n}\n\n/**\n * Public AT Fund link for a profile, if one is configured. Returns `null`\n * on any error or when the response payload's `url` field is missing or\n * non-string.\n */\nexport async function fetchAtFundLink(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<string | null> {\n const path = `/api/profiles/${encodeIdentifier(did)}/at-fund-link`;\n try {\n const data = await apiFetch<{ url?: unknown }>(config, path, {\n next: { revalidate: 3600 },\n timeoutMs: 5000,\n ...options,\n });\n return typeof data.url === 'string' ? data.url : null;\n } catch {\n return null;\n }\n}\n","import type { ProfileView } from '../../types/profile-view.js';\nimport {\n ApiError,\n apiFetch,\n encodeIdentifier,\n type ApiFetchOptions,\n type SifaApiConfig,\n} from '../client.js';\n\n/**\n * Read the aggregated public profile view via the `id.sifa.getProfileView`\n * XRPC query. This is the AppView-only join (positions, education, skills,\n * endorsements, and more) exposed as a standard lexicon method, distinct from\n * the internal `/api/profile/*` REST surface.\n *\n * Returns `null` when the AppView has no profile for the actor\n * (`ProfileNotFound`). Throws {@link ApiError} on other non-2xx responses.\n *\n * Server-callable (Next.js RSC) and client-callable (Expo, browser).\n */\nexport async function fetchGetProfileView(\n config: SifaApiConfig,\n actor: string,\n options: ApiFetchOptions = {},\n): Promise<ProfileView | null> {\n const path = `/xrpc/id.sifa.getProfileView?actor=${encodeIdentifier(actor)}`;\n try {\n return await apiFetch<ProfileView>(config, path, { retryOn429: true, ...options });\n } catch (e) {\n if (\n e instanceof ApiError &&\n e.status === 400 &&\n typeof e.body === 'object' &&\n e.body !== null &&\n (e.body as { error?: unknown }).error === 'ProfileNotFound'\n ) {\n return null;\n }\n throw e;\n }\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Industry/domain entry on the profile self record. */\nexport interface ProfileIndustryInput {\n industry: string;\n domain?: string;\n}\n\n/**\n * Location payload accepted by `updateProfileSelf`.\n *\n * Accepts both shapes during the community.lexicon.location.address\n * migration. Prefer `locality` (new) over `city` (legacy) when sending.\n * The API's locationSchema is a Zod union that resolves either input.\n */\nexport interface ProfileSelfLocation {\n country: string;\n countryCode?: string;\n region?: string;\n city?: string;\n locality?: string;\n}\n\n/** Body accepted by {@link updateProfileSelf}. */\nexport interface UpdateProfileSelfInput {\n headline?: string;\n about?: string;\n /** Schema.org Person.givenName from id.sifa.profile.self.givenName. */\n givenName?: string;\n /** Schema.org Person.familyName from id.sifa.profile.self.familyName. */\n familyName?: string;\n /** Free-form phonetic respelling of the name from id.sifa.profile.self.namePronunciation. */\n namePronunciation?: string;\n industries?: ProfileIndustryInput[];\n location?: ProfileSelfLocation;\n website?: string;\n openTo?: string[];\n preferredWorkplace?: string[];\n availableFromUtc?: number;\n availableToUtc?: number;\n}\n\n/** Update the authenticated user's `id.sifa.profile.self` record. */\nexport function updateProfileSelf(\n config: SifaApiConfig,\n data: UpdateProfileSelfInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/self', 'PUT', { body: data, ...options });\n}\n\n/** Body accepted by {@link updateProfileOverride}. */\nexport interface UpdateProfileOverrideInput {\n headline?: string | null;\n about?: string | null;\n displayName?: string | null;\n pronouns?: string | null;\n}\n\n/**\n * Override aggregated profile fields with sifa-specific values. `null`\n * clears the override and falls back to the upstream PDS value.\n */\nexport function updateProfileOverride(\n config: SifaApiConfig,\n data: UpdateProfileOverrideInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/override', 'PUT', { body: data, ...options });\n}\n\n/** Extended result for {@link refreshPds}. */\nexport interface RefreshPdsResult extends WriteResult {\n displayName?: string | null;\n avatar?: string | null;\n}\n\n/**\n * Re-pull the authenticated user's `app.bsky.actor.profile` from their\n * PDS. Returns the freshly resolved `displayName` and `avatar` on\n * success so the UI can update without a full profile refetch.\n */\nexport function refreshPds(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RefreshPdsResult> {\n return apiWrite<{ displayName?: string | null; avatar?: string | null }>(\n config,\n '/api/profile/refresh-pds',\n 'POST',\n options,\n );\n}\n\n/** Extended result for {@link uploadAvatar}. */\nexport interface UploadAvatarResult extends WriteResult {\n /** Publicly accessible URL of the newly uploaded avatar. */\n url?: string;\n}\n\n/**\n * Upload a new avatar via `multipart/form-data`. Pass either a `File`\n * (browser) or any `Blob` (Expo, node). The SDK leaves `Content-Type`\n * unset so the runtime can set the multipart boundary automatically.\n *\n * Never throws -- inspect `result.success` and `result.url`.\n */\nexport async function uploadAvatar(\n config: SifaApiConfig,\n file: Blob,\n options: ApiFetchOptions = {},\n): Promise<UploadAvatarResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/profile/avatar`;\n const formData = new FormData();\n formData.append('file', file);\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n credentials: options.credentials ?? 'include',\n body: formData,\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 30_000),\n headers: options.headers,\n });\n if (!res.ok) {\n const errBody = (await res.json().catch(() => ({}))) as {\n message?: string;\n pdsHost?: string;\n };\n const msg = errBody.message ?? `Request failed (${res.status})`;\n const pdsHost = errBody.pdsHost;\n return { success: false, error: msg, ...(pdsHost ? { pdsHost } : {}) };\n }\n const data = (await res.json()) as { url: string };\n return { success: true, url: data.url };\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n/** Delete the authenticated user's avatar override (revert to PDS avatar). */\nexport function deleteAvatarOverride(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/avatar', 'DELETE', options);\n}\n\n/** Extended result for {@link uploadNamePronunciationAudio}. */\nexport interface UploadPronunciationAudioResult extends WriteResult {\n /** Publicly accessible URL of the newly uploaded audio clip. */\n url?: string;\n}\n\n/**\n * Upload a name-pronunciation audio clip via `multipart/form-data`. Pass a\n * `File` (browser) or any `Blob` (Expo, node). The SDK leaves `Content-Type`\n * unset so the runtime sets the multipart boundary automatically.\n *\n * Never throws -- inspect `result.success` and `result.url`.\n */\nexport async function uploadNamePronunciationAudio(\n config: SifaApiConfig,\n file: Blob,\n options: ApiFetchOptions = {},\n): Promise<UploadPronunciationAudioResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/profile/pronunciation-audio`;\n const formData = new FormData();\n formData.append('file', file);\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n credentials: options.credentials ?? 'include',\n body: formData,\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 30_000),\n headers: options.headers,\n });\n if (!res.ok) {\n const errBody = (await res.json().catch(() => ({}))) as {\n message?: string;\n pdsHost?: string;\n };\n const msg = errBody.message ?? `Request failed (${res.status})`;\n const pdsHost = errBody.pdsHost;\n return { success: false, error: msg, ...(pdsHost ? { pdsHost } : {}) };\n }\n const data = (await res.json()) as { url: string };\n return { success: true, url: data.url };\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n/** Delete the name-pronunciation audio clip from the user's profile. */\nexport function deleteNamePronunciationAudio(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/pronunciation-audio', 'DELETE', options);\n}\n","import type { ProfilePosition, SkillRef } from '../../types/index.js';\nimport {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\nexport type { CreateResult, WriteResult } from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.position` record on the authenticated\n * user's PDS. The AppView signs and writes via the user's OAuth session.\n *\n * `data` should be a lexicon-shaped position record (without `createdAt`\n * or `rkey`; the AppView fills both). Validate with\n * `ProfilePositionRecordSchema.omit({ createdAt: true })` before calling\n * if you want client-side guarantees.\n *\n * Never throws -- inspect `result.success` and use `result.error` /\n * `result.pdsHost` for UI messaging.\n */\nexport function createPosition(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/position', data, options);\n}\n\n/** Update an existing position by `rkey`. */\nexport function updatePosition(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/position/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete a position by `rkey`. */\nexport function deletePosition(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/position/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n\n/** Mark a position as the user's primary (current) role. */\nexport function setPositionPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/position/${encodeURIComponent(rkey)}/primary`,\n 'PUT',\n options,\n );\n}\n\n/** Clear the \"primary\" flag on a position. */\nexport function unsetPositionPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/position/${encodeURIComponent(rkey)}/primary`,\n 'DELETE',\n options,\n );\n}\n\n/**\n * Build the PUT-body for a position update. Strips `null` `location`\n * (so JSON.stringify drops it) and includes the provided `skills` list.\n */\nfunction buildPositionPayload(\n position: ProfilePosition,\n skills: SkillRef[],\n): Record<string, unknown> {\n return {\n company: position.company,\n title: position.title,\n description: position.description,\n startedAt: position.startedAt,\n endedAt: position.endedAt,\n location: position.location ?? undefined,\n // Carry the form-controlled optional fields the AppView merge would\n // otherwise clear when absent from the PUT body. Omitting them here made\n // every link/unlink strip employmentType, workplaceType, and entityRef\n // off the position (id.sifa.profile.position#skills round-trip).\n employmentType: position.employmentType,\n workplaceType: position.workplaceType,\n entityRef: position.entityRef,\n skills,\n };\n}\n\n/**\n * Add a skill link to a position. Idempotent: if the skill is already\n * linked, resolves to `{ success: true }` without a network call.\n *\n * Implementation note: the AppView only exposes whole-record PUTs, so\n * this helper rebuilds the position body with the new skills list.\n */\nexport function linkSkillToPosition(\n config: SifaApiConfig,\n position: ProfilePosition,\n skillRef: SkillRef,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const currentSkills = position.skills ?? [];\n if (currentSkills.some((s) => s.uri === skillRef.uri)) {\n return Promise.resolve({ success: true });\n }\n return updatePosition(\n config,\n position.rkey,\n buildPositionPayload(position, [...currentSkills, skillRef]),\n options,\n );\n}\n\n/** Remove a skill link from a position. */\nexport function unlinkSkillFromPosition(\n config: SifaApiConfig,\n position: ProfilePosition,\n skillRef: SkillRef,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const remaining = (position.skills ?? []).filter((s) => s.uri !== skillRef.uri);\n return updatePosition(config, position.rkey, buildPositionPayload(position, remaining), options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.education` record on the authenticated\n * user's PDS.\n */\nexport function createEducation(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/education', data, options);\n}\n\n/** Update an existing education record by `rkey`. */\nexport function updateEducation(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/education/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete an education record by `rkey`. */\nexport function deleteEducation(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/education/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Create a new `id.sifa.profile.skill` record on the authenticated\n * user's PDS.\n */\nexport function createSkill(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/skill', data, options);\n}\n\n/** Update an existing skill record by `rkey`. */\nexport function updateSkill(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/skill/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Outcome of a bulk sub-category assign. */\nexport interface SubCategoryBulkResult {\n /** Records written. */\n updated: number;\n /** Records that already carried the label, so no write was needed. */\n unchanged: number;\n /** Requested rkeys with no matching record on the PDS. */\n skipped: string[];\n}\n\n/**\n * Set (or clear) the sub-category on many skills in one request.\n *\n * A single call replaces one PUT per skill, which tripped the AppView's\n * per-IP rate limit on any sizeable profile (#324). An empty `subCategory`\n * clears the field.\n */\nexport function updateSkillSubCategories(\n config: SifaApiConfig,\n rkeys: string[],\n subCategory: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult & SubCategoryBulkResult> {\n return apiWrite<SubCategoryBulkResult>(config, '/api/profile/skills/subcategory', 'POST', {\n body: { rkeys, subCategory },\n ...options,\n });\n}\n\n/** Delete a skill record by `rkey`. */\nexport function deleteSkill(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/skill/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Generic record-create escape hatch. Most callers should prefer the\n * dedicated section helpers (`createPosition`, `createEducation`, etc.)\n * which take typed payloads and ship matching hooks. Use this when the\n * lexicon doesn't yet have a dedicated endpoint (certifications,\n * projects, publications, volunteering, honors, languages, courses).\n *\n * `collection` is a `id.sifa.profile.*` collection NSID. Routes to\n * `POST /api/profile/records/<collection>`.\n */\nexport function createRecord(\n config: SifaApiConfig,\n collection: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(\n config,\n `/api/profile/records/${encodeURIComponent(collection)}`,\n data,\n options,\n );\n}\n\n/** Generic record-update escape hatch. See {@link createRecord}. */\nexport function updateRecord(\n config: SifaApiConfig,\n collection: string,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const path = `/api/profile/records/${encodeURIComponent(collection)}/${encodeURIComponent(rkey)}`;\n return apiWrite(config, path, 'PUT', { body: data, ...options });\n}\n\n/** Generic record-delete escape hatch. See {@link createRecord}. */\nexport function deleteRecord(\n config: SifaApiConfig,\n collection: string,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n const path = `/api/profile/records/${encodeURIComponent(collection)}/${encodeURIComponent(rkey)}`;\n return apiWrite(config, path, 'DELETE', options);\n}\n","import {\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Address payload accepted by `/api/profile/location` endpoints.\n *\n * Accepts both shapes during the community.lexicon.location.address\n * migration. Prefer `country` + `locality` (new) over `countryCode` +\n * `city` (legacy). The API's `locationSchema` is a Zod union that\n * accepts either pair.\n */\nexport interface ProfileLocationAddress {\n /** Legacy alias for `country` (alpha-2). */\n countryCode?: string;\n /** community.lexicon.location.address field -- prefer over `countryCode`. */\n country?: string;\n region?: string;\n /** Legacy alias for `locality`. */\n city?: string;\n /** community.lexicon.location.address field -- prefer over `city`. */\n locality?: string;\n}\n\n/** Body accepted by {@link createProfileLocation} / {@link updateProfileLocation}. */\nexport interface ProfileLocationInput {\n address: ProfileLocationAddress;\n type: string;\n label?: string;\n isPrimary?: boolean;\n}\n\n/** Create a new profile location entry. */\nexport function createProfileLocation(\n config: SifaApiConfig,\n data: ProfileLocationInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/profile/location', data, options);\n}\n\n/** Update an existing profile location by `rkey`. */\nexport function updateProfileLocation(\n config: SifaApiConfig,\n rkey: string,\n data: ProfileLocationInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/location/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete a profile location by `rkey`. */\nexport function deleteProfileLocation(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/location/${encodeURIComponent(rkey)}`, 'DELETE', options);\n}\n","import type { ExternalAccount } from '../../types/index.js';\nimport {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Body accepted by {@link createExternalAccount} / {@link updateExternalAccount}. */\nexport interface ExternalAccountInput {\n platform: string;\n url: string;\n label?: string;\n feedUrl?: string;\n}\n\n/** Extended create result for {@link createExternalAccount}. */\nexport interface CreateExternalAccountResult extends WriteResult {\n rkey?: string;\n feedUrl?: string | null;\n}\n\n/** Extended write result for {@link verifyExternalAccount}. */\nexport interface VerifyExternalAccountResult extends WriteResult {\n verified?: boolean;\n verifiedVia?: string;\n}\n\n/** List external accounts attached to a profile. Returns `[]` on error. */\nexport async function fetchExternalAccounts(\n config: SifaApiConfig,\n handleOrDid: string,\n options: ApiFetchOptions = {},\n): Promise<ExternalAccount[]> {\n const path = `/api/profile/${encodeIdentifier(handleOrDid)}/external-accounts`;\n try {\n const data = await apiFetch<{ accounts?: ExternalAccount[] }>(config, path, {\n credentials: 'include',\n ...options,\n });\n return data.accounts ?? [];\n } catch {\n return [];\n }\n}\n\n/**\n * Create a new external account record. Returns the newly-created `rkey`\n * and the server-resolved `feedUrl` (sifa-api inspects the target for\n * RSS feeds on platforms that publish them).\n */\nexport function createExternalAccount(\n config: SifaApiConfig,\n data: ExternalAccountInput,\n options: ApiFetchOptions = {},\n): Promise<CreateExternalAccountResult> {\n return apiWrite<{ rkey?: string; feedUrl?: string | null }>(\n config,\n '/api/profile/external-accounts',\n 'POST',\n { body: data, ...options },\n );\n}\n\n/** Update an existing external account by `rkey`. */\nexport function updateExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n data: ExternalAccountInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/external-accounts/${encodeURIComponent(rkey)}`, 'PUT', {\n body: data,\n ...options,\n });\n}\n\n/** Delete an external account by `rkey`. */\nexport function deleteExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}`,\n 'DELETE',\n options,\n );\n}\n\n/** Mark an external account as the user's primary. */\nexport function setExternalAccountPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/primary`,\n 'PUT',\n options,\n );\n}\n\n/** Clear the \"primary\" flag on an external account. */\nexport function unsetExternalAccountPrimary(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/primary`,\n 'DELETE',\n options,\n );\n}\n\n/**\n * Run server-side verification on an external account (e.g. inspect\n * the target for a keytrace claim). Returns `{ verified, verifiedVia }`\n * on success.\n */\nexport function verifyExternalAccount(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<VerifyExternalAccountResult> {\n return apiWrite<{ verified?: boolean; verifiedVia?: string }>(\n config,\n `/api/profile/external-accounts/${encodeURIComponent(rkey)}/verify`,\n 'POST',\n { body: {}, ...options },\n );\n}\n","import {\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n} from '../client.js';\n\n/** Body accepted by {@link createEndorsement}. */\nexport interface EndorsementInput {\n /** DID of the person being endorsed. */\n subjectDid: string;\n /**\n * AT-URI of the subject's `id.sifa.profile.skill` record. Omit to propose a\n * skill they have not listed; `skillName` then names what is proposed, and\n * the record is created when they accept.\n */\n skillUri?: string;\n /**\n * CID of that skill record, pinning the endorsement to the version endorsed.\n * Optional: the AppView resolves it when omitted, which is the common case\n * since only the firehose carries a CID. Never substitute another record's.\n */\n skillCid?: string;\n /**\n * Snapshot of the skill's name at endorsement time. Acts as the validity\n * anchor: if the subject later renames the skill, the mismatch is detectable.\n */\n skillName: string;\n comment?: string;\n}\n\n/** Body accepted by {@link confirmEndorsement}. */\nexport interface ConfirmEndorsementResult {\n /** Skill the endorsement resolved to, created if it was a proposal. */\n skillUri?: string;\n /** True when accepting added a new skill to the profile. */\n skillCreated?: boolean;\n}\n\nexport interface ConfirmEndorsementInput {\n endorsementUri: string;\n /**\n * Optional. When omitted the AppView resolves the CID itself, reading the\n * record from the endorser's PDS if it has none stored. Callers working from\n * the pending inbox should pass `cid` through when it is there and leave it\n * out when it is not, rather than substituting another record's CID.\n */\n endorsementCid?: string;\n}\n\n/**\n * Create an endorsement of another user's skill. The endorsed user\n * must confirm before the endorsement appears on their profile (the\n * endorsement record is on the endorser's PDS; a separate confirmation\n * record on the endorsed user's PDS gates display).\n */\nexport function createEndorsement(\n config: SifaApiConfig,\n data: EndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/endorsement', data, options);\n}\n\n/**\n * Confirm a received endorsement, writing a confirmation record to the\n * signed-in user's PDS. This is what makes the endorsement public: until the\n * confirmation exists, the endorsement is indexed but displays nowhere.\n */\nexport function confirmEndorsement(\n config: SifaApiConfig,\n data: ConfirmEndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult & ConfirmEndorsementResult> {\n return apiWriteCreate<ConfirmEndorsementResult>(\n config,\n '/api/endorsement/confirm',\n data,\n options,\n );\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface ReceivedEndorsement {\n endorserDid: string;\n /** Absent when the endorser has no Sifa profile yet. */\n endorserHandle?: string;\n endorserDisplayName?: string;\n endorserAvatar?: string;\n skillUri?: string;\n skillCid?: string;\n skillName: string;\n comment?: string;\n createdAt: string;\n}\n\nexport interface ReceivedEndorsementsPage {\n endorsements: ReceivedEndorsement[];\n cursor?: string;\n}\n\n/**\n * Confirmed endorsements a DID has received, newest first.\n *\n * Only confirmed ones exist here: the AppView inner-joins against the\n * confirmation records, so an endorsement the subject has not accepted is\n * absent rather than pending. Public -- no credentials needed.\n *\n * Returns an empty page on failure so a surface that merely decorates a page\n * cannot break it.\n */\nexport async function fetchReceivedEndorsements(\n config: SifaApiConfig,\n did: string,\n options: { limit?: number } & ApiFetchOptions = {},\n): Promise<ReceivedEndorsementsPage> {\n const { limit, ...fetchOptions } = options;\n const qs = limit ? `?limit=${limit}` : '';\n try {\n const data = await apiFetch<ReceivedEndorsementsPage>(\n config,\n `/api/endorsement/${encodeIdentifier(did)}${qs}`,\n { cache: 'no-store', timeoutMs: 5000, ...fetchOptions },\n );\n return { endorsements: data?.endorsements ?? [], cursor: data?.cursor };\n } catch {\n return { endorsements: [] };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface ReciprocitySkill {\n name: string;\n uri: string;\n /** Absent until the firehose indexes the skill; the AppView resolves it. */\n cid?: string;\n}\n\nexport interface ReciprocityCandidate {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n skills: ReciprocitySkill[];\n}\n\n/**\n * Someone the signed-in user follows on Sifa whose skills they could endorse.\n *\n * The AppView picks: it filters people already dismissed and anyone blocked,\n * requires at least one skill, and rotates the choice every twelve hours so\n * the same person is not offered indefinitely.\n *\n * `null` means there is nobody left to suggest -- a real state, not an error.\n * Failures also yield `null` so a broken suggestion never breaks the homepage.\n */\nexport async function fetchReciprocityCandidate(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<ReciprocityCandidate | null> {\n try {\n const data = await apiFetch<{ candidate: ReciprocityCandidate | null }>(\n config,\n '/api/endorsements/reciprocity-candidate',\n {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...options,\n },\n );\n return data?.candidate ?? null;\n } catch {\n return null;\n }\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** A received endorsement the subject has neither confirmed nor dismissed. */\nexport interface PendingEndorsement {\n endorserDid: string;\n /**\n * Endorser's handle, when the AppView has resolved one. Absent when the\n * endorser has no Sifa profile yet -- an endorsement can come from any AT\n * Protocol app -- so the UI needs a fallback for having no name to show.\n */\n endorserHandle?: string;\n rkey: string;\n /**\n * AT-URI of the endorsement record. The confirm mutation needs a strongRef,\n * so the AppView hands this back rather than making callers rebuild it.\n */\n uri: string;\n /**\n * CID of the endorsement record, when the AppView has it. Often absent:\n * an endorsement written by another AT Protocol app can be indexed without\n * its CID ever reaching us. Pass it through to confirm when present; the\n * AppView resolves it from the endorser's PDS when it is not.\n */\n cid?: string;\n /** Absent when this endorsement proposes a skill the subject does not have. */\n skillUri?: string;\n skillCid?: string;\n /**\n * True when accepting this will add `skillName` to the profile as well as\n * publishing the endorsement. The UI must say so: it is a bigger action than\n * confirming an endorsement of a skill already listed.\n */\n proposesNewSkill?: boolean;\n skillName: string;\n comment?: string;\n createdAt: string;\n}\n\nexport interface PendingEndorsementsPage {\n endorsements: PendingEndorsement[];\n cursor?: string;\n}\n\n/** Body accepted by {@link dismissEndorsement}. */\nexport interface DismissEndorsementInput {\n endorserDid: string;\n rkey: string;\n}\n\n/** Options for {@link fetchPendingEndorsements}, adding RSC cookie forwarding. */\nexport interface FetchPendingEndorsementsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Endorsements awaiting the signed-in user's decision. Requires credentials --\n * the AppView reads the subject DID from the session, not from a parameter, so\n * there is no way to read someone else's inbox.\n *\n * Returns an empty page on failure so a broken inbox degrades to \"nothing\n * pending\" rather than breaking the surface hosting it.\n */\nexport async function fetchPendingEndorsements(\n config: SifaApiConfig,\n options: FetchPendingEndorsementsOptions = {},\n): Promise<PendingEndorsementsPage> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<PendingEndorsementsPage>(config, '/api/endorsements/pending', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { endorsements: data?.endorsements ?? [], cursor: data?.cursor };\n } catch {\n return { endorsements: [] };\n }\n}\n\n/**\n * Take a received endorsement out of the inbox.\n *\n * This writes nothing to any PDS. An endorsement only displays once the subject\n * has confirmed it, so declining is already the default state -- the dismissal\n * is a local flag that stops it reappearing, not a published rejection.\n */\nexport function dismissEndorsement(\n config: SifaApiConfig,\n data: DismissEndorsementInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/endorsement/dismiss', 'POST', { body: data, ...options });\n}\n","import {\n apiFetch,\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** A claim naming the signed-in user that they have neither confirmed nor dismissed. */\nexport interface PendingConfirmation {\n /** DID of the person who wrote the claim. */\n claimerDid: string;\n /**\n * Claimer's handle, when the AppView has resolved one. Absent when they have\n * no Sifa profile: a claim can be written by any AT Protocol app, so the UI\n * needs a fallback for having no name to show.\n */\n claimerHandle?: string;\n claimerDisplayName?: string;\n claimerAvatar?: string;\n /** AT-URI of the record that names you. The confirm mutation needs a strongRef. */\n subjectUri: string;\n /**\n * CID of that record, when the AppView has it. Often absent, since a record\n * indexed from another app can arrive without one. Pass it through when\n * present; the AppView resolves it from the claimer's PDS when it is not.\n * Never substitute a different record's CID.\n */\n subjectCid?: string;\n relation: string;\n /** Name or title the subject record carries right now, for display and snapshotting. */\n subjectName: string;\n /** Role the claimer assigned you, for `projectMember`. Display only. */\n role?: string;\n title?: string;\n createdAt: string;\n}\n\nexport interface PendingConfirmationsPage {\n confirmations: PendingConfirmation[];\n cursor?: string;\n}\n\n/** A confirmation the signed-in user has already given. */\nexport interface GivenConfirmation {\n subjectUri: string;\n claimerDid: string;\n claimerHandle?: string;\n relation: string;\n /** The name as it stood when confirmed, so a rename shows as a difference. */\n subjectName: string;\n /** The name the record carries now. Absent when the claim no longer exists. */\n currentName?: string;\n /** The record changed materially after it was confirmed. */\n confirmedStale: boolean;\n /** They removed you from the record, or deleted it. Nothing left to withdraw. */\n claimWithdrawn: boolean;\n createdAt: string;\n}\n\n/** Body accepted by {@link createConfirmation}. */\nexport interface ConfirmationInput {\n subjectUri: string;\n subjectCid?: string;\n relation: string;\n /**\n * Snapshot of the subject's name at confirmation time. Stored in your own\n * repo, out of the claimer's reach, so a later rename is detectable.\n */\n subjectName?: string;\n}\n\n/** Body accepted by {@link dismissConfirmation} and {@link revokeConfirmation}. */\nexport interface ConfirmationSubjectInput {\n subjectUri: string;\n}\n\n/** Options for the read fetchers, adding the RSC cookie-forwarding escape hatch. */\nexport interface FetchConfirmationsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Claims awaiting the signed-in user's decision. Requires credentials -- the\n * AppView reads the subject DID from the session, not from a parameter, so\n * there is no way to read someone else's inbox.\n *\n * Returns an empty page on failure so a broken inbox degrades to \"nothing\n * pending\" rather than breaking the surface hosting it.\n */\nexport async function fetchPendingConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<PendingConfirmationsPage> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<PendingConfirmationsPage>(config, '/api/confirmations/pending', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { confirmations: data?.confirmations ?? [], cursor: data?.cursor };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Confirmations the signed-in user has already given.\n *\n * The surface for changing your mind. Without it a confirmation is one-way in\n * practice: the inbox lists only claims you have not answered, so once answered\n * there is nowhere to see it, let alone withdraw it.\n *\n * Returns an empty list on failure, matching the pending inbox: a broken list\n * should not break the page hosting it.\n */\nexport async function fetchGivenConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<{ confirmations: GivenConfirmation[] }> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<{ confirmations: GivenConfirmation[] }>(\n config,\n '/api/confirmations/mine',\n { cache: 'no-store', credentials: 'include', timeoutMs: 5000, ...rest, headers },\n );\n return { confirmations: data?.confirmations ?? [] };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Affirm that a record naming you is accurate, writing an `id.sifa.confirmation`\n * to your own PDS. Until this exists the claim renders as a bare handle with no\n * display name, avatar, or link back to you.\n *\n * Confirming does not put the claimer's record on your profile. That record\n * lives in their repository and they can rename it at will; keeping your own\n * entry is a separate, deliberate step.\n */\nexport function createConfirmation(\n config: SifaApiConfig,\n data: ConfirmationInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/confirmation', data, options);\n}\n\n/**\n * Take a claim out of the inbox without confirming it.\n *\n * This writes nothing to any PDS. A claim only gains your identity once you\n * have confirmed it, so declining is already the default state -- the dismissal\n * is a local flag that stops it reappearing, not a published rejection the\n * claimer can read.\n */\nexport function dismissConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/dismiss', 'POST', { body: data, ...options });\n}\n\n/**\n * Withdraw a confirmation you previously gave, deleting the record from your\n * PDS. The claim reverts to rendering as a bare handle.\n *\n * The usual reason is drift: the claimer renamed the project or changed the\n * role after you confirmed, so what you affirmed is no longer what is shown.\n * Also writes a dismissal, or the still-live claim returns to your inbox.\n */\nexport function revokeConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/revoke', 'POST', { body: data, ...options });\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Counts that drive the unified Inbox badge on the header bell.\n *\n * Both numbers are computed server-side and are DISJOINT, so summing them never\n * double-counts a single event:\n *\n * - `tasks` — open items that need the signed-in user's decision or attention.\n * As of this release it counts: pending confirmations, pending endorsement\n * requests, confirmation drift/withdrawn, positions with an unlinked company,\n * and (as 1) an incomplete profile. This set is defined by the AppView and MAY\n * GROW in future without an SDK release, so treat `tasks` as \"how many things\n * need attention\", not as a fixed sum of specific sources.\n * - `unreadNotifications` — unread passive notifications, EXCLUDING the actionable\n * types already counted in `tasks` (e.g. `confirmation_requested`,\n * `endorsement_received`). Computed as the residual of total unread minus\n * task-owned types, so a new/unknown actionable type still surfaces somewhere\n * rather than vanishing.\n */\nexport interface InboxCounts {\n tasks: number;\n unreadNotifications: number;\n}\n\nexport interface FetchInboxCountsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Combined inbox counts for the signed-in user, for the header bell badge.\n *\n * Requires credentials -- the AppView reads the subject from the session, not a\n * parameter. Returns `{ tasks: 0, unreadNotifications: 0 }` on ANY failure,\n * including the unauthenticated case, so the badge degrades to \"nothing waiting\"\n * rather than breaking the header. As a consequence the hook never surfaces an\n * error (`isError` stays false); a persistently-down endpoint is indistinguishable\n * from a genuine zero. That trade-off is deliberate for a poll-driven badge.\n */\n/** Coerce a server-supplied count to a safe non-negative integer. */\nfunction toCount(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;\n}\n\nexport async function fetchInboxCounts(\n config: SifaApiConfig,\n options: FetchInboxCountsOptions = {},\n): Promise<InboxCounts> {\n // Destructure cookieHeader out before spreading so the raw Cookie header (a\n // session token) never lands as a top-level property on the fetch init.\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n try {\n const data = await apiFetch<InboxCounts>(config, '/api/inbox/counts', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return {\n tasks: toCount(data?.tasks),\n unreadNotifications: toCount(data?.unreadNotifications),\n };\n } catch {\n return { tasks: 0, unreadNotifications: 0 };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * A position on the signed-in user's own profile whose free-text company is not\n * yet linked to a canonical company entity. Linking it makes the position roll\n * up under the company's `/c/` page and appear on the company roster.\n */\nexport interface UnlinkedPosition {\n /** rkey of the `id.sifa.profile.position` record, for deep-linking to the editor. */\n rkey: string;\n /** AT-URI of the position record. */\n uri: string;\n /** The free-text company label the user entered. */\n company: string;\n /** The position title, for display. Absent when the record has none. */\n title?: string;\n}\n\nexport interface UnlinkedPositionsResult {\n positions: UnlinkedPosition[];\n}\n\nexport interface FetchUnlinkedPositionsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Positions on the signed-in user's profile with an unlinked company, an \"open\n * task\" surfaced in the unified Inbox. Requires credentials -- the AppView reads\n * the owner from the session. Returns an empty list on any failure so a broken\n * list degrades to \"nothing to link\" rather than breaking the hosting surface.\n */\nexport async function fetchUnlinkedPositions(\n config: SifaApiConfig,\n options: FetchUnlinkedPositionsOptions = {},\n): Promise<UnlinkedPositionsResult> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n try {\n const data = await apiFetch<UnlinkedPositionsResult>(config, '/api/positions/unlinked', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { positions: Array.isArray(data?.positions) ? data.positions : [] };\n } catch {\n return { positions: [] };\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * The binary profile-completeness signals the AppView tracks. Each maps to a\n * concrete \"add this to your profile\" step in the unified Inbox checklist.\n */\nexport const PROFILE_COMPLETENESS_SIGNALS = [\n 'headline',\n 'about',\n 'position',\n 'education',\n 'skill',\n 'certification',\n] as const;\n\nexport type ProfileCompletenessSignal = (typeof PROFILE_COMPLETENESS_SIGNALS)[number];\n\n/**\n * Completeness of the signed-in user's own profile: which of the tracked signals\n * are still missing. `missing.length === 0` means complete.\n */\nexport interface ProfileCompleteness {\n /** True when no tracked signal is missing. */\n complete: boolean;\n /** Signals present (of {@link PROFILE_COMPLETENESS_SIGNALS}). */\n score: number;\n /** Total tracked signals. */\n total: number;\n /** The signals still missing, for the checklist. */\n missing: ProfileCompletenessSignal[];\n}\n\nexport interface FetchProfileCompletenessOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Completeness of the signed-in user's own profile, an \"open task\" surfaced in\n * the unified Inbox as a checklist. Requires credentials -- the AppView reads\n * the owner from the session. Returns a complete-looking result on any failure\n * (no missing signals) so a broken call degrades to \"nothing to do\" rather than\n * nagging the user with a phantom checklist.\n */\nexport async function fetchProfileCompleteness(\n config: SifaApiConfig,\n options: FetchProfileCompletenessOptions = {},\n): Promise<ProfileCompleteness> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n const empty: ProfileCompleteness = {\n complete: true,\n score: PROFILE_COMPLETENESS_SIGNALS.length,\n total: PROFILE_COMPLETENESS_SIGNALS.length,\n missing: [],\n };\n\n try {\n const data = await apiFetch<ProfileCompleteness>(config, '/api/profile/completeness', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n if (!data) return empty;\n const missing = Array.isArray(data.missing) ? data.missing : [];\n return {\n complete: data.complete ?? missing.length === 0,\n score: data.score ?? PROFILE_COMPLETENESS_SIGNALS.length - missing.length,\n total: data.total ?? PROFILE_COMPLETENESS_SIGNALS.length,\n missing,\n };\n } catch {\n return empty;\n }\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/**\n * Hide a keytrace claim (verified-account claim discovered on the\n * user's external accounts) from the user's profile. The claim itself\n * stays in the index; only its display is suppressed.\n */\nexport function hideKeytraceClaim(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/keytrace-claims/${encodeURIComponent(rkey)}/hide`,\n 'POST',\n options,\n );\n}\n\n/** Restore a previously-hidden keytrace claim. */\nexport function unhideKeytraceClaim(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/keytrace-claims/${encodeURIComponent(rkey)}/hide`,\n 'DELETE',\n options,\n );\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/**\n * Make a Marque-registered domain public in the owner's Links section. Marque\n * domains are owner-only by default; this reveals one. `domain` is the\n * at.marque.domain rkey (the domain name itself).\n */\nexport function revealMarqueDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/marque-domains/${encodeURIComponent(domain)}/reveal`,\n 'POST',\n options,\n );\n}\n\n/** Make a previously-revealed Marque domain owner-only again. */\nexport function unrevealMarqueDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/marque-domains/${encodeURIComponent(domain)}/reveal`,\n 'DELETE',\n options,\n );\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Extended result for {@link refreshOrcidPublications}. */\nexport interface RefreshOrcidPublicationsResult extends WriteResult {\n added?: number;\n removed?: number;\n}\n\n/**\n * Hide an ORCID-imported publication from the user's profile. The\n * `putCode` is the ORCID-side identifier; the underlying record stays\n * in the index, only its display is suppressed.\n */\nexport function hideOrcidPublication(\n config: SifaApiConfig,\n putCode: number,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/orcid-publications/${putCode}/hide`, 'POST', options);\n}\n\n/** Restore a previously-hidden ORCID publication. */\nexport function unhideOrcidPublication(\n config: SifaApiConfig,\n putCode: number,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/orcid-publications/${putCode}/hide`, 'DELETE', options);\n}\n\n/** Hide a standard (auto-imported) publication by its AT URI. */\nexport function hideStandardPublication(\n config: SifaApiConfig,\n uri: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/standard-publications/${encodeURIComponent(uri)}/hide`,\n 'POST',\n options,\n );\n}\n\n/** Restore a previously-hidden standard publication. */\nexport function unhideStandardPublication(\n config: SifaApiConfig,\n uri: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/profile/standard-publications/${encodeURIComponent(uri)}/hide`,\n 'DELETE',\n options,\n );\n}\n\n/** Bulk-hide standard publications by AT URI list. */\nexport function bulkHideStandardPublications(\n config: SifaApiConfig,\n uris: string[],\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/standard-publications/bulk-hide', 'POST', {\n body: { uris },\n ...options,\n });\n}\n\n/** Bulk-unhide standard publications by AT URI list. */\nexport function bulkUnhideStandardPublications(\n config: SifaApiConfig,\n uris: string[],\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/standard-publications/bulk-hide', 'DELETE', {\n body: { uris },\n ...options,\n });\n}\n\n/** Hide an `id.sifa.profile.publication` (user-authored publication record). */\nexport function hideSifaPublication(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/publications/${rkey}/hide`, 'POST', options);\n}\n\n/** Restore a previously-hidden Sifa publication. */\nexport function unhideSifaPublication(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/profile/publications/${rkey}/hide`, 'DELETE', options);\n}\n\n/**\n * Re-pull the authenticated user's ORCID publications. Returns counts\n * of added and removed records. The server returns `{ error: '...' }`\n * inline (not via HTTP status) on quota / linkage failures; the SDK\n * folds that into `{ success: false, error }` to keep the contract\n * consistent with other mutations.\n */\nexport async function refreshOrcidPublications(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RefreshOrcidPublicationsResult> {\n const result = await apiWrite<{ added?: number; removed?: number; error?: string }>(\n config,\n '/api/profile/orcid-publications/refresh',\n 'POST',\n { body: {}, ...options },\n );\n if (result.success && result.error) {\n return { success: false, error: result.error };\n }\n return result;\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\n\n/** Item types that can be hidden on the authenticated user's profile. */\nexport const HIDDEN_ITEM_TYPES = [\n 'position',\n 'education',\n 'certification',\n 'project',\n 'volunteering',\n 'publication',\n 'course',\n 'honor',\n 'language',\n 'externalAccount',\n] as const;\nexport type HiddenItemType = (typeof HIDDEN_ITEM_TYPES)[number];\n\n/** Source from which an item originates; disambiguates `item_id`. */\nexport const HIDDEN_ITEM_SOURCES = ['pds', 'standard', 'orcid'] as const;\nexport type HiddenItemSource = (typeof HIDDEN_ITEM_SOURCES)[number];\n\nexport interface HideProfileItemInput {\n itemType: HiddenItemType;\n source: HiddenItemSource;\n /** rkey for `pds`, AT-URI for `standard`, ORCID putCode as text for `orcid`. */\n itemId: string;\n}\n\nexport interface BulkHideProfileItemInput {\n itemType: HiddenItemType;\n source: HiddenItemSource;\n itemIds: string[];\n}\n\n/**\n * Hide one profile item. The underlying record stays on the user's PDS;\n * only its display on sifa.id is suppressed.\n */\nexport function hideProfileItem(\n config: SifaApiConfig,\n input: HideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/hide', 'POST', { ...options, body: input });\n}\n\n/** Restore a previously-hidden profile item. */\nexport function unhideProfileItem(\n config: SifaApiConfig,\n input: HideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/hide', 'DELETE', { ...options, body: input });\n}\n\n/** Bulk-hide profile items sharing the same `itemType` + `source`. */\nexport function bulkHideProfileItems(\n config: SifaApiConfig,\n input: BulkHideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/bulk-hide', 'POST', { ...options, body: input });\n}\n\n/** Bulk-unhide profile items sharing the same `itemType` + `source`. */\nexport function bulkUnhideProfileItems(\n config: SifaApiConfig,\n input: BulkHideProfileItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/profile/items/bulk-hide', 'DELETE', { ...options, body: input });\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\nexport interface HideActivityItemInput {\n /** AT-URI of the record, or the item URL for externally-sourced items. */\n uri: string;\n /** Collection NSID (or synthetic collection, e.g. `fediverse.post`). */\n collection: string;\n /**\n * Registry app id the item belongs to. Optional, and used only to take the\n * item out of the owner's OG-image activity spine, which is computed from\n * per-(day, app) counts and never sees a URI.\n */\n appId?: string;\n /** UTC day the item was created (`YYYY-MM-DD`), for the same reason. */\n activityDate?: string;\n}\n\nexport interface UnhideActivityItemInput {\n uri: string;\n}\n\n/** One activity item the authenticated user has hidden from their profile. */\nexport interface HiddenActivityItem {\n uri: string;\n collection: string;\n appId: string | null;\n activityDate: string | null;\n hiddenAt: string;\n}\n\nexport interface FetchHiddenActivityItemsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Hide one activity item from the authenticated user's profile. The record\n * stays on their PDS and stays readable by every other app; only its\n * appearance on sifa.id is suppressed.\n */\nexport function hideActivityItem(\n config: SifaApiConfig,\n input: HideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'POST', { ...options, body: input });\n}\n\n/** Restore a previously-hidden activity item. */\nexport function unhideActivityItem(\n config: SifaApiConfig,\n input: UnhideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'DELETE', { ...options, body: input });\n}\n\n/**\n * Everything the authenticated user has hidden, newest hide first. Returns\n * `[]` on any error so a settings page can still render.\n */\nexport async function fetchHiddenActivityItems(\n config: SifaApiConfig,\n options: FetchHiddenActivityItemsOptions = {},\n): Promise<HiddenActivityItem[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ items: HiddenActivityItem[] }>(\n config,\n '/api/activity/hidden-items',\n { credentials: 'include', ...options, headers },\n );\n return data.items;\n } catch {\n return [];\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Public, aggregate stats shown on the homepage and similar surfaces. */\nexport interface StatsResponse {\n profileCount: number;\n avatars: string[];\n atproto: {\n userCount: number;\n growthPerSecond: number;\n timestamp: number;\n } | null;\n}\n\n/**\n * Homepage stats (profile count, avatar samples, ATproto growth). Public\n * endpoint -- safe to cache. Returns `null` on any error so callers can\n * render a graceful empty state.\n */\nexport async function fetchStats(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<StatsResponse | null> {\n try {\n return await apiFetch<StatsResponse>(config, '/api/stats', {\n next: { revalidate: 900 },\n ...options,\n });\n } catch {\n return null;\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Catalog entry describing an ATproto app that Sifa surfaces activity for. */\nexport interface AppRegistryEntry {\n id: string;\n name: string;\n category: string;\n collectionPrefixes: string[];\n scanCollections: string[];\n urlPattern?: string;\n color: string;\n}\n\n/** Compact app representation returned by the hidden-apps endpoint. */\nexport interface HiddenApp {\n id: string;\n name: string;\n category: string;\n}\n\nexport interface FetchHiddenAppsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Public app registry shown across discovery surfaces. Heavily cached.\n * Returns `[]` on any error.\n */\nexport async function fetchAppsRegistry(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<AppRegistryEntry[]> {\n try {\n return await apiFetch<AppRegistryEntry[]>(config, '/api/apps/registry', {\n next: { revalidate: 86400 },\n ...options,\n });\n } catch {\n return [];\n }\n}\n\n/**\n * Apps the authenticated user has chosen to hide from their activity feed.\n * Requires an authenticated session. Returns `[]` on any error (including\n * the unauthenticated case).\n */\nexport async function fetchHiddenApps(\n config: SifaApiConfig,\n options: FetchHiddenAppsOptions = {},\n): Promise<HiddenApp[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ apps: HiddenApp[] }>(config, '/api/profile/hidden-apps', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.apps;\n } catch {\n return [];\n }\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** One account attached to the current browser, for the account switcher. */\nexport interface AccountSummary {\n did: string;\n handle: string | null;\n displayName: string | null;\n avatarUrl: string | null;\n /**\n * The org's uploaded logo blob CID, for a company account that set one on its\n * `/c/` page; null otherwise. The switcher resolves it to the same logo `/c/`\n * shows (via the shared company-logo resolution), so an uploaded logo appears\n * in the menu rather than the atproto avatar. Omitted by older api responses.\n */\n orgLogoBlob?: string | null;\n /** Whether this is the currently-active account. */\n active: boolean;\n}\n\nexport interface FetchAccountsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Accounts attached to this browser (the account switcher). Requires an\n * authenticated session. Returns `[]` on any error, including the\n * unauthenticated case.\n */\nexport async function fetchAccounts(\n config: SifaApiConfig,\n options: FetchAccountsOptions = {},\n): Promise<AccountSummary[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ accounts: AccountSummary[] }>(config, '/api/auth/accounts', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.accounts;\n } catch {\n return [];\n }\n}\n\n/**\n * Make an already-attached account the active one. Keyed by DID (public); the\n * server maps it to the browser's session id. Browser-only: the endpoint\n * requires an Origin header, which browsers set automatically on POST. Callers\n * typically reload the app afterwards to reset session-seeded state.\n */\nexport async function switchAccount(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<void> {\n await apiFetch(config, '/oauth/switch', {\n method: 'POST',\n body: { did },\n credentials: 'include',\n ...options,\n });\n}\n","import type { SkillSuggestion } from '../../types/index.js';\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Profile entry returned by the search endpoint. */\nexport interface ProfileSearchResult {\n did?: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatar?: string;\n about?: string;\n currentRole?: string;\n currentCompany?: string;\n industry?: string;\n domain?: string;\n countryCode?: string;\n locationCountry?: string;\n preferredWorkplace?: string[];\n claimed?: boolean;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n}\n\nexport interface SearchFilters {\n q?: string;\n skill?: string;\n country?: string;\n industry?: string;\n domain?: string;\n workplace?: string;\n app?: string;\n /**\n * Open-to filter. Values are short tokens (e.g. \"fullTime\", \"mentor\",\n * \"collab\") matching `OPEN_TO_OPTIONS[].token` from the taxonomy. The\n * API expands tokens to lex values server-side. Multiple tokens are\n * OR-combined (profile matches if any selected token is set).\n */\n openTo?: string[];\n limit?: number;\n}\n\nexport interface SearchResponse {\n profiles: ProfileSearchResult[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Skill typeahead suggestion. */\nexport interface SkillSearchResult {\n name: string;\n slug: string;\n category: string;\n userCount: number;\n}\n\nexport interface FilterOptions {\n countries: { countryCode: string; country: string; count: number }[];\n industries: { industry: string; count: number }[];\n apps: { appId: string; count: number }[];\n /**\n * Distribution of openTo selections across indexed profiles. Each entry\n * maps a short token (see {@link SearchFilters.openTo}) to the number of\n * profiles that have it set. Omitted from older API responses; treat\n * absence as \"no data\" rather than \"all zero\".\n */\n openTo?: { token: string; count: number }[];\n}\n\n/** Company entry returned by company search (workspace#299). */\nexport interface CompanySearchResult {\n /** Immutable catalogue id; the durable `/c/{publicId}` link. */\n publicId: string;\n name: string;\n domain: string | null;\n country: string | null;\n industry: string | null;\n logoUrl: string | null;\n employeeCount: number | null;\n}\n\nexport interface CompanySearchFilters {\n q?: string;\n /** ISO 3166-1 alpha-2. */\n country?: string;\n industry?: string;\n limit?: number;\n}\n\nexport interface CompanySearchResponse {\n results: CompanySearchResult[];\n hasMore: boolean;\n}\n\nconst EMPTY_SEARCH: SearchResponse = { profiles: [], total: 0, limit: 20, offset: 0 };\nconst EMPTY_FILTERS: FilterOptions = { countries: [], industries: [], apps: [], openTo: [] };\nconst EMPTY_COMPANY_SEARCH: CompanySearchResponse = { results: [], hasMore: false };\n\n/**\n * Search profiles by free-text query and optional filters. Returns an\n * empty result set when no filters are provided (matching sifa-web's\n * \"no input, no fetch\" behavior).\n */\nexport async function fetchSearchProfiles(\n config: SifaApiConfig,\n filters: SearchFilters,\n options: ApiFetchOptions = {},\n): Promise<SearchResponse> {\n const params = new URLSearchParams();\n if (filters.q) params.set('q', filters.q);\n if (filters.skill) params.set('skill', filters.skill);\n if (filters.country) params.set('country', filters.country);\n if (filters.industry) params.set('industry', filters.industry);\n if (filters.domain) params.set('domain', filters.domain);\n if (filters.workplace) params.set('workplace', filters.workplace);\n if (filters.app) params.set('app', filters.app);\n if (filters.openTo && filters.openTo.length > 0) {\n for (const token of filters.openTo) {\n if (token) params.append('openTo', token);\n }\n }\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n\n if (params.size === 0) return EMPTY_SEARCH;\n\n return apiFetch<SearchResponse>(config, `/api/search/profiles?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n}\n\n/**\n * Company search over the entity catalogue (workspace#299).\n *\n * A category of its own rather than part of profile search: the two rank\n * differently and carry different filters, and a slow category should not hold\n * up the rest of a blended results page.\n *\n * An empty query returns nothing without a network call. The API rejects a\n * blank `q` rather than scanning ~200k rows, so asking would only spend a round\n * trip to be told no.\n */\nexport async function fetchSearchCompanies(\n config: SifaApiConfig,\n filters: CompanySearchFilters,\n options: ApiFetchOptions = {},\n): Promise<CompanySearchResponse> {\n const q = filters.q?.trim();\n if (!q) return EMPTY_COMPANY_SEARCH;\n\n const params = new URLSearchParams({ q });\n if (filters.country) params.set('country', filters.country);\n if (filters.industry) params.set('industry', filters.industry);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n\n return apiFetch<CompanySearchResponse>(config, `/api/search/companies?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n}\n\n/**\n * Skill typeahead. Returns up to 8 matches for the given prefix. Empty\n * input returns an empty array without hitting the server.\n */\nexport async function fetchSkillSuggestions(\n config: SifaApiConfig,\n query: string,\n options: ApiFetchOptions = {},\n): Promise<SkillSearchResult[]> {\n if (!query.trim()) return [];\n const path = `/api/search/skills?q=${encodeURIComponent(query)}&limit=8`;\n const data = await apiFetch<{ skills?: SkillSearchResult[] }>(config, path, {\n cache: 'no-store',\n ...options,\n });\n return data.skills ?? [];\n}\n\n/** Available filter facets (countries, industries, apps) for search UI. */\nexport async function fetchSearchFilters(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<FilterOptions> {\n try {\n return await apiFetch<FilterOptions>(config, '/api/search/filters', {\n next: { revalidate: 300 },\n ...options,\n });\n } catch {\n return EMPTY_FILTERS;\n }\n}\n\n/**\n * Canonical-skill search backing the position-editor and similar\n * skill-pickers. Hits `/api/skills/search` (the canonical-skills DB\n * lookup) which is distinct from {@link fetchSkillSuggestions}'s\n * `/api/search/skills` (the profile-skill typeahead).\n *\n * Returns `[]` on empty input (no network call) or any error.\n */\nexport async function searchSkills(\n config: SifaApiConfig,\n query: string,\n limit = 10,\n options: ApiFetchOptions = {},\n): Promise<SkillSuggestion[]> {\n if (!query.trim()) return [];\n const path = `/api/skills/search?q=${encodeURIComponent(query)}&limit=${limit}`;\n try {\n const data = await apiFetch<{ skills?: SkillSuggestion[] }>(config, path, {\n cache: 'no-store',\n ...options,\n });\n return data.skills ?? [];\n } catch {\n return [];\n }\n}\n","import type { PresentationLinkView } from '../../types/index.js';\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Which claim a listed speaker makes about a topic. Phase 1 has no confirmed\n * data, so groups are named by the CLAIM, never a \"proven\" label:\n * - `spoke_about_it` — has a topic-matching delivery (or, with a topic set,\n * a matching presentation plus at least one delivery)\n * - `skilled` — holds the matching canonical skill but has no matching talk\n * (only appears when a topic is supplied)\n * - `open_to_speaking` — opted in but has never delivered (only appears when\n * no topic is supplied)\n */\nexport type SpeakerGroup = 'spoke_about_it' | 'skilled' | 'open_to_speaking';\n\n/** One person in the speaker directory. Everyone listed has opted in. */\nexport interface SpeakerCard {\n did: string;\n handle: string;\n displayName: string | null;\n avatar: string | null;\n headline: string | null;\n currentRole: string | null;\n currentCompany: string | null;\n deliveryCount: number;\n group: SpeakerGroup;\n matchedTopics: string[];\n /**\n * Self-reported event names from the speaker's own presentationDelivery\n * records — unconfirmed in Phase 1. `eventsSelfReported` is always true;\n * the web layer labels these as such.\n */\n recentEvents: string[];\n eventsSelfReported: boolean;\n /**\n * Up to 3 of the speaker's most-recent talks (self-reported), newest first.\n * `rkey` builds the talk-page URL via `buildTalkSlug(title, rkey)`. Optional:\n * absent from responses served before this field shipped, so consumers should\n * default to an empty list.\n */\n recentTalks?: { title: string; rkey: string }[];\n}\n\nexport interface SpeakersResponse {\n speakers: SpeakerCard[];\n}\n\n/** The reusable talk, or a standalone delivery when it has no parent talk. */\nexport interface TalkEvent {\n eventName: string | null;\n date: string | null;\n}\n\n/** Compact speaker card embedded in a talk row. */\nexport interface TalkSpeaker {\n did: string;\n handle: string;\n displayName: string | null;\n avatar: string | null;\n headline: string | null;\n currentRole: string | null;\n currentCompany: string | null;\n}\n\nexport interface TalkRow {\n /**\n * `presentation` = a reusable `id.sifa.profile.presentation` record.\n * `delivery` = a standalone presentationDelivery with no parent presentation.\n */\n kind: 'presentation' | 'delivery';\n rkey: string;\n title: string | null;\n snippet: string | null;\n links: PresentationLinkView[];\n writeupUri: string | null;\n speaker: TalkSpeaker;\n events: TalkEvent[];\n eventsSelfReported: boolean;\n deliveryCount: number;\n matchedTopics: string[];\n}\n\nexport interface TalksResponse {\n talks: TalkRow[];\n}\n\nexport interface SpeakerDirectoryFilters {\n /** Free-text topic (canonical skill name/slug/alias, talk title, or event). */\n topic?: string;\n /** Max rows to return; the API caps this at 50. */\n limit?: number;\n}\n\nconst EMPTY_SPEAKERS: SpeakersResponse = { speakers: [] };\nconst EMPTY_TALKS: TalksResponse = { talks: [] };\n\nfunction buildParams(filters: SpeakerDirectoryFilters): URLSearchParams {\n const params = new URLSearchParams();\n const topic = filters.topic?.trim();\n if (topic) params.set('topic', topic);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n return params;\n}\n\n/**\n * Speaker directory (Phase 1, read-only POC). Everyone returned has opted in to\n * speaking; past deliveries are a ranking signal, not an inclusion path. An\n * optional `topic` filters to people who hold the matching canonical skill,\n * have a matching presentation, or have a matching delivery. Results come\n * grouped and ordered by the API.\n *\n * Returns an empty list on any error so callers can render a graceful state.\n */\nexport async function fetchSpeakers(\n config: SifaApiConfig,\n filters: SpeakerDirectoryFilters = {},\n options: ApiFetchOptions = {},\n): Promise<SpeakersResponse> {\n const params = buildParams(filters);\n const query = params.toString();\n const path = query ? `/api/speakers?${query}` : '/api/speakers';\n try {\n return await apiFetch<SpeakersResponse>(config, path, {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return EMPTY_SPEAKERS;\n }\n}\n\n/**\n * Talk directory (Phase 1, read-only POC). Lists talks by opted-in speakers,\n * delivered-first, then latest delivery date. Same optional `topic` filter as\n * {@link fetchSpeakers}. Returns an empty list on any error.\n */\nexport async function fetchTalks(\n config: SifaApiConfig,\n filters: SpeakerDirectoryFilters = {},\n options: ApiFetchOptions = {},\n): Promise<TalksResponse> {\n const params = buildParams(filters);\n const query = params.toString();\n const path = query ? `/api/talks?${query}` : '/api/talks';\n try {\n return await apiFetch<TalksResponse>(config, path, {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return EMPTY_TALKS;\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Lightweight profile representation used by discovery endpoints. */\nexport interface SimilarProfile {\n did: string;\n handle: string;\n displayName?: string | null;\n avatar?: string | null;\n headline?: string | null;\n currentRole?: string | null;\n currentCompany?: string | null;\n industry?: string | null;\n domain?: string | null;\n}\n\nexport interface SuggestionProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n dismissed: boolean;\n blueskyVerified?: boolean;\n}\n\nexport interface SuggestionsResponse {\n onSifa: SuggestionProfile[];\n notOnSifa: SuggestionProfile[];\n cursor?: string;\n}\n\nexport interface FeaturedProfile {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n pronouns?: string;\n headline?: string;\n about?: string;\n currentRole?: string;\n currentCompany?: string;\n locationCountry?: string;\n locationRegion?: string;\n /** Legacy alias for `locationLocality`; emitted by sifa-api during the additive response window. */\n locationCity?: string;\n /** community.lexicon.location.address field name -- prefer over `locationCity`. */\n locationLocality?: string;\n countryCode?: string;\n location?: string;\n website?: string;\n openTo?: string[];\n preferredWorkplace?: string[];\n availableFromUtc?: number;\n availableToUtc?: number;\n followersCount?: number;\n atprotoFollowersCount?: number;\n pdsProvider?: { name: string; host: string } | null;\n claimed: boolean;\n featuredDate: string;\n}\n\n/** Profiles similar to the given DID (matchmaking). Returns `[]` on error. */\nexport async function fetchSimilarProfiles(\n config: SifaApiConfig,\n did: string,\n opts: { limit?: number } & ApiFetchOptions = {},\n): Promise<SimilarProfile[]> {\n const limit = opts.limit ?? 5;\n const path = `/api/discover/similar/${encodeIdentifier(did)}?limit=${limit}`;\n try {\n const data = await apiFetch<{ profiles?: SimilarProfile[] }>(config, path, {\n next: { revalidate: 300 },\n timeoutMs: 5000,\n ...opts,\n });\n return data.profiles ?? [];\n } catch {\n return [];\n }\n}\n\nexport interface FetchSuggestionsOptions extends ApiFetchOptions {\n source?: string;\n includeDismissed?: boolean;\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/** Discovery suggestions feed. Resolves to empty arrays on error. */\nexport async function fetchSuggestions(\n config: SifaApiConfig,\n opts: FetchSuggestionsOptions = {},\n): Promise<SuggestionsResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.includeDismissed) params.set('include_dismissed', 'true');\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n\n const qs = params.toString();\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n try {\n return await apiFetch<SuggestionsResponse>(config, `/api/suggestions${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n timeoutMs: 8000,\n ...opts,\n headers,\n });\n } catch {\n return { onSifa: [], notOnSifa: [] };\n }\n}\n\n/** Count of pending suggestions since an optional timestamp. */\nexport async function fetchSuggestionCount(\n config: SifaApiConfig,\n since?: string,\n options: ApiFetchOptions = {},\n): Promise<number> {\n const params = since ? `?since=${encodeURIComponent(since)}` : '';\n try {\n const data = await apiFetch<{ count?: number }>(config, `/api/suggestions/count${params}`, {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n });\n return data.count ?? 0;\n } catch {\n return 0;\n }\n}\n\n/** Featured profile (rotated by sifa-api). Returns `null` when none. */\nexport async function fetchFeaturedProfile(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<FeaturedProfile | null> {\n try {\n return await apiFetch<FeaturedProfile>(config, '/api/featured-profile', {\n next: { revalidate: 900 },\n ...options,\n });\n } catch {\n return null;\n }\n}\n","import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { FollowFeedPage } from '../../schemas/feed.js';\n\nexport interface FollowProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n claimed: boolean;\n followedAt: string;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n}\n\nexport interface FollowingResponse {\n follows: FollowProfile[];\n cursor?: string;\n}\n\n/** People the authenticated user follows. Empty on error. */\nexport async function fetchFollowing(\n config: SifaApiConfig,\n opts: { source?: string; cursor?: string; limit?: number } & ApiFetchOptions = {},\n): Promise<FollowingResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n\n try {\n return await apiFetch<FollowingResponse>(config, `/api/following${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n });\n } catch {\n return { follows: [] };\n }\n}\n\n/**\n * Result of {@link followUser}. Extends {@link WriteResult} with the\n * follow `rkey` returned by sifa-api on success. Self-follow + invalid\n * handle surface as `success: false` with the server-provided message;\n * dup-follow is idempotent (sifa-api E7) and resolves as `success: true`.\n */\nexport interface FollowUserResult extends WriteResult {\n rkey?: string;\n /** DID of the followed subject (server-resolved from the handle). */\n subjectDid?: string;\n}\n\n/**\n * Create an `id.sifa.graph.follow` record on the caller's PDS via the\n * AppView. Idempotent on duplicate (server catches the unique-violation\n * and returns 200, per sifa-api#673 E7).\n */\nexport function followUser(\n config: SifaApiConfig,\n handle: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<FollowUserResult> {\n const { note, ...rest } = opts;\n return apiWrite<{ rkey?: string; subjectDid?: string }>(\n config,\n `/api/follow/${encodeIdentifier(handle)}`,\n 'POST',\n {\n body: note !== undefined ? { note } : undefined,\n ...rest,\n },\n );\n}\n\n/** Delete the authenticated viewer's `id.sifa.graph.follow` for `handle`. */\nexport function unfollowUser(\n config: SifaApiConfig,\n handle: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/follow/${encodeIdentifier(handle)}`, 'DELETE', opts);\n}\n\nexport interface FollowListPage {\n follows: FollowProfile[];\n cursor: string | null;\n}\n\nexport interface FetchFollowListOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors {@link FetchActivityFeedOptions}; required for authenticated\n * server fetches because `credentials: 'include'` does not propagate\n * cookies from RSC).\n */\n cookieHeader?: string;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowListOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\n/**\n * Paginated list of `handle`'s followers. Returns an empty page on error\n * so the UI can render a graceful \"no followers yet\" state.\n */\nexport async function getFollowers(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/followers`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** Paginated list of who `handle` follows. */\nexport async function getFollowing(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/following`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/**\n * @deprecated The `/api/following/feed` surface was reverted (sifa-api#674).\n * Per `decisions/activity-data-strategy.md` the Sifa Timeline + ATmosphere\n * Stream are two distinct surfaces with different data paths (Barazo API\n * for Timeline, live PDS reads + Valkey for Stream). These collapsed feed\n * types are no longer consumed. Scheduled for removal in next major bump.\n */\nexport interface FetchFollowingFeedOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Comma-separated category filter (per sifa-api#673 TR10). Forwarded\n * as-is; the server validates allowed values.\n */\n categories?: string[];\n cookieHeader?: string;\n}\n\n/**\n * V5 home feed: Sifa events + curated ATmosphere creation events filtered\n * by the authenticated viewer's followees. Composite cursor (per E5/TR4).\n * Returns an empty page on error.\n *\n * @deprecated The `/api/following/feed` surface was reverted (sifa-api#674).\n * Per `decisions/activity-data-strategy.md` the Sifa Timeline + ATmosphere\n * Stream are two distinct surfaces with different data paths (Barazo API\n * for Timeline, live PDS reads + Valkey for Stream). This fetcher is no\n * longer consumed. Scheduled for removal in next major bump.\n */\nexport async function getFollowingFeed(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowFeedPage> {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n if (opts.categories && opts.categories.length > 0) {\n params.set('categories', opts.categories.join(','));\n }\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n try {\n const res = await apiFetch<{ items: FollowFeedPage['items']; cursor?: string | null }>(\n config,\n `/api/following/feed${qs ? `?${qs}` : ''}`,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [], cursor: res.cursor ?? null };\n } catch {\n return { items: [], cursor: null };\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { FollowProfileItem } from '../../schemas/follow-profile.js';\n\n/**\n * Options shared by the cursor-paginated follow-graph endpoints introduced in\n * `sifa-api#674` (mutuals + bluesky-suggestions). Mirrors\n * `FetchFollowListOptions` in `./follow.ts` but the response wrapper here uses\n * the `{ items, cursor }` shape (not `{ follows, cursor }`).\n */\nexport interface FetchFollowProfilePageOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors `FetchFollowListOptions`; required for authenticated server\n * fetches because `credentials: 'include'` does not propagate cookies from\n * RSC).\n */\n cookieHeader?: string;\n}\n\n/** Page of {@link FollowProfileItem} rows with an opaque next-page cursor. */\nexport interface FollowProfilePageResponse {\n items: FollowProfileItem[];\n cursor: string | null;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowProfilePageOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\nasync function fetchFollowProfilePage(\n config: SifaApiConfig,\n path: string,\n opts: FetchFollowProfilePageOptions,\n): Promise<FollowProfilePageResponse> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ items?: FollowProfileItem[]; cursor?: string | null }>(\n config,\n path,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [], cursor: res.cursor ?? null };\n } catch {\n return { items: [], cursor: null };\n }\n}\n\n/**\n * Cursor-paginated list of mutual sifa-source follows for `handleOrDid`\n * (X↔Y both follow each other on Sifa). Backed by\n * `GET /api/profile/{handleOrDid}/mutuals` from `sifa-api#674`. Public —\n * does not require auth. Returns an empty page on error.\n */\nexport async function getMutuals(\n config: SifaApiConfig,\n handleOrDid: string,\n opts: FetchFollowProfilePageOptions = {},\n): Promise<FollowProfilePageResponse> {\n return fetchFollowProfilePage(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handleOrDid)}/mutuals`, opts),\n opts,\n );\n}\n\n/**\n * Cursor-paginated list of Sifa users the viewer follows on Bluesky but NOT\n * on Sifa, filtered to people active on Sifa. Backed by\n * `GET /api/me/bluesky-suggestions` from `sifa-api#674`. Auth-required.\n * Returns an empty page on error.\n */\nexport async function getBlueskySuggestions(\n config: SifaApiConfig,\n opts: FetchFollowProfilePageOptions = {},\n): Promise<FollowProfilePageResponse> {\n return fetchFollowProfilePage(config, buildListPath('/api/me/bluesky-suggestions', opts), opts);\n}\n","import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { FeatureAllowlistEntry, FeatureFlag } from '../../schemas/follow-profile.js';\n\n/**\n * Options for {@link listFeatureAllowlist}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface ListFeatureAllowlistOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/feature-allowlists/:flag`. */\nexport interface FeatureAllowlistResponse {\n items: FeatureAllowlistEntry[];\n}\n\n/**\n * List all DIDs on the given feature flag's allowlist. Admin-gated server-\n * side (caller must be an admin). Returns an empty list on error so the UI\n * can render a graceful empty state.\n */\nexport async function listFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n opts: ListFeatureAllowlistOptions = {},\n): Promise<FeatureAllowlistResponse> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ items?: FeatureAllowlistEntry[] }>(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [] };\n } catch {\n return { items: [] };\n }\n}\n\n/**\n * Add (or upsert the note for) a DID on the given flag's allowlist. Maps to\n * `POST /api/admin/feature-allowlists/{flag}`. Returns a {@link WriteResult};\n * never throws.\n */\nexport function addFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n const { note, ...rest } = opts;\n return apiWrite(config, `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`, 'POST', {\n body: note !== undefined ? { did, note } : { did },\n ...rest,\n });\n}\n\n/**\n * Remove a DID from the given flag's allowlist. Maps to\n * `DELETE /api/admin/feature-allowlists/{flag}/{did}`. Returns a\n * {@link WriteResult}; never throws.\n */\nexport function removeFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}/${encodeIdentifier(did)}`,\n 'DELETE',\n opts,\n );\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Options for {@link getAdminReviewQueues}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface GetAdminReviewQueuesOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/stats/review-queues`. */\nexport interface AdminReviewQueues {\n ideas: number;\n nameCorrections: number;\n pendingCompanies: number;\n /** Sum of the three queues. */\n total: number;\n generatedAt: string;\n}\n\n/**\n * Open counts for the three admin review queues (ideas, pending companies,\n * name corrections) plus their total.\n *\n * Unlike {@link listFeatureAllowlist} this does NOT swallow errors: a zeroed\n * payload would render as \"all queues clear\" in the admin nav, which is worse\n * than rendering nothing. Callers decide how to degrade.\n */\nexport async function getAdminReviewQueues(\n config: SifaApiConfig,\n opts: GetAdminReviewQueuesOptions = {},\n): Promise<AdminReviewQueues> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n const res = await apiFetch<Partial<AdminReviewQueues>>(config, '/api/admin/stats/review-queues', {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n\n const ideas = res.ideas ?? 0;\n const nameCorrections = res.nameCorrections ?? 0;\n const pendingCompanies = res.pendingCompanies ?? 0;\n\n return {\n ideas,\n nameCorrections,\n pendingCompanies,\n // Derived rather than trusted so an API that predates the field still\n // yields a usable pill count.\n total: res.total ?? ideas + nameCorrections + pendingCompanies,\n generatedAt: res.generatedAt ?? '',\n };\n}\n","import type { ActivityLabel } from '../../cards/adult-content.js';\nimport { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { QuotedPostResult } from './quoted-posts.js';\n\n/**\n * Liveness of an activity card's destination, as reported by sifa-api's\n * `/api/activity` enrichment (see sifa-api `url-health-checker`). How liveness\n * is measured depends on the card's health strategy (see `resolveCardHealth`):\n * first-party permalinks (`record`) are checked by record existence on the PDS;\n * foreign/derived targets (`url`) by HTTP reachability (HEAD, then GET).\n *\n * ok -- record exists, or the URL returned 2xx/3xx\n * broken -- confirmed dead (record deleted, or >=2 consecutive 4xx / >=5 consecutive 5xx)\n * unverifiable -- 403/429, PDS unreachable, or network error; NOT dead\n * unknown -- newly seen, not yet checked\n *\n * Consumers should only suppress UI on `'broken'`. All other values\n * (including missing) mean \"render normally\".\n */\nexport type ActivityItemLinkHealth = 'ok' | 'broken' | 'unverifiable' | 'unknown';\n\nexport interface HeatmapDay {\n date: string;\n total: number;\n apps: { appId: string; count: number }[];\n}\n\nexport interface HeatmapResponse {\n days: HeatmapDay[];\n appTotals: { appId: string; appName: string; total: number }[];\n thresholds: [number, number, number, number];\n}\n\nexport interface ActivityItem {\n uri: string;\n cid: string;\n collection: string;\n rkey: string;\n record: Record<string, unknown>;\n appId: string;\n appName: string;\n category: string;\n indexedAt: string;\n /**\n * Set by the server when an `app.bsky.embed.record` quote was already\n * resolved upstream (AppView path). Mutually exclusive with `quotedPostUri`.\n */\n quotedPost?: QuotedPostResult;\n /**\n * Set by the server when an `app.bsky.embed.record` quote needs client-side\n * resolution (PDS path). Pass batches to {@link resolveQuotedPosts}.\n * Mutually exclusive with `quotedPost`.\n */\n quotedPostUri?: string;\n /**\n * Reachability of the card's external destination as last checked by\n * sifa-api. Undefined for legacy responses; treat as 'unknown'.\n * See {@link ActivityItemLinkHealth}.\n */\n linkHealth?: ActivityItemLinkHealth;\n /**\n * Content labels from `app.bsky.feed.defs#postView.labels`. Set by\n * sifa-api for Bluesky posts; undefined for other sources and legacy\n * responses. Pass items to {@link hasAdultContent} to decide whether to\n * gate media. See {@link ActivityLabel}.\n */\n labels?: ActivityLabel[];\n /**\n * The owner has hidden this item from their profile. Only ever set on the\n * owner's own view of their feed -- every other surface omits hidden items\n * rather than flagging them -- so a card can offer an unhide in place.\n */\n hidden?: boolean;\n}\n\nexport interface ActivityTeaserResponse {\n items: ActivityItem[];\n blueskyGated?: boolean;\n backfillPending?: boolean;\n failedApps?: string[];\n}\n\nexport interface ActivityFeedResponse {\n items: ActivityItem[];\n cursor: string | null;\n hasMore: boolean;\n availableCategories?: string[];\n blueskyGated?: boolean;\n failedApps?: string[];\n}\n\n/**\n * Per-day activity counts for a profile across all ATproto apps. Returns\n * `null` on any error so callers can render a graceful empty state.\n */\nexport async function fetchHeatmapData(\n config: SifaApiConfig,\n handleOrDid: string,\n days: number,\n options: ApiFetchOptions = {},\n): Promise<HeatmapResponse | null> {\n const path = `/api/activity/${encodeIdentifier(handleOrDid)}/heatmap?days=${days}`;\n try {\n return await apiFetch<HeatmapResponse>(config, path, {\n next: { revalidate: 900, tags: [`heatmap-${handleOrDid}`] },\n ...options,\n });\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityTeaserOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Recent activity teaser for a profile (homepage-sized slice). Caps the\n * upstream wait so the SSR path cannot hang. Returns `null` on any error.\n */\nexport async function fetchActivityTeaser(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityTeaserOptions = {},\n): Promise<ActivityTeaserResponse | null> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityTeaserResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}/teaser`,\n {\n credentials: 'include',\n timeoutMs: 8000,\n next: { revalidate: 300, tags: [`activity-teaser-${handleOrDid}`] },\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityFeedOptions extends ApiFetchOptions {\n category?: string;\n limit?: number;\n cursor?: string;\n cookieHeader?: string;\n}\n\n/**\n * Paginated activity feed for a profile. Always fresh (`cache: 'no-store'`).\n * Returns `null` on any error.\n */\nexport async function fetchActivityFeed(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityFeedOptions = {},\n): Promise<ActivityFeedResponse | null> {\n const params = new URLSearchParams();\n if (options.category) params.set('category', options.category);\n if (options.limit) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityFeedResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}${qs ? `?${qs}` : ''}`,\n {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n","import { z } from 'zod';\n\nimport { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * A single merged pull request ingested from GitHub, as served by sifa-api's\n * `GET /api/me/github/pull-requests`. Mirrors the `github_contributions` row.\n */\nexport const GithubPullRequestSchema = z.object({\n prNumber: z.number(),\n repoOwner: z.string(),\n repoName: z.string(),\n title: z.string(),\n url: z.string(),\n language: z.string().nullable(),\n additions: z.number(),\n deletions: z.number(),\n /** ISO 8601 merge timestamp. */\n mergedAt: z.string(),\n});\nexport type GithubPullRequest = z.infer<typeof GithubPullRequestSchema>;\n\nexport const MyGithubPullRequestsResponseSchema = z.object({\n items: z.array(GithubPullRequestSchema),\n hasMore: z.boolean(),\n});\nexport type MyGithubPullRequestsResponse = z.infer<typeof MyGithubPullRequestsResponseSchema>;\n\nexport interface FetchMyGithubPullRequestsOptions extends ApiFetchOptions {\n limit?: number;\n offset?: number;\n /** Forwarded as the `cookie` header for server-side (SSR) calls. */\n cookieHeader?: string;\n}\n\n/**\n * Fetch the authenticated viewer's own ingested merged PRs (newest first).\n * Auth-scoped: relies on the session cookie (`credentials: 'include'`), so it\n * returns the caller's PRs, not a public handle's. Backs the GitHub importer.\n */\nexport async function fetchMyGithubPullRequests(\n config: SifaApiConfig,\n options: FetchMyGithubPullRequestsOptions = {},\n): Promise<MyGithubPullRequestsResponse> {\n const { limit, offset, cookieHeader, ...fetchOptions } = options;\n\n const params = new URLSearchParams();\n if (limit !== undefined) params.set('limit', String(limit));\n if (offset !== undefined) params.set('offset', String(offset));\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n\n const data = await apiFetch<unknown>(\n config,\n `/api/me/github/pull-requests${qs ? `?${qs}` : ''}`,\n {\n credentials: 'include',\n cache: 'no-store',\n ...fetchOptions,\n headers,\n },\n );\n\n return MyGithubPullRequestsResponseSchema.parse(data);\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Counts confirmed endorsements received by a DID. The backend's\n * `GET /api/endorsement/:did` already returns only confirmed endorsements\n * (via inner join with `endorsementConfirmations`), so this helper just\n * returns the array length. Failures return 0 so callers can route safely.\n *\n * Public endpoint -- no credentials needed.\n */\nexport async function fetchEndorsementCount(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<number> {\n const path = `/api/endorsement/${encodeIdentifier(did)}`;\n try {\n const data = await apiFetch<unknown>(config, path, {\n cache: 'no-store',\n timeoutMs: 5000,\n ...options,\n });\n if (typeof data !== 'object' || data === null || !('endorsements' in data)) {\n return 0;\n }\n const endorsements = data.endorsements;\n return Array.isArray(endorsements) ? endorsements.length : 0;\n } catch {\n return 0;\n }\n}\n","import { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface FetchNetworkStreamCountOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n *\n * When omitted, the request falls back to `credentials: 'include'` so\n * client-side calls work without extra plumbing.\n */\n cookieHeader?: string;\n}\n\n/**\n * Counts items in the authenticated user's network stream digest. The\n * underlying `GET /api/stream/network` endpoint may 404 while the feature\n * is in development; in that case (and on any other error) this returns\n * 0 so callers can route safely to a fallback experience.\n */\nexport async function fetchNetworkStreamCount(\n config: SifaApiConfig,\n did: string,\n options: FetchNetworkStreamCountOptions = {},\n): Promise<number> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<unknown>(\n config,\n `/api/stream/network?did=${encodeIdentifier(did)}`,\n {\n cache: 'no-store',\n timeoutMs: 5000,\n ...(options.cookieHeader ? {} : { credentials: 'include' }),\n ...options,\n headers,\n },\n );\n if (typeof data !== 'object' || data === null || !('items' in data)) {\n return 0;\n }\n const items = data.items;\n return Array.isArray(items) ? items.length : 0;\n } catch {\n return 0;\n }\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Per-URI reaction state for the authenticated viewer. */\nexport interface ReactionStatus {\n reacted: boolean;\n rkey?: string;\n collection?: string;\n}\n\n/** Result of checking whether the authenticated viewer has an account on a given app. */\nexport interface AccountCheckResult {\n hasAccount: boolean;\n appName: string;\n appUrl: string;\n}\n\nexport interface FetchReactionStatusOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Batch-look up reaction status for multiple URIs. Returns `{}` for an\n * empty input list (no network call) and `null` on any error.\n */\nexport async function fetchReactionStatus(\n config: SifaApiConfig,\n uris: string[],\n options: FetchReactionStatusOptions = {},\n): Promise<Record<string, ReactionStatus> | null> {\n if (uris.length === 0) return {};\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<Record<string, ReactionStatus>>(\n config,\n `/api/reactions/status?uris=${encodeURIComponent(uris.join(','))}`,\n {\n credentials: 'include',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\nexport interface CheckAppAccountOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/**\n * Check whether the authenticated viewer has an account on a given app.\n * Returns `null` on any error.\n */\nexport async function checkAppAccount(\n config: SifaApiConfig,\n appId: string,\n options: CheckAppAccountOptions = {},\n): Promise<AccountCheckResult | null> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<AccountCheckResult>(\n config,\n `/api/reactions/account-check/${encodeURIComponent(appId)}`,\n {\n credentials: 'include',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\n/** Result of a successful {@link createReaction}. */\nexport interface ReactionResult {\n uri: string;\n rkey: string;\n}\n\n/** Structured error returned by {@link createReaction} on failure. */\nexport interface ReactionError {\n type: 'scope_insufficient' | 'error';\n /** When `type === 'scope_insufficient'`, the lexicon scope the user must re-authorize for. */\n requiredScope?: string;\n}\n\n/**\n * Create a reaction (like / star) on a target ATproto record.\n *\n * Returns a discriminated-union result instead of the generic\n * {@link WriteResult} shape because reactions have a distinct\n * \"scope insufficient\" failure that callers handle differently from\n * other errors (it triggers an OAuth scope-upgrade flow rather than\n * an error toast).\n *\n * Never throws.\n */\nexport async function createReaction(\n config: SifaApiConfig,\n targetUri: string,\n appId: string,\n targetCid?: string,\n options: ApiFetchOptions = {},\n): Promise<{ ok: true; data: ReactionResult } | { ok: false; error: ReactionError }> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/reactions`;\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(options.headers ?? {}) },\n credentials: options.credentials ?? 'include',\n body: JSON.stringify({ targetUri, appId, targetCid }),\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 10_000),\n });\n\n if (!res.ok) {\n if (res.status === 403) {\n try {\n const body = (await res.json()) as { error?: string; requiredScope?: string };\n if (body.error === 'ScopeInsufficient') {\n return {\n ok: false,\n error: { type: 'scope_insufficient', requiredScope: body.requiredScope },\n };\n }\n } catch {\n // Fall through to generic error\n }\n }\n return { ok: false, error: { type: 'error' } };\n }\n\n const data = (await res.json()) as ReactionResult;\n return { ok: true, data };\n } catch {\n return { ok: false, error: { type: 'error' } };\n }\n}\n\n/**\n * Delete a reaction (like / star) on a target ATproto record. Returns\n * `{ success: true }` on 2xx, `{ success: false, error }` on failure.\n */\nexport function deleteReaction(\n config: SifaApiConfig,\n targetUri: string,\n appId: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/reactions', 'DELETE', {\n body: { targetUri, appId },\n ...options,\n });\n}\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\nexport interface QuotedPostAuthor {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n}\n\nexport interface QuotedPostImage {\n thumb: string;\n fullsize: string;\n alt?: string;\n}\n\nexport interface QuotedPostView {\n uri: string;\n cid: string;\n author: QuotedPostAuthor;\n text: string;\n createdAt: string;\n images?: QuotedPostImage[];\n}\n\nexport type QuotedPostResult =\n | { status: 'ok'; record: QuotedPostView }\n | { status: 'deleted'; uri: string }\n | { status: 'unavailable'; uri: string };\n\n/** Max URIs per request to `POST /api/quoted-posts/resolve` (mirrors server cap). */\nexport const QUOTED_POSTS_BATCH_MAX = 20;\n\nexport interface ResolveQuotedPostsOptions extends ApiFetchOptions {\n /** Cookie header for Next.js RSC server-side calls; ignored in browsers. */\n cookieHeader?: string;\n}\n\n/**\n * Resolve a batch of AT-URIs to their quoted-post snapshots via the Sifa AppView.\n *\n * Auto-deduplicates input URIs and splits requests into chunks of\n * {@link QUOTED_POSTS_BATCH_MAX} so callers can pass an arbitrary-length array.\n * Each chunk is fired in parallel. The server caches results in Valkey, so\n * repeated calls for the same URI are cheap.\n *\n * Returns a map of `uri -> QuotedPostResult`. URIs that fail (network error,\n * non-2xx, or the server omitting them) are absent from the map; the caller\n * should render a skeleton or tombstone for those.\n */\nexport async function resolveQuotedPosts(\n config: SifaApiConfig,\n uris: string[],\n options: ResolveQuotedPostsOptions = {},\n): Promise<Record<string, QuotedPostResult>> {\n if (uris.length === 0) return {};\n\n const unique = [...new Set(uris)];\n const batches: string[][] = [];\n for (let i = 0; i < unique.length; i += QUOTED_POSTS_BATCH_MAX) {\n batches.push(unique.slice(i, i + QUOTED_POSTS_BATCH_MAX));\n }\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n const results: Record<string, QuotedPostResult> = {};\n await Promise.all(\n batches.map(async (batch) => {\n try {\n const data = await apiFetch<Record<string, QuotedPostResult>>(\n config,\n '/api/quoted-posts/resolve',\n {\n method: 'POST',\n body: { uris: batch },\n credentials: 'include',\n timeoutMs: 8000,\n ...options,\n headers,\n },\n );\n Object.assign(results, data);\n } catch {\n // Leave failed URIs absent so the consumer can render a fallback.\n }\n }),\n );\n\n return results;\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** Voter on a roadmap item. */\nexport interface RoadmapVoter {\n did: string;\n avatarUrl?: string;\n}\n\n/** Map of item key -> vote tally and voter list. */\nexport type RoadmapVotesResponse = Record<string, { count: number; voters: RoadmapVoter[] }>;\n\n/**\n * Public roadmap vote tallies, keyed by item. Returns `{}` on any error.\n */\nexport async function fetchRoadmapVotes(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RoadmapVotesResponse> {\n try {\n return await apiFetch<RoadmapVotesResponse>(config, '/api/roadmap/votes', {\n cache: 'no-store',\n ...options,\n });\n } catch {\n return {};\n }\n}\n\nexport interface FetchMyRoadmapVotesOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Roadmap items the authenticated user has voted on. Returns `[]` on any\n * error or when the response payload is shaped unexpectedly.\n */\nexport async function fetchMyRoadmapVotes(\n config: SifaApiConfig,\n options: FetchMyRoadmapVotesOptions = {},\n): Promise<string[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ voted?: string[] }>(config, '/api/roadmap/votes/me', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.voted ?? [];\n } catch {\n return [];\n }\n}\n\n/** Result of a successful {@link castRoadmapVote} -- the created upvote record. */\nexport interface RoadmapVoteResult {\n uri: string;\n rkey: string;\n}\n\n/** Structured error returned by {@link castRoadmapVote} on failure. */\nexport interface RoadmapVoteError {\n type: 'scope_insufficient' | 'error';\n /**\n * When `type === 'scope_insufficient'`, the lexicon collection the user must\n * re-authorize for (e.g. `app.userinput.upvote`). sifa-web maps this to an\n * OAuth scope-upgrade flow (`/oauth/reauth?scope=repo:<collection>`).\n */\n requiredScope?: string;\n}\n\n/**\n * Discriminated-union result of {@link castRoadmapVote}. Exported so the\n * `useCastRoadmapVote` hook and SDK consumers can type mutation handlers\n * against a single source of truth.\n */\nexport type CastRoadmapVoteResult =\n { ok: true; data: RoadmapVoteResult } | { ok: false; error: RoadmapVoteError };\n\n/**\n * Cast a vote on a roadmap item by its key.\n *\n * Writes an `app.userinput.upvote` record into the viewer's PDS (server-side,\n * via their OAuth session). Returns a discriminated-union result rather than\n * the generic {@link WriteResult} because a first-time voter's PDS grant may\n * not yet include the `app.userinput.upvote` collection: the AppView responds\n * 403 `ScopeInsufficient`, which the caller handles by triggering an OAuth\n * scope upgrade rather than showing an error. Mirrors {@link createReaction}.\n *\n * Never throws.\n */\nexport async function castRoadmapVote(\n config: SifaApiConfig,\n key: string,\n options: ApiFetchOptions = {},\n): Promise<CastRoadmapVoteResult> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}/api/roadmap/votes/${encodeURIComponent(key)}`;\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n // No body: the item key is in the URL. Do NOT declare a JSON content-type\n // for an empty body — Fastify rejects that with a 400 before the handler\n // runs. Only forward caller-provided headers.\n ...(options.headers ? { headers: options.headers } : {}),\n credentials: options.credentials ?? 'include',\n signal: options.signal ?? AbortSignal.timeout(options.timeoutMs ?? 10_000),\n });\n\n if (!res.ok) {\n if (res.status === 403) {\n try {\n const body = (await res.json()) as { error?: string; requiredScope?: string };\n if (body.error === 'ScopeInsufficient') {\n return {\n ok: false,\n error: { type: 'scope_insufficient', requiredScope: body.requiredScope },\n };\n }\n } catch {\n // Fall through to generic error.\n }\n }\n return { ok: false, error: { type: 'error' } };\n }\n\n const data = (await res.json()) as RoadmapVoteResult;\n return { ok: true, data };\n } catch {\n return { ok: false, error: { type: 'error' } };\n }\n}\n\n/** Retract a previously-cast roadmap vote. */\nexport function retractRoadmapVote(\n config: SifaApiConfig,\n key: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/roadmap/votes/${encodeURIComponent(key)}`, 'DELETE', options);\n}\n","import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * What the server managed to remove from the user's PDS.\n *\n * The wipe runs per collection, so it can partly succeed: `success: true` means\n * the account action completed, NOT that the PDS is clean. A UI that ignores\n * this can tell someone their data is gone while it is still on their data\n * server, so treat a non-empty `remaining` as \"not deleted\".\n *\n * Absent when the PDS was not touched (`deletePdsData: false`).\n */\nexport interface PdsWipeOutcome {\n /** Collections whose records were removed. */\n deleted: string[];\n /** Collections whose records are still on the PDS. Non-empty means not done. */\n remaining: string[];\n /**\n * The server could not enumerate the repo, so it does not know what survived.\n * Without this, that case is indistinguishable from \"nothing to delete\".\n */\n unknown: boolean;\n}\n\n/**\n * What a PDS wipe could not remove with the grant the session holds today.\n *\n * Read this BEFORE the destructive step. Deleting an account destroys the\n * session, so a missing scope cannot be granted afterwards -- there is nobody\n * left to ask. A non-empty `needsScopeFor` means the wipe would strand those\n * records on the user's data server.\n */\nexport interface WipePreview {\n /** id.sifa.* collections the current grant cannot delete. */\n needsScopeFor: string[];\n /**\n * The server could not enumerate the repo, so the gap list is not\n * authoritative. Distinct from an empty list, which means \"nothing to ask for\".\n */\n unknown?: boolean;\n}\n\n/**\n * Ask which id.sifa.* collections the current grant cannot delete.\n *\n * Unlike most read fetchers in this file's neighbourhood, a failure is NOT\n * flattened into an empty result: an empty gap list reads as \"a wipe will be\n * clean\", and a caller must not promise that on the strength of a request that\n * never arrived. Let it throw and warn.\n */\nexport function fetchWipePreview(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WipePreview> {\n return apiFetch<WipePreview>(config, '/api/profile/wipe-preview', {\n credentials: 'include',\n ...options,\n });\n}\n\n/** Extended write result for {@link resetProfile}. */\nexport interface ResetProfileResult extends WriteResult {\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/** Extended write result for {@link deleteAccount}. */\nexport interface DeleteAccountResult extends WriteResult {\n /** The deleted handle, returned by the server for confirmation UIs. */\n handle?: string;\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/**\n * Reset the authenticated user's Sifa profile.\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS. `deletePdsData: false` only removes the AppView's\n * indexed state -- the records on the PDS are left intact and could be\n * re-indexed later.\n *\n * Destructive. Server enforces session check + attestation; the SDK\n * does not gate on additional confirmation. Wrap call sites in your\n * own modal if you want a UX confirmation step.\n */\nexport function resetProfile(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<ResetProfileResult> {\n return apiWrite<{ ok?: boolean; pds?: PdsWipeOutcome }>(config, '/api/profile/reset', 'DELETE', {\n body: { deletePdsData },\n ...options,\n });\n}\n\n/**\n * Delete the authenticated user's account. Returns the deleted handle\n * on success (used by the post-delete confirmation screen).\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS; `false` leaves the PDS records intact.\n *\n * Destructive. Same caveat as {@link resetProfile}.\n */\nexport function deleteAccount(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<DeleteAccountResult> {\n return apiWrite<{ ok?: boolean; handle?: string; pds?: PdsWipeOutcome }>(\n config,\n '/api/profile/account',\n 'DELETE',\n {\n body: { deletePdsData },\n ...options,\n },\n );\n}\n","import type { RepoDeleteResult, RepoInventory } from '../../repo/types.js';\nimport { apiFetch, apiWrite, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Read what the user's PDS actually holds under id.sifa.*.\n *\n * A failure is not flattened into an empty inventory. Zero records reads as\n * \"Sifa has stored nothing about you\", and a request that never arrived must\n * not be allowed to say that. Let it throw.\n */\nexport function fetchRepoInventory(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<RepoInventory> {\n return apiFetch<RepoInventory>(config, '/api/me/repo-inventory', {\n credentials: 'include',\n ...options,\n });\n}\n\nexport interface RepoDeleteInput {\n collection: string;\n /** The records to remove. Omit and set `all` to remove the whole collection. */\n rkeys?: string[];\n /**\n * Remove every record in the collection, including ones written between the\n * inventory read and this call. A UI offering \"delete all of X\" must send\n * this rather than the rkeys it happened to see, or a record created in\n * between silently survives a delete the user believes was complete.\n */\n all?: boolean;\n}\n\n/**\n * Delete records from the user's own repo.\n *\n * The returned `success` means the request was accepted, NOT that the records\n * are gone: read `results` for that, per record. `needsScopeUpgrade` means\n * nothing was attempted and the user has to grant the scope first.\n *\n * Destructive and not undoable -- a deleted record's CID cannot be restored.\n * The server enforces the id.sifa.* boundary and the session check; the SDK\n * adds no confirmation step, so wrap call sites in one.\n */\nexport function deleteRepoRecords(\n config: SifaApiConfig,\n input: RepoDeleteInput,\n options: ApiFetchOptions = {},\n): Promise<RepoDeleteResult & { success: boolean; error?: string }> {\n return apiWrite<RepoDeleteResult>(config, '/api/me/repo-delete', 'POST', {\n body: input,\n ...options,\n });\n}\n\n/**\n * URL of the raw-record download.\n *\n * A URL rather than a fetcher: the response is a file the browser saves, and\n * routing it through fetch would buffer the whole repo in memory to hand it\n * straight back to a download anchor.\n */\nexport function repoExportUrl(config: SifaApiConfig): string {\n return `${config.baseUrl}/api/me/repo-export`;\n}\n","import { apiFetch, apiFetchOrNull, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** A node in the personal network graph. */\nexport interface NetworkMapNode {\n did: string;\n handle: string;\n displayName: string;\n avatar: string | null;\n /** Number of edges this node participates in within the rendered graph. */\n degree: number;\n /** Phase 2: community detection cluster id. */\n cluster?: number;\n /** Phase 2: pre-computed layout coordinates. */\n x?: number;\n y?: number;\n}\n\n/** A directed edge in the personal network graph. */\nexport interface NetworkMapEdge {\n source: string;\n target: string;\n mutual: boolean;\n /** Networks this edge was observed in, e.g. `['sifa', 'bluesky']`. */\n sources: string[];\n}\n\n/** The graph payload itself, decoupled from response metadata. */\nexport interface NetworkMapGraphData {\n nodes: NetworkMapNode[];\n edges: NetworkMapEdge[];\n /** Phase 2: cluster metadata for legend rendering. */\n clusters?: Array<{ id: number; label: string; color: string }>;\n}\n\n/** Cached graph response. */\nexport interface NetworkMapResponse {\n generatedAt: string;\n expiresAt: string;\n graph: NetworkMapGraphData;\n stats: {\n totalNodes: number;\n totalEdges: number;\n mutualCount: number;\n sources: Record<string, number>;\n };\n}\n\n/** Async job tracking generation progress. */\nexport interface NetworkMapGenerationJob {\n jobId: string;\n did: string;\n status: 'pending' | 'complete' | 'failed';\n /** 0..100 */\n progress: number;\n createdAt: string;\n completedAt?: string;\n error?: string;\n /**\n * Queue position when the job is still pending and not yet picked up\n * by the worker. 0 = next to run. Absent for in-flight or terminal\n * jobs (and for any backend that doesn't yet report position).\n */\n position?: number;\n /**\n * Estimated remaining seconds, derived server-side from the median\n * historical duration for the user's follow-count bucket multiplied\n * by `position + 1`. Absent when no historical data exists yet.\n */\n etaSeconds?: number;\n}\n\n/** Returned by `initiateNetworkMapGeneration` when a new job was started or one was already running. */\nexport interface NetworkMapPendingJob {\n jobId: string;\n status: 'pending' | 'cached';\n}\n\n/** Discriminate the union returned by `initiateNetworkMapGeneration`. */\nexport function isNetworkMapResponse(\n value: NetworkMapPendingJob | NetworkMapResponse,\n): value is NetworkMapResponse {\n return 'graph' in value;\n}\n\n/**\n * Kick off a personal network-map computation. The backend returns the\n * cached map immediately when fresh, otherwise it returns a job id that\n * the caller polls via `checkNetworkMapJobStatus`.\n */\nexport async function initiateNetworkMapGeneration(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapPendingJob | NetworkMapResponse> {\n return apiFetch<NetworkMapPendingJob | NetworkMapResponse>(config, '/api/network-map/generate', {\n method: 'POST',\n credentials: 'include',\n ...options,\n });\n}\n\n/**\n * Poll the status of an in-flight generation job. Throws on 404 (unknown\n * or expired job) — callers may want to treat that as terminal failure.\n */\nexport async function checkNetworkMapJobStatus(\n config: SifaApiConfig,\n jobId: string,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapGenerationJob> {\n return apiFetch<NetworkMapGenerationJob>(\n config,\n `/api/network-map/status/${encodeURIComponent(jobId)}`,\n {\n credentials: 'include',\n ...options,\n },\n );\n}\n\n/**\n * Fetch the most recent cached network map for the authenticated user.\n * Returns `null` when no map has ever been generated (404).\n */\nexport async function fetchNetworkMap(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<NetworkMapResponse | null> {\n return apiFetchOrNull<NetworkMapResponse>(config, '/api/network-map', {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n });\n}\n","import { z } from 'zod';\n\n/**\n * Organization entity-resolution payloads (#159). Shared by the typeahead,\n * selection, and grow-on-demand import-search endpoints on sifa-api.\n */\n\n/**\n * A nullable string constrained to an http(s) URL. Rejects `javascript:` and\n * other script-bearing schemes at the SDK boundary so a hostile API response\n * cannot smuggle an XSS payload into a rendered `href`/`src`. Note: Wikidata\n * entity URIs are canonically `http://`, so both http and https are allowed.\n */\nconst httpUrlNullable = z\n .string()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'must be an http(s) URL' })\n .nullable();\n\nconst searchResultCommon = {\n kind: z.string(),\n name: z.string(),\n domain: z.string().nullable(),\n country: z.string().nullable(),\n logoUrl: httpUrlNullable,\n parentName: z.string().nullable(),\n};\n\n/**\n * A single typeahead row. Discriminated on `source`: a curated `entity` row\n * carries `entityId`, a `pdl` staging row carries `pdlId`. The union guarantees\n * the identifier for the row's source is always present, so a stable React key\n * can never be `entity:undefined`. The disambiguation fields\n * (domain/country/parentName) drive the dropdown display.\n */\nexport const EntitySearchResultSchema = z.discriminatedUnion('source', [\n z.object({\n source: z.literal('entity'),\n entityId: z.number().int().positive(),\n ...searchResultCommon,\n }),\n z.object({\n source: z.literal('pdl'),\n pdlId: z.string().min(1),\n ...searchResultCommon,\n }),\n]);\nexport type EntitySearchResult = z.infer<typeof EntitySearchResultSchema>;\n\n/** Response of `GET /api/entities/search`. */\nexport const EntitySearchResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n hasMore: z.boolean(),\n});\nexport type EntitySearchResponse = z.infer<typeof EntitySearchResponseSchema>;\n\n/**\n * Body of `POST /api/entities/select`: promote a PDL row OR bump an entity.\n * Exactly one of `entityId`/`pdlId` must be present -- supplying both is\n * ambiguous (the server would have to silently pick one) and is rejected.\n */\nexport const EntitySelectRequestSchema = z\n .object({\n entityId: z.number().int().positive().optional(),\n pdlId: z.string().min(1).optional(),\n })\n .refine((v) => (v.entityId != null) !== (v.pdlId != null), {\n message: 'exactly one of entityId or pdlId is required',\n });\nexport type EntitySelectRequest = z.infer<typeof EntitySelectRequestSchema>;\n\n/** Response of `POST /api/entities/select`. `entityRef` is the portable\n * Wikidata/ROR/LEI URI to write to the position record, or null for a\n * PDL-only entity (its resolution stays AppView-side). */\nexport const EntitySelectResponseSchema = z.object({\n entityId: z.number().int().positive(),\n slug: z.string(),\n kind: z.string(),\n canonicalName: z.string(),\n domain: z.string().nullable(),\n /**\n * The entity's website, gated to sources trustworthy enough to prefill into a\n * record the user signs. Narrower than `domain`, which is a display value and\n * may come from a crawl. Null when the entity has no such source.\n */\n website: httpUrlNullable.default(null),\n /** Which tier `website` came from. Crawled is never an accepted source. */\n websiteTier: z.enum(['org', 'curated']).nullable().default(null),\n entityRef: httpUrlNullable,\n});\nexport type EntitySelectResponse = z.infer<typeof EntitySelectResponseSchema>;\n\n/** Response of `POST /api/entities/import-search`. */\nexport const EntityImportSearchResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n});\nexport type EntityImportSearchResponse = z.infer<typeof EntityImportSearchResponseSchema>;\n\n/**\n * Body of the domain grow-on-demand endpoints (`POST /api/entities/resolve-domain`\n * and `POST /api/entities/mint-domain`). The server re-validates the value as a\n * registrable domain; 253 is the max DNS name length.\n */\nexport const EntityResolveDomainRequestSchema = z.object({\n domain: z.string().min(1).max(253),\n});\nexport type EntityResolveDomainRequest = z.infer<typeof EntityResolveDomainRequestSchema>;\n\n/**\n * Response of `POST /api/entities/resolve-domain` (grow-on-demand Branch 1). Any\n * notable companies whose official website is the domain, imported from Wikidata.\n * `canMint` is true when nothing notable matched AND the domain is eligible for\n * the user-initiated mint-from-domain path -- it drives the \"Add <domain>\"\n * affordance.\n */\nexport const EntityResolveDomainResponseSchema = z.object({\n results: z.array(EntitySearchResultSchema),\n canMint: z.boolean(),\n});\nexport type EntityResolveDomainResponse = z.infer<typeof EntityResolveDomainResponseSchema>;\n\n/**\n * Response of `POST /api/entities/mint-domain` (grow-on-demand Branch 2). The\n * linkable entity minted from (or already resolved for) the domain. A non-2xx\n * status (e.g. the domain is not mintable, a confusable look-alike, or the site\n * yielded nothing usable) surfaces as a thrown error, not a null result.\n *\n * `pending` is true when the entity is a fresh hidden-pending mint: the\n * requesting user's own link resolves to it immediately, but it stays out of\n * other users' typeahead + aggregation until an admin approves it. Clients should\n * reflect this (\"added -- pending review\") rather than \"added & live\".\n */\nexport const EntityMintDomainResponseSchema = z.object({\n result: EntitySearchResultSchema,\n pending: z.boolean(),\n});\nexport type EntityMintDomainResponse = z.infer<typeof EntityMintDomainResponseSchema>;\n","import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport {\n EntitySearchResponseSchema,\n EntitySelectResponseSchema,\n EntityImportSearchResponseSchema,\n EntityResolveDomainResponseSchema,\n EntityMintDomainResponseSchema,\n type EntitySearchResponse,\n type EntitySearchResult,\n type EntitySelectRequest,\n type EntitySelectResponse,\n type EntityResolveDomainResponse,\n type EntityMintDomainResponse,\n} from '../../schemas/entity.js';\n\nconst EMPTY_SEARCH: EntitySearchResponse = { results: [], hasMore: false };\n\n/**\n * Organization typeahead. Returns curated entities first, then the PDL crawl,\n * deduped by domain. Empty input returns an empty result without a network call.\n */\nexport async function fetchEntitySearch(\n config: SifaApiConfig,\n query: string,\n limit?: number,\n options: ApiFetchOptions = {},\n): Promise<EntitySearchResponse> {\n if (!query.trim()) return EMPTY_SEARCH;\n const params = new URLSearchParams({ q: query });\n if (limit !== undefined) params.set('limit', String(limit));\n const data = await apiFetch<unknown>(config, `/api/entities/search?${params.toString()}`, {\n cache: 'no-store',\n ...options,\n });\n return EntitySearchResponseSchema.parse(data);\n}\n\n/**\n * Record a selection: promote a PDL row into a canonical entity (dedupe by\n * domain) or bump an existing entity's usage counter. Returns the entity plus\n * its portable `entityRef` (null for PDL-only entities). Requires a session.\n */\nexport async function selectEntity(\n config: SifaApiConfig,\n body: EntitySelectRequest,\n options: ApiFetchOptions = {},\n): Promise<EntitySelectResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/select', {\n method: 'POST',\n body,\n credentials: 'include',\n ...options,\n });\n return EntitySelectResponseSchema.parse(data);\n}\n\n/**\n * Grow-on-demand: when the local typeahead misses, resolve the query live via\n * Wikidata, import the org-class matches, and return them. Requires a session.\n * Empty input returns an empty array without a network call.\n */\nexport async function importSearchEntities(\n config: SifaApiConfig,\n query: string,\n options: ApiFetchOptions = {},\n): Promise<EntitySearchResult[]> {\n if (!query.trim()) return [];\n const data = await apiFetch<unknown>(config, '/api/entities/import-search', {\n method: 'POST',\n body: { q: query },\n credentials: 'include',\n ...options,\n });\n return EntityImportSearchResponseSchema.parse(data).results;\n}\n\n/**\n * Grow-on-demand by domain, Branch 1: when a domain-shaped typeahead query\n * misses locally, resolve any notable company whose official website is that\n * domain (Wikidata reverse P856), importing the matches. Read-only w.r.t.\n * minting. `canMint` tells the caller whether to offer the user-initiated\n * \"Add <domain>\" affordance. Requires a session.\n */\nexport async function resolveEntityDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<EntityResolveDomainResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/resolve-domain', {\n method: 'POST',\n body: { domain },\n credentials: 'include',\n ...options,\n });\n return EntityResolveDomainResponseSchema.parse(data);\n}\n\n/**\n * Grow-on-demand by domain, Branch 2 (user-initiated): mint a crawled-tier\n * entity from the domain's own homepage (or resolve it to a notable company if\n * one exists). Throws on a non-2xx response (domain not mintable, or the site\n * yielded nothing usable). Requires a session.\n */\nexport async function mintEntityDomain(\n config: SifaApiConfig,\n domain: string,\n options: ApiFetchOptions = {},\n): Promise<EntityMintDomainResponse> {\n const data = await apiFetch<unknown>(config, '/api/entities/mint-domain', {\n method: 'POST',\n body: { domain },\n credentials: 'include',\n ...options,\n });\n return EntityMintDomainResponseSchema.parse(data);\n}\n","import { apiWrite, type ApiFetchOptions, type SifaApiConfig, type WriteResult } from '../client.js';\nimport type { OrgClaimRequestInput } from '../../schemas/write/org-claim.js';\nimport type {\n OrgDomainChallengeRequestInput,\n OrgDomainVerifyRequestInput,\n OrgNotificationEmailRequestInput,\n OrgProfileUpdateRequestInput,\n} from '../../schemas/write/org-settings.js';\n\n/** How a single entity binding was resolved during a claim. */\nexport interface OrgClaimBinding {\n entityId: number;\n entityRef: string;\n validatedBy: string | null;\n status: 'active' | 'pending';\n dissolved: boolean;\n}\n\n/** The public org-profile echo returned by claim / update endpoints (no `contact`). */\nexport interface OrgProfileEcho {\n name: string;\n description: string | null;\n website: string | null;\n entityRefs: string[];\n}\n\n/** Response body of `POST /api/org/claim`. */\nexport interface OrgClaimResult {\n orgDid: string;\n status: 'active' | 'review';\n bindings: OrgClaimBinding[];\n orgProfile: OrgProfileEcho;\n}\n\n/** Response body of `PUT /api/org/profile`. */\nexport interface OrgProfileUpdateResult {\n ok: boolean;\n orgProfile: OrgProfileEcho;\n}\n\n/** Response body of `POST /api/org/domains/challenge`. */\nexport interface OrgDomainChallengeResult {\n domain: string;\n txtRecordName: string;\n txtRecordValue: string;\n}\n\n/** Response body of `POST /api/org/domains/verify` (happy path). */\nexport interface OrgDomainVerifyResult {\n status: 'verified' | 'pending';\n domain: string;\n}\n\n/** Response body of `POST /api/org/notification-emails`. */\nexport interface OrgNotificationEmailAddResult {\n ok: boolean;\n status: string;\n}\n\n/** Response body of `DELETE /api/org/notification-emails`. */\nexport interface OrgNotificationEmailRemoveResult {\n ok: boolean;\n removed: number;\n}\n\n/**\n * Finalize an org profile claim (`POST /api/org/claim`). Auth-gated (org-claim\n * JIT scope) and floor-checked server-side. Never throws -- returns the\n * structured {@link OrgClaimResult} folded into a {@link WriteResult} on success,\n * or `{ success: false, error, pdsHost? }` on failure.\n */\nexport function submitOrgClaim(\n config: SifaApiConfig,\n body: OrgClaimRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgClaimResult>> {\n return apiWrite<Partial<OrgClaimResult>>(config, '/api/org/claim', 'POST', { body, ...options });\n}\n\n/**\n * Edit the org record (`PUT /api/org/profile`). Fresh-from-body server-side PUT\n * (a cleared optional field is dropped, no spread-merge). Never throws.\n */\nexport function updateOrgProfile(\n config: SifaApiConfig,\n body: OrgProfileUpdateRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgProfileUpdateResult>> {\n return apiWrite<Partial<OrgProfileUpdateResult>>(config, '/api/org/profile', 'PUT', {\n body,\n ...options,\n });\n}\n\n/**\n * Issue a one-time DNS TXT domain challenge (`POST /api/org/domains/challenge`).\n * Returns the TXT record name + value the org must publish. Never throws.\n */\nexport function requestOrgDomainChallenge(\n config: SifaApiConfig,\n body: OrgDomainChallengeRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgDomainChallengeResult>> {\n return apiWrite<Partial<OrgDomainChallengeResult>>(config, '/api/org/domains/challenge', 'POST', {\n body,\n ...options,\n });\n}\n\n/**\n * Verify a DNS TXT domain challenge (`POST /api/org/domains/verify`). On success\n * `status` is `verified` or `pending`. Expired / confusable / not-found map to\n * non-2xx server responses and surface as `{ success: false, error }`. Never\n * throws.\n */\nexport function verifyOrgDomain(\n config: SifaApiConfig,\n body: OrgDomainVerifyRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgDomainVerifyResult>> {\n return apiWrite<Partial<OrgDomainVerifyResult>>(config, '/api/org/domains/verify', 'POST', {\n body,\n ...options,\n });\n}\n\n/**\n * Add an org notification email (`POST /api/org/notification-emails`). The\n * address must use a domain the org controls (checked server-side). An\n * individual verification email is enqueued through the (dormant) sending\n * pipeline. Never throws.\n */\nexport function addOrgNotificationEmail(\n config: SifaApiConfig,\n body: OrgNotificationEmailRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgNotificationEmailAddResult>> {\n return apiWrite<Partial<OrgNotificationEmailAddResult>>(\n config,\n '/api/org/notification-emails',\n 'POST',\n { body, ...options },\n );\n}\n\n/**\n * Remove an org notification email (`DELETE /api/org/notification-emails`).\n * Never throws.\n */\nexport function removeOrgNotificationEmail(\n config: SifaApiConfig,\n body: OrgNotificationEmailRequestInput,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult & Partial<OrgNotificationEmailRemoveResult>> {\n return apiWrite<Partial<OrgNotificationEmailRemoveResult>>(\n config,\n '/api/org/notification-emails',\n 'DELETE',\n { body, ...options },\n );\n}\n","/**\n * Canonical rule for picking the \"primary\" position to surface on profile cards,\n * social previews, and structured-data outputs.\n *\n * Without this shared helper, different surfaces (visible hero, OG image,\n * <meta description>, JSON-LD) re-derived \"primary\" inconsistently and diverged\n * for users with multiple concurrent roles.\n *\n * A `hidden` position is one the user chose not to show on their public profile.\n * It is never surfaced as the featured role — hidden wins over `primary`, so a\n * role flagged both hidden and primary is excluded rather than featured.\n *\n * Rules (in order):\n * 1. A position the user explicitly flagged `primary` AND that is still active AND not hidden.\n * 2. Otherwise, the active, non-hidden position with the most recent `startedAt`.\n * 3. Otherwise, undefined (no eligible position).\n */\n\nexport interface PrimaryPositionCandidate {\n startedAt?: string;\n endedAt?: string;\n primary?: boolean;\n hidden?: boolean;\n}\n\nexport function pickPrimaryPosition<T extends PrimaryPositionCandidate>(\n positions: readonly T[] | undefined,\n): T | undefined {\n if (!positions || positions.length === 0) return undefined;\n\n const active = positions.filter((p) => !p.endedAt && !p.hidden);\n if (active.length === 0) return undefined;\n\n const flagged = active.find((p) => p.primary === true);\n if (flagged) return flagged;\n\n return [...active].sort((a, b) => (b.startedAt ?? '').localeCompare(a.startedAt ?? ''))[0];\n}\n","/**\n * Compact professional summary derived from a {@link ProfileView}.\n *\n * The full `id.sifa.getProfileView` payload carries every section (all\n * positions, education, skills, publications, talks, and more). Third-party\n * surfaces that only want to show \"who is this, what do they do now\" — a badge,\n * a maintainer card, a byline — need a much smaller shape. This is that shape,\n * derived with the same canonical rules the Sifa web app uses (see\n * {@link pickPrimaryPosition}) so an embedded summary matches the profile page.\n *\n * Pure and I/O-free: pass it a view you already fetched. For the fetch +\n * summarize convenience, use `fetchProfileSummary` from `@singi-labs/sifa-sdk`.\n */\n\nimport type { ProfileView } from '../types/profile-view.js';\nimport { pickPrimaryPosition } from './primary-position.js';\n\nexport interface ProfileSummary {\n did: string;\n handle: string;\n displayName?: string;\n avatar?: string;\n pronouns?: string;\n headline?: string;\n /** Title of the current primary role, if the person has an active position. */\n currentTitle?: string;\n /** Current employer: the resolved entity name when linked, else the free-text company. */\n currentCompany?: string;\n /** Skill names in the order the AppView returns them, capped by `maxSkills`. */\n topSkills: string[];\n /** Whether the profile is claimed by its owner (vs an unclaimed placeholder). */\n claimed: boolean;\n}\n\nexport interface SummarizeProfileViewOptions {\n /** Maximum number of skills to include in `topSkills`. Default 5; negatives clamp to 0. */\n maxSkills?: number;\n}\n\nconst DEFAULT_MAX_SKILLS = 5;\n\nexport function summarizeProfileView(\n view: ProfileView,\n options: SummarizeProfileViewOptions = {},\n): ProfileSummary {\n const limit = Math.max(0, options.maxSkills ?? DEFAULT_MAX_SKILLS);\n const primary = pickPrimaryPosition(view.positions);\n\n return {\n did: view.did,\n handle: view.handle,\n displayName: view.displayName,\n avatar: view.avatar,\n pronouns: view.pronouns,\n headline: view.headline,\n currentTitle: primary?.title,\n currentCompany: primary ? (primary.entityName ?? primary.company) : undefined,\n topSkills: (view.skills ?? []).slice(0, limit).map((s) => s.name),\n claimed: view.claimed ?? false,\n };\n}\n","import {\n summarizeProfileView,\n type ProfileSummary,\n type SummarizeProfileViewOptions,\n} from '../../logic/profile-summary.js';\nimport { fetchGetProfileView } from './get-profile-view.js';\nimport type { ApiFetchOptions, SifaApiConfig } from '../client.js';\n\n/**\n * Fetch the aggregated public profile via `id.sifa.getProfileView` and reduce it\n * to a compact {@link ProfileSummary} (identity, headline, current role/employer,\n * top skills). Convenience over `fetchGetProfileView` + `summarizeProfileView`,\n * for third-party surfaces that only want the headline facts.\n *\n * Returns `null` when the AppView has no profile for the actor. Server-callable\n * (Next.js RSC) and client-callable (Expo, browser).\n */\nexport async function fetchProfileSummary(\n config: SifaApiConfig,\n actor: string,\n options: SummarizeProfileViewOptions & ApiFetchOptions = {},\n): Promise<ProfileSummary | null> {\n const { maxSkills, ...fetchOptions } = options;\n const view = await fetchGetProfileView(config, actor, fetchOptions);\n return view ? summarizeProfileView(view, { maxSkills }) : null;\n}\n","/**\n * Query key factory for TanStack Query.\n *\n * Keys are read-only tuples; the hierarchy matches the SDK's fetcher\n * grouping. Use these instead of inline arrays so consumers can target\n * `queryClient.invalidateQueries({ queryKey: keys.profile.all() })` and\n * similar patterns without typos.\n *\n * Convention: every leaf key starts with the namespace ('sifa') so\n * consumers can invalidate everything Sifa-related in one call.\n */\nexport const sifaQueryKeys = {\n all: () => ['sifa'] as const,\n\n profile: {\n all: () => ['sifa', 'profile'] as const,\n byHandle: (handleOrDid: string) => ['sifa', 'profile', handleOrDid] as const,\n atFundLink: (did: string) => ['sifa', 'profile', 'at-fund-link', did] as const,\n view: (actor: string) => ['sifa', 'profile', 'view', actor] as const,\n externalAccounts: (handleOrDid: string) =>\n ['sifa', 'profile', 'external-accounts', handleOrDid] as const,\n // Session-scoped: the AppView reads the owner from the session cookie, so\n // there is only ever one completeness result per client.\n completeness: () => ['sifa', 'profile', 'completeness'] as const,\n },\n\n position: {\n all: () => ['sifa', 'position'] as const,\n byOwner: (did: string) => ['sifa', 'position', 'by-owner', did] as const,\n // Session-scoped: the AppView reads the owner from the session cookie.\n unlinked: () => ['sifa', 'position', 'unlinked'] as const,\n },\n\n // Aggregate inbox counts for the header bell badge (session-scoped). The first\n // aggregate namespace: it fans in across confirmations, endorsements, drift,\n // unlinked positions and profile completeness on the server.\n inbox: {\n all: () => ['sifa', 'inbox'] as const,\n counts: () => ['sifa', 'inbox', 'counts'] as const,\n },\n\n search: {\n all: () => ['sifa', 'search'] as const,\n profiles: (filters: Record<string, unknown>) =>\n ['sifa', 'search', 'profiles', filters] as const,\n companies: (filters: Record<string, unknown>) =>\n ['sifa', 'search', 'companies', filters] as const,\n skills: (query: string) => ['sifa', 'search', 'skills', query] as const,\n canonicalSkills: (query: string, limit: number) =>\n ['sifa', 'search', 'canonical-skills', query, limit] as const,\n filters: () => ['sifa', 'search', 'filters'] as const,\n },\n\n entity: {\n all: () => ['sifa', 'entity'] as const,\n search: (query: string, limit: number) => ['sifa', 'entity', 'search', query, limit] as const,\n },\n\n discovery: {\n all: () => ['sifa', 'discovery'] as const,\n similar: (did: string, limit: number) => ['sifa', 'discovery', 'similar', did, limit] as const,\n suggestions: (opts: Record<string, unknown>) =>\n ['sifa', 'discovery', 'suggestions', opts] as const,\n suggestionCount: (since: string | undefined) =>\n ['sifa', 'discovery', 'suggestion-count', since ?? null] as const,\n featured: () => ['sifa', 'discovery', 'featured'] as const,\n },\n\n follow: {\n all: () => ['sifa', 'follow'] as const,\n following: (opts: Record<string, unknown>) => ['sifa', 'follow', 'following', opts] as const,\n followers: (handle: string) => ['sifa', 'follow', 'followers', handle] as const,\n followingOf: (handle: string) => ['sifa', 'follow', 'following-of', handle] as const,\n feed: (opts: Record<string, unknown>) => ['sifa', 'follow', 'feed', opts] as const,\n mutuals: (handle: string) => ['sifa', 'follow', 'mutuals', handle] as const,\n blueskySuggestions: () => ['sifa', 'follow', 'bluesky-suggestions'] as const,\n },\n\n admin: {\n all: () => ['sifa', 'admin'] as const,\n featureAllowlist: (flag: string) => ['sifa', 'admin', 'feature-allowlist', flag] as const,\n reviewQueues: () => ['sifa', 'admin', 'review-queues'] as const,\n },\n\n stats: {\n all: () => ['sifa', 'stats'] as const,\n homepage: () => ['sifa', 'stats', 'homepage'] as const,\n },\n\n apps: {\n all: () => ['sifa', 'apps'] as const,\n registry: () => ['sifa', 'apps', 'registry'] as const,\n hidden: () => ['sifa', 'apps', 'hidden'] as const,\n },\n\n auth: {\n all: () => ['sifa', 'auth'] as const,\n // Session-scoped: the AppView reads the account list from the browser's\n // cookies, so there is only ever one list per client.\n accounts: () => ['sifa', 'auth', 'accounts'] as const,\n },\n\n activity: {\n all: () => ['sifa', 'activity'] as const,\n heatmap: (handleOrDid: string, days: number) =>\n ['sifa', 'activity', 'heatmap', handleOrDid, days] as const,\n teaser: (handleOrDid: string) => ['sifa', 'activity', 'teaser', handleOrDid] as const,\n feed: (handleOrDid: string, opts: Record<string, unknown>) =>\n ['sifa', 'activity', 'feed', handleOrDid, opts] as const,\n // Session-scoped: the AppView reads the caller's own hides from their\n // cookie, so there is only ever one list per client.\n hiddenItems: () => ['sifa', 'activity', 'hidden-items'] as const,\n },\n\n github: {\n all: () => ['sifa', 'github'] as const,\n myPullRequests: (opts: { limit?: number; offset?: number }) =>\n ['sifa', 'github', 'my-pull-requests', opts] as const,\n },\n\n endorsement: {\n all: () => ['sifa', 'endorsement'] as const,\n count: (did: string) => ['sifa', 'endorsement', 'count', did] as const,\n // Scoped to the session rather than a DID -- the AppView reads the subject\n // from the session cookie, so there is only ever one inbox per client.\n pending: () => ['sifa', 'endorsement', 'pending'] as const,\n // Also session-scoped: the AppView picks the candidate from the viewer's\n // own follows, dismissals and blocks.\n reciprocity: () => ['sifa', 'endorsement', 'reciprocity'] as const,\n received: (did: string) => ['sifa', 'endorsement', 'received', did] as const,\n },\n\n confirmation: {\n all: () => ['sifa', 'confirmation'] as const,\n // Scoped to the session for the same reason as the endorsement inbox: the\n // AppView reads the subject from the session cookie, so there is only ever\n // one inbox per client.\n pending: () => ['sifa', 'confirmation', 'pending'] as const,\n /** Confirmations this session has given, for the withdraw surface. */\n given: () => ['sifa', 'confirmation', 'given'] as const,\n },\n\n stream: {\n all: () => ['sifa', 'stream'] as const,\n networkCount: (did: string) => ['sifa', 'stream', 'network-count', did] as const,\n },\n\n reactions: {\n all: () => ['sifa', 'reactions'] as const,\n status: (uris: string[]) => ['sifa', 'reactions', 'status', uris] as const,\n accountCheck: (appId: string) => ['sifa', 'reactions', 'account-check', appId] as const,\n },\n\n roadmap: {\n all: () => ['sifa', 'roadmap'] as const,\n votes: () => ['sifa', 'roadmap', 'votes'] as const,\n myVotes: () => ['sifa', 'roadmap', 'my-votes'] as const,\n },\n\n bskyPreferences: {\n all: () => ['sifa', 'bsky-preferences'] as const,\n contentLabels: () => ['sifa', 'bsky-preferences', 'content-labels'] as const,\n },\n\n repoInventory: {\n all: () => ['sifa', 'repo-inventory'] as const,\n list: () => ['sifa', 'repo-inventory', 'list'] as const,\n },\n destructive: {\n all: () => ['sifa', 'destructive'] as const,\n wipePreview: () => ['sifa', 'destructive', 'wipe-preview'] as const,\n },\n} as const;\n\nexport type SifaQueryKey =\n | ReturnType<typeof sifaQueryKeys.all>\n | ReturnType<typeof sifaQueryKeys.profile.all>\n | ReturnType<typeof sifaQueryKeys.profile.byHandle>\n | ReturnType<typeof sifaQueryKeys.profile.atFundLink>\n | ReturnType<typeof sifaQueryKeys.profile.externalAccounts>\n | ReturnType<typeof sifaQueryKeys.profile.completeness>\n | ReturnType<typeof sifaQueryKeys.position.all>\n | ReturnType<typeof sifaQueryKeys.position.byOwner>\n | ReturnType<typeof sifaQueryKeys.position.unlinked>\n | ReturnType<typeof sifaQueryKeys.inbox.all>\n | ReturnType<typeof sifaQueryKeys.inbox.counts>\n | ReturnType<typeof sifaQueryKeys.search.all>\n | ReturnType<typeof sifaQueryKeys.search.profiles>\n | ReturnType<typeof sifaQueryKeys.search.canonicalSkills>\n | ReturnType<typeof sifaQueryKeys.search.skills>\n | ReturnType<typeof sifaQueryKeys.search.filters>\n | ReturnType<typeof sifaQueryKeys.entity.all>\n | ReturnType<typeof sifaQueryKeys.entity.search>\n | ReturnType<typeof sifaQueryKeys.discovery.all>\n | ReturnType<typeof sifaQueryKeys.discovery.similar>\n | ReturnType<typeof sifaQueryKeys.discovery.suggestions>\n | ReturnType<typeof sifaQueryKeys.discovery.suggestionCount>\n | ReturnType<typeof sifaQueryKeys.discovery.featured>\n | ReturnType<typeof sifaQueryKeys.follow.all>\n | ReturnType<typeof sifaQueryKeys.follow.following>\n | ReturnType<typeof sifaQueryKeys.follow.followers>\n | ReturnType<typeof sifaQueryKeys.follow.followingOf>\n | ReturnType<typeof sifaQueryKeys.follow.feed>\n | ReturnType<typeof sifaQueryKeys.follow.mutuals>\n | ReturnType<typeof sifaQueryKeys.follow.blueskySuggestions>\n | ReturnType<typeof sifaQueryKeys.admin.all>\n | ReturnType<typeof sifaQueryKeys.admin.featureAllowlist>\n | ReturnType<typeof sifaQueryKeys.admin.reviewQueues>\n | ReturnType<typeof sifaQueryKeys.stats.all>\n | ReturnType<typeof sifaQueryKeys.stats.homepage>\n | ReturnType<typeof sifaQueryKeys.apps.all>\n | ReturnType<typeof sifaQueryKeys.apps.registry>\n | ReturnType<typeof sifaQueryKeys.apps.hidden>\n | ReturnType<typeof sifaQueryKeys.activity.all>\n | ReturnType<typeof sifaQueryKeys.activity.heatmap>\n | ReturnType<typeof sifaQueryKeys.activity.teaser>\n | ReturnType<typeof sifaQueryKeys.activity.feed>\n | ReturnType<typeof sifaQueryKeys.activity.hiddenItems>\n | ReturnType<typeof sifaQueryKeys.endorsement.all>\n | ReturnType<typeof sifaQueryKeys.endorsement.count>\n | ReturnType<typeof sifaQueryKeys.endorsement.pending>\n | ReturnType<typeof sifaQueryKeys.endorsement.reciprocity>\n | ReturnType<typeof sifaQueryKeys.endorsement.received>\n | ReturnType<typeof sifaQueryKeys.confirmation.all>\n | ReturnType<typeof sifaQueryKeys.confirmation.pending>\n | ReturnType<typeof sifaQueryKeys.confirmation.given>\n | ReturnType<typeof sifaQueryKeys.stream.all>\n | ReturnType<typeof sifaQueryKeys.stream.networkCount>\n | ReturnType<typeof sifaQueryKeys.reactions.all>\n | ReturnType<typeof sifaQueryKeys.reactions.status>\n | ReturnType<typeof sifaQueryKeys.reactions.accountCheck>\n | ReturnType<typeof sifaQueryKeys.roadmap.all>\n | ReturnType<typeof sifaQueryKeys.roadmap.votes>\n | ReturnType<typeof sifaQueryKeys.roadmap.myVotes>\n | ReturnType<typeof sifaQueryKeys.bskyPreferences.all>\n | ReturnType<typeof sifaQueryKeys.bskyPreferences.contentLabels>\n | ReturnType<typeof sifaQueryKeys.destructive.all>\n | ReturnType<typeof sifaQueryKeys.destructive.wipePreview>\n | ReturnType<typeof sifaQueryKeys.repoInventory.all>\n | ReturnType<typeof sifaQueryKeys.repoInventory.list>;\n","import { z } from 'zod';\n\n/**\n * Grapheme-aware refinement matching the AT Protocol lexicon `maxGraphemes`\n * constraint. JS strings are sequences of UTF-16 code units, but lexicon\n * `maxGraphemes` counts user-perceived characters (grapheme clusters), so\n * emoji sequences, regional indicators, ZWJ joins, and combining marks all\n * count as one unit each. We use `Intl.Segmenter` to enforce this correctly.\n */\nexport function maxGraphemes(max: number) {\n return (value: string): boolean => {\n const segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n let count = 0;\n for (const _ of segmenter.segment(value)) {\n count++;\n if (count > max) return false;\n }\n return true;\n };\n}\n\n/** Decentralized identifier, AT Protocol `format: did`. */\nexport const didSchema = z.string().regex(/^did:[a-z]+:[a-zA-Z0-9._:%-]+$/, 'Invalid DID');\n\n/** RFC 3339 datetime with timezone offset, AT Protocol `format: datetime`. */\nexport const datetimeSchema = z.string().datetime({ offset: true });\n\n/**\n * Freeform calendar date for user-facing profile dates (start/end, issued,\n * completed, awarded, published, etc.). Accepts a bare year, year-month,\n * year-month-day, or a full datetime (so a legacy record's RFC-3339 date maps\n * through on backfill without loss). NOT strict `datetime` -- users typically\n * remember only month/year, and LinkedIn-importer writes carry partial dates,\n * so the lexicons document these as freeform `YYYY-MM` / `YYYY-MM-DD`. Record\n * metadata like `createdAt` stays on `datetimeSchema`.\n */\nexport const partialDateSchema = z\n .string()\n .regex(/^\\d{4}(-\\d{2}(-\\d{2}(T.+)?)?)?$/, 'Expected YYYY, YYYY-MM, YYYY-MM-DD, or a datetime');\n\n/** Generic AT-URI, AT Protocol `format: at-uri`. */\nexport const atUriSchema = z.string().regex(/^at:\\/\\/[^\\s]+$/, 'Invalid AT-URI');\n\n/** Content identifier, AT Protocol `format: cid`. Loose validation -- accepts CIDv0 and CIDv1. */\nexport const cidSchema = z\n .string()\n .regex(/^(Qm[1-9A-HJ-NP-Za-km-z]{44}|b[A-Za-z0-9+/=]+)$/, 'Invalid CID');\n\n/** BCP 47 language tag, AT Protocol `format: language`. */\nexport const languageTagSchema = z\n .string()\n .regex(/^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/, 'Invalid BCP 47 language tag');\n\n/** Generic URI, AT Protocol `format: uri`. */\nexport const uriSchema = z.string().url();\n\n/**\n * StrongRef shape from `com.atproto.repo.strongRef` -- pins a record by both\n * AT-URI (identity) and CID (version).\n */\nexport const strongRefSchema = z.object({\n uri: atUriSchema,\n cid: cidSchema,\n});\n\n/**\n * Reference to an `id.sifa.profile.skill` record by AT-URI. Mirrors\n * `id.sifa.defs#skillRef`, which carries no CID at all: skills are mutable\n * records in the same user's repo, so the reference resolves live and tracks\n * edits to the target.\n */\nexport const skillRefSchema = z.object({\n uri: atUriSchema,\n});\n\n/**\n * Reference to a record by AT-URI, with an optional CID. Mirrors\n * `id.sifa.defs#externalRecordRef`. Unlike a strongRef the CID is optional:\n * consumers resolve the AT-URI live so the reference tracks edits to the\n * target, and the CID is a best-effort integrity hint only.\n */\nexport const externalRecordRefSchema = z.object({\n uri: atUriSchema,\n cid: cidSchema.optional(),\n});\n\n/**\n * Shared reference to an organization or person named by a record. Mirrors\n * `id.sifa.defs#agentRef`. `name` is a point-in-time snapshot label captured\n * when the record was saved; `did` and `entityRef` are the durable identity and\n * should be resolved live. `name` is required so an empty object cannot validate\n * as a no-op. `.passthrough()` (not `.strict()`): external apps may emit fields a\n * newer schema will define, and dropping them on a round-trip would silently\n * lose data.\n */\nexport const agentRefSchema = z\n .object({\n name: z.string().min(1).refine(maxGraphemes(256)).max(2560),\n did: didSchema.optional(),\n entityRef: uriSchema.optional(),\n })\n .passthrough();\n\nexport type AgentRef = z.infer<typeof agentRefSchema>;\n\n/**\n * Self-labels shape from `com.atproto.label.defs#selfLabels`. Modelled\n * permissively because clients rarely construct this directly; the AppView\n * handles label validation.\n */\nexport const selfLabelsSchema = z.object({\n $type: z.literal('com.atproto.label.defs#selfLabels').optional(),\n values: z.array(z.object({ val: z.string() })),\n});\n","import { z } from 'zod';\n\nimport {\n datetimeSchema,\n didSchema,\n maxGraphemes,\n partialDateSchema,\n externalRecordRefSchema,\n selfLabelsSchema,\n strongRefSchema,\n uriSchema,\n} from './shared.js';\n\n/**\n * A person named as a member of a project. Mirrors `id.sifa.defs#projectMemberRef`.\n *\n * A claim by the record author, not a fact: the named person carries a display\n * name, avatar, and profile link only once they publish a matching\n * `id.sifa.confirmation`. `role` is display only, since a record living in\n * someone else's repository cannot grant write access to anything.\n */\nexport const projectMemberRefSchema = z.object({\n did: didSchema,\n role: z.string().optional(),\n title: z.string().refine(maxGraphemes(128)).max(1280).optional(),\n});\n\nexport type ProjectMemberRef = z.infer<typeof projectMemberRefSchema>;\n\n/** Zod schema for `id.sifa.profile.project` records. */\nexport const ProfileProjectRecordSchema = z.object({\n name: z.string().min(1).refine(maxGraphemes(256)).max(2560),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n url: uriSchema.optional(),\n members: z.array(projectMemberRefSchema).max(50).optional(),\n /**\n * The canonical `id.sifa.project.self` this personal entry corresponds to.\n * A composition link. For the same project recorded on someone else's\n * profile, see `sameAs`.\n */\n projectRef: strongRefSchema.optional(),\n /**\n * The same project as recorded on another person's profile. Each side stays\n * its own record; this only says the two describe one thing. Resolves by\n * AT-URI, since they will keep editing their copy.\n */\n sameAs: externalRecordRefSchema.optional(),\n position: strongRefSchema.optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n labels: selfLabelsSchema.optional(),\n createdAt: datetimeSchema,\n});\n\nexport type ProfileProjectRecord = z.infer<typeof ProfileProjectRecordSchema>;\n","import { z } from 'zod';\n\nimport {\n datetimeSchema,\n didSchema,\n externalRecordRefSchema,\n maxGraphemes,\n partialDateSchema,\n selfLabelsSchema,\n uriSchema,\n} from './shared.js';\nimport { projectMemberRefSchema } from './profile-project.js';\n\n/** Collection NSID for involvement records. Pass to the generic record helpers. */\nexport const PROFILE_INVOLVEMENT_NSID = 'id.sifa.profile.involvement';\n\n/**\n * A public artifact proving a piece of work. Mirrors `id.sifa.defs#artifactLink`.\n * `kind` is an open enum (bare-string knownValues), so any string is accepted.\n * `.passthrough()` keeps unknown fields a newer client or co-writer may emit.\n */\nexport const ArtifactLinkSchema = z\n .object({\n url: uriSchema,\n kind: z.string().optional(),\n label: z.string().refine(maxGraphemes(200)).max(2000).optional(),\n })\n .passthrough();\n\nexport type ArtifactLink = z.infer<typeof ArtifactLinkSchema>;\n\n/**\n * Zod schema for `id.sifa.profile.involvement` records.\n *\n * `.passthrough()` (not `.strict()`): external apps (Verak, weareonhire)\n * co-write `id.sifa.*`, so an older SDK must not reject a record carrying a\n * field it doesn't know yet. `kind` is an open enum matching the lexicon's\n * knownValues but accepting any string for the same forward-compat reason.\n */\nexport const ProfileInvolvementRecordSchema = z\n .object({\n kind: z.string(),\n upstream: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n upstreamDid: didSchema.optional(),\n upstreamUrl: uriSchema.optional(),\n role: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n links: z.array(ArtifactLinkSchema).max(50).optional(),\n // Portable org entity identifier (Wikidata/ROR/LEI URI) from the resolver\n // typeahead, constrained to http(s) so a script scheme is never a valid ref.\n entityRef: z\n .string()\n .url()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'entityRef must be an http(s) URL' })\n .max(2048)\n .optional(),\n // community.lexicon.location.address — validated at the app layer.\n location: z.unknown().optional(),\n // id.sifa.defs#skillRef references (at-uri to a skill record in the same repo).\n skills: z\n .array(z.object({ uri: z.string() }))\n .max(50)\n .optional(),\n labels: selfLabelsSchema.optional(),\n collaborators: z.array(projectMemberRefSchema).max(50).optional(),\n sameAs: externalRecordRefSchema.optional(),\n createdAt: datetimeSchema,\n })\n .passthrough();\n\nexport type ProfileInvolvementRecord = z.infer<typeof ProfileInvolvementRecordSchema>;\n","import { z } from 'zod';\n\nimport { ArtifactLinkSchema } from './profile-involvement.js';\nimport {\n datetimeSchema,\n didSchema,\n maxGraphemes,\n partialDateSchema,\n selfLabelsSchema,\n} from './shared.js';\n\n// Portable entity identifier (Wikidata/ROR/LEI URI) from the typeahead. Constrained\n// to http(s) so a script-bearing scheme is never a valid ref (#159). An investment\n// carries two of these -- the company and the vehicle -- so the check is shared.\nconst entityRefField = z\n .string()\n .url()\n .refine((s) => /^https?:\\/\\//i.test(s), { message: 'entityRef must be an http(s) URL' })\n .max(2048)\n .optional();\n\n/**\n * A deliberately structured amount. Free text was rejected here: an unparseable\n * money string is worse than no amount at all, and cannot be repaired once people\n * have written them.\n */\nexport const InvestmentAmountSchema = z.object({\n /** Whole major currency units (euros, not cents). Cheque sizes are round numbers. */\n value: z.number().int().min(0),\n /** ISO 4217 three-letter code, uppercase. */\n currency: z.string().length(3),\n});\n\n/** Collection NSID for investment records. */\nexport const PROFILE_INVESTMENT_NSID = 'id.sifa.profile.investment';\n\n/** Zod schema for `id.sifa.profile.investment` records. */\nexport const ProfileInvestmentRecordSchema = z\n .object({\n /** For a limited-partner entry this names the fund, not a portfolio company. */\n company: z.string().min(1).refine(maxGraphemes(256)).max(2560),\n companyDid: didSchema.optional(),\n entityRef: entityRefField,\n role: z.string().optional(),\n stage: z.string().optional(),\n status: z.string().optional(),\n /** The vehicle the capital went through. Absent for a cheque in the person's own name. */\n via: z.string().refine(maxGraphemes(256)).max(2560).optional(),\n viaDid: didSchema.optional(),\n viaEntityRef: entityRefField,\n /**\n * Optional and empty by default. Cheque size is a personal financial disclosure,\n * and clients must not prompt for it.\n */\n amount: InvestmentAmountSchema.optional(),\n startedAt: partialDateSchema.optional(),\n endedAt: partialDateSchema.optional(),\n description: z.string().refine(maxGraphemes(5000)).max(50000).optional(),\n links: z.array(ArtifactLinkSchema).max(50).optional(),\n labels: selfLabelsSchema.optional(),\n createdAt: datetimeSchema,\n })\n .passthrough();\n\nexport type ProfileInvestmentRecord = z.infer<typeof ProfileInvestmentRecordSchema>;\n","import { PROFILE_INVESTMENT_NSID } from '../../schemas/profile-investment.js';\nimport { createRecord, updateRecord, deleteRecord } from './records.js';\nimport type { ApiFetchOptions, CreateResult, SifaApiConfig, WriteResult } from '../client.js';\n\nexport type { CreateResult, WriteResult } from '../client.js';\n\n/**\n * Typed wrappers over the generic record routes for\n * `id.sifa.profile.investment`. sifa-api serves every collection without a\n * bespoke handler through `POST|PUT|DELETE /api/profile/records/<collection>`,\n * so these exist for call-site readability, not for a different endpoint.\n *\n * Never throw -- inspect `result.success` and use `result.error` /\n * `result.pdsHost` for UI messaging.\n */\nexport function createInvestment(\n config: SifaApiConfig,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return createRecord(config, PROFILE_INVESTMENT_NSID, data, options);\n}\n\n/** Update an existing investment by `rkey`. */\nexport function updateInvestment(\n config: SifaApiConfig,\n rkey: string,\n data: Record<string, unknown>,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return updateRecord(config, PROFILE_INVESTMENT_NSID, rkey, data, options);\n}\n\n/** Delete an investment by `rkey`. */\nexport function deleteInvestment(\n config: SifaApiConfig,\n rkey: string,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return deleteRecord(config, PROFILE_INVESTMENT_NSID, rkey, options);\n}\n"]}