ember.nvp 1.14.0 → 1.16.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/.release-plan.json +37 -5
- package/CHANGELOG.md +31 -0
- package/README.md +28 -0
- package/package.json +2 -1
- package/packages/rolldown/package.json +2 -2
- package/packages/rolldown/src/transform.test.ts +3 -3
- package/packages/vite/package.json +4 -4
- package/packages/vite/src/ember.test.ts +38 -0
- package/packages/vite/src/ember.ts +38 -5
- package/src/bases/minimal-app/files/package.json +2 -2
- package/src/bases/minimal-extension/files/package.json +2 -2
- package/src/cli/generator.js +10 -0
- package/src/cli/index.js +19 -2
- package/src/cli/questions/layers.js +3 -2
- package/src/cli/questions/migration.js +69 -0
- package/src/index.js +1 -0
- package/src/layers/qunit/index.js +1 -1
- package/src/migration-from/addons.js +154 -0
- package/src/migration-from/app.js +1117 -0
- package/src/migration-from/at-ember/addon-blueprint/index.js +515 -0
- package/src/migration-from/at-ember/addon-blueprint/rollup.js +188 -0
- package/src/migration-from/at-ember/app-blueprint/index.js +60 -0
- package/src/migration-from/at-ember-tooling/classic-build-addon-blueprint/index.js +601 -0
- package/src/migration-from/at-ember-tooling/classic-build-app-blueprint/index.js +118 -0
- package/src/migration-from/babel.js +207 -0
- package/src/migration-from/ember-cli-build.js +238 -0
- package/src/migration-from/files.js +120 -0
- package/src/migration-from/findings.js +69 -0
- package/src/migration-from/index.js +81 -0
- package/src/migration-from/javascript.js +217 -0
- package/src/migration-from/layers.js +170 -0
- package/src/migration-from/library.js +311 -0
- package/src/utils/types.ts +69 -0
- package/test/ember.nvp/migration-from-fixtures.ts +506 -0
- package/test/ember.nvp/migration-from.test.ts +475 -0
package/.release-plan.json
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
"solution": {
|
|
3
3
|
"ember.nvp": {
|
|
4
4
|
"impact": "minor",
|
|
5
|
-
"oldVersion": "1.
|
|
6
|
-
"newVersion": "1.
|
|
5
|
+
"oldVersion": "1.15.0",
|
|
6
|
+
"newVersion": "1.16.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"
|
|
12
16
|
}
|
|
13
17
|
],
|
|
14
18
|
"pkgJSONPath": "./package.json"
|
|
@@ -17,11 +21,39 @@
|
|
|
17
21
|
"oldVersion": "1.2.0"
|
|
18
22
|
},
|
|
19
23
|
"@nullvoxpopuli/ember-rolldown": {
|
|
20
|
-
"
|
|
24
|
+
"impact": "minor",
|
|
25
|
+
"oldVersion": "2.10.0",
|
|
26
|
+
"newVersion": "2.11.0",
|
|
27
|
+
"tagName": "latest",
|
|
28
|
+
"constraints": [
|
|
29
|
+
{
|
|
30
|
+
"impact": "minor",
|
|
31
|
+
"reason": "Appears in changelog section :rocket: Enhancement"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"impact": "patch",
|
|
35
|
+
"reason": "Appears in changelog section :bug: Bug Fix"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"pkgJSONPath": "./packages/rolldown/package.json"
|
|
21
39
|
},
|
|
22
40
|
"@nullvoxpopuli/ember-vite": {
|
|
23
|
-
"
|
|
41
|
+
"impact": "minor",
|
|
42
|
+
"oldVersion": "1.2.0",
|
|
43
|
+
"newVersion": "1.3.0",
|
|
44
|
+
"tagName": "latest",
|
|
45
|
+
"constraints": [
|
|
46
|
+
{
|
|
47
|
+
"impact": "minor",
|
|
48
|
+
"reason": "Appears in changelog section :rocket: Enhancement"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"impact": "patch",
|
|
52
|
+
"reason": "Appears in changelog section :bug: Bug Fix"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"pkgJSONPath": "./packages/vite/package.json"
|
|
24
56
|
}
|
|
25
57
|
},
|
|
26
|
-
"description": "## Release (2026-
|
|
58
|
+
"description": "## Release (2026-10-12)\n\n* ember.nvp 1.16.0 (minor)\n* @nullvoxpopuli/ember-rolldown 2.11.0 (minor)\n* @nullvoxpopuli/ember-vite 1.3.0 (minor)\n\n#### :rocket: Enhancement\n* `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`, `ember.nvp`\n * [#163](https://github.com/NullVoxPopuli/ember.nvp/pull/163) Update the embroider dependencies, give the config hook its plugin context ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n\n#### :bug: Bug Fix\n* `@nullvoxpopuli/ember-vite`, `ember.nvp`\n * [#162](https://github.com/NullVoxPopuli/ember.nvp/pull/162) Find the embroider config plugin by name ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n* `@nullvoxpopuli/ember-rolldown`\n * [#160](https://github.com/NullVoxPopuli/ember.nvp/pull/160) Fix macOS tests ([@tcjr](https://github.com/tcjr))\n\n#### Committers: 2\n- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n- Tom Carter ([@tcjr](https://github.com/tcjr))\n"
|
|
27
59
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Release (2026-10-12)
|
|
4
|
+
|
|
5
|
+
* ember.nvp 1.16.0 (minor)
|
|
6
|
+
* @nullvoxpopuli/ember-rolldown 2.11.0 (minor)
|
|
7
|
+
* @nullvoxpopuli/ember-vite 1.3.0 (minor)
|
|
8
|
+
|
|
9
|
+
#### :rocket: Enhancement
|
|
10
|
+
* `@nullvoxpopuli/ember-rolldown`, `@nullvoxpopuli/ember-vite`, `ember.nvp`
|
|
11
|
+
* [#163](https://github.com/NullVoxPopuli/ember.nvp/pull/163) Update the embroider dependencies, give the config hook its plugin context ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
12
|
+
|
|
13
|
+
#### :bug: Bug Fix
|
|
14
|
+
* `@nullvoxpopuli/ember-vite`, `ember.nvp`
|
|
15
|
+
* [#162](https://github.com/NullVoxPopuli/ember.nvp/pull/162) Find the embroider config plugin by name ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
16
|
+
* `@nullvoxpopuli/ember-rolldown`
|
|
17
|
+
* [#160](https://github.com/NullVoxPopuli/ember.nvp/pull/160) Fix macOS tests ([@tcjr](https://github.com/tcjr))
|
|
18
|
+
|
|
19
|
+
#### Committers: 2
|
|
20
|
+
- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
21
|
+
- Tom Carter ([@tcjr](https://github.com/tcjr))
|
|
22
|
+
|
|
23
|
+
## Release (2026-10-02)
|
|
24
|
+
|
|
25
|
+
* ember.nvp 1.15.0 (minor)
|
|
26
|
+
|
|
27
|
+
#### :rocket: Enhancement
|
|
28
|
+
* `ember.nvp`
|
|
29
|
+
* [#158](https://github.com/NullVoxPopuli/ember.nvp/pull/158) Migrate projects from the older blueprints ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
30
|
+
|
|
31
|
+
#### Committers: 1
|
|
32
|
+
- @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
|
|
33
|
+
|
|
3
34
|
## Release (2026-09-30)
|
|
4
35
|
|
|
5
36
|
* ember.nvp 1.14.0 (minor)
|
package/README.md
CHANGED
|
@@ -59,6 +59,29 @@ The accepted changes land as uncommitted edits, for you to review with your own
|
|
|
59
59
|
New projects skip the confirmation, and are written as soon as generation succeeds.
|
|
60
60
|
For scripting, `--write yes` / `--write no` answers the confirmation up front.
|
|
61
61
|
|
|
62
|
+
### Migrating from an older blueprint
|
|
63
|
+
|
|
64
|
+
Run ember.nvp in a project from one of these blueprints, and choose update:
|
|
65
|
+
|
|
66
|
+
| Blueprint | Becomes |
|
|
67
|
+
| ------------------------------------------------------------------------------- | --------- |
|
|
68
|
+
| `@ember/addon-blueprint`, and the addon package of `@embroider/addon-blueprint` | a library |
|
|
69
|
+
| `@ember-tooling/classic-build-addon-blueprint` (classic addons) | a library |
|
|
70
|
+
| `@ember/app-blueprint` (Vite with `@embroider/compat`) | an app |
|
|
71
|
+
| `@ember-tooling/classic-build-app-blueprint` (classic apps) | an app |
|
|
72
|
+
|
|
73
|
+
ember.nvp checks the project before it asks about layers.
|
|
74
|
+
When the project uses something that ember.nvp does not support, such as v1 addons or `.hbs` templates, ember.nvp lists each item with what to do, and writes nothing.
|
|
75
|
+
Most of these items also work in the old setup, so you can fix them there first.
|
|
76
|
+
|
|
77
|
+
Otherwise, the migration keeps your code, and replaces the old build:
|
|
78
|
+
|
|
79
|
+
- libraries build with tsdown, and keep `addon-main.cjs`, so that apps with ember-cli can still use them
|
|
80
|
+
- apps build with Vite, without `@embroider/compat`
|
|
81
|
+
|
|
82
|
+
The layers that replace the old tooling, such as qunit for the tests, start selected.
|
|
83
|
+
After writing, ember.nvp lists what is left for you, such as settings to copy by hand.
|
|
84
|
+
|
|
62
85
|
### Wrapping
|
|
63
86
|
|
|
64
87
|
The provided CLI is only a wrapper around the exported `generateProject` function.
|
|
@@ -84,6 +107,11 @@ await generateProject(new Project(
|
|
|
84
107
|
|
|
85
108
|
All parts of the generator are idempotent, so running generators on existing projects _can_ no-op.
|
|
86
109
|
|
|
110
|
+
A project from an older blueprint is migrated first.
|
|
111
|
+
`generateProject` returns `{ todo }`, the list of what is left for the user.
|
|
112
|
+
When the project needs changes before it can migrate, `generateProject` throws a `MigrationError` with a `findings` list, and changes nothing.
|
|
113
|
+
`checkMigration(project)` gives the same lists without changing anything, and `formatFindings(findings)` prints them the way the CLI does.
|
|
114
|
+
|
|
87
115
|
To get the same don't-write-until-confirmed behavior as the CLI, wrap generation in a `Stage`.
|
|
88
116
|
A stage is a scratch copy of the target directory (without `node_modules` and `.git`).
|
|
89
117
|
Layers run against that copy, and the target directory is untouched until you commit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember.nvp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.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",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"#bases/*": "./src/bases/*/index.js",
|
|
14
14
|
"#consolidators/*": "./src/consolidators/*",
|
|
15
15
|
"#layers": "./src/layers/index.js",
|
|
16
|
+
"#migration-from": "./src/migration-from/index.js",
|
|
16
17
|
"#types": "./src/utils/types.ts",
|
|
17
18
|
"#utils/*": "./src/utils/*",
|
|
18
19
|
"#test-helpers": "./test/test-helpers.ts"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nullvoxpopuli/ember-rolldown",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Meta plugin for building ember v2 libraries/addons with rolldown & tsdown.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/core": "^7.28.10 || ^8.0.0",
|
|
47
47
|
"@babel/plugin-transform-typescript": "^7.28.10 || ^8.0.0",
|
|
48
|
-
"@embroider/core": "^4.
|
|
48
|
+
"@embroider/core": "^4.6.9",
|
|
49
49
|
"@jridgewell/remapping": "^2.3.5",
|
|
50
50
|
"@nullvoxpopuli/ember-build-tooling-utils": "workspace:*",
|
|
51
51
|
"babel-plugin-ember-template-compilation": "^4.0.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { originalPositionFor, TraceMap } from "@jridgewell/trace-mapping";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { mkdtemp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { mkdtemp, mkdir, readFile, realpath, writeFile } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { rolldown } from "rolldown";
|
|
@@ -38,7 +38,7 @@ async function generate(
|
|
|
38
38
|
files: Record<string, string>,
|
|
39
39
|
{ input = ["index.ts"], plugins = () => [], sourcemap = false }: BuildOptions = {},
|
|
40
40
|
): Promise<Build> {
|
|
41
|
-
const dir = await mkdtemp(path.join(tmpdir(), "ember-rolldown-build-"));
|
|
41
|
+
const dir = await realpath(await mkdtemp(path.join(tmpdir(), "ember-rolldown-build-")));
|
|
42
42
|
|
|
43
43
|
for (const [relative, source] of Object.entries(files)) {
|
|
44
44
|
const full = path.join(dir, relative);
|
|
@@ -347,7 +347,7 @@ describe("emberTransform (full plugin via rolldown)", () => {
|
|
|
347
347
|
});
|
|
348
348
|
|
|
349
349
|
it("emits sourcemaps for the specifier rewrite (no SOURCEMAP_BROKEN warnings)", async () => {
|
|
350
|
-
const dir = await mkdtemp(path.join(tmpdir(), "ember-rolldown-map-"));
|
|
350
|
+
const dir = await realpath(await mkdtemp(path.join(tmpdir(), "ember-rolldown-map-")));
|
|
351
351
|
|
|
352
352
|
const files = {
|
|
353
353
|
// index.ts contains a `.gts` specifier, so it goes through the rewrite.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nullvoxpopuli/ember-vite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Meta plugin for ember projects focusing on speed.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"packageManager": "pnpm@10.28.0",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@babel/core": "^7.28.10 || ^8.0.0",
|
|
29
|
-
"@embroider/core": "^4.
|
|
30
|
-
"@embroider/macros": "^1.
|
|
31
|
-
"@embroider/vite": "^1.
|
|
29
|
+
"@embroider/core": "^4.6.9",
|
|
30
|
+
"@embroider/macros": "^1.21.3",
|
|
31
|
+
"@embroider/vite": "^1.7.15",
|
|
32
32
|
"@nullvoxpopuli/ember-build-tooling-utils": "workspace:*"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { extensions } from "@embroider/vite";
|
|
2
|
+
import type { ConfigEnv, ConfigPluginContext } from "vite";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { ember } from "./ember.ts";
|
|
6
|
+
|
|
7
|
+
const ROLLDOWN = { meta: { rolldownVersion: "1.0.0" } } as ConfigPluginContext;
|
|
8
|
+
|
|
9
|
+
async function configure(env: ConfigEnv) {
|
|
10
|
+
const config: any = {};
|
|
11
|
+
const [plugin] = ember();
|
|
12
|
+
|
|
13
|
+
// @ts-expect-error the first entry is the config plugin
|
|
14
|
+
await plugin.config.call(ROLLDOWN, config, env);
|
|
15
|
+
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("ember", () => {
|
|
20
|
+
/**
|
|
21
|
+
* These values come from the config hook of `@embroider/vite`.
|
|
22
|
+
* They are missing when that hook does not run.
|
|
23
|
+
*/
|
|
24
|
+
it("applies the config from @embroider/vite", async () => {
|
|
25
|
+
const config = await configure({ command: "build", mode: "production" });
|
|
26
|
+
|
|
27
|
+
expect(config.resolve.extensions).toEqual(extensions);
|
|
28
|
+
expect(config.server.port).toBe(4200);
|
|
29
|
+
expect(config.optimizeDeps.exclude).toContain("@embroider/macros");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("gives @embroider/vite the plugin context, so that it configures rolldown", async () => {
|
|
33
|
+
const config = await configure({ command: "build", mode: "production" });
|
|
34
|
+
|
|
35
|
+
expect(config.build.rolldownOptions.moduleTypes).toEqual({ ".ts": "js" });
|
|
36
|
+
expect(config.optimizeDeps.rolldownOptions.resolve.extensions).toEqual(extensions);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -2,13 +2,43 @@ import { buildMacros } from "@embroider/macros/babel";
|
|
|
2
2
|
import { ember as embroiderEmber, extensions, resolver, templateTag } from "@embroider/vite";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
|
-
import type { ConfigEnv, ResolvedConfig } from "vite";
|
|
5
|
+
import type { ConfigEnv, ConfigPluginContext, ResolvedConfig, UserConfig } from "vite";
|
|
6
6
|
|
|
7
7
|
import { maybeBabel } from "@nullvoxpopuli/ember-build-tooling-utils";
|
|
8
8
|
|
|
9
9
|
import { testHtml } from "./test-html.ts";
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const EMBER_CONFIG = "vite-plugin-ember-config";
|
|
12
|
+
|
|
13
|
+
type ConfigHook = (
|
|
14
|
+
this: ConfigPluginContext,
|
|
15
|
+
config: UserConfig,
|
|
16
|
+
env: ConfigEnv,
|
|
17
|
+
) => Promise<unknown> | unknown;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `@embroider/vite` does not export its config hook on its own.
|
|
21
|
+
*
|
|
22
|
+
* The position of the plugin in the list changes between releases,
|
|
23
|
+
* so the name is the only stable way to find it.
|
|
24
|
+
*/
|
|
25
|
+
function findEmberConfig(): ConfigHook {
|
|
26
|
+
for (const plugin of embroiderEmber()) {
|
|
27
|
+
if (plugin.name !== EMBER_CONFIG) continue;
|
|
28
|
+
|
|
29
|
+
const hook = plugin.config;
|
|
30
|
+
const handler = typeof hook === "function" ? hook : hook?.handler;
|
|
31
|
+
|
|
32
|
+
if (handler) return handler as ConfigHook;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
throw new Error(
|
|
36
|
+
`@embroider/vite has no "${EMBER_CONFIG}" plugin with a config hook. ` +
|
|
37
|
+
`This version of @embroider/vite is not supported by @nullvoxpopuli/ember-vite.`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const emberConfig = findEmberConfig();
|
|
12
42
|
|
|
13
43
|
const cwd = process.cwd();
|
|
14
44
|
function absolutePath(relativePath: string) {
|
|
@@ -173,9 +203,12 @@ export function ember(nvpConfig: Config = {}) {
|
|
|
173
203
|
{
|
|
174
204
|
// no compat
|
|
175
205
|
name: "ember:nullvoxpopuli",
|
|
176
|
-
async config(viteConfig: any, env: ConfigEnv) {
|
|
177
|
-
|
|
178
|
-
|
|
206
|
+
async config(this: ConfigPluginContext, viteConfig: any, env: ConfigEnv) {
|
|
207
|
+
/**
|
|
208
|
+
* The hook reads the rolldown version from the plugin context,
|
|
209
|
+
* and takes its esbuild path without it.
|
|
210
|
+
*/
|
|
211
|
+
await emberConfig.call(this, viteConfig, env);
|
|
179
212
|
|
|
180
213
|
viteConfig.experimental ||= {};
|
|
181
214
|
viteConfig.build ||= {};
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"start": "vite"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@embroider/macros": "^1.
|
|
28
|
+
"@embroider/macros": "^1.21.3",
|
|
29
29
|
"@embroider/router": "^3.0.6",
|
|
30
30
|
"@glimmer/component": "^2.1.1",
|
|
31
31
|
"decorator-transforms": "^2.3.2",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@babel/plugin-transform-typescript": "^7.29.7",
|
|
38
38
|
"@babel/runtime": "^7.29.7",
|
|
39
39
|
"@ember/app-tsconfig": "^2.0.0",
|
|
40
|
-
"@embroider/core": "^4.
|
|
40
|
+
"@embroider/core": "^4.6.9",
|
|
41
41
|
"@glint/ember-tsc": "^1.7.5",
|
|
42
42
|
"@glint/template": "^1.7.7",
|
|
43
43
|
"@glint/tsserver-plugin": "^2.5.5",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"start": "vite"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@embroider/macros": "^1.
|
|
29
|
+
"@embroider/macros": "^1.21.3",
|
|
30
30
|
"@embroider/router": "^3.0.6",
|
|
31
31
|
"@glimmer/component": "^2.1.1",
|
|
32
32
|
"decorator-transforms": "^2.3.2",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@babel/plugin-transform-typescript": "^7.29.7",
|
|
39
39
|
"@babel/runtime": "^7.29.7",
|
|
40
40
|
"@ember/app-tsconfig": "^2.0.0",
|
|
41
|
-
"@embroider/core": "^4.
|
|
41
|
+
"@embroider/core": "^4.6.9",
|
|
42
42
|
"@glint/ember-tsc": "^1.7.5",
|
|
43
43
|
"@glint/template": "^1.7.7",
|
|
44
44
|
"@glint/tsserver-plugin": "^2.5.5",
|
package/src/cli/generator.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { mkdir, rm } from "node:fs/promises";
|
|
2
2
|
|
|
3
3
|
import { bases } from "#bases";
|
|
4
|
+
import { migrate } from "#migration-from";
|
|
4
5
|
import { consolidateLintingScripts } from "../consolidators/linting.js";
|
|
5
6
|
import { hasGit } from "#utils/git.js";
|
|
6
7
|
/**
|
|
7
8
|
* Generate project files by running layer functions
|
|
8
9
|
*
|
|
10
|
+
* A project from an older blueprint is migrated first.
|
|
11
|
+
* When it uses features that ember.nvp does not support,
|
|
12
|
+
* this throws a `MigrationError` that lists them, before anything changes.
|
|
13
|
+
*
|
|
9
14
|
* @param {import('#utils/project.js').Project} project
|
|
10
15
|
* @param {string} [replaceOrUpdate]
|
|
16
|
+
* @returns {Promise<{ todo: import('#types').Finding[] }>} work left for the user after a migration
|
|
11
17
|
*/
|
|
12
18
|
export async function generateProject(project, replaceOrUpdate) {
|
|
13
19
|
if (replaceOrUpdate === "replace") {
|
|
@@ -16,6 +22,8 @@ export async function generateProject(project, replaceOrUpdate) {
|
|
|
16
22
|
|
|
17
23
|
await mkdir(project.directory, { recursive: true });
|
|
18
24
|
|
|
25
|
+
let migration = await migrate(project);
|
|
26
|
+
|
|
19
27
|
await bases[project.desires.type].run(project);
|
|
20
28
|
|
|
21
29
|
/**
|
|
@@ -51,6 +59,8 @@ export async function generateProject(project, replaceOrUpdate) {
|
|
|
51
59
|
`[ember.nvp] Consolidation commit -- Please report issues to https://github.com/NullVoxPopuli/ember.nvp/`,
|
|
52
60
|
);
|
|
53
61
|
}
|
|
62
|
+
|
|
63
|
+
return { todo: migration?.report.todo ?? [] };
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
/**
|
package/src/cli/index.js
CHANGED
|
@@ -17,6 +17,8 @@ import { cwd } from "#utils/cwd.js";
|
|
|
17
17
|
import { Project } from "#utils/project.js";
|
|
18
18
|
import { Stage } from "#utils/stage.js";
|
|
19
19
|
import { askAboutProjectHere, askReplaceOrUpdate } from "./questions/replace-or-update.js";
|
|
20
|
+
import { checkForMigration, showTodo } from "./questions/migration.js";
|
|
21
|
+
import { MigrationError } from "#migration-from";
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
24
|
* This whole file's primary purpose is to be an interactive CLI
|
|
@@ -35,7 +37,11 @@ async function main() {
|
|
|
35
37
|
const projectPath = here ? cwd : await askPath(projectName);
|
|
36
38
|
const replaceOrUpdate = here ?? (await askReplaceOrUpdate(projectPath));
|
|
37
39
|
const projectType = await askProjectType(replaceOrUpdate === "update" ? projectPath : undefined);
|
|
38
|
-
const
|
|
40
|
+
const migrationLayers =
|
|
41
|
+
replaceOrUpdate === "update"
|
|
42
|
+
? await checkForMigration(projectPath, projectName, projectType)
|
|
43
|
+
: [];
|
|
44
|
+
const selectedLayers = await askLayers(projectType, migrationLayers);
|
|
39
45
|
const packageManager = await askPackageManager();
|
|
40
46
|
|
|
41
47
|
// Layer options start from what the project already uses
|
|
@@ -82,9 +88,12 @@ async function main() {
|
|
|
82
88
|
const s = p.spinner();
|
|
83
89
|
s.start("Creating your Ember app...");
|
|
84
90
|
|
|
91
|
+
/** @type {import('#types').Finding[]} */
|
|
92
|
+
let todo = [];
|
|
93
|
+
|
|
85
94
|
try {
|
|
86
95
|
// Generate the project (into the stage)
|
|
87
|
-
await generateProject(project);
|
|
96
|
+
({ todo } = await generateProject(project));
|
|
88
97
|
|
|
89
98
|
s.stop("Project generated");
|
|
90
99
|
} catch (err) {
|
|
@@ -92,6 +101,12 @@ async function main() {
|
|
|
92
101
|
|
|
93
102
|
await stage.discard();
|
|
94
103
|
|
|
104
|
+
// the message is the list for the user, and a stack trace adds nothing to it
|
|
105
|
+
if (err instanceof MigrationError) {
|
|
106
|
+
p.cancel(err.message);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
95
110
|
if (err instanceof Error) {
|
|
96
111
|
p.cancel(`Error: ${err.message}`);
|
|
97
112
|
if (err.stack) {
|
|
@@ -141,6 +156,8 @@ async function main() {
|
|
|
141
156
|
|
|
142
157
|
p.log.success(`Applied ${toApply.length} change${toApply.length === 1 ? "" : "s"}`);
|
|
143
158
|
|
|
159
|
+
showTodo(todo);
|
|
160
|
+
|
|
144
161
|
/**
|
|
145
162
|
* Converted / generated files are written expecting the project's own
|
|
146
163
|
* formatting and lint pass to run right away.
|
|
@@ -5,8 +5,9 @@ import * as p from "@clack/prompts";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @param {import('#types').ProjectType} projectType
|
|
8
|
+
* @param {string[]} [suggested] layers to select by default, beyond each layer's own default
|
|
8
9
|
*/
|
|
9
|
-
export async function askLayers(projectType) {
|
|
10
|
+
export async function askLayers(projectType, suggested = []) {
|
|
10
11
|
const optionalLayers = (await discoverLayers()).filter(
|
|
11
12
|
(layer) => typeof layer.run === "function",
|
|
12
13
|
);
|
|
@@ -37,7 +38,7 @@ export async function askLayers(projectType) {
|
|
|
37
38
|
const defaultValues = (
|
|
38
39
|
await Promise.all(
|
|
39
40
|
optionalLayers.map(async (layer) => {
|
|
40
|
-
let result = await layer.defaultValue?.(projectType);
|
|
41
|
+
let result = suggested.includes(layer.name) || (await layer.defaultValue?.(projectType));
|
|
41
42
|
|
|
42
43
|
return result && layer.name;
|
|
43
44
|
}),
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
|
+
import { checkMigration, formatFindings } from "#migration-from";
|
|
4
|
+
import { Project } from "#utils/project.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A project from an older blueprint is migrated during the update.
|
|
8
|
+
*
|
|
9
|
+
* The check runs before the layer questions,
|
|
10
|
+
* so that a project that ember.nvp cannot migrate stops here,
|
|
11
|
+
* with the list of what to change first.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} projectPath
|
|
14
|
+
* @param {string} name
|
|
15
|
+
* @param {import('#types').ProjectType} type
|
|
16
|
+
* @returns {Promise<string[]>} layers that replace the old blueprint's tooling
|
|
17
|
+
*/
|
|
18
|
+
export async function checkForMigration(projectPath, name, type) {
|
|
19
|
+
let project = new Project(projectPath, {
|
|
20
|
+
name,
|
|
21
|
+
type,
|
|
22
|
+
path: projectPath,
|
|
23
|
+
layers: [],
|
|
24
|
+
packageManager: "pnpm",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let spinner = p.spinner();
|
|
28
|
+
|
|
29
|
+
spinner.start("Checking for an older blueprint");
|
|
30
|
+
|
|
31
|
+
let result = await checkMigration(project);
|
|
32
|
+
|
|
33
|
+
if (!result) {
|
|
34
|
+
spinner.stop("No older blueprint found");
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let { migration, report } = result;
|
|
39
|
+
|
|
40
|
+
if (report.unsupported.length > 0) {
|
|
41
|
+
spinner.stop(`This project is from ${migration.label}`);
|
|
42
|
+
p.log.error(
|
|
43
|
+
`ember.nvp cannot migrate this project yet. Change these first:\n\n` +
|
|
44
|
+
formatFindings(report.unsupported),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (report.todo.length > 0) {
|
|
48
|
+
p.log.info(
|
|
49
|
+
`After that, the migration leaves these for you:\n\n${formatFindings(report.todo)}`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
p.cancel("Nothing was written");
|
|
54
|
+
return process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
spinner.stop(`Migrating from ${styleText("cyan", migration.label)}`);
|
|
58
|
+
|
|
59
|
+
return report.layers;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {import('#types').Finding[]} todo
|
|
64
|
+
*/
|
|
65
|
+
export function showTodo(todo) {
|
|
66
|
+
if (todo.length === 0) return;
|
|
67
|
+
|
|
68
|
+
p.note(formatFindings(todo), "Left to do after the migration");
|
|
69
|
+
}
|
package/src/index.js
CHANGED