learn-secrets-sdk 1.11.7 → 1.11.12

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.
@@ -1,862 +0,0 @@
1
- /**
2
- * SecretsSDK - Browser Global Build
3
- * Usage: const sdk = new SecretsSDK();
4
- */
5
- (function(global) {
6
- 'use strict';
7
-
8
- import {
9
- loadSecretsConfig,
10
- resolveEnvInSecret,
11
- resolveEnvInSecrets,
12
- resolveEnvString
13
- } from "./chunk-Y4RHJLDQ.mjs";
14
-
15
- // src/types.ts
16
- var SecretsSDKError = class extends Error {
17
- constructor(message, status, response) {
18
- super(message);
19
- this.status = status;
20
- this.response = response;
21
- this.name = "SecretsSDKError";
22
- }
23
- };
24
- var OriginMismatchError = class extends SecretsSDKError {
25
- constructor(message = "Origin not allowed for this token") {
26
- super(message, 403);
27
- this.name = "OriginMismatchError";
28
- }
29
- };
30
- var RateLimitError = class extends SecretsSDKError {
31
- constructor(message = "Rate limit exceeded", retryAfter = 60, remaining = 0, limit = 100) {
32
- super(message, 429);
33
- this.name = "RateLimitError";
34
- this.retryAfter = retryAfter;
35
- this.remaining = remaining;
36
- this.limit = limit;
37
- }
38
- };
39
- var InvalidTokenError = class extends SecretsSDKError {
40
- constructor(message = "Invalid or expired token") {
41
- super(message, 401);
42
- this.name = "InvalidTokenError";
43
- }
44
- };
45
-
46
- // src/client.ts
47
- var SecretsSDK = class {
48
- /**
49
- * Create a new SecretsSDK instance
50
- *
51
- * Zero-config mode (recommended for static sites):
52
- * const sdk = new SecretsSDK();
53
- * // Origin header is used for authentication
54
- *
55
- * Token mode (for backward compatibility):
56
- * const sdk = new SecretsSDK({ appId: '...', token: 'sk_live_...' });
57
- */
58
- constructor(options = {}) {
59
- this.rateLimitInfo = null;
60
- this.appId = options.appId || null;
61
- this.token = options.token || options.sessionToken || null;
62
- this.baseUrl = options.baseUrl || "https://cloudprototype.org";
63
- this.timeout = options.timeout || 3e4;
64
- this.retryOn429 = options.retryOn429 !== void 0 ? options.retryOn429 : true;
65
- this.zeroConfigMode = !this.appId && !this.token;
66
- }
67
- /**
68
- * Get current rate limit information
69
- */
70
- getUsage() {
71
- return this.rateLimitInfo;
72
- }
73
- /**
74
- * Parse rate limit headers from response
75
- */
76
- parseRateLimitHeaders(headers) {
77
- const limit = headers.get("X-RateLimit-Limit");
78
- const remaining = headers.get("X-RateLimit-Remaining");
79
- const reset = headers.get("X-RateLimit-Reset");
80
- if (limit && remaining && reset) {
81
- this.rateLimitInfo = {
82
- limit: parseInt(limit),
83
- remaining: parseInt(remaining),
84
- reset: parseInt(reset)
85
- };
86
- }
87
- }
88
- /**
89
- * Sleep utility for retry backoff
90
- */
91
- sleep(ms) {
92
- return new Promise((resolve) => setTimeout(resolve, ms));
93
- }
94
- /**
95
- * Make fetch request with timeout
96
- */
97
- async fetchWithTimeout(url, options, timeout) {
98
- const controller = new AbortController();
99
- const timeoutId = setTimeout(() => controller.abort(), timeout);
100
- try {
101
- const response = await fetch(url, {
102
- ...options,
103
- signal: controller.signal
104
- });
105
- return response;
106
- } finally {
107
- clearTimeout(timeoutId);
108
- }
109
- }
110
- /**
111
- * Call an external API securely through the proxy
112
- * @param keyName - Name of the API key to use
113
- * @param endpoint - API endpoint path (e.g., '/v1/chat/completions')
114
- * @param options - Request options (method, body, headers)
115
- * @returns Promise with the API response
116
- */
117
- async call(keyName, endpoint, options = {}) {
118
- let retries = 0;
119
- const maxRetries = this.retryOn429 ? 3 : 0;
120
- while (true) {
121
- try {
122
- const proxyUrl = this.zeroConfigMode ? `${this.baseUrl}/api/sdk/proxy` : `${this.baseUrl}/api/sdk/${this.appId}/proxy`;
123
- const requestHeaders = {
124
- "Content-Type": "application/json"
125
- };
126
- if (!this.zeroConfigMode && this.token) {
127
- requestHeaders["Authorization"] = `Bearer ${this.token}`;
128
- }
129
- const response = await this.fetchWithTimeout(
130
- proxyUrl,
131
- {
132
- method: "POST",
133
- headers: requestHeaders,
134
- body: JSON.stringify({
135
- keyName,
136
- endpoint,
137
- method: options.method || "GET",
138
- body: options.body,
139
- headers: options.headers
140
- })
141
- },
142
- this.timeout
143
- );
144
- this.parseRateLimitHeaders(response.headers);
145
- const result = await response.json();
146
- if (!response.ok) {
147
- const errorMessage = result.data?.message || result?.message || `Request failed with status ${response.status}`;
148
- if (response.status === 403 && errorMessage.includes("Origin")) {
149
- throw new OriginMismatchError(errorMessage);
150
- }
151
- if (response.status === 401) {
152
- throw new InvalidTokenError(errorMessage);
153
- }
154
- if (response.status === 429) {
155
- const retryAfter = this.rateLimitInfo ? this.rateLimitInfo.reset - Math.floor(Date.now() / 1e3) : 60;
156
- const error = new RateLimitError(
157
- errorMessage,
158
- retryAfter,
159
- this.rateLimitInfo?.remaining || 0,
160
- this.rateLimitInfo?.limit || 100
161
- );
162
- if (this.retryOn429 && retries < maxRetries) {
163
- retries++;
164
- const backoffMs = Math.min(1e3 * Math.pow(2, retries - 1), 8e3);
165
- await this.sleep(backoffMs);
166
- continue;
167
- }
168
- throw error;
169
- }
170
- throw new SecretsSDKError(errorMessage, response.status, result);
171
- }
172
- return result.data;
173
- } catch (err) {
174
- if (err instanceof SecretsSDKError) {
175
- throw err;
176
- }
177
- if (err instanceof Error && err.name === "AbortError") {
178
- throw new SecretsSDKError("Request timeout", 408);
179
- }
180
- throw new SecretsSDKError(
181
- err instanceof Error ? err.message : "Unknown error occurred",
182
- 500
183
- );
184
- }
185
- }
186
- }
187
- /**
188
- * Make a GET request
189
- */
190
- async get(keyName, endpoint, headers) {
191
- return this.call(keyName, endpoint, { method: "GET", headers });
192
- }
193
- /**
194
- * Make a POST request
195
- */
196
- async post(keyName, endpoint, body, headers) {
197
- return this.call(keyName, endpoint, { method: "POST", body, headers });
198
- }
199
- /**
200
- * Make a PUT request
201
- */
202
- async put(keyName, endpoint, body, headers) {
203
- return this.call(keyName, endpoint, { method: "PUT", body, headers });
204
- }
205
- /**
206
- * Make a DELETE request
207
- */
208
- async delete(keyName, endpoint, headers) {
209
- return this.call(keyName, endpoint, { method: "DELETE", headers });
210
- }
211
- /**
212
- * Make a PATCH request
213
- */
214
- async patch(keyName, endpoint, body, headers) {
215
- return this.call(keyName, endpoint, { method: "PATCH", body, headers });
216
- }
217
- /**
218
- * Secrets Management API (zero-config mode)
219
- * These methods allow programmatic CRUD operations on project secrets
220
- * Requires appId to be set (can be set in constructor or via setAppId)
221
- */
222
- /**
223
- * Set App ID for secrets management
224
- * Required before calling secrets management methods
225
- */
226
- setAppId(appId) {
227
- this.appId = appId;
228
- }
229
- /**
230
- * Make authenticated request to secrets management API
231
- */
232
- async secretsRequest(action, body) {
233
- if (!this.appId) {
234
- throw new SecretsSDKError("App ID required for secrets management. Call setAppId() first.", 400);
235
- }
236
- const response = await this.fetchWithTimeout(
237
- `${this.baseUrl}/api/projects/${this.appId}/secrets/manage?action=${action}`,
238
- {
239
- method: "POST",
240
- headers: {
241
- "Content-Type": "application/json"
242
- },
243
- body: body ? JSON.stringify(body) : void 0
244
- },
245
- this.timeout
246
- );
247
- if (!response.ok) {
248
- const errorData = await response.json().catch(() => ({}));
249
- throw new SecretsSDKError(
250
- errorData.message || `Secrets management failed: ${response.statusText}`,
251
- response.status,
252
- errorData
253
- );
254
- }
255
- return response.json();
256
- }
257
- /**
258
- * List all secrets for the project
259
- * Returns secret metadata (no API keys)
260
- */
261
- async listSecrets() {
262
- return this.secretsRequest("list");
263
- }
264
- /**
265
- * Create a new secret
266
- */
267
- async createSecret(secret) {
268
- return this.secretsRequest("create", secret);
269
- }
270
- /**
271
- * Update an existing secret
272
- */
273
- async updateSecret(update) {
274
- return this.secretsRequest("update", update);
275
- }
276
- /**
277
- * Delete a secret
278
- */
279
- async deleteSecret(name) {
280
- return this.secretsRequest("delete", { name });
281
- }
282
- /**
283
- * Sync secrets from .env file format
284
- * Bulk upload/update secrets
285
- */
286
- async syncEnv(secrets, provider) {
287
- return this.secretsRequest("sync", { secrets, provider });
288
- }
289
- };
290
-
291
- // src/credentials.ts
292
- import * as fs from "fs";
293
- import * as path from "path";
294
- import * as os from "os";
295
- function getCredentialsPath() {
296
- const homeDir = os.homedir();
297
- const learnDir = path.join(homeDir, ".learn");
298
- return path.join(learnDir, "credentials.json");
299
- }
300
- function ensureLearnDir() {
301
- const homeDir = os.homedir();
302
- const learnDir = path.join(homeDir, ".learn");
303
- if (!fs.existsSync(learnDir)) {
304
- fs.mkdirSync(learnDir, { recursive: true, mode: 448 });
305
- }
306
- }
307
- function readAllCredentials() {
308
- try {
309
- const credPath = getCredentialsPath();
310
- if (!fs.existsSync(credPath)) {
311
- return null;
312
- }
313
- const data = fs.readFileSync(credPath, "utf-8");
314
- const store = JSON.parse(data);
315
- if (store.access_token && !store["learn-secrets-sdk"] && !store["learn-auth-sdk"]) {
316
- return {
317
- "learn-secrets-sdk": store
318
- };
319
- }
320
- return store;
321
- } catch (err) {
322
- return null;
323
- }
324
- }
325
- function writeAllCredentials(store) {
326
- ensureLearnDir();
327
- const credPath = getCredentialsPath();
328
- const data = JSON.stringify(store, null, 2);
329
- fs.writeFileSync(credPath, data, { mode: 384 });
330
- }
331
- function readSDKCredentials(sdkName) {
332
- const store = readAllCredentials();
333
- if (!store) {
334
- return null;
335
- }
336
- return store[sdkName] || null;
337
- }
338
- function writeSDKCredentials(sdkName, creds) {
339
- const store = readAllCredentials() || {};
340
- store[sdkName] = creds;
341
- writeAllCredentials(store);
342
- }
343
- function deleteSDKCredentials(sdkName) {
344
- const store = readAllCredentials();
345
- if (!store) {
346
- return;
347
- }
348
- delete store[sdkName];
349
- if (Object.keys(store).length === 0) {
350
- deleteCredentials();
351
- } else {
352
- writeAllCredentials(store);
353
- }
354
- }
355
- function readCredentials() {
356
- return readSDKCredentials("learn-secrets-sdk");
357
- }
358
- function deleteCredentials() {
359
- try {
360
- const credPath = getCredentialsPath();
361
- if (fs.existsSync(credPath)) {
362
- fs.unlinkSync(credPath);
363
- }
364
- } catch (err) {
365
- }
366
- }
367
- function hasSDKCredentials(sdkName) {
368
- const creds = readSDKCredentials(sdkName);
369
- return creds !== null && !!creds.access_token;
370
- }
371
- function hasValidCredentials() {
372
- const creds = readCredentials();
373
- if (!creds) {
374
- return false;
375
- }
376
- if (!creds.expires_at) {
377
- return true;
378
- }
379
- const expiresAt = new Date(creds.expires_at);
380
- const now = /* @__PURE__ */ new Date();
381
- return expiresAt > now;
382
- }
383
-
384
- // src/machine-id.ts
385
- import { exec } from "child_process";
386
- import { promisify } from "util";
387
- import { createHash } from "crypto";
388
- import * as os2 from "os";
389
- var execAsync = promisify(exec);
390
- async function getMachineId() {
391
- const platform2 = process.platform;
392
- try {
393
- let rawId;
394
- if (platform2 === "darwin") {
395
- rawId = await getMacOSId();
396
- } else if (platform2 === "linux") {
397
- rawId = await getLinuxId();
398
- } else if (platform2 === "win32") {
399
- rawId = await getWindowsId();
400
- } else {
401
- throw new Error(`Unsupported platform: ${platform2}`);
402
- }
403
- const machineId = createHash("sha256").update(rawId).digest("hex").substring(0, 32);
404
- const fingerprintData = JSON.stringify({
405
- machineId,
406
- cpus: os2.cpus().length,
407
- arch: os2.arch(),
408
- platform: os2.platform(),
409
- homedir: os2.homedir()
410
- });
411
- const fingerprint = createHash("sha256").update(fingerprintData).digest("hex");
412
- return { machineId, fingerprint };
413
- } catch (error) {
414
- throw new Error(`Failed to get machine ID: ${error.message}`);
415
- }
416
- }
417
- async function getMacOSId() {
418
- try {
419
- const { stdout: serial } = await execAsync(
420
- `ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | sed 's/"//g'`
421
- );
422
- const { stdout: hostname } = await execAsync("hostname");
423
- const serialTrimmed = serial.trim();
424
- const hostnameTrimmed = hostname.trim();
425
- if (serialTrimmed && hostnameTrimmed) {
426
- return `${serialTrimmed}-${hostnameTrimmed}`;
427
- }
428
- const { stdout: uuid } = await execAsync(
429
- `ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk '{print $3}' | sed 's/"//g'`
430
- );
431
- return uuid.trim();
432
- } catch (error) {
433
- throw new Error("Failed to get macOS machine ID");
434
- }
435
- }
436
- async function getLinuxId() {
437
- try {
438
- const { stdout } = await execAsync(
439
- "cat /etc/machine-id 2>/dev/null || cat /var/lib/dbus/machine-id 2>/dev/null"
440
- );
441
- const machineId = stdout.trim();
442
- if (machineId) {
443
- return machineId;
444
- }
445
- throw new Error("Machine ID file not found");
446
- } catch (error) {
447
- throw new Error("Failed to get Linux machine ID");
448
- }
449
- }
450
- async function getWindowsId() {
451
- try {
452
- const { stdout } = await execAsync("wmic csproduct get uuid");
453
- const lines = stdout.split("\n").map((l) => l.trim());
454
- const uuid = lines.find((l) => l && l !== "UUID");
455
- if (uuid) {
456
- return uuid;
457
- }
458
- throw new Error("Failed to parse machine UUID from WMIC");
459
- } catch (error) {
460
- throw new Error("Failed to get Windows machine ID");
461
- }
462
- }
463
-
464
- // src/management.ts
465
- var SecretsManagement = class {
466
- constructor(options) {
467
- this.appId = options.appId;
468
- this.baseUrl = options.baseUrl || "https://cloudprototype.org";
469
- this.timeout = options.timeout || 3e4;
470
- }
471
- /**
472
- * Open a URL in the default browser
473
- */
474
- async openBrowser(url) {
475
- const { exec: exec2 } = await import("child_process");
476
- const { promisify: promisify2 } = await import("util");
477
- const execAsync2 = promisify2(exec2);
478
- const platform2 = process.platform;
479
- try {
480
- if (platform2 === "darwin") {
481
- await execAsync2(`open "${url}"`);
482
- } else if (platform2 === "win32") {
483
- await execAsync2(`start "${url}"`);
484
- } else {
485
- await execAsync2(`xdg-open "${url}"`);
486
- }
487
- } catch (err) {
488
- console.error("Failed to open browser:", err);
489
- throw new SecretsSDKError("Failed to open browser", 500);
490
- }
491
- }
492
- /**
493
- * Sleep for specified milliseconds
494
- */
495
- sleep(ms) {
496
- return new Promise((resolve) => setTimeout(resolve, ms));
497
- }
498
- /**
499
- * Browser OAuth login flow with 2FA
500
- * Opens browser for user to authorize, then prompts for 2FA code
501
- */
502
- async login() {
503
- const SDK_NAME = "learn-secrets-sdk";
504
- try {
505
- console.log(`Authenticating with Learn (${SDK_NAME})...
506
- `);
507
- const machineInfo = await getMachineId();
508
- const existingCreds = readSDKCredentials(SDK_NAME);
509
- if (existingCreds && existingCreds.access_token) {
510
- const checkResponse = await fetch(`${this.baseUrl}/api/auth/cli/check-authorization`, {
511
- method: "POST",
512
- headers: {
513
- "Content-Type": "application/json"
514
- },
515
- body: JSON.stringify({
516
- machine_id: machineInfo.machineId,
517
- sdk_name: SDK_NAME
518
- })
519
- });
520
- if (checkResponse.ok) {
521
- const checkData = await checkResponse.json();
522
- if (checkData.authorized) {
523
- console.log("This machine is already authorized.");
524
- console.log(`Logged in as: ${checkData.user_email || checkData.user_id}`);
525
- return {
526
- success: true,
527
- user: checkData.user_email || checkData.user_id
528
- };
529
- }
530
- }
531
- }
532
- const deviceResponse = await fetch(`${this.baseUrl}/api/auth/cli/device`, {
533
- method: "POST",
534
- headers: {
535
- "Content-Type": "application/json"
536
- }
537
- });
538
- if (!deviceResponse.ok) {
539
- throw new SecretsSDKError(
540
- "Failed to generate device code",
541
- deviceResponse.status
542
- );
543
- }
544
- const deviceData = await deviceResponse.json();
545
- console.log(`
546
- Log in on ${this.baseUrl}`);
547
- console.log("Login at:");
548
- console.log(deviceData.verification_uri_complete);
549
- console.log("\nPress ENTER to open in the browser...");
550
- const readline = await import("readline");
551
- const rl = readline.createInterface({
552
- input: process.stdin,
553
- output: process.stdout
554
- });
555
- await new Promise((resolve) => {
556
- rl.question("", () => {
557
- rl.close();
558
- resolve();
559
- });
560
- });
561
- console.log("Opening browser...\n");
562
- await this.openBrowser(deviceData.verification_uri_complete);
563
- let tokenData = null;
564
- const interval = deviceData.interval * 1e3;
565
- const maxAttempts = Math.ceil(deviceData.expires_in / deviceData.interval);
566
- let attempts = 0;
567
- while (attempts < maxAttempts) {
568
- await this.sleep(interval);
569
- attempts++;
570
- const tokenResponse = await fetch(`${this.baseUrl}/api/auth/cli/token`, {
571
- method: "POST",
572
- headers: {
573
- "Content-Type": "application/json"
574
- },
575
- body: JSON.stringify({
576
- device_code: deviceData.device_code
577
- })
578
- });
579
- if (tokenResponse.status === 202) {
580
- process.stdout.write(".");
581
- continue;
582
- }
583
- if (tokenResponse.ok) {
584
- tokenData = await tokenResponse.json();
585
- break;
586
- }
587
- }
588
- if (!tokenData) {
589
- throw new SecretsSDKError("Device authorization timeout", 408);
590
- }
591
- console.log("\n\nDevice authorized! Retrieving access token...");
592
- writeSDKCredentials(SDK_NAME, {
593
- access_token: tokenData.access_token,
594
- refresh_token: null,
595
- expires_at: null,
596
- user_id: tokenData.user_id,
597
- machine_id: machineInfo.machineId,
598
- sdk_name: SDK_NAME,
599
- authorized_at: (/* @__PURE__ */ new Date()).toISOString()
600
- });
601
- console.log("\nAuthentication successful!");
602
- console.log(`Logged in as: ${tokenData.user_email || tokenData.user_id}`);
603
- console.log("This machine is now permanently authorized.\n");
604
- return {
605
- success: true,
606
- user: tokenData.user_email || tokenData.user_id
607
- };
608
- } catch (err) {
609
- if (err instanceof SecretsSDKError) {
610
- throw err;
611
- }
612
- throw new SecretsSDKError(
613
- err.message || "Login failed",
614
- err.status || 500
615
- );
616
- }
617
- }
618
- /**
619
- * Check if user is authenticated
620
- */
621
- async isAuthenticated() {
622
- return hasValidCredentials();
623
- }
624
- /**
625
- * Logout - clear stored credentials
626
- */
627
- logout() {
628
- deleteCredentials();
629
- console.log("Logged out successfully");
630
- }
631
- /**
632
- * Get access token from stored credentials
633
- * Throws error if not authenticated
634
- */
635
- getAccessToken() {
636
- const creds = readCredentials();
637
- if (!creds) {
638
- throw new SecretsSDKError("Not authenticated. Run login() first.", 401);
639
- }
640
- if (creds.expires_at) {
641
- const expiresAt = new Date(creds.expires_at);
642
- const now = /* @__PURE__ */ new Date();
643
- if (expiresAt <= now) {
644
- throw new SecretsSDKError("Token expired. Run login() again.", 401);
645
- }
646
- }
647
- return creds.access_token;
648
- }
649
- /**
650
- * Make authenticated request
651
- */
652
- async request(method, path2, body) {
653
- const token = this.getAccessToken();
654
- const options = {
655
- method,
656
- headers: {
657
- "Content-Type": "application/json",
658
- Authorization: `Bearer ${token}`
659
- }
660
- };
661
- if (body) {
662
- options.body = JSON.stringify(body);
663
- }
664
- const response = await fetch(`${this.baseUrl}${path2}`, options);
665
- if (!response.ok) {
666
- const errorData = await response.json().catch(() => ({}));
667
- throw new SecretsSDKError(
668
- errorData.message || `Request failed: ${response.statusText}`,
669
- response.status,
670
- errorData
671
- );
672
- }
673
- return response.json();
674
- }
675
- /**
676
- * List all secrets (with masked API keys)
677
- */
678
- async list() {
679
- const response = await this.request(
680
- "GET",
681
- `/api/projects/${this.appId}/secrets`
682
- );
683
- return response.secrets;
684
- }
685
- /**
686
- * Sync secrets from config
687
- */
688
- async sync(secrets, options) {
689
- const response = await this.request(
690
- "POST",
691
- `/api/projects/${this.appId}/secrets/sync`,
692
- {
693
- secrets,
694
- options: {
695
- deleteMissing: options?.deleteMissing ?? false,
696
- dryRun: options?.dryRun ?? false
697
- }
698
- }
699
- );
700
- return response;
701
- }
702
- /**
703
- * Import secrets from a config object (bulk import)
704
- * Also creates SDK token if origins are provided
705
- *
706
- * @param config - The secrets configuration
707
- * @returns Import results including created/updated counts and optional SDK token
708
- */
709
- async importSecrets(config) {
710
- return this.request(
711
- "POST",
712
- `/api/projects/${this.appId}/import-secrets`,
713
- {
714
- version: config.version || "1.0",
715
- origins: config.origins,
716
- secrets: config.secrets
717
- }
718
- );
719
- }
720
- /**
721
- * Import secrets from a JSON file path
722
- * Resolves environment variables in the config
723
- */
724
- async importFromFile(configPath) {
725
- const { loadSecretsConfig: loadSecretsConfig2 } = await import("./env-resolver-FQMR3R4G.mjs");
726
- const config = loadSecretsConfig2(configPath);
727
- return this.importSecrets(config);
728
- }
729
- };
730
-
731
- // src/worker-client.ts
732
- var WorkerClient = class {
733
- constructor(options) {
734
- this.workerUrl = options.workerUrl.replace(/\/$/, "");
735
- }
736
- /**
737
- * Get public configuration
738
- *
739
- * Returns only PUBLIC_* environment variables from Worker
740
- * Safe for frontend use
741
- */
742
- async getConfig() {
743
- const response = await fetch(`${this.workerUrl}/config`, {
744
- method: "GET",
745
- credentials: "include"
746
- });
747
- if (!response.ok) {
748
- throw new Error(`Failed to get config: ${response.status} ${response.statusText}`);
749
- }
750
- const data = await response.json();
751
- return data.public || {};
752
- }
753
- /**
754
- * Proxy API request with secret injection
755
- *
756
- * Makes API call through Worker which injects secret server-side
757
- * Secret never reaches browser
758
- *
759
- * @param request - Proxy request configuration
760
- * @returns API response data
761
- */
762
- async proxy(request) {
763
- const response = await fetch(`${this.workerUrl}/proxy`, {
764
- method: "POST",
765
- headers: {
766
- "Content-Type": "application/json"
767
- },
768
- credentials: "include",
769
- body: JSON.stringify(request)
770
- });
771
- if (!response.ok) {
772
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
773
- throw new Error(error.error || `Proxy request failed: ${response.status}`);
774
- }
775
- return response.json();
776
- }
777
- /**
778
- * Generate Apple Music JWT
779
- *
780
- * Private key stays in Worker, only JWT returned to frontend
781
- *
782
- * @param request - Apple JWT request with secret name
783
- * @returns JWT token
784
- */
785
- async generateAppleJwt(request) {
786
- const response = await fetch(`${this.workerUrl}/auth/apple-jwt`, {
787
- method: "POST",
788
- headers: {
789
- "Content-Type": "application/json"
790
- },
791
- credentials: "include",
792
- body: JSON.stringify(request)
793
- });
794
- if (!response.ok) {
795
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
796
- throw new Error(error.error || `Apple JWT generation failed: ${response.status}`);
797
- }
798
- const data = await response.json();
799
- return data.token;
800
- }
801
- /**
802
- * Exchange OAuth authorization code for access token
803
- *
804
- * Client secret stays in Worker, tokens returned to frontend
805
- *
806
- * @param request - OAuth exchange request
807
- * @returns OAuth token response
808
- */
809
- async exchangeOAuthCode(request) {
810
- const response = await fetch(`${this.workerUrl}/auth/oauth`, {
811
- method: "POST",
812
- headers: {
813
- "Content-Type": "application/json"
814
- },
815
- credentials: "include",
816
- body: JSON.stringify(request)
817
- });
818
- if (!response.ok) {
819
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
820
- throw new Error(error.error || `OAuth exchange failed: ${response.status}`);
821
- }
822
- return response.json();
823
- }
824
- /**
825
- * Health check
826
- */
827
- async health() {
828
- const response = await fetch(`${this.workerUrl}/health`, {
829
- method: "GET"
830
- });
831
- if (!response.ok) {
832
- throw new Error(`Health check failed: ${response.status}`);
833
- }
834
- return response.json();
835
- }
836
- };
837
- {
838
- InvalidTokenError,
839
- OriginMismatchError,
840
- RateLimitError,
841
- SecretsManagement,
842
- SecretsSDK,
843
- SecretsSDKError,
844
- WorkerClient,
845
- deleteSDKCredentials,
846
- getMachineId,
847
- hasSDKCredentials,
848
- loadSecretsConfig,
849
- readAllCredentials,
850
- readSDKCredentials,
851
- resolveEnvInSecret,
852
- resolveEnvInSecrets,
853
- resolveEnvString,
854
- writeAllCredentials,
855
- writeSDKCredentials
856
- };
857
-
858
-
859
- // Expose SecretsSDK class as global
860
- global.SecretsSDK = SecretsSDK;
861
-
862
- })(typeof window !== 'undefined' ? window : this);