Skip to content

chore: upgrade TypeScript to 5.5.4 and typescript-eslint v8 (zero runtime change) - #490

Merged
alanhwu merged 2 commits into
mainfrom
chore/typescript-5.5.4
Sep 3, 2026
Merged

chore: upgrade TypeScript to 5.5.4 and typescript-eslint v8 (zero runtime change)#490
alanhwu merged 2 commits into
mainfrom
chore/typescript-5.5.4

Conversation

@alanhwu

@alanhwu alanhwu commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrades the compiler from TypeScript 4.9.5 to 5.5.4 (exact pin), matching the backend monorepo this service is being prepared to migrate into, together with the dev tooling that peers on the TypeScript version. Zero runtime-behavior change: no source file under lib/ or bin/ is touched, and the synthesized CloudFormation templates, including all 8 Lambda bundle asset hashes, are byte-identical to main (method below).

Package versions

package before (declared → resolved) after (declared → resolved) note
typescript ^4.8.4 → 4.9.5 5.5.4 → 5.5.4 exact pin
@typescript-eslint/parser ^5.40.1 → 5.62.0 ^8.69.0 → 8.69.0 v5 does not support TS 5.5; v8 peers on typescript >=4.8.4 <6.1.0, eslint ^8.57.0 || ^9 || ^10
@typescript-eslint/eslint-plugin ^5.40.1 → 5.62.0 ^8.69.0 → 8.69.0 same
eslint ^8.26.0 → 8.57.1 ^8.57.0 → 8.57.1 declared floor raised to what typescript-eslint v8 requires; resolved version unchanged, still eslintrc (no flat config)
ts-node ^10.9.1 → 10.9.2 ^10.9.2 → 10.9.2 range only; 10.9.2 is the latest and supports TS 5.x
prettier-plugin-organize-imports ^3.1.1 → 3.2.4 ^3.2.4 → 3.2.4 range only; 3.2.4 is the last release supporting Prettier 2 (4.x requires Prettier 3)
ts-mocha ^10.0.0 → 10.1.0 ^10.1.0 → 10.1.0 range only; 11.x evaluated and deliberately not taken, see "Why not further"
ts-jest ^29.0.3 → 29.4.1 unchanged 29.4.1 peers on typescript >=4.3 <6; 29.4.12 evaluated and deliberately not taken, see "Why not further"
prettier, @types/node, jest, @swc/jest, esbuild, everything else unchanged unchanged

yarn.lock changes are confined to the packages above and their dev-only transitive closure (typescript-eslint v5 → v8 subtree: tsutils/tslib@1, globby, natural-compare-lite … out; ts-api-utils, tinyglobby, @typescript-eslint/project-service … in). No lockfile key changed its resolved version.

Source changes the compiler forced

None. TypeScript 5.5.4 compiles both tsconfig.json (yarn build) and tsconfig.cdk.json with zero errors; no annotation, generic, or narrowing change was needed anywhere.

The only file edits outside config are the 4 test files in the second commit (style: ...), where prettier-plugin-organize-imports running on TS 5.5's organizeImports sorts import specifiers case-insensitively (MOCK_FILLER_ADDRESS now before MockQuoter, deployMarkers after DASHBOARD_..., etc.). Pure specifier reordering within existing import statements; safe to skip in review.

tsconfig

Neither tsconfig uses any option TS 5.x deprecates or rejects (importsNotUsedAsValues, preserveValueImports, noImplicitUseStrict, suppressImplicitAnyIndexErrors, keyofStringsOnly, charset, out, noStrictGenericChecks, prepend, target: ES3 — none present). moduleResolution: node and all strictness flags are left exactly as they were.

tsconfig.cdk.json, two edits:

  1. Removed "files": ["./.env.js"]. The file does not exist in the repo, and npx tsc --noEmit -p tsconfig.cdk.json was already a hard error on main under TS 4.9.5 (TS6053: File '.env.js' not found), so the CDK-side compile check in the verification list could not pass without this. ts-node (which is what cdk synth and ts-mocha actually use with this config) ignores files/include/exclude by default, so synth and integ behavior are unaffected. With the entry gone, tsc -p tsconfig.cdk.json now type-checks the whole repo under module: commonjs, which is what that check is for.
  2. Added "skipLibCheck": true, mirroring tsconfig.json. Without it the CDK-side check fails only inside third-party .d.ts files (39 errors on main with TS 4.9.5 too: @types/mocha vs @types/jest globals, @smithy/core re-exports, aws-cdk-lib expecting IMixin from constructs ^10.5 — the existing peer warning —, missing @types/async-retry behind smart-order-router). No effect on ts-node (per-file diagnostics) or on esbuild. This is the one tsconfig edit not strictly a deprecation fix; if you would rather not have it, drop it and run the check as npx tsc --noEmit -p tsconfig.cdk.json --skipLibCheck.

ESLint: preset/rule mapping (lint result identical)

.eslintrc still extends eslint:recommended, plugin:@typescript-eslint/eslint-recommended, plugin:@typescript-eslint/recommended (all still exist in v8; no rename). The custom rules, including the three no-restricted-syntax selectors banning .only/fit/fdescribe and nested it(), are untouched. What v8 changed, and how it is mapped so the lint gate does not move:

v5 behaviour v8 change mapping in .eslintrc
ban-types: warn rule removed, split in three no-unsafe-function-type: warn, no-wrapper-object-types: warn, no-empty-object-type: ["warn", { allowInterfaces: "always" }] (repo has no-empty-interface: off, so interfaces stay allowed)
no-explicit-any: warn (recommended) raised to error pinned warn
no-non-null-assertion: warn (recommended) moved to strict pinned warn
adjacent-overload-signatures, no-empty-function, no-inferrable-types: error (recommended) moved to stylistic pinned error
no-unused-vars default caughtErrors: "none" default now "all" added caughtErrors: "none" to the existing ["warn", { argsIgnorePattern: "^_" }] (otherwise 1 new warning: unused err in lib/handlers/base/api-handler.ts:310)
new in recommended: no-duplicate-enum-values: error set off — its only hits are RedshiftColumnType in bin/stacks/analytics-stack.ts:34-35, where ALL_STATUS/BOT_EVENT_TYPE/ORDER_TYPE intentionally share 'text'; see findings
no-extra-semi, no-loss-of-precision (TS versions) removed / deprecated covered by the core rules already in eslint:recommended on ESLint 8
no-var-requires replaced by no-require-imports (v8 recommended) left on; reports nothing here

Other v8-only recommended rules (no-unused-expressions, no-unsafe-declaration-merging, no-require-imports) are left on; they report nothing in this repo.

Result: yarn lint before and after: ✖ 87 problems (0 errors, 87 warnings), and the normalized file:line severity rule list is identical (64 no-explicit-any, 14 no-non-null-assertion, 8 no-unused-vars, 1 no-unsafe-function-type (was ban-types)). Prettier --check clean. No new eslint-disable, @ts-ignore, @ts-expect-error, or any casts.

Why not further: ts-mocha 11 and ts-jest 29.4.12

Both were tried and both change what gets deployed, even though neither is a runtime dependency:

  1. ts-mocha 11 drops its nested ts-node@7.0.1 in favour of the repo's ts-node 10. That removes source-map-support@0.5.21 from the tree. bunyan (a runtime dependency) does an optional, undeclared require('source-map-support'), and esbuild bundles whatever version is hoisted, so the 4 Lambda bundles that include bunyan (quote handler, hard-quote handler, two cron lambdas) would silently switch from source-map-support 0.5.21 to 0.5.13.
  2. ts-jest 29.4.12 requests semver ^7.8.5 (29.4.1 requests ^7.7.2). Together with typescript-eslint v8's ^7.7.3, that makes yarn hoist semver@7.8.5 to the top level and nest 7.7.2 under @eth-optimism/sdk. The bundled code is byte-identical, but the Lambda source maps record the new path, so 3 asset hashes (and their AWS::Lambda::Version logical IDs) change, which would redeploy identical code to prod.

