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