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