chore: Clean up TS migration artifacts (#34439)

This commit is contained in:
Matsu
2026-07-17 11:58:18 +00:00
committed by GitHub
parent a09bb99f71
commit 86eaa10ff2
62 changed files with 1 additions and 4376 deletions
@@ -10,11 +10,7 @@
"n8n-node-dev",
"n8n-nodes-base",
"n8n-playwright",
"n8n-workflow",
"typescript",
"@typescript/*",
"tsdown",
"rolldown-plugin-dts"
"n8n-workflow"
]
}
}
-4
View File
@@ -278,7 +278,3 @@ minimumReleaseAge: 4320
minimumReleaseAgeExclude:
- '@n8n/*'
- '@n8n_io/*'
- 'typescript'
- '@typescript/*'
- 'tsdown'
- 'rolldown-plugin-dts'
-123
View File
@@ -1,123 +0,0 @@
# 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**.
## Choosing the TypeScript catalog
TypeScript 7 is the native (Go) compiler, "tsgo". The `[email protected]`
package is just a launcher for the native `tsc` binary — **TS 7.0 ships no
programmatic compiler API** (`ts.createProgram`, `ts.Extension`, the `ts.*`
namespace); that lands in **TS 7.1**. Any tool that calls the compiler API at
runtime therefore cannot run against tsgo yet.
Each migrated package picks **one** of two catalogs for its `typescript`
devDependency (both give a tsgo `tsc`, so both get the full typecheck/build
speed-up):
### `catalog:typescript` — plain upgrade (the default)
```jsonc
"typescript": "catalog:typescript" // → tsgo ([email protected])
```
For packages that only *compile* with TypeScript — no code path that imports
the compiler API at runtime. This is the target for the overwhelming majority
of packages.
### `catalog:typescript-tooling` — needs the compiler API at runtime
```jsonc
"@typescript/native": "catalog:typescript-tooling", // → tsgo: provides the `tsc` bin
"typescript": "catalog:typescript-tooling" // → @typescript/typescript6: the real TS 6 API + `tsc6` bin
```
This is the official **side-by-side install** ([TS 7.0 announcement →
"Running side-by-side with TypeScript 6.0"](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0)).
The two packages expose non-colliding binaries (`tsc` from tsgo, `tsc6` from
TS 6), so `tsc`/`build`/`typecheck` still run on tsgo, while `require('typescript')`
resolves to the real TS 6 JS API that the tooling needs.
**A package needs `typescript-tooling` when it (or its tests) does any of:**
- value-imports `@typescript-eslint/*` or `typescript-eslint` (e.g.
`typescript-estree` `parse`, `@typescript-eslint/rule-tester`);
- runs ESLint programmatically (`new ESLint(...)`) with a typescript-eslint
parser;
- value-imports the `typescript` module for its API (`import ts from
'typescript'`, `ts.createProgram`, …) — **not** type-only imports.
First-party code in these packages must `import ts from 'typescript'` — the
catalog points that specifier at the TS6 API. Do **not** add a separately-named
alias dependency (e.g. `"typescript6": "npm:@typescript/typescript6@…"`); keep
the single `typescript-tooling` convention so the 7.1 cleanup is one catalog flip.
Currently on `typescript-tooling`: `@n8n/eslint-config`,
`@n8n/eslint-plugin-community-nodes`, `@n8n/node-cli`, `@n8n/nodes-langchain`.
> **Forward-looking (TS 7.1):** once the native compiler ships its own
> programmatic API, `typescript-tooling` packages can drop the side-by-side
> dance — remove `@typescript/native`, point `typescript` back at
> `catalog:typescript`, and let the tooling use the native API directly. The
> `catalog:typescript` vs `catalog:typescript-tooling` split is exactly the
> list of packages to revisit when that lands.
## 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.
```bash
# 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`.
## 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 the `config.go.json` variant, or set `module: NodeNext` +
`moduleResolution: NodeNext` locally.
3. **Migrate dynamic imports:** Run typechecks and build and fix any lingering issues
most likely related to the dynamic imports not having file extensions.
4. **Aliases:** if the package keeps path aliases, enable `tsc-alias`
`resolveFullPaths` so alias tails also get extensions in emit.
5. **Compiler:** swap the `typescript` devDependency from `catalog:` onto the
right TS 7 catalog — `catalog:typescript`, or `catalog:typescript-tooling`
if the package uses the compiler API at runtime (see
[Choosing the TypeScript catalog](#choosing-the-typescript-catalog)), then
`pnpm install`.
6. **Verify:** `pnpm --filter <pkg> run build && pnpm --filter <pkg> run typecheck && pnpm --filter <pkg> test`.
7. **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`.
-610
View File
@@ -1,610 +0,0 @@
# TypeScript 6 → 7 migration benchmarks
Generated 2026-07-16T10:36:32.332Z from `scripts/typescript-migration/results/`.
| Package | typecheck Δ | build Δ |
| --- | --- | --- |
| `@n8n/agents` | -71.1% | -67.0% |
| `@n8n/ai-node-sdk` | -53.1% | -54.3% |
| `@n8n/ai-utilities` | -66.9% | -63.2% |
| `@n8n/ai-workflow-builder` | -69.3% | -33.1% |
| `@n8n/api-types` | -64.6% | -66.6% |
| `@n8n/backend-common` | -57.0% | -54.5% |
| `@n8n/backend-network` | -59.8% | -55.9% |
| `@n8n/backend-test-utils` | -51.4% | -53.1% |
| `@n8n/chat-hub` | -50.4% | -50.5% |
| `@n8n/cli` | -45.7% | -45.7% |
| `@n8n/client-oauth2` | -45.6% | -39.7% |
| `@n8n/codemirror-lang` | -36.3% | -31.4% |
| `@n8n/codemirror-lang-html` | — | -17.0% |
| `@n8n/codemirror-lang-sql` | -42.7% | -39.2% |
| `@n8n/computer-use` | -52.8% | -53.4% |
| `@n8n/config` | -48.2% | -37.9% |
| `@n8n/constants` | -35.8% | -36.6% |
| `@n8n/crdt` | -40.8% | -41.0% |
| `@n8n/db` | -61.6% | -34.0% |
| `@n8n/decorators` | -56.6% | -53.5% |
| `@n8n/di` | -34.0% | -31.0% |
| `@n8n/engine` | -37.2% | -40.8% |
| `@n8n/errors` | -39.0% | -40.6% |
| `@n8n/eslint-config` | -71.1% | -61.5% |
| `@n8n/eslint-plugin-community-nodes` | -50.6% | -47.1% |
| `@n8n/expression-runtime` | -57.1% | -42.4% |
| `@n8n/extension-sdk` | — | -5.2% |
| `@n8n/imap` | -48.6% | -36.7% |
| `@n8n/instance-ai` | -70.0% | -40.3% |
| `@n8n/json-schema-to-zod` | -43.9% | -34.7% |
| `@n8n/local-gateway` | -46.1% | -42.1% |
| `@n8n/mcp-apps` | -12.4% | -20.2% |
| `@n8n/mcp-browser` | -57.6% | -55.6% |
| `@n8n/mcp-browser-extension` | -46.3% | +3.0% |
| `@n8n/n8n-benchmark` | -49.2% | -39.0% |
| `@n8n/n8n-nodes-langchain` | -74.2% | -21.6% |
| `@n8n/node-cli` | -55.3% | -48.3% |
| `@n8n/permissions` | -34.1% | -28.5% |
| `@n8n/scheduler` | -56.6% | -51.7% |
| `@n8n/stylelint-config` | -39.9% | -40.8% |
| `@n8n/task-runner` | -54.3% | -44.6% |
| `@n8n/tournament` | -32.0% | -34.8% |
| `@n8n/typeorm` | -37.9% | -68.7% |
| `@n8n/utils` | -49.8% | -19.6% |
| `@n8n/vitest-config` | -48.1% | -43.5% |
| `@n8n/workflow-sdk` | -67.1% | -63.3% |
| `n8n` | -75.5% | -71.3% |
```
=== @n8n/agents — median times (Δ vs "before") ===
typecheck:
before 3.04s
after 880ms -2163ms (-71.1%)
build:
before 2.30s
after 757ms -1539ms (-67.0%)
```
```
=== @n8n/ai-node-sdk — median times (Δ vs "before") ===
typecheck:
before 1.12s
after 526ms -595ms (-53.1%)
build:
before 1.21s
after 552ms -657ms (-54.3%)
```
```
=== @n8n/ai-utilities — median times (Δ vs "before") ===
typecheck:
before 2.35s
after 779ms -1571ms (-66.9%)
build:
before 4.55s
after 1.67s -2878ms (-63.2%)
```
```
=== @n8n/ai-workflow-builder — median times (Δ vs "before") ===
typecheck:
before 3.87s
after 1.19s -2683ms (-69.3%)
build:
before 3.25s
after 2.17s -1078ms (-33.1%)
```
```
=== @n8n/api-types — median times (Δ vs "before") ===
typecheck:
before 2.55s
after 903ms -1651ms (-64.6%)
build:
before 2.64s
after 882ms -1757ms (-66.6%)
```
```
=== @n8n/backend-common — median times (Δ vs "before") ===
typecheck:
before 1.34s
after 576ms -765ms (-57.0%)
build:
before 1.19s
after 541ms -649ms (-54.5%)
```
```
=== @n8n/backend-network — median times (Δ vs "before") ===
typecheck:
before 1.64s
after 659ms -980ms (-59.8%)
build:
before 1.39s
after 611ms -776ms (-55.9%)
```
```
=== @n8n/backend-test-utils — median times (Δ vs "before") ===
typecheck:
before 1.54s
after 748ms -792ms (-51.4%)
build:
before 1.60s
after 751ms -850ms (-53.1%)
```
```
=== @n8n/chat-hub — median times (Δ vs "before") ===
typecheck:
before 1.14s
after 564ms -574ms (-50.4%)
build:
before 1.07s
after 529ms -540ms (-50.5%)
```
```
=== @n8n/cli — median times (Δ vs "before") ===
typecheck:
before 943ms
after 512ms -431ms (-45.7%)
build:
before 982ms
after 533ms -449ms (-45.7%)
```
```
=== @n8n/client-oauth2 — median times (Δ vs "before") ===
typecheck:
before 872ms
after 474ms -398ms (-45.6%)
build:
before 763ms
after 460ms -303ms (-39.7%)
```
```
=== @n8n/codemirror-lang — median times (Δ vs "before") ===
typecheck:
before 699ms
after 445ms -254ms (-36.3%)
build:
before 650ms
after 446ms -204ms (-31.4%)
```
```
=== @n8n/codemirror-lang-html — median times (Δ vs "before") ===
build:
before 1.09s
after 905ms -186ms (-17.0%)
```
```
=== @n8n/codemirror-lang-sql — median times (Δ vs "before") ===
typecheck:
before 785ms
after 450ms -335ms (-42.7%)
build:
before 720ms
after 438ms -282ms (-39.2%)
```
```
=== @n8n/computer-use — median times (Δ vs "before") ===
typecheck:
before 1.27s
after 599ms -670ms (-52.8%)
build:
before 1.15s
after 535ms -614ms (-53.4%)
```
```
=== @n8n/config — median times (Δ vs "before") ===
typecheck:
before 1.02s
after 529ms -493ms (-48.2%)
build:
before 952ms
after 591ms -361ms (-37.9%)
```
```
=== @n8n/constants — median times (Δ vs "before") ===
typecheck:
before 670ms
after 430ms -240ms (-35.8%)
build:
before 691ms
after 438ms -253ms (-36.6%)
```
```
=== @n8n/crdt — median times (Δ vs "before") ===
typecheck:
before 921ms
after 545ms -376ms (-40.8%)
build:
before 808ms
after 477ms -331ms (-41.0%)
```
```
=== @n8n/db — median times (Δ vs "before") ===
typecheck:
before 2.76s
after 1.06s -1701ms (-61.6%)
build:
before 3.05s
after 2.02s -1038ms (-34.0%)
```
```
=== @n8n/decorators — median times (Δ vs "before") ===
typecheck:
before 1.40s
after 606ms -790ms (-56.6%)
build:
before 1.26s
after 588ms -677ms (-53.5%)
```
```
=== @n8n/di — median times (Δ vs "before") ===
typecheck:
before 780ms
after 515ms -265ms (-34.0%)
build:
before 713ms
after 492ms -221ms (-31.0%)
```
```
=== @n8n/engine — median times (Δ vs "before") ===
typecheck:
before 749ms
after 470ms -279ms (-37.2%)
build:
before 785ms
after 465ms -320ms (-40.8%)
```
```
=== @n8n/errors — median times (Δ vs "before") ===
typecheck:
before 807ms
after 492ms -315ms (-39.0%)
build:
before 834ms
after 495ms -339ms (-40.6%)
```
```
=== @n8n/eslint-config — median times (Δ vs "before") ===
typecheck:
before 1.73s
after 501ms -1231ms (-71.1%)
build:
before 1.32s
after 508ms -810ms (-61.5%)
```
```
=== @n8n/eslint-plugin-community-nodes — median times (Δ vs "before") ===
typecheck:
before 1.17s
after 579ms -594ms (-50.6%)
build:
before 1.13s
after 597ms -531ms (-47.1%)
```
```
=== @n8n/expression-runtime — median times (Δ vs "before") ===
typecheck:
before 1.44s
after 619ms -824ms (-57.1%)
build:
before 2.89s
after 1.66s -1225ms (-42.4%)
```
```
=== @n8n/extension-sdk — median times (Δ vs "before") ===
build:
before 2.65s
after 2.51s -139ms (-5.2%)
```
```
=== @n8n/imap — median times (Δ vs "before") ===
typecheck:
before 1.04s
after 537ms -507ms (-48.6%)
build:
before 780ms
after 494ms -286ms (-36.7%)
```
```
=== @n8n/instance-ai — median times (Δ vs "before") ===
typecheck:
before 3.36s
after 1.01s -2351ms (-70.0%)
build:
before 3.21s
after 1.91s -1293ms (-40.3%)
```
```
=== @n8n/json-schema-to-zod — median times (Δ vs "before") ===
typecheck:
before 955ms
after 536ms -419ms (-43.9%)
build:
before 2.33s
after 1.52s -807ms (-34.7%)
```
```
=== @n8n/local-gateway — median times (Δ vs "before") ===
typecheck:
before 952ms
after 513ms -439ms (-46.1%)
build:
before 2.00s
after 1.16s -844ms (-42.1%)
```
```
=== @n8n/mcp-apps — median times (Δ vs "before") ===
typecheck:
before 8.15s
after 7.14s -1011ms (-12.4%)
build:
before 3.62s
after 2.88s -731ms (-20.2%)
```
```
=== @n8n/mcp-browser — median times (Δ vs "before") ===
typecheck:
before 1.44s
after 609ms -827ms (-57.6%)
build:
before 1.35s
after 597ms -749ms (-55.6%)
```
```
=== @n8n/mcp-browser-extension — median times (Δ vs "before") ===
typecheck:
before 984ms
after 528ms -456ms (-46.3%)
build:
before 2.80s
after 2.89s +84ms (+3.0%)
```
```
=== @n8n/n8n-benchmark — median times (Δ vs "before") ===
typecheck:
before 942ms
after 479ms -463ms (-49.2%)
build:
before 948ms
after 578ms -370ms (-39.0%)
```
```
=== @n8n/n8n-nodes-langchain — median times (Δ vs "before") ===
typecheck:
before 8.30s
after 2.14s -6163ms (-74.2%)
build:
before 25.79s
after 20.23s -5560ms (-21.6%)
```
```
=== @n8n/node-cli — median times (Δ vs "before") ===
typecheck:
before 1.42s
after 634ms -785ms (-55.3%)
build:
before 1.76s
after 911ms -851ms (-48.3%)
```
```
=== @n8n/permissions — median times (Δ vs "before") ===
typecheck:
before 965ms
after 636ms -329ms (-34.1%)
build:
before 918ms
after 656ms -262ms (-28.5%)
```
```
=== @n8n/scheduler — median times (Δ vs "before") ===
typecheck:
before 1.36s
after 590ms -771ms (-56.6%)
build:
before 1.14s
after 552ms -590ms (-51.7%)
```
```
=== @n8n/stylelint-config — median times (Δ vs "before") ===
typecheck:
before 781ms
after 469ms -312ms (-39.9%)
build:
before 790ms
after 468ms -322ms (-40.8%)
```
```
=== @n8n/task-runner — median times (Δ vs "before") ===
typecheck:
before 1.64s
after 749ms -890ms (-54.3%)
build:
before 1.55s
after 862ms -693ms (-44.6%)
```
```
=== @n8n/tournament — median times (Δ vs "before") ===
typecheck:
before 724ms
after 492ms -232ms (-32.0%)
build:
before 759ms
after 495ms -264ms (-34.8%)
```
```
=== @n8n/typeorm — median times (Δ vs "before") ===
typecheck:
before 1.45s
after 898ms -547ms (-37.9%)
build:
before 2.84s
after 890ms -1949ms (-68.7%)
```
```
=== @n8n/utils — median times (Δ vs "before") ===
typecheck:
before 1.12s
after 562ms -558ms (-49.8%)
build:
before 911ms
after 732ms -179ms (-19.6%)
```
```
=== @n8n/vitest-config — median times (Δ vs "before") ===
typecheck:
before 950ms
after 493ms -457ms (-48.1%)
build:
before 898ms
after 507ms -391ms (-43.5%)
```
```
=== @n8n/workflow-sdk — median times (Δ vs "before") ===
typecheck:
before 2.42s
after 798ms -1625ms (-67.1%)
build:
before 1.91s
after 699ms -1207ms (-63.3%)
```
```
=== n8n — median times (Δ vs "before") ===
typecheck:
before 20.87s
after 5.12s -15750ms (-75.5%)
build:
before 12.86s
after 3.69s -9172ms (-71.3%)
```
-227
View File
@@ -1,227 +0,0 @@
#!/usr/bin/env node
// Per-package build/typecheck timing for the TS 6 -> 7 migration.
//
// Run it before switching compilers (writes a results file), switch the
// compiler, then run it again — the second run appends to the same file and
// prints a before/after delta table. Migration is per-package, so this always
// targets a single workspace package.
//
// Usage:
// node scripts/typescript-migration/benchmark.mjs <package> [options]
//
// Options:
// --label=<name> Key the run is stored under. Defaults to the detected
// TypeScript version (e.g. "ts-6.0.2"), so before/after
// with different compilers auto-separate. Re-running a
// label overwrites it.
// --runs=<n> Repetitions per task (default 3). Reports min/median/mean.
// --tasks=a,b Subset of "typecheck,build" (default both). Missing
// scripts are skipped with a warning.
// --no-prepare Skip the untimed dependency prebuild.
//
// Example:
// node scripts/typescript-migration/benchmark.mjs @n8n/config --label=before
import { execFileSync, spawnSync } from 'node:child_process';
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(SCRIPT_DIR, '..', '..');
const RESULTS_DIR = join(SCRIPT_DIR, 'results');
const DEFAULT_TASKS = ['typecheck', 'build'];
function parseArgs(argv) {
const opts = { runs: 3, tasks: DEFAULT_TASKS, prepare: true, label: undefined };
const positionals = [];
for (const arg of argv) {
if (arg === '--no-prepare') opts.prepare = false;
else if (arg.startsWith('--label=')) opts.label = arg.slice('--label='.length);
else if (arg.startsWith('--runs=')) opts.runs = Number(arg.slice('--runs='.length));
else if (arg.startsWith('--tasks=')) opts.tasks = arg.slice('--tasks='.length).split(',').map((t) => t.trim()).filter(Boolean);
else if (arg.startsWith('--')) fail(`Unknown option: ${arg}`);
else positionals.push(arg);
}
if (positionals.length !== 1) fail('Expected exactly one <package> argument.');
if (!Number.isInteger(opts.runs) || opts.runs < 1) fail('--runs must be a positive integer.');
opts.package = positionals[0];
return opts;
}
function fail(message) {
console.error(`\n✖ ${message}\n`);
process.exit(1);
}
// Resolve a workspace package name or directory to { name, dir, scripts }.
function resolvePackage(nameOrDir) {
// A directory path was given directly.
const asDir = resolve(REPO_ROOT, nameOrDir);
if (existsSync(join(asDir, 'package.json'))) {
const pkg = JSON.parse(readFileSync(join(asDir, 'package.json'), 'utf8'));
return { name: pkg.name, dir: asDir, scripts: pkg.scripts ?? {} };
}
// Otherwise treat it as a workspace package name and ask pnpm where it lives.
let out;
try {
out = execFileSync('pnpm', ['--filter', nameOrDir, 'exec', 'node', '-p', 'process.cwd()'], {
cwd: REPO_ROOT,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
});
} catch {
fail(`Could not resolve package "${nameOrDir}" — not a directory and pnpm --filter found no match.`);
}
const dir = out.trim().split('\n').filter(Boolean).pop();
if (!dir || !existsSync(join(dir, 'package.json'))) fail(`Resolved an invalid directory for "${nameOrDir}".`);
const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
return { name: pkg.name, dir, scripts: pkg.scripts ?? {} };
}
function detectTsVersion(pkgName) {
const res = spawnSync('pnpm', ['--filter', pkgName, 'exec', 'tsc', '--version'], {
cwd: REPO_ROOT,
encoding: 'utf8',
});
const match = /Version\s+([\d.]+)/.exec(res.stdout ?? '');
return match ? match[1] : 'unknown';
}
// Wipe compiled output + incremental caches so every timed run is cold.
function cleanBuildArtifacts(pkgDir) {
rmSync(join(pkgDir, 'dist'), { recursive: true, force: true });
rmSync(join(pkgDir, 'tsconfig.tsbuildinfo'), { force: true });
}
function timeTask(pkgName, pkgDir, task) {
cleanBuildArtifacts(pkgDir);
const start = process.hrtime.bigint();
const res = spawnSync('pnpm', ['--filter', pkgName, 'run', task], {
cwd: REPO_ROOT,
stdio: 'inherit',
});
const ms = Number(process.hrtime.bigint() - start) / 1e6;
if (res.status !== 0) fail(`Task "${task}" failed (exit ${res.status}); aborting so timings aren't polluted.`);
return ms;
}
function summarize(runsMs) {
const sorted = [...runsMs].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
const median = sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
const mean = runsMs.reduce((a, b) => a + b, 0) / runsMs.length;
return {
runsMs: runsMs.map((n) => Math.round(n)),
min: Math.round(sorted[0]),
median: Math.round(median),
mean: Math.round(mean),
};
}
function fmtMs(ms) {
return ms >= 1000 ? `${(ms / 1000).toFixed(2)}s` : `${ms}ms`;
}
// Baseline-first ordering: "before" is always the baseline and "after" always
// last regardless of recording order; anything else falls between by timestamp.
function orderLabels(runs) {
const rank = (l) => (/^before$/i.test(l) ? -1 : /^after$/i.test(l) ? 1 : 0);
return Object.keys(runs).sort((a, b) => {
if (rank(a) !== rank(b)) return rank(a) - rank(b);
return (runs[a].timestamp ?? '').localeCompare(runs[b].timestamp ?? '');
});
}
// Print a comparison table across every stored label, deltas vs the baseline.
function printComparison(data) {
const labels = orderLabels(data.runs);
if (labels.length < 2) {
console.log(`\nStored 1 run ("${labels[0]}"). Run again with a second --label to see a delta.\n`);
return;
}
const base = labels[0];
console.log(`\n=== ${data.package} — median times (Δ vs "${base}") ===`);
const tasks = new Set();
for (const l of labels) for (const t of Object.keys(data.runs[l].tasks)) tasks.add(t);
for (const task of tasks) {
console.log(`\n${task}:`);
const baseMedian = data.runs[base].tasks[task]?.median;
for (const label of labels) {
const stat = data.runs[label].tasks[task];
if (!stat) {
console.log(` ${label.padEnd(16)} (not measured)`);
continue;
}
let delta = '';
if (label !== base && baseMedian != null) {
const diff = stat.median - baseMedian;
const pct = ((diff / baseMedian) * 100).toFixed(1);
const sign = diff <= 0 ? '' : '+';
delta = ` ${sign}${fmtMs(diff)} (${sign}${pct}%)`;
}
console.log(` ${label.padEnd(16)} ${fmtMs(stat.median).padStart(9)}${delta}`);
}
}
console.log('');
}
function main() {
const opts = parseArgs(process.argv.slice(2));
const pkg = resolvePackage(opts.package);
const tsVersion = detectTsVersion(pkg.name);
const label = opts.label ?? `ts-${tsVersion}`;
const tasks = opts.tasks.filter((task) => {
if (pkg.scripts[task]) return true;
console.warn(`⚠ Package "${pkg.name}" has no "${task}" script — skipping.`);
return false;
});
if (tasks.length === 0) fail('No runnable tasks for this package.');
console.log(`\nBenchmarking ${pkg.name}`);
console.log(` label: ${label}`);
console.log(` tsc: ${tsVersion}`);
console.log(` node: ${process.version}`);
console.log(` runs/task: ${opts.runs}`);
console.log(` tasks: ${tasks.join(', ')}\n`);
if (opts.prepare) {
console.log('Prebuilding dependencies (untimed)…');
const prep = spawnSync('pnpm', ['build', `--filter=${pkg.name}^...`], {
cwd: REPO_ROOT,
stdio: 'inherit',
});
if (prep.status !== 0) fail('Dependency prebuild failed. Fix the build or pass --no-prepare.');
}
const taskStats = {};
for (const task of tasks) {
const runsMs = [];
for (let i = 0; i < opts.runs; i++) {
console.log(`\n▶ ${task} — run ${i + 1}/${opts.runs}`);
runsMs.push(timeTask(pkg.name, pkg.dir, task));
}
taskStats[task] = summarize(runsMs);
console.log(` ↳ ${task}: min ${fmtMs(taskStats[task].min)}, median ${fmtMs(taskStats[task].median)}, mean ${fmtMs(taskStats[task].mean)}`);
}
mkdirSync(RESULTS_DIR, { recursive: true });
const resultsFile = join(RESULTS_DIR, `${pkg.name.replace(/[@/]/g, '_')}.json`);
const data = existsSync(resultsFile)
? JSON.parse(readFileSync(resultsFile, 'utf8'))
: { package: pkg.name, runs: {} };
data.runs[label] = {
label,
tsVersion,
node: process.version,
timestamp: new Date().toISOString(),
tasks: taskStats,
};
writeFileSync(resultsFile, `${JSON.stringify(data, null, 2)}\n`);
console.log(`\n✔ Wrote ${resultsFile}`);
printComparison(data);
}
main();
@@ -1,61 +0,0 @@
{
"package": "@n8n/agents",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T10:45:02.610Z",
"tasks": {
"typecheck": {
"runsMs": [
3273,
2967,
3043
],
"min": 2967,
"median": 3043,
"mean": 3094
},
"build": {
"runsMs": [
2220,
3409,
2296
],
"min": 2220,
"median": 2296,
"mean": 2642
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T11:34:24.593Z",
"tasks": {
"typecheck": {
"runsMs": [
880,
895,
845
],
"min": 845,
"median": 880,
"mean": 873
},
"build": {
"runsMs": [
757,
1014,
743
],
"min": 743,
"median": 757,
"mean": 838
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/ai-node-sdk",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T11:42:11.145Z",
"tasks": {
"typecheck": {
"runsMs": [
1516,
1111,
1121
],
"min": 1111,
"median": 1121,
"mean": 1249
},
"build": {
"runsMs": [
1271,
1209,
1186
],
"min": 1186,
"median": 1209,
"mean": 1222
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T11:50:05.746Z",
"tasks": {
"typecheck": {
"runsMs": [
600,
515,
526
],
"min": 515,
"median": 526,
"mean": 547
},
"build": {
"runsMs": [
552,
540,
603
],
"min": 540,
"median": 552,
"mean": 565
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/ai-utilities",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T12:06:02.594Z",
"tasks": {
"typecheck": {
"runsMs": [
2565,
2350,
2154
],
"min": 2154,
"median": 2350,
"mean": 2357
},
"build": {
"runsMs": [
4832,
4338,
4552
],
"min": 4338,
"median": 4552,
"mean": 4574
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T12:16:24.007Z",
"tasks": {
"typecheck": {
"runsMs": [
840,
779,
753
],
"min": 753,
"median": 779,
"mean": 791
},
"build": {
"runsMs": [
2717,
1674,
1427
],
"min": 1427,
"median": 1674,
"mean": 1939
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/ai-workflow-builder",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T12:19:04.693Z",
"tasks": {
"typecheck": {
"runsMs": [
3989,
3871,
3814
],
"min": 3814,
"median": 3871,
"mean": 3891
},
"build": {
"runsMs": [
3252,
3539,
3178
],
"min": 3178,
"median": 3252,
"mean": 3323
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T13:04:08.936Z",
"tasks": {
"typecheck": {
"runsMs": [
1188,
1135,
1191
],
"min": 1135,
"median": 1188,
"mean": 1171
},
"build": {
"runsMs": [
1533,
2534,
2174
],
"min": 1533,
"median": 2174,
"mean": 2080
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/api-types",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T08:13:33.024Z",
"tasks": {
"typecheck": {
"runsMs": [
2731,
2554,
2526
],
"min": 2526,
"median": 2554,
"mean": 2604
},
"build": {
"runsMs": [
2513,
3418,
2639
],
"min": 2513,
"median": 2639,
"mean": 2857
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T08:14:34.864Z",
"tasks": {
"typecheck": {
"runsMs": [
903,
857,
1156
],
"min": 857,
"median": 903,
"mean": 972
},
"build": {
"runsMs": [
826,
927,
882
],
"min": 826,
"median": 882,
"mean": 878
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/backend-common",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T08:15:35.193Z",
"tasks": {
"typecheck": {
"runsMs": [
1352,
1323,
1341
],
"min": 1323,
"median": 1341,
"mean": 1338
},
"build": {
"runsMs": [
1190,
1227,
1190
],
"min": 1190,
"median": 1190,
"mean": 1202
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T08:16:31.011Z",
"tasks": {
"typecheck": {
"runsMs": [
629,
562,
576
],
"min": 562,
"median": 576,
"mean": 589
},
"build": {
"runsMs": [
572,
541,
519
],
"min": 519,
"median": 541,
"mean": 544
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/backend-network",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:06:30.845Z",
"tasks": {
"typecheck": {
"runsMs": [
1779,
1577,
1639
],
"min": 1577,
"median": 1639,
"mean": 1665
},
"build": {
"runsMs": [
1387,
1445,
1376
],
"min": 1376,
"median": 1387,
"mean": 1403
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:08:15.231Z",
"tasks": {
"typecheck": {
"runsMs": [
688,
625,
659
],
"min": 625,
"median": 659,
"mean": 657
},
"build": {
"runsMs": [
611,
616,
605
],
"min": 605,
"median": 611,
"mean": 611
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/backend-test-utils",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T09:27:33.022Z",
"tasks": {
"typecheck": {
"runsMs": [
1602,
1534,
1540
],
"min": 1534,
"median": 1540,
"mean": 1558
},
"build": {
"runsMs": [
1601,
1556,
1617
],
"min": 1556,
"median": 1601,
"mean": 1592
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T09:28:19.744Z",
"tasks": {
"typecheck": {
"runsMs": [
795,
748,
748
],
"min": 748,
"median": 748,
"mean": 764
},
"build": {
"runsMs": [
758,
751,
737
],
"min": 737,
"median": 751,
"mean": 749
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/chat-hub",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:38:17.186Z",
"tasks": {
"typecheck": {
"runsMs": [
1138,
1135,
1148
],
"min": 1135,
"median": 1138,
"mean": 1140
},
"build": {
"runsMs": [
1076,
1067,
1069
],
"min": 1067,
"median": 1069,
"mean": 1071
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:39:48.468Z",
"tasks": {
"typecheck": {
"runsMs": [
599,
564,
539
],
"min": 539,
"median": 564,
"mean": 567
},
"build": {
"runsMs": [
529,
514,
548
],
"min": 514,
"median": 529,
"mean": 530
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/cli",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:40:37.362Z",
"tasks": {
"typecheck": {
"runsMs": [
990,
943,
902
],
"min": 902,
"median": 943,
"mean": 945
},
"build": {
"runsMs": [
999,
970,
982
],
"min": 970,
"median": 982,
"mean": 984
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:41:16.905Z",
"tasks": {
"typecheck": {
"runsMs": [
512,
508,
614
],
"min": 508,
"median": 512,
"mean": 544
},
"build": {
"runsMs": [
605,
533,
495
],
"min": 495,
"median": 533,
"mean": 544
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/client-oauth2",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:43:33.459Z",
"tasks": {
"typecheck": {
"runsMs": [
872,
899,
824
],
"min": 824,
"median": 872,
"mean": 865
},
"build": {
"runsMs": [
759,
763,
811
],
"min": 759,
"median": 763,
"mean": 778
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:46:15.468Z",
"tasks": {
"typecheck": {
"runsMs": [
494,
459,
474
],
"min": 459,
"median": 474,
"mean": 476
},
"build": {
"runsMs": [
472,
460,
436
],
"min": 436,
"median": 460,
"mean": 456
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/code-health",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:22:22.057Z",
"tasks": {
"typecheck": {
"runsMs": [
1217,
1033,
955
],
"min": 955,
"median": 1033,
"mean": 1069
},
"build": {
"runsMs": [
890,
974,
851
],
"min": 851,
"median": 890,
"mean": 905
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:23:37.921Z",
"tasks": {
"typecheck": {
"runsMs": [
543,
530,
530
],
"min": 530,
"median": 530,
"mean": 535
},
"build": {
"runsMs": [
512,
503,
571
],
"min": 503,
"median": 512,
"mean": 529
}
}
}
}
}
@@ -1,41 +0,0 @@
{
"package": "@n8n/codemirror-lang-html",
"runs": {
"before": {
"label": "before",
"tsVersion": "4.9.5",
"node": "v24.13.0",
"timestamp": "2026-07-09T08:06:02.640Z",
"tasks": {
"build": {
"runsMs": [
1317,
951,
1091
],
"min": 951,
"median": 1091,
"mean": 1120
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T08:17:58.724Z",
"tasks": {
"build": {
"runsMs": [
1176,
905,
905
],
"min": 905,
"median": 905,
"mean": 995
}
}
}
}
}
@@ -1,7 +0,0 @@
{
"package": "@n8n/codemirror-lang-sql",
"runs": {
"before": { "label": "before", "tsVersion": "6.0.2", "node": "v22.22.0", "timestamp": "2026-07-09T00:00:00.000Z", "tasks": { "typecheck": { "runsMs": [785], "min": 785, "median": 785, "mean": 785 }, "build": { "runsMs": [720], "min": 720, "median": 720, "mean": 720 } } },
"after": { "label": "after", "tsVersion": "7.0.0", "node": "v22.22.0", "timestamp": "2026-07-09T00:01:00.000Z", "tasks": { "typecheck": { "runsMs": [450], "min": 450, "median": 450, "mean": 450 }, "build": { "runsMs": [438], "min": 438, "median": 438, "mean": 438 } } }
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/codemirror-lang",
"runs": {
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T08:05:38.559Z",
"tasks": {
"typecheck": {
"runsMs": [
433,
445,
452
],
"min": 433,
"median": 445,
"mean": 443
},
"build": {
"runsMs": [
462,
446,
430
],
"min": 430,
"median": 446,
"mean": 446
}
}
},
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T08:03:30.003Z",
"tasks": {
"typecheck": {
"runsMs": [
733,
699,
693
],
"min": 693,
"median": 699,
"mean": 708
},
"build": {
"runsMs": [
650,
651,
646
],
"min": 646,
"median": 650,
"mean": 649
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/computer-use",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:47:01.753Z",
"tasks": {
"typecheck": {
"runsMs": [
1367,
1269,
1255
],
"min": 1255,
"median": 1269,
"mean": 1297
},
"build": {
"runsMs": [
1149,
1214,
1133
],
"min": 1133,
"median": 1149,
"mean": 1165
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:51:49.540Z",
"tasks": {
"typecheck": {
"runsMs": [
792,
599,
588
],
"min": 588,
"median": 599,
"mean": 660
},
"build": {
"runsMs": [
535,
549,
530
],
"min": 530,
"median": 535,
"mean": 538
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/config",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:53:06.135Z",
"tasks": {
"typecheck": {
"runsMs": [
1022,
1083,
969
],
"min": 969,
"median": 1022,
"mean": 1024
},
"build": {
"runsMs": [
940,
979,
952
],
"min": 940,
"median": 952,
"mean": 957
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:54:38.495Z",
"tasks": {
"typecheck": {
"runsMs": [
507,
529,
584
],
"min": 507,
"median": 529,
"mean": 540
},
"build": {
"runsMs": [
596,
591,
525
],
"min": 525,
"median": 591,
"mean": 571
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/constants",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:55:20.856Z",
"tasks": {
"typecheck": {
"runsMs": [
687,
670,
664
],
"min": 664,
"median": 670,
"mean": 673
},
"build": {
"runsMs": [
691,
685,
692
],
"min": 685,
"median": 691,
"mean": 689
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:55:50.952Z",
"tasks": {
"typecheck": {
"runsMs": [
430,
448,
427
],
"min": 427,
"median": 430,
"mean": 435
},
"build": {
"runsMs": [
438,
434,
452
],
"min": 434,
"median": 438,
"mean": 442
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/crdt",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:56:21.223Z",
"tasks": {
"typecheck": {
"runsMs": [
981,
915,
921
],
"min": 915,
"median": 921,
"mean": 939
},
"build": {
"runsMs": [
808,
814,
806
],
"min": 806,
"median": 808,
"mean": 809
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:00:06.086Z",
"tasks": {
"typecheck": {
"runsMs": [
545,
561,
499
],
"min": 499,
"median": 545,
"mean": 535
},
"build": {
"runsMs": [
477,
472,
484
],
"min": 472,
"median": 477,
"mean": 478
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/db",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:09:01.003Z",
"tasks": {
"typecheck": {
"runsMs": [
2761,
2678,
2849
],
"min": 2678,
"median": 2761,
"mean": 2763
},
"build": {
"runsMs": [
3053,
3707,
2791
],
"min": 2791,
"median": 3053,
"mean": 3184
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:11:40.914Z",
"tasks": {
"typecheck": {
"runsMs": [
1146,
1043,
1060
],
"min": 1043,
"median": 1060,
"mean": 1083
},
"build": {
"runsMs": [
1064,
2015,
2380
],
"min": 1064,
"median": 2015,
"mean": 1820
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/decorators",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:12:09.541Z",
"tasks": {
"typecheck": {
"runsMs": [
1444,
1396,
1373
],
"min": 1373,
"median": 1396,
"mean": 1404
},
"build": {
"runsMs": [
1278,
1252,
1265
],
"min": 1252,
"median": 1265,
"mean": 1265
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:13:02.187Z",
"tasks": {
"typecheck": {
"runsMs": [
655,
606,
602
],
"min": 602,
"median": 606,
"mean": 621
},
"build": {
"runsMs": [
588,
631,
572
],
"min": 572,
"median": 588,
"mean": 597
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/di",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:13:31.136Z",
"tasks": {
"typecheck": {
"runsMs": [
780,
780,
780
],
"min": 780,
"median": 780,
"mean": 780
},
"build": {
"runsMs": [
713,
716,
710
],
"min": 710,
"median": 713,
"mean": 713
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:15:01.891Z",
"tasks": {
"typecheck": {
"runsMs": [
542,
515,
485
],
"min": 485,
"median": 515,
"mean": 514
},
"build": {
"runsMs": [
492,
491,
500
],
"min": 491,
"median": 492,
"mean": 494
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/engine",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:46:22.078Z",
"tasks": {
"typecheck": {
"runsMs": [
826,
749,
710
],
"min": 710,
"median": 749,
"mean": 762
},
"build": {
"runsMs": [
700,
785,
791
],
"min": 700,
"median": 785,
"mean": 759
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:47:52.009Z",
"tasks": {
"typecheck": {
"runsMs": [
494,
459,
470
],
"min": 459,
"median": 470,
"mean": 474
},
"build": {
"runsMs": [
465,
456,
475
],
"min": 456,
"median": 465,
"mean": 466
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/errors",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:48:21.086Z",
"tasks": {
"typecheck": {
"runsMs": [
943,
807,
774
],
"min": 774,
"median": 807,
"mean": 841
},
"build": {
"runsMs": [
828,
834,
843
],
"min": 828,
"median": 834,
"mean": 835
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:49:31.458Z",
"tasks": {
"typecheck": {
"runsMs": [
536,
492,
487
],
"min": 487,
"median": 492,
"mean": 505
},
"build": {
"runsMs": [
495,
494,
498
],
"min": 494,
"median": 495,
"mean": 496
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/eslint-config",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:50:43.926Z",
"tasks": {
"typecheck": {
"runsMs": [
1732,
1752,
1635
],
"min": 1635,
"median": 1732,
"mean": 1706
},
"build": {
"runsMs": [
1383,
1318,
1313
],
"min": 1313,
"median": 1318,
"mean": 1338
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:52:21.010Z",
"tasks": {
"typecheck": {
"runsMs": [
522,
498,
501
],
"min": 498,
"median": 501,
"mean": 507
},
"build": {
"runsMs": [
534,
508,
504
],
"min": 504,
"median": 508,
"mean": 515
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/eslint-plugin-community-nodes",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:54:49.761Z",
"tasks": {
"typecheck": {
"runsMs": [
1253,
1172,
1173
],
"min": 1172,
"median": 1173,
"mean": 1199
},
"build": {
"runsMs": [
1138,
1114,
1128
],
"min": 1114,
"median": 1128,
"mean": 1127
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T09:56:12.972Z",
"tasks": {
"typecheck": {
"runsMs": [
579,
650,
546
],
"min": 546,
"median": 579,
"mean": 592
},
"build": {
"runsMs": [
573,
597,
748
],
"min": 573,
"median": 597,
"mean": 639
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/expression-runtime",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:29:22.645Z",
"tasks": {
"typecheck": {
"runsMs": [
1735,
1443,
1389
],
"min": 1389,
"median": 1443,
"mean": 1522
},
"build": {
"runsMs": [
2915,
2455,
2889
],
"min": 2455,
"median": 2889,
"mean": 2753
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:31:42.484Z",
"tasks": {
"typecheck": {
"runsMs": [
621,
619,
585
],
"min": 585,
"median": 619,
"mean": 608
},
"build": {
"runsMs": [
1160,
1664,
2326
],
"min": 1160,
"median": 1664,
"mean": 1717
}
}
}
}
}
@@ -1,41 +0,0 @@
{
"package": "@n8n/extension-sdk",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:24:45.207Z",
"tasks": {
"build": {
"runsMs": [
4397,
2652,
2648
],
"min": 2648,
"median": 2652,
"mean": 3232
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:26:40.515Z",
"tasks": {
"build": {
"runsMs": [
3258,
2513,
2479
],
"min": 2479,
"median": 2513,
"mean": 2750
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/imap",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:54:07.631Z",
"tasks": {
"typecheck": {
"runsMs": [
1044,
862,
1055
],
"min": 862,
"median": 1044,
"mean": 987
},
"build": {
"runsMs": [
854,
780,
741
],
"min": 741,
"median": 780,
"mean": 792
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:55:31.419Z",
"tasks": {
"typecheck": {
"runsMs": [
534,
597,
537
],
"min": 534,
"median": 537,
"mean": 556
},
"build": {
"runsMs": [
596,
494,
492
],
"min": 492,
"median": 494,
"mean": 527
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/instance-ai",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T13:12:42.008Z",
"tasks": {
"typecheck": {
"runsMs": [
4842,
3360,
3357
],
"min": 3357,
"median": 3360,
"mean": 3853
},
"build": {
"runsMs": [
3206,
3386,
3150
],
"min": 3150,
"median": 3206,
"mean": 3248
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-09T13:18:52.244Z",
"tasks": {
"typecheck": {
"runsMs": [
1137,
1005,
1009
],
"min": 1005,
"median": 1009,
"mean": 1050
},
"build": {
"runsMs": [
1465,
2198,
1913
],
"min": 1465,
"median": 1913,
"mean": 1859
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/json-schema-to-zod",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:56:28.684Z",
"tasks": {
"typecheck": {
"runsMs": [
993,
955,
952
],
"min": 952,
"median": 955,
"mean": 967
},
"build": {
"runsMs": [
2624,
2327,
2312
],
"min": 2312,
"median": 2327,
"mean": 2421
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T10:58:23.753Z",
"tasks": {
"typecheck": {
"runsMs": [
536,
530,
549
],
"min": 530,
"median": 536,
"mean": 538
},
"build": {
"runsMs": [
1520,
1645,
1477
],
"min": 1477,
"median": 1520,
"mean": 1548
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/local-gateway",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:00:59.892Z",
"tasks": {
"typecheck": {
"runsMs": [
1009,
952,
945
],
"min": 945,
"median": 952,
"mean": 969
},
"build": {
"runsMs": [
2013,
2005,
1968
],
"min": 1968,
"median": 2005,
"mean": 1995
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:03:45.460Z",
"tasks": {
"typecheck": {
"runsMs": [
529,
507,
513
],
"min": 507,
"median": 513,
"mean": 516
},
"build": {
"runsMs": [
1161,
1180,
1140
],
"min": 1140,
"median": 1161,
"mean": 1161
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/mcp-apps",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:27:47.067Z",
"tasks": {
"typecheck": {
"runsMs": [
8405,
7543,
8147
],
"min": 7543,
"median": 8147,
"mean": 8032
},
"build": {
"runsMs": [
3889,
3235,
3615
],
"min": 3235,
"median": 3615,
"mean": 3580
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:30:54.963Z",
"tasks": {
"typecheck": {
"runsMs": [
7398,
7136,
7054
],
"min": 7054,
"median": 7136,
"mean": 7196
},
"build": {
"runsMs": [
3397,
2884,
2883
],
"min": 2883,
"median": 2884,
"mean": 3054
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/mcp-browser-extension",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:16:01.941Z",
"tasks": {
"typecheck": {
"runsMs": [
918,
984,
1162
],
"min": 918,
"median": 984,
"mean": 1022
},
"build": {
"runsMs": [
3623,
2804,
2781
],
"min": 2781,
"median": 2804,
"mean": 3070
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:17:59.341Z",
"tasks": {
"typecheck": {
"runsMs": [
528,
501,
556
],
"min": 501,
"median": 528,
"mean": 529
},
"build": {
"runsMs": [
3636,
2888,
2877
],
"min": 2877,
"median": 2888,
"mean": 3133
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/mcp-browser",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:07:14.496Z",
"tasks": {
"typecheck": {
"runsMs": [
1549,
1436,
1382
],
"min": 1382,
"median": 1436,
"mean": 1456
},
"build": {
"runsMs": [
1331,
1346,
1659
],
"min": 1331,
"median": 1346,
"mean": 1445
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:09:17.138Z",
"tasks": {
"typecheck": {
"runsMs": [
660,
609,
599
],
"min": 599,
"median": 609,
"mean": 623
},
"build": {
"runsMs": [
595,
663,
597
],
"min": 595,
"median": 597,
"mean": 618
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/n8n-benchmark",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:32:42.617Z",
"tasks": {
"typecheck": {
"runsMs": [
995,
942,
782
],
"min": 782,
"median": 942,
"mean": 906
},
"build": {
"runsMs": [
1013,
948,
913
],
"min": 913,
"median": 948,
"mean": 958
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T08:37:20.138Z",
"tasks": {
"typecheck": {
"runsMs": [
479,
476,
507
],
"min": 476,
"median": 479,
"mean": 487
},
"build": {
"runsMs": [
926,
578,
577
],
"min": 577,
"median": 578,
"mean": 694
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/n8n-nodes-langchain",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T12:09:22.053Z",
"tasks": {
"typecheck": {
"runsMs": [
9337,
7611,
8302
],
"min": 7611,
"median": 8302,
"mean": 8417
},
"build": {
"runsMs": [
26683,
25790,
24573
],
"min": 24573,
"median": 25790,
"mean": 25682
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T13:05:44.453Z",
"tasks": {
"typecheck": {
"runsMs": [
2441,
2106,
2139
],
"min": 2106,
"median": 2139,
"mean": 2229
},
"build": {
"runsMs": [
20166,
21149,
20230
],
"min": 20166,
"median": 20230,
"mean": 20515
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/node-cli",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:13:31.216Z",
"tasks": {
"typecheck": {
"runsMs": [
1521,
1388,
1419
],
"min": 1388,
"median": 1419,
"mean": 1443
},
"build": {
"runsMs": [
1637,
1770,
1762
],
"min": 1637,
"median": 1762,
"mean": 1723
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-15T11:16:23.735Z",
"tasks": {
"typecheck": {
"runsMs": [
678,
634,
593
],
"min": 593,
"median": 634,
"mean": 635
},
"build": {
"runsMs": [
911,
1068,
888
],
"min": 888,
"median": 911,
"mean": 956
}
}
}
}
}
@@ -1,41 +0,0 @@
{
"package": "@n8n/performance",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:25:40.590Z",
"tasks": {
"typecheck": {
"runsMs": [
1186,
1061,
1031
],
"min": 1031,
"median": 1061,
"mean": 1093
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:26:08.440Z",
"tasks": {
"typecheck": {
"runsMs": [
584,
538,
526
],
"min": 526,
"median": 538,
"mean": 549
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/permissions",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:51:01.528Z",
"tasks": {
"typecheck": {
"runsMs": [
1016,
956,
965
],
"min": 956,
"median": 965,
"mean": 979
},
"build": {
"runsMs": [
993,
918,
879
],
"min": 879,
"median": 918,
"mean": 930
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:51:37.138Z",
"tasks": {
"typecheck": {
"runsMs": [
639,
636,
607
],
"min": 607,
"median": 636,
"mean": 627
},
"build": {
"runsMs": [
656,
687,
596
],
"min": 596,
"median": 656,
"mean": 646
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/playwright-janitor",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:24:20.759Z",
"tasks": {
"typecheck": {
"runsMs": [
1285,
1194,
1497
],
"min": 1194,
"median": 1285,
"mean": 1325
},
"build": {
"runsMs": [
1375,
1451,
1391
],
"min": 1375,
"median": 1391,
"mean": 1406
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:25:01.813Z",
"tasks": {
"typecheck": {
"runsMs": [
597,
642,
580
],
"min": 580,
"median": 597,
"mean": 606
},
"build": {
"runsMs": [
586,
654,
629
],
"min": 586,
"median": 629,
"mean": 623
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/rules-engine",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:29:23.570Z",
"tasks": {
"typecheck": {
"runsMs": [
893,
844,
875
],
"min": 844,
"median": 875,
"mean": 871
},
"build": {
"runsMs": [
811,
812,
822
],
"min": 811,
"median": 812,
"mean": 815
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:30:00.600Z",
"tasks": {
"typecheck": {
"runsMs": [
535,
521,
515
],
"min": 515,
"median": 521,
"mean": 524
},
"build": {
"runsMs": [
565,
513,
495
],
"min": 495,
"median": 513,
"mean": 524
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/scheduler",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:53:01.463Z",
"tasks": {
"typecheck": {
"runsMs": [
1572,
1361,
1360
],
"min": 1360,
"median": 1361,
"mean": 1431
},
"build": {
"runsMs": [
1158,
1142,
1141
],
"min": 1141,
"median": 1142,
"mean": 1147
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:53:43.684Z",
"tasks": {
"typecheck": {
"runsMs": [
639,
583,
590
],
"min": 583,
"median": 590,
"mean": 604
},
"build": {
"runsMs": [
612,
545,
552
],
"min": 545,
"median": 552,
"mean": 570
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/stylelint-config",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:54:39.332Z",
"tasks": {
"typecheck": {
"runsMs": [
781,
793,
753
],
"min": 753,
"median": 781,
"mean": 776
},
"build": {
"runsMs": [
817,
778,
790
],
"min": 778,
"median": 790,
"mean": 795
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:55:38.571Z",
"tasks": {
"typecheck": {
"runsMs": [
469,
467,
480
],
"min": 467,
"median": 469,
"mean": 472
},
"build": {
"runsMs": [
457,
482,
468
],
"min": 457,
"median": 468,
"mean": 469
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/task-runner",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:56:23.946Z",
"tasks": {
"typecheck": {
"runsMs": [
1657,
1627,
1639
],
"min": 1627,
"median": 1639,
"mean": 1641
},
"build": {
"runsMs": [
1555,
1566,
1554
],
"min": 1554,
"median": 1555,
"mean": 1558
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:57:37.671Z",
"tasks": {
"typecheck": {
"runsMs": [
799,
749,
739
],
"min": 739,
"median": 749,
"mean": 762
},
"build": {
"runsMs": [
950,
862,
840
],
"min": 840,
"median": 862,
"mean": 884
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/test-impact",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:30:38.250Z",
"tasks": {
"typecheck": {
"runsMs": [
1077,
948,
912
],
"min": 912,
"median": 948,
"mean": 979
},
"build": {
"runsMs": [
926,
920,
887
],
"min": 887,
"median": 920,
"mean": 911
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:31:03.641Z",
"tasks": {
"typecheck": {
"runsMs": [
504,
570,
497
],
"min": 497,
"median": 504,
"mean": 524
},
"build": {
"runsMs": [
499,
611,
500
],
"min": 499,
"median": 500,
"mean": 537
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/tournament",
"runs": {
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:28:57.670Z",
"tasks": {
"typecheck": {
"runsMs": [
505,
492,
475
],
"min": 475,
"median": 492,
"mean": 491
},
"build": {
"runsMs": [
495,
504,
491
],
"min": 491,
"median": 495,
"mean": 496
}
}
},
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T08:59:29.660Z",
"tasks": {
"typecheck": {
"runsMs": [
724,
709,
728
],
"min": 709,
"median": 724,
"mean": 720
},
"build": {
"runsMs": [
764,
723,
759
],
"min": 723,
"median": 759,
"mean": 749
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/typeorm",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T09:29:28.550Z",
"tasks": {
"typecheck": {
"runsMs": [
1624,
1408,
1445
],
"min": 1408,
"median": 1445,
"mean": 1493
},
"build": {
"runsMs": [
1963,
2839,
2851
],
"min": 1963,
"median": 2839,
"mean": 2551
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T09:31:23.564Z",
"tasks": {
"typecheck": {
"runsMs": [
1000,
898,
799
],
"min": 799,
"median": 898,
"mean": 899
},
"build": {
"runsMs": [
808,
890,
1087
],
"min": 808,
"median": 890,
"mean": 928
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/utils",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:33:42.675Z",
"tasks": {
"typecheck": {
"runsMs": [
1265,
1120,
1116
],
"min": 1116,
"median": 1120,
"mean": 1167
},
"build": {
"runsMs": [
1298,
911,
911
],
"min": 911,
"median": 911,
"mean": 1040
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:39:45.263Z",
"tasks": {
"typecheck": {
"runsMs": [
568,
562,
554
],
"min": 554,
"median": 562,
"mean": 561
},
"build": {
"runsMs": [
1758,
714,
732
],
"min": 714,
"median": 732,
"mean": 1068
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/vitest-config",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:46:09.399Z",
"tasks": {
"typecheck": {
"runsMs": [
1087,
891,
950
],
"min": 891,
"median": 950,
"mean": 976
},
"build": {
"runsMs": [
898,
895,
898
],
"min": 895,
"median": 898,
"mean": 897
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:46:55.861Z",
"tasks": {
"typecheck": {
"runsMs": [
498,
492,
493
],
"min": 492,
"median": 493,
"mean": 494
},
"build": {
"runsMs": [
509,
495,
507
],
"min": 495,
"median": 507,
"mean": 503
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "@n8n/workflow-sdk",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:47:39.891Z",
"tasks": {
"typecheck": {
"runsMs": [
2825,
2423,
2384
],
"min": 2384,
"median": 2423,
"mean": 2544
},
"build": {
"runsMs": [
1847,
2391,
1906
],
"min": 1847,
"median": 1906,
"mean": 2048
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T09:50:01.066Z",
"tasks": {
"typecheck": {
"runsMs": [
798,
823,
763
],
"min": 763,
"median": 798,
"mean": 795
},
"build": {
"runsMs": [
699,
698,
751
],
"min": 698,
"median": 699,
"mean": 716
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "n8n-core",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:55:55.832Z",
"tasks": {
"typecheck": {
"runsMs": [
3748,
3270,
3184
],
"min": 3184,
"median": 3270,
"mean": 3401
},
"build": {
"runsMs": [
2979,
3573,
3050
],
"min": 2979,
"median": 3050,
"mean": 3201
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:58:23.587Z",
"tasks": {
"typecheck": {
"runsMs": [
1273,
1119,
1094
],
"min": 1094,
"median": 1119,
"mean": 1162
},
"build": {
"runsMs": [
1599,
1797,
978
],
"min": 978,
"median": 1599,
"mean": 1458
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "n8n-nodes-base",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:05:53.926Z",
"tasks": {
"typecheck": {
"runsMs": [
17177,
16411,
16991
],
"min": 16411,
"median": 16991,
"mean": 16860
},
"build": {
"runsMs": [
42612,
47814,
45802
],
"min": 42612,
"median": 45802,
"mean": 45409
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:20:04.736Z",
"tasks": {
"typecheck": {
"runsMs": [
4628,
3761,
3682
],
"min": 3682,
"median": 3761,
"mean": 4024
},
"build": {
"runsMs": [
33356,
32118,
31927
],
"min": 31927,
"median": 32118,
"mean": 32467
}
}
}
}
}
@@ -1,41 +0,0 @@
{
"package": "n8n-playwright",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:28:02.755Z",
"tasks": {
"typecheck": {
"runsMs": [
4097,
3332,
3298
],
"min": 3298,
"median": 3332,
"mean": 3576
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T11:28:40.308Z",
"tasks": {
"typecheck": {
"runsMs": [
1459,
1238,
1113
],
"min": 1113,
"median": 1238,
"mean": 1270
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "n8n-workflow",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:53:11.029Z",
"tasks": {
"typecheck": {
"runsMs": [
3033,
2749,
2774
],
"min": 2749,
"median": 2774,
"mean": 2852
},
"build": {
"runsMs": [
3221,
4432,
4179
],
"min": 3221,
"median": 4179,
"mean": 3944
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-16T10:54:33.021Z",
"tasks": {
"typecheck": {
"runsMs": [
1012,
896,
917
],
"min": 896,
"median": 917,
"mean": 942
},
"build": {
"runsMs": [
856,
1025,
2129
],
"min": 856,
"median": 1025,
"mean": 1337
}
}
}
}
}
@@ -1,61 +0,0 @@
{
"package": "n8n",
"runs": {
"before": {
"label": "before",
"tsVersion": "6.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T13:14:19.235Z",
"tasks": {
"typecheck": {
"runsMs": [
20872,
22190,
20170
],
"min": 20170,
"median": 20872,
"mean": 21077
},
"build": {
"runsMs": [
12860,
12735,
14095
],
"min": 12735,
"median": 12860,
"mean": 13230
}
}
},
"after": {
"label": "after",
"tsVersion": "7.0.2",
"node": "v24.13.0",
"timestamp": "2026-07-14T13:18:18.589Z",
"tasks": {
"typecheck": {
"runsMs": [
5722,
5122,
4568
],
"min": 4568,
"median": 5122,
"mean": 5137
},
"build": {
"runsMs": [
3688,
3607,
4781
],
"min": 3607,
"median": 3688,
"mean": 4025
}
}
}
}
}
-125
View File
@@ -1,125 +0,0 @@
#!/usr/bin/env node
// Roll every results/<pkg>.json into a single tracked Markdown report, so
// per-package before/after numbers are reviewable as PRs land.
//
// Usage:
// node scripts/typescript-migration/summarize.mjs [--out=<file>]
//
// Default output: scripts/typescript-migration/SUMMARY.md (committed — the
// results/ JSON is gitignored, this rollup is not).
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
const RESULTS_DIR = join(SCRIPT_DIR, 'results');
function parseArgs(argv) {
let out = join(SCRIPT_DIR, 'SUMMARY.md');
for (const arg of argv) {
if (arg.startsWith('--out=')) out = resolve(process.cwd(), arg.slice('--out='.length));
else {
console.error(`\n✖ Unknown option: ${arg}\n`);
process.exit(1);
}
}
return { out };
}
function fmtMs(ms) {
return ms >= 1000 ? `${(ms / 1000).toFixed(2)}s` : `${ms}ms`;
}
// Baseline-first ordering: a label named "before" is always the baseline and
// "after" always last, regardless of the order they were recorded in; anything
// else falls between them by timestamp. Keeps deltas pointing the right way.
function orderLabels(runs) {
const rank = (l) => (/^before$/i.test(l) ? -1 : /^after$/i.test(l) ? 1 : 0);
return Object.keys(runs).sort((a, b) => {
if (rank(a) !== rank(b)) return rank(a) - rank(b);
return (runs[a].timestamp ?? '').localeCompare(runs[b].timestamp ?? '');
});
}
// Render one package's stored runs as the Δ-vs-baseline block.
function renderBlock(data) {
const labels = orderLabels(data.runs);
const base = labels[0];
const lines = [`=== ${data.package} — median times (Δ vs "${base}") ===`];
const tasks = new Set();
for (const l of labels) for (const t of Object.keys(data.runs[l].tasks)) tasks.add(t);
for (const task of tasks) {
lines.push('', `${task}:`);
const baseMedian = data.runs[base].tasks[task]?.median;
for (const label of labels) {
const stat = data.runs[label].tasks[task];
if (!stat) {
lines.push(` ${label.padEnd(16)} (not measured)`);
continue;
}
let delta = '';
if (label !== base && baseMedian != null) {
const diff = stat.median - baseMedian;
const pct = ((diff / baseMedian) * 100).toFixed(1);
const sign = diff <= 0 ? '' : '+';
delta = ` ${sign}${fmtMs(diff)} (${sign}${pct}%)`;
}
lines.push(` ${label.padEnd(16)} ${fmtMs(stat.median).padStart(9)}${delta}`);
}
}
return lines.join('\n');
}
// One "before → after" delta per task for the overview table (first vs last label).
function overviewDelta(data, task) {
const labels = orderLabels(data.runs);
const first = data.runs[labels[0]].tasks[task]?.median;
const last = data.runs[labels[labels.length - 1]].tasks[task]?.median;
if (labels.length < 2 || first == null || last == null) return '—';
const pct = (((last - first) / first) * 100).toFixed(1);
return `${last - first <= 0 ? '' : '+'}${pct}%`;
}
function main() {
const { out } = parseArgs(process.argv.slice(2));
if (!existsSync(RESULTS_DIR)) {
console.error(`\n✖ No results directory at ${RESULTS_DIR}. Run benchmark.mjs first.\n`);
process.exit(1);
}
const files = readdirSync(RESULTS_DIR)
.filter((f) => f.endsWith('.json'))
.map((f) => JSON.parse(readFileSync(join(RESULTS_DIR, f), 'utf8')))
.sort((a, b) => a.package.localeCompare(b.package));
if (files.length === 0) {
console.error('\n✖ No result files found. Run benchmark.mjs first.\n');
process.exit(1);
}
const md = [];
md.push('# TypeScript 6 → 7 migration benchmarks', '');
md.push(`Generated ${new Date().toISOString()} from \`scripts/typescript-migration/results/\`.`, '');
// Overview table: median Δ (first → last label) per package.
md.push('| Package | typecheck Δ | build Δ |', '| --- | --- | --- |');
for (const data of files) {
md.push(`| \`${data.package}\` | ${overviewDelta(data, 'typecheck')} | ${overviewDelta(data, 'build')} |`);
}
md.push('');
// Per-package detail blocks in the benchmark's own format.
for (const data of files) {
md.push('```', renderBlock(data), '```', '');
}
mkdirSync(dirname(out), { recursive: true });
writeFileSync(out, `${md.join('\n')}\n`);
console.log(`✔ Wrote ${out} (${files.length} package${files.length === 1 ? '' : 's'})`);
}
main();