Codemods
This page documents the @archibald/codemod package — a CLI wrapper around jscodeshift used to apply automated code transformations when upgrading between Archibald major versions.
Requires Node.js >= 24
Quick start
Run the interactive CLI (will prompt for files and transform):
pnpx @archibald/codemod
Run a specific codemod on a path (or glob):
pnpx @archibald/codemod src/components "logger"
Dry-run to preview changes without modifying files:
pnpx @archibald/codemod src "commerce" --dry
Run all available codemods:
pnpx @archibald/codemod . "all"
CLI options
--force— ignore the "git must be clean" safety check--dry— do not write changes (preview only)--print— print transformed files to stdout--explicit-require— pass explicit require option to jscodeshift--jscodeshift <options...>— extra options forwarded to jscodeshift
The CLI will also prompt for missing arguments if you call it without parameters.
The versioned catalog
Codemods live in a versioned catalog under packages/codemod/codemods/, one folder per major version (v6 … v9) and one folder per codemod inside it:
codemods/
v9/
manifest.json # { "order": [...] } — run order for this major
platform-tenant-names/
meta.json # name, description, kind, engine, idempotent, postNotes, …
transform.js # the jscodeshift transform
__testfixtures__/ # <case>.input.tsx / <case>.output.tsx
The registry (packages/codemod/src/registry.ts) discovers the catalog from disk; the codemod's target version and transform path are derived from the folder, so they cannot drift. The interactive prompt lists every codemod labelled [vN] <description>, where vN is the major it migrates to.
Every codemod declares a kind in its meta.json:
transform— rewrites source code (AST).config— rewrites JSON config files (e.g.archibald.json).detect— report-only: it flags sites that need manual migration (file and line) and never writes. Use these as a checklist while upgrading.
Many codemods also carry postNotes — manual follow-up steps printed after the codemod runs. Read them: they describe the cases the codemod intentionally does not rewrite.
Codemods per major
v6
| Codemod | Kind | Description |
|---|---|---|
data-hook-aliases | transform | Rename the removed useClient/useFetchValue aliases to useDataClient/useFetchStatus |
if-rename | transform | Rename the removed IF component alias to If |
login-options-object | transform | Wrap the positional suspense argument of useLogin/useLogOut/useIsLoggedIn in an options object |
use-mutate-suspend-option | transform | Drop the removed suspendAfterFirstLoad option from useMutate calls |
renderer-abort-milliseconds | transform | Convert the removed Renderer option abortAfterSeconds to abortAfterMSeconds |
default-middleware | detect | Flag the removed default middleware (createMiddleware without a type, DefaultMiddleware types) |
data-request-reset | detect | Flag .reset() calls in files using the data layer (DataRequest.reset is now delete) |
hmr-helper | detect | Flag imports of the removed HMRHelper namespace |
cms-helper | detect | Flag imports of the removed CMSHelper |
v7
| Codemod | Kind | Description |
|---|---|---|
logger | transform | Move the logger symbols out of @archibald/core into @archibald/log and adapt createLogger to its options object |
config | transform | Replace deprecated import of Config from @archibald/core |
create-request | transform | Replace deprecated createEntity with createRequest |
use-mutation | transform | Replace deprecated useMutate with useMutation |
preload-translation | transform | Replace deprecated usePreload with usePreloadTranslation |
rename-provider | transform | Rename legacy *Provider/*DataProvider to the *ClientProvider naming schema |
testbed-wrapper | transform | Rename register/clearDefaultCustomWrapper to register/clearDefaultWrapper |
testbed-custom-wrapper | transform | Adapt the removed customWrapper testing option to the wrapper component signature |
preview-wrapper | detect | Flag deprecated useSmartEdit imports (use getPreviewWrapperComponent instead) |
capitalize | transform | Rename upperFirst to capitalize when imported from @archibald/helpers |
cli-build-imports | transform | Move build and compiler helpers from @archibald/cli to @archibald/build |
throw-on-error-config | config | Rename mutateThrowOnError to throwOnError in archibald.json |
app-client-hydrate | detect | Flag AppClient.rendered usage (replaced by the inverted hydrate) |
v8
| Codemod | Kind | Description |
|---|---|---|
commerce | transform | Replace Commerce imports with nested subpackage imports and rename them |
facet-imports | transform | Move facet schema and type imports from @archibald/storefront to @archibald/search |
search-imports | transform | Move search response/suggestion interfaces from @archibald/storefront to @archibald/search |
search-suggestions | transform | Rename the removed useSearchSuggestions hook to useSearchQuerySuggestions |
use-session-client | transform | Rename the removed useSession hook to useSessionClient |
use-is-logged-in-args | transform | Drop the removed arguments of useIsLoggedIn |
hybris-service-import | transform | Import HybrisService from @archibald/server instead of @archibald/auth |
compiler-config-parameters | transform | Rename the removed WebpackConfigParameters type to CompilerConfigParameters |
optimization-compiler-config | config | Move archibald.json experimental.compiler to optimization.compiler |
search-suggestions-implementations | detect | Flag getSearchSuggestions/onSearchSuggestions definitions and calls (use the QuerySuggestions variants) |
auth-removed-exports | detect | Flag Hybris auth providers that moved from @archibald/auth to @archibald/commerce |
commerce-product-adapter | detect | Flag the removed CommerceProductAdapter (use ProductAdapter from @archibald/product) |
v9
| Codemod | Kind | Description |
|---|---|---|
tsconfig-module-resolution | config | Switch the per-platform client/server tsconfigs to bundler module resolution so exports-only packages (Storybook 9/10) resolve |
storybook-core-imports | transform | Move the Storybook 8 packages folded into core to their storybook/* subpaths |
storybook-define-config | transform | Replace a hand-written .storybook/main.ts config object with defineConfig() from @archibald/storybook/config |
auth-provider-logout-tokens | transform | Migrate UserAuthProvider.logout to ApiServiceTokens: the declared parameter type and the token strings its callers pass |
auth-oidc-signatures | detect | Flag SessionClient<User> single-generic and AuthService.logout(token) sites (OIDC rework) |
auth-credentials-shape | detect | Flag AuthCredentials usage — the [key: string]: any index signature is gone in v9 |
product-reviews-shape | detect | Flag useReviews usage (reviews response is now { reviews: [] }, was an array) |
platform-tenant-names | transform | Wrap direct reads of project.platforms/project.tenants with platformNames()/tenantNames() (entries are InheritanceEntry now, not string) |
Shadowing config migration
shadowing-config is a native transform (its subject is archibald.json, not a JS/TS module, so jscodeshift cannot carry it — the CLI dispatches it directly). It moves project.theming to project.shadowing, rewriting each { test, replace } pair as a path template and folding rules that only differ by a single path segment into one enumerated rule:
pnpx @archibald/codemod . "shadowing-config"
Run on a directory it finds every archibald.json beneath it (ignoring node_modules). Files without a project.theming block are skipped and reported.
Safety & formatting
- By default the CLI checks that the Git working tree is clean. Use
--forceto override. - The tool ignores
node_modulesand supports TS/JS/JSX/TSX files. - If
prettieris installed, changed files will be formatted automatically after transforms.
Adding new codemods
- Create a folder
codemods/v<major>/<name>/(the folder name becomes the codemod's name and determines the version it belongs to). - Add a
meta.jsonwithname(must equal the folder name),description,kind(transform|config|detect),engine(jscodeshift),idempotent, and optionallypostNotesfor manual follow-up steps. - Add the
transform.js(a jscodeshift-compatible transform;detectcodemods report findings instead of rewriting). - Add
__testfixtures__/with<case>.input.tsx/<case>.output.tsxpairs. - Register the name in the major's
manifest.jsonorderarray — that array defines the run order.
Tips
- Always run with
--dryfirst on large changes or unfamiliar transforms. - Commit or stash changes before running transforms when not using
--force. - Pay attention to the
postNotesa codemod prints — they list what still needs a manual review.