keyenv 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -103,6 +103,19 @@ for (const env of project.environments) {
103
103
  }
104
104
  ```
105
105
 
106
+ ### Service Token Info
107
+
108
+ ```typescript
109
+ // Get current user or service token info
110
+ const user = await client.getCurrentUser();
111
+
112
+ if (user.auth_type === 'service_token') {
113
+ // Service tokens can access multiple projects
114
+ console.log('Projects:', user.project_ids);
115
+ console.log('Scopes:', user.scopes);
116
+ }
117
+ ```
118
+
106
119
  ## Error Handling
107
120
 
108
121
  ```typescript
@@ -156,6 +169,12 @@ Create a new KeyEnv client.
156
169
  | `bulkImport(projectId, env, secrets)` | Bulk import secrets |
157
170
  | `loadEnv(projectId, env)` | Load secrets into process.env |
158
171
  | `generateEnvFile(projectId, env)` | Generate .env file content |
172
+ | `listPermissions(projectId, env)` | List permissions for an environment |
173
+ | `setPermission(projectId, env, userId, role)` | Set user's permission |
174
+ | `deletePermission(projectId, env, userId)` | Delete user's permission |
175
+ | `getMyPermissions(projectId)` | Get current user's permissions |
176
+ | `getProjectDefaults(projectId)` | Get default permissions |
177
+ | `setProjectDefaults(projectId, defaults)` | Set default permissions |
159
178
 
160
179
  ## License
161
180
 
package/dist/index.d.mts CHANGED
@@ -4,6 +4,8 @@ interface KeyEnvOptions {
4
4
  token: string;
5
5
  /** Request timeout in milliseconds (default: 30000) */
6
6
  timeout?: number;
7
+ /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */
8
+ cacheTtl?: number;
7
9
  }
8
10
  /** User or service token info */
