This repository has no description
4.2 kB
167 lines
1export enum Environment {
2 LOCAL = 'local',
3 DEV = 'dev',
4 PROD = 'prod',
5}
6
7export interface EnvironmentConfig {
8 environment: Environment;
9 database: {
10 url: string;
11 };
12 auth: {
13 jwtSecret: string;
14 accessTokenExpiresIn: number;
15 refreshTokenExpiresIn: number;
16 };
17 atproto: {
18 serviceEndpoint: string;
19 baseUrl: string;
20 collections: {
21 card: string;
22 collection: string;
23 collectionLink: string;
24 };
25 };
26 server: {
27 port: number;
28 host: string;
29 };
30 app: {
31 appUrl: string;
32 };
33 iframely: {
34 apiKey: string;
35 };
36 workers: {
37 redisUrl: string;
38 redisConfig: {
39 host: string;
40 port: number;
41 password?: string;
42 maxRetriesPerRequest: number | null; // Disable automatic retries
43 };
44 };
45}
46
47export class EnvironmentConfigService {
48 private config: EnvironmentConfig;
49
50 constructor() {
51 const environment = (process.env.NODE_ENV ||
52 Environment.LOCAL) as Environment;
53
54 this.config = {
55 environment,
56 database: {
57 url:
58 process.env.DATABASE_URL ||
59 'postgres://postgres:postgres@localhost:5432/annotations',
60 },
61 auth: {
62 jwtSecret:
63 process.env.JWT_SECRET || 'default-secret-change-in-production',
64 accessTokenExpiresIn: parseInt(
65 process.env.ACCESS_TOKEN_EXPIRES_IN || '3600',
66 ),
67 refreshTokenExpiresIn: parseInt(
68 process.env.REFRESH_TOKEN_EXPIRES_IN || '2592000',
69 ),
70 },
71 atproto: {
72 serviceEndpoint:
73 process.env.ATPROTO_SERVICE_ENDPOINT || 'https://bsky.social',
74 baseUrl: process.env.BASE_URL || 'http://127.0.0.1:3000',
75 collections: {
76 card:
77 environment === Environment.PROD
78 ? 'network.cosmik.card'
79 : `network.cosmik.${environment}.card`,
80 collection:
81 environment === Environment.PROD
82 ? 'network.cosmik.collection'
83 : `network.cosmik.${environment}.collection`,
84 collectionLink:
85 environment === Environment.PROD
86 ? 'network.cosmik.collectionLink'
87 : `network.cosmik.${environment}.collectionLink`,
88 },
89 },
90 server: {
91 port: parseInt(process.env.PORT || '3000'),
92 host: process.env.HOST || '127.0.0.1',
93 },
94 app: {
95 appUrl: process.env.APP_URL || 'http://127.0.0.1:4000',
96 },
97 iframely: {
98 apiKey: process.env.IFRAMELY_API_KEY || '',
99 },
100 workers: {
101 redisConfig: {
102 host: process.env.REDIS_HOST || 'localhost',
103 port: parseInt(process.env.REDIS_PORT || '6379', 10),
104 password: process.env.REDIS_PASSWORD || undefined,
105 maxRetriesPerRequest: null, // Disable automatic retries
106 },
107 redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
108 },
109 };
110
111 this.applyEnvironmentSpecificConfig();
112 }
113
114 private applyEnvironmentSpecificConfig(): void {
115 switch (this.config.environment) {
116 case Environment.DEV:
117 // Override defaults with dev-specific values
118 break;
119 case Environment.PROD:
120 // Override defaults with production-specific values
121 if (
122 this.config.auth.jwtSecret === 'default-secret-change-in-production'
123 ) {
124 throw new Error('JWT secret must be set in production environment');
125 }
126 break;
127 case Environment.LOCAL:
128 default:
129 // Local development defaults are already set
130 break;
131 }
132 }
133
134 public get(): EnvironmentConfig {
135 return this.config;
136 }
137
138 public getDatabaseConfig() {
139 return this.config.database;
140 }
141
142 public getAuthConfig() {
143 return this.config.auth;
144 }
145
146 public getAtProtoConfig() {
147 return this.config.atproto;
148 }
149
150 public getAtProtoCollections() {
151 return this.config.atproto.collections;
152 }
153
154 public getServerConfig() {
155 return this.config.server;
156 }
157 public getAppConfig() {
158 return this.config.app;
159 }
160
161 public getIFramelyApiKey(): string {
162 return this.config.iframely.apiKey;
163 }
164 public getWorkersConfig() {
165 return this.config.workers;
166 }
167}