ember.nvp 1.7.0 → 1.8.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 (81) hide show
  1. package/.github/workflows/ci.yml +22 -0
  2. package/.release-plan.json +35 -7
  3. package/CHANGELOG.md +32 -0
  4. package/README.md +41 -28
  5. package/RELEASE.md +16 -14
  6. package/package.json +1 -1
  7. package/packages/build-tooling-utils/README.md +7 -12
  8. package/packages/build-tooling-utils/package.json +2 -2
  9. package/packages/build-tooling-utils/src/extensions.ts +4 -3
  10. package/packages/build-tooling-utils/src/maybe-babel.ts +18 -15
  11. package/packages/rolldown/README.md +105 -100
  12. package/packages/rolldown/index.ts +37 -24
  13. package/packages/rolldown/package.json +4 -4
  14. package/packages/rolldown/src/app-reexports.test.ts +4 -3
  15. package/packages/rolldown/src/app-reexports.ts +37 -27
  16. package/packages/rolldown/src/babel.test.ts +10 -5
  17. package/packages/rolldown/src/babel.ts +88 -69
  18. package/packages/rolldown/src/config.ts +21 -17
  19. package/packages/rolldown/src/dts.test.ts +42 -26
  20. package/packages/rolldown/src/externals.test.ts +16 -11
  21. package/packages/rolldown/src/externals.ts +18 -12
  22. package/packages/rolldown/src/isolated-declarations.ts +56 -43
  23. package/packages/rolldown/src/plugin-like.ts +18 -15
  24. package/packages/rolldown/src/published-types.test.ts +18 -13
  25. package/packages/rolldown/src/transform.test.ts +26 -17
  26. package/packages/rolldown/src/transform.ts +68 -48
  27. package/packages/vite/README.md +10 -11
  28. package/packages/vite/package.json +2 -2
  29. package/packages/vite/src/ember.ts +44 -36
  30. package/packages/vite/src/test-html.ts +13 -11
  31. package/src/bases/README.md +6 -3
  32. package/src/bases/minimal-app/app.test.ts +7 -4
  33. package/src/bases/minimal-app/files/app/app.ts +2 -3
  34. package/src/bases/minimal-app/files/app/router.ts +3 -3
  35. package/src/bases/minimal-app/index.js +10 -6
  36. package/src/bases/minimal-custom-element/files/README.md +16 -12
  37. package/src/bases/minimal-extension/files/README.md +13 -5
  38. package/src/bases/minimal-extension/files/app/app.ts +2 -3
  39. package/src/bases/minimal-extension/files/app/config.ts +5 -3
  40. package/src/bases/minimal-extension/index.js +16 -11
  41. package/src/bases/minimal-library/files/README.md +8 -7
  42. package/src/bases/minimal-library/index.js +21 -15
  43. package/src/cli/index.js +23 -18
  44. package/src/cli/questions/write.js +12 -10
  45. package/src/layers/are-the-types-wrong/index.js +4 -4
  46. package/src/layers/github-actions/index.js +7 -4
  47. package/src/layers/inspector-support/index.js +2 -2
  48. package/src/layers/qunit/index.js +18 -14
  49. package/src/layers/readme/index.js +2 -4
  50. package/src/layers/renovate/index.js +2 -1
  51. package/src/layers/typescript/index.js +12 -12
  52. package/src/layers/vitest/index.js +7 -3
  53. package/src/utils/babel.js +3 -2
  54. package/src/utils/buffer.js +2 -2
  55. package/src/utils/cli.js +4 -4
  56. package/src/utils/fs.js +23 -14
  57. package/src/utils/inspector-support.js +22 -19
  58. package/src/utils/npm.js +15 -12
  59. package/src/utils/project-type.js +19 -0
  60. package/src/utils/project.js +4 -13
  61. package/src/utils/remove-types.js +2 -4
  62. package/src/utils/rewrite-imports.js +43 -31
  63. package/src/utils/stage.js +44 -33
  64. package/src/utils/tsdown-config.js +6 -5
  65. package/src/utils/types.ts +9 -8
  66. package/test/ember.nvp/base-library.test.ts +6 -4
  67. package/test/ember.nvp/generator-replace-or-update.test.ts +6 -4
  68. package/test/ember.nvp/inspector-support.test.ts +4 -3
  69. package/test/ember.nvp/layer-inspector-support.test.ts +2 -3
  70. package/test/ember.nvp/layer-publish-checks.test.ts +2 -3
  71. package/test/ember.nvp/layer-qunit.test.ts +2 -2
  72. package/test/ember.nvp/layer-readme.test.ts +2 -2
  73. package/test/ember.nvp/layer-vitest.test.ts +16 -9
  74. package/test/ember.nvp/layers-load.test.ts +26 -0
  75. package/test/ember.nvp/library-src-fixtures.ts +7 -3
  76. package/test/ember.nvp/permutations/shared.ts +19 -12
  77. package/test/ember.nvp/publish-configs.test.ts +44 -31
  78. package/test/ember.nvp/rewrite-imports.test.ts +4 -3
  79. package/test/ember.nvp/scoped-css-library.test.ts +6 -4
  80. package/test/test-helpers/permutate.test.ts +3 -3
  81. package/test/test-helpers.ts +10 -6
@@ -8,20 +8,26 @@ import { join } from "node:path";
8
8
  import type { Project } from "ember.nvp";
9
9
 
10
10
  /**
11
- * A library whose package also holds dev-only code (a demo app, in-package
12
- * tests) keeps two of each build config: a permissive `tsconfig.json` and
13
- * `babel.config.js` that editors and `tsc --noEmit` use over everything, and
14
- * publish-only counterparts covering just what gets published. Either publish
15
- * config can sit in the package root or in `config/`.
11
+ * A library whose package also holds dev-only code (a demo app, in-package tests)
12
+ * keeps two of each build config:
13
+ * - a permissive `tsconfig.json` and `babel.config.js`,
14
+ * which editors and `tsc --noEmit` use over everything
15
+ * - publish-only counterparts, covering just what gets published
16
16
  *
17
- * These tests generate a real library, put the configs in each of those
18
- * places, and run the real `pnpm build`.
17
+ * Either publish config can sit in the package root or in `config/`.
18
+ *
19
+ * These tests generate a real library,
20
+ * put the configs in each of those places,
21
+ * and run the real `pnpm build`.
19
22
  */
20
23
 
21
24
  /**
22
- * A development babel config: strips TypeScript, but leaves `<template>` as the
23
- * `@ember/template-compiler` call content-tag produced. Publishing this output
24
- * would tie the artifact to one exact ember-source.
25
+ * A development babel config.
26
+ *
27
+ * Strips TypeScript, but leaves `<template>` as the
28
+ * `@ember/template-compiler` call content-tag produced.
29
+ *
30
+ * Publishing this output ties the artifact to one exact ember-source.
25
31
  */
