add lint config

This commit is contained in:
Brent Schroeter 2026-02-02 18:09:54 +00:00
parent a5c1abbbed
commit ff2e135d72
6 changed files with 1194 additions and 13 deletions

14
eslint.config.ts Normal file
View file

@ -0,0 +1,14 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";
export default defineConfig([
{
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
plugins: { js },
extends: ["js/recommended"],
languageOptions: { globals: { ...globals.browser, ...globals.node } },
},
tseslint.configs.recommended,
]);

View file

@ -1,8 +1,12 @@
[tools] [tools]
node = "24" node = "24"
[tasks.lint]
run = "npx tsc --noEmit && npx eslint ./src"
[tasks.build] [tasks.build]
run = "npx rollup -c" run = "npx rollup -c"
[tasks.test] [tasks.test]
depends = ["lint"]
run = "npx jest" run = "npx jest"

1168
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,13 +17,18 @@
"test": "mise run test" "test": "mise run test"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.2",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.3.0", "@rollup/plugin-typescript": "^12.3.0",
"@types/jest": "^30.0.0", "@types/jest": "^30.0.0",
"eslint": "^9.39.2",
"globals": "^17.3.0",
"jest": "^30.2.0", "jest": "^30.2.0",
"jiti": "^2.6.1",
"rollup": "^4.57.1", "rollup": "^4.57.1",
"ts-jest": "^29.4.6", "ts-jest": "^29.4.6",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"typescript": "^5.9.3" "typescript": "^5.9.3",
"typescript-eslint": "^8.54.0"
} }
} }

View file

@ -2,7 +2,7 @@ import { AsyncTaskQueue } from "./index";
test("example evaluates correctly", async () => { test("example evaluates correctly", async () => {
const q = new AsyncTaskQueue<number>( const q = new AsyncTaskQueue<number>(
async (nums: number[]) => {/* no-op */}, async () => {/* no-op */},
) )
// Handler will receive up to 4 items per batch. // Handler will receive up to 4 items per batch.
.batchSize(4) .batchSize(4)

View file

@ -3,7 +3,7 @@
*/ */
export class AsyncTaskQueue<T> { export class AsyncTaskQueue<T> {
private _queue: T[] = []; private _queue: T[] = [];
private readonly _handler: (item: T) => Promise<unknown>; private readonly _handler: (items: T[]) => Promise<unknown>;
private _errorHandler: (err: unknown) => unknown = console.error; private _errorHandler: (err: unknown) => unknown = console.error;
private _batchSize = 1; private _batchSize = 1;
private _throttleIntervalMs = 0; private _throttleIntervalMs = 0;
@ -48,7 +48,7 @@ export class AsyncTaskQueue<T> {
* This method updates the queue in place and returns it, so method calls may * This method updates the queue in place and returns it, so method calls may
* be chained. * be chained.
*/ */
throttleMs(intervalMs?: number): AsyncTaskQueue<T> { throttleMs(intervalMs: number): AsyncTaskQueue<T> {
if (intervalMs < 0) { if (intervalMs < 0) {
throw new Error("Interval must be zero or more milliseconds."); throw new Error("Interval must be zero or more milliseconds.");
} }
@ -82,7 +82,7 @@ export class AsyncTaskQueue<T> {
return this._queue.length; return this._queue.length;
} }
private async _processAll(): void { private async _processAll(): Promise<void> {
// Control loop is very simple: a `while` loop in a single async "thread", // Control loop is very simple: a `while` loop in a single async "thread",
// which runs until the queue is empty and then waits for // which runs until the queue is empty and then waits for
// `this._processAll()` to be called again. Because the execution // `this._processAll()` to be called again. Because the execution
@ -114,13 +114,13 @@ export class AsyncTaskQueue<T> {
/** /**
* Wraps an arbitrary async function with retry logic for exceptions. * Wraps an arbitrary async function with retry logic for exceptions.
*/ */
export function withRetry<T, U extends Promise>( export function withRetry<T extends unknown[], U>(
fn: (...args: T) => U, fn: (...args: T) => Promise<U>,
{ attempts = 6, backoffMs = (attempt) => 1000 * 2 ** attempt }: { { attempts = 6, backoffMs = (attempt) => 1000 * 2 ** attempt }: {
attempts: number; attempts: number;
backoffMs(attempt: number): number; backoffMs(attempt: number): number;
}, },
): (...args: T) => U { ): (...args: T) => Promise<U> {
return async (...args: T) => { return async (...args: T) => {
for (let attempt = 0; attempt < attempts - 1; attempt += 1) { for (let attempt = 0; attempt < attempts - 1; attempt += 1) {
try { try {