ember.nvp 1.0.0 → 1.1.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 (44) hide show
  1. package/.github/workflows/ci.yml +6 -0
  2. package/.release-plan.json +23 -15
  3. package/CHANGELOG.md +30 -0
  4. package/package.json +1 -1
  5. package/packages/rolldown/README.md +62 -0
  6. package/packages/rolldown/package.json +13 -4
  7. package/packages/rolldown/rolldown.config.js +5 -3
  8. package/packages/rolldown/src/app-reexports.test.ts +220 -0
  9. package/packages/rolldown/src/app-reexports.ts +152 -0
  10. package/packages/rolldown/src/config.ts +1 -1
  11. package/packages/rolldown/src/dts.test.ts +166 -0
  12. package/packages/rolldown/src/transform.test.ts +173 -0
  13. package/src/bases/minimal-extension/extension.test.ts +251 -0
  14. package/src/bases/minimal-extension/files/.env.development +8 -0
  15. package/src/bases/minimal-extension/files/README.md +36 -0
  16. package/src/bases/minimal-extension/files/app/app.ts +21 -0
  17. package/src/bases/minimal-extension/files/app/boot.ts +8 -0
  18. package/src/bases/minimal-extension/files/app/config.ts +22 -0
  19. package/src/bases/minimal-extension/files/app/router.ts +10 -0
  20. package/src/bases/minimal-extension/files/app/templates/application.gts +5 -0
  21. package/src/bases/minimal-extension/files/babel.config.js +49 -0
  22. package/src/bases/minimal-extension/files/index.html +17 -0
  23. package/src/bases/minimal-extension/files/package.json +58 -0
  24. package/src/bases/minimal-extension/files/public/manifest.json +9 -0
  25. package/src/bases/minimal-extension/files/tsconfig.json +13 -0
  26. package/src/bases/minimal-extension/files/vite.config.mjs +6 -0
  27. package/src/bases/minimal-extension/index.js +142 -0
  28. package/src/cli/generator.js +4 -0
  29. package/src/cli/questions/project-type.js +9 -2
  30. package/src/layers/renovate/index.js +4 -3
  31. package/src/layers/typescript/index.js +6 -0
  32. package/src/utils/types.ts +1 -1
  33. package/test/ember.nvp/base-library.test.ts +39 -32
  34. package/test/ember.nvp/layer-publish-checks.test.ts +4 -13
  35. package/test/ember.nvp/layer-qunit.test.ts +13 -30
  36. package/test/ember.nvp/layer-vitest.test.ts +4 -18
  37. package/test/ember.nvp/permutations/app-checks.test.ts +3 -0
  38. package/test/ember.nvp/permutations/extension-1.test.ts +3 -0
  39. package/test/ember.nvp/permutations/extension-2.test.ts +3 -0
  40. package/test/ember.nvp/permutations/extension-checks.test.ts +3 -0
  41. package/test/ember.nvp/permutations/library-checks.test.ts +3 -0
  42. package/test/ember.nvp/permutations/shared.ts +68 -19
  43. package/test/test-helpers.ts +25 -30
  44. package/vitest.config.js +1 -1
@@ -0,0 +1,10 @@
1
+ import EmbroiderRouter from "@embroider/router";
2
+
3
+ import config from "#config";
4
+
5
+ export default class Router extends EmbroiderRouter {
6
+ location = config.locationType;
7
+ rootURL = config.rootURL;
8
+ }
9
+
10
+ Router.map(function () {});
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <h1>Welcome to Ember</h1>
3
+
4
+ {{outlet}}
5
+ </template>
@@ -0,0 +1,49 @@
1
+ import { buildMacros } from "@embroider/macros/babel";
2
+
3
+ const macros = buildMacros({
4
+ configure(config) {
5
+ if (process.env.EMBER_ENV === "test") {
6
+ config.enableRuntimeMode();
7
+ }
8
+ },
9
+ });
10
+
11
+ export default {
12
+ plugins: [
13
+ [
14
+ "@babel/plugin-transform-typescript",
15
+ {
16
+ allExtensions: true,
17
+ onlyRemoveTypeImports: true,
18
+ allowDeclareFields: true,
19
+ },
20
+ ],
21
+ [
22
+ "babel-plugin-ember-template-compilation",
23
+ {
24
+ transforms: [...macros.templateMacros],
25
+ },
26
+ ],
27
+ [
28
+ "module:decorator-transforms",
29
+ {
30
+ runtime: {
31
+ import: import.meta.resolve("decorator-transforms/runtime-esm"),
32
+ },
33
+ },
34
+ ],
35
+ [
36
+ "@babel/plugin-transform-runtime",
37
+ {
38
+ absoluteRuntime: import.meta.dirname,
39
+ useESModules: true,
40
+ regenerator: false,
41
+ },
42
+ ],
43
+ ...macros.babelMacros,
44
+ ],
45
+
46
+ generatorOpts: {
47
+ compact: false,
48
+ },
49
+ };
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Minimal Extension</title>
6
+ <meta name="description" content="" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ </head>
9
+ <body>
10
+ <!--
11
+ Unlike a web app, this boot script cannot be inlined:
12
+ extension pages are served with a Content-Security-Policy of
13
+ `script-src 'self'`, which forbids inline scripts.
14
+ -->
15
+ <script type="module" src="./app/boot.ts"></script>
16
+ </body>
17
+ </html>
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "minimal-extension",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "description": "Your Browser Extension's description here",
6
+ "repository": "",
7
+ "license": "MIT",
8
+ "author": "",
9
+ "type": "module",
10
+ "imports": {
11
+ "#app/*": "./app/*",
12
+ "#config": "./app/config.ts",
13
+ "#components/*": "./app/components/*",
14
+ "#services/*": "./app/services/*",
15
+ "#test-helpers/*": "./tests/helpers/*",
16
+ "#utils/*": "./app/utils/*"
17
+ },
18
+ "exports": {
19
+ "./tests/*": "./tests/*",
20
+ "./*": "./app/*"
21
+ },
22
+ "scripts": {
23
+ "build": "vite build",
24
+ "build:watch": "vite build --watch --mode development",
25
+ "dev": "vite",
26
+ "start": "vite"
27
+ },
28
+ "dependencies": {
29
+ "@embroider/macros": "^1.20.3",
30
+ "@embroider/router": "^3.0.6",
31
+ "@glimmer/component": "^2.1.1",
32
+ "decorator-transforms": "^2.3.2",
33
+ "ember-source": "~7.0.0",
34
+ "ember-strict-application-resolver": "^0.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@babel/core": "^7.29.7",
38
+ "@babel/plugin-transform-runtime": "^7.29.7",
39
+ "@babel/plugin-transform-typescript": "^7.29.7",
40
+ "@babel/runtime": "^7.29.7",
41
+ "@ember/app-tsconfig": "^2.0.0",
42
+ "@embroider/core": "^4.4.2",
43
+ "@glint/ember-tsc": "^1.7.5",
44
+ "@glint/template": "^1.7.7",
45
+ "@glint/tsserver-plugin": "^2.5.5",
46
+ "@nullvoxpopuli/ember-vite": "workspace:*",
47
+ "@rollup/plugin-babel": "^7.1.0",
48
+ "babel-plugin-ember-template-compilation": "^4.0.0",
49
+ "typescript": "^6.0.3",
50
+ "vite": "^8.0.14"
51
+ },
52
+ "engines": {
53
+ "node": ">= 24"
54
+ },
55
+ "ember": {
56
+ "edition": "octane"
57
+ }
58
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "minimal-extension",
4
+ "version": "0.0.0",
5
+ "description": "Your Browser Extension's description here",
6
+ "action": {
7
+ "default_popup": "index.html"
8
+ }
9
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "@ember/app-tsconfig",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "lib": ["esnext", "dom", "dom.iterable"],
6
+ "types": [
7
+ "ember-source/types",
8
+ "@embroider/core/virtual",
9
+ "vite/client",
10
+ "@glint/ember-tsc/types"
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from "vite";
2
+ import { ember } from "@nullvoxpopuli/ember-vite";
3
+
4
+ export default defineConfig({
5
+ plugins: [ember()],
6
+ });
@@ -0,0 +1,142 @@
1
+ import { packageJson } from "ember-apply";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { getLatest } from "#utils/npm.js";
5
+ import { applyFolderTo } from "#utils/fs.js";
6
+ import { removeConfiguredPlugin } from "#utils/babel.js";
7
+
8
+ /**
9
+ * Minimal Extension Base
10
+ *
11
+ * Provides the absolute bare minimum for a browser extension (Manifest V3)
12
+ * whose popup is an Ember app:
13
+ * - type: "module" in package.json
14
+ * - public/manifest.json copied verbatim into dist
15
+ * - index.html popup booting from an external script (extension pages
16
+ * forbid inline scripts via CSP)
17
+ * - No testing framework
18
+ * - No linting or formatting
19
+ * - No ember-welcome-page
20
+ */
21
+ export default {
22
+ label: "Minimal Extension Base",
23
+ description: "Bare minimum browser extension structure with an Ember popup",
24
+
25
+ /**
26
+ * 1. Apply files
27
+ * a. Remove TS if needed
28
+ * 2. Remove TS deps/files if needed
29
+ * 3. Update name(s)
30
+ * 4. Upgrade in-range dependencies
31
+ * 5. Update an existing babel config, if any
32
+ *
33
+ * @param {import('#utils/project.js').Project} project
34
+ */
35
+ async run(project) {
36
+ await applyFiles(project);
37
+ await updateName(project);
38
+ await makeJavaScript(project);
39
+ await upgradeDependencies(project);
40
+ await updateBabelConfig(project);
41
+ },
42
+ };
43
+
44
+ /**
45
+ * @param {import('#utils/project.js').Project} project
46
+ */
47
+ async function updateBabelConfig(project) {
48
+ if (await project.hasOrWantsLayer("typescript")) return;
49
+
50
+ await removeConfiguredPlugin(project, "@babel/plugin-transform-typescript");
51
+ }
52
+
53
+ /**
54
+ * @param {import('#utils/project.js').Project} project
55
+ */
56
+ async function applyFiles(project) {
57
+ let filePath = join(import.meta.dirname, "files");
58
+
59
+ await applyFolderTo(filePath, project);
60
+ }
61
+
62
+ /**
63
+ * Operates on known files where the name matters
64
+ *
65
+ * @param {import('#utils/project.js').Project} project
66
+ */
67
+ async function updateName(project) {
68
+ await packageJson.modify((json) => {
69
+ json.name = project.desires.name;
70
+ }, project.directory);
71
+
72
+ if (!project.hasFile("public/manifest.json")) return;
73
+
74
+ let manifestPath = project.path("public/manifest.json");
75
+ let manifest = JSON.parse(await readFile(manifestPath, "utf-8"));
76
+
77
+ manifest.name = project.desires.name;
78
+
79
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
80
+ }
81
+
82
+ /**
83
+ * @param {import('#utils/project.js').Project} project
84
+ */
85
+ async function makeJavaScript(project) {
86
+ if (await project.hasOrWantsLayer("typescript")) return;
87
+
88
+ /**
89
+ * We don't actually remove anything, because we want intellisense for JS
90
+ *
91
+ * But perhaps for the sake of minimal, we do remoev it.
92
+ * And we add a layer later for JSDoc ased TS or something
93
+ */
94
+ await packageJson.removeDevDependencies(
95
+ [
96
+ "@ember/app-tsconfig",
97
+ "@glint/ember-tsc",
98
+ "@glint/template",
99
+ "@glint/tsserver-plugin",
100
+ "typescript",
101
+ ],
102
+ project.directory,
103
+ );
104
+
105
+ await project.removeFile("tsconfig.json");
106
+
107
+ await packageJson.modify((json) => {
108
+ json.imports ||= {};
109
+ json.imports["#config"] = "./app/config.js";
110
+ }, project.directory);
111
+
112
+ /**
113
+ * The import-rewriting pass only handles module files; the popup's
114
+ * <script src> points at the boot module by path, so it has to follow
115
+ * the .ts -> .js rename by hand.
116
+ */
117
+ if (!project.hasFile("index.html")) return;
118
+
119
+ let indexPath = project.path("index.html");
120
+ let indexHtml = await readFile(indexPath, "utf-8");
121
+
122
+ await writeFile(indexPath, indexHtml.replace("./app/boot.ts", "./app/boot.js"));
123
+ }
124
+
125
+ /**
126
+ * Bumps in-range only.
127
+ * Majors will need to go through PR to this repo.
128
+ *
129
+ * @param {import('#utils/project.js').Project} project
130
+ */
131
+ async function upgradeDependencies(project) {
132
+ let existing = await packageJson.read(project.directory);
133
+
134
+ await packageJson.modify(async (json) => {
135
+ if (json.dependencies) {
136
+ Object.assign(json.dependencies, await getLatest(existing.dependencies));
137
+ }
138
+ if (json.devDependencies) {
139
+ Object.assign(json.devDependencies, await getLatest(existing.devDependencies));
140
+ }
141
+ }, project.directory);
142
+ }
@@ -1,6 +1,7 @@
1
1
  import { mkdir, rm } from "node:fs/promises";
2
2
 
3
3
  import baseApp from "#bases/minimal-app";
4
+ import baseExtension from "#bases/minimal-extension";
4
5
  import baseLibrary from "#bases/minimal-library";
5
6
  import { consolidateLintingScripts } from "../consolidators/linting.js";
6
7
  import { hasGit } from "#utils/git.js";
@@ -24,6 +25,9 @@ export async function generateProject(project, replaceOrUpdate) {
24
25
  case "library":
25
26
  await baseLibrary.run(project);
26
27
  break;
28
+ case "extension":
29
+ await baseExtension.run(project);
30
+ break;
27
31
  }
28
32
 
29
33
  /**
@@ -3,12 +3,13 @@ import { answers, printArgInUse } from "#args";
3
3
 
4
4
  /**
5
5
  * addon is alias for library
6
+ * web-extension is alias for extension
6
7
  */
7
- const SUPPORTED = new Set(["app", "library", "addon"]);
8
+ const SUPPORTED = new Set(["app", "library", "addon", "extension", "web-extension"]);
8
9
 
9
10
  /**
10
11
  * @param {string | undefined} selected
11
- * @returns {selected is "app" | "library" | "addon"}
12
+ * @returns {selected is "app" | "library" | "addon" | "extension" | "web-extension"}
12
13
  */
13
14
  function isValid(selected) {
14
15
  if (!selected) return false;
@@ -25,6 +26,7 @@ export async function askProjectType() {
25
26
  printArgInUse("type", answers.type);
26
27
 
27
28
  if (answers.type === "addon") return "library";
29
+ if (answers.type === "web-extension") return "extension";
28
30
 
29
31
  return answers.type;
30
32
  }
@@ -38,6 +40,11 @@ export async function askProjectType() {
38
40
  label: "library",
39
41
  hint: "sharable code, usable by other libraries and apps alike",
40
42
  },
43
+ {
44
+ value: "extension",
45
+ label: "browser extension",
46
+ hint: "Manifest V3 extension whose popup is an Ember app",
47
+ },
41
48
  ],
42
49
  });
