ember.nvp 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.release-plan.json +37 -5
  2. package/CHANGELOG.md +31 -0
  3. package/README.md +28 -0
  4. package/package.json +2 -1
  5. package/packages/rolldown/package.json +2 -2
  6. package/packages/rolldown/src/transform.test.ts +3 -3
  7. package/packages/vite/package.json +4 -4
  8. package/packages/vite/src/ember.test.ts +38 -0
  9. package/packages/vite/src/ember.ts +38 -5
  10. package/src/bases/minimal-app/files/package.json +2 -2
  11. package/src/bases/minimal-extension/files/package.json +2 -2
  12. package/src/cli/generator.js +10 -0
  13. package/src/cli/index.js +19 -2
  14. package/src/cli/questions/layers.js +3 -2
  15. package/src/cli/questions/migration.js +69 -0
  16. package/src/index.js +1 -0
  17. package/src/layers/qunit/index.js +1 -1
  18. package/src/migration-from/addons.js +154 -0
  19. package/src/migration-from/app.js +1117 -0
  20. package/src/migration-from/at-ember/addon-blueprint/index.js +515 -0
  21. package/src/migration-from/at-ember/addon-blueprint/rollup.js +188 -0
  22. package/src/migration-from/at-ember/app-blueprint/index.js +60 -0
  23. package/src/migration-from/at-ember-tooling/classic-build-addon-blueprint/index.js +601 -0
  24. package/src/migration-from/at-ember-tooling/classic-build-app-blueprint/index.js +118 -0
  25. package/src/migration-from/babel.js +207 -0
  26. package/src/migration-from/ember-cli-build.js +238 -0
  27. package/src/migration-from/files.js +120 -0
  28. package/src/migration-from/findings.js +69 -0
  29. package/src/migration-from/index.js +81 -0
  30. package/src/migration-from/javascript.js +217 -0
  31. package/src/migration-from/layers.js +170 -0
  32. package/src/migration-from/library.js +311 -0
  33. package/src/utils/types.ts +69 -0
  34. package/test/ember.nvp/migration-from-fixtures.ts +506 -0
  35. package/test/ember.nvp/migration-from.test.ts +475 -0
