ember.nvp 1.4.0 → 1.6.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 +4 -22
- package/CHANGELOG.md +52 -0
- package/package.json +1 -1
- package/packages/rolldown/index.ts +2 -3
- package/packages/rolldown/package.json +12 -5
- package/packages/rolldown/src/app-reexports.ts +2 -2
- package/packages/rolldown/src/plugin-like.ts +23 -0
- package/packages/rolldown/src/published-types.test.ts +102 -0
- package/packages/rolldown/src/transform.test.ts +50 -2
- package/packages/rolldown/src/transform.ts +8 -1
- package/packages/rolldown/tsdown.config.ts +11 -0
- package/src/bases/minimal-app/app.test.ts +102 -1
- package/src/bases/minimal-app/files/app/app.ts +2 -1
- package/src/bases/minimal-app/files/babel.config.js +17 -1
- package/src/bases/minimal-app/files/package.json +2 -2
- package/src/bases/minimal-extension/files/app/app.ts +1 -1
- package/src/bases/minimal-extension/files/babel.config.js +17 -1
- package/src/bases/minimal-extension/files/package.json +2 -2
- package/src/bases/minimal-library/files/package.json +1 -1
- package/src/layers/eslint-bundled-ember/index.js +2 -2
- package/src/layers/eslint-bundled-nvp/index.js +2 -2
- package/src/layers/eslint-ejected/index.js +3 -3
- package/src/layers/qunit/index.js +0 -1
- package/src/layers/qunit/library-files/tests/test-helper.ts +1 -1
- package/src/layers/readme/index.js +16 -16
- package/src/utils/babel.js +20 -2
- package/test/ember.nvp/inspector-support.test.ts +13 -13
- package/test/ember.nvp/layer-inspector-support.test.ts +2 -2
- package/test/ember.nvp/layer-readme.test.ts +16 -16
- package/test/ember.nvp/layer-vitest.test.ts +1 -1
- package/packages/rolldown/rolldown.config.js +0 -23
package/.release-plan.json
CHANGED
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
"solution": {
|
|
3
3
|
"ember.nvp": {
|
|
4
4
|
"impact": "minor",
|
|
5
|
-
"oldVersion": "1.
|
|
6
|
-
"newVersion": "1.
|
|
5
|
+
"oldVersion": "1.5.0",
|
|
6
|
+
"newVersion": "1.6.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 :house: Internal"
|
|
16
12
|
}
|
|
17
13
|
],
|
|
18
14
|
"pkgJSONPath": "./package.json"
|
|
@@ -21,25 +17,11 @@
|
|
|
21
17
|
"oldVersion": "1.1.0"
|
|
22
18
|
},
|
|
23
19
|
"@nullvoxpopuli/ember-rolldown": {
|
|
24
|
-
"
|
|
25
|
-
"oldVersion": "2.5.0",
|
|
26
|
-
"newVersion": "2.6.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 :house: Internal"
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"pkgJSONPath": "./packages/rolldown/package.json"
|
|
20
|
+
"oldVersion": "2.7.0"
|
|
39
21
|
},
|
|
40
22
|
"@nullvoxpopuli/ember-vite": {
|
|
41
23
|
"oldVersion": "1.1.0"
|
|
42
24
|
}
|
|
43
25
|
},
|
|
44
|
-
"description": "## Release (2026-
|
|
26
|
+
"description": "## Release (2026-09-10)\n\n* ember.nvp 1.6.0 (minor)\n\n#### :rocket: Enhancement\n* `ember.nvp`\n * [#129](https://github.com/NullVoxPopuli/ember.nvp/pull/129) Add routes import ([@NullVoxPopuli](https://github.com/NullVoxPopuli))\n * [#127](https://github.com/NullVoxPopuli/ember.nvp/pull/127) Update eslint (+ deps) in layers ([@tcjr](https://github.com/tcjr))\n\n#### Committers: 2\n- Tom Carter ([@tcjr](https://github.com/tcjr))\n- [@NullVoxPopuli](https://github.com/NullVoxPopuli)\n"
|
|
45
27
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Release (2026-09-10)
|
|
4
|
+
|
|
5
|
+
* ember.nvp 1.6.0 (minor)
|
|
6
|
+
|
|
7
|
+
#### :rocket: Enhancement
|
|
8
|
+
* `ember.nvp`
|
|
9
|
+
* [#129](https://github.com/NullVoxPopuli/ember.nvp/pull/129) Add routes import ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
10
|
+
* [#127](https://github.com/NullVoxPopuli/ember.nvp/pull/127) Update eslint (+ deps) in layers ([@tcjr](https://github.com/tcjr))
|
|
11
|
+
|
|
12
|
+
#### Committers: 2
|
|
13
|
+
- Tom Carter ([@tcjr](https://github.com/tcjr))
|
|
14
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
15
|
+
|
|
16
|
+
## Release (2026-08-18)
|
|
17
|
+
|
|
18
|
+
* ember.nvp 1.5.0 (minor)
|
|
19
|
+
|
|
20
|
+
#### :rocket: Enhancement
|
|
21
|
+
* `ember.nvp`
|
|
22
|
+
* [#125](https://github.com/NullVoxPopuli/ember.nvp/pull/125) Update to 7.2, drop ember-strict-application-resolver polyfill ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
23
|
+
|
|
24
|
+
#### :bug: Bug Fix
|
|
25
|
+
* `ember.nvp`
|
|
26
|
+
* [#121](https://github.com/NullVoxPopuli/ember.nvp/pull/121) Fix initial README formatting ([@tcjr](https://github.com/tcjr))
|
|
27
|
+
* [#122](https://github.com/NullVoxPopuli/ember.nvp/pull/122) Strip debug code from production app builds ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
28
|
+
|
|
29
|
+
#### Committers: 2
|
|
30
|
+
- Tom Carter ([@tcjr](https://github.com/tcjr))
|
|
31
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
32
|
+
|
|
33
|
+
## Release (2026-08-07)
|
|
34
|
+
|
|
35
|
+
* @nullvoxpopuli/ember-rolldown 2.7.0 (minor)
|
|
36
|
+
|
|
37
|
+
#### :rocket: Enhancement
|
|
38
|
+
* `@nullvoxpopuli/ember-rolldown`
|
|
39
|
+
* [#118](https://github.com/NullVoxPopuli/ember.nvp/pull/118) rolldown: ship type declarations ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
40
|
+
|
|
41
|
+
#### Committers: 1
|
|
42
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
43
|
+
|
|
44
|
+
## Release (2026-08-05)
|
|
45
|
+
|
|
46
|
+
* @nullvoxpopuli/ember-rolldown 2.6.1 (patch)
|
|
47
|
+
|
|
48
|
+
#### :bug: Bug Fix
|
|
49
|
+
* `@nullvoxpopuli/ember-rolldown`
|
|
50
|
+
* [#115](https://github.com/NullVoxPopuli/ember.nvp/pull/115) rolldown: don't resolve absolute specifiers against the importer's directory ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
|
|
51
|
+
|
|
52
|
+
#### Committers: 1
|
|
53
|
+
- [@NullVoxPopuli](https://github.com/NullVoxPopuli)
|
|
54
|
+
|
|
3
55
|
## Release (2026-08-03)
|
|
4
56
|
|
|
5
57
|
* ember.nvp 1.4.0 (minor)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember.nvp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.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",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { Plugin } from "rolldown";
|
|
2
|
-
|
|
3
1
|
import { emberBabel, type BabelOptions } from "./src/babel.ts";
|
|
4
2
|
import { emberConfig } from "./src/config.ts";
|
|
5
3
|
import { emberExternals } from "./src/externals.ts";
|
|
6
4
|
import { emberIsolatedDeclarations } from "./src/isolated-declarations.ts";
|
|
7
5
|
import { emberTransform } from "./src/transform.ts";
|
|
6
|
+
import type { RolldownPluginLike } from "./src/plugin-like.ts";
|
|
8
7
|
|
|
9
8
|
interface Config {
|
|
10
9
|
/**
|
|
@@ -49,7 +48,7 @@ interface Config {
|
|
|
49
48
|
* });
|
|
50
49
|
* ```
|
|
51
50
|
*/
|
|
52
|
-
export function ember(config: Config = {}):
|
|
51
|
+
export function ember(config: Config = {}): RolldownPluginLike[] {
|
|
53
52
|
return [
|
|
54
53
|
emberConfig(),
|
|
55
54
|
emberIsolatedDeclarations(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nullvoxpopuli/ember-rolldown",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Meta plugin for building ember v2 libraries/addons with rolldown & tsdown.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -11,9 +11,16 @@
|
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"exports": {
|
|
14
|
-
".":
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./app-reexports": {
|
|
19
|
+
"types": "./dist/app-reexports.d.ts",
|
|
20
|
+
"default": "./dist/app-reexports.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"types": "dist/index.d.ts"
|
|
17
24
|
},
|
|
18
25
|
"keywords": [
|
|
19
26
|
"rolldown",
|
|
@@ -31,7 +38,7 @@
|
|
|
31
38
|
"directory": "packages/rolldown"
|
|
32
39
|
},
|
|
33
40
|
"scripts": {
|
|
34
|
-
"build": "
|
|
41
|
+
"build": "tsdown",
|
|
35
42
|
"prepack": "pnpm build"
|
|
36
43
|
},
|
|
37
44
|
"packageManager": "pnpm@10.28.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, extname, join, matchesGlob, relative, resolve, sep } from "node:path";
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { RolldownPluginLike } from "./plugin-like.ts";
|
|
5
5
|
|
|
6
6
|
export interface AppReexportsOptions {
|
|
7
7
|
/**
|
|
@@ -79,7 +79,7 @@ export interface AppReexportsOptions {
|
|
|
79
79
|
export function appReexports(
|
|
80
80
|
includeOrOptions: string | string[] | AppReexportsOptions = {},
|
|
81
81
|
options: Omit<AppReexportsOptions, "include"> = {},
|
|
82
|
-
):
|
|
82
|
+
): RolldownPluginLike {
|
|
83
83
|
const resolved =
|
|
84
84
|
typeof includeOrOptions === "string"
|
|
85
85
|
? { ...options, include: [includeOrOptions] }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What this package hands back: an object that rolldown and tsdown accept in
|
|
3
|
+
* `plugins`.
|
|
4
|
+
*
|
|
5
|
+
* Structurally this *is* rolldown's `Plugin` -- `name` is its only required
|
|
6
|
+
* member, every hook is optional -- so the two are assignable in both
|
|
7
|
+
* directions: a consumer who imports rolldown's own type can still write
|
|
8
|
+
* `const plugins: Plugin[] = ember()`, and tsdown's `plugins` option lists
|
|
9
|
+
* `{ name: string }` among the shapes it takes.
|
|
10
|
+
*
|
|
11
|
+
* Declaring it here rather than re-exporting rolldown's type is what keeps
|
|
12
|
+
* `rolldown` out of the published declarations. Otherwise it has to become a
|
|
13
|
+
* runtime `dependency` purely so consumers can resolve a type: leave it a
|
|
14
|
+
* devDependency and the declaration bundler inlines a ~200kB private copy of
|
|
15
|
+
* rolldown's types instead, nominally distinct from the consumer's own.
|
|
16
|
+
*
|
|
17
|
+
* The precise hook signatures still apply inside this package -- each plugin
|
|
18
|
+
* function is typed with rolldown's real `Plugin` (a devDependency), and this
|
|
19
|
+
* type only widens what crosses the package boundary.
|
|
20
|
+
*/
|
|
21
|
+
export interface RolldownPluginLike {
|
|
22
|
+
name: string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { readdir, readFile, rm, stat } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This package's own published shape: consumers write their build config in
|
|
9
|
+
* TypeScript, so `import { ember } from "@nullvoxpopuli/ember-rolldown"` has to
|
|
10
|
+
* carry types. Without them it is an implicit `any` (TS7016), and a config file
|
|
11
|
+
* silently stops being type-checked.
|
|
12
|
+
*/
|
|
13
|
+
const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
+
|
|
15
|
+
interface Manifest {
|
|
16
|
+
dependencies: Record<string, string>;
|
|
17
|
+
peerDependencies: Record<string, string>;
|
|
18
|
+
publishConfig: { exports: Record<string, Record<string, string>> };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function readManifest(): Promise<Manifest> {
|
|
22
|
+
return JSON.parse(await readFile(path.join(packageDir, "package.json"), "utf8")) as Manifest;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function exists(relative: string) {
|
|
26
|
+
return Boolean(await stat(path.join(packageDir, relative)).catch(() => null));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function declarations() {
|
|
30
|
+
const files = (await readdir(path.join(packageDir, "dist"))).filter((file) =>
|
|
31
|
+
file.endsWith(".d.ts"),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return Object.fromEntries(
|
|
35
|
+
await Promise.all(
|
|
36
|
+
files.map(
|
|
37
|
+
async (file) =>
|
|
38
|
+
[file, await readFile(path.join(packageDir, "dist", file), "utf8")] as const,
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe("published types", () => {
|
|
45
|
+
beforeAll(async () => {
|
|
46
|
+
// `clean` is on, but don't let these assertions depend on that: stale
|
|
47
|
+
// artifacts from an earlier build satisfy every one of them on their own
|
|
48
|
+
await rm(path.join(packageDir, "dist"), { recursive: true, force: true });
|
|
49
|
+
await execa("pnpm", ["build"], { cwd: packageDir });
|
|
50
|
+
}, 120_000);
|
|
51
|
+
|
|
52
|
+
it("every publishConfig export declares types, and they exist", async () => {
|
|
53
|
+
const manifest = await readManifest();
|
|
54
|
+
const entries = Object.entries(manifest.publishConfig.exports);
|
|
55
|
+
|
|
56
|
+
expect(entries.length).toBeGreaterThan(0);
|
|
57
|
+
|
|
58
|
+
for (const [subpath, conditions] of entries) {
|
|
59
|
+
expect(conditions, `${subpath} declares types`).toHaveProperty("types");
|
|
60
|
+
expect(await exists(conditions["types"]!), `${subpath} -> ${conditions["types"]}`).toBe(true);
|
|
61
|
+
expect(await exists(conditions["default"]!), `${subpath} -> ${conditions["default"]}`).toBe(
|
|
62
|
+
true,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A declaration may only reach for packages a consumer is guaranteed to have.
|
|
69
|
+
* Reference a devDependency and there are two ways to lose, both quiet:
|
|
70
|
+
* the specifier survives and consumers can't resolve it (`skipLibCheck` hides
|
|
71
|
+
* that, degrading the type to an error type), or the declaration bundler
|
|
72
|
+
* inlines the whole type surface — a ~200kB copy of rolldown's types, in the
|
|
73
|
+
* case that prompted this test, nominally distinct from the consumer's own.
|
|
74
|
+
*
|
|
75
|
+
* `ember()` returns plugins, so `RolldownPluginLike` exists to keep rolldown
|
|
76
|
+
* on the devDependency side of that line.
|
|
77
|
+
*/
|
|
78
|
+
it("declarations only reference packages consumers have", async () => {
|
|
79
|
+
const manifest = await readManifest();
|
|
80
|
+
const available = new Set([
|
|
81
|
+
...Object.keys(manifest.dependencies),
|
|
82
|
+
...Object.keys(manifest.peerDependencies),
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
for (const [file, contents] of Object.entries(await declarations())) {
|
|
86
|
+
const specifiers = [...contents.matchAll(/^import .* from "([^"]+)";$/gm)]
|
|
87
|
+
.map(([, specifier]) => specifier!)
|
|
88
|
+
.filter((specifier) => !specifier.startsWith("."));
|
|
89
|
+
|
|
90
|
+
for (const specifier of specifiers) {
|
|
91
|
+
const owner = specifier.startsWith("@")
|
|
92
|
+
? specifier.split("/").slice(0, 2).join("/")
|
|
93
|
+
: specifier.split("/")[0]!;
|
|
94
|
+
|
|
95
|
+
expect(available, `${file} imports ${specifier}`).toContain(owner);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// an inlined copy of a bundler's types, rather than an import of them
|
|
99
|
+
expect(contents, `${file} inlines rolldown's types`).not.toMatch(/interface PluginContext/);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -2,6 +2,7 @@ import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { rolldown } from "rolldown";
|
|
5
|
+
import type { Plugin } from "rolldown";
|
|
5
6
|
import { describe, expect, it } from "vitest";
|
|
6
7
|
|
|
7
8
|
import { emberTransform } from "./transform.ts";
|
|
@@ -15,7 +16,10 @@ import { emberTransform } from "./transform.ts";
|
|
|
15
16
|
*/
|
|
16
17
|
async function bundle(
|
|
17
18
|
files: Record<string, string>,
|
|
18
|
-
{
|
|
19
|
+
{
|
|
20
|
+
input = ["index.ts"],
|
|
21
|
+
plugins = () => [],
|
|
22
|
+
}: { input?: string[]; plugins?: (dir: string) => Plugin[] } = {},
|
|
19
23
|
): Promise<string> {
|
|
20
24
|
const dir = await mkdtemp(path.join(tmpdir(), "ember-rolldown-build-"));
|
|
21
25
|
|
|
@@ -29,7 +33,7 @@ async function bundle(
|
|
|
29
33
|
|
|
30
34
|
const build = await rolldown({
|
|
31
35
|
input: input.map((relative) => path.join(dir, relative)),
|
|
32
|
-
plugins: [emberTransform()],
|
|
36
|
+
plugins: [emberTransform(), ...plugins(dir)],
|
|
33
37
|
external: (id) => !isLocal(id),
|
|
34
38
|
onwarn() {},
|
|
35
39
|
});
|
|
@@ -174,6 +178,50 @@ describe("emberTransform (full plugin via rolldown)", () => {
|
|
|
174
178
|
`);
|
|
175
179
|
});
|
|
176
180
|
|
|
181
|
+
it("resolves an absolute .gts specifier imported from a plugin's virtual module", async () => {
|
|
182
|
+
/**
|
|
183
|
+
* The shape a code-generating plugin emits: a virtual module (id prefixed
|
|
184
|
+
* with `\0`, so it exists nowhere on disk) whose generated source imports
|
|
185
|
+
* real files by absolute path, because it has no directory to be relative
|
|
186
|
+
* to. `path.dirname` of such an id is `"\0."`, so the specifier must not be
|
|
187
|
+
* resolved against the importer's directory.
|
|
188
|
+
*/
|
|
189
|
+
const registry = (dir: string): Plugin[] => {
|
|
190
|
+
const source = "./registry?virtual=views";
|
|
191
|
+
const virtualId = `\0${source}`;
|
|
192
|
+
|
|
193
|
+
return [
|
|
194
|
+
{
|
|
195
|
+
name: "test:virtual-registry",
|
|
196
|
+
resolveId(id) {
|
|
197
|
+
return id === source ? virtualId : null;
|
|
198
|
+
},
|
|
199
|
+
load(id) {
|
|
200
|
+
if (id !== virtualId) return null;
|
|
201
|
+
|
|
202
|
+
return [
|
|
203
|
+
`import example from '${path.join(dir, "components/view/example.gts")}';`,
|
|
204
|
+
`export const views = { example };`,
|
|
205
|
+
].join("\n");
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
];
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const code = await bundle(
|
|
212
|
+
{
|
|
213
|
+
"index.ts": `export { views } from './registry?virtual=views';`,
|
|
214
|
+
"components/view/example.gts": `<template>example</template>`,
|
|
215
|
+
},
|
|
216
|
+
{ plugins: registry },
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// The absolutely-specified .gts got compiled and bundled in.
|
|
220
|
+
expect(code).not.toContain("<template>");
|
|
221
|
+
expect(code).toContain("template(");
|
|
222
|
+
expect(code).toContain("example");
|
|
223
|
+
});
|
|
224
|
+
|
|
177
225
|
it("compiles a .gts module used directly as an entry (no importer)", async () => {
|
|
178
226
|
const code = await bundle(
|
|
179
227
|
{
|
|
@@ -93,7 +93,14 @@ export function emberTransform(): Plugin {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
// An absolute specifier already names the file, so it needs no
|
|
97
|
+
// importer-relative resolution — and joining it onto the importer's
|
|
98
|
+
// directory would corrupt it. That is not hypothetical: a plugin's
|
|
99
|
+
// virtual module (id prefixed with `\0`) can generate imports of
|
|
100
|
+
// on-disk files by absolute path, and `path.dirname("\0./registry")`
|
|
101
|
+
// is `"\0."`, so joining yields `"\0./Users/.../thing.gts"` — a path
|
|
102
|
+
// no `existsSync`/`readFile` can accept (it has a null byte in it).
|
|
103
|
+
const fileName = path.isAbsolute(id) ? id : path.join(path.dirname(importer), id);
|
|
97
104
|
|
|
98
105
|
if (id.endsWith(".gts")) {
|
|
99
106
|
return {
|
|
@@ -3,8 +3,9 @@ import { generate, build, reapply } from "#test-helpers";
|
|
|
3
3
|
import { packageJson } from "ember-apply";
|
|
4
4
|
|
|
5
5
|
import type { Project } from "ember.nvp";
|
|
6
|
-
import { rm } from "node:fs/promises";
|
|
6
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
7
7
|
import { globSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
8
9
|
|
|
9
10
|
const expect = hardExpect.soft;
|
|
10
11
|
|
|
@@ -100,6 +101,106 @@ describe("typescript", () => {
|
|
|
100
101
|
});
|
|
101
102
|
});
|
|
102
103
|
|
|
104
|
+
const DEBUG_MARKERS = {
|
|
105
|
+
assert: "__debug_fixture_assert__",
|
|
106
|
+
deprecate: "__debug_fixture_deprecate__",
|
|
107
|
+
warn: "__debug_fixture_warn__",
|
|
108
|
+
isDevelopingApp: "__debug_fixture_is_developing_app__",
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Lives in app/services/ so that app.ts's eager
|
|
113
|
+
* `import.meta.glob("./services/**\/*")` pulls it into the build
|
|
114
|
+
* without needing to modify any generated files.
|
|
115
|
+
*/
|
|
116
|
+
const debugFixture = `
|
|
117
|
+
import { assert, deprecate, warn } from "@ember/debug";
|
|
118
|
+
import { isDevelopingApp, macroCondition } from "@embroider/macros";
|
|
119
|
+
|
|
120
|
+
assert("${DEBUG_MARKERS.assert}", true);
|
|
121
|
+
|
|
122
|
+
deprecate("${DEBUG_MARKERS.deprecate}", true, {
|
|
123
|
+
id: "debug-fixture",
|
|
124
|
+
until: "999.0.0",
|
|
125
|
+
for: "debug-fixture",
|
|
126
|
+
since: { available: "0.0.0", enabled: "0.0.0" },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
warn("${DEBUG_MARKERS.warn}", true, { id: "debug-fixture" });
|
|
130
|
+
|
|
131
|
+
if (macroCondition(isDevelopingApp())) {
|
|
132
|
+
console.log("${DEBUG_MARKERS.isDevelopingApp}");
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Only .js files -- the sourcemaps (.map) contain the original
|
|
138
|
+
* source (with markers) even in production builds.
|
|
139
|
+
*/
|
|
140
|
+
async function builtJavaScript(project: Project): Promise<string> {
|
|
141
|
+
let files = globSync("dist/**/*.js", { cwd: project.directory });
|
|
142
|
+
|
|
143
|
+
hardExpect(files.length, "build produced JS files").toBeGreaterThan(0);
|
|
144
|
+
|
|
145
|
+
let contents = await Promise.all(
|
|
146
|
+
files.map((file) => readFile(join(project.directory, file), "utf-8")),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return contents.join("\n");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
describe("debug macros", () => {
|
|
153
|
+
let project: Project;
|
|
154
|
+
|
|
155
|
+
beforeAll(async () => {
|
|
156
|
+
project = await generate({
|
|
157
|
+
type: "app",
|
|
158
|
+
layers: ["typescript"],
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
await mkdir(join(project.directory, "app/services"), { recursive: true });
|
|
162
|
+
await writeFile(join(project.directory, "app/services/debug-fixture.ts"), debugFixture);
|
|
163
|
+
|
|
164
|
+
let { exitCode } = await project.install();
|
|
165
|
+
|
|
166
|
+
hardExpect(exitCode, "Install succeeds").toBe(0);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
afterAll(async () => {
|
|
170
|
+
await rm(project.directory, { recursive: true, force: true });
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("has the debug-macros babel plugin", async () => {
|
|
174
|
+
let content = await project.read("babel.config.js");
|
|
175
|
+
|
|
176
|
+
expect(content).toContain("babel-plugin-debug-macros");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("development build keeps debug code", async () => {
|
|
180
|
+
let { exitCode } = await build(project);
|
|
181
|
+
|
|
182
|
+
hardExpect(exitCode).toBe(0);
|
|
183
|
+
|
|
184
|
+
let output = await builtJavaScript(project);
|
|
185
|
+
|
|
186
|
+
for (let [name, marker] of Object.entries(DEBUG_MARKERS)) {
|
|
187
|
+
expect(output, `development build contains ${name}`).toContain(marker);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("production build strips assert(), deprecate(), warn(), and if (macroCondition(isDevelopingApp()))", async () => {
|
|
192
|
+
let { exitCode } = await build(project, "production");
|
|
193
|
+
|
|
194
|
+
hardExpect(exitCode).toBe(0);
|
|
195
|
+
|
|
196
|
+
let output = await builtJavaScript(project);
|
|
197
|
+
|
|
198
|
+
for (let [name, marker] of Object.entries(DEBUG_MARKERS)) {
|
|
199
|
+
expect(output, `production build strips ${name}`).not.toContain(marker);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
103
204
|
describe("javascript", () => {
|
|
104
205
|
let project: Project;
|
|
105
206
|
beforeAll(async () => {
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
* - https://ember-primitives.pages.dev/6-utils/createService.md
|
|
11
11
|
* - https://ember-primitives.pages.dev/6-utils/createAsyncService.md
|
|
12
12
|
*/
|
|
13
|
-
import Application from "ember
|
|
13
|
+
import Application from "@ember/application";
|
|
14
14
|
|
|
15
15
|
export default class App extends Application {
|
|
16
16
|
modules = {
|
|
17
17
|
...import.meta.glob("./router.*", { eager: true }),
|
|
18
|
+
...import.meta.glob("./routes/**/*", { eager: true }),
|
|
18
19
|
...import.meta.glob("./templates/**/*", { eager: true }),
|
|
19
20
|
...import.meta.glob("./services/**/*", { eager: true }),
|
|
20
21
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { buildMacros } from "@embroider/macros/babel";
|
|
2
2
|
|
|
3
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
4
|
+
|
|
3
5
|
const macros = buildMacros({
|
|
4
6
|
configure(config) {
|
|
5
7
|
if (process.env.EMBER_ENV === "test") {
|
|
@@ -40,8 +42,22 @@ export default {
|
|
|
40
42
|
regenerator: false,
|
|
41
43
|
},
|
|
42
44
|
],
|
|
45
|
+
isProduction && [
|
|
46
|
+
"babel-plugin-debug-macros",
|
|
47
|
+
{
|
|
48
|
+
debugTools: {
|
|
49
|
+
isDebug: false,
|
|
50
|
+
source: "@ember/debug",
|
|
51
|
+
assertPredicateIndex: 1,
|
|
52
|
+
},
|
|
53
|
+
externalizeHelpers: {
|
|
54
|
+
module: "@ember/debug",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
"@ember/debug stripping",
|
|
58
|
+
],
|
|
43
59
|
...macros.babelMacros,
|
|
44
|
-
],
|
|
60
|
+
].filter(Boolean),
|
|
45
61
|
|
|
46
62
|
generatorOpts: {
|
|
47
63
|
compact: false,
|
|
@@ -29,8 +29,7 @@
|
|
|
29
29
|
"@embroider/router": "^3.0.6",
|
|
30
30
|
"@glimmer/component": "^2.1.1",
|
|
31
31
|
"decorator-transforms": "^2.3.2",
|
|
32
|
-
"ember-source": "~7.
|
|
33
|
-
"ember-strict-application-resolver": "^0.1.0"
|
|
32
|
+
"ember-source": "~7.2.0"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
|
36
35
|
"@babel/core": "^7.29.7",
|
|
@@ -44,6 +43,7 @@
|
|
|
44
43
|
"@glint/tsserver-plugin": "^2.5.5",
|
|
45
44
|
"@nullvoxpopuli/ember-vite": "workspace:*",
|
|
46
45
|
"@rollup/plugin-babel": "^7.1.0",
|
|
46
|
+
"babel-plugin-debug-macros": "^2.0.0",
|
|
47
47
|
"babel-plugin-ember-template-compilation": "^4.0.0",
|
|
48
48
|
"typescript": "^6.0.3",
|
|
49
49
|
"vite": "^8.0.14"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - https://ember-primitives.pages.dev/6-utils/createService.md
|
|
11
11
|
* - https://ember-primitives.pages.dev/6-utils/createAsyncService.md
|
|
12
12
|
*/
|
|
13
|
-
import Application from "ember
|
|
13
|
+
import Application from "@ember/application";
|
|
14
14
|
|
|
15
15
|
export default class App extends Application {
|
|
16
16
|
modules = {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { buildMacros } from "@embroider/macros/babel";
|
|
2
2
|
|
|
3
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
4
|
+
|
|
3
5
|
const macros = buildMacros({
|
|
4
6
|
configure(config) {
|
|
5
7
|
if (process.env.EMBER_ENV === "test") {
|
|
@@ -40,8 +42,22 @@ export default {
|
|
|
40
42
|
regenerator: false,
|
|
41
43
|
},
|
|
42
44
|
],
|
|
45
|
+
isProduction && [
|
|
46
|
+
"babel-plugin-debug-macros",
|
|
47
|
+
{
|
|
48
|
+
debugTools: {
|
|
49
|
+
isDebug: false,
|
|
50
|
+
source: "@ember/debug",
|
|
51
|
+
assertPredicateIndex: 1,
|
|
52
|
+
},
|
|
53
|
+
externalizeHelpers: {
|
|
54
|
+
module: "@ember/debug",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
"@ember/debug stripping",
|
|
58
|
+
],
|
|
43
59
|
...macros.babelMacros,
|
|
44
|
-
],
|
|
60
|
+
].filter(Boolean),
|
|
45
61
|
|
|
46
62
|
generatorOpts: {
|
|
47
63
|
compact: false,
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
"@embroider/router": "^3.0.6",
|
|
31
31
|
"@glimmer/component": "^2.1.1",
|
|
32
32
|
"decorator-transforms": "^2.3.2",
|
|
33
|
-
"ember-source": "~7.
|
|
34
|
-
"ember-strict-application-resolver": "^0.1.0"
|
|
33
|
+
"ember-source": "~7.2.0"
|
|
35
34
|
},
|
|
36
35
|
"devDependencies": {
|
|
37
36
|
"@babel/core": "^7.29.7",
|
|
@@ -45,6 +44,7 @@
|
|
|
45
44
|
"@glint/tsserver-plugin": "^2.5.5",
|
|
46
45
|
"@nullvoxpopuli/ember-vite": "workspace:*",
|
|
47
46
|
"@rollup/plugin-babel": "^7.1.0",
|
|
47
|
+
"babel-plugin-debug-macros": "^2.0.0",
|
|
48
48
|
"babel-plugin-ember-template-compilation": "^4.0.0",
|
|
49
49
|
"typescript": "^6.0.3",
|
|
50
50
|
"vite": "^8.0.14"
|
|
@@ -7,14 +7,14 @@ import { existsSync } from "node:fs";
|
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
|
|
9
9
|
const toInstall = {
|
|
10
|
-
"@babel/eslint-parser": "^
|
|
11
|
-
"@eslint/js": "^
|
|
10
|
+
"@babel/eslint-parser": "^8.0.1",
|
|
11
|
+
"@eslint/js": "^10.0.1",
|
|
12
12
|
"eslint-config-prettier": "^10.1.8",
|
|
13
13
|
"eslint-plugin-ember": "^12.7.5",
|
|
14
14
|
"eslint-plugin-n": "^17.23.2",
|
|
15
15
|
"eslint-plugin-qunit": "^8.2.5",
|
|
16
16
|
"typescript-eslint": "^8.53.0",
|
|
17
|
-
eslint: "^9.
|
|
17
|
+
eslint: "^10.9.1",
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -28,7 +28,6 @@ const libraryDeps = {
|
|
|
28
28
|
"@embroider/macros": "^1.20.3",
|
|
29
29
|
"@nullvoxpopuli/ember-vite": "workspace:*",
|
|
30
30
|
"babel-plugin-ember-template-compilation": "^4.0.0",
|
|
31
|
-
"ember-strict-application-resolver": "^0.1.0",
|
|
32
31
|
vite: "^8.0.14",
|
|
33
32
|
};
|
|
34
33
|
const libraryTsDeps = {
|
|
@@ -4,7 +4,7 @@ import * as QUnit from "qunit";
|
|
|
4
4
|
import { setup } from "qunit-dom";
|
|
5
5
|
import { setupEmberOnerrorValidation, start as qunitStart } from "ember-qunit";
|
|
6
6
|
import { setTesting } from "@embroider/macros";
|
|
7
|
-
import EmberApp from "ember
|
|
7
|
+
import EmberApp from "@ember/application";
|
|
8
8
|
|
|
9
9
|
class Router extends EmberRouter {
|
|
10
10
|
location = "none";
|
|
@@ -21,23 +21,23 @@ An Ember application created with \`ember.nvp\`.
|
|
|
21
21
|
|
|
22
22
|
### Installation
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
\`\`\`sh
|
|
25
25
|
${project.packageManager} install
|
|
26
|
-
|
|
26
|
+
\`\`\`
|
|
27
27
|
|
|
28
28
|
### Development
|
|
29
29
|
|
|
30
30
|
To start the local development server:
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
\`\`\`sh
|
|
33
33
|
${project.runPrefix} dev
|
|
34
|
-
|
|
34
|
+
\`\`\`
|
|
35
35
|
|
|
36
36
|
or
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
\`\`\`sh
|
|
39
39
|
${project.runPrefix} start
|
|
40
|
-
|
|
40
|
+
\`\`\`
|
|
41
41
|
${layerDocsMarkdown}`;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -61,29 +61,29 @@ A browser extension using Ember created with \`ember.nvp\`.
|
|
|
61
61
|
|
|
62
62
|
To start development:
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
\`\`\`sh
|
|
65
65
|
${project.runPrefix} dev
|
|
66
|
-
|
|
66
|
+
\`\`\`
|
|
67
67
|
|
|
68
68
|
or
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
\`\`\`sh
|
|
71
71
|
${project.runPrefix} start
|
|
72
|
-
|
|
72
|
+
\`\`\`
|
|
73
73
|
|
|
74
74
|
### Building
|
|
75
75
|
|
|
76
76
|
To build the library:
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
\`\`\`sh
|
|
79
79
|
${project.runPrefix} build
|
|
80
|
-
|
|
80
|
+
\`\`\`
|
|
81
81
|
|
|
82
82
|
or
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
\`\`\`sh
|
|
85
85
|
${project.runPrefix} build:watch
|
|
86
|
-
|
|
86
|
+
\`\`\`
|
|
87
87
|
${layerDocsMarkdown}`;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -107,9 +107,9 @@ An Ember library/addon created with \`ember.nvp\`.
|
|
|
107
107
|
|
|
108
108
|
To build the library:
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
\`\`\`sh
|
|
111
111
|
${project.runPrefix} build
|
|
112
|
-
|
|
112
|
+
\`\`\`
|
|
113
113
|
${layerDocsMarkdown}`;
|
|
114
114
|
}
|
|
115
115
|
|
package/src/utils/babel.js
CHANGED
|
@@ -65,15 +65,33 @@ export async function prependPlugin(project, plugin, configPath = "babel.config.
|
|
|
65
65
|
root
|
|
66
66
|
.find(j.Property, {
|
|
67
67
|
key: { name: "plugins" },
|
|
68
|
-
value: { type: "ArrayExpression" },
|
|
69
68
|
})
|
|
70
69
|
.forEach(
|
|
71
70
|
/**
|
|
72
71
|
* @param {any} path
|
|
73
72
|
*/
|
|
74
73
|
(path) => {
|
|
75
|
-
path.node.value
|
|
74
|
+
let array = pluginsArrayOf(path.node.value);
|
|
75
|
+
|
|
76
|
+
array?.elements.unshift(plugin);
|
|
76
77
|
},
|
|
77
78
|
);
|
|
78
79
|
});
|
|
79
80
|
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The plugins value may be the array itself, or the array with
|
|
84
|
+
* methods chained off of it: `[ ... ].filter(Boolean)`
|
|
85
|
+
*
|
|
86
|
+
* @param {any} node
|
|
87
|
+
* @returns {any | undefined} the underlying ArrayExpression
|
|
88
|
+
*/
|
|
89
|
+
function pluginsArrayOf(node) {
|
|
90
|
+
if (node.type === "ArrayExpression") return node;
|
|
91
|
+
|
|
92
|
+
if (node.type === "CallExpression" && node.callee.type === "MemberExpression") {
|
|
93
|
+
return pluginsArrayOf(node.callee.object);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
@@ -10,7 +10,7 @@ import { hasInspectorSupport, wireInspectorSupport } from "#utils/inspector-supp
|
|
|
10
10
|
describe("wireInspectorSupport", () => {
|
|
11
11
|
it("wires the generated shape (export default class extends Application)", () => {
|
|
12
12
|
const code = [
|
|
13
|
-
`import Application from "ember
|
|
13
|
+
`import Application from "@ember/application";`,
|
|
14
14
|
``,
|
|
15
15
|
`export default class App extends Application {`,
|
|
16
16
|
` modules = {`,
|
|
@@ -20,7 +20,7 @@ describe("wireInspectorSupport", () => {
|
|
|
20
20
|
].join("\n");
|
|
21
21
|
|
|
22
22
|
expect(wireInspectorSupport(code, "app/app.ts")).toMatchInlineSnapshot(`
|
|
23
|
-
"import Application from "ember
|
|
23
|
+
"import Application from "@ember/application";
|
|
24
24
|
import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
25
25
|
export default class App extends Application {
|
|
26
26
|
modules = { ...import.meta.glob("./router.*", { eager: true }) };
|
|
@@ -31,7 +31,7 @@ describe("wireInspectorSupport", () => {
|
|
|
31
31
|
|
|
32
32
|
it("wires a named class exported in a separate statement", () => {
|
|
33
33
|
const code = [
|
|
34
|
-
`import Application from "ember
|
|
34
|
+
`import Application from "@ember/application";`,
|
|
35
35
|
``,
|
|
36
36
|
`class App extends Application {`,
|
|
37
37
|
` modules = {};`,
|
|
@@ -41,7 +41,7 @@ describe("wireInspectorSupport", () => {
|
|
|
41
41
|
].join("\n");
|
|
42
42
|
|
|
43
43
|
expect(wireInspectorSupport(code, "app/app.js")).toMatchInlineSnapshot(`
|
|
44
|
-
"import Application from "ember
|
|
44
|
+
"import Application from "@ember/application";
|
|
45
45
|
import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
46
46
|
class App extends Application {
|
|
47
47
|
modules = { };
|
|
@@ -53,13 +53,13 @@ describe("wireInspectorSupport", () => {
|
|
|
53
53
|
|
|
54
54
|
it("wires an anonymous default-exported class", () => {
|
|
55
55
|
const code = [
|
|
56
|
-
`import Application from "ember
|
|
56
|
+
`import Application from "@ember/application";`,
|
|
57
57
|
``,
|
|
58
58
|
`export default class extends Application {}`,
|
|
59
59
|
].join("\n");
|
|
60
60
|
|
|
61
61
|
expect(wireInspectorSupport(code, "app/app.js")).toMatchInlineSnapshot(`
|
|
62
|
-
"import Application from "ember
|
|
62
|
+
"import Application from "@ember/application";
|
|
63
63
|
import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
64
64
|
export default class extends Application {
|
|
65
65
|
inspector = setupInspector(this);
|
|
@@ -69,7 +69,7 @@ describe("wireInspectorSupport", () => {
|
|
|
69
69
|
|
|
70
70
|
it("wires a class expression assigned to a variable", () => {
|
|
71
71
|
const code = [
|
|
72
|
-
`import Application from "ember
|
|
72
|
+
`import Application from "@ember/application";`,
|
|
73
73
|
``,
|
|
74
74
|
`const App = class extends Application {`,
|
|
75
75
|
` modules = {};`,
|
|
@@ -79,7 +79,7 @@ describe("wireInspectorSupport", () => {
|
|
|
79
79
|
].join("\n");
|
|
80
80
|
|
|
81
81
|
expect(wireInspectorSupport(code, "app/app.js")).toMatchInlineSnapshot(`
|
|
82
|
-
"import Application from "ember
|
|
82
|
+
"import Application from "@ember/application";
|
|
83
83
|
import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
84
84
|
const App = class extends Application {
|
|
85
85
|
modules = { };
|
|
@@ -108,14 +108,14 @@ describe("wireInspectorSupport", () => {
|
|
|
108
108
|
it("adds only the missing member when the import is already present", () => {
|
|
109
109
|
const code = [
|
|
110
110
|
`import wireUp from "@embroider/legacy-inspector-support/ember-source-4.12";`,
|
|
111
|
-
`import Application from "ember
|
|
111
|
+
`import Application from "@ember/application";`,
|
|
112
112
|
``,
|
|
113
113
|
`export default class App extends Application {}`,
|
|
114
114
|
].join("\n");
|
|
115
115
|
|
|
116
116
|
expect(wireInspectorSupport(code, "app/app.ts")).toMatchInlineSnapshot(`
|
|
117
117
|
"import wireUp from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
118
|
-
import Application from "ember
|
|
118
|
+
import Application from "@ember/application";
|
|
119
119
|
export default class App extends Application {
|
|
120
120
|
inspector = wireUp(this);
|
|
121
121
|
}"
|
|
@@ -124,7 +124,7 @@ describe("wireInspectorSupport", () => {
|
|
|
124
124
|
|
|
125
125
|
it("is idempotent", () => {
|
|
126
126
|
const code = [
|
|
127
|
-
`import Application from "ember
|
|
127
|
+
`import Application from "@ember/application";`,
|
|
128
128
|
``,
|
|
129
129
|
`export default class App extends Application {`,
|
|
130
130
|
` modules = {};`,
|
|
@@ -157,7 +157,7 @@ describe("wireInspectorSupport", () => {
|
|
|
157
157
|
describe("hasInspectorSupport", () => {
|
|
158
158
|
it("is false before wiring and true after", () => {
|
|
159
159
|
const code = [
|
|
160
|
-
`import Application from "ember
|
|
160
|
+
`import Application from "@ember/application";`,
|
|
161
161
|
``,
|
|
162
162
|
`export default class App extends Application {}`,
|
|
163
163
|
].join("\n");
|
|
@@ -169,7 +169,7 @@ describe("hasInspectorSupport", () => {
|
|
|
169
169
|
it("is false when only the import is present", () => {
|
|
170
170
|
const code = [
|
|
171
171
|
`import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";`,
|
|
172
|
-
`import Application from "ember
|
|
172
|
+
`import Application from "@ember/application";`,
|
|
173
173
|
``,
|
|
174
174
|
`export default class App extends Application {}`,
|
|
175
175
|
].join("\n");
|
|
@@ -52,10 +52,10 @@ describe("layer: inspector-support", () => {
|
|
|
52
52
|
* - https://ember-primitives.pages.dev/6-utils/createService.md
|
|
53
53
|
* - https://ember-primitives.pages.dev/6-utils/createAsyncService.md
|
|
54
54
|
*/
|
|
55
|
-
import Application from 'ember
|
|
55
|
+
import Application from '@ember/application';
|
|
56
56
|
import setupInspector from "@embroider/legacy-inspector-support/ember-source-4.12";
|
|
57
57
|
export default class App extends Application {
|
|
58
|
-
modules = { ...import.meta.glob('./router.*', { eager: true }), ...import.meta.glob('./templates/**/*', { eager: true }), ...import.meta.glob('./services/**/*', { eager: true }) };
|
|
58
|
+
modules = { ...import.meta.glob('./router.*', { eager: true }), ...import.meta.glob('./routes/**/*', { eager: true }), ...import.meta.glob('./templates/**/*', { eager: true }), ...import.meta.glob('./services/**/*', { eager: true }) };
|
|
59
59
|
inspector = setupInspector(this);
|
|
60
60
|
}"
|
|
61
61
|
`);
|
|
@@ -42,23 +42,23 @@ describe("layer: readme", () => {
|
|
|
42
42
|
|
|
43
43
|
### Installation
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
\`\`\`sh
|
|
46
46
|
pnpm install
|
|
47
|
-
|
|
47
|
+
\`\`\`
|
|
48
48
|
|
|
49
49
|
### Development
|
|
50
50
|
|
|
51
51
|
To start the local development server:
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
\`\`\`sh
|
|
54
54
|
pnpm dev
|
|
55
|
-
|
|
55
|
+
\`\`\`
|
|
56
56
|
|
|
57
57
|
or
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
\`\`\`sh
|
|
60
60
|
pnpm start
|
|
61
|
-
|
|
61
|
+
\`\`\`
|
|
62
62
|
|
|
63
63
|
## Features & Tooling
|
|
64
64
|
|
|
@@ -109,9 +109,9 @@ describe("layer: readme", () => {
|
|
|
109
109
|
|
|
110
110
|
To build the library:
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
\`\`\`sh
|
|
113
113
|
npm run build
|
|
114
|
-
|
|
114
|
+
\`\`\`
|
|
115
115
|
|
|
116
116
|
## Features & Tooling
|
|
117
117
|
|
|
@@ -156,29 +156,29 @@ describe("layer: readme", () => {
|
|
|
156
156
|
|
|
157
157
|
To start development:
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
\`\`\`sh
|
|
160
160
|
pnpm dev
|
|
161
|
-
|
|
161
|
+
\`\`\`
|
|
162
162
|
|
|
163
163
|
or
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
\`\`\`sh
|
|
166
166
|
pnpm start
|
|
167
|
-
|
|
167
|
+
\`\`\`
|
|
168
168
|
|
|
169
169
|
### Building
|
|
170
170
|
|
|
171
171
|
To build the library:
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
\`\`\`sh
|
|
174
174
|
pnpm build
|
|
175
|
-
|
|
175
|
+
\`\`\`
|
|
176
176
|
|
|
177
177
|
or
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
\`\`\`sh
|
|
180
180
|
pnpm build:watch
|
|
181
|
-
|
|
181
|
+
\`\`\`
|
|
182
182
|
|
|
183
183
|
## Features & Tooling
|
|
184
184
|
|
|
@@ -91,7 +91,7 @@ function appTests(ext: "ts" | "js") {
|
|
|
91
91
|
[`tests/application/welcome-test.g${ext}`]: `import { describe, expect } from "vitest";
|
|
92
92
|
import { applicationTest } from "ember-vitest";
|
|
93
93
|
import { visit } from "@ember/test-helpers";
|
|
94
|
-
import Application from "ember
|
|
94
|
+
import Application from "@ember/application";
|
|
95
95
|
|
|
96
96
|
import Router from "#app/router.${ext}";
|
|
97
97
|
import ApplicationTemplate from "#app/templates/application.g${ext}";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "rolldown";
|
|
2
|
-
|
|
3
|
-
import manifest from "./package.json" with { type: "json" };
|
|
4
|
-
|
|
5
|
-
const deps = [
|
|
6
|
-
...Object.keys(manifest.dependencies || {}),
|
|
7
|
-
...Object.keys(manifest.peerDependencies || {}),
|
|
8
|
-
];
|
|
9
|
-
|
|
10
|
-
export default defineConfig({
|
|
11
|
-
input: {
|
|
12
|
-
index: "index.ts",
|
|
13
|
-
"app-reexports": "src/app-reexports.ts",
|
|
14
|
-
},
|
|
15
|
-
output: {
|
|
16
|
-
format: "esm",
|
|
17
|
-
dir: "dist",
|
|
18
|
-
},
|
|
19
|
-
external(id) {
|
|
20
|
-
if (id.startsWith("node:")) return true;
|
|
21
|
-
if (deps.some((dep) => id.startsWith(dep))) return true;
|
|
22
|
-
},
|
|
23
|
-
});
|