diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bceb2de..2b54bcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,12 +24,12 @@ jobs: - name: Node setup uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: pnpm setup uses: pnpm/action-setup@v3 with: - version: 9 + version: 10 - name: Install dependencies run: | diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 56e85dc..201116c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -42,11 +42,11 @@ jobs: - name: Node setup uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: pnpm setup uses: pnpm/action-setup@v3 with: - version: 9 + version: 10 - name: Install dependencies run: | pnpm i diff --git a/.github/workflows/release-github.yml b/.github/workflows/release-github.yml index 622aaae..bdfde5c 100644 --- a/.github/workflows/release-github.yml +++ b/.github/workflows/release-github.yml @@ -67,11 +67,11 @@ jobs: - name: Node setup uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: pnpm setup uses: pnpm/action-setup@v3 with: - version: 9 + version: 10 - name: Install dependencies run: | pnpm i diff --git a/README.md b/README.md index 17d31df..d613d41 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ This repo is meant to be used as a template for typescript monorepo projects. I This repo has the following prerequisites: -* The latest LTS version of Node (currently 20) is installed. +* The latest LTS version of Node (currently 22) is installed. * If you are using nvm, you can run `nvm install` or `nvm use` to install or use the correct version, respectively. -* The latest version of `pnpm` (currently 9) is globally installed. +* The latest version of `pnpm` (currently 10) is globally installed. + * Corepack is also currently an option, but note it is [planned to be removed from the default Node installation](https://github.com/nodejs/TSC/pull/1697#issuecomment-2737093616). Run `pnpm i` from the project root to install dependencies. diff --git a/build/eslint-config-shared/base.cjs b/build/eslint-config-shared/base.cjs deleted file mode 100644 index 50d80f8..0000000 --- a/build/eslint-config-shared/base.cjs +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -// This config includes all the recommended configs, including type-checking, and the strict config. -// It then also upgrades most of the rules to "error" that the recommended configs leave at "warn". - -module.exports = { - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/strict-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked", - ], - parserOptions: { - // Enabling type checking - project: true, - }, - rules: { - // Couple warns that I'm not ready to be errors - "@typescript-eslint/consistent-type-definitions": ["warn", "type"], - "@typescript-eslint/no-unnecessary-condition": "warn", - "@typescript-eslint/prefer-readonly": "error", - // Left as warn, for sync implementations complying with async interfaces - "@typescript-eslint/require-await": "warn", - }, -}; diff --git a/build/eslint-config-shared/eslint-additions.cjs b/build/eslint-config-shared/eslint-additions.cjs deleted file mode 100644 index 60d3834..0000000 --- a/build/eslint-config-shared/eslint-additions.cjs +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; - -// This config includes rules that are not mentioned in the recommended rulesets but seem good. -// Only includes base eslint rules, not typescript-eslint - the latter are in typescript-eslint-additions.js - -module.exports = { - rules: { - // "Possible Problems" - "array-callback-return": "error", - // Try to get this on - // "no-await-in-loop": "error", - "no-constant-binary-expression": "error", - "no-constructor-return": "error", - // Can't distinguish type vs. normal import statements - // "no-duplicate-imports": "error", - "no-new-native-nonconstructor": "error", - "no-promise-executor-return": "error", - "no-self-compare": "error", - "no-template-curly-in-string": "error", - "no-unmodified-loop-condition": "error", - "no-unreachable-loop": "error", - "no-unused-private-class-members": "error", - // "no-use-before-define": "error", // Disabled by typescript-eslint - "require-atomic-updates": "error", - - // "Suggestions" - "accessor-pairs": "error", - "arrow-body-style": "error", // formatting? - "block-scoped-var": "error", - "camelcase": "error", // formatting? - // "capitalized-comments": "error", // formatting, and I don't care - "class-methods-use-this": "warn", // Warn, so I can conform with interfaces - "complexity": "error", // formatting? - "consistent-return": "error", - "consistent-this": "error", - "curly": "error", - "default-case": "error", - "default-case-last": "error", - // "default-param-last": "error", // Disabled by typescript-eslint - // "dot-notation": "error", // Disabled by typescript-eslint - "eqeqeq": "error", - "func-name-matching": "error", - // Try to get this on - // "func-names": "error", - "func-style": "error", - "grouped-accessor-pairs": "error", // formatting? - "guard-for-in": "error", - "id-denylist": "error", - // "id-length": ["error", { "exceptions": ["x", "y", "z", "w", "i", "j", "k"] }], - // Don't think I like this one anyway - // "init-declarations": "error", // Disabled by typescript-eslint - "logical-assignment-operators": "error", - "new-cap": "error", // formatting - "no-alert": "error", - // "no-array-constructor": "error", // Disabled by typescript-eslint - "no-bitwise": "error", - "no-caller": "error", - "no-confusing-arrow": "error", - "no-continue": "error", - "no-div-regex": "error", - "no-else-return": "error", - "no-eval": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-label": "error", - "no-floating-decimal": "error", - "no-implicit-coercion": "error", - "no-implicit-globals": "error", - // "no-implied-eval": "error", // Disabled by typescript-eslint - // "no-invalid-this": "error", // Disabled by typescript-eslint - "no-iterator": "error", - "no-label-var": "error", - "no-labels": "error", - "no-lone-blocks": "error", - "no-lonely-if": "error", - // "no-loop-func": "error", // Disabled by typescript-eslint - // "no-magic-numbers": "error", // Disabled by typescript-eslint - "no-mixed-operators": "error", - "no-multi-assign": "error", - "no-multi-str": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-wrappers": "error", - "no-octal-escape": "error", - "no-param-reassign": "error", - // "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }] // Not sure I agree with this one - "no-proto": "error", - "no-return-assign": "error", - "no-return-await": "error", - "no-script-url": "error", - "no-sequences": "error", - // "no-shadow": "error", // Disabled by typescript-eslint - // "no-throw-literal": "error", // Disabled by typescript-eslint - "no-undef-init": "error", - "no-unneeded-ternary": "error", - "no-useless-call": "error", - "no-useless-computed-key": "error", - "no-useless-concat": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-var": "error", - "object-shorthand": "error", - // "prefer-arrow-callback": "error", // Probably try to get this on, or maybe omit tests? - "prefer-const": "error", - "prefer-destructuring": "error", - "prefer-object-has-own": "error", - "prefer-object-spread": "error", - "prefer-promise-reject-errors": "error", - "prefer-rest-params": "error", - "prefer-spread": "error", - "prefer-template": "error", - "radix": ["error", "as-needed"], - // "sort-imports": ["error", { "ignoreDeclarationSort": true }], // Not sure about the right config here - "spaced-comment": "error", // formatting - "strict": "error", - "symbol-description": "error", - "yoda": "error", - } -}; diff --git a/build/eslint-config-shared/formatting.cjs b/build/eslint-config-shared/formatting.cjs deleted file mode 100644 index 2ef27fa..0000000 --- a/build/eslint-config-shared/formatting.cjs +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; - -// This config includes formatting-specific rules only. - -module.exports = { - rules: { - "array-bracket-newline": "error", - "array-bracket-spacing": "error", - // "array-element-newline": "error", - "arrow-parens": "error", - "arrow-spacing": "error", - "block-spacing": "error", // Some of these are in the list that want to be disabled? - "brace-style": ["error", "1tbs", { "allowSingleLine": true }], - "comma-dangle": ["error", "only-multiline"], - "comma-spacing": "error", - "comma-style": "error", - "computed-property-spacing": "error", - "dot-location": ["error", "property"], - "eol-last": "error", - "func-call-spacing": "error", - "function-call-argument-newline": ["error", "consistent"], - "function-paren-newline": ["error", "multiline-arguments"], - "generator-star-spacing": "error", - // "implicit-arrow-linebreak": "error", - "indent": "error", - "jsx-quotes": "error", - "key-spacing": "error", - "keyword-spacing": "error", - // "line-comment-position": "error", - "linebreak-style": "error", - // "lines-around-comment": "error", - // "lines-between-class-members": "error", - // "max-len": "error", - // "max-statements-per-line": "error", - "multiline-ternary": ["error", "always-multiline"], - "new-parens": "error", - // "newline-per-chained-call": "error", - // "no-extra-parens": "error", - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multiple-empty-lines": "error", - "no-tabs": "error", - "no-trailing-spaces": "error", - "no-whitespace-before-property": "error", - // "nonblock-statement-body-position": "error", - "object-curly-newline": "error", - "object-curly-spacing": ["error", "always"], - "object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }], - "operator-linebreak": ["error", "before"], - "padded-blocks": ["error", "never"], - // "padding-line-between-statements": "error", - "quotes": "error", - "rest-spread-spacing": "error", - "semi": "error", - "semi-spacing": "error", - "semi-style": "error", - "space-before-blocks": "error", - "space-before-function-paren": ["error", {"anonymous": "never", "named": "never", "asyncArrow": "always"}], - "space-in-parens": "error", - "space-infix-ops": "error", - "space-unary-ops": "error", - "switch-colon-spacing": "error", - "template-curly-spacing": ["error", "always"], - "template-tag-spacing": "error", - "unicode-bom": "error", - "wrap-iife": ["error", "inside"], - // "wrap-regex": "error", - "yield-star-spacing": "error", - } -}; diff --git a/build/eslint-config-shared/index.mjs b/build/eslint-config-shared/index.mjs new file mode 100644 index 0000000..6213bc8 --- /dev/null +++ b/build/eslint-config-shared/index.mjs @@ -0,0 +1,22 @@ +import { jsConfigs } from "./js.mjs"; +import { perfectionistConfigs } from "./perfectionist.mjs"; +import { reactConfigs } from "./react.mjs"; +import { stylisticConfigs } from "./stylistic.mjs"; +import { tseslintConfigs } from "./tseslint.mjs"; + +export default [ + ...jsConfigs, + ...tseslintConfigs, + ...reactConfigs, + ...perfectionistConfigs, + ...stylisticConfigs, + { + linterOptions: { + reportUnusedDisableDirectives: "error", + reportUnusedInlineConfigs: "error", + }, + }, + { + ignores: ["built/**", "webpacked/**"], + }, +]; diff --git a/build/eslint-config-shared/js.mjs b/build/eslint-config-shared/js.mjs new file mode 100644 index 0000000..34cef85 --- /dev/null +++ b/build/eslint-config-shared/js.mjs @@ -0,0 +1,207 @@ +import js from "@eslint/js"; + +export const jsConfigs = [ + js.configs.recommended, + { + rules: { + "accessor-pairs": "error", + "array-callback-return": "error", + "arrow-body-style": "error", + "block-scoped-var": "error", + "camelcase": "error", + // "capitalized-comments": "error", + "class-methods-use-this": "error", // Might need to warn instead to conform with interfaces + "complexity": "error", + "consistent-return": "error", + "consistent-this": "error", + // "constructor-super": "error", // Disabled by tseslint's eslint-recommended-raw + "curly": "error", + "default-case": "error", + "default-case-last": "error", + // "default-param-last": "error", // Disabled for @typescript-eslint/default-param-last + // "dot-notation": "error", // Disabled by tseslint's stylistic-type-checked + "eqeqeq": "error", + // "for-direction": "error", // Enabled in recommended + "func-name-matching": "error", + // "func-names": "error", + "func-style": "error", + // "getter-return": "error", // Disabled by tseslint's eslint-recommended-raw + "grouped-accessor-pairs": "error", + "guard-for-in": "error", + "id-denylist": "error", + // "id-length": "error", + // "id-match": "error", + // "init-declarations": "error", // Disabled for @typescript-eslint/init-declarations + "logical-assignment-operators": "error", + // "max-classes-per-file": "error", + // "max-depth": "error", + // "max-lines": "error", + // "max-lines-per-function": "error", + // "max-nested-callbacks": "error", + // "max-params": "error", + // "max-statements": "error", + "new-cap": "error", + "no-alert": "error", + // "no-array-constructor": "error", // Disabled by tseslint's recommended-type-checked + // "no-async-promise-executor": "error", // Enabled in recommended + // "no-await-in-loop": "error", + "no-bitwise": "error", + "no-caller": "error", + // "no-case-declarations": "error", // Enabled in recommended + // "no-class-assign": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-compare-neg-zero": "error", // Enabled in recommended + // "no-cond-assign": "error", // Enabled in recommended + // "no-console": "error", + // "no-const-assign": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-constant-binary-expression": "error", // Enabled in recommended + // "no-constant-condition": "error", // Enabled in recommended + "no-constructor-return": "error", + "no-continue": "error", + // "no-control-regex": "error", // Enabled in recommended + // "no-debugger": "error", // Enabled in recommended + // "no-delete-var": "error", // Enabled in recommended + "no-div-regex": "error", + // "no-dupe-args": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-dupe-class-members": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-dupe-else-if": "error", // Enabled in recommended + // "no-dupe-keys": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-duplicate-case": "error", // Enabled in recommended + "no-duplicate-imports": "error", + "no-else-return": "error", + // "no-empty": "error", // Enabled in recommended + // "no-empty-character-class": "error", // Enabled in recommended + // "no-empty-function": "error", // Disabled by tseslint's stylistic-type-checked + // "no-empty-pattern": "error", // Enabled in recommended + // "no-empty-static-block": "error", // Enabled in recommended + // "no-eq-null": "error", + "no-eval": "error", + // "no-ex-assign": "error", // Enabled in recommended + "no-extend-native": "error", + "no-extra-bind": "error", + // "no-extra-boolean-cast": "error", // Enabled in recommended + "no-extra-label": "error", + // "no-fallthrough": "error", // Enabled in recommended + // "no-func-assign": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-global-assign": "error", // Enabled in recommended + "no-implicit-coercion": "error", + "no-implicit-globals": "error", + // "no-implied-eval": "error", // Disabled by tseslint's recommended-type-checked + // "no-import-assign": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-inline-comments": "error", + // "no-inner-declarations": "error", + // "no-invalid-regexp": "error", // Enabled in recommended + // "no-invalid-this": "error", + // "no-irregular-whitespace": "error", // Enabled in recommended + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + // "no-loop-func": "error", + // "no-loss-of-precision": "error", // Enabled in recommended + // "no-magic-numbers": "error", + // "no-misleading-character-class": "error", // Enabled in recommended + "no-multi-assign": "error", + "no-multi-str": "error", + // "no-negated-condition": "error", + // "no-nested-ternary": "error", + "no-new": "error", + "no-new-func": "error", + // "no-new-native-nonconstructor": "error", // Disabled by tseslint's eslint-recommended-raw + "no-new-wrappers": "error", + // "no-nonoctal-decimal-escape": "error", // Enabled in recommended + // "no-obj-calls": "error", // Disabled by tseslint's eslint-recommended-raw + "no-object-constructor": "error", + // "no-octal": "error", // Enabled in recommended + "no-octal-escape": "error", + "no-param-reassign": "error", + // "no-plusplus": "error", + "no-promise-executor-return": "error", + "no-proto": "error", + // "no-prototype-builtins": "error", // Enabled in recommended + // "no-redeclare": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-regex-spaces": "error", // Enabled in recommended + // "no-restricted-exports": "error", + // "no-restricted-globals": "error", + // "no-restricted-imports": "error", + // "no-restricted-properties": "error", + // "no-restricted-syntax": "error", + "no-return-assign": "error", + "no-script-url": "error", + // "no-self-assign": "error", // Enabled in recommended + "no-self-compare": "error", + "no-sequences": "error", + // "no-setter-return": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-shadow": "error", + // "no-shadow-restricted-names": "error", // Enabled in recommended + // "no-sparse-arrays": "error", // Enabled in recommended + "no-template-curly-in-string": "error", + // "no-ternary": "error", + // "no-this-before-super": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-throw-literal": "error", // Disabled by tseslint's recommended-type-checked + // "no-unassigned-vars": "error", + // "no-undef": "error", // Disabled by tseslint's eslint-recommended-raw + "no-undef-init": "error", + // "no-undefined": "error", + // "no-underscore-dangle": "error", + // "no-unexpected-multiline": "error", // Enabled in recommended + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + // "no-unreachable": "error", // Disabled by tseslint's eslint-recommended-raw + "no-unreachable-loop": "error", + // "no-unsafe-finally": "error", // Enabled in recommended + // "no-unsafe-negation": "error", // Disabled by tseslint's eslint-recommended-raw + // "no-unsafe-optional-chaining": "error", // Enabled in recommended + // "no-unused-expressions": "error", // Disabled by tseslint's recommended-type-checked + // "no-unused-labels": "error", // Enabled in recommended + // "no-unused-private-class-members": "error", // Enabled in recommended + // "no-unused-vars": "error", // Disabled by tseslint's recommended-type-checked + // "no-use-before-define": "error", + // "no-useless-assignment": "error", + // "no-useless-backreference": "error", // Enabled in recommended + "no-useless-call": "error", + // "no-useless-catch": "error", // Enabled in recommended + "no-useless-computed-key": "error", + "no-useless-concat": "error", + // "no-useless-constructor": "error", // Disabled by tseslint's strict-type-checked + // "no-useless-escape": "error", // Enabled in recommended + "no-useless-rename": "error", + "no-useless-return": "error", + // "no-var": "error", // Enabled by tseslint's eslint-recommended-raw + // "no-void": "error", + // "no-warning-comments": "error", + // "no-with": "error", // Disabled by tseslint's eslint-recommended-raw + "object-shorthand": "error", + // "one-var": "error", + // "operator-assignment": "error", + // "prefer-arrow-callback": "error", + // "prefer-const": "error", // Enabled by tseslint's eslint-recommended-raw + "prefer-destructuring": "error", + // "prefer-exponentiation-operator": "error", + // "prefer-named-capture-group": "error", + // "prefer-numeric-literals": "error", + "prefer-object-has-own": "error", + "prefer-object-spread": "error", + // "prefer-promise-reject-errors": "error", // Disabled by tseslint's recommended-type-checked + // "prefer-regex-literals": "error", + // "prefer-rest-params": "error", // Enabled by tseslint's eslint-recommended-raw + // "prefer-spread": "error", // Enabled by tseslint's eslint-recommended-raw + "prefer-template": "error", + "radix": ["error", "as-needed"], + "require-atomic-updates": "error", + // "require-await": "error", // Disabled by tseslint's recommended-type-checked + // "require-unicode-regexp": "error", + // "require-yield": "error", // Enabled in recommended + // "sort-imports": "error", + // "sort-keys": "error", + // "sort-vars": "error", + "strict": "error", + "symbol-description": "error", + "unicode-bom": "error", + // "use-isnan": "error", // Enabled in recommended + // "valid-typeof": "error", // Enabled in recommended + // "vars-on-top": "error", + "yoda": "error", + }, + }, +]; diff --git a/build/eslint-config-shared/package.json b/build/eslint-config-shared/package.json index 1501e40..ff6c3d9 100644 --- a/build/eslint-config-shared/package.json +++ b/build/eslint-config-shared/package.json @@ -3,8 +3,16 @@ "version": "0.0.0", "private": true, "description": "Shared eslint config used throughout the monorepo", + "main": "index.mjs", "keywords": [], "author": "Matt Rakow", "license": "Unlicense", - "type": "module" + "type": "module", + "devDependencies": { + "@eslint/js": "^9.30.1", + "@stylistic/eslint-plugin": "^5.1.0", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-react": "^7.37.5", + "typescript-eslint": "^8.34.1" + } } diff --git a/build/eslint-config-shared/perfectionist.mjs b/build/eslint-config-shared/perfectionist.mjs new file mode 100644 index 0000000..d12622f --- /dev/null +++ b/build/eslint-config-shared/perfectionist.mjs @@ -0,0 +1,29 @@ +import pluginPerfectionist from "eslint-plugin-perfectionist"; + +export const perfectionistConfigs = [ + pluginPerfectionist.configs["recommended-natural"], + { + rules: { + // "sort-array-includes": "error", + // "sort-classes": "error", + // "sort-decorators": "error", + // "sort-enums": "error", + // "sort-exports": "error", + // "sort-heritage-clauses": "error", + // "sort-imports": "error", + // "sort-interfaces": "error", + // "sort-intersection-types": "error", + // "sort-jsx-props": "error", + // "sort-maps": "error", + // "sort-named-exports": "error", + // "sort-modules": "error", + // "sort-named-imports": "error", + // "sort-object-types": "error", + // "sort-objects": "error", + // "sort-sets": "error", + // "sort-switch-case": "error", + // "sort-union-types": "error", + // "sort-variable-declarations": "error", + }, + }, +]; diff --git a/build/eslint-config-shared/react.mjs b/build/eslint-config-shared/react.mjs new file mode 100644 index 0000000..1ebde7f --- /dev/null +++ b/build/eslint-config-shared/react.mjs @@ -0,0 +1,118 @@ +import pluginReact from "eslint-plugin-react"; + +export const reactConfigs = [ + pluginReact.configs.flat.recommended, + pluginReact.configs.flat["jsx-runtime"], + { + settings: { + react: { + version: "detect", + }, + }, + }, + { + rules: { + // "react/boolean-prop-naming": "error", + // "react/button-has-type": "error", + // "react/checked-requires-onchange-or-readonly": "error", + // "react/default-props-match-prop-types": "error", + // "react/destructuring-assignment": "error", + // "react/display-name": "error", // Enabled in recommended + // "react/forbid-component-props": "error", + // "react/forbid-dom-props": "error", + // "react/forbid-elements": "error", + // "react/forbid-foreign-prop-types": "error", + // "react/forbid-prop-types": "error", + // "react/forward-ref-uses-ref": "error", + // "react/function-component-definition": "error", + // "react/hook-use-state": "error", + // "react/iframe-missing-sandbox": "error", + // "react/jsx-boolean-value": "error", + // "react/jsx-child-element-spacing": "error", + // "react/jsx-closing-bracket-location": "error", + // "react/jsx-closing-tag-location": "error", + // "react/jsx-curly-brace-presence": "error", + // "react/jsx-curly-newline": "error", + // "react/jsx-curly-spacing": "error", + // "react/jsx-equals-spacing": "error", + // "react/jsx-filename-extension": "error", + // "react/jsx-first-prop-new-line": "error", + // "react/jsx-fragments": "error", + // "react/jsx-handler-names": "error", + // "react/jsx-indent": "error", + // "react/jsx-indent-props": "error", + // "react/jsx-key": "error", // Enabled in recommended + // "react/jsx-max-depth": "error", + // "react/jsx-max-props-per-line": "error", + // "react/jsx-newline": "error", + // "react/jsx-no-bind": "error", + // "react/jsx-no-comment-textnodes": "error", // Enabled in recommended + // "react/jsx-no-constructed-context-values": "error", + // "react/jsx-no-duplicate-props": "error", // Enabled in recommended + // "react/jsx-no-leaked-render": "error", + // "react/jsx-no-literals": "error", + // "react/jsx-no-script-url": "error", + // "react/jsx-no-target-blank": "error", // Enabled in recommended + // "react/jsx-no-undef": "error", // Enabled in recommended + // "react/jsx-no-useless-fragment": "error", + // "react/jsx-one-expression-per-line": "error", + // "react/jsx-pascal-case": "error", + // "react/jsx-props-no-multi-spaces": "error", + // "react/jsx-props-no-spread-multi": "error", + // "react/jsx-props-no-spreading": "error", + // "react/jsx-sort-props": "error", + // "react/jsx-tag-spacing": "error", + // "react/jsx-uses-react": "error", // Enabled in recommended, but disabled in jsx-runtime + // "react/jsx-uses-vars": "error", // Enabled in recommended + // "react/jsx-wrap-multilines": "error", + // "react/no-access-state-in-setstate": "error", + // "react/no-adjacent-inline-elements": "error", + // "react/no-array-index-key": "error", + // "react/no-arrow-function-lifecycle": "error", + // "react/no-children-prop": "error", // Enabled in recommended + // "react/no-danger": "error", + // "react/no-danger-with-children": "error", // Enabled in recommended + // "react/no-deprecated": "error", // Enabled in recommended + // "react/no-did-mount-set-state": "error", + // "react/no-did-update-set-state": "error", + // "react/no-direct-mutation-state": "error", // Enabled in recommended + // "react/no-find-dom-node": "error", // Enabled in recommended + // "react/no-invalid-html-attribute": "error", + // "react/no-is-mounted": "error", // Enabled in recommended + // "react/no-multi-comp": "error", + // "react/no-namespace": "error", + // "react/no-object-type-as-default-prop": "error", + // "react/no-redundant-should-component-update": "error", + // "react/no-render-return-value": "error", // Enabled in recommended + // "react/no-set-state": "error", + // "react/no-string-refs": "error", // Enabled in recommended + // "react/no-this-in-sfc": "error", + // "react/no-typos": "error", + // "react/no-unescaped-entities": "error", // Enabled in recommended + // "react/no-unknown-property": "error", // Enabled in recommended + "react/no-unsafe": "error", // Disabled in recommended + // "react/no-unstable-nested-components": "error", + // "react/no-unused-class-component-methods": "error", + // "react/no-unused-prop-types": "error", + // "react/no-unused-state": "error", + // "react/no-will-update-set-state": "error", + // "react/prefer-es6-class": "error", + // "react/prefer-exact-props": "error", + // "react/prefer-read-only-props": "error", + // "react/prefer-stateless-function": "error", + // "react/prop-types": "error", // Enabled in recommended + // "react/react-in-jsx-scope": "error", // Enabled in recommended, but disabled in jsx-runtime + // "react/require-default-props": "error", + // "react/require-optimization": "error", + // "react/require-render-return": "error", // Enabled in recommended + // "react/self-closing-comp": "error", + // "react/sort-comp": "error", + // "react/sort-default-props": "error", + // "react/sort-prop-types": "error", + // "react/state-in-constructor": "error", + // "react/static-property-placement": "error", + // "react/style-prop-object": "error", + // "react/void-dom-elements-no-children": "error", + }, + }, +]; diff --git a/build/eslint-config-shared/shared.cjs b/build/eslint-config-shared/shared.cjs deleted file mode 100644 index 7d86f73..0000000 --- a/build/eslint-config-shared/shared.cjs +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; - -module.exports = { - extends: [ - "./base.cjs", - "./eslint-additions.cjs", - "./typescript-eslint-additions.cjs", - "./formatting.cjs", - ], -}; diff --git a/build/eslint-config-shared/stylistic.mjs b/build/eslint-config-shared/stylistic.mjs new file mode 100644 index 0000000..68e7622 --- /dev/null +++ b/build/eslint-config-shared/stylistic.mjs @@ -0,0 +1,104 @@ +import pluginStylistic from "@stylistic/eslint-plugin"; + +export const stylisticConfigs = [ + pluginStylistic.configs.recommended, + { + rules: { + "@stylistic/array-bracket-newline": "error", + // "@stylistic/array-bracket-spacing": "error", // Enabled in recommended + // "@stylistic/array-element-newline": "error", + // "@stylistic/arrow-parens": "error", // Enabled in recommended + // "@stylistic/arrow-spacing": "error", // Enabled in recommended + // "@stylistic/block-spacing": "error", // Enabled in recommended + "@stylistic/brace-style": ["error", "1tbs", { "allowSingleLine": true }], // Enabled in recommended + // "@stylistic/comma-dangle": "error", // Enabled in recommended + // "@stylistic/comma-spacing": "error", // Enabled in recommended + // "@stylistic/comma-style": "error", // Enabled in recommended + // "@stylistic/computed-property-spacing": "error", // Enabled in recommended + // "@stylistic/curly-newline": "error", + // "@stylistic/dot-location": "error", // Enabled in recommended + // "@stylistic/eol-last": "error", // Enabled in recommended + "@stylistic/function-call-argument-newline": ["error", "consistent"], + "@stylistic/function-call-spacing": "error", + "@stylistic/function-paren-newline": "error", + // "@stylistic/generator-star-spacing": "error", // Enabled in recommended + // "@stylistic/implicit-arrow-linebreak": "error", + "@stylistic/indent": ["error", 4], // Enabled in recommended + // "@stylistic/indent-binary-ops": "error", // Enabled in recommended + // "@stylistic/jsx-child-element-spacing": "error", + // "@stylistic/jsx-closing-bracket-location": "error", // Enabled in recommended + // "@stylistic/jsx-closing-tag-location": "error", // Enabled in recommended + // "@stylistic/jsx-curly-brace-presence": "error", // Enabled in recommended + // "@stylistic/jsx-curly-newline": "error", // Enabled in recommended + // "@stylistic/jsx-curly-spacing": "error", // Enabled in recommended + // "@stylistic/jsx-equals-spacing": "error", // Enabled in recommended + // "@stylistic/jsx-first-prop-new-line": "error", // Enabled in recommended + // "@stylistic/jsx-function-call-newline": "error", // Enabled in recommended + // "@stylistic/jsx-indent": "error", + // "@stylistic/jsx-indent-props": "error", // Enabled in recommended + // "@stylistic/jsx-max-props-per-line": "error", // Enabled in recommended + // "@stylistic/jsx-newline": "error", + "@stylistic/jsx-one-expression-per-line": "off", // Enabled in recommended + // "@stylistic/jsx-pascal-case": "error", + // "@stylistic/jsx-props-no-multi-spaces": "error", + // "@stylistic/jsx-quotes": "error", // Enabled in recommended + // "@stylistic/jsx-self-closing-comp": "error", + // "@stylistic/jsx-sort-props": "error", + // "@stylistic/jsx-tag-spacing": "error", // Enabled in recommended + // "@stylistic/jsx-wrap-multilines": "error", // Enabled in recommended + // "@stylistic/key-spacing": "error", // Enabled in recommended + // "@stylistic/keyword-spacing": "error", // Enabled in recommended + // "@stylistic/line-comment-position": "error", + "@stylistic/linebreak-style": "error", + // "@stylistic/lines-around-comment": "error", + // "@stylistic/lines-between-class-members": "error", // Enabled in recommended + // "@stylistic/max-len": "error", + // "@stylistic/max-statements-per-line": "error", // Enabled in recommended + // "@stylistic/member-delimiter-style": "error", // Enabled in recommended + // "@stylistic/multiline-comment-style": "error", + // "@stylistic/multiline-ternary": "error", // Enabled in recommended + // "@stylistic/new-parens": "error", // Enabled in recommended + // "@stylistic/newline-per-chained-call": "error", + "@stylistic/no-confusing-arrow": "error", + // "@stylistic/no-extra-parens": "error", // Enabled in recommended + // "@stylistic/no-extra-semi": "error", + // "@stylistic/no-floating-decimal": "error", // Enabled in recommended + // "@stylistic/no-mixed-operators": "error", // Enabled in recommended + // "@stylistic/no-mixed-spaces-and-tabs": "error", // Enabled in recommended + // "@stylistic/no-multi-spaces": "error", // Enabled in recommended + // "@stylistic/no-multiple-empty-lines": "error", // Enabled in recommended + // "@stylistic/no-tabs": "error", // Enabled in recommended + // "@stylistic/no-trailing-spaces": "error", // Enabled in recommended + // "@stylistic/no-whitespace-before-property": "error", // Enabled in recommended + // "@stylistic/nonblock-statement-body-position": "error", + // "@stylistic/object-curly-newline": "error", + // "@stylistic/object-curly-spacing": "error", // Enabled in recommended + "@stylistic/object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }], + // "@stylistic/one-var-declaration-per-line": "error", + // "@stylistic/operator-linebreak": "error", // Enabled in recommended + // "@stylistic/padded-blocks": "error", // Enabled in recommended + // "@stylistic/padding-line-between-statements": "error", + // "@stylistic/quote-props": "error", // Enabled in recommended + "@stylistic/quotes": ["error", "double"], // Enabled in recommended + // "@stylistic/rest-spread-spacing": "error", // Enabled in recommended + "@stylistic/semi": ["error", "always"], // Enabled in recommended + // "@stylistic/semi-spacing": "error", // Enabled in recommended + "@stylistic/semi-style": "error", + // "@stylistic/space-before-blocks": "error", // Enabled in recommended + "@stylistic/space-before-function-paren": ["error", {"anonymous": "never", "named": "never", "asyncArrow": "always"}], // Enabled in recommended + // "@stylistic/space-in-parens": "error", // Enabled in recommended + // "@stylistic/space-infix-ops": "error", // Enabled in recommended + // "@stylistic/space-unary-ops": "error", // Enabled in recommended + // "@stylistic/spaced-comment": "error", // Enabled in recommended + "@stylistic/switch-colon-spacing": "error", + "@stylistic/template-curly-spacing": ["error", "always"], // Enabled in recommended + // "@stylistic/template-tag-spacing": "error", // Enabled in recommended + // "@stylistic/type-annotation-spacing": "error", // Enabled in recommended + // "@stylistic/type-generic-spacing": "error", // Enabled in recommended + // "@stylistic/type-named-tuple-spacing": "error", // Enabled in recommended + "@stylistic/wrap-iife": ["error", "inside"], // Enabled in recommended + // "@stylistic/wrap-regex": "error", + // "@stylistic/yield-star-spacing": "error", // Enabled in recommended + }, + }, +]; diff --git a/build/eslint-config-shared/tseslint.mjs b/build/eslint-config-shared/tseslint.mjs new file mode 100644 index 0000000..965b0bc --- /dev/null +++ b/build/eslint-config-shared/tseslint.mjs @@ -0,0 +1,168 @@ +import tseslint from "typescript-eslint"; + +// The typescript-eslint plugin doesn't provide a single, easily includable config. +// Instead, each of their configs are composed from multiple individual configs that +// won't work individually (e.g. they omit the languageOptions, files, etc.). They +// expect you to use their helper method to flatten their configs back into a single +// usable config. I'm choosing to avoid that helper to try to keep tighter control +// over the config. For now I extract and reassemble the rules from the source +// config, but it might be better to later just take a static copy of the "all" +// ruleset and just customize it directly rather than reaching into the config like this. +const strictTypeCheckedConfig = tseslint.configs.strictTypeChecked; +const strictTypeCheckedRules = strictTypeCheckedConfig.reduce( + (acc, curr) => curr.rules !== undefined ? { ...acc, ...curr.rules } : acc, + {}, +); +const stylisticTypeCheckedConfig = tseslint.configs.stylisticTypeChecked; +const stylisticTypeCheckedRules = stylisticTypeCheckedConfig.reduce( + (acc, curr) => curr.rules !== undefined ? { ...acc, ...curr.rules } : acc, + {}, +); + +export const tseslintConfigs = [ + { + files: ["**/*.{ts,mts,cts,tsx}"], + plugins: { + "@typescript-eslint": tseslint.plugin, + }, + languageOptions: { + parser: tseslint.parser, + parserOptions: { + projectService: true, + }, + }, + rules: { + ...strictTypeCheckedRules, + ...stylisticTypeCheckedRules, + // "@typescript-eslint/adjacent-overload-signatures": "error", // Enabled in stylistic + // "@typescript-eslint/array-type": "error", // Enabled in stylistic + // "@typescript-eslint/await-thenable": "error", // Enabled in recommended + // "@typescript-eslint/ban-ts-comment": "error", // Enabled in recommended + // "@typescript-eslint/ban-tslint-comment": "error", // Enabled in stylistic + // "@typescript-eslint/class-literal-property-style": "error", // Enabled in stylistic + // "@typescript-eslint/class-methods-use-this": "error", + // "@typescript-eslint/consistent-generic-constructors": "error", // Enabled in stylistic + // "@typescript-eslint/consistent-indexed-object-style": "error", // Enabled in stylistic + // "@typescript-eslint/consistent-return": "error", + // "@typescript-eslint/consistent-type-assertions": "error", // Enabled in stylistic + // "@typescript-eslint/consistent-type-definitions": "error", // Enabled in stylistic + // "@typescript-eslint/consistent-type-exports": "error", + // "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/default-param-last": "error", + // "@typescript-eslint/dot-notation": "error", // Enabled in stylistic + // "@typescript-eslint/explicit-function-return-type": "error", + // "@typescript-eslint/explicit-member-accessibility": "error", + // "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/init-declarations": "error", + // "@typescript-eslint/max-params": "error", + // "@typescript-eslint/member-ordering": "error", + // "@typescript-eslint/method-signature-style": "error", + // "@typescript-eslint/naming-convention": "error", + // "@typescript-eslint/no-array-constructor": "error", // Enabled in recommended + // "@typescript-eslint/no-array-delete": "error", // Enabled in recommended + // "@typescript-eslint/no-base-to-string": "error", // Enabled in recommended + // "@typescript-eslint/no-confusing-non-null-assertion": "error", // Enabled in stylistic + // "@typescript-eslint/no-confusing-void-expression": "error", // Enabled in strict + // "@typescript-eslint/no-deprecated": "error", // Enabled in strict + // "@typescript-eslint/no-dupe-class-members": "error", + // "@typescript-eslint/no-duplicate-enum-values": "error", // Enabled in recommended + // "@typescript-eslint/no-duplicate-type-constituents": "error", // Enabled in recommended + // "@typescript-eslint/no-dynamic-delete": "error", // Enabled in strict + // "@typescript-eslint/no-empty-function": "error", // Enabled in stylistic + // "@typescript-eslint/no-empty-object-type": "error", // Enabled in recommended + // "@typescript-eslint/no-explicit-any": "error", // Enabled in recommended + // "@typescript-eslint/no-extra-non-null-assertion": "error", // Enabled in recommended + // "@typescript-eslint/no-extraneous-class": "error", // Enabled in strict + // "@typescript-eslint/no-floating-promises": "error", // Enabled in recommended + // "@typescript-eslint/no-for-in-array": "error", // Enabled in recommended + // "@typescript-eslint/no-implied-eval": "error", // Enabled in recommended + // "@typescript-eslint/no-import-type-side-effects": "error", + // "@typescript-eslint/no-inferrable-types": "error", // Enabled in stylistic + // "@typescript-eslint/no-invalid-this": "error", + // "@typescript-eslint/no-invalid-void-type": "error", // Enabled in strict + // "@typescript-eslint/no-loop-func": "error", + // "@typescript-eslint/no-magic-numbers": "error", + // "@typescript-eslint/no-meaningless-void-operator": "error", // Enabled in strict + // "@typescript-eslint/no-misused-new": "error", // Enabled in recommended + // "@typescript-eslint/no-misused-promises": "error", // Enabled in recommended + // "@typescript-eslint/no-misused-spread": "error", // Enabled in strict + // "@typescript-eslint/no-mixed-enums": "error", // Enabled in strict + // "@typescript-eslint/no-namespace": "error", // Enabled in recommended + // "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error", // Enabled in strict + // "@typescript-eslint/no-non-null-asserted-optional-chain": "error", // Enabled in recommended + // "@typescript-eslint/no-non-null-assertion": "error", // Enabled in strict + // "@typescript-eslint/no-redeclare": "error", + // "@typescript-eslint/no-redundant-type-constituents": "error", // Enabled in recommended + // "@typescript-eslint/no-require-imports": "error", // Enabled in recommended + // "@typescript-eslint/no-restricted-imports": "error", + // "@typescript-eslint/no-restricted-types": "error", + // "@typescript-eslint/no-shadow": "error", + // "@typescript-eslint/no-this-alias": "error", // Enabled in recommended + // "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error", // Enabled in strict + // "@typescript-eslint/no-unnecessary-condition": "error", // Enabled in strict + // "@typescript-eslint/no-unnecessary-parameter-property-assignment": "error", + // "@typescript-eslint/no-unnecessary-qualifier": "error", + // "@typescript-eslint/no-unnecessary-template-expression": "error", // Enabled in strict + // "@typescript-eslint/no-unnecessary-type-arguments": "error", // Enabled in strict + // "@typescript-eslint/no-unnecessary-type-assertion": "error", // Enabled in recommended + // "@typescript-eslint/no-unnecessary-type-constraint": "error", // Enabled in recommended + // "@typescript-eslint/no-unnecessary-type-conversion": "error", + // "@typescript-eslint/no-unnecessary-type-parameters": "error", // Enabled in strict + // "@typescript-eslint/no-unsafe-argument": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-assignment": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-call": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-declaration-merging": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-enum-comparison": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-function-type": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-member-access": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-return": "error", // Enabled in recommended + // "@typescript-eslint/no-unsafe-type-assertion": "error", + // "@typescript-eslint/no-unsafe-unary-minus": "error", // Enabled in recommended + // "@typescript-eslint/no-unused-expressions": "error", // Enabled in recommended + // "@typescript-eslint/no-unused-vars": "error", // Enabled in recommended + // "@typescript-eslint/no-use-before-define": "error", + // "@typescript-eslint/no-useless-constructor": "error", // Enabled in strict + // "@typescript-eslint/no-useless-empty-export": "error", + // "@typescript-eslint/no-wrapper-object-types": "error", // Enabled in recommended + // "@typescript-eslint/non-nullable-type-assertion-style": "error", // Enabled in stylistic + // "@typescript-eslint/only-throw-error": "error", // Enabled in recommended + // "@typescript-eslint/parameter-properties": "error", + // "@typescript-eslint/prefer-as-const": "error", // Enabled in recommended + // "@typescript-eslint/prefer-destructuring": "error", + // "@typescript-eslint/prefer-enum-initializers": "error", + // "@typescript-eslint/prefer-find": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-for-of": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-function-type": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-includes": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-literal-enum-member": "error", // Enabled in strict + // "@typescript-eslint/prefer-namespace-keyword": "error", // Enabled in recommended + // "@typescript-eslint/prefer-nullish-coalescing": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-optional-chain": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-promise-reject-errors": "error", // Enabled in recommended + "@typescript-eslint/prefer-readonly": "error", + // "@typescript-eslint/prefer-readonly-parameter-types": "error", + // "@typescript-eslint/prefer-reduce-type-parameter": "error", // Enabled in strict + // "@typescript-eslint/prefer-regexp-exec": "error", // Enabled in stylistic + // "@typescript-eslint/prefer-return-this-type": "error", // Enabled in strict + // "@typescript-eslint/prefer-string-starts-ends-with": "error", // Enabled in stylistic + // "@typescript-eslint/promise-function-async": "error", + // "@typescript-eslint/related-getter-setter-pairs": "error", // Enabled in strict + // "@typescript-eslint/require-array-sort-compare": "error", + // "@typescript-eslint/require-await": "error", // Enabled in recommended + // "@typescript-eslint/restrict-plus-operands": "error", // Enabled in recommended + "@typescript-eslint/restrict-template-expressions": ["error", { + allowBoolean: true, + allowNullish: true, + allowNumber: true, + allowRegExp: true, + }], // Enabled in recommended + // "@typescript-eslint/return-await": "error", // Enabled in strict + // "@typescript-eslint/strict-boolean-expressions": "error", + // "@typescript-eslint/switch-exhaustiveness-check": "error", + // "@typescript-eslint/triple-slash-reference": "error", // Enabled in recommended + // "@typescript-eslint/unbound-method": "error", // Enabled in recommended + // "@typescript-eslint/unified-signatures": "error", // Enabled in strict + // "@typescript-eslint/use-unknown-in-catch-callback-variable": "error", // Enabled in strict + } + }, +]; diff --git a/build/eslint-config-shared/typescript-eslint-additions.cjs b/build/eslint-config-shared/typescript-eslint-additions.cjs deleted file mode 100644 index c8d848a..0000000 --- a/build/eslint-config-shared/typescript-eslint-additions.cjs +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -// This config includes rules that are not mentioned in the recommended rulesets but seem good. -// Only includes typescript-eslint rules, not base eslint - the latter are in eslint-additions.js - -module.exports = { - rules: { - "@typescript-eslint/no-unnecessary-condition": "error", - "@typescript-eslint/restrict-template-expressions": ["error", { - allowBoolean: true, - allowNullish: true, - allowNumber: true, - allowRegExp: true, - }], - } -}; diff --git a/examples/.eslintrc.cjs b/examples/.eslintrc.cjs deleted file mode 100644 index c5a9ba3..0000000 --- a/examples/.eslintrc.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: [ - "eslint-config-shared/shared.cjs", - ], - root: true, -}; diff --git a/examples/eslint.config.js b/examples/eslint.config.js new file mode 100644 index 0000000..c89576d --- /dev/null +++ b/examples/eslint.config.js @@ -0,0 +1,3 @@ +import projectConfigs from "eslint-config-shared"; + +export default projectConfigs; diff --git a/examples/package.json b/examples/package.json index e5470cd..4ded621 100644 --- a/examples/package.json +++ b/examples/package.json @@ -4,8 +4,8 @@ "description": "Examples for demonstrating packages in the monorepo", "scripts": { "build": "tsc", - "clean": "rm -rf built && rm -rf webpacked", - "lint": "eslint src", + "clean": "rm -rf built webpacked", + "lint": "eslint", "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests built/.*.test.js", "webpack": "webpack", "start": "webpack-dev-server" @@ -17,24 +17,22 @@ "dependencies": { "@chumpchief/package1": "workspace:*", "@chumpchief/package2": "workspace:*", - "react": "^18.3.1", - "react-dom": "^18.3.1" + "react": "^19.1.0", + "react-dom": "^19.1.0" }, "devDependencies": { - "@jest/globals": "^29.7.0", - "@types/react": "^18.3.1", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", - "eslint": "^8.57.0", + "@jest/globals": "^30.0.4", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "eslint": "^9.30.1", "eslint-config-shared": "workspace:*", - "html-webpack-plugin": "^5.6.0", - "jest": "^29.7.0", - "ts-loader": "^9.5.1", + "html-webpack-plugin": "^5.6.3", + "jest": "^30.0.4", + "ts-loader": "^9.5.2", "tsconfig-shared": "workspace:*", - "typescript": "^5.4.5", - "webpack": "^5.91.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" + "typescript": "^5.8.3", + "webpack": "^5.100.0", + "webpack-cli": "^6.0.1", + "webpack-dev-server": "^5.2.2" } } diff --git a/examples/src/index.tsx b/examples/src/index.tsx index 2423edb..e28f923 100644 --- a/examples/src/index.tsx +++ b/examples/src/index.tsx @@ -1,4 +1,5 @@ import { createRoot } from "react-dom/client"; + import { ExampleListView } from "./exampleListView.js"; const contentDiv = document.querySelector("#content"); diff --git a/examples/src/package1-example/view/appView.tsx b/examples/src/package1-example/view/appView.tsx index 7ad9da8..4a18052 100644 --- a/examples/src/package1-example/view/appView.tsx +++ b/examples/src/package1-example/view/appView.tsx @@ -1,6 +1,7 @@ -import { foo1, foo2, bar1, bar2 } from "@chumpchief/package1"; import type { FC } from "react"; +import { bar1, bar2, foo1, foo2 } from "@chumpchief/package1"; + export const AppView: FC = () => (