@@ -0,0 +1,506 @@
1
+ /**
2
+ * Projects from the older blueprints, cut down to the files that the migrations read.
3
+ *
4
+ * Each one follows what the blueprint generates:
5
+ * - `@ember/addon-blueprint` 0.18
6
+ * - `@ember/app-blueprint` 7.5
7
+ * - `@ember-tooling/classic-build-app-blueprint` 7.5
8
+ * - `@ember-tooling/classic-build-addon-blueprint` 7.5
9
+ */
10
+
11
+ const json = (value: unknown) => JSON.stringify(value, null, 2) + "\n";
12
+
13
+ export const addonBlueprint: Record<string, string> = {
14
+ "package.json": json({
15
+ name: "my-addon",
16
+ version: "0.0.0",
17
+ keywords: ["ember-addon"],
18
+ files: ["addon-main.cjs", "declarations", "dist", "src"],
19
+ scripts: {
20
+ build: "rollup --config",
21
+ prepack: "rollup --config",
22
+ start: "vite dev",
23
+ test: "vite build --mode=development --out-dir dist-tests && testem --file testem.cjs ci --port 0",
24
+ },
25
+ dependencies: {
26
+ "@embroider/addon-shim": "^1.8.9",
27
+ "decorator-transforms": "^2.2.2",
28
+ },
29
+ devDependencies: {
30
+ "@embroider/addon-dev": "^8.1.0",
31
+ "@embroider/vite": "^1.1.5",
32
+ "@glimmer/component": "^2.0.0",
33
+ "@rollup/plugin-babel": "^6.0.4",
34
+ "ember-source": "^6.7.0",
35
+ "ember-strict-application-resolver": "^0.1.0",
36
+ rollup: "^4.22.5",
37
+ typescript: "~5.8.3",
38
+ },
39
+ "ember-addon": { version: 2, type: "addon", main: "addon-main.cjs" },
40
+ exports: {
41
+ ".": { types: "./declarations/index.d.ts", default: "./dist/index.js" },
42
+ "./addon-main.js": "./addon-main.cjs",
43
+ "./*": { types: "./declarations/*.d.ts", default: "./dist/*.js" },
44
+ },
45
+ }),
46
+ "addon-main.cjs": `'use strict';
47
+
48
+ const { addonV1Shim } = require('@embroider/addon-shim');
49
+ module.exports = addonV1Shim(__dirname);
50
+ `,
51
+ "rollup.config.mjs": `import { babel } from '@rollup/plugin-babel';
52
+ import { Addon } from '@embroider/addon-dev/rollup';
53
+
54
+ const addon = new Addon({ srcDir: 'src', destDir: 'dist' });
55
+
56
+ export default {
57
+ output: addon.output(),
58
+ plugins: [
59
+ addon.publicEntrypoints(['**/*.js', 'index.js', 'template-registry.js']),
60
+ addon.appReexports(['components/**/*.js', 'helpers/**/*.js', 'modifiers/**/*.js', 'services/**/*.js']),
61
+ addon.dependencies(),
62
+ babel({ extensions: ['.js', '.gjs', '.ts', '.gts'], babelHelpers: 'bundled', configFile: './babel.publish.config.cjs' }),
63
+ addon.hbs(),
64
+ addon.gjs(),
65
+ addon.declarations('declarations', 'pnpm ember-tsc --declaration --project ./tsconfig.publish.json'),
66
+ addon.keepAssets(['**/*.css']),
67
+ addon.clean(),
68
+ ],
69
+ };
70
+ `,
71
+ "babel.config.cjs": `const { buildMacros } = require('@embroider/macros/babel');
72
+ const macros = buildMacros();
73
+
74
+ module.exports = {
75
+ plugins: [
76
+ ['@babel/plugin-transform-typescript', { allExtensions: true }],
77
+ ['babel-plugin-ember-template-compilation', { transforms: [...macros.templateMacros] }],
78
+ ['module:decorator-transforms', { runtime: { import: require.resolve('decorator-transforms/runtime-esm') } }],
79
+ ...macros.babelMacros,
80
+ ],
81
+ };
82
+ `,
83
+ "babel.publish.config.cjs": `module.exports = {
84
+ plugins: [
85
+ ['@babel/plugin-transform-typescript', { allExtensions: true }],
86
+ ['babel-plugin-ember-template-compilation', { targetFormat: 'hbs', transforms: [] }],
87
+ ['module:decorator-transforms', { runtime: { import: 'decorator-transforms/runtime-esm' } }],
88
+ ],
89
+ };
90
+ `,
91
+ "tsconfig.json": json({
92
+ extends: "@ember/app-tsconfig",
93
+ include: ["src/**/*", "tests/**/*", "demo-app/**/*"],
94
+ compilerOptions: { rootDir: ".", types: ["ember-source/types"] },
95
+ }),
96
+ "tsconfig.publish.json": json({
97
+ extends: "@ember/library-tsconfig",
98
+ include: ["./src/**/*"],
99
+ compilerOptions: { allowJs: true, declarationDir: "declarations", rootDir: "./src" },
100
+ }),
101
+ "vite.config.mjs": `import { defineConfig } from 'vite';
102
+ import { ember } from '@embroider/vite';
103
+
104
+ export default defineConfig({ plugins: [ember()] });
105
+ `,
106
+ "testem.cjs": `module.exports = {
107
+ test_page: 'tests/index.html?hidepassed',
108
+ cwd: 'dist-tests',
109
+ launch_in_ci: ['Chrome'],
110
+ browser_args: {
111
+ Chrome: {
112
+ ci: [
113
+ process.env.CI ? '--no-sandbox' : null,
114
+ '--headless=new',
115
+ '--disable-dev-shm-usage',
116
+ '--disable-software-rasterizer',
117
+ '--mute-audio',
118
+ '--remote-debugging-port=0',
119
+ '--window-size=1440,900',
120
+ ].filter(Boolean),
121
+ },
122
+ },
123
+ };
124
+ `,
125
+ "tests/index.html": `<script type="module">import { start } from "./test-helper.js"; start();</script>\n`,
126
+ "tests/test-helper.ts": `import EmberApp from 'ember-strict-application-resolver';\nexport function start() {}\n`,
127
+ "index.html": `<script type="module">import { App } from './demo-app/app'; App.create({});</script>\n`,
128
+ "demo-app/app.gts": `import EmberApp from 'ember-strict-application-resolver';
129
+ import EmberRouter from '@ember/routing/router';
130
+
131
+ class Router extends EmberRouter {}
132
+
133
+ export class App extends EmberApp {
134
+ modules = { './router': Router };
135
+ }
136
+
137
+ Router.map(function () {});
138
+ `,
139
+ "demo-app/templates/application.gts": `import { pageTitle } from 'ember-page-title';
140
+
141
+ const greeting = 'hello';
142
+
143
+ <template>
144
+ {{pageTitle "Demo App"}}
145
+
146
+ <h1>Welcome to ember!</h1>
147
+
148
+ {{greeting}}, world!
149
+ </template>
150
+ `,
151
+ "unpublished-development-types/index.d.ts": `// Add any types here that you need for local development only.\n`,
152
+ "src/index.ts": `export {};\n`,
153
+ };
154
+
155
+ export const appBlueprint: Record<string, string> = {
156
+ "package.json": json({
157
+ name: "my-app",
158
+ version: "0.0.0",
159
+ private: true,
160
+ exports: { "./tests/*": "./tests/*", "./*": "./app/*" },
161
+ scripts: {
162
+ build: "vite build",
163
+ start: "vite",
164
+ test: "vite build --mode development && testem ci --port 0",
165
+ },
166
+ devDependencies: {
167
+ "@embroider/compat": "^4.1.25",
168
+ "@embroider/core": "^4.6.7",
169
+ "@embroider/legacy-inspector-support": "^0.1.3",
170
+ "@embroider/vite": "^1.7.13",
171
+ "@warp-drive/core": "~5.8.2",
172
+ "@warp-drive/ember": "~5.8.2",
173
+ "ember-cli": "~7.3.0",
174
+ "ember-cli-deprecation-workflow": "^4.0.1",
175
+ "ember-load-initializers": "^3.0.1",
176
+ "ember-page-title": "^9.0.3",
177
+ "ember-resolver": "^13.2.0",
178
+ "ember-source": "~7.3.0",
179
+ typescript: "^6.0.3",
180
+ },
181
+ }),
182
+ "ember-cli-build.mjs": `import { dirname } from 'node:path';
183
+ import { fileURLToPath } from 'node:url';
184
+ import EmberApp from 'ember-cli/lib/broccoli/ember-app.js';
185
+ import { compatBuild } from '@embroider/compat';
186
+
187
+ export default async function (defaults) {
188
+ const { setConfig } = await import('@warp-drive/core/build-config');
189
+ const { buildOnce } = await import('@embroider/vite');
190
+
191
+ const app = new EmberApp(defaults, {
192
+ // Add options here
193
+ });
194
+
195
+ setConfig(app, dirname(fileURLToPath(import.meta.url)), {
196
+ compatWith: '5.8',
197
+ });
198
+
199
+ return compatBuild(app, buildOnce);
200
+ }
201
+ `,
202
+ "config/environment.js": `'use strict';
203
+
204
+ module.exports = function (environment) {
205
+ const ENV = {
206
+ modulePrefix: 'my-app',
207
+ environment,
208
+ rootURL: '/',
209
+ locationType: 'history',
210
+ EmberENV: { EXTEND_PROTOTYPES: false, FEATURES: {} },
211
+ APP: {},
212
+ };
213
+
214
+ if (environment === 'test') {
215
+ ENV.locationType = 'none';
216
+ ENV.APP.rootElement = '#ember-testing';
217
+ ENV.APP.autoboot = false;
218
+ }
219
+
220
+ return ENV;
221
+ };
222
+ `,
223
+ "config/optional-features.json": json({
224
+ "application-template-wrapper": false,
225
+ "default-async-observers": true,
226
+ "jquery-integration": false,
227
+ "template-only-glimmer-components": true,
228
+ "no-implicit-route-model": true,
229
+ }),
230
+ "babel.config.mjs": `import { babelCompatSupport, templateCompatSupport } from '@embroider/compat/babel';
231
+
232
+ export default {
233
+ plugins: [
234
+ ['@babel/plugin-transform-typescript', { allExtensions: true }],
235
+ ['babel-plugin-ember-template-compilation', { transforms: [...templateCompatSupport()] }],
236
+ ['module:decorator-transforms', { runtime: { import: 'decorator-transforms/runtime-esm' } }],
237
+ ...babelCompatSupport(),
238
+ ],
239
+ };
240
+ `,
241
+ "vite.config.mjs": `import { defineConfig } from 'vite';
242
+ import { extensions, classicEmberSupport, ember } from '@embroider/vite';
243
+ import { babel } from '@rollup/plugin-babel';
244
+
245
+ export default defineConfig({
246
+ plugins: [classicEmberSupport(), ember(), babel({ babelHelpers: 'runtime', extensions })],
247
+ });
248
+ `,
249
+ "index.html": `<!DOCTYPE html>
250
+ <html>
251
+ <head>
252
+ <title>MyApp</title>
253
+
254
+ {{content-for "head"}}
255
+
256
+ <link integrity="" rel="stylesheet" href="/@embroider/virtual/vendor.css">
257
+ <link integrity="" rel="stylesheet" href="/@embroider/virtual/app.css">
258
+
259
+ {{content-for "head-footer"}}
260
+ </head>
261
+ <body>
262
+ {{content-for "body"}}
263
+
264
+ <script src="/@embroider/virtual/vendor.js"></script>
265
+ <script type="module">
266
+ import Application from './app/app';
267
+ import environment from './app/config/environment';
268
+
269
+ Application.create(environment.APP);
270
+ </script>
271
+
272
+ {{content-for "body-footer"}}
273
+ </body>
274
+ </html>
275
+ `,
276
+ "app/app.ts": `import '@warp-drive/ember/install';
277
+ import Application from '@ember/application';
278
+ import compatModules from '@embroider/virtual/compat-modules';
279
+ import Resolver from 'ember-resolver';
280
+ import loadInitializers from 'ember-load-initializers';
281
+ import config from 'my-app/config/environment';
282
+ import { importSync, isDevelopingApp, macroCondition } from '@embroider/macros';
283
+ import setupInspector from '@embroider/legacy-inspector-support/ember-source-4.12';
284
+
285
+ if (macroCondition(isDevelopingApp())) {
286
+ importSync('./deprecation-workflow');
287
+ }
288
+
289
+ export default class App extends Application {
290
+ modulePrefix = config.modulePrefix;
291
+ podModulePrefix = config.podModulePrefix;
292
+ Resolver = Resolver.withModules(compatModules);
293
+ inspector = setupInspector(this);
294
+ }
295
+
296
+ loadInitializers(App, config.modulePrefix, compatModules);
297
+ `,
298
+ "app/config/environment.ts": `import loadConfigFromMeta from '@embroider/config-meta-loader';\n\nexport default loadConfigFromMeta('my-app');\n`,
299
+ "app/router.ts": `import EmberRouter from '@embroider/router';
300
+ import config from 'my-app/config/environment';
301
+
302
+ export default class Router extends EmberRouter {
303
+ location = config.locationType;
304
+ rootURL = config.rootURL;
305
+ }
306
+
307
+ Router.map(function () {});
308
+ `,
309
+ "app/deprecation-workflow.ts": `import setupDeprecationWorkflow from 'ember-cli-deprecation-workflow';\n\nsetupDeprecationWorkflow({ workflow: [] });\n`,
310
+ "app/styles/app.css": "",
311
+ "app/templates/application.gts": `import { pageTitle } from 'ember-page-title';\n\n<template>{{pageTitle "MyApp"}}{{outlet}}</template>\n`,
312
+ "testem.cjs": `module.exports = { test_page: 'tests/index.html?hidepassed', cwd: 'dist' };\n`,
313
+ "tests/index.html": `{{content-for "test-head"}}\n`,
314
+ "tests/test-helper.ts": `import Application from 'my-app/app';
315
+ import config from 'my-app/config/environment';
316
+ import * as QUnit from 'qunit';
317
+ import { setApplication } from '@ember/test-helpers';
318
+ import { setup } from 'qunit-dom';
319
+ import { start as qunitStart } from 'ember-qunit';
320
+
321
+ export function start() {
322
+ setApplication(Application.create(config.APP));
323
+ setup(QUnit.assert);
324
+ qunitStart();
325
+ }
326
+ `,
327
+ "tsconfig.json": json({
328
+ extends: "@ember/app-tsconfig",
329
+ include: ["app", "tests", "types"],
330
+ compilerOptions: { allowJs: true, types: ["ember-source/types", "@embroider/core/virtual"] },
331
+ }),
332
+ };
333
+
334
+ export const classicApp: Record<string, string> = {
335
+ "package.json": json({
336
+ name: "my-classic-app",
337
+ version: "0.0.0",
338
+ private: true,
339
+ scripts: {
340
+ build: "ember build --environment=production",
341
+ start: "ember serve",
342
+ "test:ember": "ember test",
343
+ },
344
+ devDependencies: {
345
+ "@tsconfig/ember": "^3.0.12",
346
+ "ember-cli": "~7.5.0-alpha.1",
347
+ "ember-cli-app-version": "^7.0.0",
348
+ "ember-cli-babel": "^8.3.2",
349
+ "ember-cli-htmlbars": "^7.0.1",
350
+ "ember-load-initializers": "^3.0.1",
351
+ "ember-page-title": "^9.0.3",
352
+ "ember-resolver": "^13.2.0",
353
+ "ember-source": "~7.3.0",
354
+ "loader.js": "^4.7.0",
355
+ typescript: "^5.9.3",
356
+ },
357
+ }),
358
+ "ember-cli-build.js": `'use strict';
359
+
360
+ const EmberApp = require('ember-cli/lib/broccoli/ember-app');
361
+
362
+ module.exports = function (defaults) {
363
+ const app = new EmberApp(defaults, {
364
+ 'ember-cli-babel': { enableTypeScriptTransform: true },
365
+ });
366
+
367
+ return app.toTree();
368
+ };
369
+ `,
370
+ "config/environment.js": appBlueprint["config/environment.js"]!.replace(
371
+ "my-app",
372
+ "my-classic-app",
373
+ ),
374
+ "app/index.html": `<!DOCTYPE html>
375
+ <html>
376
+ <head>
377
+ <title>MyClassicApp</title>
378
+
379
+ {{content-for "head"}}
380
+
381
+ <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
382
+ <link integrity="" rel="stylesheet" href="{{rootURL}}assets/my-classic-app.css">
383
+ <link rel="icon" href="{{rootURL}}assets/favicon.png">
384
+
385
+ {{content-for "head-footer"}}
386
+ </head>
387
+ <body>
388
+ {{content-for "body"}}
389
+
390
+ <script src="{{rootURL}}assets/vendor.js"></script>
391
+ <script src="{{rootURL}}assets/my-classic-app.js"></script>
392
+
393
+ {{content-for "body-footer"}}
394
+ </body>
395
+ </html>
396
+ `,
397
+ "app/app.ts": `import Application from '@ember/application';
398
+ import Resolver from 'ember-resolver';
399
+ import loadInitializers from 'ember-load-initializers';
400
+ import config from 'my-classic-app/config/environment';
401
+
402
+ export default class App extends Application {
403
+ modulePrefix = config.modulePrefix;
404
+ podModulePrefix = config.podModulePrefix;
405
+ Resolver = Resolver;
406
+ }
407
+
408
+ loadInitializers(App, config.modulePrefix);
409
+ `,
410
+ "app/router.ts": appBlueprint["app/router.ts"]!.replace("my-app", "my-classic-app"),
411
+ "app/styles/app.css": "",
412
+ "app/templates/application.gts": `<template>{{outlet}}</template>\n`,
413
+ "tsconfig.json": json({
414
+ extends: "@tsconfig/ember",
415
+ glint: { environment: ["ember-loose", "ember-template-imports"] },
416
+ compilerOptions: {
417
+ baseUrl: ".",
418
+ paths: { "my-classic-app/*": ["app/*"], "*": ["types/*"] },
419
+ types: ["ember-source/types"],
420
+ },
421
+ }),
422
+ "types/global.d.ts": `import '@glint/environment-ember-loose';\n`,
423
+ "testem.js": `'use strict';
424
+
425
+ module.exports = {
426
+ test_page: 'tests/index.html?hidepassed',
427
+ launch_in_ci: ['Chrome'],
428
+ browser_args: {
429
+ Chrome: {
430
+ ci: [
431
+ process.env.CI ? '--no-sandbox' : null,
432
+ '--headless',
433
+ '--disable-dev-shm-usage',
434
+ '--disable-software-rasterizer',
435
+ '--mute-audio',
436
+ '--remote-debugging-port=0',
437
+ '--window-size=1440,900',
438
+ ].filter(Boolean),
439
+ },
440
+ },
441
+ };
442
+ `,
443
+ "tests/index.html": `{{content-for "test-head"}}\n`,
444
+ "tests/test-helper.ts": appBlueprint["tests/test-helper.ts"]!.replaceAll(
445
+ "my-app",
446
+ "my-classic-app",
447
+ ),
448
+ };
449
+
450
+ export const classicAddon: Record<string, string> = {
451
+ "package.json": json({
452
+ name: "my-classic-addon",
453
+ version: "0.0.0",
454
+ keywords: ["ember-addon"],
455
+ scripts: {
456
+ build: "ember build --environment=production",
457
+ start: "ember serve",
458
+ "test:ember": "ember test",
459
+ "test:ember-compatibility": "ember try:each",
460
+ },
461
+ dependencies: {
462
+ "ember-cli-babel": "^8.3.2",
463
+ "ember-cli-htmlbars": "^7.0.1",
464
+ "ember-template-imports": "^4.4.0",
465
+ },
466
+ devDependencies: {
467
+ "ember-cli": "~7.5.0-alpha.1",
468
+ "ember-qunit": "^9.1.0",
469
+ "ember-source": "~7.3.0",
470
+ },
471
+ peerDependencies: { "ember-source": ">= 4.0.0" },
472
+ "ember-addon": { configPath: "tests/dummy/config" },
473
+ }),
474
+ "index.js": `'use strict';\n\nmodule.exports = {\n name: require('./package').name,\n};\n`,
475
+ "ember-cli-build.js": `'use strict';
476
+
477
+ const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
478
+
479
+ module.exports = function (defaults) {
480
+ return new EmberAddon(defaults, {}).toTree();
481
+ };
482
+ `,
483
+ ".npmignore": "/tests/\n",
484
+ ".prettierrc.js": `'use strict';\n\nmodule.exports = { singleQuote: true };\n`,
485
+ "testem.js": classicApp["testem.js"]!,
486
+ "addon/.gitkeep": "",
487
+ "app/.gitkeep": "",
488
+ "tests/dummy/app/app.js": `import Application from '@ember/application';\n\nexport default class App extends Application {}\n`,
489
+ "tests/dummy/app/router.js": `import EmberRouter from '@ember/routing/router';\n\nexport default class Router extends EmberRouter {}\n\nRouter.map(function () {});\n`,
490
+ "tests/dummy/app/templates/application.gjs": `import pageTitle from 'ember-page-title/helpers/page-title';
491
+
492
+ <template>
493
+ {{pageTitle "Dummy"}}
494
+
495
+ <h2 id="title">Welcome to Ember</h2>
496
+
497
+ {{outlet}}
498
+ </template>
499
+ `,
500
+ "tests/dummy/config/environment.js": appBlueprint["config/environment.js"]!.replace(
501
+ "my-app",
502
+ "dummy",
503
+ ),
504
+ "tests/index.html": `{{content-for "test-head"}}\n`,
505
+ "tests/test-helper.js": `import Application from 'dummy/app';\nexport function start() {}\n`,
506
+ };