ember.nvp 1.17.0 → 1.17.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.
@@ -46,6 +46,7 @@ jobs:
46
46
  "@nullvoxpopuli/ember-rolldown>@babel/core": "^8.0.0"
47
47
  "@nullvoxpopuli/ember-rolldown>@babel/plugin-transform-typescript": "^8.0.0"
48
48
  "@nullvoxpopuli/ember-vite>@babel/core": "^8.0.0"
49
+ "@nullvoxpopuli/ember-vite>@babel/plugin-transform-typescript": "^8.0.0"
49
50
  EOF
50
51
  - run: pnpm install --no-frozen-lockfile
51
52
  - run: pnpm test:node packages/
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "solution": {
3
3
  "ember.nvp": {
4
- "impact": "minor",
5
- "oldVersion": "1.16.0",
6
- "newVersion": "1.17.0",
4
+ "impact": "patch",
5
+ "oldVersion": "1.17.0",
6
+ "newVersion": "1.17.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",
15
- "reason": "Appears in changelog section :bug: Bug Fix"
15
+ "reason": "Appears in changelog section :house: Internal"
16
16
  }
17
17
  ],
18
18
  "pkgJSONPath": "./package.json"
@@ -21,21 +21,21 @@
21
21
  "oldVersion": "1.2.0"
22
22
  },
23
23
  "@nullvoxpopuli/ember-rolldown": {
24
- "impact": "minor",
25
- "oldVersion": "2.11.0",
26
- "newVersion": "2.12.0",
24
+ "oldVersion": "2.12.0"
25
+ },
26
+ "@nullvoxpopuli/ember-vite": {
27
+ "impact": "patch",
28
+ "oldVersion": "1.3.0",
29
+ "newVersion": "1.3.1",
27
30
  "tagName": "latest",
28
31
  "constraints": [
29
32
  {
30
- "impact": "minor",
31
- "reason": "Appears in changelog section :rocket: Enhancement"
33
+ "impact": "patch",
34
+ "reason": "Appears in changelog section :bug: Bug Fix"
32
35
  }
33
36
  ],
34
- "pkgJSONPath": "./packages/rolldown/package.json"
35
- },
36
- "@nullvoxpopuli/ember-vite": {
37
- "oldVersion": "1.3.0"
37
+ "pkgJSONPath": "./packages/vite/package.json"
38
38
  }
39
39
  },
40
- "description": "## Release (2026-10-16)\n\n* ember.nvp 1.17.0 (minor)\n* @nullvoxpopuli/ember-rolldown 2.12.0 (minor)\n\n#### :rocket: Enhancement\n* `@nullvoxpopuli/ember-rolldown`, `ember.nvp`\n * [#166](https://github.com/NullVoxPopuli/ember.nvp/pull/166) Require babel-plugin-ember-template-compilation 4.0.1 ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n\n#### :bug: Bug Fix\n* `ember.nvp`\n * [#164](https://github.com/NullVoxPopuli/ember.nvp/pull/164) Add vite/client types to the dev tsconfig of libraries with tests ([@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"
40
+ "description": "## Release (2026-10-25)\n\n* ember.nvp 1.17.1 (patch)\n* @nullvoxpopuli/ember-vite 1.3.1 (patch)\n\n#### :bug: Bug Fix\n* `ember.nvp`, `@nullvoxpopuli/ember-vite`\n * [#169](https://github.com/NullVoxPopuli/ember.nvp/pull/169) Take the macros development mode from the vite mode ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))\n\n#### :house: Internal\n* `ember.nvp`\n * [#167](https://github.com/NullVoxPopuli/ember.nvp/pull/167) Expect rolldown 1.2.15 module comments in generated output ([@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"
41
41
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## Release (2026-10-25)
4
+
5
+ * ember.nvp 1.17.1 (patch)
6
+ * @nullvoxpopuli/ember-vite 1.3.1 (patch)
7
+
8
+ #### :bug: Bug Fix
9
+ * `ember.nvp`, `@nullvoxpopuli/ember-vite`
10
+ * [#169](https://github.com/NullVoxPopuli/ember.nvp/pull/169) Take the macros development mode from the vite mode ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
11
+
12
+ #### :house: Internal
13
+ * `ember.nvp`
14
+ * [#167](https://github.com/NullVoxPopuli/ember.nvp/pull/167) Expect rolldown 1.2.15 module comments in generated output ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
15
+
16
+ #### Committers: 1
17
+ - @NullVoxPopuli's reduced-access machine account for AI usage ([@NullVoxPopuli-ai-agent](https://github.com/NullVoxPopuli-ai-agent))
18
+
3
19
  ## Release (2026-10-16)
4
20
 
5
21
  * ember.nvp 1.17.0 (minor)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember.nvp",
3
- "version": "1.17.0",
3
+ "version": "1.17.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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nullvoxpopuli/ember-vite",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Meta plugin for ember projects focusing on speed.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -35,6 +35,9 @@
35
35
  "node": ">= 24"
36
36
  },
37
37
  "devDependencies": {
38
+ "@babel/plugin-transform-typescript": "^7.28.10 || ^8.0.0",
39
+ "babel-plugin-ember-template-compilation": "^4.0.1",
40
+ "decorator-transforms": "^2.4.0",
38
41
  "rolldown": "^1.1.2",
39
42
  "typescript": "^6.0.3",
40
43
  "vite": "^8.0.14"
@@ -1,6 +1,7 @@
1
1
  import { extensions } from "@embroider/vite";
2
- import type { ConfigEnv, ConfigPluginContext } from "vite";
3
- import { describe, expect, it } from "vitest";
2
+ import { fileURLToPath } from "node:url";
3
+ import type { ConfigEnv, ConfigPluginContext, Plugin } from "vite";
4
+ import { afterEach, describe, expect, it } from "vitest";
4
5
 
5
6
  import { ember } from "./ember.ts";
6
7
 
@@ -36,3 +37,74 @@ describe("ember", () => {
36
37
  expect(config.optimizeDeps.rolldownOptions.resolve.extensions).toEqual(extensions);
37
38
  });
38
39
  });
