learn-secrets-sdk 1.3.0 → 1.4.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.
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Entry point for the learn-secrets CLI
4
+ // This file is executed when running: learn-secrets <command>
5
+
6
+ // Check Node version
7
+ const nodeVersion = process.versions.node;
8
+ const majorVersion = parseInt(nodeVersion.split('.')[0], 10);
9
+
10
+ if (majorVersion < 16) {
11
+ console.error('Error: Node.js 16 or higher is required');
12
+ console.error(`You are running Node.js ${nodeVersion}`);
13
+ process.exit(1);
14
+ }
15
+
16
+ // Run the CLI
17
+ require('../dist/cli/index.js');
@@ -0,0 +1,11 @@
1
+ export interface InitOptions {
2
+ origins: string;
3
+ env?: string;
4
+ project?: string;
5
+ baseUrl?: string;
6
+ yes?: boolean;
7
+ }
8
+ /**
9
+ * Init command - onboard a new site by uploading .env secrets
10
+ */
11
+ export declare function initCommand(options: InitOptions): Promise<void>;
@@ -0,0 +1,113 @@
1
+ import { SecretsManagement } from '../../management.js';
2
+ import { parseEnvFile } from '../utils/env-parser.js';
3
+ import { detectApiKeys, summarizeDetectedSecrets } from '../utils/key-detector.js';
4
+ import { hasValidCredentials } from '../../credentials.js';
5
+ /**
6
+ * Init command - onboard a new site by uploading .env secrets
7
+ */
8
+ export async function initCommand(options) {
9
+ // Validate authentication
10
+ if (!hasValidCredentials()) {
11
+ console.error('Error: Not authenticated. Run "learn-secrets login" first.');
12
+ process.exit(1);
13
+ }
14
+ // Validate required options
15
+ if (!options.origins) {
16
+ console.error('Error: --origins is required');
17
+ console.error('Example: learn-secrets init --origins mysite.com,localhost');
18
+ process.exit(1);
19
+ }
20
+ if (!options.project) {
21
+ console.error('Error: --project is required');
22
+ console.error('Example: learn-secrets init --project my-app-id --origins mysite.com');
23
+ process.exit(1);
24
+ }
25
+ // Parse origins
26
+ const origins = options.origins.split(',').map(o => o.trim()).filter(Boolean);
27
+ if (origins.length === 0) {
28
+ console.error('Error: No valid origins provided');
29
+ process.exit(1);
30
+ }
31
+ console.log(`\nOnboarding site for project: ${options.project}`);
32
+ console.log(`Origins: ${origins.join(', ')}\n`);
33
+ // Load and detect secrets from .env
34
+ const envFile = options.env || '.env';
35
+ let secrets;
36
+ try {
37
+ console.log(`Reading ${envFile}...`);
38
+ const envVars = parseEnvFile(envFile);
39
+ secrets = detectApiKeys(envVars);
40
+ if (secrets.length === 0) {
41
+ console.log('\nNo API keys detected in .env file.');
42
+ console.log('Make sure your .env contains variables like:');
43
+ console.log(' OPENAI_API_KEY=sk-...');
44
+ console.log(' ANTHROPIC_API_KEY=sk-ant-...');
45
+ process.exit(0);
46
+ }
47
+ console.log('\n' + summarizeDetectedSecrets(secrets));
48
+ console.log('');
49
+ }
50
+ catch (error) {
51
+ console.error(`Error reading ${envFile}:`, error.message);
52
+ process.exit(1);
53
+ }
54
+ // Ask for confirmation unless --yes flag
55
+ if (!options.yes) {
56
+ const readline = await import('readline');
57
+ const rl = readline.createInterface({
58
+ input: process.stdin,
59
+ output: process.stdout
60
+ });
61
+ const answer = await new Promise((resolve) => {
62
+ rl.question('Upload these secrets? (y/N): ', resolve);
63
+ });
64
+ rl.close();
65
+ if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
66
+ console.log('Cancelled.');
67
+ process.exit(0);
68
+ }
69
+ }
70
+ // Upload secrets
71
+ console.log('\nUploading secrets...');
72
+ const mgmt = new SecretsManagement({
73
+ appId: options.project,
74
+ baseUrl: options.baseUrl
75
+ });
76
+ try {
77
+ const result = await mgmt.importSecrets({
78
+ version: '1.0',
79
+ origins,
80
+ secrets
81
+ });
82
+ console.log('\nSuccess!');
83
+ console.log(` Created: ${result.results.created} secrets`);
84
+ console.log(` Updated: ${result.results.updated} secrets`);
85
+ if (result.results.failed > 0) {
86
+ console.log(` Failed: ${result.results.failed} secrets`);
87
+ for (const failure of result.results.details.failed) {
88
+ console.log(` - ${failure.name}: ${failure.error}`);
89
+ }
90
+ }
91
+ if (result.sdkToken) {
92
+ console.log('\nSDK Token created:');
93
+ console.log(` ${result.sdkToken.token}`);
94
+ console.log('\n IMPORTANT: Save this token - it will not be shown again.');
95
+ console.log(' Add it to your static site code:');
96
+ console.log('');
97
+ console.log(' const sdk = new SecretsSDK();');
98
+ console.log(' // No appId or token needed - uses origin-based auth!');
99
+ }
100
+ console.log('\nYour site is ready!');
101
+ console.log(`Visit: https://ctklearn.carsontkempf.workers.dev to manage secrets`);
102
+ }
103
+ catch (error) {
104
+ console.error('\nUpload failed:', error.message);
105
+ if (error.status === 401) {
106
+ console.error('Your session may have expired. Try running "learn-secrets login" again.');
107
+ }
108
+ if (error.status === 404) {
109
+ console.error(`Project "${options.project}" not found. Check your project ID.`);
110
+ }
111
+ process.exit(1);
112
+ }
113
+ }
@@ -0,0 +1,7 @@
1
+ export interface LoginOptions {
2
+ baseUrl?: string;
3
+ }
4
+ /**
5
+ * Login command - authenticate via browser OAuth flow
6
+ */
7
+ export declare function loginCommand(options?: LoginOptions): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { SecretsManagement } from '../../management.js';
2
+ /**
3
+ * Login command - authenticate via browser OAuth flow
4
+ */
5
+ export async function loginCommand(options = {}) {
6
+ console.log('Authenticating with Learn Secrets...\n');
7
+ // Create management client (appId not needed for login)
8
+ const mgmt = new SecretsManagement({
9
+ appId: 'temp', // Will be set after login
10
+ baseUrl: options.baseUrl
11
+ });
12
+ try {
13
+ const result = await mgmt.login();
14
+ console.log(`\nLogged in as: ${result.user}`);
15
+ console.log('Credentials saved to ~/.learn/credentials.json');
16
+ console.log('\nYou can now run: learn-secrets init --origins yourdomain.com');
17
+ }
18
+ catch (error) {
19
+ console.error('\nLogin failed:', error.message);
20
+ process.exit(1);
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { loginCommand } from './commands/login.js';
4
+ import { initCommand } from './commands/init.js';
5
+ const program = new Command();
6
+ program
7
+ .name('learn-secrets')
8
+ .description('CLI tool for managing API secrets in static sites')
9
+ .version('1.4.0');
10
+ // Login command
11
+ program
12
+ .command('login')
13
+ .description('Authenticate with Learn Secrets via browser')
14
+ .option('--base-url <url>', 'Custom base URL for API')
15
+ .action(async (options) => {
16
+ await loginCommand(options);
17
+ });
18
+ // Init command
19
+ program
20
+ .command('init')
21
+ .description('Initialize secrets for a new site')
22
+ .requiredOption('-o, --origins <domains>', 'Comma-separated list of allowed origins (e.g., mysite.com,localhost)')
23
+ .requiredOption('-p, --project <appid>', 'Project app ID from dashboard')
24
+ .option('-e, --env <file>', 'Path to .env file (default: .env)', '.env')
25
+ .option('--base-url <url>', 'Custom base URL for API')
26
+ .option('-y, --yes', 'Skip confirmation prompt')
27
+ .action(async (options) => {
28
+ await initCommand(options);
29
+ });
30
+ // Parse arguments
31
+ program.parse(process.argv);
32
+ // Show help if no command provided
33
+ if (!process.argv.slice(2).length) {
34
+ program.outputHelp();
35
+ }
@@ -0,0 +1,19 @@
1
+ export interface EnvVariable {
2
+ key: string;
3
+ value: string;
4
+ }
5
+ /**
6
+ * Parse a .env file into key-value pairs
7
+ * Supports:
8
+ * - KEY=value
9
+ * - KEY="value"
10
+ * - KEY='value'
11
+ * - # comments
12
+ * - Empty lines
13
+ */
14
+ export declare function parseEnvFile(filePath: string): EnvVariable[];
15
+ /**
16
+ * Load environment variables from a .env file
17
+ * Returns a Map for easy lookup
18
+ */
19
+ export declare function loadEnvFile(filePath: string): Map<string, string>;
@@ -0,0 +1,47 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ /**
4
+ * Parse a .env file into key-value pairs
5
+ * Supports:
6
+ * - KEY=value
7
+ * - KEY="value"
8
+ * - KEY='value'
9
+ * - # comments
10
+ * - Empty lines
11
+ */
12
+ export function parseEnvFile(filePath) {
13
+ const resolvedPath = resolve(filePath);
14
+ if (!existsSync(resolvedPath)) {
15
+ throw new Error(`File not found: ${resolvedPath}`);
16
+ }
17
+ const content = readFileSync(resolvedPath, 'utf-8');
18
+ const lines = content.split('\n');
19
+ const variables = [];
20
+ for (const line of lines) {
21
+ const trimmed = line.trim();
22
+ // Skip empty lines and comments
23
+ if (!trimmed || trimmed.startsWith('#')) {
24
+ continue;
25
+ }
26
+ // Match KEY=value, KEY="value", or KEY='value'
27
+ const match = trimmed.match(/^([A-Z0-9_]+)\s*=\s*(['"]?)(.+?)\2$/i);
28
+ if (match) {
29
+ const key = match[1];
30
+ const value = match[3];
31
+ variables.push({ key, value });
32
+ }
33
+ }
34
+ return variables;
35
+ }
36
+ /**
37
+ * Load environment variables from a .env file
38
+ * Returns a Map for easy lookup
39
+ */
40
+ export function loadEnvFile(filePath) {
41
+ const variables = parseEnvFile(filePath);
42
+ const map = new Map();
43
+ for (const { key, value } of variables) {
44
+ map.set(key, value);
45
+ }
46
+ return map;
47
+ }
@@ -0,0 +1,33 @@
1
+ import type { SecretConfig } from '../../types.js';
2
+ import type { EnvVariable } from './env-parser.js';
3
+ interface ProviderPattern {
4
+ pattern: RegExp;
5
+ provider: string;
6
+ baseUrl?: string;
7
+ authHeader?: string;
8
+ authPrefix?: string;
9
+ }
10
+ /**
11
+ * Detect if an environment variable is likely an API key
12
+ */
13
+ export declare function isLikelyApiKey(key: string, value: string): boolean;
14
+ /**
15
+ * Detect provider from environment variable name
16
+ */
17
+ export declare function detectProvider(key: string): ProviderPattern | null;
18
+ /**
19
+ * Convert environment variable to secret name
20
+ * OPENAI_API_KEY -> openai
21
+ * MY_API_KEY -> my-api
22
+ */
23
+ export declare function envKeyToSecretName(key: string): string;
24
+ /**
25
+ * Detect API keys from environment variables
26
+ * Returns SecretConfig array ready for import
27
+ */
28
+ export declare function detectApiKeys(envVars: EnvVariable[]): SecretConfig[];
29
+ /**
30
+ * Display detected secrets summary (for user confirmation)
31
+ */
32
+ export declare function summarizeDetectedSecrets(secrets: SecretConfig[]): string;
33
+ export {};
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Common API key patterns and their providers
3
+ */
4
+ const PROVIDER_PATTERNS = [
5
+ {
6
+ pattern: /^OPENAI_API_KEY$/i,
7
+ provider: 'openai',
8
+ baseUrl: 'https://api.openai.com',
9
+ authHeader: 'Authorization',
10
+ authPrefix: 'Bearer '
11
+ },
12
+ {
13
+ pattern: /^ANTHROPIC_API_KEY$/i,
14
+ provider: 'anthropic',
15
+ baseUrl: 'https://api.anthropic.com',
16
+ authHeader: 'x-api-key',
17
+ authPrefix: ''
18
+ },
19
+ {
20
+ pattern: /^STRIPE_(SECRET_)?KEY$/i,
21
+ provider: 'stripe',
22
+ baseUrl: 'https://api.stripe.com',
23
+ authHeader: 'Authorization',
24
+ authPrefix: 'Bearer '
25
+ },
26
+ {
27
+ pattern: /^GITHUB_TOKEN$/i,
28
+ provider: 'github',
29
+ baseUrl: 'https://api.github.com',
30
+ authHeader: 'Authorization',
31
+ authPrefix: 'Bearer '
32
+ },
33
+ {
34
+ pattern: /^GOOGLE_API_KEY$/i,
35
+ provider: 'google',
36
+ baseUrl: 'https://www.googleapis.com',
37
+ authHeader: 'Authorization',
38
+ authPrefix: 'Bearer '
39
+ }
40
+ ];
41
+ /**
42
+ * Detect if an environment variable is likely an API key
43
+ */
44
+ export function isLikelyApiKey(key, value) {
45
+ // Check common patterns
46
+ const keyPatterns = [
47
+ /_API_KEY$/i,
48
+ /_SECRET$/i,
49
+ /_TOKEN$/i,
50
+ /^API_KEY_/i,
51
+ /^SECRET_/i,
52
+ /^TOKEN_/i
53
+ ];
54
+ for (const pattern of keyPatterns) {
55
+ if (pattern.test(key)) {
56
+ return true;
57
+ }
58
+ }
59
+ // Check value patterns (looks like a key/token)
60
+ const valuePatterns = [
61
+ /^sk-[a-zA-Z0-9_-]+$/, // OpenAI, Stripe
62
+ /^sk-ant-[a-zA-Z0-9_-]+$/, // Anthropic
63
+ /^ghp_[a-zA-Z0-9]+$/, // GitHub
64
+ /^ya29\.[a-zA-Z0-9_-]+$/, // Google OAuth
65
+ /^[a-f0-9]{32}$/, // 32-char hex
66
+ /^[a-f0-9]{40}$/, // 40-char hex (like GitHub)
67
+ /^[a-zA-Z0-9_-]{40,}$/ // Long random string
68
+ ];
69
+ for (const pattern of valuePatterns) {
70
+ if (pattern.test(value)) {
71
+ return true;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+ /**
77
+ * Detect provider from environment variable name
78
+ */
79
+ export function detectProvider(key) {
80
+ for (const pattern of PROVIDER_PATTERNS) {
81
+ if (pattern.pattern.test(key)) {
82
+ return pattern;
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+ /**
88
+ * Convert environment variable to secret name
89
+ * OPENAI_API_KEY -> openai
90
+ * MY_API_KEY -> my-api
91
+ */
92
+ export function envKeyToSecretName(key) {
93
+ return key
94
+ .toLowerCase()
95
+ .replace(/_api_key$/i, '')
96
+ .replace(/_secret$/i, '')
97
+ .replace(/_token$/i, '')
98
+ .replace(/_key$/i, '')
99
+ .replace(/_/g, '-');
100
+ }
101
+ /**
102
+ * Detect API keys from environment variables
103
+ * Returns SecretConfig array ready for import
104
+ */
105
+ export function detectApiKeys(envVars) {
106
+ const secrets = [];
107
+ for (const { key, value } of envVars) {
108
+ // Skip if doesn't look like an API key
109
+ if (!isLikelyApiKey(key, value)) {
110
+ continue;
111
+ }
112
+ // Detect provider
113
+ const providerInfo = detectProvider(key);
114
+ const secretName = envKeyToSecretName(key);
115
+ if (providerInfo) {
116
+ // Known provider
117
+ secrets.push({
118
+ name: secretName,
119
+ provider: providerInfo.provider,
120
+ api_key: value,
121
+ base_url: providerInfo.baseUrl,
122
+ auth_header: providerInfo.authHeader,
123
+ auth_prefix: providerInfo.authPrefix
124
+ });
125
+ }
126
+ else {
127
+ // Custom/unknown provider
128
+ secrets.push({
129
+ name: secretName,
130
+ provider: 'custom',
131
+ api_key: value,
132
+ base_url: '', // User must configure
133
+ auth_header: 'Authorization',
134
+ auth_prefix: 'Bearer '
135
+ });
136
+ }
137
+ }
138
+ return secrets;
139
+ }
140
+ /**
141
+ * Display detected secrets summary (for user confirmation)
142
+ */
143
+ export function summarizeDetectedSecrets(secrets) {
144
+ if (secrets.length === 0) {
145
+ return 'No API keys detected in .env file';
146
+ }
147
+ const lines = ['Detected API keys:'];
148
+ for (const secret of secrets) {
149
+ const masked = secret.api_key.substring(0, 8) + '...';
150
+ lines.push(` - ${secret.name} (${secret.provider}): ${masked}`);
151
+ }
152
+ return lines.join('\n');
153
+ }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { SecretsSDKOptions, ProxyRequest, RateLimitInfo } from './types';
1
+ import type { SecretsSDKOptions, ProxyRequest, RateLimitInfo } from './types.js';
2
2
  export declare class SecretsSDK {
3
3
  private appId;
4
4
  private token;
package/dist/client.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types';
1
+ import { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types.js';
2
2
  export class SecretsSDK {
3
3
  /**
4
4
  * Create a new SecretsSDK instance
@@ -1,4 +1,4 @@
1
- import type { CLICredentials } from './types';
1
+ import type { CLICredentials } from './types.js';
2
2
  /**
3
3
  * Get the path to the credentials file
4
4
  * Defaults to ~/.learn/credentials.json
@@ -1,4 +1,4 @@
1
- import type { SecretConfig } from './types';
1
+ import type { SecretConfig } from './types.js';
2
2
  /**
3
3
  * Resolve environment variable references in a string
4
4
  * Supports ${VAR} and $VAR syntax
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { SecretsSDK } from './client';
2
- export { SecretsManagement } from './management';
3
- export { resolveEnvString, resolveEnvInSecret, resolveEnvInSecrets, loadSecretsConfig } from './env-resolver';
4
- export { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types';
5
- export type { SecretsSDKOptions, ProxyRequest, ProxyResponse, RateLimitInfo, SecretsManagementOptions, SecretConfig, MaskedSecret, SyncOptions, SyncResult, CLICredentials } from './types';
1
+ export { SecretsSDK } from './client.js';
2
+ export { SecretsManagement } from './management.js';
3
+ export { resolveEnvString, resolveEnvInSecret, resolveEnvInSecrets, loadSecretsConfig } from './env-resolver.js';
4
+ export { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types.js';
5
+ export type { SecretsSDKOptions, ProxyRequest, ProxyResponse, RateLimitInfo, SecretsManagementOptions, SecretConfig, MaskedSecret, SyncOptions, SyncResult, CLICredentials } from './types.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { SecretsSDK } from './client';
2
- export { SecretsManagement } from './management';
3
- export { resolveEnvString, resolveEnvInSecret, resolveEnvInSecrets, loadSecretsConfig } from './env-resolver';
4
- export { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types';
1
+ export { SecretsSDK } from './client.js';
2
+ export { SecretsManagement } from './management.js';
3
+ export { resolveEnvString, resolveEnvInSecret, resolveEnvInSecrets, loadSecretsConfig } from './env-resolver.js';
4
+ export { SecretsSDKError, OriginMismatchError, RateLimitError, InvalidTokenError } from './types.js';
@@ -1,4 +1,4 @@
1
- import { type SecretsManagementOptions, type SecretConfig, type MaskedSecret, type SyncOptions, type SyncResult } from './types';
1
+ import { type SecretsManagementOptions, type SecretConfig, type MaskedSecret, type SyncOptions, type SyncResult } from './types.js';
2
2
  /**
3
3
  * SecretsManagement class for CLI authentication and secrets management
4
4
  */
@@ -48,4 +48,51 @@ export declare class SecretsManagement {
48
48
  * Sync secrets from config
49
49
  */
50
50
  sync(secrets: SecretConfig[], options?: SyncOptions): Promise<SyncResult>;
51
+ /**
52
+ * Import secrets from a config object (bulk import)
53
+ * Also creates SDK token if origins are provided
54
+ *
55
+ * @param config - The secrets configuration
56
+ * @returns Import results including created/updated counts and optional SDK token
57
+ */
58
+ importSecrets(config: {
59
+ version?: string;
60
+ origins?: string[];
61
+ secrets: SecretConfig[];
62
+ }): Promise<{
63
+ success: boolean;
64
+ results: {
65
+ created: number;
66
+ updated: number;
67
+ failed: number;
68
+ details: {
69
+ created: string[];
70
+ updated: string[];
71
+ failed: {
72
+ name: string;
73
+ error: string;
74
+ }[];
75
+ };
76
+ };
77
+ sdkToken?: {
78
+ token: string;
79
+ message: string;
80
+ };
81
+ }>;
82
+ /**
83
+ * Import secrets from a JSON file path
84
+ * Resolves environment variables in the config
85
+ */
86
+ importFromFile(configPath: string): Promise<{
87
+ success: boolean;
88
+ results: {
89
+ created: number;
90
+ updated: number;
91
+ failed: number;
92
+ };
93
+ sdkToken?: {
94
+ token: string;
95
+ message: string;
96
+ };
97
+ }>;
51
98
  }
@@ -1,5 +1,5 @@
1
- import { SecretsSDKError } from './types';
2
- import { readCredentials, writeCredentials, deleteCredentials, hasValidCredentials } from './credentials';
1
+ import { SecretsSDKError } from './types.js';
2
+ import { readCredentials, writeCredentials, deleteCredentials, hasValidCredentials } from './credentials.js';
3
3
  /**
4
4
  * SecretsManagement class for CLI authentication and secrets management
5
5
  */
@@ -188,4 +188,27 @@ export class SecretsManagement {
188
188
  });
189
189
  return response;
190
190
  }
191
+ /**
192
+ * Import secrets from a config object (bulk import)
193
+ * Also creates SDK token if origins are provided
194
+ *
195
+ * @param config - The secrets configuration
196
+ * @returns Import results including created/updated counts and optional SDK token
197
+ */
198
+ async importSecrets(config) {
199
+ return this.request('POST', `/api/projects/${this.appId}/import-secrets`, {
200
+ version: config.version || '1.0',
201
+ origins: config.origins,
202
+ secrets: config.secrets
203
+ });
204
+ }
205
+ /**
206
+ * Import secrets from a JSON file path
207
+ * Resolves environment variables in the config
208
+ */
209
+ async importFromFile(configPath) {
210
+ const { loadSecretsConfig } = await import('./env-resolver');
211
+ const config = loadSecretsConfig(configPath);
212
+ return this.importSecrets(config);
213
+ }
191
214
  }
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "learn-secrets-sdk",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Secure API proxy SDK for static sites with domain-scoped tokens",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "learn-secrets": "./bin/learn-secrets.js"
10
+ },
8
11
  "files": [
9
- "dist"
12
+ "dist",
13
+ "bin",
14
+ "secrets.template.json"
10
15
  ],
11
16
  "scripts": {
12
17
  "build": "tsc && tsc --project tsconfig.esm.json",
@@ -17,11 +22,17 @@
17
22
  "proxy",
18
23
  "secrets",
19
24
  "static-sites",
20
- "security"
25
+ "security",
26
+ "cli",
27
+ "secrets-management"
21
28
  ],
22
29
  "author": "",
23
30
  "license": "MIT",
31
+ "dependencies": {
32
+ "commander": "^12.0.0"
33
+ },
24
34
  "devDependencies": {
35
+ "@types/node": "^20.0.0",
25
36
  "typescript": "^5.0.0"
26
37
  }
27
38
  }
@@ -0,0 +1,42 @@
1
+ {
2
+ "version": "1.0",
3
+ "project": "your-app-id",
4
+ "origins": [
5
+ "localhost",
6
+ "yourdomain.com"
7
+ ],
8
+ "secrets": [
9
+ {
10
+ "name": "test-echo",
11
+ "provider": "custom",
12
+ "api_key": "test",
13
+ "base_url": "https://httpbin.org",
14
+ "auth_header": "Authorization",
15
+ "auth_prefix": "Bearer "
16
+ },
17
+ {
18
+ "name": "openai",
19
+ "provider": "openai",
20
+ "api_key": "${OPENAI_API_KEY}",
21
+ "base_url": "https://api.openai.com",
22
+ "auth_header": "Authorization",
23
+ "auth_prefix": "Bearer "
24
+ },
25
+ {
26
+ "name": "anthropic",
27
+ "provider": "anthropic",
28
+ "api_key": "${ANTHROPIC_API_KEY}",
29
+ "base_url": "https://api.anthropic.com",
30
+ "auth_header": "x-api-key",
31
+ "auth_prefix": ""
32
+ },
33
+ {
34
+ "name": "stripe",
35
+ "provider": "stripe",
36
+ "api_key": "${STRIPE_SECRET_KEY}",
37
+ "base_url": "https://api.stripe.com",
38
+ "auth_header": "Authorization",
39
+ "auth_prefix": "Bearer "
40
+ }
41
+ ]
42
+ }