Skip to content

feat(migrate): add 'trokky migrate' to upgrade v0.1.x projects to v2 - #1

Merged
amenophis1er merged 3 commits into
mainfrom
foreman/trokky-cli-v0-1-to-v2-def3
Sep 8, 2026
Merged

amenophis1er merged 3 commits into
mainfrom
foreman/trokky-cli-v0-1-to-v2-def3

Conversation

@amenophis1er

@amenophis1er amenophis1er commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Turns the throwaway codemod used to migrate a real site by hand into a real, tested command. Production sites still have to be migrated with it.

Rewrites import/export specifiers, require() and dynamic import() across .ts/.tsx/.js/.mjs/.astro, updates package.json dependencies to the v2 packages, and reports what it could not fix.

Safety

Dry run is the default; --write refuses a dirty git tree unless --force, so there is always a diff to revert to. Review confirmed a dry run leaves a full copy of a real project byte-identical by tree hash, and that a second run is a provable no-op.

Rewriting is safe by construction, not by map ordering: a specifier matches only on equality or prefix + "/", so @trokky/core can never match inside @trokky/core-extras, nor @trokky/mail inside @trokky/mail-adapter-console.

Warnings

Three detectors, the third being the point of the exercise:

  1. Imports reaching into @trokky/*/src/…, which v2 does not ship.
  2. import.meta.env.TROKKY_API_URL in an Astro project — inlined at build time, so it must be set for the site build and not only the server process, or every media request 404s.
  3. Singleton divergence — a collection the structure calls a singleton whose schema does not declare it. This is a data-loss trap: trokky restore takes an id-preserving PUT only for schema-level singletons, so without the flag it regenerates the document ids and the structure points at documents that no longer exist.

What review caught

Two silent failures, both fixed in the last commit.

  • The singleton check only ran for six exact filenames. Mutation testing showed that moving a project's structure.ts to structure/index.ts took the output from 16 divergence warnings to zero — printing the same No warnings. as a genuinely clean project. Splitting a long structure across a directory is a normal thing to do. Any file containing a singleton entry now counts, and the report always states what it examined: Singleton check: N entries across M structure file(s), against K schema file(s).
  • A package.json with a one-line dependency block matched no section and came back byte-identical with no error — sources rewritten, manifest still asking for deleted packages, install failing later on the deploy host. Now cross-checked against the parsed JSON and refused with an actionable message.

Also reports stale @trokky pins in resolutions/overrides, which are deliberately not rewritten.

Verification

Exercised dry-run against real projects of both shapes (single package and monorepo), plus an end-to-end fixture: rewrite correctness, warning output, byte-identical dry runs and idempotent re-runs.

Note for monorepos: run it at the repo root so it sees every workspace, not at a single package directory.

go vet ./... and go test ./... green.

…packages

Rewrites @trokky/* specifiers (longest match first), updates package.json
dependencies in place, and reports internal imports, Astro build-time
TROKKY_API_URL inlining and structure/schema singleton divergence.
Dry-run by default; --write refuses a dirty git tree unless --force.
Both would have passed for success on a real site.

The singleton check only ran when the structure lived in a file named
structure.{ts,js,mjs} or trokky.config.{ts,js,mjs}. Anything else was never
fed to the check, and the report then printed the same "No warnings." line it
prints when a project is genuinely clean. Reviewed by mutation: moving IGF's
structure.ts to structure/index.ts and stripping the flags took the output from
16 divergence warnings to zero, with nothing to tell the operator that nothing
had been examined. Splitting a structure across a directory is not exotic —
FUCEC's is already 500+ lines. Any source file containing a singleton entry is
now treated as a structure source, and a file may be both a structure and a
schema source rather than only whichever the switch matched first.

The report now always states what was examined ("Singleton check: 24 entries
across 2 structure file(s), against 39 schema file(s)") and says so explicitly
when it found no entries at all. "No warnings" alone cannot be told apart from
"never looked", and only one of those is safe to restore over.

A package.json whose dependency block is written on one line matched no
section, so the file came back byte-identical with no error: sources rewritten,
manifest still asking for packages that no longer exist, install failing later
on the deploy host. The line scan is now cross-checked against the parsed JSON
and refuses the file with an actionable message instead of doing nothing.

Also reports stale @Trokky pins in resolutions/overrides, which are deliberately
not rewritten but must not pass unmentioned.

Verified against both real sites, dry run only: IGF 16 entries over 2 structure
files against 22 schemas, FUCEC 24 over 2 against 39, no divergence on either —
now demonstrably checked rather than merely silent.
@amenophis1er
amenophis1er merged commit b92acc4 into main Sep 8, 2026
1 check passed
@amenophis1er
amenophis1er deleted the foreman/trokky-cli-v0-1-to-v2-def3 branch September 8, 2026 17:52
amenophis1er added a commit that referenced this pull request Sep 9, 2026
)

* feat(migrate): add 'trokky migrate' to upgrade v0.1.x projects to v2 packages

Rewrites @trokky/* specifiers (longest match first), updates package.json
dependencies in place, and reports internal imports, Astro build-time
TROKKY_API_URL inlining and structure/schema singleton divergence.
Dry-run by default; --write refuses a dirty git tree unless --force.

* docs(readme): document trokky migrate, its mapping table and warnings

* fix(migrate): close two silent failures review found

Both would have passed for success on a real site.

The singleton check only ran when the structure lived in a file named
structure.{ts,js,mjs} or trokky.config.{ts,js,mjs}. Anything else was never
fed to the check, and the report then printed the same "No warnings." line it
prints when a project is genuinely clean. Reviewed by mutation: moving a real
project's structure.ts to structure/index.ts and stripping the flags took the
output from 16 divergence warnings to zero, with nothing to tell the operator
that nothing had been examined. Splitting a structure across a directory is not
exotic — one production project's is already 500+ lines. Any source file
containing a singleton entry is now treated as a structure source, and a file
may be both a structure and a schema source rather than only whichever the
switch matched first.

The report now always states what was examined ("Singleton check: 24 entries
across 2 structure file(s), against 39 schema file(s)") and says so explicitly
when it found no entries at all. "No warnings" alone cannot be told apart from
"never looked", and only one of those is safe to restore over.

A package.json whose dependency block is written on one line matched no
section, so the file came back byte-identical with no error: sources rewritten,
manifest still asking for packages that no longer exist, install failing later
on the deploy host. The line scan is now cross-checked against the parsed JSON
and refuses the file with an actionable message instead of doing nothing.

Also reports stale @Trokky pins in resolutions/overrides, which are deliberately
not rewritten but must not pass unmentioned.

Verified against two real sites, dry run only: 16 entries over 2 structure files
against 22 schemas on one, 24 over 2 against 39 on the other, no divergence on
either — now demonstrably checked rather than merely silent.

---------

Co-authored-by: Amen <2668333+amenophis1er@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant