keyenv 1.1.0 → 1.1.1
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/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +40 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,8 @@ interface KeyEnvOptions {
|
|
|
6
6
|
timeout?: number;
|
|
7
7
|
/** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */
|
|
8
8
|
cacheTtl?: number;
|
|
9
|
+
/** Custom API base URL (default: https://api.keyenv.dev). Also configurable via KEYENV_API_URL env var. */
|
|
10
|
+
baseUrl?: string;
|
|
9
11
|
}
|
|
10
12
|
/** User or service token info */
|
|
11
13
|
interface User {
|
|
@@ -141,8 +143,10 @@ interface ProjectDefault {
|
|
|
141
143
|
*/
|
|
142
144
|
declare class KeyEnv {
|
|
143
145
|
private readonly token;
|
|
146
|
+
private readonly baseUrl;
|
|
144
147
|
private readonly timeout;
|
|
145
148
|
private readonly cacheTtl;
|
|
149
|
+
private readonly secretsCache;
|
|
146
150
|
constructor(options: KeyEnvOptions);
|
|
147
151
|
private request;
|
|
148
152
|
/** Get the current user or service token info */
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ interface KeyEnvOptions {
|
|
|
6
6
|
timeout?: number;
|
|
7
7
|
/** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */
|
|
8
8
|
cacheTtl?: number;
|
|
9
|
+
/** Custom API base URL (default: https://api.keyenv.dev). Also configurable via KEYENV_API_URL env var. */
|
|
10
|
+
baseUrl?: string;
|
|
9
11
|
}
|
|
10
12
|
/** User or service token info */
|
|
11
13
|
interface User {
|
|
@@ -141,8 +143,10 @@ interface ProjectDefault {
|
|
|
141
143
|
*/
|
|
142
144
|
declare class KeyEnv {
|
|
143
145
|
private readonly token;
|
|
146
|
+
private readonly baseUrl;
|
|
144
147
|
private readonly timeout;
|
|
145
148
|
private readonly cacheTtl;
|
|
149
|
+
private readonly secretsCache;
|
|
146
150
|
constructor(options: KeyEnvOptions);
|
|
147
151
|
private request;
|
|
148
152
|
/** Get the current user or service token info */
|
package/dist/index.js
CHANGED
|
@@ -40,26 +40,28 @@ var KeyEnvError = class extends Error {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
// src/client.ts
|
|
43
|
-
var
|
|
43
|
+
var DEFAULT_BASE_URL = "https://api.keyenv.dev";
|
|
44
44
|
var DEFAULT_TIMEOUT = 3e4;
|
|
45
|
-
var secretsCache = /* @__PURE__ */ new Map();
|
|
46
45
|
function getCacheKey(projectId, environment) {
|
|
47
46
|
return `${projectId}:${environment}`;
|
|
48
47
|
}
|
|
49
48
|
var KeyEnv = class {
|
|
50
49
|
token;
|
|
50
|
+
baseUrl;
|
|
51
51
|
timeout;
|
|
52
52
|
cacheTtl;
|
|
53
|
+
secretsCache = /* @__PURE__ */ new Map();
|
|
53
54
|
constructor(options) {
|
|
54
55
|
if (!options.token) {
|
|
55
56
|
throw new Error("KeyEnv token is required");
|
|
56
57
|
}
|
|
57
58
|
this.token = options.token;
|
|
59
|
+
this.baseUrl = (options.baseUrl ?? process.env.KEYENV_API_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
58
60
|
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
59
61
|
this.cacheTtl = options.cacheTtl ?? (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);
|
|
60
62
|
}
|
|
61
63
|
async request(method, path, body) {
|
|
62
|
-
const url = `${
|
|
64
|
+
const url = `${this.baseUrl}${path}`;
|
|
63
65
|
const controller = new AbortController();
|
|
64
66
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
65
67
|
try {
|
|
@@ -98,7 +100,8 @@ var KeyEnv = class {
|
|
|
98
100
|
}
|
|
99
101
|
/** Get the current user or service token info */
|
|
100
102
|
async getCurrentUser() {
|
|
101
|
-
|
|
103
|
+
const response = await this.request("GET", "/api/v1/users/me");
|
|
104
|
+
return response.data;
|
|
102
105
|
}
|
|
103
106
|
/** Validate the token and return user info */
|
|
104
107
|
async validateToken() {
|
|
@@ -107,15 +110,17 @@ var KeyEnv = class {
|
|
|
107
110
|
/** List all accessible projects */
|
|
108
111
|
async listProjects() {
|
|
109
112
|
const response = await this.request("GET", "/api/v1/projects");
|
|
110
|
-
return response.
|
|
113
|
+
return response.data;
|
|
111
114
|
}
|
|
112
115
|
/** Get a project by ID */
|
|
113
116
|
async getProject(projectId) {
|
|
114
|
-
|
|
117
|
+
const response = await this.request("GET", `/api/v1/projects/${projectId}`);
|
|
118
|
+
return response.data;
|
|
115
119
|
}
|
|
116
120
|
/** Create a new project */
|
|
117
121
|
async createProject(teamId, name) {
|
|
118
|
-
|
|
122
|
+
const response = await this.request("POST", "/api/v1/projects", { team_id: teamId, name });
|
|
123
|
+
return response.data;
|
|
119
124
|
}
|
|
120
125
|
/** Delete a project */
|
|
121
126
|
async deleteProject(projectId) {
|
|
@@ -127,15 +132,16 @@ var KeyEnv = class {
|
|
|
127
132
|
"GET",
|
|
128
133
|
`/api/v1/projects/${projectId}/environments`
|
|
129
134
|
);
|
|
130
|
-
return response.
|
|
135
|
+
return response.data;
|
|
131
136
|
}
|
|
132
137
|
/** Create a new environment */
|
|
133
138
|
async createEnvironment(projectId, name, inheritsFrom) {
|
|
134
|
-
|
|
139
|
+
const response = await this.request(
|
|
135
140
|
"POST",
|
|
136
141
|
`/api/v1/projects/${projectId}/environments`,
|
|
137
142
|
{ name, inherits_from: inheritsFrom }
|
|
138
143
|
);
|
|
144
|
+
return response.data;
|
|
139
145
|
}
|
|
140
146
|
/** Delete an environment */
|
|
141
147
|
async deleteEnvironment(projectId, environment) {
|
|
@@ -147,7 +153,7 @@ var KeyEnv = class {
|
|
|
147
153
|
"GET",
|
|
148
154
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets`
|
|
149
155
|
);
|
|
150
|
-
return response.
|
|
156
|
+
return response.data;
|
|
151
157
|
}
|
|
152
158
|
/**
|
|
153
159
|
* Export all secrets with their decrypted values.
|
|
@@ -163,22 +169,25 @@ var KeyEnv = class {
|
|
|
163
169
|
async exportSecrets(projectId, environment) {
|
|
164
170
|
const cacheKey = getCacheKey(projectId, environment);
|
|
165
171
|
if (this.cacheTtl > 0) {
|
|
166
|
-
const cached = secretsCache.get(cacheKey);
|
|
172
|
+
const cached = this.secretsCache.get(cacheKey);
|
|
167
173
|
if (cached && Date.now() < cached.expiresAt) {
|
|
168
174
|
return cached.secrets;
|
|
169
175
|
}
|
|
176
|
+
if (cached) {
|
|
177
|
+
this.secretsCache.delete(cacheKey);
|
|
178
|
+
}
|
|
170
179
|
}
|
|
171
180
|
const response = await this.request(
|
|
172
181
|
"GET",
|
|
173
182
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/export`
|
|
174
183
|
);
|
|
175
184
|
if (this.cacheTtl > 0) {
|
|
176
|
-
secretsCache.set(cacheKey, {
|
|
177
|
-
secrets: response.
|
|
185
|
+
this.secretsCache.set(cacheKey, {
|
|
186
|
+
secrets: response.data,
|
|
178
187
|
expiresAt: Date.now() + this.cacheTtl * 1e3
|
|
179
188
|
});
|
|
180
189
|
}
|
|
181
|
-
return response.
|
|
190
|
+
return response.data;
|
|
182
191
|
}
|
|
183
192
|
/**
|
|
184
193
|
* Export secrets as a key-value object
|
|
@@ -198,7 +207,7 @@ var KeyEnv = class {
|
|
|
198
207
|
"GET",
|
|
199
208
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`
|
|
200
209
|
);
|
|
201
|
-
return response.
|
|
210
|
+
return response.data;
|
|
202
211
|
}
|
|
203
212
|
/** Create a new secret */
|
|
204
213
|
async createSecret(projectId, environment, key, value, description) {
|
|
@@ -208,7 +217,7 @@ var KeyEnv = class {
|
|
|
208
217
|
{ key, value, description }
|
|
209
218
|
);
|
|
210
219
|
this.clearCache(projectId, environment);
|
|
211
|
-
return response.
|
|
220
|
+
return response.data;
|
|
212
221
|
}
|
|
213
222
|
/** Update a secret's value */
|
|
214
223
|
async updateSecret(projectId, environment, key, value, description) {
|
|
@@ -218,7 +227,7 @@ var KeyEnv = class {
|
|
|
218
227
|
{ value, description }
|
|
219
228
|
);
|
|
220
229
|
this.clearCache(projectId, environment);
|
|
221
|
-
return response.
|
|
230
|
+
return response.data;
|
|
222
231
|
}
|
|
223
232
|
/** Set a secret (create or update) */
|
|
224
233
|
async setSecret(projectId, environment, key, value, description) {
|
|
@@ -245,7 +254,7 @@ var KeyEnv = class {
|
|
|
245
254
|
"GET",
|
|
246
255
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`
|
|
247
256
|
);
|
|
248
|
-
return response.
|
|
257
|
+
return response.data;
|
|
249
258
|
}
|
|
250
259
|
/**
|
|
251
260
|
* Bulk import secrets
|
|
@@ -258,13 +267,13 @@ var KeyEnv = class {
|
|
|
258
267
|
* ```
|
|
259
268
|
*/
|
|
260
269
|
async bulkImport(projectId, environment, secrets, options = {}) {
|
|
261
|
-
const
|
|
270
|
+
const response = await this.request(
|
|
262
271
|
"POST",
|
|
263
272
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,
|
|
264
273
|
{ secrets, overwrite: options.overwrite ?? false }
|
|
265
274
|
);
|
|
266
275
|
this.clearCache(projectId, environment);
|
|
267
|
-
return
|
|
276
|
+
return response.data;
|
|
268
277
|
}
|
|
269
278
|
/**
|
|
270
279
|
* Load secrets into process.env
|
|
@@ -292,8 +301,8 @@ var KeyEnv = class {
|
|
|
292
301
|
];
|
|
293
302
|
for (const secret of secrets) {
|
|
294
303
|
const value = secret.value;
|
|
295
|
-
if (value.includes("\n") || value.includes('"') || value.includes("'") || value.includes(" ")) {
|
|
296
|
-
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
304
|
+
if (value.includes("\n") || value.includes('"') || value.includes("'") || value.includes(" ") || value.includes("$")) {
|
|
305
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
|
|
297
306
|
lines.push(`${secret.key}="${escaped}"`);
|
|
298
307
|
} else {
|
|
299
308
|
lines.push(`${secret.key}=${value}`);
|
|
@@ -308,15 +317,15 @@ var KeyEnv = class {
|
|
|
308
317
|
*/
|
|
309
318
|
clearCache(projectId, environment) {
|
|
310
319
|
if (projectId && environment) {
|
|
311
|
-
secretsCache.delete(getCacheKey(projectId, environment));
|
|
320
|
+
this.secretsCache.delete(getCacheKey(projectId, environment));
|
|
312
321
|
} else if (projectId) {
|
|
313
|
-
for (const key of secretsCache.keys()) {
|
|
322
|
+
for (const key of this.secretsCache.keys()) {
|
|
314
323
|
if (key.startsWith(`${projectId}:`)) {
|
|
315
|
-
secretsCache.delete(key);
|
|
324
|
+
this.secretsCache.delete(key);
|
|
316
325
|
}
|
|
317
326
|
}
|
|
318
327
|
} else {
|
|
319
|
-
secretsCache.clear();
|
|
328
|
+
this.secretsCache.clear();
|
|
320
329
|
}
|
|
321
330
|
}
|
|
322
331
|
// ============================================================================
|
|
@@ -340,7 +349,7 @@ var KeyEnv = class {
|
|
|
340
349
|
"GET",
|
|
341
350
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions`
|
|
342
351
|
);
|
|
343
|
-
return response.
|
|
352
|
+
return response.data;
|
|
344
353
|
}
|
|
345
354
|
/**
|
|
346
355
|
* Set a user's permission for an environment.
|
|
@@ -361,7 +370,7 @@ var KeyEnv = class {
|
|
|
361
370
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,
|
|
362
371
|
{ role }
|
|
363
372
|
);
|
|
364
|
-
return response.
|
|
373
|
+
return response.data;
|
|
365
374
|
}
|
|
366
375
|
/**
|
|
367
376
|
* Delete a user's permission for an environment.
|
|
@@ -399,7 +408,7 @@ var KeyEnv = class {
|
|
|
399
408
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions`,
|
|
400
409
|
{ permissions: permissions.map((p) => ({ user_id: p.userId, role: p.role })) }
|
|
401
410
|
);
|
|
402
|
-
return response.
|
|
411
|
+
return response.data;
|
|
403
412
|
}
|
|
404
413
|
/**
|
|
405
414
|
* Get the current user's permissions for all environments in a project.
|
|
@@ -433,7 +442,7 @@ var KeyEnv = class {
|
|
|
433
442
|
"GET",
|
|
434
443
|
`/api/v1/projects/${projectId}/permissions/defaults`
|
|
435
444
|
);
|
|
436
|
-
return response.
|
|
445
|
+
return response.data;
|
|
437
446
|
}
|
|
438
447
|
/**
|
|
439
448
|
* Set default permission settings for a project's environments.
|
|
@@ -454,7 +463,7 @@ var KeyEnv = class {
|
|
|
454
463
|
`/api/v1/projects/${projectId}/permissions/defaults`,
|
|
455
464
|
{ defaults: defaults.map((d) => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }
|
|
456
465
|
);
|
|
457
|
-
return response.
|
|
466
|
+
return response.data;
|
|
458
467
|
}
|
|
459
468
|
};
|
|
460
469
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts"],"sourcesContent":["export { KeyEnv } from './client.js';\nexport { KeyEnvError } from './types.js';\nexport type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\n","/** KeyEnv client configuration options */\nexport interface KeyEnvOptions {\n /** Service token for authentication */\n token: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */\n cacheTtl?: number;\n}\n\n/** User or service token info */\nexport interface User {\n id: string;\n email?: string;\n name?: string;\n clerk_id?: string;\n avatar_url?: string;\n /** Present for service tokens */\n auth_type?: 'service_token' | 'user';\n /** Team ID (for service tokens) */\n team_id?: string;\n /** Project IDs (for project-scoped service tokens) */\n project_ids?: string[];\n /** Token scopes (for service tokens) */\n scopes?: string[];\n created_at: string;\n}\n\n/** Project */\nexport interface Project {\n id: string;\n team_id: string;\n name: string;\n slug: string;\n description?: string;\n created_at: string;\n}\n\n/** Environment */\nexport interface Environment {\n id: string;\n project_id: string;\n name: string;\n inherits_from?: string;\n created_at: string;\n}\n\n/** Project with environments */\nexport interface ProjectWithEnvironments extends Project {\n environments: Environment[];\n}\n\n/** Secret (without value) */\nexport interface Secret {\n id: string;\n environment_id: string;\n key: string;\n type: string;\n description?: string;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\n/** Secret with decrypted value */\nexport interface SecretWithValue extends Secret {\n value: string;\n inherited_from?: string;\n}\n\n/** Secret history entry */\nexport interface SecretHistory {\n id: string;\n secret_id: string;\n value: string;\n version: number;\n changed_by?: string;\n changed_at: string;\n}\n\n/** Bulk import request item */\nexport interface BulkSecretItem {\n key: string;\n value: string;\n description?: string;\n}\n\n/** Bulk import result */\nexport interface BulkImportResult {\n created: number;\n updated: number;\n skipped: number;\n}\n\n/** API error response */\nexport interface ApiError {\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\n/** KeyEnv API error */\nexport class KeyEnvError extends Error {\n public readonly status: number;\n public readonly code?: string;\n public readonly details?: Record<string, unknown>;\n\n constructor(message: string, status: number, code?: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'KeyEnvError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/** Environment permission role */\nexport type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';\n\n/** Environment permission for a user */\nexport interface EnvironmentPermission {\n id: string;\n environment_id: string;\n user_id: string;\n role: EnvironmentRole;\n user_email?: string;\n user_name?: string;\n granted_by?: string;\n created_at: string;\n updated_at: string;\n}\n\n/** User's permission for an environment */\nexport interface MyPermission {\n environment_id: string;\n environment_name: string;\n role: EnvironmentRole;\n can_read: boolean;\n can_write: boolean;\n can_admin: boolean;\n}\n\n/** Response for getting user's permissions */\nexport interface MyPermissionsResponse {\n permissions: MyPermission[];\n is_team_admin: boolean;\n}\n\n/** Project default permission for an environment */\nexport interface ProjectDefault {\n id: string;\n project_id: string;\n environment_name: string;\n default_role: EnvironmentRole;\n created_at: string;\n}\n","import type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n ApiError,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\n/** Module-level cache for secrets (survives across warm serverless invocations) */\nconst secretsCache = new Map<string, { secrets: SecretWithValue[]; expiresAt: number }>();\n\nfunction getCacheKey(projectId: string, environment: string): string {\n return `${projectId}:${environment}`;\n}\n\n/**\n * KeyEnv API client for managing secrets\n *\n * @example\n * ```ts\n * import { KeyEnv } from 'keyenv';\n *\n * const client = new KeyEnv({ token: process.env.KEYENV_TOKEN });\n *\n * // Export all secrets for an environment\n * const secrets = await client.exportSecrets('project-id', 'production');\n * ```\n */\nexport class KeyEnv {\n private readonly token: string;\n private readonly timeout: number;\n private readonly cacheTtl: number;\n\n constructor(options: KeyEnvOptions) {\n if (!options.token) {\n throw new Error('KeyEnv token is required');\n }\n this.token = options.token;\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n // Cache TTL: constructor option → env var → 0 (disabled)\n this.cacheTtl = options.cacheTtl ??\n (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'keyenv-node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n let errorData: ApiError = { error: 'Unknown error' };\n try {\n errorData = await response.json() as ApiError;\n } catch {\n errorData = { error: response.statusText };\n }\n throw new KeyEnvError(errorData.error, response.status, errorData.code, errorData.details);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof KeyEnvError) throw error;\n if (error instanceof Error && error.name === 'AbortError') {\n throw new KeyEnvError('Request timeout', 408);\n }\n throw new KeyEnvError(error instanceof Error ? error.message : 'Network error', 0);\n }\n }\n\n /** Get the current user or service token info */\n async getCurrentUser(): Promise<User> {\n return this.request<User>('GET', '/api/v1/users/me');\n }\n\n /** Validate the token and return user info */\n async validateToken(): Promise<User> {\n return this.getCurrentUser();\n }\n\n /** List all accessible projects */\n async listProjects(): Promise<Project[]> {\n const response = await this.request<{ projects: Project[] }>('GET', '/api/v1/projects');\n return response.projects;\n }\n\n /** Get a project by ID */\n async getProject(projectId: string): Promise<ProjectWithEnvironments> {\n return this.request<ProjectWithEnvironments>('GET', `/api/v1/projects/${projectId}`);\n }\n\n /** Create a new project */\n async createProject(teamId: string, name: string): Promise<Project> {\n return this.request<Project>('POST', '/api/v1/projects', { team_id: teamId, name });\n }\n\n /** Delete a project */\n async deleteProject(projectId: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}`);\n }\n\n /** List environments in a project */\n async listEnvironments(projectId: string): Promise<Environment[]> {\n const response = await this.request<{ environments: Environment[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments`\n );\n return response.environments;\n }\n\n /** Create a new environment */\n async createEnvironment(projectId: string, name: string, inheritsFrom?: string): Promise<Environment> {\n return this.request<Environment>(\n 'POST', `/api/v1/projects/${projectId}/environments`,\n { name, inherits_from: inheritsFrom }\n );\n }\n\n /** Delete an environment */\n async deleteEnvironment(projectId: string, environment: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}/environments/${environment}`);\n }\n\n /** List secrets in an environment (keys and metadata only) */\n async listSecrets(projectId: string, environment: string): Promise<Secret[]> {\n const response = await this.request<{ secrets: Secret[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets`\n );\n return response.secrets;\n }\n\n /**\n * Export all secrets with their decrypted values.\n * Results are cached when cacheTtl > 0.\n * @example\n * ```ts\n * const secrets = await client.exportSecrets('project-id', 'production');\n * for (const secret of secrets) {\n * process.env[secret.key] = secret.value;\n * }\n * ```\n */\n async exportSecrets(projectId: string, environment: string): Promise<SecretWithValue[]> {\n const cacheKey = getCacheKey(projectId, environment);\n\n // Check cache if TTL > 0\n if (this.cacheTtl > 0) {\n const cached = secretsCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.secrets;\n }\n }\n\n const response = await this.request<{ secrets: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\n );\n\n // Store in cache if TTL > 0\n if (this.cacheTtl > 0) {\n secretsCache.set(cacheKey, {\n secrets: response.secrets,\n expiresAt: Date.now() + (this.cacheTtl * 1000),\n });\n }\n\n return response.secrets;\n }\n\n /**\n * Export secrets as a key-value object\n * @example\n * ```ts\n * const env = await client.exportSecretsAsObject('project-id', 'production');\n * // { DATABASE_URL: '...', API_KEY: '...' }\n * ```\n */\n async exportSecretsAsObject(projectId: string, environment: string): Promise<Record<string, string>> {\n const secrets = await this.exportSecrets(projectId, environment);\n return Object.fromEntries(secrets.map((s) => [s.key, s.value]));\n }\n\n /** Get a single secret with its value */\n async getSecret(projectId: string, environment: string, key: string): Promise<SecretWithValue> {\n const response = await this.request<{ secret: SecretWithValue }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n return response.secret;\n }\n\n /** Create a new secret */\n async createSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ secret: Secret }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets`,\n { key, value, description }\n );\n this.clearCache(projectId, environment);\n return response.secret;\n }\n\n /** Update a secret's value */\n async updateSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ secret: Secret }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,\n { value, description }\n );\n this.clearCache(projectId, environment);\n return response.secret;\n }\n\n /** Set a secret (create or update) */\n async setSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n try {\n return await this.updateSecret(projectId, environment, key, value, description);\n } catch (error) {\n if (error instanceof KeyEnvError && error.status === 404) {\n return this.createSecret(projectId, environment, key, value, description);\n }\n throw error;\n }\n }\n\n /** Delete a secret */\n async deleteSecret(projectId: string, environment: string, key: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n this.clearCache(projectId, environment);\n }\n\n /** Get secret version history */\n async getSecretHistory(projectId: string, environment: string, key: string): Promise<SecretHistory[]> {\n const response = await this.request<{ history: SecretHistory[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`\n );\n return response.history;\n }\n\n /**\n * Bulk import secrets\n * @example\n * ```ts\n * await client.bulkImport('project-id', 'development', [\n * { key: 'DATABASE_URL', value: 'postgres://...' },\n * { key: 'API_KEY', value: 'sk_...' },\n * ], { overwrite: true });\n * ```\n */\n async bulkImport(\n projectId: string, environment: string, secrets: BulkSecretItem[], options: { overwrite?: boolean } = {}\n ): Promise<BulkImportResult> {\n const result = await this.request<BulkImportResult>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\n this.clearCache(projectId, environment);\n return result;\n }\n\n /**\n * Load secrets into process.env\n * @example\n * ```ts\n * await client.loadEnv('project-id', 'production');\n * console.log(process.env.DATABASE_URL);\n * ```\n */\n async loadEnv(projectId: string, environment: string): Promise<number> {\n const secrets = await this.exportSecrets(projectId, environment);\n for (const secret of secrets) {\n process.env[secret.key] = secret.value;\n }\n return secrets.length;\n }\n\n /** Generate .env file content from secrets */\n async generateEnvFile(projectId: string, environment: string): Promise<string> {\n const secrets = await this.exportSecrets(projectId, environment);\n const lines = [\n '# Generated by KeyEnv',\n `# Environment: ${environment}`,\n `# Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n for (const secret of secrets) {\n const value = secret.value;\n if (value.includes('\\n') || value.includes('\"') || value.includes(\"'\") || value.includes(' ')) {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n lines.push(`${secret.key}=\"${escaped}\"`);\n } else {\n lines.push(`${secret.key}=${value}`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n }\n\n /**\n * Clear the secrets cache.\n * @param projectId - Clear cache for specific project (optional)\n * @param environment - Clear cache for specific environment (requires projectId)\n */\n clearCache(projectId?: string, environment?: string): void {\n if (projectId && environment) {\n secretsCache.delete(getCacheKey(projectId, environment));\n } else if (projectId) {\n // Clear all environments for this project\n for (const key of secretsCache.keys()) {\n if (key.startsWith(`${projectId}:`)) {\n secretsCache.delete(key);\n }\n }\n } else {\n secretsCache.clear();\n }\n }\n\n // ============================================================================\n // Environment Permission Management\n // ============================================================================\n\n /**\n * List all permissions for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @returns Array of environment permissions\n * @example\n * ```ts\n * const permissions = await client.listPermissions('project-id', 'production');\n * for (const perm of permissions) {\n * console.log(`${perm.user_email}: ${perm.role}`);\n * }\n * ```\n */\n async listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ permissions: EnvironmentPermission[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/permissions`\n );\n return response.permissions;\n }\n\n /**\n * Set a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to set permission for\n * @param role - The permission role ('none', 'read', 'write', or 'admin')\n * @returns The created or updated permission\n * @example\n * ```ts\n * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');\n * console.log(`Set ${permission.user_email} to ${permission.role}`);\n * ```\n */\n async setPermission(\n projectId: string, environment: string, userId: string, role: EnvironmentRole\n ): Promise<EnvironmentPermission> {\n const response = await this.request<{ permission: EnvironmentPermission }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,\n { role }\n );\n return response.permission;\n }\n\n /**\n * Delete a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to delete permission for\n * @example\n * ```ts\n * await client.deletePermission('project-id', 'production', 'user-id');\n * ```\n */\n async deletePermission(projectId: string, environment: string, userId: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`\n );\n }\n\n /**\n * Bulk set permissions for multiple users in an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param permissions - Array of user permissions to set\n * @returns Array of created or updated permissions\n * @example\n * ```ts\n * const permissions = await client.bulkSetPermissions('project-id', 'production', [\n * { userId: 'user-1', role: 'write' },\n * { userId: 'user-2', role: 'read' },\n * ]);\n * ```\n */\n async bulkSetPermissions(\n projectId: string, environment: string, permissions: Array<{ userId: string; role: EnvironmentRole }>\n ): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ permissions: EnvironmentPermission[] }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions`,\n { permissions: permissions.map(p => ({ user_id: p.userId, role: p.role })) }\n );\n return response.permissions;\n }\n\n /**\n * Get the current user's permissions for all environments in a project.\n * @param projectId - The project ID\n * @returns The user's permissions and team admin status\n * @example\n * ```ts\n * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');\n * for (const perm of permissions) {\n * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);\n * }\n * ```\n */\n async getMyPermissions(projectId: string): Promise<MyPermissionsResponse> {\n return this.request<MyPermissionsResponse>('GET', `/api/v1/projects/${projectId}/my-permissions`);\n }\n\n /**\n * Get default permission settings for a project's environments.\n * @param projectId - The project ID\n * @returns Array of project default permissions\n * @example\n * ```ts\n * const defaults = await client.getProjectDefaults('project-id');\n * for (const def of defaults) {\n * console.log(`${def.environment_name}: ${def.default_role}`);\n * }\n * ```\n */\n async getProjectDefaults(projectId: string): Promise<ProjectDefault[]> {\n const response = await this.request<{ defaults: ProjectDefault[] }>(\n 'GET', `/api/v1/projects/${projectId}/permissions/defaults`\n );\n return response.defaults;\n }\n\n /**\n * Set default permission settings for a project's environments.\n * @param projectId - The project ID\n * @param defaults - Array of default permissions to set\n * @returns Array of updated project default permissions\n * @example\n * ```ts\n * const defaults = await client.setProjectDefaults('project-id', [\n * { environmentName: 'development', defaultRole: 'write' },\n * { environmentName: 'production', defaultRole: 'read' },\n * ]);\n * ```\n */\n async setProjectDefaults(\n projectId: string, defaults: Array<{ environmentName: string; defaultRole: EnvironmentRole }>\n ): Promise<ProjectDefault[]> {\n const response = await this.request<{ defaults: ProjectDefault[] }>(\n 'PUT', `/api/v1/projects/${projectId}/permissions/defaults`,\n { defaults: defaults.map(d => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }\n );\n return response.defaults;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts"],"sourcesContent":["export { KeyEnv } from './client.js';\nexport { KeyEnvError } from './types.js';\nexport type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\n","/** KeyEnv client configuration options */\nexport interface KeyEnvOptions {\n /** Service token for authentication */\n token: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */\n cacheTtl?: number;\n /** Custom API base URL (default: https://api.keyenv.dev). Also configurable via KEYENV_API_URL env var. */\n baseUrl?: string;\n}\n\n/** User or service token info */\nexport interface User {\n id: string;\n email?: string;\n name?: string;\n clerk_id?: string;\n avatar_url?: string;\n /** Present for service tokens */\n auth_type?: 'service_token' | 'user';\n /** Team ID (for service tokens) */\n team_id?: string;\n /** Project IDs (for project-scoped service tokens) */\n project_ids?: string[];\n /** Token scopes (for service tokens) */\n scopes?: string[];\n created_at: string;\n}\n\n/** Project */\nexport interface Project {\n id: string;\n team_id: string;\n name: string;\n slug: string;\n description?: string;\n created_at: string;\n}\n\n/** Environment */\nexport interface Environment {\n id: string;\n project_id: string;\n name: string;\n inherits_from?: string;\n created_at: string;\n}\n\n/** Project with environments */\nexport interface ProjectWithEnvironments extends Project {\n environments: Environment[];\n}\n\n/** Secret (without value) */\nexport interface Secret {\n id: string;\n environment_id: string;\n key: string;\n type: string;\n description?: string;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\n/** Secret with decrypted value */\nexport interface SecretWithValue extends Secret {\n value: string;\n inherited_from?: string;\n}\n\n/** Secret history entry */\nexport interface SecretHistory {\n id: string;\n secret_id: string;\n value: string;\n version: number;\n changed_by?: string;\n changed_at: string;\n}\n\n/** Bulk import request item */\nexport interface BulkSecretItem {\n key: string;\n value: string;\n description?: string;\n}\n\n/** Bulk import result */\nexport interface BulkImportResult {\n created: number;\n updated: number;\n skipped: number;\n}\n\n/** API error response */\nexport interface ApiError {\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\n/** KeyEnv API error */\nexport class KeyEnvError extends Error {\n public readonly status: number;\n public readonly code?: string;\n public readonly details?: Record<string, unknown>;\n\n constructor(message: string, status: number, code?: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'KeyEnvError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/** Environment permission role */\nexport type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';\n\n/** Environment permission for a user */\nexport interface EnvironmentPermission {\n id: string;\n environment_id: string;\n user_id: string;\n role: EnvironmentRole;\n user_email?: string;\n user_name?: string;\n granted_by?: string;\n created_at: string;\n updated_at: string;\n}\n\n/** User's permission for an environment */\nexport interface MyPermission {\n environment_id: string;\n environment_name: string;\n role: EnvironmentRole;\n can_read: boolean;\n can_write: boolean;\n can_admin: boolean;\n}\n\n/** Response for getting user's permissions */\nexport interface MyPermissionsResponse {\n permissions: MyPermission[];\n is_team_admin: boolean;\n}\n\n/** Project default permission for an environment */\nexport interface ProjectDefault {\n id: string;\n project_id: string;\n environment_name: string;\n default_role: EnvironmentRole;\n created_at: string;\n}\n","import type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n ApiError,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\nfunction getCacheKey(projectId: string, environment: string): string {\n return `${projectId}:${environment}`;\n}\n\n/**\n * KeyEnv API client for managing secrets\n *\n * @example\n * ```ts\n * import { KeyEnv } from 'keyenv';\n *\n * const client = new KeyEnv({ token: process.env.KEYENV_TOKEN });\n *\n * // Export all secrets for an environment\n * const secrets = await client.exportSecrets('project-id', 'production');\n * ```\n */\nexport class KeyEnv {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly cacheTtl: number;\n private readonly secretsCache = new Map<string, { secrets: SecretWithValue[]; expiresAt: number }>();\n\n constructor(options: KeyEnvOptions) {\n if (!options.token) {\n throw new Error('KeyEnv token is required');\n }\n this.token = options.token;\n // Base URL: constructor option → env var → default\n this.baseUrl = (options.baseUrl ?? process.env.KEYENV_API_URL ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n // Cache TTL: constructor option → env var → 0 (disabled)\n this.cacheTtl = options.cacheTtl ??\n (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'keyenv-node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n let errorData: ApiError = { error: 'Unknown error' };\n try {\n errorData = await response.json() as ApiError;\n } catch {\n errorData = { error: response.statusText };\n }\n throw new KeyEnvError(errorData.error, response.status, errorData.code, errorData.details);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof KeyEnvError) throw error;\n if (error instanceof Error && error.name === 'AbortError') {\n throw new KeyEnvError('Request timeout', 408);\n }\n throw new KeyEnvError(error instanceof Error ? error.message : 'Network error', 0);\n }\n }\n\n /** Get the current user or service token info */\n async getCurrentUser(): Promise<User> {\n const response = await this.request<{ data: User }>('GET', '/api/v1/users/me');\n return response.data;\n }\n\n /** Validate the token and return user info */\n async validateToken(): Promise<User> {\n return this.getCurrentUser();\n }\n\n /** List all accessible projects */\n async listProjects(): Promise<Project[]> {\n const response = await this.request<{ data: Project[] }>('GET', '/api/v1/projects');\n return response.data;\n }\n\n /** Get a project by ID */\n async getProject(projectId: string): Promise<ProjectWithEnvironments> {\n const response = await this.request<{ data: ProjectWithEnvironments }>('GET', `/api/v1/projects/${projectId}`);\n return response.data;\n }\n\n /** Create a new project */\n async createProject(teamId: string, name: string): Promise<Project> {\n const response = await this.request<{ data: Project }>('POST', '/api/v1/projects', { team_id: teamId, name });\n return response.data;\n }\n\n /** Delete a project */\n async deleteProject(projectId: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}`);\n }\n\n /** List environments in a project */\n async listEnvironments(projectId: string): Promise<Environment[]> {\n const response = await this.request<{ data: Environment[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments`\n );\n return response.data;\n }\n\n /** Create a new environment */\n async createEnvironment(projectId: string, name: string, inheritsFrom?: string): Promise<Environment> {\n const response = await this.request<{ data: Environment }>(\n 'POST', `/api/v1/projects/${projectId}/environments`,\n { name, inherits_from: inheritsFrom }\n );\n return response.data;\n }\n\n /** Delete an environment */\n async deleteEnvironment(projectId: string, environment: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}/environments/${environment}`);\n }\n\n /** List secrets in an environment (keys and metadata only) */\n async listSecrets(projectId: string, environment: string): Promise<Secret[]> {\n const response = await this.request<{ data: Secret[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets`\n );\n return response.data;\n }\n\n /**\n * Export all secrets with their decrypted values.\n * Results are cached when cacheTtl > 0.\n * @example\n * ```ts\n * const secrets = await client.exportSecrets('project-id', 'production');\n * for (const secret of secrets) {\n * process.env[secret.key] = secret.value;\n * }\n * ```\n */\n async exportSecrets(projectId: string, environment: string): Promise<SecretWithValue[]> {\n const cacheKey = getCacheKey(projectId, environment);\n\n // Check cache if TTL > 0\n if (this.cacheTtl > 0) {\n const cached = this.secretsCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.secrets;\n }\n // Delete expired entry to prevent memory leaks\n if (cached) {\n this.secretsCache.delete(cacheKey);\n }\n }\n\n const response = await this.request<{ data: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\n );\n\n // Store in cache if TTL > 0\n if (this.cacheTtl > 0) {\n this.secretsCache.set(cacheKey, {\n secrets: response.data,\n expiresAt: Date.now() + (this.cacheTtl * 1000),\n });\n }\n\n return response.data;\n }\n\n /**\n * Export secrets as a key-value object\n * @example\n * ```ts\n * const env = await client.exportSecretsAsObject('project-id', 'production');\n * // { DATABASE_URL: '...', API_KEY: '...' }\n * ```\n */\n async exportSecretsAsObject(projectId: string, environment: string): Promise<Record<string, string>> {\n const secrets = await this.exportSecrets(projectId, environment);\n return Object.fromEntries(secrets.map((s) => [s.key, s.value]));\n }\n\n /** Get a single secret with its value */\n async getSecret(projectId: string, environment: string, key: string): Promise<SecretWithValue> {\n const response = await this.request<{ data: SecretWithValue }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n return response.data;\n }\n\n /** Create a new secret */\n async createSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ data: Secret }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets`,\n { key, value, description }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /** Update a secret's value */\n async updateSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ data: Secret }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,\n { value, description }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /** Set a secret (create or update) */\n async setSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n try {\n return await this.updateSecret(projectId, environment, key, value, description);\n } catch (error) {\n if (error instanceof KeyEnvError && error.status === 404) {\n return this.createSecret(projectId, environment, key, value, description);\n }\n throw error;\n }\n }\n\n /** Delete a secret */\n async deleteSecret(projectId: string, environment: string, key: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n this.clearCache(projectId, environment);\n }\n\n /** Get secret version history */\n async getSecretHistory(projectId: string, environment: string, key: string): Promise<SecretHistory[]> {\n const response = await this.request<{ data: SecretHistory[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`\n );\n return response.data;\n }\n\n /**\n * Bulk import secrets\n * @example\n * ```ts\n * await client.bulkImport('project-id', 'development', [\n * { key: 'DATABASE_URL', value: 'postgres://...' },\n * { key: 'API_KEY', value: 'sk_...' },\n * ], { overwrite: true });\n * ```\n */\n async bulkImport(\n projectId: string, environment: string, secrets: BulkSecretItem[], options: { overwrite?: boolean } = {}\n ): Promise<BulkImportResult> {\n const response = await this.request<{ data: BulkImportResult }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /**\n * Load secrets into process.env\n * @example\n * ```ts\n * await client.loadEnv('project-id', 'production');\n * console.log(process.env.DATABASE_URL);\n * ```\n */\n async loadEnv(projectId: string, environment: string): Promise<number> {\n const secrets = await this.exportSecrets(projectId, environment);\n for (const secret of secrets) {\n process.env[secret.key] = secret.value;\n }\n return secrets.length;\n }\n\n /** Generate .env file content from secrets */\n async generateEnvFile(projectId: string, environment: string): Promise<string> {\n const secrets = await this.exportSecrets(projectId, environment);\n const lines = [\n '# Generated by KeyEnv',\n `# Environment: ${environment}`,\n `# Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n for (const secret of secrets) {\n const value = secret.value;\n if (value.includes('\\n') || value.includes('\"') || value.includes(\"'\") || value.includes(' ') || value.includes('$')) {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n').replace(/\\$/g, '\\\\$');\n lines.push(`${secret.key}=\"${escaped}\"`);\n } else {\n lines.push(`${secret.key}=${value}`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n }\n\n /**\n * Clear the secrets cache.\n * @param projectId - Clear cache for specific project (optional)\n * @param environment - Clear cache for specific environment (requires projectId)\n */\n clearCache(projectId?: string, environment?: string): void {\n if (projectId && environment) {\n this.secretsCache.delete(getCacheKey(projectId, environment));\n } else if (projectId) {\n // Clear all environments for this project\n for (const key of this.secretsCache.keys()) {\n if (key.startsWith(`${projectId}:`)) {\n this.secretsCache.delete(key);\n }\n }\n } else {\n this.secretsCache.clear();\n }\n }\n\n // ============================================================================\n // Environment Permission Management\n // ============================================================================\n\n /**\n * List all permissions for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @returns Array of environment permissions\n * @example\n * ```ts\n * const permissions = await client.listPermissions('project-id', 'production');\n * for (const perm of permissions) {\n * console.log(`${perm.user_email}: ${perm.role}`);\n * }\n * ```\n */\n async listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ data: EnvironmentPermission[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/permissions`\n );\n return response.data;\n }\n\n /**\n * Set a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to set permission for\n * @param role - The permission role ('none', 'read', 'write', or 'admin')\n * @returns The created or updated permission\n * @example\n * ```ts\n * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');\n * console.log(`Set ${permission.user_email} to ${permission.role}`);\n * ```\n */\n async setPermission(\n projectId: string, environment: string, userId: string, role: EnvironmentRole\n ): Promise<EnvironmentPermission> {\n const response = await this.request<{ data: EnvironmentPermission }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,\n { role }\n );\n return response.data;\n }\n\n /**\n * Delete a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to delete permission for\n * @example\n * ```ts\n * await client.deletePermission('project-id', 'production', 'user-id');\n * ```\n */\n async deletePermission(projectId: string, environment: string, userId: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`\n );\n }\n\n /**\n * Bulk set permissions for multiple users in an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param permissions - Array of user permissions to set\n * @returns Array of created or updated permissions\n * @example\n * ```ts\n * const permissions = await client.bulkSetPermissions('project-id', 'production', [\n * { userId: 'user-1', role: 'write' },\n * { userId: 'user-2', role: 'read' },\n * ]);\n * ```\n */\n async bulkSetPermissions(\n projectId: string, environment: string, permissions: Array<{ userId: string; role: EnvironmentRole }>\n ): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ data: EnvironmentPermission[] }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions`,\n { permissions: permissions.map(p => ({ user_id: p.userId, role: p.role })) }\n );\n return response.data;\n }\n\n /**\n * Get the current user's permissions for all environments in a project.\n * @param projectId - The project ID\n * @returns The user's permissions and team admin status\n * @example\n * ```ts\n * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');\n * for (const perm of permissions) {\n * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);\n * }\n * ```\n */\n async getMyPermissions(projectId: string): Promise<MyPermissionsResponse> {\n return this.request<MyPermissionsResponse>('GET', `/api/v1/projects/${projectId}/my-permissions`);\n }\n\n /**\n * Get default permission settings for a project's environments.\n * @param projectId - The project ID\n * @returns Array of project default permissions\n * @example\n * ```ts\n * const defaults = await client.getProjectDefaults('project-id');\n * for (const def of defaults) {\n * console.log(`${def.environment_name}: ${def.default_role}`);\n * }\n * ```\n */\n async getProjectDefaults(projectId: string): Promise<ProjectDefault[]> {\n const response = await this.request<{ data: ProjectDefault[] }>(\n 'GET', `/api/v1/projects/${projectId}/permissions/defaults`\n );\n return response.data;\n }\n\n /**\n * Set default permission settings for a project's environments.\n * @param projectId - The project ID\n * @param defaults - Array of default permissions to set\n * @returns Array of updated project default permissions\n * @example\n * ```ts\n * const defaults = await client.setProjectDefaults('project-id', [\n * { environmentName: 'development', defaultRole: 'write' },\n * { environmentName: 'production', defaultRole: 'read' },\n * ]);\n * ```\n */\n async setProjectDefaults(\n projectId: string, defaults: Array<{ environmentName: string; defaultRole: EnvironmentRole }>\n ): Promise<ProjectDefault[]> {\n const response = await this.request<{ data: ProjectDefault[] }>(\n 'PUT', `/api/v1/projects/${projectId}/permissions/defaults`,\n { defaults: defaults.map(d => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }\n );\n return response.data;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -13,26 +13,28 @@ var KeyEnvError = class extends Error {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
// src/client.ts
|
|
16
|
-
var
|
|
16
|
+
var DEFAULT_BASE_URL = "https://api.keyenv.dev";
|
|
17
17
|
var DEFAULT_TIMEOUT = 3e4;
|
|
18
|
-
var secretsCache = /* @__PURE__ */ new Map();
|
|
19
18
|
function getCacheKey(projectId, environment) {
|
|
20
19
|
return `${projectId}:${environment}`;
|
|
21
20
|
}
|
|
22
21
|
var KeyEnv = class {
|
|
23
22
|
token;
|
|
23
|
+
baseUrl;
|
|
24
24
|
timeout;
|
|
25
25
|
cacheTtl;
|
|
26
|
+
secretsCache = /* @__PURE__ */ new Map();
|
|
26
27
|
constructor(options) {
|
|
27
28
|
if (!options.token) {
|
|
28
29
|
throw new Error("KeyEnv token is required");
|
|
29
30
|
}
|
|
30
31
|
this.token = options.token;
|
|
32
|
+
this.baseUrl = (options.baseUrl ?? process.env.KEYENV_API_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
31
33
|
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
32
34
|
this.cacheTtl = options.cacheTtl ?? (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);
|
|
33
35
|
}
|
|
34
36
|
async request(method, path, body) {
|
|
35
|
-
const url = `${
|
|
37
|
+
const url = `${this.baseUrl}${path}`;
|
|
36
38
|
const controller = new AbortController();
|
|
37
39
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
38
40
|
try {
|
|
@@ -71,7 +73,8 @@ var KeyEnv = class {
|
|
|
71
73
|
}
|
|
72
74
|
/** Get the current user or service token info */
|
|
73
75
|
async getCurrentUser() {
|
|
74
|
-
|
|
76
|
+
const response = await this.request("GET", "/api/v1/users/me");
|
|
77
|
+
return response.data;
|
|
75
78
|
}
|
|
76
79
|
/** Validate the token and return user info */
|
|
77
80
|
async validateToken() {
|
|
@@ -80,15 +83,17 @@ var KeyEnv = class {
|
|
|
80
83
|
/** List all accessible projects */
|
|
81
84
|
async listProjects() {
|
|
82
85
|
const response = await this.request("GET", "/api/v1/projects");
|
|
83
|
-
return response.
|
|
86
|
+
return response.data;
|
|
84
87
|
}
|
|
85
88
|
/** Get a project by ID */
|
|
86
89
|
async getProject(projectId) {
|
|
87
|
-
|
|
90
|
+
const response = await this.request("GET", `/api/v1/projects/${projectId}`);
|
|
91
|
+
return response.data;
|
|
88
92
|
}
|
|
89
93
|
/** Create a new project */
|
|
90
94
|
async createProject(teamId, name) {
|
|
91
|
-
|
|
95
|
+
const response = await this.request("POST", "/api/v1/projects", { team_id: teamId, name });
|
|
96
|
+
return response.data;
|
|
92
97
|
}
|
|
93
98
|
/** Delete a project */
|
|
94
99
|
async deleteProject(projectId) {
|
|
@@ -100,15 +105,16 @@ var KeyEnv = class {
|
|
|
100
105
|
"GET",
|
|
101
106
|
`/api/v1/projects/${projectId}/environments`
|
|
102
107
|
);
|
|
103
|
-
return response.
|
|
108
|
+
return response.data;
|
|
104
109
|
}
|
|
105
110
|
/** Create a new environment */
|
|
106
111
|
async createEnvironment(projectId, name, inheritsFrom) {
|
|
107
|
-
|
|
112
|
+
const response = await this.request(
|
|
108
113
|
"POST",
|
|
109
114
|
`/api/v1/projects/${projectId}/environments`,
|
|
110
115
|
{ name, inherits_from: inheritsFrom }
|
|
111
116
|
);
|
|
117
|
+
return response.data;
|
|
112
118
|
}
|
|
113
119
|
/** Delete an environment */
|
|
114
120
|
async deleteEnvironment(projectId, environment) {
|
|
@@ -120,7 +126,7 @@ var KeyEnv = class {
|
|
|
120
126
|
"GET",
|
|
121
127
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets`
|
|
122
128
|
);
|
|
123
|
-
return response.
|
|
129
|
+
return response.data;
|
|
124
130
|
}
|
|
125
131
|
/**
|
|
126
132
|
* Export all secrets with their decrypted values.
|
|
@@ -136,22 +142,25 @@ var KeyEnv = class {
|
|
|
136
142
|
async exportSecrets(projectId, environment) {
|
|
137
143
|
const cacheKey = getCacheKey(projectId, environment);
|
|
138
144
|
if (this.cacheTtl > 0) {
|
|
139
|
-
const cached = secretsCache.get(cacheKey);
|
|
145
|
+
const cached = this.secretsCache.get(cacheKey);
|
|
140
146
|
if (cached && Date.now() < cached.expiresAt) {
|
|
141
147
|
return cached.secrets;
|
|
142
148
|
}
|
|
149
|
+
if (cached) {
|
|
150
|
+
this.secretsCache.delete(cacheKey);
|
|
151
|
+
}
|
|
143
152
|
}
|
|
144
153
|
const response = await this.request(
|
|
145
154
|
"GET",
|
|
146
155
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/export`
|
|
147
156
|
);
|
|
148
157
|
if (this.cacheTtl > 0) {
|
|
149
|
-
secretsCache.set(cacheKey, {
|
|
150
|
-
secrets: response.
|
|
158
|
+
this.secretsCache.set(cacheKey, {
|
|
159
|
+
secrets: response.data,
|
|
151
160
|
expiresAt: Date.now() + this.cacheTtl * 1e3
|
|
152
161
|
});
|
|
153
162
|
}
|
|
154
|
-
return response.
|
|
163
|
+
return response.data;
|
|
155
164
|
}
|
|
156
165
|
/**
|
|
157
166
|
* Export secrets as a key-value object
|
|
@@ -171,7 +180,7 @@ var KeyEnv = class {
|
|
|
171
180
|
"GET",
|
|
172
181
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`
|
|
173
182
|
);
|
|
174
|
-
return response.
|
|
183
|
+
return response.data;
|
|
175
184
|
}
|
|
176
185
|
/** Create a new secret */
|
|
177
186
|
async createSecret(projectId, environment, key, value, description) {
|
|
@@ -181,7 +190,7 @@ var KeyEnv = class {
|
|
|
181
190
|
{ key, value, description }
|
|
182
191
|
);
|
|
183
192
|
this.clearCache(projectId, environment);
|
|
184
|
-
return response.
|
|
193
|
+
return response.data;
|
|
185
194
|
}
|
|
186
195
|
/** Update a secret's value */
|
|
187
196
|
async updateSecret(projectId, environment, key, value, description) {
|
|
@@ -191,7 +200,7 @@ var KeyEnv = class {
|
|
|
191
200
|
{ value, description }
|
|
192
201
|
);
|
|
193
202
|
this.clearCache(projectId, environment);
|
|
194
|
-
return response.
|
|
203
|
+
return response.data;
|
|
195
204
|
}
|
|
196
205
|
/** Set a secret (create or update) */
|
|
197
206
|
async setSecret(projectId, environment, key, value, description) {
|
|
@@ -218,7 +227,7 @@ var KeyEnv = class {
|
|
|
218
227
|
"GET",
|
|
219
228
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`
|
|
220
229
|
);
|
|
221
|
-
return response.
|
|
230
|
+
return response.data;
|
|
222
231
|
}
|
|
223
232
|
/**
|
|
224
233
|
* Bulk import secrets
|
|
@@ -231,13 +240,13 @@ var KeyEnv = class {
|
|
|
231
240
|
* ```
|
|
232
241
|
*/
|
|
233
242
|
async bulkImport(projectId, environment, secrets, options = {}) {
|
|
234
|
-
const
|
|
243
|
+
const response = await this.request(
|
|
235
244
|
"POST",
|
|
236
245
|
`/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,
|
|
237
246
|
{ secrets, overwrite: options.overwrite ?? false }
|
|
238
247
|
);
|
|
239
248
|
this.clearCache(projectId, environment);
|
|
240
|
-
return
|
|
249
|
+
return response.data;
|
|
241
250
|
}
|
|
242
251
|
/**
|
|
243
252
|
* Load secrets into process.env
|
|
@@ -265,8 +274,8 @@ var KeyEnv = class {
|
|
|
265
274
|
];
|
|
266
275
|
for (const secret of secrets) {
|
|
267
276
|
const value = secret.value;
|
|
268
|
-
if (value.includes("\n") || value.includes('"') || value.includes("'") || value.includes(" ")) {
|
|
269
|
-
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
277
|
+
if (value.includes("\n") || value.includes('"') || value.includes("'") || value.includes(" ") || value.includes("$")) {
|
|
278
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
|
|
270
279
|
lines.push(`${secret.key}="${escaped}"`);
|
|
271
280
|
} else {
|
|
272
281
|
lines.push(`${secret.key}=${value}`);
|
|
@@ -281,15 +290,15 @@ var KeyEnv = class {
|
|
|
281
290
|
*/
|
|
282
291
|
clearCache(projectId, environment) {
|
|
283
292
|
if (projectId && environment) {
|
|
284
|
-
secretsCache.delete(getCacheKey(projectId, environment));
|
|
293
|
+
this.secretsCache.delete(getCacheKey(projectId, environment));
|
|
285
294
|
} else if (projectId) {
|
|
286
|
-
for (const key of secretsCache.keys()) {
|
|
295
|
+
for (const key of this.secretsCache.keys()) {
|
|
287
296
|
if (key.startsWith(`${projectId}:`)) {
|
|
288
|
-
secretsCache.delete(key);
|
|
297
|
+
this.secretsCache.delete(key);
|
|
289
298
|
}
|
|
290
299
|
}
|
|
291
300
|
} else {
|
|
292
|
-
secretsCache.clear();
|
|
301
|
+
this.secretsCache.clear();
|
|
293
302
|
}
|
|
294
303
|
}
|
|
295
304
|
// ============================================================================
|
|
@@ -313,7 +322,7 @@ var KeyEnv = class {
|
|
|
313
322
|
"GET",
|
|
314
323
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions`
|
|
315
324
|
);
|
|
316
|
-
return response.
|
|
325
|
+
return response.data;
|
|
317
326
|
}
|
|
318
327
|
/**
|
|
319
328
|
* Set a user's permission for an environment.
|
|
@@ -334,7 +343,7 @@ var KeyEnv = class {
|
|
|
334
343
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,
|
|
335
344
|
{ role }
|
|
336
345
|
);
|
|
337
|
-
return response.
|
|
346
|
+
return response.data;
|
|
338
347
|
}
|
|
339
348
|
/**
|
|
340
349
|
* Delete a user's permission for an environment.
|
|
@@ -372,7 +381,7 @@ var KeyEnv = class {
|
|
|
372
381
|
`/api/v1/projects/${projectId}/environments/${environment}/permissions`,
|
|
373
382
|
{ permissions: permissions.map((p) => ({ user_id: p.userId, role: p.role })) }
|
|
374
383
|
);
|
|
375
|
-
return response.
|
|
384
|
+
return response.data;
|
|
376
385
|
}
|
|
377
386
|
/**
|
|
378
387
|
* Get the current user's permissions for all environments in a project.
|
|
@@ -406,7 +415,7 @@ var KeyEnv = class {
|
|
|
406
415
|
"GET",
|
|
407
416
|
`/api/v1/projects/${projectId}/permissions/defaults`
|
|
408
417
|
);
|
|
409
|
-
return response.
|
|
418
|
+
return response.data;
|
|
410
419
|
}
|
|
411
420
|
/**
|
|
412
421
|
* Set default permission settings for a project's environments.
|
|
@@ -427,7 +436,7 @@ var KeyEnv = class {
|
|
|
427
436
|
`/api/v1/projects/${projectId}/permissions/defaults`,
|
|
428
437
|
{ defaults: defaults.map((d) => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }
|
|
429
438
|
);
|
|
430
|
-
return response.
|
|
439
|
+
return response.data;
|
|
431
440
|
}
|
|
432
441
|
};
|
|
433
442
|
export {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/client.ts"],"sourcesContent":["/** KeyEnv client configuration options */\nexport interface KeyEnvOptions {\n /** Service token for authentication */\n token: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */\n cacheTtl?: number;\n}\n\n/** User or service token info */\nexport interface User {\n id: string;\n email?: string;\n name?: string;\n clerk_id?: string;\n avatar_url?: string;\n /** Present for service tokens */\n auth_type?: 'service_token' | 'user';\n /** Team ID (for service tokens) */\n team_id?: string;\n /** Project IDs (for project-scoped service tokens) */\n project_ids?: string[];\n /** Token scopes (for service tokens) */\n scopes?: string[];\n created_at: string;\n}\n\n/** Project */\nexport interface Project {\n id: string;\n team_id: string;\n name: string;\n slug: string;\n description?: string;\n created_at: string;\n}\n\n/** Environment */\nexport interface Environment {\n id: string;\n project_id: string;\n name: string;\n inherits_from?: string;\n created_at: string;\n}\n\n/** Project with environments */\nexport interface ProjectWithEnvironments extends Project {\n environments: Environment[];\n}\n\n/** Secret (without value) */\nexport interface Secret {\n id: string;\n environment_id: string;\n key: string;\n type: string;\n description?: string;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\n/** Secret with decrypted value */\nexport interface SecretWithValue extends Secret {\n value: string;\n inherited_from?: string;\n}\n\n/** Secret history entry */\nexport interface SecretHistory {\n id: string;\n secret_id: string;\n value: string;\n version: number;\n changed_by?: string;\n changed_at: string;\n}\n\n/** Bulk import request item */\nexport interface BulkSecretItem {\n key: string;\n value: string;\n description?: string;\n}\n\n/** Bulk import result */\nexport interface BulkImportResult {\n created: number;\n updated: number;\n skipped: number;\n}\n\n/** API error response */\nexport interface ApiError {\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\n/** KeyEnv API error */\nexport class KeyEnvError extends Error {\n public readonly status: number;\n public readonly code?: string;\n public readonly details?: Record<string, unknown>;\n\n constructor(message: string, status: number, code?: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'KeyEnvError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/** Environment permission role */\nexport type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';\n\n/** Environment permission for a user */\nexport interface EnvironmentPermission {\n id: string;\n environment_id: string;\n user_id: string;\n role: EnvironmentRole;\n user_email?: string;\n user_name?: string;\n granted_by?: string;\n created_at: string;\n updated_at: string;\n}\n\n/** User's permission for an environment */\nexport interface MyPermission {\n environment_id: string;\n environment_name: string;\n role: EnvironmentRole;\n can_read: boolean;\n can_write: boolean;\n can_admin: boolean;\n}\n\n/** Response for getting user's permissions */\nexport interface MyPermissionsResponse {\n permissions: MyPermission[];\n is_team_admin: boolean;\n}\n\n/** Project default permission for an environment */\nexport interface ProjectDefault {\n id: string;\n project_id: string;\n environment_name: string;\n default_role: EnvironmentRole;\n created_at: string;\n}\n","import type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n ApiError,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\n/** Module-level cache for secrets (survives across warm serverless invocations) */\nconst secretsCache = new Map<string, { secrets: SecretWithValue[]; expiresAt: number }>();\n\nfunction getCacheKey(projectId: string, environment: string): string {\n return `${projectId}:${environment}`;\n}\n\n/**\n * KeyEnv API client for managing secrets\n *\n * @example\n * ```ts\n * import { KeyEnv } from 'keyenv';\n *\n * const client = new KeyEnv({ token: process.env.KEYENV_TOKEN });\n *\n * // Export all secrets for an environment\n * const secrets = await client.exportSecrets('project-id', 'production');\n * ```\n */\nexport class KeyEnv {\n private readonly token: string;\n private readonly timeout: number;\n private readonly cacheTtl: number;\n\n constructor(options: KeyEnvOptions) {\n if (!options.token) {\n throw new Error('KeyEnv token is required');\n }\n this.token = options.token;\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n // Cache TTL: constructor option → env var → 0 (disabled)\n this.cacheTtl = options.cacheTtl ??\n (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'keyenv-node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n let errorData: ApiError = { error: 'Unknown error' };\n try {\n errorData = await response.json() as ApiError;\n } catch {\n errorData = { error: response.statusText };\n }\n throw new KeyEnvError(errorData.error, response.status, errorData.code, errorData.details);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof KeyEnvError) throw error;\n if (error instanceof Error && error.name === 'AbortError') {\n throw new KeyEnvError('Request timeout', 408);\n }\n throw new KeyEnvError(error instanceof Error ? error.message : 'Network error', 0);\n }\n }\n\n /** Get the current user or service token info */\n async getCurrentUser(): Promise<User> {\n return this.request<User>('GET', '/api/v1/users/me');\n }\n\n /** Validate the token and return user info */\n async validateToken(): Promise<User> {\n return this.getCurrentUser();\n }\n\n /** List all accessible projects */\n async listProjects(): Promise<Project[]> {\n const response = await this.request<{ projects: Project[] }>('GET', '/api/v1/projects');\n return response.projects;\n }\n\n /** Get a project by ID */\n async getProject(projectId: string): Promise<ProjectWithEnvironments> {\n return this.request<ProjectWithEnvironments>('GET', `/api/v1/projects/${projectId}`);\n }\n\n /** Create a new project */\n async createProject(teamId: string, name: string): Promise<Project> {\n return this.request<Project>('POST', '/api/v1/projects', { team_id: teamId, name });\n }\n\n /** Delete a project */\n async deleteProject(projectId: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}`);\n }\n\n /** List environments in a project */\n async listEnvironments(projectId: string): Promise<Environment[]> {\n const response = await this.request<{ environments: Environment[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments`\n );\n return response.environments;\n }\n\n /** Create a new environment */\n async createEnvironment(projectId: string, name: string, inheritsFrom?: string): Promise<Environment> {\n return this.request<Environment>(\n 'POST', `/api/v1/projects/${projectId}/environments`,\n { name, inherits_from: inheritsFrom }\n );\n }\n\n /** Delete an environment */\n async deleteEnvironment(projectId: string, environment: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}/environments/${environment}`);\n }\n\n /** List secrets in an environment (keys and metadata only) */\n async listSecrets(projectId: string, environment: string): Promise<Secret[]> {\n const response = await this.request<{ secrets: Secret[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets`\n );\n return response.secrets;\n }\n\n /**\n * Export all secrets with their decrypted values.\n * Results are cached when cacheTtl > 0.\n * @example\n * ```ts\n * const secrets = await client.exportSecrets('project-id', 'production');\n * for (const secret of secrets) {\n * process.env[secret.key] = secret.value;\n * }\n * ```\n */\n async exportSecrets(projectId: string, environment: string): Promise<SecretWithValue[]> {\n const cacheKey = getCacheKey(projectId, environment);\n\n // Check cache if TTL > 0\n if (this.cacheTtl > 0) {\n const cached = secretsCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.secrets;\n }\n }\n\n const response = await this.request<{ secrets: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\n );\n\n // Store in cache if TTL > 0\n if (this.cacheTtl > 0) {\n secretsCache.set(cacheKey, {\n secrets: response.secrets,\n expiresAt: Date.now() + (this.cacheTtl * 1000),\n });\n }\n\n return response.secrets;\n }\n\n /**\n * Export secrets as a key-value object\n * @example\n * ```ts\n * const env = await client.exportSecretsAsObject('project-id', 'production');\n * // { DATABASE_URL: '...', API_KEY: '...' }\n * ```\n */\n async exportSecretsAsObject(projectId: string, environment: string): Promise<Record<string, string>> {\n const secrets = await this.exportSecrets(projectId, environment);\n return Object.fromEntries(secrets.map((s) => [s.key, s.value]));\n }\n\n /** Get a single secret with its value */\n async getSecret(projectId: string, environment: string, key: string): Promise<SecretWithValue> {\n const response = await this.request<{ secret: SecretWithValue }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n return response.secret;\n }\n\n /** Create a new secret */\n async createSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ secret: Secret }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets`,\n { key, value, description }\n );\n this.clearCache(projectId, environment);\n return response.secret;\n }\n\n /** Update a secret's value */\n async updateSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ secret: Secret }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,\n { value, description }\n );\n this.clearCache(projectId, environment);\n return response.secret;\n }\n\n /** Set a secret (create or update) */\n async setSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n try {\n return await this.updateSecret(projectId, environment, key, value, description);\n } catch (error) {\n if (error instanceof KeyEnvError && error.status === 404) {\n return this.createSecret(projectId, environment, key, value, description);\n }\n throw error;\n }\n }\n\n /** Delete a secret */\n async deleteSecret(projectId: string, environment: string, key: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n this.clearCache(projectId, environment);\n }\n\n /** Get secret version history */\n async getSecretHistory(projectId: string, environment: string, key: string): Promise<SecretHistory[]> {\n const response = await this.request<{ history: SecretHistory[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`\n );\n return response.history;\n }\n\n /**\n * Bulk import secrets\n * @example\n * ```ts\n * await client.bulkImport('project-id', 'development', [\n * { key: 'DATABASE_URL', value: 'postgres://...' },\n * { key: 'API_KEY', value: 'sk_...' },\n * ], { overwrite: true });\n * ```\n */\n async bulkImport(\n projectId: string, environment: string, secrets: BulkSecretItem[], options: { overwrite?: boolean } = {}\n ): Promise<BulkImportResult> {\n const result = await this.request<BulkImportResult>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\n this.clearCache(projectId, environment);\n return result;\n }\n\n /**\n * Load secrets into process.env\n * @example\n * ```ts\n * await client.loadEnv('project-id', 'production');\n * console.log(process.env.DATABASE_URL);\n * ```\n */\n async loadEnv(projectId: string, environment: string): Promise<number> {\n const secrets = await this.exportSecrets(projectId, environment);\n for (const secret of secrets) {\n process.env[secret.key] = secret.value;\n }\n return secrets.length;\n }\n\n /** Generate .env file content from secrets */\n async generateEnvFile(projectId: string, environment: string): Promise<string> {\n const secrets = await this.exportSecrets(projectId, environment);\n const lines = [\n '# Generated by KeyEnv',\n `# Environment: ${environment}`,\n `# Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n for (const secret of secrets) {\n const value = secret.value;\n if (value.includes('\\n') || value.includes('\"') || value.includes(\"'\") || value.includes(' ')) {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n lines.push(`${secret.key}=\"${escaped}\"`);\n } else {\n lines.push(`${secret.key}=${value}`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n }\n\n /**\n * Clear the secrets cache.\n * @param projectId - Clear cache for specific project (optional)\n * @param environment - Clear cache for specific environment (requires projectId)\n */\n clearCache(projectId?: string, environment?: string): void {\n if (projectId && environment) {\n secretsCache.delete(getCacheKey(projectId, environment));\n } else if (projectId) {\n // Clear all environments for this project\n for (const key of secretsCache.keys()) {\n if (key.startsWith(`${projectId}:`)) {\n secretsCache.delete(key);\n }\n }\n } else {\n secretsCache.clear();\n }\n }\n\n // ============================================================================\n // Environment Permission Management\n // ============================================================================\n\n /**\n * List all permissions for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @returns Array of environment permissions\n * @example\n * ```ts\n * const permissions = await client.listPermissions('project-id', 'production');\n * for (const perm of permissions) {\n * console.log(`${perm.user_email}: ${perm.role}`);\n * }\n * ```\n */\n async listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ permissions: EnvironmentPermission[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/permissions`\n );\n return response.permissions;\n }\n\n /**\n * Set a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to set permission for\n * @param role - The permission role ('none', 'read', 'write', or 'admin')\n * @returns The created or updated permission\n * @example\n * ```ts\n * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');\n * console.log(`Set ${permission.user_email} to ${permission.role}`);\n * ```\n */\n async setPermission(\n projectId: string, environment: string, userId: string, role: EnvironmentRole\n ): Promise<EnvironmentPermission> {\n const response = await this.request<{ permission: EnvironmentPermission }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,\n { role }\n );\n return response.permission;\n }\n\n /**\n * Delete a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to delete permission for\n * @example\n * ```ts\n * await client.deletePermission('project-id', 'production', 'user-id');\n * ```\n */\n async deletePermission(projectId: string, environment: string, userId: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`\n );\n }\n\n /**\n * Bulk set permissions for multiple users in an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param permissions - Array of user permissions to set\n * @returns Array of created or updated permissions\n * @example\n * ```ts\n * const permissions = await client.bulkSetPermissions('project-id', 'production', [\n * { userId: 'user-1', role: 'write' },\n * { userId: 'user-2', role: 'read' },\n * ]);\n * ```\n */\n async bulkSetPermissions(\n projectId: string, environment: string, permissions: Array<{ userId: string; role: EnvironmentRole }>\n ): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ permissions: EnvironmentPermission[] }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions`,\n { permissions: permissions.map(p => ({ user_id: p.userId, role: p.role })) }\n );\n return response.permissions;\n }\n\n /**\n * Get the current user's permissions for all environments in a project.\n * @param projectId - The project ID\n * @returns The user's permissions and team admin status\n * @example\n * ```ts\n * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');\n * for (const perm of permissions) {\n * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);\n * }\n * ```\n */\n async getMyPermissions(projectId: string): Promise<MyPermissionsResponse> {\n return this.request<MyPermissionsResponse>('GET', `/api/v1/projects/${projectId}/my-permissions`);\n }\n\n /**\n * Get default permission settings for a project's environments.\n * @param projectId - The project ID\n * @returns Array of project default permissions\n * @example\n * ```ts\n * const defaults = await client.getProjectDefaults('project-id');\n * for (const def of defaults) {\n * console.log(`${def.environment_name}: ${def.default_role}`);\n * }\n * ```\n */\n async getProjectDefaults(projectId: string): Promise<ProjectDefault[]> {\n const response = await this.request<{ defaults: ProjectDefault[] }>(\n 'GET', `/api/v1/projects/${projectId}/permissions/defaults`\n );\n return response.defaults;\n }\n\n /**\n * Set default permission settings for a project's environments.\n * @param projectId - The project ID\n * @param defaults - Array of default permissions to set\n * @returns Array of updated project default permissions\n * @example\n * ```ts\n * const defaults = await client.setProjectDefaults('project-id', [\n * { environmentName: 'development', defaultRole: 'write' },\n * { environmentName: 'production', defaultRole: 'read' },\n * ]);\n * ```\n */\n async setProjectDefaults(\n projectId: string, defaults: Array<{ environmentName: string; defaultRole: EnvironmentRole }>\n ): Promise<ProjectDefault[]> {\n const response = await this.request<{ defaults: ProjectDefault[] }>(\n 'PUT', `/api/v1/projects/${projectId}/permissions/defaults`,\n { defaults: defaults.map(d => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }\n );\n return response.defaults;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/client.ts"],"sourcesContent":["/** KeyEnv client configuration options */\nexport interface KeyEnvOptions {\n /** Service token for authentication */\n token: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */\n cacheTtl?: number;\n /** Custom API base URL (default: https://api.keyenv.dev). Also configurable via KEYENV_API_URL env var. */\n baseUrl?: string;\n}\n\n/** User or service token info */\nexport interface User {\n id: string;\n email?: string;\n name?: string;\n clerk_id?: string;\n avatar_url?: string;\n /** Present for service tokens */\n auth_type?: 'service_token' | 'user';\n /** Team ID (for service tokens) */\n team_id?: string;\n /** Project IDs (for project-scoped service tokens) */\n project_ids?: string[];\n /** Token scopes (for service tokens) */\n scopes?: string[];\n created_at: string;\n}\n\n/** Project */\nexport interface Project {\n id: string;\n team_id: string;\n name: string;\n slug: string;\n description?: string;\n created_at: string;\n}\n\n/** Environment */\nexport interface Environment {\n id: string;\n project_id: string;\n name: string;\n inherits_from?: string;\n created_at: string;\n}\n\n/** Project with environments */\nexport interface ProjectWithEnvironments extends Project {\n environments: Environment[];\n}\n\n/** Secret (without value) */\nexport interface Secret {\n id: string;\n environment_id: string;\n key: string;\n type: string;\n description?: string;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\n/** Secret with decrypted value */\nexport interface SecretWithValue extends Secret {\n value: string;\n inherited_from?: string;\n}\n\n/** Secret history entry */\nexport interface SecretHistory {\n id: string;\n secret_id: string;\n value: string;\n version: number;\n changed_by?: string;\n changed_at: string;\n}\n\n/** Bulk import request item */\nexport interface BulkSecretItem {\n key: string;\n value: string;\n description?: string;\n}\n\n/** Bulk import result */\nexport interface BulkImportResult {\n created: number;\n updated: number;\n skipped: number;\n}\n\n/** API error response */\nexport interface ApiError {\n error: string;\n code?: string;\n details?: Record<string, unknown>;\n}\n\n/** KeyEnv API error */\nexport class KeyEnvError extends Error {\n public readonly status: number;\n public readonly code?: string;\n public readonly details?: Record<string, unknown>;\n\n constructor(message: string, status: number, code?: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'KeyEnvError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/** Environment permission role */\nexport type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';\n\n/** Environment permission for a user */\nexport interface EnvironmentPermission {\n id: string;\n environment_id: string;\n user_id: string;\n role: EnvironmentRole;\n user_email?: string;\n user_name?: string;\n granted_by?: string;\n created_at: string;\n updated_at: string;\n}\n\n/** User's permission for an environment */\nexport interface MyPermission {\n environment_id: string;\n environment_name: string;\n role: EnvironmentRole;\n can_read: boolean;\n can_write: boolean;\n can_admin: boolean;\n}\n\n/** Response for getting user's permissions */\nexport interface MyPermissionsResponse {\n permissions: MyPermission[];\n is_team_admin: boolean;\n}\n\n/** Project default permission for an environment */\nexport interface ProjectDefault {\n id: string;\n project_id: string;\n environment_name: string;\n default_role: EnvironmentRole;\n created_at: string;\n}\n","import type {\n KeyEnvOptions,\n User,\n Project,\n ProjectWithEnvironments,\n Environment,\n Secret,\n SecretWithValue,\n SecretHistory,\n BulkSecretItem,\n BulkImportResult,\n ApiError,\n EnvironmentRole,\n EnvironmentPermission,\n MyPermissionsResponse,\n ProjectDefault,\n} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\nfunction getCacheKey(projectId: string, environment: string): string {\n return `${projectId}:${environment}`;\n}\n\n/**\n * KeyEnv API client for managing secrets\n *\n * @example\n * ```ts\n * import { KeyEnv } from 'keyenv';\n *\n * const client = new KeyEnv({ token: process.env.KEYENV_TOKEN });\n *\n * // Export all secrets for an environment\n * const secrets = await client.exportSecrets('project-id', 'production');\n * ```\n */\nexport class KeyEnv {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly cacheTtl: number;\n private readonly secretsCache = new Map<string, { secrets: SecretWithValue[]; expiresAt: number }>();\n\n constructor(options: KeyEnvOptions) {\n if (!options.token) {\n throw new Error('KeyEnv token is required');\n }\n this.token = options.token;\n // Base URL: constructor option → env var → default\n this.baseUrl = (options.baseUrl ?? process.env.KEYENV_API_URL ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n // Cache TTL: constructor option → env var → 0 (disabled)\n this.cacheTtl = options.cacheTtl ??\n (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'keyenv-node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n let errorData: ApiError = { error: 'Unknown error' };\n try {\n errorData = await response.json() as ApiError;\n } catch {\n errorData = { error: response.statusText };\n }\n throw new KeyEnvError(errorData.error, response.status, errorData.code, errorData.details);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof KeyEnvError) throw error;\n if (error instanceof Error && error.name === 'AbortError') {\n throw new KeyEnvError('Request timeout', 408);\n }\n throw new KeyEnvError(error instanceof Error ? error.message : 'Network error', 0);\n }\n }\n\n /** Get the current user or service token info */\n async getCurrentUser(): Promise<User> {\n const response = await this.request<{ data: User }>('GET', '/api/v1/users/me');\n return response.data;\n }\n\n /** Validate the token and return user info */\n async validateToken(): Promise<User> {\n return this.getCurrentUser();\n }\n\n /** List all accessible projects */\n async listProjects(): Promise<Project[]> {\n const response = await this.request<{ data: Project[] }>('GET', '/api/v1/projects');\n return response.data;\n }\n\n /** Get a project by ID */\n async getProject(projectId: string): Promise<ProjectWithEnvironments> {\n const response = await this.request<{ data: ProjectWithEnvironments }>('GET', `/api/v1/projects/${projectId}`);\n return response.data;\n }\n\n /** Create a new project */\n async createProject(teamId: string, name: string): Promise<Project> {\n const response = await this.request<{ data: Project }>('POST', '/api/v1/projects', { team_id: teamId, name });\n return response.data;\n }\n\n /** Delete a project */\n async deleteProject(projectId: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}`);\n }\n\n /** List environments in a project */\n async listEnvironments(projectId: string): Promise<Environment[]> {\n const response = await this.request<{ data: Environment[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments`\n );\n return response.data;\n }\n\n /** Create a new environment */\n async createEnvironment(projectId: string, name: string, inheritsFrom?: string): Promise<Environment> {\n const response = await this.request<{ data: Environment }>(\n 'POST', `/api/v1/projects/${projectId}/environments`,\n { name, inherits_from: inheritsFrom }\n );\n return response.data;\n }\n\n /** Delete an environment */\n async deleteEnvironment(projectId: string, environment: string): Promise<void> {\n await this.request<void>('DELETE', `/api/v1/projects/${projectId}/environments/${environment}`);\n }\n\n /** List secrets in an environment (keys and metadata only) */\n async listSecrets(projectId: string, environment: string): Promise<Secret[]> {\n const response = await this.request<{ data: Secret[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets`\n );\n return response.data;\n }\n\n /**\n * Export all secrets with their decrypted values.\n * Results are cached when cacheTtl > 0.\n * @example\n * ```ts\n * const secrets = await client.exportSecrets('project-id', 'production');\n * for (const secret of secrets) {\n * process.env[secret.key] = secret.value;\n * }\n * ```\n */\n async exportSecrets(projectId: string, environment: string): Promise<SecretWithValue[]> {\n const cacheKey = getCacheKey(projectId, environment);\n\n // Check cache if TTL > 0\n if (this.cacheTtl > 0) {\n const cached = this.secretsCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.secrets;\n }\n // Delete expired entry to prevent memory leaks\n if (cached) {\n this.secretsCache.delete(cacheKey);\n }\n }\n\n const response = await this.request<{ data: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\n );\n\n // Store in cache if TTL > 0\n if (this.cacheTtl > 0) {\n this.secretsCache.set(cacheKey, {\n secrets: response.data,\n expiresAt: Date.now() + (this.cacheTtl * 1000),\n });\n }\n\n return response.data;\n }\n\n /**\n * Export secrets as a key-value object\n * @example\n * ```ts\n * const env = await client.exportSecretsAsObject('project-id', 'production');\n * // { DATABASE_URL: '...', API_KEY: '...' }\n * ```\n */\n async exportSecretsAsObject(projectId: string, environment: string): Promise<Record<string, string>> {\n const secrets = await this.exportSecrets(projectId, environment);\n return Object.fromEntries(secrets.map((s) => [s.key, s.value]));\n }\n\n /** Get a single secret with its value */\n async getSecret(projectId: string, environment: string, key: string): Promise<SecretWithValue> {\n const response = await this.request<{ data: SecretWithValue }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n return response.data;\n }\n\n /** Create a new secret */\n async createSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ data: Secret }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets`,\n { key, value, description }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /** Update a secret's value */\n async updateSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n const response = await this.request<{ data: Secret }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,\n { value, description }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /** Set a secret (create or update) */\n async setSecret(\n projectId: string, environment: string, key: string, value: string, description?: string\n ): Promise<Secret> {\n try {\n return await this.updateSecret(projectId, environment, key, value, description);\n } catch (error) {\n if (error instanceof KeyEnvError && error.status === 404) {\n return this.createSecret(projectId, environment, key, value, description);\n }\n throw error;\n }\n }\n\n /** Delete a secret */\n async deleteSecret(projectId: string, environment: string, key: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`\n );\n this.clearCache(projectId, environment);\n }\n\n /** Get secret version history */\n async getSecretHistory(projectId: string, environment: string, key: string): Promise<SecretHistory[]> {\n const response = await this.request<{ data: SecretHistory[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}/history`\n );\n return response.data;\n }\n\n /**\n * Bulk import secrets\n * @example\n * ```ts\n * await client.bulkImport('project-id', 'development', [\n * { key: 'DATABASE_URL', value: 'postgres://...' },\n * { key: 'API_KEY', value: 'sk_...' },\n * ], { overwrite: true });\n * ```\n */\n async bulkImport(\n projectId: string, environment: string, secrets: BulkSecretItem[], options: { overwrite?: boolean } = {}\n ): Promise<BulkImportResult> {\n const response = await this.request<{ data: BulkImportResult }>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\n this.clearCache(projectId, environment);\n return response.data;\n }\n\n /**\n * Load secrets into process.env\n * @example\n * ```ts\n * await client.loadEnv('project-id', 'production');\n * console.log(process.env.DATABASE_URL);\n * ```\n */\n async loadEnv(projectId: string, environment: string): Promise<number> {\n const secrets = await this.exportSecrets(projectId, environment);\n for (const secret of secrets) {\n process.env[secret.key] = secret.value;\n }\n return secrets.length;\n }\n\n /** Generate .env file content from secrets */\n async generateEnvFile(projectId: string, environment: string): Promise<string> {\n const secrets = await this.exportSecrets(projectId, environment);\n const lines = [\n '# Generated by KeyEnv',\n `# Environment: ${environment}`,\n `# Generated at: ${new Date().toISOString()}`,\n '',\n ];\n\n for (const secret of secrets) {\n const value = secret.value;\n if (value.includes('\\n') || value.includes('\"') || value.includes(\"'\") || value.includes(' ') || value.includes('$')) {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n').replace(/\\$/g, '\\\\$');\n lines.push(`${secret.key}=\"${escaped}\"`);\n } else {\n lines.push(`${secret.key}=${value}`);\n }\n }\n\n return lines.join('\\n') + '\\n';\n }\n\n /**\n * Clear the secrets cache.\n * @param projectId - Clear cache for specific project (optional)\n * @param environment - Clear cache for specific environment (requires projectId)\n */\n clearCache(projectId?: string, environment?: string): void {\n if (projectId && environment) {\n this.secretsCache.delete(getCacheKey(projectId, environment));\n } else if (projectId) {\n // Clear all environments for this project\n for (const key of this.secretsCache.keys()) {\n if (key.startsWith(`${projectId}:`)) {\n this.secretsCache.delete(key);\n }\n }\n } else {\n this.secretsCache.clear();\n }\n }\n\n // ============================================================================\n // Environment Permission Management\n // ============================================================================\n\n /**\n * List all permissions for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @returns Array of environment permissions\n * @example\n * ```ts\n * const permissions = await client.listPermissions('project-id', 'production');\n * for (const perm of permissions) {\n * console.log(`${perm.user_email}: ${perm.role}`);\n * }\n * ```\n */\n async listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ data: EnvironmentPermission[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/permissions`\n );\n return response.data;\n }\n\n /**\n * Set a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to set permission for\n * @param role - The permission role ('none', 'read', 'write', or 'admin')\n * @returns The created or updated permission\n * @example\n * ```ts\n * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');\n * console.log(`Set ${permission.user_email} to ${permission.role}`);\n * ```\n */\n async setPermission(\n projectId: string, environment: string, userId: string, role: EnvironmentRole\n ): Promise<EnvironmentPermission> {\n const response = await this.request<{ data: EnvironmentPermission }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,\n { role }\n );\n return response.data;\n }\n\n /**\n * Delete a user's permission for an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param userId - The user ID to delete permission for\n * @example\n * ```ts\n * await client.deletePermission('project-id', 'production', 'user-id');\n * ```\n */\n async deletePermission(projectId: string, environment: string, userId: string): Promise<void> {\n await this.request<void>(\n 'DELETE', `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`\n );\n }\n\n /**\n * Bulk set permissions for multiple users in an environment.\n * @param projectId - The project ID\n * @param environment - The environment name\n * @param permissions - Array of user permissions to set\n * @returns Array of created or updated permissions\n * @example\n * ```ts\n * const permissions = await client.bulkSetPermissions('project-id', 'production', [\n * { userId: 'user-1', role: 'write' },\n * { userId: 'user-2', role: 'read' },\n * ]);\n * ```\n */\n async bulkSetPermissions(\n projectId: string, environment: string, permissions: Array<{ userId: string; role: EnvironmentRole }>\n ): Promise<EnvironmentPermission[]> {\n const response = await this.request<{ data: EnvironmentPermission[] }>(\n 'PUT', `/api/v1/projects/${projectId}/environments/${environment}/permissions`,\n { permissions: permissions.map(p => ({ user_id: p.userId, role: p.role })) }\n );\n return response.data;\n }\n\n /**\n * Get the current user's permissions for all environments in a project.\n * @param projectId - The project ID\n * @returns The user's permissions and team admin status\n * @example\n * ```ts\n * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');\n * for (const perm of permissions) {\n * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);\n * }\n * ```\n */\n async getMyPermissions(projectId: string): Promise<MyPermissionsResponse> {\n return this.request<MyPermissionsResponse>('GET', `/api/v1/projects/${projectId}/my-permissions`);\n }\n\n /**\n * Get default permission settings for a project's environments.\n * @param projectId - The project ID\n * @returns Array of project default permissions\n * @example\n * ```ts\n * const defaults = await client.getProjectDefaults('project-id');\n * for (const def of defaults) {\n * console.log(`${def.environment_name}: ${def.default_role}`);\n * }\n * ```\n */\n async getProjectDefaults(projectId: string): Promise<ProjectDefault[]> {\n const response = await this.request<{ data: ProjectDefault[] }>(\n 'GET', `/api/v1/projects/${projectId}/permissions/defaults`\n );\n return response.data;\n }\n\n /**\n * Set default permission settings for a project's environments.\n * @param projectId - The project ID\n * @param defaults - Array of default permissions to set\n * @returns Array of updated project default permissions\n * @example\n * ```ts\n * const defaults = await client.setProjectDefaults('project-id', [\n * { environmentName: 'development', defaultRole: 'write' },\n * { environmentName: 'production', defaultRole: 'read' },\n * ]);\n * ```\n */\n async setProjectDefaults(\n projectId: string, defaults: Array<{ environmentName: string; defaultRole: EnvironmentRole }>\n ): Promise<ProjectDefault[]> {\n const response = await this.request<{ data: ProjectDefault[] }>(\n 'PUT', `/api/v1/projects/${projectId}/permissions/defaults`,\n { defaults: defaults.map(d => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }\n );\n return response.data;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyenv",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Official Node.js SDK for KeyEnv - Secure secrets management",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"build": "tsup",
|
|
20
20
|
"test": "vitest run",
|
|
21
21
|
"test:watch": "vitest",
|
|
22
|
+
"test:integration": "vitest run src/__tests__/integration.test.ts",
|
|
22
23
|
"lint": "eslint src --ext .ts",
|
|
23
24
|
"typecheck": "tsc --noEmit",
|
|
24
25
|
"prepublishOnly": "npm run build"
|