ember.nvp 0.1.0 → 0.2.1

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 (94) hide show
  1. package/.github/workflows/ci.yml +41 -0
  2. package/.github/workflows/plan-release.yml +2 -2
  3. package/.github/workflows/publish.yml +4 -5
  4. package/.prettierignore +2 -1
  5. package/.prettierrc.js +10 -0
  6. package/.release-plan.json +6 -6
  7. package/CHANGELOG.md +53 -0
  8. package/README.md +79 -142
  9. package/package.json +28 -5
  10. package/pnpm-workspace.yaml +3 -0
  11. package/src/bases/README.md +5 -0
  12. package/src/bases/minimal-app/app.test.ts +203 -0
  13. package/src/bases/minimal-app/files/.env.development +8 -0
  14. package/src/bases/minimal-app/files/app/app.ts +21 -0
  15. package/src/bases/minimal-app/files/app/config.ts +17 -0
  16. package/src/bases/minimal-app/files/app/router.ts +51 -0
  17. package/src/bases/minimal-app/files/app/templates/application.gts +5 -0
  18. package/src/{layers/minimal/files-ts → bases/minimal-app/files}/babel.config.js +8 -5
  19. package/src/{layers/minimal → bases/minimal-app}/files/index.html +3 -5
  20. package/src/bases/minimal-app/files/package.json +57 -0
  21. package/src/{layers/minimal → bases/minimal-app}/files/tsconfig.json +0 -6
  22. package/src/bases/minimal-app/index.js +111 -0
  23. package/src/bases/minimal-library/index.js +10 -0
  24. package/src/cli/args.js +57 -0
  25. package/src/cli/generator.js +66 -11
  26. package/src/cli/index.js +44 -13
  27. package/src/cli/questions/layers.js +39 -50
  28. package/src/cli/questions/name.js +22 -6
  29. package/src/cli/questions/ok.js +38 -0
  30. package/src/cli/questions/package-manager.js +23 -2
  31. package/src/cli/questions/path.js +59 -0
  32. package/src/cli/questions/project-type.js +55 -0
  33. package/src/consolidators/linting.js +51 -0
  34. package/src/index.js +2 -0
  35. package/src/layers/eslint-bundled-ember/files/eslint.config.js +14 -0
  36. package/src/layers/eslint-bundled-ember/index.js +91 -0
  37. package/src/layers/eslint-bundled-nvp/app.test.ts +91 -0
  38. package/src/layers/eslint-bundled-nvp/files/eslint.config.js +16 -0
  39. package/src/layers/eslint-bundled-nvp/index.js +91 -0
  40. package/src/layers/eslint-ejected/index.js +95 -0
  41. package/src/layers/git/index.js +33 -0
  42. package/src/layers/github-actions/app.test.ts +73 -0
  43. package/src/layers/github-actions/index.js +200 -0
  44. package/src/layers/index.js +47 -0
  45. package/src/layers/prettier/files/.prettierrc.js +4 -0
  46. package/src/layers/prettier/index.js +45 -18
  47. package/src/layers/qunit/app.test.ts +90 -0
  48. package/src/layers/qunit/files/testem.cjs +26 -0
  49. package/src/layers/qunit/files/tests/index.html +16 -7
  50. package/src/layers/qunit/files/tests/test-helper.ts +65 -7
  51. package/src/layers/qunit/files/tests/unit/macros-test.ts +26 -0
  52. package/src/layers/qunit/index.js +83 -34
  53. package/src/layers/release-plan/index.js +5 -0
  54. package/src/layers/renovate/files/app.json5 +14 -0
  55. package/src/layers/renovate/files/library.json5 +16 -0
  56. package/src/layers/renovate/index.js +68 -0
  57. package/src/layers/typescript/app.test.ts +93 -0
  58. package/src/layers/typescript/index.js +145 -0
  59. package/src/layers/vitest/files/vitest.config.mjs +1 -5
  60. package/src/layers/vitest/index.js +43 -26
  61. package/src/utils/babel.js +76 -0
  62. package/src/utils/buffer.js +15 -0
  63. package/src/utils/cli.js +45 -0
  64. package/src/utils/cwd.js +1 -0
  65. package/src/utils/fs.js +85 -0
  66. package/src/utils/git.js +41 -0
  67. package/src/utils/git.test.ts +36 -0
  68. package/src/utils/manifest.js +9 -0
  69. package/src/utils/npm.js +29 -0
  70. package/src/utils/object.js +10 -0
  71. package/src/utils/project.js +249 -0
  72. package/src/utils/remove-types.js +90 -0
  73. package/src/utils/types.ts +48 -0
  74. package/test/ember.nvp/cli.test.ts +12 -0
  75. package/test/ember.nvp/layers.test.ts +35 -0
  76. package/test/ember.nvp/permutations.test.ts +200 -0
  77. package/test/manual.sh +11 -0
  78. package/test/test-helpers/permutate.test.ts +70 -0
  79. package/test/test-helpers.ts +175 -0
  80. package/tsconfig.json +10 -2
  81. package/vitest.config.js +9 -0
  82. package/src/layers/eslint/index.js +0 -42
  83. package/src/layers/minimal/files/app/app.ts +0 -10
  84. package/src/layers/minimal/files/app/config.ts +0 -18
  85. package/src/layers/minimal/files/app/router.ts +0 -9
  86. package/src/layers/minimal/files/app/templates/application.gts +0 -7
  87. package/src/layers/minimal/files-js/babel.config.js +0 -38
  88. package/src/layers/minimal/index.js +0 -89
  89. package/src/layers/prettier/files/.prettierrc.cjs +0 -15
  90. package/src/layers/qunit/files/tests/unit/.gitkeep +0 -0
  91. /package/src/{layers/minimal → bases/minimal-app}/files/vite.config.mjs +0 -0
  92. /package/src/layers/{eslint/files/eslint.config.mjs → eslint-ejected/files/eslint.config.js} +0 -0
  93. /package/src/layers/{minimal/files/app/routes → qunit/files/tests/application}/.gitkeep +0 -0
  94. /package/src/layers/qunit/files/tests/{integration → rendering}/.gitkeep +0 -0
