@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.
- package/README.md +157 -0
- package/dist/commands/create-tool.d.ts +8 -0
- package/dist/commands/create-tool.js +76 -0
- package/dist/commands/create-tool.js.map +1 -0
- package/dist/commands/delete.d.ts +3 -0
- package/dist/commands/delete.js +17 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.js +77 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +6 -0
- package/dist/commands/dev.js +178 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/env-vars.d.ts +12 -0
- package/dist/commands/env-vars.js +40 -0
- package/dist/commands/env-vars.js.map +1 -0
- package/dist/commands/functions.d.ts +3 -0
- package/dist/commands/functions.js +26 -0
- package/dist/commands/functions.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +94 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.js +125 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logs.d.ts +7 -0
- package/dist/commands/logs.js +81 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/open.d.ts +3 -0
- package/dist/commands/open.js +24 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/rollback.d.ts +1 -0
- package/dist/commands/rollback.js +13 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/schedules.d.ts +11 -0
- package/dist/commands/schedules.js +49 -0
- package/dist/commands/schedules.js.map +1 -0
- package/dist/commands/secrets.d.ts +7 -0
- package/dist/commands/secrets.js +47 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +62 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tail.d.ts +4 -0
- package/dist/commands/tail.js +108 -0
- package/dist/commands/tail.js.map +1 -0
- package/dist/commands/templates.d.ts +8 -0
- package/dist/commands/templates.js +69 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/webhooks.d.ts +8 -0
- package/dist/commands/webhooks.js +38 -0
- package/dist/commands/webhooks.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +259 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +12 -0
- package/dist/lib/api.js +31 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/bundler.d.ts +10 -0
- package/dist/lib/bundler.js +124 -0
- package/dist/lib/bundler.js.map +1 -0
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/config.js +56 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/output.d.ts +6 -0
- package/dist/lib/output.js +19 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/prompt.d.ts +5 -0
- package/dist/lib/prompt.js +40 -0
- package/dist/lib/prompt.js.map +1 -0
- package/package.json +50 -0
|
@@ -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,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,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,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,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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"}
|