@shadimakhoul/ggcoach 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +381 -0
- package/dist/types/auth.d.ts +18 -3
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/jwt.d.ts +4 -4
- package/dist/utils/jwt.d.ts.map +1 -1
- package/dist/utils/jwt.js +20 -47
- package/dist/utils/jwt.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +10 -0
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/redis.d.ts +2 -0
- package/dist/utils/redis.d.ts.map +1 -0
- package/dist/utils/redis.js +20 -0
- package/dist/utils/redis.js.map +1 -0
- package/dist/utils/validateEnv.d.ts +2 -0
- package/dist/utils/validateEnv.d.ts.map +1 -0
- package/dist/utils/validateEnv.js +20 -0
- package/dist/utils/validateEnv.js.map +1 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# @shadimakhoul/ggcoach
|
|
2
|
+
|
|
3
|
+
Shared utilities, middleware, and types for Node.js/Express microservices.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @shadimakhoul/ggcoach
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
- [JWT](#jwt)
|
|
14
|
+
- [Middleware](#middleware)
|
|
15
|
+
- [Request Validation](#request-validation)
|
|
16
|
+
- [OpenAPI / Swagger](#openapi--swagger)
|
|
17
|
+
- [Config & Bootstrap](#config--bootstrap)
|
|
18
|
+
- [Logger](#logger)
|
|
19
|
+
- [Types](#types)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## JWT
|
|
24
|
+
|
|
25
|
+
Generic JWT helpers. You define the payload shape; the library handles signing and verification.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { generateToken, generateRefreshToken, verifyToken, JWTConfig, BaseJWTPayload } from '@shadimakhoul/ggcoach';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### `JWTConfig`
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
interface JWTConfig {
|
|
35
|
+
secret: string;
|
|
36
|
+
expiresIn: string; // e.g. '1h', '7d'
|
|
37
|
+
issuer: string; // e.g. 'my-auth-service'
|
|
38
|
+
audience: string; // e.g. 'my-app'
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### `BaseJWTPayload`
|
|
43
|
+
|
|
44
|
+
The minimum shape required by the library. Extend it with your own fields.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
interface BaseJWTPayload {
|
|
48
|
+
tokenType?: 'access' | 'refresh';
|
|
49
|
+
tokenVersion?: number;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Usage
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// 1. Define your payload
|
|
57
|
+
interface MyPayload extends BaseJWTPayload {
|
|
58
|
+
userId: string;
|
|
59
|
+
role: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const config: JWTConfig = {
|
|
63
|
+
secret: process.env.JWT_SECRET!,
|
|
64
|
+
expiresIn: '1h',
|
|
65
|
+
issuer: 'my-auth-service',
|
|
66
|
+
audience: 'my-app',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// 2. Issue tokens
|
|
70
|
+
const accessToken = generateToken<MyPayload>(config, { userId: '123', role: 'admin' });
|
|
71
|
+
const refreshToken = generateRefreshToken<MyPayload>(config, { userId: '123', role: 'admin' });
|
|
72
|
+
// tokenType is stamped automatically: 'access' / 'refresh'
|
|
73
|
+
|
|
74
|
+
// 3. Verify
|
|
75
|
+
const decoded = verifyToken<MyPayload>(config, accessToken);
|
|
76
|
+
// decoded.tokenType === 'access'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> `verifyToken` throws `Error('Invalid or expired token')` on failure.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Middleware
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import {
|
|
87
|
+
authenticateToken,
|
|
88
|
+
optionalAuth,
|
|
89
|
+
requireAdmin,
|
|
90
|
+
requireSuperAdmin,
|
|
91
|
+
requireInternalToken,
|
|
92
|
+
createRateLimiter,
|
|
93
|
+
authRateLimiter,
|
|
94
|
+
generalRateLimiter,
|
|
95
|
+
errorHandler,
|
|
96
|
+
createCorsOptions,
|
|
97
|
+
corsMiddleware,
|
|
98
|
+
} from '@shadimakhoul/ggcoach';
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `authenticateToken(JWT_SECRET)`
|
|
102
|
+
|
|
103
|
+
Express middleware that reads a `Bearer` token from `Authorization`, verifies it (issuer `ggcoach-auth-service`, audience `ggcoach-app`), checks the token version against Redis, and sets `req.user`. Requires Redis to be initialized (see [Redis](#redis)).
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
app.use(authenticateToken(process.env.JWT_SECRET!));
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### `optionalAuth(JWT_SECRET)`
|
|
110
|
+
|
|
111
|
+
Same as `authenticateToken` but does not reject the request if no token is provided or if it's invalid. `req.user` is set only when a valid token is present.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
app.use(optionalAuth(process.env.JWT_SECRET!));
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `requireAdmin` / `requireSuperAdmin`
|
|
118
|
+
|
|
119
|
+
Guards that check `req.user.accountType`. Must be placed after `authenticateToken`.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
router.get('/admin/users', authenticateToken(secret), requireAdmin, handler);
|
|
123
|
+
router.post('/admin/promote', authenticateToken(secret), requireSuperAdmin, handler);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `requireInternalToken(ALLOW_DIRECT_ACCESS, INTERNAL_SERVICE_TOKEN)`
|
|
127
|
+
|
|
128
|
+
Validates the `x-internal-token` header for service-to-service calls.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
app.use(requireInternalToken(
|
|
132
|
+
process.env.ALLOW_DIRECT_ACCESS === 'true',
|
|
133
|
+
process.env.INTERNAL_SERVICE_TOKEN!,
|
|
134
|
+
));
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Rate limiters
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// Pre-built limiters
|
|
141
|
+
app.use('/auth', authRateLimiter); // 5 req / 15 min
|
|
142
|
+
app.use(generalRateLimiter); // 1000 req / 15 min
|
|
143
|
+
|
|
144
|
+
// Custom limiter
|
|
145
|
+
const customLimiter = createRateLimiter(
|
|
146
|
+
5 * 60 * 1000, // windowMs
|
|
147
|
+
20, // max requests
|
|
148
|
+
);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `errorHandler`
|
|
152
|
+
|
|
153
|
+
Centralised Express error handler. Recognises `ECONNREFUSED`/`ETIMEDOUT` socket errors and Sequelize/Joi validation errors, mapping each to an appropriate status code. In `development`, also echoes the stack trace and `x-request-id` header. Register as the last middleware.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
app.use(errorHandler);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `createCorsOptions(allowedOrigins?, allowedHosts?)` / `corsMiddleware`
|
|
160
|
+
|
|
161
|
+
Returns a CORS options object for the `cors` package. Passing no arguments allows all origins. `corsMiddleware` is a ready-to-use instance built from the no-argument defaults.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
// Allow specific origins and wildcard sub-domains
|
|
165
|
+
app.use(cors(createCorsOptions(
|
|
166
|
+
['https://app.example.com'],
|
|
167
|
+
['example.com'], // matches *.example.com
|
|
168
|
+
)));
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Request Validation
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { validateRequest, validateRequestZod, validateUploadedFilesZod } from '@shadimakhoul/ggcoach';
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### `validateRequest(joiSchema)`
|
|
180
|
+
|
|
181
|
+
Validates `req.body` against a Joi schema, stripping unknown keys and collecting all errors before responding `400`.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
router.post('/users', validateRequest(createUserJoiSchema), handler);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### `validateRequestZod(zodSchema, target?, contentType?)`
|
|
188
|
+
|
|
189
|
+
Validates `req.body` (default), `req.params`, or `req.query` against a Zod schema and replaces it with the parsed value.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
router.get('/users/:id', validateRequestZod(idParamSchema, 'params'), handler);
|
|
193
|
+
router.post('/users', validateRequestZod(createUserSchema), handler);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### `validateUploadedFilesZod(fileSchema, requestBodySchema?)`
|
|
197
|
+
|
|
198
|
+
Validates `req.files` (e.g. from `multer`) against a Zod schema. Intended for `multipart/form-data` uploads.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
router.post('/upload', validateUploadedFilesZod(fileArraySchema), handler);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
> All three attach schema metadata (`__schema`, `__schemaType`, `__schemaTarget`, `__contentType`) to the middleware function, which [`buildOpenApiSpecFromExpress`](#openapi--swagger) reads to auto-generate request bodies/parameters.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## OpenAPI / Swagger
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { buildOpenApiSpecFromExpress, zodToOpenAPI, setupSwagger } from '@shadimakhoul/ggcoach';
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### `buildOpenApiSpecFromExpress(app, baseSpec, options?)`
|
|
215
|
+
|
|
216
|
+
Walks a live Express app's router stack and generates an OpenAPI paths object: routes and methods via `express-list-endpoints`, request bodies/parameters from any `validateRequest*` schemas attached to route handlers, and a `security: [{ bearerAuth: [] }]` requirement on routes guarded by `authenticateToken`, `requireAdmin`, or `requireSuperAdmin`. Generated paths are merged under whatever `paths` already exist on `baseSpec`.
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
const spec = buildOpenApiSpecFromExpress(app, {
|
|
220
|
+
openapi: '3.0.0',
|
|
221
|
+
info: { title: 'My Service', version: '1.0.0' },
|
|
222
|
+
paths: {},
|
|
223
|
+
}, {
|
|
224
|
+
tagResolver: (path, method) => (path.startsWith('/admin') ? ['Admin'] : ['Public']),
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `zodToOpenAPI(zodSchema)`
|
|
229
|
+
|
|
230
|
+
Converts a Zod schema to an OpenAPI-compatible JSON Schema object (normalises `z.toJSONSchema` output — nullable unions, `const`, nested `properties`/`items`/`oneOf`/`anyOf`/`allOf`). Used internally by `buildOpenApiSpecFromExpress`.
|
|
231
|
+
|
|
232
|
+
### `setupSwagger(port, app, options?)`
|
|
233
|
+
|
|
234
|
+
Serves `swagger.json` and the Swagger UI (pre-themed dark mode) on an Express app.
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
setupSwagger(3000, app, {
|
|
238
|
+
getSpec: () => buildOpenApiSpecFromExpress(app, baseSpec),
|
|
239
|
+
// or a static spec:
|
|
240
|
+
// spec: mySpec,
|
|
241
|
+
basePath: '/api-docs', // default
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Config & Bootstrap
|
|
248
|
+
|
|
249
|
+
### `initExpress(isDevelopment, allowedOrigins?, allowedHosts?)`
|
|
250
|
+
|
|
251
|
+
Creates a pre-configured Express app with Helmet, CORS, general rate limiting, JSON/urlencoded body parsing (10mb limit), and Morgan logging piped through the shared [logger](#logger).
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import { initExpress } from '@shadimakhoul/ggcoach';
|
|
255
|
+
|
|
256
|
+
const app = initExpress(
|
|
257
|
+
process.env.NODE_ENV === 'development',
|
|
258
|
+
['https://app.example.com'],
|
|
259
|
+
);
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Redis
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import { initializeRedis, getRedisClient, closeRedis, buildRedisUrl } from '@shadimakhoul/ggcoach';
|
|
266
|
+
|
|
267
|
+
await initializeRedis(process.env.REDIS_URL!);
|
|
268
|
+
const client = getRedisClient();
|
|
269
|
+
await closeRedis();
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`initializeRedis(hostOrUrl, username?, password?)` accepts either a full `redis://`/`rediss://` URL or a bare host (in which case it connects on port `16837`). It's a singleton — subsequent calls return the existing open client. `authenticateToken`/`optionalAuth` rely on `getRedisClient()`, so initialize Redis before mounting auth middleware.
|
|
273
|
+
|
|
274
|
+
`buildRedisUrl(value, user?, password?)` builds a `redis://`/`rediss://` connection string from a host, a Heroku-style Redis hostname (`redis-XXXX.example.com` → port `XXXX`), or an existing URL, injecting credentials only if not already present. Useful for normalising `REDIS_URL`/`REDIS_HOST` env vars before passing them to `initializeRedis`.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
const url = buildRedisUrl(process.env.REDIS_HOST, process.env.REDIS_USER, process.env.REDIS_PASSWORD);
|
|
278
|
+
await initializeRedis(url);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Secrets bootstrap
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
import { bootstrapSecrets } from '@shadimakhoul/ggcoach';
|
|
285
|
+
|
|
286
|
+
await bootstrapSecrets('my-service', {
|
|
287
|
+
secretsServiceUrl: process.env.SECRETS_SERVICE_URL!,
|
|
288
|
+
internalServiceToken: process.env.INTERNAL_SERVICE_TOKEN,
|
|
289
|
+
dev: process.env.NODE_ENV === 'development',
|
|
290
|
+
retries: 3,
|
|
291
|
+
retryDelayMs: 3000,
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Fetches secrets for `serviceName` from a central secrets service and populates `process.env` for any key not already set. Fails silently (after exhausting `retries`) so a missing/unreachable secrets service doesn't crash startup — pair with `validateEnvVars` to enforce required vars afterward.
|
|
296
|
+
|
|
297
|
+
### Env validation
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { validateEnvVars } from '@shadimakhoul/ggcoach';
|
|
301
|
+
|
|
302
|
+
validateEnvVars(['JWT_SECRET', 'REDIS_URL', 'DATABASE_URL']);
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Throws (by default) if any required env var is missing, logging each missing key at `crit` level first. Pass `throwOnMissing = false` to log a `warn` and return `false` instead of throwing.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Logger
|
|
310
|
+
|
|
311
|
+
Winston logger pre-configured with console + file transports, custom levels (`alert` > `crit` > `error` > `warn` > `info`), and optional Telegram alerting.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
import { logger, initLogger, stream } from '@shadimakhoul/ggcoach';
|
|
315
|
+
|
|
316
|
+
logger.info('Server started');
|
|
317
|
+
logger.warn('Something looks off');
|
|
318
|
+
logger.error('Something failed', { error });
|
|
319
|
+
logger.crit('Critical failure', { error });
|
|
320
|
+
logger.alert('Page someone now');
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The default export `logger` lazily initializes on first use (writing to `./logs/combined.log` and `./logs/error.log`, log level from `LOG_LEVEL` env var, default `info`). Call `initLogger(logsDir?, telegramConfig?)` explicitly if you need a custom logs directory or to configure Telegram before the first log call.
|
|
324
|
+
|
|
325
|
+
### Telegram alerting
|
|
326
|
+
|
|
327
|
+
If `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` are set in the environment, `alert`/`crit`/`error` level logs are automatically forwarded to Telegram — no code changes needed. Per-level chat IDs fall back to `TELEGRAM_CHAT_ID` if unset:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
TELEGRAM_BOT_TOKEN=...
|
|
331
|
+
TELEGRAM_CHAT_ID=... # default fallback chat
|
|
332
|
+
TELEGRAM_ALERT_CHAT_ID=... # optional override for `alert` level
|
|
333
|
+
TELEGRAM_CRIT_CHAT_ID=... # optional override for `crit` level
|
|
334
|
+
TELEGRAM_ERROR_CHAT_ID=... # optional override for `error` level
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Or configure it explicitly instead of via env vars:
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
initLogger(undefined, {
|
|
341
|
+
botToken: process.env.TELEGRAM_BOT_TOKEN!,
|
|
342
|
+
chatIds: { alert: '...', crit: '...', error: '...' },
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### `stream`
|
|
347
|
+
|
|
348
|
+
Adapter for Morgan (or any logger expecting a `{ write(message) }` stream); used internally by `initExpress`.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Types
|
|
353
|
+
|
|
354
|
+
Key types exported from the package:
|
|
355
|
+
|
|
356
|
+
| Type | Description |
|
|
357
|
+
|---|---|
|
|
358
|
+
| `JWTConfig` | Config object for all JWT helpers |
|
|
359
|
+
| `BaseJWTPayload` | Minimum payload shape — extend for your project |
|
|
360
|
+
| `JWTPayload` | ggCoach-specific payload extending `BaseJWTPayload` |
|
|
361
|
+
| `UserAttributes` | Full ggCoach user model shape |
|
|
362
|
+
| `UserCreationAttributes` | `UserAttributes` minus auto-generated fields |
|
|
363
|
+
| `AuthResponse` | Standard auth endpoint response envelope |
|
|
364
|
+
| `AccountType` | Enum: `Client`, `Provider`, `Admin`, `SuperAdmin` |
|
|
365
|
+
| `IApiResponse<T>` | Generic `{ success, data?, message?, error?, meta? }` response envelope |
|
|
366
|
+
| `IAdminUser` | Admin dashboard user shape |
|
|
367
|
+
| `IPermission` | Permission record shape |
|
|
368
|
+
| `IAppRole` | Role record shape (name, permissions, active users count) |
|
|
369
|
+
| `IPaginationQuery` | Standard `page`/`limit`/`sortBy`/`sortOrder`/`search` query shape |
|
|
370
|
+
| `OpenApiSpec`, `OpenApiPaths`, `TagResolver`, `BuildOptions`, `Endpoint`, `SchemaMap` | Supporting types for [`buildOpenApiSpecFromExpress`](#openapi--swagger) |
|
|
371
|
+
|
|
372
|
+
`Express.Request` is also augmented globally with an optional `user?: JWTPayload` field.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Publishing
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
npm run build # compile TypeScript to dist/
|
|
380
|
+
npm publish # runs build first via prepublishOnly
|
|
381
|
+
```
|
package/dist/types/auth.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { AccountType } from "./enums";
|
|
2
|
-
export interface
|
|
2
|
+
export interface JWTConfig {
|
|
3
|
+
secret: string;
|
|
4
|
+
expiresIn: string;
|
|
5
|
+
issuer: string;
|
|
6
|
+
audience: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BaseJWTPayload {
|
|
9
|
+
tokenType?: 'access' | 'refresh';
|
|
10
|
+
tokenVersion?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface JWTPayload extends BaseJWTPayload {
|
|
3
13
|
id: number;
|
|
4
14
|
email: string;
|
|
5
15
|
phoneNumber: string | null;
|
|
@@ -9,8 +19,8 @@ export interface JWTPayload {
|
|
|
9
19
|
is_active: boolean;
|
|
10
20
|
emailVerified: boolean;
|
|
11
21
|
phoneVerified: boolean;
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
roleId?: number | null;
|
|
23
|
+
permissions?: string[];
|
|
14
24
|
}
|
|
15
25
|
export interface UserAttributes {
|
|
16
26
|
id: number;
|
|
@@ -28,6 +38,11 @@ export interface UserAttributes {
|
|
|
28
38
|
tokenVersion?: number;
|
|
29
39
|
created_at?: Date;
|
|
30
40
|
updated_at?: Date;
|
|
41
|
+
roleId?: number | null;
|
|
42
|
+
permissions?: string[];
|
|
43
|
+
twoFactorEnabled?: boolean;
|
|
44
|
+
twoFactorSecret?: string | null;
|
|
45
|
+
twoFactorTempSecret?: string | null;
|
|
31
46
|
}
|
|
32
47
|
declare global {
|
|
33
48
|
namespace Express {
|
package/dist/types/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,UAAU,CAAC;SACnB;KACF;CACF;AAED,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAClD,cAAc,EACZ,IAAI,GACJ,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,iBAAiB,CACpB;CAAG;AAEJ,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACvC,MAAM,EAAE;YACN,YAAY,EAAE,MAAM,CAAC;YACrB,aAAa,EAAE,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -17,6 +17,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./jwt"), exports);
|
|
18
18
|
__exportStar(require("./logger"), exports);
|
|
19
19
|
__exportStar(require("./openapi"), exports);
|
|
20
|
+
__exportStar(require("./redis"), exports);
|
|
20
21
|
__exportStar(require("./secrets"), exports);
|
|
22
|
+
__exportStar(require("./validateEnv"), exports);
|
|
21
23
|
__exportStar(require("./zodToOpenAPI"), exports);
|
|
22
24
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wCAAsB;AACtB,2CAAyB;AACzB,4CAA0B;AAC1B,4CAA0B;AAC1B,iDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wCAAsB;AACtB,2CAAyB;AACzB,4CAA0B;AAC1B,0CAAwB;AACxB,4CAA0B;AAC1B,gDAA8B;AAC9B,iDAA+B"}
|
package/dist/utils/jwt.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const generateToken:
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
1
|
+
import { BaseJWTPayload, JWTConfig } from '../types';
|
|
2
|
+
export declare const generateToken: <T extends BaseJWTPayload>(config: JWTConfig, payload: T) => string;
|
|
3
|
+
export declare const generateRefreshToken: <T extends BaseJWTPayload>(config: JWTConfig, payload: T) => string;
|
|
4
|
+
export declare const verifyToken: <T extends BaseJWTPayload>(config: JWTConfig, token: string) => T;
|
|
5
5
|
//# sourceMappingURL=jwt.d.ts.map
|
package/dist/utils/jwt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../utils/jwt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../utils/jwt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErD,eAAO,MAAM,aAAa,qCAAsC,SAAS,iBAAe,MAQvF,CAAC;AAEF,eAAO,MAAM,oBAAoB,qCAAsC,SAAS,iBAAe,MAQ9F,CAAC;AAEF,eAAO,MAAM,WAAW,qCAAsC,SAAS,SAAS,MAAM,MASrF,CAAC"}
|
package/dist/utils/jwt.js
CHANGED
|
@@ -3,63 +3,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.verifyToken = exports.generateRefreshToken = exports.generateToken = void 0;
|
|
7
7
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
-
const generateToken = (
|
|
9
|
-
const payload = {
|
|
10
|
-
id: user.id,
|
|
11
|
-
email: user.email,
|
|
12
|
-
phoneNumber: user.phoneNumber,
|
|
13
|
-
firstName: user.firstName,
|
|
14
|
-
lastName: user.lastName,
|
|
15
|
-
accountType: user.accountType,
|
|
16
|
-
is_active: user.is_active,
|
|
17
|
-
emailVerified: user.emailVerified,
|
|
18
|
-
phoneVerified: user.phoneVerified,
|
|
19
|
-
tokenVersion: user.tokenVersion ?? 0,
|
|
20
|
-
tokenType: 'access',
|
|
21
|
-
};
|
|
8
|
+
const generateToken = (config, payload) => {
|
|
22
9
|
const options = {
|
|
23
|
-
expiresIn:
|
|
24
|
-
issuer:
|
|
25
|
-
audience:
|
|
10
|
+
expiresIn: config.expiresIn,
|
|
11
|
+
issuer: config.issuer,
|
|
12
|
+
audience: config.audience,
|
|
26
13
|
};
|
|
27
|
-
return jsonwebtoken_1.default.sign(payload,
|
|
14
|
+
return jsonwebtoken_1.default.sign({ ...payload, tokenType: 'access' }, config.secret, options);
|
|
28
15
|
};
|
|
29
16
|
exports.generateToken = generateToken;
|
|
30
|
-
const
|
|
17
|
+
const generateRefreshToken = (config, payload) => {
|
|
18
|
+
const options = {
|
|
19
|
+
expiresIn: config.expiresIn,
|
|
20
|
+
issuer: config.issuer,
|
|
21
|
+
audience: config.audience,
|
|
22
|
+
};
|
|
23
|
+
return jsonwebtoken_1.default.sign({ ...payload, tokenType: 'refresh' }, config.secret, options);
|
|
24
|
+
};
|
|
25
|
+
exports.generateRefreshToken = generateRefreshToken;
|
|
26
|
+
const verifyToken = (config, token) => {
|
|
31
27
|
try {
|
|
32
|
-
|
|
33
|
-
issuer:
|
|
34
|
-
audience:
|
|
28
|
+
return jsonwebtoken_1.default.verify(token, config.secret, {
|
|
29
|
+
issuer: config.issuer,
|
|
30
|
+
audience: config.audience,
|
|
35
31
|
});
|
|
36
|
-
return decoded;
|
|
37
32
|
}
|
|
38
|
-
catch
|
|
33
|
+
catch {
|
|
39
34
|
throw new Error('Invalid or expired token');
|
|
40
35
|
}
|
|
41
36
|
};
|
|
42
37
|
exports.verifyToken = verifyToken;
|
|
43
|
-
const generateRefreshToken = (JWT_SECRET, JWT_EXPIRES_IN, user) => {
|
|
44
|
-
const payload = {
|
|
45
|
-
id: user.id,
|
|
46
|
-
email: user.email,
|
|
47
|
-
phoneNumber: user.phoneNumber,
|
|
48
|
-
firstName: user.firstName,
|
|
49
|
-
lastName: user.lastName,
|
|
50
|
-
accountType: user.accountType,
|
|
51
|
-
is_active: user.is_active,
|
|
52
|
-
emailVerified: user.emailVerified,
|
|
53
|
-
phoneVerified: user.phoneVerified,
|
|
54
|
-
tokenVersion: user.tokenVersion ?? 0,
|
|
55
|
-
tokenType: 'refresh',
|
|
56
|
-
};
|
|
57
|
-
const options = {
|
|
58
|
-
expiresIn: JWT_EXPIRES_IN,
|
|
59
|
-
issuer: 'ggcoach-auth-service',
|
|
60
|
-
audience: 'ggcoach-app'
|
|
61
|
-
};
|
|
62
|
-
return jsonwebtoken_1.default.sign(payload, JWT_SECRET, options);
|
|
63
|
-
};
|
|
64
|
-
exports.generateRefreshToken = generateRefreshToken;
|
|
65
38
|
//# sourceMappingURL=jwt.js.map
|
package/dist/utils/jwt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../utils/jwt.ts"],"names":[],"mappings":";;;;;;AAAA,gEAA+B;
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../utils/jwt.ts"],"names":[],"mappings":";;;;;;AAAA,gEAA+B;AAGxB,MAAM,aAAa,GAAG,CAA2B,MAAiB,EAAE,OAAU,EAAU,EAAE;IAC/F,MAAM,OAAO,GAAoB;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KACP,CAAC;IAErB,OAAO,sBAAG,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC,CAAC;AARW,QAAA,aAAa,iBAQxB;AAEK,MAAM,oBAAoB,GAAG,CAA2B,MAAiB,EAAE,OAAU,EAAU,EAAE;IACtG,MAAM,OAAO,GAAoB;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KACP,CAAC;IAErB,OAAO,sBAAG,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAChF,CAAC,CAAC;AARW,QAAA,oBAAoB,wBAQ/B;AAEK,MAAM,WAAW,GAAG,CAA2B,MAAiB,EAAE,KAAa,EAAK,EAAE;IAC3F,IAAI,CAAC;QACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,CAAM,CAAC;IACV,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC,CAAC;AATW,QAAA,WAAW,eAStB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAuB9B,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AA6DD,eAAO,MAAM,UAAU,aACZ,MAAM,mBACE,cAAc,KAC9B,QAAQ,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAuB9B,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AA6DD,eAAO,MAAM,UAAU,aACZ,MAAM,mBACE,cAAc,KAC9B,QAAQ,MAsEV,CAAC;AAGF,eAAO,MAAM,MAAM,gBAQjB,CAAC;AAGH,eAAO,MAAM,MAAM;qBACA,MAAM;CAIxB,CAAC"}
|
package/dist/utils/logger.js
CHANGED
|
@@ -66,6 +66,16 @@ const logFormat = printf(({ level, message, timestamp: ts, ...meta }) => {
|
|
|
66
66
|
});
|
|
67
67
|
let loggerInstance = null;
|
|
68
68
|
const initLogger = (logsDir = path_1.default.resolve(process.cwd(), 'logs'), telegramConfig) => {
|
|
69
|
+
if (!telegramConfig && process.env.TELEGRAM_BOT_TOKEN && process.env.TELEGRAM_CHAT_ID) {
|
|
70
|
+
telegramConfig = {
|
|
71
|
+
botToken: process.env.TELEGRAM_BOT_TOKEN,
|
|
72
|
+
chatIds: {
|
|
73
|
+
alert: process.env.TELEGRAM_ALERT_CHAT_ID || process.env.TELEGRAM_CHAT_ID,
|
|
74
|
+
crit: process.env.TELEGRAM_CRIT_CHAT_ID || process.env.TELEGRAM_CHAT_ID,
|
|
75
|
+
error: process.env.TELEGRAM_ERROR_CHAT_ID || process.env.TELEGRAM_CHAT_ID,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
69
79
|
if (!fs_1.default.existsSync(logsDir)) {
|
|
70
80
|
try {
|
|
71
81
|
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../utils/logger.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../utils/redis.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,WAAY,MAAM,SAAS,MAAM,aAAa,MAAM,KAAG,MAkBhF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildRedisUrl = void 0;
|
|
4
|
+
const buildRedisUrl = (value, user, password) => {
|
|
5
|
+
if (!value) {
|
|
6
|
+
throw new Error('REDIS_URL or REDIS_HOST must be set');
|
|
7
|
+
}
|
|
8
|
+
const url = /^rediss?:\/\//i.test(value)
|
|
9
|
+
? new URL(value)
|
|
10
|
+
: new URL(`redis://${value}:${value.match(/^redis-(\d+)\./)?.[1] || '6379'}`);
|
|
11
|
+
if (user && !url.username) {
|
|
12
|
+
url.username = user;
|
|
13
|
+
}
|
|
14
|
+
if (password && !url.password) {
|
|
15
|
+
url.password = password;
|
|
16
|
+
}
|
|
17
|
+
return url.toString();
|
|
18
|
+
};
|
|
19
|
+
exports.buildRedisUrl = buildRedisUrl;
|
|
20
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../utils/redis.ts"],"names":[],"mappings":";;;AAAO,MAAM,aAAa,GAAG,CAAC,KAAc,EAAE,IAAa,EAAE,QAAiB,EAAU,EAAE;IACxF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC;QAChB,CAAC,CAAC,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;IAEhF,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC1B,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC,CAAC;AAlBW,QAAA,aAAa,iBAkBxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateEnv.d.ts","sourceRoot":"","sources":["../../utils/validateEnv.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,aAAc,MAAM,EAAE,+BAA0B,OAiB3E,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateEnvVars = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const validateEnvVars = (required, throwOnMissing = true) => {
|
|
6
|
+
const missing = required.filter((name) => !process.env[name]);
|
|
7
|
+
if (missing.length === 0) {
|
|
8
|
+
logger_1.logger.info('All required environment variables are present');
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
const message = `Missing required environment variables: ${missing.join(', ')}`;
|
|
12
|
+
missing.forEach((m) => logger_1.logger.crit(`ENV MISSING: ${m}`));
|
|
13
|
+
if (throwOnMissing) {
|
|
14
|
+
throw new Error(message);
|
|
15
|
+
}
|
|
16
|
+
logger_1.logger.warn(message);
|
|
17
|
+
return false;
|
|
18
|
+
};
|
|
19
|
+
exports.validateEnvVars = validateEnvVars;
|
|
20
|
+
//# sourceMappingURL=validateEnv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateEnv.js","sourceRoot":"","sources":["../../utils/validateEnv.ts"],"names":[],"mappings":";;;AAAA,qCAAkC;AAE3B,MAAM,eAAe,GAAG,CAAC,QAAkB,EAAE,cAAc,GAAG,IAAI,EAAW,EAAE;IACpF,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,eAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,2CAA2C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChF,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzD,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,eAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAjBW,QAAA,eAAe,mBAiB1B"}
|