With ts-mocha on 10.x and ts-jest unchanged, everything is identical. Both bumps are ready to take once the phantom source-map-support dependency is made explicit (finding 1). ts-mocha 10 → ts-node 7.0.1 → TS 5.5.4 was checked: ts-mocha -p tsconfig.cdk.json --dry-run test/integ/**/*.test.ts compiles the integ suite and stops at the same COSIGNER_ADDR env check as on main.

Findings (preserved as-is, for separate PRs)

  1. Phantom runtime dependency: bunyan optionally requires source-map-support, which this repo never declares. Which version ends up inside the prod Lambda bundles is decided by yarn hoisting of dev tooling (today: 0.5.21 via ts-mocha 10 → ts-node 7). Suggest declaring source-map-support (pinned to 0.5.21 to keep the bundle identical), then taking ts-mocha 11 / ts-jest 29.4.12.
  2. RedshiftColumnType duplicate enum values (bin/stacks/analytics-stack.ts:30-35): ALL_STATUS, BOT_EVENT_TYPE, ORDER_TYPE all equal 'text'. Looks intentional (semantic aliases for the same SQL type), but no-duplicate-enum-values would flag it; rule left off here, decide separately.
  3. Unused catch binding catch (err) at lib/handlers/base/api-handler.ts:310; harmless, surfaced only by v8's new caughtErrors default.
  4. tsc -p tsconfig.cdk.json never compiled on main (missing .env.js in files, and 39 third-party .d.ts errors without skipLibCheck). Fixed here as described above; nothing depended on it because ts-node ignores files.

Verification

Run from a clean yarn install --frozen-lockfile of this branch (Node 22.21.0, yarn 1.22.22, Java 1.8 available for jest-dynamodb):

