|
1 |
| -import * as dotenv from 'dotenv'; |
2 |
| -import validator from 'validator'; |
3 |
| - |
4 |
| -dotenv.config(); |
5 |
| - |
6 |
| -// -------------------------------------------------------------------------------- |
| 1 | +import { Validator, ConfigSchema } from './env-validation'; |
7 | 2 |
|
8 | 3 | // --------------------------------------------------------------------------------
|
9 | 4 |
|
10 |
| -class EnvValidationError extends Error { |
11 |
| - constructor(message) { |
12 |
| - super(`\n${message}`); |
13 |
| - this.name = 'EnvValidationError'; |
14 |
| - } |
15 |
| -} |
16 |
| - |
17 |
| -// function validateEnvVariablesResults(errors: string[]): void { |
18 |
| -// if (0 < errors.length) { |
19 |
| -// throw new EnvValidationErrorr(errors.join('\n')); |
20 |
| -// } |
21 |
| -// } |
| 5 | +const v = new Validator(); |
22 | 6 |
|
23 |
| -function envErrorMessage(envName: string, envValue: string, message: string): string { |
24 |
| - return `[Env_Error] ${envName}: '${envValue}' ${message}`; |
25 |
| -} |
| 7 | +const mySchema = new ConfigSchema({ |
| 8 | + API_GATEWAY_PROTOCOL: v.protocol, |
| 9 | + API_GATEWAY_HOST: v.host, |
| 10 | + API_GATEWAY_PORT: v.port, |
| 11 | + API_GATEWAY_PROTOCOL_SECURE: v.protocol, |
| 12 | + API_ENDPOINT: v.endpoint, |
26 | 13 |
|
27 |
| -// -------------------------------------------------------------------------------- |
| 14 | + FRONT_END_URL: v.url, |
28 | 15 |
|
29 |
| -/** |
30 |
| - * Validation functions for environment variables |
31 |
| - */ |
| 16 | + MOBILE_APP: v.exists, |
| 17 | + MOBILE_APP_NAME: v.exists, |
| 18 | + MOBILE_APP_DOWNLOAD_URL: v.url, |
| 19 | + PLAY_STORE_DOWNLOAD_LINK: v.url, |
| 20 | + IOS_DOWNLOAD_LINK: v.url, |
32 | 21 |
|
33 |
| -export function isValidProtocol(protocol: string): boolean { |
34 |
| - return ['http', 'https'].includes(protocol); |
35 |
| -} |
| 22 | + PLATFORM_NAME: v.exists, |
| 23 | + POWERED_BY: v.exists, |
| 24 | + PLATFORM_WEB_URL: v.url, |
| 25 | + POWERED_BY_URL: v.url, |
| 26 | + UPLOAD_LOGO_HOST: v.host, |
| 27 | + BRAND_LOGO: v.url, |
| 28 | + PLATFORM_ADMIN_EMAIL: v.email, |
36 | 29 |
|
37 |
| -export function isValidHost(host: string): boolean { |
38 |
| - const ipv4Regex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/g; |
39 |
| - const ipv6Regex = |
40 |
| - /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))g/; |
41 |
| - return ipv4Regex.test(host) || 'localhost' === host || ipv6Regex.test(host); |
42 |
| -} |
43 |
| - |
44 |
| -export function isValidPort(port: string): boolean { |
45 |
| - const portNumber = Number(port); |
46 |
| - return !isNaN(portNumber) && 1024 < portNumber && 65536 > portNumber; |
47 |
| -} |
48 |
| - |
49 |
| -export function isValidEndpoint(endpoint: string): { errorMessage: string; isValid: boolean } { |
50 |
| - const [host, port] = endpoint.split(':'); |
51 |
| - return { |
52 |
| - errorMessage: envErrorMessage('VARIABLE', endpoint, 'is not a valid endpoint.'), |
53 |
| - isValid: isValidHost(host) && isValidPort(port) |
54 |
| - }; |
55 |
| -} |
56 |
| - |
57 |
| -export function isValidURL(url: string): { errorMessage: string; isValid: boolean } { |
58 |
| - return { |
59 |
| - errorMessage: envErrorMessage('VARIABLE', url, 'is not a valid URL.'), |
60 |
| - isValid: validator.isURL(url) || url.startsWith('http://localhost') // REVISAR |
61 |
| - }; |
62 |
| -} |
63 |
| - |
64 |
| -// export function isNotEmptyString(value: string): boolean { |
65 |
| -// return '' !== value.trim(); |
66 |
| -// } |
67 |
| - |
68 |
| -// -------------------------------------------------------------------------------- |
69 |
| - |
70 |
| -// class EnvValidationError extends Error { |
71 |
| -// constructor(envName: string, envValue: string, message: string) { |
72 |
| -// super(`[Env_Error] ${envName}: '${envValue}' ${message}`); |
73 |
| -// this.name = 'EnvValidationError'; |
74 |
| -// } |
75 |
| -// } |
76 |
| - |
77 |
| -type ValidatorFn = (envVariable: string) => { errorMessage: string; isValid: boolean }; |
78 |
| - |
79 |
| -type EnvValidationResult = { |
80 |
| - error: string; |
81 |
| - success: boolean; |
82 |
| - // data: { [K in keyof T]: string }; |
83 |
| -}; |
84 |
| - |
85 |
| -class EnvSchema { |
86 |
| - private schema: Record<string, ValidatorFn>; |
87 |
| - private errors: string[]; |
88 |
| - // private validatedVariables = {}; |
89 |
| - |
90 |
| - constructor(schema: Record<string, ValidatorFn>) { |
91 |
| - this.schema = schema; |
92 |
| - this.errors = []; |
93 |
| - } |
94 |
| - |
95 |
| - public validate(env: Record<string, string>): EnvValidationResult { |
96 |
| - for (const [envVariable, validatorFn] of Object.entries(this.schema)) { |
97 |
| - const { errorMessage, isValid } = validatorFn(env[envVariable]); |
98 |
| - |
99 |
| - if (!isValid) { |
100 |
| - this.errors.push(errorMessage); |
101 |
| - } |
102 |
| - } |
103 |
| - |
104 |
| - const hasErrors = 0 < this.errors.length; |
105 |
| - if (hasErrors) { |
106 |
| - return { |
107 |
| - error: this.errors.join('\n'), |
108 |
| - success: false |
109 |
| - }; |
110 |
| - } |
111 |
| - return { error: null, success: true }; |
112 |
| - } |
113 |
| -} |
114 |
| - |
115 |
| -const envSchema = new EnvSchema({ |
116 |
| - FRONT_END_URL: isValidURL, |
117 |
| - API_ENDPOINT: isValidEndpoint |
| 30 | + SOCKET_HOST: v.host |
118 | 31 | });
|
119 | 32 |
|
120 |
| -const { error, success } = envSchema.validate(process.env); |
| 33 | +const { errors, success, data } = mySchema.safeParse(); |
121 | 34 |
|
122 | 35 | if (!success) {
|
123 |
| - throw new EnvValidationError(error); |
| 36 | + throw errors; |
124 | 37 | }
|
125 | 38 |
|
126 |
| -// const { |
127 |
| -// // API |
128 |
| -// // API_GATEWAY_PROTOCOL, |
129 |
| -// // API_GATEWAY_HOST, |
130 |
| -// // API_GATEWAY_PORT, |
131 |
| -// // API_GATEWAY_PROTOCOL_SECURE, |
132 |
| -// // API_ENDPOINT, |
133 |
| - |
134 |
| -// // FRONT_END |
135 |
| -// // FRONT_END_URL |
136 |
| - |
137 |
| -// // MOBILE |
138 |
| -// // MOBILE_APP, |
139 |
| -// // MOBILE_APP_NAME, |
140 |
| -// // MOBILE_APP_DOWNLOAD_URL, |
141 |
| -// // PLAY_STORE_DOWNLOAD_LINK |
142 |
| -// // IOS_DOWNLOAD_LINK |
143 |
| -// } = process.env; |
144 |
| - |
145 |
| -// const { error , isSuccess, data } = validar(process.env); |
146 |
| - |
147 |
| -// if (!isSuccess) { |
148 |
| -// throw [new Error("pepe")]; |
149 |
| -// } |
150 |
| - |
151 |
| -// if (0 < errors.length) { |
152 |
| -// throw errors; |
153 |
| -// } |
154 |
| - |
155 |
| -// -------------------------------------------------------------------------------- |
156 |
| - |
157 |
| -// if (!isValidURL(FRONT_END_URL)) { |
158 |
| -// // throw new EnvValidationError('FRONT_END_URL', FRONT_END_URL, 'is not a valid URL.'); |
159 |
| -// errors.push(new EnvValidationError('FRONT_END_URL', FRONT_END_URL, 'is not a valid URL.')); |
160 |
| -// // errors.push(); |
161 |
| -// } |
162 |
| - |
163 |
| -// export { FRONT_END_URL }; |
164 |
| - |
165 |
| -// -------------------------------------------------------------------------------- |
166 |
| - |
167 |
| -// if (!isNotEmptyString(MOBILE_APP)) { |
168 |
| -// throw new EnvValidationError('MOBILE_APP', MOBILE_APP, 'must not be an empty string.'); |
169 |
| - |
170 |
| -// } |
171 |
| - |
172 |
| -// if (!isNotEmptyString(MOBILE_APP_NAME)) { |
173 |
| -// throw new EnvValidationError('MOBILE_APP_NAME', MOBILE_APP_NAME, 'is not a valid URL.'); |
174 |
| -// } |
175 |
| - |
176 |
| -// if (!isValidURL(MOBILE_APP_DOWNLOAD_URL)) { |
177 |
| -// throw new EnvValidationError('MOBILE_APP_DOWNLOAD_URL', MOBILE_APP_DOWNLOAD_URL, 'is not a valid URL.'); |
178 |
| -// } |
179 |
| - |
180 |
| -// if (!isValidURL(PLAY_STORE_DOWNLOAD_LINK)) { |
181 |
| -// throw new EnvValidationError('PLAY_STORE_DOWNLOAD_LINK', PLAY_STORE_DOWNLOAD_LINK, 'is not a valid URL.'); |
182 |
| -// } |
183 |
| - |
184 |
| -// -------------------------------------------------------------------------------- |
185 |
| - |
186 |
| -// if (!isValidProtocol(API_GATEWAY_PROTOCOL)) { |
187 |
| -// // throw new EnvValidationError('API_GATEWAY_PROTOCOL', API_GATEWAY_PROTOCOL, 'is not a valid protocol.'); |
188 |
| -// errors.push(new EnvValidationError('API_GATEWAY_PROTOCOL', API_GATEWAY_PROTOCOL, 'is not a valid protocol.')); |
189 |
| -// } |
190 |
| - |
191 |
| -// if (!isValidHost(API_GATEWAY_HOST)) { |
192 |
| -// // throw new EnvValidationError('API_GATEWAY_HOST', API_GATEWAY_HOST, 'is not a valid host.'); |
193 |
| -// errors.push(new EnvValidationError('API_GATEWAY_HOST', API_GATEWAY_HOST, 'is not a valid host.')); |
194 |
| -// } |
195 |
| - |
196 |
| -// const success = true; |
197 |
| - |
198 |
| -// if (success) { |
199 |
| -// throw errors; |
200 |
| -// } |
201 |
| - |
202 |
| -// if (!isValidPort(API_GATEWAY_PORT)) { |
203 |
| -// throw new EnvValidationError('API_GATEWAY_PORT', API_GATEWAY_PORT, 'is not a valid port.'); |
204 |
| -// } |
205 |
| - |
206 |
| -// if (!isValidProtocol(API_GATEWAY_PROTOCOL_SECURE)) { |
207 |
| -// throw new EnvValidationError('API_GATEWAY_PROTOCOL_SECURE', API_GATEWAY_PROTOCOL_SECURE, 'is not a valid protocol.'); |
208 |
| -// } |
209 |
| - |
210 |
| -// if (!isValidEndpoint(API_ENDPOINT)) { |
211 |
| -// throw new EnvValidationError('API_ENDPOINT', API_ENDPOINT, 'is not a valid endpoint.'); |
212 |
| -// } |
213 |
| - |
214 |
| -// export const API = { |
215 |
| -// GATEWAY_PROTOCOL: API_GATEWAY_PROTOCOL, |
216 |
| -// GATEWAY_HOST: API_GATEWAY_HOST, |
217 |
| -// GATEWAY_PORT: API_GATEWAY_PORT, |
218 |
| -// GATEWAY_PROTOCOL_SECURE: API_GATEWAY_PROTOCOL_SECURE, |
219 |
| -// ENDPOINT: API_ENDPOINT |
220 |
| -// }; |
221 |
| - |
222 |
| -// -------------------------------------------------------------------------------- |
223 |
| - |
224 |
| -// -------------------------------------------------------------------------------- |
| 39 | +export const { API_GATEWAY_PROTOCOL, API_GATEWAY_PORT } = data; |
0 commit comments