@fold-run/cli 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +157 -0
  2. package/dist/commands/create-tool.d.ts +8 -0
  3. package/dist/commands/create-tool.js +76 -0
  4. package/dist/commands/create-tool.js.map +1 -0
  5. package/dist/commands/delete.d.ts +3 -0
  6. package/dist/commands/delete.js +17 -0
  7. package/dist/commands/delete.js.map +1 -0
  8. package/dist/commands/deploy.d.ts +5 -0
  9. package/dist/commands/deploy.js +77 -0
  10. package/dist/commands/deploy.js.map +1 -0
  11. package/dist/commands/dev.d.ts +6 -0
  12. package/dist/commands/dev.js +178 -0
  13. package/dist/commands/dev.js.map +1 -0
  14. package/dist/commands/env-vars.d.ts +12 -0
  15. package/dist/commands/env-vars.js +40 -0
  16. package/dist/commands/env-vars.js.map +1 -0
  17. package/dist/commands/functions.d.ts +3 -0
  18. package/dist/commands/functions.js +26 -0
  19. package/dist/commands/functions.js.map +1 -0
  20. package/dist/commands/init.d.ts +3 -0
  21. package/dist/commands/init.js +94 -0
  22. package/dist/commands/init.js.map +1 -0
  23. package/dist/commands/login.d.ts +3 -0
  24. package/dist/commands/login.js +125 -0
  25. package/dist/commands/login.js.map +1 -0
  26. package/dist/commands/logs.d.ts +7 -0
  27. package/dist/commands/logs.js +81 -0
  28. package/dist/commands/logs.js.map +1 -0
  29. package/dist/commands/open.d.ts +3 -0
  30. package/dist/commands/open.js +24 -0
  31. package/dist/commands/open.js.map +1 -0
  32. package/dist/commands/rollback.d.ts +1 -0
  33. package/dist/commands/rollback.js +13 -0
  34. package/dist/commands/rollback.js.map +1 -0
  35. package/dist/commands/schedules.d.ts +11 -0
  36. package/dist/commands/schedules.js +49 -0
  37. package/dist/commands/schedules.js.map +1 -0
  38. package/dist/commands/secrets.d.ts +7 -0
  39. package/dist/commands/secrets.js +47 -0
  40. package/dist/commands/secrets.js.map +1 -0
  41. package/dist/commands/status.d.ts +3 -0
  42. package/dist/commands/status.js +62 -0
  43. package/dist/commands/status.js.map +1 -0
  44. package/dist/commands/tail.d.ts +4 -0
  45. package/dist/commands/tail.js +108 -0
  46. package/dist/commands/tail.js.map +1 -0
  47. package/dist/commands/templates.d.ts +8 -0
  48. package/dist/commands/templates.js +69 -0
  49. package/dist/commands/templates.js.map +1 -0
  50. package/dist/commands/webhooks.d.ts +8 -0
  51. package/dist/commands/webhooks.js +38 -0
  52. package/dist/commands/webhooks.js.map +1 -0
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.js +259 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/lib/api.d.ts +12 -0
  57. package/dist/lib/api.js +31 -0
  58. package/dist/lib/api.js.map +1 -0
  59. package/dist/lib/bundler.d.ts +10 -0
  60. package/dist/lib/bundler.js +124 -0
  61. package/dist/lib/bundler.js.map +1 -0
  62. package/dist/lib/config.d.ts +9 -0
  63. package/dist/lib/config.js +56 -0
  64. package/dist/lib/config.js.map +1 -0
  65. package/dist/lib/output.d.ts +6 -0
  66. package/dist/lib/output.js +19 -0
  67. package/dist/lib/output.js.map +1 -0
  68. package/dist/lib/prompt.d.ts +5 -0
  69. package/dist/lib/prompt.js +40 -0
  70. package/dist/lib/prompt.js.map +1 -0
  71. package/package.json +50 -0
@@ -0,0 +1,3 @@
1
+ export declare function initCommand(opts: {
2
+ name?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,94 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ const FUNCTION_TEMPLATE = `import { defineHandler } from '@fold-run/runtime';
5
+
6
+ export default defineHandler(async (ctx) => {
7
+ const url = new URL(ctx.request.url);
8
+
9
+ if (url.pathname === '/') {
10
+ return ctx.json({ message: 'Hello from fold.run!' });
11
+ }
12
+
13
+ if (url.pathname === '/kv-demo') {
14
+ // ctx.kv — Fold KV store (attach via dashboard → Bindings)
15
+ const visits = Number(await ctx.kv.get('visits') ?? '0') + 1;
16
+ await ctx.kv.put('visits', String(visits));
17
+ return ctx.json({ visits });
18
+ }
19
+
20
+ return ctx.json({ error: 'Not found' }, 404);
21
+ });
22
+ `;
23
+ const TSCONFIG_TEMPLATE = `{
24
+ "compilerOptions": {
25
+ "target": "ESNext",
26
+ "module": "ESNext",
27
+ "moduleResolution": "bundler",
28
+ "strict": true,
29
+ "skipLibCheck": true
30
+ },
31
+ "include": ["*.ts"]
32
+ }
33
+ `;
34
+ /** Detect which package manager is in use based on lockfile presence */
35
+ function detectPackageManager(dir) {
36
+ if (existsSync(join(dir, 'pnpm-lock.yaml')))
37
+ return 'pnpm';
38
+ if (existsSync(join(dir, 'yarn.lock')))
39
+ return 'yarn';
40
+ return 'npm';
41
+ }
42
+ export async function initCommand(opts) {
43
+ const dir = resolve(opts.name ?? '.');
44
+ const name = opts.name ?? dir.split('/').pop() ?? 'my-function';
45
+ if (opts.name && !existsSync(dir)) {
46
+ mkdirSync(dir, { recursive: true });
47
+ }
48
+ const functionPath = join(dir, 'function.ts');
49
+ const configPath = join(dir, 'fold.json');
50
+ const pkgPath = join(dir, 'package.json');
51
+ const tsconfigPath = join(dir, 'tsconfig.json');
52
+ if (existsSync(functionPath)) {
53
+ console.error(`${functionPath} already exists. Aborting.`);
54
+ process.exit(1);
55
+ }
56
+ // Write source files
57
+ writeFileSync(functionPath, FUNCTION_TEMPLATE);
58
+ writeFileSync(configPath, `${JSON.stringify({ name, entrypoint: 'function.ts', intent: { bindings: [] } }, null, 2)}\n`);
59
+ // Scaffold package.json if none exists
60
+ if (!existsSync(pkgPath)) {
61
+ writeFileSync(pkgPath, `${JSON.stringify({
62
+ name,
63
+ version: '0.1.0',
64
+ type: 'module',
65
+ private: true,
66
+ devDependencies: {
67
+ '@fold-run/runtime': '^0.1.0',
68
+ typescript: '^5.7.0',
69
+ },
70
+ }, null, 2)}\n`);
71
+ }
72
+ // Scaffold tsconfig.json if none exists
73
+ if (!existsSync(tsconfigPath)) {
74
+ writeFileSync(tsconfigPath, TSCONFIG_TEMPLATE);
75
+ }
76
+ // Install dependencies
77
+ const pm = detectPackageManager(dir);
78
+ const installCmd = pm === 'yarn' ? 'yarn' : `${pm} install`;
79
+ console.log(`Installing @fold-run/runtime...`);
80
+ try {
81
+ execSync(installCmd, { cwd: dir, stdio: 'inherit' });
82
+ }
83
+ catch {
84
+ console.warn(`\nCould not run '${installCmd}'. Run it manually to get type hints.`);
85
+ }
86
+ console.log(`\nInitialized ${name}:`);
87
+ console.log(` ${functionPath}`);
88
+ console.log(` ${configPath}`);
89
+ console.log(`\nNext steps:`);
90
+ console.log(` fold login`);
91
+ console.log(` fold dev # local dev server`);
92
+ console.log(` fold deploy # deploy to fold.run`);
93
+ }
94
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function loginCommand(opts: {
2
+ method?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,125 @@
1
+ import { stdin, stdout } from 'node:process';
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { saveConfig } from '../lib/config.js';
4
+ import { readSecret } from '../lib/prompt.js';
5
+ export async function loginCommand(opts) {
6
+ const rl = createInterface({ input: stdin, output: stdout });
7
+ try {
8
+ const apiUrl = (await rl.question('API URL [https://api.fold.run]: ')).trim() || 'https://api.fold.run';
9
+ // Enforce HTTPS (allow http://localhost for local dev)
10
+ if (!apiUrl.startsWith('https://') && !apiUrl.startsWith('http://localhost')) {
11
+ console.error('API URL must use HTTPS (http://localhost allowed for local dev).');
12
+ process.exit(1);
13
+ }
14
+ // Validate by hitting the health endpoint
15
+ try {
16
+ const res = await fetch(`${apiUrl}/health`);
17
+ if (!res.ok)
18
+ throw new Error(`HTTP ${res.status}`);
19
+ }
20
+ catch (err) {
21
+ console.error(`Could not reach ${apiUrl}/health: ${err}`);
22
+ process.exit(1);
23
+ }
24
+ const method = opts.method ??
25
+ ((await rl.question('Login method (browser/email/token) [browser]: ')).trim().toLowerCase() || 'browser');
26
+ let token;
27
+ let tenantId;
28
+ if (method === 'browser') {
29
+ rl.close();
30
+ const result = await deviceAuthFlow(apiUrl);
31
+ token = result.token;
32
+ tenantId = result.tenantId;
33
+ }
34
+ else if (method === 'email') {
35
+ const email = (await rl.question('Email: ')).trim();
36
+ rl.close();
37
+ const password = (await readSecret('Password: ')).trim();
38
+ if (!email || !password) {
39
+ console.error('Email and password are required.');
40
+ process.exit(1);
41
+ }
42
+ const res = await fetch(`${apiUrl}/auth/login`, {
43
+ method: 'POST',
44
+ headers: { 'Content-Type': 'application/json' },
45
+ body: JSON.stringify({ email, password }),
46
+ });
47
+ if (!res.ok) {
48
+ const data = (await res.json());
49
+ console.error(`Login failed: ${data.error ?? `HTTP ${res.status}`}`);
50
+ process.exit(1);
51
+ }
52
+ const data = (await res.json());
53
+ token = data.token;
54
+ tenantId = data.tenant_id;
55
+ console.log(`Authenticated as ${email} (${data.role})`);
56
+ }
57
+ else {
58
+ token = (await rl.question('API Token: ')).trim();
59
+ tenantId = (await rl.question('Tenant ID (optional): ')).trim() || undefined;
60
+ rl.close();
61
+ if (!token) {
62
+ console.error('Token is required.');
63
+ process.exit(1);
64
+ }
65
+ }
66
+ saveConfig({ apiUrl, token, tenantId });
67
+ console.log(`Logged in to ${apiUrl}`);
68
+ if (tenantId)
69
+ console.log(`Default tenant: ${tenantId}`);
70
+ }
71
+ finally {
72
+ rl.close();
73
+ }
74
+ }
75
+ async function deviceAuthFlow(apiUrl) {
76
+ // Step 1: Request device code
77
+ const codeRes = await fetch(`${apiUrl}/auth/device/code`, { method: 'POST' });
78
+ if (!codeRes.ok) {
79
+ const err = (await codeRes.json().catch(() => ({})));
80
+ console.error(`Failed to start device auth: ${err.error ?? `HTTP ${codeRes.status}`}`);
81
+ process.exit(1);
82
+ }
83
+ const { device_code, user_code, verification_uri, interval } = (await codeRes.json());
84
+ console.log('\nOpen this URL in your browser to authenticate:\n');
85
+ console.log(` ${verification_uri}\n`);
86
+ console.log(`Enter this code: \x1b[1m${user_code}\x1b[0m\n`);
87
+ // Try to open browser automatically
88
+ try {
89
+ const { exec } = await import('node:child_process');
90
+ const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
91
+ exec(`${cmd} ${verification_uri}`);
92
+ }
93
+ catch {
94
+ // User can open manually
95
+ }
96
+ console.log('Waiting for authorization...');
97
+ // Step 2: Poll for token
98
+ const pollInterval = (interval ?? 5) * 1000;
99
+ const maxAttempts = 120; // 10 minutes max
100
+ for (let i = 0; i < maxAttempts; i++) {
101
+ await new Promise((r) => setTimeout(r, pollInterval));
102
+ const tokenRes = await fetch(`${apiUrl}/auth/device/token`, {
103
+ method: 'POST',
104
+ headers: { 'Content-Type': 'application/json' },
105
+ body: JSON.stringify({ device_code }),
106
+ });
107
+ if (tokenRes.ok) {
108
+ const data = (await tokenRes.json());
109
+ console.log('\nAuthorized!');
110
+ return { token: data.token, tenantId: data.tenant_id };
111
+ }
112
+ if (tokenRes.status === 428) {
113
+ // authorization_pending — keep polling
114
+ process.stdout.write('.');
115
+ continue;
116
+ }
117
+ // Any other error — fail
118
+ const err = (await tokenRes.json().catch(() => ({})));
119
+ console.error(`\nAuthorization failed: ${err.error ?? `HTTP ${tokenRes.status}`}`);
120
+ process.exit(1);
121
+ }
122
+ console.error('\nAuthorization timed out. Please try again.');
123
+ process.exit(1);
124
+ }
125
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function logsCommand(opts: {
2
+ functionId?: string;
3
+ tenant?: string;
4
+ follow?: boolean;
5
+ limit?: string;
6
+ verbose?: boolean;
7
+ }): Promise<void>;
@@ -0,0 +1,81 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ import { isJsonMode } from '../lib/output.js';
4
+ export async function logsCommand(opts) {
5
+ const config = requireConfig();
6
+ const tenantId = opts.tenant ?? config.tenantId;
7
+ const params = new URLSearchParams();
8
+ if (opts.functionId)
9
+ params.set('function_id', opts.functionId);
10
+ else if (tenantId)
11
+ params.set('tenant_id', tenantId);
12
+ if (opts.limit)
13
+ params.set('limit', opts.limit);
14
+ const verbose = opts.verbose ?? false;
15
+ if (!opts.follow) {
16
+ const result = (await apiFetch(config, `/activations?${params}`));
17
+ if (isJsonMode()) {
18
+ console.log(JSON.stringify(result.activations, null, 2));
19
+ }
20
+ else {
21
+ printActivations(result.activations, verbose);
22
+ }
23
+ return;
24
+ }
25
+ // Follow mode: poll every 2 seconds
26
+ let lastSeen = Date.now();
27
+ // Show recent activations first
28
+ const initial = (await apiFetch(config, `/activations?${params}`));
29
+ if (initial.activations.length) {
30
+ printActivations(initial.activations, verbose);
31
+ lastSeen = Math.max(...initial.activations.map((a) => a.triggered_at));
32
+ }
33
+ console.log('Watching for activations... (Ctrl+C to stop)\n');
34
+ while (true) {
35
+ await new Promise((resolve) => setTimeout(resolve, 2000));
36
+ params.set('since', String(lastSeen));
37
+ const result = (await apiFetch(config, `/activations?${params}`));
38
+ if (result.activations.length) {
39
+ printActivations(result.activations.reverse(), verbose);
40
+ lastSeen = Math.max(...result.activations.map((a) => a.triggered_at));
41
+ }
42
+ }
43
+ }
44
+ function printActivations(activations, verbose) {
45
+ for (const a of activations) {
46
+ const time = new Date(a.triggered_at).toISOString();
47
+ const status = a.status === 'success' ? '\x1b[32mOK\x1b[0m' : '\x1b[31mERR\x1b[0m';
48
+ const duration = a.duration_ms != null ? `${a.duration_ms}ms` : '-';
49
+ const httpStatus = a.response_status ?? '-';
50
+ console.log(`${time} ${status} ${httpStatus} ${duration} ${a.id}`);
51
+ if (a.error_message) {
52
+ console.log(` \x1b[31m${a.error_message}\x1b[0m`);
53
+ }
54
+ if (verbose) {
55
+ if (a.request_headers) {
56
+ try {
57
+ const headers = JSON.parse(a.request_headers);
58
+ const method = headers[':method'] ?? headers.method ?? '';
59
+ const path = headers[':path'] ?? headers.path ?? '';
60
+ if (method || path)
61
+ console.log(` \x1b[36m${method} ${path}\x1b[0m`);
62
+ }
63
+ catch {
64
+ // ignore malformed headers
65
+ }
66
+ }
67
+ if (a.logs) {
68
+ try {
69
+ const logEntries = JSON.parse(a.logs);
70
+ for (const entry of logEntries) {
71
+ console.log(` \x1b[90m${entry}\x1b[0m`);
72
+ }
73
+ }
74
+ catch {
75
+ // ignore malformed logs
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function openCommand(functionId: string, opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { exec } from 'node:child_process';
2
+ import { platform } from 'node:os';
3
+ import { apiFetch } from '../lib/api.js';
4
+ import { requireConfig } from '../lib/config.js';
5
+ export async function openCommand(functionId, opts) {
6
+ const config = requireConfig();
7
+ const tenantId = opts.tenant ?? config.tenantId;
8
+ if (!tenantId) {
9
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
10
+ process.exit(1);
11
+ }
12
+ // Fetch function info to get the URL
13
+ const result = (await apiFetch(config, `/functions?tenant_id=${tenantId}`));
14
+ const fn = result.functions.find((f) => f.id === functionId || f.name === functionId);
15
+ if (!fn) {
16
+ console.error(`Function "${functionId}" not found. Use \`fold functions\` to list available functions.`);
17
+ process.exit(1);
18
+ }
19
+ const url = fn.url;
20
+ console.log(`Opening ${url}`);
21
+ const cmd = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';
22
+ exec(`${cmd} ${url}`);
23
+ }
24
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/commands/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,IAAyB;IAC7E,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC;IAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qCAAqC;IACrC,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,wBAAwB,QAAQ,EAAE,CAAC,CAAkC,CAAC;IAC7G,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAEtF,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,CAAC,KAAK,CAAC,aAAa,UAAU,kEAAkE,CAAC,CAAC;QACzG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC;IACnB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;IAE9B,MAAM,GAAG,GAAG,QAAQ,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7F,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function rollbackCommand(functionId: string, version: string): Promise<void>;
@@ -0,0 +1,13 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ export async function rollbackCommand(functionId, version) {
4
+ const config = requireConfig();
5
+ console.log(`Rolling back ${functionId} to version ${version}...`);
6
+ const result = (await apiFetch(config, '/rollback', {
7
+ body: { function_id: functionId, version: parseInt(version, 10) },
8
+ }));
9
+ console.log(`\nRolled back successfully!`);
10
+ console.log(` Reverted to: v${result.rolled_back_to}`);
11
+ console.log(` New version: v${result.new_version}`);
12
+ }
13
+ //# sourceMappingURL=rollback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/commands/rollback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AASjD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB,EAAE,OAAe;IACvE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,gBAAgB,UAAU,eAAe,OAAO,KAAK,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE;QAClD,IAAI,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE;KAClE,CAAC,CAAmB,CAAC;IAEtB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare function schedulesListCommand(opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
4
+ export declare function schedulesCreateCommand(functionId: string, cron: string, opts: {
5
+ tenant?: string;
6
+ }): Promise<void>;
7
+ export declare function schedulesDeleteCommand(functionId: string): Promise<void>;
8
+ export declare function schedulesToggleCommand(functionId: string, opts: {
9
+ enable?: boolean;
10
+ disable?: boolean;
11
+ }): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ export async function schedulesListCommand(opts) {
4
+ const config = requireConfig();
5
+ const qs = opts.tenant ? `?tenant_id=${opts.tenant}` : '';
6
+ const data = (await apiFetch(config, `/schedules${qs}`));
7
+ if (data.schedules.length === 0) {
8
+ console.log('No scheduled triggers configured.');
9
+ return;
10
+ }
11
+ console.log(`\n Scheduled Triggers\n`);
12
+ for (const s of data.schedules) {
13
+ const status = s.enabled ? '\x1b[32mactive\x1b[0m' : '\x1b[33mpaused\x1b[0m';
14
+ const lastRun = s.last_run_at ? new Date(s.last_run_at).toISOString().slice(0, 19) : 'never';
15
+ console.log(` ${s.function_name}`);
16
+ console.log(` Cron: ${s.cron_expression}`);
17
+ console.log(` Status: ${status}`);
18
+ console.log(` Last run: ${lastRun}`);
19
+ console.log(` ID: ${s.id}`);
20
+ console.log();
21
+ }
22
+ }
23
+ export async function schedulesCreateCommand(functionId, cron, opts) {
24
+ const config = requireConfig();
25
+ const qs = opts.tenant ? `?tenant_id=${opts.tenant}` : '';
26
+ const data = (await apiFetch(config, `/schedules${qs}`, {
27
+ body: { function_id: functionId, cron_expression: cron },
28
+ }));
29
+ console.log(`\n Schedule created!`);
30
+ console.log(` Function: ${data.function_name}`);
31
+ console.log(` Cron: ${data.cron_expression}`);
32
+ console.log(` ID: ${data.id}\n`);
33
+ }
34
+ export async function schedulesDeleteCommand(functionId) {
35
+ const config = requireConfig();
36
+ await apiFetch(config, `/schedules/${functionId}`, { method: 'DELETE' });
37
+ console.log('Schedule deleted.');
38
+ }
39
+ export async function schedulesToggleCommand(functionId, opts) {
40
+ const config = requireConfig();
41
+ const enabled = opts.enable ? true : opts.disable ? false : undefined;
42
+ if (enabled === undefined) {
43
+ console.error('Specify --enable or --disable');
44
+ process.exit(1);
45
+ }
46
+ await apiFetch(config, `/schedules/${functionId}`, { method: 'PUT', body: { enabled } });
47
+ console.log(`Schedule ${enabled ? 'enabled' : 'disabled'}.`);
48
+ }
49
+ //# sourceMappingURL=schedules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/commands/schedules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function secretsSetCommand(name: string, opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
4
+ export declare function secretsListCommand(opts: {
5
+ tenant?: string;
6
+ }): Promise<void>;
7
+ export declare function secretsDeleteCommand(id: string): Promise<void>;
@@ -0,0 +1,47 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ import { output } from '../lib/output.js';
4
+ import { readSecret } from '../lib/prompt.js';
5
+ export async function secretsSetCommand(name, opts) {
6
+ const config = requireConfig();
7
+ const tenantId = opts.tenant ?? config.tenantId;
8
+ if (!tenantId) {
9
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
10
+ process.exit(1);
11
+ }
12
+ const value = (await readSecret('Secret value: ')).trim();
13
+ if (!value) {
14
+ console.error('Value is required.');
15
+ process.exit(1);
16
+ }
17
+ await apiFetch(config, '/secrets', {
18
+ body: { tenant_id: tenantId, name, value },
19
+ });
20
+ console.log(`Secret "${name}" set for tenant ${tenantId}.`);
21
+ }
22
+ export async function secretsListCommand(opts) {
23
+ const config = requireConfig();
24
+ const tenantId = opts.tenant ?? config.tenantId;
25
+ if (!tenantId) {
26
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
27
+ process.exit(1);
28
+ }
29
+ const result = (await apiFetch(config, `/secrets?tenant_id=${tenantId}`));
30
+ output(result.secrets, () => {
31
+ if (!result.secrets.length) {
32
+ console.log('No secrets configured.');
33
+ return;
34
+ }
35
+ console.log(`Secrets for ${tenantId}:\n`);
36
+ for (const s of result.secrets) {
37
+ const created = new Date(s.created_at).toISOString().slice(0, 10);
38
+ console.log(` ${s.name} (created ${created}) [${s.id}]`);
39
+ }
40
+ });
41
+ }
42
+ export async function secretsDeleteCommand(id) {
43
+ const config = requireConfig();
44
+ await apiFetch(config, `/secrets/${id}`, { method: 'DELETE' });
45
+ console.log(`Secret ${id} deleted.`);
46
+ }
47
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/commands/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAQ9C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,IAAyB;IAC7E,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC;IAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE;QACjC,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE;KAC3C,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,oBAAoB,QAAQ,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAyB;IAChE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC;IAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,sBAAsB,QAAQ,EAAE,CAAC,CAA8B,CAAC;IAEvG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,KAAK,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,cAAc,OAAO,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EAAU;IACnD,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,MAAM,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function statusCommand(opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,62 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { loadConfig } from '../lib/config.js';
3
+ export async function statusCommand(opts) {
4
+ const config = loadConfig();
5
+ console.log('Fold CLI Status');
6
+ console.log('───────────────');
7
+ if (!config) {
8
+ console.log('Auth: Not logged in');
9
+ console.log('\nRun `fold login` to get started.');
10
+ return;
11
+ }
12
+ console.log(`API: ${config.apiUrl}`);
13
+ // Decode JWT to show role/tenant
14
+ try {
15
+ const payload = JSON.parse(Buffer.from(config.token.split('.')[1], 'base64url').toString());
16
+ if (payload.role)
17
+ console.log(`Role: ${payload.role}`);
18
+ if (payload.tenant_id)
19
+ console.log(`Tenant: ${payload.tenant_id}`);
20
+ if (payload.exp) {
21
+ const expDate = new Date(payload.exp * 1000);
22
+ const daysLeft = Math.ceil((expDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
23
+ console.log(`Expires: ${expDate.toISOString().slice(0, 10)} (${daysLeft} days)`);
24
+ }
25
+ }
26
+ catch {
27
+ console.log('Token: (admin key or invalid JWT)');
28
+ }
29
+ const tenantId = opts.tenant ?? config.tenantId;
30
+ if (!tenantId) {
31
+ console.log('\nNo tenant context. Use --tenant to specify one.');
32
+ return;
33
+ }
34
+ // Fetch functions
35
+ try {
36
+ const result = (await apiFetch(config, `/functions?tenant_id=${tenantId}`));
37
+ console.log(`\nFunctions (${result.functions.length}):`);
38
+ if (result.functions.length === 0) {
39
+ console.log(' No functions deployed.');
40
+ }
41
+ else {
42
+ for (const fn of result.functions) {
43
+ const age = timeSince(new Date(fn.deployed_at));
44
+ console.log(` ${fn.name} v${fn.version} [${fn.status}] — ${age}`);
45
+ }
46
+ }
47
+ }
48
+ catch (err) {
49
+ console.log(`\nCould not fetch functions: ${err}`);
50
+ }
51
+ }
52
+ function timeSince(date) {
53
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
54
+ if (seconds < 60)
55
+ return `${seconds}s ago`;
56
+ if (seconds < 3600)
57
+ return `${Math.floor(seconds / 60)}m ago`;
58
+ if (seconds < 86400)
59
+ return `${Math.floor(seconds / 3600)}h ago`;
60
+ return `${Math.floor(seconds / 86400)}d ago`;
61
+ }
62
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function tailCommand(opts: {
2
+ functionId?: string;
3
+ tenant?: string;
4
+ }): Promise<void>;