Skip to content

feat!: modernize toolchain and ship ESM-only build#1373

Merged
tada5hi merged 4 commits into
masterfrom
feat/modernize-toolchain-v4
May 20, 2026
Merged

feat!: modernize toolchain and ship ESM-only build#1373
tada5hi merged 4 commits into
masterfrom
feat/modernize-toolchain-v4

Conversation

@tada5hi
Copy link
Copy Markdown
Owner

@tada5hi tada5hi commented May 20, 2026

Summary

Aligns the project with tada5hi/typescript-template and prepares for a v4 release alongside typeorm@1.0. Build system, test runner, linter, husky, publish action and TypeScript major are all swapped together in one PR.

Before After
Bundler Rollup 4 + @swc/core + tsc --emitDeclarationOnly tsdown (rolldown + oxc)
Test runner Jest 30 + ts-jest Vitest 4 + unplugin-swc
Linter ESLint 8 + @tada5hi/eslint-config-typescript (.eslintrc) ESLint 10 flat config + @tada5hi/eslint-config v2 (eslint.config.mjs)
TypeScript 5.9 6
Publish action npx workspaces-publish tada5hi/monoship@v2
Husky hook format v8 (shebang + _/husky.sh source) v9 (one line)
commitlint config commitlint.config.js commitlint.config.mjs
Package type implicit CJS, dual CJS+ESM dist \"type\": \"module\", ESM-only dist
engines.node ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0 >=22.0.0
CLI binaries typeorm-extension (cjs) + typeorm-extension-esm (mjs) typeorm-extension only
build script one step build:types (typecheck) → build:js (tsdown)

Build behaviour preserved across the swap

