Summary
Since 9.3.0, @rdlabo/ionic-theme-ios26 cannot be installed with npm ≥ 12, and even when installation succeeds the package fails to load under ESM. Two separate problems, both in @rdlabo/ionic-theme-utils.
Last working version for us: 9.1.0. Reproduced on 9.3.4.
Problem 1 — ionic-theme-utils is not published to npm
9.3.x depends on it via a git URL:
"dependencies": {
"@rdlabo/ionic-theme-utils": "git+https://github.com/rdlabo-dev/ionic-theme-utils.git#e82be4389d9209750229f5fee990046b5b1217da"
}
The package itself is not on the registry:
$ npm view @rdlabo/ionic-theme-utils versions
npm error 404 Not Found - GET https://registry.npmjs.org/@rdlabo%2fionic-theme-utils
npm 12 refuses git dependencies by default:
npm error code EALLOWGIT
npm error Fetching packages of type "git" have been disabled
Two consequences:
- Consumers must set
allow-git=all in .npmrc. The value cannot be scoped to a single package (--allow-git=@rdlabo/ionic-theme-utils → Must be one of: all, none, root), and root does not apply because the git dependency sits inside a third-party package. So the only workaround relaxes git fetching for the entire dependency tree.
- The lockfile entry npm writes for the nested package has no
resolved and no integrity:
"node_modules/@rdlabo/ionic-theme-ios26/node_modules/@rdlabo/ionic-theme-utils": {
"version": "0.1.0"
}
The parent entry is complete (registry URL + sha512), so this looks like an npm bug in how it locks git dependencies of registry packages — but the effect is that the nested dependency has no verifiable source.
This also makes the failure environment-dependent and easy to miss: locally the built files may survive from an earlier install, so tests pass; CI starts from an empty tree and fails.
Problem 2 — extensionless relative import under "type": "module"
ionic-theme-utils sets "type": "module", but dist/index.js emits:
export { createIosTransitionAnimation, shadow, } from './transition/ios.transition';
ESM requires the full file extension. dist/transition/ios.transition.js does exist, but Node will not resolve it:
Error: Cannot find module '.../dist/transition/ios.transition'
imported from .../dist/index.js
Looks like tsc is run without moduleResolution settings that rewrite/preserve .js extensions for ESM output.
Note that the git repo ships no dist/ — it is built on install via prepare. So consumers additionally need install scripts to run for that dependency.
Suggested fixes
- Publish
@rdlabo/ionic-theme-utils to npm and depend on it by version. This removes the allow-git requirement, restores integrity hashing, and makes npm ci reproducible.
- Emit explicit
.js extensions in the compiled ESM output (e.g. write the import as ./transition/ios.transition.js in the source, since TypeScript preserves specifiers verbatim).
(1) alone does not fix (2) — both are needed.
Environment
- npm 12.0.2, Node 22 (local) and Node 26 (CI)
@ionic/react 9.0.3
- Failing version:
@rdlabo/ionic-theme-ios26@9.3.4
- Last known good:
9.1.0
Summary
Since
9.3.0,@rdlabo/ionic-theme-ios26cannot be installed with npm ≥ 12, and even when installation succeeds the package fails to load under ESM. Two separate problems, both in@rdlabo/ionic-theme-utils.Last working version for us:
9.1.0. Reproduced on9.3.4.Problem 1 —
ionic-theme-utilsis not published to npm9.3.xdepends on it via a git URL:The package itself is not on the registry:
npm 12 refuses git dependencies by default:
Two consequences:
allow-git=allin.npmrc. The value cannot be scoped to a single package (--allow-git=@rdlabo/ionic-theme-utils→Must be one of: all, none, root), androotdoes not apply because the git dependency sits inside a third-party package. So the only workaround relaxes git fetching for the entire dependency tree.resolvedand nointegrity:The parent entry is complete (registry URL + sha512), so this looks like an npm bug in how it locks git dependencies of registry packages — but the effect is that the nested dependency has no verifiable source.
This also makes the failure environment-dependent and easy to miss: locally the built files may survive from an earlier install, so tests pass; CI starts from an empty tree and fails.
Problem 2 — extensionless relative import under
"type": "module"ionic-theme-utilssets"type": "module", butdist/index.jsemits:ESM requires the full file extension.
dist/transition/ios.transition.jsdoes exist, but Node will not resolve it:Looks like
tscis run withoutmoduleResolutionsettings that rewrite/preserve.jsextensions for ESM output.Note that the git repo ships no
dist/— it is built on install viaprepare. So consumers additionally need install scripts to run for that dependency.Suggested fixes
@rdlabo/ionic-theme-utilsto npm and depend on it by version. This removes theallow-gitrequirement, restores integrity hashing, and makesnpm cireproducible..jsextensions in the compiled ESM output (e.g. write the import as./transition/ios.transition.jsin the source, since TypeScript preserves specifiers verbatim).(1) alone does not fix (2) — both are needed.
Environment
@ionic/react9.0.3@rdlabo/ionic-theme-ios26@9.3.49.1.0