Skip to content

[Bug]: ng add fails with "exports is not defined in ES module scope" — schematics are CommonJS under a "type": "module" package #20

Description

@AdamKITZ

Describe the bug

ng add @ngm-dev/mat-exp cannot run at all in 2.0.0 and 2.0.1.

The compiled schematics under schematics/ng-add/ are CommonJS (exports.default = ngAdd, require(...)), but the package's package.json declares "type": "module". There is no schematics/package.json containing {"type":"commonjs"} and the files do not use the .cjs extension, so Node loads them as ESM and they throw on the first line.

This is a regression introduced in 2.0.0:

Version "type" field schematics emitted as ng add
1.0.1 (absent → CommonJS) CommonJS works
2.0.0 module CommonJS fails
2.0.1 module CommonJS fails

Two related problems show up on the way to it:

  1. The failed install is not atomic and reports success. ng add installs the npm package before running the schematic. When the schematic dies, the dependency stays in package.json and node_modules while the stylesheet is never wired up — and the command still exits with code 0, so CI or any wrapper script reads it as a success.

  2. --components=all is rejected by the package's own schema. schema.json types components as "type": "array", but the implementation explicitly handles the string: buildIncludeBlock() has an if (components === 'all') branch. The schema's own description states that a single comma-separated entry is "handled gracefully with a warning rather than a hard schema-validation failure" — in practice it is a hard validation failure.

Reproduction steps

In any Angular 22 workspace that already has @angular/material installed and themed:

  1. npx ng add @ngm-dev/mat-exp --skip-confirmation --components=all
    → fails schema validation (problem 2 above), but the package is already installed and the command exits 0.
  2. npx ng generate @ngm-dev/mat-exp:ng-add --components=button,icon-button
    → now the factory is actually loaded, and it throws.

git status after step 1 shows package.json and package-lock.json modified, with the global stylesheet untouched.

Expected behavior

ng add @ngm-dev/mat-exp installs the package and wires the global stylesheet, as the README documents.

--components=all is accepted, since the implementation supports it and the schema description promises it.

If the schematic fails, the command exits non-zero and does not leave the dependency half-installed.

Actual behavior

Step 1:

Installing package
Schematic input does not validate against the Schema: {"components":"all","project":"..."}
Errors:

  Data path "/components" must be array.

(exit code 0, package installed, stylesheet untouched)

Step 2:

An unhandled exception occurred: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension
and '.../node_modules/@ngm-dev/mat-exp/package.json' contains "type": "module".
To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

(exit code 127)

@ngm-dev/mat-exp version

2.0.1

Angular version

22.1.4

Browser(s)

Chrome

Additional context

Node v24.15.0, npm 11.12.1, @angular/build 22.1.6, TypeScript 6.0.3.

Likely fix: ship schematics/package.json with {"type":"commonjs"}, or emit the schematics as .cjs, or compile them to ESM.

Separately: gsap is a peer dependency and is not installed by ng add, so even a successful install leaves the motion features non-functional until the user runs npm install gsap themselves. Worth calling out in the install guide if that is intended.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions