Upgrade eslint-config-expensify to 4.0.6#802
Conversation
Adopt modular v4 flat config with eslint-seatbelt to grandfather type-checked violations while removing the bespoke TypeScript plugin setup and App-specific rulesdir overrides from the old monolithic config. Co-authored-by: Cursor <cursoragent@cursor.com>
Base config already allows ?? and ?. in TypeScript and bans them only in JavaScript via file-scoped rules in es6.js. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the local class-methods-use-this override now that react.js no longer re-enables the rule disabled in style.js. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Drop no-restricted-syntax from tests block (browserConfig already sets the same 3 restrictions globally) - Drop react/jsx-props-no-spreading: off (not enabled by any upstream config; was a no-op) - Drop rulesdir/no-multiple-onyx-in-file: off (not enabled by any upstream config; was a no-op) - Drop @typescript-eslint/no-require-imports: off for .native.ts (tsExpensifyConfig already turns it off for all *.ts/*.tsx globally) Co-authored-by: Cursor <cursoragent@cursor.com>
Autofixes applied: - rulesdir/prefer-at: arr[N] → arr.at(N) - @typescript-eslint/dot-notation: obj['prop'] → obj.prop - @typescript-eslint/non-nullable-type-assertion-style: as NonNullable<T> → ! - @typescript-eslint/no-unnecessary-type-assertion: remove redundant casts - @typescript-eslint/prefer-nullish-coalescing: || → ?? where applicable - jsdoc/no-types: remove JSDoc type annotations in TS files Follow-up fixes for autofix side-effects: - Remove GenericCollection/OnyxInput unused imports made orphaned by the removal of type assertions that were their only usage - Add no-non-null-assertion seatbelt entries for the four files where non-nullable-type-assertion-style converted as NonNullable<T> → ! - Update seatbelt for newly surfaced unbound-method and unsafe-* counts in OnyxConnectionManager and OnyxCache perf-test files Co-authored-by: Cursor <cursoragent@cursor.com>
Configure Node globals for CJS config files, disable no-use-before-define in OnyxUtils, and relax test naming rules for collection key object properties. Co-authored-by: Cursor <cursoragent@cursor.com>
Use lodash.bindall and inline noop instead of umbrella lodash subpath imports that fail extraneous-deps. Co-authored-by: Cursor <cursoragent@cursor.com>
Type getItem with void key usage and hoist handlers outside the connect loop to satisfy no-loop-func. Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve template expressions, nullish coalescing, non-null assertions in lib code, unbound-method in tests, and type cleanup across OnyxUtils, merge, and utils. Update seatbelt to drop fixed suppressions while keeping test-only allowances. Co-authored-by: Cursor <cursoragent@cursor.com>
…pensify-4 Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # lib/OnyxConnectionManager.ts # lib/OnyxUtils.ts # tests/unit/OnyxConnectionManagerTest.ts # tests/unit/collectionHydrationTest.ts # tests/unit/onyxTest.ts # tests/unit/onyxUtilsTest.ts
Restore variadic noop stubs for InstanceSync, correct the circuit breaker halfOpen state check, guard indexed key lookups, and add lodash.bindall type declarations so prepare/build succeeds in CI. Co-authored-by: Cursor <cursoragent@cursor.com>
Remove stale seatbelt entries for dropped no-unsafe-argument rule, restore CustomTypeOptions as an augmentable interface for test:types, fix private property access and collection typing in tests, and restore IDB abort mocks so write-error normalization tests propagate DOMException. Co-authored-by: Cursor <cursoragent@cursor.com>
Sync seatbelt counts, add perf-test prefer-at override, restore CustomTypeOptions interface augmentation, fix typecheck issues in perf and storage provider tests, and resolve OnyxConnectionManager seatbelt rules. Co-authored-by: Cursor <cursoragent@cursor.com>
Add seatbelt entries for new rule violations, disable dot-notation in tests that access private APIs, and restore no-unsafe-argument budget. Co-authored-by: Cursor <cursoragent@cursor.com>
Dot-notation is disabled for test files globally, so the per-line directives were unused and caused lint to fail CI. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the local lodash.bindall module shim with the official DefinitelyTyped package now that imports use lodash.bindall directly. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop dot-notation and prefer-at disables for tests; use typed test harnesses for private member access, getAtIndex for array indexing, and restore useLiveRef deprecation with seatbelt-documented exceptions. Co-authored-by: Cursor <cursoragent@cursor.com>
Use unknown intermediate casts and ConnectOptions for generateConnectionID so test harness types match the real API. Co-authored-by: Cursor <cursoragent@cursor.com>
Fix lint CI prettier diff check after typecheck harness changes. Co-authored-by: Cursor <cursoragent@cursor.com>
The shared typescript config does not lint typeProperty, so the snake_case exception had no effect. Document why the tests override must repeat the base naming-convention rules. Co-authored-by: Cursor <cursoragent@cursor.com>
Grandfather snake_case type properties (record_key, page_size, page_count) that mirror SQLite column and PRAGMA result names after the eslint-config-expensify 4 upgrade started linting typeProperty names. Co-authored-by: Cursor <cursoragent@cursor.com>
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Record<string, unknown> excluded interface-based CustomTypeOptions values from deep nullish mapping, breaking partial nested Onyx.merge updates. Revert to the object constraint (arrays/builtins still excluded via NonTransformableTypes) and add a compile-time regression test for interface-shaped settings updates. Co-authored-by: Cursor <cursoragent@cursor.com>
This comment was marked as resolved.
This comment was marked as resolved.
Wrap JSON.stringify in a try/fallback path so circular objects, BigInt, functions, and symbols no longer throw during error normalization before classifyError can run. Co-authored-by: Cursor <cursoragent@cursor.com>
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
Call helper functions directly in setWithRetry, multiSetWithRetry, and setCollectionWithRetry instead of referencing the OnyxUtils export before it is defined. Move logKeyChanged and logKeyRemoved above their first use. Co-authored-by: Cursor <cursoragent@cursor.com>
Forward-declare the OnyxUtils export and route retry helpers through it so jest.spyOn(OnyxUtils, 'retryOperation' | 'getMergeQueue' | ...) still intercepts internal calls without needing no-use-before-define off. Co-authored-by: Cursor <cursoragent@cursor.com>
Retry helpers call sibling functions directly — all are already defined above them in the file. Update tests to count Storage.setItem attempts and seed the real merge queue instead of spying on the export object. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3f31868ab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (lastChange === undefined) { | ||
| return {result: (existingValue ?? {}) as TChange, replaceNullPatches: []}; |
There was a problem hiding this comment.
Preserve undefined updates instead of writing empty objects
When Onyx.update() batches a SET/MULTI_SET entry whose value is undefined (for example from a JS caller or an optional Partial multiSet property), the queue is [null, undefined] and Onyx.ts calls mergeChanges(operations) before forwarding the result to set(). This new fallback turns that undefined into {} because no existingValue is supplied, so an update that should be ignored like Onyx.set()/multiSet() currently do will instead write an empty object and notify subscribers. Keep the old undefined result here or skip undefined set entries before batching.
Useful? React with 👍 / 👎.
When Onyx.update batches [null, undefined], return undefined instead of
coercing to {} so set() ignores the entry like a direct multiSet would.
Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
eslint-config-expensifyfrom2.0.108to4.0.6and replaces the monolithicimport expensify from 'eslint-config-expensify'config with modular sub-configs (browser,react,typescript,jest,scripts), matching the pattern used inexpensify-common.@typescript-eslintplugin/parser block and ~40 per-rule overrides that duplicated what v4 now ships (type imports/exports, import extensions, redeclare handling, JSDoc disables, etc.).eslint-seatbeltwith an initial baseline (eslint.seatbelt.tsv) to grandfather existing type-checked violations from the jump torecommendedTypeChecked, without blocking CI.eslint-plugin-import,eslint-plugin-jsx-a11y,eslint-plugin-react,@typescript-eslint/*,@lwc/eslint-plugin-lwc,@react-native-community/eslint-config) now provided transitively byeslint-config-expensify.eslint-disablecomments for rules that v4 no longer reports (dot-notation,@typescript-eslint/no-empty-function).Overrides retained (by category)
Onyx / project-structure specific (intentional):
rulesdir/no-multiple-onyx-in-file: offimport/extensions: offtests/**, mocksno-restricted-syntax(allowfor...of/for...in)@typescript-eslint/no-require-imports: off**/*.native.ts(x)require()globals.jestMemoryOnlyProvider.tsglobalIgnoresfor.github/**,dist/**,cpp/**, etc.Not Onyx-specific (generic library / TypeScript conventions — candidates to remove over time):
class-methods-use-this: offes/no-optional-chaining: offes/no-nullish-coalescing-operators: offreact/prop-types: offreact/require-default-props: offreact/jsx-props-no-spreading: offuseOnyx) spread props intentionallyDeliberately not imported:
eslint-config-expensify/expensify— contains App-onlyrulesdir/*rules (prefer-onyx-connect-in-libs,no-onyx-connect, restrictedreact-nativeimports, etc.) that do not apply to this package.Follow-up work
eslint.seatbelt.tsvby fixing type-checked violations (813 grandfathered warnings), especially@typescript-eslint/no-unsafe-*in generic Onyx typing code and tests.Test plan
npm ciand confirm dependencies install cleanly.CI=true npm run lintand confirm it exits 0 (seatbelt frozen mode).npm run buildand confirm TypeScript compilation succeeds.npm testand confirm the unit test suite passes.