26
32
  const devBabelConfig = `export default {
27
33
  plugins: [
@@ -31,8 +37,10 @@ const devBabelConfig = `export default {
31
37
  `;
32
38
 
33
39
  /**
34
- * A publish babel config: compiles templates to \`precompileTemplate\`, which is
35
- * what a published library ships (the consuming app does the final compile).
40
+ * A publish babel config.
41
+ *
42
+ * Compiles templates to `precompileTemplate`, which is what a published library ships.
43
+ * The consuming app does the final compile.
36
44
  */
37
45
  const publishBabelConfig = `export default {
38
46
  plugins: [
@@ -44,11 +52,14 @@ const publishBabelConfig = `export default {
44
52
  `;
45
53
 
46
54
  /**
47
- * The `tsconfig.json` such a library actually has: it covers the demo app as
48
- * well as `src`, and deliberately has no `isolatedDeclarations` -- dev-only
49
- * code shouldn't be held to a declaration-emit constraint. If the build reads
50
- * this file rather than the publish tsconfig, the guard fails it, which is what
51
- * makes every assertion below meaningful.
55
+ * The `tsconfig.json` such a library actually has.
56
+ *
57
+ * It covers the demo app as well as `src`,
58
+ * and deliberately has no `isolatedDeclarations`:
59
+ * dev-only code must not be held to a declaration-emit constraint.
60
+ *
61
+ * If the build reads this file rather than the publish tsconfig, the guard fails it.
62
+ * That is what makes every assertion below meaningful.
52
63
  */
53
64
  const devTsconfig = `{
54
65
  "extends": "@ember/library-tsconfig",
@@ -61,8 +72,8 @@ const devTsconfig = `{
61
72
  `;
62
73
 
63
74
  /**
64
- * Relative paths in a tsconfig resolve against the file itself, so the copy
65
- * kept in `config/` has to reach back out to `src`.
75
+ * Relative paths in a tsconfig resolve against the file itself,
76
+ * so the copy kept in `config/` has to reach back out to `src`.
66
77
  */
67
78
  function publishTsconfig(directory: "." | "config"): string {
68
79
  const src = directory === "config" ? "../src" : "./src";
@@ -211,9 +222,9 @@ describe("publish configs", () => {
211
222
  // ...and the dev config, which has no template compilation, did not.
212
223
  expect(output).not.toContain("@ember/template-compiler");
213
224
 
214
- // Declarations emitted, so the guard read the publish tsconfig: the
215
- // dev tsconfig.json covering demo-app/ has no isolatedDeclarations and
216
- // would have failed the build.
225
+ // Declarations emitted, so the guard read the publish tsconfig.
226
+ // The dev tsconfig.json covering demo-app/ has no isolatedDeclarations,
227
+ // and would have failed the build.
217
228
  expect(await listFiles(join(project.directory, "dist"))).toContain("index.d.ts");
218
229
  });
219
230
  }
@@ -224,17 +235,18 @@ describe("publish configs", () => {
224
235
 
225
236
  expect(build.exitCode, build.all).toBe(0);
226
237
 
227
- // Nothing compiled the template, so content-tag's output survives -- the
228
- // artifact you don't want to publish, which is why the preference exists.
238
+ // Nothing compiled the template, so content-tag's output survives.
239
+ // That is the artifact you don't want to publish: the reason the preference exists.
229
240
  expect(output).toContain("@ember/template-compiler");
230
241
  expect(output).not.toContain("precompileTemplate");
231
242
  });
232
243
 
233
244
  /**
234
- * Writes `files` into the project and builds with `tsconfigOption` as tsdown's
235
- * `tsconfig`, for the cases about *which* tsconfig the guard ends up reading.
236
- * The publish babel config is always present so these fail for tsconfig
237
- * reasons only.
245
+ * Writes `files` into the project and builds with `tsconfigOption` as tsdown's `tsconfig`.
246
+ * For the cases about *which* tsconfig the guard ends up reading.
247
+ *
248
+ * The publish babel config is always present,
249
+ * so these fail for tsconfig reasons only.
238
250
  */
239
251
  async function buildWithTsconfigOption(
240
252
  tsconfigOption: string,
@@ -295,9 +307,10 @@ describe("publish configs", () => {
295
307
  });
296
308
 
297
309
  it("rejects tsconfig: false while declarations are on", async () => {
298
- // No tsconfig means no isolatedDeclarations, so tsdown falls back to the
299
- // tsc-based pipeline, which can't see compiled .gts and dies with
300
- // "Source file not found". Fail with something actionable instead.
310
+ // No tsconfig means no isolatedDeclarations,
311
+ // so tsdown falls back to the tsc-based pipeline.
312
+ // That pipeline can't see compiled .gts and dies with "Source file not found".
313
+ // Fail with something actionable instead.
301
314
  const { build } = await buildWithTsconfigOption("false");
302
315
 
303
316
  expect(build.exitCode).not.toBe(0);
@@ -6,9 +6,10 @@ import { dirname, join } from "node:path";
6
6
  import { rewriteImportsToMatchFiles } from "#utils/rewrite-imports.js";
7
7
 
8
8
  /**
9
- * Generation renames files (e.g. type removal turns .ts into .js), so
10
- * import specifiers are checked against the emitted project tree:
11
- * whatever file actually exists on disk wins.
9
+ * Generation renames files (e.g. type removal turns .ts into .js),
10
+ * so import specifiers are checked against the emitted project tree.
11
+ *
12
+ * Whatever file actually exists on disk wins.
12
13
  */
13
14
  describe("rewriteImportsToMatchFiles", () => {
14
15
  const dirs: string[] = [];
@@ -7,8 +7,8 @@ import { dirname, join } from "node:path";
7
7
  import type { Project } from "ember.nvp";
8
8
 
9
9
  /**
10
- * Integration test for building a library that uses ember-scoped-css through
11
- * `@nullvoxpopuli/ember-rolldown` (tsdown):
10
+ * Integration test for building a library that uses ember-scoped-css
11
+ * through `@nullvoxpopuli/ember-rolldown` (tsdown):
12
12
  *
13
13
  * - the `scopedCSS()` unplugin (ember-scoped-css/rollup) resolves and rewrites
14
14
  * the `?scoped=` CSS requests the template transform injects
@@ -18,8 +18,10 @@ import type { Project } from "ember.nvp";
18
18
  * `dist/style.css` and keeps the import in `dist/index.js`, so consuming
19
19
  * apps load the styles through the module graph
20
20
  *
21
- * Covers all three authoring modes: co-located `.css`, inline
22
- * `<style scoped>`, and the `scopedClass` pseudo-helper in module code.
21
+ * Covers all three authoring modes:
22
+ * - co-located `.css`
23
+ * - inline `<style scoped>`
24
+ * - the `scopedClass` pseudo-helper in module code
23
25
  */
24
26
 
25
27
  const source = {
@@ -19,7 +19,7 @@ describe("permutate", () => {
19
19
  it("skips duplicate entries", () => {
20
20
  const result = permutate(["a", "b", "b"]);
21
21
 
22
- // Should not include ["a", "b"] twice
22
+ // Must not include ["a", "b"] twice
23
23
  const count = result.filter((perm) => perm.join(",") === "a,b").length;
24
24
  expect(count).toBe(1);
25
25
  });
@@ -77,8 +77,8 @@ describe("permutate", () => {
77
77
  expect(eslintCount).toBeLessThanOrEqual(1);
78
78
  }
79
79
 
80
- // Should have permutations like: ["a"], ["a", "eslint-foo"], ["a", "b"], etc.
81
- // but NOT ["a", "eslint-foo", "eslint-bar"]
80
+ // Expected permutations: ["a"], ["a", "eslint-foo"], ["a", "b"], etc.
81
+ // Never ["a", "eslint-foo", "eslint-bar"]
82
82
  const hasMultipleEslint = result.some(
83
83
  (perm) => perm.filter((item) => item.startsWith("eslint-")).length > 1,
84
84
  );
@@ -19,9 +19,11 @@ export const bases = [minimalApp, minimalAddon, minimalExtension, minimalCustomE
19
19
  export const layers = await discoverLayers();
20
20
 
21
21
  /**
22
- * Layers in the same group are alternatives to each other (one eslint
23
- * config, one test framework): selecting two of them would produce a
24
- * broken project, so permutations never combine them.
22
+ * Layers in the same group are alternatives to each other
23
+ * (one eslint config, one test framework).
24
+ *
25
+ * Selecting two of them produces a broken project,
26
+ * so permutations never combine them.
25
27
  */
26
28
  function exclusivityGroup(name: string): string | undefined {
27
29
  if (name.startsWith("eslint-")) return "eslint";
@@ -190,9 +192,11 @@ export async function expectIsSetup(project: Project, layer: DiscoveredLayer) {
190
192
  }
191
193
 
192
194
  /**
193
- * List every file under `directory` (recursively) as sorted paths relative
194
- * to `directory`. `node_modules` is always excluded; pass
195
- * `{ includeDist: false }` to also exclude the `dist/` build output.
195
+ * List every file under `directory` (recursively),
196
+ * as sorted paths relative to `directory`.
197
+ *
198
+ * `node_modules` is always excluded.
199
+ * Pass `{ includeDist: false }` to also exclude the `dist/` build output.
196
200
  */
197
201
  export async function listFiles(
198
202
  directory: string,