@@ -0,0 +1,41 @@
1
+ name: CI
2
+ on:
3
+ workflow_dispatch:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ ##############################################################
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ env:
18
+ HOME: /tmp/home
19
+ WORKSPACE: /tmp/workspace
20
+
21
+ jobs:
22
+ lints:
23
+ name: "Lint"
24
+ runs-on: ubuntu-latest
25
+ timeout-minutes: 10
26
+
27
+ steps:
28
+ - uses: wyvox/action@v1
29
+ - run: pnpm lint
30
+
31
+ node_tests:
32
+ name: "Node Tests"
33
+ runs-on: ubuntu-latest
34
+ timeout-minutes: 15
35
+
36
+ steps:
37
+ - uses: wyvox/action@v1
38
+ - run: |
39
+ git config --global user.name "ci"
40
+ git config --global user.email "non@none.none"
41
+ pnpm test:node
@@ -23,7 +23,7 @@ jobs:
23
23
  steps:
24
24
  - uses: release-plan/actions/should-prepare-release@v1
25
25
  with:
26
- ref: 'main'
26
+ ref: "main"
27
27
  id: should-prepare
28
28
 
29
29
  create-prepare-release-pr:
@@ -40,7 +40,7 @@ jobs:
40
40
  - uses: release-plan/actions/prepare@v1
41
41
  name: Run release-plan prepare
42
42
  with:
43
- ref: 'main'
43
+ ref: "main"
44
44
  env:
45
45
  GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
46
46
  id: explanation
@@ -10,7 +10,7 @@ on:
10
10
  - main
11
11
  - master
12
12
  paths:
13
- - '.release-plan.json'
13
+ - ".release-plan.json"
14
14
 
15
15
  concurrency:
16
16
  group: publish-${{ github.head_ref || github.ref }}
@@ -27,13 +27,12 @@ jobs:
27
27
 
28
28
  steps:
29
29
  - uses: actions/checkout@v6
30
- - uses: pnpm/action-setup@v4
30
+ - uses: pnpm/action-setup@v5
31
31
  - uses: actions/setup-node@v6
32
32
  with:
33
- node-version: 22
34
- registry-url: 'https://registry.npmjs.org'
33
+ node-version: 24
34
+ registry-url: "https://registry.npmjs.org"
35
35
  cache: pnpm
36
- - run: npm install -g npm@latest # ensure that the globally installed npm is new enough to support OIDC
37
36
  - run: pnpm install --frozen-lockfile
