@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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Enkryptify
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # @enkryptify/sdk
2
+
3
+ [![CI](https://github.com/enkryptify/sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/enkryptify/sdk/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@enkryptify/sdk)](https://www.npmjs.com/package/@enkryptify/sdk)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Official TypeScript SDK for [Enkryptify](https://enkryptify.com) — fetch and manage secrets from the Enkryptify API.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pnpm add @enkryptify/sdk
13
+ ```
14
+
15
+ ```bash
16
+ npm install @enkryptify/sdk
17
+ ```
18
+
19
+ ```bash
20
+ yarn add @enkryptify/sdk
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import Enkryptify from "@enkryptify/sdk";
27
+
28
+ const client = new Enkryptify({
29
+ apiKey: "your-api-key",
30
+ workspaceId: "your-workspace-id",
31
+ projectId: "your-project-id",
32
+ environment: "production",
33
+ });
34
+
35
+ const dbUrl = await client.get("DATABASE_URL");
36
+ console.log(dbUrl);
37
+ ```
38
+
39
+ ## API Reference
40
+
41
+ ### `new Enkryptify(config)`
42
+
43
+ Creates a new Enkryptify client.
44
+
45
+ | Parameter | Type | Description |
46
+ | ------------- | -------- | ------------------------------------- |
47
+ | `apiKey` | `string` | Your Enkryptify API key |
48
+ | `workspaceId` | `string` | The workspace ID |
49
+ | `projectId` | `string` | The project ID |
50
+ | `environment` | `string` | The environment (e.g. `"production"`) |
51
+
52
+ ### `client.get(key): Promise<string>`
53
+
54
+ Fetches a secret by key. Throws `EnkryptifyError` if the secret is not found.
55
+
56
+ ### `EnkryptifyError`
57
+
58
+ Custom error class for all SDK errors.
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ # Install dependencies
64
+ pnpm install
65
+
66
+ # Build
67
+ pnpm build
68
+
69
+ # Run tests
70
+ pnpm test
71
+
72
+ # Run tests in watch mode
73
+ pnpm test:watch
74
+
75
+ # Lint
76
+ pnpm lint
77
+
78
+ # Format
79
+ pnpm format
80
+
81
+ # Typecheck
82
+ pnpm check
83
+ ```
84
+
85
+ ## Contributing
86
+
87
+ Please read our [Contributing Guide](CONTRIBUTING.md) before submitting a pull request.
88
+
89
+ ## License
90
+
91
+ [MIT](LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,529 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ // src/errors.ts
6
+ var EnkryptifyError = class extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "EnkryptifyError";
10
+ }
11
+ };
12
+ var SecretNotFoundError = class extends EnkryptifyError {
13
+ constructor(key, workspace, environment) {
14
+ super(
15
+ `Secret "${key}" not found in workspace "${workspace}" (environment: "${environment}"). Verify the secret exists in your Enkryptify dashboard.
16
+ Docs: https://docs.enkryptify.com/sdk/troubleshooting#secret-not-found`
17
+ );
18
+ this.name = "SecretNotFoundError";
19
+ }
20
+ };
21
+ var AuthenticationError = class extends EnkryptifyError {
22
+ constructor() {
23
+ super(
24
+ "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"
25
+ );
26
+ this.name = "AuthenticationError";
27
+ }
28
+ };
29
+ var AuthorizationError = class extends EnkryptifyError {
30
+ constructor() {
31
+ super(
32
+ "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"
33
+ );
34
+ this.name = "AuthorizationError";
35
+ }
36
+ };
37
+ var NotFoundError = class extends EnkryptifyError {
38
+ constructor(method, endpoint) {
39
+ super(
40
+ `Resource not found (HTTP 404) for ${method} ${endpoint}. Workspace, project, or environment not found. Verify your configuration.
41
+ Docs: https://docs.enkryptify.com/sdk/troubleshooting#not-found`
42
+ );
43
+ this.name = "NotFoundError";
44
+ }
45
+ };
46
+ var RateLimitError = class extends EnkryptifyError {
47
+ retryAfter;
48
+ constructor(retryAfter) {
49
+ const parsed = retryAfter ? parseInt(retryAfter, 10) : null;
50
+ const retrySeconds = parsed !== null && !Number.isNaN(parsed) ? parsed : null;
51
+ super(
52
+ `Rate limited (HTTP 429). ${retrySeconds ? `Retry after ${retrySeconds} seconds.` : "Please retry later."}
53
+ Docs: https://docs.enkryptify.com/sdk/troubleshooting#rate-limiting`
54
+ );
55
+ this.name = "RateLimitError";
56
+ this.retryAfter = retrySeconds;
57
+ }
58
+ };
59
+ var ApiError = class extends EnkryptifyError {
60
+ status;
61
+ constructor(status, statusText, method, endpoint) {
62
+ super(
63
+ `API request failed (HTTP ${status}) for ${method} ${endpoint}. ${statusText ? statusText + ". " : ""}This may be a temporary server issue \u2014 retry in a few moments.
64
+ Docs: https://docs.enkryptify.com/sdk/troubleshooting#api-errors`
65
+ );
66
+ this.name = "ApiError";
67
+ this.status = status;
68
+ }
69
+ };
70
+
71
+ // src/internal/token-store.ts
72
+ var store = /* @__PURE__ */ new WeakMap();
73
+ function storeToken(provider, token) {
74
+ store.set(provider, token);
75
+ }
76
+ function retrieveToken(provider) {
77
+ const token = store.get(provider);
78
+ if (!token) {
79
+ throw new EnkryptifyError(
80
+ "Invalid or destroyed auth provider. Create a new one via Enkryptify.fromEnv().\nDocs: https://docs.enkryptify.com/sdk/auth"
81
+ );
82
+ }
83
+ return token;
84
+ }
85
+
86
+ // src/auth.ts
87
+ var EnvAuthProvider = class {
88
+ _brand = "EnkryptifyAuthProvider";
89
+ constructor() {
90
+ const token = process.env.ENKRYPTIFY_TOKEN;
91
+ if (!token) {
92
+ throw new EnkryptifyError(
93
+ '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'
94
+ );
95
+ }
96
+ storeToken(this, token);
97
+ }
98
+ };
99
+ var TokenAuthProvider = class {
100
+ _brand = "EnkryptifyAuthProvider";
101
+ constructor(token) {
102
+ storeToken(this, token);
103
+ }
104
+ };
105
+
106
+ // src/api.ts
107
+ var EnkryptifyApi = class {
108
+ #baseUrl;
109
+ #auth;
110
+ constructor(baseUrl, auth) {
111
+ this.#baseUrl = baseUrl;
112
+ this.#auth = auth;
113
+ }
114
+ async fetchSecret(workspace, project, secretName, environmentId) {
115
+ const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret/${encodeURIComponent(secretName)}`;
116
+ const params = new URLSearchParams({ environmentId, resolve: "true" });
117
+ return this.#request("GET", `${path}?${params.toString()}`);
118
+ }
119
+ async fetchAllSecrets(workspace, project, environmentId) {
120
+ const path = `/v1/workspace/${encodeURIComponent(workspace)}/project/${encodeURIComponent(project)}/secret`;
121
+ const params = new URLSearchParams({ environmentId, resolve: "true" });
122
+ return this.#request("GET", `${path}?${params.toString()}`);
123
+ }
124
+ async #request(method, endpoint) {
125
+ const token = retrieveToken(this.#auth);
126
+ const url = `${this.#baseUrl}${endpoint}`;
127
+ const response = await fetch(url, {
128
+ method,
129
+ headers: {
130
+ Authorization: `Bearer ${token}`,
131
+ "Content-Type": "application/json"
132
+ }
133
+ });
134
+ if (response.status === 401) {
135
+ throw new AuthenticationError();
136
+ }
137
+ if (response.status === 403) {
138
+ throw new AuthorizationError();
139
+ }
140
+ if (response.status === 404) {
141
+ throw new NotFoundError(method, endpoint);
142
+ }
143
+ if (response.status === 429) {
144
+ throw new RateLimitError(response.headers.get("Retry-After"));
145
+ }
146
+ if (!response.ok) {
147
+ throw new ApiError(response.status, response.statusText, method, endpoint);
148
+ }
149
+ return response.json();
150
+ }
151
+ };
152
+
153
+ // src/cache.ts
154
+ var SecretCache = class {
155
+ #store = /* @__PURE__ */ new Map();
156
+ #ttl;
157
+ constructor(ttl) {
158
+ this.#ttl = ttl;
159
+ }
160
+ get(key) {
161
+ const entry = this.#store.get(key);
162
+ if (!entry) return void 0;
163
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
164
+ this.#store.delete(key);
165
+ return void 0;
166
+ }
167
+ return entry.value;
168
+ }
169
+ set(key, value) {
170
+ this.#store.set(key, {
171
+ value,
172
+ expiresAt: this.#ttl === -1 ? null : Date.now() + this.#ttl
173
+ });
174
+ }
175
+ has(key) {
176
+ return this.get(key) !== void 0;
177
+ }
178
+ clear() {
179
+ this.#store.clear();
180
+ this.#store = /* @__PURE__ */ new Map();
181
+ }
182
+ get size() {
183
+ return this.#store.size;
184
+ }
185
+ };
186
+
187
+ // src/logger.ts
188
+ var LEVELS = {
189
+ debug: 0,
190
+ info: 1,
191
+ warn: 2,
192
+ error: 3
193
+ };
194
+ var Logger = class {
195
+ #level;
196
+ constructor(level = "info") {
197
+ this.#level = LEVELS[level];
198
+ }
199
+ debug(message) {
200
+ if (this.#level <= LEVELS.debug) {
201
+ console.debug(`[Enkryptify] ${message}`);
202
+ }
203
+ }
204
+ info(message) {
205
+ if (this.#level <= LEVELS.info) {
206
+ console.info(`[Enkryptify] ${message}`);
207
+ }
208
+ }
209
+ warn(message) {
210
+ if (this.#level <= LEVELS.warn) {
211
+ console.warn(`[Enkryptify] ${message}`);
212
+ }
213
+ }
214
+ error(message) {
215
+ if (this.#level <= LEVELS.error) {
216
+ console.error(`[Enkryptify] ${message}`);
217
+ }
218
+ }
219
+ };
220
+
221
+ // src/token-exchange.ts
222
+ var TokenExchangeManager = class {
223
+ #baseUrl;
224
+ #staticToken;
225
+ #auth;
226
+ #logger;
227
+ #jwt = null;
228
+ #refreshTimer = null;
229
+ #exchangePromise = null;
230
+ constructor(baseUrl, staticToken, auth, logger) {
231
+ this.#baseUrl = baseUrl;
232
+ this.#staticToken = staticToken;
233
+ this.#auth = auth;
234
+ this.#logger = logger;
235
+ }
236
+ async ensureToken() {
237
+ if (this.#jwt) return;
238
+ if (this.#exchangePromise) {
239
+ return this.#exchangePromise;
240
+ }
241
+ this.#exchangePromise = this.#exchange();
242
+ try {
243
+ await this.#exchangePromise;
244
+ } finally {
245
+ this.#exchangePromise = null;
246
+ }
247
+ }
248
+ async #exchange() {
249
+ try {
250
+ const response = await fetch(`${this.#baseUrl}/v1/auth/exchange`, {
251
+ method: "POST",
252
+ headers: {
253
+ Authorization: `Bearer ${this.#staticToken}`,
254
+ "Content-Type": "application/json"
255
+ }
256
+ });
257
+ if (!response.ok) {
258
+ throw new Error(`Token exchange failed with HTTP ${response.status}`);
259
+ }
260
+ const data = await response.json();
261
+ this.#jwt = data.accessToken;
262
+ storeToken(this.#auth, this.#jwt);
263
+ this.#logger.debug("Token exchanged for short-lived JWT");
264
+ const refreshMs = (data.expiresIn - 60) * 1e3;
265
+ this.#scheduleRefresh(refreshMs);
266
+ } catch (error) {
267
+ this.#jwt = null;
268
+ storeToken(this.#auth, this.#staticToken);
269
+ this.#logger.warn(
270
+ `Token exchange failed, falling back to static token: ${error instanceof Error ? error.message : String(error)}`
271
+ );
272
+ }
273
+ }
274
+ #scheduleRefresh(ms) {
275
+ if (this.#refreshTimer) {
276
+ clearTimeout(this.#refreshTimer);
277
+ }
278
+ this.#refreshTimer = setTimeout(() => {
279
+ this.#jwt = null;
280
+ this.#exchange();
281
+ }, ms);
282
+ this.#refreshTimer.unref?.();
283
+ }
284
+ destroy() {
285
+ if (this.#refreshTimer) {
286
+ clearTimeout(this.#refreshTimer);
287
+ this.#refreshTimer = null;
288
+ }
289
+ this.#jwt = null;
290
+ }
291
+ };
292
+
293
+ // src/enkryptify.ts
294
+ var Enkryptify = class _Enkryptify {
295
+ #api;
296
+ #cache;
297
+ #logger;
298
+ #workspace;
299
+ #project;
300
+ #environment;
301
+ #strict;
302
+ #usePersonalValues;
303
+ #cacheEnabled;
304
+ #eagerCache;
305
+ #destroyed = false;
306
+ #eagerLoaded = false;
307
+ #tokenExchange = null;
308
+ constructor(config) {
309
+ if (!config.workspace) {
310
+ throw new EnkryptifyError(
311
+ 'Missing required config field "workspace". Provide a workspace slug or ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
312
+ );
313
+ }
314
+ if (!config.project) {
315
+ throw new EnkryptifyError(
316
+ 'Missing required config field "project". Provide a project slug or ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
317
+ );
318
+ }
319
+ if (!config.environment) {
320
+ throw new EnkryptifyError(
321
+ 'Missing required config field "environment". Provide an environment ID.\nDocs: https://docs.enkryptify.com/sdk/configuration'
322
+ );
323
+ }
324
+ let auth;
325
+ if (config.token) {
326
+ _Enkryptify.#validateTokenFormat(config.token);
327
+ auth = new TokenAuthProvider(config.token);
328
+ } else if (config.auth) {
329
+ if (config.auth._brand !== "EnkryptifyAuthProvider") {
330
+ throw new EnkryptifyError(
331
+ "Invalid auth provider. Use Enkryptify.fromEnv() or pass a token option.\nDocs: https://docs.enkryptify.com/sdk/auth"
332
+ );
333
+ }
334
+ auth = config.auth;
335
+ } else {
336
+ const envToken = process.env.ENKRYPTIFY_TOKEN;
337
+ if (!envToken) {
338
+ throw new EnkryptifyError(
339
+ "No token provided. Set ENKRYPTIFY_TOKEN or pass token in options.\nDocs: https://docs.enkryptify.com/sdk/auth"
340
+ );
341
+ }
342
+ _Enkryptify.#validateTokenFormat(envToken);
343
+ auth = new TokenAuthProvider(envToken);
344
+ }
345
+ retrieveToken(auth);
346
+ this.#workspace = config.workspace;
347
+ this.#project = config.project;
348
+ this.#environment = config.environment;
349
+ this.#strict = config.options?.strict ?? true;
350
+ this.#usePersonalValues = config.options?.usePersonalValues ?? true;
351
+ this.#cacheEnabled = config.cache?.enabled ?? true;
352
+ this.#eagerCache = config.cache?.eager ?? true;
353
+ const cacheTtl = config.cache?.ttl ?? -1;
354
+ this.#logger = new Logger(config.logger?.level ?? "info");
355
+ this.#cache = this.#cacheEnabled ? new SecretCache(cacheTtl) : null;
356
+ const baseUrl = config.baseUrl ?? "https://api.enkryptify.com";
357
+ this.#api = new EnkryptifyApi(baseUrl, auth);
358
+ if (config.useTokenExchange) {
359
+ const staticToken = retrieveToken(auth);
360
+ this.#tokenExchange = new TokenExchangeManager(baseUrl, staticToken, auth, this.#logger);
361
+ }
362
+ this.#logger.info(
363
+ `Initialized for workspace "${this.#workspace}", project "${this.#project}", environment "${this.#environment}"`
364
+ );
365
+ }
366
+ static fromEnv() {
367
+ return new EnvAuthProvider();
368
+ }
369
+ static #validateTokenFormat(token) {
370
+ if (!token) {
371
+ throw new EnkryptifyError("Token must be a non-empty string.\nDocs: https://docs.enkryptify.com/sdk/auth");
372
+ }
373
+ if (token.startsWith("ek_live_")) return;
374
+ const dotCount = token.split(".").length - 1;
375
+ if (dotCount === 2) return;
376
+ throw new EnkryptifyError(
377
+ "Invalid token format. Expected an ek_live_ token or JWT.\nDocs: https://docs.enkryptify.com/sdk/auth#token-format"
378
+ );
379
+ }
380
+ async get(key, options) {
381
+ this.#guardDestroyed();
382
+ const useCache = this.#cacheEnabled && options?.cache !== false;
383
+ if (useCache && this.#cache) {
384
+ const cached = this.#cache.get(key);
385
+ if (cached !== void 0) {
386
+ this.#logger.debug(`Cache hit for secret "${key}"`);
387
+ return cached;
388
+ }
389
+ this.#logger.debug(`Cache miss for secret "${key}", fetching from API`);
390
+ }
391
+ await this.#tokenExchange?.ensureToken();
392
+ if (useCache && this.#eagerCache && !this.#eagerLoaded) {
393
+ return this.#fetchAndCacheAll(key);
394
+ }
395
+ return this.#fetchAndCacheSingle(key);
396
+ }
397
+ getFromCache(key) {
398
+ this.#guardDestroyed();
399
+ if (!this.#cacheEnabled || !this.#cache) {
400
+ throw new EnkryptifyError(
401
+ "Cache is disabled. Enable caching in the config or use get() to fetch from the API.\nDocs: https://docs.enkryptify.com/sdk/configuration#caching"
402
+ );
403
+ }
404
+ const value = this.#cache.get(key);
405
+ if (value === void 0) {
406
+ throw new SecretNotFoundError(key, this.#workspace, this.#environment);
407
+ }
408
+ return value;
409
+ }
410
+ async preload() {
411
+ this.#guardDestroyed();
412
+ if (!this.#cacheEnabled || !this.#cache) {
413
+ throw new EnkryptifyError(
414
+ "Cannot preload: caching is disabled. Enable caching in the config.\nDocs: https://docs.enkryptify.com/sdk/configuration#caching"
415
+ );
416
+ }
417
+ await this.#tokenExchange?.ensureToken();
418
+ const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);
419
+ let count = 0;
420
+ for (const secret of secrets) {
421
+ const value = this.#resolveValue(secret);
422
+ if (value !== void 0) {
423
+ this.#cache.set(secret.name, value);
424
+ count++;
425
+ }
426
+ }
427
+ this.#eagerLoaded = true;
428
+ this.#logger.info(`Preloaded ${count} secrets into cache`);
429
+ }
430
+ destroy() {
431
+ if (this.#destroyed) return;
432
+ this.#tokenExchange?.destroy();
433
+ this.#cache?.clear();
434
+ this.#destroyed = true;
435
+ this.#logger.info("Client destroyed, all cached secrets cleared");
436
+ }
437
+ #guardDestroyed() {
438
+ if (this.#destroyed) {
439
+ throw new EnkryptifyError(
440
+ "This Enkryptify client has been destroyed. Create a new instance to continue.\nDocs: https://docs.enkryptify.com/sdk/lifecycle"
441
+ );
442
+ }
443
+ }
444
+ async #fetchAndCacheAll(key) {
445
+ this.#logger.debug(
446
+ `Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret`
447
+ );
448
+ const start = Date.now();
449
+ const secrets = await this.#api.fetchAllSecrets(this.#workspace, this.#project, this.#environment);
450
+ this.#logger.debug(`API responded with ${secrets.length} secret(s) in ${Date.now() - start}ms`);
451
+ let found;
452
+ for (const secret of secrets) {
453
+ const value = this.#resolveValue(secret);
454
+ if (value !== void 0 && this.#cache) {
455
+ this.#cache.set(secret.name, value);
456
+ this.#logger.debug(
457
+ `Cached secret "${secret.name}" (${this.#cache ? "TTL: cache configured" : "no expiry"})`
458
+ );
459
+ }
460
+ if (secret.name === key) {
461
+ found = value;
462
+ }
463
+ }
464
+ this.#eagerLoaded = true;
465
+ if (found !== void 0) {
466
+ return found;
467
+ }
468
+ return this.#handleNotFound(key);
469
+ }
470
+ async #fetchAndCacheSingle(key) {
471
+ this.#logger.debug(
472
+ `Fetching secret(s) from API: GET /v1/workspace/${this.#workspace}/project/${this.#project}/secret/${key}`
473
+ );
474
+ let secret;
475
+ try {
476
+ const start = Date.now();
477
+ secret = await this.#api.fetchSecret(this.#workspace, this.#project, key, this.#environment);
478
+ this.#logger.debug(`API responded with 1 secret(s) in ${Date.now() - start}ms`);
479
+ } catch (error) {
480
+ if (error instanceof NotFoundError) {
481
+ return this.#handleNotFound(key);
482
+ }
483
+ throw error;
484
+ }
485
+ const value = this.#resolveValue(secret);
486
+ if (value === void 0) {
487
+ return this.#handleNotFound(key);
488
+ }
489
+ if (this.#cacheEnabled && this.#cache) {
490
+ this.#cache.set(key, value);
491
+ }
492
+ return value;
493
+ }
494
+ #handleNotFound(key) {
495
+ if (this.#strict) {
496
+ throw new SecretNotFoundError(key, this.#workspace, this.#environment);
497
+ }
498
+ this.#logger.warn(`Secret "${key}" not found (strict mode disabled, returning empty string)`);
499
+ return "";
500
+ }
501
+ #resolveValue(secret) {
502
+ const envValues = secret.values.filter((v) => v.environmentId === this.#environment);
503
+ if (this.#usePersonalValues) {
504
+ const personal = envValues.find((v) => v.isPersonal);
505
+ if (personal) return personal.value;
506
+ const shared = envValues.find((v) => !v.isPersonal);
507
+ if (shared) {
508
+ this.#logger.warn(`No personal value for "${secret.name}", falling back to shared value`);
509
+ return shared.value;
510
+ }
511
+ } else {
512
+ const shared = envValues.find((v) => !v.isPersonal);
513
+ if (shared) return shared.value;
514
+ }
515
+ return void 0;
516
+ }
517
+ };
518
+
519
+ exports.ApiError = ApiError;
520
+ exports.AuthenticationError = AuthenticationError;
521
+ exports.AuthorizationError = AuthorizationError;
522
+ exports.Enkryptify = Enkryptify;
523
+ exports.EnkryptifyError = EnkryptifyError;
524
+ exports.NotFoundError = NotFoundError;
525
+ exports.RateLimitError = RateLimitError;
526
+ exports.SecretNotFoundError = SecretNotFoundError;
527
+ exports.default = Enkryptify;
528
+ //# sourceMappingURL=index.cjs.map
529
+ //# sourceMappingURL=index.cjs.map