Skip to content

Commit 9f73e1f

Browse files
committed
chore: add some migrations info in Readme
1 parent 2cf250e commit 9f73e1f

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

  • projects/igniteui-angular/migrations
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Ignite UI for Angular — `ng update` Migrations
2+
3+
This directory hosts the migration schematics that run when consumers execute
4+
`ng update igniteui-angular`. Each `update-*` folder is a versioned migration
5+
listed in [`migration-collection.json`](./migration-collection.json) and
6+
implemented in `update-*/index.ts`. Shared helpers live in
7+
[`common/`](./common). The collection has `"encapsulation": true` so every
8+
migration is loaded in its own isolated CommonJS context by the Angular
9+
schematics tooling.
10+
11+
## Dynamic `@angular/compiler` import via `nativeImport`
12+
13+
`@angular/compiler` is an ES module. The migrations themselves are emitted as
14+
CommonJS, so they cannot statically `import` it; they have to use a runtime
15+
dynamic `import()`. To avoid TypeScript downleveling that dynamic call into a
16+
synchronous `require()` (which would crash on an ESM target), the call is
17+
routed through a tiny `.cjs` helper:
18+
19+
- [`common/import-helper.cts`](./common/import-helper.cts) — authored as
20+
a TypeScript CJS module. The dynamic `import()` is preserved in the emitted
21+
[`common/import-helper.cjs`](./common/import-helper.cjs) because the file's
22+
forced `.cjs` extension prevents the compiler from rewriting it.
23+
- Migrations call it via:
24+
```ts
25+
import { nativeImport } from 'igniteui-angular/migrations/common/import-helper.cjs';
26+
// ...
27+
const { HtmlParser } = await nativeImport<typeof import('@angular/compiler')>(
28+
'@angular/compiler'
29+
);
30+
```
31+
32+
### Why the bare `igniteui-angular/...` specifier
33+
34+
Schematics encapsulation (`"encapsulation": true` in
35+
[`migration-collection.json`](./migration-collection.json)) wraps every
36+
migration in a sandboxed module loader. Relative requires (`../common/...`)
37+
go through that wrapper and the dynamic `import()` ends up being intercepted
38+
and converted by the wrapper, defeating the purpose of the helper. A **bare
39+
package specifier** bypasses the wrapper because the wrapper only encapsulates
40+
the migration's own files, not requires that resolve to a real package.
41+
42+
This is the trick PR
43+
[#13712 — fix(migrations,ng-add): turn on encapsulation for devkit/schematics deps](https://github.com/IgniteUI/igniteui-angular/pull/13712)
44+
introduced when encapsulation was first enabled. Every migration that needs
45+
`@angular/compiler` follows the same pattern.
46+
47+
To keep TypeScript happy with the bare specifier at compile time,
48+
[`tsconfig.json`](./tsconfig.json) maps it back to the source:
49+
50+
```jsonc
51+
"paths": {
52+
"igniteui-angular/*": ["../*"],
53+
"@infragistics/igniteui-angular/*": ["../*"]
54+
}
55+
```
56+
57+
At consumer install time the specifier resolves naturally through their
58+
`node_modules/igniteui-angular/migrations/common/import-helper.cjs`.
59+
60+
## Running migration tests locally
61+
62+
`npm run test:schematics` compiles the migrations with
63+
[`tsconfig.spec.json`](./tsconfig.spec.json) into `dist/igniteui-angular/...`
64+
and runs the compiled `*.spec.js` files through Jasmine. In this repo there is
65+
no `node_modules/igniteui-angular` (the library is the workspace itself), so
66+
the bare `igniteui-angular/migrations/common/import-helper.cjs` specifier
67+
would not resolve at runtime.
68+
69+
[`tsconfig-paths-bootstrap.js`](./tsconfig-paths-bootstrap.js) fixes that. It
70+
is loaded with `node --require` before Jasmine starts and installs a runtime
71+
path map (via the `tsconfig-paths` package) that points
72+
`igniteui-angular/*` at `dist/igniteui-angular/*`. The bootstrap deliberately
73+
does **not** read [`tsconfig.json`](./tsconfig.json) because:
74+
75+
- the compile-time map targets source under `../*` (i.e. `.ts` / `.cts`),
76+
which Jasmine cannot execute;
77+
- the runtime map must point at the compiled output in `dist/`.
78+
79+
The wiring in [`package.json`](../../../package.json) looks like:
80+
81+
```text
82+
node -r ./projects/igniteui-angular/migrations/tsconfig-paths-bootstrap.js \
83+
./node_modules/jasmine/bin/jasmine.js \
84+
"dist/igniteui-angular/migrations/**/*.spec.js" \
85+
"dist/igniteui-angular/schematics/**/*.spec.js"
86+
```
87+
88+
This setup is internal to the repo's test runner; published migrations are
89+
unaffected and rely on the consumer's regular `node_modules` resolution.

0 commit comments

Comments
 (0)