diff --git a/BUCK b/BUCK index d3d038e40a..a667aa22f0 100644 --- a/BUCK +++ b/BUCK @@ -106,7 +106,6 @@ pnpm_workspace( "//app/auth-portal:package.json", "//app/web:package.json", "//bin/auth-api:package.json", - "//lib/eslint-config:package.json", "//lib/ts-lib:package.json", "//lib/tsconfig:package.json", "//lib/vue-lib:package.json", diff --git a/app/auth-portal/.eslintrc.cjs b/app/auth-portal/.eslintrc.cjs deleted file mode 100644 index 2d44205b7f..0000000000 --- a/app/auth-portal/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["@si/eslint-config/vue"], -}; diff --git a/app/auth-portal/.eslintrc.js b/app/auth-portal/.eslintrc.js new file mode 100644 index 0000000000..9fc387baac --- /dev/null +++ b/app/auth-portal/.eslintrc.js @@ -0,0 +1,9 @@ +import eslint from "@eslint/js"; +import pluginVue from "eslint-plugin-vue"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; + +export default [ + eslint.configs.recommended, + ...pluginVue.configs["flat/recommended"], + eslintPluginPrettierRecommended, +]; diff --git a/app/auth-portal/BUCK b/app/auth-portal/BUCK index 42e5c93b78..ae9562c79c 100644 --- a/app/auth-portal/BUCK +++ b/app/auth-portal/BUCK @@ -46,7 +46,6 @@ prod_deps_srcs = { } dev_deps_srcs = { - "lib/eslint-config": "//lib/eslint-config:src", "lib/tsconfig": "//lib/tsconfig:src", } @@ -60,7 +59,7 @@ vite_app( eslint( name = "check-lint-typescript", - srcs = [":src"] + glob([".eslint*"]), + srcs = [":src"] + glob(["*eslint*"]), prod_deps_srcs = prod_deps_srcs, dev_deps_srcs = dev_deps_srcs, ) diff --git a/app/auth-portal/eslint.config.ts b/app/auth-portal/eslint.config.ts new file mode 100644 index 0000000000..742a5d1877 --- /dev/null +++ b/app/auth-portal/eslint.config.ts @@ -0,0 +1,239 @@ +import { globalIgnores } from "eslint/config"; +import { + defineConfigWithVueTs, + vueTsConfigs, +} from "@vue/eslint-config-typescript"; +import pluginVue from "eslint-plugin-vue"; +import pluginVitest from "@vitest/eslint-plugin"; +import skipFormatting from "@vue/eslint-config-prettier/skip-formatting"; +import importPlugin from "eslint-plugin-import"; +import tselint from "typescript-eslint"; +import vueParser from "vue-eslint-parser"; +import { fileURLToPath } from "url"; +import path from "path"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// To allow more languages other than `ts` in `.vue` files, uncomment the following lines: +// import { configureVueProject } from '@vue/eslint-config-typescript' +// configureVueProject({ scriptLangs: ['ts', 'tsx'] }) +// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup + +export default defineConfigWithVueTs( + { + name: "app/files-to-lint", + files: ["**/*.{vue,ts,mts,tsx}"], + }, + + globalIgnores([ + "**/dist/**", + "**/dist-ssr/**", + "**/coverage/**", + "eslint.config.ts", + ]), + + ...pluginVue.configs["flat/essential"], + vueTsConfigs.recommended, + importPlugin.flatConfigs["recommended"], + tselint.configs["recommendedTypeChecked"], + { + languageOptions: { + parser: vueParser, + parserOptions: { + parser: "@typescript-eslint/parser", + // project: [`${__dirname}/tsconfig.json`], + tsconfigRootDir: __dirname, + // project: [`./tsconfig.json`, `./tsconfig.node.json`], + // parserOptions: { + // ecmaVersion: "latest", + // sourceType: "module", + // // project: ["./tsconfig.json", "./tsconfig.node.json"], + // // TODO: figure our correct settings here + // // project: [`${__dirname}/tsconfig.json`], + // }, + }, + }, + }, + + { + ...pluginVitest.configs.recommended, + files: ["src/**/__tests__/*"], + }, + + skipFormatting, + + { + settings: { + "import/resolver": { + node: { + extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"], + }, + typescript: { + // Optional: Specify the path to your tsconfig.json if it's not in the root + project: "./tsconfig.json", + }, + }, + }, + }, + + { + rules: { + // dont want this + "@typescript-eslint/consistent-type-imports": 0, + "import/named": 0, + + // warning on this because we have some shenanigans where it is a promise but a literal `await` is not present + "@typescript-eslint/require-await": "warn", + + // "prettier/prettier": "warn", + "@typescript-eslint/quotes": 0, + + // this is currently breaking, so turning it off + "@typescript-eslint/unbound-method": 0, + + // some strict rules from TS / airbnb presets to relax ----------- + camelcase: "off", + // "@typescript-eslint/ban-ts-comment": "off", + // "import/prefer-default-export": 0, + "no-plusplus": 0, + radix: 0, + "prefer-destructuring": 0, + "no-else-return": 0, // sometimes clearer even though unnecessary + "prefer-arrow-callback": 0, + "arrow-body-style": 0, + "@typescript-eslint/lines-between-class-members": 0, // often nice to group related one-liners + "max-classes-per-file": 0, // can make sense to colocate small classes + "consistent-return": 0, // often can make sense to return (undefined) early + "no-useless-return": 0, // sometimes helps clarify you are bailing early + "no-continue": 0, + "no-underscore-dangle": 0, + "no-await-in-loop": 0, + "no-lonely-if": 0, + "@typescript-eslint/no-unused-vars": [ + "warn", + { + argsIgnorePattern: "^_|^(response)$", + varsIgnorePattern: "^_|^(props|emit)$", + }, + ], + "@typescript-eslint/return-await": 0, + + // other ----------------------------------------------------- + "no-undef": 0, // handled by typescript, which is better aware of global types + // curly: ["error", "multi-line"], + // "brace-style": "error", + "max-len": [ + "warn", // just a warning since prettier will enforce + 120, + 2, + { + // bumped to 120, otherwise same as airbnb's rule but ignoring comments + ignoreUrls: true, + ignoreComments: true, + ignoreRegExpLiterals: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }, + ], + "max-statements-per-line": ["error", { max: 1 }], + // "@typescript-eslint/no-floating-promises": "error", + + // custom plugin configs ------------------------------------------ + // make import/order understand our alias paths + // "import/order": [ + // "warn", + // { + // pathGroups: [ + // { + // pattern: "@/**", + // group: "internal", + // position: "after", + // }, + // ], + // pathGroupsExcludedImportTypes: ["internal", "external", "builtins"], + // groups: [ + // "builtin", + // "external", + // "unknown", + // "internal", + // ["sibling", "parent"], + // "index", + // "object", + // "type", + // ], + // }, + // ], + + // rules to disable for now, but will likely be turned back on -------- + // TODO: review these rules, infractions case by case, probably turn back on? + "@typescript-eslint/no-use-before-define": 0, + // "import/no-cycle": 0, + "no-param-reassign": 0, + "no-restricted-syntax": 0, + "@typescript-eslint/naming-convention": 0, + "@typescript-eslint/no-shadow": 0, + "guard-for-in": 0, + + // some rules to downgrade to warning while developing -------------------- + // useful so things dont crash when code is temporarily commented out + "no-console": "warn", + "@typescript-eslint/no-empty-function": "warn", + "no-debugger": "warn", + "no-alert": "warn", + "no-empty": "warn", + + // good to warn people + "@typescript-eslint/no-base-to-string": "warn", + "@typescript-eslint/restrict-template-expressions": "warn", + // dont want to error here because we often have async funcs used with other lib calls that dont await, but they do not have to await! + "@typescript-eslint/no-misused-promises": "warn", + + // turning this off, b/c our instances are actually for meaning & clarity + "@typescript-eslint/no-redundant-type-constituents": 0, + + // rules that we want to warn, but disable agressive auto-fixing ----------- + "prefer-const": 0, + "no-unreachable": 0, // handy when you return early or throw an error while debugging + // unreachable code will be removed by default, so we disable autofix, but leave a warning + // "no-autofix/no-unreachable": 1, + // useful while debugging and commenting things out, otherwise gets automatically changed from let to const + // "no-autofix/prefer-const": "warn", + + "vue/block-order": [ + "error", + { + order: [ + "template", + "script[setup]", + "script:not([setup])", // necessary for default exports to not get hoisted below imports in setup block + "style:not([scoped])", + "style[scoped]", + ], + }, + ], + "vue/no-undef-components": [ + "error", + { + ignorePatterns: [ + "v-.*", // vue-konva requires global registration :( will hopefully fix soon! + "router-(view|link)", // vue router is fairly standard to use via global registration + ], + }, + ], + "vue/multi-word-component-names": "off", + "vue/require-default-prop": "off", + "vue/padding-line-between-blocks": "error", + "vue/prefer-true-attribute-shorthand": "error", + "vue/eqeqeq": "error", + "vue/no-multiple-template-root": "error", + + "vue/attribute-hyphenation": ["error", "never", { ignore: [] }], + "vue/v-on-event-hyphenation": "off", + + "@typescript-eslint/ban-ts-comment": 0, + // skipping for now, but should re-enable + "@typescript-eslint/no-floating-promises": 0, + }, + }, +); diff --git a/app/auth-portal/package.json b/app/auth-portal/package.json index b3d30a6770..882fbea64e 100644 --- a/app/auth-portal/package.json +++ b/app/auth-portal/package.json @@ -8,11 +8,12 @@ "dev": "vite", "build": "vite-ssg build", "build2": "vite build", + "build:check": "vue-tsc --noEmit", "build:analyze": "RUN_BUILD_ANALYZER=1 pnpm run build", "preview": "vite preview", "lint": "eslint src --ext .ts,.js,.cjs,.vue", - "lint:strict": "pnpm run lint --max-warnings=0", - "lint:fix": "pnpm run lint --fix", + "lint:strict": "pnpm run lint --quiet", + "lint:fix": "pnpm run lint --fix --quiet", "deploy": "pnpm run build && netlify deploy --dir=dist --prod", "test": "vitest --run", "test:validation": "vitest run src/lib/validations.test.ts" @@ -29,28 +30,39 @@ "less": "^4.2.0", "local-storage-fallback": "^5.0.0", "lodash-es": "^4.17.21", - "pinia": "^2.2.4", + "pinia": "^3.0.0", "posthog-js": "^1.176.0", "vite-ssg": "^0.23.8", "vue": "^3.5.13", "vue-router": "^4.4.5" }, "devDependencies": { - "@si/eslint-config": "workspace:*", "@si/tsconfig": "workspace:*", "@types/lodash-es": "^4.17.12", "@types/node": "^18.19.59", + "@typescript-eslint/eslint-plugin": "8.47.0", + "@typescript-eslint/parser": "8.47.0", "@vitejs/plugin-vue": "^5.1.4", - "eslint": "^8.57.1", + "@vitest/eslint-plugin": "1.6.6", + "@vue/eslint-config-prettier": "10.2.0", + "@vue/eslint-config-typescript": "^14.6.0", + "eslint": "^9.39.2", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-vue": "^10.6.2", "netlify-cli": "^23.1.1", + "prettier": "~2.8.4", "rollup-plugin-visualizer": "^5.12.0", - "typescript": "^5.0.4", + "typescript": "^5.9.3", + "typescript-eslint": "^8.53.0", "unplugin-icons": "^0.17.4", "vite": "^5.4.21", - "vite-plugin-checker": "^0.6.4", + "vite-plugin-checker": "^0.12.0", "vite-plugin-markdown": "^2.2.0", "vite-svg-loader": "^3.4.0", "vitest": "^3.2.4", - "vue-tsc": "^1.8.27" + "vue-eslint-parser": "^10.2.0", + "vue-tsc": "^3.2.0" } } diff --git a/app/auth-portal/src/pages/WorkspaceAuthTokensPage.vue b/app/auth-portal/src/pages/WorkspaceAuthTokensPage.vue index e80c712b49..5d0acd65c8 100644 --- a/app/auth-portal/src/pages/WorkspaceAuthTokensPage.vue +++ b/app/auth-portal/src/pages/WorkspaceAuthTokensPage.vue @@ -184,7 +184,7 @@ const listedTokens = computed(() => { return ( _.reverse( _.sortBy(_.values(authTokens.state.value), "createdAt"), - ) as Array + ) ).map((token) => { const d = new Date(token.expiresAt as unknown as string); const isExpired = d.getTime() < now.value; diff --git a/app/auth-portal/src/shims.d.ts b/app/auth-portal/src/shims.d.ts index b5d540d31f..cd7b1cf1a7 100644 --- a/app/auth-portal/src/shims.d.ts +++ b/app/auth-portal/src/shims.d.ts @@ -9,11 +9,6 @@ declare module "*.md" { // When "Mode.HTML" is requested const html: string; - // When "Mode.React" is requested. VFC could take a generic like React.VFC<{ MyComponent: TypeOfMyComponent }> - import React from "react"; - - const ReactComponent: React.VFC; - // When "Mode.Vue" is requested import { ComponentOptions, Component } from "vue"; @@ -23,12 +18,5 @@ declare module "*.md" { ) => ComponentOptions; // Modify below per your usage - export { - attributes, - toc, - html, - ReactComponent, - VueComponent, - VueComponentWith, - }; + export { attributes, toc, html, VueComponent, VueComponentWith }; } diff --git a/app/docs/eslint.config.ts b/app/docs/eslint.config.ts new file mode 100644 index 0000000000..626a82f891 --- /dev/null +++ b/app/docs/eslint.config.ts @@ -0,0 +1,32 @@ +import { globalIgnores } from "eslint/config"; +import { + defineConfigWithVueTs, + vueTsConfigs, +} from "@vue/eslint-config-typescript"; +import pluginVue from "eslint-plugin-vue"; +import pluginVitest from "@vitest/eslint-plugin"; +import skipFormatting from "@vue/eslint-config-prettier/skip-formatting"; + +// To allow more languages other than `ts` in `.vue` files, uncomment the following lines: +// import { configureVueProject } from '@vue/eslint-config-typescript' +// configureVueProject({ scriptLangs: ['ts', 'tsx'] }) +// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup + +export default defineConfigWithVueTs( + { + name: "app/files-to-lint", + files: ["**/*.{vue,ts,mts,tsx}"], + }, + + globalIgnores(["**/dist/**", "**/dist-ssr/**", "**/coverage/**"]), + + ...pluginVue.configs["flat/essential"], + vueTsConfigs.recommended, + + { + ...pluginVitest.configs.recommended, + files: ["src/**/__tests__/*"], + }, + + skipFormatting, +); diff --git a/app/docs/package.json b/app/docs/package.json index 2f3dd8607d..31a74d74b9 100644 --- a/app/docs/package.json +++ b/app/docs/package.json @@ -11,21 +11,32 @@ }, "devDependencies": { "@braintree/sanitize-url": "^7.1.1", - "@si/eslint-config": "workspace:*", - "@types/jest": "^30.0.0", "@si/tsconfig": "workspace:*", + "@types/jest": "^30.0.0", "@types/node": "^18.19.127", + "@typescript-eslint/eslint-plugin": "8.47.0", + "@typescript-eslint/parser": "8.47.0", + "@vitest/eslint-plugin": "1.6.6", + "@vue/eslint-config-prettier": "10.2.0", + "@vue/eslint-config-typescript": "^14.6.0", "cytoscape": "^3.33.1", "cytoscape-cose-bilkent": "^4.1.0", "dayjs": "^1.11.18", "debug": "^4.3.4", - "eslint": "^8.57.1", + "eslint": "^9.39.2", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-vue": "^10.6.2", "medium-zoom": "^1.1.0", "mermaid": "^11.12.0", + "prettier": "~2.8.4", "typescript": "^4.9.5", + "typescript-eslint": "^8.53.0", "vitepress": "^1.6.4", "vitepress-plugin-lightbox": "^1.0.3", "vitepress-plugin-mermaid": "^2.0.17", + "vue-eslint-parser": "^10.2.0", "widdershins": "^4.0.1" }, "dependencies": { diff --git a/app/web/.eslintignore b/app/web/.eslintignore deleted file mode 100644 index 99db336401..0000000000 --- a/app/web/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -*.css -*.less -*.jpg \ No newline at end of file diff --git a/app/web/.eslintrc.cjs b/app/web/.eslintrc.cjs deleted file mode 100644 index 01f5ca3cee..0000000000 --- a/app/web/.eslintrc.cjs +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = { - extends: ["@si/eslint-config/vue"], - rules: { - "@typescript-eslint/ban-ts-comment": 0, - // skipping for now, but should re-enable - "@typescript-eslint/no-floating-promises": 0, - }, - overrides: [ - // overrides for files at the root - which are all for config/build - { - files: ["./*", "./build-src/*"], - env: { node: true }, - rules: { - // these files often refer to dev dependencies - "import/no-extraneous-dependencies": 0, - "import/extensions": 0, - }, - }, - { - files: ["./src/newhotness/testing/*"], - env: { node: true }, - rules: { - // these files often refer to dev dependencies - "import/no-extraneous-dependencies": 0, - }, - }, - ], -}; diff --git a/app/web/.eslintrc.js b/app/web/.eslintrc.js new file mode 100644 index 0000000000..9fc387baac --- /dev/null +++ b/app/web/.eslintrc.js @@ -0,0 +1,9 @@ +import eslint from "@eslint/js"; +import pluginVue from "eslint-plugin-vue"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; + +export default [ + eslint.configs.recommended, + ...pluginVue.configs["flat/recommended"], + eslintPluginPrettierRecommended, +]; diff --git a/app/web/.prettierrc.cjs b/app/web/.prettierrc.cjs index 4ce72b3a05..d68b57bf8c 100644 --- a/app/web/.prettierrc.cjs +++ b/app/web/.prettierrc.cjs @@ -3,4 +3,5 @@ module.exports = { trailingComma: "all", tabWidth: 2, bracketSpacing: true, + printWidth: 120, }; diff --git a/app/web/BUCK b/app/web/BUCK index e159f1d26d..fc5adaaf1d 100644 --- a/app/web/BUCK +++ b/app/web/BUCK @@ -55,7 +55,6 @@ prod_deps_srcs = { } dev_deps_srcs = { - "lib/eslint-config": "//lib/eslint-config:src", "lib/tsconfig": "//lib/tsconfig:src", } @@ -68,7 +67,7 @@ vite_app( eslint( name = "check-lint-typescript", - srcs = [":src"] + glob([".eslint*"]), + srcs = [":src"] + glob(["*eslint*"]), prod_deps_srcs = prod_deps_srcs, dev_deps_srcs = dev_deps_srcs, ) @@ -104,7 +103,7 @@ test_suite( pnpm_task_binary( name = "fix-lint", - command = "lint:fix", + command = "lint:fix --quiet", srcs = glob(["src/**/*"]), path = "app/web", deps = [ diff --git a/app/web/README.md b/app/web/README.md index f5b1071cd9..eb2c93fb77 100644 --- a/app/web/README.md +++ b/app/web/README.md @@ -1,36 +1,43 @@ # app/web ## Project setup + ``` pnpm install ``` ### Compiles and hot-reloads for development + ``` pnpm run start ``` ### Compiles and minifies for production + ``` pnpm run build ``` ### Lint check (no fix) + ``` pnpm run lint ``` ### Type check (no fix) + ``` pnpm run build:check ``` ### Code formatting check (no fix) + ``` pnpm run fmt:check ``` ### Format code (WILL FIX) + ``` pnpm run fmt ``` @@ -40,48 +47,40 @@ pnpm run fmt This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 ` + + - - - diff --git a/app/web/src/components/Workspace/WorkspaceAdminDashboard.vue b/app/web/src/components/Workspace/WorkspaceAdminDashboard.vue index 7960fd4334..026ae210a7 100644 --- a/app/web/src/components/Workspace/WorkspaceAdminDashboard.vue +++ b/app/web/src/components/Workspace/WorkspaceAdminDashboard.vue @@ -39,10 +39,7 @@

KILL FUNCTION EXECUTION

- +
{{ flag.name }}:
-
+
{{ flag.value }}
@@ -90,12 +75,7 @@ diff --git a/app/web/src/components/layout/navbar/Navbar.vue b/app/web/src/components/layout/navbar/Navbar.vue index c28e775253..5a36b541bc 100644 --- a/app/web/src/components/layout/navbar/Navbar.vue +++ b/app/web/src/components/layout/navbar/Navbar.vue @@ -31,11 +31,7 @@ import NavbarPanelLeft from "./NavbarPanelLeft.vue"; const workspacesStore = useWorkspacesStore(); const invalidWorkspace = computed( - () => - !!( - workspacesStore.urlSelectedWorkspaceId && - !workspacesStore.selectedWorkspace - ), + () => !!(workspacesStore.urlSelectedWorkspaceId && !workspacesStore.selectedWorkspace), ); // top bar is always dark, so this keeps the workspace and change set dropdowns looking correct diff --git a/app/web/src/components/layout/navbar/NavbarButton.vue b/app/web/src/components/layout/navbar/NavbarButton.vue index 53c0a8db1a..6bed701726 100644 --- a/app/web/src/components/layout/navbar/NavbarButton.vue +++ b/app/web/src/components/layout/navbar/NavbarButton.vue @@ -24,10 +24,7 @@ - + diff --git a/app/web/src/components/layout/navbar/NavbarPanelCenter.vue b/app/web/src/components/layout/navbar/NavbarPanelCenter.vue index 0f574602b1..961a95d213 100644 --- a/app/web/src/components/layout/navbar/NavbarPanelCenter.vue +++ b/app/web/src/components/layout/navbar/NavbarPanelCenter.vue @@ -1,7 +1,5 @@