@byfungsi/funforge 0.1.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.
Files changed (59) hide show
  1. package/README.md +273 -0
  2. package/dist/__tests__/api.test.d.ts +5 -0
  3. package/dist/__tests__/api.test.d.ts.map +1 -0
  4. package/dist/__tests__/api.test.js +177 -0
  5. package/dist/__tests__/config.test.d.ts +5 -0
  6. package/dist/__tests__/config.test.d.ts.map +1 -0
  7. package/dist/__tests__/config.test.js +58 -0
  8. package/dist/__tests__/mcp.test.d.ts +7 -0
  9. package/dist/__tests__/mcp.test.d.ts.map +1 -0
  10. package/dist/__tests__/mcp.test.js +142 -0
  11. package/dist/__tests__/project-config.test.d.ts +5 -0
  12. package/dist/__tests__/project-config.test.d.ts.map +1 -0
  13. package/dist/__tests__/project-config.test.js +122 -0
  14. package/dist/__tests__/tarball.test.d.ts +5 -0
  15. package/dist/__tests__/tarball.test.d.ts.map +1 -0
  16. package/dist/__tests__/tarball.test.js +113 -0
  17. package/dist/api.d.ts +157 -0
  18. package/dist/api.d.ts.map +1 -0
  19. package/dist/api.js +165 -0
  20. package/dist/cli.d.ts +8 -0
  21. package/dist/cli.d.ts.map +1 -0
  22. package/dist/cli.js +129 -0
  23. package/dist/commands/apps.d.ts +29 -0
  24. package/dist/commands/apps.d.ts.map +1 -0
  25. package/dist/commands/apps.js +151 -0
  26. package/dist/commands/auth.d.ts +27 -0
  27. package/dist/commands/auth.d.ts.map +1 -0
  28. package/dist/commands/auth.js +127 -0
  29. package/dist/commands/config.d.ts +31 -0
  30. package/dist/commands/config.d.ts.map +1 -0
  31. package/dist/commands/config.js +287 -0
  32. package/dist/commands/deploy.d.ts +24 -0
  33. package/dist/commands/deploy.d.ts.map +1 -0
  34. package/dist/commands/deploy.js +196 -0
  35. package/dist/commands/domains.d.ts +35 -0
  36. package/dist/commands/domains.d.ts.map +1 -0
  37. package/dist/commands/domains.js +217 -0
  38. package/dist/commands/env.d.ts +26 -0
  39. package/dist/commands/env.d.ts.map +1 -0
  40. package/dist/commands/env.js +183 -0
  41. package/dist/config.d.ts +22 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +23 -0
  44. package/dist/credentials.d.ts +46 -0
  45. package/dist/credentials.d.ts.map +1 -0
  46. package/dist/credentials.js +60 -0
  47. package/dist/index.d.ts +14 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +18 -0
  50. package/dist/mcp.d.ts +19 -0
  51. package/dist/mcp.d.ts.map +1 -0
  52. package/dist/mcp.js +480 -0
  53. package/dist/project-config.d.ts +47 -0
  54. package/dist/project-config.d.ts.map +1 -0
  55. package/dist/project-config.js +55 -0
  56. package/dist/tarball.d.ts +29 -0
  57. package/dist/tarball.d.ts.map +1 -0
  58. package/dist/tarball.js +148 -0
  59. package/package.json +45 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Domain Management Commands
