@alienplatform/sdk 1.3.3

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.
Files changed (119) hide show
  1. package/.turbo/turbo-build.log +27 -0
  2. package/AGENTS.md +70 -0
  3. package/LICENSE.md +105 -0
  4. package/dist/bindings/artifact-registry.d.ts +88 -0
  5. package/dist/bindings/artifact-registry.d.ts.map +1 -0
  6. package/dist/bindings/build.d.ts +67 -0
  7. package/dist/bindings/build.d.ts.map +1 -0
  8. package/dist/bindings/function.d.ts +72 -0
  9. package/dist/bindings/function.d.ts.map +1 -0
  10. package/dist/bindings/index.d.ts +12 -0
  11. package/dist/bindings/index.d.ts.map +1 -0
  12. package/dist/bindings/kv.d.ts +113 -0
  13. package/dist/bindings/kv.d.ts.map +1 -0
  14. package/dist/bindings/queue.d.ts +81 -0
  15. package/dist/bindings/queue.d.ts.map +1 -0
  16. package/dist/bindings/service-account.d.ts +46 -0
  17. package/dist/bindings/service-account.d.ts.map +1 -0
  18. package/dist/bindings/storage.d.ts +164 -0
  19. package/dist/bindings/storage.d.ts.map +1 -0
  20. package/dist/bindings/vault.d.ts +65 -0
  21. package/dist/bindings/vault.d.ts.map +1 -0
  22. package/dist/channel.d.ts +39 -0
  23. package/dist/channel.d.ts.map +1 -0
  24. package/dist/commands/client.d.ts +47 -0
  25. package/dist/commands/client.d.ts.map +1 -0
  26. package/dist/commands/errors.d.ts +198 -0
  27. package/dist/commands/errors.d.ts.map +1 -0
  28. package/dist/commands/index.d.ts +23 -0
  29. package/dist/commands/index.d.ts.map +1 -0
  30. package/dist/commands/index.js +387 -0
  31. package/dist/commands/types.d.ts +40 -0
  32. package/dist/commands/types.d.ts.map +1 -0
  33. package/dist/commands.d.ts +55 -0
  34. package/dist/commands.d.ts.map +1 -0
  35. package/dist/context.d.ts +182 -0
  36. package/dist/context.d.ts.map +1 -0
  37. package/dist/dist.js +6021 -0
  38. package/dist/errors.d.ts +334 -0
  39. package/dist/errors.d.ts.map +1 -0
  40. package/dist/events.d.ts +163 -0
  41. package/dist/events.d.ts.map +1 -0
  42. package/dist/generated/artifact_registry.d.ts +292 -0
  43. package/dist/generated/artifact_registry.d.ts.map +1 -0
  44. package/dist/generated/build.d.ts +184 -0
  45. package/dist/generated/build.d.ts.map +1 -0
  46. package/dist/generated/container.d.ts +101 -0
  47. package/dist/generated/container.d.ts.map +1 -0
  48. package/dist/generated/control.d.ts +236 -0
  49. package/dist/generated/control.d.ts.map +1 -0
  50. package/dist/generated/function.d.ts +107 -0
  51. package/dist/generated/function.d.ts.map +1 -0
  52. package/dist/generated/google/protobuf/duration.d.ts +94 -0
  53. package/dist/generated/google/protobuf/duration.d.ts.map +1 -0
  54. package/dist/generated/google/protobuf/timestamp.d.ts +124 -0
  55. package/dist/generated/google/protobuf/timestamp.d.ts.map +1 -0
  56. package/dist/generated/kv.d.ts +182 -0
  57. package/dist/generated/kv.d.ts.map +1 -0
  58. package/dist/generated/queue.d.ts +127 -0
  59. package/dist/generated/queue.d.ts.map +1 -0
  60. package/dist/generated/service_account.d.ts +112 -0
  61. package/dist/generated/service_account.d.ts.map +1 -0
  62. package/dist/generated/storage.d.ts +783 -0
  63. package/dist/generated/storage.d.ts.map +1 -0
  64. package/dist/generated/vault.d.ts +107 -0
  65. package/dist/generated/vault.d.ts.map +1 -0
  66. package/dist/generated/wait_until.d.ts +149 -0
  67. package/dist/generated/wait_until.d.ts.map +1 -0
  68. package/dist/global.d.ts +208 -0
  69. package/dist/global.d.ts.map +1 -0
  70. package/dist/grpc-utils.d.ts +25 -0
  71. package/dist/grpc-utils.d.ts.map +1 -0
  72. package/dist/index.d.ts +38 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +38713 -0
  75. package/dist/types.d.ts +327 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/wait-until.d.ts +115 -0
  78. package/dist/wait-until.d.ts.map +1 -0
  79. package/package.json +63 -0
  80. package/scripts/generate-proto.sh +46 -0
  81. package/src/bindings/AGENTS.md +105 -0
  82. package/src/bindings/artifact-registry.ts +316 -0
  83. package/src/bindings/build.ts +195 -0
  84. package/src/bindings/function.ts +164 -0
  85. package/src/bindings/index.ts +12 -0
  86. package/src/bindings/kv.ts +240 -0
  87. package/src/bindings/queue.ts +191 -0
  88. package/src/bindings/service-account.ts +113 -0
  89. package/src/bindings/storage.ts +535 -0
  90. package/src/bindings/vault.ts +133 -0
  91. package/src/channel.ts +102 -0
  92. package/src/commands/client.ts +446 -0
  93. package/src/commands/errors.ts +126 -0
  94. package/src/commands/index.ts +41 -0
  95. package/src/commands/types.ts +52 -0
  96. package/src/commands.ts +76 -0
  97. package/src/context.ts +368 -0
  98. package/src/errors.ts +259 -0
  99. package/src/events.ts +511 -0
  100. package/src/generated/artifact_registry.ts +1952 -0
  101. package/src/generated/build.ts +1263 -0
  102. package/src/generated/container.ts +485 -0
  103. package/src/generated/control.ts +1922 -0
  104. package/src/generated/function.ts +741 -0
  105. package/src/generated/google/protobuf/duration.ts +196 -0
  106. package/src/generated/google/protobuf/timestamp.ts +226 -0
  107. package/src/generated/kv.ts +1137 -0
  108. package/src/generated/queue.ts +729 -0
  109. package/src/generated/service_account.ts +766 -0
  110. package/src/generated/storage.ts +3653 -0
  111. package/src/generated/vault.ts +519 -0
  112. package/src/generated/wait_until.ts +781 -0
  113. package/src/global.ts +287 -0
  114. package/src/grpc-utils.ts +159 -0
  115. package/src/index.ts +154 -0
  116. package/src/types.ts +386 -0
  117. package/src/wait-until.ts +273 -0
  118. package/tsconfig.json +8 -0
  119. package/tsdown.config.ts +17 -0
