Skip to content

9.3.x uninstallable with npm >=12: ionic-theme-utils is git-only and its ESM import lacks a file extension #217

Description

@Revisor01

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:

  1. 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.
  2. 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

  1. 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.
  2. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions