You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two hardening fixes for the v1 codemod discovered during a full audit of all 32 transforms.
Scope v1 transforms to typeorm imports
A number of v1 transforms previously rewrote any file matching their pattern, regardless of whether the file imported TypeORM. Examples:
datasource-sqlite-type / datasource-sqlite-options — any type: "sqlite", busyTimeout, or flags property got mutated (e.g. HTTP clients with flags, Cypress configs with type: "sqlite")
repository-exist — any .exist(...) call got renamed to .exists(...)
find-options-string-select / find-options-string-relations — any select: [...] or relations: [...] property got rewritten into object form
…and 12 more
All 17 affected transforms now bail out early via fileImportsFrom(root, j, "typeorm") — matching the pattern already used by datasource-sap, file-logger, and connection-options-reader.
Fixtures for each transform were updated to include a typeorm import so the tests still exercise the guarded path.
Skip .d.ts files
The codemod CLI passed extensions: "ts,tsx,js,jsx" with no ignorePattern default. Because .d.ts files match the .ts extension, jscodeshift was visiting ambient declaration files. Transforms that rename identifiers (e.g. connection-to-datasource renaming Connection → DataSource) would corrupt declaration files that re-export TypeORM types.
Added **/*.d.ts as a default ignore pattern. User-supplied --ignore patterns are merged with the default, not replaced.
Many v1 transforms now return undefined unless the file has an ESM import from "typeorm", but
fileImportsFrom only checks ImportDeclaration nodes. Because the CLI still scans js/jsx,
CommonJS (require("typeorm")) and TS import = require("typeorm") files will be silently skipped,
producing incomplete migrations.
+ if (!fileImportsFrom(root, j, "typeorm")) return undefined
Evidence
The new early-return guard is added in transforms (example: repository-exist) and depends on
fileImportsFrom. fileImportsFrom only matches ESM ImportDeclaration from the exact module
string, so it will not detect CommonJS require() or TS import-equals patterns. The runner still
includes js,jsx in its scanned extensions, so those files can be visited but will now be skipped
by the guarded transforms.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Transforms now gate execution on `fileImportsFrom(..., "typeorm")`, but `fileImportsFrom` only detects ESM `import` statements. This makes transforms skip CommonJS (`require("typeorm")`) and TS `import = require("typeorm")` files, even though the CLI scans `js/jsx`.
### Issue Context
The import-gating is used as a safety heuristic to prevent false positives, but it must recognize the module-loading syntaxes the codemod claims to scan.
### Fix Focus Areas
- packages/codemod/src/transforms/ast-helpers.ts[44-56]
- packages/codemod/src/cli/run-transforms.ts[106-113]
- packages/codemod/test/transforms/ast-helpers.test.ts[1-47]
### Suggested implementation notes
- Extend `fileImportsFrom` to also return true when it finds:
- `TSImportEqualsDeclaration` whose module reference is `require("typeorm")`
- `CallExpression` patterns like `require("typeorm")` (optionally only when assigned to a const/let)
- Add unit tests for `fileImportsFrom` covering ESM import, side-effect import, TS import-equals, and CommonJS require.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The CLI now always ignores **/*.d.ts and merges user --ignore patterns with defaults, which is
user-facing behavior. The codemod README documents --ignore but does not mention the new default
ignore behavior, so users may be confused when .d.ts files are skipped.
+ const ignorePattern = [...DEFAULT_IGNORE_PATTERNS, ...(ignore ?? [])]+
let result: Awaited<ReturnType<typeof jscodeshift>>
try {
result = await jscodeshift(transform, paths, {
Evidence
PR Compliance ID 2 requires documentation updates for user-facing changes. The PR introduces a
default **/*.d.ts ignore pattern and merges it with --ignore, but the codemod README’s
--ignore option documentation does not describe these defaults/merging semantics.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The codemod CLI now ignores `**/*.d.ts` by default and merges user-provided `--ignore` patterns with this default, but the user docs do not mention this behavior.
## Issue Context
Without documentation, users may assume `--ignore` fully controls ignored files and may be surprised that `.d.ts` files are always skipped.
## Fix Focus Areas
- packages/codemod/README.md[5-37]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
datasource-sqlite-type/datasource-sqlite-options now return early unless the file imports from
"typeorm", so they will not transform ormconfig.ts-style configs that export a plain options
object without any imports. This can leave sqlite-related settings (e.g., type: "sqlite",
busyTimeout, flags) unmigrated in a documented configuration approach.
+ // Only operate on files that import from typeorm — avoid mutating+ // unrelated `{ type: "sqlite" }` objects in other libraries' configs+ if (!fileImportsFrom(root, j, "typeorm")) return undefined+
Evidence
Both sqlite transforms now hard-require a typeormImportDeclaration via fileImportsFrom(...),
and otherwise return undefined (no transform). The TypeORM upgrade docs explicitly show an
ormconfig.ts example that exports a config object without importing TypeORM; such a file will
always fail fileImportsFrom(...) and therefore be skipped by these transforms.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`datasource-sqlite-type` and `datasource-sqlite-options` now bail out unless the file contains `import ... from "typeorm"`. This skips the documented `ormconfig.ts` pattern (plain `export default { ... }` with no imports), so sqlite migrations may not be applied where they are actually needed.
### Issue Context
The repo documentation for upgrading recommends using a TS/JS config file like `ormconfig.ts` that exports an object and does not necessarily import TypeORM. These files should still be eligible for sqlite option/type rewrites.
### Fix Focus Areas
- Update the guard condition to also allow known TypeORM config files (e.g., basename `ormconfig.ts` / `ormconfig.js`), or use a more precise AST scope (e.g., only mutate objects that are the argument to `new DataSource(...)`, plus allow `export default { ... }` in `ormconfig.*`).
- Ensure both sqlite transforms apply the same improved eligibility logic.
- packages/codemod/src/transforms/v1/datasource-sqlite-type.ts[8-28]
- packages/codemod/src/transforms/v1/datasource-sqlite-options.ts[9-38]
- packages/codemod/src/transforms/ast-helpers.ts[44-56]
- docs/docs/releases/1.0/02-upgrading-from-0.3.md[391-400]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
4. Decorator alias not migrated 🐞 Bug≡ Correctness
Description
forEachDecoratorObjectArg now restricts traversal to decorators whose callee is an Identifier
with a name in TYPEORM_COLUMN_DECORATORS, so column transforms will silently skip TypeORM column
decorators imported under an alias (e.g. import { Column as ORMColumn } ...; @ORMColumn(...)).
This can leave readonly/width/zerofill options un-migrated even though the file is
TypeORM-related.
+ if (decoratorNames) {+ const callee = decorator.expression.callee+ if (+ callee.type !== "Identifier" ||+ !decoratorNames.has(callee.name)+ ) {+ continue+ }+ }
Evidence
The new decoratorNames gate only accepts CallExpression.callee values that are Identifiers
whose .name is contained in the provided set; aliases necessarily change the identifier name and
will not match. Both column-readonly and column-width-zerofill pass TYPEORM_COLUMN_DECORATORS,
which only contains the canonical TypeORM decorator names, so aliased local names are excluded from
traversal.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`forEachDecoratorObjectArg(..., TYPEORM_COLUMN_DECORATORS)` only matches canonical decorator identifiers (e.g. `Column`) and will skip aliased imports (e.g. `Column as ORMColumn`), causing column transforms to miss required rewrites.
### Issue Context
This is introduced by the new `decoratorNames` filter requiring `callee.type === "Identifier"` and `decoratorNames.has(callee.name)`.
### Fix Focus Areas
- packages/codemod/src/transforms/ast-helpers.ts[117-175]
- packages/codemod/src/transforms/v1/column-readonly.ts[1-44]
- packages/codemod/src/transforms/v1/column-width-zerofill.ts[1-32]
### Implementation direction
- In the column transforms, derive a set of *local* decorator identifiers by scanning `ImportDeclaration`s from `"typeorm"` and adding `specifier.local.name` when `specifier.imported.name` is one of the canonical column decorator names.
- Pass that derived set into `forEachDecoratorObjectArg` instead of `TYPEORM_COLUMN_DECORATORS` directly.
- (Optional) Add a focused fixture demonstrating `import { Column as ORMColumn } from "typeorm"` to prevent regressions.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
5. Declaration extensions not ignored ☑ 🐞 Bug☼ Reliability
Description
DEFAULT_IGNORE_PATTERNS only excludes **/*.d.ts, so declaration files using .d.mts / .d.cts
are still eligible for codemod transforms. In projects that use those extensions,
identifier-renaming transforms can still rewrite declaration output despite the intent to skip
ambient declarations.
+// Patterns that should never be processed by any codemod transform.+// Ambient declarations (`.d.ts`) describe types consumers rely on — renaming+// identifiers inside them would silently corrupt published types.+export const DEFAULT_IGNORE_PATTERNS = ["**/*.d.ts"]++/**+ * Merges user-supplied `--ignore` patterns with the defaults. Defaults are+ * listed first so they apply alongside any user additions.+ */+export const buildIgnorePatterns = (userPatterns?: string[]): string[] => [+ ...DEFAULT_IGNORE_PATTERNS,+ ...(userPatterns ?? []),+]
Evidence
The CLI always builds and passes ignorePattern from DEFAULT_IGNORE_PATTERNS, which currently
only contains **/*.d.ts, and the usage text communicates that only *.d.ts is always excluded;
other TS declaration extensions are not covered by the default ignore list.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The codemod’s default ignore list only excludes `**/*.d.ts`. TypeScript projects can also have declaration files with `.d.mts` and `.d.cts`; these currently remain eligible for transforms.
### Issue Context
The CLI now always passes `ignorePattern` built from `DEFAULT_IGNORE_PATTERNS`, so expanding that list is the most reliable way to ensure all declaration outputs are skipped.
### Fix Focus Areas
- packages/codemod/src/cli/run-transforms.ts[26-38]
- packages/codemod/src/cli/print-usage.ts[17-23]
### Suggested change
- Update `DEFAULT_IGNORE_PATTERNS` to include:
- `**/*.d.ts`
- `**/*.d.mts`
- `**/*.d.cts`
- Update usage/README wording if needed to reflect the broader exclusion.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This PR adds fileImportsFrom(..., "typeorm") guards to many non-sqlite transforms (e.g.
column-readonly), so any file that uses TypeORM APIs but doesn’t directly import typeorm will
now be skipped. This is a behavior change beyond the PR’s stated sqlite-scoping, and it is not
documented in the README’s scoping guidance.
+ if (!fileImportsFrom(root, j, "typeorm")) return undefined+
Evidence
Non-sqlite transforms now bail out solely based on a direct typeorm import check. The helper only
checks for ImportDeclaration from exactly "typeorm", and the README’s scoping section mentions
reliance on type annotations but does not mention a per-file import requirement—so users may not
realize why some legitimate TypeORM call-sites are no longer being migrated.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Multiple non-sqlite transforms now require a direct `typeorm` import in the same file to run, which can reduce migration coverage for valid TypeORM usage (e.g., injected repositories/query builders) and is not reflected in the README scoping guidance.
### Issue Context
Some import-gating is clearly justified for transforms that match generic config properties (e.g. sqlite options), but broadening it to other transforms is a notable behavior change and should either be explicitly documented or limited to transforms where false positives are a known problem.
### Fix Focus Areas
- packages/codemod/src/transforms/v1/column-readonly.ts[8-14]
- packages/codemod/src/transforms/v1/repository-exist.ts[8-16]
- packages/codemod/README.md[51-54]
### Suggested implementation notes
- Option A (docs): Update README scoping section to explicitly note that many transforms run only in files that import from `typeorm`, and suggest adding `import "typeorm"` when needed.
- Option B (code): Narrow import-gating to the specific transforms where it is required to prevent known false positives, or introduce a CLI flag to disable import-gating for users who prefer maximum coverage.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
DEFAULT_IGNORE_PATTERNS is exported as a mutable array, so other modules/tests could accidentally
mutate it at runtime and change CLI behavior for subsequent runs. This makes the ignore baseline
fragile despite the local non-mutation test.
+// Patterns that should never be processed by any codemod transform.+// Ambient declarations (`.d.ts`) describe types consumers rely on — renaming+// identifiers inside them would silently corrupt published types.+export const DEFAULT_IGNORE_PATTERNS = ["**/*.d.ts"]++/**+ * Merges user-supplied `--ignore` patterns with the defaults. Defaults are+ * listed first so they apply alongside any user additions.+ */+export const buildIgnorePatterns = (userPatterns?: string[]): string[] => [+ ...DEFAULT_IGNORE_PATTERNS,+ ...(userPatterns ?? []),+]
Evidence
The default ignore list is exported as a plain array, which can be mutated by any importer;
buildIgnorePatterns then spreads from that shared reference, so mutations affect all future ignore
construction.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`DEFAULT_IGNORE_PATTERNS` is exported as a mutable array, allowing accidental external mutation and creating fragile global behavior.
### Issue Context
Even though `buildIgnorePatterns` does not mutate defaults, other imports can.
### Fix Focus Areas
- packages/codemod/src/cli/run-transforms.ts[26-38]
### Implementation direction
- Make the export immutable, e.g.:
- `export const DEFAULT_IGNORE_PATTERNS = Object.freeze(["**/*.d.ts"] as const)`
- and have `buildIgnorePatterns` return `string[]` via spreading into a new array.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
ⓘ The new review experience is currently in Beta. Learn more
pkuczynski
changed the title
fix(codemod): scope sqlite transforms to typeorm imports and skip .d.ts files
fix(codemod): scope v1 transforms to typeorm imports and skip .d.ts files
Apr 17, 2026
Good point — the .d.ts skip lives in the CLI, so the transform fixtures can't really cover it. Added a small unit test for the default ignore and the merge with --ignore in c075ad0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two hardening fixes for the v1 codemod discovered during a full audit of all 32 transforms.
Scope v1 transforms to typeorm imports
A number of v1 transforms previously rewrote any file matching their pattern, regardless of whether the file imported TypeORM. Examples:
datasource-sqlite-type/datasource-sqlite-options— anytype: "sqlite",busyTimeout, orflagsproperty got mutated (e.g. HTTP clients withflags, Cypress configs withtype: "sqlite")repository-exist— any.exist(...)call got renamed to.exists(...)find-options-string-select/find-options-string-relations— anyselect: [...]orrelations: [...]property got rewritten into object formAll 17 affected transforms now bail out early via
fileImportsFrom(root, j, "typeorm")— matching the pattern already used bydatasource-sap,file-logger, andconnection-options-reader.Fixtures for each transform were updated to include a
typeormimport so the tests still exercise the guarded path.Skip
.d.tsfilesThe codemod CLI passed
extensions: "ts,tsx,js,jsx"with noignorePatterndefault. Because.d.tsfiles match the.tsextension, jscodeshift was visiting ambient declaration files. Transforms that rename identifiers (e.g.connection-to-datasourcerenamingConnection→DataSource) would corrupt declaration files that re-export TypeORM types.Added
**/*.d.tsas a default ignore pattern. User-supplied--ignorepatterns are merged with the default, not replaced.