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:
-
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.
-
--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:
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.
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.
Describe the bug
ng add @ngm-dev/mat-expcannot 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'spackage.jsondeclares"type": "module". There is noschematics/package.jsoncontaining{"type":"commonjs"}and the files do not use the.cjsextension, so Node loads them as ESM and they throw on the first line.This is a regression introduced in 2.0.0:
"type"fieldng addmodulemoduleTwo related problems show up on the way to it:
The failed install is not atomic and reports success.
ng addinstalls the npm package before running the schematic. When the schematic dies, the dependency stays inpackage.jsonandnode_moduleswhile 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.--components=allis rejected by the package's own schema.schema.jsontypescomponentsas"type": "array", but the implementation explicitly handles the string:buildIncludeBlock()has anif (components === 'all')branch. The schema's owndescriptionstates 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/materialinstalled and themed: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.
npx ng generate @ngm-dev/mat-exp:ng-add --components=button,icon-button→ now the factory is actually loaded, and it throws.
git statusafter step 1 showspackage.jsonandpackage-lock.jsonmodified, with the global stylesheet untouched.Expected behavior
ng add @ngm-dev/mat-expinstalls the package and wires the global stylesheet, as the README documents.--components=allis 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:
(exit code 0, package installed, stylesheet untouched)
Step 2:
(exit code 127)
@ngm-dev/mat-expversion2.0.1
Angular version
22.1.4
Browser(s)
Chrome
Additional context
Node v24.15.0, npm 11.12.1,
@angular/build22.1.6, TypeScript 6.0.3.Likely fix: ship
schematics/package.jsonwith{"type":"commonjs"}, or emit the schematics as.cjs, or compile them to ESM.Separately:
gsapis a peer dependency and is not installed byng add, so even a successful install leaves the motion features non-functional until the user runsnpm install gsapthemselves. Worth calling out in the install guide if that is intended.