-
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathenv.ts
More file actions
156 lines (129 loc) · 4.67 KB
/
env.ts
File metadata and controls
156 lines (129 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { confirm } from '@inquirer/prompts';
import fs from 'fs-extra';
import ora from 'ora';
import path from 'path';
import { globals } from '../constants';
import addDependency from '../util/addDependency';
import addToGitignore from '../util/addToGitignore';
import commit, { handleCommitError } from '../util/commit';
import copyTemplate from '../util/copyTemplate';
import getProjectDir from '../util/getProjectDir';
import print from '../util/print';
import writeFile from '../util/writeFile';
type Options = {
interactive?: boolean;
};
const API_PATH = 'src/util/api/api.ts';
const HARDCODED_API_URL = "'https://api.github.com/orgs/thoughtbot/repos'";
const REPLACED_API_URL =
// eslint-disable-next-line no-template-curly-in-string
"`${process.env.EXPO_PUBLIC_API_BASE_URL ?? ''}/orgs/thoughtbot/repos`";
const JEST_CONFIG_PATH = 'jest.config.js';
const JEST_SETUP_FILES_BEFORE = ' setupFilesAfterEnv: [';
const JEST_SETUP_FILES_AFTER =
" setupFiles: ['./jest.setup.env.js'],\n setupFilesAfterEnv: [";
async function patchFile(
filePath: string,
search: string,
replacement: string,
): Promise<boolean> {
if (!(await fs.pathExists(filePath))) return false;
const contents = (await fs.readFile(filePath)).toString();
const updated = contents.replace(search, replacement);
if (updated === contents) return false;
await writeFile(filePath, updated, { format: true });
return true;
}
export async function addEnv(options: Options = {}) {
const { interactive = true } = options;
globals.interactive = interactive;
await printIntro();
const spinner = ora().start('Setting up environment configuration');
const projectDir = await getProjectDir();
await addDependency('dotenv', { dev: true });
await copyTemplate({
templateDir: 'environments',
templateFile: 'env.example',
destination: '.env.example',
});
await copyTemplate({
templateDir: 'environments',
templateFile: 'src/config/index.ts',
});
await copyTemplate({
templateDir: 'environments',
templateFile: 'jest.setup.env.js',
});
await copyTemplate({
templateDir: 'environments',
templateFile: 'env.test',
destination: '.env.test',
});
const envPath = path.join(projectDir, '.env');
if (!(await fs.pathExists(envPath))) {
await fs.copy(path.join(projectDir, '.env.example'), envPath);
}
await addToGitignore('.env');
const patchedApi = await patchFile(
path.join(projectDir, API_PATH),
HARDCODED_API_URL,
REPLACED_API_URL,
);
const patchedJest = await patchFile(
path.join(projectDir, JEST_CONFIG_PATH),
JEST_SETUP_FILES_BEFORE,
JEST_SETUP_FILES_AFTER,
);
await commit('Add environment variable management support.').catch(
handleCommitError,
);
spinner.succeed(`Successfully set up environment variable management!
What was added:
- .env.example: Template of environment variables (committed to git)
- .env: Your local environment variables (gitignored)
- .env.test: Environment variables for Jest (committed to git)
- jest.setup.env.js: Loads .env.test before tests run
- src/config/index.ts: Typed helper to access config values in your app${
patchedApi
? `\n - ${API_PATH}: Updated to use EXPO_PUBLIC_API_BASE_URL`
: ''
}${
patchedJest
? `\n - ${JEST_CONFIG_PATH}: Added setupFiles to load jest.setup.env.js`
: ''
}
Usage in your app:
import getConfig from 'src/config';
const { apiBaseUrl } = getConfig();
Variables prefixed with EXPO_PUBLIC_ are automatically loaded by the Expo CLI
and inlined into your app bundle — no dotenv or extra config required.
These values are visible in plain text in the compiled app.
Never store secrets as EXPO_PUBLIC_ variables.
`);
}
async function printIntro() {
print("Let's set up environment variable management!");
print(`
We will configure your Expo app to handle environment variables using the
built-in EXPO_PUBLIC_ mechanism. This includes:
- .env.example: Template showing your environment variables (committed)
- .env: Your local values (gitignored)
- .env.test: Environment variables for Jest tests (committed)
- jest.setup.env.js: Loads .env.test before each test run
- src/config/index.ts: Typed helper for safe config access
Variables prefixed with EXPO_PUBLIC_ are automatically loaded by the Expo CLI
and inlined into the app bundle at build time. No extra packages needed.
`);
if (!globals.interactive) {
return;
}
const proceed = await confirm({ message: 'Ready to proceed?' });
if (!proceed) {
process.exit(0);
}
print('');
}
export default function addEnvAction(...args: unknown[]) {
const options = (args[0] as unknown[])[0] as Options;
return addEnv(options);
}