feat(update): start migrating to typescript for script
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-07-20 19:56:59 -04:00
parent f50ee16e0f
commit 96067d726b
8 changed files with 650 additions and 0 deletions

1
apps/update/.envrc Normal file
View file

@ -0,0 +1 @@
use flake $FLAKE#node

86
apps/update/app.ts Normal file
View file

@ -0,0 +1,86 @@
import { spawnSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
/* Constants */
const FLAKE = process.env.FLAKE;
/* Parse Args */
const args = {} as Record<string, unknown>;
let lastFlag: string | null = null;
for (let i = 2; i < process.argv.length; ++i) {
const arg = process.argv[i];
if (arg.toString().startsWith('-')) {
lastFlag = arg.toString().replace(/^-{1,2}/, '');
args[lastFlag] = true;
}
else if (lastFlag) {
args[lastFlag] = arg;
lastFlag = null;
}
else {
console.error(`Could not parse args: ${arg.toString()}`);
}
}
/* Functions */
const updateFirefoxAddons = () => {
console.log('Updating firefox addons using mozilla-addons-to-nix');
const DIR = `${FLAKE}/pkgs/firefox-addons`;
const GENERATED_FILE = `${DIR}/generated-firefox-addons.nix`;
const SLUGS = `${DIR}/addons.json`;
const nameMap = Object.fromEntries([...JSON.parse(readFileSync(SLUGS, 'utf-8'))]
.map((addon) => [addon.slug, addon.pname || addon.slug]));
const nixExpr = `'
x: let
inherit (builtins) attrValues filter hasAttr isAttrs map;
in
map (d: d.name) (filter (y:
isAttrs y &&
hasAttr "type" y &&
y.type == "derivation") (attrValues x))
'`;
const OLD_VERS = Object.fromEntries([...JSON.parse(spawnSync('nix', [
'eval',
'.#legacyPackages.x86_64-linux.firefoxAddons',
'--apply',
nixExpr,
'--json',
], { shell: true }).stdout.toString())]
.map((p) => {
const pname = p.replace(/-[0-9].*$/, '');
return [pname, p.replace(`${pname}-`, '')];
})
.filter((pinfo) => pinfo[0] !== 'frankerfacez'));
const NEW_VERS = Object.fromEntries(spawnSync(
'mozilla-addons-to-nix',
[SLUGS, GENERATED_FILE],
{ shell: true },
).stdout
.toString()
.split('\n')
.map((p) => {
const pinfo = p.replace('Fetched ', '').split(' ');
return [nameMap[pinfo[0]], pinfo[2]];
}));
return Object.keys(OLD_VERS)
.sort()
.filter((pname) => OLD_VERS[pname] !== NEW_VERS[pname])
.map((pname) => `${pname}: ${OLD_VERS[pname]} -> ${NEW_VERS[pname]}`)
.join('\n');
};
/* Exec functions based on args */
if (args['f'] || args['firefox']) {
console.log(updateFirefoxAddons());
}

35
apps/update/default.nix Normal file
View file

@ -0,0 +1,35 @@
{
lib,
system,
buildNpmPackage,
makeWrapper,
mozilla-addons-to-nix,
nodejs_latest,
...
}: let
inherit (lib) concatMapStringsSep getBin;
inherit (builtins) readFile fromJSON;
packageJSON = fromJSON (readFile ./package.json);
pname = packageJSON.name;
in
buildNpmPackage rec {
name = pname;
inherit (packageJSON) version;
src = ./.;
npmDepsHash = "sha256-qpnQSJNl68LrsU8foJYxdBXpoFj7VKQahC9DFmleWTs=";
runtimeInputs = [
mozilla-addons-to-nix.packages.${system}.default
];
nativeBuildInputs = [makeWrapper];
postInstall = ''
wrapProgram $out/bin/${pname} \
--prefix PATH : ${concatMapStringsSep ":" (p: getBin p) runtimeInputs}
'';
nodejs = nodejs_latest;
meta.mainProgram = pname;
}

View file

@ -0,0 +1,464 @@
// TODO: switch to typescript https://github.com/eslint/eslint/pull/18134
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import stylistic from '@stylistic/eslint-plugin';
// import stylisticRules from '@stylistic/eslint-plugin/rule-options';
import jsdoc from 'eslint-plugin-jsdoc';
export default tseslint.config(
{
languageOptions: {
parserOptions: {
project: true,
tsconfigDirName: import.meta.dirname,
},
},
plugins: {
jsdoc,
// @ts-expect-error this works
'@stylistic': stylistic, // as typeof stylisticRules,
},
extends: [
eslint.configs.recommended,
jsdoc.configs['flat/recommended-typescript'],
...tseslint.configs.recommended,
],
rules: {
// JSDoc settings
'jsdoc/tag-lines': ['warn', 'any', { startLines: 1 }],
'jsdoc/check-line-alignment': ['warn', 'always', {
tags: ['param', 'arg', 'argument', 'property', 'prop'],
}],
// Newer settings
'@typescript-eslint/no-extraneous-class': ['off'],
'@typescript-eslint/no-implied-eval': ['off'],
// Pre-flat config
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'array-callback-return': [
'error',
{
allowImplicit: true,
checkForEach: true,
},
],
'no-constructor-return': [
'error',
],
'no-unreachable-loop': [
'error',
{
ignore: [
'ForInStatement',
'ForOfStatement',
],
},
],
'no-use-before-define': [
'error',
{
functions: false,
},
],
'block-scoped-var': [
'error',
],
'class-methods-use-this': [
'error',
],
'curly': [
'warn',
],
'default-case-last': [
'warn',
],
'default-param-last': [
'error',
],
'eqeqeq': [
'error',
'smart',
],
'func-names': [
'warn',
'never',
],
'func-style': [
'warn',
'expression',
],
'logical-assignment-operators': [
'warn',
'always',
],
'no-array-constructor': [
'error',
],
'no-empty-function': [
'warn',
],
'no-empty-static-block': [
'warn',
],
'no-extend-native': [
'error',
],
'no-extra-bind': [
'warn',
],
'no-implicit-coercion': [
'warn',
],
'no-iterator': [
'error',
],
'no-labels': [
'error',
],
'no-lone-blocks': [
'error',
],
'no-lonely-if': [
'error',
],
'no-loop-func': [
'error',
],
'no-magic-numbers': [
'error',
{
ignore: [
-1,
0.1,
0,
1,
2,
3,
4,
5,
10,
12,
33,
66,
100,
255,
360,
450,
500,
1000,
],
ignoreDefaultValues: true,
ignoreClassFieldInitialValues: true,
},
],
'no-multi-assign': [
'error',
],
'no-new-wrappers': [
'error',
],
'no-object-constructor': [
'error',
],
'no-proto': [
'error',
],
'no-return-assign': [
'error',
],
'no-sequences': [
'error',
],
'no-shadow': [
'error',
{
builtinGlobals: true,
allow: [
'Window',
],
},
],
'no-undef-init': [
'warn',
],
'no-undefined': [
'error',
],
'no-useless-constructor': [
'warn',
],
'no-useless-escape': [
'off',
],
'no-useless-return': [
'error',
],
'no-var': [
'error',
],
'no-void': [
'off',
],
'no-with': [
'error',
],
'object-shorthand': [
'error',
'always',
],
'one-var': [
'error',
'never',
],
'operator-assignment': [
'warn',
'always',
],
'prefer-arrow-callback': [
'error',
],
'prefer-const': [
'error',
],
'prefer-object-has-own': [
'error',
],
'prefer-regex-literals': [
'error',
],
'prefer-template': [
'warn',
],
'no-prototype-builtins': 'off',
'@typescript-eslint/no-var-requires': [
'off',
],
'@stylistic/array-bracket-newline': [
'warn',
'consistent',
],
'@stylistic/array-bracket-spacing': [
'warn',
'never',
],
'@stylistic/arrow-parens': [
'warn',
'always',
],
'@stylistic/brace-style': [
'warn',
'stroustrup',
],
'@stylistic/comma-dangle': [
'warn',
'always-multiline',
],
'@stylistic/comma-spacing': [
'warn',
{
before: false,
after: true,
},
],
'@stylistic/comma-style': [
'error',
'last',
],
'@stylistic/dot-location': [
'error',
'property',
],
'@stylistic/function-call-argument-newline': [
'warn',
'consistent',
],
'@stylistic/function-paren-newline': [
'warn',
'consistent',
],
'@stylistic/indent': [
'warn',
4,
{
SwitchCase: 1,
ignoreComments: true,
ignoredNodes: ['TemplateLiteral > *'],
},
],
'@stylistic/key-spacing': [
'warn',
{
beforeColon: false,
afterColon: true,
},
],
'@stylistic/keyword-spacing': [
'warn',
{
before: true,
},
],
'@stylistic/linebreak-style': [
'error',
'unix',
],
'@stylistic/lines-between-class-members': [
'warn',
'always',
{
exceptAfterSingleLine: true,
},
],
'@stylistic/max-len': [
'warn',
{
code: 105,
ignoreComments: true,
ignoreTrailingComments: true,
ignoreUrls: true,
},
],
'@stylistic/multiline-ternary': [
'warn',
'always-multiline',
],
'@stylistic/new-parens': [
'error',
],
'@stylistic/no-mixed-operators': [
'warn',
],
'@stylistic/no-mixed-spaces-and-tabs': [
'error',
],
'@stylistic/no-multi-spaces': [
'error',
],
'@stylistic/no-tabs': [
'error',
],
'@stylistic/no-trailing-spaces': [
'error',
],
'@stylistic/no-whitespace-before-property': [
'warn',
],
'@stylistic/nonblock-statement-body-position': [
'error',
'below',
],
'@stylistic/object-curly-newline': [
'warn',
{
consistent: true,
},
],
'@stylistic/object-curly-spacing': [
'warn',
'always',
],
'@stylistic/operator-linebreak': [
'warn',
'after',
],
'@stylistic/padded-blocks': [
'error',
'never',
],
'@stylistic/padding-line-between-statements': [
'warn',
{
blankLine: 'always',
prev: '*',
next: 'return',
},
{
blankLine: 'always',
prev: [
'const',
'let',
'var',
],
next: '*',
},
{
blankLine: 'any',
prev: [
'const',
'let',
'var',
],
next: [
'const',
'let',
'var',
],
},
{
blankLine: 'always',
prev: [
'case',
'default',
],
next: '*',
},
],
'@stylistic/quote-props': [
'error',
'consistent-as-needed',
],
'@stylistic/quotes': [
'error',
'single',
{
avoidEscape: true,
},
],
'@stylistic/semi': [
'error',
'always',
],
'@stylistic/semi-spacing': [
'warn',
],
'@stylistic/space-before-blocks': [
'warn',
],
'@stylistic/space-before-function-paren': [
'warn',
'never',
],
'@stylistic/space-infix-ops': [
'warn',
],
'@stylistic/spaced-comment': [
'warn',
'always',
],
'@stylistic/switch-colon-spacing': [
'warn',
],
'@stylistic/wrap-regex': [
'warn',
],
},
},
);

BIN
apps/update/package-lock.json generated Normal file

Binary file not shown.

23
apps/update/package.json Normal file
View file

@ -0,0 +1,23 @@
{
"name": "update-flake",
"version": "0.0.0",
"bin": "out/bin/app.cjs",
"type": "module",
"scripts": {
"build": "node_ver=$(node -v); esbuild app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
},
"devDependencies": {
"@eslint/js": "9.7.0",
"@stylistic/eslint-plugin": "2.3.0",
"@types/eslint__js": "8.42.3",
"@types/node": "20.14.11",
"esbuild": "0.23.0",
"eslint": "9.7.0",
"eslint-plugin-jsdoc": "48.7.0",
"typescript": "5.5.3",
"typescript-eslint": "7.16.1"
},
"overrides": {
"eslint": "$eslint"
}
}

31
apps/update/tsconfig.json Normal file
View file

@ -0,0 +1,31 @@
{
"compilerOptions": {
// Env
"target": "ESNext",
"lib": ["ESNext"],
// Module
"module": "nodenext",
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true,
"baseUrl": ".",
// Emit
"noEmit": true,
"newLine": "LF",
// Interop
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
// Type Checking
"strict": true,
"noImplicitAny": false,
"allowJs": true,
"checkJs": true
},
"includes": [
"*.ts",
"**/*.ts",
"*.js",
"**/*.js"
]
}

View file

@ -163,6 +163,16 @@
formatter = perSystem (_: pkgs: pkgs.alejandra);
# Scripts
apps = perSystem (system: pkgs: let
inherit (pkgs) lib callPackage;
in {
updateFlake = {
program = lib.getExe (callPackage ./apps/update ({} // inputs));
type = "app";
};
});
# For nix-fast-build
checks =
perSystem (system: pkgs: