Chore: Update eslint configuration (#224)

- Update missing dev dependencies
- Fix root .eslintrc.json and client and server versions
- Add lint.yaml workflow
- Remove babel settings
- Clean up and fix eslint and ts errors
This commit is contained in:
Elisha Nuchi
2024-06-02 18:01:12 -04:00
committed by GitHub
parent a976451c78
commit 85223ca42a
19 changed files with 1411 additions and 594 deletions
+20 -14
View File
@@ -1,31 +1,37 @@
{ {
"root": true, "root": true,
"parser": "@typescript-eslint/parser",
"extends": [ "extends": [
"airbnb-base", "airbnb-base",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended"
"plugin:react-hooks/recommended"
], ],
"plugins": ["react-refresh", "prettier"], "plugins": ["prettier", "googleappsscript"],
"env": {
"googleappsscript/googleappsscript": true
},
"rules": { "rules": {
"prettier/prettier": "error", "prettier/prettier": "error",
"camelcase": "warn", "camelcase": "warn",
"import/prefer-default-export": "warn", "import/prefer-default-export": "warn",
"import/no-extraneous-dependencies": "warn", "import/no-extraneous-dependencies": "warn",
"prefer-object-spread": "warn", "prefer-object-spread": "warn",
"spaced-comment": "off", "import/extensions": [
"react-refresh/only-export-components": [ "error",
"warn", "ignorePackages",
{ "allowConstantExport": true } {
"js": "never",
"ts": "never"
}
] ]
}, },
"parserOptions": {
"babelOptions": {
"configFile": "./dev/.babelrc"
}
},
"env": { "browser": true, "es2020": true },
"ignorePatterns": ["dist", ".eslintrc.json"], "ignorePatterns": ["dist", ".eslintrc.json"],
"parser": "@typescript-eslint/parser" "settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts"]
}
}
}
} }
+18
View File
@@ -0,0 +1,18 @@
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: macos-13
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install packages
run: yarn install
- name: Run lint
run: yarn lint
+4 -3
View File
@@ -9,6 +9,7 @@
}, },
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"lint": "eslint .",
"test:integration": "jest --forceExit test/local-development.test", "test:integration": "jest --forceExit test/local-development.test",
"test:integration:extended": "cross-env IS_EXTENDED=true jest --forceExit test/local-development.test", "test:integration:extended": "cross-env IS_EXTENDED=true jest --forceExit test/local-development.test",
"test:integration:extended:ci-reporter": "cross-env IS_EXTENDED=true jest --forceExit || node test/utils/image-reporter-standalone.js", "test:integration:extended:ci-reporter": "cross-env IS_EXTENDED=true jest --forceExit || node test/utils/image-reporter-standalone.js",
@@ -48,9 +49,7 @@
"react-transition-group": "^4.4.2" "react-transition-group": "^4.4.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.24.4", "@babel/preset-env": "^7.24.6",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.24.4",
"@google/clasp": "^2.4.2", "@google/clasp": "^2.4.2",
"@types/expect-puppeteer": "^5.0.0", "@types/expect-puppeteer": "^5.0.0",
"@types/jest-environment-puppeteer": "^5.0.2", "@types/jest-environment-puppeteer": "^5.0.2",
@@ -69,6 +68,7 @@
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-googleappsscript": "^1.0.4", "eslint-plugin-googleappsscript": "^1.0.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^26.5.3", "eslint-plugin-jest": "^26.5.3",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
@@ -83,6 +83,7 @@
"puppeteer": "^14.3.0", "puppeteer": "^14.3.0",
"puppeteer-extra": "^3.2.3", "puppeteer-extra": "^3.2.3",
"puppeteer-extra-plugin-stealth": "^2.9.0", "puppeteer-extra-plugin-stealth": "^2.9.0",
"rollup": "^4.18.0",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"vite": "^5.2.0", "vite": "^5.2.0",
-8
View File
@@ -1,8 +0,0 @@
{
"presets": ["@babel/react"],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-optional-chaining"
]
}
+12 -21
View File
@@ -1,35 +1,24 @@
{ {
"root": true, "root": true,
"parser": "@babel/eslint-parser",
"extends": [ "extends": [
"airbnb-base", "airbnb-base",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"plugin:react/recommended" "eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended"
], ],
"plugins": ["babel", "react", "prettier"], "plugins": ["react-refresh", "prettier"],
"env": {
"browser": true,
"es6": true
},
"globals": {
"google": false,
"alert": false,
"css": true
},
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": { "rules": {
"prettier/prettier": "error", "prettier/prettier": "error",
"react/prop-types": "warn",
"camelcase": "warn", "camelcase": "warn",
"import/prefer-default-export": "warn", "import/prefer-default-export": "warn",
"import/no-extraneous-dependencies": "warn", "import/no-extraneous-dependencies": "warn",
"prefer-object-spread": "warn", "prefer-object-spread": "warn",
"spaced-comment": "off",
"react-refresh/only-export-components": [
"warn",
{ "allowConstantExport": true }
],
"import/extensions": [ "import/extensions": [
"error", "error",
"ignorePackages", "ignorePackages",
@@ -50,5 +39,7 @@
"extensions": [".js", ".jsx", ".ts", ".tsx"] "extensions": [".js", ".jsx", ".ts", ".tsx"]
} }
} }
} },
"env": { "browser": true, "es2020": true },
"parser": "@typescript-eslint/parser"
} }
@@ -23,9 +23,7 @@ const FormInput = ({ submitNewSheet }: FormInputProps) => {
}; };
return ( return (
<form <form onSubmit={handleSubmit}>
onSubmit={handleSubmit}
>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={10}> <Grid item xs={10}>
<TextField <TextField
@@ -4,7 +4,6 @@ import { Button, Typography } from '@mui/material';
import FormInput from './FormInput'; import FormInput from './FormInput';
import SheetTable from './SheetTable'; import SheetTable from './SheetTable';
// This is a wrapper for google.script.run that lets us use promises. // This is a wrapper for google.script.run that lets us use promises.
import { serverFunctions } from '../../utils/serverFunctions'; import { serverFunctions } from '../../utils/serverFunctions';
@@ -40,29 +39,40 @@ const SheetEditor = () => {
</Typography> </Typography>
<Typography variant="body1" gutterBottom sx={{ marginBottom: '30px' }}> <Typography variant="body1" gutterBottom sx={{ marginBottom: '30px' }}>
This is a sample app that uses the <code>mui</code> library This is a sample app that uses the <code>mui</code> library to help us
to help us build a simple React app. Enter a name for a new sheet, hit build a simple React app. Enter a name for a new sheet, hit enter and
enter and the new sheet will be created. Click the red button next to the sheet name to the new sheet will be created. Click the red button next to the sheet
delete it. name to delete it.
</Typography> </Typography>
<FormInput submitNewSheet={submitNewSheet} /> <FormInput submitNewSheet={submitNewSheet} />
{names.length > 0 && {names.length > 0 && (
<SheetTable rows={names.map((name) => { <SheetTable
return { rows={names.map((name) => {
sheetName: name.name, return {
goToButton: <Button sheetName: name.name,
variant="outlined" goToButton: (
disabled={name?.isActive} <Button
onClick={() => setActiveSheet(name.name)} variant="outlined"
>Go To Sheet</Button>, disabled={name?.isActive}
deleteButton: <Button onClick={() => setActiveSheet(name.name)}
variant="contained" >
color="error" Go To Sheet
onClick={() => deleteSheet(name.index)} </Button>
>Delete</Button> ),
} deleteButton: (
})} />} <Button
variant="contained"
color="error"
onClick={() => deleteSheet(name.index)}
>
Delete
</Button>
),
};
})}
/>
)}
</div> </div>
); );
}; };
@@ -1,5 +1,12 @@
import * as React from 'react'; import * as React from 'react';
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material'; import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from '@mui/material';
type sheetRow = { type sheetRow = {
sheetName: string; sheetName: string;
@@ -1,7 +1,11 @@
import { useState, ChangeEvent, FormEvent } from 'react'; import { useState, ChangeEvent, FormEvent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const FormInput = ({ submitNewSheet }: { submitNewSheet: Function }) => { const FormInput = ({
submitNewSheet,
}: {
submitNewSheet: (arg: string) => void;
}) => {
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
const handleChange = (event: ChangeEvent<HTMLInputElement>) => const handleChange = (event: ChangeEvent<HTMLInputElement>) =>
-18
View File
@@ -1,18 +0,0 @@
{
"presets": [
[
"@babel/env",
{
"modules": false
}
]
],
"plugins": [
"transform-es3-property-literals",
"transform-es3-member-expression-literals",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-object-assign",
"@babel/plugin-proposal-optional-chaining"
]
}
+16 -3
View File
@@ -1,7 +1,12 @@
{ {
"root": true, "root": true,
"parser": "@babel/eslint-parser", "parser": "@typescript-eslint/parser",
"extends": ["airbnb-base", "plugin:prettier/recommended"], "extends": [
"airbnb-base",
"plugin:prettier/recommended",
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"plugins": ["prettier", "googleappsscript"], "plugins": ["prettier", "googleappsscript"],
"env": { "env": {
"googleappsscript/googleappsscript": true "googleappsscript/googleappsscript": true
@@ -11,7 +16,15 @@
"camelcase": "warn", "camelcase": "warn",
"import/prefer-default-export": "warn", "import/prefer-default-export": "warn",
"import/no-extraneous-dependencies": "warn", "import/no-extraneous-dependencies": "warn",
"prefer-object-spread": "warn" "prefer-object-spread": "warn",
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"ts": "never"
}
]
}, },
"settings": { "settings": {
"import/resolver": { "import/resolver": {
+1 -1
View File
@@ -1,3 +1,3 @@
{ {
"presets": ["@babel/preset-env"] "presets": ["@babel/preset-env"]
} }
+6 -3
View File
@@ -1,12 +1,14 @@
{ {
"root": true, "root": true,
"parser": "@babel/eslint-parser", "parser": "@typescript-eslint/parser",
"extends": [ "extends": [
"airbnb-base", "airbnb-base",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended" "plugin:jest/recommended"
], ],
"plugins": ["babel", "prettier"], "plugins": ["prettier"],
"env": { "env": {
"browser": true, "browser": true,
"es6": true, "es6": true,
@@ -27,8 +29,9 @@
"jest/no-done-callback": "off", "jest/no-done-callback": "off",
"prettier/prettier": "error", "prettier/prettier": "error",
"camelcase": "warn", "camelcase": "warn",
"import/prefer-default-export": "warn", "import/prefer-default-export": "off",
"import/no-extraneous-dependencies": "warn", "import/no-extraneous-dependencies": "warn",
"import/extensions": "off",
"jest/expect-expect": "off", "jest/expect-expect": "off",
"no-new": "off", "no-new": "off",
"no-underscore-dangle": "off" "no-underscore-dangle": "off"
+8 -4
View File
@@ -3,7 +3,6 @@
// This allows using stealth mode. // This allows using stealth mode.
import fs from 'fs'; import fs from 'fs';
const fsPromises = fs.promises;
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import puppeteer from 'puppeteer-extra'; import puppeteer from 'puppeteer-extra';
@@ -11,9 +10,11 @@ import puppeteer from 'puppeteer-extra';
// add stealth plugin and use defaults (all evasion techniques) // add stealth plugin and use defaults (all evasion techniques)
import StealthPlugin from 'puppeteer-extra-plugin-stealth'; import StealthPlugin from 'puppeteer-extra-plugin-stealth';
const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
import jestPuppeteerConfig from './jest-puppeteer.config.js'; import jestPuppeteerConfig from './jest-puppeteer.config.js';
const fsPromises = fs.promises;
const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
export default async function globalSetup() { export default async function globalSetup() {
puppeteer.use(StealthPlugin()); puppeteer.use(StealthPlugin());
const browser = await puppeteer.launch(jestPuppeteerConfig.launch); const browser = await puppeteer.launch(jestPuppeteerConfig.launch);
@@ -23,5 +24,8 @@ export default async function globalSetup() {
// use the file system to expose the wsEndpoint for TestEnvironments // use the file system to expose the wsEndpoint for TestEnvironments
await fsPromises.mkdir(DIR, { recursive: true }); await fsPromises.mkdir(DIR, { recursive: true });
await fsPromises.writeFile(path.join(DIR, 'wsEndpoint'), browser.wsEndpoint()); await fsPromises.writeFile(
}; path.join(DIR, 'wsEndpoint'),
browser.wsEndpoint()
);
}
+3 -2
View File
@@ -3,10 +3,11 @@
// This allows using stealth mode. // This allows using stealth mode.
import fs from 'fs'; import fs from 'fs';
const fsPromises = fs.promises;
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
const fsPromises = fs.promises;
const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup'); const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
export default async function globalTeardown() { export default async function globalTeardown() {
// close the browser instance // close the browser instance
@@ -14,4 +15,4 @@ export default async function globalTeardown() {
// clean-up the wsEndpoint file // clean-up the wsEndpoint file
await fsPromises.rmdir(DIR, { recursive: true, force: true }); await fsPromises.rmdir(DIR, { recursive: true, force: true });
}; }
+4 -2
View File
@@ -2,9 +2,9 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
import { exec } from 'child_process'; import { exec } from 'child_process';
import { configureToMatchImageSnapshot } from 'jest-image-snapshot'; import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
import dotenv from 'dotenv';
import { openAddon } from './utils/open-addon'; import { openAddon } from './utils/open-addon';
import dotenv from 'dotenv';
dotenv.config(); dotenv.config();
const isExtended = `${process.env.IS_EXTENDED}` === 'true'; const isExtended = `${process.env.IS_EXTENDED}` === 'true';
@@ -57,7 +57,9 @@ describe(`Local setup ${isExtended ? '*extended*' : ''}`, () => {
if (isExtended) { if (isExtended) {
await openAddon(page); await openAddon(page);
} else { } else {
await page.goto('https://localhost:3000/dialog-demo-bootstrap/index.html'); await page.goto(
'https://localhost:3000/dialog-demo-bootstrap/index.html'
);
await page.waitForTimeout(3000); await page.waitForTimeout(3000);
} }
}); });
+1 -5
View File
@@ -11,10 +11,6 @@ import NodeEnvironment from 'jest-environment-node';
const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup'); const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
export default class PuppeteerEnvironment extends NodeEnvironment.default { export default class PuppeteerEnvironment extends NodeEnvironment.default {
constructor(config) {
super(config);
}
async setup() { async setup() {
await super.setup(); await super.setup();
// get the wsEndpoint // get the wsEndpoint
@@ -36,4 +32,4 @@ export default class PuppeteerEnvironment extends NodeEnvironment.default {
getVmContext() { getVmContext() {
return super.getVmContext(); return super.getVmContext();
} }
} }
+7 -2
View File
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import { resolve } from 'path'; import { resolve } from 'path';
import { BuildOptions, ServerOptions, build, defineConfig } from 'vite'; import { BuildOptions, ServerOptions, build, defineConfig } from 'vite';
import { existsSync, readFileSync } from 'fs'; import { existsSync, readFileSync } from 'fs';
@@ -150,7 +151,7 @@ const buildConfig = ({ mode }: { mode: string }) => {
...clientEntrypoints.map((entrypoint) => ({ ...clientEntrypoints.map((entrypoint) => ({
src: devServerWrapper, src: devServerWrapper,
dest: './', dest: './',
rename: entrypoint.filename + '.html', rename: `${entrypoint.filename}.html`,
transform: (contents: string) => transform: (contents: string) =>
contents contents
.toString() .toString()
@@ -175,16 +176,19 @@ const buildConfig = ({ mode }: { mode: string }) => {
name: 'build-client-production-bundles', name: 'build-client-production-bundles',
closeBundle: async () => { closeBundle: async () => {
console.log('Building client production bundles...'); console.log('Building client production bundles...');
// eslint-disable-next-line no-restricted-syntax
for (const clientEntrypoint of clientEntrypoints) { for (const clientEntrypoint of clientEntrypoints) {
console.log('Building client bundle for', clientEntrypoint.name); console.log('Building client bundle for', clientEntrypoint.name);
// eslint-disable-next-line no-await-in-loop
const buildOutput = await build( const buildOutput = await build(
clientBuildConfig({ clientBuildConfig({
clientEntrypointRoot: clientEntrypoint.filename, clientEntrypointRoot: clientEntrypoint.filename,
template: clientEntrypoint.template, template: clientEntrypoint.template,
}) })
); );
// eslint-disable-next-line no-await-in-loop
await writeFile( await writeFile(
resolve(__dirname, outDir, clientEntrypoint.filename + '.html'), resolve(__dirname, outDir, `${clientEntrypoint.filename}.html`),
// @ts-expect-error - output is an array of RollupOutput // @ts-expect-error - output is an array of RollupOutput
buildOutput.output[0].source buildOutput.output[0].source
); );
@@ -207,4 +211,5 @@ export default async ({ command, mode }: { command: string; mode: string }) => {
// for 'build' mode, we have two paths: build assets for local development, and build for production // for 'build' mode, we have two paths: build assets for local development, and build for production
return buildConfig({ mode }); return buildConfig({ mode });
} }
return {};
}; };
+1266 -482
View File
File diff suppressed because it is too large Load Diff