style: add explicit types to eliminate implicit any in index.ts
This commit is contained in:
@@ -65,6 +65,7 @@
|
||||
nodejs_22
|
||||
firefox
|
||||
geckodriver
|
||||
typescript-language-server
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { Builder, type WebDriver } from "selenium-webdriver";
|
||||
export { type WebDriver };
|
||||
import firefox from "selenium-webdriver/firefox.js";
|
||||
|
||||
export interface DriverOptions {
|
||||
|
||||
65
src/index.ts
65
src/index.ts
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
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 { readFileSync, writeFileSync } from "node:fs";
|
||||
import TurndownService from "turndown";
|
||||
@@ -11,6 +11,18 @@ const POLL_INTERVAL_MS = 200;
|
||||
const startTime = Date.now();
|
||||
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
|
||||
const [command, ...args] = process.argv.slice(2);
|
||||
const headless = !args.includes("--no-headless");
|
||||
@@ -23,7 +35,7 @@ const configPath = getOption("--config");
|
||||
let appConfig: GlimpseConfig = {};
|
||||
let timeoutMs = DEFAULT_TIMEOUT_MS;
|
||||
|
||||
function getOption(name) {
|
||||
function getOption(name: string) {
|
||||
const prefix = `${name}=`;
|
||||
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
|
||||
}
|
||||
@@ -36,14 +48,14 @@ function elapsedMs() {
|
||||
return Date.now() - startTime;
|
||||
}
|
||||
|
||||
function printResult(result) {
|
||||
function printResult(result: unknown) {
|
||||
if (result === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const outputValue =
|
||||
result && typeof result === "object" && !Array.isArray(result)
|
||||
? { ...result, elapsedMs: result.elapsedMs ?? elapsedMs() }
|
||||
? { ...result, elapsedMs: (result as any).elapsedMs ?? elapsedMs() }
|
||||
: result;
|
||||
const output =
|
||||
typeof outputValue === "object"
|
||||
@@ -56,18 +68,18 @@ class CliError extends Error {
|
||||
code: string;
|
||||
details: Record<string, unknown>;
|
||||
|
||||
constructor(code, message, details = {}) {
|
||||
constructor(code: string, message: string, details = {}) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.details = details;
|
||||
}
|
||||
}
|
||||
|
||||
function cliError(code, message, details = {}) {
|
||||
function cliError(code: string, message: string, details = {}) {
|
||||
throw new CliError(code, message, details);
|
||||
}
|
||||
|
||||
function unknownCommand(name) {
|
||||
function unknownCommand(name: string) {
|
||||
cliError("UNKNOWN_COMMAND", `Unknown command: ${name}`);
|
||||
}
|
||||
|
||||
@@ -166,8 +178,8 @@ function getPreludeScriptSource() {
|
||||
return inlineJs;
|
||||
}
|
||||
|
||||
async function withDriver(action) {
|
||||
let driver;
|
||||
async function withDriver(action: (driver: WebDriver) => Promise<unknown>) {
|
||||
let driver: WebDriver;
|
||||
|
||||
try {
|
||||
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") {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await driver.wait(async () => {
|
||||
const readyState = await driver.executeScript(
|
||||
const readyState = (await driver.executeScript(
|
||||
"return document.readyState",
|
||||
);
|
||||
)) as string;
|
||||
return waitUntil === "interactive"
|
||||
? ["interactive", "complete"].includes(readyState)
|
||||
: readyState === "complete";
|
||||
@@ -204,14 +216,14 @@ async function waitForReadyState(driver) {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForJs(driver) {
|
||||
async function waitForJs(driver: WebDriver) {
|
||||
if (!waitJs) {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeoutMs) {
|
||||
let result;
|
||||
let result: unknown;
|
||||
|
||||
try {
|
||||
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();
|
||||
if (!scriptSource) {
|
||||
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;
|
||||
|
||||
return withDriver(async (driver) => {
|
||||
return withDriver(async (driver: WebDriver) => {
|
||||
// Navigate To Page
|
||||
try {
|
||||
await driver.get(targetUrl);
|
||||
@@ -340,7 +355,7 @@ async function snapshotCommand() {
|
||||
|
||||
if (!targetUrl) usage();
|
||||
|
||||
return withPage(targetUrl, async (driver) => {
|
||||
return withPage(targetUrl, async (driver: WebDriver) => {
|
||||
// Capture Page Metadata
|
||||
const [url, title, result] = await Promise.all([
|
||||
driver.getCurrentUrl(),
|
||||
@@ -362,7 +377,7 @@ async function execCommand() {
|
||||
|
||||
if (!targetUrl || (!inlineJs && !scriptPath)) usage();
|
||||
|
||||
return withPage(targetUrl, async (_driver, scriptResult) => scriptResult);
|
||||
return withPage(targetUrl, async (_driver: WebDriver, scriptResult: unknown) => scriptResult);
|
||||
}
|
||||
|
||||
async function screenshotCommand() {
|
||||
@@ -371,7 +386,7 @@ async function screenshotCommand() {
|
||||
|
||||
if (!targetUrl) usage();
|
||||
|
||||
return withPage(targetUrl, async (driver) => {
|
||||
return withPage(targetUrl, async (driver: WebDriver) => {
|
||||
// Save Screenshot
|
||||
const image = await driver.takeScreenshot();
|
||||
writeFileSync(outputPath, image, "base64");
|
||||
@@ -385,11 +400,11 @@ async function screenshotCommand() {
|
||||
});
|
||||
}
|
||||
|
||||
function markdownTitle(text) {
|
||||
function markdownTitle(text: string) {
|
||||
return text.replaceAll(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
function articleToMarkdown(article) {
|
||||
function articleToMarkdown(article: ReaderArticle) {
|
||||
const turndown = new TurndownService({
|
||||
headingStyle: "atx",
|
||||
codeBlockStyle: "fenced",
|
||||
@@ -413,7 +428,7 @@ function articleToMarkdown(article) {
|
||||
return `${parts.join("\n\n").trim()}\n`;
|
||||
}
|
||||
|
||||
function renderReaderOutput(article, format) {
|
||||
function renderReaderOutput(article: ReaderArticle, format: string) {
|
||||
switch (format) {
|
||||
case "markdown":
|
||||
return article.markdown;
|
||||
@@ -464,7 +479,7 @@ async function readerCommand() {
|
||||
|
||||
if (!targetUrl) usage();
|
||||
|
||||
return withPage(targetUrl, async (driver) => {
|
||||
return withPage(targetUrl, async (driver: WebDriver) => {
|
||||
// Capture Final Url
|
||||
const finalUrl = await driver.getCurrentUrl();
|
||||
|
||||
@@ -473,7 +488,7 @@ async function readerCommand() {
|
||||
await driver.get(readerUrl);
|
||||
|
||||
// Wait For Reader Content
|
||||
let article;
|
||||
let article: ReaderArticle;
|
||||
try {
|
||||
article = await driver.wait(
|
||||
async () => {
|
||||
|
||||
Reference in New Issue
Block a user