@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
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # @fold-run/cli
2
+
3
+ Command-line interface for [fold.run](https://fold.run) — deploy serverless functions with automatic TypeScript bundling, secrets management, and AI-powered code generation.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @fold-run/cli
9
+ ```
10
+
11
+ Requires Node.js 18+.
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ # Authenticate
17
+ fold login
18
+
19
+ # Scaffold a new project
20
+ fold init my-worker
21
+
22
+ # Start local dev server
23
+ cd my-worker
24
+ fold dev
25
+
26
+ # Deploy
27
+ fold deploy
28
+ ```
29
+
30
+ ## Commands
31
+
32
+ ### Getting started
33
+
34
+ | Command | Description |
35
+ |---------|-------------|
36
+ | `fold init [name]` | Scaffold a new project with `worker.ts` and `fold.json` |
37
+ | `fold login` | Authenticate via email/password or API token |
38
+ | `fold logout` | Remove saved credentials |
39
+ | `fold whoami` | Show current login info (API, tenant, role) |
40
+ | `fold status` | Show config and deployed functions |
41
+
42
+ ### Deploy & manage
43
+
44
+ | Command | Description |
45
+ |---------|-------------|
46
+ | `fold deploy [file]` | Deploy a function (reads `fold.json` if no file given) |
47
+ | `fold dev [file]` | Start a local dev server on port 8787 |
48
+ | `fold functions` | List deployed functions |
49
+ | `fold delete <function-id>` | Delete a deployed function |
50
+ | `fold rollback <function-id> <version>` | Rollback to a previous version |
51
+ | `fold logs` | View activation logs (`-F` to follow, `-v` for details) |
52
+
53
+ ### Configuration
54
+
55
+ | Command | Description |
56
+ |---------|-------------|
57
+ | `fold secrets set <name>` | Create or update a tenant secret (masked input) |
58
+ | `fold secrets list` | List secrets (names only) |
59
+ | `fold secrets delete <id>` | Delete a secret |
60
+ | `fold env set <name> -f <fn-id>` | Set a function environment variable (masked input) |
61
+ | `fold env list -f <fn-id>` | List function env vars |
62
+ | `fold env delete <name> -f <fn-id>` | Delete a function env var |
63
+
64
+ ### Integrations
65
+
66
+ | Command | Description |
67
+ |---------|-------------|
68
+ | `fold webhooks list` | List webhook endpoints |
69
+ | `fold webhooks create <fn-id> <path>` | Create a webhook endpoint |
70
+ | `fold webhooks delete <id>` | Delete a webhook endpoint |
71
+ | `fold schedules list` | List scheduled triggers |
72
+ | `fold schedules create <fn-id> <cron>` | Create a cron trigger |
73
+ | `fold schedules toggle <fn-id>` | Enable or disable a schedule |
74
+ | `fold schedules delete <fn-id>` | Delete a schedule |
75
+
76
+ ### AI & templates
77
+
78
+ | Command | Description |
79
+ |---------|-------------|
80
+ | `fold create-tool <name> <description>` | Generate and deploy an MCP tool from natural language |
81
+ | `fold tools list` | List deployed MCP tools |
82
+ | `fold templates list` | Browse the template marketplace |
83
+ | `fold templates get <name>` | View a template's details and code |
84
+ | `fold templates deploy <name>` | Deploy a function from a template |
85
+
86
+ ## fold.json
87
+
88
+ The project manifest configures defaults for `fold deploy`:
89
+
90
+ ```json
91
+ {
92
+ "name": "my-worker",
93
+ "entrypoint": "worker.ts",
94
+ "tenant_id": "tenant-abc",
95
+ "intent": {
96
+ "trigger": "http",
97
+ "bindings": ["KV:cache", "D1:db"]
98
+ }
99
+ }
100
+ ```
101
+
102
+ | Field | Description |
103
+ |-------|-------------|
104
+ | `name` | Function name (used if `--name` not passed) |
105
+ | `entrypoint` | File to deploy (used if no file argument given) |
106
+ | `tenant_id` | Default tenant (overridden by `--tenant` flag or config) |
107
+ | `intent.trigger` | Trigger type hint |
108
+ | `intent.bindings` | Resource bindings in `TYPE:name` format |
109
+
110
+ ## Global options
111
+
112
+ | Flag | Description |
113
+ |------|-------------|
114
+ | `--json` | Output results as JSON (works with `functions`, `logs`, `deploy`, `secrets list`, `env list`) |
115
+ | `-V, --version` | Print version |
116
+ | `-h, --help` | Show help |
117
+
118
+ ## Authentication
119
+
120
+ Credentials are stored in `~/.config/fold/config.json` (mode `0600`). The CLI supports two auth methods:
121
+
122
+ - **Email/password** — authenticates via the API and stores a JWT
123
+ - **API token** — direct token input for CI/automation
124
+
125
+ The CLI checks JWT expiry before each command and exits early if the token has expired.
126
+
127
+ ## TypeScript bundling
128
+
129
+ `.ts` and `.tsx` files are automatically bundled with esbuild before deploy:
130
+
131
+ - Target: `esnext`, format: ESM
132
+ - Tree-shaking and minification enabled
133
+ - `cloudflare:*` imports kept external
134
+ - Skip with `--no-bundle` to deploy raw JS
135
+
136
+ ## Development
137
+
138
+ ```bash
139
+ # Install dependencies
140
+ pnpm install
141
+
142
+ # Build
143
+ pnpm build
144
+
145
+ # Watch mode
146
+ pnpm dev
147
+
148
+ # Run tests
149
+ pnpm test
150
+
151
+ # Type check
152
+ pnpm typecheck
153
+ ```
154
+
155
+ ## License
156
+
157
+ MIT
@@ -0,0 +1,8 @@
1
+ export declare function createToolCommand(name: string, description: string, opts: {
2
+ tenant?: string;
3
+ schema?: string;
4
+ yes?: boolean;
5
+ }): Promise<void>;
6
+ export declare function toolsListCommand(opts: {
7
+ tenant?: string;
8
+ }): Promise<void>;
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { apiFetch } from '../lib/api.js';
4
+ import { requireConfig } from '../lib/config.js';
5
+ export async function createToolCommand(name, description, 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
+ // Load optional input schema from file
13
+ let inputSchema;
14
+ if (opts.schema) {
15
+ try {
16
+ const schemaText = readFileSync(resolve(opts.schema), 'utf-8');
17
+ inputSchema = JSON.parse(schemaText);
18
+ }
19
+ catch (err) {
20
+ console.error(`Could not read schema file: ${err}`);
21
+ process.exit(1);
22
+ }
23
+ }
24
+ console.log(`Generating tool "${name}"...`);
25
+ // Step 1: Generate tool code + schema
26
+ const genResult = (await apiFetch(config, '/ai/generate-tool', {
27
+ body: { description, input_schema: inputSchema },
28
+ }));
29
+ if (!opts.yes) {
30
+ console.log('\nGenerated code:\n');
31
+ console.log(genResult.code);
32
+ console.log('\nInput schema:');
33
+ console.log(JSON.stringify(genResult.input_schema, null, 2));
34
+ console.log('');
35
+ }
36
+ // Step 2: Deploy with tool metadata
37
+ console.log(`Deploying to tenant ${tenantId}...`);
38
+ const result = (await apiFetch(config, '/deploy', {
39
+ body: {
40
+ tenant_id: tenantId,
41
+ name,
42
+ code: genResult.code,
43
+ tool_metadata: {
44
+ description,
45
+ input_schema: genResult.input_schema,
46
+ },
47
+ },
48
+ }));
49
+ console.log('\nDeployed as MCP tool!');
50
+ console.log(` Function: ${result.function_id}`);
51
+ console.log(` URL: ${result.url}`);
52
+ console.log(` MCP endpoint: ${result.mcp_endpoint}`);
53
+ console.log(` Tool name: ${result.tool_name}`);
54
+ console.log(` Version: ${result.version}`);
55
+ }
56
+ export async function toolsListCommand(opts) {
57
+ const config = requireConfig();
58
+ const tenantId = opts.tenant ?? config.tenantId;
59
+ if (!tenantId) {
60
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
61
+ process.exit(1);
62
+ }
63
+ const result = (await apiFetch(config, `/tools?tenant_id=${tenantId}`));
64
+ if (result.tools.length === 0) {
65
+ console.log('No MCP tools deployed. Use `fold create-tool` to create one.');
66
+ return;
67
+ }
68
+ console.log(`MCP endpoint: ${result.mcp_endpoint}\n`);
69
+ console.log('Tools:');
70
+ for (const tool of result.tools) {
71
+ console.log(` ${tool.tool_name} — ${tool.description}`);
72
+ console.log(` URL: ${tool.url}`);
73
+ console.log('');
74
+ }
75
+ }
76
+ //# sourceMappingURL=create-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-tool.js","sourceRoot":"","sources":["../../src/commands/create-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function deleteCommand(functionId: string, opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,17 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ export async function deleteCommand(functionId, opts) {
4
+ const config = requireConfig();
5
+ const tenantId = opts.tenant ?? config.tenantId;
6
+ if (!tenantId) {
7
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
8
+ process.exit(1);
9
+ }
10
+ console.log(`Deleting function ${functionId}...`);
11
+ await apiFetch(config, `/functions/${functionId}`, {
12
+ method: 'DELETE',
13
+ body: { tenant_id: tenantId },
14
+ });
15
+ console.log('Function deleted.');
16
+ }
17
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB,EAAE,IAAyB;IAC/E,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,OAAO,CAAC,GAAG,CAAC,qBAAqB,UAAU,KAAK,CAAC,CAAC;IAElD,MAAM,QAAQ,CAAC,MAAM,EAAE,cAAc,UAAU,EAAE,EAAE;QACjD,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;KAC9B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function deployCommand(file: string | undefined, opts: {
2
+ name?: string;
3
+ tenant?: string;
4
+ noBundle?: boolean;
5
+ }): Promise<void>;
@@ -0,0 +1,77 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { basename, resolve } from 'node:path';
3
+ import { apiFetch } from '../lib/api.js';
4
+ import { bundleFile } from '../lib/bundler.js';
5
+ import { requireConfig } from '../lib/config.js';
6
+ import { output } from '../lib/output.js';
7
+ function loadManifest() {
8
+ const manifestPath = resolve('fold.json');
9
+ if (!existsSync(manifestPath))
10
+ return null;
11
+ try {
12
+ return JSON.parse(readFileSync(manifestPath, 'utf-8'));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export async function deployCommand(file, opts) {
19
+ const config = requireConfig();
20
+ const manifest = loadManifest();
21
+ const tenantId = opts.tenant ?? manifest?.tenant_id ?? config.tenantId;
22
+ if (!tenantId) {
23
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
24
+ process.exit(1);
25
+ }
26
+ const resolvedFile = file ?? manifest?.entrypoint;
27
+ if (!resolvedFile) {
28
+ console.error('No file specified and no fold.json with entrypoint found.\nUsage: fold deploy <file>');
29
+ process.exit(1);
30
+ }
31
+ const filePath = resolve(resolvedFile);
32
+ let code;
33
+ if (!opts.noBundle && /\.tsx?$/.test(resolvedFile)) {
34
+ // Bundle TypeScript files with esbuild
35
+ console.log('Bundling TypeScript...');
36
+ try {
37
+ code = await bundleFile(filePath);
38
+ }
39
+ catch (err) {
40
+ console.error(`Bundle failed: ${err}`);
41
+ process.exit(1);
42
+ }
43
+ }
44
+ else {
45
+ try {
46
+ code = readFileSync(filePath, 'utf-8');
47
+ }
48
+ catch {
49
+ console.error(`Could not read file: ${resolvedFile}`);
50
+ process.exit(1);
51
+ }
52
+ }
53
+ const name = opts.name ?? manifest?.name ?? basename(resolvedFile).replace(/\.(tsx?|js|mjs)$/, '');
54
+ console.log(`Deploying ${name} to tenant ${tenantId}...`);
55
+ const body = { tenant_id: tenantId, name, code };
56
+ if (manifest?.intent)
57
+ body.intent = manifest.intent;
58
+ const result = (await apiFetch(config, '/deploy', { body }));
59
+ output(result, () => {
60
+ console.log(`\nDeployed successfully!`);
61
+ console.log(` Function: ${result.function_id}`);
62
+ console.log(` URL: ${result.url}`);
63
+ console.log(` Version: ${result.version}`);
64
+ console.log(` Status: ${result.status}`);
65
+ if (result.leak_warnings?.length) {
66
+ console.log(`\n\x1b[33mWarning: ${result.leak_warnings.length} potential secret leak${result.leak_warnings.length > 1 ? 's' : ''} detected in deployed code:\x1b[0m`);
67
+ for (const w of result.leak_warnings.slice(0, 10)) {
68
+ console.log(` \x1b[33mLine ${w.line}:\x1b[0m ${w.description} (${w.match})`);
69
+ }
70
+ if (result.leak_warnings.length > 10) {
71
+ console.log(` ...and ${result.leak_warnings.length - 10} more`);
72
+ }
73
+ console.log(`\n Consider using secrets or env vars instead of hardcoding sensitive values.`);
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function devCommand(file: string | undefined, opts: {
2
+ port?: string;
3
+ noBundle?: boolean;
4
+ watch?: boolean;
5
+ env?: string[];
6
+ }): Promise<void>;
@@ -0,0 +1,178 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync, readFileSync, watch } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { bundleFile } from '../lib/bundler.js';
5
+ /** Parse KEY=VALUE pairs from --env flags and a .env file in cwd */
6
+ function loadEnvVars(envFlags) {
7
+ const vars = {};
8
+ // Load .env file if present
9
+ const dotenvPath = resolve('.env');
10
+ if (existsSync(dotenvPath)) {
11
+ const lines = readFileSync(dotenvPath, 'utf-8').split('\n');
12
+ for (const line of lines) {
13
+ const trimmed = line.trim();
14
+ if (!trimmed || trimmed.startsWith('#'))
15
+ continue;
16
+ const eq = trimmed.indexOf('=');
17
+ if (eq === -1)
18
+ continue;
19
+ const key = trimmed.slice(0, eq).trim();
20
+ const raw = trimmed.slice(eq + 1).trim();
21
+ // Strip surrounding quotes
22
+ vars[key] = raw.replace(/^(['"])(.*)\1$/, '$2');
23
+ }
24
+ }
25
+ // --env flags override .env file
26
+ for (const flag of envFlags) {
27
+ const eq = flag.indexOf('=');
28
+ if (eq === -1) {
29
+ vars[flag.trim()] = '';
30
+ }
31
+ else {
32
+ vars[flag.slice(0, eq).trim()] = flag.slice(eq + 1);
33
+ }
34
+ }
35
+ return vars;
36
+ }
37
+ function loadManifest() {
38
+ const manifestPath = resolve('fold.json');
39
+ if (!existsSync(manifestPath))
40
+ return null;
41
+ try {
42
+ return JSON.parse(readFileSync(manifestPath, 'utf-8'));
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ async function buildCode(filePath, resolvedFile, noBundle) {
49
+ if (!noBundle && /\.tsx?$/.test(resolvedFile)) {
50
+ return await bundleFile(filePath, { dev: true });
51
+ }
52
+ return readFileSync(filePath, 'utf-8');
53
+ }
54
+ function makeLoaderCode(code, port, env) {
55
+ const encodedCode = Buffer.from(code).toString('base64');
56
+ const encodedEnv = JSON.stringify(env);
57
+ return `
58
+ import { createServer } from 'node:http';
59
+
60
+ const code = Buffer.from(${JSON.stringify(encodedCode)}, 'base64').toString();
61
+ const blob = new Blob([code], { type: 'application/javascript' });
62
+ const url = URL.createObjectURL(blob);
63
+ const mod = await import(url);
64
+ const handler = mod.default;
65
+ const env = ${encodedEnv};
66
+
67
+ if (!handler?.fetch) {
68
+ console.error('Function must export default { fetch(request, env) { ... } }');
69
+ process.exit(1);
70
+ }
71
+
72
+ const server = createServer(async (req, res) => {
73
+ const protocol = 'http';
74
+ const host = req.headers.host || 'localhost:${port}';
75
+ const requestUrl = new URL(req.url || '/', protocol + '://' + host);
76
+
77
+ const chunks = [];
78
+ for await (const chunk of req) chunks.push(chunk);
79
+ const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;
80
+
81
+ const request = new Request(requestUrl.toString(), {
82
+ method: req.method,
83
+ headers: Object.entries(req.headers).reduce((h, [k, v]) => {
84
+ if (v) h[k] = Array.isArray(v) ? v.join(', ') : v;
85
+ return h;
86
+ }, {}),
87
+ body: req.method !== 'GET' && req.method !== 'HEAD' ? body : undefined,
88
+ });
89
+
90
+ try {
91
+ const response = await handler.fetch(request, env);
92
+ res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
93
+ const respBody = await response.arrayBuffer();
94
+ res.end(Buffer.from(respBody));
95
+ } catch (err) {
96
+ console.error('Function error:', err);
97
+ res.writeHead(500);
98
+ res.end('Internal Server Error');
99
+ }
100
+ });
101
+
102
+ server.listen(${port}, () => {
103
+ console.log('Local dev server running at http://localhost:${port}');
104
+ });
105
+ `;
106
+ }
107
+ function spawnServer(loaderCode) {
108
+ return spawn('node', ['--input-type=module', '-e', loaderCode], {
109
+ stdio: 'inherit',
110
+ });
111
+ }
112
+ export async function devCommand(file, opts) {
113
+ const manifest = loadManifest();
114
+ const resolvedFile = file ?? manifest?.entrypoint;
115
+ if (!resolvedFile) {
116
+ console.error('No file specified and no fold.json with entrypoint found.\nUsage: fold dev <file>');
117
+ process.exit(1);
118
+ }
119
+ const filePath = resolve(resolvedFile);
120
+ const port = parseInt(opts.port ?? '8787', 10);
121
+ const noBundle = opts.noBundle ?? false;
122
+ const watchMode = opts.watch !== false; // default true
123
+ const env = loadEnvVars(opts.env ?? []);
124
+ if (Object.keys(env).length > 0) {
125
+ console.log(`Loaded env: ${Object.keys(env).join(', ')}`);
126
+ }
127
+ let code;
128
+ try {
129
+ code = await buildCode(filePath, resolvedFile, noBundle);
130
+ }
131
+ catch (err) {
132
+ console.error(`Build failed: ${err}`);
133
+ process.exit(1);
134
+ }
135
+ let child = spawnServer(makeLoaderCode(code, port, env));
136
+ if (watchMode) {
137
+ let debounce = null;
138
+ const watchDir = dirname(filePath);
139
+ console.log(`Watching ${watchDir} for changes...\n`);
140
+ watch(watchDir, { recursive: true }, (_event, filename) => {
141
+ if (!filename || /node_modules|\.git|dist/.test(filename))
142
+ return;
143
+ if (!/\.(ts|tsx|js|mjs|json)$/.test(filename))
144
+ return;
145
+ if (debounce)
146
+ clearTimeout(debounce);
147
+ debounce = setTimeout(async () => {
148
+ console.log(`\n\x1b[33mChange detected:\x1b[0m ${filename}`);
149
+ try {
150
+ const newCode = await buildCode(filePath, resolvedFile, noBundle);
151
+ child.kill('SIGTERM');
152
+ await new Promise((r) => child.on('exit', () => r()));
153
+ child = spawnServer(makeLoaderCode(newCode, port, env));
154
+ console.log('\x1b[32mReloaded.\x1b[0m\n');
155
+ }
156
+ catch (err) {
157
+ console.error(`\x1b[31mRebuild failed:\x1b[0m ${err}`);
158
+ }
159
+ }, 200);
160
+ });
161
+ }
162
+ else {
163
+ console.log('Press Ctrl+C to stop\n');
164
+ }
165
+ child.on('exit', (exitCode) => {
166
+ if (!watchMode)
167
+ process.exit(exitCode ?? 0);
168
+ });
169
+ process.on('SIGINT', () => {
170
+ child.kill('SIGINT');
171
+ process.exit(0);
172
+ });
173
+ process.on('SIGTERM', () => {
174
+ child.kill('SIGTERM');
175
+ process.exit(0);
176
+ });
177
+ }
178
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare function envSetCommand(name: string, opts: {
2
+ functionId: string;
3
+ tenant?: string;
4
+ value?: string;
5
+ }): Promise<void>;
6
+ export declare function envListCommand(opts: {
7
+ functionId: string;
8
+ tenant?: string;
9
+ }): Promise<void>;
10
+ export declare function envDeleteCommand(name: string, opts: {
11
+ functionId: string;
12
+ }): Promise<void>;
@@ -0,0 +1,40 @@
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 envSetCommand(name, opts) {
6
+ const config = requireConfig();
7
+ let value = opts.value;
8
+ if (!value) {
9
+ value = (await readSecret('Value: ')).trim();
10
+ }
11
+ if (!value) {
12
+ console.error('Value is required.');
13
+ process.exit(1);
14
+ }
15
+ await apiFetch(config, '/env-vars', {
16
+ body: { function_id: opts.functionId, name, value },
17
+ });
18
+ console.log(`Env var "${name}" set for function ${opts.functionId}.`);
19
+ }
20
+ export async function envListCommand(opts) {
21
+ const config = requireConfig();
22
+ const result = (await apiFetch(config, `/env-vars/${opts.functionId}`));
23
+ output(result.env_vars, () => {
24
+ if (!result.env_vars.length) {
25
+ console.log('No env vars configured.');
26
+ return;
27
+ }
28
+ console.log(`Env vars for ${opts.functionId}:\n`);
29
+ for (const e of result.env_vars) {
30
+ const created = new Date(e.created_at).toISOString().slice(0, 10);
31
+ console.log(` ${e.name} = ${e.value_preview} (${created})`);
32
+ }
33
+ });
34
+ }
35
+ export async function envDeleteCommand(name, opts) {
36
+ const config = requireConfig();
37
+ await apiFetch(config, `/env-vars/${opts.functionId}/${name}`, { method: 'DELETE' });
38
+ console.log(`Env var "${name}" deleted.`);
39
+ }
40
+ //# sourceMappingURL=env-vars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-vars.js","sourceRoot":"","sources":["../../src/commands/env-vars.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;AAU9C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,IAA6D;IAE7D,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,CAAC;IAED,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,WAAW,EAAE;QAClC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE;KACpD,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,sBAAsB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAA6C;IAChF,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,aAAa,IAAI,CAAC,UAAU,EAAE,CAAC,CAA2B,CAAC;IAElG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAChC,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,MAAM,CAAC,CAAC,aAAa,MAAM,OAAO,GAAG,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,IAA4B;IAC/E,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,MAAM,QAAQ,CAAC,MAAM,EAAE,aAAa,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function functionsCommand(opts: {
2
+ tenant?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,26 @@
1
+ import { apiFetch } from '../lib/api.js';
2
+ import { requireConfig } from '../lib/config.js';
3
+ import { output } from '../lib/output.js';
4
+ export async function functionsCommand(opts) {
5
+ const config = requireConfig();
6
+ const tenantId = opts.tenant ?? config.tenantId;
7
+ if (!tenantId) {
8
+ console.error('No tenant ID. Use --tenant or set one during `fold login`.');
9
+ process.exit(1);
10
+ }
11
+ const result = (await apiFetch(config, `/functions?tenant_id=${tenantId}`));
12
+ output(result.functions, () => {
13
+ if (!result.functions.length) {
14
+ console.log('No functions deployed.');
15
+ return;
16
+ }
17
+ console.log(`Functions for ${tenantId}:\n`);
18
+ for (const fn of result.functions) {
19
+ console.log(` ${fn.name} (v${fn.version}) [${fn.status}]`);
20
+ console.log(` ID: ${fn.id}`);
21
+ console.log(` URL: ${fn.url}`);
22
+ console.log('');
23
+ }
24
+ });
25
+ }
26
+ //# sourceMappingURL=functions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../src/commands/functions.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;AAW1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAyB;IAC9D,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,wBAAwB,QAAQ,EAAE,CAAC,CAAkC,CAAC;IAE7G,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE;QAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,KAAK,CAAC,CAAC;QAC5C,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,OAAO,MAAM,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}