@@ -0,0 +1,535 @@
1
+ /**
2
+ * Storage binding implementation.
3
+ *
4
+ * Provides object storage operations with streaming support.
5
+ */
6
+
7
+ import { type Channel, createClient } from "nice-grpc"
8
+ import {
9
+ type StorageServiceClient as GeneratedClient,
10
+ type StorageObjectMeta as ProtoObjectMeta,
11
+ StorageHttpMethod,
12
+ StoragePutModeEnum,
13
+ type StoragePutMultipartChunkRequest,
14
+ StorageServiceDefinition,
15
+ } from "../generated/storage.js"
16
+ import { wrapGrpcCall } from "../grpc-utils.js"
17
+ import type {
18
+ SignedUrlOptions,
19
+ SignedUrlResult,
20
+ StorageGetOptions,
21
+ StorageGetResult,
22
+ StorageListResult,
23
+ StorageObjectMeta,
24
+ StoragePutOptions,
25
+ } from "../types.js"
26
+
27
+ /**
28
+ * Storage binding for object storage operations.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { storage } from "@alienplatform/sdk"
33
+ *
34
+ * const bucket = storage("my-bucket")
35
+ *
36
+ * // Upload a file
37
+ * await bucket.put("images/photo.jpg", imageData, { contentType: "image/jpeg" })
38
+ *
39
+ * // Download a file
40
+ * const result = await bucket.get("images/photo.jpg")
41
+ * console.log("Size:", result.meta.size)
42
+ *
43
+ * // List files
44
+ * for await (const file of bucket.list("images/")) {
45
+ * console.log(file.location)
46
+ * }
47
+ *
48
+ * // Generate a signed URL
49
+ * const { url } = await bucket.signedUrl("images/photo.jpg", { operation: "get" })
50
+ * ```
51
+ */
52
+ export class Storage {
53
+ private readonly client: GeneratedClient
54
+ private readonly bindingName: string
55
+
56
+ constructor(channel: Channel, bindingName: string) {
57
+ this.client = createClient(StorageServiceDefinition, channel)
58
+ this.bindingName = bindingName
59
+ }
60
+
61
+ /**
62
+ * Get an object from storage.
63
+ *
64
+ * @param path - Path to the object
65
+ * @param options - Get options (range, conditionals)
66
+ * @returns Object data and metadata
67
+ */
68
+ async get(path: string, options?: StorageGetOptions): Promise<StorageGetResult> {
69
+ return await wrapGrpcCall(
70
+ "StorageService",
71
+ "Get",
72
+ async () => {
73
+ const stream = this.client.get({
74
+ bindingName: this.bindingName,
75
+ path,
76
+ options: options
77
+ ? {
78
+ ifMatch: options.ifMatch,
79
+ ifNoneMatch: options.ifNoneMatch,
80
+ ifModifiedSince: options.ifModifiedSince,
81
+ ifUnmodifiedSince: options.ifUnmodifiedSince,
82
+ range:
83
+ options.rangeStart !== undefined || options.rangeEnd !== undefined
84
+ ? {
85
+ bounded: {
86
+ start: options.rangeStart ?? 0,
87
+ end: options.rangeEnd ?? 0,
88
+ },
89
+ }
90
+ : undefined,
91
+ head: false,
92
+ }
93
+ : undefined,
94
+ })
95
+
96
+ let meta: StorageObjectMeta | undefined
97
+ const chunks: Uint8Array[] = []
98
+
99
+ for await (const part of stream) {
100
+ if (part.metadata) {
101
+ meta = this.fromProtoMeta(part.metadata)
102
+ }
103
+ if (part.chunkData && part.chunkData.length > 0) {
104
+ chunks.push(part.chunkData)
105
+ }
106
+ }
107
+
108
+ if (!meta) {
109
+ throw new Error("No metadata received from storage")
110
+ }
111
+
112
+ // Combine chunks
113
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
114
+ const data = new Uint8Array(totalLength)
115
+ let offset = 0
116
+ for (const chunk of chunks) {
117
+ data.set(chunk, offset)
118
+ offset += chunk.length
119
+ }
120
+
121
+ return { meta, data }
122
+ },
123
+ { bindingName: this.bindingName },
124
+ )
125
+ }
126
+
127
+ /**
128
+ * Get an object as a UTF-8 string.
129
+ *
130
+ * @param path - Path to the object
131
+ * @param options - Get options
132
+ * @returns Object content as string
133
+ */
134
+ async getText(path: string, options?: StorageGetOptions): Promise<string> {
135
+ const result = await this.get(path, options)
136
+ return new TextDecoder().decode(result.data)
137
+ }
138
+
139
+ /**
140
+ * Get an object and parse as JSON.
141
+ *
142
+ * @param path - Path to the object
143
+ * @param options - Get options
144
+ * @returns Parsed JSON content
145
+ */
146
+ async getJson<T = unknown>(path: string, options?: StorageGetOptions): Promise<T> {
147
+ const text = await this.getText(path, options)
148
+ return JSON.parse(text) as T
149
+ }
150
+
151
+ /**
152
+ * Put an object to storage.
153
+ *
154
+ * @param path - Path to store the object
155
+ * @param data - Object data
156
+ * @param options - Put options (content type, metadata)
157
+ */
158
+ async put(
159
+ path: string,
160
+ data: Uint8Array | string | object,
161
+ options?: StoragePutOptions,
162
+ ): Promise<void> {
163
+ let bytes: Uint8Array
164
+ let contentType = options?.contentType
165
+
166
+ if (typeof data === "string") {
167
+ bytes = new TextEncoder().encode(data)
168
+ contentType ??= "text/plain; charset=utf-8"
169
+ } else if (data instanceof Uint8Array) {
170
+ bytes = data
171
+ contentType ??= "application/octet-stream"
172
+ } else {
173
+ bytes = new TextEncoder().encode(JSON.stringify(data))
174
+ contentType ??= "application/json"
175
+ }
176
+
177
+ // Build attributes for content-type and metadata
178
+ const attributePairs: Array<{ key: string; value: string }> = []
179
+ if (contentType) {
180
+ attributePairs.push({ key: "content-type", value: contentType })
181
+ }
182
+ if (options?.metadata) {
183
+ for (const [key, value] of Object.entries(options.metadata)) {
184
+ attributePairs.push({ key: `metadata:${key}`, value })
185
+ }
186
+ }
187
+
188
+ await wrapGrpcCall(
189
+ "StorageService",
190
+ "Put",
191
+ async () => {
192
+ await this.client.put({
193
+ bindingName: this.bindingName,
194
+ path,
195
+ data: bytes,
196
+ options: {
197
+ mode: options?.ifNotExists
198
+ ? StoragePutModeEnum.PUT_MODE_CREATE
199
+ : StoragePutModeEnum.PUT_MODE_OVERWRITE,
200
+ attributes: attributePairs.length > 0 ? { pairs: attributePairs } : undefined,
201
+ },
202
+ })
203
+ },
204
+ { bindingName: this.bindingName },
205
+ )
206
+ }
207
+
208
+ /**
209
+ * Put an object using streaming (for large files).
210
+ *
211
+ * @param path - Path to store the object
212
+ * @param chunks - Async iterable of data chunks
213
+ * @param options - Put options
214
+ */
215
+ async putMultipart(
216
+ path: string,
217
+ chunks: AsyncIterable<Uint8Array>,
218
+ options?: StoragePutOptions,
219
+ ): Promise<void> {
220
+ const bindingName = this.bindingName
221
+
222
+ // Build attributes for content-type and metadata
223
+ const attributePairs: Array<{ key: string; value: string }> = []
224
+ if (options?.contentType) {
225
+ attributePairs.push({ key: "content-type", value: options.contentType })
226
+ }
227
+ if (options?.metadata) {
228
+ for (const [key, value] of Object.entries(options.metadata)) {
229
+ attributePairs.push({ key: `metadata:${key}`, value })
230
+ }
231
+ }
232
+
233
+ await wrapGrpcCall(
234
+ "StorageService",
235
+ "PutMultipart",
236
+ async () => {
237
+ async function* generateChunks(): AsyncIterable<StoragePutMultipartChunkRequest> {
238
+ // First chunk: metadata
239
+ yield {
240
+ metadata: {
241
+ bindingName,
242
+ path,
243
+ options:
244
+ attributePairs.length > 0 ? { attributes: { pairs: attributePairs } } : undefined,
245
+ },
246
+ chunkData: undefined,
247
+ }
248
+
249
+ // Subsequent chunks: data
250
+ for await (const chunk of chunks) {
251
+ yield {
252
+ metadata: undefined,
253
+ chunkData: chunk,
254
+ }
255
+ }
256
+ }
257
+
258
+ await this.client.putMultipart(generateChunks())
259
+ },
260
+ { bindingName: this.bindingName },
261
+ )
262
+ }
263
+
264
+ /**
265
+ * Delete an object from storage.
266
+ *
267
+ * @param path - Path to the object
268
+ */
269
+ async delete(path: string): Promise<void> {
270
+ await wrapGrpcCall(
271
+ "StorageService",
272
+ "Delete",
273
+ async () => {
274
+ await this.client.delete({
275
+ bindingName: this.bindingName,
276
+ path,
277
+ })
278
+ },
279
+ { bindingName: this.bindingName },
280
+ )
281
+ }
282
+
283
+ /**
284
+ * List objects in storage.
285
+ *
286
+ * @param prefix - Optional prefix filter
287
+ * @param options - List options
288
+ * @returns Async iterable of object metadata
289
+ */
290
+ async *list(prefix?: string, options?: { offset?: string }): AsyncIterable<StorageObjectMeta> {
291
+ const stream = this.client.list({
292
+ bindingName: this.bindingName,
293
+ prefix,
294
+ offset: options?.offset,
295
+ })
296
+
297
+ for await (const meta of stream) {
298
+ yield this.fromProtoMeta(meta)
299
+ }
300
+ }
301
+
302
+ /**
303
+ * List objects with delimiter (for directory-like listing).
304
+ *
305
+ * @param prefix - Optional prefix filter
306
+ * @returns List result with objects and common prefixes
307
+ */
308
+ async listWithDelimiter(prefix?: string): Promise<StorageListResult> {
309
+ return await wrapGrpcCall(
310
+ "StorageService",
311
+ "ListWithDelimiter",
312
+ async () => {
313
+ const response = await this.client.listWithDelimiter({
314
+ bindingName: this.bindingName,
315
+ prefix,
316
+ })
317
+ return {
318
+ commonPrefixes: response.commonPrefixes,
319
+ objects: response.objects.map(obj => this.fromProtoMeta(obj)),
320
+ }
321
+ },
322
+ { bindingName: this.bindingName },
323
+ )
324
+ }
325
+
326
+ /**
327
+ * Get object metadata without downloading content.
328
+ *
329
+ * @param path - Path to the object
330
+ * @returns Object metadata
331
+ */
332
+ async head(path: string): Promise<StorageObjectMeta> {
333
+ return await wrapGrpcCall(
334
+ "StorageService",
335
+ "Head",
336
+ async () => {
337
+ const response = await this.client.head({
338
+ bindingName: this.bindingName,
339
+ path,
340
+ })
341
+ return this.fromProtoMeta(response)
342
+ },
343
+ { bindingName: this.bindingName },
344
+ )
345
+ }
346
+
347
+ /**
348
+ * Check if an object exists.
349
+ *
350
+ * @param path - Path to the object
351
+ * @returns True if the object exists
352
+ */
353
+ async exists(path: string): Promise<boolean> {
354
+ try {
355
+ await this.head(path)
356
+ return true
357
+ } catch (error) {
358
+ if (error instanceof Error && "code" in error && (error as any).code === "NOT_FOUND") {
359
+ return false
360
+ }
361
+ throw error
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Get the base directory path for this storage binding.
367
+ *
368
+ * @returns Base directory path
369
+ */
370
+ async getBaseDir(): Promise<string> {
371
+ return await wrapGrpcCall(
372
+ "StorageService",
373
+ "GetBaseDir",
374
+ async () => {
375
+ const response = await this.client.getBaseDir({
376
+ bindingName: this.bindingName,
377
+ })
378
+ return response.path
379
+ },
380
+ { bindingName: this.bindingName },
381
+ )
382
+ }
383
+
384
+ /**
385
+ * Get the underlying URL for this storage binding.
386
+ *
387
+ * @returns Storage URL
388
+ */
389
+ async getUrl(): Promise<string> {
390
+ return await wrapGrpcCall(
391
+ "StorageService",
392
+ "GetUrl",
393
+ async () => {
394
+ const response = await this.client.getUrl({
395
+ bindingName: this.bindingName,
396
+ })
397
+ return response.url
398
+ },
399
+ { bindingName: this.bindingName },
400
+ )
401
+ }
402
+
403
+ /**
404
+ * Copy an object within the same storage binding.
405
+ *
406
+ * @param from - Source path
407
+ * @param to - Destination path
408
+ */
409
+ async copy(from: string, to: string): Promise<void> {
410
+ await wrapGrpcCall(
411
+ "StorageService",
412
+ "Copy",
413
+ async () => {
414
+ await this.client.copy({
415
+ bindingName: this.bindingName,
416
+ fromPath: from,
417
+ toPath: to,
418
+ })
419
+ },
420
+ { bindingName: this.bindingName },
421
+ )
422
+ }
423
+
424
+ /**
425
+ * Rename (move) an object within the same storage binding.
426
+ *
427
+ * @param from - Source path
428
+ * @param to - Destination path
429
+ */
430
+ async rename(from: string, to: string): Promise<void> {
431
+ await wrapGrpcCall(
432
+ "StorageService",
433
+ "Rename",
434
+ async () => {
435
+ await this.client.rename({
436
+ bindingName: this.bindingName,
437
+ fromPath: from,
438
+ toPath: to,
439
+ })
440
+ },
441
+ { bindingName: this.bindingName },
442
+ )
443
+ }
444
+
445
+ /**
446
+ * Copy an object only if the destination doesn't exist.
447
+ *
448
+ * @param from - Source path
449
+ * @param to - Destination path
450
+ */
451
+ async copyIfNotExists(from: string, to: string): Promise<void> {
452
+ await wrapGrpcCall(
453
+ "StorageService",
454
+ "CopyIfNotExists",
455
+ async () => {
456
+ await this.client.copyIfNotExists({
457
+ bindingName: this.bindingName,
458
+ fromPath: from,
459
+ toPath: to,
460
+ })
461
+ },
462
+ { bindingName: this.bindingName },
463
+ )
464
+ }
465
+
466
+ /**
467
+ * Rename (move) an object only if the destination doesn't exist.
468
+ *
469
+ * @param from - Source path
470
+ * @param to - Destination path
471
+ */
472
+ async renameIfNotExists(from: string, to: string): Promise<void> {
473
+ await wrapGrpcCall(
474
+ "StorageService",
475
+ "RenameIfNotExists",
476
+ async () => {
477
+ await this.client.renameIfNotExists({
478
+ bindingName: this.bindingName,
479
+ fromPath: from,
480
+ toPath: to,
481
+ })
482
+ },
483
+ { bindingName: this.bindingName },
484
+ )
485
+ }
486
+
487
+ /**
488
+ * Generate a signed URL for an object.
489
+ *
490
+ * @param path - Path to the object
491
+ * @param options - Signed URL options
492
+ * @returns Signed URL result
493
+ */
494
+ async signedUrl(path: string, options: SignedUrlOptions): Promise<SignedUrlResult> {
495
+ const operationMap: Record<SignedUrlOptions["operation"], StorageHttpMethod> = {
496
+ get: StorageHttpMethod.HTTP_METHOD_GET,
497
+ put: StorageHttpMethod.HTTP_METHOD_PUT,
498
+ delete: StorageHttpMethod.HTTP_METHOD_DELETE,
499
+ }
500
+
501
+ // Calculate expiration time
502
+ const expiresInSeconds = options.expiresInSeconds ?? 3600
503
+ const expirationTime = new Date(Date.now() + expiresInSeconds * 1000)
504
+
505
+ return await wrapGrpcCall(
506
+ "StorageService",
507
+ "SignedUrl",
508
+ async () => {
509
+ const response = await this.client.signedUrl({
510
+ bindingName: this.bindingName,
511
+ path,
512
+ httpMethod: operationMap[options.operation],
513
+ expirationTime,
514
+ })
515
+ return {
516
+ url: response.url,
517
+ expiresAt: expirationTime,
518
+ }
519
+ },
520
+ { bindingName: this.bindingName },
521
+ )
522
+ }
523
+
524
+ // Private helpers
525
+
526
+ private fromProtoMeta(proto: ProtoObjectMeta): StorageObjectMeta {
527
+ return {
528
+ location: proto.location,
529
+ lastModified: proto.lastModified,
530
+ size: proto.size,
531
+ etag: proto.eTag,
532
+ version: proto.version,
533
+ }
534
+ }
535
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Vault binding implementation.
3
+ *
4
+ * Provides secure secret management operations.
5
+ */
6
+
7
+ import { type Channel, createClient } from "nice-grpc"
8
+ import {
9
+ type VaultServiceClient as GeneratedVaultServiceClient,
10
+ VaultServiceDefinition,
11
+ } from "../generated/vault.js"
12
+ import { wrapGrpcCall } from "../grpc-utils.js"
13
+
14
+ /**
15
+ * Vault binding for secret management operations.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { vault } from "@alienplatform/sdk"
20
+ *
21
+ * const secrets = vault("app-secrets")
22
+ *
23
+ * // Get a secret
24
+ * const apiKey = await secrets.get("API_KEY")
25
+ *
26
+ * // Set a secret
27
+ * await secrets.set("DATABASE_URL", "postgres://...")
28
+ *
29
+ * // Delete a secret
30
+ * await secrets.delete("OLD_KEY")
31
+ * ```
32
+ */
33
+ export class Vault {
34
+ private readonly client: GeneratedVaultServiceClient
35
+ private readonly bindingName: string
36
+
37
+ constructor(channel: Channel, bindingName: string) {
38
+ this.client = createClient(VaultServiceDefinition, channel)
39
+ this.bindingName = bindingName
40
+ }
41
+
42
+ /**
43
+ * Get a secret value.
44
+ *
45
+ * @param secretName - Name of the secret
46
+ * @returns Secret value
47
+ */
48
+ async get(secretName: string): Promise<string> {
49
+ return await wrapGrpcCall(
50
+ "VaultService",
51
+ "GetSecret",
52
+ async () => {
53
+ const response = await this.client.getSecret({
54
+ bindingName: this.bindingName,
55
+ secretName,
56
+ })
57
+ return response.value
58
+ },
59
+ { bindingName: this.bindingName, secretName },
60
+ )
61
+ }
62
+
63
+ /**
64
+ * Get a secret as JSON.
65
+ *
66
+ * @param secretName - Name of the secret
67
+ * @returns Parsed JSON value
68
+ */
69
+ async getJson<T = unknown>(secretName: string): Promise<T> {
70
+ const value = await this.get(secretName)
71
+ return JSON.parse(value) as T
72
+ }
73
+
74
+ /**
75
+ * Set a secret value.
76
+ *
77
+ * @param secretName - Name of the secret
78
+ * @param value - Secret value (string or object for JSON)
79
+ */
80
+ async set(secretName: string, value: string | object): Promise<void> {
81
+ const stringValue = typeof value === "string" ? value : JSON.stringify(value)
82
+
83
+ await wrapGrpcCall(
84
+ "VaultService",
85
+ "SetSecret",
86
+ async () => {
87
+ await this.client.setSecret({
88
+ bindingName: this.bindingName,
89
+ secretName,
90
+ value: stringValue,
91
+ })
92
+ },
93
+ { bindingName: this.bindingName, secretName },
94
+ )
95
+ }
96
+
97
+ /**
98
+ * Delete a secret.
99
+ *
100
+ * @param secretName - Name of the secret to delete
101
+ */
102
+ async delete(secretName: string): Promise<void> {
103
+ await wrapGrpcCall(
104
+ "VaultService",
105
+ "DeleteSecret",
106
+ async () => {
107
+ await this.client.deleteSecret({
108
+ bindingName: this.bindingName,
109
+ secretName,
110
+ })
111
+ },
112
+ { bindingName: this.bindingName, secretName },
113
+ )
114
+ }
115
+
116
+ /**
117
+ * Check if a secret exists.
118
+ *
119
+ * @param secretName - Name of the secret
120
+ * @returns True if the secret exists
121
+ */
122
+ async exists(secretName: string): Promise<boolean> {
123
+ try {
124
+ await this.get(secretName)
125
+ return true
126
+ } catch (error) {
127
+ if (error instanceof Error && "code" in error && (error as any).code === "SECRET_NOT_FOUND") {
128
+ return false
129
+ }
130
+ throw error
131
+ }
132
+ }
133
+ }