huntr-cli 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/cli.js +312 -357
- package/dist/cli.js.map +4 -4
- package/package.json +1 -1
- package/src/cli.ts +394 -217
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/api/client.ts", "../src/api/personal/user.ts", "../src/api/personal/boards.ts", "../src/api/personal/jobs.ts", "../src/api/personal/activities.ts", "../src/api/personal/index.ts", "../src/cli.ts", "../src/config/token-manager.ts", "../src/config/config-manager.ts", "../src/config/keychain-manager.ts", "../src/config/clerk-session-manager.ts", "../src/commands/capture-session.ts"
|
|
4
|
-
"sourcesContent": ["import axios, { AxiosInstance, AxiosError } from 'axios';\n\n// Note: We do not auto-load .env to avoid noisy logs.\n// If you want .env loaded, run with HUNTR_LOAD_ENV=true and we will load it explicitly.\nimport dotenv from 'dotenv';\nif (process.env.HUNTR_LOAD_ENV === 'true') {\n dotenv.config({ debug: false });\n}\n\n/** A static token string OR an async function that returns a fresh token. */\nexport type TokenProvider = string | (() => Promise<string>);\n\nexport class HuntrApiClient {\n private axiosInstance: AxiosInstance;\n private tokenProvider: () => Promise<string>;\n\n constructor(tokenProvider: TokenProvider, baseURL: string = 'https://api.huntr.co/org') {\n this.tokenProvider =\n typeof tokenProvider === 'string'\n ? async () => tokenProvider\n : tokenProvider;\n\n this.axiosInstance = axios.create({ baseURL });\n\n // Inject a fresh Authorization header before every request\n this.axiosInstance.interceptors.request.use(async (config) => {\n const token = await this.tokenProvider();\n if (!token) throw new Error('No API token available.');\n config.headers = config.headers ?? {};\n config.headers['Authorization'] = `Bearer ${token}`;\n config.headers['Content-Type'] = 'application/json';\n return config;\n });\n\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error: AxiosError) => {\n if (error.response) {\n const status = error.response.status;\n const apiError = error.response.data as any;\n const message = apiError?.error?.message ?? apiError?.message ?? 'API request failed';\n throw new Error(`HTTP ${status}: ${message}`);\n }\n if (error.request) {\n throw new Error('No response from API - check your network connection');\n }\n throw error;\n },\n );\n }\n\n async get<T>(endpoint: string, params?: Record<string, any>): Promise<T> {\n const response = await this.axiosInstance.get<T>(endpoint, { params });\n return response.data;\n }\n\n async post<T>(endpoint: string, data?: any): Promise<T> {\n const response = await this.axiosInstance.post<T>(endpoint, data);\n return response.data;\n }\n\n async put<T>(endpoint: string, data?: any): Promise<T> {\n const response = await this.axiosInstance.put<T>(endpoint, data);\n return response.data;\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n const response = await this.axiosInstance.delete<T>(endpoint);\n return response.data;\n }\n\n async *paginate<T>(\n endpoint: string,\n params: Record<string, any> = {},\n limit: number = 100,\n ): AsyncGenerator<T[], void, undefined> {\n let next: string | undefined = undefined;\n\n do {\n const queryParams: Record<string, any> = { ...params, limit };\n if (next) queryParams.next = next;\n const response = await this.get<{ data: T[]; next?: string }>(endpoint, queryParams);\n yield response.data;\n next = response.next;\n } while (next);\n }\n}\n\nexport const createClient = (tokenProvider: TokenProvider, baseURL?: string): HuntrApiClient => {\n return new HuntrApiClient(tokenProvider, baseURL);\n};\n", "import { HuntrApiClient } from '../client';\nimport { UserProfile } from '../../types/personal';\n\nexport class PersonalUserApi {\n constructor(private client: HuntrApiClient) {}\n\n async getProfile(): Promise<UserProfile> {\n // Official endpoint returns the current user's profile\n return this.client.get<UserProfile>('/user');\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { Board } from '../../types/personal';\n\nexport class PersonalBoardsApi {\n constructor(private client: HuntrApiClient) {}\n\n async list(): Promise<Board[]> {\n // Official endpoint: /api/user/boards returns an array of boards\n const res = await this.client.get<unknown>('/user/boards');\n if (Array.isArray(res)) return res as Board[];\n if (res && typeof res === 'object' && Array.isArray((res as any).data)) return (res as any).data as Board[];\n // Fallback if API returns an object map\n if (res && typeof res === 'object') return Object.values(res as Record<string, Board>);\n return [];\n }\n\n async get(boardId: string): Promise<Board> {\n // There isn't a documented /api/user/boards/:id; use /api/boards/:id if needed\n return this.client.get<Board>(`/boards/${boardId}`);\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { PersonalJob, PersonalJobsResponse } from '../../types/personal';\n\nexport class PersonalJobsApi {\n constructor(private client: HuntrApiClient) {}\n\n // API returns { jobs: { [id]: PersonalJob } } \u2014 an object map, not an array\n async listByBoard(boardId: string): Promise<PersonalJobsResponse> {\n return this.client.get<PersonalJobsResponse>(`/board/${boardId}/jobs`);\n }\n\n // Convenience: returns flat array\n async listByBoardFlat(boardId: string): Promise<PersonalJob[]> {\n const response = await this.listByBoard(boardId);\n return Object.values(response.jobs);\n }\n\n async get(boardId: string, jobId: string): Promise<PersonalJob> {\n return this.client.get<PersonalJob>(`/board/${boardId}/jobs/${jobId}`);\n }\n\n async create(boardId: string, job: Partial<PersonalJob>): Promise<PersonalJob> {\n return this.client.post<PersonalJob>(`/board/${boardId}/jobs`, job);\n }\n\n async update(boardId: string, jobId: string, updates: Partial<PersonalJob>): Promise<PersonalJob> {\n return this.client.put<PersonalJob>(`/board/${boardId}/jobs/${jobId}`, updates);\n }\n\n async delete(boardId: string, jobId: string): Promise<void> {\n return this.client.delete<void>(`/board/${boardId}/jobs/${jobId}`);\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { PersonalAction, PersonalJob, PersonalJobsResponse } from '../../types/personal';\n\nexport class PersonalActionsApi {\n constructor(private client: HuntrApiClient) {}\n\n // Returns object map { [actionId]: PersonalAction }\n async listByBoard(boardId: string): Promise<Record<string, PersonalAction>> {\n return this.client.get<Record<string, PersonalAction>>(`/board/${boardId}/actions`);\n }\n\n // Returns flattened array sorted by date desc, optionally filtered by action types\n async listByBoardFlat(\n boardId: string,\n opts?: { since?: Date; types?: string[] },\n ): Promise<PersonalAction[]> {\n const raw = await this.listByBoard(boardId);\n let actions = Object.values(raw);\n\n if (opts?.since) {\n const cutoff = opts.since.getTime();\n actions = actions.filter(a => new Date(a.date || a.createdAt).getTime() >= cutoff);\n }\n\n if (opts?.types && opts.types.length > 0) {\n actions = actions.filter(a => opts.types!.includes(a.actionType));\n }\n\n return actions.sort((a, b) =>\n new Date(b.date || b.createdAt).getTime() - new Date(a.date || a.createdAt).getTime(),\n );\n }\n\n // Joins actions with job data to produce enriched rows\n async weekSummary(boardId: string): Promise<Array<{\n date: string;\n actionType: string;\n company: string;\n jobTitle: string;\n status: string;\n url: string;\n address: string;\n }>> {\n const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n const [actions, jobsResponse] = await Promise.all([\n this.listByBoardFlat(boardId, { since }),\n this.client.get<PersonalJobsResponse>(`/board/${boardId}/jobs`),\n ]);\n\n const jobs = jobsResponse.jobs;\n\n return actions\n .filter(a => a.actionType !== 'ACTIVITY_CREATED')\n .map(a => {\n const jobId = a.data?._job;\n const job: PersonalJob | undefined = jobId ? jobs[jobId] : undefined;\n return {\n date: new Date(a.date || a.createdAt).toISOString().substring(0, 16),\n actionType: a.actionType,\n company: a.data?.company?.name ?? '',\n jobTitle: a.data?.job?.title ?? '',\n status: a.data?.toList?.name ?? '',\n url: job?.url ?? '',\n address: job?.location?.address ?? '',\n };\n });\n }\n}\n", "import { createClient, TokenProvider } from '../client';\nimport { PersonalUserApi } from './user';\nimport { PersonalBoardsApi } from './boards';\nimport { PersonalJobsApi } from './jobs';\nimport { PersonalActionsApi } from './activities';\n\nexport class HuntrPersonalApi {\n public user: PersonalUserApi;\n public boards: PersonalBoardsApi;\n public jobs: PersonalJobsApi;\n public actions: PersonalActionsApi;\n\n constructor(tokenProvider: TokenProvider) {\n const client = createClient(tokenProvider, 'https://api.huntr.co/api');\n this.user = new PersonalUserApi(client);\n this.boards = new PersonalBoardsApi(client);\n this.jobs = new PersonalJobsApi(client);\n this.actions = new PersonalActionsApi(client);\n }\n}\n\nexport * from './user';\nexport * from './boards';\nexport * from './jobs';\nexport * from './activities';\n", "#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { HuntrPersonalApi } from './api/personal';\nimport { TokenManager } from './config/token-manager';\nimport { ClerkSessionManager } from './config/clerk-session-manager';\nimport { captureSession, checkCdpSession } from './commands/capture-session';\nimport {\n parseListOptions,\n validateFields,\n formatTableWithFields,\n formatCsvWithFields,\n formatJsonWithFields,\n formatPdf,\n formatExcel,\n} from './lib/list-options';\n\nconst program = new Command();\nconst tokenManager = new TokenManager();\n\nasync function getApi(token?: string): Promise<HuntrPersonalApi> {\n const provider = await tokenManager.getTokenProvider({ token });\n return new HuntrPersonalApi(provider);\n}\n\nprogram\n .name('huntr')\n .description('CLI tool for Huntr')\n .version('1.0.0')\n .option('-t, --token <token>', 'API token (overrides all other sources)');\n\n// \u2500\u2500 me \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nprogram\n .command('me')\n .description('Show your user profile')\n .option('-j, --json', 'Output as JSON')\n .action(async (options, command) => {\n try {\n const api = await getApi(command.parent?.opts().token);\n const profile = await api.user.getProfile();\n if (options.json) {\n console.log(JSON.stringify(profile, null, 2));\n } else {\n console.log(`Name: ${profile.givenName ?? profile.firstName ?? ''} ${profile.familyName ?? profile.lastName ?? ''}`);\n console.log(`Email: ${profile.email}`);\n console.log(`ID: ${profile.id}`);\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 boards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst boards = program.command('boards').description('Manage your boards');\n\nboards\n .command('list')\n .description('List all your boards')\n .option('-f, --format <format>', 'Output format: table (default), json, csv, pdf, excel')\n .option('-j, --json', 'Output as JSON (legacy, same as --format json)')\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .action(async (options, command) => {\n try {\n const AVAILABLE_FIELDS = ['ID', 'Name', 'Created'];\n const listOpts = parseListOptions(options);\n const fields = validateFields(AVAILABLE_FIELDS, listOpts.fields);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n const response = await api.boards.list();\n const boardsList = Array.isArray(response) ? response : (response as any).data ?? [];\n\n if (boardsList.length === 0) {\n console.log('No boards found.');\n return;\n }\n\n const rows = boardsList.map((b: any) => ({\n ID: b.id,\n Name: b.name ?? 'N/A',\n Created: new Date(b.createdAt).toLocaleDateString(),\n }));\n\n if (listOpts.format === 'json') {\n console.log(formatJsonWithFields(rows, fields));\n } else if (listOpts.format === 'csv') {\n console.log(formatCsvWithFields(rows, fields));\n } else if (listOpts.format === 'pdf') {\n const buffer = formatPdf(rows, fields, 'Boards List');\n process.stdout.write(buffer);\n } else if (listOpts.format === 'excel') {\n const buffer = await formatExcel(rows, fields, 'Boards');\n process.stdout.write(buffer);\n } else {\n console.log(formatTableWithFields(rows, fields));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nboards\n .command('get')\n .description('Get details of a specific board')\n .argument('<board-id>', 'Board ID')\n .option('-j, --json', 'Output as JSON')\n .action(async (boardId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const board = await api.boards.get(boardId);\n if (options.json) {\n console.log(JSON.stringify(board, null, 2));\n } else {\n console.log(`Board: ${board.name}`);\n console.log(`ID: ${board.id}`);\n console.log(`Created: ${new Date(board.createdAt).toLocaleString()}`);\n if (board.lists?.length) {\n console.log('\\nLists:');\n board.lists.forEach(l => console.log(` - ${l.name}`));\n }\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 jobs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst jobs = program.command('jobs').description('Manage jobs on your boards');\n\nconst JOB_AVAILABLE_FIELDS: ReadonlyArray<string> = [\n 'ID', 'Title', 'URL', 'RootDomain', 'Description',\n 'CompanyId', 'ListId', 'BoardId',\n 'SalaryMin', 'SalaryMax', 'SalaryCurrency',\n 'LocationAddress', 'LocationName', 'LocationUrl', 'LocationLat', 'LocationLng',\n 'Created', 'Updated', 'LastMoved',\n];\n\njobs\n .command('fields')\n .description('List available fields for jobs list')\n .option('-j, --json', 'Output as JSON')\n .action(async (options) => {\n try {\n const rows = JOB_AVAILABLE_FIELDS.map((f: string) => ({ Field: f }));\n if (options.json) {\n console.log(JSON.stringify(rows.map(r => r.Field), null, 2));\n } else {\n console.log(formatTableWithFields(rows, ['Field']));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\njobs\n .command('list')\n .description('List jobs on a board')\n .argument('<board-id>', 'Board ID')\n .option('-f, --format <format>', 'Output format: table (default), json, csv, pdf, excel')\n .option('-j, --json', 'Output as JSON (legacy, same as --format json)')\n .option('--fields <fields>', 'Comma-separated list of fields to include (use \"help\" or \"all\")')\n .action(async (boardId, options, command) => {\n try {\n const AVAILABLE_FIELDS = [...JOB_AVAILABLE_FIELDS];\n const listOpts = parseListOptions(options);\n\n // If user asked for field help, print and exit success\n const wantsHelp = (listOpts.fields ?? []).some(f => /^(help|\\?)$/i.test(f));\n if (wantsHelp) {\n const rows = AVAILABLE_FIELDS.map(f => ({ Field: f }));\n console.log(formatTableWithFields(rows, ['Field']));\n return;\n }\n\n const requested = listOpts.fields;\n const fields = (requested && requested.length === 1 && /^(all)$/i.test(requested[0]))\n ? AVAILABLE_FIELDS.slice()\n : validateFields(AVAILABLE_FIELDS, requested);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n const jobsList = await api.jobs.listByBoardFlat(boardId);\n\n if (jobsList.length === 0) {\n console.log('No jobs found.');\n return;\n }\n\n const rows = jobsList.map(j => ({\n ID: j.id,\n Title: j.title ?? '',\n URL: j.url ?? '',\n RootDomain: j.rootDomain ?? '',\n Description: j.htmlDescription ?? '',\n CompanyId: j._company ?? '',\n ListId: j._list ?? '',\n BoardId: j._board ?? '',\n SalaryMin: j.salary?.min ?? '',\n SalaryMax: j.salary?.max ?? '',\n SalaryCurrency: j.salary?.currency ?? '',\n LocationAddress: j.location?.address ?? '',\n LocationName: j.location?.name ?? '',\n LocationUrl: j.location?.url ?? '',\n LocationLat: j.location?.lat ?? '',\n LocationLng: j.location?.lng ?? '',\n Created: new Date(j.createdAt).toLocaleDateString(),\n Updated: j.updatedAt ? new Date(j.updatedAt).toLocaleDateString() : '',\n LastMoved: j.lastMovedAt ? new Date(j.lastMovedAt).toLocaleDateString() : '',\n }));\n\n if (listOpts.format === 'json') {\n console.log(formatJsonWithFields(rows, fields));\n } else if (listOpts.format === 'csv') {\n console.log(formatCsvWithFields(rows, fields));\n } else if (listOpts.format === 'pdf') {\n const buffer = formatPdf(rows, fields, 'Jobs List');\n process.stdout.write(buffer);\n } else if (listOpts.format === 'excel') {\n const buffer = await formatExcel(rows, fields, 'Jobs');\n process.stdout.write(buffer);\n } else {\n console.log(formatTableWithFields(rows, fields));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\njobs\n .command('get')\n .description('Get details of a specific job')\n .argument('<board-id>', 'Board ID')\n .argument('<job-id>', 'Job ID')\n .option('-j, --json', 'Output as JSON')\n .action(async (boardId, jobId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const job = await api.jobs.get(boardId, jobId);\n if (options.json) {\n console.log(JSON.stringify(job, null, 2));\n } else {\n console.log('\\nJob Details:');\n console.log(` Title: ${job.title}`);\n console.log(` URL: ${job.url ?? 'N/A'}`);\n console.log(` Location: ${job.location?.address ?? 'N/A'}`);\n if (job.salary) {\n console.log(` Salary: ${job.salary.min ?? 'N/A'} - ${job.salary.max ?? 'N/A'} ${job.salary.currency ?? ''}`);\n }\n console.log(` Created: ${new Date(job.createdAt).toLocaleString()}`);\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 activities \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst activities = program.command('activities').description('View your board activity log');\n\nactivities\n .command('list')\n .description('List actions for a board')\n .argument('<board-id>', 'Board ID')\n .option('-f, --format <format>', 'Output format: table (default), json, csv, pdf, excel')\n .option('-d, --days <days>', 'Filter to last N days (e.g. 7 for past week)')\n .option('-w, --week', 'Filter to last 7 days (legacy, same as --days 7)')\n .option('--types <types>', 'Comma-separated action types (e.g. JOB_MOVED,NOTE_CREATED)')\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .option('-j, --json', 'Output as JSON (legacy, same as --format json)')\n .action(async (boardId, options, command) => {\n try {\n const AVAILABLE_FIELDS = [\n 'ID',\n 'Date',\n 'Created',\n 'Updated',\n 'Type',\n 'Company',\n 'CompanyId',\n 'Job',\n 'JobId',\n 'FromStatus',\n 'FromStatusId',\n 'ToStatus',\n 'ToStatusId',\n 'Note',\n 'NoteId',\n 'BoardId',\n ];\n const listOpts = parseListOptions(options);\n const fields = validateFields(AVAILABLE_FIELDS, listOpts.fields);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n\n const apiOpts: { since?: Date; types?: string[] } = {};\n if (listOpts.days) {\n apiOpts.since = new Date(Date.now() - listOpts.days * 24 * 60 * 60 * 1000);\n }\n if (listOpts.types) {\n apiOpts.types = listOpts.types;\n }\n\n const actions = await api.actions.listByBoardFlat(boardId, apiOpts);\n\n if (actions.length === 0) {\n console.log('No activities found.');\n return;\n }\n\n const rows = actions.map(a => ({\n ID: a.id,\n Date: new Date(a.date || a.createdAt).toISOString().substring(0, 16),\n Created: new Date(a.createdAt).toISOString().substring(0, 16),\n Updated: a.updatedAt ? new Date(a.updatedAt).toISOString().substring(0, 16) : '',\n Type: a.actionType,\n Company: a.data?.company?.name ?? '',\n CompanyId: a.data?._company ?? '',\n Job: (a.data?.job?.title ?? '').substring(0, 40),\n JobId: a.data?._job ?? '',\n FromStatus: a.data?.fromList?.name ?? '',\n FromStatusId: a.data?._fromList ?? '',\n ToStatus: a.data?.toList?.name ?? '',\n ToStatusId: a.data?._toList ?? '',\n Note: a.data?.note?.text ?? '',\n NoteId: a.data?.note?.id ?? '',\n BoardId: a.data?._board ?? '',\n }));\n\n if (listOpts.format === 'json') {\n console.log(formatJsonWithFields(rows, fields));\n } else if (listOpts.format === 'csv') {\n console.log(formatCsvWithFields(rows, fields));\n } else if (listOpts.format === 'pdf') {\n const buffer = formatPdf(rows, fields, 'Activities List');\n process.stdout.write(buffer);\n } else if (listOpts.format === 'excel') {\n const buffer = await formatExcel(rows, fields, 'Activities');\n process.stdout.write(buffer);\n } else {\n console.log(formatTableWithFields(rows, fields));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nactivities\n .command('fields')\n .description('Show available fields for activities list command')\n .action(() => {\n const AVAILABLE_FIELDS = [\n 'ID',\n 'Date',\n 'Created',\n 'Updated',\n 'Type',\n 'Company',\n 'CompanyId',\n 'Job',\n 'JobId',\n 'FromStatus',\n 'FromStatusId',\n 'ToStatus',\n 'ToStatusId',\n 'Note',\n 'NoteId',\n 'BoardId',\n ];\n const rows = AVAILABLE_FIELDS.map(f => ({ Field: f }));\n console.log(formatTableWithFields(rows, ['Field']));\n });\n\nactivities\n .command('week-csv')\n .description('Export last 7 days of activity as CSV')\n .argument('<board-id>', 'Board ID')\n .action(async (boardId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const rows = await api.actions.weekSummary(boardId);\n const lines = ['Date,Action,Company,Job Title,Status,Job URL,Address'];\n for (const r of rows) {\n lines.push([\n r.date,\n r.actionType,\n `\"${r.company.replace(/\"/g, '\"\"')}\"`,\n `\"${r.jobTitle.replace(/\"/g, '\"\"')}\"`,\n r.status,\n r.url,\n `\"${r.address.replace(/\"/g, '\"\"')}\"`,\n ].join(','));\n }\n console.log(lines.join('\\n'));\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst config = program.command('config').description('Manage CLI configuration');\n\nconfig\n .command('set-token')\n .description('Save API token to config file or keychain')\n .argument('<token>', 'API token to save')\n .option('-k, --keychain', 'Save to macOS Keychain instead of config file')\n .action(async (token, options) => {\n try {\n const location = options.keychain ? 'keychain' : 'config';\n await tokenManager.saveToken(token, location);\n const locationName = options.keychain ? 'macOS Keychain' : '~/.huntr/config.json';\n console.log(`\u2713 Token saved to ${locationName}`);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('capture-session')\n .description('Capture Clerk session from your browser automatically (recommended)')\n .action(async () => {\n try {\n await captureSession();\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('check-cdp')\n .description('Check Chrome DevTools + Clerk cookie visibility for session capture')\n .action(async () => {\n try {\n await checkCdpSession();\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('set-session')\n .description('Save Clerk session cookie for automatic JWT refresh (recommended)')\n .argument('<session-cookie>', 'Value of the __session cookie from your browser')\n .argument('[session-id]', 'Clerk session ID (sess_...) \u2014 auto-detected from cookie if omitted')\n .addHelpText('after', `\nHow to get your __session cookie:\n 1. Open huntr.co in Chrome and log in\n 2. Open DevTools \u2192 Application \u2192 Cookies \u2192 https://huntr.co\n 3. Find the cookie named __session and copy its Value (the long JWT string)\n 4. Run: huntr config set-session <value>\n\nThe session ID (sess_...) is extracted automatically from the JWT.\nThe session persists for weeks; re-run set-session if you get auth errors.\n `)\n .action(async (sessionCookie, sessionId) => {\n try {\n const mgr = tokenManager.clerkSession;\n\n // Auto-detect session ID from the JWT payload (sid claim)\n let resolvedSessionId = sessionId as string | undefined;\n if (!resolvedSessionId) {\n const detected = ClerkSessionManager.extractSessionId(sessionCookie);\n if (detected) {\n resolvedSessionId = detected;\n console.log(` Session ID detected: ${resolvedSessionId}`);\n } else {\n console.error(\n 'Could not auto-detect session ID from the __session JWT.\\n' +\n 'Find it in the browser console: Clerk.session.id\\n' +\n 'Then run: huntr config set-session <cookie> <session-id>',\n );\n process.exit(1);\n }\n }\n\n // Strip prefix if user pasted \"__session=...\" prefix\n const rawCookie = sessionCookie.startsWith('__session=')\n ? sessionCookie.slice('__session='.length)\n : sessionCookie;\n\n await mgr.saveSession(rawCookie, resolvedSessionId!);\n\n // Verify it works immediately\n console.log(' Testing session\u2026');\n try {\n const token = await mgr.getFreshToken();\n console.log(`\u2713 Session saved and verified (token starts with: ${token.substring(0, 20)}\u2026)`);\n console.log(' Tokens will auto-refresh before each command.');\n } catch (err) {\n console.warn(`\u26A0 Session saved but test refresh failed: ${err instanceof Error ? err.message : err}`);\n console.warn(' Your cookie may be expired. Try extracting it again from the browser.');\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('test-session')\n .description('Test the stored Clerk session by fetching a fresh token and calling /me')\n .action(async () => {\n try {\n const mgr = tokenManager.clerkSession;\n if (!(await mgr.hasSession())) {\n console.error('No session stored. Run: huntr config set-session <__session-cookie>');\n process.exit(1);\n }\n process.stdout.write(' Refreshing token from Clerk\u2026 ');\n const token = await mgr.getFreshToken();\n console.log(`\u2713 (${token.substring(0, 20)}\u2026)`);\n process.stdout.write(' Calling Huntr API /me\u2026 ');\n const api = new (await import('./api/personal')).HuntrPersonalApi(token);\n const profile = await api.user.getProfile();\n console.log('\u2713');\n console.log(`\\n Logged in as: ${profile.givenName ?? profile.firstName ?? ''} ${profile.familyName ?? profile.lastName ?? ''} <${profile.email}>`);\n console.log(' Session is working correctly. Tokens auto-refresh before each command.');\n } catch (error) {\n console.error('\\nFailed:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('show-token')\n .description('Show which authentication sources are configured')\n .action(async () => {\n try {\n const sources = await tokenManager.showTokenSources();\n console.log('\\nConfigured authentication sources:');\n console.log(` Environment variable (HUNTR_API_TOKEN): ${sources.env ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` Clerk session (auto-refresh): ${sources.clerkSession ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` Config file (~/.huntr/config.json): ${sources.config ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` macOS Keychain: ${sources.keychain ? '\u2713 Set' : '\u2717 Not set'}`);\n if (!sources.env && !sources.clerkSession && !sources.config && !sources.keychain) {\n console.log('\\nNo credentials found.');\n console.log('Recommended: huntr config set-session <__session-cookie>');\n console.log('Alternative: huntr config set-token <token> [--keychain]');\n } else if (sources.clerkSession) {\n console.log('\\n\u2713 Clerk session active \u2014 tokens refresh automatically.');\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('clear-token')\n .description('Remove saved API token')\n .option('-k, --keychain', 'Clear from macOS Keychain only')\n .option('-c, --config', 'Clear from config file only')\n .action(async (options) => {\n try {\n let location: 'config' | 'keychain' | 'all' = 'all';\n if (options.keychain && !options.config) location = 'keychain';\n else if (options.config && !options.keychain) location = 'config';\n await tokenManager.clearToken(location);\n const message = location === 'all' ? 'all locations'\n : location === 'keychain' ? 'macOS Keychain'\n : 'config file';\n console.log(`\u2713 Token cleared from ${message}`);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('clear-session')\n .description('Remove saved Clerk session cookie')\n .action(async () => {\n try {\n await tokenManager.clerkSession.clearSession();\n console.log('\u2713 Clerk session cleared');\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n", "import { password } from '@inquirer/prompts';\nimport { ConfigManager } from './config-manager';\nimport { KeychainManager } from './keychain-manager';\nimport { ClerkSessionManager } from './clerk-session-manager';\nimport type { TokenProvider } from '../api/client';\n\nexport interface TokenOptions {\n token?: string;\n usePrompt?: boolean;\n}\n\nexport class TokenManager {\n private configManager: ConfigManager;\n private keychainManager: KeychainManager;\n readonly clerkSession: ClerkSessionManager;\n\n constructor() {\n this.configManager = new ConfigManager();\n this.keychainManager = new KeychainManager();\n this.clerkSession = new ClerkSessionManager();\n }\n\n /**\n * Returns a TokenProvider for use with HuntrPersonalApi.\n *\n * Resolution order:\n * 1. CLI --token argument (static, passed via options)\n * 2. HUNTR_API_TOKEN env var (static)\n * 3. Stored Clerk session cookie \u2192 auto-refresh on every call\n * 4. Static token from config file or keychain\n * 5. Interactive prompt\n */\n async getTokenProvider(options: TokenOptions = {}): Promise<TokenProvider> {\n // 1. CLI argument \u2014 static token\n if (options.token) {\n return options.token;\n }\n\n // 2. Environment variable \u2014 static token\n const envToken = process.env.HUNTR_API_TOKEN;\n if (envToken) {\n return envToken;\n }\n\n // 3. Clerk session \u2014 dynamic refresh\n if (await this.clerkSession.hasSession()) {\n return () => this.clerkSession.getFreshToken();\n }\n\n // 4. Static token from config or keychain\n const configToken = this.configManager.getToken();\n if (configToken) return configToken;\n\n const keychainToken = await this.keychainManager.getToken();\n if (keychainToken) return keychainToken;\n\n // 5. Interactive prompt \u2014 static token (short-lived, but usable)\n if (options.usePrompt !== false) {\n const promptedToken = await password({\n message: 'Enter your Huntr API token:',\n mask: '*',\n });\n\n if (promptedToken) {\n const saveChoice = await this.promptSaveLocation();\n if (saveChoice !== 'none') {\n await this.saveToken(promptedToken, saveChoice);\n }\n return promptedToken;\n }\n }\n\n throw new Error(\n 'No Huntr credentials found. Options:\\n' +\n ' \u2022 Clerk session (recommended): huntr config set-session <__session-cookie>\\n' +\n ' \u2022 Static token: huntr config set-token <token> [--keychain]\\n' +\n ' \u2022 CLI flag: huntr --token <token> <command>\\n' +\n ' \u2022 Environment: HUNTR_API_TOKEN=<token> huntr <command>',\n );\n }\n\n /**\n * Legacy helper \u2014 returns a resolved static token string.\n * Use getTokenProvider() for new code so session refresh works.\n */\n async getToken(options: TokenOptions = {}): Promise<string> {\n if (options.token) return options.token;\n const envToken = process.env.HUNTR_API_TOKEN;\n if (envToken) return envToken;\n const configToken = this.configManager.getToken();\n if (configToken) return configToken;\n const keychainToken = await this.keychainManager.getToken();\n if (keychainToken) return keychainToken;\n throw new Error('No static token found. Try huntr config set-token or set-session.');\n }\n\n private async promptSaveLocation(): Promise<'config' | 'keychain' | 'none'> {\n const { select } = await import('@inquirer/prompts');\n return await select({\n message: 'Where would you like to save this token?',\n choices: [\n { name: 'Save to config file (~/.huntr/config.json)', value: 'config' as const },\n { name: 'Save to macOS Keychain (secure)', value: 'keychain' as const },\n { name: 'Do not save (enter each time)', value: 'none' as const },\n ],\n }) as 'config' | 'keychain' | 'none';\n }\n\n async saveToken(token: string, location: 'config' | 'keychain'): Promise<void> {\n if (location === 'config') {\n this.configManager.setToken(token);\n } else {\n await this.keychainManager.setToken(token);\n }\n }\n\n async clearToken(location?: 'config' | 'keychain' | 'all'): Promise<void> {\n if (!location || location === 'all' || location === 'config') {\n this.configManager.clearToken();\n }\n if (!location || location === 'all' || location === 'keychain') {\n await this.keychainManager.deleteToken();\n }\n }\n\n async showTokenSources(): Promise<{\n env: boolean;\n config: boolean;\n keychain: boolean;\n clerkSession: boolean;\n }> {\n return {\n env: !!process.env.HUNTR_API_TOKEN,\n config: !!this.configManager.getToken(),\n keychain: !!(await this.keychainManager.getToken()),\n clerkSession: await this.clerkSession.hasSession(),\n };\n }\n}\n", "import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport interface HuntrConfig {\n apiToken?: string;\n api?: {\n boardsPath?: '/boards' | '/board';\n boardsShape?: 'array' | 'dataArray' | 'map';\n };\n}\n\nexport class ConfigManager {\n private configDir: string;\n private configPath: string;\n\n constructor() {\n this.configDir = path.join(os.homedir(), '.huntr');\n this.configPath = path.join(this.configDir, 'config.json');\n }\n\n private ensureConfigDir(): void {\n if (!fs.existsSync(this.configDir)) {\n fs.mkdirSync(this.configDir, { recursive: true });\n }\n }\n\n getConfig(): HuntrConfig {\n try {\n if (fs.existsSync(this.configPath)) {\n const content = fs.readFileSync(this.configPath, 'utf-8');\n return JSON.parse(content);\n }\n } catch (error) {\n // Return empty config if file doesn't exist or is invalid\n }\n return {};\n }\n\n setConfig(config: HuntrConfig): void {\n this.ensureConfigDir();\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));\n }\n\n getToken(): string | undefined {\n return this.getConfig().apiToken;\n }\n\n getBoardsApiPrefs(): { path?: '/boards' | '/board'; shape?: 'array' | 'dataArray' | 'map' } {\n const cfg = this.getConfig();\n return { path: cfg.api?.boardsPath, shape: cfg.api?.boardsShape };\n }\n\n setBoardsApiPrefs(prefs: { path: '/boards' | '/board'; shape: 'array' | 'dataArray' | 'map' }): void {\n const cfg = this.getConfig();\n cfg.api = cfg.api ?? {};\n cfg.api.boardsPath = prefs.path;\n cfg.api.boardsShape = prefs.shape;\n this.setConfig(cfg);\n }\n\n setToken(token: string): void {\n const config = this.getConfig();\n config.apiToken = token;\n this.setConfig(config);\n }\n\n clearToken(): void {\n const config = this.getConfig();\n delete config.apiToken;\n this.setConfig(config);\n }\n}\n", "import keytar from 'keytar';\n\nconst SERVICE_NAME = 'huntr-cli';\nconst ACCOUNT_NAME = 'api-token';\n\nexport class KeychainManager {\n async getToken(): Promise<string | null> {\n try {\n return await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n } catch (error) {\n return null;\n }\n }\n\n async setToken(token: string): Promise<void> {\n try {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);\n } catch (error) {\n throw new Error('Failed to save token to keychain');\n }\n }\n\n async deleteToken(): Promise<boolean> {\n try {\n return await keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n } catch (error) {\n return false;\n }\n }\n}\n", "import keytar from 'keytar';\nimport https from 'https';\n\nconst SERVICE_NAME = 'huntr-cli';\nconst ACCOUNT_SESSION_COOKIE = 'clerk-session-cookie'; // __session value\nconst ACCOUNT_SESSION_ID = 'clerk-session-id'; // sess_...\nconst ACCOUNT_CLIENT_UAT = 'clerk-client-uat'; // __client_uat value (optional)\nconst ACCOUNT_EXTRA_COOKIES = 'clerk-extra-cookies'; // JSON map of clerk-domain cookies\n\nconst CLERK_HOST = 'clerk.huntr.co';\n\n/**\n * Manages Clerk session-based JWT refresh for the Huntr CLI.\n *\n * Modern Clerk architecture (v5+):\n * - __session cookie : stores the short-lived session JWT (60s exp).\n * The cookie itself has a long expiry (1 year);\n * Clerk JS updates its *value* via FAPI silently.\n * - __client_uat : Unix timestamp of last client update \u2014 not a credential.\n *\n * To refresh from outside a browser, we POST the __session value to Clerk's\n * FAPI tokens endpoint. Clerk validates the session and returns a fresh JWT.\n *\n * Endpoint:\n * POST https://clerk.huntr.co/v1/client/sessions/{sessionId}/tokens\n * Cookie: __session=<value>\n * Response: { jwt: \"ey...\" }\n *\n * The __session value must be re-extracted from the browser periodically\n * (roughly every few weeks, when Clerk rotates the underlying session).\n * For daily use it persists fine.\n */\nexport class ClerkSessionManager {\n // \u2500\u2500 storage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async saveSession(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string,\n extraCookies?: Record<string, string>,\n ): Promise<void> {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE, sessionCookieValue);\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_SESSION_ID, sessionId);\n if (clientUat) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT, clientUat);\n }\n if (extraCookies && Object.keys(extraCookies).length > 0) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES, JSON.stringify(extraCookies));\n }\n }\n\n async getSessionCookie(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE);\n }\n\n async getSessionId(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_SESSION_ID);\n }\n\n async getClientUat(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT);\n }\n\n async getExtraCookies(): Promise<Record<string, string>> {\n const raw = await keytar.getPassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES);\n if (!raw) return {};\n try {\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (typeof v === 'string' && v.length > 0) out[k] = v;\n }\n return out;\n } catch {\n return {};\n }\n }\n\n async clearSession(): Promise<void> {\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_SESSION_ID);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES);\n }\n\n async hasSession(): Promise<boolean> {\n const cookie = await this.getSessionCookie();\n const sessionId = await this.getSessionId();\n return !!(cookie && sessionId);\n }\n\n // \u2500\u2500 token refresh \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Returns a fresh Clerk JWT by POSTing to the Clerk FAPI tokens endpoint\n * using the stored __session cookie value.\n */\n async getFreshToken(): Promise<string> {\n const sessionCookie = await this.getSessionCookie();\n const sessionId = await this.getSessionId();\n const clientUat = await this.getClientUat();\n const extraCookies = await this.getExtraCookies();\n\n if (!sessionCookie || !sessionId) {\n throw new Error(\n 'No Clerk session stored. Run:\\n' +\n ' huntr config set-session <__session-cookie-value>\\n' +\n 'See \"huntr config set-session --help\" for instructions.',\n );\n }\n\n return this.fetchToken(sessionCookie, sessionId, clientUat, extraCookies);\n }\n\n async refreshFromProvidedSession(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string | null,\n extraCookies?: Record<string, string>,\n ): Promise<string> {\n return this.fetchToken(sessionCookieValue, sessionId, clientUat, extraCookies);\n }\n\n private fetchToken(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string | null,\n extraCookies: Record<string, string> = {},\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n // Match the exact request Clerk JS makes (version pinned to what huntr.co loads)\n const path = `/v1/client/sessions/${sessionId}/tokens?_clerk_js_version=4.73.14`;\n // Strip any \"__session=\" prefix if user pasted it with the name\n const raw = sessionCookieValue.startsWith('__session=')\n ? sessionCookieValue.slice('__session='.length)\n : sessionCookieValue;\n // Send all cookies Clerk expects, matching browser credentials:include behaviour\n const uat = clientUat && clientUat.trim() ? clientUat.trim() : '1';\n const cookieParts = [`__session=${raw}`, `__client_uat=${uat}`];\n for (const [name, value] of Object.entries(extraCookies)) {\n if (!value || name === '__session' || name === '__client_uat') continue;\n if (!/^[A-Za-z0-9_.-]+$/.test(name)) continue;\n cookieParts.push(`${name}=${value}`);\n }\n const cookieHeader = cookieParts.join('; ');\n\n const options = {\n hostname: CLERK_HOST,\n path,\n method: 'POST',\n headers: {\n 'Cookie': cookieHeader,\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Content-Length': '0',\n 'Accept': 'application/json',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\n 'Origin': 'https://huntr.co',\n 'Referer': 'https://huntr.co/',\n 'sec-fetch-site': 'same-site',\n 'sec-fetch-mode': 'cors',\n 'sec-fetch-dest': 'empty',\n },\n };\n\n const req = https.request(options, (res) => {\n let body = '';\n res.on('data', (chunk: Buffer) => { body += chunk.toString(); });\nres.on('end', () => {\n void (async () => {\n if (res.statusCode === 200 || res.statusCode === 201) {\n try {\n const data = JSON.parse(body);\n // Clerk FAPI response: { object: 'token', jwt: '...' }\n const token = data.jwt ?? data.token ?? data.object?.jwt;\n if (!token) {\n reject(new Error(`Unexpected Clerk response: ${body.substring(0, 300)}`));\n } else {\n // Clerk may rotate __session on refresh via Set-Cookie.\n // Persisting it prevents \"works once, fails later\" behavior.\n await this.persistRotatedSessionCookie(res.headers['set-cookie'], sessionId, raw, uat, extraCookies);\n resolve(token as string);\n }\n } catch {\n reject(new Error(`Failed to parse Clerk response: ${body.substring(0, 300)}`));\n }\n } else if (res.statusCode === 401 || res.statusCode === 403) {\n reject(new Error(\n `Clerk session expired or invalid (HTTP ${res.statusCode}).\\n` +\n 'Re-extract your __session cookie from the browser:\\n' +\n ' DevTools \u2192 Application \u2192 Cookies \u2192 https://huntr.co \u2192 __session \u2192 Value\\n' +\n 'Then run: huntr config set-session <new-value>',\n ));\n } else {\n reject(new Error(\n `Clerk token refresh failed: HTTP ${res.statusCode}\\n${body.substring(0, 300)}`,\n ));\n }\n })();\n });\n });\n\n req.on('error', (err: Error) =>\n reject(new Error(`Network error refreshing token: ${err.message}`)),\n );\n req.end();\n });\n }\n\n private async persistRotatedSessionCookie(\n setCookie: string | string[] | undefined,\n sessionId: string,\n currentSessionCookie: string,\n clientUat?: string,\n extraCookies: Record<string, string> = {},\n ): Promise<void> {\n if (!setCookie) return;\n const cookies = Array.isArray(setCookie) ? setCookie : [setCookie];\n let sessionCookie: string = currentSessionCookie;\n let rotatedUat = clientUat;\n const rotatedExtras: Record<string, string> = { ...extraCookies };\n\n for (const header of cookies) {\n const firstPair = header.split(';', 1)[0] ?? '';\n const idx = firstPair.indexOf('=');\n if (idx <= 0) continue;\n const name = firstPair.slice(0, idx);\n const value = firstPair.slice(idx + 1);\n if (!value) continue;\n\n if (name === '__session') {\n sessionCookie = value;\n } else if (name === '__client_uat') {\n rotatedUat = value;\n } else if (/^[A-Za-z0-9_.-]+$/.test(name)) {\n rotatedExtras[name] = value;\n }\n }\n\n await this.saveSession(sessionCookie, sessionId, rotatedUat, rotatedExtras);\n }\n\n // \u2500\u2500 session-id extraction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Extracts the Clerk session ID (sess_...) from a __session JWT value.\n * The __session cookie value IS a JWT; its payload contains `sid`.\n */\n static extractSessionId(sessionJwt: string): string | null {\n try {\n const raw = sessionJwt.startsWith('__session=')\n ? sessionJwt.slice('__session='.length)\n : sessionJwt;\n\n const parts = raw.split('.');\n if (parts.length < 2) return null;\n\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n const sid = payload.sid ?? payload.session_id;\n if (typeof sid === 'string' && sid.startsWith('sess_')) return sid;\n } catch {\n // fall through\n }\n return null;\n }\n}\n", "#!/usr/bin/env node\n/**\n * Session capture via Chrome DevTools Protocol (CDP).\n * - Connects to a Chrome instance started with --remote-debugging-port.\n * - Reads required Huntr/Clerk cookies from the active huntr.co tab.\n * - Verifies refresh with Clerk and stores session data in macOS Keychain.\n */\n\nimport { mkdirSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { spawn } from 'child_process';\nimport net from 'net';\nimport { ClerkSessionManager } from '../config/clerk-session-manager';\n\nconst CDP_PORT = 9222;\nconst CDP_USER_DATA_DIR = join(tmpdir(), 'huntr-cdp-profile');\nconst HUNTR_APP_URL = 'https://huntr.co/home';\nconst HUNTR_COOKIE_URLS = ['https://huntr.co/', HUNTR_APP_URL, 'https://clerk.huntr.co/'];\nconst CAPTURED_COOKIE_NAMES = new Set(['__session', '__client_uat', '__client', '__cf_bm', '_cfuvid']);\nconst TAB_WAIT_TIMEOUT_MS = 45_000;\nconst TOKEN_WAIT_TIMEOUT_MS = 120_000;\nconst POLL_INTERVAL_MS = 1_500;\nconst CLERK_SESSION_ID_EVAL_EXPRESSION = `(() => {\n const sid = window.Clerk?.session?.id;\n return typeof sid === 'string' ? sid : '';\n})()`;\n\ntype ChromeTab = {\n url?: string;\n type?: string;\n title?: string;\n webSocketDebuggerUrl?: string;\n};\n\ntype SessionCookieWaitResult = {\n sessionCookie: string | null;\n sessionId?: string;\n clientUat?: string | null;\n extraCookies?: Record<string, string>;\n freshToken?: string;\n tab?: ChromeTab;\n lastValueDescription?: string;\n lastError?: string;\n};\n\ntype SessionSnapshot = {\n sessionCookie: string;\n clientUat: string | null;\n extraCookies: Record<string, string>;\n clerkSessionId: string | null;\n};\n\nexport async function captureSession(): Promise<void> {\n console.log('\\nConnecting to Chrome via DevTools Protocol\u2026');\n\n // Step 1: Check if Chrome is already running with remote debugging\n let tabs = await getChromeTabs().catch(() => null);\n\n if (!tabs) {\n console.log(' Chrome not running with --remote-debugging-port. Launching\u2026');\n await launchChromeWithDebugging();\n // Give it a moment to start\n await new Promise(r => setTimeout(r, 2000));\n tabs = await getChromeTabs().catch(() => null);\n }\n\n if (!tabs) {\n throw new Error(\n 'Could not connect to Chrome DevTools Protocol.\\n' +\n 'Please quit Chrome and re-run this command, or start Chrome manually with:\\n' +\n ` /Applications/Google\\\\ Chrome.app/Contents/MacOS/Google\\\\ Chrome --remote-debugging-port=${CDP_PORT} --user-data-dir=${CDP_USER_DATA_DIR} ${HUNTR_APP_URL}\\n` +\n ' (If this is your first run, sign in to huntr.co in that profile once.)\\n' +\n 'Then run: huntr config capture-session',\n );\n }\n\n // Step 2: Find the huntr.co tab\n let huntrTab = findBestHuntrTab(tabs);\n if (!huntrTab) {\n console.log(` Opening ${HUNTR_APP_URL} in debug profile\u2026`);\n await openHuntrAppInDebugProfile();\n }\n\n console.log(' Waiting for huntr.co tab to become available\u2026');\n huntrTab = await waitForHuntrTab(TAB_WAIT_TIMEOUT_MS);\n if (!huntrTab || !huntrTab.webSocketDebuggerUrl) {\n throw new Error(\n 'No huntr.co tab found in Chrome DevTools.\\n' +\n `Please open ${HUNTR_APP_URL} in Chrome (in the debug profile) and re-run.`,\n );\n }\n\n console.log(` Found huntr.co tab: ${huntrTab.title}`);\n const mgr = new ClerkSessionManager();\n console.log(' Waiting for login and extracting Clerk session cookie\u2026');\n\n // Step 3: Poll until we have a cookie pair that actually refreshes via Clerk\n const cookieWait = await waitForValidHuntrSessionCookie(mgr, TOKEN_WAIT_TIMEOUT_MS);\n if (!cookieWait.sessionCookie) {\n const details = [\n `Last tab URL: ${cookieWait.tab?.url ?? '(none)'}`,\n cookieWait.lastValueDescription ? `Last cookie value: ${cookieWait.lastValueDescription}` : '',\n cookieWait.lastError ? `Last eval error: ${cookieWait.lastError}` : '',\n ].filter(Boolean).join('\\n');\n throw new Error(\n 'Timed out waiting for authenticated huntr session.\\n' +\n 'Please finish signing in on the opened Chrome window, then re-run.\\n' +\n details,\n );\n }\n const sessionCookie = cookieWait.sessionCookie;\n const sessionId = cookieWait.sessionId;\n const clientUat = cookieWait.clientUat;\n const extraCookies = cookieWait.extraCookies ?? {};\n\n if (!sessionId) {\n throw new Error('Could not extract session ID from session cookie.');\n }\n\n console.log(` Session ID: ${sessionId}`);\n\n await mgr.saveSession(sessionCookie, sessionId, clientUat ?? undefined, extraCookies);\n console.log(' Saved to macOS Keychain.');\n\n // Step 5: Immediately test the refresh endpoint\n process.stdout.write(' Testing auto-refresh\u2026 ');\n await mgr.getFreshToken();\n console.log('\u2713');\n console.log('\\n\u2713 Session captured and verified!');\n console.log(' Tokens will auto-refresh before every command.');\n console.log(' Run: node dist/cli.js activities week-csv 68bf9e33f871e5004a5eb58e');\n}\n\nexport async function checkCdpSession(): Promise<void> {\n console.log('\\nChecking Chrome DevTools session visibility\u2026');\n const tabs = await getChromeTabs().catch(() => null);\n\n if (!tabs) {\n throw new Error(\n 'Could not connect to Chrome DevTools Protocol.\\n' +\n 'Start Chrome with:\\n' +\n ` /Applications/Google\\\\ Chrome.app/Contents/MacOS/Google\\\\ Chrome --remote-debugging-port=${CDP_PORT} --user-data-dir=${CDP_USER_DATA_DIR} ${HUNTR_APP_URL}`,\n );\n }\n\n const huntrTab = findBestHuntrTab(tabs);\n if (!huntrTab?.webSocketDebuggerUrl) {\n throw new Error('No huntr.co page tab found. Open huntr.co in the debug-profile Chrome and retry.');\n }\n\n console.log(` Using tab: ${huntrTab.title ?? '(untitled)'}`);\n console.log(` URL: ${huntrTab.url ?? '(unknown)'}`);\n\n const snapshot = await getSessionSnapshotInTab(huntrTab.webSocketDebuggerUrl, huntrTab.url);\n if (!snapshot?.sessionCookie) {\n throw new Error(\n 'CDP connected, but __session cookie is not visible yet.\\n' +\n 'Finish login in that tab, wait for the app page to load, then retry.',\n );\n }\n\n const sessionId =\n ClerkSessionManager.extractSessionId(snapshot.sessionCookie) ??\n snapshot.clerkSessionId ??\n undefined;\n if (!sessionId || !sessionId.startsWith('sess_')) {\n throw new Error('Found __session cookie, but could not derive a valid Clerk session ID.');\n }\n\n const visibleCookies = [\n '__session',\n snapshot.clientUat ? '__client_uat' : null,\n ...Object.keys(snapshot.extraCookies),\n ].filter(Boolean) as string[];\n console.log(` Visible cookies: ${visibleCookies.sort().join(', ')}`);\n\n const mgr = new ClerkSessionManager();\n process.stdout.write(' Testing Clerk refresh with visible cookies\u2026 ');\n const fresh = await mgr.refreshFromProvidedSession(\n snapshot.sessionCookie,\n sessionId,\n snapshot.clientUat,\n snapshot.extraCookies,\n );\n console.log('\u2713');\n console.log(` Session ID: ${sessionId}`);\n console.log(` Refresh token preview: ${fresh.substring(0, 20)}\u2026`);\n}\n\nasync function getChromeTabs(): Promise<ChromeTab[]> {\n const response = await fetch(`http://127.0.0.1:${CDP_PORT}/json`);\n if (!response.ok) throw new Error(`CDP returned ${response.status}`);\n const json: unknown = await response.json();\n if (!Array.isArray(json)) throw new Error('Unexpected CDP /json response');\n return json as ChromeTab[];\n}\n\nasync function launchChromeWithDebugging(): Promise<void> {\n // Chrome requires an explicit user-data-dir when remote debugging is enabled.\n mkdirSync(CDP_USER_DATA_DIR, { recursive: true });\n const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';\n spawn(chromePath, [\n `--remote-debugging-port=${CDP_PORT}`,\n `--user-data-dir=${CDP_USER_DATA_DIR}`,\n '--no-first-run',\n '--no-default-browser-check',\n HUNTR_APP_URL,\n ], { detached: true, stdio: 'ignore' }).unref();\n}\n\nasync function openHuntrAppInDebugProfile(): Promise<void> {\n // Launching again with the same user-data-dir opens a tab in that profile.\n await launchChromeWithDebugging();\n}\n\nasync function waitForHuntrTab(timeoutMs: number): Promise<ChromeTab | undefined> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const tabs = await getChromeTabs().catch(() => null);\n const tab = tabs ? findBestHuntrTab(tabs) : undefined;\n if (tab?.webSocketDebuggerUrl) return tab;\n await sleep(POLL_INTERVAL_MS);\n }\n return undefined;\n}\n\nasync function waitForValidHuntrSessionCookie(\n mgr: ClerkSessionManager,\n timeoutMs: number,\n): Promise<SessionCookieWaitResult> {\n const deadline = Date.now() + timeoutMs;\n let lastTab: ChromeTab | undefined;\n let lastValueDescription: string | undefined;\n let lastError: string | undefined;\n let printedHint = false;\n\n while (Date.now() < deadline) {\n const tabs = await getChromeTabs().catch(() => null);\n const huntrTabs = tabs ? findHuntrTabs(tabs) : [];\n\n for (const tab of huntrTabs) {\n if (!tab.webSocketDebuggerUrl) continue;\n lastTab = tab;\n\n try {\n const snapshot = await getSessionSnapshotInTab(tab.webSocketDebuggerUrl, tab.url);\n lastValueDescription = describeValue(snapshot);\n\n if (!snapshot?.sessionCookie || snapshot.sessionCookie.split('.').length !== 3) {\n continue;\n }\n\n const sessionId =\n ClerkSessionManager.extractSessionId(snapshot.sessionCookie) ??\n snapshot.clerkSessionId ??\n undefined;\n\n if (!sessionId || !sessionId.startsWith('sess_')) {\n continue;\n }\n\n const freshToken = await mgr.refreshFromProvidedSession(\n snapshot.sessionCookie,\n sessionId,\n snapshot.clientUat,\n snapshot.extraCookies,\n );\n if (freshToken && freshToken.split('.').length === 3) {\n return {\n sessionCookie: snapshot.sessionCookie,\n sessionId,\n clientUat: snapshot.clientUat,\n extraCookies: snapshot.extraCookies,\n freshToken,\n tab,\n lastValueDescription,\n lastError,\n };\n }\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n }\n\n if (!printedHint && huntrTabs.length > 0) {\n console.log(' Waiting for you to finish signing into huntr.co in that Chrome window\u2026');\n printedHint = true;\n }\n await sleep(POLL_INTERVAL_MS);\n }\n\n return { sessionCookie: null, tab: lastTab, lastValueDescription, lastError };\n}\n\nfunction isHuntrAppTab(tab: ChromeTab): boolean {\n if (!tab.url || tab.type !== 'page') return false;\n try {\n const parsed = new URL(tab.url);\n if (!parsed.hostname.endsWith('huntr.co')) return false;\n return parsed.pathname !== '/' && parsed.pathname.length > 1;\n } catch {\n return false;\n }\n}\n\nfunction isHuntrTab(tab: ChromeTab): boolean {\n if (!tab.url || tab.type !== 'page') return false;\n try {\n const parsed = new URL(tab.url);\n return parsed.hostname.endsWith('huntr.co');\n } catch {\n return false;\n }\n}\n\nfunction findHuntrTabs(tabs: ChromeTab[]): ChromeTab[] {\n const huntrTabs = tabs.filter(isHuntrTab);\n const appTabs = huntrTabs.filter(isHuntrAppTab);\n return appTabs.length > 0 ? appTabs : huntrTabs;\n}\n\nfunction findBestHuntrTab(tabs: ChromeTab[]): ChromeTab | undefined {\n return findHuntrTabs(tabs)[0];\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function getSessionSnapshotInTab(wsUrl: string, pageUrl?: string): Promise<SessionSnapshot | null> {\n const cookies = await getCookiesInTab(wsUrl, pageUrl);\n const sessionCookie = cookies.__session ?? null;\n if (!sessionCookie) return null;\n\n const clerkSessionIdRaw = await evaluateInTab(wsUrl, CLERK_SESSION_ID_EVAL_EXPRESSION).catch(() => '');\n const clerkSessionId =\n typeof clerkSessionIdRaw === 'string' && clerkSessionIdRaw.startsWith('sess_')\n ? clerkSessionIdRaw\n : null;\n\n return {\n sessionCookie,\n clientUat: cookies.__client_uat ?? null,\n extraCookies: Object.fromEntries(\n Object.entries(cookies).filter(([name]) => name !== '__session' && name !== '__client_uat'),\n ),\n clerkSessionId,\n };\n}\n\nasync function getCookiesInTab(wsUrl: string, pageUrl?: string): Promise<Record<string, string>> {\n try {\n await cdpRequestInTab(wsUrl, 'Network.enable');\n } catch {\n // Not all targets require/allow Network.enable first.\n }\n\n const urls = pageUrl ? Array.from(new Set([pageUrl, ...HUNTR_COOKIE_URLS])) : HUNTR_COOKIE_URLS;\n const result = await cdpRequestInTab(wsUrl, 'Network.getCookies', { urls });\n const cookies = (result as { cookies?: unknown[] } | null)?.cookies;\n const out: Record<string, string> = {};\n\n if (!Array.isArray(cookies)) return out;\n\n for (const cookie of cookies) {\n if (!cookie || typeof cookie !== 'object') continue;\n const c = cookie as Record<string, unknown>;\n const name = c.name;\n const value = c.value;\n const domain = c.domain;\n\n if (typeof name !== 'string' || typeof value !== 'string') continue;\n if (typeof domain === 'string' && !domain.includes('huntr.co')) continue;\n if (CAPTURED_COOKIE_NAMES.has(name)) {\n out[name] = value;\n }\n }\n\n return out;\n}\n\nasync function evaluateInTab(wsUrl: string, expression: string): Promise<unknown> {\n const result = await cdpRequestInTab(wsUrl, 'Runtime.evaluate', {\n expression,\n awaitPromise: true,\n returnByValue: true,\n });\n\n const evalResult = (result ?? {}) as Record<string, unknown>;\n const exceptionDetails = evalResult.exceptionDetails as Record<string, unknown> | undefined;\n if (exceptionDetails) {\n const text = typeof exceptionDetails.text === 'string' ? exceptionDetails.text : 'Runtime.evaluate failed';\n throw new Error(text);\n }\n\n const runtimeResult = evalResult.result as Record<string, unknown> | undefined;\n if (!runtimeResult || !Object.prototype.hasOwnProperty.call(runtimeResult, 'value')) return undefined;\n return runtimeResult.value;\n}\n\nfunction cdpRequestInTab(\n wsUrl: string,\n method: string,\n params: Record<string, unknown> = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n // Use Node's built-in WebSocket (Node 22+) or fall back to a raw WS handshake\n const WebSocketImpl = (globalThis as any).WebSocket;\n\n if (WebSocketImpl) {\n connectWithWebSocket(wsUrl, WebSocketImpl, method, params, resolve, reject);\n } else {\n // Node < 22: implement minimal WS client over net/tls\n connectWithRawWS(wsUrl, method, params, resolve, reject);\n }\n });\n}\n\nfunction connectWithWebSocket(\n wsUrl: string,\n WS: typeof WebSocket,\n method: string,\n params: Record<string, unknown>,\n resolve: (v: unknown) => void,\n reject: (e: Error) => void,\n): void {\n const ws = new WS(wsUrl);\n const id = 1;\n\n ws.onopen = () => {\n ws.send(JSON.stringify({\n id,\n method,\n params,\n }));\n };\n\n ws.onmessage = async (evt: MessageEvent) => {\n try {\n const raw = await wsDataToText(evt.data);\n const msg = JSON.parse(raw);\n if (msg.id !== id) return;\n if (msg.error) {\n ws.close();\n reject(new Error(msg.error?.message ?? `CDP ${method} failed`));\n return;\n }\n\n ws.close();\n resolve(msg.result as unknown);\n } catch (e) {\n ws.close();\n reject(e instanceof Error ? e : new Error(String(e)));\n }\n };\n\n ws.onerror = () => reject(new Error('WebSocket connection to Chrome DevTools failed'));\n\n setTimeout(() => { ws.close(); reject(new Error('Timeout waiting for Chrome response')); }, 10_000);\n}\n\nasync function wsDataToText(data: unknown): Promise<string> {\n if (typeof data === 'string') return data;\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(data)) return data.toString('utf8');\n if (data instanceof ArrayBuffer) return Buffer.from(data).toString('utf8');\n if (typeof Blob !== 'undefined' && data instanceof Blob) return await data.text();\n return String(data);\n}\n\nfunction connectWithRawWS(\n wsUrl: string,\n method: string,\n params: Record<string, unknown>,\n resolve: (v: unknown) => void,\n reject: (e: Error) => void,\n): void {\n // Parse ws://host:port/path\n const match = wsUrl.match(/^ws:\\/\\/([^/:]+):(\\d+)(\\/.*)?$/);\n if (!match) { reject(new Error(`Cannot parse WS URL: ${wsUrl}`)); return; }\n\n const host = match[1];\n const port = parseInt(match[2], 10);\n const path = match[3] ?? '/';\n\n const socket = net.createConnection(port, host);\n\n const key = Buffer.from(Math.random().toString(36)).toString('base64');\n let buffer = '';\n let handshakeDone = false;\n const msgId = 1;\n\n socket.on('connect', () => {\n socket.write(\n `GET ${path} HTTP/1.1\\r\\n` +\n `Host: ${host}:${port}\\r\\n` +\n 'Upgrade: websocket\\r\\n' +\n 'Connection: Upgrade\\r\\n' +\n `Sec-WebSocket-Key: ${key}\\r\\n` +\n 'Sec-WebSocket-Version: 13\\r\\n\\r\\n',\n );\n });\n\n socket.on('data', (data: Buffer) => {\n if (!handshakeDone) {\n buffer += data.toString();\n if (buffer.includes('\\r\\n\\r\\n')) {\n handshakeDone = true;\n // Send the evaluate command\n const payload = JSON.stringify({\n id: msgId,\n method,\n params,\n });\n socket.write(encodeWsFrame(payload));\n }\n return;\n }\n\n // Parse WebSocket frame\n try {\n const msg = decodeWsFrame(data);\n if (msg) {\n const parsed = JSON.parse(msg);\n if (parsed.id !== msgId) return;\n if (parsed.error) {\n socket.destroy();\n reject(new Error(parsed.error?.message ?? `CDP ${method} failed`));\n return;\n }\n\n socket.destroy();\n resolve(parsed.result as unknown);\n }\n } catch {\n // partial frame, wait for more data\n }\n });\n\n socket.on('error', (e: Error) => reject(e));\n setTimeout(() => { socket.destroy(); reject(new Error('Timeout')); }, 10_000);\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') return `string, ${value.length} chars`;\n if (Array.isArray(value)) return `array, ${value.length} items`;\n if (typeof value === 'object') {\n const keys = Object.keys(value as Record<string, unknown>);\n return `object, keys: ${keys.slice(0, 6).join(', ') || '(none)'}`;\n }\n return typeof value;\n}\n\nfunction encodeWsFrame(payload: string): Buffer {\n const data = Buffer.from(payload, 'utf8');\n const len = data.length;\n const mask = Buffer.from([\n Math.random() * 256, Math.random() * 256,\n Math.random() * 256, Math.random() * 256,\n ].map(Math.floor));\n\n const header = len < 126\n ? Buffer.from([0x81, 0x80 | len])\n : len < 65536\n ? Buffer.from([0x81, 0xfe, len >> 8, len & 0xff])\n : Buffer.from([0x81, 0xff, 0, 0, 0, 0, (len >> 24) & 0xff, (len >> 16) & 0xff, (len >> 8) & 0xff, len & 0xff]);\n\n const masked = Buffer.alloc(len);\n for (let i = 0; i < len; i++) masked[i] = data[i] ^ mask[i % 4];\n return Buffer.concat([header, mask, masked]);\n}\n\nfunction decodeWsFrame(buf: Buffer): string | null {\n if (buf.length < 2) return null;\n const len = buf[1] & 0x7f;\n let offset = 2;\n const payloadLen = len < 126 ? len : len === 126 ? (buf.readUInt16BE(2), offset += 2, buf.readUInt16BE(2)) : null;\n if (payloadLen === null) return null;\n return buf.slice(offset, offset + (payloadLen as number)).toString('utf8');\n}\n", "/**\n * Shared CLI options for list commands (boards, jobs, activities).\n * Provides consistent flag parsing and validation across all list subcommands.\n */\n\nexport type OutputFormat = 'table' | 'json' | 'csv' | 'pdf' | 'excel';\n\nexport interface ListOptions {\n /** Output format: table (default), json, csv, pdf, or excel */\n format: OutputFormat;\n /** Number of days to filter to (activities only, default: all) */\n days?: number;\n /** Action types to filter (activities only, comma-separated) */\n types?: string[];\n /** Selected fields to include in output (comma-separated) */\n fields?: string[];\n}\n\n/**\n * Parses common list options from CLI arguments.\n * Supports aliases: -f/--format, -d/--days, --json (legacy compatibility), --fields.\n */\nexport function parseListOptions(opts: Record<string, unknown>): ListOptions {\n let format: OutputFormat = 'table';\n\n // Handle legacy --json flag\n if (opts.json) {\n format = 'json';\n }\n // Handle new --format flag (takes precedence over --json)\n if (opts.format) {\n const fmt = String(opts.format).toLowerCase();\n if (!['table', 'json', 'csv', 'pdf', 'excel'].includes(fmt)) {\n throw new Error(`Invalid format: ${fmt}. Must be table, json, csv, pdf, or excel.`);\n }\n format = fmt as OutputFormat;\n }\n\n let days: number | undefined;\n if (opts.days) {\n const d = parseInt(String(opts.days), 10);\n if (isNaN(d) || d < 1 || d > 365) {\n throw new Error('Days must be a number between 1 and 365');\n }\n days = d;\n }\n\n // Legacy --week flag for activities (maps to 7 days)\n if (opts.week && !days) {\n days = 7;\n }\n\n let types: string[] | undefined;\n if (opts.types) {\n types = String(opts.types)\n .split(',')\n .map(t => t.trim())\n .filter(t => t.length > 0);\n }\n\n let fields: string[] | undefined;\n if (opts.fields) {\n fields = String(opts.fields)\n .split(',')\n .map(f => f.trim())\n .filter(f => f.length > 0);\n }\n\n return { format, days, types, fields };\n}\n\n/**\n * Formats table output with consistent column widths.\n */\nexport function formatTable<T extends Record<string, unknown>>(rows: T[]): string {\n if (rows.length === 0) return '';\n\n const keys = Object.keys(rows[0]);\n const colWidths: Record<string, number> = {};\n\n // Calculate column widths\n for (const key of keys) {\n colWidths[key] = key.length;\n for (const row of rows) {\n const val = String(row[key] ?? '');\n colWidths[key] = Math.max(colWidths[key], val.length);\n }\n }\n\n // Format header\n const header = keys.map(k => k.padEnd(colWidths[k])).join(' ');\n const divider = keys.map(k => '\u2500'.repeat(colWidths[k])).join(' ');\n\n // Format rows\n const lines = [header, divider];\n for (const row of rows) {\n const line = keys.map(k => String(row[k] ?? '').padEnd(colWidths[k])).join(' ');\n lines.push(line);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Converts array of objects to CSV with proper escaping.\n */\nexport function formatCsv<T extends Record<string, unknown>>(rows: T[], headers?: string[]): string {\n if (rows.length === 0) return headers ? headers.join(',') : '';\n\n const keys = headers || Object.keys(rows[0]);\n const lines = [keys.map(escapeCsvField).join(',')];\n\n for (const row of rows) {\n const values = keys.map(k => {\n const val = row[k];\n return escapeCsvField(String(val ?? ''));\n });\n lines.push(values.join(','));\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeCsvField(field: string): string {\n if (field.includes(',') || field.includes('\"') || field.includes('\\n')) {\n return `\"${field.replace(/\"/g, '\"\"')}\"`;\n }\n return field;\n}\n\n/**\n * Validates and filters fields based on available fields.\n * If no fields are requested, returns all available fields.\n * Throws an error if requested fields don't exist.\n */\nexport function validateFields(availableFields: string[], requestedFields?: string[]): string[] {\n if (!requestedFields || requestedFields.length === 0) {\n return availableFields;\n }\n\n const invalid = requestedFields.filter(f => !availableFields.includes(f));\n if (invalid.length > 0) {\n const invalidStr = invalid.join(', ');\n const availableStr = availableFields.join(', ');\n throw new Error(\n `Unknown field(s): ${invalidStr}\\nAvailable fields: ${availableStr}`,\n );\n }\n\n return requestedFields;\n}\n\n/**\n * Formats table output with specific fields and consistent column widths.\n * @param rows Data rows\n * @param headers Field names to include (in order)\n */\nexport function formatTableWithFields<T extends Record<string, unknown>>(\n rows: T[],\n headers: string[],\n): string {\n if (rows.length === 0) return '';\n\n const colWidths: Record<string, number> = {};\n\n // Calculate column widths\n for (const key of headers) {\n colWidths[key] = key.length;\n for (const row of rows) {\n const val = String(row[key] ?? '');\n colWidths[key] = Math.max(colWidths[key], val.length);\n }\n }\n\n // Format header\n const header = headers.map(k => k.padEnd(colWidths[k])).join(' ');\n const divider = headers.map(k => '\u2500'.repeat(colWidths[k])).join(' ');\n\n // Format rows\n const lines = [header, divider];\n for (const row of rows) {\n const line = headers.map(k => String(row[k] ?? '').padEnd(colWidths[k])).join(' ');\n lines.push(line);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats CSV output with specific fields.\n * @param rows Data rows\n * @param headers Field names to include (in order)\n */\nexport function formatCsvWithFields<T extends Record<string, unknown>>(\n rows: T[],\n headers: string[],\n): string {\n if (rows.length === 0) return headers.join(',');\n\n const lines = [headers.map(escapeCsvField).join(',')];\n\n for (const row of rows) {\n const values = headers.map(h => {\n const val = row[h];\n return escapeCsvField(String(val ?? ''));\n });\n lines.push(values.join(','));\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output with specific fields.\n * @param rows Data rows\n * @param headers Field names to include (in order)\n */\nexport function formatJsonWithFields<T extends Record<string, unknown>>(\n rows: T[],\n headers: string[],\n): string {\n const filtered = rows.map(row => {\n const obj: Record<string, unknown> = {};\n for (const header of headers) {\n obj[header] = row[header];\n }\n return obj;\n });\n return JSON.stringify(filtered, null, 2);\n}\n\n/**\n * Formats PDF output with specific fields.\n * Requires pdfkit to be installed.\n * @param rows Data rows\n * @param headers Field names to include (in order)\n * @param title Optional title for the PDF\n */\nexport function formatPdf<T extends Record<string, unknown>>(\n rows: T[],\n headers: string[],\n title?: string,\n): Buffer {\n // Dynamically import pdfkit to avoid hard dependency at load time\n // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require\n const PDFDocument = require('pdfkit');\n\n const doc = new PDFDocument({ margin: 40, size: 'letter' });\n const chunks: Buffer[] = [];\n\n // Collect output\n doc.on('data', (chunk: Buffer) => chunks.push(chunk));\n\n // Title\n if (title) {\n doc.fontSize(16).font('Helvetica-Bold').text(title, { underline: true });\n doc.moveDown();\n }\n\n // Metadata\n const now = new Date();\n doc\n .fontSize(10)\n .font('Helvetica')\n .text(`Generated: ${now.toISOString()}`, { lineGap: 5 });\n doc.moveDown();\n\n // Table header\n const colWidth = (doc.page.width - 80) / headers.length;\n const yStart = doc.y;\n\n // Header background\n doc.rect(40, yStart, doc.page.width - 80, 25).fill('#e8e8e8');\n\n // Header text\n doc.fontSize(10).font('Helvetica-Bold').fillColor('black');\n headers.forEach((header, i) => {\n doc.text(header, 40 + i * colWidth + 5, yStart + 5, {\n width: colWidth - 10,\n ellipsis: true,\n });\n });\n\n doc.moveDown(1.5);\n\n // Data rows\n doc.font('Helvetica').fontSize(9);\n const rowHeight = 20;\n\n for (const row of rows) {\n const yRow = doc.y;\n\n // Alternate row background\n if (rows.indexOf(row) % 2 === 0) {\n doc.rect(40, yRow, doc.page.width - 80, rowHeight).fill('#f5f5f5');\n doc.fillColor('black');\n }\n\n headers.forEach((header, i) => {\n const val = String(row[header] ?? '');\n doc.text(val, 40 + i * colWidth + 5, yRow + 3, {\n width: colWidth - 10,\n ellipsis: true,\n });\n });\n\n doc.moveDown(1.2);\n }\n\n // Footer\n doc.fontSize(9).font('Helvetica').text('huntr-cli', { align: 'center' });\n\n doc.end();\n\n return Buffer.concat(chunks);\n}\n\n/**\n * Formats Excel output with specific fields.\n * Requires exceljs to be installed.\n * @param rows Data rows\n * @param headers Field names to include (in order)\n * @param title Optional sheet title\n */\nexport async function formatExcel<T extends Record<string, unknown>>(\n rows: T[],\n headers: string[],\n title?: string,\n): Promise<Buffer> {\n // Dynamically import exceljs to avoid hard dependency at load time\n // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require\n const ExcelJS = require('exceljs');\n\n const workbook = new ExcelJS.Workbook();\n const worksheet = workbook.addWorksheet(title || 'Data', {\n pageSetup: { paperSize: 9, orientation: 'landscape' },\n });\n\n // Add header row\n worksheet.addRow(headers);\n const headerRow = worksheet.getRow(1);\n headerRow.font = { bold: true, color: { argb: 'FFFFFFFF' } };\n headerRow.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: 'FF4472C4' },\n };\n headerRow.alignment = { horizontal: 'center', vertical: 'center' };\n\n // Add data rows\n for (const row of rows) {\n const values = headers.map(h => row[h] ?? '');\n worksheet.addRow(values);\n }\n\n // Auto-adjust column widths\n headers.forEach((header, i) => {\n let maxLen = header.length;\n for (const row of rows) {\n const val = String(row[header] ?? '');\n maxLen = Math.max(maxLen, val.length);\n }\n const col = worksheet.getColumn(i + 1);\n col.width = Math.min(maxLen + 2, 50); // Cap at 50 chars\n });\n\n // Generate buffer\n const buffer = await workbook.xlsx.writeBuffer();\n return buffer as Buffer;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["config", "jobs", "config", "keytar", "SERVICE_NAME", "path", "path"
|
|
3
|
+
"sources": ["../src/api/client.ts", "../src/api/personal/user.ts", "../src/api/personal/boards.ts", "../src/api/personal/jobs.ts", "../src/api/personal/activities.ts", "../src/api/personal/index.ts", "../src/cli.ts", "../src/config/token-manager.ts", "../src/config/config-manager.ts", "../src/config/keychain-manager.ts", "../src/config/clerk-session-manager.ts", "../src/commands/capture-session.ts"],
|
|
4
|
+
"sourcesContent": ["import axios, { AxiosInstance, AxiosError } from 'axios';\n\n// Note: We do not auto-load .env to avoid noisy logs.\n// If you want .env loaded, run with HUNTR_LOAD_ENV=true and we will load it explicitly.\nimport dotenv from 'dotenv';\nif (process.env.HUNTR_LOAD_ENV === 'true') {\n dotenv.config({ debug: false });\n}\n\n/** A static token string OR an async function that returns a fresh token. */\nexport type TokenProvider = string | (() => Promise<string>);\n\nexport class HuntrApiClient {\n private axiosInstance: AxiosInstance;\n private tokenProvider: () => Promise<string>;\n\n constructor(tokenProvider: TokenProvider, baseURL: string = 'https://api.huntr.co/org') {\n this.tokenProvider =\n typeof tokenProvider === 'string'\n ? async () => tokenProvider\n : tokenProvider;\n\n this.axiosInstance = axios.create({ baseURL });\n\n // Inject a fresh Authorization header before every request\n this.axiosInstance.interceptors.request.use(async (config) => {\n const token = await this.tokenProvider();\n if (!token) throw new Error('No API token available.');\n config.headers = config.headers ?? {};\n config.headers['Authorization'] = `Bearer ${token}`;\n config.headers['Content-Type'] = 'application/json';\n return config;\n });\n\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n (error: AxiosError) => {\n if (error.response) {\n const status = error.response.status;\n const apiError = error.response.data as any;\n const message = apiError?.error?.message ?? apiError?.message ?? 'API request failed';\n throw new Error(`HTTP ${status}: ${message}`);\n }\n if (error.request) {\n throw new Error('No response from API - check your network connection');\n }\n throw error;\n },\n );\n }\n\n async get<T>(endpoint: string, params?: Record<string, any>): Promise<T> {\n const response = await this.axiosInstance.get<T>(endpoint, { params });\n return response.data;\n }\n\n async post<T>(endpoint: string, data?: any): Promise<T> {\n const response = await this.axiosInstance.post<T>(endpoint, data);\n return response.data;\n }\n\n async put<T>(endpoint: string, data?: any): Promise<T> {\n const response = await this.axiosInstance.put<T>(endpoint, data);\n return response.data;\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n const response = await this.axiosInstance.delete<T>(endpoint);\n return response.data;\n }\n\n async *paginate<T>(\n endpoint: string,\n params: Record<string, any> = {},\n limit: number = 100,\n ): AsyncGenerator<T[], void, undefined> {\n let next: string | undefined = undefined;\n\n do {\n const queryParams: Record<string, any> = { ...params, limit };\n if (next) queryParams.next = next;\n const response = await this.get<{ data: T[]; next?: string }>(endpoint, queryParams);\n yield response.data;\n next = response.next;\n } while (next);\n }\n}\n\nexport const createClient = (tokenProvider: TokenProvider, baseURL?: string): HuntrApiClient => {\n return new HuntrApiClient(tokenProvider, baseURL);\n};\n", "import { HuntrApiClient } from '../client';\nimport { UserProfile } from '../../types/personal';\n\nexport class PersonalUserApi {\n constructor(private client: HuntrApiClient) {}\n\n async getProfile(): Promise<UserProfile> {\n // Official endpoint returns the current user's profile\n return this.client.get<UserProfile>('/user');\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { Board } from '../../types/personal';\n\nexport class PersonalBoardsApi {\n constructor(private client: HuntrApiClient) {}\n\n async list(): Promise<Board[]> {\n // Official endpoint: /api/user/boards returns an array of boards\n const res = await this.client.get<unknown>('/user/boards');\n if (Array.isArray(res)) return res as Board[];\n if (res && typeof res === 'object' && Array.isArray((res as any).data)) return (res as any).data as Board[];\n // Fallback if API returns an object map\n if (res && typeof res === 'object') return Object.values(res as Record<string, Board>);\n return [];\n }\n\n async get(boardId: string): Promise<Board> {\n // There isn't a documented /api/user/boards/:id; use /api/boards/:id if needed\n return this.client.get<Board>(`/boards/${boardId}`);\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { PersonalJob, PersonalJobsResponse } from '../../types/personal';\n\nexport class PersonalJobsApi {\n constructor(private client: HuntrApiClient) {}\n\n // API returns { jobs: { [id]: PersonalJob } } \u2014 an object map, not an array\n async listByBoard(boardId: string): Promise<PersonalJobsResponse> {\n return this.client.get<PersonalJobsResponse>(`/board/${boardId}/jobs`);\n }\n\n // Convenience: returns flat array\n async listByBoardFlat(boardId: string): Promise<PersonalJob[]> {\n const response = await this.listByBoard(boardId);\n return Object.values(response.jobs);\n }\n\n async get(boardId: string, jobId: string): Promise<PersonalJob> {\n return this.client.get<PersonalJob>(`/board/${boardId}/jobs/${jobId}`);\n }\n\n async create(boardId: string, job: Partial<PersonalJob>): Promise<PersonalJob> {\n return this.client.post<PersonalJob>(`/board/${boardId}/jobs`, job);\n }\n\n async update(boardId: string, jobId: string, updates: Partial<PersonalJob>): Promise<PersonalJob> {\n return this.client.put<PersonalJob>(`/board/${boardId}/jobs/${jobId}`, updates);\n }\n\n async delete(boardId: string, jobId: string): Promise<void> {\n return this.client.delete<void>(`/board/${boardId}/jobs/${jobId}`);\n }\n}\n", "import { HuntrApiClient } from '../client';\nimport { PersonalAction, PersonalJob, PersonalJobsResponse } from '../../types/personal';\n\nexport class PersonalActionsApi {\n constructor(private client: HuntrApiClient) {}\n\n // Returns object map { [actionId]: PersonalAction }\n async listByBoard(boardId: string): Promise<Record<string, PersonalAction>> {\n return this.client.get<Record<string, PersonalAction>>(`/board/${boardId}/actions`);\n }\n\n // Returns flattened array sorted by date desc, optionally filtered by action types\n async listByBoardFlat(\n boardId: string,\n opts?: { since?: Date; types?: string[] },\n ): Promise<PersonalAction[]> {\n const raw = await this.listByBoard(boardId);\n let actions = Object.values(raw);\n\n if (opts?.since) {\n const cutoff = opts.since.getTime();\n actions = actions.filter(a => new Date(a.date || a.createdAt).getTime() >= cutoff);\n }\n\n if (opts?.types && opts.types.length > 0) {\n actions = actions.filter(a => opts.types!.includes(a.actionType));\n }\n\n return actions.sort((a, b) =>\n new Date(b.date || b.createdAt).getTime() - new Date(a.date || a.createdAt).getTime(),\n );\n }\n\n // Joins actions with job data to produce enriched rows\n async weekSummary(boardId: string): Promise<Array<{\n date: string;\n actionType: string;\n company: string;\n jobTitle: string;\n status: string;\n url: string;\n address: string;\n }>> {\n const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);\n const [actions, jobsResponse] = await Promise.all([\n this.listByBoardFlat(boardId, { since }),\n this.client.get<PersonalJobsResponse>(`/board/${boardId}/jobs`),\n ]);\n\n const jobs = jobsResponse.jobs;\n\n return actions\n .filter(a => a.actionType !== 'ACTIVITY_CREATED')\n .map(a => {\n const jobId = a.data?._job;\n const job: PersonalJob | undefined = jobId ? jobs[jobId] : undefined;\n return {\n date: new Date(a.date || a.createdAt).toISOString().substring(0, 16),\n actionType: a.actionType,\n company: a.data?.company?.name ?? '',\n jobTitle: a.data?.job?.title ?? '',\n status: a.data?.toList?.name ?? '',\n url: job?.url ?? '',\n address: job?.location?.address ?? '',\n };\n });\n }\n}\n", "import { createClient, TokenProvider } from '../client';\nimport { PersonalUserApi } from './user';\nimport { PersonalBoardsApi } from './boards';\nimport { PersonalJobsApi } from './jobs';\nimport { PersonalActionsApi } from './activities';\n\nexport class HuntrPersonalApi {\n public user: PersonalUserApi;\n public boards: PersonalBoardsApi;\n public jobs: PersonalJobsApi;\n public actions: PersonalActionsApi;\n\n constructor(tokenProvider: TokenProvider) {\n const client = createClient(tokenProvider, 'https://api.huntr.co/api');\n this.user = new PersonalUserApi(client);\n this.boards = new PersonalBoardsApi(client);\n this.jobs = new PersonalJobsApi(client);\n this.actions = new PersonalActionsApi(client);\n }\n}\n\nexport * from './user';\nexport * from './boards';\nexport * from './jobs';\nexport * from './activities';\n", "#!/usr/bin/env node\n\nimport { Command, InvalidArgumentError } from 'commander';\nimport { HuntrPersonalApi } from './api/personal';\nimport { TokenManager } from './config/token-manager';\nimport { ClerkSessionManager } from './config/clerk-session-manager';\nimport { captureSession, checkCdpSession } from './commands/capture-session';\n\nconst program = new Command();\nconst tokenManager = new TokenManager();\n\ntype OutputFormat = 'json' | 'table' | 'csv';\n\ntype SharedListOptions = {\n format?: OutputFormat;\n json?: boolean;\n days?: number;\n since?: Date;\n until?: Date;\n limit?: number;\n week?: boolean;\n};\n\nfunction parsePositiveInt(value: string, flagName: string): number {\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || Number.isNaN(parsed) || parsed <= 0) {\n throw new InvalidArgumentError(`${flagName} must be a positive integer.`);\n }\n return parsed;\n}\n\nfunction parseDaysOption(value: string): number {\n return parsePositiveInt(value, '--days');\n}\n\nfunction parseLimitOption(value: string): number {\n return parsePositiveInt(value, '--limit');\n}\n\nfunction parseFormatOption(value: string): OutputFormat {\n const normalized = value.toLowerCase();\n if (normalized === 'json' || normalized === 'table' || normalized === 'csv') {\n return normalized;\n }\n throw new InvalidArgumentError('--format must be one of: json, table, csv.');\n}\n\nfunction parseDateOption(value: string): Date {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n throw new InvalidArgumentError('Date must be in YYYY-MM-DD format.');\n }\n\n const [yearStr, monthStr, dayStr] = value.split('-');\n const year = Number(yearStr);\n const month = Number(monthStr);\n const day = Number(dayStr);\n const date = new Date(Date.UTC(year, month - 1, day, 0, 0, 0, 0));\n\n if (\n date.getUTCFullYear() !== year ||\n date.getUTCMonth() !== month - 1 ||\n date.getUTCDate() !== day\n ) {\n throw new InvalidArgumentError(`Invalid calendar date: ${value}`);\n }\n\n return date;\n}\n\nfunction resolveOutputFormat(options: SharedListOptions): OutputFormat {\n if (options.json) {\n if (options.format && options.format !== 'json') {\n throw new Error(`--json cannot be combined with --format ${options.format}.`);\n }\n return 'json';\n }\n return options.format ?? 'json';\n}\n\nfunction resolveDateRange(options: SharedListOptions): { since?: Date; until?: Date } {\n let days = options.days;\n if (options.week) {\n if (options.days || options.since || options.until) {\n throw new Error('--week cannot be combined with --days, --since, or --until.');\n }\n days = 7;\n }\n\n if (days && (options.since || options.until)) {\n throw new Error('--days cannot be combined with --since or --until.');\n }\n\n const since = days ? new Date(Date.now() - days * 24 * 60 * 60 * 1000) : options.since;\n const until = options.until\n ? new Date(Date.UTC(\n options.until.getUTCFullYear(),\n options.until.getUTCMonth(),\n options.until.getUTCDate(),\n 23, 59, 59, 999,\n ))\n : undefined;\n\n if (since && until && since.getTime() > until.getTime()) {\n throw new Error('--since must be earlier than or equal to --until.');\n }\n\n return { since, until };\n}\n\nfunction filterByDateRange<T>(\n items: T[],\n getDate: (item: T) => string | undefined,\n range: { since?: Date; until?: Date },\n): T[] {\n return items.filter(item => {\n const raw = getDate(item);\n if (!raw) return true;\n\n const timestamp = new Date(raw).getTime();\n if (Number.isNaN(timestamp)) return false;\n if (range.since && timestamp < range.since.getTime()) return false;\n if (range.until && timestamp > range.until.getTime()) return false;\n return true;\n });\n}\n\nfunction applyLimit<T>(items: T[], limit?: number): T[] {\n if (!limit) return items;\n return items.slice(0, limit);\n}\n\nfunction csvCell(value: unknown): string {\n const str = value == null ? '' : String(value);\n if (/[\",\\n]/.test(str)) return `\"${str.replace(/\"/g, '\"\"')}\"`;\n return str;\n}\n\nfunction printCsv(headers: string[], rows: unknown[][]): void {\n const lines = [headers.join(',')];\n for (const row of rows) {\n lines.push(row.map(csvCell).join(','));\n }\n console.log(lines.join('\\n'));\n}\n\nasync function getApi(token?: string): Promise<HuntrPersonalApi> {\n const provider = await tokenManager.getTokenProvider({ token });\n return new HuntrPersonalApi(provider);\n}\n\nprogram\n .name('huntr')\n .description('CLI tool for Huntr')\n .version('1.1.0')\n .option('-t, --token <token>', 'API token (overrides all other sources)');\n\n// \u2500\u2500 me \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nprogram\n .command('me')\n .description('Show your user profile')\n .option('-j, --json', 'Output as JSON')\n .action(async (options, command) => {\n try {\n const api = await getApi(command.parent?.opts().token);\n const profile = await api.user.getProfile();\n if (options.json) {\n console.log(JSON.stringify(profile, null, 2));\n } else {\n console.log(`Name: ${profile.givenName ?? profile.firstName ?? ''} ${profile.familyName ?? profile.lastName ?? ''}`);\n console.log(`Email: ${profile.email}`);\n console.log(`ID: ${profile.id}`);\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 boards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst boards = program.command('boards').description('Manage your boards');\n\nboards\n .command('list')\n .description('List all your boards')\n .option('-f, --format <format>', 'Output format: json | table | csv', parseFormatOption, 'json')\n .option('-j, --json', 'Output as JSON (alias for --format json)')\n .option('-d, --days <n>', 'Show only boards created in last N days', parseDaysOption)\n .option('--since <date>', 'Show boards created since YYYY-MM-DD', parseDateOption)\n .option('--until <date>', 'Show boards created until YYYY-MM-DD (inclusive)', parseDateOption)\n .option('--limit <n>', 'Maximum rows to output', parseLimitOption)\n .action(async (options, command) => {\n try {\n const format = resolveOutputFormat(options);\n const range = resolveDateRange(options);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n const response = await api.boards.list();\n const boardsList = Array.isArray(response) ? response : (response as any).data ?? [];\n const sorted = [...boardsList].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n const filtered = applyLimit(filterByDateRange(sorted, b => b.createdAt, range), options.limit);\n\n if (format === 'json') {\n console.log(JSON.stringify(filtered, null, 2));\n } else if (filtered.length === 0) {\n console.log('No boards found.');\n } else if (format === 'csv') {\n printCsv(\n ['id', 'name', 'created_at'],\n filtered.map((b: any) => [b.id, b.name ?? '', b.createdAt ?? '']),\n );\n } else {\n console.table(filtered.map((b: any) => ({\n ID: b.id,\n Name: b.name ?? 'N/A',\n Created: new Date(b.createdAt).toLocaleDateString(),\n })));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nboards\n .command('get')\n .description('Get details of a specific board')\n .argument('<board-id>', 'Board ID')\n .option('-j, --json', 'Output as JSON')\n .action(async (boardId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const board = await api.boards.get(boardId);\n if (options.json) {\n console.log(JSON.stringify(board, null, 2));\n } else {\n console.log(`Board: ${board.name}`);\n console.log(`ID: ${board.id}`);\n console.log(`Created: ${new Date(board.createdAt).toLocaleString()}`);\n if (board.lists?.length) {\n console.log('\\nLists:');\n board.lists.forEach(l => console.log(` - ${l.name}`));\n }\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 jobs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst jobs = program.command('jobs').description('Manage jobs on your boards');\n\njobs\n .command('list')\n .description('List jobs on a board')\n .argument('<board-id>', 'Board ID')\n .option('-f, --format <format>', 'Output format: json | table | csv', parseFormatOption, 'json')\n .option('-j, --json', 'Output as JSON (alias for --format json)')\n .option('-d, --days <n>', 'Show only jobs created in last N days', parseDaysOption)\n .option('--since <date>', 'Show jobs created since YYYY-MM-DD', parseDateOption)\n .option('--until <date>', 'Show jobs created until YYYY-MM-DD (inclusive)', parseDateOption)\n .option('--limit <n>', 'Maximum rows to output', parseLimitOption)\n .action(async (boardId, options, command) => {\n try {\n const format = resolveOutputFormat(options);\n const range = resolveDateRange(options);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n const jobsList = await api.jobs.listByBoardFlat(boardId);\n const sorted = [...jobsList].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n const filtered = applyLimit(filterByDateRange(sorted, j => j.createdAt, range), options.limit);\n\n if (format === 'json') {\n console.log(JSON.stringify(filtered, null, 2));\n } else if (filtered.length === 0) {\n console.log('No jobs found.');\n } else if (format === 'csv') {\n printCsv(\n ['id', 'title', 'url', 'created_at'],\n filtered.map(j => [j.id, j.title, j.url ?? '', j.createdAt]),\n );\n } else {\n console.table(filtered.map(j => ({\n ID: j.id,\n Title: j.title,\n URL: j.url ?? 'N/A',\n Created: new Date(j.createdAt).toLocaleDateString(),\n })));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\njobs\n .command('get')\n .description('Get details of a specific job')\n .argument('<board-id>', 'Board ID')\n .argument('<job-id>', 'Job ID')\n .option('-j, --json', 'Output as JSON')\n .action(async (boardId, jobId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const job = await api.jobs.get(boardId, jobId);\n if (options.json) {\n console.log(JSON.stringify(job, null, 2));\n } else {\n console.log('\\nJob Details:');\n console.log(` Title: ${job.title}`);\n console.log(` URL: ${job.url ?? 'N/A'}`);\n console.log(` Location: ${job.location?.address ?? 'N/A'}`);\n if (job.salary) {\n console.log(` Salary: ${job.salary.min ?? 'N/A'} - ${job.salary.max ?? 'N/A'} ${job.salary.currency ?? ''}`);\n }\n console.log(` Created: ${new Date(job.createdAt).toLocaleString()}`);\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 activities \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst activities = program.command('activities').description('View your board activity log');\n\nactivities\n .command('list')\n .description('List actions for a board')\n .argument('<board-id>', 'Board ID')\n .option('-f, --format <format>', 'Output format: json | table | csv', parseFormatOption, 'json')\n .option('-j, --json', 'Output as JSON (alias for --format json)')\n .option('-d, --days <n>', 'Show only actions from last N days', parseDaysOption)\n .option('--since <date>', 'Show actions since YYYY-MM-DD', parseDateOption)\n .option('--until <date>', 'Show actions until YYYY-MM-DD (inclusive)', parseDateOption)\n .option('--limit <n>', 'Maximum rows to output', parseLimitOption)\n .option('-w, --week', 'Alias for --days 7')\n .option('--types <types>', 'Comma-separated action types (e.g. JOB_MOVED,NOTE_CREATED)')\n .action(async (boardId, options, command) => {\n try {\n const format = resolveOutputFormat(options);\n const range = resolveDateRange(options);\n\n const api = await getApi(command.parent?.parent?.opts().token);\n const opts: { since?: Date; types?: string[] } = {};\n if (range.since) opts.since = range.since;\n if (options.types) opts.types = options.types.split(',').map((t: string) => t.trim()).filter(Boolean);\n\n const actionsRaw = await api.actions.listByBoardFlat(boardId, opts);\n const actions = applyLimit(\n filterByDateRange(actionsRaw, a => a.date || a.createdAt, range),\n options.limit,\n );\n\n if (format === 'json') {\n console.log(JSON.stringify(actions, null, 2));\n } else if (actions.length === 0) {\n console.log('No activities found.');\n } else if (format === 'csv') {\n printCsv(\n ['date', 'type', 'company', 'job', 'status'],\n actions.map(a => [\n new Date(a.date || a.createdAt).toISOString(),\n a.actionType,\n a.data?.company?.name ?? '',\n a.data?.job?.title ?? '',\n a.data?.toList?.name ?? '',\n ]),\n );\n } else {\n console.table(actions.map(a => ({\n Date: new Date(a.date || a.createdAt).toISOString().substring(0, 16),\n Type: a.actionType,\n Company: a.data?.company?.name ?? '',\n Job: (a.data?.job?.title ?? '').substring(0, 40),\n Status: a.data?.toList?.name ?? '',\n })));\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nactivities\n .command('week-csv')\n .description('Export last 7 days of activity as CSV')\n .argument('<board-id>', 'Board ID')\n .action(async (boardId, options, command) => {\n try {\n const api = await getApi(command.parent?.parent?.opts().token);\n const rows = await api.actions.weekSummary(boardId);\n const lines = ['Date,Action,Company,Job Title,Status,Job URL'];\n for (const r of rows) {\n lines.push([\n r.date,\n r.actionType,\n `\"${r.company.replace(/\"/g, '\"\"')}\"`,\n `\"${r.jobTitle.replace(/\"/g, '\"\"')}\"`,\n r.status,\n r.url,\n ].join(','));\n }\n console.log(lines.join('\\n'));\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst config = program.command('config').description('Manage CLI configuration');\n\nconfig\n .command('set-token')\n .description('Save API token to config file or keychain')\n .argument('<token>', 'API token to save')\n .option('-k, --keychain', 'Save to macOS Keychain instead of config file')\n .action(async (token, options) => {\n try {\n const location = options.keychain ? 'keychain' : 'config';\n await tokenManager.saveToken(token, location);\n const locationName = options.keychain ? 'macOS Keychain' : '~/.huntr/config.json';\n console.log(`\u2713 Token saved to ${locationName}`);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('capture-session')\n .description('Capture Clerk session from your browser automatically (recommended)')\n .action(async () => {\n try {\n await captureSession();\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('check-cdp')\n .description('Check Chrome DevTools + Clerk cookie visibility for session capture')\n .action(async () => {\n try {\n await checkCdpSession();\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('set-session')\n .description('Save Clerk session cookie for automatic JWT refresh (recommended)')\n .argument('<session-cookie>', 'Value of the __session cookie from your browser')\n .argument('[session-id]', 'Clerk session ID (sess_...) \u2014 auto-detected from cookie if omitted')\n .addHelpText('after', `\nHow to get your __session cookie:\n 1. Open huntr.co in Chrome and log in\n 2. Open DevTools \u2192 Application \u2192 Cookies \u2192 https://huntr.co\n 3. Find the cookie named __session and copy its Value (the long JWT string)\n 4. Run: huntr config set-session <value>\n\nThe session ID (sess_...) is extracted automatically from the JWT.\nThe session persists for weeks; re-run set-session if you get auth errors.\n `)\n .action(async (sessionCookie, sessionId) => {\n try {\n const mgr = tokenManager.clerkSession;\n\n // Auto-detect session ID from the JWT payload (sid claim)\n let resolvedSessionId = sessionId as string | undefined;\n if (!resolvedSessionId) {\n const detected = ClerkSessionManager.extractSessionId(sessionCookie);\n if (detected) {\n resolvedSessionId = detected;\n console.log(` Session ID detected: ${resolvedSessionId}`);\n } else {\n console.error(\n 'Could not auto-detect session ID from the __session JWT.\\n' +\n 'Find it in the browser console: Clerk.session.id\\n' +\n 'Then run: huntr config set-session <cookie> <session-id>',\n );\n process.exit(1);\n }\n }\n\n // Strip prefix if user pasted \"__session=...\" prefix\n const rawCookie = sessionCookie.startsWith('__session=')\n ? sessionCookie.slice('__session='.length)\n : sessionCookie;\n\n await mgr.saveSession(rawCookie, resolvedSessionId!);\n\n // Verify it works immediately\n console.log(' Testing session\u2026');\n try {\n const token = await mgr.getFreshToken();\n console.log(`\u2713 Session saved and verified (token starts with: ${token.substring(0, 20)}\u2026)`);\n console.log(' Tokens will auto-refresh before each command.');\n } catch (err) {\n console.warn(`\u26A0 Session saved but test refresh failed: ${err instanceof Error ? err.message : err}`);\n console.warn(' Your cookie may be expired. Try extracting it again from the browser.');\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('test-session')\n .description('Test the stored Clerk session by fetching a fresh token and calling /me')\n .action(async () => {\n try {\n const mgr = tokenManager.clerkSession;\n if (!(await mgr.hasSession())) {\n console.error('No session stored. Run: huntr config set-session <__session-cookie>');\n process.exit(1);\n }\n process.stdout.write(' Refreshing token from Clerk\u2026 ');\n const token = await mgr.getFreshToken();\n console.log(`\u2713 (${token.substring(0, 20)}\u2026)`);\n process.stdout.write(' Calling Huntr API /me\u2026 ');\n const api = new (await import('./api/personal')).HuntrPersonalApi(token);\n const profile = await api.user.getProfile();\n console.log('\u2713');\n console.log(`\\n Logged in as: ${profile.givenName ?? profile.firstName ?? ''} ${profile.familyName ?? profile.lastName ?? ''} <${profile.email}>`);\n console.log(' Session is working correctly. Tokens auto-refresh before each command.');\n } catch (error) {\n console.error('\\nFailed:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('show-token')\n .description('Show which authentication sources are configured')\n .action(async () => {\n try {\n const sources = await tokenManager.showTokenSources();\n console.log('\\nConfigured authentication sources:');\n console.log(` Environment variable (HUNTR_API_TOKEN): ${sources.env ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` Clerk session (auto-refresh): ${sources.clerkSession ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` Config file (~/.huntr/config.json): ${sources.config ? '\u2713 Set' : '\u2717 Not set'}`);\n console.log(` macOS Keychain: ${sources.keychain ? '\u2713 Set' : '\u2717 Not set'}`);\n if (!sources.env && !sources.clerkSession && !sources.config && !sources.keychain) {\n console.log('\\nNo credentials found.');\n console.log('Recommended: huntr config set-session <__session-cookie>');\n console.log('Alternative: huntr config set-token <token> [--keychain]');\n } else if (sources.clerkSession) {\n console.log('\\n\u2713 Clerk session active \u2014 tokens refresh automatically.');\n }\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('clear-token')\n .description('Remove saved API token')\n .option('-k, --keychain', 'Clear from macOS Keychain only')\n .option('-c, --config', 'Clear from config file only')\n .action(async (options) => {\n try {\n let location: 'config' | 'keychain' | 'all' = 'all';\n if (options.keychain && !options.config) location = 'keychain';\n else if (options.config && !options.keychain) location = 'config';\n await tokenManager.clearToken(location);\n const message = location === 'all' ? 'all locations'\n : location === 'keychain' ? 'macOS Keychain'\n : 'config file';\n console.log(`\u2713 Token cleared from ${message}`);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nconfig\n .command('clear-session')\n .description('Remove saved Clerk session cookie')\n .action(async () => {\n try {\n await tokenManager.clerkSession.clearSession();\n console.log('\u2713 Clerk session cleared');\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\n// \u2500\u2500 completions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nprogram\n .command('completions')\n .description('Generate shell completion script')\n .argument('<shell>', 'Shell to generate completions for: bash | zsh | fish')\n .addHelpText('after', `\nExamples:\n # bash\n huntr completions bash >> ~/.bash_completion\n source ~/.bash_completion\n\n # zsh (oh-my-zsh or fpath)\n huntr completions zsh > \"$HOME/.zsh/completions/_huntr\"\n # then add $HOME/.zsh/completions to your fpath in ~/.zshrc\n\n # fish\n huntr completions fish > ~/.config/fish/completions/huntr.fish\n `)\n .action((shell: string) => {\n switch (shell) {\n case 'bash':\n /* eslint-disable no-useless-escape */\n console.log(`# huntr bash completion\n# Add to ~/.bash_completion or ~/.bashrc:\n# source <(huntr completions bash)\n\n_huntr_completions() {\n local cur prev words cword\n _init_completion || return\n\n local top_commands=\"me boards jobs activities config completions\"\n local boards_commands=\"list get\"\n local jobs_commands=\"list get\"\n local activities_commands=\"list week-csv\"\n local config_commands=\"set-token capture-session check-cdp set-session test-session show-token clear-token clear-session\"\n\n case \"\\${words[1]}\" in\n boards)\n COMPREPLY=( \\$(compgen -W \"\\${boards_commands}\" -- \"\\${cur}\") )\n return ;;\n jobs)\n COMPREPLY=( \\$(compgen -W \"\\${jobs_commands}\" -- \"\\${cur}\") )\n return ;;\n activities)\n COMPREPLY=( \\$(compgen -W \"\\${activities_commands}\" -- \"\\${cur}\") )\n return ;;\n config)\n COMPREPLY=( \\$(compgen -W \"\\${config_commands}\" -- \"\\${cur}\") )\n return ;;\n completions)\n COMPREPLY=( \\$(compgen -W \"bash zsh fish\" -- \"\\${cur}\") )\n return ;;\n esac\n\n COMPREPLY=( \\$(compgen -W \"\\${top_commands}\" -- \"\\${cur}\") )\n}\n\ncomplete -F _huntr_completions huntr\n`);\n /* eslint-enable no-useless-escape */\n break;\n\n case 'zsh':\n /* eslint-disable no-useless-escape */\n console.log(`#compdef huntr\n# huntr zsh completion\n# Save to a directory in your fpath, e.g. ~/.zsh/completions/_huntr\n\n_huntr() {\n local -a top_commands boards_commands jobs_commands activities_commands config_commands\n top_commands=(\n 'me:Show your user profile'\n 'boards:Manage your boards'\n 'jobs:Manage jobs on your boards'\n 'activities:View your board activity log'\n 'config:Manage CLI configuration'\n 'completions:Generate shell completion script'\n )\n boards_commands=('list:List all your boards' 'get:Get details of a specific board')\n jobs_commands=('list:List jobs on a board' 'get:Get details of a specific job')\n activities_commands=('list:List actions for a board' 'week-csv:Export last 7 days of activity as CSV')\n config_commands=(\n 'set-token:Save API token'\n 'capture-session:Capture Clerk session from browser'\n 'check-cdp:Check Chrome DevTools connectivity'\n 'set-session:Save Clerk session cookie'\n 'test-session:Test stored Clerk session'\n 'show-token:Show configured auth sources'\n 'clear-token:Remove saved API token'\n 'clear-session:Remove saved Clerk session'\n )\n\n local state\n _arguments -C \\\\\n '(-t --token)'{-t,--token}'[API token]:token:' \\\\\n '1: :->command' \\\\\n '*: :->args' && return 0\n\n case \\$state in\n command) _describe 'command' top_commands ;;\n args)\n case \\$words[2] in\n boards) _describe 'boards command' boards_commands ;;\n jobs) _describe 'jobs command' jobs_commands ;;\n activities) _describe 'activities command' activities_commands ;;\n config) _describe 'config command' config_commands ;;\n completions) _values 'shell' bash zsh fish ;;\n esac ;;\n esac\n}\n\n_huntr \"\\$@\"\n`);\n /* eslint-enable no-useless-escape */\n break;\n\n case 'fish':\n console.log(`# huntr fish completion\n# Save to ~/.config/fish/completions/huntr.fish\n\nset -l top_commands me boards jobs activities config completions\n\n# Disable file completions globally\ncomplete -c huntr -f\n\n# Top-level commands\ncomplete -c huntr -n \"__fish_use_subcommand\" -a me -d \"Show your user profile\"\ncomplete -c huntr -n \"__fish_use_subcommand\" -a boards -d \"Manage your boards\"\ncomplete -c huntr -n \"__fish_use_subcommand\" -a jobs -d \"Manage jobs on your boards\"\ncomplete -c huntr -n \"__fish_use_subcommand\" -a activities -d \"View your board activity log\"\ncomplete -c huntr -n \"__fish_use_subcommand\" -a config -d \"Manage CLI configuration\"\ncomplete -c huntr -n \"__fish_use_subcommand\" -a completions -d \"Generate shell completion script\"\n\n# Global flag\ncomplete -c huntr -s t -l token -d \"API token (overrides all other sources)\" -r\n\n# boards subcommands\ncomplete -c huntr -n \"__fish_seen_subcommand_from boards\" -a list -d \"List all your boards\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from boards\" -a get -d \"Get details of a specific board\"\n\n# jobs subcommands\ncomplete -c huntr -n \"__fish_seen_subcommand_from jobs\" -a list -d \"List jobs on a board\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from jobs\" -a get -d \"Get details of a specific job\"\n\n# activities subcommands\ncomplete -c huntr -n \"__fish_seen_subcommand_from activities\" -a list -d \"List actions for a board\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from activities\" -a week-csv -d \"Export last 7 days as CSV\"\n\n# config subcommands\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a set-token -d \"Save API token\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a capture-session -d \"Capture Clerk session from browser\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a check-cdp -d \"Check Chrome DevTools connectivity\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a set-session -d \"Save Clerk session cookie\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a test-session -d \"Test stored Clerk session\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a show-token -d \"Show configured auth sources\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a clear-token -d \"Remove saved API token\"\ncomplete -c huntr -n \"__fish_seen_subcommand_from config\" -a clear-session -d \"Remove saved Clerk session\"\n\n# completions shell argument\ncomplete -c huntr -n \"__fish_seen_subcommand_from completions\" -a \"bash zsh fish\"\n`);\n break;\n\n default:\n console.error(`Unknown shell: ${shell}. Supported: bash, zsh, fish`);\n process.exit(1);\n }\n });\n\nprogram.parse();\n", "import { password } from '@inquirer/prompts';\nimport { ConfigManager } from './config-manager';\nimport { KeychainManager } from './keychain-manager';\nimport { ClerkSessionManager } from './clerk-session-manager';\nimport type { TokenProvider } from '../api/client';\n\nexport interface TokenOptions {\n token?: string;\n usePrompt?: boolean;\n}\n\nexport class TokenManager {\n private configManager: ConfigManager;\n private keychainManager: KeychainManager;\n readonly clerkSession: ClerkSessionManager;\n\n constructor() {\n this.configManager = new ConfigManager();\n this.keychainManager = new KeychainManager();\n this.clerkSession = new ClerkSessionManager();\n }\n\n /**\n * Returns a TokenProvider for use with HuntrPersonalApi.\n *\n * Resolution order:\n * 1. CLI --token argument (static, passed via options)\n * 2. HUNTR_API_TOKEN env var (static)\n * 3. Stored Clerk session cookie \u2192 auto-refresh on every call\n * 4. Static token from config file or keychain\n * 5. Interactive prompt\n */\n async getTokenProvider(options: TokenOptions = {}): Promise<TokenProvider> {\n // 1. CLI argument \u2014 static token\n if (options.token) {\n return options.token;\n }\n\n // 2. Environment variable \u2014 static token\n const envToken = process.env.HUNTR_API_TOKEN;\n if (envToken) {\n return envToken;\n }\n\n // 3. Clerk session \u2014 dynamic refresh\n if (await this.clerkSession.hasSession()) {\n return () => this.clerkSession.getFreshToken();\n }\n\n // 4. Static token from config or keychain\n const configToken = this.configManager.getToken();\n if (configToken) return configToken;\n\n const keychainToken = await this.keychainManager.getToken();\n if (keychainToken) return keychainToken;\n\n // 5. Interactive prompt \u2014 static token (short-lived, but usable)\n if (options.usePrompt !== false) {\n const promptedToken = await password({\n message: 'Enter your Huntr API token:',\n mask: '*',\n });\n\n if (promptedToken) {\n const saveChoice = await this.promptSaveLocation();\n if (saveChoice !== 'none') {\n await this.saveToken(promptedToken, saveChoice);\n }\n return promptedToken;\n }\n }\n\n throw new Error(\n 'No Huntr credentials found. Options:\\n' +\n ' \u2022 Clerk session (recommended): huntr config set-session <__session-cookie>\\n' +\n ' \u2022 Static token: huntr config set-token <token> [--keychain]\\n' +\n ' \u2022 CLI flag: huntr --token <token> <command>\\n' +\n ' \u2022 Environment: HUNTR_API_TOKEN=<token> huntr <command>',\n );\n }\n\n /**\n * Legacy helper \u2014 returns a resolved static token string.\n * Use getTokenProvider() for new code so session refresh works.\n */\n async getToken(options: TokenOptions = {}): Promise<string> {\n if (options.token) return options.token;\n const envToken = process.env.HUNTR_API_TOKEN;\n if (envToken) return envToken;\n const configToken = this.configManager.getToken();\n if (configToken) return configToken;\n const keychainToken = await this.keychainManager.getToken();\n if (keychainToken) return keychainToken;\n throw new Error('No static token found. Try huntr config set-token or set-session.');\n }\n\n private async promptSaveLocation(): Promise<'config' | 'keychain' | 'none'> {\n const { select } = await import('@inquirer/prompts');\n return await select({\n message: 'Where would you like to save this token?',\n choices: [\n { name: 'Save to config file (~/.huntr/config.json)', value: 'config' as const },\n { name: 'Save to macOS Keychain (secure)', value: 'keychain' as const },\n { name: 'Do not save (enter each time)', value: 'none' as const },\n ],\n }) as 'config' | 'keychain' | 'none';\n }\n\n async saveToken(token: string, location: 'config' | 'keychain'): Promise<void> {\n if (location === 'config') {\n this.configManager.setToken(token);\n } else {\n await this.keychainManager.setToken(token);\n }\n }\n\n async clearToken(location?: 'config' | 'keychain' | 'all'): Promise<void> {\n if (!location || location === 'all' || location === 'config') {\n this.configManager.clearToken();\n }\n if (!location || location === 'all' || location === 'keychain') {\n await this.keychainManager.deleteToken();\n }\n }\n\n async showTokenSources(): Promise<{\n env: boolean;\n config: boolean;\n keychain: boolean;\n clerkSession: boolean;\n }> {\n return {\n env: !!process.env.HUNTR_API_TOKEN,\n config: !!this.configManager.getToken(),\n keychain: !!(await this.keychainManager.getToken()),\n clerkSession: await this.clerkSession.hasSession(),\n };\n }\n}\n", "import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport interface HuntrConfig {\n apiToken?: string;\n api?: {\n boardsPath?: '/boards' | '/board';\n boardsShape?: 'array' | 'dataArray' | 'map';\n };\n}\n\nexport class ConfigManager {\n private configDir: string;\n private configPath: string;\n\n constructor() {\n this.configDir = path.join(os.homedir(), '.huntr');\n this.configPath = path.join(this.configDir, 'config.json');\n }\n\n private ensureConfigDir(): void {\n if (!fs.existsSync(this.configDir)) {\n fs.mkdirSync(this.configDir, { recursive: true });\n }\n }\n\n getConfig(): HuntrConfig {\n try {\n if (fs.existsSync(this.configPath)) {\n const content = fs.readFileSync(this.configPath, 'utf-8');\n return JSON.parse(content);\n }\n } catch (error) {\n // Return empty config if file doesn't exist or is invalid\n }\n return {};\n }\n\n setConfig(config: HuntrConfig): void {\n this.ensureConfigDir();\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));\n }\n\n getToken(): string | undefined {\n return this.getConfig().apiToken;\n }\n\n getBoardsApiPrefs(): { path?: '/boards' | '/board'; shape?: 'array' | 'dataArray' | 'map' } {\n const cfg = this.getConfig();\n return { path: cfg.api?.boardsPath, shape: cfg.api?.boardsShape };\n }\n\n setBoardsApiPrefs(prefs: { path: '/boards' | '/board'; shape: 'array' | 'dataArray' | 'map' }): void {\n const cfg = this.getConfig();\n cfg.api = cfg.api ?? {};\n cfg.api.boardsPath = prefs.path;\n cfg.api.boardsShape = prefs.shape;\n this.setConfig(cfg);\n }\n\n setToken(token: string): void {\n const config = this.getConfig();\n config.apiToken = token;\n this.setConfig(config);\n }\n\n clearToken(): void {\n const config = this.getConfig();\n delete config.apiToken;\n this.setConfig(config);\n }\n}\n", "import keytar from 'keytar';\n\nconst SERVICE_NAME = 'huntr-cli';\nconst ACCOUNT_NAME = 'api-token';\n\nexport class KeychainManager {\n async getToken(): Promise<string | null> {\n try {\n return await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n } catch (error) {\n return null;\n }\n }\n\n async setToken(token: string): Promise<void> {\n try {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);\n } catch (error) {\n throw new Error('Failed to save token to keychain');\n }\n }\n\n async deleteToken(): Promise<boolean> {\n try {\n return await keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n } catch (error) {\n return false;\n }\n }\n}\n", "import keytar from 'keytar';\nimport https from 'https';\n\nconst SERVICE_NAME = 'huntr-cli';\nconst ACCOUNT_SESSION_COOKIE = 'clerk-session-cookie'; // __session value\nconst ACCOUNT_SESSION_ID = 'clerk-session-id'; // sess_...\nconst ACCOUNT_CLIENT_UAT = 'clerk-client-uat'; // __client_uat value (optional)\nconst ACCOUNT_EXTRA_COOKIES = 'clerk-extra-cookies'; // JSON map of clerk-domain cookies\n\nconst CLERK_HOST = 'clerk.huntr.co';\n\n/**\n * Manages Clerk session-based JWT refresh for the Huntr CLI.\n *\n * Modern Clerk architecture (v5+):\n * - __session cookie : stores the short-lived session JWT (60s exp).\n * The cookie itself has a long expiry (1 year);\n * Clerk JS updates its *value* via FAPI silently.\n * - __client_uat : Unix timestamp of last client update \u2014 not a credential.\n *\n * To refresh from outside a browser, we POST the __session value to Clerk's\n * FAPI tokens endpoint. Clerk validates the session and returns a fresh JWT.\n *\n * Endpoint:\n * POST https://clerk.huntr.co/v1/client/sessions/{sessionId}/tokens\n * Cookie: __session=<value>\n * Response: { jwt: \"ey...\" }\n *\n * The __session value must be re-extracted from the browser periodically\n * (roughly every few weeks, when Clerk rotates the underlying session).\n * For daily use it persists fine.\n */\nexport class ClerkSessionManager {\n // \u2500\u2500 storage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async saveSession(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string,\n extraCookies?: Record<string, string>,\n ): Promise<void> {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE, sessionCookieValue);\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_SESSION_ID, sessionId);\n if (clientUat) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT, clientUat);\n }\n if (extraCookies && Object.keys(extraCookies).length > 0) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES, JSON.stringify(extraCookies));\n }\n }\n\n async getSessionCookie(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE);\n }\n\n async getSessionId(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_SESSION_ID);\n }\n\n async getClientUat(): Promise<string | null> {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT);\n }\n\n async getExtraCookies(): Promise<Record<string, string>> {\n const raw = await keytar.getPassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES);\n if (!raw) return {};\n try {\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (typeof v === 'string' && v.length > 0) out[k] = v;\n }\n return out;\n } catch {\n return {};\n }\n }\n\n async clearSession(): Promise<void> {\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_SESSION_COOKIE);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_SESSION_ID);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_CLIENT_UAT);\n await keytar.deletePassword(SERVICE_NAME, ACCOUNT_EXTRA_COOKIES);\n }\n\n async hasSession(): Promise<boolean> {\n const cookie = await this.getSessionCookie();\n const sessionId = await this.getSessionId();\n return !!(cookie && sessionId);\n }\n\n // \u2500\u2500 token refresh \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Returns a fresh Clerk JWT by POSTing to the Clerk FAPI tokens endpoint\n * using the stored __session cookie value.\n */\n async getFreshToken(): Promise<string> {\n const sessionCookie = await this.getSessionCookie();\n const sessionId = await this.getSessionId();\n const clientUat = await this.getClientUat();\n const extraCookies = await this.getExtraCookies();\n\n if (!sessionCookie || !sessionId) {\n throw new Error(\n 'No Clerk session stored. Run:\\n' +\n ' huntr config set-session <__session-cookie-value>\\n' +\n 'See \"huntr config set-session --help\" for instructions.',\n );\n }\n\n return this.fetchToken(sessionCookie, sessionId, clientUat, extraCookies);\n }\n\n async refreshFromProvidedSession(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string | null,\n extraCookies?: Record<string, string>,\n ): Promise<string> {\n return this.fetchToken(sessionCookieValue, sessionId, clientUat, extraCookies);\n }\n\n private fetchToken(\n sessionCookieValue: string,\n sessionId: string,\n clientUat?: string | null,\n extraCookies: Record<string, string> = {},\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n // Match the exact request Clerk JS makes (version pinned to what huntr.co loads)\n const path = `/v1/client/sessions/${sessionId}/tokens?_clerk_js_version=4.73.14`;\n // Strip any \"__session=\" prefix if user pasted it with the name\n const raw = sessionCookieValue.startsWith('__session=')\n ? sessionCookieValue.slice('__session='.length)\n : sessionCookieValue;\n // Send all cookies Clerk expects, matching browser credentials:include behaviour\n const uat = clientUat && clientUat.trim() ? clientUat.trim() : '1';\n const cookieParts = [`__session=${raw}`, `__client_uat=${uat}`];\n for (const [name, value] of Object.entries(extraCookies)) {\n if (!value || name === '__session' || name === '__client_uat') continue;\n if (!/^[A-Za-z0-9_.-]+$/.test(name)) continue;\n cookieParts.push(`${name}=${value}`);\n }\n const cookieHeader = cookieParts.join('; ');\n\n const options = {\n hostname: CLERK_HOST,\n path,\n method: 'POST',\n headers: {\n 'Cookie': cookieHeader,\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Content-Length': '0',\n 'Accept': 'application/json',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',\n 'Origin': 'https://huntr.co',\n 'Referer': 'https://huntr.co/',\n 'sec-fetch-site': 'same-site',\n 'sec-fetch-mode': 'cors',\n 'sec-fetch-dest': 'empty',\n },\n };\n\n const req = https.request(options, (res) => {\n let body = '';\n res.on('data', (chunk: Buffer) => { body += chunk.toString(); });\nres.on('end', () => {\n void (async () => {\n if (res.statusCode === 200 || res.statusCode === 201) {\n try {\n const data = JSON.parse(body);\n // Clerk FAPI response: { object: 'token', jwt: '...' }\n const token = data.jwt ?? data.token ?? data.object?.jwt;\n if (!token) {\n reject(new Error(`Unexpected Clerk response: ${body.substring(0, 300)}`));\n } else {\n // Clerk may rotate __session on refresh via Set-Cookie.\n // Persisting it prevents \"works once, fails later\" behavior.\n await this.persistRotatedSessionCookie(res.headers['set-cookie'], sessionId, raw, uat, extraCookies);\n resolve(token as string);\n }\n } catch {\n reject(new Error(`Failed to parse Clerk response: ${body.substring(0, 300)}`));\n }\n } else if (res.statusCode === 401 || res.statusCode === 403) {\n reject(new Error(\n `Clerk session expired or invalid (HTTP ${res.statusCode}).\\n` +\n 'Re-extract your __session cookie from the browser:\\n' +\n ' DevTools \u2192 Application \u2192 Cookies \u2192 https://huntr.co \u2192 __session \u2192 Value\\n' +\n 'Then run: huntr config set-session <new-value>',\n ));\n } else {\n reject(new Error(\n `Clerk token refresh failed: HTTP ${res.statusCode}\\n${body.substring(0, 300)}`,\n ));\n }\n })();\n });\n });\n\n req.on('error', (err: Error) =>\n reject(new Error(`Network error refreshing token: ${err.message}`)),\n );\n req.end();\n });\n }\n\n private async persistRotatedSessionCookie(\n setCookie: string | string[] | undefined,\n sessionId: string,\n currentSessionCookie: string,\n clientUat?: string,\n extraCookies: Record<string, string> = {},\n ): Promise<void> {\n if (!setCookie) return;\n const cookies = Array.isArray(setCookie) ? setCookie : [setCookie];\n let sessionCookie: string = currentSessionCookie;\n let rotatedUat = clientUat;\n const rotatedExtras: Record<string, string> = { ...extraCookies };\n\n for (const header of cookies) {\n const firstPair = header.split(';', 1)[0] ?? '';\n const idx = firstPair.indexOf('=');\n if (idx <= 0) continue;\n const name = firstPair.slice(0, idx);\n const value = firstPair.slice(idx + 1);\n if (!value) continue;\n\n if (name === '__session') {\n sessionCookie = value;\n } else if (name === '__client_uat') {\n rotatedUat = value;\n } else if (/^[A-Za-z0-9_.-]+$/.test(name)) {\n rotatedExtras[name] = value;\n }\n }\n\n await this.saveSession(sessionCookie, sessionId, rotatedUat, rotatedExtras);\n }\n\n // \u2500\u2500 session-id extraction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Extracts the Clerk session ID (sess_...) from a __session JWT value.\n * The __session cookie value IS a JWT; its payload contains `sid`.\n */\n static extractSessionId(sessionJwt: string): string | null {\n try {\n const raw = sessionJwt.startsWith('__session=')\n ? sessionJwt.slice('__session='.length)\n : sessionJwt;\n\n const parts = raw.split('.');\n if (parts.length < 2) return null;\n\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n const sid = payload.sid ?? payload.session_id;\n if (typeof sid === 'string' && sid.startsWith('sess_')) return sid;\n } catch {\n // fall through\n }\n return null;\n }\n}\n", "#!/usr/bin/env node\n/**\n * Session capture via Chrome DevTools Protocol (CDP).\n * - Connects to a Chrome instance started with --remote-debugging-port.\n * - Reads required Huntr/Clerk cookies from the active huntr.co tab.\n * - Verifies refresh with Clerk and stores session data in macOS Keychain.\n */\n\nimport { mkdirSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { spawn } from 'child_process';\nimport net from 'net';\nimport { ClerkSessionManager } from '../config/clerk-session-manager';\n\nconst CDP_PORT = 9222;\nconst CDP_USER_DATA_DIR = join(tmpdir(), 'huntr-cdp-profile');\nconst HUNTR_APP_URL = 'https://huntr.co/home';\nconst HUNTR_COOKIE_URLS = ['https://huntr.co/', HUNTR_APP_URL, 'https://clerk.huntr.co/'];\nconst CAPTURED_COOKIE_NAMES = new Set(['__session', '__client_uat', '__client', '__cf_bm', '_cfuvid']);\nconst TAB_WAIT_TIMEOUT_MS = 45_000;\nconst TOKEN_WAIT_TIMEOUT_MS = 120_000;\nconst POLL_INTERVAL_MS = 1_500;\nconst CLERK_SESSION_ID_EVAL_EXPRESSION = `(() => {\n const sid = window.Clerk?.session?.id;\n return typeof sid === 'string' ? sid : '';\n})()`;\n\ntype ChromeTab = {\n url?: string;\n type?: string;\n title?: string;\n webSocketDebuggerUrl?: string;\n};\n\ntype SessionCookieWaitResult = {\n sessionCookie: string | null;\n sessionId?: string;\n clientUat?: string | null;\n extraCookies?: Record<string, string>;\n freshToken?: string;\n tab?: ChromeTab;\n lastValueDescription?: string;\n lastError?: string;\n};\n\ntype SessionSnapshot = {\n sessionCookie: string;\n clientUat: string | null;\n extraCookies: Record<string, string>;\n clerkSessionId: string | null;\n};\n\nexport async function captureSession(): Promise<void> {\n console.log('\\nConnecting to Chrome via DevTools Protocol\u2026');\n\n // Step 1: Check if Chrome is already running with remote debugging\n let tabs = await getChromeTabs().catch(() => null);\n\n if (!tabs) {\n console.log(' Chrome not running with --remote-debugging-port. Launching\u2026');\n await launchChromeWithDebugging();\n // Give it a moment to start\n await new Promise(r => setTimeout(r, 2000));\n tabs = await getChromeTabs().catch(() => null);\n }\n\n if (!tabs) {\n throw new Error(\n 'Could not connect to Chrome DevTools Protocol.\\n' +\n 'Please quit Chrome and re-run this command, or start Chrome manually with:\\n' +\n ` /Applications/Google\\\\ Chrome.app/Contents/MacOS/Google\\\\ Chrome --remote-debugging-port=${CDP_PORT} --user-data-dir=${CDP_USER_DATA_DIR} ${HUNTR_APP_URL}\\n` +\n ' (If this is your first run, sign in to huntr.co in that profile once.)\\n' +\n 'Then run: huntr config capture-session',\n );\n }\n\n // Step 2: Find the huntr.co tab\n let huntrTab = findBestHuntrTab(tabs);\n if (!huntrTab) {\n console.log(` Opening ${HUNTR_APP_URL} in debug profile\u2026`);\n await openHuntrAppInDebugProfile();\n }\n\n console.log(' Waiting for huntr.co tab to become available\u2026');\n huntrTab = await waitForHuntrTab(TAB_WAIT_TIMEOUT_MS);\n if (!huntrTab || !huntrTab.webSocketDebuggerUrl) {\n throw new Error(\n 'No huntr.co tab found in Chrome DevTools.\\n' +\n `Please open ${HUNTR_APP_URL} in Chrome (in the debug profile) and re-run.`,\n );\n }\n\n console.log(` Found huntr.co tab: ${huntrTab.title}`);\n const mgr = new ClerkSessionManager();\n console.log(' Waiting for login and extracting Clerk session cookie\u2026');\n\n // Step 3: Poll until we have a cookie pair that actually refreshes via Clerk\n const cookieWait = await waitForValidHuntrSessionCookie(mgr, TOKEN_WAIT_TIMEOUT_MS);\n if (!cookieWait.sessionCookie) {\n const details = [\n `Last tab URL: ${cookieWait.tab?.url ?? '(none)'}`,\n cookieWait.lastValueDescription ? `Last cookie value: ${cookieWait.lastValueDescription}` : '',\n cookieWait.lastError ? `Last eval error: ${cookieWait.lastError}` : '',\n ].filter(Boolean).join('\\n');\n throw new Error(\n 'Timed out waiting for authenticated huntr session.\\n' +\n 'Please finish signing in on the opened Chrome window, then re-run.\\n' +\n details,\n );\n }\n const sessionCookie = cookieWait.sessionCookie;\n const sessionId = cookieWait.sessionId;\n const clientUat = cookieWait.clientUat;\n const extraCookies = cookieWait.extraCookies ?? {};\n\n if (!sessionId) {\n throw new Error('Could not extract session ID from session cookie.');\n }\n\n console.log(` Session ID: ${sessionId}`);\n\n await mgr.saveSession(sessionCookie, sessionId, clientUat ?? undefined, extraCookies);\n console.log(' Saved to macOS Keychain.');\n\n // Step 5: Immediately test the refresh endpoint\n process.stdout.write(' Testing auto-refresh\u2026 ');\n await mgr.getFreshToken();\n console.log('\u2713');\n console.log('\\n\u2713 Session captured and verified!');\n console.log(' Tokens will auto-refresh before every command.');\n console.log(' Run: node dist/cli.js activities week-csv 68bf9e33f871e5004a5eb58e');\n}\n\nexport async function checkCdpSession(): Promise<void> {\n console.log('\\nChecking Chrome DevTools session visibility\u2026');\n const tabs = await getChromeTabs().catch(() => null);\n\n if (!tabs) {\n throw new Error(\n 'Could not connect to Chrome DevTools Protocol.\\n' +\n 'Start Chrome with:\\n' +\n ` /Applications/Google\\\\ Chrome.app/Contents/MacOS/Google\\\\ Chrome --remote-debugging-port=${CDP_PORT} --user-data-dir=${CDP_USER_DATA_DIR} ${HUNTR_APP_URL}`,\n );\n }\n\n const huntrTab = findBestHuntrTab(tabs);\n if (!huntrTab?.webSocketDebuggerUrl) {\n throw new Error('No huntr.co page tab found. Open huntr.co in the debug-profile Chrome and retry.');\n }\n\n console.log(` Using tab: ${huntrTab.title ?? '(untitled)'}`);\n console.log(` URL: ${huntrTab.url ?? '(unknown)'}`);\n\n const snapshot = await getSessionSnapshotInTab(huntrTab.webSocketDebuggerUrl, huntrTab.url);\n if (!snapshot?.sessionCookie) {\n throw new Error(\n 'CDP connected, but __session cookie is not visible yet.\\n' +\n 'Finish login in that tab, wait for the app page to load, then retry.',\n );\n }\n\n const sessionId =\n ClerkSessionManager.extractSessionId(snapshot.sessionCookie) ??\n snapshot.clerkSessionId ??\n undefined;\n if (!sessionId || !sessionId.startsWith('sess_')) {\n throw new Error('Found __session cookie, but could not derive a valid Clerk session ID.');\n }\n\n const visibleCookies = [\n '__session',\n snapshot.clientUat ? '__client_uat' : null,\n ...Object.keys(snapshot.extraCookies),\n ].filter(Boolean) as string[];\n console.log(` Visible cookies: ${visibleCookies.sort().join(', ')}`);\n\n const mgr = new ClerkSessionManager();\n process.stdout.write(' Testing Clerk refresh with visible cookies\u2026 ');\n const fresh = await mgr.refreshFromProvidedSession(\n snapshot.sessionCookie,\n sessionId,\n snapshot.clientUat,\n snapshot.extraCookies,\n );\n console.log('\u2713');\n console.log(` Session ID: ${sessionId}`);\n console.log(` Refresh token preview: ${fresh.substring(0, 20)}\u2026`);\n}\n\nasync function getChromeTabs(): Promise<ChromeTab[]> {\n const response = await fetch(`http://127.0.0.1:${CDP_PORT}/json`);\n if (!response.ok) throw new Error(`CDP returned ${response.status}`);\n const json: unknown = await response.json();\n if (!Array.isArray(json)) throw new Error('Unexpected CDP /json response');\n return json as ChromeTab[];\n}\n\nasync function launchChromeWithDebugging(): Promise<void> {\n // Chrome requires an explicit user-data-dir when remote debugging is enabled.\n mkdirSync(CDP_USER_DATA_DIR, { recursive: true });\n const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';\n spawn(chromePath, [\n `--remote-debugging-port=${CDP_PORT}`,\n `--user-data-dir=${CDP_USER_DATA_DIR}`,\n '--no-first-run',\n '--no-default-browser-check',\n HUNTR_APP_URL,\n ], { detached: true, stdio: 'ignore' }).unref();\n}\n\nasync function openHuntrAppInDebugProfile(): Promise<void> {\n // Launching again with the same user-data-dir opens a tab in that profile.\n await launchChromeWithDebugging();\n}\n\nasync function waitForHuntrTab(timeoutMs: number): Promise<ChromeTab | undefined> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const tabs = await getChromeTabs().catch(() => null);\n const tab = tabs ? findBestHuntrTab(tabs) : undefined;\n if (tab?.webSocketDebuggerUrl) return tab;\n await sleep(POLL_INTERVAL_MS);\n }\n return undefined;\n}\n\nasync function waitForValidHuntrSessionCookie(\n mgr: ClerkSessionManager,\n timeoutMs: number,\n): Promise<SessionCookieWaitResult> {\n const deadline = Date.now() + timeoutMs;\n let lastTab: ChromeTab | undefined;\n let lastValueDescription: string | undefined;\n let lastError: string | undefined;\n let printedHint = false;\n\n while (Date.now() < deadline) {\n const tabs = await getChromeTabs().catch(() => null);\n const huntrTabs = tabs ? findHuntrTabs(tabs) : [];\n\n for (const tab of huntrTabs) {\n if (!tab.webSocketDebuggerUrl) continue;\n lastTab = tab;\n\n try {\n const snapshot = await getSessionSnapshotInTab(tab.webSocketDebuggerUrl, tab.url);\n lastValueDescription = describeValue(snapshot);\n\n if (!snapshot?.sessionCookie || snapshot.sessionCookie.split('.').length !== 3) {\n continue;\n }\n\n const sessionId =\n ClerkSessionManager.extractSessionId(snapshot.sessionCookie) ??\n snapshot.clerkSessionId ??\n undefined;\n\n if (!sessionId || !sessionId.startsWith('sess_')) {\n continue;\n }\n\n const freshToken = await mgr.refreshFromProvidedSession(\n snapshot.sessionCookie,\n sessionId,\n snapshot.clientUat,\n snapshot.extraCookies,\n );\n if (freshToken && freshToken.split('.').length === 3) {\n return {\n sessionCookie: snapshot.sessionCookie,\n sessionId,\n clientUat: snapshot.clientUat,\n extraCookies: snapshot.extraCookies,\n freshToken,\n tab,\n lastValueDescription,\n lastError,\n };\n }\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n }\n\n if (!printedHint && huntrTabs.length > 0) {\n console.log(' Waiting for you to finish signing into huntr.co in that Chrome window\u2026');\n printedHint = true;\n }\n await sleep(POLL_INTERVAL_MS);\n }\n\n return { sessionCookie: null, tab: lastTab, lastValueDescription, lastError };\n}\n\nfunction isHuntrAppTab(tab: ChromeTab): boolean {\n if (!tab.url || tab.type !== 'page') return false;\n try {\n const parsed = new URL(tab.url);\n if (!parsed.hostname.endsWith('huntr.co')) return false;\n return parsed.pathname !== '/' && parsed.pathname.length > 1;\n } catch {\n return false;\n }\n}\n\nfunction isHuntrTab(tab: ChromeTab): boolean {\n if (!tab.url || tab.type !== 'page') return false;\n try {\n const parsed = new URL(tab.url);\n return parsed.hostname.endsWith('huntr.co');\n } catch {\n return false;\n }\n}\n\nfunction findHuntrTabs(tabs: ChromeTab[]): ChromeTab[] {\n const huntrTabs = tabs.filter(isHuntrTab);\n const appTabs = huntrTabs.filter(isHuntrAppTab);\n return appTabs.length > 0 ? appTabs : huntrTabs;\n}\n\nfunction findBestHuntrTab(tabs: ChromeTab[]): ChromeTab | undefined {\n return findHuntrTabs(tabs)[0];\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function getSessionSnapshotInTab(wsUrl: string, pageUrl?: string): Promise<SessionSnapshot | null> {\n const cookies = await getCookiesInTab(wsUrl, pageUrl);\n const sessionCookie = cookies.__session ?? null;\n if (!sessionCookie) return null;\n\n const clerkSessionIdRaw = await evaluateInTab(wsUrl, CLERK_SESSION_ID_EVAL_EXPRESSION).catch(() => '');\n const clerkSessionId =\n typeof clerkSessionIdRaw === 'string' && clerkSessionIdRaw.startsWith('sess_')\n ? clerkSessionIdRaw\n : null;\n\n return {\n sessionCookie,\n clientUat: cookies.__client_uat ?? null,\n extraCookies: Object.fromEntries(\n Object.entries(cookies).filter(([name]) => name !== '__session' && name !== '__client_uat'),\n ),\n clerkSessionId,\n };\n}\n\nasync function getCookiesInTab(wsUrl: string, pageUrl?: string): Promise<Record<string, string>> {\n try {\n await cdpRequestInTab(wsUrl, 'Network.enable');\n } catch {\n // Not all targets require/allow Network.enable first.\n }\n\n const urls = pageUrl ? Array.from(new Set([pageUrl, ...HUNTR_COOKIE_URLS])) : HUNTR_COOKIE_URLS;\n const result = await cdpRequestInTab(wsUrl, 'Network.getCookies', { urls });\n const cookies = (result as { cookies?: unknown[] } | null)?.cookies;\n const out: Record<string, string> = {};\n\n if (!Array.isArray(cookies)) return out;\n\n for (const cookie of cookies) {\n if (!cookie || typeof cookie !== 'object') continue;\n const c = cookie as Record<string, unknown>;\n const name = c.name;\n const value = c.value;\n const domain = c.domain;\n\n if (typeof name !== 'string' || typeof value !== 'string') continue;\n if (typeof domain === 'string' && !domain.includes('huntr.co')) continue;\n if (CAPTURED_COOKIE_NAMES.has(name)) {\n out[name] = value;\n }\n }\n\n return out;\n}\n\nasync function evaluateInTab(wsUrl: string, expression: string): Promise<unknown> {\n const result = await cdpRequestInTab(wsUrl, 'Runtime.evaluate', {\n expression,\n awaitPromise: true,\n returnByValue: true,\n });\n\n const evalResult = (result ?? {}) as Record<string, unknown>;\n const exceptionDetails = evalResult.exceptionDetails as Record<string, unknown> | undefined;\n if (exceptionDetails) {\n const text = typeof exceptionDetails.text === 'string' ? exceptionDetails.text : 'Runtime.evaluate failed';\n throw new Error(text);\n }\n\n const runtimeResult = evalResult.result as Record<string, unknown> | undefined;\n if (!runtimeResult || !Object.prototype.hasOwnProperty.call(runtimeResult, 'value')) return undefined;\n return runtimeResult.value;\n}\n\nfunction cdpRequestInTab(\n wsUrl: string,\n method: string,\n params: Record<string, unknown> = {},\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n // Use Node's built-in WebSocket (Node 22+) or fall back to a raw WS handshake\n const WebSocketImpl = (globalThis as any).WebSocket;\n\n if (WebSocketImpl) {\n connectWithWebSocket(wsUrl, WebSocketImpl, method, params, resolve, reject);\n } else {\n // Node < 22: implement minimal WS client over net/tls\n connectWithRawWS(wsUrl, method, params, resolve, reject);\n }\n });\n}\n\nfunction connectWithWebSocket(\n wsUrl: string,\n WS: typeof WebSocket,\n method: string,\n params: Record<string, unknown>,\n resolve: (v: unknown) => void,\n reject: (e: Error) => void,\n): void {\n const ws = new WS(wsUrl);\n const id = 1;\n\n ws.onopen = () => {\n ws.send(JSON.stringify({\n id,\n method,\n params,\n }));\n };\n\n ws.onmessage = async (evt: MessageEvent) => {\n try {\n const raw = await wsDataToText(evt.data);\n const msg = JSON.parse(raw);\n if (msg.id !== id) return;\n if (msg.error) {\n ws.close();\n reject(new Error(msg.error?.message ?? `CDP ${method} failed`));\n return;\n }\n\n ws.close();\n resolve(msg.result as unknown);\n } catch (e) {\n ws.close();\n reject(e instanceof Error ? e : new Error(String(e)));\n }\n };\n\n ws.onerror = () => reject(new Error('WebSocket connection to Chrome DevTools failed'));\n\n setTimeout(() => { ws.close(); reject(new Error('Timeout waiting for Chrome response')); }, 10_000);\n}\n\nasync function wsDataToText(data: unknown): Promise<string> {\n if (typeof data === 'string') return data;\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(data)) return data.toString('utf8');\n if (data instanceof ArrayBuffer) return Buffer.from(data).toString('utf8');\n if (typeof Blob !== 'undefined' && data instanceof Blob) return await data.text();\n return String(data);\n}\n\nfunction connectWithRawWS(\n wsUrl: string,\n method: string,\n params: Record<string, unknown>,\n resolve: (v: unknown) => void,\n reject: (e: Error) => void,\n): void {\n // Parse ws://host:port/path\n const match = wsUrl.match(/^ws:\\/\\/([^/:]+):(\\d+)(\\/.*)?$/);\n if (!match) { reject(new Error(`Cannot parse WS URL: ${wsUrl}`)); return; }\n\n const host = match[1];\n const port = parseInt(match[2], 10);\n const path = match[3] ?? '/';\n\n const socket = net.createConnection(port, host);\n\n const key = Buffer.from(Math.random().toString(36)).toString('base64');\n let buffer = '';\n let handshakeDone = false;\n const msgId = 1;\n\n socket.on('connect', () => {\n socket.write(\n `GET ${path} HTTP/1.1\\r\\n` +\n `Host: ${host}:${port}\\r\\n` +\n 'Upgrade: websocket\\r\\n' +\n 'Connection: Upgrade\\r\\n' +\n `Sec-WebSocket-Key: ${key}\\r\\n` +\n 'Sec-WebSocket-Version: 13\\r\\n\\r\\n',\n );\n });\n\n socket.on('data', (data: Buffer) => {\n if (!handshakeDone) {\n buffer += data.toString();\n if (buffer.includes('\\r\\n\\r\\n')) {\n handshakeDone = true;\n // Send the evaluate command\n const payload = JSON.stringify({\n id: msgId,\n method,\n params,\n });\n socket.write(encodeWsFrame(payload));\n }\n return;\n }\n\n // Parse WebSocket frame\n try {\n const msg = decodeWsFrame(data);\n if (msg) {\n const parsed = JSON.parse(msg);\n if (parsed.id !== msgId) return;\n if (parsed.error) {\n socket.destroy();\n reject(new Error(parsed.error?.message ?? `CDP ${method} failed`));\n return;\n }\n\n socket.destroy();\n resolve(parsed.result as unknown);\n }\n } catch {\n // partial frame, wait for more data\n }\n });\n\n socket.on('error', (e: Error) => reject(e));\n setTimeout(() => { socket.destroy(); reject(new Error('Timeout')); }, 10_000);\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') return `string, ${value.length} chars`;\n if (Array.isArray(value)) return `array, ${value.length} items`;\n if (typeof value === 'object') {\n const keys = Object.keys(value as Record<string, unknown>);\n return `object, keys: ${keys.slice(0, 6).join(', ') || '(none)'}`;\n }\n return typeof value;\n}\n\nfunction encodeWsFrame(payload: string): Buffer {\n const data = Buffer.from(payload, 'utf8');\n const len = data.length;\n const mask = Buffer.from([\n Math.random() * 256, Math.random() * 256,\n Math.random() * 256, Math.random() * 256,\n ].map(Math.floor));\n\n const header = len < 126\n ? Buffer.from([0x81, 0x80 | len])\n : len < 65536\n ? Buffer.from([0x81, 0xfe, len >> 8, len & 0xff])\n : Buffer.from([0x81, 0xff, 0, 0, 0, 0, (len >> 24) & 0xff, (len >> 16) & 0xff, (len >> 8) & 0xff, len & 0xff]);\n\n const masked = Buffer.alloc(len);\n for (let i = 0; i < len; i++) masked[i] = data[i] ^ mask[i % 4];\n return Buffer.concat([header, mask, masked]);\n}\n\nfunction decodeWsFrame(buf: Buffer): string | null {\n if (buf.length < 2) return null;\n const len = buf[1] & 0x7f;\n let offset = 2;\n const payloadLen = len < 126 ? len : len === 126 ? (buf.readUInt16BE(2), offset += 2, buf.readUInt16BE(2)) : null;\n if (payloadLen === null) return null;\n return buf.slice(offset, offset + (payloadLen as number)).toString('utf8');\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;AAAA,OAAO,WAA0C;AAIjD,OAAO,YAAY;AAJnB,IAYa,gBA4EA;AAxFb;AAAA;AAAA;AAKA,QAAI,QAAQ,IAAI,mBAAmB,QAAQ;AACzC,aAAO,OAAO,EAAE,OAAO,MAAM,CAAC;AAAA,IAChC;AAKO,IAAM,iBAAN,MAAqB;AAAA,MAI1B,YAAY,eAA8B,UAAkB,4BAA4B;AACtF,aAAK,gBACH,OAAO,kBAAkB,WACrB,YAAY,gBACZ;AAEN,aAAK,gBAAgB,MAAM,OAAO,EAAE,QAAQ,CAAC;AAG7C,aAAK,cAAc,aAAa,QAAQ,IAAI,OAAOA,YAAW;AAC5D,gBAAM,QAAQ,MAAM,KAAK,cAAc;AACvC,cAAI,CAAC,MAAO,OAAM,IAAI,MAAM,yBAAyB;AACrD,UAAAA,QAAO,UAAUA,QAAO,WAAW,CAAC;AACpC,UAAAA,QAAO,QAAQ,eAAe,IAAI,UAAU,KAAK;AACjD,UAAAA,QAAO,QAAQ,cAAc,IAAI;AACjC,iBAAOA;AAAA,QACT,CAAC;AAED,aAAK,cAAc,aAAa,SAAS;AAAA,UACvC,CAAC,aAAa;AAAA,UACd,CAAC,UAAsB;AACrB,gBAAI,MAAM,UAAU;AAClB,oBAAM,SAAS,MAAM,SAAS;AAC9B,oBAAM,WAAW,MAAM,SAAS;AAChC,oBAAM,UAAU,UAAU,OAAO,WAAW,UAAU,WAAW;AACjE,oBAAM,IAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,EAAE;AAAA,YAC9C;AACA,gBAAI,MAAM,SAAS;AACjB,oBAAM,IAAI,MAAM,sDAAsD;AAAA,YACxE;AACA,kBAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,MAEA,MAAM,IAAO,UAAkB,QAA0C;AACvE,cAAM,WAAW,MAAM,KAAK,cAAc,IAAO,UAAU,EAAE,OAAO,CAAC;AACrE,eAAO,SAAS;AAAA,MAClB;AAAA,MAEA,MAAM,KAAQ,UAAkB,MAAwB;AACtD,cAAM,WAAW,MAAM,KAAK,cAAc,KAAQ,UAAU,IAAI;AAChE,eAAO,SAAS;AAAA,MAClB;AAAA,MAEA,MAAM,IAAO,UAAkB,MAAwB;AACrD,cAAM,WAAW,MAAM,KAAK,cAAc,IAAO,UAAU,IAAI;AAC/D,eAAO,SAAS;AAAA,MAClB;AAAA,MAEA,MAAM,OAAU,UAA8B;AAC5C,cAAM,WAAW,MAAM,KAAK,cAAc,OAAU,QAAQ;AAC5D,eAAO,SAAS;AAAA,MAClB;AAAA,MAEA,OAAO,SACL,UACA,SAA8B,CAAC,GAC/B,QAAgB,KACsB;AACtC,YAAI,OAA2B;AAE/B,WAAG;AACD,gBAAM,cAAmC,EAAE,GAAG,QAAQ,MAAM;AAC5D,cAAI,KAAM,aAAY,OAAO;AAC7B,gBAAM,WAAW,MAAM,KAAK,IAAkC,UAAU,WAAW;AACnF,gBAAM,SAAS;AACf,iBAAO,SAAS;AAAA,QAClB,SAAS;AAAA,MACX;AAAA,IACF;AAEO,IAAM,eAAe,CAAC,eAA8B,YAAqC;AAC9F,aAAO,IAAI,eAAe,eAAe,OAAO;AAAA,IAClD;AAAA;AAAA;;;AC1FA,IAGa;AAHb;AAAA;AAAA;AAGO,IAAM,kBAAN,MAAsB;AAAA,MAC3B,YAAoB,QAAwB;AAAxB;AAAA,MAAyB;AAAA,MAE7C,MAAM,aAAmC;AAEvC,eAAO,KAAK,OAAO,IAAiB,OAAO;AAAA,MAC7C;AAAA,IACF;AAAA;AAAA;;;ACVA,IAGa;AAHb;AAAA;AAAA;AAGO,IAAM,oBAAN,MAAwB;AAAA,MAC7B,YAAoB,QAAwB;AAAxB;AAAA,MAAyB;AAAA,MAE7C,MAAM,OAAyB;AAE7B,cAAM,MAAM,MAAM,KAAK,OAAO,IAAa,cAAc;AACzD,YAAI,MAAM,QAAQ,GAAG,EAAG,QAAO;AAC/B,YAAI,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAS,IAAY,IAAI,EAAG,QAAQ,IAAY;AAE5F,YAAI,OAAO,OAAO,QAAQ,SAAU,QAAO,OAAO,OAAO,GAA4B;AACrF,eAAO,CAAC;AAAA,MACV;AAAA,MAEA,MAAM,IAAI,SAAiC;AAEzC,eAAO,KAAK,OAAO,IAAW,WAAW,OAAO,EAAE;AAAA,MACpD;AAAA,IACF;AAAA;AAAA;;;ACpBA,IAGa;AAHb;AAAA;AAAA;AAGO,IAAM,kBAAN,MAAsB;AAAA,MAC3B,YAAoB,QAAwB;AAAxB;AAAA,MAAyB;AAAA;AAAA,MAG7C,MAAM,YAAY,SAAgD;AAChE,eAAO,KAAK,OAAO,IAA0B,UAAU,OAAO,OAAO;AAAA,MACvE;AAAA;AAAA,MAGA,MAAM,gBAAgB,SAAyC;AAC7D,cAAM,WAAW,MAAM,KAAK,YAAY,OAAO;AAC/C,eAAO,OAAO,OAAO,SAAS,IAAI;AAAA,MACpC;AAAA,MAEA,MAAM,IAAI,SAAiB,OAAqC;AAC9D,eAAO,KAAK,OAAO,IAAiB,UAAU,OAAO,SAAS,KAAK,EAAE;AAAA,MACvE;AAAA,MAEA,MAAM,OAAO,SAAiB,KAAiD;AAC7E,eAAO,KAAK,OAAO,KAAkB,UAAU,OAAO,SAAS,GAAG;AAAA,MACpE;AAAA,MAEA,MAAM,OAAO,SAAiB,OAAe,SAAqD;AAChG,eAAO,KAAK,OAAO,IAAiB,UAAU,OAAO,SAAS,KAAK,IAAI,OAAO;AAAA,MAChF;AAAA,MAEA,MAAM,OAAO,SAAiB,OAA8B;AAC1D,eAAO,KAAK,OAAO,OAAa,UAAU,OAAO,SAAS,KAAK,EAAE;AAAA,MACnE;AAAA,IACF;AAAA;AAAA;;;AChCA,IAGa;AAHb;AAAA;AAAA;AAGO,IAAM,qBAAN,MAAyB;AAAA,MAC9B,YAAoB,QAAwB;AAAxB;AAAA,MAAyB;AAAA;AAAA,MAG7C,MAAM,YAAY,SAA0D;AAC1E,eAAO,KAAK,OAAO,IAAoC,UAAU,OAAO,UAAU;AAAA,MACpF;AAAA;AAAA,MAGA,MAAM,gBACJ,SACA,MAC2B;AAC3B,cAAM,MAAM,MAAM,KAAK,YAAY,OAAO;AAC1C,YAAI,UAAU,OAAO,OAAO,GAAG;AAE/B,YAAI,MAAM,OAAO;AACf,gBAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,oBAAU,QAAQ,OAAO,OAAK,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK,MAAM;AAAA,QACnF;AAEA,YAAI,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG;AACxC,oBAAU,QAAQ,OAAO,OAAK,KAAK,MAAO,SAAS,EAAE,UAAU,CAAC;AAAA,QAClE;AAEA,eAAO,QAAQ;AAAA,UAAK,CAAC,GAAG,MACtB,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ;AAAA,QACtF;AAAA,MACF;AAAA;AAAA,MAGA,MAAM,YAAY,SAQd;AACF,cAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI;AAC3D,cAAM,CAAC,SAAS,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,UAChD,KAAK,gBAAgB,SAAS,EAAE,MAAM,CAAC;AAAA,UACvC,KAAK,OAAO,IAA0B,UAAU,OAAO,OAAO;AAAA,QAChE,CAAC;AAED,cAAMC,QAAO,aAAa;AAE1B,eAAO,QACJ,OAAO,OAAK,EAAE,eAAe,kBAAkB,EAC/C,IAAI,OAAK;AACR,gBAAM,QAAQ,EAAE,MAAM;AACtB,gBAAM,MAA+B,QAAQA,MAAK,KAAK,IAAI;AAC3D,iBAAO;AAAA,YACL,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,GAAG,EAAE;AAAA,YACnE,YAAY,EAAE;AAAA,YACd,SAAS,EAAE,MAAM,SAAS,QAAQ;AAAA,YAClC,UAAU,EAAE,MAAM,KAAK,SAAS;AAAA,YAChC,QAAQ,EAAE,MAAM,QAAQ,QAAQ;AAAA,YAChC,KAAK,KAAK,OAAO;AAAA,YACjB,SAAS,KAAK,UAAU,WAAW;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACL;AAAA,IACF;AAAA;AAAA;;;ACnEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMa;AANb;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAiBA;AACA;AACA;AACA;AAlBO,IAAM,mBAAN,MAAuB;AAAA,MAM5B,YAAY,eAA8B;AACxC,cAAM,SAAS,aAAa,eAAe,0BAA0B;AACrE,aAAK,OAAO,IAAI,gBAAgB,MAAM;AACtC,aAAK,SAAS,IAAI,kBAAkB,MAAM;AAC1C,aAAK,OAAO,IAAI,gBAAgB,MAAM;AACtC,aAAK,UAAU,IAAI,mBAAmB,MAAM;AAAA,MAC9C;AAAA,IACF;AAAA;AAAA;;;AChBA;AADA,SAAS,SAAS,4BAA4B;;;ACF9C,SAAS,gBAAgB;;;ACAzB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAUR,IAAM,gBAAN,MAAoB;AAAA,EAIzB,cAAc;AACZ,SAAK,YAAY,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ;AACjD,SAAK,aAAa,KAAK,KAAK,KAAK,WAAW,aAAa;AAAA,EAC3D;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,CAAC,GAAG,WAAW,KAAK,SAAS,GAAG;AAClC,SAAG,UAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,YAAyB;AACvB,QAAI;AACF,UAAI,GAAG,WAAW,KAAK,UAAU,GAAG;AAClC,cAAM,UAAU,GAAG,aAAa,KAAK,YAAY,OAAO;AACxD,eAAO,KAAK,MAAM,OAAO;AAAA,MAC3B;AAAA,IACF,SAAS,OAAO;AAAA,IAEhB;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,UAAUC,SAA2B;AACnC,SAAK,gBAAgB;AACrB,OAAG,cAAc,KAAK,YAAY,KAAK,UAAUA,SAAQ,MAAM,CAAC,CAAC;AAAA,EACnE;AAAA,EAEA,WAA+B;AAC7B,WAAO,KAAK,UAAU,EAAE;AAAA,EAC1B;AAAA,EAEA,oBAA4F;AAC1F,UAAM,MAAM,KAAK,UAAU;AAC3B,WAAO,EAAE,MAAM,IAAI,KAAK,YAAY,OAAO,IAAI,KAAK,YAAY;AAAA,EAClE;AAAA,EAEA,kBAAkB,OAAmF;AACnG,UAAM,MAAM,KAAK,UAAU;AAC3B,QAAI,MAAM,IAAI,OAAO,CAAC;AACtB,QAAI,IAAI,aAAa,MAAM;AAC3B,QAAI,IAAI,cAAc,MAAM;AAC5B,SAAK,UAAU,GAAG;AAAA,EACpB;AAAA,EAEA,SAAS,OAAqB;AAC5B,UAAMA,UAAS,KAAK,UAAU;AAC9B,IAAAA,QAAO,WAAW;AAClB,SAAK,UAAUA,OAAM;AAAA,EACvB;AAAA,EAEA,aAAmB;AACjB,UAAMA,UAAS,KAAK,UAAU;AAC9B,WAAOA,QAAO;AACd,SAAK,UAAUA,OAAM;AAAA,EACvB;AACF;;;ACxEA,OAAO,YAAY;AAEnB,IAAM,eAAe;AACrB,IAAM,eAAe;AAEd,IAAM,kBAAN,MAAsB;AAAA,EAC3B,MAAM,WAAmC;AACvC,QAAI;AACF,aAAO,MAAM,OAAO,YAAY,cAAc,YAAY;AAAA,IAC5D,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,OAA8B;AAC3C,QAAI;AACF,YAAM,OAAO,YAAY,cAAc,cAAc,KAAK;AAAA,IAC5D,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAM,cAAgC;AACpC,QAAI;AACF,aAAO,MAAM,OAAO,eAAe,cAAc,YAAY;AAAA,IAC/D,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC7BA,OAAOC,aAAY;AACnB,OAAO,WAAW;AAElB,IAAMC,gBAAe;AACrB,IAAM,yBAAyB;AAC/B,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAC3B,IAAM,wBAAwB;AAE9B,IAAM,aAAa;AAuBZ,IAAM,sBAAN,MAA0B;AAAA;AAAA,EAG/B,MAAM,YACJ,oBACA,WACA,WACA,cACe;AACf,UAAMD,QAAO,YAAYC,eAAc,wBAAwB,kBAAkB;AACjF,UAAMD,QAAO,YAAYC,eAAc,oBAAoB,SAAS;AACpE,QAAI,WAAW;AACb,YAAMD,QAAO,YAAYC,eAAc,oBAAoB,SAAS;AAAA,IACtE;AACA,QAAI,gBAAgB,OAAO,KAAK,YAAY,EAAE,SAAS,GAAG;AACxD,YAAMD,QAAO,YAAYC,eAAc,uBAAuB,KAAK,UAAU,YAAY,CAAC;AAAA,IAC5F;AAAA,EACF;AAAA,EAEA,MAAM,mBAA2C;AAC/C,WAAOD,QAAO,YAAYC,eAAc,sBAAsB;AAAA,EAChE;AAAA,EAEA,MAAM,eAAuC;AAC3C,WAAOD,QAAO,YAAYC,eAAc,kBAAkB;AAAA,EAC5D;AAAA,EAEA,MAAM,eAAuC;AAC3C,WAAOD,QAAO,YAAYC,eAAc,kBAAkB;AAAA,EAC5D;AAAA,EAEA,MAAM,kBAAmD;AACvD,UAAM,MAAM,MAAMD,QAAO,YAAYC,eAAc,qBAAqB;AACxE,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,YAAM,MAA8B,CAAC;AACrC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,YAAI,OAAO,MAAM,YAAY,EAAE,SAAS,EAAG,KAAI,CAAC,IAAI;AAAA,MACtD;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,eAA8B;AAClC,UAAMD,QAAO,eAAeC,eAAc,sBAAsB;AAChE,UAAMD,QAAO,eAAeC,eAAc,kBAAkB;AAC5D,UAAMD,QAAO,eAAeC,eAAc,kBAAkB;AAC5D,UAAMD,QAAO,eAAeC,eAAc,qBAAqB;AAAA,EACjE;AAAA,EAEA,MAAM,aAA+B;AACnC,UAAM,SAAS,MAAM,KAAK,iBAAiB;AAC3C,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,WAAO,CAAC,EAAE,UAAU;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAiC;AACrC,UAAM,gBAAgB,MAAM,KAAK,iBAAiB;AAClD,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,UAAM,eAAe,MAAM,KAAK,gBAAgB;AAEhD,QAAI,CAAC,iBAAiB,CAAC,WAAW;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAEA,WAAO,KAAK,WAAW,eAAe,WAAW,WAAW,YAAY;AAAA,EAC1E;AAAA,EAEA,MAAM,2BACJ,oBACA,WACA,WACA,cACiB;AACjB,WAAO,KAAK,WAAW,oBAAoB,WAAW,WAAW,YAAY;AAAA,EAC/E;AAAA,EAEQ,WACN,oBACA,WACA,WACA,eAAuC,CAAC,GACvB;AACjB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEtC,YAAMC,QAAO,uBAAuB,SAAS;AAE7C,YAAM,MAAM,mBAAmB,WAAW,YAAY,IAClD,mBAAmB,MAAM,aAAa,MAAM,IAC5C;AAEJ,YAAM,MAAM,aAAa,UAAU,KAAK,IAAI,UAAU,KAAK,IAAI;AAC/D,YAAM,cAAc,CAAC,aAAa,GAAG,IAAI,gBAAgB,GAAG,EAAE;AAC9D,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACxD,YAAI,CAAC,SAAS,SAAS,eAAe,SAAS,eAAgB;AAC/D,YAAI,CAAC,oBAAoB,KAAK,IAAI,EAAG;AACrC,oBAAY,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE;AAAA,MACrC;AACA,YAAM,eAAe,YAAY,KAAK,IAAI;AAE1C,YAAM,UAAU;AAAA,QACd,UAAU;AAAA,QACV,MAAAA;AAAA,QACA,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB,kBAAkB;AAAA,UAClB,UAAU;AAAA,UACV,cAAc;AAAA,UACd,UAAU;AAAA,UACV,WAAW;AAAA,UACX,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA,YAAM,MAAM,MAAM,QAAQ,SAAS,CAAC,QAAQ;AAC1C,YAAI,OAAO;AACX,YAAI,GAAG,QAAQ,CAAC,UAAkB;AAAE,kBAAQ,MAAM,SAAS;AAAA,QAAG,CAAC;AACvE,YAAI,GAAG,OAAO,MAAM;AACV,gBAAM,YAAY;AAClB,gBAAI,IAAI,eAAe,OAAO,IAAI,eAAe,KAAK;AACpD,kBAAI;AACF,sBAAM,OAAO,KAAK,MAAM,IAAI;AAE1B,sBAAM,QAAQ,KAAK,OAAO,KAAK,SAAS,KAAK,QAAQ;AACrD,oBAAI,CAAC,OAAO;AACV,yBAAO,IAAI,MAAM,8BAA8B,KAAK,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,gBAC1E,OAAO;AAGL,wBAAM,KAAK,4BAA4B,IAAI,QAAQ,YAAY,GAAG,WAAW,KAAK,KAAK,YAAY;AACnG,0BAAQ,KAAe;AAAA,gBACzB;AAAA,cACJ,QAAQ;AACN,uBAAO,IAAI,MAAM,mCAAmC,KAAK,UAAU,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,cAC/E;AAAA,YACF,WAAW,IAAI,eAAe,OAAO,IAAI,eAAe,KAAK;AAC3D,qBAAO,IAAI;AAAA,gBACT,0CAA0C,IAAI,UAAU;AAAA;AAAA;AAAA;AAAA,cAI1D,CAAC;AAAA,YACH,OAAO;AACL,qBAAO,IAAI;AAAA,gBACT,oCAAoC,IAAI,UAAU;AAAA,EAAK,KAAK,UAAU,GAAG,GAAG,CAAC;AAAA,cAC/E,CAAC;AAAA,YACH;AAAA,UACA,GAAG;AAAA,QACL,CAAC;AAAA,MACH,CAAC;AAED,UAAI;AAAA,QAAG;AAAA,QAAS,CAAC,QACf,OAAO,IAAI,MAAM,mCAAmC,IAAI,OAAO,EAAE,CAAC;AAAA,MACpE;AACA,UAAI,IAAI;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,4BACZ,WACA,WACA,sBACA,WACA,eAAuC,CAAC,GACzB;AACf,QAAI,CAAC,UAAW;AAChB,UAAM,UAAU,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AACjE,QAAI,gBAAwB;AAC5B,QAAI,aAAa;AACjB,UAAM,gBAAwC,EAAE,GAAG,aAAa;AAEhE,eAAW,UAAU,SAAS;AAC5B,YAAM,YAAY,OAAO,MAAM,KAAK,CAAC,EAAE,CAAC,KAAK;AAC7C,YAAM,MAAM,UAAU,QAAQ,GAAG;AACjC,UAAI,OAAO,EAAG;AACd,YAAM,OAAO,UAAU,MAAM,GAAG,GAAG;AACnC,YAAM,QAAQ,UAAU,MAAM,MAAM,CAAC;AACrC,UAAI,CAAC,MAAO;AAEZ,UAAI,SAAS,aAAa;AACxB,wBAAgB;AAAA,MAClB,WAAW,SAAS,gBAAgB;AAClC,qBAAa;AAAA,MACf,WAAW,oBAAoB,KAAK,IAAI,GAAG;AACzC,sBAAc,IAAI,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,eAAe,WAAW,YAAY,aAAa;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,iBAAiB,YAAmC;AACzD,QAAI;AACF,YAAM,MAAM,WAAW,WAAW,YAAY,IAC1C,WAAW,MAAM,aAAa,MAAM,IACpC;AAEJ,YAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,UAAI,MAAM,SAAS,EAAG,QAAO;AAE7B,YAAM,UAAU,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,OAAO,CAAC;AAC/E,YAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,UAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,OAAO,EAAG,QAAO;AAAA,IACjE,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACF;;;AH7PO,IAAM,eAAN,MAAmB;AAAA,EAKxB,cAAc;AACZ,SAAK,gBAAgB,IAAI,cAAc;AACvC,SAAK,kBAAkB,IAAI,gBAAgB;AAC3C,SAAK,eAAe,IAAI,oBAAoB;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,iBAAiB,UAAwB,CAAC,GAA2B;AAEzE,QAAI,QAAQ,OAAO;AACjB,aAAO,QAAQ;AAAA,IACjB;AAGA,UAAM,WAAW,QAAQ,IAAI;AAC7B,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAGA,QAAI,MAAM,KAAK,aAAa,WAAW,GAAG;AACxC,aAAO,MAAM,KAAK,aAAa,cAAc;AAAA,IAC/C;AAGA,UAAM,cAAc,KAAK,cAAc,SAAS;AAChD,QAAI,YAAa,QAAO;AAExB,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,SAAS;AAC1D,QAAI,cAAe,QAAO;AAG1B,QAAI,QAAQ,cAAc,OAAO;AAC/B,YAAM,gBAAgB,MAAM,SAAS;AAAA,QACnC,SAAS;AAAA,QACT,MAAM;AAAA,MACR,CAAC;AAED,UAAI,eAAe;AACjB,cAAM,aAAa,MAAM,KAAK,mBAAmB;AACjD,YAAI,eAAe,QAAQ;AACzB,gBAAM,KAAK,UAAU,eAAe,UAAU;AAAA,QAChD;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,IAKF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,UAAwB,CAAC,GAAoB;AAC1D,QAAI,QAAQ,MAAO,QAAO,QAAQ;AAClC,UAAM,WAAW,QAAQ,IAAI;AAC7B,QAAI,SAAU,QAAO;AACrB,UAAM,cAAc,KAAK,cAAc,SAAS;AAChD,QAAI,YAAa,QAAO;AACxB,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,SAAS;AAC1D,QAAI,cAAe,QAAO;AAC1B,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AAAA,EAEA,MAAc,qBAA8D;AAC1E,UAAM,EAAE,OAAO,IAAI,MAAM,OAAO,mBAAmB;AACnD,WAAO,MAAM,OAAO;AAAA,MAClB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,8CAA8C,OAAO,SAAkB;AAAA,QAC/E,EAAE,MAAM,mCAAmC,OAAO,WAAoB;AAAA,QACtE,EAAE,MAAM,iCAAiC,OAAO,OAAgB;AAAA,MAClE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UAAU,OAAe,UAAgD;AAC7E,QAAI,aAAa,UAAU;AACzB,WAAK,cAAc,SAAS,KAAK;AAAA,IACnC,OAAO;AACL,YAAM,KAAK,gBAAgB,SAAS,KAAK;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,UAAyD;AACxE,QAAI,CAAC,YAAY,aAAa,SAAS,aAAa,UAAU;AAC5D,WAAK,cAAc,WAAW;AAAA,IAChC;AACA,QAAI,CAAC,YAAY,aAAa,SAAS,aAAa,YAAY;AAC9D,YAAM,KAAK,gBAAgB,YAAY;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAM,mBAKH;AACD,WAAO;AAAA,MACL,KAAK,CAAC,CAAC,QAAQ,IAAI;AAAA,MACnB,QAAQ,CAAC,CAAC,KAAK,cAAc,SAAS;AAAA,MACtC,UAAU,CAAC,CAAE,MAAM,KAAK,gBAAgB,SAAS;AAAA,MACjD,cAAc,MAAM,KAAK,aAAa,WAAW;AAAA,IACnD;AAAA,EACF;AACF;;;AIlIA,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,aAAa;AACtB,OAAO,SAAS;AAGhB,IAAM,WAAW;AACjB,IAAM,oBAAoB,KAAK,OAAO,GAAG,mBAAmB;AAC5D,IAAM,gBAAgB;AACtB,IAAM,oBAAoB,CAAC,qBAAqB,eAAe,yBAAyB;AACxF,IAAM,wBAAwB,oBAAI,IAAI,CAAC,aAAa,gBAAgB,YAAY,WAAW,SAAS,CAAC;AACrG,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,mBAAmB;AACzB,IAAM,mCAAmC;AAAA;AAAA;AAAA;AA8BzC,eAAsB,iBAAgC;AACpD,UAAQ,IAAI,oDAA+C;AAG3D,MAAI,OAAO,MAAM,cAAc,EAAE,MAAM,MAAM,IAAI;AAEjD,MAAI,CAAC,MAAM;AACT,YAAQ,IAAI,oEAA+D;AAC3E,UAAM,0BAA0B;AAEhC,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAI,CAAC;AAC1C,WAAO,MAAM,cAAc,EAAE,MAAM,MAAM,IAAI;AAAA,EAC/C;AAEA,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR;AAAA;AAAA,6FAE8F,QAAQ,oBAAoB,iBAAiB,IAAI,aAAa;AAAA;AAAA;AAAA,IAG9J;AAAA,EACF;AAGA,MAAI,WAAW,iBAAiB,IAAI;AACpC,MAAI,CAAC,UAAU;AACb,YAAQ,IAAI,aAAa,aAAa,yBAAoB;AAC1D,UAAM,2BAA2B;AAAA,EACnC;AAEA,UAAQ,IAAI,sDAAiD;AAC7D,aAAW,MAAM,gBAAgB,mBAAmB;AACpD,MAAI,CAAC,YAAY,CAAC,SAAS,sBAAsB;AAC/C,UAAM,IAAI;AAAA,MACR;AAAA,cACe,aAAa;AAAA,IAC9B;AAAA,EACF;AAEA,UAAQ,IAAI,yBAAyB,SAAS,KAAK,EAAE;AACrD,QAAM,MAAM,IAAI,oBAAoB;AACpC,UAAQ,IAAI,+DAA0D;AAGtE,QAAM,aAAa,MAAM,+BAA+B,KAAK,qBAAqB;AAClF,MAAI,CAAC,WAAW,eAAe;AAC7B,UAAM,UAAU;AAAA,MACd,iBAAiB,WAAW,KAAK,OAAO,QAAQ;AAAA,MAChD,WAAW,uBAAuB,sBAAsB,WAAW,oBAAoB,KAAK;AAAA,MAC5F,WAAW,YAAY,oBAAoB,WAAW,SAAS,KAAK;AAAA,IACtE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC3B,UAAM,IAAI;AAAA,MACR,6HAEA;AAAA,IACF;AAAA,EACF;AACA,QAAM,gBAAgB,WAAW;AACjC,QAAM,YAAY,WAAW;AAC7B,QAAM,YAAY,WAAW;AAC7B,QAAM,eAAe,WAAW,gBAAgB,CAAC;AAEjD,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,UAAQ,IAAI,iBAAiB,SAAS,EAAE;AAExC,QAAM,IAAI,YAAY,eAAe,WAAW,aAAa,QAAW,YAAY;AACpF,UAAQ,IAAI,4BAA4B;AAGxC,UAAQ,OAAO,MAAM,+BAA0B;AAC/C,QAAM,IAAI,cAAc;AACxB,UAAQ,IAAI,QAAG;AACf,UAAQ,IAAI,yCAAoC;AAChD,UAAQ,IAAI,kDAAkD;AAC9D,UAAQ,IAAI,sEAAsE;AACpF;AAEA,eAAsB,kBAAiC;AACrD,UAAQ,IAAI,qDAAgD;AAC5D,QAAM,OAAO,MAAM,cAAc,EAAE,MAAM,MAAM,IAAI;AAEnD,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR;AAAA;AAAA,6FAE8F,QAAQ,oBAAoB,iBAAiB,IAAI,aAAa;AAAA,IAC9J;AAAA,EACF;AAEA,QAAM,WAAW,iBAAiB,IAAI;AACtC,MAAI,CAAC,UAAU,sBAAsB;AACnC,UAAM,IAAI,MAAM,kFAAkF;AAAA,EACpG;AAEA,UAAQ,IAAI,gBAAgB,SAAS,SAAS,YAAY,EAAE;AAC5D,UAAQ,IAAI,UAAU,SAAS,OAAO,WAAW,EAAE;AAEnD,QAAM,WAAW,MAAM,wBAAwB,SAAS,sBAAsB,SAAS,GAAG;AAC1F,MAAI,CAAC,UAAU,eAAe;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,QAAM,YACJ,oBAAoB,iBAAiB,SAAS,aAAa,KAC3D,SAAS,kBACT;AACF,MAAI,CAAC,aAAa,CAAC,UAAU,WAAW,OAAO,GAAG;AAChD,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AAEA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,SAAS,YAAY,iBAAiB;AAAA,IACtC,GAAG,OAAO,KAAK,SAAS,YAAY;AAAA,EACtC,EAAE,OAAO,OAAO;AAChB,UAAQ,IAAI,sBAAsB,eAAe,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE;AAEpE,QAAM,MAAM,IAAI,oBAAoB;AACpC,UAAQ,OAAO,MAAM,qDAAgD;AACrE,QAAM,QAAQ,MAAM,IAAI;AAAA,IACtB,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACA,UAAQ,IAAI,QAAG;AACf,UAAQ,IAAI,iBAAiB,SAAS,EAAE;AACxC,UAAQ,IAAI,4BAA4B,MAAM,UAAU,GAAG,EAAE,CAAC,QAAG;AACnE;AAEA,eAAe,gBAAsC;AACnD,QAAM,WAAW,MAAM,MAAM,oBAAoB,QAAQ,OAAO;AAChE,MAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,gBAAgB,SAAS,MAAM,EAAE;AACnE,QAAM,OAAgB,MAAM,SAAS,KAAK;AAC1C,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,OAAM,IAAI,MAAM,+BAA+B;AACzE,SAAO;AACT;AAEA,eAAe,4BAA2C;AAExD,YAAU,mBAAmB,EAAE,WAAW,KAAK,CAAC;AAChD,QAAM,aAAa;AACnB,QAAM,YAAY;AAAA,IAChB,2BAA2B,QAAQ;AAAA,IACnC,mBAAmB,iBAAiB;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,EAAE,UAAU,MAAM,OAAO,SAAS,CAAC,EAAE,MAAM;AAChD;AAEA,eAAe,6BAA4C;AAEzD,QAAM,0BAA0B;AAClC;AAEA,eAAe,gBAAgB,WAAmD;AAChF,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,OAAO,MAAM,cAAc,EAAE,MAAM,MAAM,IAAI;AACnD,UAAM,MAAM,OAAO,iBAAiB,IAAI,IAAI;AAC5C,QAAI,KAAK,qBAAsB,QAAO;AACtC,UAAM,MAAM,gBAAgB;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,eAAe,+BACb,KACA,WACkC;AAClC,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,cAAc;AAElB,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,OAAO,MAAM,cAAc,EAAE,MAAM,MAAM,IAAI;AACnD,UAAM,YAAY,OAAO,cAAc,IAAI,IAAI,CAAC;AAEhD,eAAW,OAAO,WAAW;AAC3B,UAAI,CAAC,IAAI,qBAAsB;AAC/B,gBAAU;AAEV,UAAI;AACF,cAAM,WAAW,MAAM,wBAAwB,IAAI,sBAAsB,IAAI,GAAG;AAChF,+BAAuB,cAAc,QAAQ;AAE7C,YAAI,CAAC,UAAU,iBAAiB,SAAS,cAAc,MAAM,GAAG,EAAE,WAAW,GAAG;AAC9E;AAAA,QACF;AAEA,cAAM,YACJ,oBAAoB,iBAAiB,SAAS,aAAa,KAC3D,SAAS,kBACT;AAEF,YAAI,CAAC,aAAa,CAAC,UAAU,WAAW,OAAO,GAAG;AAChD;AAAA,QACF;AAEA,cAAM,aAAa,MAAM,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AACA,YAAI,cAAc,WAAW,MAAM,GAAG,EAAE,WAAW,GAAG;AACpD,iBAAO;AAAA,YACL,eAAe,SAAS;AAAA,YACxB;AAAA,YACA,WAAW,SAAS;AAAA,YACpB,cAAc,SAAS;AAAA,YACvB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,oBAAY,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,CAAC,eAAe,UAAU,SAAS,GAAG;AACxC,cAAQ,IAAI,+EAA0E;AACtF,oBAAc;AAAA,IAChB;AACA,UAAM,MAAM,gBAAgB;AAAA,EAC9B;AAEA,SAAO,EAAE,eAAe,MAAM,KAAK,SAAS,sBAAsB,UAAU;AAC9E;AAEA,SAAS,cAAc,KAAyB;AAC9C,MAAI,CAAC,IAAI,OAAO,IAAI,SAAS,OAAQ,QAAO;AAC5C,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,IAAI,GAAG;AAC9B,QAAI,CAAC,OAAO,SAAS,SAAS,UAAU,EAAG,QAAO;AAClD,WAAO,OAAO,aAAa,OAAO,OAAO,SAAS,SAAS;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,KAAyB;AAC3C,MAAI,CAAC,IAAI,OAAO,IAAI,SAAS,OAAQ,QAAO;AAC5C,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,IAAI,GAAG;AAC9B,WAAO,OAAO,SAAS,SAAS,UAAU;AAAA,EAC5C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,MAAgC;AACrD,QAAM,YAAY,KAAK,OAAO,UAAU;AACxC,QAAM,UAAU,UAAU,OAAO,aAAa;AAC9C,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,iBAAiB,MAA0C;AAClE,SAAO,cAAc,IAAI,EAAE,CAAC;AAC9B;AAEA,eAAe,MAAM,IAA2B;AAC9C,QAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACtD;AAEA,eAAe,wBAAwB,OAAe,SAAmD;AACvG,QAAM,UAAU,MAAM,gBAAgB,OAAO,OAAO;AACpD,QAAM,gBAAgB,QAAQ,aAAa;AAC3C,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,oBAAoB,MAAM,cAAc,OAAO,gCAAgC,EAAE,MAAM,MAAM,EAAE;AACrG,QAAM,iBACJ,OAAO,sBAAsB,YAAY,kBAAkB,WAAW,OAAO,IACzE,oBACA;AAEN,SAAO;AAAA,IACL;AAAA,IACA,WAAW,QAAQ,gBAAgB;AAAA,IACnC,cAAc,OAAO;AAAA,MACnB,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,MAAM,SAAS,eAAe,SAAS,cAAc;AAAA,IAC5F;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,gBAAgB,OAAe,SAAmD;AAC/F,MAAI;AACF,UAAM,gBAAgB,OAAO,gBAAgB;AAAA,EAC/C,QAAQ;AAAA,EAER;AAEA,QAAM,OAAO,UAAU,MAAM,KAAK,oBAAI,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAAC,IAAI;AAC9E,QAAM,SAAS,MAAM,gBAAgB,OAAO,sBAAsB,EAAE,KAAK,CAAC;AAC1E,QAAM,UAAW,QAA2C;AAC5D,QAAM,MAA8B,CAAC;AAErC,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AAEpC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,UAAM,IAAI;AACV,UAAM,OAAO,EAAE;AACf,UAAM,QAAQ,EAAE;AAChB,UAAM,SAAS,EAAE;AAEjB,QAAI,OAAO,SAAS,YAAY,OAAO,UAAU,SAAU;AAC3D,QAAI,OAAO,WAAW,YAAY,CAAC,OAAO,SAAS,UAAU,EAAG;AAChE,QAAI,sBAAsB,IAAI,IAAI,GAAG;AACnC,UAAI,IAAI,IAAI;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,cAAc,OAAe,YAAsC;AAChF,QAAM,SAAS,MAAM,gBAAgB,OAAO,oBAAoB;AAAA,IAC9D;AAAA,IACA,cAAc;AAAA,IACd,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,aAAc,UAAU,CAAC;AAC/B,QAAM,mBAAmB,WAAW;AACpC,MAAI,kBAAkB;AACpB,UAAM,OAAO,OAAO,iBAAiB,SAAS,WAAW,iBAAiB,OAAO;AACjF,UAAM,IAAI,MAAM,IAAI;AAAA,EACtB;AAEA,QAAM,gBAAgB,WAAW;AACjC,MAAI,CAAC,iBAAiB,CAAC,OAAO,UAAU,eAAe,KAAK,eAAe,OAAO,EAAG,QAAO;AAC5F,SAAO,cAAc;AACvB;AAEA,SAAS,gBACP,OACA,QACA,SAAkC,CAAC,GACjB;AAClB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEtC,UAAM,gBAAiB,WAAmB;AAE1C,QAAI,eAAe;AACjB,2BAAqB,OAAO,eAAe,QAAQ,QAAQ,SAAS,MAAM;AAAA,IAC5E,OAAO;AAEL,uBAAiB,OAAO,QAAQ,QAAQ,SAAS,MAAM;AAAA,IACzD;AAAA,EACF,CAAC;AACH;AAEA,SAAS,qBACP,OACA,IACA,QACA,QACA,SACA,QACM;AACN,QAAM,KAAK,IAAI,GAAG,KAAK;AACvB,QAAM,KAAK;AAEX,KAAG,SAAS,MAAM;AAChB,OAAG,KAAK,KAAK,UAAU;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,CAAC;AAAA,EACJ;AAEA,KAAG,YAAY,OAAO,QAAsB;AAC1C,QAAI;AACF,YAAM,MAAM,MAAM,aAAa,IAAI,IAAI;AACvC,YAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,UAAI,IAAI,OAAO,GAAI;AACnB,UAAI,IAAI,OAAO;AACb,WAAG,MAAM;AACT,eAAO,IAAI,MAAM,IAAI,OAAO,WAAW,OAAO,MAAM,SAAS,CAAC;AAC9D;AAAA,MACF;AAEA,SAAG,MAAM;AACT,cAAQ,IAAI,MAAiB;AAAA,IAC/B,SAAS,GAAG;AACV,SAAG,MAAM;AACT,aAAO,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,IACtD;AAAA,EACF;AAEA,KAAG,UAAU,MAAM,OAAO,IAAI,MAAM,gDAAgD,CAAC;AAErF,aAAW,MAAM;AAAE,OAAG,MAAM;AAAG,WAAO,IAAI,MAAM,qCAAqC,CAAC;AAAA,EAAG,GAAG,GAAM;AACpG;AAEA,eAAe,aAAa,MAAgC;AAC1D,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,WAAW,eAAe,OAAO,SAAS,IAAI,EAAG,QAAO,KAAK,SAAS,MAAM;AACvF,MAAI,gBAAgB,YAAa,QAAO,OAAO,KAAK,IAAI,EAAE,SAAS,MAAM;AACzE,MAAI,OAAO,SAAS,eAAe,gBAAgB,KAAM,QAAO,MAAM,KAAK,KAAK;AAChF,SAAO,OAAO,IAAI;AACpB;AAEA,SAAS,iBACP,OACA,QACA,QACA,SACA,QACM;AAEN,QAAM,QAAQ,MAAM,MAAM,gCAAgC;AAC1D,MAAI,CAAC,OAAO;AAAE,WAAO,IAAI,MAAM,wBAAwB,KAAK,EAAE,CAAC;AAAG;AAAA,EAAQ;AAE1E,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAClC,QAAMC,QAAO,MAAM,CAAC,KAAK;AAEzB,QAAM,SAAS,IAAI,iBAAiB,MAAM,IAAI;AAE9C,QAAM,MAAM,OAAO,KAAK,KAAK,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,QAAQ;AACrE,MAAI,SAAS;AACb,MAAI,gBAAgB;AACpB,QAAM,QAAQ;AAEd,SAAO,GAAG,WAAW,MAAM;AACzB,WAAO;AAAA,MACL,OAAOA,KAAI;AAAA,QACF,IAAI,IAAI,IAAI;AAAA;AAAA;AAAA,qBAGC,GAAG;AAAA;AAAA;AAAA;AAAA,IAE3B;AAAA,EACF,CAAC;AAED,SAAO,GAAG,QAAQ,CAAC,SAAiB;AAClC,QAAI,CAAC,eAAe;AAClB,gBAAU,KAAK,SAAS;AACxB,UAAI,OAAO,SAAS,UAAU,GAAG;AAC/B,wBAAgB;AAEhB,cAAM,UAAU,KAAK,UAAU;AAAA,UAC7B,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,QACF,CAAC;AACD,eAAO,MAAM,cAAc,OAAO,CAAC;AAAA,MACrC;AACA;AAAA,IACF;AAGA,QAAI;AACF,YAAM,MAAM,cAAc,IAAI;AAC9B,UAAI,KAAK;AACP,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,YAAI,OAAO,OAAO,MAAO;AACzB,YAAI,OAAO,OAAO;AAChB,iBAAO,QAAQ;AACf,iBAAO,IAAI,MAAM,OAAO,OAAO,WAAW,OAAO,MAAM,SAAS,CAAC;AACjE;AAAA,QACF;AAEA,eAAO,QAAQ;AACf,gBAAQ,OAAO,MAAiB;AAAA,MAClC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF,CAAC;AAED,SAAO,GAAG,SAAS,CAAC,MAAa,OAAO,CAAC,CAAC;AAC1C,aAAW,MAAM;AAAE,WAAO,QAAQ;AAAG,WAAO,IAAI,MAAM,SAAS,CAAC;AAAA,EAAG,GAAG,GAAM;AAC9E;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO,WAAW,MAAM,MAAM;AAC7D,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,UAAU,MAAM,MAAM;AACvD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,OAAO,OAAO,KAAK,KAAgC;AACzD,WAAO,iBAAiB,KAAK,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,KAAK,QAAQ;AAAA,EACjE;AACA,SAAO,OAAO;AAChB;AAEA,SAAS,cAAc,SAAyB;AAC9C,QAAM,OAAO,OAAO,KAAK,SAAS,MAAM;AACxC,QAAM,MAAM,KAAK;AACjB,QAAM,OAAO,OAAO,KAAK;AAAA,IACvB,KAAK,OAAO,IAAI;AAAA,IAAK,KAAK,OAAO,IAAI;AAAA,IACrC,KAAK,OAAO,IAAI;AAAA,IAAK,KAAK,OAAO,IAAI;AAAA,EACvC,EAAE,IAAI,KAAK,KAAK,CAAC;AAEjB,QAAM,SAAS,MAAM,MACjB,OAAO,KAAK,CAAC,KAAM,MAAO,GAAG,CAAC,IAC9B,MAAM,QACN,OAAO,KAAK,CAAC,KAAM,KAAM,OAAO,GAAG,MAAM,GAAI,CAAC,IAC9C,OAAO,KAAK,CAAC,KAAM,KAAM,GAAG,GAAG,GAAG,GAAI,OAAO,KAAM,KAAO,OAAO,KAAM,KAAO,OAAO,IAAK,KAAM,MAAM,GAAI,CAAC;AAE/G,QAAM,SAAS,OAAO,MAAM,GAAG;AAC/B,WAAS,IAAI,GAAG,IAAI,KAAK,IAAK,QAAO,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAC9D,SAAO,OAAO,OAAO,CAAC,QAAQ,MAAM,MAAM,CAAC;AAC7C;AAEA,SAAS,cAAc,KAA4B;AACjD,MAAI,IAAI,SAAS,EAAG,QAAO;AAC3B,QAAM,MAAM,IAAI,CAAC,IAAI;AACrB,MAAI,SAAS;AACb,QAAM,aAAa,MAAM,MAAM,MAAM,QAAQ,OAAO,IAAI,aAAa,CAAC,GAAG,UAAU,GAAG,IAAI,aAAa,CAAC,KAAK;AAC7G,MAAI,eAAe,KAAM,QAAO;AAChC,SAAO,IAAI,MAAM,QAAQ,SAAU,UAAqB,EAAE,SAAS,MAAM;AAC3E;;;AL7jBA,IAAM,UAAU,IAAI,QAAQ;AAC5B,IAAM,eAAe,IAAI,aAAa;AActC,SAAS,iBAAiB,OAAe,UAA0B;AACjE,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,MAAI,CAAC,OAAO,SAAS,MAAM,KAAK,OAAO,MAAM,MAAM,KAAK,UAAU,GAAG;AACnE,UAAM,IAAI,qBAAqB,GAAG,QAAQ,8BAA8B;AAAA,EAC1E;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,iBAAiB,OAAO,QAAQ;AACzC;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,iBAAiB,OAAO,SAAS;AAC1C;AAEA,SAAS,kBAAkB,OAA6B;AACtD,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,eAAe,UAAU,eAAe,WAAW,eAAe,OAAO;AAC3E,WAAO;AAAA,EACT;AACA,QAAM,IAAI,qBAAqB,4CAA4C;AAC7E;AAEA,SAAS,gBAAgB,OAAqB;AAC5C,MAAI,CAAC,sBAAsB,KAAK,KAAK,GAAG;AACtC,UAAM,IAAI,qBAAqB,oCAAoC;AAAA,EACrE;AAEA,QAAM,CAAC,SAAS,UAAU,MAAM,IAAI,MAAM,MAAM,GAAG;AACnD,QAAM,OAAO,OAAO,OAAO;AAC3B,QAAM,QAAQ,OAAO,QAAQ;AAC7B,QAAM,MAAM,OAAO,MAAM;AACzB,QAAM,OAAO,IAAI,KAAK,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC;AAEhE,MACE,KAAK,eAAe,MAAM,QAC1B,KAAK,YAAY,MAAM,QAAQ,KAC/B,KAAK,WAAW,MAAM,KACtB;AACA,UAAM,IAAI,qBAAqB,0BAA0B,KAAK,EAAE;AAAA,EAClE;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,SAA0C;AACrE,MAAI,QAAQ,MAAM;AAChB,QAAI,QAAQ,UAAU,QAAQ,WAAW,QAAQ;AAC/C,YAAM,IAAI,MAAM,2CAA2C,QAAQ,MAAM,GAAG;AAAA,IAC9E;AACA,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,UAAU;AAC3B;AAEA,SAAS,iBAAiB,SAA4D;AACpF,MAAI,OAAO,QAAQ;AACnB,MAAI,QAAQ,MAAM;AAChB,QAAI,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,OAAO;AAClD,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,QAAQ,SAAS,QAAQ,QAAQ;AAC5C,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AAEA,QAAM,QAAQ,OAAO,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,KAAK,GAAI,IAAI,QAAQ;AACjF,QAAM,QAAQ,QAAQ,QAClB,IAAI,KAAK,KAAK;AAAA,IACd,QAAQ,MAAM,eAAe;AAAA,IAC7B,QAAQ,MAAM,YAAY;AAAA,IAC1B,QAAQ,MAAM,WAAW;AAAA,IACzB;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,EACd,CAAC,IACC;AAEJ,MAAI,SAAS,SAAS,MAAM,QAAQ,IAAI,MAAM,QAAQ,GAAG;AACvD,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,SAAO,EAAE,OAAO,MAAM;AACxB;AAEA,SAAS,kBACP,OACA,SACA,OACK;AACL,SAAO,MAAM,OAAO,UAAQ;AAC1B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,YAAY,IAAI,KAAK,GAAG,EAAE,QAAQ;AACxC,QAAI,OAAO,MAAM,SAAS,EAAG,QAAO;AACpC,QAAI,MAAM,SAAS,YAAY,MAAM,MAAM,QAAQ,EAAG,QAAO;AAC7D,QAAI,MAAM,SAAS,YAAY,MAAM,MAAM,QAAQ,EAAG,QAAO;AAC7D,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,WAAc,OAAY,OAAqB;AACtD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,MAAM,GAAG,KAAK;AAC7B;AAEA,SAAS,QAAQ,OAAwB;AACvC,QAAM,MAAM,SAAS,OAAO,KAAK,OAAO,KAAK;AAC7C,MAAI,SAAS,KAAK,GAAG,EAAG,QAAO,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC;AAC1D,SAAO;AACT;AAEA,SAAS,SAAS,SAAmB,MAAyB;AAC5D,QAAM,QAAQ,CAAC,QAAQ,KAAK,GAAG,CAAC;AAChC,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,GAAG,CAAC;AAAA,EACvC;AACA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEA,eAAe,OAAO,OAA2C;AAC/D,QAAM,WAAW,MAAM,aAAa,iBAAiB,EAAE,MAAM,CAAC;AAC9D,SAAO,IAAI,iBAAiB,QAAQ;AACtC;AAEA,QACG,KAAK,OAAO,EACZ,YAAY,oBAAoB,EAChC,QAAQ,OAAO,EACf,OAAO,uBAAuB,yCAAyC;AAI1E,QACG,QAAQ,IAAI,EACZ,YAAY,wBAAwB,EACpC,OAAO,cAAc,gBAAgB,EACrC,OAAO,OAAO,SAAS,YAAY;AAClC,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,KAAK,EAAE,KAAK;AACrD,UAAM,UAAU,MAAM,IAAI,KAAK,WAAW;AAC1C,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,IAC9C,OAAO;AACL,cAAQ,IAAI,SAAS,QAAQ,aAAa,QAAQ,aAAa,EAAE,IAAI,QAAQ,cAAc,QAAQ,YAAY,EAAE,EAAE;AACnH,cAAQ,IAAI,UAAU,QAAQ,KAAK,EAAE;AACrC,cAAQ,IAAI,OAAO,QAAQ,EAAE,EAAE;AAAA,IACjC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,IAAM,SAAS,QAAQ,QAAQ,QAAQ,EAAE,YAAY,oBAAoB;AAEzE,OACG,QAAQ,MAAM,EACd,YAAY,sBAAsB,EAClC,OAAO,yBAAyB,qCAAqC,mBAAmB,MAAM,EAC9F,OAAO,cAAc,0CAA0C,EAC/D,OAAO,kBAAkB,2CAA2C,eAAe,EACnF,OAAO,kBAAkB,wCAAwC,eAAe,EAChF,OAAO,kBAAkB,oDAAoD,eAAe,EAC5F,OAAO,eAAe,0BAA0B,gBAAgB,EAChE,OAAO,OAAO,SAAS,YAAY;AAClC,MAAI;AACF,UAAM,SAAS,oBAAoB,OAAO;AAC1C,UAAM,QAAQ,iBAAiB,OAAO;AAEtC,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,WAAW,MAAM,IAAI,OAAO,KAAK;AACvC,UAAM,aAAa,MAAM,QAAQ,QAAQ,IAAI,WAAY,SAAiB,QAAQ,CAAC;AACnF,UAAM,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AAC/G,UAAM,WAAW,WAAW,kBAAkB,QAAQ,OAAK,EAAE,WAAW,KAAK,GAAG,QAAQ,KAAK;AAE7F,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,IAC/C,WAAW,SAAS,WAAW,GAAG;AAChC,cAAQ,IAAI,kBAAkB;AAAA,IAChC,WAAW,WAAW,OAAO;AAC3B;AAAA,QACE,CAAC,MAAM,QAAQ,YAAY;AAAA,QAC3B,SAAS,IAAI,CAAC,MAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,aAAa,EAAE,CAAC;AAAA,MAClE;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,SAAS,IAAI,CAAC,OAAY;AAAA,QACtC,IAAI,EAAE;AAAA,QACN,MAAM,EAAE,QAAQ;AAAA,QAChB,SAAS,IAAI,KAAK,EAAE,SAAS,EAAE,mBAAmB;AAAA,MACpD,EAAE,CAAC;AAAA,IACL;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,KAAK,EACb,YAAY,iCAAiC,EAC7C,SAAS,cAAc,UAAU,EACjC,OAAO,cAAc,gBAAgB,EACrC,OAAO,OAAO,SAAS,SAAS,YAAY;AAC3C,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,OAAO;AAC1C,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,IAC5C,OAAO;AACL,cAAQ,IAAI,UAAU,MAAM,IAAI,EAAE;AAClC,cAAQ,IAAI,OAAO,MAAM,EAAE,EAAE;AAC7B,cAAQ,IAAI,YAAY,IAAI,KAAK,MAAM,SAAS,EAAE,eAAe,CAAC,EAAE;AACpE,UAAI,MAAM,OAAO,QAAQ;AACvB,gBAAQ,IAAI,UAAU;AACtB,cAAM,MAAM,QAAQ,OAAK,QAAQ,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,IAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE,YAAY,4BAA4B;AAE7E,KACG,QAAQ,MAAM,EACd,YAAY,sBAAsB,EAClC,SAAS,cAAc,UAAU,EACjC,OAAO,yBAAyB,qCAAqC,mBAAmB,MAAM,EAC9F,OAAO,cAAc,0CAA0C,EAC/D,OAAO,kBAAkB,yCAAyC,eAAe,EACjF,OAAO,kBAAkB,sCAAsC,eAAe,EAC9E,OAAO,kBAAkB,kDAAkD,eAAe,EAC1F,OAAO,eAAe,0BAA0B,gBAAgB,EAChE,OAAO,OAAO,SAAS,SAAS,YAAY;AAC3C,MAAI;AACF,UAAM,SAAS,oBAAoB,OAAO;AAC1C,UAAM,QAAQ,iBAAiB,OAAO;AAEtC,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,WAAW,MAAM,IAAI,KAAK,gBAAgB,OAAO;AACvD,UAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AAC7G,UAAM,WAAW,WAAW,kBAAkB,QAAQ,OAAK,EAAE,WAAW,KAAK,GAAG,QAAQ,KAAK;AAE7F,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,IAC/C,WAAW,SAAS,WAAW,GAAG;AAChC,cAAQ,IAAI,gBAAgB;AAAA,IAC9B,WAAW,WAAW,OAAO;AAC3B;AAAA,QACE,CAAC,MAAM,SAAS,OAAO,YAAY;AAAA,QACnC,SAAS,IAAI,OAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,SAAS,CAAC;AAAA,MAC7D;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,SAAS,IAAI,QAAM;AAAA,QAC/B,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,QACT,KAAK,EAAE,OAAO;AAAA,QACd,SAAS,IAAI,KAAK,EAAE,SAAS,EAAE,mBAAmB;AAAA,MACpD,EAAE,CAAC;AAAA,IACL;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,KACG,QAAQ,KAAK,EACb,YAAY,+BAA+B,EAC3C,SAAS,cAAc,UAAU,EACjC,SAAS,YAAY,QAAQ,EAC7B,OAAO,cAAc,gBAAgB,EACrC,OAAO,OAAO,SAAS,OAAO,SAAS,YAAY;AAClD,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,MAAM,MAAM,IAAI,KAAK,IAAI,SAAS,KAAK;AAC7C,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,IAC1C,OAAO;AACL,cAAQ,IAAI,gBAAgB;AAC5B,cAAQ,IAAI,eAAe,IAAI,KAAK,EAAE;AACtC,cAAQ,IAAI,eAAe,IAAI,OAAO,KAAK,EAAE;AAC7C,cAAQ,IAAI,eAAe,IAAI,UAAU,WAAW,KAAK,EAAE;AAC3D,UAAI,IAAI,QAAQ;AACd,gBAAQ,IAAI,eAAe,IAAI,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,YAAY,EAAE,EAAE;AAAA,MAChH;AACA,cAAQ,IAAI,eAAe,IAAI,KAAK,IAAI,SAAS,EAAE,eAAe,CAAC,EAAE;AAAA,IACvE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,IAAM,aAAa,QAAQ,QAAQ,YAAY,EAAE,YAAY,8BAA8B;AAE3F,WACG,QAAQ,MAAM,EACd,YAAY,0BAA0B,EACtC,SAAS,cAAc,UAAU,EACjC,OAAO,yBAAyB,qCAAqC,mBAAmB,MAAM,EAC9F,OAAO,cAAc,0CAA0C,EAC/D,OAAO,kBAAkB,sCAAsC,eAAe,EAC9E,OAAO,kBAAkB,iCAAiC,eAAe,EACzE,OAAO,kBAAkB,6CAA6C,eAAe,EACrF,OAAO,eAAe,0BAA0B,gBAAgB,EAChE,OAAO,cAAc,oBAAoB,EACzC,OAAO,mBAAmB,4DAA4D,EACtF,OAAO,OAAO,SAAS,SAAS,YAAY;AAC3C,MAAI;AACF,UAAM,SAAS,oBAAoB,OAAO;AAC1C,UAAM,QAAQ,iBAAiB,OAAO;AAEtC,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,OAA2C,CAAC;AAClD,QAAI,MAAM,MAAO,MAAK,QAAQ,MAAM;AACpC,QAAI,QAAQ,MAAO,MAAK,QAAQ,QAAQ,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAEpG,UAAM,aAAa,MAAM,IAAI,QAAQ,gBAAgB,SAAS,IAAI;AAClE,UAAM,UAAU;AAAA,MACd,kBAAkB,YAAY,OAAK,EAAE,QAAQ,EAAE,WAAW,KAAK;AAAA,MAC/D,QAAQ;AAAA,IACV;AAEA,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,IAC9C,WAAW,QAAQ,WAAW,GAAG;AAC/B,cAAQ,IAAI,sBAAsB;AAAA,IACpC,WAAW,WAAW,OAAO;AAC3B;AAAA,QACE,CAAC,QAAQ,QAAQ,WAAW,OAAO,QAAQ;AAAA,QAC3C,QAAQ,IAAI,OAAK;AAAA,UACf,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY;AAAA,UAC5C,EAAE;AAAA,UACF,EAAE,MAAM,SAAS,QAAQ;AAAA,UACzB,EAAE,MAAM,KAAK,SAAS;AAAA,UACtB,EAAE,MAAM,QAAQ,QAAQ;AAAA,QAC1B,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,QAAQ,IAAI,QAAM;AAAA,QAC9B,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,GAAG,EAAE;AAAA,QACnE,MAAM,EAAE;AAAA,QACR,SAAS,EAAE,MAAM,SAAS,QAAQ;AAAA,QAClC,MAAM,EAAE,MAAM,KAAK,SAAS,IAAI,UAAU,GAAG,EAAE;AAAA,QAC/C,QAAQ,EAAE,MAAM,QAAQ,QAAQ;AAAA,MAClC,EAAE,CAAC;AAAA,IACL;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,WACG,QAAQ,UAAU,EAClB,YAAY,uCAAuC,EACnD,SAAS,cAAc,UAAU,EACjC,OAAO,OAAO,SAAS,SAAS,YAAY;AAC3C,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK;AAC7D,UAAM,OAAO,MAAM,IAAI,QAAQ,YAAY,OAAO;AAClD,UAAM,QAAQ,CAAC,8CAA8C;AAC7D,eAAW,KAAK,MAAM;AACpB,YAAM,KAAK;AAAA,QACT,EAAE;AAAA,QACF,EAAE;AAAA,QACF,IAAI,EAAE,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,QACjC,IAAI,EAAE,SAAS,QAAQ,MAAM,IAAI,CAAC;AAAA,QAClC,EAAE;AAAA,QACF,EAAE;AAAA,MACJ,EAAE,KAAK,GAAG,CAAC;AAAA,IACb;AACA,YAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAAA,EAC9B,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,IAAM,SAAS,QAAQ,QAAQ,QAAQ,EAAE,YAAY,0BAA0B;AAE/E,OACG,QAAQ,WAAW,EACnB,YAAY,2CAA2C,EACvD,SAAS,WAAW,mBAAmB,EACvC,OAAO,kBAAkB,+CAA+C,EACxE,OAAO,OAAO,OAAO,YAAY;AAChC,MAAI;AACF,UAAM,WAAW,QAAQ,WAAW,aAAa;AACjD,UAAM,aAAa,UAAU,OAAO,QAAQ;AAC5C,UAAM,eAAe,QAAQ,WAAW,mBAAmB;AAC3D,YAAQ,IAAI,yBAAoB,YAAY,EAAE;AAAA,EAChD,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,iBAAiB,EACzB,YAAY,qEAAqE,EACjF,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,eAAe;AAAA,EACvB,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,WAAW,EACnB,YAAY,qEAAqE,EACjF,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,gBAAgB;AAAA,EACxB,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,aAAa,EACrB,YAAY,mEAAmE,EAC/E,SAAS,oBAAoB,iDAAiD,EAC9E,SAAS,gBAAgB,yEAAoE,EAC7F,YAAY,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASrB,EACA,OAAO,OAAO,eAAe,cAAc;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa;AAGzB,QAAI,oBAAoB;AACxB,QAAI,CAAC,mBAAmB;AACtB,YAAM,WAAW,oBAAoB,iBAAiB,aAAa;AACnE,UAAI,UAAU;AACZ,4BAAoB;AACpB,gBAAQ,IAAI,0BAA0B,iBAAiB,EAAE;AAAA,MAC3D,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA,QAGF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAGA,UAAM,YAAY,cAAc,WAAW,YAAY,IACnD,cAAc,MAAM,aAAa,MAAM,IACvC;AAEJ,UAAM,IAAI,YAAY,WAAW,iBAAkB;AAGnD,YAAQ,IAAI,yBAAoB;AAChC,QAAI;AACF,YAAM,QAAQ,MAAM,IAAI,cAAc;AACtC,cAAQ,IAAI,yDAAoD,MAAM,UAAU,GAAG,EAAE,CAAC,SAAI;AAC1F,cAAQ,IAAI,iDAAiD;AAAA,IAC/D,SAAS,KAAK;AACZ,cAAQ,KAAK,iDAA4C,eAAe,QAAQ,IAAI,UAAU,GAAG,EAAE;AACnG,cAAQ,KAAK,yEAAyE;AAAA,IACxF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,cAAc,EACtB,YAAY,yEAAyE,EACrF,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,MAAM,aAAa;AACzB,QAAI,CAAE,MAAM,IAAI,WAAW,GAAI;AAC7B,cAAQ,MAAM,qEAAqE;AACnF,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,OAAO,MAAM,sCAAiC;AACtD,UAAM,QAAQ,MAAM,IAAI,cAAc;AACtC,YAAQ,IAAI,WAAM,MAAM,UAAU,GAAG,EAAE,CAAC,SAAI;AAC5C,YAAQ,OAAO,MAAM,gCAA2B;AAChD,UAAM,MAAM,KAAK,MAAM,mEAA0B,iBAAiB,KAAK;AACvE,UAAM,UAAU,MAAM,IAAI,KAAK,WAAW;AAC1C,YAAQ,IAAI,QAAG;AACf,YAAQ,IAAI;AAAA,kBAAqB,QAAQ,aAAa,QAAQ,aAAa,EAAE,IAAI,QAAQ,cAAc,QAAQ,YAAY,EAAE,KAAK,QAAQ,KAAK,GAAG;AAClJ,YAAQ,IAAI,0EAA0E;AAAA,EACxF,SAAS,OAAO;AACd,YAAQ,MAAM,aAAa,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACzE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,YAAY,EACpB,YAAY,kDAAkD,EAC9D,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,UAAU,MAAM,aAAa,iBAAiB;AACpD,YAAQ,IAAI,sCAAsC;AAClD,YAAQ,IAAI,6CAA6C,QAAQ,MAAe,eAAU,gBAAW,EAAE;AACvG,YAAQ,IAAI,6CAA6C,QAAQ,eAAe,eAAU,gBAAW,EAAE;AACvG,YAAQ,IAAI,6CAA6C,QAAQ,SAAe,eAAU,gBAAW,EAAE;AACvG,YAAQ,IAAI,6CAA6C,QAAQ,WAAe,eAAU,gBAAW,EAAE;AACvG,QAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,gBAAgB,CAAC,QAAQ,UAAU,CAAC,QAAQ,UAAU;AACjF,cAAQ,IAAI,yBAAyB;AACrC,cAAQ,IAAI,0DAA0D;AACtE,cAAQ,IAAI,0DAA0D;AAAA,IACxE,WAAW,QAAQ,cAAc;AAC/B,cAAQ,IAAI,oEAA0D;AAAA,IACxE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,aAAa,EACrB,YAAY,wBAAwB,EACpC,OAAO,kBAAkB,gCAAgC,EACzD,OAAO,gBAAgB,6BAA6B,EACpD,OAAO,OAAO,YAAY;AACzB,MAAI;AACF,QAAI,WAA0C;AAC9C,QAAI,QAAQ,YAAY,CAAC,QAAQ,OAAQ,YAAW;AAAA,aAC3C,QAAQ,UAAU,CAAC,QAAQ,SAAU,YAAW;AACzD,UAAM,aAAa,WAAW,QAAQ;AACtC,UAAM,UAAU,aAAa,QAAQ,kBACjC,aAAa,aAAa,mBAC1B;AACJ,YAAQ,IAAI,6BAAwB,OAAO,EAAE;AAAA,EAC/C,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,OACG,QAAQ,eAAe,EACvB,YAAY,mCAAmC,EAC/C,OAAO,YAAY;AAClB,MAAI;AACF,UAAM,aAAa,aAAa,aAAa;AAC7C,YAAQ,IAAI,8BAAyB;AAAA,EACvC,SAAS,OAAO;AACd,YAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,QACG,QAAQ,aAAa,EACrB,YAAY,kCAAkC,EAC9C,SAAS,WAAW,sDAAsD,EAC1E,YAAY,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAYrB,EACA,OAAO,CAAC,UAAkB;AACzB,UAAQ,OAAO;AAAA,IACb,KAAK;AAEH,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAoCnB;AAEO;AAAA,IAEF,KAAK;AAEH,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAgDnB;AAEO;AAAA,IAEF,KAAK;AACH,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA2CnB;AACO;AAAA,IAEF;AACE,cAAQ,MAAM,kBAAkB,KAAK,8BAA8B;AACnE,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF,CAAC;AAEH,QAAQ,MAAM;",
|
|
6
|
+
"names": ["config", "jobs", "config", "keytar", "SERVICE_NAME", "path", "path"]
|
|
7
7
|
}
|