From e009d4cd5221fb59190d9039d09fe30b59f77574 Mon Sep 17 00:00:00 2001 From: Ron Cohen Date: Mon, 6 Apr 2026 21:15:32 +0200 Subject: [PATCH 1/2] Replace ESLint and Prettier with Oxc tooling --- .github/workflows/package-ci.yml | 12 +- .gitignore | 1 - .husky/pre-commit | 1 + .oxfmtrc.json | 25 + .oxlintrc.json | 24 + package.json | 32 +- packages/browser-sdk/eslint.config.js | 37 - packages/browser-sdk/package.json | 48 +- packages/browser-sdk/src/bulkQueue.ts | 2 +- packages/browser-sdk/src/client.ts | 20 +- packages/browser-sdk/src/feedback/feedback.ts | 11 +- .../src/feedback/ui/FeedbackDialog.tsx | 11 +- .../src/feedback/ui/FeedbackForm.tsx | 1 - .../src/feedback/ui/StarRating.tsx | 5 +- packages/browser-sdk/src/feedback/ui/index.ts | 1 - packages/browser-sdk/src/flag/flagCache.ts | 1 - packages/browser-sdk/src/flag/flags.ts | 1 - packages/browser-sdk/src/hooksManager.ts | 2 +- packages/browser-sdk/src/httpClient.ts | 2 +- packages/browser-sdk/src/sse.ts | 2 +- packages/browser-sdk/src/toolbar/Switch.tsx | 56 +- packages/browser-sdk/src/toolbar/Toolbar.tsx | 1 - packages/browser-sdk/src/toolbar/index.ts | 1 - packages/browser-sdk/src/ui/Dialog.tsx | 2 +- .../floating-ui-preact-dom/useFloating.ts | 8 +- packages/browser-sdk/test/client.test.ts | 1 - .../test/e2e/acceptance.browser.spec.ts | 1 + .../test/e2e/feedback-widget.browser.spec.ts | 1 + packages/browser-sdk/test/flags.test.ts | 3 +- packages/browser-sdk/test/init.test.ts | 1 - packages/browser-sdk/test/rateLimiter.test.ts | 1 - packages/browser-sdk/test/sse.test.ts | 1 - packages/browser-sdk/test/usage.test.ts | 1 - packages/browser-sdk/tsconfig.eslint.json | 4 - packages/browser-sdk/vite.config.mjs | 1 + packages/cli/commands/flags.ts | 3 +- packages/cli/commands/init.ts | 3 +- packages/cli/commands/mcp.ts | 5 +- packages/cli/commands/new.ts | 1 - packages/cli/commands/rules.ts | 5 +- packages/cli/eslint.config.js | 3 - packages/cli/package.json | 37 +- packages/cli/stores/config.ts | 5 +- packages/cli/tsconfig.eslint.json | 3 - packages/cli/utils/auth.ts | 2 +- packages/cli/utils/gen.ts | 4 +- packages/cli/utils/version.ts | 1 + packages/eslint-config/base.js | 170 - packages/eslint-config/package.json | 23 - packages/flag-evaluation/eslint.config.js | 3 - packages/flag-evaluation/package.json | 31 +- packages/flag-evaluation/tsconfig.eslint.json | 4 - packages/management-sdk/eslint.config.js | 8 - .../app/flags/company/page.tsx | 5 +- .../customer-admin-panel/app/flags/page.tsx | 3 +- .../app/flags/user/page.tsx | 5 +- .../customer-admin-panel/package.json | 7 +- packages/management-sdk/package.json | 31 +- packages/management-sdk/src/api.ts | 2 +- packages/management-sdk/tsconfig.eslint.json | 4 - packages/node-sdk/eslint.config.js | 3 - .../node-sdk/examples/express/app.test.ts | 2 +- packages/node-sdk/examples/express/app.ts | 6 +- .../node-sdk/examples/express/package.json | 11 +- packages/node-sdk/examples/express/serve.ts | 3 +- packages/node-sdk/package.json | 41 +- packages/node-sdk/src/config.ts | 1 - .../test/flagsFallbackProvider.test.ts | 1 + packages/node-sdk/test/flusher.test.ts | 1 + packages/node-sdk/test/utils.test.ts | 1 + packages/node-sdk/tsconfig.eslint.json | 4 - .../eslint.config.js | 3 - .../example/.eslintrc.json | 3 - .../example/app/featureManagement.ts | 3 +- .../example/app/layout.tsx | 1 + .../example/app/page.tsx | 3 +- .../example/components/Context.tsx | 2 +- .../example/components/HuddleFeature.tsx | 3 +- .../components/OpenFeatureProvider.tsx | 3 +- .../example/package.json | 9 +- .../openfeature-browser-provider/package.json | 39 +- .../tsconfig.eslint.json | 4 - .../vite.config.js | 1 + .../eslint.config.js | 3 - .../openfeature-node-provider/example/app.ts | 10 +- .../example/package.json | 8 +- .../example/reflag.ts | 1 + .../example/serve.ts | 2 +- .../openfeature-node-provider/package.json | 43 +- .../tsconfig.eslint.json | 4 - .../react-native-sdk/dev/bare-rn/.eslintrc.js | 4 - .../dev/bare-rn/.prettierrc.js | 5 - packages/react-native-sdk/dev/bare-rn/App.tsx | 116 +- .../dev/bare-rn/babel.config.js | 2 +- .../react-native-sdk/dev/bare-rn/index.js | 6 +- .../dev/bare-rn/metro.config.js | 10 +- packages/react-native-sdk/dev/expo/App.tsx | 11 +- .../react-native-sdk/dev/expo/package.json | 2 +- packages/react-native-sdk/eslint.config.js | 18 - packages/react-native-sdk/package.json | 37 +- packages/react-native-sdk/src/index.tsx | 2 +- .../react-native-sdk/tsconfig.eslint.json | 4 - .../dev/nextjs-bootstrap-demo/.eslintrc.json | 3 - .../dev/nextjs-bootstrap-demo/app/layout.tsx | 4 +- .../dev/nextjs-bootstrap-demo/app/page.tsx | 1 + .../components/Flags.tsx | 1 + .../dev/nextjs-bootstrap-demo/package.json | 9 +- .../dev/nextjs-bootstrap-demo/tsconfig.json | 14 +- .../dev/nextjs-flag-demo/.eslintrc.json | 3 - .../dev/nextjs-flag-demo/app/layout.tsx | 1 + .../dev/nextjs-flag-demo/app/page.tsx | 1 + .../dev/nextjs-flag-demo/components/Flags.tsx | 1 + .../nextjs-flag-demo/components/Providers.tsx | 1 + .../dev/nextjs-flag-demo/package.json | 9 +- .../dev/nextjs-flag-demo/tsconfig.json | 21 +- packages/react-sdk/eslint.config.js | 50 - packages/react-sdk/package.json | 59 +- packages/react-sdk/test/usage.test.tsx | 4 +- packages/react-sdk/tsconfig.eslint.json | 4 - packages/react-sdk/vite.config.mjs | 1 + packages/rest-api-sdk/package.json | 6 +- packages/tsconfig/package.json | 4 +- packages/vue-sdk/eslint.config.js | 54 - packages/vue-sdk/package.json | 49 +- packages/vue-sdk/tsconfig.eslint.json | 4 - packages/vue-sdk/vite.config.mjs | 1 + yarn.lock | 4845 +++-------------- 127 files changed, 1220 insertions(+), 5056 deletions(-) create mode 100755 .husky/pre-commit create mode 100644 .oxfmtrc.json create mode 100644 .oxlintrc.json delete mode 100644 packages/browser-sdk/eslint.config.js delete mode 100644 packages/browser-sdk/tsconfig.eslint.json delete mode 100644 packages/cli/eslint.config.js delete mode 100644 packages/cli/tsconfig.eslint.json delete mode 100644 packages/eslint-config/base.js delete mode 100644 packages/eslint-config/package.json delete mode 100644 packages/flag-evaluation/eslint.config.js delete mode 100644 packages/flag-evaluation/tsconfig.eslint.json delete mode 100644 packages/management-sdk/eslint.config.js delete mode 100644 packages/management-sdk/tsconfig.eslint.json delete mode 100644 packages/node-sdk/eslint.config.js delete mode 100644 packages/node-sdk/tsconfig.eslint.json delete mode 100644 packages/openfeature-browser-provider/eslint.config.js delete mode 100644 packages/openfeature-browser-provider/example/.eslintrc.json delete mode 100644 packages/openfeature-browser-provider/tsconfig.eslint.json delete mode 100644 packages/openfeature-node-provider/eslint.config.js delete mode 100644 packages/openfeature-node-provider/tsconfig.eslint.json delete mode 100644 packages/react-native-sdk/dev/bare-rn/.eslintrc.js delete mode 100644 packages/react-native-sdk/dev/bare-rn/.prettierrc.js delete mode 100644 packages/react-native-sdk/eslint.config.js delete mode 100644 packages/react-native-sdk/tsconfig.eslint.json delete mode 100644 packages/react-sdk/dev/nextjs-bootstrap-demo/.eslintrc.json delete mode 100644 packages/react-sdk/dev/nextjs-flag-demo/.eslintrc.json delete mode 100644 packages/react-sdk/eslint.config.js delete mode 100644 packages/react-sdk/tsconfig.eslint.json delete mode 100644 packages/vue-sdk/eslint.config.js delete mode 100644 packages/vue-sdk/tsconfig.eslint.json diff --git a/.github/workflows/package-ci.yml b/.github/workflows/package-ci.yml index 38f3d41f8..064a3b20c 100644 --- a/.github/workflows/package-ci.yml +++ b/.github/workflows/package-ci.yml @@ -46,15 +46,9 @@ jobs: name: Build & Test Report path: ./packages/*/junit.xml reporter: jest-junit - - id: prettier - name: Check styling - run: yarn prettier + - id: fmt + name: Check formatting + run: yarn fmt - id: lint name: Check for linting errors run: yarn lint:ci - - name: Annotate from ESLint report - uses: ataylorme/eslint-annotate-action@v2 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - report-json: ./packages/*/eslint-report.json - fail-on-warning: true diff --git a/.gitignore b/.gitignore index a754d878b..0d520eb65 100644 --- a/.gitignore +++ b/.gitignore @@ -41,5 +41,4 @@ playwright/.cache/ junit.xml .next -eslint-report.json reflag.config.json diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..372362317 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +yarn lint-staged diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 000000000..5ad80bb63 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,25 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "printWidth": 80, + "ignorePatterns": [ + "**/__snapshots__/**", + "**/build/**", + "**/dist/**", + "**/gen/**", + "coverage/**", + "playwright-report/**", + "test-results/**", + "packages/management-sdk/src/generated/**", + "packages/node-sdk/examples/cloudflare-worker/worker-configuration.d.ts" + ], + "experimentalSortImports": { + "groups": [ + "builtin", + "external", + "internal", + ["parent", "sibling", "index"] + ], + "internalPattern": ["@reflag/", "@/"], + "newlinesBetween": true + } +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 000000000..07b6d739d --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,24 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["typescript", "react", "import"], + "rules": { + "no-unused-vars": "warn", + "unicorn/no-thenable": "off", + "react/exhaustive-deps": "warn", + "import/no-duplicates": "warn", + "sort-imports": "off", + "typescript/no-floating-promises": "error" + }, + "ignorePatterns": [ + "build/", + "**/build/**", + "**/dist/**", + "**/gen/**", + "node_modules/", + "coverage/", + "playwright-report/", + "test-results/", + "packages/management-sdk/src/generated/**", + "packages/node-sdk/examples/cloudflare-worker/worker-configuration.d.ts" + ] +} diff --git a/package.json b/package.json index e551f0435..76d8323be 100644 --- a/package.json +++ b/package.json @@ -16,21 +16,25 @@ "build": "lerna run build --stream", "test:ci": "lerna run test:ci --stream", "test": "lerna run test --stream", - "format": "lerna run format --stream", - "prettier": "lerna run prettier --stream", - "prettier:fix": "lerna run prettier -- --write", - "lint": "lerna run lint --stream", - "lint:ci": "lerna run lint:ci --stream", + "format": "yarn fmt:fix && yarn lint:fix", + "lint": "yarn oxlint .", + "lint:ci": "yarn oxlint .", "version-packages": "changeset version && YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install", "release-packages": "yarn build && yarn release", "release": "changeset publish", - "docs": "./docs.sh" + "docs": "./docs.sh", + "lint:fix": "yarn oxlint --fix .", + "fmt": "yarn oxfmt --check .", + "fmt:fix": "yarn oxfmt --write .", + "postinstall": "husky" }, - "packageManager": "yarn@4.10.3", "devDependencies": { "@changesets/cli": "^2.29.6", + "husky": "^9.1.7", "lerna": "^8.1.3", - "prettier": "^3.5.2", + "lint-staged": "^16.2.7", + "oxfmt": "^0.27.0", + "oxlint": "^1.42.0", "react": "19.1.0", "react-dom": "19.1.0", "typedoc": "0.27.6", @@ -42,5 +46,15 @@ "resolutions": { "react": "19.1.0", "react-dom": "19.1.0" - } + }, + "lint-staged": { + "*.{ts,tsx,js,jsx,mjs,cjs,mts,cts,vue}": [ + "oxfmt --write", + "oxlint --fix" + ], + "*.{json,md,yml,yaml,css,html}": [ + "oxfmt --write" + ] + }, + "packageManager": "yarn@4.10.3" } diff --git a/packages/browser-sdk/eslint.config.js b/packages/browser-sdk/eslint.config.js deleted file mode 100644 index 8fbaf1877..000000000 --- a/packages/browser-sdk/eslint.config.js +++ /dev/null @@ -1,37 +0,0 @@ -const base = require("@reflag/eslint-config"); -const preactConfig = require("eslint-config-preact"); - -const compatPlugin = require("eslint-plugin-compat"); -const reactPlugin = require("eslint-plugin-react"); -const reactHooksPlugin = require("eslint-plugin-react-hooks"); - -module.exports = [ - ...base, - { - // Preact projects - files: ["**/*.tsx"], - - settings: { - react: { - // We only care about marking h() as being a used variable. - pragma: "h", - // We use "react 16.0" to avoid pushing folks to UNSAFE_ methods. - version: "16.0", - }, - }, - plugins: { - compat: compatPlugin, - react: reactPlugin, - "react-hooks": reactHooksPlugin, - }, - rules: { - ...preactConfig.rules, - // Ignore React attributes that are not valid in Preact. - // Alternatively, we could use the preact/compat alias or turn off the rule. - "react/no-unknown-property": ["off"], - "no-unused-vars": ["off"], - "react/no-danger": ["off"], - }, - }, - { ignores: ["dist/", "example/"] }, -]; diff --git a/packages/browser-sdk/package.json b/packages/browser-sdk/package.json index 1ea8b94ee..1cc397caf 100644 --- a/packages/browser-sdk/package.json +++ b/packages/browser-sdk/package.json @@ -1,29 +1,11 @@ { "name": "@reflag/browser-sdk", "version": "1.4.7", - "packageManager": "yarn@4.1.1", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/reflagcom/javascript.git" }, - "publishConfig": { - "access": "public" - }, - "scripts": { - "dev": "vite", - "build": "tsc --project tsconfig.native.json && tsc --project tsconfig.build.json && vite build", - "test": "vitest run", - "test:watch": "vitest", - "test:e2e": "yarn build && playwright test", - "test:ci": "yarn test --reporter=default --reporter=junit --outputFile=junit.xml && yarn test:e2e", - "coverage": "yarn test --coverage", - "lint": "eslint .", - "lint:ci": "eslint --output-file eslint-report.json --format json .", - "prettier": "prettier --check .", - "format": "yarn lint --fix && yarn prettier --write", - "preversion": "yarn lint && yarn prettier && yarn test && yarn build" - }, "files": [ "dist" ], @@ -32,12 +14,31 @@ "react-native": "./dist/index.native.js", "exports": { ".": { + "types": "./dist/types/src/index.d.ts", "react-native": "./dist/index.native.js", "import": "./dist/reflag-browser-sdk.mjs", - "require": "./dist/reflag-browser-sdk.umd.js", - "types": "./dist/types/src/index.d.ts" + "require": "./dist/reflag-browser-sdk.umd.js" } }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "dev": "vite", + "build": "tsc --project tsconfig.native.json && tsc --project tsconfig.build.json && vite build", + "test": "vitest run", + "test:watch": "vitest", + "test:e2e": "yarn build && playwright test", + "test:ci": "yarn test --reporter=default --reporter=junit --outputFile=junit.xml && yarn test:e2e", + "coverage": "yarn test --coverage", + "lint": "oxlint .", + "lint:ci": "oxlint .", + "format": "yarn fmt:fix && yarn lint:fix", + "preversion": "yarn lint && yarn fmt && yarn test && yarn build", + "lint:fix": "oxlint --fix .", + "fmt": "oxfmt --check .", + "fmt:fix": "oxfmt --write ." + }, "dependencies": { "@floating-ui/dom": "^1.6.8", "fast-equals": "^5.2.2", @@ -46,14 +47,11 @@ }, "devDependencies": { "@playwright/test": "^1.49.1", - "@reflag/eslint-config": "0.0.2", "@reflag/tsconfig": "0.0.2", "@types/js-cookie": "^3.0.6", "@types/node": "^22.12.0", "@vitest/coverage-v8": "^2.0.4", "c8": "~10.1.3", - "eslint": "^9.21.0", - "eslint-config-preact": "^1.5.0", "http-server": "^14.1.1", "jsdom": "^24.1.0", "msw": "^2.3.4", @@ -61,11 +59,11 @@ "postcss": "^8.4.33", "postcss-nesting": "^12.0.2", "postcss-preset-env": "^9.3.0", - "prettier": "^3.5.2", "typescript": "^5.7.3", "vite": "^5.3.5", "vite-plugin-dts": "^4.0.0-beta.1", "vite-plugin-static-copy": "^2.3.2", "vitest": "^2.0.4" - } + }, + "packageManager": "yarn@4.1.1" } diff --git a/packages/browser-sdk/src/bulkQueue.ts b/packages/browser-sdk/src/bulkQueue.ts index df95bbd91..5034e511f 100644 --- a/packages/browser-sdk/src/bulkQueue.ts +++ b/packages/browser-sdk/src/bulkQueue.ts @@ -1,6 +1,6 @@ -import { logResponseError } from "./utils/responseError"; import { BULK_QUEUE_FLUSH_DELAY_MS, BULK_QUEUE_MAX_SIZE } from "./config"; import { Logger } from "./logger"; +import { logResponseError } from "./utils/responseError"; const DROP_ERROR_THROTTLE_MS = 15 * 60 * 1000; diff --git a/packages/browser-sdk/src/client.ts b/packages/browser-sdk/src/client.ts index 1be8f82d8..f17b52bb8 100644 --- a/packages/browser-sdk/src/client.ts +++ b/packages/browser-sdk/src/client.ts @@ -1,5 +1,13 @@ import { deepEqual } from "fast-equals"; +import { BulkEvent, BulkQueue } from "./bulkQueue"; +import { + API_BASE_URL, + APP_BASE_URL, + IS_SERVER, + SSE_REALTIME_BASE_URL, +} from "./config"; +import { ReflagContext, ReflagDeprecatedContext } from "./context"; import { AutoFeedback, Feedback, @@ -15,21 +23,13 @@ import { FlagsClient, RawFlags, } from "./flag/flags"; -import { ToolbarPosition } from "./ui/types"; -import { logResponseError } from "./utils/responseError"; -import { BulkEvent, BulkQueue } from "./bulkQueue"; -import { - API_BASE_URL, - APP_BASE_URL, - IS_SERVER, - SSE_REALTIME_BASE_URL, -} from "./config"; -import { ReflagContext, ReflagDeprecatedContext } from "./context"; import { HookArgs, HooksManager, State } from "./hooksManager"; import { HttpClient } from "./httpClient"; import { Logger, loggerWithPrefix, quietConsoleLogger } from "./logger"; import { StorageAdapter } from "./storage"; import { showToolbarToggle } from "./toolbar"; +import { ToolbarPosition } from "./ui/types"; +import { logResponseError } from "./utils/responseError"; const isMobile = typeof window !== "undefined" && window.innerWidth < 768; const isNode = typeof document === "undefined"; // deno supports "window" but not "document" according to https://remix.run/docs/en/main/guides/gotchas diff --git a/packages/browser-sdk/src/feedback/feedback.ts b/packages/browser-sdk/src/feedback/feedback.ts index 20e6c939e..4a553f5dd 100644 --- a/packages/browser-sdk/src/feedback/feedback.ts +++ b/packages/browser-sdk/src/feedback/feedback.ts @@ -5,12 +5,6 @@ import { AblySSEChannel, openAblySSEChannel } from "../sse"; import { Position } from "../ui/types"; import { logResponseError } from "../utils/responseError"; import { retryOnThrow } from "../utils/retry"; - -import { - FeedbackSubmission, - FeedbackTranslations, - OpenFeedbackFormOptions, -} from "./ui/types"; import { FeedbackPromptCompletionHandler, parsePromptMessage, @@ -19,6 +13,11 @@ import { import { getAuthToken } from "./promptStorage"; import * as feedbackLib from "./ui"; import { DEFAULT_POSITION } from "./ui"; +import { + FeedbackSubmission, + FeedbackTranslations, + OpenFeedbackFormOptions, +} from "./ui/types"; const INITIAL_FETCH_RETRY_DELAYS_MS = [0, 5000]; diff --git a/packages/browser-sdk/src/feedback/ui/FeedbackDialog.tsx b/packages/browser-sdk/src/feedback/ui/FeedbackDialog.tsx index f551045fc..d5a834064 100644 --- a/packages/browser-sdk/src/feedback/ui/FeedbackDialog.tsx +++ b/packages/browser-sdk/src/feedback/ui/FeedbackDialog.tsx @@ -4,10 +4,9 @@ import { useCallback, useState } from "preact/hooks"; import { feedbackContainerId } from "../../ui/constants"; import { Dialog, useDialog } from "../../ui/Dialog"; import { Close } from "../../ui/icons/Close"; - import { DEFAULT_TRANSLATIONS } from "./config/defaultTranslations"; -import { useTimer } from "./hooks/useTimer"; import { FeedbackForm } from "./FeedbackForm"; +import { useTimer } from "./hooks/useTimer"; import styles from "./index.css?inline"; import { RadialProgress } from "./RadialProgress"; import { @@ -76,7 +75,7 @@ export const FeedbackDialog: FunctionComponent = ({ }, [autoClose, close, onDismiss]); return ( - <> +