{"version":3,"sources":["../src/client.ts","../src/auth/oauth.ts","../src/places/places.ts","../src/tree/pedigree.ts","../src/utils/gedcom-converter.ts"],"names":["parentId"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * FamilySearch SDK Client\n *\n * A modern, TypeScript-first SDK for FamilySearch API v3\n *\n * Features:\n * - Full TypeScript support with comprehensive type definitions\n * - OAuth v3 compatible\n * - Promise-based API\n * - Environment support (production, beta, integration)\n * - Configurable logging\n */\n\nimport type {\n\tEnvironmentConfig,\n\tFamilySearchApiError,\n\tFamilySearchApiResponse,\n\tFamilySearchEnvironment,\n\tFamilySearchPlace,\n\tFamilySearchPerson,\n\tFamilySearchSDKConfig,\n\tFamilySearchUser,\n\tPersonWithRelationships,\n\tPersonNotesResponse,\n\tPersonMemoriesResponse,\n\tPersonSearchResponse,\n\tPedigreeData,\n\tRelationshipDetails,\n\tSDKLogger,\n} from \"./types\";\n\n// Environment configuration\nconst ENVIRONMENT_CONFIGS: Record<FamilySearchEnvironment, EnvironmentConfig> =\n\t{\n\t\tproduction: {\n\t\t\tidentHost: \"https://ident.familysearch.org\",\n\t\t\tplatformHost: \"https://api.familysearch.org\",\n\t\t},\n\t\tbeta: {\n\t\t\tidentHost: \"https://identbeta.familysearch.org\",\n\t\t\tplatformHost: \"https://apibeta.familysearch.org\",\n\t\t},\n\t\tintegration: {\n\t\t\tidentHost: \"https://identint.familysearch.org\",\n\t\t\tplatformHost: \"https://api-integ.familysearch.org\",\n\t\t},\n\t};\n\n// Default no-op logger\nconst noopLogger: SDKLogger = {\n\tlog: () => {},\n\twarn: () => {},\n\terror: () => {},\n};\n\n/**\n * FamilySearch SDK Client\n *\n * @example\n * ```typescript\n * const sdk = new FamilySearchSDK({\n *   environment: 'production',\n *   accessToken: 'your-oauth-token'\n * });\n *\n * const user = await sdk.getCurrentUser();\n * console.log(user?.displayName);\n * ```\n */\nexport class FamilySearchSDK {\n\tprivate environment: FamilySearchEnvironment;\n\tprivate accessToken: string | null = null;\n\tprivate appKey: string | null = null;\n\tprivate logger: SDKLogger;\n\n\tconstructor(config: FamilySearchSDKConfig = {}) {\n\t\tthis.environment = config.environment || \"integration\";\n\t\tthis.accessToken = config.accessToken || null;\n\t\tthis.appKey = config.appKey || null;\n\t\tthis.logger = config.logger || noopLogger;\n\t}\n\n\t/**\n\t * Get the current environment\n\t */\n\tgetEnvironment(): FamilySearchEnvironment {\n\t\treturn this.environment;\n\t}\n\n\t/**\n\t * Set OAuth access token\n\t */\n\tsetAccessToken(token: string): void {\n\t\tthis.accessToken = token;\n\t}\n\n\t/**\n\t * Get current access token\n\t */\n\tgetAccessToken(): string | null {\n\t\treturn this.accessToken;\n\t}\n\n\t/**\n\t * Clear access token\n\t */\n\tclearAccessToken(): void {\n\t\tthis.accessToken = null;\n\t}\n\n\t/**\n\t * Check if SDK has a valid access token\n\t */\n\thasAccessToken(): boolean {\n\t\treturn !!this.accessToken;\n\t}\n\n\t/**\n\t * Get environment configuration\n\t */\n\tgetConfig(): EnvironmentConfig {\n\t\treturn ENVIRONMENT_CONFIGS[this.environment];\n\t}\n\n\t/**\n\t * Make authenticated API request\n\t */\n\tprivate async request<T>(\n\t\turl: string,\n\t\toptions: RequestInit = {}\n\t): Promise<FamilySearchApiResponse<T>> {\n\t\tconst config = this.getConfig();\n\t\tconst fullUrl = url.startsWith(\"http\")\n\t\t\t? url\n\t\t\t: `${config.platformHost}${url}`;\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tAccept: \"application/json\",\n\t\t\t...(options.headers as Record<string, string>),\n\t\t};\n\n\t\t// Add authorization header if token is available\n\t\t// FamilySearch API endpoints that require auth start with /platform/\n\t\tconst requiresAuth = fullUrl.includes(\"/platform/\");\n\t\tif (this.accessToken && requiresAuth) {\n\t\t\theaders.Authorization = `Bearer ${this.accessToken}`;\n\t\t}\n\n\t\t// Add app key if available\n\t\tif (this.appKey) {\n\t\t\theaders[\"X-FS-App-Key\"] = this.appKey;\n\t\t}\n\n\t\tthis.logger.log(\n\t\t\t`[FamilySearch SDK] ${options.method || \"GET\"} ${fullUrl}`\n\t\t);\n\n\t\ttry {\n\t\t\tconst response = await fetch(fullUrl, {\n\t\t\t\t...options,\n\t\t\t\theaders,\n\t\t\t});\n\n\t\t\tconst responseHeaders: Record<string, string> = {};\n\t\t\tresponse.headers.forEach((value, key) => {\n\t\t\t\tresponseHeaders[key] = value;\n\t\t\t});\n\n\t\t\tlet data: T | undefined;\n\t\t\tconst contentType = response.headers.get(\"content-type\");\n\t\t\tif (contentType && contentType.includes(\"application/json\")) {\n\t\t\t\ttry {\n\t\t\t\t\tdata = await response.json();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.logger.warn(\n\t\t\t\t\t\t\"[FamilySearch SDK] Failed to parse JSON response:\",\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst apiResponse: FamilySearchApiResponse<T> = {\n\t\t\t\tdata,\n\t\t\t\tstatusCode: response.status,\n\t\t\t\tstatusText: response.statusText,\n\t\t\t\theaders: responseHeaders,\n\t\t\t};\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = new Error(\n\t\t\t\t\t`FamilySearch API error: ${response.status} ${response.statusText}`\n\t\t\t\t) as FamilySearchApiError;\n\t\t\t\terror.statusCode = response.status;\n\t\t\t\terror.response = apiResponse;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn apiResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\"[FamilySearch SDK] Request failed:\", error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * GET request\n\t */\n\tasync get<T>(\n\t\turl: string,\n\t\toptions: RequestInit = {}\n\t): Promise<FamilySearchApiResponse<T>> {\n\t\treturn this.request<T>(url, { ...options, method: \"GET\" });\n\t}\n\n\t/**\n\t * POST request\n\t */\n\tasync post<T>(\n\t\turl: string,\n\t\tbody?: unknown,\n\t\toptions: RequestInit = {}\n\t): Promise<FamilySearchApiResponse<T>> {\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...(options.headers as Record<string, string>),\n\t\t};\n\n\t\treturn this.request<T>(url, {\n\t\t\t...options,\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\t}\n\n\t/**\n\t * PUT request\n\t */\n\tasync put<T>(\n\t\turl: string,\n\t\tbody?: unknown,\n\t\toptions: RequestInit = {}\n\t): Promise<FamilySearchApiResponse<T>> {\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...(options.headers as Record<string, string>),\n\t\t};\n\n\t\treturn this.request<T>(url, {\n\t\t\t...options,\n\t\t\tmethod: \"PUT\",\n\t\t\theaders,\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\t}\n\n\t/**\n\t * DELETE request\n\t */\n\tasync delete<T>(\n\t\turl: string,\n\t\toptions: RequestInit = {}\n\t): Promise<FamilySearchApiResponse<T>> {\n\t\treturn this.request<T>(url, { ...options, method: \"DELETE\" });\n\t}\n\n\t// ====================================\n\t// User API\n\t// ====================================\n\n\t/**\n\t * Get current authenticated user\n\t */\n\tasync getCurrentUser(): Promise<FamilySearchUser | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<{ users: FamilySearchUser[] }>(\n\t\t\t\t\"/platform/users/current\"\n\t\t\t);\n\n\t\t\tconst user = response.data?.users?.[0];\n\t\t\treturn user || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t\"[FamilySearch SDK] Failed to get current user:\",\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// ====================================\n\t// Tree/Pedigree API\n\t// ====================================\n\n\t/**\n\t * Get person by ID\n\t */\n\tasync getPerson(personId: string): Promise<FamilySearchPerson | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<{ persons: FamilySearchPerson[] }>(\n\t\t\t\t`/platform/tree/persons/${personId}`\n\t\t\t);\n\n\t\t\tconst person = response.data?.persons?.[0];\n\t\t\treturn person || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get person ${personId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get person with full details including sources\n\t */\n\tasync getPersonWithDetails(\n\t\tpersonId: string\n\t): Promise<PersonWithRelationships | null> {\n\t\ttry {\n\t\t\tconst response = await this.get(\n\t\t\t\t`/platform/tree/persons/${personId}?sourceDescriptions=true`\n\t\t\t);\n\t\t\treturn (response.data as PersonWithRelationships) || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get person details ${personId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get notes for a person\n\t */\n\tasync getPersonNotes(\n\t\tpersonId: string\n\t): Promise<PersonNotesResponse | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<PersonNotesResponse>(\n\t\t\t\t`/platform/tree/persons/${personId}/notes`\n\t\t\t);\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get notes for ${personId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get memories for a person\n\t */\n\tasync getPersonMemories(\n\t\tpersonId: string\n\t): Promise<PersonMemoriesResponse | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<PersonMemoriesResponse>(\n\t\t\t\t`/platform/tree/persons/${personId}/memories`\n\t\t\t);\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get memories for ${personId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get couple relationship details\n\t */\n\tasync getCoupleRelationship(\n\t\trelationshipId: string\n\t): Promise<RelationshipDetails | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<RelationshipDetails>(\n\t\t\t\t`/platform/tree/couple-relationships/${relationshipId}`\n\t\t\t);\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get couple relationship ${relationshipId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get child-and-parents relationship details\n\t */\n\tasync getChildAndParentsRelationship(\n\t\trelationshipId: string\n\t): Promise<RelationshipDetails | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<RelationshipDetails>(\n\t\t\t\t`/platform/tree/child-and-parents-relationships/${relationshipId}`\n\t\t\t);\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get child-and-parents relationship ${relationshipId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get ancestry for a person\n\t */\n\tasync getAncestry(\n\t\tpersonId: string,\n\t\tgenerations: number = 4\n\t): Promise<FamilySearchApiResponse<PedigreeData>> {\n\t\treturn this.get<PedigreeData>(\n\t\t\t`/platform/tree/ancestry?person=${personId}&generations=${generations}`\n\t\t);\n\t}\n\n\t/**\n\t * Get descendancy for a person\n\t */\n\tasync getDescendancy(\n\t\tpersonId: string,\n\t\tgenerations: number = 2\n\t): Promise<FamilySearchApiResponse<PedigreeData>> {\n\t\treturn this.get<PedigreeData>(\n\t\t\t`/platform/tree/descendancy?person=${personId}&generations=${generations}`\n\t\t);\n\t}\n\n\t/**\n\t * Search for persons\n\t */\n\tasync searchPersons(\n\t\tquery: Record<string, string>,\n\t\toptions: { start?: number; count?: number } = {}\n\t): Promise<FamilySearchApiResponse<PersonSearchResponse>> {\n\t\tconst params = new URLSearchParams({\n\t\t\t...query,\n\t\t\t...(options.start !== undefined && {\n\t\t\t\tstart: options.start.toString(),\n\t\t\t}),\n\t\t\t...(options.count !== undefined && {\n\t\t\t\tcount: options.count.toString(),\n\t\t\t}),\n\t\t});\n\n\t\treturn this.get<PersonSearchResponse>(\n\t\t\t`/platform/tree/search?${params.toString()}`\n\t\t);\n\t}\n\n\t// ====================================\n\t// Places API\n\t// ====================================\n\n\t/**\n\t * Search for places\n\t */\n\tasync searchPlaces(\n\t\tname: string,\n\t\toptions: {\n\t\t\tparentId?: string;\n\t\t\ttypeId?: string;\n\t\t\tdate?: string;\n\t\t\tstart?: number;\n\t\t\tcount?: number;\n\t\t} = {}\n\t): Promise<{ places: FamilySearchPlace[] } | null> {\n\t\ttry {\n\t\t\tconst params = new URLSearchParams({\n\t\t\t\tname,\n\t\t\t\t...(options.parentId && { parentId: options.parentId }),\n\t\t\t\t...(options.typeId && { typeId: options.typeId }),\n\t\t\t\t...(options.date && { date: options.date }),\n\t\t\t\t...(options.start !== undefined && {\n\t\t\t\t\tstart: options.start.toString(),\n\t\t\t\t}),\n\t\t\t\t...(options.count !== undefined && {\n\t\t\t\t\tcount: options.count.toString(),\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tconst response = await this.get<{ places: FamilySearchPlace[] }>(\n\t\t\t\t`/platform/places/search?${params.toString()}`\n\t\t\t);\n\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t\"[FamilySearch SDK] Failed to search places:\",\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get place by ID\n\t */\n\tasync getPlace(placeId: string): Promise<FamilySearchPlace | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<{ places: FamilySearchPlace[] }>(\n\t\t\t\t`/platform/places/${placeId}`\n\t\t\t);\n\n\t\t\tconst place = response.data?.places?.[0];\n\t\t\treturn place || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t`[FamilySearch SDK] Failed to get place ${placeId}:`,\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// ====================================\n\t// Import/Export API\n\t// ====================================\n\n\t/**\n\t * Get GEDCOM export for a person and their ancestors\n\t */\n\tasync exportGEDCOM(personId: string): Promise<string | null> {\n\t\ttry {\n\t\t\tconst response = await this.get<string>(\n\t\t\t\t`/platform/tree/persons/${personId}/gedcomx`,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAccept: \"application/x-gedcomx-v1+json\",\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\n\t\t\treturn response.data || null;\n\t\t} catch (error) {\n\t\t\tthis.logger.error(\n\t\t\t\t\"[FamilySearch SDK] Failed to export GEDCOM:\",\n\t\t\t\terror\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n// ====================================\n// Singleton Instance Management\n// ====================================\n\nlet sdkInstance: FamilySearchSDK | null = null;\n\n/**\n * Initialize the global SDK instance\n */\nexport function initFamilySearchSDK(\n\tconfig: FamilySearchSDKConfig = {}\n): FamilySearchSDK {\n\tif (!sdkInstance) {\n\t\tsdkInstance = new FamilySearchSDK(config);\n\t} else {\n\t\t// Update existing instance with new config\n\t\tif (config.accessToken !== undefined) {\n\t\t\tsdkInstance.setAccessToken(config.accessToken);\n\t\t}\n\t\tif (config.environment !== undefined) {\n\t\t\t// Re-create instance if environment changes\n\t\t\tsdkInstance = new FamilySearchSDK(config);\n\t\t}\n\t}\n\treturn sdkInstance;\n}\n\n/**\n * Get the global SDK instance\n */\nexport function getFamilySearchSDK(): FamilySearchSDK {\n\tif (!sdkInstance) {\n\t\tsdkInstance = new FamilySearchSDK();\n\t}\n\treturn sdkInstance;\n}\n\n/**\n * Create a new SDK instance (for testing or multiple environments)\n */\nexport function createFamilySearchSDK(\n\tconfig: FamilySearchSDKConfig = {}\n): FamilySearchSDK {\n\treturn new FamilySearchSDK(config);\n}\n\n/**\n * Reset the global SDK instance (mainly for testing)\n */\nexport function resetFamilySearchSDK(): void {\n\tsdkInstance = null;\n}\n\n// Export environment configs for external use\nexport { ENVIRONMENT_CONFIGS };\n","/**\n * FamilySearch OAuth Authentication Module\n *\n * Provides OAuth 2.0 authentication utilities for FamilySearch API v3.\n * This module is designed to be framework-agnostic and can be used\n * in any JavaScript/TypeScript environment.\n */\n\nimport type {\n\tFamilySearchEnvironment,\n\tOAuthConfig,\n\tOAuthEndpoints,\n\tOAuthStateValidation,\n\tOAuthTokenResponse,\n} from \"../types\";\n\n// OAuth endpoints by environment\nconst OAUTH_ENDPOINTS: Record<FamilySearchEnvironment, OAuthEndpoints> = {\n\tproduction: {\n\t\tauthorization:\n\t\t\t\"https://ident.familysearch.org/cis-web/oauth2/v3/authorization\",\n\t\ttoken: \"https://ident.familysearch.org/cis-web/oauth2/v3/token\",\n\t\tcurrentUser: \"https://api.familysearch.org/platform/users/current\",\n\t},\n\tbeta: {\n\t\tauthorization:\n\t\t\t\"https://identbeta.familysearch.org/cis-web/oauth2/v3/authorization\",\n\t\ttoken: \"https://identbeta.familysearch.org/cis-web/oauth2/v3/token\",\n\t\tcurrentUser: \"https://apibeta.familysearch.org/platform/users/current\",\n\t},\n\tintegration: {\n\t\tauthorization:\n\t\t\t\"https://identint.familysearch.org/cis-web/oauth2/v3/authorization\",\n\t\ttoken: \"https://identint.familysearch.org/cis-web/oauth2/v3/token\",\n\t\tcurrentUser:\n\t\t\t\"https://api-integ.familysearch.org/platform/users/current\",\n\t},\n};\n\n/**\n * Get OAuth endpoints for a specific environment\n */\nexport function getOAuthEndpoints(\n\tenvironment: FamilySearchEnvironment = \"integration\"\n): OAuthEndpoints {\n\treturn OAUTH_ENDPOINTS[environment];\n}\n\n/**\n * Generate a cryptographically secure random state for CSRF protection\n */\nexport function generateOAuthState(): string {\n\tconst array = new Uint8Array(32);\n\tcrypto.getRandomValues(array);\n\treturn Array.from(array, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n\t\t\"\"\n\t);\n}\n\n/**\n * Build the authorization URL for OAuth flow\n */\nexport function buildAuthorizationUrl(\n\tconfig: OAuthConfig,\n\tstate: string,\n\toptions: {\n\t\tscopes?: string[];\n\t\tprompt?: string;\n\t} = {}\n): string {\n\tconst endpoints = getOAuthEndpoints(config.environment);\n\tconst url = new URL(endpoints.authorization);\n\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", config.clientId);\n\turl.searchParams.set(\"redirect_uri\", config.redirectUri);\n\turl.searchParams.set(\"state\", state);\n\n\tif (options.scopes && options.scopes.length > 0) {\n\t\turl.searchParams.set(\"scope\", options.scopes.join(\" \"));\n\t}\n\n\tif (options.prompt) {\n\t\turl.searchParams.set(\"prompt\", options.prompt);\n\t}\n\n\treturn url.toString();\n}\n\n/**\n * Exchange authorization code for access token\n */\nexport async function exchangeCodeForToken(\n\tcode: string,\n\tconfig: OAuthConfig\n): Promise<OAuthTokenResponse> {\n\tconst endpoints = getOAuthEndpoints(config.environment);\n\n\tconst response = await fetch(endpoints.token, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: code,\n\t\t\tclient_id: config.clientId,\n\t\t\tredirect_uri: config.redirectUri,\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.text();\n\t\tthrow new Error(`Failed to exchange code for token: ${error}`);\n\t}\n\n\treturn response.json();\n}\n\n/**\n * Refresh an access token using a refresh token\n */\nexport async function refreshAccessToken(\n\trefreshToken: string,\n\tconfig: OAuthConfig\n): Promise<OAuthTokenResponse> {\n\tconst endpoints = getOAuthEndpoints(config.environment);\n\n\tconst response = await fetch(endpoints.token, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\trefresh_token: refreshToken,\n\t\t\tclient_id: config.clientId,\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.text();\n\t\tthrow new Error(`Failed to refresh token: ${error}`);\n\t}\n\n\treturn response.json();\n}\n\n/**\n * Validate an access token by making a test API call\n */\nexport async function validateAccessToken(\n\taccessToken: string,\n\tenvironment: FamilySearchEnvironment = \"integration\"\n): Promise<boolean> {\n\tconst endpoints = getOAuthEndpoints(environment);\n\n\ttry {\n\t\tconst response = await fetch(endpoints.currentUser, {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t});\n\n\t\treturn response.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Get user info from access token\n */\nexport async function getUserInfo(\n\taccessToken: string,\n\tenvironment: FamilySearchEnvironment = \"integration\"\n): Promise<{\n\tsub: string;\n\tname?: string;\n\tgiven_name?: string;\n\tfamily_name?: string;\n\temail?: string;\n\temail_verified?: boolean;\n} | null> {\n\tconst endpoints = getOAuthEndpoints(environment);\n\n\ttry {\n\t\tconst response = await fetch(endpoints.currentUser, {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = await response.json();\n\t\tconst fsUser = data.users?.[0];\n\n\t\tif (!fsUser || !fsUser.id) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tsub: fsUser.id,\n\t\t\tname: fsUser.contactName || fsUser.displayName,\n\t\t\tgiven_name: fsUser.givenName,\n\t\t\tfamily_name: fsUser.familyName,\n\t\t\temail: fsUser.email,\n\t\t\temail_verified: fsUser.email ? true : false,\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ====================================\n// Browser-specific OAuth Helpers\n// ====================================\n\n/**\n * Storage keys for OAuth state management\n */\nexport const OAUTH_STORAGE_KEYS = {\n\tstate: \"fs_oauth_state\",\n\tlinkMode: \"fs_oauth_link_mode\",\n\tlang: \"fs_oauth_lang\",\n\tparentUid: \"fs_oauth_parent_uid\",\n} as const;\n\n/**\n * Store OAuth state in localStorage for popup flow\n * Uses localStorage instead of sessionStorage because popup windows\n * don't share sessionStorage with the parent window\n */\nexport function storeOAuthState(\n\tstate: string,\n\toptions: {\n\t\tisLinkMode?: boolean;\n\t\tlang?: string;\n\t\tparentUid?: string;\n\t} = {}\n): void {\n\tif (typeof localStorage === \"undefined\") {\n\t\t// In server-side or non-browser environments, state storage is not available\n\t\t// Callers should handle this by implementing their own state storage mechanism\n\t\tthrow new Error(\n\t\t\t\"localStorage is not available. For server-side usage, implement custom state storage.\"\n\t\t);\n\t}\n\n\tlocalStorage.setItem(OAUTH_STORAGE_KEYS.state, state);\n\n\tif (options.isLinkMode) {\n\t\tlocalStorage.setItem(OAUTH_STORAGE_KEYS.linkMode, \"true\");\n\t} else {\n\t\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.linkMode);\n\t}\n\n\tif (options.lang) {\n\t\tlocalStorage.setItem(OAUTH_STORAGE_KEYS.lang, options.lang);\n\t} else {\n\t\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.lang);\n\t}\n\n\tif (options.parentUid) {\n\t\tlocalStorage.setItem(OAUTH_STORAGE_KEYS.parentUid, options.parentUid);\n\t} else {\n\t\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.parentUid);\n\t}\n}\n\n/**\n * Validate OAuth state from callback and extract metadata\n * Returns invalid state if localStorage is not available (SSR/Node.js environments)\n */\nexport function validateOAuthState(state: string): OAuthStateValidation {\n\tif (typeof localStorage === \"undefined\") {\n\t\t// In server-side environments, return invalid state\n\t\t// Callers should implement their own state validation for SSR\n\t\treturn { valid: false, isLinkMode: false };\n\t}\n\n\tconst storedState = localStorage.getItem(OAUTH_STORAGE_KEYS.state);\n\tconst isLinkMode =\n\t\tlocalStorage.getItem(OAUTH_STORAGE_KEYS.linkMode) === \"true\";\n\tconst lang = localStorage.getItem(OAUTH_STORAGE_KEYS.lang) || undefined;\n\tconst parentUid =\n\t\tlocalStorage.getItem(OAUTH_STORAGE_KEYS.parentUid) || undefined;\n\n\t// Clean up stored values\n\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.state);\n\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.linkMode);\n\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.lang);\n\tlocalStorage.removeItem(OAUTH_STORAGE_KEYS.parentUid);\n\n\treturn {\n\t\tvalid: storedState === state,\n\t\tisLinkMode,\n\t\tlang,\n\t\tparentUid,\n\t};\n}\n\n/**\n * Open OAuth authorization in a popup window\n */\nexport function openOAuthPopup(\n\tauthUrl: string,\n\toptions: {\n\t\twidth?: number;\n\t\theight?: number;\n\t\twindowName?: string;\n\t} = {}\n): Window | null {\n\tif (typeof window === \"undefined\") {\n\t\tthrow new Error(\"window is not available\");\n\t}\n\n\tconst width = options.width || 500;\n\tconst height = options.height || 600;\n\tconst windowName = options.windowName || \"FamilySearch Login\";\n\n\tconst left = window.screenX + (window.outerWidth - width) / 2;\n\tconst top = window.screenY + (window.outerHeight - height) / 2;\n\n\tconst popup = window.open(\n\t\tauthUrl,\n\t\twindowName,\n\t\t`width=${width},height=${height},left=${left},top=${top},toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes`\n\t);\n\n\tif (popup) {\n\t\tpopup.focus();\n\t}\n\n\treturn popup;\n}\n\n/**\n * Parse OAuth callback parameters from URL\n */\nexport function parseCallbackParams(\n\turl: string = typeof window !== \"undefined\" ? window.location.href : \"\"\n): {\n\tcode?: string;\n\tstate?: string;\n\terror?: string;\n\terror_description?: string;\n} {\n\tconst urlObj = new URL(url);\n\tconst params = urlObj.searchParams;\n\n\treturn {\n\t\tcode: params.get(\"code\") || undefined,\n\t\tstate: params.get(\"state\") || undefined,\n\t\terror: params.get(\"error\") || undefined,\n\t\terror_description: params.get(\"error_description\") || undefined,\n\t};\n}\n\n// ====================================\n// Token Storage Helpers\n// ====================================\n\n/**\n * Generate a storage key scoped to a user ID\n */\nexport function getTokenStorageKey(\n\tuserId: string,\n\ttype: \"access\" | \"expires\" | \"refresh\" | \"environment\"\n): string {\n\treturn `fs_token_${userId}_${type}`;\n}\n\n/**\n * Store access token with expiration\n * Per FamilySearch compatibility requirements:\n * - Access tokens stored in sessionStorage (cleared on browser close)\n * - Refresh tokens stored in localStorage (for re-authentication)\n */\nexport function storeTokens(\n\tuserId: string,\n\ttokens: {\n\t\taccessToken: string;\n\t\texpiresAt?: number;\n\t\trefreshToken?: string;\n\t\tenvironment?: string;\n\t}\n): void {\n\tif (typeof sessionStorage === \"undefined\" || typeof localStorage === \"undefined\") {\n\t\tthrow new Error(\"Storage APIs are not available\");\n\t}\n\n\t// Access tokens in sessionStorage (temporary)\n\tsessionStorage.setItem(\n\t\tgetTokenStorageKey(userId, \"access\"),\n\t\ttokens.accessToken\n\t);\n\n\tif (tokens.expiresAt) {\n\t\tsessionStorage.setItem(\n\t\t\tgetTokenStorageKey(userId, \"expires\"),\n\t\t\ttokens.expiresAt.toString()\n\t\t);\n\t}\n\n\t// Refresh tokens in localStorage (persistent)\n\tif (tokens.refreshToken) {\n\t\tlocalStorage.setItem(\n\t\t\tgetTokenStorageKey(userId, \"refresh\"),\n\t\t\ttokens.refreshToken\n\t\t);\n\t}\n\n\tif (tokens.environment) {\n\t\tlocalStorage.setItem(\n\t\t\tgetTokenStorageKey(userId, \"environment\"),\n\t\t\ttokens.environment\n\t\t);\n\t}\n}\n\n/**\n * Get stored access token\n */\nexport function getStoredAccessToken(userId: string): string | null {\n\tif (typeof sessionStorage === \"undefined\") {\n\t\treturn null;\n\t}\n\n\tconst token = sessionStorage.getItem(getTokenStorageKey(userId, \"access\"));\n\tconst expiresAt = sessionStorage.getItem(\n\t\tgetTokenStorageKey(userId, \"expires\")\n\t);\n\n\tif (!token) {\n\t\treturn null;\n\t}\n\n\t// Check expiration with 5-minute buffer\n\tconst EXPIRATION_BUFFER = 5 * 60 * 1000;\n\tif (expiresAt && Date.now() > parseInt(expiresAt) - EXPIRATION_BUFFER) {\n\t\treturn null;\n\t}\n\n\treturn token;\n}\n\n/**\n * Get stored refresh token\n */\nexport function getStoredRefreshToken(userId: string): string | null {\n\tif (typeof localStorage === \"undefined\") {\n\t\treturn null;\n\t}\n\n\treturn localStorage.getItem(getTokenStorageKey(userId, \"refresh\"));\n}\n\n/**\n * Clear all stored tokens for a user\n */\nexport function clearStoredTokens(userId: string): void {\n\tif (typeof sessionStorage !== \"undefined\") {\n\t\tsessionStorage.removeItem(getTokenStorageKey(userId, \"access\"));\n\t\tsessionStorage.removeItem(getTokenStorageKey(userId, \"expires\"));\n\t}\n\n\tif (typeof localStorage !== \"undefined\") {\n\t\tlocalStorage.removeItem(getTokenStorageKey(userId, \"refresh\"));\n\t\tlocalStorage.removeItem(getTokenStorageKey(userId, \"environment\"));\n\t}\n}\n\n/**\n * Clear all FamilySearch tokens from storage\n */\nexport function clearAllTokens(): void {\n\tif (typeof sessionStorage === \"undefined\" || typeof localStorage === \"undefined\") {\n\t\treturn;\n\t}\n\n\tconst keysToRemove: string[] = [];\n\n\t// Find all fs_token_* keys in sessionStorage\n\tfor (let i = 0; i < sessionStorage.length; i++) {\n\t\tconst key = sessionStorage.key(i);\n\t\tif (key && key.startsWith(\"fs_token_\")) {\n\t\t\tkeysToRemove.push(key);\n\t\t}\n\t}\n\n\t// Find all fs_token_* keys in localStorage\n\tfor (let i = 0; i < localStorage.length; i++) {\n\t\tconst key = localStorage.key(i);\n\t\tif (key && key.startsWith(\"fs_token_\")) {\n\t\t\tkeysToRemove.push(key);\n\t\t}\n\t}\n\n\t// Remove from both storages\n\tkeysToRemove.forEach((key) => {\n\t\tsessionStorage.removeItem(key);\n\t\tlocalStorage.removeItem(key);\n\t});\n}\n\nexport { OAUTH_ENDPOINTS };\n","/**\n * FamilySearch Places API Module\n *\n * Provides helpers for searching and retrieving place information\n * from the FamilySearch Places API.\n *\n * API Documentation: https://developers.familysearch.org/main/page/places-endpoints\n */\n\nimport type { FamilySearchSDK } from \"../client\";\nimport type {\n\tPlaceDescription,\n\tPlaceDetailsResponse,\n\tPlaceSearchResponse,\n\tPlaceSearchResult,\n} from \"../types\";\n\n/**\n * Search for places by name\n *\n * @param sdk - FamilySearch SDK instance\n * @param query - The search query string\n * @param options - Optional search parameters\n * @returns Promise with search results\n *\n * @example\n * ```typescript\n * const results = await searchPlaces(sdk, \"London\", { date: \"1850\" });\n * ```\n */\nexport async function searchPlaces(\n\tsdk: FamilySearchSDK,\n\tquery: string,\n\toptions?: {\n\t\tcount?: number;\n\t\tstart?: number;\n\t\tdate?: string;\n\t\tparentId?: string;\n\t}\n): Promise<PlaceSearchResult[]> {\n\t// Build query parameters according to FamilySearch API docs\n\tconst queryParts = [`name:\"${query}\"`];\n\n\t// Add date to query if provided\n\tif (options?.date) {\n\t\tqueryParts.push(`+date:${options.date}`);\n\t}\n\n\t// Add parentId to query if provided\n\tif (options?.parentId) {\n\t\tqueryParts.push(`+parentId:${options.parentId}`);\n\t}\n\n\tconst finalQuery = queryParts.join(\" \");\n\n\tconst params = new URLSearchParams({\n\t\tq: finalQuery,\n\t\t...(options?.count && { count: options.count.toString() }),\n\t\t...(options?.start && { start: options.start.toString() }),\n\t});\n\n\tconst response = await sdk.get<PlaceSearchResponse>(\n\t\t`/platform/places/search?${params.toString()}`\n\t);\n\n\tconst data = response.data || {};\n\n\t// Check if entries exist\n\tif (!data?.entries?.length) {\n\t\t// If we had a date filter and got no results, try again without it\n\t\tif (options?.date) {\n\t\t\tconst { date: _date, ...optionsWithoutDate } = options;\n\t\t\treturn searchPlaces(sdk, query, optionsWithoutDate);\n\t\t}\n\t\treturn [];\n\t}\n\n\t// Transform the response into a cleaner format\n\treturn (\n\t\tdata.entries?.map((entry) => {\n\t\t\tconst place = entry.content?.gedcomx?.places?.[0];\n\t\t\treturn {\n\t\t\t\tid: place?.id || entry.id,\n\t\t\t\ttitle: entry.title,\n\t\t\t\tfullyQualifiedName: entry.title,\n\t\t\t\tnames: place?.names,\n\t\t\t\tstandardized: place?.jurisdiction\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tid: place.jurisdiction.id,\n\t\t\t\t\t\t\tfullyQualifiedName: place.jurisdiction.name,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t\tjurisdiction: place?.jurisdiction,\n\t\t\t\ttemporalDescription: place?.temporalDescription,\n\t\t\t};\n\t\t}) || []\n\t);\n}\n\n/**\n * Get a specific place by its ID\n *\n * @param sdk - FamilySearch SDK instance\n * @param id - The FamilySearch place ID\n * @returns Promise with place details\n */\nexport async function getPlaceById(\n\tsdk: FamilySearchSDK,\n\tid: string\n): Promise<PlaceDescription | null> {\n\tconst response = await sdk.get<PlaceDetailsResponse>(\n\t\t`/platform/places/${id}`\n\t);\n\treturn response.data?.places?.[0] || null;\n}\n\n/**\n * Get child places of a specific place\n *\n * @param sdk - FamilySearch SDK instance\n * @param id - The parent place ID\n * @param options - Optional parameters\n * @returns Promise with child places\n */\nexport async function getPlaceChildren(\n\tsdk: FamilySearchSDK,\n\tid: string,\n\toptions?: {\n\t\tcount?: number;\n\t\tstart?: number;\n\t}\n): Promise<PlaceSearchResult[]> {\n\tconst params = new URLSearchParams({\n\t\t...(options?.count && { count: options.count.toString() }),\n\t\t...(options?.start && { start: options.start.toString() }),\n\t});\n\n\tconst queryString = params.toString();\n\tconst url = `/platform/places/${id}/children${queryString ? `?${queryString}` : \"\"}`;\n\n\tconst response = await sdk.get<PlaceSearchResponse>(url);\n\tconst data = response.data || {};\n\n\t// Transform the response\n\treturn (\n\t\tdata.entries?.map((entry) => {\n\t\t\tconst place = entry.content?.gedcomx?.places?.[0];\n\t\t\treturn {\n\t\t\t\tid: place?.id || entry.id,\n\t\t\t\ttitle: entry.title,\n\t\t\t\tfullyQualifiedName: entry.title,\n\t\t\t\tnames: place?.names,\n\t\t\t\tjurisdiction: place?.jurisdiction,\n\t\t\t};\n\t\t}) || []\n\t);\n}\n\n/**\n * Get detailed information about a place including standardized names and aliases\n *\n * @param sdk - FamilySearch SDK instance\n * @param id - The FamilySearch place ID\n * @returns Promise with detailed place information\n */\nexport async function getPlaceDetails(\n\tsdk: FamilySearchSDK,\n\tid: string\n): Promise<{\n\tid: string;\n\tname: string;\n\tstandardizedName?: string;\n\taliases: string[];\n\tlatitude?: number;\n\tlongitude?: number;\n\tjurisdiction?: string;\n} | null> {\n\tconst place = await getPlaceById(sdk, id);\n\n\tif (!place) {\n\t\treturn null;\n\t}\n\n\t// Extract primary name (first name entry or English name)\n\tconst primaryName =\n\t\tplace.names?.find((n) => n.lang === \"en\")?.value ||\n\t\tplace.names?.[0]?.value ||\n\t\t\"\";\n\n\t// Extract all alternative names as aliases\n\tconst aliases =\n\t\tplace.names\n\t\t\t?.filter((n) => n.value !== primaryName)\n\t\t\t.map((n) => n.value || \"\")\n\t\t\t.filter(Boolean) || [];\n\n\treturn {\n\t\tid: place.id || id,\n\t\tname: primaryName,\n\t\tstandardizedName: place.jurisdiction?.name,\n\t\taliases,\n\t\tlatitude: place.latitude,\n\t\tlongitude: place.longitude,\n\t\tjurisdiction: place.jurisdiction?.name,\n\t};\n}\n","/**\n * FamilySearch Tree/Pedigree API Module\n *\n * Provides helpers for fetching and managing family tree data\n * including pedigree, ancestry, and relationship information.\n */\n\nimport type { FamilySearchSDK } from \"../client\";\nimport type {\n\tEnhancedPedigreeData,\n\tEnhancedPerson,\n\tFamilySearchUser,\n\tPedigreeData,\n\tProgressCallback,\n\tRelationship,\n} from \"../types\";\n\n/**\n * Fetch pedigree/ancestry data with enhanced details\n *\n * @param sdk - FamilySearch SDK instance\n * @param personId - Optional person ID to start from. If not provided, uses current user.\n * @param options - Fetch options\n * @returns Promise with enhanced pedigree data\n *\n * @example\n * ```typescript\n * const pedigree = await fetchPedigree(sdk, \"XXXX-YYY\", {\n *   generations: 5,\n *   onProgress: (p) => console.log(`${p.percent}% complete`)\n * });\n * ```\n */\nexport async function fetchPedigree(\n\tsdk: FamilySearchSDK,\n\tpersonId?: string,\n\toptions: {\n\t\tgenerations?: number;\n\t\tonProgress?: ProgressCallback;\n\t\tincludeDetails?: boolean;\n\t\tincludeNotes?: boolean;\n\t\tincludeRelationshipDetails?: boolean;\n\t} = {}\n): Promise<EnhancedPedigreeData> {\n\tconst {\n\t\tgenerations = 4,\n\t\tonProgress,\n\t\tincludeDetails = true,\n\t\tincludeNotes = true,\n\t\tincludeRelationshipDetails = true,\n\t} = options;\n\n\t// Get current user's person ID if not provided\n\tlet targetPersonId = personId;\n\tif (!targetPersonId) {\n\t\tonProgress?.({\n\t\t\tstage: \"getting_current_user\",\n\t\t\tcurrent: 0,\n\t\t\ttotal: 1,\n\t\t\tpercent: 0,\n\t\t});\n\n\t\tconst currentUser = await sdk.getCurrentUser();\n\t\ttargetPersonId =\n\t\t\tcurrentUser?.personId ||\n\t\t\tcurrentUser?.treeUserId ||\n\t\t\tcurrentUser?.id;\n\n\t\tif (!targetPersonId) {\n\t\t\tthrow new Error(\"Could not determine person ID for current user\");\n\t\t}\n\t}\n\n\t// Step 1: Fetch ancestry structure\n\tonProgress?.({\n\t\tstage: \"fetching_ancestry_structure\",\n\t\tcurrent: 1,\n\t\ttotal: 3,\n\t\tpercent: 10,\n\t});\n\n\tconst ancestryResponse = await sdk.getAncestry(targetPersonId, generations);\n\tconst ancestry = ancestryResponse.data as PedigreeData;\n\n\tif (!ancestry.persons || ancestry.persons.length === 0) {\n\t\tthrow new Error(\"No persons found in ancestry\");\n\t}\n\n\t// Step 2: Enhance each person with detailed data\n\tonProgress?.({\n\t\tstage: \"fetching_person_details\",\n\t\tcurrent: 0,\n\t\ttotal: ancestry.persons.length,\n\t\tpercent: 20,\n\t});\n\n\tconst personsWithDetails: EnhancedPerson[] = [];\n\tfor (let i = 0; i < ancestry.persons.length; i++) {\n\t\tconst person = ancestry.persons[i];\n\n\t\tonProgress?.({\n\t\t\tstage: \"fetching_person_details\",\n\t\t\tcurrent: i + 1,\n\t\t\ttotal: ancestry.persons.length,\n\t\t\tpercent: 20 + Math.floor(((i + 1) / ancestry.persons.length) * 45),\n\t\t});\n\n\t\ttry {\n\t\t\tconst enhanced: EnhancedPerson = { ...person };\n\n\t\t\t// Fetch full person details with sources\n\t\t\tif (includeDetails) {\n\t\t\t\tenhanced.fullDetails = (await sdk.getPersonWithDetails(\n\t\t\t\t\tperson.id\n\t\t\t\t)) as EnhancedPerson[\"fullDetails\"];\n\t\t\t}\n\n\t\t\t// Fetch notes\n\t\t\tif (includeNotes) {\n\t\t\t\tenhanced.notes = (await sdk.getPersonNotes(\n\t\t\t\t\tperson.id\n\t\t\t\t)) as EnhancedPerson[\"notes\"];\n\t\t\t}\n\n\t\t\tpersonsWithDetails.push(enhanced);\n\t\t} catch {\n\t\t\t// Fallback to basic person data\n\t\t\tpersonsWithDetails.push(person as EnhancedPerson);\n\t\t}\n\t}\n\n\t// Step 3: Enhance couple relationships with marriage details\n\tonProgress?.({\n\t\tstage: \"fetching_relationship_details\",\n\t\tcurrent: 0,\n\t\ttotal: ancestry.relationships?.length || 0,\n\t\tpercent: 65,\n\t});\n\n\tconst relationshipsWithDetails: Relationship[] = [];\n\tif (ancestry.relationships && includeRelationshipDetails) {\n\t\tfor (let i = 0; i < ancestry.relationships.length; i++) {\n\t\t\tconst rel = ancestry.relationships[i];\n\n\t\t\tonProgress?.({\n\t\t\t\tstage: \"fetching_relationship_details\",\n\t\t\t\tcurrent: i + 1,\n\t\t\t\ttotal: ancestry.relationships.length,\n\t\t\t\tpercent:\n\t\t\t\t\t65 +\n\t\t\t\t\tMath.floor(((i + 1) / ancestry.relationships.length) * 25),\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Only fetch details for couple relationships\n\t\t\t\tif (rel.type?.includes?.(\"Couple\")) {\n\t\t\t\t\tconst relDetails = await sdk.getCoupleRelationship(rel.id);\n\t\t\t\t\trelationshipsWithDetails.push({\n\t\t\t\t\t\t...rel,\n\t\t\t\t\t\tdetails: relDetails as Relationship[\"details\"],\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\trelationshipsWithDetails.push(rel);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\trelationshipsWithDetails.push(rel);\n\t\t\t}\n\t\t}\n\t} else if (ancestry.relationships) {\n\t\trelationshipsWithDetails.push(...ancestry.relationships);\n\t}\n\n\t// Step 4: Extract additional relationships from person details\n\tonProgress?.({\n\t\tstage: \"extracting_additional_relationships\",\n\t\tcurrent: 0,\n\t\ttotal: 1,\n\t\tpercent: 90,\n\t});\n\n\tconst allRelationships = [...relationshipsWithDetails];\n\tconst relationshipIds = new Set(relationshipsWithDetails.map((r) => r.id));\n\n\tpersonsWithDetails.forEach((person) => {\n\t\t// Extract child-parent relationships from person details\n\t\tconst childAndParentsRels =\n\t\t\tperson.fullDetails?.childAndParentsRelationships;\n\t\tif (childAndParentsRels && Array.isArray(childAndParentsRels)) {\n\t\t\tchildAndParentsRels.forEach((rel) => {\n\t\t\t\tif (!relationshipIds.has(rel.id)) {\n\t\t\t\t\trelationshipIds.add(rel.id);\n\t\t\t\t\tallRelationships.push({\n\t\t\t\t\t\tid: rel.id,\n\t\t\t\t\t\ttype: \"http://gedcomx.org/ParentChild\",\n\t\t\t\t\t\tperson1: rel.parent1,\n\t\t\t\t\t\tperson2: rel.child,\n\t\t\t\t\t\tparent2: rel.parent2,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// Extract couple relationships from person details\n\t\tconst relationships = person.fullDetails?.relationships;\n\t\tif (relationships && Array.isArray(relationships)) {\n\t\t\trelationships.forEach((rel) => {\n\t\t\t\tif (rel.type?.includes?.(\"Couple\") && !relationshipIds.has(rel.id)) {\n\t\t\t\t\trelationshipIds.add(rel.id);\n\t\t\t\t\tallRelationships.push({\n\t\t\t\t\t\tid: rel.id,\n\t\t\t\t\t\ttype: rel.type,\n\t\t\t\t\t\tperson1: rel.person1,\n\t\t\t\t\t\tperson2: rel.person2,\n\t\t\t\t\t\tfacts: rel.facts,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\tonProgress?.({\n\t\tstage: \"completing_data_fetch\",\n\t\tcurrent: 1,\n\t\ttotal: 1,\n\t\tpercent: 98,\n\t});\n\n\treturn {\n\t\tpersons: personsWithDetails,\n\t\trelationships: allRelationships,\n\t\tenvironment: sdk.getEnvironment(),\n\t};\n}\n\n/**\n * Get current user information\n */\nexport async function getCurrentUser(\n\tsdk: FamilySearchSDK\n): Promise<FamilySearchUser | null> {\n\treturn sdk.getCurrentUser();\n}\n\n/**\n * Get person by ID with full details\n */\nexport async function getPersonWithDetails(\n\tsdk: FamilySearchSDK,\n\tpersonId: string\n): Promise<EnhancedPerson | null> {\n\ttry {\n\t\tconst [details, notes] = await Promise.all([\n\t\t\tsdk.getPersonWithDetails(personId),\n\t\t\tsdk.getPersonNotes(personId),\n\t\t]);\n\n\t\tif (!details) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// The details response contains the person data in persons array\n\t\tconst fullDetails = details as EnhancedPerson[\"fullDetails\"];\n\t\tconst personData = fullDetails?.persons?.[0];\n\n\t\tif (!personData) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\t...personData,\n\t\t\tfullDetails: fullDetails,\n\t\t\tnotes: notes as EnhancedPerson[\"notes\"],\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Fetch multiple persons at once\n */\nexport async function fetchMultiplePersons(\n\tsdk: FamilySearchSDK,\n\tpersonIds: string[]\n): Promise<unknown> {\n\tconst pids = personIds.join(\",\");\n\tconst response = await sdk.get(`/platform/tree/persons?pids=${pids}`);\n\treturn response.data;\n}\n","/**\n * FamilySearch to GEDCOM Converter\n *\n * Converts FamilySearch API responses into GEDCOM 5.5 format\n */\n\nimport type {\n\tEnhancedPedigreeData,\n\tPersonData,\n\tPersonFact,\n\tRelationship,\n\tSourceDescription,\n\tSourceReference,\n} from \"../types\";\n\n/**\n * Transform FamilySearch API URLs to web URLs\n * Supports: apibeta.familysearch.org, beta.familysearch.org, integration.familysearch.org\n */\nfunction transformFamilySearchUrl(url: string): string {\n\t// If it's not an API URL, return as-is\n\tif (!url.includes(\"/platform/tree/persons/\")) {\n\t\treturn url;\n\t}\n\n\t// Extract person ID from API URL\n\tconst personId = url.match(/persons\\/([^/?]+)/)?.[1];\n\tif (!personId) {\n\t\treturn url;\n\t}\n\n\t// Detect environment from the URL\n\tlet baseUrl = \"https://www.familysearch.org\";\n\n\tif (\n\t\turl.includes(\"integration.familysearch.org\") ||\n\t\turl.includes(\"api-integ.familysearch.org\")\n\t) {\n\t\tbaseUrl = \"https://integration.familysearch.org\";\n\t} else if (\n\t\turl.includes(\"beta.familysearch.org\") ||\n\t\turl.includes(\"apibeta.familysearch.org\")\n\t) {\n\t\tbaseUrl = \"https://beta.familysearch.org\";\n\t}\n\n\treturn `${baseUrl}/tree/person/${personId}`;\n}\n\n/**\n * Transform FamilySearch source URLs to web-accessible ARK URLs\n *\n * FamilySearch API returns source URLs in the format:\n * - https://api.familysearch.org/platform/sources/ark:/NAAN/Name\n * - https://apibeta.familysearch.org/platform/sources/ark:/NAAN/Name\n * - https://api-integ.familysearch.org/platform/sources/ark:/NAAN/Name\n *\n * These need to be transformed to web-accessible URLs:\n * - https://www.familysearch.org/ark:/NAAN/Name\n * - https://beta.familysearch.org/ark:/NAAN/Name\n * - https://integration.familysearch.org/ark:/NAAN/Name\n *\n * ARK (Archival Resource Key) format: ark:/NAAN/Name\n * - NAAN: Name Assigning Authority Number\n * - Name: Unique identifier\n *\n * @param url - FamilySearch API source URL\n * @returns Web-accessible ARK URL\n */\nfunction transformSourceUrl(url: string): string {\n\tif (!url) return url;\n\n\t// If it's already a web URL (not API URL with /platform/), return as-is\n\tif (!url.includes(\"/platform/\") && url.includes(\"ark:\")) {\n\t\treturn url;\n\t}\n\n\t// Extract ARK identifier from URL\n\tconst arkMatch = url.match(/ark:\\/[^/?]+\\/[^/?]+/);\n\tif (!arkMatch) {\n\t\treturn url;\n\t}\n\n\tconst arkId = arkMatch[0];\n\n\t// Detect environment from URL\n\tlet baseUrl = \"https://www.familysearch.org\";\n\n\tif (\n\t\turl.includes(\"integration.familysearch.org\") ||\n\t\turl.includes(\"api-integ.familysearch.org\")\n\t) {\n\t\tbaseUrl = \"https://integration.familysearch.org\";\n\t} else if (\n\t\turl.includes(\"beta.familysearch.org\") ||\n\t\turl.includes(\"apibeta.familysearch.org\")\n\t) {\n\t\tbaseUrl = \"https://beta.familysearch.org\";\n\t}\n\n\treturn `${baseUrl}/${arkId}`;\n}\n\n/**\n * Extract name from FamilySearch person\n */\nfunction extractName(person?: PersonData): string | null {\n\tif (!person) return null;\n\n\t// Try structured name\n\tif (person.names?.[0]?.nameForms?.[0]) {\n\t\tconst nameForm = person.names[0].nameForms[0];\n\n\t\t// Build from parts\n\t\tconst parts = nameForm.parts || [];\n\t\tconst given = parts.find((p) => p.type?.includes(\"Given\"))?.value || \"\";\n\t\tconst surname =\n\t\t\tparts.find((p) => p.type?.includes(\"Surname\"))?.value || \"\";\n\n\t\tif (given || surname) {\n\t\t\treturn `${given} /${surname}/`.trim();\n\t\t}\n\n\t\tif (nameForm.fullText) {\n\t\t\treturn nameForm.fullText;\n\t\t}\n\t}\n\n\t// Try display name\n\tif (person.display?.name) {\n\t\treturn person.display.name;\n\t}\n\n\treturn null;\n}\n\n/**\n * Extract gender from FamilySearch person\n */\nfunction extractGender(person?: PersonData): string | null {\n\tif (!person) return null;\n\n\tif (person.gender?.type?.includes(\"Male\")) {\n\t\treturn \"M\";\n\t} else if (person.gender?.type?.includes(\"Female\")) {\n\t\treturn \"F\";\n\t} else if (person.display?.gender === \"Male\") {\n\t\treturn \"M\";\n\t} else if (person.display?.gender === \"Female\") {\n\t\treturn \"F\";\n\t}\n\n\treturn null;\n}\n\n/**\n * Extract a specific fact (like birth or death) from FamilySearch person\n */\nfunction extractFact(\n\tperson: PersonData | undefined,\n\tfactType: \"BIRTH\" | \"DEATH\"\n): { date?: string; place?: string } | null {\n\tif (!person) return null;\n\n\tconst result: { date?: string; place?: string } = {};\n\n\t// Try structured facts\n\tconst factTypeUrl = `http://gedcomx.org/${factType === \"BIRTH\" ? \"Birth\" : \"Death\"}`;\n\tconst fact = person.facts?.find((f) => f.type === factTypeUrl);\n\n\tif (fact) {\n\t\tif (fact.date?.formal || fact.date?.original) {\n\t\t\tresult.date = (fact.date?.formal || fact.date?.original)?.replace(\n\t\t\t\t/^(-|\\+)/,\n\t\t\t\t\"\"\n\t\t\t);\n\t\t}\n\t\tif (fact.place?.original) {\n\t\t\tresult.place = fact.place.original;\n\t\t}\n\t}\n\n\t// Try display data\n\tif (factType === \"BIRTH\") {\n\t\tresult.date = result.date || person.display?.birthDate;\n\t\tresult.place = result.place || person.display?.birthPlace;\n\t} else if (factType === \"DEATH\") {\n\t\tresult.date = result.date || person.display?.deathDate;\n\t\tresult.place = result.place || person.display?.deathPlace;\n\t}\n\n\treturn result.date || result.place ? result : null;\n}\n\n/**\n * Format a date for GEDCOM\n */\nfunction formatDateForGedcom(date: Date): string {\n\tconst months = [\n\t\t\"JAN\",\n\t\t\"FEB\",\n\t\t\"MAR\",\n\t\t\"APR\",\n\t\t\"MAY\",\n\t\t\"JUN\",\n\t\t\"JUL\",\n\t\t\"AUG\",\n\t\t\"SEP\",\n\t\t\"OCT\",\n\t\t\"NOV\",\n\t\t\"DEC\",\n\t];\n\n\tconst day = date.getDate();\n\tconst month = months[date.getMonth()];\n\tconst year = date.getFullYear();\n\n\treturn `${day} ${month} ${year}`;\n}\n\n/**\n * Convert a FamilySearch fact to GEDCOM lines\n */\nfunction convertFactToGedcom(fact: PersonFact): string[] {\n\tconst lines: string[] = [];\n\n\tif (!fact.type) return lines;\n\n\t// Map FamilySearch fact types to GEDCOM tags\n\tconst typeMap: Record<string, string> = {\n\t\t\"http://gedcomx.org/Burial\": \"BURI\",\n\t\t\"http://gedcomx.org/Christening\": \"CHR\",\n\t\t\"http://gedcomx.org/Baptism\": \"BAPM\",\n\t\t\"http://gedcomx.org/Marriage\": \"MARR\",\n\t\t\"http://gedcomx.org/Divorce\": \"DIV\",\n\t\t\"http://gedcomx.org/Residence\": \"RESI\",\n\t\t\"http://gedcomx.org/Occupation\": \"OCCU\",\n\t\t\"http://gedcomx.org/Immigration\": \"IMMI\",\n\t\t\"http://gedcomx.org/Emigration\": \"EMIG\",\n\t\t\"http://gedcomx.org/Naturalization\": \"NATU\",\n\t\t\"http://gedcomx.org/Census\": \"CENS\",\n\t};\n\n\tconst gedcomTag = typeMap[fact.type] || \"EVEN\";\n\n\t// Special handling for occupation with value\n\tif (gedcomTag === \"OCCU\" && fact.value) {\n\t\tlines.push(`1 OCCU ${fact.value}`);\n\t} else {\n\t\tlines.push(`1 ${gedcomTag}`);\n\t}\n\n\t// Add FamilySearch link for this specific fact/event (conclusion link)\n\tif (fact.links?.conclusion?.href) {\n\t\tconst webUrl = transformFamilySearchUrl(fact.links.conclusion.href);\n\t\tlines.push(`2 _FS_LINK ${webUrl}`);\n\t}\n\n\t// Add date\n\tif (fact.date?.formal || fact.date?.original) {\n\t\tlines.push(\n\t\t\t`2 DATE ${(fact.date?.formal || fact.date?.original)?.replace(/^(-|\\+)/, \"\")}`\n\t\t);\n\t}\n\n\t// Add place\n\tif (fact.place?.original) {\n\t\tlines.push(`2 PLAC ${fact.place.original}`);\n\t}\n\n\t// Add value as note for non-occupation facts\n\tif (fact.value && gedcomTag !== \"OCCU\") {\n\t\tlines.push(`2 NOTE ${fact.value}`);\n\t}\n\n\treturn lines;\n}\n\n/**\n * Options for GEDCOM conversion\n */\nexport interface GedcomConversionOptions {\n\t/** Tree name for the GEDCOM file header */\n\ttreeName?: string;\n\t/** Include FamilySearch links in output */\n\tincludeLinks?: boolean;\n\t/** Include notes in output */\n\tincludeNotes?: boolean;\n\n\t/** FamilySearch environment (production, beta, integration) */\n\tenvironment?: \"production\" | \"beta\" | \"integration\";\n\n\t/** Allow orphan families (families not connected to root person) */\n\tallowOrphanFamilies?: boolean;\n\n\t/**\n\t * Set of person IDs who are in the direct ancestry of the root person.\n\t * These are the persons returned by the ancestry API before fullTree expansion.\n\t * Used to determine which persons are \"connectable\" to the root person.\n\t */\n\tancestryPersonIds?: Set<string>;\n}\n\n/**\n * Convert FamilySearch pedigree data to GEDCOM format\n *\n * @param pedigreeData - Enhanced pedigree data from FamilySearch\n * @param options - Conversion options\n * @returns GEDCOM 5.5 formatted string\n *\n * @example\n * ```typescript\n * const pedigree = await fetchPedigree(sdk);\n * const gedcom = convertToGedcom(pedigree, { treeName: \"My Family Tree\" });\n * ```\n */\nexport function convertToGedcom(\n\tpedigreeData: EnhancedPedigreeData,\n\toptions: GedcomConversionOptions = {}\n): string {\n\tconst {\n\t\ttreeName = \"FamilySearch Import\",\n\t\tincludeLinks = true,\n\t\tincludeNotes = true,\n\t\tenvironment = \"production\",\n\t} = options;\n\n\tif (!pedigreeData || !pedigreeData.persons) {\n\t\tthrow new Error(\"Invalid FamilySearch data: no persons found\");\n\t}\n\n\tconst lines: string[] = [];\n\n\t// GEDCOM Header\n\tlines.push(\"0 HEAD\");\n\tlines.push(\"1 SOUR FamilySearch\");\n\tlines.push(\"2 VERS 1.0\");\n\tlines.push(\"2 NAME FamilySearch API\");\n\tlines.push(\"1 DEST ANY\");\n\tlines.push(\"1 DATE \" + formatDateForGedcom(new Date()));\n\tlines.push(\"1 SUBM @SUBM1@\");\n\tlines.push(\"1 FILE \" + treeName);\n\tlines.push(\"1 GEDC\");\n\tlines.push(\"2 VERS 5.5\");\n\tlines.push(\"2 FORM LINEAGE-LINKED\");\n\tlines.push(\"1 CHAR UTF-8\");\n\n\t// Submitter record\n\tlines.push(\"0 @SUBM1@ SUBM\");\n\n\t// ==============================================\n\t// COLLECT AND CREATE SOURCE RECORDS\n\t// ==============================================\n\tconst sourceMap = new Map<string, SourceDescription>();\n\tlet sourceCounter = 1;\n\n\t// Extract source descriptions from all persons\n\tpedigreeData.persons.forEach((person) => {\n\t\tconst sourceDescriptions = person.fullDetails?.sourceDescriptions;\n\n\t\tif (sourceDescriptions && Array.isArray(sourceDescriptions)) {\n\t\t\tsourceDescriptions.forEach((source) => {\n\t\t\t\tif (source.id && !sourceMap.has(source.id)) {\n\t\t\t\t\tsourceMap.set(source.id, source);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t// Create GEDCOM SOUR records for each source\n\tsourceMap.forEach((source) => {\n\t\tconst sourceId = `@S${sourceCounter++}@`;\n\n\t\tlines.push(`0 ${sourceId} SOUR`);\n\n\t\t// Add title (use titles[0] if available, otherwise default)\n\t\tconst title = source.titles?.[0]?.value || \"FamilySearch Source\";\n\t\tlines.push(`1 TITL ${title}`);\n\n\t\t// Add citation as TEXT\n\t\tif (source.citations?.[0]?.value) {\n\t\t\tlines.push(`1 TEXT ${source.citations[0].value}`);\n\t\t}\n\n\t\t// Add web link if available\n\t\tif (source.about) {\n\t\t\tconst webUrl = transformSourceUrl(source.about);\n\t\t\tlines.push(`1 WWW ${webUrl}`);\n\t\t}\n\n\t\t// Add resource type as NOTE\n\t\tif (source.resourceType) {\n\t\t\tlines.push(`1 NOTE Resource Type: ${source.resourceType}`);\n\t\t}\n\t});\n\n\t// ==============================================\n\t// STEP 1: BUILD PERSON ID MAPPING ONLY\n\t// Create GEDCOM IDs for all persons (for relationship processing)\n\t// INDI records will be created later after filtering\n\t// ==============================================\n\tconst personIdMap = new Map<string, string>();\n\tpedigreeData.persons.forEach((person, index) => {\n\t\tconst gedcomId = `@I${index + 1}@`;\n\t\tpersonIdMap.set(person.id, gedcomId);\n\t});\n\n\t// Build family data structures\n\tconst families = new Map<\n\t\tstring,\n\t\t{ spouses: Set<string>; children: string[] }\n\t>();\n\tconst childToParents = new Map<string, string[]>();\n\n\t// ==============================================\n\t// COLLECT ALL RELATIONSHIPS (from pedigree AND person details)\n\t// ==============================================\n\tconst allRelationships: Relationship[] = [\n\t\t...(pedigreeData.relationships || []),\n\t];\n\n\t// Extract relationships from person.fullDetails.relationships\n\tpedigreeData.persons.forEach((person) => {\n\t\tconst personRelationships = person.fullDetails\n\t\t\t?.relationships as Relationship[];\n\n\t\tif (personRelationships && Array.isArray(personRelationships)) {\n\t\t\tpersonRelationships.forEach((rel) => {\n\t\t\t\tconst exists = allRelationships.some((r) => r.id === rel.id);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tallRelationships.push(rel);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// Extract childAndParentsRelationships and convert to standard format\n\t\tconst childAndParentsRels = person.fullDetails\n\t\t\t?.childAndParentsRelationships as Array<{\n\t\t\tid: string;\n\t\t\tparent1?: { resourceId: string };\n\t\t\tparent2?: { resourceId: string };\n\t\t\tchild?: { resourceId: string };\n\t\t}>;\n\n\t\tif (childAndParentsRels && Array.isArray(childAndParentsRels)) {\n\t\t\tchildAndParentsRels.forEach((capRel) => {\n\t\t\t\t// Convert to ParentChild relationship format\n\t\t\t\tif (capRel.parent1 && capRel.child) {\n\t\t\t\t\tconst rel: Relationship = {\n\t\t\t\t\t\tid: `${capRel.id}-p1`,\n\t\t\t\t\t\ttype: \"http://gedcomx.org/ParentChild\",\n\t\t\t\t\t\tperson1: { resourceId: capRel.parent1.resourceId },\n\t\t\t\t\t\tperson2: { resourceId: capRel.child.resourceId },\n\t\t\t\t\t\tparent2: capRel.parent2\n\t\t\t\t\t\t\t? { resourceId: capRel.parent2.resourceId }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst exists = allRelationships.some(\n\t\t\t\t\t\t(r) => r.id === rel.id\n\t\t\t\t\t);\n\t\t\t\t\tif (!exists) {\n\t\t\t\t\t\tallRelationships.push(rel);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If parent2 exists, also add relationship for parent2\n\t\t\t\tif (capRel.parent2 && capRel.child) {\n\t\t\t\t\tconst rel: Relationship = {\n\t\t\t\t\t\tid: `${capRel.id}-p2`,\n\t\t\t\t\t\ttype: \"http://gedcomx.org/ParentChild\",\n\t\t\t\t\t\tperson1: { resourceId: capRel.parent2.resourceId },\n\t\t\t\t\t\tperson2: { resourceId: capRel.child.resourceId },\n\t\t\t\t\t\tparent2: capRel.parent1\n\t\t\t\t\t\t\t? { resourceId: capRel.parent1.resourceId }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst exists = allRelationships.some(\n\t\t\t\t\t\t(r) => r.id === rel.id\n\t\t\t\t\t);\n\t\t\t\t\tif (!exists) {\n\t\t\t\t\t\tallRelationships.push(rel);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t// Create a Set of valid person IDs for fast lookup\n\tconst validPersonIds = new Set(pedigreeData.persons.map((p) => p.id));\n\n\t// Process all relationships, filtering out invalid person IDs\n\tallRelationships.forEach((rel) => {\n\t\tif (rel.type?.includes(\"ParentChild\")) {\n\t\t\tconst parentId = rel.person1?.resourceId;\n\t\t\tconst childId = rel.person2?.resourceId;\n\t\t\tconst parent2Id = rel.parent2?.resourceId;\n\n\t\t\t// Validate all person IDs exist in dataset\n\t\t\tif (!parentId || !childId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip if child doesn't exist in dataset\n\t\t\tif (!validPersonIds.has(childId)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Filter parent IDs - only include parents who exist in dataset\n\t\t\tconst validParents: string[] = [];\n\t\t\tif (validPersonIds.has(parentId)) {\n\t\t\t\tvalidParents.push(parentId);\n\t\t\t}\n\t\t\tif (parent2Id && validPersonIds.has(parent2Id)) {\n\t\t\t\tvalidParents.push(parent2Id);\n\t\t\t}\n\n\t\t\t// Only add relationship if at least one parent exists\n\t\t\tif (validParents.length > 0) {\n\t\t\t\tif (!childToParents.has(childId)) {\n\t\t\t\t\tchildToParents.set(childId, []);\n\t\t\t\t}\n\t\t\t\tconst parents = childToParents.get(childId)!;\n\t\t\t\tvalidParents.forEach((parentId) => {\n\t\t\t\t\tif (!parents.includes(parentId)) {\n\t\t\t\t\t\tparents.push(parentId);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (rel.type?.includes(\"Couple\")) {\n\t\t\tconst person1 = rel.person1?.resourceId;\n\t\t\tconst person2 = rel.person2?.resourceId;\n\n\t\t\tif (!person1 || !person2) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only add couple if BOTH persons exist in dataset\n\t\t\tif (validPersonIds.has(person1) && validPersonIds.has(person2)) {\n\t\t\t\tconst famKey = [person1, person2].sort().join(\"-\");\n\t\t\t\tif (!families.has(famKey)) {\n\t\t\t\t\tfamilies.set(famKey, {\n\t\t\t\t\t\tspouses: new Set([person1, person2]),\n\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\t// Add children to their families\n\tchildToParents.forEach((parents, childId) => {\n\t\tif (parents.length >= 2) {\n\t\t\tconst famKey = parents.slice(0, 2).sort().join(\"-\");\n\t\t\tif (!families.has(famKey)) {\n\t\t\t\tfamilies.set(famKey, {\n\t\t\t\t\tspouses: new Set(parents.slice(0, 2)),\n\t\t\t\t\tchildren: [],\n\t\t\t\t});\n\t\t\t}\n\t\t\tfamilies.get(famKey)!.children.push(childId);\n\t\t} else if (parents.length === 1) {\n\t\t\tconst famKey = `single-${parents[0]}`;\n\t\t\tif (!families.has(famKey)) {\n\t\t\t\tfamilies.set(famKey, {\n\t\t\t\t\tspouses: new Set([parents[0]]),\n\t\t\t\t\tchildren: [],\n\t\t\t\t});\n\t\t\t}\n\t\t\tfamilies.get(famKey)!.children.push(childId);\n\t\t}\n\t});\n\n\t// Build set of persons who are \"connectable\" to the root person\n\t// A person is connectable if:\n\t// 1. They are in the direct ancestry (ancestryPersonIds)\n\t// 2. They are a spouse of someone in the ancestry\n\t// 3. They are a descendant of someone in the ancestry (recursive)\n\t// 4. They are a spouse of a descendant (recursive)\n\tconst connectablePersons = new Set<string>();\n\n\t// If ancestryPersonIds is provided, use graph traversal\n\t// Otherwise, fall back to old logic (everyone in childToParents)\n\tif (options.ancestryPersonIds && options.ancestryPersonIds.size > 0) {\n\t\t// Step 1: Add all ancestry persons\n\t\toptions.ancestryPersonIds.forEach((personId) => {\n\t\t\tconnectablePersons.add(personId);\n\t\t});\n\n\t\t// Step 2: Add spouses of ancestry persons\n\t\tfamilies.forEach((family) => {\n\t\t\tconst spouses = Array.from(family.spouses);\n\t\t\t// If any spouse is in ancestry, add all spouses\n\t\t\tif (spouses.some((spouseId) => connectablePersons.has(spouseId))) {\n\t\t\t\tspouses.forEach((spouseId) => connectablePersons.add(spouseId));\n\t\t\t}\n\t\t});\n\n\t\t// Step 3: Recursively expand the graph DOWNWARD and SIDEWAYS only\n\t\t// Add: descendants + their spouses (NO upward traversal to parents)\n\t\t// Keep iterating until no new persons are added\n\t\tlet addedNewPersons = true;\n\t\twhile (addedNewPersons) {\n\t\t\taddedNewPersons = false;\n\t\t\tconst beforeSize = connectablePersons.size;\n\n\t\t\t// 3a. Add children of connectable persons (downward traversal)\n\t\t\tchildToParents.forEach((parents, childId) => {\n\t\t\t\t// If any parent is connectable, the child is connectable\n\t\t\t\tif (\n\t\t\t\t\tparents.some((parentId) => connectablePersons.has(parentId))\n\t\t\t\t) {\n\t\t\t\t\tif (!connectablePersons.has(childId)) {\n\t\t\t\t\t\tconnectablePersons.add(childId);\n\t\t\t\t\t\taddedNewPersons = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// 3b. Add spouses of connectable persons (sideways traversal)\n\t\t\tfamilies.forEach((family) => {\n\t\t\t\tconst spouses = Array.from(family.spouses);\n\t\t\t\tconst hasConnectableSpouse = spouses.some((spouseId) =>\n\t\t\t\t\tconnectablePersons.has(spouseId)\n\t\t\t\t);\n\t\t\t\tconst hasConnectableChild = family.children.some((childId) =>\n\t\t\t\t\tconnectablePersons.has(childId)\n\t\t\t\t);\n\n\t\t\t\t// If any spouse OR child is connectable, add all spouses\n\t\t\t\tif (hasConnectableSpouse || hasConnectableChild) {\n\t\t\t\t\tspouses.forEach((spouseId) => {\n\t\t\t\t\t\tif (!connectablePersons.has(spouseId)) {\n\t\t\t\t\t\t\tconnectablePersons.add(spouseId);\n\t\t\t\t\t\t\taddedNewPersons = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst afterSize = connectablePersons.size;\n\t\t\tif (afterSize > beforeSize) {\n\t\t\t\taddedNewPersons = afterSize !== beforeSize;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Fallback: old logic (everyone in parent-child relationships)\n\t\tchildToParents.forEach((parents, childId) => {\n\t\t\tconnectablePersons.add(childId);\n\t\t\tparents.forEach((parentId) => connectablePersons.add(parentId));\n\t\t});\n\t}\n\n\t// ==============================================\n\t// STEP 4: DETECT ORPHAN FAMILIES AND BUILD PERSON-TO-FAMILY MAPPING\n\t// Identify which families are orphan (disconnected from ancestry)\n\t// ==============================================\n\tconst allowOrphanFamilies = options.allowOrphanFamilies === true; // Default to false\n\tconst orphanFamKeys = new Set<string>(); // Keys of families that are orphan\n\n\t// Build a map from personId to all their FAM keys (as spouse or child)\n\tconst personToFamKeys = new Map<string, Set<string>>();\n\tfamilies.forEach((family, key) => {\n\t\tconst spouseArray = Array.from(family.spouses);\n\n\t\t// Check if this is an orphan family\n\t\tconst anyMemberConnectable =\n\t\t\tspouseArray.some((spouseId) => connectablePersons.has(spouseId)) ||\n\t\t\tfamily.children.some((childId) => connectablePersons.has(childId));\n\n\t\tconst isOrphanFamily = !anyMemberConnectable;\n\n\t\t// Track orphan family keys\n\t\tif (isOrphanFamily) {\n\t\t\torphanFamKeys.add(key);\n\t\t}\n\n\t\t// Map each person to their families\n\t\tspouseArray.forEach((spouseId) => {\n\t\t\tif (!personToFamKeys.has(spouseId))\n\t\t\t\tpersonToFamKeys.set(spouseId, new Set());\n\t\t\tpersonToFamKeys.get(spouseId)!.add(key);\n\t\t});\n\t\tfamily.children.forEach((childId) => {\n\t\t\tif (!personToFamKeys.has(childId))\n\t\t\t\tpersonToFamKeys.set(childId, new Set());\n\t\t\tpersonToFamKeys.get(childId)!.add(key);\n\t\t});\n\t});\n\n\t// ==============================================\n\t// STEP 5: CREATE INDI RECORDS (WITH ORPHAN FILTERING)\n\t// ==============================================\n\n\tpedigreeData.persons.forEach((person) => {\n\t\tconst gedcomId = personIdMap.get(person.id);\n\t\tif (!gedcomId) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`[GEDCOM] Person ${person.id} not found in personIdMap`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// ==============================================\n\t\t// ORPHAN PERSON FILTERING\n\t\t// If allowOrphanFamilies=false, skip persons who are ONLY in orphan families\n\t\t// ==============================================\n\t\tif (!allowOrphanFamilies) {\n\t\t\tconst famKeys = personToFamKeys.get(person.id);\n\t\t\t// If person belongs to families, check if ALL of them are orphan families\n\t\t\tif (\n\t\t\t\tfamKeys &&\n\t\t\t\tfamKeys.size > 0 &&\n\t\t\t\tArray.from(famKeys).every((key) => orphanFamKeys.has(key))\n\t\t\t) {\n\t\t\t\treturn; // Skip this orphan person\n\t\t\t}\n\t\t}\n\n\t\tlines.push(`0 ${gedcomId} INDI`);\n\n\t\t// Add FamilySearch ID tag\n\t\tif (person.id) {\n\t\t\tlines.push(`1 _FS_ID ${person.id}`);\n\t\t}\n\n\t\t// Add FamilySearch link for this person\n\t\tif (includeLinks) {\n\t\t\tconst personLink =\n\t\t\t\tperson.links?.person?.href ||\n\t\t\t\tperson.identifiers?.[\"http://gedcomx.org/Persistent\"]?.[0];\n\n\t\t\tif (personLink) {\n\t\t\t\tconst webUrl = transformFamilySearchUrl(personLink);\n\t\t\t\tlines.push(`1 _FS_LINK ${webUrl}`);\n\t\t\t} else if (person.id) {\n\t\t\t\t// Fallback: construct web URL from person ID if no link provided\n\t\t\t\tlet baseUrl = \"https://www.familysearch.org\";\n\t\t\t\tif (environment === \"beta\") {\n\t\t\t\t\tbaseUrl = \"https://beta.familysearch.org\";\n\t\t\t\t} else if (environment === \"integration\") {\n\t\t\t\t\tbaseUrl = \"https://integration.familysearch.org\";\n\t\t\t\t}\n\t\t\t\tconst webUrl = `${baseUrl}/tree/person/${person.id}`;\n\t\t\t\tlines.push(`1 _FS_LINK ${webUrl}`);\n\t\t\t}\n\t\t}\n\n\t\t// Extract from fullDetails if available, otherwise use basic person data\n\t\tconst personData = person.fullDetails?.persons?.[0] || person;\n\n\t\t// Name\n\t\tconst name = extractName(personData);\n\t\tif (name) {\n\t\t\tlines.push(`1 NAME ${name}`);\n\t\t}\n\n\t\t// Gender\n\t\tconst gender = extractGender(personData);\n\t\tif (gender) {\n\t\t\tlines.push(`1 SEX ${gender}`);\n\t\t}\n\n\t\t// Birth\n\t\tconst birth = extractFact(personData, \"BIRTH\");\n\t\tif (birth) {\n\t\t\tlines.push(\"1 BIRT\");\n\t\t\tif (birth.date) {\n\t\t\t\tlines.push(`2 DATE ${birth.date}`);\n\t\t\t}\n\t\t\tif (birth.place) {\n\t\t\t\tlines.push(`2 PLAC ${birth.place}`);\n\t\t\t}\n\t\t}\n\n\t\t// Death\n\t\tconst death = extractFact(personData, \"DEATH\");\n\t\tif (death) {\n\t\t\tlines.push(\"1 DEAT\");\n\t\t\tif (death.date) {\n\t\t\t\tlines.push(`2 DATE ${death.date}`);\n\t\t\t}\n\t\t\tif (death.place) {\n\t\t\t\tlines.push(`2 PLAC ${death.place}`);\n\t\t\t}\n\t\t}\n\n\t\t// Add all other facts from fullDetails\n\t\tpersonData.facts?.forEach((fact) => {\n\t\t\tif (\n\t\t\t\tfact.type &&\n\t\t\t\tfact.type !== \"http://gedcomx.org/Birth\" &&\n\t\t\t\tfact.type !== \"http://gedcomx.org/Death\"\n\t\t\t) {\n\t\t\t\tconst factLines = convertFactToGedcom(fact);\n\t\t\t\tfactLines.forEach((line) => lines.push(line));\n\t\t\t}\n\t\t});\n\n\t\t// Add notes\n\t\tif (includeNotes && person.notes?.persons?.[0]?.notes) {\n\t\t\tperson.notes.persons[0].notes.forEach((note) => {\n\t\t\t\tif (note.text) {\n\t\t\t\t\tconst noteText = note.text.replace(/\\n/g, \" \");\n\t\t\t\t\tlines.push(`1 NOTE ${noteText}`);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// ==============================================\n\t\t// ADD SOURCE CITATIONS TO PERSON\n\t\t// ==============================================\n\t\tconst personSources = (\n\t\t\tpersonData as PersonData & { sources?: SourceReference[] }\n\t\t)?.sources;\n\n\t\tif (personSources && Array.isArray(personSources)) {\n\t\t\tpersonSources.forEach((sourceRef) => {\n\t\t\t\tconst sourceId = sourceRef.descriptionId;\n\t\t\t\tif (!sourceId) return;\n\n\t\t\t\t// Find source index\n\t\t\t\tconst sourceIds = Array.from(sourceMap.keys());\n\t\t\t\tconst sourceIndex = sourceIds.indexOf(sourceId);\n\t\t\t\tif (sourceIndex === -1) return;\n\n\t\t\t\tconst gedcomSourceId = `@S${sourceIndex + 1}@`;\n\t\t\t\tlines.push(`1 SOUR ${gedcomSourceId}`);\n\n\t\t\t\t// Add qualifiers as notes\n\t\t\t\tif (\n\t\t\t\t\tsourceRef.qualifiers &&\n\t\t\t\t\tArray.isArray(sourceRef.qualifiers)\n\t\t\t\t) {\n\t\t\t\t\tsourceRef.qualifiers.forEach((qualifier) => {\n\t\t\t\t\t\tif (qualifier.name && qualifier.value) {\n\t\t\t\t\t\t\tlines.push(\n\t\t\t\t\t\t\t\t`2 NOTE ${qualifier.name}: ${qualifier.value}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t// ==============================================\n\t// STEP 6: CREATE FAM RECORDS (WITH ORPHAN FILTERING)\n\t// ==============================================\n\n\t// Create FAM records\n\tlet famIndex = 1;\n\tconst familyIdMap = new Map<string, string>();\n\n\tfamilies.forEach((family, key) => {\n\t\t// ==============================================\n\t\t// INVALID FAM RECORD PREVENTION\n\t\t// ==============================================\n\n\t\t// Check if parents exist in personIdMap\n\t\tconst spouseArray = Array.from(family.spouses);\n\t\tconst parentsInMap = spouseArray.filter((id) => personIdMap.has(id));\n\n\t\tconst hasNoParents = parentsInMap.length === 0;\n\t\tconst hasSingleParentNoChildren =\n\t\t\tparentsInMap.length === 1 && family.children.length === 0;\n\n\t\t// Skip invalid FAM records\n\t\tif (hasNoParents) {\n\t\t\t// Orphaned child - no parents exist in dataset\n\t\t\tif (family.children.length > 0) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[FS SDK GEDCOM] Skipping FAM for orphaned child(ren): ${family.children.length} child(ren) with 0 parents`\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn; // Skip this FAM record\n\t\t}\n\n\t\tif (hasSingleParentNoChildren) {\n\t\t\t// Single spouse with no children and no other spouse\n\t\t\t// This is an orphaned single-spouse family (invalid per GEDCOM 5.5)\n\t\t\treturn; // Skip this FAM record\n\t\t}\n\n\t\t// Check if this is an orphan family\n\t\t// Family is orphan if NO members (neither spouses NOR children) are connectable to root person\n\t\t// This means the family is isolated and doesn't connect to the ancestry tree\n\t\tconst anyMemberConnectable =\n\t\t\tspouseArray.some((spouseId) => connectablePersons.has(spouseId)) ||\n\t\t\tfamily.children.some((childId) => connectablePersons.has(childId));\n\n\t\tconst isOrphanFamily = !anyMemberConnectable;\n\n\t\t// If orphan families are NOT allowed, skip them entirely\n\t\tif (isOrphanFamily && !allowOrphanFamilies) {\n\t\t\treturn; // Skip this family - no FAM record created\n\t\t}\n\n\t\tconst famId = `@F${famIndex++}@`;\n\t\tfamilyIdMap.set(key, famId);\n\n\t\tlines.push(`0 ${famId} FAM`);\n\n\t\t// Add _IS_ORPHAN_FAMILY tag if this is an orphan family (and allowed)\n\t\tif (isOrphanFamily && allowOrphanFamilies) {\n\t\t\tlines.push(`1 _IS_ORPHAN_FAMILY Y`);\n\t\t}\n\n\t\tif (spouseArray.length === 2) {\n\t\t\tconst [person1, person2] = spouseArray;\n\t\t\tconst person1Data = pedigreeData.persons?.find(\n\t\t\t\t(p) => p.id === person1\n\t\t\t);\n\t\t\tconst person2Data = pedigreeData.persons?.find(\n\t\t\t\t(p) => p.id === person2\n\t\t\t);\n\n\t\t\tconst gender1 = extractGender(\n\t\t\t\tperson1Data?.fullDetails?.persons?.[0] || person1Data\n\t\t\t);\n\t\t\tconst gender2 = extractGender(\n\t\t\t\tperson2Data?.fullDetails?.persons?.[0] || person2Data\n\t\t\t);\n\n\t\t\tconst p1 = personIdMap.get(person1);\n\t\t\tconst p2 = personIdMap.get(person2);\n\t\t\tif (gender1 === \"M\" || gender2 === \"F\") {\n\t\t\t\tif (p1) lines.push(`1 HUSB ${p1}`);\n\t\t\t\tif (p2) lines.push(`1 WIFE ${p2}`);\n\t\t\t} else {\n\t\t\t\tif (p2) lines.push(`1 HUSB ${p2}`);\n\t\t\t\tif (p1) lines.push(`1 WIFE ${p1}`);\n\t\t\t}\n\n\t\t\t// Add marriage facts\n\t\t\taddMarriageFacts(lines, allRelationships, person1, person2);\n\t\t} else if (spouseArray.length === 1) {\n\t\t\tconst parentData = pedigreeData.persons?.find(\n\t\t\t\t(p) => p.id === spouseArray[0]\n\t\t\t);\n\t\t\tconst gender = extractGender(\n\t\t\t\tparentData?.fullDetails?.persons?.[0] || parentData\n\t\t\t);\n\n\t\t\tif (gender === \"M\") {\n\t\t\t\tlines.push(`1 HUSB ${personIdMap.get(spouseArray[0])}`);\n\t\t\t} else {\n\t\t\t\tlines.push(`1 WIFE ${personIdMap.get(spouseArray[0])}`);\n\t\t\t}\n\t\t}\n\n\t\t// Add children\n\t\tfamily.children.forEach((childId) => {\n\t\t\tconst childGedcomId = personIdMap.get(childId);\n\t\t\tif (childGedcomId) {\n\t\t\t\tlines.push(`1 CHIL ${childGedcomId}`);\n\t\t\t}\n\t\t});\n\t});\n\n\t// Add FAMC links to individuals\n\tchildToParents.forEach((parents, childId) => {\n\t\tconst childGedcomId = personIdMap.get(childId);\n\t\tif (!childGedcomId) return;\n\n\t\tlet famId: string | undefined;\n\t\tif (parents.length >= 2) {\n\t\t\tconst famKey = parents.slice(0, 2).sort().join(\"-\");\n\t\t\tfamId = familyIdMap.get(famKey);\n\t\t} else if (parents.length === 1) {\n\t\t\tconst famKey = `single-${parents[0]}`;\n\t\t\tfamId = familyIdMap.get(famKey);\n\t\t}\n\n\t\tif (famId) {\n\t\t\tconst indiRecordIndex = lines.findIndex(\n\t\t\t\t(line) => line === `0 ${childGedcomId} INDI`\n\t\t\t);\n\t\t\tif (indiRecordIndex !== -1) {\n\t\t\t\tlines.splice(indiRecordIndex + 1, 0, `1 FAMC ${famId}`);\n\t\t\t}\n\t\t}\n\t});\n\n\t// Add FAMS links to individuals\n\tfamilies.forEach((family, key) => {\n\t\tconst famId = familyIdMap.get(key);\n\t\tif (!famId) return;\n\n\t\tfamily.spouses.forEach((spouseId) => {\n\t\t\tconst spouseGedcomId = personIdMap.get(spouseId);\n\t\t\tif (!spouseGedcomId) return;\n\n\t\t\tconst indiRecordIndex = lines.findIndex(\n\t\t\t\t(line) => line === `0 ${spouseGedcomId} INDI`\n\t\t\t);\n\t\t\tif (indiRecordIndex !== -1) {\n\t\t\t\tlet insertIndex = indiRecordIndex + 1;\n\t\t\t\twhile (\n\t\t\t\t\tinsertIndex < lines.length &&\n\t\t\t\t\tlines[insertIndex].startsWith(\"1 FAMC\")\n\t\t\t\t) {\n\t\t\t\t\tinsertIndex++;\n\t\t\t\t}\n\t\t\t\tlines.splice(insertIndex, 0, `1 FAMS ${famId}`);\n\t\t\t}\n\t\t});\n\t});\n\n\t// Final validation: Check for orphaned persons (not in any family)\n\tconst personsInFamilies = new Set<string>();\n\tfamilies.forEach((family) => {\n\t\tfamily.spouses.forEach((id) => personsInFamilies.add(id));\n\t\tfamily.children.forEach((id) => personsInFamilies.add(id));\n\t});\n\n\t// GEDCOM Trailer\n\tlines.push(\"0 TRLR\");\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Helper to add marriage facts to FAM record\n */\nfunction addMarriageFacts(\n\tlines: string[],\n\trelationships: Relationship[],\n\tperson1: string,\n\tperson2: string\n): void {\n\tconst relKey = [person1, person2].sort().join(\"-\");\n\n\tconst rel = relationships.find((r) => {\n\t\tconst a = r.person1?.resourceId || r.person1?.resource?.resourceId;\n\t\tconst b = r.person2?.resourceId || r.person2?.resource?.resourceId;\n\t\tif (!a || !b) return false;\n\t\treturn [a, b].sort().join(\"-\") === relKey;\n\t});\n\n\tif (!rel) return;\n\n\tconst marriageFacts: PersonFact[] = [];\n\n\t// Check facts directly on relationship\n\tif (rel.facts && Array.isArray(rel.facts)) {\n\t\trel.facts.forEach((f) => {\n\t\t\tif (f.type?.includes(\"Marriage\")) {\n\t\t\t\tmarriageFacts.push(f);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Check details.facts\n\tif (rel.details?.facts && Array.isArray(rel.details.facts)) {\n\t\tmarriageFacts.push(\n\t\t\t...rel.details.facts.filter((f) => f.type?.includes(\"Marriage\"))\n\t\t);\n\t}\n\n\t// Check details.persons[].facts\n\tif (rel.details?.persons && Array.isArray(rel.details.persons)) {\n\t\trel.details.persons.forEach((p) => {\n\t\t\tif (p.facts && Array.isArray(p.facts)) {\n\t\t\t\tp.facts.forEach((f) => {\n\t\t\t\t\tif (f.type?.includes(\"Marriage\")) {\n\t\t\t\t\t\tmarriageFacts.push(f);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t// Add marriage facts to FAM record\n\tmarriageFacts.forEach((mf) => {\n\t\tconst factLines = convertFactToGedcom(mf);\n\t\tfactLines.forEach((line) => lines.push(line));\n\t});\n}\n\n// Alias for backwards compatibility\nexport const convertFamilySearchToGedcom = convertToGedcom;\n"]}