3
+ *
4
+ * - domains list: List custom domains
5
+ * - domains add: Add a custom domain
6
+ * - domains remove: Remove a domain
7
+ * - domains verify: Verify DNS and provision SSL
8
+ */
9
+ import chalk from "chalk";
10
+ import ora from "ora";
11
+ import { ApiError, apiRequest } from "../api.js";
12
+ import { isAuthenticated } from "../credentials.js";
13
+ import { readConfig } from "../project-config.js";
14
+ /**
15
+ * funforge domains list
16
+ *
17
+ * List all custom domains for the linked app.
18
+ */
19
+ export async function domainsListCommand() {
20
+ requireAuth();
21
+ const appId = await getLinkedAppId();
22
+ const spinner = ora("Fetching domains...").start();
23
+ try {
24
+ const { domains } = await apiRequest(`/api/cli/apps/${appId}/domains`);
25
+ spinner.stop();
26
+ if (domains.length === 0) {
27
+ console.log(chalk.yellow("No custom domains configured."));
28
+ console.log(chalk.gray("Add one with `funforge domains add <domain>`"));
29
+ return;
30
+ }
31
+ console.log(chalk.bold("Custom Domains:"));
32
+ console.log();
33
+ for (const domain of domains) {
34
+ const status = domain.verified
35
+ ? chalk.green("verified")
36
+ : chalk.yellow("pending verification");
37
+ const ssl = domain.sslStatus === "active"
38
+ ? chalk.green("SSL active")
39
+ : domain.sslStatus
40
+ ? chalk.yellow(`SSL: ${domain.sslStatus}`)
41
+ : "";
42
+ console.log(` ${chalk.cyan(domain.domain)}`);
43
+ console.log(` Status: ${status}`);
44
+ if (ssl) {
45
+ console.log(` ${ssl}`);
46
+ }
47
+ console.log(` ID: ${chalk.gray(domain.id)}`);
48
+ console.log();
49
+ }
50
+ }
51
+ catch (error) {
52
+ spinner.fail("Failed to fetch domains");
53
+ handleError(error);
54
+ }
55
+ }
56
+ /**
57
+ * funforge domains add <domain>
58
+ *
59
+ * Add a custom domain to the linked app.
60
+ */
61
+ export async function domainsAddCommand(domain, options) {
62
+ requireAuth();
63
+ const appId = await getLinkedAppId();
64
+ // Normalize domain (remove protocol if present)
65
+ const cleanDomain = domain
66
+ .replace(/^https?:\/\//, "")
67
+ .replace(/\/.*$/, "")
68
+ .toLowerCase();
69
+ const verificationMethod = options.method || "cname";
70
+ if (!["cname", "txt"].includes(verificationMethod)) {
71
+ console.log(chalk.red(`Invalid verification method: ${verificationMethod}`));
72
+ console.log(chalk.gray("Valid options: cname, txt"));
73
+ process.exit(1);
74
+ }
75
+ const spinner = ora(`Adding domain ${cleanDomain}...`).start();
76
+ try {
77
+ const { domain: addedDomain, verification } = await apiRequest(`/api/cli/apps/${appId}/domains`, {
78
+ method: "POST",
79
+ body: {
80
+ domain: cleanDomain,
81
+ verificationMethod,
82
+ },
83
+ });
84
+ spinner.succeed(`Domain ${chalk.cyan(cleanDomain)} added!`);
85
+ console.log();
86
+ console.log(chalk.bold("DNS Configuration Required:"));
87
+ console.log();
88
+ console.log(` Add this ${verification.type.toUpperCase()} record to your DNS:`);
89
+ console.log();
90
+ console.log(` ${chalk.gray("Name:")} ${chalk.cyan(verification.name)}`);
91
+ console.log(` ${chalk.gray("Value:")} ${chalk.cyan(verification.value)}`);
92
+ console.log();
93
+ console.log(chalk.gray("After adding the DNS record, run:"));
94
+ console.log(chalk.gray(` funforge domains verify ${cleanDomain}`));
95
+ console.log();
96
+ console.log(chalk.gray(`Domain ID: ${addedDomain.id}`));
97
+ }
98
+ catch (error) {
99
+ spinner.fail("Failed to add domain");
100
+ handleError(error);
101
+ }
102
+ }
103
+ /**
104
+ * funforge domains remove <domain>
105
+ *
106
+ * Remove a custom domain from the linked app.
107
+ */
108
+ export async function domainsRemoveCommand(domain) {
109
+ requireAuth();
110
+ const appId = await getLinkedAppId();
111
+ // First, find the domain ID
112
+ const spinner = ora("Finding domain...").start();
113
+ try {
114
+ const { domains } = await apiRequest(`/api/cli/apps/${appId}/domains`);
115
+ const cleanDomain = domain.toLowerCase();
116
+ const targetDomain = domains.find((d) => d.domain.toLowerCase() === cleanDomain || d.id === domain);
117
+ if (!targetDomain) {
118
+ spinner.fail(`Domain not found: ${domain}`);
119
+ console.log(chalk.gray("Use `funforge domains list` to see available domains"));
120
+ process.exit(1);
121
+ }
122
+ spinner.text = `Removing ${targetDomain.domain}...`;
123
+ await apiRequest(`/api/cli/apps/${appId}/domains/${targetDomain.id}`, {
124
+ method: "DELETE",
125
+ });
126
+ spinner.succeed(`Domain ${chalk.cyan(targetDomain.domain)} removed`);
127
+ }
128
+ catch (error) {
129
+ spinner.fail("Failed to remove domain");
130
+ handleError(error);
131
+ }
132
+ }
133
+ /**
134
+ * funforge domains verify <domain>
135
+ *
136
+ * Verify DNS and provision SSL for a custom domain.
137
+ */
138
+ export async function domainsVerifyCommand(domain) {
139
+ requireAuth();
140
+ const appId = await getLinkedAppId();
141
+ // First, find the domain ID
142
+ const spinner = ora("Finding domain...").start();
143
+ try {
144
+ const { domains } = await apiRequest(`/api/cli/apps/${appId}/domains`);
145
+ const cleanDomain = domain.toLowerCase();
146
+ const targetDomain = domains.find((d) => d.domain.toLowerCase() === cleanDomain || d.id === domain);
147
+ if (!targetDomain) {
148
+ spinner.fail(`Domain not found: ${domain}`);
149
+ console.log(chalk.gray("Use `funforge domains list` to see available domains"));
150
+ process.exit(1);
151
+ }
152
+ if (targetDomain.verified) {
153
+ spinner.succeed(`Domain ${chalk.cyan(targetDomain.domain)} is already verified`);
154
+ return;
155
+ }
156
+ spinner.text = `Verifying ${targetDomain.domain}...`;
157
+ const result = await apiRequest(`/api/cli/apps/${appId}/domains/${targetDomain.id}/verify`, { method: "POST" });
158
+ if (result.verified) {
159
+ spinner.succeed(`Domain ${chalk.cyan(targetDomain.domain)} verified!`);
160
+ if (result.sslStatus) {
161
+ console.log(` SSL Status: ${chalk.cyan(result.sslStatus)}`);
162
+ }
163
+ }
164
+ else {
165
+ spinner.fail(`Domain verification failed`);
166
+ if (result.message) {
167
+ console.log(chalk.yellow(result.message));
168
+ }
169
+ console.log();
170
+ console.log(chalk.gray("Make sure your DNS record is correctly configured."));
171
+ console.log(chalk.gray("DNS changes can take up to 48 hours to propagate."));
172
+ }
173
+ }
174
+ catch (error) {
175
+ spinner.fail("Failed to verify domain");
176
+ handleError(error);
177
+ }
178
+ }
179
+ /**
180
+ * Get the linked app ID or exit
181
+ */
182
+ async function getLinkedAppId() {
183
+ const config = await readConfig();
184
+ if (!config?.appId) {
185
+ console.log(chalk.red("Not linked to an app."));
186
+ console.log(chalk.gray("Run `funforge link <app-id>` first."));
187
+ process.exit(1);
188
+ }
189
+ return config.appId;
190
+ }
191
+ /**
192
+ * Check if user is authenticated, exit if not
193
+ */
194
+ function requireAuth() {
195
+ if (!isAuthenticated()) {
196
+ console.log(chalk.red("Not authenticated."));
197
+ console.log(chalk.gray("Run `funforge login` first."));
198
+ process.exit(1);
199
+ }
200
+ }
201
+ /**
202
+ * Handle API errors
203
+ */
204
+ function handleError(error) {
205
+ if (error instanceof ApiError) {
206
+ console.error(chalk.red(`Error ${error.statusCode}: ${error.message}`));
207
+ if (error.body &&
208
+ typeof error.body === "object" &&
209
+ "message" in error.body) {
210
+ console.error(chalk.gray(error.body.message));
211
+ }
212
+ }
213
+ else {
214
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
215
+ }
216
+ process.exit(1);
217
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Environment Variable Commands
3
+ *
4
+ * - env list: Show environment variables
5
+ * - env set: Set environment variable(s)
6
+ * - env unset: Remove environment variable(s)
7
+ */
8
+ /**
9
+ * funforge env list
10
+ *
11
+ * List environment variables for the linked app.
12
+ */
13
+ export declare function envListCommand(): Promise<void>;
14
+ /**
15
+ * funforge env set KEY=VALUE [KEY2=VALUE2 ...]
16
+ *
17
+ * Set one or more environment variables.
18
+ */
19
+ export declare function envSetCommand(pairs: string[]): Promise<void>;
20
+ /**
21
+ * funforge env unset KEY [KEY2 ...]
22
+ *
23
+ * Remove one or more environment variables.
24
+ */
25
+ export declare function envUnsetCommand(keys: string[]): Promise<void>;
26
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAqDpD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDlE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCnE"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Environment Variable Commands
3
+ *
4
+ * - env list: Show environment variables
5
+ * - env set: Set environment variable(s)
6
+ * - env unset: Remove environment variable(s)
7
+ */
8
+ import chalk from "chalk";
9
+ import ora from "ora";
10
+ import { ApiError, apiRequest } from "../api.js";
11
+ import { isAuthenticated } from "../credentials.js";
12
+ import { readConfig } from "../project-config.js";
13
+ /**
14
+ * funforge env list
15
+ *
16
+ * List environment variables for the linked app.
17
+ */
18
+ export async function envListCommand() {
19
+ requireAuth();
20
+ const appId = await getLinkedAppId();
21
+ const spinner = ora("Fetching environment variables...").start();
22
+ try {
23
+ const { appEnvVars, userEnvVars } = await apiRequest(`/api/cli/apps/${appId}/env`);
24
+ spinner.stop();
25
+ const appKeys = Object.keys(appEnvVars);
26
+ const userKeys = Object.keys(userEnvVars);
27
+ if (appKeys.length === 0 && userKeys.length === 0) {
28
+ console.log(chalk.yellow("No environment variables set."));
29
+ console.log(chalk.gray("Set one with `funforge env set KEY=VALUE`"));
30
+ return;
31
+ }
32
+ if (appKeys.length > 0) {
33
+ console.log(chalk.bold("App Environment Variables:"));
34
+ for (const key of appKeys.sort()) {
35
+ const value = appEnvVars[key];
36
+ const displayValue = value.length > 50 ? value.slice(0, 47) + "..." : value;
37
+ console.log(` ${chalk.cyan(key)}=${displayValue}`);
38
+ }
39
+ console.log();
40
+ }
41
+ if (userKeys.length > 0) {
42
+ console.log(chalk.bold("User Environment Variables (inherited):"));
43
+ for (const key of userKeys.sort()) {
44
+ const value = userEnvVars[key];
45
+ const displayValue = value.length > 50 ? value.slice(0, 47) + "..." : value;
46
+ // Show if overridden by app
47
+ const overridden = appKeys.includes(key);
48
+ if (overridden) {
49
+ console.log(chalk.gray(` ${key}=${displayValue} (overridden by app)`));
50
+ }
51
+ else {
52
+ console.log(` ${chalk.gray(key)}=${displayValue}`);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ catch (error) {
58
+ spinner.fail("Failed to fetch environment variables");
59
+ handleError(error);
60
+ }
61
+ }
62
+ /**
63
+ * funforge env set KEY=VALUE [KEY2=VALUE2 ...]
64
+ *
65
+ * Set one or more environment variables.
66
+ */
67
+ export async function envSetCommand(pairs) {
68
+ requireAuth();
69
+ const appId = await getLinkedAppId();
70
+ if (pairs.length === 0) {
71
+ console.log(chalk.red("Usage: funforge env set KEY=VALUE [KEY2=VALUE2 ...]"));
72
+ process.exit(1);
73
+ }
74
+ // Parse KEY=VALUE pairs
75
+ const envVars = {};
76
+ for (const pair of pairs) {
77
+ const eqIndex = pair.indexOf("=");
78
+ if (eqIndex === -1) {
79
+ console.log(chalk.red(`Invalid format: ${pair}`));
80
+ console.log(chalk.gray("Expected: KEY=VALUE"));
81
+ process.exit(1);
82
+ }
83
+ const key = pair.slice(0, eqIndex);
84
+ const value = pair.slice(eqIndex + 1);
85
+ if (!key.match(/^[A-Za-z_][A-Za-z0-9_]*$/)) {
86
+ console.log(chalk.red(`Invalid key: ${key}`));
87
+ console.log(chalk.gray("Keys must start with a letter or underscore"));
88
+ process.exit(1);
89
+ }
90
+ envVars[key] = value;
91
+ }
92
+ const spinner = ora("Setting environment variables...").start();
93
+ try {
94
+ await apiRequest(`/api/cli/apps/${appId}/env`, {
95
+ method: "PATCH",
96
+ body: { envVars },
97
+ });
98
+ spinner.succeed(`Set ${Object.keys(envVars).length} environment variable(s)`);
99
+ for (const key of Object.keys(envVars)) {
100
+ console.log(` ${chalk.cyan(key)}`);
101
+ }
102
+ console.log();
103
+ console.log(chalk.gray("Note: Changes take effect on next deployment."));
104
+ }
105
+ catch (error) {
106
+ spinner.fail("Failed to set environment variables");
107
+ handleError(error);
108
+ }
109
+ }
110
+ /**
111
+ * funforge env unset KEY [KEY2 ...]
112
+ *
113
+ * Remove one or more environment variables.
114
+ */
115
+ export async function envUnsetCommand(keys) {
116
+ requireAuth();
117
+ const appId = await getLinkedAppId();
118
+ if (keys.length === 0) {
119
+ console.log(chalk.red("Usage: funforge env unset KEY [KEY2 ...]"));
120
+ process.exit(1);
121
+ }
122
+ // Build payload with null values for deletion
123
+ const envVars = {};
124
+ for (const key of keys) {
125
+ envVars[key] = null;
126
+ }
127
+ const spinner = ora("Removing environment variables...").start();
128
+ try {
129
+ await apiRequest(`/api/cli/apps/${appId}/env`, {
130
+ method: "PATCH",
131
+ body: { envVars },
132
+ });
133
+ spinner.succeed(`Removed ${keys.length} environment variable(s)`);
134
+ for (const key of keys) {
135
+ console.log(` ${chalk.gray(key)}`);
136
+ }
137
+ console.log();
138
+ console.log(chalk.gray("Note: Changes take effect on next deployment."));
139
+ }
140
+ catch (error) {
141
+ spinner.fail("Failed to remove environment variables");
142
+ handleError(error);
143
+ }
144
+ }
145
+ /**
146
+ * Get the linked app ID or exit
147
+ */
148
+ async function getLinkedAppId() {
149
+ const config = await readConfig();
150
+ if (!config?.appId) {
151
+ console.log(chalk.red("Not linked to an app."));
152
+ console.log(chalk.gray("Run `funforge link <app-id>` first."));
153
+ process.exit(1);
154
+ }
155
+ return config.appId;
156
+ }
157
+ /**
158
+ * Check if user is authenticated, exit if not
159
+ */
160
+ function requireAuth() {
161
+ if (!isAuthenticated()) {
162
+ console.log(chalk.red("Not authenticated."));
163
+ console.log(chalk.gray("Run `funforge login` first."));
164
+ process.exit(1);
165
+ }
166
+ }
167
+ /**
168
+ * Handle API errors
169
+ */
170
+ function handleError(error) {
171
+ if (error instanceof ApiError) {
172
+ console.error(chalk.red(`Error ${error.statusCode}: ${error.message}`));
173
+ if (error.body &&
174
+ typeof error.body === "object" &&
175
+ "message" in error.body) {
176
+ console.error(chalk.gray(error.body.message));
177
+ }
178
+ }
179
+ else {
180
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
181
+ }
182
+ process.exit(1);
183
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * FunForge CLI Configuration
3
+ *
4
+ * Handles API endpoints and default settings.
5
+ */
6
+ export interface Config {
7
+ /** API base URL */
8
+ apiUrl: string;
9
+ /** Auth URL for device flow */
10
+ authUrl: string;
11
+ /** Default timeout for API requests (ms) */
12
+ timeout: number;
13
+ }
14
+ /**
15
+ * Production configuration
16
+ */
17
+ export declare const config: Config;
18
+ /**
19
+ * Get config with optional overrides from environment
20
+ */
21
+ export declare function getConfig(): Config;
22
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,MAAM;IACrB,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAIpB,CAAC;AAEF;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAMlC"}
package/dist/config.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * FunForge CLI Configuration
3
+ *
4
+ * Handles API endpoints and default settings.
5
+ */
6
+ /**
7
+ * Production configuration
8
+ */
9
+ export const config = {
10
+ apiUrl: "https://api.fungsi.app",
11
+ authUrl: "https://cloud.fungsi.app",
12
+ timeout: 30000,
13
+ };
14
+ /**
15
+ * Get config with optional overrides from environment
16
+ */
17
+ export function getConfig() {
18
+ return {
19
+ apiUrl: process.env.FUNFORGE_API_URL ?? config.apiUrl,
20
+ authUrl: process.env.FUNFORGE_AUTH_URL ?? config.authUrl,
21
+ timeout: Number(process.env.FUNFORGE_TIMEOUT) || config.timeout,
22
+ };
23
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Credential Store
3
+ *
4
+ * Manages API keys and authentication state using conf.
5
+ * Credentials are stored in platform-specific config directories.
6
+ */
7
+ interface Credentials {
8
+ /** API key for authenticated requests */
9
+ apiKey?: string;
10
+ /** User ID (for display) */
11
+ userId?: string;
12
+ /** User email (for display) */
13
+ email?: string;
14
+ /** When the credentials were stored */
15
+ savedAt?: string;
16
+ }
17
+ /**
18
+ * Save credentials after successful authentication
19
+ */
20
+ export declare function saveCredentials(creds: {
21
+ apiKey: string;
22
+ userId: string;
23
+ email: string;
24
+ }): void;
25
+ /**
26
+ * Get stored API key
27
+ */
28
+ export declare function getApiKey(): string | undefined;
29
+ /**
30
+ * Get stored credentials (for whoami)
31
+ */
32
+ export declare function getCredentials(): Credentials;
33
+ /**
34
+ * Clear all stored credentials (logout)
35
+ */
36
+ export declare function clearCredentials(): void;
37
+ /**
38
+ * Check if user is authenticated
39
+ */
40
+ export declare function isAuthenticated(): boolean;
41
+ /**
42
+ * Get the config file path (for debugging)
43
+ */
44
+ export declare function getConfigPath(): string;
45
+ export {};
46
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,UAAU,WAAW;IACnB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAYD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAKP;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAO5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Credential Store
3
+ *
4
+ * Manages API keys and authentication state using conf.
5
+ * Credentials are stored in platform-specific config directories.
6
+ */
7
+ import Conf from "conf";
8
+ const store = new Conf({
9
+ projectName: "funforge",
10
+ schema: {
11
+ apiKey: { type: "string" },
12
+ userId: { type: "string" },
13
+ email: { type: "string" },
14
+ savedAt: { type: "string" },
15
+ },
16
+ });
17
+ /**
18
+ * Save credentials after successful authentication
19
+ */
20
+ export function saveCredentials(creds) {
21
+ store.set("apiKey", creds.apiKey);
22
+ store.set("userId", creds.userId);
23
+ store.set("email", creds.email);
24
+ store.set("savedAt", new Date().toISOString());
25
+ }
26
+ /**
27
+ * Get stored API key
28
+ */
29
+ export function getApiKey() {
30
+ return store.get("apiKey");
31
+ }
32
+ /**
33
+ * Get stored credentials (for whoami)
34
+ */
35
+ export function getCredentials() {
36
+ return {
37
+ apiKey: store.get("apiKey"),
38
+ userId: store.get("userId"),
39
+ email: store.get("email"),
40
+ savedAt: store.get("savedAt"),
41
+ };
42
+ }
43
+ /**
44
+ * Clear all stored credentials (logout)
45
+ */
46
+ export function clearCredentials() {
47
+ store.clear();
48
+ }
49
+ /**
50
+ * Check if user is authenticated
51
+ */
52
+ export function isAuthenticated() {
53
+ return !!store.get("apiKey");
54
+ }
55
+ /**
56
+ * Get the config file path (for debugging)
57
+ */
58
+ export function getConfigPath() {
59
+ return store.path;
60
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * FunForge
3
+ *
4
+ * Deploy without git, without leaving your editor.
5
+ *
6
+ * This module exports the programmatic API for FunForge.
7
+ * For CLI usage, run `funforge` directly.
8
+ */
9
+ export { getConfig, type Config } from "./config.js";
10
+ export { saveCredentials, getApiKey, getCredentials, clearCredentials, isAuthenticated, } from "./credentials.js";
11
+ export { apiRequest, ApiError, initDeviceAuth, pollDeviceAuth, listApps, getApp, createApp, getUploadUrl, uploadTarball, createDeployment, getDeployment, type App, type Deployment, type DeviceAuthInitResponse, type DeviceAuthPollResponse, } from "./api.js";
12
+ export { readConfig, writeConfig, updateConfig, configExists, getLinkedAppId, type FunForgeConfig, } from "./project-config.js";
13
+ export { createTarball, readTarball, formatSize, type TarballResult, } from "./tarball.js";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrD,OAAO,EACL,eAAe,EACf,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,UAAU,EACV,QAAQ,EACR,cAAc,EACd,cAAc,EACd,QAAQ,EACR,MAAM,EACN,SAAS,EACT,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * FunForge
3
+ *
4
+ * Deploy without git, without leaving your editor.
5
+ *
6
+ * This module exports the programmatic API for FunForge.
7
+ * For CLI usage, run `funforge` directly.
8
+ */
9
+ // Config
10
+ export { getConfig } from "./config.js";
11
+ // Credentials
12
+ export { saveCredentials, getApiKey, getCredentials, clearCredentials, isAuthenticated, } from "./credentials.js";
13
+ // API
14
+ export { apiRequest, ApiError, initDeviceAuth, pollDeviceAuth, listApps, getApp, createApp, getUploadUrl, uploadTarball, createDeployment, getDeployment, } from "./api.js";
15
+ // Project config
16
+ export { readConfig, writeConfig, updateConfig, configExists, getLinkedAppId, } from "./project-config.js";
17
+ // Tarball
18
+ export { createTarball, readTarball, formatSize, } from "./tarball.js";
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * FunForge MCP Server
4
+ *
5
+ * Model Context Protocol server for editor integration.
6
+ * Exposes FunForge CLI functionality as MCP tools.
7
+ *
8
+ * Usage in claude_desktop_config.json:
9
+ * {
10
+ * "mcpServers": {
11
+ * "funforge": {
12
+ * "command": "npx",
13
+ * "args": ["@byfungsi/funforge-mcp"]
14
+ * }
15
+ * }
16
+ * }
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}