From 75fad5aaf8295bf9b4bda93c0aa59695a24ebe2b Mon Sep 17 00:00:00 2001 From: Michael Gauthier Date: Thu, 28 May 2026 11:09:23 -0300 Subject: [PATCH] Update to use shared silverorange linting rules --- eslint.config.mjs | 97 +-------- package.json | 12 +- pnpm-lock.yaml | 382 ++++++++++++++++++++---------------- src/compileLess.ts | 64 +++--- src/composerDumpAutoload.ts | 24 ++- src/execFile.ts | 17 ++ src/getSymlinks.ts | 11 +- src/hashQueue.ts | 6 +- src/legaseer.ts | 12 +- src/lintPhpSyntax.ts | 49 ++--- src/setupSymlinks.ts | 3 +- 11 files changed, 324 insertions(+), 353 deletions(-) create mode 100644 src/execFile.ts diff --git a/eslint.config.mjs b/eslint.config.mjs index 351ad9a..f8509c2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,96 +1,11 @@ -import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; -import eslintConfigPrettier from 'eslint-config-prettier'; +import { defineConfig } from 'eslint/config'; +import { config } from '@silverorange-inc/eslint-config-node'; -export default tseslint.config( - eslint.configs.recommended, - tseslint.configs.strict, - eslintConfigPrettier, +export default defineConfig([ + config, { rules: { - 'constructor-super': 'error', - curly: 'error', - 'dot-notation': 'error', - 'guard-for-in': 'error', - 'new-parens': 'error', - 'no-bitwise': 'error', - 'no-caller': 'error', - 'no-cond-assign': 'error', - 'no-debugger': 'error', - 'no-empty': 'error', - 'no-empty-function': 'error', - 'no-new-wrappers': 'error', - 'no-throw-literal': 'error', - 'no-undef-init': 'error', - 'no-unsafe-finally': 'error', - 'no-unused-labels': 'error', - 'object-shorthand': 'error', - 'one-var': ['error', 'never'], - 'prefer-const': 'error', - radix: 'error', - 'use-isnan': 'error', - 'no-shadow': 'error', - 'no-unused-expressions': 'error', + 'no-console': 'off', }, }, - { - rules: { - '@typescript-eslint/adjacent-overload-signatures': 'error', - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: ['function', 'memberLike'], - format: ['camelCase'], - }, - { - selector: ['property', 'variable'], - format: ['camelCase', 'UPPER_CASE', 'PascalCase'], - }, - { - // Allow any format in object literals (like this one) - selector: ['objectLiteralProperty'], - format: null, - }, - { - selector: ['parameter'], - format: ['camelCase'], - filter: { - regex: '^_+$', - match: false, - }, - }, - { selector: 'typeLike', format: ['PascalCase'] }, - ], - '@typescript-eslint/no-unused-vars': [ - 'error', - { - args: 'all', - argsIgnorePattern: '^_', - caughtErrors: 'all', - caughtErrorsIgnorePattern: '^_', - destructuredArrayIgnorePattern: '^_', - varsIgnorePattern: '^_', - ignoreRestSiblings: true, - }, - ], - '@typescript-eslint/explicit-member-accessibility': [ - 'error', - { - overrides: { - constructors: 'no-public', - }, - }, - ], - '@typescript-eslint/consistent-type-assertions': [ - 'error', - { assertionStyle: 'as' }, - ], - '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], - '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/prefer-function-type': 'error', - '@typescript-eslint/unified-signatures': 'error', - }, - }, -); +]); diff --git a/package.json b/package.json index 5cbcca8..734b864 100644 --- a/package.json +++ b/package.json @@ -36,21 +36,19 @@ "globby": "^16.1.1", "minimist": "^1.2.5", "postcss": "^8.5.8", - "proper-lockfile": "^4.1.2" + "proper-lockfile": "^4.1.2", + "zod": "^4.4.3" }, "devDependencies": { - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "^10.0.1", + "@silverorange-inc/eslint-config-node": "^1.0.2", "@types/fancy-log": "^2.0.2", "@types/minimist": "^1.2.1", "@types/node": "^25.5.0", "@types/proper-lockfile": "^4.1.1", - "eslint": "^10.0.3", - "eslint-config-prettier": "^10.1.8", + "eslint": "^9.39.4", "prettier": "^3.8.1", "tsx": "^4.21.0", - "typescript": "^5.9.3", - "typescript-eslint": "^8.57.0" + "typescript": "^5.9.3" }, "overrides": { "brace-expansion": "^1.1.13" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 400fe94..611ef9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,13 +32,13 @@ importers: proper-lockfile: specifier: ^4.1.2 version: 4.1.2 + zod: + specifier: ^4.4.3 + version: 4.4.3 devDependencies: - '@eslint/eslintrc': - specifier: ^3.3.5 - version: 3.3.5 - '@eslint/js': - specifier: ^10.0.1 - version: 10.0.1(eslint@10.0.3) + '@silverorange-inc/eslint-config-node': + specifier: ^1.0.2 + version: 1.0.2(eslint@9.39.4)(typescript@5.9.3) '@types/fancy-log': specifier: ^2.0.2 version: 2.0.2 @@ -52,11 +52,8 @@ importers: specifier: ^4.1.1 version: 4.1.4 eslint: - specifier: ^10.0.3 - version: 10.0.3 - eslint-config-prettier: - specifier: ^10.1.8 - version: 10.1.8(eslint@10.0.3) + specifier: ^9.39.4 + version: 9.39.4 prettier: specifier: ^3.8.1 version: 3.8.1 @@ -66,9 +63,6 @@ importers: typescript: specifier: ^5.9.3 version: 5.9.3 - typescript-eslint: - specifier: ^8.57.0 - version: 8.57.0(eslint@10.0.3)(typescript@5.9.3) packages: @@ -254,38 +248,33 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.23.3': - resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.5.3': - resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@1.1.1': - resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.5': resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@10.0.1': - resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - peerDependencies: - eslint: ^10.0.0 - peerDependenciesMeta: - eslint: - optional: true + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@3.0.3': - resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.6.1': - resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -315,13 +304,16 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@silverorange-inc/eslint-config-node@1.0.2': + resolution: {integrity: sha512-OQaNsz68cs1V9mE0YkAecFQT9PIWNKoYeDkdHDNwM8yBKELoV8eAa9QL6WhN/05fLEFV4FIBcsWDEHKlQFCZcQ==} + engines: {node: ^22.14.0} + peerDependencies: + eslint: ^9.39.4 + '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@types/esrecurse@4.3.1': - resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -343,63 +335,63 @@ packages: '@types/retry@0.12.5': resolution: {integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==} - '@typescript-eslint/eslint-plugin@8.57.0': - resolution: {integrity: sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==} + '@typescript-eslint/eslint-plugin@8.60.0': + resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.57.0 + '@typescript-eslint/parser': ^8.60.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.57.0': - resolution: {integrity: sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==} + '@typescript-eslint/parser@8.60.0': + resolution: {integrity: sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.57.0': - resolution: {integrity: sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==} + '@typescript-eslint/project-service@8.60.0': + resolution: {integrity: sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.57.0': - resolution: {integrity: sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==} + '@typescript-eslint/scope-manager@8.60.0': + resolution: {integrity: sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.57.0': - resolution: {integrity: sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==} + '@typescript-eslint/tsconfig-utils@8.60.0': + resolution: {integrity: sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.57.0': - resolution: {integrity: sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==} + '@typescript-eslint/type-utils@8.60.0': + resolution: {integrity: sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.57.0': - resolution: {integrity: sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==} + '@typescript-eslint/types@8.60.0': + resolution: {integrity: sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.57.0': - resolution: {integrity: sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==} + '@typescript-eslint/typescript-estree@8.60.0': + resolution: {integrity: sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.57.0': - resolution: {integrity: sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==} + '@typescript-eslint/utils@8.60.0': + resolution: {integrity: sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.57.0': - resolution: {integrity: sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==} + '@typescript-eslint/visitor-keys@8.60.0': + resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -419,6 +411,10 @@ packages: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -444,10 +440,21 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true @@ -486,9 +493,9 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-scope@9.1.2: - resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} @@ -502,9 +509,9 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.0.3: - resolution: {integrity: sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: jiti: '*' @@ -516,10 +523,6 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@11.2.0: - resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -611,6 +614,10 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -670,6 +677,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -807,6 +817,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -815,8 +829,8 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - ts-api-utils@2.4.0: - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -830,12 +844,12 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.57.0: - resolution: {integrity: sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==} + typescript-eslint@8.60.0: + resolution: {integrity: sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} @@ -865,6 +879,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + snapshots: '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': @@ -957,26 +974,26 @@ snapshots: '@esbuild/win32-x64@0.27.4': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3)': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': dependencies: - eslint: 10.0.3 + eslint: 9.39.4 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.23.3': + '@eslint/config-array@0.21.2': dependencies: - '@eslint/object-schema': 3.0.3 + '@eslint/object-schema': 2.1.7 debug: 4.4.3 - minimatch: 10.2.4 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.3': + '@eslint/config-helpers@0.4.2': dependencies: - '@eslint/core': 1.1.1 + '@eslint/core': 0.17.0 - '@eslint/core@1.1.1': + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 @@ -994,15 +1011,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@10.0.1(eslint@10.0.3)': - optionalDependencies: - eslint: 10.0.3 + '@eslint/js@9.39.4': {} - '@eslint/object-schema@3.0.3': {} + '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.6.1': + '@eslint/plugin-kit@0.4.1': dependencies: - '@eslint/core': 1.1.1 + '@eslint/core': 0.17.0 levn: 0.4.1 '@humanfs/core@0.19.1': {} @@ -1028,9 +1043,17 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@sindresorhus/merge-streams@4.0.0': {} + '@silverorange-inc/eslint-config-node@1.0.2(eslint@9.39.4)(typescript@5.9.3)': + dependencies: + '@eslint/js': 9.39.4 + eslint: 9.39.4 + eslint-config-prettier: 10.1.8(eslint@9.39.4) + typescript-eslint: 8.60.0(eslint@9.39.4)(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + - typescript - '@types/esrecurse@4.3.1': {} + '@sindresorhus/merge-streams@4.0.0': {} '@types/estree@1.0.8': {} @@ -1050,95 +1073,95 @@ snapshots: '@types/retry@0.12.5': {} - '@typescript-eslint/eslint-plugin@8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3)(typescript@5.9.3))(eslint@10.0.3)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.0(eslint@10.0.3)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/type-utils': 8.57.0(eslint@10.0.3)(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.0 - eslint: 10.0.3 + '@typescript-eslint/parser': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/type-utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.0 + eslint: 9.39.4 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.0(eslint@10.0.3)(typescript@5.9.3)': + '@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.0 debug: 4.4.3 - eslint: 10.0.3 + eslint: 9.39.4 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.57.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.60.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3) - '@typescript-eslint/types': 8.57.0 + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3) + '@typescript-eslint/types': 8.60.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.57.0': + '@typescript-eslint/scope-manager@8.60.0': dependencies: - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 - '@typescript-eslint/tsconfig-utils@8.57.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.60.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.57.0(eslint@10.0.3)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3)(typescript@5.9.3) + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) debug: 4.4.3 - eslint: 10.0.3 - ts-api-utils: 2.4.0(typescript@5.9.3) + eslint: 9.39.4 + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.57.0': {} + '@typescript-eslint/types@8.60.0': {} - '@typescript-eslint/typescript-estree@8.57.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.60.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.57.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.57.0(typescript@5.9.3) - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/visitor-keys': 8.57.0 + '@typescript-eslint/project-service': 8.60.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3) + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 debug: 4.4.3 minimatch: 10.2.4 semver: 7.7.4 tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.0(eslint@10.0.3)(typescript@5.9.3)': + '@typescript-eslint/utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3) - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - eslint: 10.0.3 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + eslint: 9.39.4 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.57.0': + '@typescript-eslint/visitor-keys@8.60.0': dependencies: - '@typescript-eslint/types': 8.57.0 + '@typescript-eslint/types': 8.60.0 eslint-visitor-keys: 5.0.1 acorn-jsx@5.3.2(acorn@8.16.0): @@ -1156,6 +1179,10 @@ snapshots: ansi-colors@4.1.3: {} + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + argparse@2.0.1: {} balanced-match@1.0.2: {} @@ -1177,10 +1204,21 @@ snapshots: callsites@3.1.0: {} + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chokidar@5.0.0: dependencies: readdirp: 5.0.0 + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + color-support@1.1.3: {} concat-map@0.0.1: {} @@ -1228,14 +1266,12 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.0.3): + eslint-config-prettier@10.1.8(eslint@9.39.4): dependencies: - eslint: 10.0.3 + eslint: 9.39.4 - eslint-scope@9.1.2: + eslint-scope@8.4.0: dependencies: - '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -1245,25 +1281,28 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.0.3: + eslint@9.39.4: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.3 - '@eslint/config-helpers': 0.5.3 - '@eslint/core': 1.1.1 - '@eslint/plugin-kit': 0.6.1 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 ajv: 6.14.0 + chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 9.1.2 - eslint-visitor-keys: 5.0.1 - espree: 11.2.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -1274,7 +1313,8 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.4 + lodash.merge: 4.6.2 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -1286,12 +1326,6 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 4.2.1 - espree@11.2.0: - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - eslint-visitor-keys: 5.0.1 - esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -1378,6 +1412,8 @@ snapshots: graceful-fs@4.2.11: {} + has-flag@4.0.0: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -1424,6 +1460,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.merge@4.6.2: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -1528,6 +1566,10 @@ snapshots: strip-json-comments@3.1.1: {} + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -1537,7 +1579,7 @@ snapshots: dependencies: is-number: 7.0.0 - ts-api-utils@2.4.0(typescript@5.9.3): + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -1552,13 +1594,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.57.0(eslint@10.0.3)(typescript@5.9.3): + typescript-eslint@8.60.0(eslint@9.39.4)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.57.0(@typescript-eslint/parser@8.57.0(eslint@10.0.3)(typescript@5.9.3))(eslint@10.0.3)(typescript@5.9.3) - '@typescript-eslint/parser': 8.57.0(eslint@10.0.3)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.0(eslint@10.0.3)(typescript@5.9.3) - eslint: 10.0.3 + '@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/parser': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + eslint: 9.39.4 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -1580,3 +1622,5 @@ snapshots: word-wrap@1.2.5: {} yocto-queue@0.1.0: {} + + zod@4.4.3: {} diff --git a/src/compileLess.ts b/src/compileLess.ts index f33b811..2198c58 100644 --- a/src/compileLess.ts +++ b/src/compileLess.ts @@ -1,11 +1,11 @@ import fs from 'node:fs'; import { relative, dirname } from 'node:path'; -import { execFile } from 'node:child_process'; import log from 'fancy-log'; import colors from 'ansi-colors'; import postcss from 'postcss'; import postcssRebaseURL from '@csstools/postcss-rebase-url'; import paths from './paths.js'; +import { execFile, isExecFileException } from './execFile.js'; const fsPromises = fs.promises; @@ -102,46 +102,32 @@ function rebaseUrls(css: string, from: string, to: string) { }); } -function compileLessFile(fileName: string) { - return new Promise((resolve, reject) => { - execFile('lessc', [fileName], (error, stdout, stderr) => { - if (error !== null) { - if (error.code === 1) { - log('Error compiling', colors.red(fileName)); - console.error(); - console.error(stderr.trim()); - console.error(); - resolve(); - } else { - console.error(stderr); - log(`exec error: ${error}`); - reject(error); - } +async function compileLessFile(fileName: string) { + try { + const { stdout } = await execFile('lessc', [fileName]); + const outputFileName = getOutputFileName(fileName); + const css = await rebaseUrls(stdout, fileName, outputFileName); + + await fsPromises.mkdir(dirname(outputFileName), { recursive: true }); + await fsPromises.writeFile(outputFileName, css.toString()); + + log('Compiled', colors.cyan(fileName), 'to', colors.cyan(outputFileName)); + } catch (error) { + if (isExecFileException(error)) { + if (error.code === 1) { + log('Error compiling', colors.red(fileName)); + console.error(); + console.error((error.stderr ?? '').trim()); + console.error(); } else { - const outputFileName = getOutputFileName(fileName); - rebaseUrls(stdout, fileName, outputFileName).then((css) => { - fs.mkdir(dirname(outputFileName), { recursive: true }, (dirError) => { - if (dirError) { - reject(dirError); - } else { - fs.writeFile(outputFileName, css.toString(), (writeError) => { - if (writeError) { - reject(writeError); - } - log( - 'Compiled', - colors.cyan(fileName), - 'to', - colors.cyan(outputFileName), - ); - resolve(); - }); - } - }); - }); + console.error(error.stderr); + log(`exec error: ${error.message}`); + throw error; } - }); - }); + } else { + throw error; + } + } } export function compileAllLess(lessFiles: Set) { diff --git a/src/composerDumpAutoload.ts b/src/composerDumpAutoload.ts index dae3d96..72765f5 100644 --- a/src/composerDumpAutoload.ts +++ b/src/composerDumpAutoload.ts @@ -1,16 +1,14 @@ -import { execFile } from 'node:child_process'; import log from 'fancy-log'; +import { execFile, isExecFileException } from './execFile.js'; -export function composerDumpAutoload() { - return new Promise((resolve, reject) => { - execFile('composer', ['-q', 'dump-autoload'], (error) => { - if (error !== null) { - log(`exec error: ${error}`); - reject(error); - } else { - log('Rebuilt PHP autoloader map.'); - resolve(); - } - }); - }); +export async function composerDumpAutoload() { + try { + await execFile('composer', ['-q', 'dump-autoload']); + log('Rebuilt PHP autoloader map.'); + } catch (error) { + if (isExecFileException(error)) { + log(`exec error: ${error.message}`); + } + throw error; + } } diff --git a/src/execFile.ts b/src/execFile.ts new file mode 100644 index 0000000..e93394f --- /dev/null +++ b/src/execFile.ts @@ -0,0 +1,17 @@ +import type { ExecFileException } from 'node:child_process'; +import { promisify } from 'node:util'; + +export const execFile = promisify( + (await import('node:child_process')).execFile, +); + +export function isExecFileException( + error: unknown, +): error is ExecFileException { + return ( + error instanceof Error && + Object.hasOwn(error, 'code') && + Object.hasOwn(error, 'stdout') && + Object.hasOwn(error, 'stderr') + ); +} diff --git a/src/getSymlinks.ts b/src/getSymlinks.ts index 4703f1c..2ce5840 100644 --- a/src/getSymlinks.ts +++ b/src/getSymlinks.ts @@ -1,3 +1,4 @@ +import * as z from 'zod'; import minimist from 'minimist'; export function getSymlinks() { @@ -6,6 +7,12 @@ export function getSymlinks() { default: { symlinks: '' }, }; - const options = minimist(process.argv.slice(2), knownOptions); - return options.symlinks; + try { + return z + .object({ symlinks: z.string() }) + .transform(({ symlinks: value }) => value.split(',')) + .parse(minimist(process.argv.slice(2), knownOptions)); + } catch { + return []; + } } diff --git a/src/hashQueue.ts b/src/hashQueue.ts index 073406c..5b0f187 100644 --- a/src/hashQueue.ts +++ b/src/hashQueue.ts @@ -16,7 +16,7 @@ async function runQueued(key: string) { console.error(e); } hashRunning[key] = undefined; - runQueued(key); + await runQueued(key); } } @@ -24,5 +24,7 @@ export function queue(key: string, promise: () => Promise) { if (!hashQueue[key]) { hashQueue[key] = promise; } - runQueued(key); + + // intentionally do not await, we fire and forget + void runQueued(key); } diff --git a/src/legaseer.ts b/src/legaseer.ts index 3dc29a1..03d0401 100644 --- a/src/legaseer.ts +++ b/src/legaseer.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import readline from 'node:readline'; +import readline, { type Key } from 'node:readline'; import log from 'fancy-log'; import colors from 'ansi-colors'; import chokidar from 'chokidar'; @@ -113,11 +113,11 @@ async function main() { } process.on('SIGINT', () => { - shutdown(); + void shutdown(); }); process.on('SIGTERM', () => { - shutdown(); + void shutdown(); }); // Handling SIGINT when process is bootstrapped from Yarn does not work @@ -133,11 +133,11 @@ async function main() { process.stdin.setRawMode(true); } - process.stdin.on('keypress', (_, key) => { + process.stdin.on('keypress', (_, key: Key) => { if (key.ctrl && key.name === 'c') { - shutdown(); + void shutdown(); } }); } -main(); +await main(); diff --git a/src/lintPhpSyntax.ts b/src/lintPhpSyntax.ts index a89eff8..93266e2 100644 --- a/src/lintPhpSyntax.ts +++ b/src/lintPhpSyntax.ts @@ -1,33 +1,38 @@ -import { execFile } from 'node:child_process'; import log from 'fancy-log'; import colors from 'ansi-colors'; +import { execFile, isExecFileException } from './execFile.js'; export function lintPhpSyntax(fileName: string) { return async function lint() { - return new Promise((resolve, reject) => { - execFile('php', ['-l', fileName], (error, stdout, stderr) => { - if (error !== null && error.code !== 255) { - log(`exec error: ${error}`); - console.error(stderr); - reject(error); - } else { - // remove whitespace - let contents = stdout.replace(/(^\s+|\s+$)/g, ''); + let stdout: string = ''; - // exclude valid files from output - if (!/^No syntax errors detected in .*\.php/.test(contents)) { - // remove stdin filename - contents = contents.replace(/in .*\.php on line/, 'on line'); + try { + ({ stdout } = await execFile('php', ['-l', fileName])); + } catch (error) { + if (isExecFileException(error)) { + if (error.code !== 255) { + log(`exec error: ${error.message}`); + console.error(error.stderr); + throw error; + } - // remove unnecessary line - contents = contents.replace(/\s+Errors parsing .*\.php$/g, ''); + // There were linting errors, capture those. + stdout = error.stdout ?? ''; + } + } - log(colors.red('[PHP]'), fileName, '->', contents); - } + // remove whitespace + let contents = stdout.replace(/(^\s+|\s+$)/g, ''); - resolve(); - } - }); - }); + // exclude valid files from output + if (!/^No syntax errors detected in .*\.php/.test(contents)) { + // remove stdin filename + contents = contents.replace(/in .*\.php on line/, 'on line'); + + // remove unnecessary line + contents = contents.replace(/\s+Errors parsing .*\.php$/g, ''); + + log(colors.red('[PHP]'), fileName, '->', contents); + } }; } diff --git a/src/setupSymlinks.ts b/src/setupSymlinks.ts index b79b575..0c95938 100644 --- a/src/setupSymlinks.ts +++ b/src/setupSymlinks.ts @@ -11,8 +11,7 @@ import { getSymlinks } from './getSymlinks.js'; * * @param symlinks */ -function setup(symlinks: string) { - const packages = symlinks.split(','); +function setup(packages: string[]) { packages.forEach((packageName) => { let packageFound = false; paths.vendors.forEach((vendorPath) => {