ember.nvp 0.6.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +17 -2
- package/.release-plan.json +29 -5
- package/CHANGELOG.md +73 -0
- package/package.json +3 -2
- package/packages/build-tooling-utils/README.md +37 -0
- package/packages/build-tooling-utils/index.ts +2 -0
- package/packages/build-tooling-utils/package.json +42 -0
- package/packages/build-tooling-utils/rolldown.config.js +18 -0
- package/packages/build-tooling-utils/src/extensions.ts +18 -0
- package/packages/build-tooling-utils/src/maybe-babel.ts +146 -0
- package/packages/rolldown/README.md +120 -0
- package/packages/rolldown/index.ts +60 -0
- package/packages/rolldown/package.json +59 -0
- package/packages/rolldown/rolldown.config.js +21 -0
- package/packages/rolldown/src/babel.ts +136 -0
- package/packages/rolldown/src/config.ts +50 -0
- package/packages/rolldown/src/externals.ts +83 -0
- package/packages/rolldown/src/isolated-declarations.ts +65 -0
- package/packages/rolldown/src/transform.ts +162 -0
- package/packages/vite/README.md +7 -21
- package/packages/vite/index.ts +1 -1
- package/packages/vite/package.json +4 -6
- package/packages/vite/src/ember.ts +129 -15
- package/packages/vite/src/test-html.ts +86 -0
- package/src/bases/minimal-app/files/app/router.ts +1 -0
- package/src/bases/minimal-app/files/tsconfig.json +1 -0
- package/src/bases/minimal-app/index.js +2 -2
- package/src/bases/minimal-library/files/README.md +41 -0
- package/src/bases/minimal-library/files/package.json +49 -0
- package/src/bases/minimal-library/files/tsconfig.json +10 -0
- package/src/bases/minimal-library/files/tsdown.config.js +7 -0
- package/src/bases/minimal-library/index.js +158 -2
- package/src/cli/index.js +21 -2
- package/src/cli/questions/layers.js +5 -2
- package/src/cli/questions/project-type.js +0 -5
- package/src/layers/are-the-types-wrong/index.js +74 -0
- package/src/layers/git/files/gitignore +14 -1
- package/src/layers/git/index.js +6 -5
- package/src/layers/github-actions/index.js +12 -8
- package/src/layers/index.js +1 -1
- package/src/layers/inspector-support/index.js +101 -0
- package/src/layers/prettier/files/.prettierignore +4 -0
- package/src/layers/publint/index.js +68 -0
- package/src/layers/qunit/files/tests/unit/macros-test.ts +2 -2
- package/src/layers/qunit/index.js +107 -7
- package/src/layers/qunit/library-files/config/test/babel.config.js +41 -0
- package/src/layers/qunit/library-files/config/test/testem.cjs +26 -0
- package/src/layers/qunit/library-files/tests/test-helper.ts +36 -0
- package/src/layers/qunit/library-files/tests/unit/.gitkeep +0 -0
- package/src/layers/qunit/library-files/vite.config.mjs +6 -0
- package/src/layers/typescript/index.js +43 -7
- package/src/layers/vitest/files/vitest.config.mjs +11 -11
- package/src/layers/vitest/index.js +70 -32
- package/src/utils/babel.js +9 -6
- package/src/utils/fs.js +44 -3
- package/src/utils/inspector-support.js +196 -0
- package/src/utils/npm.js +21 -7
- package/src/utils/remove-types.js +5 -0
- package/src/utils/rewrite-imports.js +157 -0
- package/src/utils/tsdown-config.js +85 -0
- package/src/utils/types.ts +5 -1
- package/test/ember.nvp/base-library.test.ts +236 -0
- package/test/ember.nvp/generator-replace-or-update.test.ts +2 -3
- package/test/ember.nvp/inspector-support.test.ts +179 -0
- package/test/ember.nvp/layer-inspector-support.test.ts +69 -0
- package/test/ember.nvp/layer-publish-checks.test.ts +109 -0
- package/test/ember.nvp/layer-qunit.test.ts +381 -16
- package/test/ember.nvp/layer-vitest.test.ts +250 -0
- package/test/ember.nvp/layers.test.ts +16 -0
- package/test/ember.nvp/library-src-fixtures.ts +81 -0
- package/test/ember.nvp/permutations/app-1.test.ts +3 -0
- package/test/ember.nvp/permutations/app-2.test.ts +3 -0
- package/test/ember.nvp/permutations/library-1.test.ts +3 -0
- package/test/ember.nvp/permutations/library-2.test.ts +3 -0
- package/test/ember.nvp/permutations/shared.ts +239 -0
- package/test/ember.nvp/rewrite-imports.test.ts +235 -0
- package/test/test-helpers/permutate.test.ts +17 -0
- package/test/test-helpers.ts +46 -8
- package/tsconfig.json +1 -0
- package/packages/vite/src/maybe-babel.ts +0 -219
- package/src/layers/qunit/files/run-tests.mjs +0 -30
- package/src/layers/vitest/files/tests/test-helper.ts +0 -5
- package/test/ember.nvp/permutations.test.ts +0 -200
- /package/src/{layers/vitest/files/tests/integration/.gitkeep → bases/minimal-library/files/src/index.ts} +0 -0
- /package/src/layers/{vitest/files/tests/unit → qunit/library-files/tests/rendering}/.gitkeep +0 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -29,13 +29,28 @@ jobs:
|
|
|
29
29
|
- run: pnpm lint
|
|
30
30
|
|
|
31
31
|
node_tests:
|
|
32
|
-
name: "Node Tests"
|
|
32
|
+
name: "Node Tests (${{ matrix.slice.name }})"
|
|
33
33
|
runs-on: ubuntu-latest
|
|
34
34
|
timeout-minutes: 15
|
|
35
35
|
|
|
36
|
+
strategy:
|
|
37
|
+
fail-fast: false
|
|
38
|
+
matrix:
|
|
39
|
+
slice:
|
|
40
|
+
- name: app permutations 1/2
|
|
41
|
+
args: test/ember.nvp/permutations/app-1.test.ts
|
|
42
|
+
- name: app permutations 2/2
|
|
43
|
+
args: test/ember.nvp/permutations/app-2.test.ts
|
|
44
|
+
- name: library permutations 1/2
|
|
45
|
+
args: test/ember.nvp/permutations/library-1.test.ts
|
|
46
|
+
- name: library permutations 2/2
|
|
47
|
+
args: test/ember.nvp/permutations/library-2.test.ts
|
|
48
|
+
- name: everything else
|
|
49
|
+
args: --exclude 'test/ember.nvp/permutations/**'
|
|
50
|
+
|
|
36
51
|
steps:
|
|
37
52
|
- uses: wyvox/action@v1
|
|
38
53
|
- run: |
|
|
39
54
|
git config --global user.name "ci"
|
|
40
55
|
git config --global user.email "non@none.none"
|
|
41
|
-
pnpm test:node
|
|
56
|
+
pnpm test:node ${{ matrix.slice.args }}
|
package/.release-plan.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"solution": {
|
|
3
3
|
"ember.nvp": {
|
|
4
|
-
"impact": "
|
|
5
|
-
"oldVersion": "0.
|
|
6
|
-
"newVersion": "0.
|
|
4
|
+
"impact": "major",
|
|
5
|
+
"oldVersion": "0.7.0",
|
|
6
|
+
"newVersion": "1.0.0",
|
|
7
7
|
"tagName": "latest",
|
|
8
8
|
"constraints": [
|
|
9
|
+
{
|
|
10
|
+
"impact": "major",
|
|
11
|
+
"reason": "Appears in changelog section :boom: Breaking Change"
|
|
12
|
+
},
|
|
9
13
|
{
|
|
10
14
|
"impact": "minor",
|
|
11
15
|
"reason": "Appears in changelog section :rocket: Enhancement"
|
|
@@ -13,9 +17,29 @@
|
|
|
13
17
|
],
|
|
14
18
|
"pkgJSONPath": "./package.json"
|
|
15
19
|
},
|
|
20
|
+
"@nullvoxpopuli/ember-build-tooling-utils": {
|
|
21
|
+
"oldVersion": "1.1.0"
|
|
22
|
+
},
|
|
23
|
+
"@nullvoxpopuli/ember-rolldown": {
|
|
24
|
+
"impact": "major",
|
|
25
|
+
"oldVersion": "1.1.0",
|
|
26
|
+
"newVersion": "2.0.0",
|
|
27
|
+
"tagName": "latest",
|
|
28
|
+
"constraints": [
|
|
29
|
+
{
|
|
30
|
+
"impact": "major",
|
|
31
|
+
"reason": "Appears in changelog section :boom: Breaking Change"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"impact": "minor",
|
|
35
|
+
"reason": "Appears in changelog section :rocket: Enhancement"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"pkgJSONPath": "./packages/rolldown/package.json"
|
|
39
|
+
},
|
|
16
40
|
"@nullvoxpopuli/ember-vite": {
|
|
17
|
-
"oldVersion": "1.0
|
|
41
|
+
"oldVersion": "1.1.0"
|
|
18
42
|
}
|
|
19
43
|
},
|
|
20
|
-
"description": "## Release (2026-07-
|
|
44
|
+
"description": "## Release (2026-07-18)\n\n* ember.nvp 1.0.0 (major)\n* @nullvoxpopuli/ember-rolldown 2.0.0 (major)\n\n#### :boom: Breaking Change\n* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#86](https://github.com/NullVoxPopuli/ember.nvp/pull/86) Remove defineConfig ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :rocket: Enhancement\n* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#84](https://github.com/NullVoxPopuli/ember.nvp/pull/84) Create config plugin for rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### Committers: 1\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
|
|
21
45
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Release (2026-07-18)
|
|
4
|
+
|
|
5
|
+
* ember.nvp 1.0.0 (major)
|
|
6
|
+
* @nullvoxpopuli/ember-rolldown 2.0.0 (major)
|
|
7
|
+
|
|
8
|
+
#### :boom: Breaking Change
|
|
9
|
+
* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
10
|
+
* [#86](https://github.com/NullVoxPopuli/ember.nvp/pull/86) Remove defineConfig ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
11
|
+
|
|
12
|
+
#### :rocket: Enhancement
|
|
13
|
+
* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
14
|
+
* [#84](https://github.com/NullVoxPopuli/ember.nvp/pull/84) Create config plugin for rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
15
|
+
|
|
16
|
+
#### Committers: 1
|
|
17
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
18
|
+
|
|
19
|
+
## Release (2026-07-17)
|
|
20
|
+
|
|
21
|
+
* ember.nvp 0.7.0 (minor)
|
|
22
|
+
* @nullvoxpopuli/ember-build-tooling-utils 1.1.0 (minor)
|
|
23
|
+
* @nullvoxpopuli/ember-rolldown 1.1.0 (minor)
|
|
24
|
+
* @nullvoxpopuli/ember-vite 1.1.0 (minor)
|
|
25
|
+
|
|
26
|
+
#### :rocket: Enhancement
|
|
27
|
+
* `ember.nvp`
|
|
28
|
+
* [#78](https://github.com/NullVoxPopuli/ember.nvp/pull/78) publint and are-the-types-wrong layers ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
29
|
+
* [#77](https://github.com/NullVoxPopuli/ember.nvp/pull/77) TypeScript is the default for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
30
|
+
* [#73](https://github.com/NullVoxPopuli/ember.nvp/pull/73) Implement the vitest layer for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
31
|
+
* [#71](https://github.com/NullVoxPopuli/ember.nvp/pull/71) Add inspector-support layer (Ember Inspector wiring via ember-estree codemod) ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
32
|
+
* `@nullvoxpopuli/ember-vite`, `ember.nvp`
|
|
33
|
+
* [#72](https://github.com/NullVoxPopuli/ember.nvp/pull/72) qunit layer: support libraries (tests without any index.html) ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
34
|
+
* [#61](https://github.com/NullVoxPopuli/ember.nvp/pull/61) Update maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
35
|
+
* `ember.nvp`, `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`
|
|
36
|
+
* [#63](https://github.com/NullVoxPopuli/ember.nvp/pull/63) Library support via rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
37
|
+
* [#66](https://github.com/NullVoxPopuli/ember.nvp/pull/66) Lean on node 24: RegExp.escape, import.meta.dirname, fs.rm ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
38
|
+
* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
39
|
+
* [#67](https://github.com/NullVoxPopuli/ember.nvp/pull/67) Export our own defineConfig, preloaded with ember library defaults ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
40
|
+
* [#64](https://github.com/NullVoxPopuli/ember.nvp/pull/64) Make both library flavors build: isolated declarations, hbs targetFormat, real tests ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
41
|
+
* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
42
|
+
* [#65](https://github.com/NullVoxPopuli/ember.nvp/pull/65) No generated babel.config.js; drop the plugin packages' dist build ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
43
|
+
* `@nullvoxpopuli/ember-vite`
|
|
44
|
+
* [#62](https://github.com/NullVoxPopuli/ember.nvp/pull/62) Cleanup maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
45
|
+
|
|
46
|
+
#### :bug: Bug Fix
|
|
47
|
+
* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
48
|
+
* [#83](https://github.com/NullVoxPopuli/ember.nvp/pull/83) Can't publish TS, build with rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
49
|
+
* `@nullvoxpopuli/ember-rolldown`
|
|
50
|
+
* [#82](https://github.com/NullVoxPopuli/ember.nvp/pull/82) Fix watching in the rolldown plugin ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
51
|
+
* `ember.nvp`
|
|
52
|
+
* [#79](https://github.com/NullVoxPopuli/ember.nvp/pull/79) The library base generates an empty src ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
53
|
+
* [#74](https://github.com/NullVoxPopuli/ember.nvp/pull/74) Generated TS libraries type check: drop allowJs, load ember/glint types ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
54
|
+
* [#70](https://github.com/NullVoxPopuli/ember.nvp/pull/70) Library template is private; generated libraries are publishable ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
55
|
+
* [#58](https://github.com/NullVoxPopuli/ember.nvp/pull/58) Fix lint:types in generated qunit apps: import #app/app.ts with extension ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
56
|
+
* [#59](https://github.com/NullVoxPopuli/ember.nvp/pull/59) Make freshly generated apps pass their own pnpm lint ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
57
|
+
* `@nullvoxpopuli/ember-vite`, `ember.nvp`
|
|
58
|
+
* [#75](https://github.com/NullVoxPopuli/ember.nvp/pull/75) packages/vite: built-in babel fallback when no config file exists ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
59
|
+
|
|
60
|
+
#### :memo: Documentation
|
|
61
|
+
* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
|
|
62
|
+
* [#68](https://github.com/NullVoxPopuli/ember.nvp/pull/68) Docs pass: outcome-focused, timeless READMEs and comments ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
63
|
+
|
|
64
|
+
#### :house: Internal
|
|
65
|
+
* `ember.nvp`
|
|
66
|
+
* [#81](https://github.com/NullVoxPopuli/ember.nvp/pull/81) Split the app permutations CI slice in two ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
67
|
+
* [#80](https://github.com/NullVoxPopuli/ember.nvp/pull/80) Split the app and library permutations CI slices in two ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
68
|
+
* [#76](https://github.com/NullVoxPopuli/ember.nvp/pull/76) Shard CI: per-base permutation files, parallel Node Tests jobs ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
69
|
+
* `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`, `ember.nvp`
|
|
70
|
+
* [#69](https://github.com/NullVoxPopuli/ember.nvp/pull/69) Remove comments from config files (generated and in READMEs) ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
71
|
+
|
|
72
|
+
#### Committers: 2
|
|
73
|
+
- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
74
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
75
|
+
|
|
3
76
|
## Release (2026-07-04)
|
|
4
77
|
|
|
5
78
|
* ember.nvp 0.6.0 (minor)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember.nvp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "ember project generator, alternative to the official blueprints, but more modern -- hopefully one day to upstream back in to ember-cli / official blueprints",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"content-tag": "^4.2.0",
|
|
25
25
|
"diff": "^9.0.0",
|
|
26
26
|
"ember-apply": "^2.17.0",
|
|
27
|
+
"ember-estree": "^0.7.0",
|
|
28
|
+
"enhanced-resolve": "^5.24.2",
|
|
27
29
|
"execa": "^9.6.1",
|
|
28
30
|
"latest-version": "^9.0.0",
|
|
29
31
|
"package-name-regex": "^5.0.0"
|
|
@@ -39,7 +41,6 @@
|
|
|
39
41
|
"prettier": "^3.8.3",
|
|
40
42
|
"prettier-plugin-ember-template-tag": "^2.1.6",
|
|
41
43
|
"release-plan": "^0.18.0",
|
|
42
|
-
"rimraf": "^6.1.3",
|
|
43
44
|
"typescript": "^5.9.3",
|
|
44
45
|
"vite": "^8.0.14",
|
|
45
46
|
"vitest": "^4.1.7"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# `@nullvoxpopuli/ember-build-tooling-utils`
|
|
2
|
+
|
|
3
|
+
Shared build tooling for the `@nullvoxpopuli` ember meta-plugins
|
|
4
|
+
([`@nullvoxpopuli/ember-vite`](../vite) and
|
|
5
|
+
[`@nullvoxpopuli/ember-rolldown`](../rolldown)).
|
|
6
|
+
|
|
7
|
+
It's intentionally bundler-agnostic (no `vite`/`rolldown` dependency) so both
|
|
8
|
+
meta-plugins can consume the same logic.
|
|
9
|
+
|
|
10
|
+
Requires node 24+, and — since this package ships TypeScript source — a
|
|
11
|
+
modern TypeScript when type-checking: 6+ with `lib` covering `es2025` (e.g.
|
|
12
|
+
`esnext`).
|
|
13
|
+
|
|
14
|
+
## Exports
|
|
15
|
+
|
|
16
|
+
### `maybeBabel(options?)`
|
|
17
|
+
|
|
18
|
+
A babel plugin (`@rollup/plugin-babel`) wrapped in a
|
|
19
|
+
[`@rolldown/pluginutils`](https://github.com/rolldown/rolldown) filter so babel
|
|
20
|
+
runs **only** on files that actually need it:
|
|
21
|
+
|
|
22
|
+
- template-tag files (`.gts`/`.gjs`)
|
|
23
|
+
- files importing template/macro modules (`@ember/template-compiler`,
|
|
24
|
+
`@embroider/macros`, …)
|
|
25
|
+
- local (non-`node_modules`) code using decorators
|
|
26
|
+
|
|
27
|
+
Everything else skips babel and is handled by the bundler's native (oxc)
|
|
28
|
+
transform. The point: don't buy rolldown/oxc speed and then give it all back by
|
|
29
|
+
routing every module through babel.
|
|
30
|
+
|
|
31
|
+
`options` extends `@rollup/plugin-babel`'s options, plus a `filter.include`
|
|
32
|
+
(`imports` / `code`) to opt additional files in.
|
|
33
|
+
|
|
34
|
+
### `extensions`
|
|
35
|
+
|
|
36
|
+
The list of file extensions ember source can be authored in. Mirrors
|
|
37
|
+
embroider's canonical list (see `extensions.ts` for details).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nullvoxpopuli/ember-build-tooling-utils",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Shared build tooling for @nullvoxpopuli ember meta-plugins: maybeBabel (run babel only where needed) and the ember file extensions list.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"main": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"ember",
|
|
12
|
+
"babel",
|
|
13
|
+
"rolldown",
|
|
14
|
+
"vite",
|
|
15
|
+
"meta plugin",
|
|
16
|
+
"build"
|
|
17
|
+
],
|
|
18
|
+
"author": "NullVoxPopuli",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/NullVoxPopuli/ember.nvp",
|
|
23
|
+
"directory": "packages/build-tooling-utils"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "rolldown --config",
|
|
27
|
+
"prepack": "pnpm build"
|
|
28
|
+
},
|
|
29
|
+
"packageManager": "pnpm@10.28.0",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@babel/core": "^7.28.10",
|
|
32
|
+
"@rolldown/pluginutils": "^1.0.1",
|
|
33
|
+
"@rollup/plugin-babel": "^7.1.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">= 24"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"rolldown": "^1.1.2",
|
|
40
|
+
"typescript": "^6.0.3"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from "rolldown";
|
|
2
|
+
|
|
3
|
+
import manifest from "./package.json" with { type: "json" };
|
|
4
|
+
|
|
5
|
+
const deps = Object.keys(manifest.dependencies || {});
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
input: "index.ts",
|
|
9
|
+
output: {
|
|
10
|
+
format: "esm",
|
|
11
|
+
file: "dist/index.js",
|
|
12
|
+
codeSplitting: false,
|
|
13
|
+
},
|
|
14
|
+
external(id) {
|
|
15
|
+
if (id.startsWith("node:")) return true;
|
|
16
|
+
if (deps.some((dep) => id.startsWith(dep))) return true;
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The file extensions ember source can be authored in.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors embroider's canonical list, which is only exported from
|
|
5
|
+
* `@embroider/vite` (its `src/ember.ts`) — copied rather than depended on so
|
|
6
|
+
* this shared tooling stays bundler-agnostic. Keep in sync.
|
|
7
|
+
*/
|
|
8
|
+
export const extensions = [
|
|
9
|
+
".mjs",
|
|
10
|
+
".gjs",
|
|
11
|
+
".js",
|
|
12
|
+
".mts",
|
|
13
|
+
".gts",
|
|
14
|
+
".ts",
|
|
15
|
+
".hbs",
|
|
16
|
+
".hbs.js",
|
|
17
|
+
".json",
|
|
18
|
+
];
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasons we have to have babel
|
|
3
|
+
* - decorators
|
|
4
|
+
* - ember-concurrency
|
|
5
|
+
* - scoped-css
|
|
6
|
+
* - template compilation optimization
|
|
7
|
+
*
|
|
8
|
+
* `maybeBabel` runs babel ONLY on the files that actually need it (template-tag
|
|
9
|
+
* files, files importing template/macro modules, and local code using
|
|
10
|
+
* decorators). Everything else skips babel so the bundler's native (oxc)
|
|
11
|
+
* transform handles it -- the whole point being to keep the fast path fast and
|
|
12
|
+
* not re-slow the build by sending every file through babel.
|
|
13
|
+
*
|
|
14
|
+
* This is shared between the vite (app) and rolldown/tsdown (library)
|
|
15
|
+
* meta-plugins.
|
|
16
|
+
*/
|
|
17
|
+
import { and, code, id, include, not, or } from "@rolldown/pluginutils";
|
|
18
|
+
import { babel } from "@rollup/plugin-babel";
|
|
19
|
+
import type { RollupBabelInputPluginOptions } from "@rollup/plugin-babel";
|
|
20
|
+
|
|
21
|
+
import { extensions } from "./extensions.ts";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* If a file imports any of these, it needs babel (templates, macros, and a
|
|
25
|
+
* couple of addons that ship decorator-adjacent runtime code).
|
|
26
|
+
*/
|
|
27
|
+
const babelRequiredImports = [
|
|
28
|
+
// Templates
|
|
29
|
+
// (old non template() form)
|
|
30
|
+
"@ember/template-compiler",
|
|
31
|
+
"@ember/template-compilation",
|
|
32
|
+
|
|
33
|
+
// Legacy templates (hbs / loose mode)
|
|
34
|
+
"ember-cli-htmlbars",
|
|
35
|
+
"ember-cli-htmlbars-inline-precompile",
|
|
36
|
+
"htmlbars-inline-precompile",
|
|
37
|
+
|
|
38
|
+
// Build Macros
|
|
39
|
+
// (since import.meta.env is not available in all environments)
|
|
40
|
+
"@embroider/macros",
|
|
41
|
+
"@glimmer/env",
|
|
42
|
+
"@ember/debug",
|
|
43
|
+
"@ember/application/deprecations",
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const decoratorRegex = /(?<![\w'"`])(?<!\*\s+)(?<!\/\/[^\n]*)(?<!\/\*[^\n]*)@\w+/;
|
|
47
|
+
// └────┬─────┘└───┬───┘└──────┬──────┘└──────┬──────┘└┬─┘
|
|
48
|
+
// │ │ │ │ │
|
|
49
|
+
// │ │ │ │ └── the `@decorator`
|
|
50
|
+
// │ │ │ └──────── not inside a single-line block comment (`/* @dec */`)
|
|
51
|
+
// │ │ └─────────────────────── not on a `//` line comment
|
|
52
|
+
// │ └─────────────────────────────────── not a JSDoc tag, even with multiple spaces (`* @param`)
|
|
53
|
+
// └────────────────────────────────────────────── not mid-identifier or inside a string
|
|
54
|
+
|
|
55
|
+
const nodeModulesPattern = /\/node_modules\//;
|
|
56
|
+
|
|
57
|
+
const extensionRegExp = new RegExp(
|
|
58
|
+
`(${extensions
|
|
59
|
+
.filter((ext) => ext !== ".json")
|
|
60
|
+
.map(RegExp.escape)
|
|
61
|
+
.join("|")})(\\?.*)?(#.*)?$`,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
type Options = Omit<RollupBabelInputPluginOptions, "filter"> & {
|
|
65
|
+
filter?: {
|
|
66
|
+
include: {
|
|
67
|
+
/**
|
|
68
|
+
* If any additional (custom) plugins are provided, a pattern
|
|
69
|
+
* should be provided that detects their usage
|
|
70
|
+
*
|
|
71
|
+
* for example, to also run babel on files that import from ember-concurrency
|
|
72
|
+
* ```js
|
|
73
|
+
* {
|
|
74
|
+
* code: ['ember-concurrency'],
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
imports: string[];
|
|
79
|
+
/**
|
|
80
|
+
* If any additional (custom) plugins are provided, a pattern
|
|
81
|
+
* should be provided that detects their usage
|
|
82
|
+
*
|
|
83
|
+
* for example, to also run babel on files that use polyfilled APIs,
|
|
84
|
+
* or use the "formatMessage" technique for translations
|
|
85
|
+
* ```js
|
|
86
|
+
* {
|
|
87
|
+
* code: ['myPolyfilledAPICall(', /\bintl\.formatMessage\b/],
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
code: (string | RegExp)[];
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export function maybeBabel(userOptions: Options = {}) {
|
|
97
|
+
const { filter, ...options } = userOptions;
|
|
98
|
+
|
|
99
|
+
const plugin = babel({
|
|
100
|
+
babelHelpers: "runtime",
|
|
101
|
+
extensions,
|
|
102
|
+
skipPreflightCheck: true,
|
|
103
|
+
...options,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const importsRegex = new RegExp(
|
|
107
|
+
babelRequiredImports
|
|
108
|
+
.concat(filter?.include?.imports ?? [])
|
|
109
|
+
.map(RegExp.escape)
|
|
110
|
+
.join("|"),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const maybeBabelFilter = [
|
|
114
|
+
include(
|
|
115
|
+
and(
|
|
116
|
+
// is one of the babel-supported extensions
|
|
117
|
+
id(extensionRegExp),
|
|
118
|
+
or(
|
|
119
|
+
// always run gts and gjs through babel
|
|
120
|
+
id(/\.gts$/),
|
|
121
|
+
id(/\.gjs$/),
|
|
122
|
+
// imports one of the modules above
|
|
123
|
+
code(importsRegex),
|
|
124
|
+
// (a common way to do translations)
|
|
125
|
+
// local app code using a decorator
|
|
126
|
+
// NOTE: maybeBabel requires that all libraries compile away their decorators
|
|
127
|
+
//
|
|
128
|
+
// TODO: what do we do when native decorators start shipping?
|
|
129
|
+
// (ignore decorator transforming entirely?)
|
|
130
|
+
and(not(id(nodeModulesPattern)), code(decoratorRegex)),
|
|
131
|
+
// user provided additional opt-ins to the regex here
|
|
132
|
+
...(filter?.include?.code?.map((x) => code(x)) ?? []),
|
|
133
|
+
),
|
|
134
|
+
),
|
|
135
|
+
),
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
// types are incorrect
|
|
139
|
+
(plugin.transform as { filter: unknown }).filter = maybeBabelFilter;
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
...plugin,
|
|
143
|
+
enforce: "pre",
|
|
144
|
+
name: "nullvoxpopuli:babel",
|
|
145
|
+
} as ReturnType<typeof babel>;
|
|
146
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# `@nullvoxpopuli/ember-rolldown`
|
|
2
|
+
|
|
3
|
+
A batteries-included meta-plugin for building Ember v2 libraries (addons) with
|
|
4
|
+
[rolldown](https://rolldown.rs/) — or [tsdown](https://tsdown.dev/), which is
|
|
5
|
+
built on top of rolldown and also emits `.d.ts` files.
|
|
6
|
+
|
|
7
|
+
It compiles `.gts`/`.gjs` and template-tag (`<template>`) source into
|
|
8
|
+
publishable output, so a single `ember()` call replaces the usual stack of
|
|
9
|
+
`@embroider/*` externals handling, content-tag preprocessing, and babel wiring.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm add --save-dev @nullvoxpopuli/ember-rolldown
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires node 24+, and — since these packages ship TypeScript source — a
|
|
18
|
+
modern TypeScript when type-checking: 6+ with `lib` covering `es2025` (e.g.
|
|
19
|
+
`esnext`).
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Import `defineConfig` from the bundler you're using — `tsdown` or `rolldown` —
|
|
24
|
+
so it carries that tool's own config types; `@nullvoxpopuli/ember-rolldown`
|
|
25
|
+
provides `ember()` (the defaults travel with the plugin, not `defineConfig`).
|
|
26
|
+
|
|
27
|
+
In your `tsdown.config.js` (recommended — emits declarations):
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
import { defineConfig } from "tsdown";
|
|
31
|
+
import { ember } from "@nullvoxpopuli/ember-rolldown";
|
|
32
|
+
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
entry: ["./src/index.ts"],
|
|
35
|
+
plugins: [ember()],
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This builds your entry to `dist/*.js` and `dist/*.d.ts` with sourcemaps,
|
|
40
|
+
cleaning `dist/` between builds and leaving the ember virtual packages to the
|
|
41
|
+
consuming app. You choose the `entry` and `plugins`; any tsdown option you
|
|
42
|
+
pass wins.
|
|
43
|
+
|
|
44
|
+
Or in a plain `rolldown.config.js`:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { defineConfig } from "rolldown";
|
|
48
|
+
import { ember } from "@nullvoxpopuli/ember-rolldown";
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
input: ["src/index.ts"],
|
|
52
|
+
plugins: [ember()],
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A `babel.config.js` is optional. Without one, `ember()` compiles templates
|
|
57
|
+
(to `precompileTemplate`), decorators (via
|
|
58
|
+
[decorator-transforms](https://github.com/ef4/decorator-transforms)), and
|
|
59
|
+
TypeScript; with one, your config runs instead.
|
|
60
|
+
|
|
61
|
+
### Declarations
|
|
62
|
+
|
|
63
|
+
Declarations are emitted with isolated declarations — the only declaration
|
|
64
|
+
pipeline that can see `<template>` (`.gts`/`.gjs`) modules, which exist only
|
|
65
|
+
inside the bundler's module graph. Your `tsconfig.json` must enable it
|
|
66
|
+
(`ember()` errors otherwise):
|
|
67
|
+
|
|
68
|
+
```jsonc
|
|
69
|
+
{
|
|
70
|
+
"compilerOptions": {
|
|
71
|
+
"isolatedDeclarations": true,
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Isolated declarations means every exported value carries an explicit type
|
|
77
|
+
annotation. For template-only components:
|
|
78
|
+
|
|
79
|
+
```gts
|
|
80
|
+
import type { TOC } from "@ember/component/template-only";
|
|
81
|
+
|
|
82
|
+
export const Badge: TOC<BadgeSignature> = <template>...</template>;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## What `ember()` does
|
|
86
|
+
|
|
87
|
+
`ember()` returns an array of rolldown plugins:
|
|
88
|
+
|
|
89
|
+
- **`emberIsolatedDeclarations()`** — errors when a `tsconfig.json` is present
|
|
90
|
+
without `isolatedDeclarations: true`.
|
|
91
|
+
- **`emberExternals()`** — keeps your `dependencies`, `peerDependencies`, and
|
|
92
|
+
the ember virtual packages (e.g. `@ember/component`, `@glimmer/tracking`, the
|
|
93
|
+
template compiler) external, so the consuming app resolves them.
|
|
94
|
+
- **`emberTransform()`** — preprocesses `<template>` via
|
|
95
|
+
[content-tag](https://github.com/embroider-build/content-tag) and maps
|
|
96
|
+
`.gts`/`.gjs` to `.ts`/`.js` so rolldown understands them. Also rewrites
|
|
97
|
+
`.gts` specifiers in emitted `.d.ts` files.
|
|
98
|
+
- **`emberBabel()`** — runs babel with `babelHelpers: "bundled"`, but only on
|
|
99
|
+
the files that actually need it (template-tag, decorators, template imports);
|
|
100
|
+
everything else stays on rolldown's fast native (oxc) transform.
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
ember({
|
|
106
|
+
babel: {
|
|
107
|
+
configFile: "./babel.config.js",
|
|
108
|
+
babelHelpers: "bundled",
|
|
109
|
+
plugins: [],
|
|
110
|
+
filter: { include: { imports: ["ember-concurrency"], code: [] } },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Each option is documented on `BabelOptions`.
|
|
116
|
+
|
|
117
|
+
## Credit
|
|
118
|
+
|
|
119
|
+
The `emberExternals` and `emberTransform` plugins are derived from
|
|
120
|
+
[embroider-build/embroider#2658](https://github.com/embroider-build/embroider/pull/2658).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Plugin } from "rolldown";
|
|
2
|
+
|
|
3
|
+
import { emberBabel, type BabelOptions } from "./src/babel.ts";
|
|
4
|
+
import { emberConfig } from "./src/config.ts";
|
|
5
|
+
import { emberExternals } from "./src/externals.ts";
|
|
6
|
+
import { emberIsolatedDeclarations } from "./src/isolated-declarations.ts";
|
|
7
|
+
import { emberTransform } from "./src/transform.ts";
|
|
8
|
+
|
|
9
|
+
interface Config {
|
|
10
|
+
/**
|
|
11
|
+
* Options for the babel step; see `BabelOptions`.
|
|
12
|
+
*/
|
|
13
|
+
babel?: BabelOptions;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A batteries-included plugin for building Ember v2 libraries (addons) with
|
|
18
|
+
* rolldown (or tsdown, which is built on rolldown).
|
|
19
|
+
*
|
|
20
|
+
* It bundles everything needed to compile `.gts`/`.gjs` and template-tag
|
|
21
|
+
* (`<template>`) source into publishable output:
|
|
22
|
+
*
|
|
23
|
+
* - `emberConfig()` — applies sensible tsdown defaults for a library build
|
|
24
|
+
* (sourcemaps, `clean`, `dts`, `.js`/`.d.ts` extensions, quiet logging);
|
|
25
|
+
* anything you set explicitly still wins.
|
|
26
|
+
* - `emberIsolatedDeclarations()` — errors when a tsconfig.json is present
|
|
27
|
+
* without `isolatedDeclarations: true` (required: it is the only
|
|
28
|
+
* declaration pipeline that can see compiled template-tag modules).
|
|
29
|
+
* - `emberExternals()` — keeps your dependencies, peerDependencies, and the
|
|
30
|
+
* ember virtual packages external, so consuming apps resolve them.
|
|
31
|
+
* - `emberTransform()` — preprocesses `<template>` via content-tag and maps
|
|
32
|
+
* `.gts`/`.gjs` to `.ts`/`.js` so rolldown can understand them.
|
|
33
|
+
* - `emberBabel()` — runs babel (template compilation, decorators, type
|
|
34
|
+
* stripping) with `babelHelpers: "bundled"`, but only on the files that
|
|
35
|
+
* actually need it (via `maybeBabel`); everything else stays on the fast
|
|
36
|
+
* native transform. The library's own `babel.config.js` is used when it
|
|
37
|
+
* exists; no config file is required.
|
|
38
|
+
*
|
|
39
|
+
* Usage in `tsdown.config.js` (import `defineConfig` from `tsdown` — or from
|
|
40
|
+
* `rolldown` for a `rolldown.config.js` — so it carries the correct types):
|
|
41
|
+
*
|
|
42
|
+
* ```js
|
|
43
|
+
* import { defineConfig } from "tsdown";
|
|
44
|
+
* import { ember } from "@nullvoxpopuli/ember-rolldown";
|
|
45
|
+
*
|
|
46
|
+
* export default defineConfig({
|
|
47
|
+
* entry: ["./src/index.ts"],
|
|
48
|
+
* plugins: [ember()],
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function ember(config: Config = {}): Plugin[] {
|
|
53
|
+
return [
|
|
54
|
+
emberConfig(),
|
|
55
|
+
emberIsolatedDeclarations(),
|
|
56
|
+
emberExternals(),
|
|
57
|
+
emberTransform(),
|
|
58
|
+
emberBabel(config.babel),
|
|
59
|
+
];
|
|
60
|
+
}
|