43
50
 
@@ -14,10 +14,11 @@ export default {
14
14
  return;
15
15
  }
16
16
 
17
+ // extensions aren't published to npm either, so they follow the app config
17
18
  let source =
18
- project.type === "app"
19
- ? join(import.meta.dirname, "files/app.json5")
20
- : join(import.meta.dirname, "files/library.json5");
19
+ project.type === "library"
20
+ ? join(import.meta.dirname, "files/library.json5")
21
+ : join(import.meta.dirname, "files/app.json5");
21
22
 
22
23
  let destination = join(project.directory, ".github/renovate.json5");
23
24
 
@@ -7,6 +7,7 @@ import { getLatest } from "#utils/npm.js";
7
7
 
8
8
  const bases = join(import.meta.dirname, "../../bases");
9
9
  const appBase = join(bases, "minimal-app/files");
10
+ const extensionBase = join(bases, "minimal-extension/files");
10
11
  const libraryBase = join(bases, "minimal-library/files");
11
12
 
12
13
  const sharedDeps = {
@@ -149,6 +150,11 @@ async function addTSConfig(project) {
149
150
  return;
150
151
  }
151
152
 
153
+ if (project.type === "extension") {
154
+ await cp(join(extensionBase, "tsconfig.json"), project.path("tsconfig.json"));
155
+ return;
156
+ }
157
+
152
158
  if (project.type === "library") {
153
159
  await cp(join(libraryBase, "tsconfig.json"), project.path("tsconfig.json"));
154
160
  }
@@ -1,6 +1,6 @@
1
1
  import { Project } from "./project.js";
2
2
  export type PackageManager = "pnpm" | "npm";
3
- export type ProjectType = "app" | "library";
3
+ export type ProjectType = "app" | "library" | "extension";
4
4
 
5
5
  export interface Layer {
6
6
  /**
@@ -1,9 +1,9 @@
1
1
  import { describe, it, beforeAll, afterAll, expect } from "vitest";
2
- import { generate, mktemp, pinYukuParser } from "#test-helpers";
2
+ import { generate, listFiles, mktemp } from "#test-helpers";
3
3
  import { writeLibrarySource } from "./library-src-fixtures.ts";
4
4
  import { execa } from "execa";
5
- import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
6
- import { join, relative, sep } from "node:path";
5
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
+ import { join } from "node:path";
7
7
 
8
8
  import type { Project } from "ember.nvp";
9
9
 
@@ -14,23 +14,7 @@ import type { Project } from "ember.nvp";
14
14
  * them.
15
15
  */
16
16
 
17
- async function listFiles(directory: string): Promise<string[]> {
18
- const entries = await readdir(directory, { withFileTypes: true, recursive: true });
19
-
20
- return entries
21
- .filter((entry) => entry.isFile())
22
- .map((entry) => relative(directory, join(entry.parentPath, entry.name)))
23
- .filter((path) => !path.split(sep).includes("node_modules"))
24
- .sort();
25
- }
26
-
27
- async function read(project: Project, filePath: string): Promise<string> {
28
- return readFile(join(project.directory, filePath), "utf-8");
29
- }
30
-
31
17
  async function installAndBuild(project: Project) {
32
- await pinYukuParser(project);
33
-
34
18
  let install = await execa("pnpm install", { cwd: project.directory, shell: true });
35
19
  expect(install.exitCode).toBe(0);
36
20
 
@@ -68,11 +52,11 @@ describe("base: minimal-library", () => {
68
52
  ]
69
53
  `);
70
54
 
71
- expect(await read(project, "src/index.js")).toBe("");
55
+ expect(await project.read("src/index.js")).toBe("");
72
56
  });
73
57
 
74
58
  it("is publishable", async () => {
75
- let manifest = JSON.parse(await read(project, "package.json"));
59
+ let manifest = JSON.parse((await project.read("package.json"))!);
76
60
 
77
61
  // The template is private (it lives in a workspace); the generated
78
62
  // library must not be
@@ -80,14 +64,14 @@ describe("base: minimal-library", () => {
80
64
  });
81
65
 
82
66
  it("has no TypeScript leftovers", async () => {
83
- let manifest = JSON.parse(await read(project, "package.json"));
67
+ let manifest = JSON.parse((await project.read("package.json"))!);
84
68
 
85
69
  expect(manifest.devDependencies).not.toHaveProperty("typescript");
86
70
  expect(manifest.devDependencies).not.toHaveProperty("@ember/library-tsconfig");
87
71
  // No declarations are emitted without types
88
72
  expect(JSON.stringify(manifest.exports)).not.toContain("types");
89
73
 
90
- expect(await read(project, "tsdown.config.js")).toMatchInlineSnapshot(`
74
+ expect(await project.read("tsdown.config.js")).toMatchInlineSnapshot(`
91
75
  "import { defineConfig } from "tsdown";
92
76
  import { ember } from "@nullvoxpopuli/ember-rolldown";
93
77
 
@@ -131,7 +115,7 @@ describe("base: minimal-library", () => {
131
115
  await writeLibrarySource(project, "javascript");
132
116
  await installAndBuild(project);
133
117
 
134
- let output = await read(project, "dist/index.js");
118
+ let output = await project.read("dist/index.js");
135
119
 
136
120
  // Published libraries ship precompileTemplate (the consuming app does
137
121
  // the final compile), never wire format
@@ -167,12 +151,11 @@ describe("base: minimal-library", () => {
167
151
  ]
168
152
  `);
169
153
 
170
- expect(await read(project, "src/index.ts")).toBe("");
154
+ expect(await project.read("src/index.ts")).toBe("");
171
155
  });
172
156
 
173
157
  it("type checks", async () => {
174
158
  await writeLibrarySource(project, "typescript");
175
- await pinYukuParser(project);
176
159
 
177
160
  let install = await execa("pnpm install", { cwd: project.directory, shell: true });
178
161
  expect(install.exitCode).toBe(0);
@@ -184,16 +167,40 @@ describe("base: minimal-library", () => {
184
167
  it("builds, including declarations", async () => {
185
168
  await installAndBuild(project);
186
169
 
187
- let output = await read(project, "dist/index.js");
170
+ let output = await project.read("dist/index.js");
188
171
 
189
172
  expect(output).toContain("precompileTemplate");
190
173
  expect(output).not.toContain("createTemplateFactory");
191
174
 
192
- let declarations = await read(project, "dist/index.d.ts");
193
-
194
- expect(declarations).toContain("declare class Greeting extends Component<GreetingSignature>");
195
- expect(declarations).toContain("declare const Badge: TOC<BadgeSignature>");
196
- expect(declarations).toContain("declare function add(a: number, b: number): number");
175
+ let declarations = await project.read("dist/index.d.ts");
176
+
177
+ expect(declarations).toMatchInlineSnapshot(`
178
+ "import { TOC } from "@ember/component/template-only";
179
+ import Component from "@glimmer/component";
180
+ //#region src/components/badge.d.ts
181
+ interface BadgeSignature {
182
+ Element: HTMLSpanElement;
183
+ Blocks: {
184
+ default: [];
185
+ };
186
+ }
187
+ declare const Badge: TOC<BadgeSignature>;
188
+ //#endregion
189
+ //#region src/components/greeting.d.ts
190
+ interface GreetingSignature {
191
+ Element: HTMLParagraphElement;
192
+ Args: {
193
+ name: string;
194
+ };
195
+ }
196
+ declare class Greeting extends Component<GreetingSignature> {}
197
+ //#endregion
198
+ //#region src/utils/math.d.ts
199
+ declare function add(a: number, b: number): number;
200
+ //#endregion
201
+ export { Badge, type BadgeSignature, Greeting, type GreetingSignature, add };
202
+ //# sourceMappingURL=index.d.ts.map"
203
+ `);
197
204
 
198
205
  expect(await listFiles(join(project.directory, "dist"))).toMatchInlineSnapshot(`
199
206
  [
@@ -1,8 +1,7 @@
1
1
  import { describe, it, beforeAll, afterAll, expect } from "vitest";
2
- import { generate, pinYukuParser } from "#test-helpers";
2
+ import { generate } from "#test-helpers";
3
3
  import { execa } from "execa";
4
- import { readFile, rm } from "node:fs/promises";
5
- import { join } from "node:path";
4
+ import { rm } from "node:fs/promises";
6
5
 
7
6
  import type { Project } from "ember.nvp";
8
7
 
@@ -12,10 +11,6 @@ import type { Project } from "ember.nvp";
12
11
  * output.
13
12
  */
14
13
 
15
- async function read(project: Project, filePath: string): Promise<string> {
16
- return readFile(join(project.directory, filePath), "utf-8");
17
- }
18
-
19
14
  describe("layers: publint + are-the-types-wrong", () => {
20
15
  const dirs: string[] = [];
21
16
 
@@ -40,7 +35,7 @@ describe("layers: publint + are-the-types-wrong", () => {
40
35
  });
41
36
 
42
37
  it("wires both checks into the build", async () => {
43
- expect(await read(project, "tsdown.config.js")).toMatchInlineSnapshot(`
38
+ expect(await project.read("tsdown.config.js")).toMatchInlineSnapshot(`
44
39
  "import { defineConfig } from "tsdown";
45
40
  import { ember } from "@nullvoxpopuli/ember-rolldown";
46
41
  export default defineConfig({ entry: ["./src/index.ts"], plugins: [ember()], attw: { profile: "esm-only" }, publint: true })"
@@ -48,8 +43,6 @@ describe("layers: publint + are-the-types-wrong", () => {
48
43
  });
49
44
 
50
45
  it("both checks run and pass in the build", async () => {
51
- await pinYukuParser(project);
52
-
53
46
  let install = await execa("pnpm install", { cwd: project.directory, shell: true });
54
47
  expect(install.exitCode).toBe(0);
55
48
 
@@ -80,7 +73,7 @@ describe("layers: publint + are-the-types-wrong", () => {
80
73
  });
81
74
 
82
75
  it("wires publint only (no declarations to check)", async () => {
83
- expect(await read(project, "tsdown.config.js")).toMatchInlineSnapshot(`
76
+ expect(await project.read("tsdown.config.js")).toMatchInlineSnapshot(`
84
77
  "import { defineConfig } from "tsdown";
85
78
  import { ember } from "@nullvoxpopuli/ember-rolldown";
86
79
  export default defineConfig({ entry: ["./src/index.js"], dts: false, plugins: [ember()], publint: true })"
@@ -88,8 +81,6 @@ describe("layers: publint + are-the-types-wrong", () => {
88
81
  });
89
82
 
90
83
  it("publint runs and passes in the build", async () => {
91
- await pinYukuParser(project);
92
-
93
84
  let install = await execa("pnpm install", { cwd: project.directory, shell: true });
94
85
  expect(install.exitCode).toBe(0);
95
86