1"use strict"; 2 3Object.defineProperty(exports, "__esModule", { 4 value: true 5}); 6exports.environmentVariableSerializerPlugin = environmentVariableSerializerPlugin; 7exports.getTransformEnvironment = getTransformEnvironment; 8exports.replaceEnvironmentVariables = replaceEnvironmentVariables; 9exports.serverPreludeSerializerPlugin = serverPreludeSerializerPlugin; 10function _CountingSet() { 11 const data = _interopRequireDefault(require("metro/src/lib/CountingSet")); 12 _CountingSet = function () { 13 return data; 14 }; 15 return data; 16} 17function _countLines() { 18 const data = _interopRequireDefault(require("metro/src/lib/countLines")); 19 _countLines = function () { 20 return data; 21 }; 22 return data; 23} 24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 25/** 26 * Copyright © 2022 650 Industries. 27 * 28 * This source code is licensed under the MIT license found in the 29 * LICENSE file in the root directory of this source tree. 30 */ 31 32const debug = require('debug')('expo:metro-config:serializer:env-var'); 33function replaceEnvironmentVariables(code, env) { 34 // match and replace env variables that aren't NODE_ENV or JEST_WORKER_ID 35 // return code.match(/process\.env\.(EXPO_PUBLIC_[A-Z_]+)/g); 36 return code.replace(/process\.env\.([a-zA-Z0-9_]+)/gm, match => { 37 var _env$name; 38 const name = match.replace('process.env.', ''); 39 if ( 40 // Must start with EXPO_PUBLIC_ to be replaced 41 !/^EXPO_PUBLIC_/.test(name)) { 42 return match; 43 } 44 const value = JSON.stringify((_env$name = env[name]) !== null && _env$name !== void 0 ? _env$name : ''); 45 debug(`Inlining environment variable "${match}" with ${value}`); 46 return value; 47 }); 48} 49function getTransformEnvironment(url) { 50 const match = url.match(/[&?]transform\.environment=([^&]+)/); 51 return match ? match[1] : null; 52} 53function getAllExpoPublicEnvVars() { 54 // Create an object containing all environment variables that start with EXPO_PUBLIC_ 55 const env = {}; 56 for (const key in process.env) { 57 if (key.startsWith('EXPO_PUBLIC_')) { 58 // @ts-ignore 59 env[key] = process.env[key]; 60 } 61 } 62 return env; 63} 64 65/** Strips the process.env polyfill in server environments to allow for accessing environment variables off the global. */ 66function serverPreludeSerializerPlugin(entryPoint, preModules, graph, options) { 67 if (options.sourceUrl && getTransformEnvironment(options.sourceUrl) === 'node') { 68 const prelude = preModules.find(module => module.path === '__prelude__'); 69 if (prelude) { 70 debug('Stripping environment variable polyfill in server environment.'); 71 prelude.output[0].data.code = prelude.output[0].data.code.replace(/process=this\.process\|\|{},/, '').replace(/process\.env=process\.env\|\|{};process\.env\.NODE_ENV=process\.env\.NODE_ENV\|\|"\w+";/, ''); 72 } 73 } 74 return [entryPoint, preModules, graph, options]; 75} 76function environmentVariableSerializerPlugin(entryPoint, preModules, graph, options) { 77 // Skip replacement in Node.js environments. 78 if (options.sourceUrl && getTransformEnvironment(options.sourceUrl) === 'node') { 79 debug('Skipping environment variable inlining in Node.js environment.'); 80 return [entryPoint, preModules, graph, options]; 81 } 82 83 // Adds about 5ms on a blank Expo Router app. 84 // TODO: We can probably cache the results. 85 86 // In development, we need to add the process.env object to ensure it 87 // persists between Fast Refresh updates. 88 if (options.dev) { 89 // Set the process.env object to the current environment variables object 90 // ensuring they aren't iterable, settable, or enumerable. 91 const str = `process.env=Object.defineProperties(process.env, {${Object.keys(getAllExpoPublicEnvVars()).map(key => `${JSON.stringify(key)}: { value: ${JSON.stringify(process.env[key])} }`).join(',')}});`; 92 const [firstModule, ...restModules] = preModules; 93 // const envCode = `var process=this.process||{};${str}`; 94 // process.env 95 return [entryPoint, [ 96 // First module defines the process.env object. 97 firstModule, 98 // Second module modifies the process.env object. 99 getEnvPrelude(str), 100 // Now we add the rest 101 ...restModules], graph, options]; 102 } 103 104 // In production, inline all process.env variables to ensure they cannot be iterated and read arbitrarily. 105 for (const value of graph.dependencies.values()) { 106 // Skip node_modules, the feature is a bit too sensitive to allow in arbitrary code. 107 if (/node_modules/.test(value.path)) { 108 continue; 109 } 110 for (const index in value.output) { 111 // TODO: This probably breaks source maps. 112 const code = replaceEnvironmentVariables(value.output[index].data.code, process.env); 113 value.output[index].data.code = code; 114 } 115 } 116 return [entryPoint, preModules, graph, options]; 117} 118function getEnvPrelude(contents) { 119 const code = '// HMR env vars from Expo CLI (dev-only)\n' + contents; 120 const name = '__env__'; 121 const lineCount = (0, _countLines().default)(code); 122 return { 123 dependencies: new Map(), 124 getSource: () => Buffer.from(code), 125 inverseDependencies: new (_CountingSet().default)(), 126 path: name, 127 output: [{ 128 type: 'js/script/virtual', 129 data: { 130 code, 131 // @ts-expect-error: typed incorrectly upstream 132 lineCount, 133 map: [] 134 } 135 }] 136 }; 137} 138//# sourceMappingURL=environmentVariableSerializerPlugin.js.map