@valentine-efagene/qshelter-common 2.0.32 → 2.0.34
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.
|
@@ -69,8 +69,13 @@ export declare class ConfigService {
|
|
|
69
69
|
/**
|
|
70
70
|
* Get database credentials - combines secret and infrastructure config
|
|
71
71
|
* Returns a complete DatabaseCredentials object ready to use
|
|
72
|
+
* For test stage (LocalStack), reads directly from SSM parameters
|
|
72
73
|
*/
|
|
73
74
|
getDatabaseCredentials(stage?: string): Promise<DatabaseCredentials>;
|
|
75
|
+
/**
|
|
76
|
+
* Get a secure parameter from SSM (with decryption)
|
|
77
|
+
*/
|
|
78
|
+
getSecureParameter(name: string): Promise<string>;
|
|
74
79
|
/**
|
|
75
80
|
* Get encryption secrets from Secrets Manager
|
|
76
81
|
*/
|
|
@@ -8,8 +8,20 @@ export class ConfigService {
|
|
|
8
8
|
cacheTimestamps = new Map();
|
|
9
9
|
CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
10
10
|
constructor(region = 'us-east-1') {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const stage = process.env.NODE_ENV || process.env.STAGE || 'dev';
|
|
12
|
+
const isLocalStack = stage === 'test' || process.env.LOCALSTACK_ENDPOINT;
|
|
13
|
+
// Configure AWS clients for LocalStack or AWS
|
|
14
|
+
const clientConfig = { region };
|
|
15
|
+
if (isLocalStack) {
|
|
16
|
+
const endpoint = process.env.LOCALSTACK_ENDPOINT || 'http://localhost:4566';
|
|
17
|
+
clientConfig.endpoint = endpoint;
|
|
18
|
+
clientConfig.credentials = {
|
|
19
|
+
accessKeyId: 'test',
|
|
20
|
+
secretAccessKey: 'test',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
this.ssmClient = new SSMClient(clientConfig);
|
|
24
|
+
this.secretsClient = new SecretsManagerClient(clientConfig);
|
|
13
25
|
}
|
|
14
26
|
static getInstance(region) {
|
|
15
27
|
if (!ConfigService.instance) {
|
|
@@ -92,24 +104,67 @@ export class ConfigService {
|
|
|
92
104
|
/**
|
|
93
105
|
* Get database credentials - combines secret and infrastructure config
|
|
94
106
|
* Returns a complete DatabaseCredentials object ready to use
|
|
107
|
+
* For test stage (LocalStack), reads directly from SSM parameters
|
|
95
108
|
*/
|
|
96
109
|
async getDatabaseCredentials(stage = process.env.NODE_ENV || 'dev') {
|
|
97
110
|
const cacheKey = `db-credentials-${stage}`;
|
|
98
111
|
const cached = this.getFromCache(cacheKey);
|
|
99
112
|
if (cached)
|
|
100
113
|
return cached;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
let credentials;
|
|
115
|
+
// For test stage (LocalStack), read directly from SSM parameters
|
|
116
|
+
if (stage === 'test') {
|
|
117
|
+
const pathPrefix = `/qshelter/${stage}/`;
|
|
118
|
+
const host = await this.getParameter(`${pathPrefix}DB_HOST`);
|
|
119
|
+
const port = await this.getParameter(`${pathPrefix}DB_PORT`);
|
|
120
|
+
const username = await this.getParameter(`${pathPrefix}DB_USER`);
|
|
121
|
+
const password = await this.getSecureParameter(`${pathPrefix}DB_PASSWORD`);
|
|
122
|
+
const database = await this.getParameter(`${pathPrefix}DB_NAME`);
|
|
123
|
+
credentials = {
|
|
124
|
+
username,
|
|
125
|
+
password,
|
|
126
|
+
host,
|
|
127
|
+
port: parseInt(port, 10),
|
|
128
|
+
database,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// For dev/prod, use infrastructure config + Secrets Manager
|
|
133
|
+
const infraConfig = await this.getInfrastructureConfig(stage);
|
|
134
|
+
const dbSecret = await this.getSecret(infraConfig.databaseSecretArn);
|
|
135
|
+
credentials = {
|
|
136
|
+
username: dbSecret.username,
|
|
137
|
+
password: dbSecret.password,
|
|
138
|
+
host: infraConfig.dbHost,
|
|
139
|
+
port: infraConfig.dbPort,
|
|
140
|
+
database: `qshelter_${stage}`,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
110
143
|
this.setCache(cacheKey, credentials);
|
|
111
144
|
return credentials;
|
|
112
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Get a secure parameter from SSM (with decryption)
|
|
148
|
+
*/
|
|
149
|
+
async getSecureParameter(name) {
|
|
150
|
+
const cached = this.getFromCache(`secure-${name}`);
|
|
151
|
+
if (cached)
|
|
152
|
+
return cached;
|
|
153
|
+
try {
|
|
154
|
+
const command = new GetParameterCommand({
|
|
155
|
+
Name: name,
|
|
156
|
+
WithDecryption: true,
|
|
157
|
+
});
|
|
158
|
+
const response = await this.ssmClient.send(command);
|
|
159
|
+
const value = response.Parameter?.Value || '';
|
|
160
|
+
this.setCache(`secure-${name}`, value);
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.error(`Error fetching secure parameter ${name}:`, error);
|
|
165
|
+
throw new Error(`Failed to load secure parameter ${name}: ${error.message}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
113
168
|
/**
|
|
114
169
|
* Get encryption secrets from Secrets Manager
|
|
115
170
|
*/
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -672,7 +672,7 @@ model PaymentPlan {
|
|
|
672
672
|
// Fund collection behavior
|
|
673
673
|
// true = we collect funds via wallet/gateway (e.g., downpayment)
|
|
674
674
|
// false = external payment, we only track/reconcile (e.g., bank mortgage)
|
|
675
|
-
collectFunds
|
|
675
|
+
collectFunds Boolean @default(true)
|
|
676
676
|
|
|
677
677
|
createdAt DateTime @default(now())
|
|
678
678
|
updatedAt DateTime @updatedAt
|
|
@@ -773,7 +773,7 @@ model PropertyPaymentMethodPhase {
|
|
|
773
773
|
// Fund collection behavior (inherited from PaymentPlan if not set)
|
|
774
774
|
// true = we collect funds via wallet/gateway (e.g., downpayment)
|
|
775
775
|
// false = external payment, we only track/reconcile (e.g., bank mortgage)
|
|
776
|
-
collectFunds
|
|
776
|
+
collectFunds Boolean? // null = inherit from PaymentPlan
|
|
777
777
|
|
|
778
778
|
// Activation rules
|
|
779
779
|
requiresPreviousPhaseCompletion Boolean @default(true)
|
|
@@ -941,7 +941,7 @@ model ContractPhase {
|
|
|
941
941
|
// Fund collection behavior (snapshotted from template at contract creation)
|
|
942
942
|
// true = we collect funds via wallet/gateway (e.g., downpayment)
|
|
943
943
|
// false = external payment, we only track/reconcile (e.g., bank mortgage)
|
|
944
|
-
collectFunds
|
|
944
|
+
collectFunds Boolean @default(true)
|
|
945
945
|
|
|
946
946
|
// Progress counters (for efficient activation checks)
|
|
947
947
|
approvedDocumentsCount Int @default(0)
|