check result
yarn install --frozen-lockfile && yarn build ✅ exit 0
npx tsc --noEmit -p tsconfig.cdk.json ✅ exit 0 (fails on main, see above)
yarn test:unit ✅ 36 suites, 347 tests, 38 snapshots passed; no .snap file modified
test/handlers/*/response-surface.test.ts ✅ pass with .snap files unmodified
yarn lint ✅ 87 problems / 0 errors, identical file:line/rule/severity set to main; prettier clean
npx cdk synth vs main ✅ all 7 *.template.json (root, pipeline, 2 nested, beta/prod assembly sets) byte-identical; 8/8 Lambda asset.* hashes identical

Synth comparison method (the naive comparison is misleading, see below): main and this branch each checked out in a git worktree, each with its own clean yarn install --frozen-lockfile, identical already-converged cdk.context.json, cdk synth run twice per side (run 1 == run 2 on both), then md5 over every *.template.json and over the asset.* directory names. A first attempt that reused the main checkout's long-lived node_modules for the baseline produced spurious asset-hash differences (its physical layout differs from a clean install: nested router-sdk copies, stale bufferutil/utf-8-validate), which is why the baseline was rebuilt from a clean install.

Not run: yarn test:integ (needs the integ env / COSIGNER_ADDR); compile of the integ suite under the new toolchain was verified with --dry-run as noted above.

alanhwu and others added 2 commits September 3, 2026 17:25
Pin typescript at 5.5.4 (matches the backend monorepo compiler) and move the
tooling that peers on it: @typescript-eslint/{parser,eslint-plugin} 5.62 -> 8.69
(eslint floor raised to ^8.57.0, still eslintrc), ts-node ^10.9.2, ts-mocha
^10.1.0, prettier-plugin-organize-imports ^3.2.4. ts-jest and ts-mocha 11 are
deliberately not bumped further: both change yarn hoisting in a way that alters
the Lambda bundles (semver source-map paths; bunyan's optional require of
source-map-support), see the PR description.

TS 5.5.4 compiles both tsconfigs with zero source changes. .eslintrc maps the
removed ban-types rule and pins the v5 `recommended` severities so the lint
result is identical (87 warnings, 0 errors, same file:line/rule set).
tsconfig.cdk.json drops the non-existent `.env.js` files entry (already a hard
TS6053 error for tsc on main; ts-node ignores `files`) and gains skipLibCheck
to match tsconfig.json, so `tsc -p tsconfig.cdk.json` now passes.

Synthesized templates and all 8 Lambda asset hashes are byte-identical to main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Pure specifier reordering inside existing import statements (TS 5's
organizeImports sorts case-insensitively). No code change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​typescript-eslint/​parser@​5.62.0 ⏵ 8.69.09910072 +298100
Updated@​typescript-eslint/​eslint-plugin@​5.62.0 ⏵ 8.69.09910080 +298100
Updatedtypescript@​4.9.5 ⏵ 5.5.4100 +11009010090

View full report

@socket-security

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn Low
Filesystem access: npm fdir with module fs

Module: fs

Location: Package overview

From: yarn.locknpm/@typescript-eslint/parser@8.69.0npm/@typescript-eslint/eslint-plugin@8.69.0npm/fdir@6.5.0

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/fdir@6.5.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Filesystem access: npm tinyglobby with module fs

Module: fs

Location: Package overview

From: yarn.locknpm/@typescript-eslint/parser@8.69.0npm/@typescript-eslint/eslint-plugin@8.69.0npm/tinyglobby@0.2.17

ℹ Read more on: This package | This alert | What is filesystem access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: If a package must read the file system, clarify what it will read and ensure it reads only what it claims to. If appropriate, packages can leave file system access to consumers and operate on data passed to it instead.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tinyglobby@0.2.17. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@alanhwu
alanhwu requested a review from SocksNFlops September 3, 2026 21:41
@alanhwu
alanhwu merged commit c2ec148 into main Sep 3, 2026
6 checks passed
@alanhwu
alanhwu deleted the chore/typescript-5.5.4 branch September 3, 2026 21:55
alanhwu added a commit that referenced this pull request Sep 3, 2026
…1, ts-jest 29.4.12; fix the two suppressed lint findings (#491)

* build: externalize source-map-support from the Lambda bundles

All nine NodejsFunctions now share LAMBDA_BUNDLING (minify + sourceMap as
before) with externalModules: ['@aws-sdk/*', 'source-map-support']. The first
entry restates CDK's default; the second stops bunyan's optional, undeclared
require('source-map-support') from pulling whichever copy dev tooling happens
to hoist into the production bundles. Nothing here uses it (no logger is
created with src: true, and NODE_OPTIONS=--enable-source-maps already covers
stack traces), and bunyan's try/catch handles the missing module.

Effect: the 4 bundles that include bunyan (quote, hard-quote, fade-rate cron,
redshift reaper) lose source-map-support, source-map and buffer-from (~35 KB
each); the 4 analytics bundles are byte-identical. Asset hashes stop moving on
unrelated dependency PRs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore(deps): ts-mocha 10 -> 11.1.0, ts-jest 29.4.1 -> 29.4.12

Both were held back from #490 because they changed the Lambda bundles through
yarn hoisting (ts-mocha 11 drops the nested ts-node 7 that supplied
source-map-support 0.5.21; ts-jest 29.4.12 moves semver 7.8.5 to the top
level). With source-map-support externalized that no longer matters. Integ
tests now compile under the repo's ts-node 10.9.2 instead of ts-node 7.0.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(lint): resolve the two findings #490 had to suppress

Remove the caughtErrors:"none" and no-duplicate-enum-values:"off" overrides
added in #490 to keep the lint gate identical, and fix what they hid:
- api-handler.ts: `catch (err)` with an unused binding -> `catch {}`.
- analytics-stack.ts: drop the unused RS_DATA_TYPES.ALL_STATUS and
  BOT_EVENT_TYPE members that duplicated ORDER_TYPE's 'text' value (the only
  one referenced). Column types are unchanged, so the Analytics template is
  byte-identical.

Lint stays at 87 warnings / 0 errors with the same file:line/rule set.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants