ember.nvp 0.6.0 → 0.7.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.
Files changed (85) hide show
  1. package/.github/workflows/ci.yml +17 -2
  2. package/.release-plan.json +88 -4
  3. package/CHANGELOG.md +57 -0
  4. package/package.json +3 -2
  5. package/packages/build-tooling-utils/README.md +37 -0
  6. package/packages/build-tooling-utils/index.ts +2 -0
  7. package/packages/build-tooling-utils/package.json +42 -0
  8. package/packages/build-tooling-utils/rolldown.config.js +18 -0
  9. package/packages/build-tooling-utils/src/extensions.ts +18 -0
  10. package/packages/build-tooling-utils/src/maybe-babel.ts +146 -0
  11. package/packages/rolldown/README.md +115 -0
  12. package/packages/rolldown/index.ts +56 -0
  13. package/packages/rolldown/package.json +59 -0
  14. package/packages/rolldown/rolldown.config.js +21 -0
  15. package/packages/rolldown/src/babel.ts +136 -0
  16. package/packages/rolldown/src/define-config.ts +32 -0
  17. package/packages/rolldown/src/externals.ts +83 -0
  18. package/packages/rolldown/src/isolated-declarations.ts +65 -0
  19. package/packages/rolldown/src/transform.ts +162 -0
  20. package/packages/vite/README.md +7 -21
  21. package/packages/vite/index.ts +1 -1
  22. package/packages/vite/package.json +4 -6
  23. package/packages/vite/src/ember.ts +129 -15
  24. package/packages/vite/src/test-html.ts +86 -0
  25. package/src/bases/minimal-app/files/app/router.ts +1 -0
  26. package/src/bases/minimal-app/files/tsconfig.json +1 -0
  27. package/src/bases/minimal-app/index.js +2 -2
  28. package/src/bases/minimal-library/files/README.md +41 -0
  29. package/src/bases/minimal-library/files/package.json +49 -0
  30. package/src/bases/minimal-library/files/tsconfig.json +10 -0
  31. package/src/bases/minimal-library/files/tsdown.config.js +6 -0
  32. package/src/bases/minimal-library/index.js +158 -2
  33. package/src/cli/index.js +21 -2
  34. package/src/cli/questions/layers.js +5 -2
  35. package/src/cli/questions/project-type.js +0 -5
  36. package/src/layers/are-the-types-wrong/index.js +74 -0
  37. package/src/layers/git/files/gitignore +14 -1
  38. package/src/layers/git/index.js +6 -5
  39. package/src/layers/github-actions/index.js +12 -8
  40. package/src/layers/index.js +1 -1
  41. package/src/layers/inspector-support/index.js +101 -0
  42. package/src/layers/prettier/files/.prettierignore +4 -0
  43. package/src/layers/publint/index.js +68 -0
  44. package/src/layers/qunit/files/tests/unit/macros-test.ts +2 -2
  45. package/src/layers/qunit/index.js +107 -7
  46. package/src/layers/qunit/library-files/config/test/babel.config.js +41 -0
  47. package/src/layers/qunit/library-files/config/test/testem.cjs +26 -0
  48. package/src/layers/qunit/library-files/tests/test-helper.ts +36 -0
  49. package/src/layers/qunit/library-files/tests/unit/.gitkeep +0 -0
  50. package/src/layers/qunit/library-files/vite.config.mjs +6 -0
  51. package/src/layers/typescript/index.js +43 -7
  52. package/src/layers/vitest/files/vitest.config.mjs +11 -11
  53. package/src/layers/vitest/index.js +70 -32
  54. package/src/utils/babel.js +9 -6
  55. package/src/utils/fs.js +44 -3
  56. package/src/utils/inspector-support.js +196 -0
  57. package/src/utils/npm.js +21 -7
  58. package/src/utils/remove-types.js +5 -0
  59. package/src/utils/rewrite-imports.js +157 -0
  60. package/src/utils/tsdown-config.js +85 -0
  61. package/src/utils/types.ts +5 -1
  62. package/test/ember.nvp/base-library.test.ts +232 -0
  63. package/test/ember.nvp/generator-replace-or-update.test.ts +2 -3
  64. package/test/ember.nvp/inspector-support.test.ts +179 -0
  65. package/test/ember.nvp/layer-inspector-support.test.ts +69 -0
  66. package/test/ember.nvp/layer-publish-checks.test.ts +103 -0
  67. package/test/ember.nvp/layer-qunit.test.ts +376 -15
  68. package/test/ember.nvp/layer-vitest.test.ts +250 -0
  69. package/test/ember.nvp/layers.test.ts +16 -0
  70. package/test/ember.nvp/library-src-fixtures.ts +81 -0
  71. package/test/ember.nvp/permutations/app-1.test.ts +3 -0
  72. package/test/ember.nvp/permutations/app-2.test.ts +3 -0
  73. package/test/ember.nvp/permutations/library-1.test.ts +3 -0
  74. package/test/ember.nvp/permutations/library-2.test.ts +3 -0
  75. package/test/ember.nvp/permutations/shared.ts +239 -0
  76. package/test/ember.nvp/rewrite-imports.test.ts +235 -0
  77. package/test/test-helpers/permutate.test.ts +17 -0
  78. package/test/test-helpers.ts +20 -7
  79. package/tsconfig.json +1 -0
  80. package/packages/vite/src/maybe-babel.ts +0 -219
  81. package/src/layers/qunit/files/run-tests.mjs +0 -30
  82. package/src/layers/vitest/files/tests/test-helper.ts +0 -5
  83. package/test/ember.nvp/permutations.test.ts +0 -200
  84. /package/src/{layers/vitest/files/tests/integration/.gitkeep → bases/minimal-library/files/src/index.ts} +0 -0
  85. /package/src/layers/{vitest/files/tests/unit → qunit/library-files/tests/rendering}/.gitkeep +0 -0
@@ -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 }}
@@ -2,20 +2,104 @@
2
2
  "solution": {
3
3
  "ember.nvp": {
4
4
  "impact": "minor",
5
- "oldVersion": "0.5.0",
6
- "newVersion": "0.6.0",
5
+ "oldVersion": "0.6.0",
6
+ "newVersion": "0.7.0",
7
7
  "tagName": "latest",
8
8
  "constraints": [
9
9
  {
10
10
  "impact": "minor",
11
11
  "reason": "Appears in changelog section :rocket: Enhancement"
12
+ },
13
+ {
14
+ "impact": "patch",
15
+ "reason": "Appears in changelog section :bug: Bug Fix"
16
+ },
17
+ {
18
+ "impact": "patch",
19
+ "reason": "Appears in changelog section :memo: Documentation"
20
+ },
21
+ {
22
+ "impact": "patch",
23
+ "reason": "Appears in changelog section :house: Internal"
12
24
  }
13
25
  ],
14
26
  "pkgJSONPath": "./package.json"
15
27
  },
28
+ "@nullvoxpopuli/ember-build-tooling-utils": {
29
+ "impact": "minor",
30
+ "oldVersion": "1.0.0",
31
+ "newVersion": "1.1.0",
32
+ "tagName": "latest",
33
+ "constraints": [
34
+ {
35
+ "impact": "minor",
36
+ "reason": "Appears in changelog section :rocket: Enhancement"
37
+ },
38
+ {
39
+ "impact": "patch",
40
+ "reason": "Appears in changelog section :bug: Bug Fix"
41
+ },
42
+ {
43
+ "impact": "patch",
44
+ "reason": "Appears in changelog section :memo: Documentation"
45
+ }
46
+ ],
47
+ "pkgJSONPath": "./packages/build-tooling-utils/package.json"
48
+ },
49
+ "@nullvoxpopuli/ember-rolldown": {
50
+ "impact": "minor",
51
+ "oldVersion": "1.0.0",
52
+ "newVersion": "1.1.0",
53
+ "tagName": "latest",
54
+ "constraints": [
55
+ {
56
+ "impact": "patch",
57
+ "reason": "Has dependency `workspace:*` on @nullvoxpopuli/ember-build-tooling-utils"
58
+ },
59
+ {
60
+ "impact": "minor",
61
+ "reason": "Appears in changelog section :rocket: Enhancement"
62
+ },
63
+ {
64
+ "impact": "patch",
65
+ "reason": "Appears in changelog section :bug: Bug Fix"
66
+ },
67
+ {
68
+ "impact": "patch",
69
+ "reason": "Appears in changelog section :memo: Documentation"
70
+ },
71
+ {
72
+ "impact": "patch",
73
+ "reason": "Appears in changelog section :house: Internal"
74
+ }
75
+ ],
76
+ "pkgJSONPath": "./packages/rolldown/package.json"
77
+ },
16
78
  "@nullvoxpopuli/ember-vite": {
17
- "oldVersion": "1.0.3"
79
+ "impact": "minor",
80
+ "oldVersion": "1.0.3",
81
+ "newVersion": "1.1.0",
82
+ "tagName": "latest",
83
+ "constraints": [
84
+ {
85
+ "impact": "minor",
86
+ "reason": "Appears in changelog section :rocket: Enhancement"
87
+ },
88
+ {
89
+ "impact": "patch",
90
+ "reason": "Has dependency `workspace:*` on @nullvoxpopuli/ember-build-tooling-utils"
91
+ },
92
+ {
93
+ "impact": "patch",
94
+ "reason": "Appears in changelog section :bug: Bug Fix"
95
+ },
96
+ {
97
+ "impact": "patch",
98
+ "reason": "Appears in changelog section :house: Internal"
99
+ }
100
+ ],
101
+ "pkgJSONPath": "./packages/vite/package.json"
18
102
  }
19
103
  },
