@dataformer/env-service 2.2.0 → 2.4.0
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/CHANGELOG.md +17 -0
- package/dist/index.js +109 -18
- package/package.json +2 -3
- package/src/index.ts +143 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @dataformer/env-service
|
|
2
2
|
|
|
3
|
+
## 2.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fix circular dependency with LoggerService, EnvService, and SecretManagerClient
|
|
8
|
+
|
|
9
|
+
## 2.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- LoggerService upgraded
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @dataformer/secret-manager-client@2.3.0
|
|
19
|
+
|
|
3
20
|
## 2.2.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,60 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import readline from "readline";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { SecretManagerServiceClient } from "@google-cloud/secret-manager";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
function getGcpProjectIdFromGcloud() {
|
|
7
|
+
try {
|
|
8
|
+
const cmd = "gcloud config get-value core/project";
|
|
9
|
+
const projectId2 = execSync(cmd, { encoding: "utf8", stdio: "pipe" }).trim();
|
|
10
|
+
if (projectId2 && projectId2 !== "(unset)") {
|
|
11
|
+
return projectId2;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function getProjectId() {
|
|
19
|
+
if (process.env.GCP_PROJECT_ID) {
|
|
20
|
+
return process.env.GCP_PROJECT_ID;
|
|
21
|
+
}
|
|
22
|
+
const gcloudProjectId = getGcpProjectIdFromGcloud();
|
|
23
|
+
if (gcloudProjectId) {
|
|
24
|
+
return gcloudProjectId;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(
|
|
27
|
+
"\u{1F6A8} GCP project ID is required for Secret Manager.\n\nCI/CD DEPLOYMENT (REQUIRED):\n Set GCP_PROJECT_ID as environment variable\n Example: GCP_PROJECT_ID=dataformer-prod\n\nLOCAL DEVELOPMENT:\n Set your gcloud project: gcloud config set project YOUR_PROJECT_ID\n Verify with: gcloud config get-value project"
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
var secretManagerClient = null;
|
|
6
31
|
var secretManagerInitialized = false;
|
|
7
|
-
|
|
32
|
+
var projectId = null;
|
|
33
|
+
async function getSecretManagerClient() {
|
|
8
34
|
if (secretManagerInitialized) {
|
|
9
|
-
return
|
|
35
|
+
return secretManagerClient && projectId ? { client: secretManagerClient, projectId } : null;
|
|
10
36
|
}
|
|
11
37
|
try {
|
|
12
|
-
|
|
38
|
+
projectId = getProjectId();
|
|
39
|
+
secretManagerClient = new SecretManagerServiceClient({ projectId });
|
|
13
40
|
secretManagerInitialized = true;
|
|
14
|
-
return
|
|
41
|
+
return { client: secretManagerClient, projectId };
|
|
15
42
|
} catch (error) {
|
|
16
|
-
console.error("[EnvService.ts] Failed to initialize
|
|
43
|
+
console.error("[EnvService.ts] Failed to initialize SecretManagerServiceClient:", error.message);
|
|
17
44
|
console.warn("[EnvService.ts] Secret Manager functionality will be unavailable.");
|
|
18
45
|
secretManagerInitialized = true;
|
|
19
46
|
return null;
|
|
20
47
|
}
|
|
21
48
|
}
|
|
49
|
+
function buildSecretName(projectId2, baseSecretId) {
|
|
50
|
+
return `${projectId2}_${baseSecretId}`;
|
|
51
|
+
}
|
|
52
|
+
function buildSecretPath(projectId2, secretName) {
|
|
53
|
+
return `projects/${projectId2}/secrets/${secretName}`;
|
|
54
|
+
}
|
|
55
|
+
function buildSecretVersionPath(projectId2, secretName, version = "latest") {
|
|
56
|
+
return `projects/${projectId2}/secrets/${secretName}/versions/${version}`;
|
|
57
|
+
}
|
|
22
58
|
var rl = readline.createInterface({
|
|
23
59
|
input: process.stdin,
|
|
24
60
|
output: process.stdout
|
|
@@ -40,12 +76,26 @@ function obfuscateCred(cred) {
|
|
|
40
76
|
}
|
|
41
77
|
}
|
|
42
78
|
async function getEnvVar(baseSecretKey) {
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
79
|
+
const smClient = await getSecretManagerClient();
|
|
80
|
+
if (!smClient) {
|
|
45
81
|
console.warn(`[EnvService.ts] SecretManager not available for getEnvVar (key: ${baseSecretKey})`);
|
|
46
82
|
return null;
|
|
47
83
|
}
|
|
48
|
-
|
|
84
|
+
try {
|
|
85
|
+
const secretName = buildSecretName(smClient.projectId, baseSecretKey);
|
|
86
|
+
const secretVersionPath = buildSecretVersionPath(smClient.projectId, secretName);
|
|
87
|
+
const [response] = await smClient.client.accessSecretVersion({
|
|
88
|
+
name: secretVersionPath
|
|
89
|
+
});
|
|
90
|
+
const secretValue = response.payload?.data?.toString();
|
|
91
|
+
return secretValue || null;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error.code === 5) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
console.warn(`[EnvService.ts] Failed to get secret ${baseSecretKey}: ${error.message}`);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
49
99
|
}
|
|
50
100
|
async function getCustomSearchApiKey() {
|
|
51
101
|
const apiKey = await getEnvVar("CUSTOM_SEARCH_API_KEY");
|
|
@@ -67,15 +117,15 @@ async function getGcpProjectId() {
|
|
|
67
117
|
return envProjectId;
|
|
68
118
|
}
|
|
69
119
|
try {
|
|
70
|
-
const { execSync } = await import("child_process");
|
|
71
|
-
const
|
|
120
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
121
|
+
const projectId2 = execSync2("gcloud config get-value project", {
|
|
72
122
|
encoding: "utf8",
|
|
73
123
|
stdio: ["ignore", "pipe", "ignore"]
|
|
74
124
|
}).trim();
|
|
75
|
-
if (!
|
|
125
|
+
if (!projectId2 || projectId2 === "(unset)") {
|
|
76
126
|
throw new Error("No GCP project configured. Run `gcloud config set project YOUR_PROJECT_ID`");
|
|
77
127
|
}
|
|
78
|
-
return
|
|
128
|
+
return projectId2;
|
|
79
129
|
} catch (error) {
|
|
80
130
|
throw new Error(
|
|
81
131
|
"GCP_PROJECT_ID not found. Either:\n1. Set GCP_PROJECT_ID environment variable (for deployed environments), or\n2. Configure gcloud: `gcloud config set project YOUR_PROJECT_ID` (for local development)"
|
|
@@ -83,17 +133,58 @@ async function getGcpProjectId() {
|
|
|
83
133
|
}
|
|
84
134
|
}
|
|
85
135
|
async function setEnvVar(baseSecretKey, value) {
|
|
86
|
-
const
|
|
87
|
-
if (!
|
|
136
|
+
const smClient = await getSecretManagerClient();
|
|
137
|
+
if (!smClient) {
|
|
88
138
|
console.warn(`[EnvService.ts] SecretManager not available for setEnvVar (key: ${baseSecretKey})`);
|
|
89
139
|
return false;
|
|
90
140
|
}
|
|
91
|
-
|
|
141
|
+
try {
|
|
142
|
+
const secretName = buildSecretName(smClient.projectId, baseSecretKey);
|
|
143
|
+
const addVersion = async () => {
|
|
144
|
+
const secretPath = buildSecretPath(smClient.projectId, secretName);
|
|
145
|
+
await smClient.client.addSecretVersion({
|
|
146
|
+
parent: secretPath,
|
|
147
|
+
payload: {
|
|
148
|
+
data: Buffer.from(value, "utf8")
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
console.log(`\u2705 Secret '${baseSecretKey}' saved in GCP project: ${smClient.projectId}`);
|
|
152
|
+
};
|
|
153
|
+
try {
|
|
154
|
+
await addVersion();
|
|
155
|
+
return true;
|
|
156
|
+
} catch (err) {
|
|
157
|
+
if (err.code === 5) {
|
|
158
|
+
await smClient.client.createSecret({
|
|
159
|
+
parent: `projects/${smClient.projectId}`,
|
|
160
|
+
secretId: secretName,
|
|
161
|
+
secret: {
|
|
162
|
+
replication: {
|
|
163
|
+
automatic: {}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
console.log(`[EnvService.ts] Created secret resource: ${secretName}`);
|
|
168
|
+
await addVersion();
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
console.warn(`[EnvService.ts] setEnvVar failed: ${err.message}`);
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.warn(`[EnvService.ts] Failed to set secret ${baseSecretKey}: ${error.message}`);
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
92
178
|
}
|
|
93
179
|
var setLogToConsole = async () => {
|
|
94
180
|
const logToConsole = await askQuestion("Use consoleLogger to log to console? (yes, no)", "no");
|
|
95
181
|
if (logToConsole) {
|
|
96
|
-
|
|
182
|
+
const normalizedValue = logToConsole.toLowerCase();
|
|
183
|
+
if (normalizedValue === "yes" || normalizedValue === "no") {
|
|
184
|
+
await setEnvVar("LOG_TO_CONSOLE", normalizedValue);
|
|
185
|
+
} else {
|
|
186
|
+
console.warn(`Invalid LOG_TO_CONSOLE value: '${logToConsole}'. Only 'yes' or 'no' are valid.`);
|
|
187
|
+
}
|
|
97
188
|
}
|
|
98
189
|
};
|
|
99
190
|
var setPostgresUser = async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dataformer/env-service",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Environment service for Dataformer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@google-cloud/secret-manager": "^5.4.0"
|
|
16
|
-
"@dataformer/secret-manager-client": "^2.2.0"
|
|
15
|
+
"@google-cloud/secret-manager": "^5.4.0"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
18
|
"tsup": "^8.0.0",
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// EnvService.ts - Manages environment variables and credentials using Google Secret Manager.
|
|
2
2
|
//
|
|
3
3
|
// HOW TO USE:
|
|
4
|
-
// This script
|
|
4
|
+
// This script can be invoked via the wrapper `env.js` in the project root (after building):
|
|
5
5
|
// Commands are passed as arguments, e.g.:
|
|
6
6
|
// node env.js printEnv - Prints all current environment variable values.
|
|
7
|
-
// node env.js
|
|
7
|
+
// node env.js setGeminiApiKey - Prompts to set the Gemini API key.
|
|
8
|
+
// node env.js setPostgresUser - Prompts to set the PostgreSQL user.
|
|
8
9
|
// ... and so on for other specific setters listed in the `run` function's switch statement.
|
|
9
10
|
//
|
|
11
|
+
// Alternatively, you can run it directly from the compiled output:
|
|
12
|
+
// node packages/services/env-service/dist/index.js printEnv
|
|
13
|
+
//
|
|
10
14
|
// GCLOUD AUTHENTICATION REQUIREMENT:
|
|
11
15
|
// This script requires you to be authenticated with Google Cloud CLI (`gcloud`).
|
|
12
16
|
// The credentials are used by the underlying SecretManagerClient to access Google Secret Manager.
|
|
@@ -35,29 +39,83 @@
|
|
|
35
39
|
|
|
36
40
|
import readline from 'readline';
|
|
37
41
|
import path from 'path';
|
|
38
|
-
import {
|
|
42
|
+
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
|
|
43
|
+
import { execSync } from 'child_process';
|
|
39
44
|
|
|
40
|
-
//
|
|
41
|
-
|
|
45
|
+
// Helper functions for GCP project ID detection
|
|
46
|
+
function getGcpProjectIdFromGcloud(): string | null {
|
|
47
|
+
try {
|
|
48
|
+
const cmd = 'gcloud config get-value core/project';
|
|
49
|
+
const projectId = execSync(cmd, { encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
50
|
+
if (projectId && projectId !== '(unset)') {
|
|
51
|
+
return projectId;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getProjectId(): string {
|
|
60
|
+
// Project ID resolution priority:
|
|
61
|
+
// 1. GCP_PROJECT_ID env var (REQUIRED for CI/CD)
|
|
62
|
+
// 2. gcloud config project (for local development)
|
|
63
|
+
if (process.env.GCP_PROJECT_ID) {
|
|
64
|
+
return process.env.GCP_PROJECT_ID;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const gcloudProjectId = getGcpProjectIdFromGcloud();
|
|
68
|
+
if (gcloudProjectId) {
|
|
69
|
+
return gcloudProjectId;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
throw new Error(
|
|
73
|
+
'🚨 GCP project ID is required for Secret Manager.\n\n' +
|
|
74
|
+
'CI/CD DEPLOYMENT (REQUIRED):\n' +
|
|
75
|
+
' Set GCP_PROJECT_ID as environment variable\n' +
|
|
76
|
+
' Example: GCP_PROJECT_ID=dataformer-prod\n\n' +
|
|
77
|
+
'LOCAL DEVELOPMENT:\n' +
|
|
78
|
+
' Set your gcloud project: gcloud config set project YOUR_PROJECT_ID\n' +
|
|
79
|
+
' Verify with: gcloud config get-value project'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Secret Manager direct implementation
|
|
84
|
+
let secretManagerClient: SecretManagerServiceClient | null = null;
|
|
42
85
|
let secretManagerInitialized = false;
|
|
86
|
+
let projectId: string | null = null;
|
|
43
87
|
|
|
44
|
-
async function
|
|
88
|
+
async function getSecretManagerClient(): Promise<{ client: SecretManagerServiceClient; projectId: string } | null> {
|
|
45
89
|
if (secretManagerInitialized) {
|
|
46
|
-
return
|
|
90
|
+
return secretManagerClient && projectId ? { client: secretManagerClient, projectId } : null;
|
|
47
91
|
}
|
|
48
92
|
|
|
49
93
|
try {
|
|
50
|
-
|
|
94
|
+
projectId = getProjectId();
|
|
95
|
+
secretManagerClient = new SecretManagerServiceClient({ projectId });
|
|
51
96
|
secretManagerInitialized = true;
|
|
52
|
-
return
|
|
97
|
+
return { client: secretManagerClient, projectId };
|
|
53
98
|
} catch (error) {
|
|
54
|
-
console.error('[EnvService.ts] Failed to initialize
|
|
99
|
+
console.error('[EnvService.ts] Failed to initialize SecretManagerServiceClient:', (error as Error).message);
|
|
55
100
|
console.warn('[EnvService.ts] Secret Manager functionality will be unavailable.');
|
|
56
101
|
secretManagerInitialized = true; // Prevent retrying
|
|
57
102
|
return null;
|
|
58
103
|
}
|
|
59
104
|
}
|
|
60
105
|
|
|
106
|
+
// Helper functions for secret operations
|
|
107
|
+
function buildSecretName(projectId: string, baseSecretId: string): string {
|
|
108
|
+
return `${projectId}_${baseSecretId}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function buildSecretPath(projectId: string, secretName: string): string {
|
|
112
|
+
return `projects/${projectId}/secrets/${secretName}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildSecretVersionPath(projectId: string, secretName: string, version: string = 'latest'): string {
|
|
116
|
+
return `projects/${projectId}/secrets/${secretName}/versions/${version}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
61
119
|
const rl = readline.createInterface({
|
|
62
120
|
input: process.stdin,
|
|
63
121
|
output: process.stdout,
|
|
@@ -83,12 +141,29 @@ function obfuscateCred(cred: string | null): string {
|
|
|
83
141
|
|
|
84
142
|
// --- Generic Environment Variable Accessors ---
|
|
85
143
|
async function getEnvVar(baseSecretKey: string): Promise<string | null> {
|
|
86
|
-
const
|
|
87
|
-
if (!
|
|
144
|
+
const smClient = await getSecretManagerClient();
|
|
145
|
+
if (!smClient) {
|
|
88
146
|
console.warn(`[EnvService.ts] SecretManager not available for getEnvVar (key: ${baseSecretKey})`);
|
|
89
147
|
return null;
|
|
90
148
|
}
|
|
91
|
-
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const secretName = buildSecretName(smClient.projectId, baseSecretKey);
|
|
152
|
+
const secretVersionPath = buildSecretVersionPath(smClient.projectId, secretName);
|
|
153
|
+
|
|
154
|
+
const [response] = await smClient.client.accessSecretVersion({
|
|
155
|
+
name: secretVersionPath,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const secretValue = response.payload?.data?.toString();
|
|
159
|
+
return secretValue || null;
|
|
160
|
+
} catch (error: any) {
|
|
161
|
+
if (error.code === 5) { // NOT_FOUND
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
console.warn(`[EnvService.ts] Failed to get secret ${baseSecretKey}: ${error.message}`);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
92
167
|
}
|
|
93
168
|
|
|
94
169
|
export async function getCustomSearchApiKey(): Promise<string> {
|
|
@@ -137,21 +212,67 @@ export async function getGcpProjectId(): Promise<string> {
|
|
|
137
212
|
}
|
|
138
213
|
|
|
139
214
|
async function setEnvVar(baseSecretKey: string, value: string): Promise<boolean> {
|
|
140
|
-
const
|
|
141
|
-
if (!
|
|
215
|
+
const smClient = await getSecretManagerClient();
|
|
216
|
+
if (!smClient) {
|
|
142
217
|
console.warn(`[EnvService.ts] SecretManager not available for setEnvVar (key: ${baseSecretKey})`);
|
|
143
218
|
return false; // Indicate failure
|
|
144
219
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
const secretName = buildSecretName(smClient.projectId, baseSecretKey);
|
|
223
|
+
|
|
224
|
+
// Try to add a version first
|
|
225
|
+
const addVersion = async (): Promise<void> => {
|
|
226
|
+
const secretPath = buildSecretPath(smClient.projectId, secretName);
|
|
227
|
+
await smClient.client.addSecretVersion({
|
|
228
|
+
parent: secretPath,
|
|
229
|
+
payload: {
|
|
230
|
+
data: Buffer.from(value, 'utf8'),
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
console.log(`✅ Secret '${baseSecretKey}' saved in GCP project: ${smClient.projectId}`);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
await addVersion();
|
|
238
|
+
return true;
|
|
239
|
+
} catch (err: any) {
|
|
240
|
+
if (err.code === 5) { // NOT_FOUND → create then retry
|
|
241
|
+
// Create the secret resource first
|
|
242
|
+
await smClient.client.createSecret({
|
|
243
|
+
parent: `projects/${smClient.projectId}`,
|
|
244
|
+
secretId: secretName,
|
|
245
|
+
secret: {
|
|
246
|
+
replication: {
|
|
247
|
+
automatic: {},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
console.log(`[EnvService.ts] Created secret resource: ${secretName}`);
|
|
252
|
+
|
|
253
|
+
await addVersion();
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
console.warn(`[EnvService.ts] setEnvVar failed: ${err.message}`);
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
} catch (error: any) {
|
|
260
|
+
console.warn(`[EnvService.ts] Failed to set secret ${baseSecretKey}: ${error.message}`);
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
148
263
|
}
|
|
149
264
|
|
|
150
265
|
// --- Specific Setters (Now use generic setEnvVar) ---
|
|
151
266
|
const setLogToConsole = async (): Promise<void> => {
|
|
152
267
|
const logToConsole = await askQuestion('Use consoleLogger to log to console? (yes, no)', 'no');
|
|
153
268
|
if (logToConsole) {
|
|
154
|
-
|
|
269
|
+
// Normalize to lowercase and validate - only 'yes' or 'no' are valid
|
|
270
|
+
const normalizedValue = logToConsole.toLowerCase();
|
|
271
|
+
if (normalizedValue === 'yes' || normalizedValue === 'no') {
|
|
272
|
+
await setEnvVar('LOG_TO_CONSOLE', normalizedValue);
|
|
273
|
+
} else {
|
|
274
|
+
console.warn(`Invalid LOG_TO_CONSOLE value: '${logToConsole}'. Only 'yes' or 'no' are valid.`);
|
|
275
|
+
}
|
|
155
276
|
}
|
|
156
277
|
};
|
|
157
278
|
|
|
@@ -311,12 +432,12 @@ const getProjectRoot = (): string => {
|
|
|
311
432
|
};
|
|
312
433
|
|
|
313
434
|
const _getResolvedGcpProjectId = async (): Promise<string | null> => {
|
|
314
|
-
const
|
|
315
|
-
if (!
|
|
435
|
+
const smClient = await getSecretManagerClient();
|
|
436
|
+
if (!smClient) {
|
|
316
437
|
console.warn('[EnvService.ts] SecretManager not available for _getResolvedGcpProjectId');
|
|
317
438
|
return null;
|
|
318
439
|
}
|
|
319
|
-
return
|
|
440
|
+
return smClient.projectId;
|
|
320
441
|
};
|
|
321
442
|
|
|
322
443
|
const printEnv = async (): Promise<void> => {
|