diff --git a/lib/babel-options-util.js b/lib/babel-options-util.js index ee26306b..592d3284 100644 --- a/lib/babel-options-util.js +++ b/lib/babel-options-util.js @@ -437,6 +437,38 @@ function _addClassProperties(addPlugin, plugins, options, config, parent, projec ); } +function _addImportMetaEnv(plugins, parent, project) { + const { hasPlugin, addPlugin } = require("ember-cli-babel-plugin-helpers"); + + if (hasPlugin(plugins, "@import-meta-env/babel")) { + if (parent === project) { + project.ui.writeWarnLine( + `${_parentName( + parent + )} has added the @import-meta-env/babel plugin to its build, but ember-cli-babel provides this by default! You can remove the plugin, or the addon that provided it.` + ); + } + } else { + const isProduction = process.env.EMBER_ENV === "production"; + const isDebug = !isProduction; + + addPlugin( + plugins, + [ + require.resolve('@import-meta-env/babel'), + { + env: { + DEV: isDebug, + PROD: isProduction, + } + } + ], + ); + } + + return plugins; +} + function _addTypeScriptPlugin(plugins, parent, project) { const { hasPlugin, addPlugin } = require("ember-cli-babel-plugin-helpers"); @@ -627,6 +659,7 @@ function _shouldIncludeHelpers(options, appInstance) { module.exports = { _addDecoratorPlugins, _addTypeScriptPlugin, + _addImportMetaEnv, _getAddonProvidedConfig, _shouldCompileModules, _shouldIncludeHelpers, diff --git a/lib/ember-plugins.js b/lib/ember-plugins.js index 66509a31..625a1baa 100644 --- a/lib/ember-plugins.js +++ b/lib/ember-plugins.js @@ -147,8 +147,8 @@ function _getEmberDataPackagesPolyfill(appRoot, config) { function _getModuleResolutionPlugins(config) { if (!config.disableModuleResolution) { - const resolvePath = require("../lib/relative-module-paths") - .resolveRelativeModulePath; + const resolvePath = + require("../lib/relative-module-paths").resolveRelativeModulePath; return [ [require.resolve("babel-plugin-module-resolver"), { resolvePath }], [ @@ -162,16 +162,16 @@ function _getModuleResolutionPlugins(config) { function _getProposalDecoratorsAndClassPlugins(config) { if (!config.shouldIgnoreDecoratorAndClassPlugins) { return [ - /** - * Required for apps to use `@ember/template-compliation` - * for transforming templates from babel-plugin-ember-template-compilation - * which shipped in ember-cli-htmlbars 6.2 - * - * Normally this plugin wouldn't be required because the feature has shipped - * in all browsers, but because we have legacy decorators, and - * legacy decorators do not support parsing the static block syntax, - * we need to compile it away. - */ + /** + * Required for apps to use `@ember/template-compliation` + * for transforming templates from babel-plugin-ember-template-compilation + * which shipped in ember-cli-htmlbars 6.2 + * + * Normally this plugin wouldn't be required because the feature has shipped + * in all browsers, but because we have legacy decorators, and + * legacy decorators do not support parsing the static block syntax, + * we need to compile it away. + */ ["@babel/plugin-transform-class-static-block"], ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties"], @@ -179,6 +179,18 @@ function _getProposalDecoratorsAndClassPlugins(config) { } } +function _getImportMetaEnv(config) { + const isProduction = process.env.EMBER_ENV === "production"; + const isDebug = !isProduction; + + return [ + [ + "module:@import-meta-env/babel", + { env: { DEV: isDebug, PROD: isProduction } }, + ], + ]; +} + /** * This function allows returns all the required Ember specific babel plugins for the app to transpile correctly. * As the first argument, you need to pass in the appRoot (which is usually the __dirname). @@ -198,6 +210,7 @@ function _getProposalDecoratorsAndClassPlugins(config) { module.exports = function (appRoot, config = {}) { return [] .concat( + _getImportMetaEnv(config), _getProposalDecoratorsAndClassPlugins(config), _getDebugMacroPlugins(appRoot), _getEmberModulesAPIPolyfill(appRoot, config), @@ -211,4 +224,5 @@ module.exports.getDebugMacroPlugins = _getDebugMacroPlugins; module.exports.getEmberModulesAPIPolyfill = _getEmberModulesAPIPolyfill; module.exports.getEmberDataPackagesPolyfill = _getEmberDataPackagesPolyfill; module.exports.getModuleResolutionPlugins = _getModuleResolutionPlugins; -module.exports.getProposalDecoratorsAndClassPlugins = _getProposalDecoratorsAndClassPlugins; +module.exports.getProposalDecoratorsAndClassPlugins = + _getProposalDecoratorsAndClassPlugins; diff --git a/lib/get-babel-options.js b/lib/get-babel-options.js index 41f73f7e..ecd862a2 100644 --- a/lib/get-babel-options.js +++ b/lib/get-babel-options.js @@ -1,6 +1,7 @@ const { _addDecoratorPlugins, _addTypeScriptPlugin, + _addImportMetaEnv, _getAddonProvidedConfig, _shouldCompileModules, _shouldIncludeHelpers, @@ -47,6 +48,8 @@ module.exports = function getBabelOptions(config, appInstance) { ); } + userPlugins = _addImportMetaEnv(userPlugins.slice(), parent, project), + options.plugins = [] .concat( shouldIncludeHelpers && _getHelpersPlugin(project), diff --git a/node-tests/get-babel-options-test.js b/node-tests/get-babel-options-test.js index 4dfeac70..18c07431 100644 --- a/node-tests/get-babel-options-test.js +++ b/node-tests/get-babel-options-test.js @@ -4,6 +4,7 @@ const CoreObject = require("core-object"); const AddonMixin = require("../index"); let { _addTypeScriptPlugin, + _addImportMetaEnv, _getAddonProvidedConfig, _addDecoratorPlugins, } = require("../lib/babel-options-util"); @@ -66,6 +67,39 @@ describe("get-babel-options", function () { }); }); + describe("_getImportMetaEnv", function () { + it("it should preconfigure meta.env.DEV and meta.env.PROD based on the same state @ember/debug uses", function () { + let result = _addImportMetaEnv( + [], + {}, + this.addon.parent, + this.addon.project + ); + + expect(result.length).to.equal(1, "plugin was added"); + expect(result[0][0]).to.equal(require.resolve('@import-meta-env/babel')); + expect(result[0][1]).to.deep.equal({ env: { DEV: true, PROD: false }}); + }); + + it("should warn and not add the plugin if already added", function () { + this.addon.project.ui = { + writeWarnLine(message) { + expect(message).to.match( + /has added the @import-meta-env/ + ); + }, + }; + expect( + _addImportMetaEnv( + [["@import-meta-env/babel"]], + {}, + this.addon.parent, + this.addon.project + ).length + ).to.equal(1, "plugin was not added"); + }); + }); + describe("_addDecoratorPlugins", function () { it("should include babel transforms by default", function () { expect( diff --git a/package.json b/package.json index f83d2611..e75ad844 100644 --- a/package.json +++ b/package.json @@ -46,14 +46,15 @@ "@babel/helper-compilation-targets": "^7.20.7", "@babel/plugin-proposal-class-properties": "^7.16.5", "@babel/plugin-proposal-decorators": "^7.20.13", - "@babel/plugin-transform-class-static-block": "^7.22.11", "@babel/plugin-proposal-private-methods": "^7.16.5", "@babel/plugin-proposal-private-property-in-object": "^7.20.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", "@babel/plugin-transform-modules-amd": "^7.20.11", "@babel/plugin-transform-runtime": "^7.13.9", "@babel/plugin-transform-typescript": "^7.20.13", "@babel/preset-env": "^7.20.2", "@babel/runtime": "7.12.18", + "@import-meta-env/babel": "^0.4.4", "amd-name-resolver": "^1.3.1", "babel-plugin-debug-macros": "^0.3.4", "babel-plugin-ember-data-packages-polyfill": "^0.1.2", @@ -65,6 +66,7 @@ "broccoli-source": "^3.0.1", "calculate-cache-key-for-tree": "^2.0.0", "clone": "^2.1.2", + "dotenv": "^16.3.1", "ember-cli-babel-plugin-helpers": "^1.1.1", "ember-cli-version-checker": "^5.1.2", "ensure-posix-path": "^1.0.2", diff --git a/tests/acceptance/simple-test.js b/tests/acceptance/simple-test.js index df12cf91..c5953d40 100755 --- a/tests/acceptance/simple-test.js +++ b/tests/acceptance/simple-test.js @@ -5,6 +5,11 @@ import { setupApplicationTest } from 'ember-qunit'; module('Acceptance | ES6 features work correctly', function(hooks) { setupApplicationTest(hooks); + test('import.meta.env', function (assert) { + assert.true(import.meta.env.DEV); + assert.false(import.meta.env.PROD); + }); + test('visit /', async function(assert) { await visit('/'); diff --git a/yarn.lock b/yarn.lock index 2b3454cb..fd8dbd88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -178,7 +178,7 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== @@ -1470,6 +1470,14 @@ resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== +"@import-meta-env/babel@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@import-meta-env/babel/-/babel-0.4.4.tgz#8c6be1df6fc7550670210e7c4f587de853a0429c" + integrity sha512-x+m7dgDcEczXyMFUOiozht1SzDuG0/UYdCPFakeSr1iDQbEeJvhzkC6sXRWr5GzV6fru6JHcOiLV1xulID0oNw== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + picocolors "^1.0.0" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -4265,6 +4273,11 @@ dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" +dotenv@^16.3.1: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"