40
+
41
+ /**
42
+ * This package has no babel config,
43
+ * so `ember()` uses its default babel plugins,
44
+ * and babel resolves them from here.
45
+ */
46
+ const PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));
47
+
48
+ const DEV_CHECK = [
49
+ `import { isDevelopingApp, macroCondition } from "@embroider/macros";`,
50
+ `export const build = macroCondition(isDevelopingApp()) ? "development build" : "other build";`,
51
+ ].join("\n");
52
+
53
+ const CONTEXT = {
54
+ error(error: unknown) {
55
+ throw error;
56
+ },
57
+ };
58
+
59
+ /**
60
+ * Runs the config hook, then the babel plugin, the way vite does.
61
+ */
62
+ async function compile(mode: string) {
63
+ const plugins = ember() as Plugin[];
64
+ const config: any = {};
65
+
66
+ // @ts-expect-error the first entry is the config plugin
67
+ await plugins[0].config.call(ROLLDOWN, config, { command: "build", mode });
68
+
69
+ const babel = plugins.find((plugin) => plugin.name === "nullvoxpopuli:babel");
70
+ // @ts-expect-error the babel plugin has an object transform hook
71
+ const result = await babel.transform.handler.call(CONTEXT, DEV_CHECK, `${PACKAGE_ROOT}app.js`);
72
+
73
+ return result.code as string;
74
+ }
75
+
76
+ describe("default babel plugins", () => {
77
+ let restoreCwd: (() => void) | undefined;
78
+
79
+ afterEach(() => {
80
+ restoreCwd?.();
81
+ restoreCwd = undefined;
82
+ });
83
+
84
+ function inPackageRoot() {
85
+ const previous = process.cwd();
86
+ process.chdir(PACKAGE_ROOT);
87
+ restoreCwd = () => process.chdir(previous);
88
+ }
89
+
90
+ /**
91
+ * vite sets NODE_ENV from the mode only after the config hooks run.
92
+ * Under vitest, NODE_ENV is "test".
93
+ */
94
+ it("keeps development-only code in development mode", async () => {
95
+ inPackageRoot();
96
+
97
+ const code = await compile("development");
98
+
99
+ expect(code).toContain("development build");
100
+ });
101
+
102
+ it("removes development-only code in production mode", async () => {
103
+ inPackageRoot();
104
+
105
+ const code = await compile("production");
106
+
107
+ expect(code).not.toContain("development build");
108
+ expect(code).toContain("other build");
109
+ });
110
+ });
@@ -59,9 +59,20 @@ function absolutePath(relativePath: string) {
59
59
  *
60
60
  * The plugins are named, not imported.
61
61
  * babel resolves them from the project, which carries them as its own dependencies.
62
+ *
63
+ * The macros take development mode from the vite mode.
64
+ * `buildMacros` reads NODE_ENV, but vite sets NODE_ENV
65
+ * only after the config hooks run.
62
66
  */
63
- function defaultBabelPlugins() {
64
- const macros = buildMacros();
67
+ function defaultBabelPlugins(mode: string) {
68
+ const macros = buildMacros({
69
+ configure(config) {
70
+ if (isDev(mode)) {
71
+ config.enablePackageDevelopment(process.cwd());
72
+ config.enableRuntimeMode();
73
+ }
74
+ },
75
+ });
65
76
 
66
77
  return [
67
78
  [
@@ -106,11 +117,15 @@ function babelOptions(nvpConfig: Config): BabelOptions {
106
117
  return { configFile };
107
118
  }
108
119
 
120
+ /**
121
+ * The config hook fills this list, once it knows the vite mode.
122
+ * The babel plugins keep a reference to it, so they see the filled list.
123
+ */
109
124
  return {
110
125
  configFile: false,
111
126
  babelrc: false,
112
127
  babelHelpers: "inline",
113
- plugins: defaultBabelPlugins(),
128
+ plugins: [],
114
129
  };
115
130
  }
116
131
 
@@ -210,6 +225,14 @@ export function ember(nvpConfig: Config = {}) {
210
225
  */
211
226
  await emberConfig.call(this, viteConfig, env);
212
227
 
228
+ if ("plugins" in babel) {
229
+ babel.plugins.length = 0;
230
+
231
+ for (const plugin of defaultBabelPlugins(env.mode)) {
232
+ babel.plugins.push(plugin);
233
+ }
234
+ }
235
+
213
236
  viteConfig.experimental ||= {};
214
237
  viteConfig.build ||= {};
215
238
  viteConfig.optimizeDeps ||= {};
@@ -50,10 +50,10 @@ async function listDist(project: Project) {
50
50
  }
51
51
 
52
52
  /**
53
- * The bundled chunk's own imports are hoisted above its first region marker.
53
+ * The bundled chunk's own imports are hoisted to its first lines.
54
54
  *
55
- * ember-source's doc comments below it also start lines with `import`,
56
- * so only that head is inspected.
55
+ * ember-source's doc comments further down also start lines with `import`,
56
+ * so only the leading import lines count.
57
57
  */
58
58
  async function chunkImports(project: Project) {
59
59
  let files = await listFiles(join(project.directory, "dist"));
@@ -62,9 +62,17 @@ async function chunkImports(project: Project) {
62
62
  expect(chunk).toBeDefined();
63
63
 
64
64
  let code = (await project.read(`dist/${chunk}`)) ?? "";
65
- let head = code.split("//#region")[0] ?? "";
65
+ let imports: string[] = [];
66
66
 
67
- return head.match(/^import .*$/gm) ?? [];
67
+ for (let line of code.split("\n")) {
68
+ if (line.startsWith("import ")) {
69
+ imports.push(line);
70
+ } else if (line.trim() !== "") {
71
+ break;
72
+ }
73
+ }
74
+
75
+ return imports;
68
76
  }
69
77
 
70
78
  /**
@@ -179,7 +179,6 @@ describe("base: minimal-library", () => {
179
179
  expect(declarations).toMatchInlineSnapshot(`
180
180
  "import { TOC } from "@ember/component/template-only";
181
181
  import Component from "@glimmer/component";
182
- //#region src/components/badge.d.ts
183
182
  interface BadgeSignature {
184
183
  Element: HTMLSpanElement;
185
184
  Blocks: {
@@ -187,8 +186,6 @@ describe("base: minimal-library", () => {
187
186
  };
188
187
  }
189
188
  declare const Badge: TOC<BadgeSignature>;
190
- //#endregion
191
- //#region src/components/greeting.d.ts
192
189
  interface GreetingSignature {
193
190
  Element: HTMLParagraphElement;
194
191
  Args: {
@@ -196,10 +193,7 @@ describe("base: minimal-library", () => {
196
193
  };
197
194
  }
198
195
  declare class Greeting extends Component<GreetingSignature> {}
199
- //#endregion
200
- //#region src/utils/math.d.ts
201
196
  declare function add(a: number, b: number): number;
202
- //#endregion
203
197
  export { Badge, type BadgeSignature, Greeting, type GreetingSignature, add };
204
198
  //# sourceMappingURL=index.d.ts.map"
205
199
  `);
@@ -168,16 +168,13 @@ describe("library with ember-scoped-css", () => {
168
168
  import { precompileTemplate } from "@ember/template-compilation";
169
169
  import { setComponentTemplate } from "@ember/component";
170
170
  import templateOnly from "@ember/component/template-only";
171
- //#region src/components/badge.ts
171
+ // src/components/badge.ts
172
172
  const Badge = setComponentTemplate(precompileTemplate("<span class=\\"badge_e1025e732\\" ...attributes>{{yield}}</span>", { strictMode: true }), templateOnly());
173
- //#endregion
174
- //#region src/components/banner.ts
173
+ // src/components/banner.ts
175
174
  const Banner = setComponentTemplate(precompileTemplate("\\n<div class=\\"banner_e88952290\\" ...attributes>{{yield}}</div>", { strictMode: true }), templateOnly());
176
- //#endregion
177
- //#region src/components/chip.ts
175
+ // src/components/chip.ts
178
176
  const chipClass = "chip_ec34dd962";
179
177
  const Chip = setComponentTemplate(precompileTemplate("<span class=\\"chip_ec34dd962\\" ...attributes></span>", { strictMode: true }), templateOnly());
180
- //#endregion
181
178
  export { Badge, Banner, Chip, chipClass };
182
179
 
183
180
  //# sourceMappingURL=index.js.map"