n8n/scripts/typescript-migration
2026-07-15 16:07:30 +03:00
..
results Nodes langchain 2026-07-15 16:07:30 +03:00
add-import-extensions.mjs chore: Set up repository for TypeScript 7 migration (#33890) 2026-07-09 13:21:16 +03:00
benchmark.mjs chore: Set up repository for TypeScript 7 migration (#33890) 2026-07-09 13:21:16 +03:00
README.md chore: Set up repository for TypeScript 7 migration (#33890) 2026-07-09 13:21:16 +03:00
summarize.mjs chore: Set up repository for TypeScript 7 migration (#33890) 2026-07-09 13:21:16 +03:00
SUMMARY.md chore: Migrate more packages to Typescript 7 (#34216) 2026-07-15 12:42:14 +03:00

TypeScript 6 → 7 migration tooling

Support scripts for migrating the monorepo from TypeScript 6.0.2 to the TypeScript 7 line, and for moving legacy packages off moduleResolution: node onto NodeNext. Migration is done per package.

Scripts

benchmark.mjs — build/typecheck timing

Times a single package's build and typecheck scripts and records the result to a per-package JSON file. Run it before switching compilers, switch, then run it again — the second run appends to the same file and prints a delta table.

# before the switch
node scripts/typescript-migration/benchmark.mjs @n8n/config --label=before

# … swap in the TS 7 compiler …

# after — appends to the same file and prints the before/after delta
node scripts/typescript-migration/benchmark.mjs @n8n/config --label=after

Options

Flag Default Meaning
<package> Workspace name (@n8n/config) or a package dir.
--label=<name> ts-<tsc version> Storage key. Different compilers auto-separate by version.
--runs=<n> 3 Repetitions per task; reports min/median/mean.
--tasks=a,b typecheck,build Subset to run. Missing scripts are skipped with a warning.
--no-prepare prepare on Skip the untimed dependency prebuild.

How it isolates the package — dependencies are prebuilt once (untimed) via turbo run build --filter=<pkg>^..., then each timed run deletes the package's dist/ + *.tsbuildinfo (cold compile) and runs the package script directly with pnpm --filter <pkg> run <task>, bypassing turbo's cache. So the numbers reflect only that package's own tsc (+ tsc-alias) time.

Results land in results/<pkg>.json (gitignored). The label is compiler- agnostic: this script never installs or selects TypeScript — wire that up separately and just re-run with a new --label.

add-import-extensions.mjs — NodeNext import codemod

Adds explicit .js / .json / /index.js extensions to relative import, re-export, and dynamic-import() specifiers, which NodeNext (and ESM) require.

# dry-run: prints every rewrite it would make
node scripts/typescript-migration/add-import-extensions.mjs packages/workflow

# apply
node scripts/typescript-migration/add-import-extensions.mjs packages/workflow --write
  • Uses ts-morph (already a catalog dep) and the package's tsconfig.json to find source files.
  • Skips bare/alias specifiers (@/…, @utils/…, package names) — alias tails get their extension from tsc-alias's resolveFullPaths at build time.
  • Skips specifiers that already carry a known extension.
  • Reports any relative specifier it can't resolve on disk for manual review; it does not guess.

Per-package migration loop

  1. Baseline: benchmark.mjs <pkg> --label=before.
  2. Config: point the package's tsconfig at NodeNext — extend @n8n/typescript-config/modern, or set module: NodeNext + moduleResolution: NodeNext locally.
  3. Codemod: run add-import-extensions.mjs <pkg> (review), then --write.
  4. Aliases: if the package keeps path aliases, enable tsc-alias resolveFullPaths so alias tails also get extensions in emit.
  5. Verify: pnpm --filter <pkg> run build && pnpm --filter <pkg> run typecheck && pnpm --filter <pkg> test.
  6. After: benchmark.mjs <pkg> --label=after → confirm the delta table.

Migrate leaf/low-dependency packages first (workflow, @n8n/config, @n8n/di) so downstream typechecks stay green, then work up toward cli.