add eslint

This commit is contained in:
Venkatesan Ravi
2025-10-31 16:38:09 -07:00
parent 7a20ea0c72
commit 516109161d
12 changed files with 513 additions and 22 deletions

View File

@@ -16,6 +16,10 @@ indent_size = 2
indent_style = space
indent_size = 2
[*.mjs]
indent_style = space
indent_size = 2
[*.yaml]
indent_style = space
indent_size = 2

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
bundle.cjs
node_modules
result

View File

@@ -1,8 +1,7 @@
// esbuild.cjs
const esbuild = require("esbuild");
import { build } from "esbuild";
async function main() {
await esbuild.build({
await build({
entryPoints: ["./src/cli.ts"],
bundle: true,
sourcemap: "inline",

31
eslint.config.mjs Normal file
View File

@@ -0,0 +1,31 @@
import eslint from "@eslint/js";
import { defineConfig, globalIgnores } from "eslint/config";
import tseslint from "typescript-eslint";
export default defineConfig(
eslint.configs.recommended,
tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
},
},
},
{
rules: {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/typedef": [
"error",
{
memberVariableDeclaration: true,
parameter: true,
propertyDeclaration: true,
variableDeclaration: true,
},
],
},
},
[globalIgnores(["**bundle.cjs", "esbuild.ts", "eslint.config.mjs"])],
);

View File

@@ -42,7 +42,7 @@ pkgs.stdenvNoCC.mkDerivation (finalAttrs: {
pnpmDeps = pkgs.pnpm.fetchDeps {
fetcherVersion = 1;
hash = "sha256-xhTEHi8UVeYD/OtTQMtFYk6SqX43+Tx73tCOoyCwOyw=";
hash = "sha256-LjdZDFenfylIpKxRpVmPUten/1IyL/cmI6QjDfcmfDc=";
inherit (finalAttrs) pname src version;
};

View File

@@ -1,11 +1,13 @@
{
"devDependencies": {
"@eslint/js": "^9.39.0",
"@types/node": "^24.9.2",
"@vitest/coverage-v8": "^4.0.6",
"esbuild": "^0.25.11",
"eslint": "^9.38.0",
"tsx": "^4.20.6",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.2",
"vitest": "^4.0.6"
},
"dependencies": {

437
pnpm-lock.yaml generated
View File

@@ -26,6 +26,9 @@ importers:
specifier: ^4.1.12
version: 4.1.12
devDependencies:
"@eslint/js":
specifier: ^9.39.0
version: 9.39.0
"@types/node":
specifier: ^24.9.2
version: 24.9.2
@@ -44,6 +47,9 @@ importers:
typescript:
specifier: ^5.9.3
version: 5.9.3
typescript-eslint:
specifier: ^8.46.2
version: 8.46.2(eslint@9.38.0)(typescript@5.9.3)
vitest:
specifier: ^4.0.6
version: 4.0.6(@types/node@24.9.2)(tsx@4.20.6)(yaml@2.8.1)
@@ -377,6 +383,13 @@ packages:
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
"@eslint/js@9.39.0":
resolution:
{
integrity: sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
"@eslint/object-schema@2.1.7":
resolution:
{
@@ -438,6 +451,27 @@ packages:
integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==,
}
"@nodelib/fs.scandir@2.1.5":
resolution:
{
integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==,
}
engines: { node: ">= 8" }
"@nodelib/fs.stat@2.0.5":
resolution:
{
integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==,
}
engines: { node: ">= 8" }
"@nodelib/fs.walk@1.2.8":
resolution:
{
integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==,
}
engines: { node: ">= 8" }
"@rollup/rollup-android-arm-eabi@4.52.5":
resolution:
{
@@ -650,6 +684,95 @@ packages:
integrity: sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==,
}
"@typescript-eslint/eslint-plugin@8.46.2":
resolution:
{
integrity: sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
"@typescript-eslint/parser": ^8.46.2
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/parser@8.46.2":
resolution:
{
integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/project-service@8.46.2":
resolution:
{
integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/scope-manager@8.46.2":
resolution:
{
integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
"@typescript-eslint/tsconfig-utils@8.46.2":
resolution:
{
integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/type-utils@8.46.2":
resolution:
{
integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/types@8.46.2":
resolution:
{
integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
"@typescript-eslint/typescript-estree@8.46.2":
resolution:
{
integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/utils@8.46.2":
resolution:
{
integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
"@typescript-eslint/visitor-keys@8.46.2":
resolution:
{
integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
"@vitest/coverage-v8@4.0.6":
resolution:
{
@@ -772,6 +895,19 @@ packages:
integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==,
}
brace-expansion@2.0.2:
resolution:
{
integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==,
}
braces@3.0.3:
resolution:
{
integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==,
}
engines: { node: ">=8" }
callsites@3.1.0:
resolution:
{
@@ -960,6 +1096,13 @@ packages:
integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==,
}
fast-glob@3.3.3:
resolution:
{
integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==,
}
engines: { node: ">=8.6.0" }
fast-json-stable-stringify@2.1.0:
resolution:
{
@@ -972,6 +1115,12 @@ packages:
integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==,
}
fastq@1.19.1:
resolution:
{
integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==,
}
fdir@6.5.0:
resolution:
{
@@ -991,6 +1140,13 @@ packages:
}
engines: { node: ">=16.0.0" }
fill-range@7.1.1:
resolution:
{
integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==,
}
engines: { node: ">=8" }
find-up@5.0.0:
resolution:
{
@@ -1025,6 +1181,13 @@ packages:
integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==,
}
glob-parent@5.1.2:
resolution:
{
integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==,
}
engines: { node: ">= 6" }
glob-parent@6.0.2:
resolution:
{
@@ -1039,6 +1202,12 @@ packages:
}
engines: { node: ">=18" }
graphemer@1.4.0:
resolution:
{
integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==,
}
has-flag@4.0.0:
resolution:
{
@@ -1059,6 +1228,13 @@ packages:
}
engines: { node: ">= 4" }
ignore@7.0.5:
resolution:
{
integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==,
}
engines: { node: ">= 4" }
import-fresh@3.3.1:
resolution:
{
@@ -1087,6 +1263,13 @@ packages:
}
engines: { node: ">=0.10.0" }
is-number@7.0.0:
resolution:
{
integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==,
}
engines: { node: ">=0.12.0" }
isexe@2.0.0:
resolution:
{
@@ -1197,12 +1380,33 @@ packages:
}
engines: { node: ">=10" }
merge2@1.4.1:
resolution:
{
integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==,
}
engines: { node: ">= 8" }
micromatch@4.0.8:
resolution:
{
integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==,
}
engines: { node: ">=8.6" }
minimatch@3.1.2:
resolution:
{
integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==,
}
minimatch@9.0.5:
resolution:
{
integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==,
}
engines: { node: ">=16 || 14 >=14.17" }
ms@2.1.3:
resolution:
{
@@ -1289,6 +1493,13 @@ packages:
integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==,
}
picomatch@2.3.1:
resolution:
{
integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==,
}
engines: { node: ">=8.6" }
picomatch@4.0.3:
resolution:
{
@@ -1317,6 +1528,12 @@ packages:
}
engines: { node: ">=6" }
queue-microtask@1.2.3:
resolution:
{
integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==,
}
resolve-from@4.0.0:
resolution:
{
@@ -1330,6 +1547,13 @@ packages:
integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==,
}
reusify@1.1.0:
resolution:
{
integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==,
}
engines: { iojs: ">=1.0.0", node: ">=0.10.0" }
rollup@4.52.5:
resolution:
{
@@ -1338,6 +1562,12 @@ packages:
engines: { node: ">=18.0.0", npm: ">=8.0.0" }
hasBin: true
run-parallel@1.2.0:
resolution:
{
integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==,
}
semver@7.7.3:
resolution:
{
@@ -1425,6 +1655,22 @@ packages:
}
engines: { node: ">=14.0.0" }
to-regex-range@5.0.1:
resolution:
{
integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==,
}
engines: { node: ">=8.0" }
ts-api-utils@2.1.0:
resolution:
{
integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==,
}
engines: { node: ">=18.12" }
peerDependencies:
typescript: ">=4.8.4"
tsx@4.20.6:
resolution:
{
@@ -1440,6 +1686,16 @@ packages:
}
engines: { node: ">= 0.8.0" }
typescript-eslint@8.46.2:
resolution:
{
integrity: sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==,
}
engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 }
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
typescript@5.9.3:
resolution:
{
@@ -1728,6 +1984,8 @@ snapshots:
"@eslint/js@9.38.0": {}
"@eslint/js@9.39.0": {}
"@eslint/object-schema@2.1.7": {}
"@eslint/plugin-kit@0.4.1":
@@ -1755,6 +2013,18 @@ snapshots:
"@jridgewell/resolve-uri": 3.1.2
"@jridgewell/sourcemap-codec": 1.5.5
"@nodelib/fs.scandir@2.1.5":
dependencies:
"@nodelib/fs.stat": 2.0.5
run-parallel: 1.2.0
"@nodelib/fs.stat@2.0.5": {}
"@nodelib/fs.walk@1.2.8":
dependencies:
"@nodelib/fs.scandir": 2.1.5
fastq: 1.19.1
"@rollup/rollup-android-arm-eabi@4.52.5":
optional: true
@@ -1838,6 +2108,99 @@ snapshots:
dependencies:
undici-types: 7.16.0
"@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0)(typescript@5.9.3))(eslint@9.38.0)(typescript@5.9.3)":
dependencies:
"@eslint-community/regexpp": 4.12.2
"@typescript-eslint/parser": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
"@typescript-eslint/scope-manager": 8.46.2
"@typescript-eslint/type-utils": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
"@typescript-eslint/utils": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
"@typescript-eslint/visitor-keys": 8.46.2
eslint: 9.38.0
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/parser@8.46.2(eslint@9.38.0)(typescript@5.9.3)":
dependencies:
"@typescript-eslint/scope-manager": 8.46.2
"@typescript-eslint/types": 8.46.2
"@typescript-eslint/typescript-estree": 8.46.2(typescript@5.9.3)
"@typescript-eslint/visitor-keys": 8.46.2
debug: 4.4.3
eslint: 9.38.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/project-service@8.46.2(typescript@5.9.3)":
dependencies:
"@typescript-eslint/tsconfig-utils": 8.46.2(typescript@5.9.3)
"@typescript-eslint/types": 8.46.2
debug: 4.4.3
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/scope-manager@8.46.2":
dependencies:
"@typescript-eslint/types": 8.46.2
"@typescript-eslint/visitor-keys": 8.46.2
"@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.9.3)":
dependencies:
typescript: 5.9.3
"@typescript-eslint/type-utils@8.46.2(eslint@9.38.0)(typescript@5.9.3)":
dependencies:
"@typescript-eslint/types": 8.46.2
"@typescript-eslint/typescript-estree": 8.46.2(typescript@5.9.3)
"@typescript-eslint/utils": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
debug: 4.4.3
eslint: 9.38.0
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/types@8.46.2": {}
"@typescript-eslint/typescript-estree@8.46.2(typescript@5.9.3)":
dependencies:
"@typescript-eslint/project-service": 8.46.2(typescript@5.9.3)
"@typescript-eslint/tsconfig-utils": 8.46.2(typescript@5.9.3)
"@typescript-eslint/types": 8.46.2
"@typescript-eslint/visitor-keys": 8.46.2
debug: 4.4.3
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.3
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/utils@8.46.2(eslint@9.38.0)(typescript@5.9.3)":
dependencies:
"@eslint-community/eslint-utils": 4.9.0(eslint@9.38.0)
"@typescript-eslint/scope-manager": 8.46.2
"@typescript-eslint/types": 8.46.2
"@typescript-eslint/typescript-estree": 8.46.2(typescript@5.9.3)
eslint: 9.38.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
"@typescript-eslint/visitor-keys@8.46.2":
dependencies:
"@typescript-eslint/types": 8.46.2
eslint-visitor-keys: 4.2.1
"@vitest/coverage-v8@4.0.6(vitest@4.0.6(@types/node@24.9.2)(tsx@4.20.6)(yaml@2.8.1))":
dependencies:
"@bcoe/v8-coverage": 1.0.2
@@ -1928,6 +2291,14 @@ snapshots:
balanced-match: 1.0.2
concat-map: 0.0.1
brace-expansion@2.0.2:
dependencies:
balanced-match: 1.0.2
braces@3.0.3:
dependencies:
fill-range: 7.1.1
callsites@3.1.0: {}
chai@6.2.0: {}
@@ -2068,10 +2439,22 @@ snapshots:
fast-deep-equal@3.1.3: {}
fast-glob@3.3.3:
dependencies:
"@nodelib/fs.stat": 2.0.5
"@nodelib/fs.walk": 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
micromatch: 4.0.8
fast-json-stable-stringify@2.1.0: {}
fast-levenshtein@2.0.6: {}
fastq@1.19.1:
dependencies:
reusify: 1.1.0
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
@@ -2080,6 +2463,10 @@ snapshots:
dependencies:
flat-cache: 4.0.1
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
find-up@5.0.0:
dependencies:
locate-path: 6.0.0
@@ -2099,18 +2486,26 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
glob-parent@6.0.2:
dependencies:
is-glob: 4.0.3
globals@14.0.0: {}
graphemer@1.4.0: {}
has-flag@4.0.0: {}
html-escaper@2.0.2: {}
ignore@5.3.2: {}
ignore@7.0.5: {}
import-fresh@3.3.1:
dependencies:
parent-module: 1.0.1
@@ -2124,6 +2519,8 @@ snapshots:
dependencies:
is-extglob: 2.1.1
is-number@7.0.0: {}
isexe@2.0.0: {}
istanbul-lib-coverage@3.2.2: {}
@@ -2188,10 +2585,21 @@ snapshots:
dependencies:
semver: 7.7.3
merge2@1.4.1: {}
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.2
ms@2.1.3: {}
nanoid@3.3.11: {}
@@ -2233,6 +2641,8 @@ snapshots:
picocolors@1.1.1: {}
picomatch@2.3.1: {}
picomatch@4.0.3: {}
postcss@8.5.6:
@@ -2245,10 +2655,14 @@ snapshots:
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
resolve-from@4.0.0: {}
resolve-pkg-maps@1.0.0: {}
reusify@1.1.0: {}
rollup@4.52.5:
dependencies:
"@types/estree": 1.0.8
@@ -2277,6 +2691,10 @@ snapshots:
"@rollup/rollup-win32-x64-msvc": 4.52.5
fsevents: 2.3.3
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
semver@7.7.3: {}
shebang-command@2.0.0:
@@ -2310,6 +2728,14 @@ snapshots:
tinyrainbow@3.0.3: {}
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
ts-api-utils@2.1.0(typescript@5.9.3):
dependencies:
typescript: 5.9.3
tsx@4.20.6:
dependencies:
esbuild: 0.25.11
@@ -2321,6 +2747,17 @@ snapshots:
dependencies:
prelude-ls: 1.2.1
typescript-eslint@8.46.2(eslint@9.38.0)(typescript@5.9.3):
dependencies:
"@typescript-eslint/eslint-plugin": 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0)(typescript@5.9.3))(eslint@9.38.0)(typescript@5.9.3)
"@typescript-eslint/parser": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
"@typescript-eslint/typescript-estree": 8.46.2(typescript@5.9.3)
"@typescript-eslint/utils": 8.46.2(eslint@9.38.0)(typescript@5.9.3)
eslint: 9.38.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
typescript@5.9.3: {}
undici-types@7.16.0: {}

2
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,2 @@
onlyBuiltDependencies:
- esbuild

View File

@@ -2,17 +2,21 @@
import { Command } from "commander";
import { applySystem } from "./system";
const program = new Command();
type Options = {
config: string;
};
const program: Command = new Command();
program
.name("jellarr-ts")
.description("Minimal Jellyfin config applier")
.option("-c, --config <path>", "YAML config file", "config.yml")
.action(async (opts) => {
.action(async (opts: Options) => {
await applySystem(opts.config);
});
program.parseAsync().catch((err) => {
program.parseAsync().catch((err: unknown) => {
console.error(err);
process.exit(1);
});

View File

@@ -2,13 +2,13 @@ import createClient from "openapi-fetch";
import type { paths } from "../generated/schema";
export function makeClient(baseUrl: string, apiKey: string) {
const client = createClient<paths>({
const client: ReturnType<typeof createClient<paths>> = createClient<paths>({
baseUrl: baseUrl.replace(/\/+$/, ""),
});
client.use({
async onRequest({ request }) {
const headers = new Headers(request.headers);
onRequest({ request }: { request: Request }): Request {
const headers: Headers = new Headers(request.headers);
headers.set("X-Emby-Token", apiKey);
headers.set(
"X-Emby-Authorization",

View File

@@ -1,6 +1,10 @@
import YAML from "yaml";
import { promises as fs } from "fs";
import createClient from "openapi-fetch";
import YAML from "yaml";
import { makeClient } from "./client";
import type { components, paths } from "../generated/schema";
type ServerConfiguration = components["schemas"]["ServerConfiguration"];
interface Config {
version: number;
@@ -9,34 +13,40 @@ interface Config {
}
export async function applySystem(path: string) {
const cfg = YAML.parse(await fs.readFile(path, "utf8")) as Config;
const cfg: Config = YAML.parse(await fs.readFile(path, "utf8")) as Config;
const { base_url, system } = cfg;
const apiKey = process.env.JELLYFIN_API_KEY;
const apiKey: string | undefined = process.env.JELLYFIN_API_KEY;
if (!apiKey) throw new Error("JELLYFIN_API_KEY required");
const jf = makeClient(base_url, apiKey);
const jf: ReturnType<typeof createClient<paths>> = makeClient(
base_url,
apiKey,
);
// eslint-disable-next-line @typescript-eslint/typedef
const read = await jf.GET("/System/Configuration");
if (read.error) {
throw new Error(
`Failed to get config: ${read.response?.status ?? "unknown"}`,
);
throw new Error(`Failed to get config: ${read.response.status.toString()}`);
}
const current = read.data;
const current: ServerConfiguration = read.data as ServerConfiguration;
if (current?.EnableMetrics === system.enableMetrics) {
if (current.EnableMetrics === system.enableMetrics) {
console.log("✓ Already up to date");
return;
}
console.log("→ Updating EnableMetrics...");
const body = { ...(current as any), EnableMetrics: system.enableMetrics };
const body: ServerConfiguration = {
...current,
EnableMetrics: system.enableMetrics,
};
// eslint-disable-next-line @typescript-eslint/typedef
const write = await jf.POST("/System/Configuration", { body });
if (write.error) {
throw new Error(`Update failed: ${write.response?.status ?? "unknown"}`);
throw new Error(`Update failed: ${write.response.status.toString()}`);
}
console.log("✓ Updated");

View File

@@ -8,7 +8,8 @@
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist"
"outDir": "dist",
"noImplicitAny": true
},
"include": ["src", "generated"]
}