38
37
  - name: Publish to NPM
39
38
  run: NPM_CONFIG_PROVENANCE=true pnpm release-plan publish
package/.prettierignore CHANGED
@@ -1,2 +1,3 @@
1
1
  pnpm-lock.yaml
2
-
2
+ CHANGELOG.md
3
+ dist
package/.prettierrc.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @see https://prettier.io/docs/configuration
3
+ * @type {import("prettier").Config}
4
+ */
5
+ const config = {
6
+ printWidth: 100,
7
+ plugins: ["prettier-plugin-ember-template-tag"],
8
+ };
9
+
10
+ export default config;
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "solution": {
3
3
  "ember.nvp": {
4
- "impact": "minor",
5
- "oldVersion": "0.0.0",
6
- "newVersion": "0.1.0",
4
+ "impact": "patch",
5
+ "oldVersion": "0.2.0",
6
+ "newVersion": "0.2.1",
7
7
  "tagName": "latest",
8
8
  "constraints": [
9
9
  {
10
- "impact": "minor",
11
- "reason": "Appears in changelog section :rocket: Enhancement"
10
+ "impact": "patch",
11
+ "reason": "Appears in changelog section :bug: Bug Fix"
12
12
  },
13
13
  {
14
14
  "impact": "patch",
@@ -18,5 +18,5 @@
18
18
  "pkgJSONPath": "./package.json"
19
19
  }
20
20
  },
21
- "description": "## Release (2026-01-21)\n\n* ember.nvp 0.1.0 (minor)\n\n#### :rocket: Enhancement\n* `ember.nvp`\n * [#1](https://github.com/NullVoxPopuli/ember.nvp/pull/1) Implementation planning ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### :house: Internal\n* `ember.nvp`\n * [#2](https://github.com/NullVoxPopuli/ember.nvp/pull/2) pnpm dlx create-release-plan-setup@latest --update ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#1](https://github.com/NullVoxPopuli/ember.nvp/pull/1) Implementation planning ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### Committers: 1\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
21
+ "description": "## Release (2026-05-15)\n\n* ember.nvp 0.2.1 (patch)\n\n#### :bug: Bug Fix\n* `ember.nvp`\n * [#29](https://github.com/NullVoxPopuli/ember.nvp/pull/29) Fix production vite build broken by setTesting in app/config.ts ([@Copilot](https://github.com/apps/copilot-swe-agent))\n\n#### :house: Internal\n* `ember.nvp`\n * [#31](https://github.com/NullVoxPopuli/ember.nvp/pull/31) Update release-plan ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n\n#### Committers: 2\n- Copilot [Bot] ([@copilot-swe-agent](https://github.com/apps/copilot-swe-agent))\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
22
22
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # Changelog
2
2
 
3
+ ## Release (2026-05-15)
4
+
5
+ * ember.nvp 0.2.1 (patch)
6
+
7
+ #### :bug: Bug Fix
8
+ * `ember.nvp`
9
+ * [#29](https://github.com/NullVoxPopuli/ember.nvp/pull/29) Fix production vite build broken by setTesting in app/config.ts ([@Copilot](https://github.com/apps/copilot-swe-agent))
10
+
11
+ #### :house: Internal
12
+ * `ember.nvp`
13
+ * [#31](https://github.com/NullVoxPopuli/ember.nvp/pull/31) Update release-plan ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
14
+
15
+ #### Committers: 2
16
+ - Copilot [Bot] ([@copilot-swe-agent](https://github.com/apps/copilot-swe-agent))
17
+ - [@NullVoxPopuli](https://github.com/NullVoxPopuli)
18
+
19
+ ## Release (2026-01-28)
20
+
21
+ * ember.nvp 0.2.0 (minor)
22
+
23
+ #### :rocket: Enhancement
24
+ * `ember.nvp`
25
+ * [#20](https://github.com/NullVoxPopuli/ember.nvp/pull/20) Implement idemponent and modern qunit layer ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
26
+ * [#18](https://github.com/NullVoxPopuli/ember.nvp/pull/18) Ensure the TS utilities handle the babel plugin ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
27
+ * [#17](https://github.com/NullVoxPopuli/ember.nvp/pull/17) Support emitting JavaScript projects ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
28
+ * [#16](https://github.com/NullVoxPopuli/ember.nvp/pull/16) Commit changes automatically if git is in use ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
29
+ * [#14](https://github.com/NullVoxPopuli/ember.nvp/pull/14) Add idempotent GitHub Actions ci.yml ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
30
+ * [#11](https://github.com/NullVoxPopuli/ember.nvp/pull/11) Add idempotent renovate config generation ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
31
+ * [#9](https://github.com/NullVoxPopuli/ember.nvp/pull/9) Add eslint codemod/applyable, enable type checking internally on the JS ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
32
+ * [#8](https://github.com/NullVoxPopuli/ember.nvp/pull/8) Add idempotent prettier codemod/applyable ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
33
+ * [#6](https://github.com/NullVoxPopuli/ember.nvp/pull/6) Add git support with proper defaults (ie automatic --skip-git if you are already in a git repo) ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
34
+ * [#4](https://github.com/NullVoxPopuli/ember.nvp/pull/4) Implementation: minimal-app ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
35
+
36
+ #### :bug: Bug Fix
37
+ * `ember.nvp`
38
+ * [#22](https://github.com/NullVoxPopuli/ember.nvp/pull/22) Fix accidental stdoutput during git interactions ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
39
+ * [#10](https://github.com/NullVoxPopuli/ember.nvp/pull/10) Various CLI fixes ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
40
+
41
+ #### :memo: Documentation
42
+ * `ember.nvp`
43
+ * [#12](https://github.com/NullVoxPopuli/ember.nvp/pull/12) Clarify rationale and usage caveats in README ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
44
+
45
+ #### :house: Internal
46
+ * `ember.nvp`
47
+ * [#19](https://github.com/NullVoxPopuli/ember.nvp/pull/19) Forgot to enable tests for GH Actions ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
48
+ * [#21](https://github.com/NullVoxPopuli/ember.nvp/pull/21) Refactor hases and wantses ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
49
+ * [#15](https://github.com/NullVoxPopuli/ember.nvp/pull/15) Add reapply test utility for more easily re-applying layers in the manual testing ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
50
+ * [#13](https://github.com/NullVoxPopuli/ember.nvp/pull/13) Speed up permutations test ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
51
+ * [#7](https://github.com/NullVoxPopuli/ember.nvp/pull/7) Implement idempotent testing for layers that may (or may not) have been applied during the initial generation of a project ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
52
+
53
+ #### Committers: 1
54
+ - [@NullVoxPopuli](https://github.com/NullVoxPopuli)
55
+
3
56
  ## Release (2026-01-21)
4
57
 
5
58
  * ember.nvp 0.1.0 (minor)
package/README.md CHANGED
@@ -1,88 +1,84 @@
1
1
  # ember.nvp
2
2
 
3
- _ember project generator: alternative to the official blueprints, but more modern -- hopefully one day to upstream back in to ember-cli / official blueprints_
3
+ _ember project generator: a reenvisioning of blueprints -- hopefully one day to upstream back in to ember-cli / official blueprints, **if** all the caveats can be cleaned up_
4
4
 
5
- ## Reqs
6
-
7
- - node 24+
5
+ > [!NOTE]
6
+ > **Why isn't this work happening in the default blueprints?** for a long time now, I've felt the old blueprint system from the very early days of ember-cli has not allowed for expressive enough layering of what people actually want out of a project generator. That said, that means there are some compromises in the CLI/generator in this repo. Throughout all files generated, whenever there is a caveat, there will be a comment in the file with the caveat, explaining status, open issues, and how we can collectively move forward. It's possible that one day ember-cli adopts or is inspired by this project, but it's too early to tell at the moment.
8
7
 
9
- ## What this does?
8
+ _I can't recommend using this tool unless your comfortable with the emitted caveats in the project_.
9
+ (And being comfortable debugging build issues is recommended)
10
10
 
11
- - Always `"type": "module"`
12
- - Interactive CLI
13
- - choose your features
14
-
15
- Good for:
16
-
17
- - demos
18
- - reproductions
19
- - existing monorepos
20
- - example integrations with other tools
11
+ But I'm very excited about this tool, because it's everything I've ever wanted from a project generator. Each layer is idempotent, and knows about the other layers. So if, for example, you omit eslint when setting up your project, but do have github-actions, when you do add eslint, your github-actions will be updated as well. And this works in any order.
21
12
 
22
13
  ## Usage
23
14
 
24
- Install dependencies first:
25
-
26
15
  ```bash
27
- pnpm install
16
+ npx ember.nvp
28
17
  ```
29
18
 
30
- Then run the interactive CLI:
19
+ or, faster:
31
20
 
32
21
  ```bash
33
- node src/cli/index.js
22
+ pnpm dlx ember.nvp
34
23
  ```
35
24
 
36
- Or link it locally for easier testing:
25
+ Using the unreleased version:
37
26
 
38
27
  ```bash
39
- pnpm link --global
40
- ember.nvp
28
+ pnpm dlx NullVoxPopuli/ember.nvp
29
+ # or, slower:
30
+ npx NullVoxPopuli/ember.nvp
41
31
  ```
42
32
 
43
- ### Example Session
33
+ ### Wrapping
44
34
 
35
+ The provided CLI is only a wrapper around our exported `generateProject` function.
36
+
37
+ Other tools can call `generateProject` themselves if they wish to provide a different terminal or graphical UI.
38
+
39
+ ```js
40
+ import { generateProject, Project } from 'ember.nvp';
41
+
42
+
43
+ await generateProject(new Project(
44
+ directoryToGenerateIn
45
+ // desires
46
+ {
47
+ name,
48
+ path,
49
+ type,
50
+ layers,
51
+ packageManager,
52
+ }
53
+ ));
45
54
  ```
46
- ┌ ember.nvp
47
- │
48
- ◆ What is your project name?
49
- │ my-awesome-app
50
- │
51
- ◇ Base Layer
52
- │ minimal layer is always included.
53
- │ It provides: type: "module", no compat, no testing, no linting.
54
- │ Perfect for demos and reproductions.
55
- │
56
- ◆ Select additional features: (press space to select)
57
- │ ◻ ESLint - Code linting with ESLint
58
- │ ◻ Prettier - Code formatting with Prettier
59
- │ ◻ QUnit - Testing with QUnit
60
- │ ◻ Vitest - Testing with Vitest (modern & fast)
61
- │
62
- ◆ Which package manager?
63
- │ ● pnpm - Fast, disk space efficient
64
- │ npm - Node default
65
- │ yarn - Classic alternative
66
- │
67
- ◇ Project created!
68
- │
69
- ◇ Next steps
70
- │ cd my-awesome-app
71
- │ pnpm install
72
- │ pnpm start
73
- │
74
- └ ✓ Project ready! Happy coding!
75
- ```
76
55
 
77
- The CLI will guide you through:
56
+ All parts of the generator are idempotent, so running generators on existing projects _can_ no-op.
57
+
58
+ ## Reqs
59
+
60
+ - node 24+
61
+
62
+ ## What this does?
63
+
64
+ - Always `"type": "module"`
65
+ - Modern, incremental
66
+ - Interactive CLI
67
+ - choose your features
68
+ - The generators fro the different types of projects are never out of date from each other
69
+ - each feature/layer is a mini codemod that has to support working within all the other layers -- so eslint for example is always derived the same way -- no way for "app" and "library" configs to get out of sync
78
70
 
79
- 1. **Project name** - Choose your project name
80
- 2. **Feature selection** - Select which layers you want (linting, testing, formatting)
81
- 3. **Package manager** - Choose pnpm, npm, or yarn
71
+ Good for:
72
+
73
+ - demos
74
+ - reproductions
75
+ - existing monorepos
76
+ - example integrations with other tools
82
77
 
83
78
  ## Layers
84
79
 
85
- Each layer is a standalone module that can add features to your ember project:
80
+ Each layer is a standalone module that can add features to your ember project,
81
+ and every layer is aware of the other layers, so if, for example, you run github actions first, and then later decide to add linting, the github actions output will be updated.
86
82
 
87
83
  ### 🎯 Minimal (always included)
88
84
 
@@ -97,6 +93,16 @@ The base layer, matching the `--minimal` flag from [ember-cli/ember-app-blueprin
97
93
 
98
94
  Perfect for demos, reproductions, and learning!
99
95
 
96
+ ### Git
97
+
98
+ Runs `git init` for you.
99
+
100
+ By default this layer is enabled, _unless_ you are running the generator in a git repo already -- then you have to opt in to git.
101
+
102
+ ### GitHub Actions (optional)
103
+
104
+ Adds simple GitHub Actions workflow to your project
105
+
100
106
  ### 📝 ESLint (optional)
101
107
 
102
108
  Adds modern ESLint configuration with:
@@ -116,75 +122,30 @@ Code formatting with:
116
122
 
117
123
  ### 🧪 QUnit (optional)
118
124
 
119
- Traditional Ember testing with:
120
-
121
- - QUnit test framework
122
- - @ember/test-helpers
123
- - Test HTML setup
124
- - Playwright for CI
125
+ - Both co-located tests as well as traditionally located tests with QUnit.
126
+ - New Theme: [qunit-theme-ember](https://github.com/IgnaceMaes/qunit-theme-ember)
127
+ - Default utilities to help you find why tests are stuck
125
128
 
126
129
  ### ⚡ Vitest (optional)
127
130
 
128
- Modern testing alternative:
129
-
130
- - Vitest (faster than QUnit)
131
- - @ember/test-helpers
132
- - Happy DOM
133
- - Watch mode & UI
131
+ Super experimental vitest setup using [ember-vitest](https://github.com/NullVoxPopuli/ember-vitest)
134
132
 
135
133
  ## Architecture
136
134
 
137
- ```
138
- src/
139
- ├── cli/ # Interactive CLI entry point
140
- │ └── index.js # Main CLI with prompts
141
- ├── layers/ # Feature layers (auto-discovered)
142
- │ ├── minimal/ # Base layer (always included)
143
- │ │ ├── index.js # Layer definition with run function
144
- │ │ └── files/ # Template files to copy
145
- │ ├── eslint/
146
- │ │ ├── index.js
147
- │ │ └── files/
148
- │ ├── prettier/
149
- │ │ ├── index.js
150
- │ │ └── files/
151
- │ ├── qunit/
152
- │ │ ├── index.js
153
- │ │ └── files/
154
- │ └── vitest/
155
- │ ├── index.js
156
- │ └── files/
157
- └── lib/ # Shared utilities
158
- └── generator.js # Project generation orchestration
159
- ```
160
-
161
- ### Layer Architecture
162
-
163
- Each layer now uses **ember-apply** utilities for robust file and package.json manipulation:
164
-
165
- - **`index.js`** - Exports an object with:
166
- - `label` - Display name
167
- - `description` - Short description
168
- - `run({ targetDir, projectName })` - Async function that applies the layer
169
-
170
- - **`files/`** - Directory containing template files to copy to the target project
171
- - Use `__PROJECT_NAME__` placeholder for project name substitution
172
- - Files are copied using `ember-apply`'s `files.applyFolder()`
173
-
174
135
  ### How Layers Work
175
136
 
176
137
  1. **Discovery**: CLI scans `src/layers/` and imports each `index.js`
177
138
  2. **Selection**: User selects which optional layers to include
178
139
  3. **Execution**: Each layer's `run()` function is called in sequence:
179
140
  ```js
180
- await layer.run({ targetDir: "/path/to/project", projectName: "my-app" });
141
+ await layer.run(project);
181
142
  ```
182
- 4. **Layer Functions**: Inside `run()`, layers use `ember-apply` to:
143
+ 4. **Layer Functions**: Inside `run()`, layers use [`ember-apply`](https://ember-apply.pages.dev/) to apply codemods in order to:
183
144
  - Copy files from `files/` directory
184
145
  - Add dependencies/devDependencies to package.json
185
146
  - Add npm scripts
186
147
  - Modify package.json metadata
187
- - Transform existing files (e.g., replace placeholders)
148
+ - etc
188
149
 
189
150
  ### Adding New Layers
190
151
 
@@ -194,48 +155,24 @@ To add a new layer, create a new directory in `src/layers/` with:
194
155
 
195
156
  ```js
196
157
  import { packageJson, files } from "ember-apply";
197
- import { dirname, join } from "node:path";
198
- import { fileURLToPath } from "node:url";
199
-
200
- const __dirname = dirname(fileURLToPath(import.meta.url));
158
+ import { join } from "node:path";
201
159
 
202
160
  export default {
203
161
  label: "My Feature",
204
162
  description: "What this feature does",
205
163
 
206
- async run({ targetDir, projectName }) {
164
+ async run(project) {
207
165
  // Copy files from files/ directory
208
- await files.applyFolder(join(__dirname, "files"), targetDir);
209
-
210
- // Add dependencies
211
- await packageJson.addDependencies(
212
- {
213
- "some-package": "^1.0.0",
214
- },
215
- targetDir,
216
- );
217
-
218
- // Add devDependencies
219
- await packageJson.addDevDependencies(
220
- {
221
- "dev-package": "^2.0.0",
222
- },
223
- targetDir,
224
- );
225
-
226
- // Add scripts
227
- await packageJson.addScripts(
228
- {
229
- "my-script": 'echo "Hello"',
230
- },
231
- targetDir,
232
- );
166
+ await files.applyFolder(join(import.meta.dirname, "files"), project.directory);
167
+
168
+ await packageJson.addDependencies({ "some-package": "^1.0.0" }, project.directory);
169
+
170
+ await packageJson.addScripts({ "my-script": 'echo "Hello"' }, project.directory);
233
171
  },
234
172
  };
235
173
  ```
236
174
 
237
175
  2. **`files/`** directory - Template files to copy:
238
- - Use `__PROJECT_NAME__` as a placeholder for the project name
239
176
  - Files will be copied to the target directory maintaining structure
240
177
 
241
178
  The CLI will automatically discover and offer it as an option!
package/package.json CHANGED
@@ -1,17 +1,31 @@
1
1
  {
2
2
  "name": "ember.nvp",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
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",
7
7
  "url": "git@github.com:NullVoxPopuli/ember.nvp.git"
8
8
  },
9
9
  "type": "module",
10
+ "imports": {
11
+ "#args": "./src/cli/args.js",
12
+ "#bases/*": "./src/bases/*/index.js",
13
+ "#consolidators/*": "./src/consolidators/*",
14
+ "#layers": "./src/layers/index.js",
15
+ "#types": "./src/utils/types.ts",
16
+ "#utils/*": "./src/utils/*",
17
+ "#test-helpers": "./test/test-helpers.ts"
18
+ },
19
+ "exports": "./src/index.js",
10
20
  "bin": "./src/cli/index.js",
11
21
  "dependencies": {
12
22
  "@clack/prompts": "^0.11.0",
13
- "ember-apply": "^2.16.0",
14
- "picocolors": "^1.1.1"
23
+ "babel-remove-types": "^1.1.0",
24
+ "content-tag": "^4.1.0",
25
+ "ember-apply": "^2.17.0",
26
+ "execa": "^9.6.1",
27
+ "latest-version": "^9.0.0",
28
+ "package-name-regex": "^5.0.0"
15
29
  },
16
30
  "devDependencies": {
17
31
  "@ember/app-tsconfig": "^2.0.0",
@@ -19,17 +33,26 @@
19
33
  "@glint/ember-tsc": "^1.0.9",
20
34
  "@glint/template": "^1.7.3",
21
35
  "@glint/tsserver-plugin": "^2.0.9",
36
+ "concurrently": "^9.2.1",
22
37
  "ember-source": "^6.10.0",
23
38
  "prettier": "^3.7.4",
24
39
  "prettier-plugin-ember-template-tag": "^2.1.2",
25
- "release-plan": "^0.17.4"
40
+ "release-plan": "^0.18.0",
41
+ "rimraf": "^6.1.2",
42
+ "vite": "^7.3.1",
43
+ "vitest": "^4.0.17"
26
44
  },
27
45
  "engines": {
28
46
  "node": ">= 24"
29
47
  },
30
48
  "scripts": {
31
49
  "format": "prettier . --write",
50
+ "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto",
51
+ "lint:fix": "pnpm format",
32
52
  "lint:format": "prettier . --check",
33
- "new": "node ./src/cli/index.js"
53
+ "lint:types": "tsc --noEmit",
54
+ "new": "./test/manual.sh",
55
+ "test:node": "FORCE_COLOR=1 vitest run --reporter=verbose --printConsoleTrace",
56
+ "test:vitest": "FORCE_COLOR=1 vitest"
34
57
  }
35
58
  }
@@ -0,0 +1,3 @@
1
+ packages:
2
+ - .
3
+ - src/bases/*/files
@@ -0,0 +1,5 @@
1
+ Each of these base projects are _real_ projects that can be ran in these directories.
2
+
3
+ For changing the name of a project, the code in the base layer's index.js should find all the places the name is used and swap it out (codemod style).
4
+
5
+ We don't want to use ejs, because it makes the base layers unrunnable.