@enkryptify/sdk 0.1.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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/index.cjs +529 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +98 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +517 -0
- package/dist/index.js.map +1 -0
- package/package.json +89 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var EnkryptifyError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "EnkryptifyError";
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var SecretNotFoundError = class extends EnkryptifyError {
|
|
9
|
+
constructor(key, workspace, environment) {
|
|
10
|
+
super(
|
|
11
|
+
`Secret "${key}" not found in workspace "${workspace}" (environment: "${environment}"). Verify the secret exists in your Enkryptify dashboard.
|
|
12
|
+
Docs: https://docs.enkryptify.com/sdk/troubleshooting#secret-not-found`
|
|
13
|
+
);
|
|
14
|
+
this.name = "SecretNotFoundError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var AuthenticationError = class extends EnkryptifyError {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(
|
|
20
|
+
"Authentication failed (HTTP 401). Token is invalid, expired, or revoked. Generate a new token in your Enkryptify dashboard.\nDocs: https://docs.enkryptify.com/sdk/auth#token-issues"
|
|
21
|
+
);
|
|
22
|
+
this.name = "AuthenticationError";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var AuthorizationError = class extends EnkryptifyError {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(
|
|
28
|
+
"Authorization failed (HTTP 403). Token does not have access to this resource. Check that your token has the required permissions.\nDocs: https://docs.enkryptify.com/sdk/auth#permissions"
|
|
29
|
+
);
|
|
30
|
+
this.name = "AuthorizationError";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var NotFoundError = class extends EnkryptifyError {
|
|
34
|
+
constructor(method, endpoint) {
|
|
35
|
+
super(
|
|
36
|
+
`Resource not found (HTTP 404) for ${method} ${endpoint}. Workspace, project, or environment not found. Verify your configuration.
|
|
37
|
+
Docs: https://docs.enkryptify.com/sdk/troubleshooting#not-found`
|
|
38
|
+
);
|
|
39
|
+
this.name = "NotFoundError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var RateLimitError = class extends EnkryptifyError {
|
|
43
|
+
retryAfter;
|
|
44
|
+
constructor(retryAfter) {
|
|
45
|
+
const parsed = retryAfter ? parseInt(retryAfter, 10) : null;
|
|
46
|
+
const retrySeconds = parsed !== null && !Number.isNaN(parsed) ? parsed : null;
|
|
47
|
+
super(
|
|
48
|
+
`Rate limited (HTTP 429). ${retrySeconds ? `Retry after ${retrySeconds} seconds.` : "Please retry later."}
|
|
49
|
+
Docs: https://docs.enkryptify.com/sdk/troubleshooting#rate-limiting`
|
|
50
|
+
);
|
|
51
|
+
this.name = "RateLimitError";
|
|
52
|
+
this.retryAfter = retrySeconds;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var ApiError = class extends EnkryptifyError {
|
|
56
|
+
status;
|
|
57
|
+
constructor(status, statusText, method, endpoint) {
|
|
58
|
+
super(
|
|
59
|
+
`API request failed (HTTP ${status}) for ${method} ${endpoint}. ${statusText ? statusText + ". " : ""}This may be a temporary server issue \u2014 retry in a few moments.
|
|
60
|
+
Docs: https://docs.enkryptify.com/sdk/troubleshooting#api-errors`
|
|
61
|
+
);
|
|
62
|
+
this.name = "ApiError";
|
|
63
|
+
this.status = status;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/internal/token-store.ts
|
|
68
|
+
var store = /* @__PURE__ */ new WeakMap();
|
|
69
|
+
function storeToken(provider, token) {
|
|
70
|
+
store.set(provider, token);
|
|
71
|
+
}
|
|
72
|
+
function retrieveToken(provider) {
|
|
73
|
+
const token = store.get(provider);
|
|
74
|
+
if (!token) {
|
|
75
|
+
throw new EnkryptifyError(
|
|
76
|
+
"Invalid or destroyed auth provider. Create a new one via Enkryptify.fromEnv().\nDocs: https://docs.enkryptify.com/sdk/auth"
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return token;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/auth.ts
|
|
83
|
+
var EnvAuthProvider = class {
|
|
84
|
+
_brand = "EnkryptifyAuthProvider";
|
|
85
|
+
constructor() {
|
|
86
|
+
const token = process.env.ENKRYPTIFY_TOKEN;
|
|
87
|
+
if (!token) {
|
|
88
|
+
throw new EnkryptifyError(
|
|
89
|
+
'ENKRYPTIFY_TOKEN environment variable is not set. Set it before initializing the SDK:\n export ENKRYPTIFY_TOKEN="ek_..."\nDocs: https://docs.enkryptify.com/sdk/auth#environment-variables'
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
storeToken(this, token);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var TokenAuthProvider = class {
|
|
96
|
+
_brand = "EnkryptifyAuthProvider";
|
|
97
|
+
constructor(token) {
|
|
98
|
+
storeToken(this, token);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/api.ts
|
|
103
|
+
var EnkryptifyApi = class {
|
|
104
|
+
#baseUrl;
|
|
105
|
+
#auth;
|
|
106
|
+
constructor(baseUrl, auth) {
|
|
107
|
+
this.#baseUrl = baseUrl;
|
|
108
|
+
this.#auth = auth;
|
|
109
|
+
}
|
|
110
|
+
async fetchSecret(workspace, project, secretName, environmentId) {
|
|
111
|
+
const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret/${encodeURIComponent(secretName)}`;
|
|
112
|
+
const params = new URLSearchParams({ environmentId, resolve: "true" });
|
|
113
|
+
return this.#request("GET", `${path}?${params.toString()}`);
|
|
114
|
+
}
|
|
115
|
+
async fetchAllSecrets(workspace, project, environmentId) {
|
|
116
|
+
const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret`;
|
|
117
|
+
const params = new URLSearchParams({ environmentId, resolve: "true" });
|
|
118
|
+
return this.#request("GET", `${path}?${params.toString()}`);
|
|
119
|
+
}
|
|
120
|
+
async #request(method, endpoint) {
|
|
121
|
+
const token = retrieveToken(this.#auth);
|
|
122
|
+
const url = `${this.#baseUrl}${endpoint}`;
|
|
123
|
+
const response = await fetch(url, {
|
|
124
|
+
method,
|
|
125
|
+
headers: {
|
|
126
|
+
Authorization: `Bearer ${token}`,
|
|
127
|
+
"Content-Type": "application/json"
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
if (response.status === 401) {
|
|
131
|
+
throw new AuthenticationError();
|
|
132
|
+
}
|
|
133
|
+
if (response.status === 403) {
|
|
134
|
+
throw new AuthorizationError();
|
|
135
|
+
}
|
|
136
|
+
if (response.status === 404) {
|
|
137
|
+
throw new NotFoundError(method, endpoint);
|
|
138
|
+
}
|
|
139
|
+
if (response.status === 429) {
|
|
140
|
+
throw new RateLimitError(response.headers.get("Retry-After"));
|
|
141
|
+
}
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
throw new ApiError(response.status, response.statusText, method, endpoint);
|
|
144
|
+
}
|
|
145
|
+
return response.json();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// src/cache.ts
|
|
150
|
+
var SecretCache = class {
|
|
151
|
+
#store = /* @__PURE__ */ new Map();
|
|
152
|
+
#ttl;
|
|
153
|
+
constructor(ttl) {
|
|
154
|
+
this.#ttl = ttl;
|
|
155
|
+
}
|
|
156
|
+
get(key) {
|
|
157
|
+
const entry = this.#store.get(key);
|
|
158
|
+
if (!entry) return void 0;
|
|
159
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
160
|
+
this.#store.delete(key);
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
return entry.value;
|
|
164
|
+
}
|
|
165
|
+
set(key, value) {
|
|
166
|
+
this.#store.set(key, {
|
|
167
|
+
value,
|
|
168
|
+
expiresAt: this.#ttl === -1 ? null : Date.now() + this.#ttl
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
has(key) {
|
|
172
|
+
return this.get(key) !== void 0;
|
|
173
|
+
}
|
|
174
|
+
clear() {
|
|
175
|
+
this.#store.clear();
|
|
176
|
+
this.#store = /* @__PURE__ */ new Map();
|
|
177
|
+
}
|
|
178
|
+
get size() {
|
|
179
|
+
return this.#store.size;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/logger.ts
|
|
184
|
+
var LEVELS = {
|
|
185
|
+
debug: 0,
|
|
186
|
+
info: 1,
|
|
187
|
+
warn: 2,
|
|
188
|
+
error: 3
|
|
189
|
+
};
|
|
190
|
+
var Logger = class {
|
|
191
|
+
#level;
|
|
192
|
+
constructor(level = "info") {
|
|
193
|
+
this.#level = LEVELS[level];
|
|
194
|
+
}
|
|
195
|
+
debug(message) {
|
|
196
|
+
if (this.#level <= LEVELS.debug) {
|
|
197
|
+
console.debug(`[Enkryptify] ${message}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
info(message) {
|
|
201
|
+
if (this.#level <= LEVELS.info) {
|
|
202
|
+
console.info(`[Enkryptify] ${message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
warn(message) {
|
|
206
|
+
if (this.#level <= LEVELS.warn) {
|
|
207
|
+
console.warn(`[Enkryptify] ${message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
error(message) {
|
|
211
|
+
if (this.#level <= LEVELS.error) {
|
|
212
|
+
console.error(`[Enkryptify] ${message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// src/token-exchange.ts
|
|
218
|
+
var TokenExchangeManager = class {
|
|
219
|
+
#baseUrl;
|
|
220
|
+
#staticToken;
|
|
221
|
+
#auth;
|
|
222
|
+
#logger;
|
|
223
|
+
#jwt = null;
|
|
224
|
+
#refreshTimer = null;
|
|
225
|
+
#exchangePromise = null;
|
|
226
|
+
constructor(baseUrl, staticToken, auth, logger) {
|
|
227
|
+
this.#baseUrl = baseUrl;
|
|
228
|
+
this.#staticToken = staticToken;
|
|
229
|
+
this.#auth = auth;
|
|
230
|
+
this.#logger = logger;
|
|
231
|
+
}
|
|
232
|
+
async ensureToken() {
|
|
233
|
+
if (this.#jwt) return;
|
|
234
|
+
if (this.#exchangePromise) {
|
|
235
|
+
return this.#exchangePromise;
|
|
236
|
+
}
|
|
237
|
+
this.#exchangePromise = this.#exchange();
|
|
238
|
+
try {
|
|
239
|
+
await this.#exchangePromise;
|
|
240
|
+
} finally {
|
|
241
|
+
this.#exchangePromise = null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async #exchange() {
|
|
245
|
+
try {
|
|
246
|
+
const response = await fetch(`${this.#baseUrl}/v1/auth/exchange`, {
|
|
247
|
+
method: "POST",
|
|
248
|
+
headers: {
|
|
249
|
+
Authorization: `Bearer ${this.#staticToken}`,
|
|
250
|
+
"Content-Type": "application/json"
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
throw new Error(`Token exchange failed with HTTP ${response.status}`);
|
|
255
|
+
}
|
|
256
|
+
const data = await response.json();
|
|
257
|
+
this.#jwt = data.accessToken;
|
|
258
|
+
storeToken(this.#auth, this.#jwt);
|
|
259
|
+
this.#logger.debug("Token exchanged for short-lived JWT");
|
|
260
|
+
const refreshMs = (data.expiresIn - 60) * 1e3;
|
|
261
|
+
this.#scheduleRefresh(refreshMs);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
this.#jwt = null;
|
|
264
|
+
storeToken(this.#auth, this.#staticToken);
|
|
265
|
+
this.#logger.warn(
|
|
266
|
+
`Token exchange failed, falling back to static token: ${error instanceof Error ? error.message : String(error)}`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
#scheduleRefresh(ms) {
|
|
271
|
+
if (this.#refreshTimer) {
|
|
272
|
+
clearTimeout(this.#refreshTimer);
|
|
273
|
+
}
|
|
274
|
+
this.#refreshTimer = setTimeout(() => {
|
|
275
|
+
this.#jwt = null;
|
|
276
|
+
this.#exchange();
|
|
277
|
+
}, ms);
|
|
278
|
+
this.#refreshTimer.unref?.();
|
|
279
|
+
}
|
|
280
|
+
destroy() {
|
|
281
|
+
if (this.#refreshTimer) {
|
|
282
|
+
clearTimeout(this.#refreshTimer);
|
|
283
|
+
this.#refreshTimer = null;
|
|
284
|
+
}
|
|
285
|
+
this.#jwt = null;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/enkryptify.ts
|
|
290
|
+
var Enkryptify = class _Enkryptify {
|
|
291
|
+
#api;
|
|
292
|
+
#cache;
|
|
293
|
+
#logger;
|
|
294
|
+
#workspace;
|
|
295
|
+
#project;
|
|
296
|
+
#environment;
|
|
297
|
+
#strict;
|
|
298
|
+
#usePersonalValues;
|
|
299
|
+
#cacheEnabled;
|
|
300
|
+
#eagerCache;
|
|
301
|
+
#destroyed = false;
|
|
302
|
+
#eagerLoaded = false;
|
|
303
|
+
#tokenExchange = null;
|
|
304
|
+
constructor(config) {
|
|
305
|
+
if (!config.workspace) {
|
|
306
|
+
throw new EnkryptifyError(
|
|
307
|
+
'Missing required config field "workspace". Provide a workspace slug or ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (!config.project) {
|
|
311
|
+
throw new EnkryptifyError(
|
|
312
|
+
'Missing required config field "project". Provide a project slug or ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
if (!config.environment) {
|
|
316
|
+
throw new EnkryptifyError(
|
|
317
|
+
'Missing required config field "environment". Provide an environment ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
let auth;
|
|
321
|
+
if (config.token) {
|
|
322
|
+
_Enkryptify.#validateTokenFormat(config.token);
|
|
323
|
+
auth = new TokenAuthProvider(config.token);
|
|
324
|
+
} else if (config.auth) {
|
|
325
|
+
if (config.auth._brand !== "EnkryptifyAuthProvider") {
|
|
326
|
+
throw new EnkryptifyError(
|
|
327
|
+
"Invalid auth provider. Use Enkryptify.fromEnv() or pass a token option.\nDocs: https://docs.enkryptify.com/sdk/auth"
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
auth = config.auth;
|
|
331
|
+
} else {
|
|
332
|
+
const envToken = process.env.ENKRYPTIFY_TOKEN;
|
|
333
|
+
if (!envToken) {
|
|
334
|
+
throw new EnkryptifyError(
|
|
335
|
+
"No token provided. Set ENKRYPTIFY_TOKEN or pass token in options.\nDocs: https://docs.enkryptify.com/sdk/auth"
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
_Enkryptify.#validateTokenFormat(envToken);
|
|
339
|
+
auth = new TokenAuthProvider(envToken);
|
|
340
|
+
}
|
|
341
|
+
retrieveToken(auth);
|
|
342
|
+
this.#workspace = config.workspace;
|
|
343
|
+
this.#project = config.project;
|
|
344
|
+
this.#environment = config.environment;
|
|
345
|
+
this.#strict = config.options?.strict ?? true;
|
|
346
|
+
this.#usePersonalValues = config.options?.usePersonalValues ?? true;
|
|
347
|
+
this.#cacheEnabled = config.cache?.enabled ?? true;
|
|
348
|
+
this.#eagerCache = config.cache?.eager ?? true;
|
|
349
|
+
const cacheTtl = config.cache?.ttl ?? -1;
|
|
350
|
+
this.#logger = new Logger(config.logger?.level ?? "info");
|
|
351
|
+
this.#cache = this.#cacheEnabled ? new SecretCache(cacheTtl) : null;
|
|
352
|
+
const baseUrl = config.baseUrl ?? "https://api.enkryptify.com";
|
|
353
|
+
this.#api = new EnkryptifyApi(baseUrl, auth);
|
|
354
|
+
if (config.useTokenExchange) {
|
|
355
|
+
const staticToken = retrieveToken(auth);
|
|
356
|
+
this.#tokenExchange = new TokenExchangeManager(baseUrl, staticToken, auth, this.#logger);
|
|
357
|
+
}
|
|
358
|
+
this.#logger.info(
|
|
359
|
+
`Initialized for workspace "${this.#workspace}", project "${this.#project}", environment "${this.#environment}"`
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
static fromEnv() {
|
|
363
|
+
return new EnvAuthProvider();
|
|
364
|
+
}
|
|
365
|
+
static #validateTokenFormat(token) {
|
|
366
|
+
if (!token) {
|
|
367
|
+
throw new EnkryptifyError("Token must be a non-empty string.\nDocs: https://docs.enkryptify.com/sdk/auth");
|
|
368
|
+
}
|
|
369
|
+
if (token.startsWith("ek_live_")) return;
|
|
370
|
+
const dotCount = token.split(".").length - 1;
|
|
371
|
+
if (dotCount === 2) return;
|
|
372
|
+
throw new EnkryptifyError(
|
|
373
|
+
"Invalid token format. Expected an ek_live_ token or JWT.\nDocs: https://docs.enkryptify.com/sdk/auth#token-format"
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
async get(key, options) {
|
|
377
|
+
this.#guardDestroyed();
|
|
378
|
+
const useCache = this.#cacheEnabled && options?.cache !== false;
|
|
379
|
+
if (useCache && this.#cache) {
|
|
380
|
+
const cached = this.#cache.get(key);
|
|
381
|
+
if (cached !== void 0) {
|
|
382
|
+
this.#logger.debug(`Cache hit for secret "${key}"`);
|
|
383
|
+
return cached;
|
|
384
|
+
}
|
|
385
|
+
this.#logger.debug(`Cache miss for secret "${key}", fetching from API`);
|
|
386
|
+
}
|
|
387
|
+
await this.#tokenExchange?.ensureToken();
|
|
388
|
+
if (useCache && this.#eagerCache && !this.#eagerLoaded) {
|
|
389
|
+
return this.#fetchAndCacheAll(key);
|
|
390
|
+
}
|
|
391
|
+
return this.#fetchAndCacheSingle(key);
|
|
392
|
+
}
|
|
393
|
+
getFromCache(key) {
|
|
394
|
+
this.#guardDestroyed();
|
|
395
|
+
if (!this.#cacheEnabled || !this.#cache) {
|
|
396
|
+
throw new EnkryptifyError(
|
|
397
|
+
"Cache is disabled. Enable caching in the config or use get() to fetch from the API.\nDocs: https://docs.enkryptify.com/sdk/configuration#caching"
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
const value = this.#cache.get(key);
|
|
401
|
+
if (value === void 0) {
|
|
402
|
+
throw new SecretNotFoundError(key, this.#workspace, this.#environment);
|
|
403
|
+
}
|
|
404
|
+
return value;
|
|
405
|
+
}
|
|
406
|
+
async preload() {
|
|
407
|
+
this.#guardDestroyed();
|
|
408
|
+
if (!this.#cacheEnabled || !this.#cache) {
|
|
409
|
+
throw new EnkryptifyError(
|
|
410
|
+
"Cannot preload: caching is disabled. Enable caching in the config.\nDocs: https://docs.enkryptify.com/sdk/configuration#caching"
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
await this.#tokenExchange?.ensureToken();
|
|
414
|
+
const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);
|
|
415
|
+
let count = 0;
|
|
416
|
+
for (const secret of secrets) {
|
|
417
|
+
const value = this.#resolveValue(secret);
|
|
418
|
+
if (value !== void 0) {
|
|
419
|
+
this.#cache.set(secret.name, value);
|
|
420
|
+
count++;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
this.#eagerLoaded = true;
|
|
424
|
+
this.#logger.info(`Preloaded ${count} secrets into cache`);
|
|
425
|
+
}
|
|
426
|
+
destroy() {
|
|
427
|
+
if (this.#destroyed) return;
|
|
428
|
+
this.#tokenExchange?.destroy();
|
|
429
|
+
this.#cache?.clear();
|
|
430
|
+
this.#destroyed = true;
|
|
431
|
+
this.#logger.info("Client destroyed, all cached secrets cleared");
|
|
432
|
+
}
|
|
433
|
+
#guardDestroyed() {
|
|
434
|
+
if (this.#destroyed) {
|
|
435
|
+
throw new EnkryptifyError(
|
|
436
|
+
"This Enkryptify client has been destroyed. Create a new instance to continue.\nDocs: https://docs.enkryptify.com/sdk/lifecycle"
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
async #fetchAndCacheAll(key) {
|
|
441
|
+
this.#logger.debug(
|
|
442
|
+
`Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret`
|
|
443
|
+
);
|
|
444
|
+
const start = Date.now();
|
|
445
|
+
const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);
|
|
446
|
+
this.#logger.debug(`API responded with ${secrets.length} secret(s) in ${Date.now() - start}ms`);
|
|
447
|
+
let found;
|
|
448
|
+
for (const secret of secrets) {
|
|
449
|
+
const value = this.#resolveValue(secret);
|
|
450
|
+
if (value !== void 0 && this.#cache) {
|
|
451
|
+
this.#cache.set(secret.name, value);
|
|
452
|
+
this.#logger.debug(
|
|
453
|
+
`Cached secret "${secret.name}" (${this.#cache ? "TTL: cache configured" : "no expiry"})`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
if (secret.name === key) {
|
|
457
|
+
found = value;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
this.#eagerLoaded = true;
|
|
461
|
+
if (found !== void 0) {
|
|
462
|
+
return found;
|
|
463
|
+
}
|
|
464
|
+
return this.#handleNotFound(key);
|
|
465
|
+
}
|
|
466
|
+
async #fetchAndCacheSingle(key) {
|
|
467
|
+
this.#logger.debug(
|
|
468
|
+
`Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret/${key}`
|
|
469
|
+
);
|
|
470
|
+
let secret;
|
|
471
|
+
try {
|
|
472
|
+
const start = Date.now();
|
|
473
|
+
secret = await this.#api.fetchSecret(this.#workspace, this.#project, key, this.#environment);
|
|
474
|
+
this.#logger.debug(`API responded with 1 secret(s) in ${Date.now() - start}ms`);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
if (error instanceof NotFoundError) {
|
|
477
|
+
return this.#handleNotFound(key);
|
|
478
|
+
}
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
const value = this.#resolveValue(secret);
|
|
482
|
+
if (value === void 0) {
|
|
483
|
+
return this.#handleNotFound(key);
|
|
484
|
+
}
|
|
485
|
+
if (this.#cacheEnabled && this.#cache) {
|
|
486
|
+
this.#cache.set(key, value);
|
|
487
|
+
}
|
|
488
|
+
return value;
|
|
489
|
+
}
|
|
490
|
+
#handleNotFound(key) {
|
|
491
|
+
if (this.#strict) {
|
|
492
|
+
throw new SecretNotFoundError(key, this.#workspace, this.#environment);
|
|
493
|
+
}
|
|
494
|
+
this.#logger.warn(`Secret "${key}" not found (strict mode disabled, returning empty string)`);
|
|
495
|
+
return "";
|
|
496
|
+
}
|
|
497
|
+
#resolveValue(secret) {
|
|
498
|
+
const envValues = secret.values.filter((v) => v.environmentId === this.#environment);
|
|
499
|
+
if (this.#usePersonalValues) {
|
|
500
|
+
const personal = envValues.find((v) => v.isPersonal);
|
|
501
|
+
if (personal) return personal.value;
|
|
502
|
+
const shared = envValues.find((v) => !v.isPersonal);
|
|
503
|
+
if (shared) {
|
|
504
|
+
this.#logger.warn(`No personal value for "${secret.name}", falling back to shared value`);
|
|
505
|
+
return shared.value;
|
|
506
|
+
}
|
|
507
|
+
} else {
|
|
508
|
+
const shared = envValues.find((v) => !v.isPersonal);
|
|
509
|
+
if (shared) return shared.value;
|
|
510
|
+
}
|
|
511
|
+
return void 0;
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
export { ApiError, AuthenticationError, AuthorizationError, Enkryptify, EnkryptifyError, NotFoundError, RateLimitError, SecretNotFoundError, Enkryptify as default };
|
|
516
|
+
//# sourceMappingURL=index.js.map
|
|
517
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/internal/token-store.ts","../src/auth.ts","../src/api.ts","../src/cache.ts","../src/logger.ts","../src/token-exchange.ts","../src/enkryptify.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export class EnkryptifyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EnkryptifyError\";\n }\n}\n\nexport class SecretNotFoundError extends EnkryptifyError {\n constructor(key: string, workspace: string, environment: string) {\n super(\n `Secret \"${key}\" not found in workspace \"${workspace}\" (environment: \"${environment}\"). ` +\n `Verify the secret exists in your Enkryptify dashboard.\\n` +\n `Docs: https://docs.enkryptify.com/sdk/troubleshooting#secret-not-found`,\n );\n this.name = \"SecretNotFoundError\";\n }\n}\n\nexport class AuthenticationError extends EnkryptifyError {\n constructor() {\n super(\n \"Authentication failed (HTTP 401). Token is invalid, expired, or revoked. \" +\n \"Generate a new token in your Enkryptify dashboard.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth#token-issues\",\n );\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class AuthorizationError extends EnkryptifyError {\n constructor() {\n super(\n \"Authorization failed (HTTP 403). Token does not have access to this resource. \" +\n \"Check that your token has the required permissions.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth#permissions\",\n );\n this.name = \"AuthorizationError\";\n }\n}\n\nexport class NotFoundError extends EnkryptifyError {\n constructor(method: string, endpoint: string) {\n super(\n `Resource not found (HTTP 404) for ${method} ${endpoint}. ` +\n \"Workspace, project, or environment not found. Verify your configuration.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/troubleshooting#not-found\",\n );\n this.name = \"NotFoundError\";\n }\n}\n\nexport class RateLimitError extends EnkryptifyError {\n public readonly retryAfter: number | null;\n\n constructor(retryAfter?: string | null) {\n const parsed = retryAfter ? parseInt(retryAfter, 10) : null;\n const retrySeconds = parsed !== null && !Number.isNaN(parsed) ? parsed : null;\n super(\n `Rate limited (HTTP 429). ` +\n `${retrySeconds ? `Retry after ${retrySeconds} seconds.` : \"Please retry later.\"}\\n` +\n \"Docs: https://docs.enkryptify.com/sdk/troubleshooting#rate-limiting\",\n );\n this.name = \"RateLimitError\";\n this.retryAfter = retrySeconds;\n }\n}\n\nexport class ApiError extends EnkryptifyError {\n public readonly status: number;\n\n constructor(status: number, statusText: string, method: string, endpoint: string) {\n super(\n `API request failed (HTTP ${status}) for ${method} ${endpoint}. ` +\n `${statusText ? statusText + \". \" : \"\"}` +\n `This may be a temporary server issue — retry in a few moments.\\n` +\n `Docs: https://docs.enkryptify.com/sdk/troubleshooting#api-errors`,\n );\n this.name = \"ApiError\";\n this.status = status;\n }\n}\n","import { EnkryptifyError } from \"@/errors\";\n\nconst store = new WeakMap<object, string>();\n\nexport function storeToken(provider: object, token: string): void {\n store.set(provider, token);\n}\n\nexport function retrieveToken(provider: object): string {\n const token = store.get(provider);\n if (!token) {\n throw new EnkryptifyError(\n \"Invalid or destroyed auth provider. Create a new one via Enkryptify.fromEnv().\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth\",\n );\n }\n return token;\n}\n","import type { EnkryptifyAuthProvider } from \"@/types\";\nimport { EnkryptifyError } from \"@/errors\";\nimport { storeToken } from \"@/internal/token-store\";\n\nexport class EnvAuthProvider implements EnkryptifyAuthProvider {\n readonly _brand = \"EnkryptifyAuthProvider\" as const;\n\n constructor() {\n const token = process.env.ENKRYPTIFY_TOKEN;\n if (!token) {\n throw new EnkryptifyError(\n \"ENKRYPTIFY_TOKEN environment variable is not set. Set it before initializing the SDK:\\n\" +\n ' export ENKRYPTIFY_TOKEN=\"ek_...\"\\n' +\n \"Docs: https://docs.enkryptify.com/sdk/auth#environment-variables\",\n );\n }\n storeToken(this, token);\n }\n}\n\nexport class TokenAuthProvider implements EnkryptifyAuthProvider {\n readonly _brand = \"EnkryptifyAuthProvider\" as const;\n\n constructor(token: string) {\n storeToken(this, token);\n }\n}\n","import type { EnkryptifyAuthProvider, Secret } from \"@/types\";\nimport { AuthenticationError, AuthorizationError, NotFoundError, RateLimitError, ApiError } from \"@/errors\";\nimport { retrieveToken } from \"@/internal/token-store\";\n\nexport class EnkryptifyApi {\n #baseUrl: string;\n #auth: EnkryptifyAuthProvider;\n\n constructor(baseUrl: string, auth: EnkryptifyAuthProvider) {\n this.#baseUrl = baseUrl;\n this.#auth = auth;\n }\n\n async fetchSecret(workspace: string, project: string, secretName: string, environmentId: string): Promise<Secret> {\n const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret/${encodeURIComponent(secretName)}`;\n const params = new URLSearchParams({ environmentId, resolve: \"true\" });\n return this.#request(\"GET\", `${path}?${params.toString()}`);\n }\n\n async fetchAllSecrets(workspace: string, project: string, environmentId: string): Promise<Secret[]> {\n const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret`;\n const params = new URLSearchParams({ environmentId, resolve: \"true\" });\n return this.#request(\"GET\", `${path}?${params.toString()}`);\n }\n\n async #request<T>(method: string, endpoint: string): Promise<T> {\n const token = retrieveToken(this.#auth);\n const url = `${this.#baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (response.status === 401) {\n throw new AuthenticationError();\n }\n\n if (response.status === 403) {\n throw new AuthorizationError();\n }\n\n if (response.status === 404) {\n throw new NotFoundError(method, endpoint);\n }\n\n if (response.status === 429) {\n throw new RateLimitError(response.headers.get(\"Retry-After\"));\n }\n\n if (!response.ok) {\n throw new ApiError(response.status, response.statusText, method, endpoint);\n }\n\n return response.json() as Promise<T>;\n }\n}\n","interface CacheEntry {\n value: string;\n expiresAt: number | null;\n}\n\nexport class SecretCache {\n #store = new Map<string, CacheEntry>();\n #ttl: number;\n\n constructor(ttl: number) {\n this.#ttl = ttl;\n }\n\n get(key: string): string | undefined {\n const entry = this.#store.get(key);\n if (!entry) return undefined;\n\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.#store.delete(key);\n return undefined;\n }\n\n return entry.value;\n }\n\n set(key: string, value: string): void {\n this.#store.set(key, {\n value,\n expiresAt: this.#ttl === -1 ? null : Date.now() + this.#ttl,\n });\n }\n\n has(key: string): boolean {\n return this.get(key) !== undefined;\n }\n\n clear(): void {\n this.#store.clear();\n this.#store = new Map();\n }\n\n get size(): number {\n return this.#store.size;\n }\n}\n","type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/* eslint-disable no-console */\nexport class Logger {\n #level: number;\n\n constructor(level: LogLevel = \"info\") {\n this.#level = LEVELS[level];\n }\n\n debug(message: string): void {\n if (this.#level <= LEVELS.debug) {\n console.debug(`[Enkryptify] ${message}`);\n }\n }\n\n info(message: string): void {\n if (this.#level <= LEVELS.info) {\n console.info(`[Enkryptify] ${message}`);\n }\n }\n\n warn(message: string): void {\n if (this.#level <= LEVELS.warn) {\n console.warn(`[Enkryptify] ${message}`);\n }\n }\n\n error(message: string): void {\n if (this.#level <= LEVELS.error) {\n console.error(`[Enkryptify] ${message}`);\n }\n }\n}\n","import type { EnkryptifyAuthProvider, TokenExchangeResponse } from \"@/types\";\nimport type { Logger } from \"@/logger\";\nimport { storeToken } from \"@/internal/token-store\";\n\nexport class TokenExchangeManager {\n #baseUrl: string;\n #staticToken: string;\n #auth: EnkryptifyAuthProvider;\n #logger: Logger;\n #jwt: string | null = null;\n #refreshTimer: ReturnType<typeof setTimeout> | null = null;\n #exchangePromise: Promise<void> | null = null;\n\n constructor(baseUrl: string, staticToken: string, auth: EnkryptifyAuthProvider, logger: Logger) {\n this.#baseUrl = baseUrl;\n this.#staticToken = staticToken;\n this.#auth = auth;\n this.#logger = logger;\n }\n\n async ensureToken(): Promise<void> {\n if (this.#jwt) return;\n\n // Deduplicate concurrent exchange calls\n if (this.#exchangePromise) {\n return this.#exchangePromise;\n }\n\n this.#exchangePromise = this.#exchange();\n try {\n await this.#exchangePromise;\n } finally {\n this.#exchangePromise = null;\n }\n }\n\n async #exchange(): Promise<void> {\n try {\n const response = await fetch(`${this.#baseUrl}/v1/auth/exchange`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.#staticToken}`,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n throw new Error(`Token exchange failed with HTTP ${response.status}`);\n }\n\n const data = (await response.json()) as TokenExchangeResponse;\n this.#jwt = data.accessToken;\n storeToken(this.#auth, this.#jwt);\n this.#logger.debug(\"Token exchanged for short-lived JWT\");\n\n // Refresh 60 seconds before expiry\n const refreshMs = (data.expiresIn - 60) * 1000;\n this.#scheduleRefresh(refreshMs);\n } catch (error) {\n // Fallback to static token\n this.#jwt = null;\n storeToken(this.#auth, this.#staticToken);\n this.#logger.warn(\n `Token exchange failed, falling back to static token: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n #scheduleRefresh(ms: number): void {\n if (this.#refreshTimer) {\n clearTimeout(this.#refreshTimer);\n }\n this.#refreshTimer = setTimeout(() => {\n this.#jwt = null;\n this.#exchange();\n }, ms);\n // Don't keep the process alive just for token refresh\n this.#refreshTimer.unref?.();\n }\n\n destroy(): void {\n if (this.#refreshTimer) {\n clearTimeout(this.#refreshTimer);\n this.#refreshTimer = null;\n }\n this.#jwt = null;\n }\n}\n","import type { EnkryptifyAuthProvider, EnkryptifyConfig, IEnkryptify, Secret } from \"@/types\";\nimport { EnkryptifyError, SecretNotFoundError, NotFoundError } from \"@/errors\";\nimport { EnvAuthProvider, TokenAuthProvider } from \"@/auth\";\nimport { EnkryptifyApi } from \"@/api\";\nimport { SecretCache } from \"@/cache\";\nimport { Logger } from \"@/logger\";\nimport { retrieveToken } from \"@/internal/token-store\";\nimport { TokenExchangeManager } from \"@/token-exchange\";\n\nexport class Enkryptify implements IEnkryptify {\n #api: EnkryptifyApi;\n #cache: SecretCache | null;\n #logger: Logger;\n #workspace: string;\n #project: string;\n #environment: string;\n #strict: boolean;\n #usePersonalValues: boolean;\n #cacheEnabled: boolean;\n #eagerCache: boolean;\n #destroyed = false;\n #eagerLoaded = false;\n #tokenExchange: TokenExchangeManager | null = null;\n\n constructor(config: EnkryptifyConfig) {\n if (!config.workspace) {\n throw new EnkryptifyError(\n 'Missing required config field \"workspace\". Provide a workspace slug or ID.\\n' +\n \"Docs: https://docs.enkryptify.com/sdk/configuration\",\n );\n }\n if (!config.project) {\n throw new EnkryptifyError(\n 'Missing required config field \"project\". Provide a project slug or ID.\\n' +\n \"Docs: https://docs.enkryptify.com/sdk/configuration\",\n );\n }\n if (!config.environment) {\n throw new EnkryptifyError(\n 'Missing required config field \"environment\". Provide an environment ID.\\n' +\n \"Docs: https://docs.enkryptify.com/sdk/configuration\",\n );\n }\n\n // Resolve auth provider: token option → auth option → env var\n let auth: EnkryptifyAuthProvider;\n if (config.token) {\n Enkryptify.#validateTokenFormat(config.token);\n auth = new TokenAuthProvider(config.token);\n } else if (config.auth) {\n if (config.auth._brand !== \"EnkryptifyAuthProvider\") {\n throw new EnkryptifyError(\n \"Invalid auth provider. Use Enkryptify.fromEnv() or pass a token option.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth\",\n );\n }\n auth = config.auth;\n } else {\n const envToken = process.env.ENKRYPTIFY_TOKEN;\n if (!envToken) {\n throw new EnkryptifyError(\n \"No token provided. Set ENKRYPTIFY_TOKEN or pass token in options.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth\",\n );\n }\n Enkryptify.#validateTokenFormat(envToken);\n auth = new TokenAuthProvider(envToken);\n }\n\n // Validate that the auth provider has a token in the store\n retrieveToken(auth);\n\n this.#workspace = config.workspace;\n this.#project = config.project;\n this.#environment = config.environment;\n this.#strict = config.options?.strict ?? true;\n this.#usePersonalValues = config.options?.usePersonalValues ?? true;\n\n this.#cacheEnabled = config.cache?.enabled ?? true;\n this.#eagerCache = config.cache?.eager ?? true;\n const cacheTtl = config.cache?.ttl ?? -1;\n\n this.#logger = new Logger(config.logger?.level ?? \"info\");\n this.#cache = this.#cacheEnabled ? new SecretCache(cacheTtl) : null;\n\n const baseUrl = config.baseUrl ?? \"https://api.enkryptify.com\";\n this.#api = new EnkryptifyApi(baseUrl, auth);\n\n if (config.useTokenExchange) {\n const staticToken = retrieveToken(auth);\n this.#tokenExchange = new TokenExchangeManager(baseUrl, staticToken, auth, this.#logger);\n }\n\n this.#logger.info(\n `Initialized for workspace \"${this.#workspace}\", project \"${this.#project}\", environment \"${this.#environment}\"`,\n );\n }\n\n static fromEnv(): EnkryptifyAuthProvider {\n return new EnvAuthProvider();\n }\n\n static #validateTokenFormat(token: string): void {\n if (!token) {\n throw new EnkryptifyError(\"Token must be a non-empty string.\\nDocs: https://docs.enkryptify.com/sdk/auth\");\n }\n\n // Accept ek_live_ API tokens\n if (token.startsWith(\"ek_live_\")) return;\n\n // Accept JWTs (three base64 segments separated by dots)\n const dotCount = token.split(\".\").length - 1;\n if (dotCount === 2) return;\n\n throw new EnkryptifyError(\n \"Invalid token format. Expected an ek_live_ token or JWT.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/auth#token-format\",\n );\n }\n\n async get(key: string, options?: { cache?: boolean }): Promise<string> {\n this.#guardDestroyed();\n\n const useCache = this.#cacheEnabled && options?.cache !== false;\n\n if (useCache && this.#cache) {\n const cached = this.#cache.get(key);\n if (cached !== undefined) {\n this.#logger.debug(`Cache hit for secret \"${key}\"`);\n return cached;\n }\n this.#logger.debug(`Cache miss for secret \"${key}\", fetching from API`);\n }\n\n await this.#tokenExchange?.ensureToken();\n\n if (useCache && this.#eagerCache && !this.#eagerLoaded) {\n return this.#fetchAndCacheAll(key);\n }\n\n return this.#fetchAndCacheSingle(key);\n }\n\n getFromCache(key: string): string {\n this.#guardDestroyed();\n\n if (!this.#cacheEnabled || !this.#cache) {\n throw new EnkryptifyError(\n \"Cache is disabled. Enable caching in the config or use get() to fetch from the API.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/configuration#caching\",\n );\n }\n\n const value = this.#cache.get(key);\n if (value === undefined) {\n throw new SecretNotFoundError(key, this.#workspace, this.#environment);\n }\n\n return value;\n }\n\n async preload(): Promise<void> {\n this.#guardDestroyed();\n\n if (!this.#cacheEnabled || !this.#cache) {\n throw new EnkryptifyError(\n \"Cannot preload: caching is disabled. Enable caching in the config.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/configuration#caching\",\n );\n }\n\n await this.#tokenExchange?.ensureToken();\n\n const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);\n\n let count = 0;\n for (const secret of secrets) {\n const value = this.#resolveValue(secret);\n if (value !== undefined) {\n this.#cache.set(secret.name, value);\n count++;\n }\n }\n\n this.#eagerLoaded = true;\n this.#logger.info(`Preloaded ${count} secrets into cache`);\n }\n\n destroy(): void {\n if (this.#destroyed) return;\n this.#tokenExchange?.destroy();\n this.#cache?.clear();\n this.#destroyed = true;\n this.#logger.info(\"Client destroyed, all cached secrets cleared\");\n }\n\n #guardDestroyed(): void {\n if (this.#destroyed) {\n throw new EnkryptifyError(\n \"This Enkryptify client has been destroyed. Create a new instance to continue.\\n\" +\n \"Docs: https://docs.enkryptify.com/sdk/lifecycle\",\n );\n }\n }\n\n async #fetchAndCacheAll(key: string): Promise<string> {\n this.#logger.debug(\n `Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret`,\n );\n const start = Date.now();\n const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);\n this.#logger.debug(`API responded with ${secrets.length} secret(s) in ${Date.now() - start}ms`);\n\n let found: string | undefined;\n\n for (const secret of secrets) {\n const value = this.#resolveValue(secret);\n if (value !== undefined && this.#cache) {\n this.#cache.set(secret.name, value);\n this.#logger.debug(\n `Cached secret \"${secret.name}\" (${this.#cache ? \"TTL: cache configured\" : \"no expiry\"})`,\n );\n }\n if (secret.name === key) {\n found = value;\n }\n }\n\n this.#eagerLoaded = true;\n\n if (found !== undefined) {\n return found;\n }\n\n return this.#handleNotFound(key);\n }\n\n async #fetchAndCacheSingle(key: string): Promise<string> {\n this.#logger.debug(\n `Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret/${key}`,\n );\n let secret: Secret;\n try {\n const start = Date.now();\n secret = await this.#api.fetchSecret(this.#workspace, this.#project, key, this.#environment);\n this.#logger.debug(`API responded with 1 secret(s) in ${Date.now() - start}ms`);\n } catch (error) {\n // NotFoundError is imported at the module level via @/errors\n if (error instanceof NotFoundError) {\n return this.#handleNotFound(key);\n }\n throw error;\n }\n\n const value = this.#resolveValue(secret);\n if (value === undefined) {\n return this.#handleNotFound(key);\n }\n\n if (this.#cacheEnabled && this.#cache) {\n this.#cache.set(key, value);\n }\n\n return value;\n }\n\n #handleNotFound(key: string): string {\n if (this.#strict) {\n throw new SecretNotFoundError(key, this.#workspace, this.#environment);\n }\n this.#logger.warn(`Secret \"${key}\" not found (strict mode disabled, returning empty string)`);\n return \"\";\n }\n\n #resolveValue(secret: Secret): string | undefined {\n const envValues = secret.values.filter((v) => v.environmentId === this.#environment);\n\n if (this.#usePersonalValues) {\n const personal = envValues.find((v) => v.isPersonal);\n if (personal) return personal.value;\n\n const shared = envValues.find((v) => !v.isPersonal);\n if (shared) {\n this.#logger.warn(`No personal value for \"${secret.name}\", falling back to shared value`);\n return shared.value;\n }\n } else {\n const shared = envValues.find((v) => !v.isPersonal);\n if (shared) return shared.value;\n }\n\n return undefined;\n }\n}\n"]}
|