The new tsdown.config.ts re-implements the two non-trivial rollup behaviours so the dist output stays equivalent:

  1. CLI cross-module rewrite (cliRewriteExternal plugin) — relative imports in src/cli/* that traverse out of the CLI subtree are externalised to \"typeorm-extension\" so the CLI bundle stays small and shares singleton state (DataSource registry, env cache, factory manager) with the library that consumers import directly. The plugin is POSIX-safe across platforms.
  2. typeorm deep-import .js suffix (typeormDeepImportExtension plugin) — runtime typeorm/<deep> imports get a .js suffix so Node's strict ESM resolver finds them (typeorm's package.json exports map does not expose those subpaths). Uses a negative-lookbehind so already-suffixed paths aren't double-.js.js'd.

Vitest specifics

Two non-obvious tuning choices that affect TypeORM behaviour:

  • unplugin-swc — vitest's default oxc transform does not emit decorator metadata. Without swc, TypeORM entity columns lose their design:type reflect-metadata and dataSource.initialize() throws.
  • server.deps.inline: [/locter/]locter.load() uses await import(id) for dynamic loading. By default vitest treats node_modules as externals, so that import() falls through to Node's native loader, escaping vitest's module graph. The result: entity classes loaded statically (via vitest) and entity classes loaded dynamically through a seeder file (via Node) are different module instances, and dataSource.getRepository(SameNameButDifferentClass) throws EntityMetadataNotFoundError. Inlining locter forces it through vite-node and restores module identity. Long-term fix belongs in locter — issue to follow.

TypeScript 6

CompilerOptions / TypeAcquisition etc. are no longer top-level exports of the typescript package; they live under the ts.* namespace. src/utils/tsconfig/type.ts switched to import type ts from 'typescript' + ts.CompilerOptions accordingly.

tsconfig.json sets moduleResolution: node10 + ignoreDeprecations: \"6.0\" so type-only deep imports into typeorm/driver/... still resolve (typeorm's package exports don't expose those subpaths; bundler/nodenext modes refuse them).

Four strict options are explicitly relaxed to keep the existing source passing typecheck. Tightening them is intentional follow-up work, not regression scope:

  • noUncheckedIndexedAccess: false
  • noUnusedLocals: false
  • noUnusedParameters: false
  • verbatimModuleSyntax: false

Docs

  • README.MD and docs/guide/cli.md no longer mention the dual binary, cli.cjs, or ts-node-esm. Examples updated to tsx.
  • New docs/guide/migration-guide-v4.md walks consumers through the upgrade. Wired into the VitePress sidebar.
  • Agent docs (AGENTS.md, .agents/*) updated to reflect the new toolchain and now include a Documentation Sync Rule requiring future code changes to update both agent docs and user-facing VitePress docs.

Verification

  • npm run buildbuild:types clean → build:js emits dist/index.mjs (89.69 kB) + dist/index.d.mts (41.41 kB) + bin/cli.mjs (8.59 kB)
  • npm test — 21 test files, 51/51 passing
  • npm run lint — 0 errors
  • Smoke-tested public API (121 exports present) and CLI subcommand help renders correctly

Test plan

  • CI green on this branch
  • Manual npm pack + install in a downstream consumer project (verify ESM import, verify require() via Node 22 require(esm), verify CLI binary)
  • Coverage report still uploads to Codecov

Breaking changes (see migration guide)

  • Package is ESM-only. Node ≥ 22 required (CJS consumers continue to work via require(esm)).
  • typeorm-extension-esm binary removed — use typeorm-extension (now backed by bin/cli.mjs).
  • TypeORM peer dep will move to ^1.0.0 alongside this release.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Vitest configuration with SWC transpilation for testing.
    • Added tsdown build configuration for ESM bundling.
  • Bug Fixes

    • Updated error handling to use modern catch syntax.
  • Documentation

    • Updated CLI documentation to use tsx with ESM binary instead of ts-node.
    • Updated migration guide for v4, highlighting ESM-only package and simplified CLI.
    • Refreshed toolchain references in developer documentation.
  • Chores

    • Package is now ESM-only; CommonJS support removed.
    • Minimum Node version raised to >=22.0.0.
    • Upgraded GitHub Actions and Release Please workflow.
    • Migrated from Jest to Vitest and Rollup to tsdown.
    • Replaced ESLint config format; removed old configuration file.
    • CLI consolidated to single bin/cli.mjs entry point.

Review Change Stack

Bundler, test runner, linter, husky, publish action and TypeScript major
all swapped in one go to align with @tada5hi/typescript-template and the
upcoming typeorm@1.0 release.

Build:
- Replace rollup + @swc/core with tsdown (rolldown + oxc). One config
  emits both the library (dist/index.mjs + dist/index.d.mts) and the
  CLI (bin/cli.mjs).
- Split the build script into build:types (tsc --noEmit) and build:js
  (tsdown), composed by build.
- Preserve the two rollup-only behaviours: the CLI bundle marks
  cross-domain imports as external and rewrites them to "typeorm-extension"
  so the CLI shares singleton state with the consumer's installed library;
  the library bundle suffixes runtime typeorm/<deep> imports with .js so
  Node's strict ESM resolver accepts them.
- The CLI rewrite plugin is now POSIX-safe across platforms.

Tests:
- Replace jest + ts-jest with vitest 4 + unplugin-swc (so TypeORM
  decorator metadata is still emitted).
- Inline locter via server.deps.inline so dynamic .ts loading from inside
  locter.load() goes through vite-node and shares entity-class identity
  with the test module.
- __dirname -> import.meta.dirname in 3 test files + 1 fixture.

Lint:
- ESLint 8 + @tada5hi/eslint-config-typescript + .eslintrc -> ESLint 10
  flat config + @tada5hi/eslint-config v2 in eslint.config.mjs.
- Drop import/no-cycle (eslint-plugin-import-lite does not ship it).

TypeScript 6:
- import type { CompilerOptions, TypeAcquisition } from 'typescript' is
  no longer valid; the public types restructured behind the ts.* namespace.
  src/utils/tsconfig/type.ts updated accordingly.
- tsconfig sets moduleResolution: node10 + ignoreDeprecations: "6.0" so
  type-only deep imports into typeorm subpaths still resolve.
- Relaxed strict options (noUncheckedIndexedAccess, noUnusedLocals,
  noUnusedParameters, verbatimModuleSyntax) explicitly set to false to
  preserve the pre-existing source patterns; tightening them is intentional
  future work.

CI / Release:
- googleapis/release-please-action@v5, actions/setup-node@v4, cache@v4.
- workspaces-publish -> tada5hi/monoship@v2.
- husky 9 hook in v9 format (no shebang, no _/husky.sh source).
- commitlint.config.js -> commitlint.config.mjs.

Docs:
- README and docs/guide/cli.md no longer mention the dual binary or
  cli.cjs. Added docs/guide/migration-guide-v4.md and wired it into the
  VitePress sidebar.
- AGENTS.md + .agents/* updated to describe the new toolchain. Added a
  Documentation Sync Rule to AGENTS.md.

BREAKING CHANGE: typeorm-extension is now ESM-only. CJS consumers on
Node 22+ can still require('typeorm-extension') thanks to require(esm)
support; older Node versions can no longer consume the package.
Minimum Node is now 22 (was 20.19). The typeorm-extension-esm binary
alias is removed - use typeorm-extension. See docs/guide/migration-guide-v4.md.
Copilot AI review requested due to automatic review settings May 20, 2026 09:51
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Warning

Rate limit exceeded

@tada5hi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 13 minutes and 26 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 962a2743-d85b-424a-b4f7-11f5bea7adeb

📥 Commits

Reviewing files that changed from the base of the PR and between b55c4fb and b899126.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • docs/guide/migration-guide-v4.md
  • package.json
  • src/env/module.ts
  • src/env/utils.ts
  • src/helpers/entity/metadata.ts
  • src/helpers/entity/uniqueness.ts
  • src/utils/file-path.ts
  • test/data/entity/user.ts
  • test/data/seed/user.ts
  • test/data/typeorm/FakeSelectQueryBuilder.ts
  • test/unit/database/index.spec.ts
  • test/unit/query/filters.spec.ts
  • tsdown.config.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/modernize-toolchain-v4

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Modernizes typeorm-extension’s build/test/lint/release toolchain and switches the package to an ESM-only distribution, while refactoring a few internal modules (query, database context/method wiring) to match the new template.

Changes:

  • Replace Rollup/Jest/ESLint v8 configs with tsdown + Vitest + ESLint flat config, and update CI/release workflows accordingly.
  • Publish ESM-only output ("type": "module"), simplify CLI binary to a single entry, and update docs/migration guides.
  • Refactor query and database modules (types/options wiring, context normalization) and apply related test updates.

Reviewed changes

Copilot reviewed 77 out of 84 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tsdown.config.ts Adds tsdown build config and re-implements prior Rollup behaviors via plugins.
tsconfig.json Updates TS compiler settings for ESM/noEmit/tooling alignment.
tsconfig.eslint.json Removes Jest-era ESLint project config.
test/vitest.config.ts Introduces Vitest config (swc transform + coverage + deps inline).
test/unit/utils/tsconfig.spec.ts Updates ESM path resolution usage (import.meta.dirname).
test/unit/utils/file-path.spec.ts Refactors loops/object literals (formatting + minor cleanups).
test/unit/seeder/seeder.spec.ts Refactors object literal formatting.
test/unit/seeder/factory.spec.ts Refactors loop style.
test/unit/query/relations.spec.ts Refactors object literal formatting.
test/unit/query/index.spec.ts Adds pagination defaulting coverage + formatting tweaks.
test/unit/query/filters.spec.ts Formatting changes (includes trailing whitespace issues).
test/unit/helper/entity-join-columns.spec.ts Refactors object literal formatting.
test/unit/env/module.spec.ts Refactors object literal formatting.
test/unit/database/migration.spec.ts Ensures DataSource init/destroy around migration generation.
test/unit/database/index.spec.ts Refactors imports/object literals.
test/unit/data-source/options/module.spec.ts Refactors object literal formatting.
test/unit/data-source/options/env.spec.ts Refactors object literals; updates calls.
test/unit/data-source/find.spec.ts Switches to node:path + ESM dirname usage.
test/jest.config.js Removes Jest config.
test/data/typeorm/utils.ts Refactors object literal formatting and calls.
test/data/typeorm/FakeSelectQueryBuilder.ts Updates type signature; introduces whitespace-only line.
test/data/typeorm/factory.ts Refactors object literal formatting.
test/data/typeorm/data-source-default.ts Switches to node:path + import.meta.dirname.
test/data/seed/user.ts Re-formats insert object literal (introduces trailing spaces).
test/data/seed/role.ts Refactors object literal formatting.
test/data/entity/user.ts Re-formats imports/indentation.
test/data/entity/role.ts Fixes indentation for fields.
src/utils/tsconfig/type.ts Re-formats types (but still uses TS6-incompatible type imports).
src/utils/tsconfig/module.ts Minor string API modernization (includes) and catch cleanup.
src/utils/separator.ts Minor loop + string API modernization.
src/utils/object.ts Adds extendObject() helper.
src/utils/file-system.ts Simplifies catch clause.
src/utils/file-path.ts Refactors loops/includes usage and key iteration.
src/seeder/utils/prepare.ts Refactors loops and parsing (Number.parseInt).
src/seeder/factory/utils.ts Refactors loops and config iteration.
src/seeder/factory/module.ts Changes faker import/loading approach; refactors loops.
src/seeder/executor.ts Loop refactors + Number.parseInt usage.
src/query/utils/option.ts Loop refactor.
src/query/utils/alias.ts Loop refactor.
src/query/type.ts Reworks QueryApplyOptions typing to local option types.
src/query/parameter/sort/module.ts Loop refactor for parse output application.
src/query/parameter/relations/type.ts Adds onJoin hook type and option.
src/query/parameter/relations/module.ts Adds onJoin callback invocation; defaults options param.
src/query/parameter/filters/type.ts Type formatting adjustments.
src/query/parameter/filters/module.ts Loop refactors.
src/query/parameter/fields/type.ts Type formatting adjustments.
src/query/module.ts Threads QueryApplyOptions into parse-output application + merges relation options.
src/helpers/entity/uniqueness.ts Adds doc comments + loop refactors (introduces trailing spaces).
src/helpers/entity/metadata.ts Import formatting adjustments.
src/helpers/entity/join-columns.ts Refactors object literal and loop style.
src/env/utils.ts Import formatting adjustments.
src/env/module.ts Import formatting adjustments.
src/database/utils/schema.ts Refactors runMigrations call formatting.
src/database/utils/migration.ts Changes generated template to import type; removes init/destroy responsibility; refactors file write.
src/database/utils/context.ts Refactors to normalized options builder and new context input types.
src/database/methods/type.ts Adds new database context types.
src/database/methods/index.ts New barrel for database methods.
src/database/methods/drop/module.ts New dropDatabase method entry using new context types.
src/database/methods/drop/index.ts New barrel export.
src/database/methods/create/module.ts New createDatabase method entry using new context types.
src/database/methods/create/index.ts New barrel export.
src/database/methods/check/types.ts Removes base/create/drop context types (moved to new type file).
src/database/methods/check/module.ts Updates imports/paths and catch cleanup.
src/database/methods/check/index.ts New barrel export.
src/database/index.ts Re-exports via methods barrel.
src/database/drop.ts Removes legacy dropDatabase entry.
src/database/create.ts Removes legacy createDatabase entry.
src/database/driver/utils/create.ts Minor includes() refactor.
src/database/driver/utils/build.ts Updates DriverOptions type import path.
src/database/driver/types.ts Adds DriverOptions type definition file.
src/database/driver/sqlite.ts Updates context input types + refactors initialization.
src/database/driver/postgres.ts Updates context input types + DriverOptions import path.
src/database/driver/oracle.ts Updates context input types + DriverOptions import path.
src/database/driver/mysql.ts Updates context input types + DriverOptions import path.
src/database/driver/mssql.ts Updates context input types + DriverOptions import path.
src/database/driver/mongodb.ts Updates context input types + DriverOptions import path.
src/database/driver/index.ts Exports types instead of removed type.
src/database/driver/cockroachdb.ts Updates context input types.
src/data-source/find/module.ts Refactors loops and module export iteration.
src/cli/commands/seed/create.ts Simplifies catch clause.
src/cli/commands/database/drop.ts Refactors option declaration formatting.
src/cli/commands/database/create.ts Updates to new DatabaseCreateContextInput type usage.
rollup.config.mjs Removes Rollup build config.
release-please-config.json Minor formatting/key ordering updates.
README.MD Updates CLI usage examples for ESM + tsx.
package.json Switches to ESM-only metadata, toolchain scripts, and dependency changes.
eslint.config.mjs Adds ESLint flat config with project overrides/ignores.
docs/guide/query.md Fixes minor grammar.
docs/guide/migration-guide-v4.md Adds v4 migration guide (includes TypeORM peer claim mismatch).
docs/guide/migration-guide-v3.md Adds note referencing v4 ESM-only change.
docs/guide/cli.md Updates CLI docs for ESM loader usage.
docs/.vitepress/config.mjs Sidebar/navigation update + formatting fixes.
commitlint.config.mjs Converts commitlint config to ESM.
commitlint.config.js Removes CJS commitlint config.
CLAUDE.md Adds agent doc references.
CHANGELOG.md Updates changelog content.
AGENTS.md Adds agent guide + documentation sync rule.
.release-please-manifest.json Updates manifest version.
.husky/commit-msg Updates Husky v9 hook format.
.gitignore Updates ignored paths.
.github/workflows/release.yml Updates release flow (release-please v5 + monoship).
.github/workflows/main.yml Updates CI triggers, concurrency, and job ordering.
.github/dependabot.yml Retargets updates to master.
.github/actions/install/action.yml Updates setup-node/cache versions and cache key.
.github/actions/build/action.yml Updates cache action version and formatting.
.eslintrc Removes legacy ESLint config.
.agents/testing.md Adds testing/tooling documentation for Vitest + swc.
.agents/structure.md Adds project structure documentation.
.agents/conventions.md Adds conventions/tooling documentation.
.agents/architecture.md Adds architecture documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/tsconfig/type.ts
Comment thread package.json Outdated
Comment thread package.json
Comment on lines 2 to +4
"name": "typeorm-extension",
"version": "3.9.0",
"type": "module",
Comment thread package.json
Comment thread docs/guide/migration-guide-v4.md Outdated
Comment thread test/data/typeorm/FakeSelectQueryBuilder.ts
Comment thread test/unit/query/filters.spec.ts
Comment thread src/helpers/entity/uniqueness.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
src/cli/commands/seed/create.ts (1)

87-87: ⚡ Quick win

Unused catch binding removed correctly.

The modernization from catch (e) to catch is appropriate since the error was never used.

Consider logging the actual error for easier debugging when file writes fail:

📝 Optional: Log error details for debugging
     try {
         await fs.promises.writeFile(filePath, template, { encoding: 'utf-8' });
-    } catch {
+    } catch (e) {
         consola.warn(`The seed could not be written to the path ${filePath}.`);
+        consola.error(e);
         process.exit(1);
     }

This would help users diagnose issues like permission errors, disk space, or path problems.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/commands/seed/create.ts` at line 87, The empty catch was
intentionally simplified but now loses useful error context; change the bare
`catch` back to `catch (err)` in the failing file-write block in create.ts and
log the error (e.g., `console.error("Failed to write seed file:", err)` or use
the module's existing logger) so permission/disk/path errors are visible for
debugging.
README.MD (1)

68-75: 💤 Low value

Optional: Add language identifier to code fence.

The code block starting at line 68 is missing a language identifier. Adding json would enable syntax highlighting and satisfy markdown linting:

-```
+```json
 "scripts": {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.MD` around lines 68 - 75, The code block showing the package.json
"scripts" object is missing a Markdown language identifier; update the fence
that contains the "scripts" block (which includes keys like "db:create",
"db:drop", "seed:run", "seed:create") to use ```json so the block begins with
```json to enable JSON syntax highlighting and satisfy the linter.
docs/guide/cli.md (1)

11-18: 💤 Low value

Optional: Add language identifier to code fence.

The code block starting at line 11 is missing a language identifier. Adding json would enable syntax highlighting:

-```
+```json
 "scripts": {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/guide/cli.md` around lines 11 - 18, The fenced code block showing the
npm "scripts" object should specify a language for syntax highlighting; update
the opening fence from ``` to ```json so the block containing "scripts" and keys
like "db:create", "db:drop", "seed:run", and "seed:create" is marked as JSON.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actions/build/action.yml:
- Line 9: Replace the floating tag "uses: actions/cache@v4" with a pinned commit
SHA to ensure reproducible builds; locate the composite action step that uses
"actions/cache@v4" and change it to the full commit reference
(actions/cache@<full-commit-sha>) by finding the latest stable commit on the
actions/cache repository and using that SHA in the action.yml.

In @.github/actions/install/action.yml:
- Line 15: Replace the floating action tags used in the workflow (specifically
the two occurrences "actions/setup-node@v4" and "actions/cache@v4") with pinned
commit SHAs to prevent supply-chain risk; locate the lines that call those
actions in the action.yml and swap the tag portion (e.g., "`@v4`") with the
corresponding commit SHA for each repository (e.g.,
"`@b1f6e04751a816d7b3694d8e5c19456590111534`" for setup-node) and update both
occurrences consistently so the workflow references immutable SHAs instead of
floating tags.

In @.github/workflows/main.yml:
- Around line 50-52: Replace each floating checkout action usage in the
"Checkout" step with a pinned commit SHA of actions/checkout and add
persist-credentials: false; specifically update every "Checkout" step that
currently uses actions/checkout@v6 (the four occurrences) to reference the full
commit SHA instead of `@v6` and include persist-credentials: false under that step
to disable passing GITHUB_TOKEN to subsequent steps.

In @.github/workflows/release.yml:
- Line 33: The workflow uses mutable action tags
(googleapis/release-please-action@v5 and the other action at `@v2`) which should
be replaced with immutable commit SHAs; update the uses entries to point to the
corresponding full-length commit SHA for googleapis/release-please-action and
the other action (the ad-m/github-push-action referenced at `@v2`) by looking up
the action repositories' stable release commit on GitHub and substituting the
tag (e.g., `@v5/`@v2) with the full 40-character commit SHA so the release
workflow is pinned immutably.

In `@src/utils/file-path.ts`:
- Around line 70-72: The loop in src/utils/file-path.ts is incorrectly using
substring matching (base.includes(jsExtension)) which mis-detects extensions
like "my-json.ts"; change the check to test the filename's extension suffix
instead (e.g., use base.endsWith(jsExtension) or compare path.extname(base)
against entries in jsExtensions) so only actual file extensions trigger the
early return in the loop over jsExtensions; update the loop that references
base, jsExtensions and input accordingly.

In `@tsconfig.json`:
- Line 7: The tsconfig.json currently sets "moduleResolution": "node10", which
forces legacy CommonJS-style resolution; update the moduleResolution compiler
option to a modern ESM-aware resolver (for example "nodenext" or
"node16"/"bundler" depending on your Node target) so package.json exports and
conditional resolution work correctly; open tsconfig.json and replace the
"moduleResolution" value from "node10" with the chosen modern resolver and run a
quick build to confirm no import resolution regressions.

In `@tsdown.config.ts`:
- Around line 31-33: The current rule in tsdown.config.ts blindly externalizes
any import with source.startsWith('../') to { id: 'typeorm-extension', external:
true }; change it to resolve the import path and only externalize when that
resolved path actually escapes the CLI directory. Use path.resolve/path.dirname
on the importer (handle importer possibly undefined) and path.relative to the
project's src/cli root to determine if the import is outside src/cli
(relativePath.startsWith('..') or path.isAbsolute check), and only then return
the externalization object; otherwise let the import pass through. Ensure you
reference the existing source and importer variables and the return value { id:
'typeorm-extension', external: true } in the updated condition.

---

Nitpick comments:
In `@docs/guide/cli.md`:
- Around line 11-18: The fenced code block showing the npm "scripts" object
should specify a language for syntax highlighting; update the opening fence from
``` to ```json so the block containing "scripts" and keys like "db:create",
"db:drop", "seed:run", and "seed:create" is marked as JSON.

In `@README.MD`:
- Around line 68-75: The code block showing the package.json "scripts" object is
missing a Markdown language identifier; update the fence that contains the
"scripts" block (which includes keys like "db:create", "db:drop", "seed:run",
"seed:create") to use ```json so the block begins with ```json to enable JSON
syntax highlighting and satisfy the linter.

In `@src/cli/commands/seed/create.ts`:
- Line 87: The empty catch was intentionally simplified but now loses useful
error context; change the bare `catch` back to `catch (err)` in the failing
file-write block in create.ts and log the error (e.g., `console.error("Failed to
write seed file:", err)` or use the module's existing logger) so
permission/disk/path errors are visible for debugging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bbdc0c7d-396b-45e1-a55c-208ba68464fb

📥 Commits

Reviewing files that changed from the base of the PR and between 6f23c4c and b55c4fb.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (83)
  • .agents/conventions.md
  • .agents/structure.md
  • .agents/testing.md
  • .eslintrc
  • .github/actions/build/action.yml
  • .github/actions/install/action.yml
  • .github/workflows/main.yml
  • .github/workflows/release.yml
  • .gitignore
  • .husky/commit-msg
  • AGENTS.md
  • README.MD
  • commitlint.config.js
  • commitlint.config.mjs
  • docs/.vitepress/config.mjs
  • docs/guide/cli.md
  • docs/guide/migration-guide-v3.md
  • docs/guide/migration-guide-v4.md
  • eslint.config.mjs
  • package.json
  • release-please-config.json
  • rollup.config.mjs
  • src/cli/commands/database/create.ts
  • src/cli/commands/database/drop.ts
  • src/cli/commands/seed/create.ts
  • src/data-source/find/module.ts
  • src/database/driver/sqlite.ts
  • src/database/driver/utils/create.ts
  • src/database/methods/check/module.ts
  • src/database/utils/context.ts
  • src/database/utils/migration.ts
  • src/database/utils/schema.ts
  • src/env/module.ts
  • src/env/utils.ts
  • src/helpers/entity/join-columns.ts
  • src/helpers/entity/metadata.ts
  • src/helpers/entity/uniqueness.ts
  • src/query/module.ts
  • src/query/parameter/fields/type.ts
  • src/query/parameter/filters/module.ts
  • src/query/parameter/filters/type.ts
  • src/query/parameter/relations/module.ts
  • src/query/parameter/sort/module.ts
  • src/query/type.ts
  • src/query/utils/alias.ts
  • src/query/utils/option.ts
  • src/seeder/executor.ts
  • src/seeder/factory/module.ts
  • src/seeder/factory/utils.ts
  • src/seeder/utils/prepare.ts
  • src/utils/file-path.ts
  • src/utils/file-system.ts
  • src/utils/object.ts
  • src/utils/separator.ts
  • src/utils/tsconfig/module.ts
  • src/utils/tsconfig/type.ts
  • test/data/entity/role.ts
  • test/data/entity/user.ts
  • test/data/seed/role.ts
  • test/data/seed/user.ts
  • test/data/typeorm/FakeSelectQueryBuilder.ts
  • test/data/typeorm/data-source-default.ts
  • test/data/typeorm/factory.ts
  • test/data/typeorm/utils.ts
  • test/jest.config.js
  • test/unit/data-source/find.spec.ts
  • test/unit/data-source/options/env.spec.ts
  • test/unit/data-source/options/module.spec.ts
  • test/unit/database/index.spec.ts
  • test/unit/database/migration.spec.ts
  • test/unit/env/module.spec.ts
  • test/unit/helper/entity-join-columns.spec.ts
  • test/unit/query/filters.spec.ts
  • test/unit/query/index.spec.ts
  • test/unit/query/relations.spec.ts
  • test/unit/seeder/factory.spec.ts
  • test/unit/seeder/seeder.spec.ts
  • test/unit/utils/file-path.spec.ts
  • test/unit/utils/tsconfig.spec.ts
  • test/vitest.config.ts
  • tsconfig.eslint.json
  • tsconfig.json
  • tsdown.config.ts
💤 Files with no reviewable changes (5)
  • rollup.config.mjs
  • test/jest.config.js
  • commitlint.config.js
  • tsconfig.eslint.json
  • .eslintrc

key: ${{ runner.os }}-build-${{ github.sha }}
- name: Use cache
id: 'cache'
uses: actions/cache@v4
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

cat -n .github/actions/build/action.yml | head -20

Repository: tada5hi/typeorm-extension

Length of output: 708


🏁 Script executed:

# Check if there are other pinned actions in the repository to understand the pattern
rg "uses: .+@" .github/ -A 1 -B 1

Repository: tada5hi/typeorm-extension

Length of output: 2413


Pin actions/cache to a specific commit SHA in composite actions.

This composite action uses actions/cache@v4 (floating tag). Pinning to a specific commit SHA ensures reproducible CI runs and prevents unexpected upstream changes if the maintainer reassigns the version tag.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actions/build/action.yml at line 9, Replace the floating tag "uses:
actions/cache@v4" with a pinned commit SHA to ensure reproducible builds; locate
the composite action step that uses "actions/cache@v4" and change it to the full
commit reference (actions/cache@<full-commit-sha>) by finding the latest stable
commit on the actions/cache repository and using that SHA in the action.yml.

shell: bash
run: echo ${{ github.ref }}
- name: Use Node.js ${{ inputs.node-version }}
uses: actions/setup-node@v4
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

cat -n .github/actions/install/action.yml | head -30

Repository: tada5hi/typeorm-extension

Length of output: 1173


Pin setup/install action dependencies to commit SHAs.

Lines 15 and 21 use floating tags (actions/setup-node@v4, actions/cache@v4). Replace these with pinned commit SHAs (e.g., actions/setup-node@b1f6e04751a816d7b3694d8e5c19456590111534) to prevent supply chain risks from tag reassignments and improve auditability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actions/install/action.yml at line 15, Replace the floating action
tags used in the workflow (specifically the two occurrences
"actions/setup-node@v4" and "actions/cache@v4") with pinned commit SHAs to
prevent supply-chain risk; locate the lines that call those actions in the
action.yml and swap the tag portion (e.g., "`@v4`") with the corresponding commit
SHA for each repository (e.g., "`@b1f6e04751a816d7b3694d8e5c19456590111534`" for
setup-node) and update both occurrences consistently so the workflow references
immutable SHAs instead of floating tags.

Comment on lines +50 to +52
- name: Checkout
uses: actions/checkout@v6

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, check if the workflow file exists and its size
ls -lh .github/workflows/main.yml 2>/dev/null || echo "File not found"

Repository: tada5hi/typeorm-extension

Length of output: 145


🏁 Script executed:

# Read the entire workflow file to understand its structure
cat -n .github/workflows/main.yml

Repository: tada5hi/typeorm-extension

Length of output: 2687


🌐 Web query:

GitHub Actions security hardening commit SHA pinning best practices

💡 Result:

Pinning GitHub Actions to a full-length commit SHA is a critical security best practice that transforms a mutable action reference into an immutable one [1][2][3][4]. Because tags (e.g., @v4) and branches (e.g., @main) can be moved or deleted by action maintainers or malicious actors, they are not secure trust anchors [3][5][6]. Pinning to a full-length SHA ensures that the exact, validated code you tested is the same code executed in your pipeline, mitigating the risk of supply chain attacks where malicious code is injected into a tag or repository after you have already audited it [1][4][7][8]. Best Practices for SHA Pinning: 1. Use Full-Length SHAs: Always use the full 40-character commit SHA rather than a shortened version to ensure absolute uniqueness and collision resistance [3][9][4]. 2. Include Version Comments: To maintain readability and ease of maintenance, append the original tag as a comment in your workflow file [10][6][7]. Example: uses: actions/checkout@11bd719 # v4.2.2 3. Automate Updates: Pinning creates a maintenance overhead, as you will not receive automatic security patches [1][6]. Use dependency management tools like Dependabot or Renovate to monitor, create pull requests for, and update these SHAs automatically [1][6]. 4. Enforce via Organization Policy: Organizations can enforce this security standard by enabling the "Require actions to be pinned to a full-length commit SHA" policy in GitHub settings [1][2][3][7]. This policy applies to the entire dependency tree, including transitive actions (sub-actions), and will cause workflows to fail if unpinned actions are detected [1][2]. 5. Verify Sources: Only pin SHAs from trusted, official action repositories [3][9]. Do not pin SHAs from forks, as these may not be maintained or could be inherently insecure [3][11]. 6. Layered Security: While SHA pinning provides immutability, it should be part of a broader security strategy, including limiting the permissions granted to workflows, using scoped secrets, and monitoring outbound network traffic [12][5][13].

Citations:


🌐 Web query:

GitHub Actions persist-credentials false security recommendation

💡 Result:

The persist-credentials input in the actions/checkout action controls whether the repository's authentication token (typically GITHUB_TOKEN) is configured in the local git environment for the runner [1][2][3]. Security Recommendation It is a widely adopted security best practice to set persist-credentials: false in your actions/checkout step unless your workflow specifically requires authenticated git operations (like git push) [4][5]. Reasoning By default (persist-credentials: true), the actions/checkout action stores the authentication token in the local git configuration [1][2][5]. This makes the token accessible to all subsequent steps in the same job [6][5]. If a workflow includes third-party actions or scripts that are compromised or malicious, those processes could potentially access and misuse the persisted token [7][8][5]. Setting this to false removes the credentials from the git config, significantly reducing the attack surface for such scenarios [4][5]. Important Context - Evolution of Security: Recent versions of actions/checkout have improved security by storing credentials in a separate file under $RUNNER_TEMP instead of directly in .git/config, which helps prevent leaks (e.g., via artifact uploads) [1][2][9]. However, the principle of least privilege still makes persist-credentials: false the recommended choice for read-only workflows [5]. - Functional Impact: If your workflow performs authenticated git operations later in the job—such as using git-auto-commit-action—those operations may fail if you set persist-credentials to false [6]. In such cases, you must manually re-authenticate (e.g., using git remote set-url with an explicit token) or keep the default persistence enabled only for specific jobs that require it [6][4]. - Broader Security: While persist-credentials: false mitigates one specific vector, it is not a complete solution. Always ensure your workflow permissions are scoped to the least privileges necessary using the permissions key in your workflow file [7][10].

Citations:


Pin checkout action to commit SHA and disable persisted credentials across all jobs.

The workflow uses floating tags for actions/checkout@v6 and does not set persist-credentials: false in four places: lines 24–25, 36–37, 50–51, and 70–71. This exposes the repository to supply chain attacks where malicious code could be injected into a mutable tag reference, and allows downstream steps to access the GITHUB_TOKEN unnecessarily.

Pinning to a full-length commit SHA makes the action reference immutable and verifiable. Since all jobs only perform read-only operations (checkout, install, build, lint/test), set persist-credentials: false to prevent compromised actions from accessing or misusing the authentication token.

Suggested hardening patch
-            - name: Checkout
-              uses: actions/checkout@v6
+            - name: Checkout
+              uses: actions/checkout@<checkout_v6_commit_sha>
+              with:
+                  persist-credentials: false

Apply this pattern to all four checkout steps (lines 24–25, 36–37, 50–51, and 70–71).

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 50-51: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 51-51: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/main.yml around lines 50 - 52, Replace each floating
checkout action usage in the "Checkout" step with a pinned commit SHA of
actions/checkout and add persist-credentials: false; specifically update every
"Checkout" step that currently uses actions/checkout@v6 (the four occurrences)
to reference the full commit SHA instead of `@v6` and include persist-credentials:
false under that step to disable passing GITHUB_TOKEN to subsequent steps.

- uses: google-github-actions/release-please-action@v4
- name: Release Please
id: release
uses: googleapis/release-please-action@v5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/release.yml | head -80

Repository: tada5hi/typeorm-extension

Length of output: 2926


🏁 Script executed:

rg "uses:" .github/workflows/release.yml -n

Repository: tada5hi/typeorm-extension

Length of output: 430


🏁 Script executed:

web_search
GitHub Actions pinning to commit SHA supply chain security best practice

Repository: tada5hi/typeorm-extension

Length of output: 165


🌐 Web query:

GitHub Actions pinning commit SHA immutable security supply chain

💡 Result:

GitHub Actions pinning to a full-length commit SHA is the recommended way to mitigate supply-chain risk from malicious or compromised actions, because it makes the action reference an “immutable release” (the exact commit) rather than a mutable tag/branch reference.[1] 1) What SHA pinning fixes (and why tags are riskier) - GitHub’s security guidance states: “Pinning an action to a full-length commit SHA is currently the only way to use an action as an immutable release.”[1] - GitHub also notes that if you pin to a tag, you “risk” the tag being moved or deleted by an attacker with access to the action repository.[1] 2) How SHA pinning helps supply-chain attacks - If an action repository maintainer account is compromised or the maintainer updates/mutates a tag/branch, workflows referencing mutable identifiers could start executing attacker-controlled code. GitHub’s changelog describes this class of risk and recommends SHA pinning to prevent malicious code introduced in new/updated branches/tags from being automatically used.[2] 3) Example syntax - Use: owner/repo@<40-char-full-SHA> (optionally with a comment documenting the intended version). This is the pattern GitHub shows in its “Secure use reference” guidance.[1] 4) Organization-level enforcement (so unpinned actions fail) - GitHub introduced an “allowed actions policy” capability to enforce SHA pinning: administrators can require actions to be pinned to a full commit SHA, and workflows that attempt to use actions that aren’t pinned will fail.[2] 5) Important limitations / remaining supply-chain risk - SHA pinning does not eliminate all supply-chain risk: the pinned action could itself fetch and execute other dependencies (e.g., other actions, packages, container images). SHA pinning prevents the workflow from switching to a different version of the pinned action without changing the SHA, but you still need to manage transitive dependencies and execution behavior. Bottom line - For CI/CD integrity, pin GitHub Actions to full-length commit SHAs and enable/require SHA-pinning policies so tag/branch references are blocked; this is GitHub’s documented approach to using actions as immutable releases.[1][2]

Citations:


Pin release workflow actions to immutable commit SHAs for supply-chain hardening.

Lines 33 and 62 reference mutable tags (@v5, @v2) instead of full-length commit SHAs. GitHub's security guidance documents that SHA pinning is the only way to use actions as immutable releases; mutable tags risk being moved or mutated by an attacker with repository access. This is particularly critical in release pipelines and is commonly enforced by organizational pinning policies.

Suggested patch
-                uses: googleapis/release-please-action@v5
+                uses: googleapis/release-please-action@<release_please_v5_commit_sha>
...
-                uses: tada5hi/monoship@v2
+                uses: tada5hi/monoship@<monoship_v2_commit_sha>
🧰 Tools
🪛 zizmor (1.25.2)

[error] 33-33: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 33, The workflow uses mutable action
tags (googleapis/release-please-action@v5 and the other action at `@v2`) which
should be replaced with immutable commit SHAs; update the uses entries to point
to the corresponding full-length commit SHA for googleapis/release-please-action
and the other action (the ad-m/github-push-action referenced at `@v2`) by looking
up the action repositories' stable release commit on GitHub and substituting the
tag (e.g., `@v5/`@v2) with the full 40-character commit SHA so the release
workflow is pinned immutably.

Comment thread src/utils/file-path.ts Outdated
Comment thread tsconfig.json
"lib": ["ESNext"],
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node10",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

TypeScript 6: what are the behavioral differences between moduleResolution "node10", "node16", "nodenext", and "bundler" for ESM packages using package.json exports?

💡 Result:

In TypeScript 6, the practical behavioral differences among moduleResolution = "node10", "node16", "nodenext", and "bundler" for ESM packages using package.json "exports" mainly come from (a) which Node.js ESM/CJS resolution algorithm is modeled and (b) whether TypeScript enforces Node-style relative-extension rules. 1) moduleResolution: "node10" (legacy) - Models Node.js behavior for versions older than v10, which only support CommonJS require (not modern dual ESM/CJS resolution). TypeScript describes "node10" as for Node.js versions older than v10 and says you probably won’t need it in modern code. [1] - Because it’s the legacy CommonJS-only model, it’s generally not the right choice for ESM packages that rely on modern package.json "exports" + conditional resolution. 2) moduleResolution: "node16" and "nodenext" (Node’s dual ESM/CJS package.json "exports" + conditions) - Both are intended for “modern versions of Node.js” and TypeScript says that, when combined with the corresponding module settings, they “picks the right algorithm for each resolution based on whether Node.js will see an import or require” in emitted output. [2] - For package.json "exports" specifically: TypeScript’s Modules Reference states that when moduleResolution is set to node16, nodenext, or bundler (and resolvePackageJsonExports isn’t disabled), TypeScript “follows Node.js’s package.json "exports" spec when resolving” bare specifiers from a package directory. [3] - Relative import extension behavior: - TypeScript’s module resolution docs state bundler never requires file extensions on relative paths, but Node16/NodeNext do enforce Node ESM extension semantics. [2][4] - A concrete example from the (TypeScript module-resolution) reference: with Node16/NodeNext, an ESM import must include the file extension, e.g. import { x } from "./module.js" is valid, while import { x } from "./module" is an error. [4] - Conditional exports matching (types/import/require): - TypeScript always matches the "types" and "default" conditions (if present) when resolving through conditional "exports". [3] - It also matches versioned "types@{selector}" conditions according to the same rules as typesVersions. [3] - Practical difference between node16 vs nodenext: - The official TSConfig reference groups node16 and nodenext together as modern Node.js modes but doesn’t spell out a separate behavioral distinction in the snippets we found; the key behavioral distinctions that affect package.json exports in practice are shared: Node-like exports-following and relative-extension enforcement. [2][3][4] 3) moduleResolution: "bundler" (export maps supported, but relative-extension rules are relaxed) - TypeScript says bundler “supports package.json "imports" and "exports", but unlike the Node.js resolution modes, bundler never requires file extensions on relative paths in imports.” [2] - For package.json "exports" in the Node.js package sense: Typescript’s Modules Reference likewise says that when moduleResolution is bundler, and resolvePackageJsonExports isn’t disabled, TypeScript follows Node.js’s package.json "exports" spec for resolving from a node_modules lookup. [3] - Relative-extension behavior: - bundler never requires file extensions on relative imports. [2] - This is the main behavioral difference vs node16/nodenext for ESM consumers: Node16/NodeNext will error on extensionless relative imports under ESM-style rules, while bundler does not. [2][4] - TypeScript 6 also clarifies the intent: TypeScript can’t model a scenario where some dependencies are “bundled” and others are left as real external imports; it recommends using bundler resolution only for code paths you expect to be handled by a bundler/runtime consistently. [5] Summary (for ESM packages using package.json "exports") - "node10": legacy CommonJS-only model; not appropriate for modern ESM/exports behavior. [1] - "node16" / "nodenext": both follow Node’s conditional exports when resolving packages, and they enforce Node ESM relative import extensions (e.g. require.js in ESM-style relative imports). [3][2][4] - "bundler": also supports package.json "exports" during resolution, but it relaxes relative import extension requirements (extensionless relative imports are allowed). [2][3] If you tell me your specific scenario (consumer is Node ESM vs bundler like Vite, and an example exports map you’re using), I can say exactly which mode will accept/reject the imports you have.

Citations:


Use a modern ESM resolver instead of node10.

moduleResolution: "node10" models Node.js versions older than v10 and only supports CommonJS. It is inappropriate for ESM-only packages relying on modern package.json exports and conditional resolution. Use node16, nodenext (recommended for Node >=22), or bundler instead.

Suggested change
-        "moduleResolution": "node10",
+        "moduleResolution": "nodenext",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tsconfig.json` at line 7, The tsconfig.json currently sets
"moduleResolution": "node10", which forces legacy CommonJS-style resolution;
update the moduleResolution compiler option to a modern ESM-aware resolver (for
example "nodenext" or "node16"/"bundler" depending on your Node target) so
package.json exports and conditional resolution work correctly; open
tsconfig.json and replace the "moduleResolution" value from "node10" with the
chosen modern resolver and run a quick build to confirm no import resolution
regressions.

Comment thread tsdown.config.ts
tada5hi added 3 commits May 20, 2026 14:09
- type.ts: use `import type * as ts from 'typescript'` namespace pattern
  so the file stays valid under stricter moduleResolution modes (Copilot).
- file-path.ts: tighten the "already a js extension" check from substring
  match to a regex that respects glob brace expansions, so paths like
  `my-json.ts` are still transformable while `*.{ts,js}` is still
  recognised (CodeRabbit).
- tsdown.config.ts: only externalise `../` CLI imports whose resolved
  target actually leaves src/cli/, so internal upward references stay
  bundled into the CLI (CodeRabbit).
- package.json: add `"default": "./dist/index.mjs"` to exports so
  CJS-via-require(esm) consumers have an explicit fall-through condition
  (Copilot).
- migration-guide-v4.md: clarify that the typeorm@^1.0.0 peer-dep bump
  is a separate follow-up release (Copilot).
- Strip trailing whitespace from 9 source/test files left by ESLint
  --fix during the modernization (Copilot, editorconfig violation).

Filed #1374 for the broader SHA-pinning hardening that applies to all
.github/ workflow files, not just those touched here.
The lock committed in b85dcb9 was incomplete — missing the esbuild@0.28.0
sub-tree (peer of vitest's nested vite). A clean install adds 458 lines
and unblocks 'npm ci' on CI.
@tada5hi tada5hi merged commit 8df2109 into master May 20, 2026
3 checks passed
@tada5hi tada5hi deleted the feat/modernize-toolchain-v4 branch May 20, 2026 12:22
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