20
- "description": "## Release (2026-07-04)\n\n* ember.nvp 0.6.0 (minor)\n\n#### :rocket: Enhancement\n* `ember.nvp`\n * [#56](https://github.com/NullVoxPopuli/ember.nvp/pull/56) Stage all generation in a copy-on-write overlay; confirm before writing ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n\n#### Committers: 1\n- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n"
104
+ "description": "## Release (2026-07-17)\n\n* ember.nvp 0.7.0 (minor)\n* @nullvoxpopuli/ember-build-tooling-utils 1.1.0 (minor)\n* @nullvoxpopuli/ember-rolldown 1.1.0 (minor)\n* @nullvoxpopuli/ember-vite 1.1.0 (minor)\n\n#### :rocket: Enhancement\n* `ember.nvp`\n * [#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))\n * [#77](https://github.com/NullVoxPopuli/ember.nvp/pull/77) TypeScript is the default for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n * [#73](https://github.com/NullVoxPopuli/ember.nvp/pull/73) Implement the vitest layer for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n * [#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))\n* `@nullvoxpopuli/ember-vite`, `ember.nvp`\n * [#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))\n * [#61](https://github.com/NullVoxPopuli/ember.nvp/pull/61) Update maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n* `ember.nvp`, `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`\n * [#63](https://github.com/NullVoxPopuli/ember.nvp/pull/63) Library support via rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#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))\n* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#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))\n * [#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))\n* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#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))\n* `@nullvoxpopuli/ember-vite`\n * [#62](https://github.com/NullVoxPopuli/ember.nvp/pull/62) Cleanup maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :bug: Bug Fix\n* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#83](https://github.com/NullVoxPopuli/ember.nvp/pull/83) Can't publish TS, build with rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n* `@nullvoxpopuli/ember-rolldown`\n * [#82](https://github.com/NullVoxPopuli/ember.nvp/pull/82) Fix watching in the rolldown plugin ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n* `ember.nvp`\n * [#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))\n * [#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))\n * [#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))\n * [#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))\n * [#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))\n* `@nullvoxpopuli/ember-vite`, `ember.nvp`\n * [#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))\n\n#### :memo: Documentation\n* `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#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))\n\n#### :house: Internal\n* `ember.nvp`\n * [#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))\n * [#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))\n * [#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))\n* `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`, `ember.nvp`\n * [#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))\n\n#### Committers: 2\n- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
21
105
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## Release (2026-07-17)
4
+
5
+ * ember.nvp 0.7.0 (minor)
6
+ * @nullvoxpopuli/ember-build-tooling-utils 1.1.0 (minor)
7
+ * @nullvoxpopuli/ember-rolldown 1.1.0 (minor)
8
+ * @nullvoxpopuli/ember-vite 1.1.0 (minor)
9
+
10
+ #### :rocket: Enhancement
11
+ * `ember.nvp`
12
+ * [#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))
13
+ * [#77](https://github.com/NullVoxPopuli/ember.nvp/pull/77) TypeScript is the default for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
14
+ * [#73](https://github.com/NullVoxPopuli/ember.nvp/pull/73) Implement the vitest layer for libraries ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
15
+ * [#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))
16
+ * `@nullvoxpopuli/ember-vite`, `ember.nvp`
17
+ * [#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))
18
+ * [#61](https://github.com/NullVoxPopuli/ember.nvp/pull/61) Update maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
19
+ * `ember.nvp`, `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`
20
+ * [#63](https://github.com/NullVoxPopuli/ember.nvp/pull/63) Library support via rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
21
+ * [#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))
22
+ * `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
23
+ * [#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))
24
+ * [#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))
25
+ * `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
26
+ * [#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))
27
+ * `@nullvoxpopuli/ember-vite`
28
+ * [#62](https://github.com/NullVoxPopuli/ember.nvp/pull/62) Cleanup maybeBabel ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
29
+
30
+ #### :bug: Bug Fix
31
+ * `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
32
+ * [#83](https://github.com/NullVoxPopuli/ember.nvp/pull/83) Can't publish TS, build with rolldown ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
33
+ * `@nullvoxpopuli/ember-rolldown`
34
+ * [#82](https://github.com/NullVoxPopuli/ember.nvp/pull/82) Fix watching in the rolldown plugin ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
35
+ * `ember.nvp`
36
+ * [#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))
37
+ * [#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))
38
+ * [#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))
39
+ * [#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))
40
+ * [#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))
41
+ * `@nullvoxpopuli/ember-vite`, `ember.nvp`
42
+ * [#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))
43
+
44
+ #### :memo: Documentation
45
+ * `@nullvoxpopuli/ember-build-tooling-utils`, `@nullvoxpopuli/ember-rolldown`, `ember.nvp`
46
+ * [#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))
47
+
48
+ #### :house: Internal
49
+ * `ember.nvp`
50
+ * [#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))
51
+ * [#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))
52
+ * [#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))
53
+ * `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`, `ember.nvp`
54
+ * [#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))
55
+
56
+ #### Committers: 2
57
+ - @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
58
+ - [@NullVoxPopuli](https://github.com/NullVoxPopuli)
59
+
3
60
  ## Release (2026-07-04)
4
61
 
5
62
  * ember.nvp 0.6.0 (minor)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember.nvp",
3
- "version": "0.6.0",
3
+ "version": "0.7.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,2 @@
1
+ export { maybeBabel } from "./src/maybe-babel.ts";
2
+ export { extensions } from "./src/extensions.ts";
@@ -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,115 @@
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
+ In your `tsdown.config.js` (recommended — emits declarations):
24
+
25
+ ```js
26
+ import { defineConfig, ember } from "@nullvoxpopuli/ember-rolldown";
27
+
28
+ export default defineConfig({
29
+ entry: ["./src/index.ts"],
30
+ plugins: [ember()],
31
+ });
32
+ ```
33
+
34
+ This builds your entry to `dist/*.js` and `dist/*.d.ts` with sourcemaps,
35
+ cleaning `dist/` between builds and leaving the ember virtual packages to the
36
+ consuming app. You choose the `entry` and `plugins`; any tsdown option you
37
+ pass wins.
38
+
39
+ Or in a plain `rolldown.config.js`:
40
+
41
+ ```js
42
+ import { defineConfig } from "rolldown";
43
+ import { ember } from "@nullvoxpopuli/ember-rolldown";
44
+
45
+ export default defineConfig({
46
+ input: ["src/index.ts"],
47
+ plugins: [ember()],
48
+ });
49
+ ```
50
+
51
+ A `babel.config.js` is optional. Without one, `ember()` compiles templates
52
+ (to `precompileTemplate`), decorators (via
53
+ [decorator-transforms](https://github.com/ef4/decorator-transforms)), and
54
+ TypeScript; with one, your config runs instead.
55
+
56
+ ### Declarations
57
+
58
+ Declarations are emitted with isolated declarations — the only declaration
59
+ pipeline that can see `<template>` (`.gts`/`.gjs`) modules, which exist only
60
+ inside the bundler's module graph. Your `tsconfig.json` must enable it
61
+ (`ember()` errors otherwise):
62
+
63
+ ```jsonc
64
+ {
65
+ "compilerOptions": {
66
+ "isolatedDeclarations": true,
67
+ },
68
+ }
69
+ ```
70
+
71
+ Isolated declarations means every exported value carries an explicit type
72
+ annotation. For template-only components:
73
+
74
+ ```gts
75
+ import type { TOC } from "@ember/component/template-only";
76
+
77
+ export const Badge: TOC<BadgeSignature> = <template>...</template>;
78
+ ```
79
+
80
+ ## What `ember()` does
81
+
82
+ `ember()` returns an array of rolldown plugins:
83
+
84
+ - **`emberIsolatedDeclarations()`** — errors when a `tsconfig.json` is present
85
+ without `isolatedDeclarations: true`.
86
+ - **`emberExternals()`** — keeps your `dependencies`, `peerDependencies`, and
87
+ the ember virtual packages (e.g. `@ember/component`, `@glimmer/tracking`, the
88
+ template compiler) external, so the consuming app resolves them.
89
+ - **`emberTransform()`** — preprocesses `<template>` via
90
+ [content-tag](https://github.com/embroider-build/content-tag) and maps
91
+ `.gts`/`.gjs` to `.ts`/`.js` so rolldown understands them. Also rewrites
92
+ `.gts` specifiers in emitted `.d.ts` files.
93
+ - **`emberBabel()`** — runs babel with `babelHelpers: "bundled"`, but only on
94
+ the files that actually need it (template-tag, decorators, template imports);
95
+ everything else stays on rolldown's fast native (oxc) transform.
96
+
97
+ ## Configuration
98
+
99
+ ```ts
100
+ ember({
101
+ babel: {
102
+ configFile: "./babel.config.js",
103
+ babelHelpers: "bundled",
104
+ plugins: [],
105
+ filter: { include: { imports: ["ember-concurrency"], code: [] } },
106
+ },
107
+ });
108
+ ```
109
+
110
+ Each option is documented on `BabelOptions`.
111
+
112
+ ## Credit
113
+
114
+ The `emberExternals` and `emberTransform` plugins are derived from
115
+ [embroider-build/embroider#2658](https://github.com/embroider-build/embroider/pull/2658).