1- import {
2- decryptEnvSecrets ,
3- digest ,
4- encryptEnvSecrets ,
5- reconstructPrivateKey ,
6- unwrapEnvKeys ,
7- } from "./utils/crypto" ;
1+
82import axios from "axios" ;
93import {
104 App ,
@@ -21,8 +15,10 @@ import {
2115 normalizeKey ,
2216 resolveSecretReferences ,
2317 SecretFetcher ,
24- } from "./utils/secrets " ;
18+ } from "./utils/secretReferencing " ;
2519import { LIB_VERSION } from "../version" ;
20+ import { reconstructPrivateKey , unwrapEnvKeys , digest , decryptEnvSecrets , encryptEnvSecrets } from "./utils/crypto" ;
21+
2622
2723const DEFAULT_HOST = "https://console.phase.dev" ;
2824
@@ -156,128 +152,82 @@ export default class Phase {
156152 async get ( options : GetSecretOptions ) : Promise < Secret [ ] > {
157153 return new Promise < Secret [ ] > ( async ( resolve , reject ) => {
158154 const cache = new Map < string , string > ( ) ;
159-
155+
160156 const app = this . apps . find ( ( app ) => app . id === options . appId ) ;
161157 if ( ! app ) {
162- reject ( "Invalid app id" ) ;
163- return ;
158+ return reject ( "Invalid app id" ) ;
164159 }
165-
166- const env = app ? .environments . find (
167- ( env ) => env . name . toLowerCase ( ) === options . envName . toLowerCase ( )
160+
161+ const env = app . environments . find (
162+ ( e ) => e . name . toLowerCase ( ) === options . envName . toLowerCase ( )
168163 ) ;
169164 if ( ! env ) {
170- reject ( `Invalid environment name: ${ options . envName } ` ) ;
171- return ;
165+ return reject ( `Invalid environment name: ${ options . envName } ` ) ;
172166 }
173-
167+
174168 try {
175169 const queryHeaders = {
176170 environment : env . id ,
177171 path : options . path || "/" ,
178- keyDigest : null ,
172+ keyDigest : options . key
173+ ? await digest ( options . key . toUpperCase ( ) , env . salt )
174+ : null ,
179175 } ;
180-
181- if ( options . key ) {
182- const keyDigest = await digest ( options . key . toUpperCase ( ) , env . salt ) ;
183- queryHeaders . keyDigest = keyDigest ;
184- }
185-
186- const res = await axios ( {
187- url : `${ this . host } /service/secrets/` ,
188- method : "get" ,
189- headers : {
190- ...queryHeaders ,
191- ...this . getAuthHeaders ( ) ,
192- } ,
176+
177+ const res = await axios . get ( `${ this . host } /service/secrets/` , {
178+ headers : { ...queryHeaders , ...this . getAuthHeaders ( ) } ,
193179 } ) ;
194-
195- let secretsToDecrypt = res . data
196- . filter ( ( secret : Secret ) =>
197- options . path ? secret . path === options . path : true
198- )
199- . filter ( ( secret : Secret ) =>
200- options . tags
201- ? secret . tags . some ( ( tag ) => options . tags ?. includes ( tag ) )
202- : true
203- ) ;
204-
205- // Decrypt fetched secrets
180+
181+ const secretsToDecrypt = res . data . filter (
182+ ( secret : Secret ) =>
183+ ( ! options . path || secret . path === options . path ) &&
184+ ( ! options . tags || secret . tags . some ( ( tag ) => options . tags ?. includes ( tag ) ) )
185+ ) ;
186+
206187 const secrets = await decryptEnvSecrets ( secretsToDecrypt , env . keypair ) ;
207-
188+
189+ // Create lookup map
208190 const secretLookup = new Map < string , Secret > (
209191 secrets . map ( ( s ) => [ normalizeKey ( env . name , s . path , s . key ) , s ] )
210192 ) ;
211-
212- // 🛠 Fetch local and cross-environment secrets as needed
213- const fetcher : SecretFetcher = async (
214- envName : string ,
215- path : string ,
216- key : string
217- ) => {
193+
194+ // Fetcher for resolving references
195+ const fetcher : SecretFetcher = async ( envName , path , key ) => {
218196 const cacheKey = normalizeKey ( envName , path , key ) ;
219-
197+
220198 if ( cache . has ( cacheKey ) ) {
221- return {
222- id : "" ,
223- key,
224- value : cache . get ( cacheKey ) ! ,
225- comment : "" ,
226- environment : envName ,
227- folder : undefined ,
228- path,
229- tags : [ ] ,
230- keyDigest : "" ,
231- createdAt : undefined ,
232- updatedAt : new Date ( ) . toISOString ( ) ,
233- version : 1 ,
234- } ;
199+ return { id : "" , key, value : cache . get ( cacheKey ) ! , comment : "" , environment : envName , folder : undefined , path, tags : [ ] , keyDigest : "" , createdAt : undefined , updatedAt : new Date ( ) . toISOString ( ) , version : 1 } ;
235200 }
236-
201+
237202 let secret = secretLookup . get ( cacheKey ) ;
238-
239203 if ( ! secret ) {
240- // 🔄 Fetch cross-environment secret dynamically
241- const crossEnvSecrets = await this . get ( {
242- ...options ,
243- envName,
244- path,
245- tags : undefined ,
246- } ) ;
247-
204+ const crossEnvSecrets = await this . get ( { ...options , envName, path, tags : undefined } ) ;
248205 secret = crossEnvSecrets . find ( ( s ) => s . key === key ) ;
249- if ( ! secret )
250- throw new Error ( `Missing secret: ${ envName } :${ path } :${ key } ` ) ;
251-
252- // Store for future lookups
206+ if ( ! secret ) throw new Error ( `Missing secret: ${ envName } :${ path } :${ key } ` ) ;
207+
253208 secretLookup . set ( cacheKey , secret ) ;
254209 }
255-
210+
256211 cache . set ( cacheKey , secret . value ) ;
257212 return secret ;
258213 } ;
259-
260- // Resolve references in secret values
214+
215+ // Resolve references
261216 const resolvedSecrets = await Promise . all (
262217 secrets . map ( async ( secret ) => ( {
263218 ...secret ,
264- value : await resolveSecretReferences (
265- secret . value ,
266- options . envName ,
267- options . path || "/" ,
268- fetcher ,
269- cache
270- ) ,
219+ value : await resolveSecretReferences ( secret . value , options . envName , options . path || "/" , fetcher , cache ) ,
271220 } ) )
272221 ) ;
273-
222+
274223 resolve ( resolvedSecrets ) ;
275224 } catch ( err ) {
276- console . log ( `Error fetching secrets: ${ err } ` ) ;
225+ console . error ( `Error fetching secrets: ${ err } ` ) ;
277226 reject ( err ) ;
278227 }
279228 } ) ;
280229 }
230+
281231
282232
283233
0 commit comments