diff --git a/files/_js_babel.config.cjs b/files/_js_babel.config.cjs index 419088a..57f7df2 100644 --- a/files/_js_babel.config.cjs +++ b/files/_js_babel.config.cjs @@ -1,7 +1,13 @@ +<% if (compat) { %> const { babelCompatSupport, templateCompatSupport, } = require('@embroider/compat/babel'); +<% } else { %> +const { buildMacros } = require('@embroider/macros/babel'); + +const macros = buildMacros(); +<% } %> module.exports = { plugins: [ @@ -13,8 +19,9 @@ module.exports = { 'ember-cli-htmlbars', 'ember-cli-htmlbars-inline-precompile', 'htmlbars-inline-precompile', - ], - transforms: [...templateCompatSupport()], + ],<% if (compat) { %> + transforms: [...templateCompatSupport()],<% } else { %> + transforms: [...macros.templateMacros],<% } %> }, ], [ @@ -32,8 +39,9 @@ module.exports = { useESModules: true, regenerator: false, }, - ], - ...babelCompatSupport(), + ],<% if (compat) { %> + ...babelCompatSupport(),<% } else { %> + ...macros.babelMacros,<% } %> ], generatorOpts: { diff --git a/files/_ts_babel.config.cjs b/files/_ts_babel.config.cjs index 9572987..a79aaaf 100644 --- a/files/_ts_babel.config.cjs +++ b/files/_ts_babel.config.cjs @@ -1,7 +1,13 @@ +<% if (compat) { %> const { babelCompatSupport, templateCompatSupport, } = require('@embroider/compat/babel'); +<% } else { %> +const { buildMacros } = require('@embroider/macros/babel'); + +const macros = buildMacros(); +<% } %> module.exports = { plugins: [ @@ -21,8 +27,9 @@ module.exports = { 'ember-cli-htmlbars', 'ember-cli-htmlbars-inline-precompile', 'htmlbars-inline-precompile', - ], - transforms: [...templateCompatSupport()], + ],<% if (compat) { %> + transforms: [...templateCompatSupport()],<% } else { %> + transforms: [...macros.templateMacros],<% } %> }, ], [ @@ -40,8 +47,9 @@ module.exports = { useESModules: true, regenerator: false, }, - ], - ...babelCompatSupport(), + ],<% if (compat) { %> + ...babelCompatSupport(),<% } else { %> + ...macros.babelMacros,<% } %> ], generatorOpts: { diff --git a/files/app/app.ts b/files/app/app.ts index fae6378..6105f05 100644 --- a/files/app/app.ts +++ b/files/app/app.ts @@ -1,7 +1,8 @@ -import Application from '@ember/application'; -import compatModules from '@embroider/virtual/compat-modules'; -import Resolver from 'ember-resolver'; -import loadInitializers from 'ember-load-initializers'; +import Application from '@ember/application';<% if (compat) { %> +import compatModules from '@embroider/virtual/compat-modules';<% } else { %> +import { registry } from './registry.ts';<% } %> +import Resolver from 'ember-resolver';<% if (compat) %> +import loadInitializers from 'ember-load-initializers';<% } %> import config from '<%= modulePrefix %>/config/environment'; import { importSync, isDevelopingApp, macroCondition } from '@embroider/macros'; @@ -11,8 +12,9 @@ if (macroCondition(isDevelopingApp())) { export default class App extends Application { modulePrefix = config.modulePrefix; - podModulePrefix = config.podModulePrefix; - Resolver = Resolver.withModules(compatModules); + podModulePrefix = config.podModulePrefix;<% if (compat) { %> + Resolver = Resolver.withModules(compatModules);<% } else { %> + Resolver = Resolver.withModules(registry);<% } %> } - -loadInitializers(App, config.modulePrefix, compatModules); +<% if (compat) { %> +loadInitializers(App, config.modulePrefix, compatModules);<% } %> diff --git a/files/app/config/environment.ts b/files/app/config/__compat__environment.ts similarity index 100% rename from files/app/config/environment.ts rename to files/app/config/__compat__environment.ts diff --git a/files/app/config/__no-compat__environment.ts b/files/app/config/__no-compat__environment.ts new file mode 100644 index 0000000..3858dd3 --- /dev/null +++ b/files/app/config/__no-compat__environment.ts @@ -0,0 +1,30 @@ +import { getGlobalConfig } from '@embroider/macros/src/addon/runtime'; + +const ENV = { + modulePrefix: 'limber', + environment: import.meta.env.DEV ? 'development' : 'production', + rootURL: '/', + locationType: 'history', + EmberENV: {}, + APP: {}, +} as { + environment: string; + modulePrefix: string; + podModulePrefix?: string; + locationType: 'history' | 'hash' | 'none'; + rootURL: string; + EmberENV: Record; + APP: Record; +}; + +export default ENV; + +export function enterTestMode() { + ENV.locationType = 'none'; + ENV.APP.rootElement = '#ember-testing'; + ENV.APP.autoboot = false; + + let config = getGlobalConfig()['@embroider/macros']; + + if (config) config.isTesting = true; +} diff --git a/files/app/registry.ts b/files/app/registry.ts new file mode 100644 index 0000000..5b08859 --- /dev/null +++ b/files/app/registry.ts @@ -0,0 +1,31 @@ +import PageTitleService from 'ember-page-title/services/page-title'; + +import Router from './router.ts'; + +const appName = '<%= modulePrefix %>'; + +function formatAsResolverEntries(imports: Record) { + return Object.fromEntries( + Object.entries(imports).map(([k, v]) => [ + k.replace(/\.g?(j|t)s$/, '').replace(/^\.\//, `${appName}/`), + v, + ]) + ); +} + +/** + * A global registry is needed until: + * - Services can be referenced via import paths (rather than strings) + * - we design a new routing system + */ +const resolverRegistry = { + ...formatAsResolverEntries(import.meta.glob('./templates/**/*.{gjs,gts}', { eager: true })), + ...formatAsResolverEntries(import.meta.glob('./services/**/*.{js,ts}', { eager: true })), + ...formatAsResolverEntries(import.meta.glob('./routes/**/*.{js,ts}', { eager: true })), + [`${appName}/router`]: Router, +}; + +export const registry = { + [`${appName}/services/page-title`]: PageTitleService, + ...resolverRegistry, +}; diff --git a/files/package.json b/files/package.json index 8293c80..e9b8d01 100644 --- a/files/package.json +++ b/files/package.json @@ -53,10 +53,10 @@ "@ember/test-waiters": "^4.1.0", "@embroider/macros": "^1.18.0", "@embroider/core": "^4.1.0", - "@embroider/vite": "^1.1.5", - "@embroider/compat": "^4.1.0", - "@embroider/router": "^3.0.1", - "@embroider/config-meta-loader": "^1.0.0", + "@embroider/vite": "^1.1.5",<% if (compat) { %> + "@embroider/compat": "^4.1.0",<% } %> + "@embroider/router": "^3.0.1",<% if (compat) { %> + "@embroider/config-meta-loader": "^1.0.0",<% } %> "@eslint/js": "^9.27.0", "@glimmer/component": "^2.0.0<% if (typescript) { %>", "@glint/core": "^1.5.2", @@ -75,8 +75,8 @@ "ember-cli": "~6.5.0-beta.0", "ember-cli-babel": "^8.2.0", "ember-cli-deprecation-workflow": "^3.3.0<% if (emberData) { %>", - "ember-data": "~5.5.0<% } %>", - "ember-load-initializers": "^3.0.1", + "ember-data": "~5.5.0<% } %>",<% if (compat) { %> + "ember-load-initializers": "^3.0.1",<% } %> "ember-modifier": "^4.2.2", "ember-page-title": "^9.0.2", "ember-qunit": "^9.0.3", diff --git a/files/vite.config.mjs b/files/vite.config.mjs index 219253d..2762aa9 100644 --- a/files/vite.config.mjs +++ b/files/vite.config.mjs @@ -3,8 +3,8 @@ import { extensions, classicEmberSupport, ember } from '@embroider/vite'; import { babel } from '@rollup/plugin-babel'; export default defineConfig({ - plugins: [ - classicEmberSupport(), + plugins: [<% if (compat) { %> + classicEmberSupport(),<% } %> ember(), // extra plugins here babel({ diff --git a/index.js b/index.js index c1a89cd..e6f5b10 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,16 @@ const stringUtil = require('ember-cli-string-utils'); const chalk = require('chalk'); const directoryForPackageName = require('./lib/directory-for-package-name'); +function hasCompat(options) { + let compat = options.compat ?? true; + + if (options.noCompat) { + compat = false; + } + + return compat; +} + module.exports = { description: 'The default blueprint for ember-cli projects.', @@ -59,6 +69,8 @@ module.exports = { execBinPrefix = 'pnpm'; } + let compat = hasCompat(options); + return { appDirectory: directoryForPackageName(name), name, @@ -79,6 +91,8 @@ module.exports = { ciProvider: options.ciProvider, typescript: options.typescript, packageManager: options.packageManager ?? 'npm', + compat: compat, + noCompat: !compat, }; }, @@ -106,6 +120,18 @@ module.exports = { files = files.filter((file) => !file.includes('ember-data/')); } + if (hasCompat(options)) { + files = files.filter((file) => { + if (file.includes('ember-cli-build.js')) return false; + if (file.includes('config/environment.js')) return false; + if (file.includes('config/targets.js')) return false; + + return true; + }); + } else { + files = files.filter((file) => !file.includes('registry.ts')); + } + this._files = files; return this._files; @@ -162,6 +188,30 @@ module.exports = { return fileInfo; } + if (file.includes('__compat__')) { + if (!hasCompat(options)) { + return null; + } + + let prefix = '__compat__'; + fileInfo.outputBasePath = fileInfo.outputPath.replace(prefix, ''); + fileInfo.outputPath = fileInfo.outputPath.replace(prefix, ''); + fileInfo.displayPath = fileInfo.outputPath.replace(prefix, ''); + return fileInfo; + } + + if (file.includes('__no-compat__')) { + if (hasCompat(options)) { + return null; + } + + let prefix = '__no-compat__'; + fileInfo.outputBasePath = fileInfo.outputPath.replace(prefix, ''); + fileInfo.outputPath = fileInfo.outputPath.replace(prefix, ''); + fileInfo.displayPath = fileInfo.outputPath.replace(prefix, ''); + return fileInfo; + } + return fileInfo; }, };