9
11
  interface User {
@@ -16,8 +18,8 @@ interface User {
16
18
  auth_type?: 'service_token' | 'user';
17
19
  /** Team ID (for service tokens) */
18
20
  team_id?: string;
19
- /** Project ID (for project-scoped service tokens) */
20
- project_id?: string;
21
+ /** Project IDs (for project-scoped service tokens) */
22
+ project_ids?: string[];
21
23
  /** Token scopes (for service tokens) */
22
24
  scopes?: string[];
23
25
  created_at: string;
@@ -87,6 +89,42 @@ declare class KeyEnvError extends Error {
87
89
  readonly details?: Record<string, unknown>;
88
90
  constructor(message: string, status: number, code?: string, details?: Record<string, unknown>);
89
91
  }
92
+ /** Environment permission role */
93
+ type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';
94
+ /** Environment permission for a user */
95
+ interface EnvironmentPermission {
96
+ id: string;
97
+ environment_id: string;
98
+ user_id: string;
99
+ role: EnvironmentRole;
100
+ user_email?: string;
101
+ user_name?: string;
102
+ granted_by?: string;
103
+ created_at: string;
104
+ updated_at: string;
105
+ }
106
+ /** User's permission for an environment */
107
+ interface MyPermission {
108
+ environment_id: string;
109
+ environment_name: string;
110
+ role: EnvironmentRole;
111
+ can_read: boolean;
112
+ can_write: boolean;
113
+ can_admin: boolean;
114
+ }
115
+ /** Response for getting user's permissions */
116
+ interface MyPermissionsResponse {
117
+ permissions: MyPermission[];
118
+ is_team_admin: boolean;
119
+ }
120
+ /** Project default permission for an environment */
121
+ interface ProjectDefault {
122
+ id: string;
123
+ project_id: string;
124
+ environment_name: string;
125
+ default_role: EnvironmentRole;
126
+ created_at: string;
127
+ }
90
128
 
91
129
  /**
92
130
  * KeyEnv API client for managing secrets
@@ -104,6 +142,7 @@ declare class KeyEnvError extends Error {
104
142
  declare class KeyEnv {
105
143
  private readonly token;
106
144
  private readonly timeout;
145
+ private readonly cacheTtl;
107
146
  constructor(options: KeyEnvOptions);
108
147
  private request;
109
148
  /** Get the current user or service token info */
@@ -127,7 +166,8 @@ declare class KeyEnv {
127
166
  /** List secrets in an environment (keys and metadata only) */
128
167
  listSecrets(projectId: string, environment: string): Promise<Secret[]>;
129
168
  /**
130
- * Export all secrets with their decrypted values
169
+ * Export all secrets with their decrypted values.
170
+ * Results are cached when cacheTtl > 0.
131
171
  * @example
132
172
  * ```ts
133
173
  * const secrets = await client.exportSecrets('project-id', 'production');
@@ -182,6 +222,112 @@ declare class KeyEnv {
182
222
  loadEnv(projectId: string, environment: string): Promise<number>;
183
223
  /** Generate .env file content from secrets */
184
224
  generateEnvFile(projectId: string, environment: string): Promise<string>;
225
+ /**
226
+ * Clear the secrets cache.
227
+ * @param projectId - Clear cache for specific project (optional)
228
+ * @param environment - Clear cache for specific environment (requires projectId)
229
+ */
230
+ clearCache(projectId?: string, environment?: string): void;
231
+ /**
232
+ * List all permissions for an environment.
233
+ * @param projectId - The project ID
234
+ * @param environment - The environment name
235
+ * @returns Array of environment permissions
236
+ * @example
237
+ * ```ts
238
+ * const permissions = await client.listPermissions('project-id', 'production');
239
+ * for (const perm of permissions) {
240
+ * console.log(`${perm.user_email}: ${perm.role}`);
241
+ * }
242
+ * ```
243
+ */
244
+ listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]>;
245
+ /**
246
+ * Set a user's permission for an environment.
247
+ * @param projectId - The project ID
248
+ * @param environment - The environment name
249
+ * @param userId - The user ID to set permission for
250
+ * @param role - The permission role ('none', 'read', 'write', or 'admin')
251
+ * @returns The created or updated permission
252
+ * @example
253
+ * ```ts
254
+ * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');
255
+ * console.log(`Set ${permission.user_email} to ${permission.role}`);
256
+ * ```
257
+ */
258
+ setPermission(projectId: string, environment: string, userId: string, role: EnvironmentRole): Promise<EnvironmentPermission>;
259
+ /**
260
+ * Delete a user's permission for an environment.
261
+ * @param projectId - The project ID
262
+ * @param environment - The environment name
263
+ * @param userId - The user ID to delete permission for
264
+ * @example
265
+ * ```ts
266
+ * await client.deletePermission('project-id', 'production', 'user-id');
267
+ * ```
268
+ */
269
+ deletePermission(projectId: string, environment: string, userId: string): Promise<void>;
270
+ /**
271
+ * Bulk set permissions for multiple users in an environment.
272
+ * @param projectId - The project ID
273
+ * @param environment - The environment name
274
+ * @param permissions - Array of user permissions to set
275
+ * @returns Array of created or updated permissions
276
+ * @example
277
+ * ```ts
278
+ * const permissions = await client.bulkSetPermissions('project-id', 'production', [
279
+ * { userId: 'user-1', role: 'write' },
280
+ * { userId: 'user-2', role: 'read' },
281
+ * ]);
282
+ * ```
283
+ */
284
+ bulkSetPermissions(projectId: string, environment: string, permissions: Array<{
285
+ userId: string;
286
+ role: EnvironmentRole;
287
+ }>): Promise<EnvironmentPermission[]>;
288
+ /**
289
+ * Get the current user's permissions for all environments in a project.
290
+ * @param projectId - The project ID
291
+ * @returns The user's permissions and team admin status
292
+ * @example
293
+ * ```ts
294
+ * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');
295
+ * for (const perm of permissions) {
296
+ * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);
297
+ * }
298
+ * ```
299
+ */
300
+ getMyPermissions(projectId: string): Promise<MyPermissionsResponse>;
301
+ /**
302
+ * Get default permission settings for a project's environments.
303
+ * @param projectId - The project ID
304
+ * @returns Array of project default permissions
305
+ * @example
306
+ * ```ts
307
+ * const defaults = await client.getProjectDefaults('project-id');
308
+ * for (const def of defaults) {
309
+ * console.log(`${def.environment_name}: ${def.default_role}`);
310
+ * }
311
+ * ```
312
+ */
313
+ getProjectDefaults(projectId: string): Promise<ProjectDefault[]>;
314
+ /**
315
+ * Set default permission settings for a project's environments.
316
+ * @param projectId - The project ID
317
+ * @param defaults - Array of default permissions to set
318
+ * @returns Array of updated project default permissions
319
+ * @example
320
+ * ```ts
321
+ * const defaults = await client.setProjectDefaults('project-id', [
322
+ * { environmentName: 'development', defaultRole: 'write' },
323
+ * { environmentName: 'production', defaultRole: 'read' },
324
+ * ]);
325
+ * ```
326
+ */
327
+ setProjectDefaults(projectId: string, defaults: Array<{
328
+ environmentName: string;
329
+ defaultRole: EnvironmentRole;
330
+ }>): Promise<ProjectDefault[]>;
185
331
  }
186
332
 
187
- export { type BulkImportResult, type BulkSecretItem, type Environment, KeyEnv, KeyEnvError, type KeyEnvOptions, type Project, type ProjectWithEnvironments, type Secret, type SecretHistory, type SecretWithValue, type User };
333
+ export { type BulkImportResult, type BulkSecretItem, type Environment, type EnvironmentPermission, type EnvironmentRole, KeyEnv, KeyEnvError, type KeyEnvOptions, type MyPermission, type MyPermissionsResponse, type Project, type ProjectDefault, type ProjectWithEnvironments, type Secret, type SecretHistory, type SecretWithValue, type User };
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ interface KeyEnvOptions {
4
4
  token: string;
5
5
  /** Request timeout in milliseconds (default: 30000) */
6
6
  timeout?: number;
7
+ /** Cache TTL in seconds for exportSecrets/loadEnv (default: 0 = disabled). Also configurable via KEYENV_CACHE_TTL env var. */
8
+ cacheTtl?: number;
7
9
  }
8
10
  /** User or service token info */
9
11
  interface User {
@@ -16,8 +18,8 @@ interface User {
16
18
  auth_type?: 'service_token' | 'user';
17
19
  /** Team ID (for service tokens) */
18
20
  team_id?: string;
19
- /** Project ID (for project-scoped service tokens) */
20
- project_id?: string;
21
+ /** Project IDs (for project-scoped service tokens) */
22
+ project_ids?: string[];
21
23
  /** Token scopes (for service tokens) */
22
24
  scopes?: string[];
23
25
  created_at: string;
@@ -87,6 +89,42 @@ declare class KeyEnvError extends Error {
87
89
  readonly details?: Record<string, unknown>;
88
90
  constructor(message: string, status: number, code?: string, details?: Record<string, unknown>);
89
91
  }
92
+ /** Environment permission role */
93
+ type EnvironmentRole = 'none' | 'read' | 'write' | 'admin';
94
+ /** Environment permission for a user */
95
+ interface EnvironmentPermission {
96
+ id: string;
97
+ environment_id: string;
98
+ user_id: string;
99
+ role: EnvironmentRole;
100
+ user_email?: string;
101
+ user_name?: string;
102
+ granted_by?: string;
103
+ created_at: string;
104
+ updated_at: string;
105
+ }
106
+ /** User's permission for an environment */
107
+ interface MyPermission {
108
+ environment_id: string;
109
+ environment_name: string;
110
+ role: EnvironmentRole;
111
+ can_read: boolean;
112
+ can_write: boolean;
113
+ can_admin: boolean;
114
+ }
115
+ /** Response for getting user's permissions */
116
+ interface MyPermissionsResponse {
117
+ permissions: MyPermission[];
118
+ is_team_admin: boolean;
119
+ }
120
+ /** Project default permission for an environment */
121
+ interface ProjectDefault {
122
+ id: string;
123
+ project_id: string;
124
+ environment_name: string;
125
+ default_role: EnvironmentRole;
126
+ created_at: string;
127
+ }
90
128
 
91
129
  /**
92
130
  * KeyEnv API client for managing secrets
@@ -104,6 +142,7 @@ declare class KeyEnvError extends Error {
104
142
  declare class KeyEnv {
105
143
  private readonly token;
106
144
  private readonly timeout;
145
+ private readonly cacheTtl;
107
146
  constructor(options: KeyEnvOptions);
108
147
  private request;
109
148
  /** Get the current user or service token info */
@@ -127,7 +166,8 @@ declare class KeyEnv {
127
166
  /** List secrets in an environment (keys and metadata only) */
128
167
  listSecrets(projectId: string, environment: string): Promise<Secret[]>;
129
168
  /**
130
- * Export all secrets with their decrypted values
169
+ * Export all secrets with their decrypted values.
170
+ * Results are cached when cacheTtl > 0.
131
171
  * @example
132
172
  * ```ts
133
173
  * const secrets = await client.exportSecrets('project-id', 'production');
@@ -182,6 +222,112 @@ declare class KeyEnv {
182
222
  loadEnv(projectId: string, environment: string): Promise<number>;
183
223
  /** Generate .env file content from secrets */
184
224
  generateEnvFile(projectId: string, environment: string): Promise<string>;
225
+ /**
226
+ * Clear the secrets cache.
227
+ * @param projectId - Clear cache for specific project (optional)
228
+ * @param environment - Clear cache for specific environment (requires projectId)
229
+ */
230
+ clearCache(projectId?: string, environment?: string): void;
231
+ /**
232
+ * List all permissions for an environment.
233
+ * @param projectId - The project ID
234
+ * @param environment - The environment name
235
+ * @returns Array of environment permissions
236
+ * @example
237
+ * ```ts
238
+ * const permissions = await client.listPermissions('project-id', 'production');
239
+ * for (const perm of permissions) {
240
+ * console.log(`${perm.user_email}: ${perm.role}`);
241
+ * }
242
+ * ```
243
+ */
244
+ listPermissions(projectId: string, environment: string): Promise<EnvironmentPermission[]>;
245
+ /**
246
+ * Set a user's permission for an environment.
247
+ * @param projectId - The project ID
248
+ * @param environment - The environment name
249
+ * @param userId - The user ID to set permission for
250
+ * @param role - The permission role ('none', 'read', 'write', or 'admin')
251
+ * @returns The created or updated permission
252
+ * @example
253
+ * ```ts
254
+ * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');
255
+ * console.log(`Set ${permission.user_email} to ${permission.role}`);
256
+ * ```
257
+ */
258
+ setPermission(projectId: string, environment: string, userId: string, role: EnvironmentRole): Promise<EnvironmentPermission>;
259
+ /**
260
+ * Delete a user's permission for an environment.
261
+ * @param projectId - The project ID
262
+ * @param environment - The environment name
263
+ * @param userId - The user ID to delete permission for
264
+ * @example
265
+ * ```ts
266
+ * await client.deletePermission('project-id', 'production', 'user-id');
267
+ * ```
268
+ */
269
+ deletePermission(projectId: string, environment: string, userId: string): Promise<void>;
270
+ /**
271
+ * Bulk set permissions for multiple users in an environment.
272
+ * @param projectId - The project ID
273
+ * @param environment - The environment name
274
+ * @param permissions - Array of user permissions to set
275
+ * @returns Array of created or updated permissions
276
+ * @example
277
+ * ```ts
278
+ * const permissions = await client.bulkSetPermissions('project-id', 'production', [
279
+ * { userId: 'user-1', role: 'write' },
280
+ * { userId: 'user-2', role: 'read' },
281
+ * ]);
282
+ * ```
283
+ */
284
+ bulkSetPermissions(projectId: string, environment: string, permissions: Array<{
285
+ userId: string;
286
+ role: EnvironmentRole;
287
+ }>): Promise<EnvironmentPermission[]>;
288
+ /**
289
+ * Get the current user's permissions for all environments in a project.
290
+ * @param projectId - The project ID
291
+ * @returns The user's permissions and team admin status
292
+ * @example
293
+ * ```ts
294
+ * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');
295
+ * for (const perm of permissions) {
296
+ * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);
297
+ * }
298
+ * ```
299
+ */
300
+ getMyPermissions(projectId: string): Promise<MyPermissionsResponse>;
301
+ /**
302
+ * Get default permission settings for a project's environments.
303
+ * @param projectId - The project ID
304
+ * @returns Array of project default permissions
305
+ * @example
306
+ * ```ts
307
+ * const defaults = await client.getProjectDefaults('project-id');
308
+ * for (const def of defaults) {
309
+ * console.log(`${def.environment_name}: ${def.default_role}`);
310
+ * }
311
+ * ```
312
+ */
313
+ getProjectDefaults(projectId: string): Promise<ProjectDefault[]>;
314
+ /**
315
+ * Set default permission settings for a project's environments.
316
+ * @param projectId - The project ID
317
+ * @param defaults - Array of default permissions to set
318
+ * @returns Array of updated project default permissions
319
+ * @example
320
+ * ```ts
321
+ * const defaults = await client.setProjectDefaults('project-id', [
322
+ * { environmentName: 'development', defaultRole: 'write' },
323
+ * { environmentName: 'production', defaultRole: 'read' },
324
+ * ]);
325
+ * ```
326
+ */
327
+ setProjectDefaults(projectId: string, defaults: Array<{
328
+ environmentName: string;
329
+ defaultRole: EnvironmentRole;
330
+ }>): Promise<ProjectDefault[]>;
185
331
  }
186
332
 
187
- export { type BulkImportResult, type BulkSecretItem, type Environment, KeyEnv, KeyEnvError, type KeyEnvOptions, type Project, type ProjectWithEnvironments, type Secret, type SecretHistory, type SecretWithValue, type User };
333
+ export { type BulkImportResult, type BulkSecretItem, type Environment, type EnvironmentPermission, type EnvironmentRole, KeyEnv, KeyEnvError, type KeyEnvOptions, type MyPermission, type MyPermissionsResponse, type Project, type ProjectDefault, type ProjectWithEnvironments, type Secret, type SecretHistory, type SecretWithValue, type User };
package/dist/index.js CHANGED
@@ -42,15 +42,21 @@ var KeyEnvError = class extends Error {
42
42
  // src/client.ts
43
43
  var BASE_URL = "https://api.keyenv.dev";
44
44
  var DEFAULT_TIMEOUT = 3e4;
45
+ var secretsCache = /* @__PURE__ */ new Map();
46
+ function getCacheKey(projectId, environment) {
47
+ return `${projectId}:${environment}`;
48
+ }
45
49
  var KeyEnv = class {
46
50
  token;
47
51
  timeout;
52
+ cacheTtl;
48
53
  constructor(options) {
49
54
  if (!options.token) {
50
55
  throw new Error("KeyEnv token is required");
51
56
  }
52
57
  this.token = options.token;
53
58
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
59
+ this.cacheTtl = options.cacheTtl ?? (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);
54
60
  }
55
61
  async request(method, path, body) {
56
62
  const url = `${BASE_URL}${path}`;
@@ -144,7 +150,8 @@ var KeyEnv = class {
144
150
  return response.secrets;
145
151
  }
146
152
  /**
147
- * Export all secrets with their decrypted values
153
+ * Export all secrets with their decrypted values.
154
+ * Results are cached when cacheTtl > 0.
148
155
  * @example
149
156
  * ```ts
150
157
  * const secrets = await client.exportSecrets('project-id', 'production');
@@ -154,10 +161,23 @@ var KeyEnv = class {
154
161
  * ```
155
162
  */
156
163
  async exportSecrets(projectId, environment) {
164
+ const cacheKey = getCacheKey(projectId, environment);
165
+ if (this.cacheTtl > 0) {
166
+ const cached = secretsCache.get(cacheKey);
167
+ if (cached && Date.now() < cached.expiresAt) {
168
+ return cached.secrets;
169
+ }
170
+ }
157
171
  const response = await this.request(
158
172
  "GET",
159
173
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`
160
174
  );
175
+ if (this.cacheTtl > 0) {
176
+ secretsCache.set(cacheKey, {
177
+ secrets: response.secrets,
178
+ expiresAt: Date.now() + this.cacheTtl * 1e3
179
+ });
180
+ }
161
181
  return response.secrets;
162
182
  }
163
183
  /**
@@ -187,6 +207,7 @@ var KeyEnv = class {
187
207
  `/api/v1/projects/${projectId}/environments/${environment}/secrets`,
188
208
  { key, value, description }
189
209
  );
210
+ this.clearCache(projectId, environment);
190
211
  return response.secret;
191
212
  }
192
213
  /** Update a secret's value */
@@ -196,6 +217,7 @@ var KeyEnv = class {
196
217
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,
197
218
  { value, description }
198
219
  );
220
+ this.clearCache(projectId, environment);
199
221
  return response.secret;
200
222
  }
201
223
  /** Set a secret (create or update) */
@@ -215,6 +237,7 @@ var KeyEnv = class {
215
237
  "DELETE",
216
238
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`
217
239
  );
240
+ this.clearCache(projectId, environment);
218
241
  }
219
242
  /** Get secret version history */
220
243
  async getSecretHistory(projectId, environment, key) {
@@ -235,11 +258,13 @@ var KeyEnv = class {
235
258
  * ```
236
259
  */
237
260
  async bulkImport(projectId, environment, secrets, options = {}) {
238
- return this.request(
261
+ const result = await this.request(
239
262
  "POST",
240
263
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,
241
264
  { secrets, overwrite: options.overwrite ?? false }
242
265
  );
266
+ this.clearCache(projectId, environment);
267
+ return result;
243
268
  }
244
269
  /**
245
270
  * Load secrets into process.env
@@ -276,6 +301,161 @@ var KeyEnv = class {
276
301
  }
277
302
  return lines.join("\n") + "\n";
278
303
  }
304
+ /**
305
+ * Clear the secrets cache.
306
+ * @param projectId - Clear cache for specific project (optional)
307
+ * @param environment - Clear cache for specific environment (requires projectId)
308
+ */
309
+ clearCache(projectId, environment) {
310
+ if (projectId && environment) {
311
+ secretsCache.delete(getCacheKey(projectId, environment));
312
+ } else if (projectId) {
313
+ for (const key of secretsCache.keys()) {
314
+ if (key.startsWith(`${projectId}:`)) {
315
+ secretsCache.delete(key);
316
+ }
317
+ }
318
+ } else {
319
+ secretsCache.clear();
320
+ }
321
+ }
322
+ // ============================================================================
323
+ // Environment Permission Management
324
+ // ============================================================================
325
+ /**
326
+ * List all permissions for an environment.
327
+ * @param projectId - The project ID
328
+ * @param environment - The environment name
329
+ * @returns Array of environment permissions
330
+ * @example
331
+ * ```ts
332
+ * const permissions = await client.listPermissions('project-id', 'production');
333
+ * for (const perm of permissions) {
334
+ * console.log(`${perm.user_email}: ${perm.role}`);
335
+ * }
336
+ * ```
337
+ */
338
+ async listPermissions(projectId, environment) {
339
+ const response = await this.request(
340
+ "GET",
341
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions`
342
+ );
343
+ return response.permissions;
344
+ }
345
+ /**
346
+ * Set a user's permission for an environment.
347
+ * @param projectId - The project ID
348
+ * @param environment - The environment name
349
+ * @param userId - The user ID to set permission for
350
+ * @param role - The permission role ('none', 'read', 'write', or 'admin')
351
+ * @returns The created or updated permission
352
+ * @example
353
+ * ```ts
354
+ * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');
355
+ * console.log(`Set ${permission.user_email} to ${permission.role}`);
356
+ * ```
357
+ */
358
+ async setPermission(projectId, environment, userId, role) {
359
+ const response = await this.request(
360
+ "PUT",
361
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,
362
+ { role }
363
+ );
364
+ return response.permission;
365
+ }
366
+ /**
367
+ * Delete a user's permission for an environment.
368
+ * @param projectId - The project ID
369
+ * @param environment - The environment name
370
+ * @param userId - The user ID to delete permission for
371
+ * @example
372
+ * ```ts
373
+ * await client.deletePermission('project-id', 'production', 'user-id');
374
+ * ```
375
+ */
376
+ async deletePermission(projectId, environment, userId) {
377
+ await this.request(
378
+ "DELETE",
379
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`
380
+ );
381
+ }
382
+ /**
383
+ * Bulk set permissions for multiple users in an environment.
384
+ * @param projectId - The project ID
385
+ * @param environment - The environment name
386
+ * @param permissions - Array of user permissions to set
387
+ * @returns Array of created or updated permissions
388
+ * @example
389
+ * ```ts
390
+ * const permissions = await client.bulkSetPermissions('project-id', 'production', [
391
+ * { userId: 'user-1', role: 'write' },
392
+ * { userId: 'user-2', role: 'read' },
393
+ * ]);
394
+ * ```
395
+ */
396
+ async bulkSetPermissions(projectId, environment, permissions) {
397
+ const response = await this.request(
398
+ "PUT",
399
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions`,
400
+ { permissions: permissions.map((p) => ({ user_id: p.userId, role: p.role })) }
401
+ );
402
+ return response.permissions;
403
+ }
404
+ /**
405
+ * Get the current user's permissions for all environments in a project.
406
+ * @param projectId - The project ID
407
+ * @returns The user's permissions and team admin status
408
+ * @example
409
+ * ```ts
410
+ * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');
411
+ * for (const perm of permissions) {
412
+ * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);
413
+ * }
414
+ * ```
415
+ */
416
+ async getMyPermissions(projectId) {
417
+ return this.request("GET", `/api/v1/projects/${projectId}/my-permissions`);
418
+ }
419
+ /**
420
+ * Get default permission settings for a project's environments.
421
+ * @param projectId - The project ID
422
+ * @returns Array of project default permissions
423
+ * @example
424
+ * ```ts
425
+ * const defaults = await client.getProjectDefaults('project-id');
426
+ * for (const def of defaults) {
427
+ * console.log(`${def.environment_name}: ${def.default_role}`);
428
+ * }
429
+ * ```
430
+ */
431
+ async getProjectDefaults(projectId) {
432
+ const response = await this.request(
433
+ "GET",
434
+ `/api/v1/projects/${projectId}/permissions/defaults`
435
+ );
436
+ return response.defaults;
437
+ }
438
+ /**
439
+ * Set default permission settings for a project's environments.
440
+ * @param projectId - The project ID
441
+ * @param defaults - Array of default permissions to set
442
+ * @returns Array of updated project default permissions
443
+ * @example
444
+ * ```ts
445
+ * const defaults = await client.setProjectDefaults('project-id', [
446
+ * { environmentName: 'development', defaultRole: 'write' },
447
+ * { environmentName: 'production', defaultRole: 'read' },
448
+ * ]);
449
+ * ```
450
+ */
451
+ async setProjectDefaults(projectId, defaults) {
452
+ const response = await this.request(
453
+ "PUT",
454
+ `/api/v1/projects/${projectId}/permissions/defaults`,
455
+ { defaults: defaults.map((d) => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }
456
+ );
457
+ return response.defaults;
458
+ }
279
459
  };
280
460
  // Annotate the CommonJS export names for ESM import in node:
281
461
  0 && (module.exports = {
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} 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}\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 ID (for project-scoped service tokens) */\n project_id?: 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","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} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\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\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 }\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 * @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 response = await this.request<{ secrets: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\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 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 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 }\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 return this.request<BulkImportResult>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\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"],"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}\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":[]}
package/dist/index.mjs CHANGED
@@ -15,15 +15,21 @@ var KeyEnvError = class extends Error {
15
15
  // src/client.ts
16
16
  var BASE_URL = "https://api.keyenv.dev";
17
17
  var DEFAULT_TIMEOUT = 3e4;
18
+ var secretsCache = /* @__PURE__ */ new Map();
19
+ function getCacheKey(projectId, environment) {
20
+ return `${projectId}:${environment}`;
21
+ }
18
22
  var KeyEnv = class {
19
23
  token;
20
24
  timeout;
25
+ cacheTtl;
21
26
  constructor(options) {
22
27
  if (!options.token) {
23
28
  throw new Error("KeyEnv token is required");
24
29
  }
25
30
  this.token = options.token;
26
31
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
32
+ this.cacheTtl = options.cacheTtl ?? (process.env.KEYENV_CACHE_TTL ? parseInt(process.env.KEYENV_CACHE_TTL, 10) : 0);
27
33
  }
28
34
  async request(method, path, body) {
29
35
  const url = `${BASE_URL}${path}`;
@@ -117,7 +123,8 @@ var KeyEnv = class {
117
123
  return response.secrets;
118
124
  }
119
125
  /**
120
- * Export all secrets with their decrypted values
126
+ * Export all secrets with their decrypted values.
127
+ * Results are cached when cacheTtl > 0.
121
128
  * @example
122
129
  * ```ts
123
130
  * const secrets = await client.exportSecrets('project-id', 'production');
@@ -127,10 +134,23 @@ var KeyEnv = class {
127
134
  * ```
128
135
  */
129
136
  async exportSecrets(projectId, environment) {
137
+ const cacheKey = getCacheKey(projectId, environment);
138
+ if (this.cacheTtl > 0) {
139
+ const cached = secretsCache.get(cacheKey);
140
+ if (cached && Date.now() < cached.expiresAt) {
141
+ return cached.secrets;
142
+ }
143
+ }
130
144
  const response = await this.request(
131
145
  "GET",
132
146
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`
133
147
  );
148
+ if (this.cacheTtl > 0) {
149
+ secretsCache.set(cacheKey, {
150
+ secrets: response.secrets,
151
+ expiresAt: Date.now() + this.cacheTtl * 1e3
152
+ });
153
+ }
134
154
  return response.secrets;
135
155
  }
136
156
  /**
@@ -160,6 +180,7 @@ var KeyEnv = class {
160
180
  `/api/v1/projects/${projectId}/environments/${environment}/secrets`,
161
181
  { key, value, description }
162
182
  );
183
+ this.clearCache(projectId, environment);
163
184
  return response.secret;
164
185
  }
165
186
  /** Update a secret's value */
@@ -169,6 +190,7 @@ var KeyEnv = class {
169
190
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`,
170
191
  { value, description }
171
192
  );
193
+ this.clearCache(projectId, environment);
172
194
  return response.secret;
173
195
  }
174
196
  /** Set a secret (create or update) */
@@ -188,6 +210,7 @@ var KeyEnv = class {
188
210
  "DELETE",
189
211
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/${key}`
190
212
  );
213
+ this.clearCache(projectId, environment);
191
214
  }
192
215
  /** Get secret version history */
193
216
  async getSecretHistory(projectId, environment, key) {
@@ -208,11 +231,13 @@ var KeyEnv = class {
208
231
  * ```
209
232
  */
210
233
  async bulkImport(projectId, environment, secrets, options = {}) {
211
- return this.request(
234
+ const result = await this.request(
212
235
  "POST",
213
236
  `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,
214
237
  { secrets, overwrite: options.overwrite ?? false }
215
238
  );
239
+ this.clearCache(projectId, environment);
240
+ return result;
216
241
  }
217
242
  /**
218
243
  * Load secrets into process.env
@@ -249,6 +274,161 @@ var KeyEnv = class {
249
274
  }
250
275
  return lines.join("\n") + "\n";
251
276
  }
277
+ /**
278
+ * Clear the secrets cache.
279
+ * @param projectId - Clear cache for specific project (optional)
280
+ * @param environment - Clear cache for specific environment (requires projectId)
281
+ */
282
+ clearCache(projectId, environment) {
283
+ if (projectId && environment) {
284
+ secretsCache.delete(getCacheKey(projectId, environment));
285
+ } else if (projectId) {
286
+ for (const key of secretsCache.keys()) {
287
+ if (key.startsWith(`${projectId}:`)) {
288
+ secretsCache.delete(key);
289
+ }
290
+ }
291
+ } else {
292
+ secretsCache.clear();
293
+ }
294
+ }
295
+ // ============================================================================
296
+ // Environment Permission Management
297
+ // ============================================================================
298
+ /**
299
+ * List all permissions for an environment.
300
+ * @param projectId - The project ID
301
+ * @param environment - The environment name
302
+ * @returns Array of environment permissions
303
+ * @example
304
+ * ```ts
305
+ * const permissions = await client.listPermissions('project-id', 'production');
306
+ * for (const perm of permissions) {
307
+ * console.log(`${perm.user_email}: ${perm.role}`);
308
+ * }
309
+ * ```
310
+ */
311
+ async listPermissions(projectId, environment) {
312
+ const response = await this.request(
313
+ "GET",
314
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions`
315
+ );
316
+ return response.permissions;
317
+ }
318
+ /**
319
+ * Set a user's permission for an environment.
320
+ * @param projectId - The project ID
321
+ * @param environment - The environment name
322
+ * @param userId - The user ID to set permission for
323
+ * @param role - The permission role ('none', 'read', 'write', or 'admin')
324
+ * @returns The created or updated permission
325
+ * @example
326
+ * ```ts
327
+ * const permission = await client.setPermission('project-id', 'production', 'user-id', 'write');
328
+ * console.log(`Set ${permission.user_email} to ${permission.role}`);
329
+ * ```
330
+ */
331
+ async setPermission(projectId, environment, userId, role) {
332
+ const response = await this.request(
333
+ "PUT",
334
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`,
335
+ { role }
336
+ );
337
+ return response.permission;
338
+ }
339
+ /**
340
+ * Delete a user's permission for an environment.
341
+ * @param projectId - The project ID
342
+ * @param environment - The environment name
343
+ * @param userId - The user ID to delete permission for
344
+ * @example
345
+ * ```ts
346
+ * await client.deletePermission('project-id', 'production', 'user-id');
347
+ * ```
348
+ */
349
+ async deletePermission(projectId, environment, userId) {
350
+ await this.request(
351
+ "DELETE",
352
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions/${userId}`
353
+ );
354
+ }
355
+ /**
356
+ * Bulk set permissions for multiple users in an environment.
357
+ * @param projectId - The project ID
358
+ * @param environment - The environment name
359
+ * @param permissions - Array of user permissions to set
360
+ * @returns Array of created or updated permissions
361
+ * @example
362
+ * ```ts
363
+ * const permissions = await client.bulkSetPermissions('project-id', 'production', [
364
+ * { userId: 'user-1', role: 'write' },
365
+ * { userId: 'user-2', role: 'read' },
366
+ * ]);
367
+ * ```
368
+ */
369
+ async bulkSetPermissions(projectId, environment, permissions) {
370
+ const response = await this.request(
371
+ "PUT",
372
+ `/api/v1/projects/${projectId}/environments/${environment}/permissions`,
373
+ { permissions: permissions.map((p) => ({ user_id: p.userId, role: p.role })) }
374
+ );
375
+ return response.permissions;
376
+ }
377
+ /**
378
+ * Get the current user's permissions for all environments in a project.
379
+ * @param projectId - The project ID
380
+ * @returns The user's permissions and team admin status
381
+ * @example
382
+ * ```ts
383
+ * const { permissions, is_team_admin } = await client.getMyPermissions('project-id');
384
+ * for (const perm of permissions) {
385
+ * console.log(`${perm.environment_name}: ${perm.role} (can_write: ${perm.can_write})`);
386
+ * }
387
+ * ```
388
+ */
389
+ async getMyPermissions(projectId) {
390
+ return this.request("GET", `/api/v1/projects/${projectId}/my-permissions`);
391
+ }
392
+ /**
393
+ * Get default permission settings for a project's environments.
394
+ * @param projectId - The project ID
395
+ * @returns Array of project default permissions
396
+ * @example
397
+ * ```ts
398
+ * const defaults = await client.getProjectDefaults('project-id');
399
+ * for (const def of defaults) {
400
+ * console.log(`${def.environment_name}: ${def.default_role}`);
401
+ * }
402
+ * ```
403
+ */
404
+ async getProjectDefaults(projectId) {
405
+ const response = await this.request(
406
+ "GET",
407
+ `/api/v1/projects/${projectId}/permissions/defaults`
408
+ );
409
+ return response.defaults;
410
+ }
411
+ /**
412
+ * Set default permission settings for a project's environments.
413
+ * @param projectId - The project ID
414
+ * @param defaults - Array of default permissions to set
415
+ * @returns Array of updated project default permissions
416
+ * @example
417
+ * ```ts
418
+ * const defaults = await client.setProjectDefaults('project-id', [
419
+ * { environmentName: 'development', defaultRole: 'write' },
420
+ * { environmentName: 'production', defaultRole: 'read' },
421
+ * ]);
422
+ * ```
423
+ */
424
+ async setProjectDefaults(projectId, defaults) {
425
+ const response = await this.request(
426
+ "PUT",
427
+ `/api/v1/projects/${projectId}/permissions/defaults`,
428
+ { defaults: defaults.map((d) => ({ environment_name: d.environmentName, default_role: d.defaultRole })) }
429
+ );
430
+ return response.defaults;
431
+ }
252
432
  };
253
433
  export {
254
434
  KeyEnv,
@@ -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}\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 ID (for project-scoped service tokens) */\n project_id?: 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","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} from './types.js';\nimport { KeyEnvError } from './types.js';\n\nconst BASE_URL = 'https://api.keyenv.dev';\nconst DEFAULT_TIMEOUT = 30000;\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\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 }\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 * @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 response = await this.request<{ secrets: SecretWithValue[] }>(\n 'GET', `/api/v1/projects/${projectId}/environments/${environment}/secrets/export`\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 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 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 }\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 return this.request<BulkImportResult>(\n 'POST', `/api/v1/projects/${projectId}/environments/${environment}/secrets/bulk`,\n { secrets, overwrite: options.overwrite ?? false }\n );\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"],"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}\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyenv",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
4
  "description": "Official Node.js SDK for KeyEnv - Secure secrets management",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",