style: add explicit types to eliminate implicit any in index.ts

This commit is contained in:
2026-05-02 18:47:08 -04:00
parent 6b3ec32b3a
commit 8db4ed1370
3 changed files with 42 additions and 25 deletions

View File

@@ -65,6 +65,7 @@
nodejs_22 nodejs_22
firefox firefox
geckodriver geckodriver
typescript-language-server
]; ];
}; };
} }

View File

@@ -1,5 +1,6 @@
import { execFileSync } from "node:child_process"; import { execFileSync } from "node:child_process";
import { Builder, type WebDriver } from "selenium-webdriver"; import { Builder, type WebDriver } from "selenium-webdriver";
export { type WebDriver };
import firefox from "selenium-webdriver/firefox.js"; import firefox from "selenium-webdriver/firefox.js";
export interface DriverOptions { export interface DriverOptions {

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env node #!/usr/bin/env node
import { loadConfig, type GlimpseConfig } from "./config.js"; import { loadConfig, type GlimpseConfig } from "./config.js";
import { createDriver } from "./driver.js"; import { createDriver, type WebDriver } from "./driver.js";
import { searchKagi } from "./providers/kagi.js"; import { searchKagi } from "./providers/kagi.js";
import { readFileSync, writeFileSync } from "node:fs"; import { readFileSync, writeFileSync } from "node:fs";
import TurndownService from "turndown"; import TurndownService from "turndown";
@@ -11,6 +11,18 @@ const POLL_INTERVAL_MS = 200;
const startTime = Date.now(); const startTime = Date.now();
const runContext: { targetUrl?: string; currentUrl?: string } = {}; const runContext: { targetUrl?: string; currentUrl?: string } = {};
interface ReaderArticle {
title?: string;
byline?: string;
siteName?: string;
html?: string;
text?: string;
readerUrl?: string;
sourceUrl?: string;
finalUrl?: string;
markdown?: string;
}
// Parse CLI Args // Parse CLI Args
const [command, ...args] = process.argv.slice(2); const [command, ...args] = process.argv.slice(2);
const headless = !args.includes("--no-headless"); const headless = !args.includes("--no-headless");
@@ -23,7 +35,7 @@ const configPath = getOption("--config");
let appConfig: GlimpseConfig = {}; let appConfig: GlimpseConfig = {};
let timeoutMs = DEFAULT_TIMEOUT_MS; let timeoutMs = DEFAULT_TIMEOUT_MS;
function getOption(name) { function getOption(name: string) {
const prefix = `${name}=`; const prefix = `${name}=`;
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length); return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
} }
@@ -36,14 +48,14 @@ function elapsedMs() {
return Date.now() - startTime; return Date.now() - startTime;
} }
function printResult(result) { function printResult(result: unknown) {
if (result === undefined) { if (result === undefined) {
return; return;
} }
const outputValue = const outputValue =
result && typeof result === "object" && !Array.isArray(result) result && typeof result === "object" && !Array.isArray(result)
? { ...result, elapsedMs: result.elapsedMs ?? elapsedMs() } ? { ...result, elapsedMs: (result as any).elapsedMs ?? elapsedMs() }
: result; : result;
const output = const output =
typeof outputValue === "object" typeof outputValue === "object"
@@ -56,18 +68,18 @@ class CliError extends Error {
code: string; code: string;
details: Record<string, unknown>; details: Record<string, unknown>;
constructor(code, message, details = {}) { constructor(code: string, message: string, details = {}) {
super(message); super(message);
this.code = code; this.code = code;
this.details = details; this.details = details;
} }
} }
function cliError(code, message, details = {}) { function cliError(code: string, message: string, details = {}) {
throw new CliError(code, message, details); throw new CliError(code, message, details);
} }
function unknownCommand(name) { function unknownCommand(name: string) {
cliError("UNKNOWN_COMMAND", `Unknown command: ${name}`); cliError("UNKNOWN_COMMAND", `Unknown command: ${name}`);
} }
@@ -166,8 +178,8 @@ function getPreludeScriptSource() {
return inlineJs; return inlineJs;
} }
async function withDriver(action) { async function withDriver(action: (driver: WebDriver) => Promise<unknown>) {
let driver; let driver: WebDriver;
try { try {
driver = await createDriver({ headless, existingUrl }); driver = await createDriver({ headless, existingUrl });
@@ -182,16 +194,16 @@ async function withDriver(action) {
} }
} }
async function waitForReadyState(driver) { async function waitForReadyState(driver: WebDriver) {
if (waitUntil === "none") { if (waitUntil === "none") {
return; return;
} }
try { try {
await driver.wait(async () => { await driver.wait(async () => {
const readyState = await driver.executeScript( const readyState = (await driver.executeScript(
"return document.readyState", "return document.readyState",
); )) as string;
return waitUntil === "interactive" return waitUntil === "interactive"
? ["interactive", "complete"].includes(readyState) ? ["interactive", "complete"].includes(readyState)
: readyState === "complete"; : readyState === "complete";
@@ -204,14 +216,14 @@ async function waitForReadyState(driver) {
} }
} }
async function waitForJs(driver) { async function waitForJs(driver: WebDriver) {
if (!waitJs) { if (!waitJs) {
return; return;
} }
const start = Date.now(); const start = Date.now();
while (Date.now() - start < timeoutMs) { while (Date.now() - start < timeoutMs) {
let result; let result: unknown;
try { try {
result = await driver.executeScript(waitJs); result = await driver.executeScript(waitJs);
@@ -232,7 +244,7 @@ async function waitForJs(driver) {
); );
} }
async function runPreludeScript(driver) { async function runPreludeScript(driver: WebDriver) {
const scriptSource = getPreludeScriptSource(); const scriptSource = getPreludeScriptSource();
if (!scriptSource) { if (!scriptSource) {
return undefined; return undefined;
@@ -245,10 +257,13 @@ async function runPreludeScript(driver) {
} }
} }
async function withPage(targetUrl, action) { async function withPage(
targetUrl: string,
action: (driver: WebDriver, scriptResult: unknown) => Promise<unknown>,
) {
runContext.targetUrl = targetUrl; runContext.targetUrl = targetUrl;
return withDriver(async (driver) => { return withDriver(async (driver: WebDriver) => {
// Navigate To Page // Navigate To Page
try { try {
await driver.get(targetUrl); await driver.get(targetUrl);
@@ -340,7 +355,7 @@ async function snapshotCommand() {
if (!targetUrl) usage(); if (!targetUrl) usage();
return withPage(targetUrl, async (driver) => { return withPage(targetUrl, async (driver: WebDriver) => {
// Capture Page Metadata // Capture Page Metadata
const [url, title, result] = await Promise.all([ const [url, title, result] = await Promise.all([
driver.getCurrentUrl(), driver.getCurrentUrl(),
@@ -362,7 +377,7 @@ async function execCommand() {
if (!targetUrl || (!inlineJs && !scriptPath)) usage(); if (!targetUrl || (!inlineJs && !scriptPath)) usage();
return withPage(targetUrl, async (_driver, scriptResult) => scriptResult); return withPage(targetUrl, async (_driver: WebDriver, scriptResult: unknown) => scriptResult);
} }
async function screenshotCommand() { async function screenshotCommand() {
@@ -371,7 +386,7 @@ async function screenshotCommand() {
if (!targetUrl) usage(); if (!targetUrl) usage();
return withPage(targetUrl, async (driver) => { return withPage(targetUrl, async (driver: WebDriver) => {
// Save Screenshot // Save Screenshot
const image = await driver.takeScreenshot(); const image = await driver.takeScreenshot();
writeFileSync(outputPath, image, "base64"); writeFileSync(outputPath, image, "base64");
@@ -385,11 +400,11 @@ async function screenshotCommand() {
}); });
} }
function markdownTitle(text) { function markdownTitle(text: string) {
return text.replaceAll(/\s+/g, " ").trim(); return text.replaceAll(/\s+/g, " ").trim();
} }
function articleToMarkdown(article) { function articleToMarkdown(article: ReaderArticle) {
const turndown = new TurndownService({ const turndown = new TurndownService({
headingStyle: "atx", headingStyle: "atx",
codeBlockStyle: "fenced", codeBlockStyle: "fenced",
@@ -413,7 +428,7 @@ function articleToMarkdown(article) {
return `${parts.join("\n\n").trim()}\n`; return `${parts.join("\n\n").trim()}\n`;
} }
function renderReaderOutput(article, format) { function renderReaderOutput(article: ReaderArticle, format: string) {
switch (format) { switch (format) {
case "markdown": case "markdown":
return article.markdown; return article.markdown;
@@ -464,7 +479,7 @@ async function readerCommand() {
if (!targetUrl) usage(); if (!targetUrl) usage();
return withPage(targetUrl, async (driver) => { return withPage(targetUrl, async (driver: WebDriver) => {
// Capture Final Url // Capture Final Url
const finalUrl = await driver.getCurrentUrl(); const finalUrl = await driver.getCurrentUrl();
@@ -473,7 +488,7 @@ async function readerCommand() {
await driver.get(readerUrl); await driver.get(readerUrl);
// Wait For Reader Content // Wait For Reader Content
let article; let article: ReaderArticle;
try { try {
article = await driver.wait( article = await driver.wait(
async () => { async () => {