From a4ab7a2e0473f7b979f25232bb8b01679154ac52 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Wed, 15 Mar 2023 15:45:36 +0100 Subject: [PATCH] feat: support `import.meta.env` (#129) --- src/babel.ts | 2 + src/plugins/import-meta-env.ts | 105 +++++++++++++++++++++++ test/__snapshots__/fixtures.test.ts.snap | 5 ++ test/fixtures/env/index.ts | 3 + 4 files changed, 115 insertions(+) create mode 100644 src/plugins/import-meta-env.ts create mode 100644 test/fixtures/env/index.ts diff --git a/src/babel.ts b/src/babel.ts index 751b7e7b..067c05b4 100644 --- a/src/babel.ts +++ b/src/babel.ts @@ -5,6 +5,7 @@ import type { } from "@babel/core"; import { TransformOptions, TRANSFORM_RESULT } from "./types"; import { TransformImportMetaPlugin } from "./plugins/babel-plugin-transform-import-meta"; +import { importMetaEnvPlugin } from "./plugins/import-meta-env"; export default function transform(opts: TransformOptions): TRANSFORM_RESULT { const _opts: BabelTransformOptions & { plugins: PluginItem[] } = { @@ -25,6 +26,7 @@ export default function transform(opts: TransformOptions): TRANSFORM_RESULT { [TransformImportMetaPlugin, { filename: opts.filename }], [require("@babel/plugin-syntax-class-properties")], [require("@babel/plugin-proposal-export-namespace-from")], + [importMetaEnvPlugin], ], }; diff --git a/src/plugins/import-meta-env.ts b/src/plugins/import-meta-env.ts new file mode 100644 index 00000000..8732e001 --- /dev/null +++ b/src/plugins/import-meta-env.ts @@ -0,0 +1,105 @@ +/** + * Based on https://github.com/iendeavor/import-meta-env/tree/main/packages/babel 0.4.2 (MIT) + +Modified to use runtime only without dotenv dependency + +--- + +MIT License + +Copyright (c) 2021 Ernest + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +import type BabelCore from "@babel/core"; +import type { PluginObj } from "@babel/core"; + +export const accessor = `process.env`; + +const replaceEnvForRuntime = ( + template: typeof BabelCore.template, + property: string +) => template.expression.ast(`${accessor}.${property}`); + +export function importMetaEnvPlugin({ template, types }: any) { + return { + name: "@import-meta-env/babel", + visitor: { + Identifier(path) { + if (!types.isIdentifier(path)) { + return; + } + + // {}.{} + if (!types.isMemberExpression(path.parentPath)) { + return; + } + // {}.{}.{} + if (!types.isMemberExpression(path.parentPath.node)) { + return; + } + // {}.{}.{}.{} + // @ts-ignore + if (!types.isMemberExpression(path.parentPath.node.object)) { + return; + } + + // {}.{}.{}.PROPERTY + // @ts-ignore + if (path.parentPath.computed) { + return; + } + // @ts-ignore + if (!types.isIdentifier(path.parentPath.node.property)) { + return; + } + + // {}.{}.env.PROPERTY + // @ts-ignore + if (!types.isIdentifier(path.parentPath.node.object.property)) { + return; + } + // @ts-ignore + if (path.parentPath.node.object.property.name !== "env") { + return; + } + + // import.meta.env.PROPERTY + // @ts-ignore + if (!types.isMetaProperty(path.parentPath.node.object.object)) { + return; + } + // @ts-ignore + if (path.parentPath.node.object.object.property.name !== "meta") { + return; + } + // @ts-ignore + if (path.parentPath.node.object.object.meta.name !== "import") { + return; + } + + path.parentPath.replaceWith( + // @ts-ignore + replaceEnvForRuntime(template, path.parentPath.node.property.name) + ); + }, + }, + }; +} diff --git a/test/__snapshots__/fixtures.test.ts.snap b/test/__snapshots__/fixtures.test.ts.snap index 7159640f..d7f9539a 100644 --- a/test/__snapshots__/fixtures.test.ts.snap +++ b/test/__snapshots__/fixtures.test.ts.snap @@ -4,6 +4,11 @@ exports[`fixtures > async > stdout 1`] = `"works"`; exports[`fixtures > circular > stdout 1`] = `"FooBar"`; +exports[`fixtures > env > stdout 1`] = ` +"process.env.TEST true +import.meta.env.TEST true" +`; + exports[`fixtures > error-parse > stderr 1`] = ` "/lib/index.js:2 throw err; /* ↓ Check stack trace ↓ */ diff --git a/test/fixtures/env/index.ts b/test/fixtures/env/index.ts new file mode 100644 index 00000000..6a8d05af --- /dev/null +++ b/test/fixtures/env/index.ts @@ -0,0 +1,3 @@ +console.log("process.env.TEST", process.env.TEST); +// @ts-ignore +console.log("import.meta.env.TEST", import.meta.env.TEST);