framlit-mcp 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,22 +50,26 @@ Add to your editor's MCP config:
50
50
  ### CLI (Terminal)
51
51
 
52
52
  ```bash
53
- # Set your API key (get it at https://framlit.app/settings/api-keys)
54
- export FRAMLIT_API_KEY=fml_your_api_key_here
53
+ # Install globally
54
+ npm install -g framlit-mcp
55
55
 
56
- # Use directly via npx
57
- npx framlit generate "A logo animation with rotating 3D text"
56
+ # Authorize this machine — opens your browser
57
+ framlit login
58
58
 
59
- # Or install globally
60
- npm install -g framlit-mcp
59
+ # You're ready
61
60
  framlit generate "Product demo with fade-in text"
62
61
  ```
63
62
 
63
+ Prefer an env var? `export FRAMLIT_API_KEY=fml_...` still works and takes
64
+ precedence over `framlit login` — handy for CI and container setups.
65
+
64
66
  ## CLI Usage
65
67
 
66
68
  ```bash
67
- # Set your API key first
68
- export FRAMLIT_API_KEY=fml_your_api_key_here
69
+ # One-time auth (or set FRAMLIT_API_KEY in your shell)
70
+ framlit login
71
+ framlit whoami # email / plan / credits
72
+ framlit logout # remove ~/.framlit/config
69
73
 
70
74
  # Generate video code
71
75
  framlit generate "Logo animation with rotating text" --format landscape
@@ -52,6 +52,45 @@ export interface PreviewResult {
52
52
  previewUrl: string;
53
53
  expiresAt: string;
54
54
  }
55
+ export interface BatchJob {
56
+ jobId: string;
57
+ status: 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled';
58
+ totalRows: number;
59
+ completedRows?: number;
60
+ failedRows?: number;
61
+ progress?: number;
62
+ estimatedCredits?: number;
63
+ results?: Array<{
64
+ rowIndex: number;
65
+ filename: string;
66
+ status: string;
67
+ videoUrl?: string;
68
+ error?: string;
69
+ }>;
70
+ summary?: Record<string, unknown>;
71
+ message?: string;
72
+ refundedCredits?: number;
73
+ }
74
+ export interface Variation {
75
+ id: string;
76
+ style: string;
77
+ aiReasoning: string;
78
+ codeLength?: number;
79
+ code?: string;
80
+ selected?: boolean;
81
+ createdAt?: string;
82
+ }
83
+ export interface VariationsResult {
84
+ projectId: string;
85
+ totalGenerated: number;
86
+ creditsUsed: number;
87
+ creditsRemaining: number;
88
+ variations: Variation[];
89
+ errors?: Array<{
90
+ style: string;
91
+ error: string;
92
+ }>;
93
+ }
55
94
  export declare class FramlitClient {
56
95
  private apiKey;
57
96
  private baseUrl;
@@ -117,5 +156,57 @@ export declare class FramlitClient {
117
156
  * Create a temporary preview
118
157
  */
119
158
  createPreview(code: string): Promise<PreviewResult>;
159
+ /**
160
+ * Create a batch job from rows of data
161
+ */
162
+ createBatch(params: {
163
+ rows: Record<string, string>[];
164
+ templateId?: string;
165
+ templateCode?: string;
166
+ }): Promise<BatchJob>;
167
+ /**
168
+ * Start a batch job (triggers rendering)
169
+ */
170
+ startBatch(jobId: string): Promise<BatchJob>;
171
+ /**
172
+ * Get batch job status
173
+ */
174
+ getBatchStatus(jobId: string): Promise<BatchJob>;
175
+ /**
176
+ * List user's batch jobs
177
+ */
178
+ listBatches(): Promise<BatchJob[]>;
179
+ /**
180
+ * Cancel a batch job
181
+ */
182
+ cancelBatch(jobId: string): Promise<BatchJob>;
183
+ /**
184
+ * Generate style variations for a project
185
+ */
186
+ generateVariations(params: {
187
+ projectId: string;
188
+ prompt: string;
189
+ videoFormat?: 'landscape' | 'portrait' | 'square';
190
+ styles?: string[];
191
+ existingCode?: string;
192
+ model?: 'sonnet' | 'haiku';
193
+ }): Promise<VariationsResult>;
194
+ /**
195
+ * List variations for a project
196
+ */
197
+ listVariations(projectId: string): Promise<{
198
+ projectId: string;
199
+ variations: Variation[];
200
+ totalCount: number;
201
+ }>;
202
+ /**
203
+ * Apply a variation to a project
204
+ */
205
+ applyVariation(projectId: string, variationId: string): Promise<{
206
+ message: string;
207
+ projectId: string;
208
+ variationId: string;
209
+ style: string;
210
+ }>;
120
211
  }
121
212
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -129,6 +129,73 @@ class FramlitClient {
129
129
  body: JSON.stringify({ code }),
130
130
  });
131
131
  }
132
+ // -------------------------------------------------------------------------
133
+ // Batch
134
+ // -------------------------------------------------------------------------
135
+ /**
136
+ * Create a batch job from rows of data
137
+ */
138
+ async createBatch(params) {
139
+ return this.request('/batch', {
140
+ method: 'POST',
141
+ body: JSON.stringify(params),
142
+ });
143
+ }
144
+ /**
145
+ * Start a batch job (triggers rendering)
146
+ */
147
+ async startBatch(jobId) {
148
+ return this.request(`/batch/${jobId}`, {
149
+ method: 'POST',
150
+ });
151
+ }
152
+ /**
153
+ * Get batch job status
154
+ */
155
+ async getBatchStatus(jobId) {
156
+ return this.request(`/batch/${jobId}`);
157
+ }
158
+ /**
159
+ * List user's batch jobs
160
+ */
161
+ async listBatches() {
162
+ return this.request('/batch');
163
+ }
164
+ /**
165
+ * Cancel a batch job
166
+ */
167
+ async cancelBatch(jobId) {
168
+ return this.request(`/batch/${jobId}`, {
169
+ method: 'DELETE',
170
+ });
171
+ }
172
+ // -------------------------------------------------------------------------
173
+ // Style Variations
174
+ // -------------------------------------------------------------------------
175
+ /**
176
+ * Generate style variations for a project
177
+ */
178
+ async generateVariations(params) {
179
+ return this.request('/variations', {
180
+ method: 'POST',
181
+ body: JSON.stringify(params),
182
+ });
183
+ }
184
+ /**
185
+ * List variations for a project
186
+ */
187
+ async listVariations(projectId) {
188
+ return this.request(`/variations/${projectId}`);
189
+ }
190
+ /**
191
+ * Apply a variation to a project
192
+ */
193
+ async applyVariation(projectId, variationId) {
194
+ return this.request(`/variations/${projectId}`, {
195
+ method: 'POST',
196
+ body: JSON.stringify({ variationId }),
197
+ });
198
+ }
132
199
  }
133
200
  exports.FramlitClient = FramlitClient;
134
201
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `framlit login` — Stripe/Vercel-style CLI login.
3
+ *
4
+ * Flow:
5
+ * 1. Generate 32-hex state token for CSRF.
6
+ * 2. Start a tiny HTTP server on OS-assigned port (127.0.0.1).
7
+ * 3. Open https://framlit.app/developers/cli-authorize in the browser with
8
+ * cli_callback + state query params.
9
+ * 4. User signs in + clicks Authorize on framlit.app.
10
+ * 5. framlit.app 303-redirects the browser to
11
+ * http://127.0.0.1:PORT/?key=fml_…&state=<same>
12
+ * 6. Our local server receives the GET, validates state (timing-safe),
13
+ * saves ~/.framlit/config, responds with a success HTML page,
14
+ * and shuts itself down.
15
+ *
16
+ * Issue #63.
17
+ */
18
+ export declare function cmdLogin(): Promise<void>;
19
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgJH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAiF9C"}
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * `framlit login` — Stripe/Vercel-style CLI login.
4
+ *
5
+ * Flow:
6
+ * 1. Generate 32-hex state token for CSRF.
7
+ * 2. Start a tiny HTTP server on OS-assigned port (127.0.0.1).
8
+ * 3. Open https://framlit.app/developers/cli-authorize in the browser with
9
+ * cli_callback + state query params.
10
+ * 4. User signs in + clicks Authorize on framlit.app.
11
+ * 5. framlit.app 303-redirects the browser to
12
+ * http://127.0.0.1:PORT/?key=fml_…&state=<same>
13
+ * 6. Our local server receives the GET, validates state (timing-safe),
14
+ * saves ~/.framlit/config, responds with a success HTML page,
15
+ * and shuts itself down.
16
+ *
17
+ * Issue #63.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.cmdLogin = cmdLogin;
21
+ const node_http_1 = require("node:http");
22
+ const node_crypto_1 = require("node:crypto");
23
+ const node_child_process_1 = require("node:child_process");
24
+ const node_os_1 = require("node:os");
25
+ const node_url_1 = require("node:url");
26
+ const client_js_1 = require("../../api/client.js");
27
+ const config_js_1 = require("../config.js");
28
+ const exit_codes_js_1 = require("../exit-codes.js");
29
+ const LOGIN_TIMEOUT_MS = 120_000;
30
+ const AUTHORIZE_PATH = '/developers/cli-authorize';
31
+ function getWebBaseUrl() {
32
+ // FRAMLIT_API_URL points at the API root; strip trailing slashes and
33
+ // reuse it for the consent page too. Defaults to prod.
34
+ const api = process.env.FRAMLIT_API_URL || 'https://framlit.app';
35
+ return api.replace(/\/$/, '');
36
+ }
37
+ function openBrowser(url) {
38
+ const sys = (0, node_os_1.platform)();
39
+ const cmd = sys === 'darwin' ? 'open' : sys === 'win32' ? 'start' : 'xdg-open';
40
+ try {
41
+ const child = (0, node_child_process_1.spawn)(cmd, [url], { stdio: 'ignore', detached: true });
42
+ child.unref();
43
+ }
44
+ catch {
45
+ // Fall back silently — we print the URL so user can copy-paste.
46
+ }
47
+ }
48
+ const SUCCESS_HTML = `<!doctype html>
49
+ <html>
50
+ <head>
51
+ <meta charset="utf-8" />
52
+ <title>Framlit CLI — Authorized</title>
53
+ <style>
54
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #0b0f14; color: #e5e7eb; }
55
+ .card { max-width: 420px; padding: 32px; background: #111827; border: 1px solid #1f2937; border-radius: 16px; text-align: center; }
56
+ h1 { margin: 0 0 8px; font-size: 20px; }
57
+ p { margin: 0; color: #9ca3af; font-size: 14px; }
58
+ .check { font-size: 40px; margin-bottom: 12px; }
59
+ </style>
60
+ </head>
61
+ <body>
62
+ <div class="card">
63
+ <div class="check">✓</div>
64
+ <h1>framlit CLI authorized</h1>
65
+ <p>You can close this tab and return to your terminal.</p>
66
+ </div>
67
+ </body>
68
+ </html>`;
69
+ const FAILURE_HTML = (reason) => `<!doctype html>
70
+ <html>
71
+ <head><meta charset="utf-8" /><title>Framlit CLI — Authorization failed</title>
72
+ <style>body{font-family:sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0b0f14;color:#fca5a5;}.card{max-width:420px;padding:32px;text-align:center;}</style>
73
+ </head>
74
+ <body><div class="card"><h1>Authorization failed</h1><p>${reason}</p><p style="color:#9ca3af;margin-top:8px">Check your terminal for details.</p></div></body>
75
+ </html>`;
76
+ async function waitForCallback(server, port, expectedState) {
77
+ return new Promise((resolve, reject) => {
78
+ const timeout = setTimeout(() => {
79
+ server.close();
80
+ reject(new Error(`Login timed out after ${LOGIN_TIMEOUT_MS / 1000}s`));
81
+ }, LOGIN_TIMEOUT_MS);
82
+ server.on('request', (req, res) => {
83
+ if (!req.url || !req.url.startsWith('/')) {
84
+ res.statusCode = 404;
85
+ res.end('Not found');
86
+ return;
87
+ }
88
+ const url = new node_url_1.URL(req.url, `http://127.0.0.1:${port}`);
89
+ const key = url.searchParams.get('key');
90
+ const state = url.searchParams.get('state');
91
+ if (!key || !state) {
92
+ res.statusCode = 400;
93
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
94
+ res.end(FAILURE_HTML('Missing key or state parameter.'));
95
+ return;
96
+ }
97
+ // Timing-safe state comparison — the expected and actual both come
98
+ // from the CLI and framlit.app respectively; a mismatch means either
99
+ // CSRF attempt or a stale tab. Either way: reject.
100
+ const a = Buffer.from(state);
101
+ const b = Buffer.from(expectedState);
102
+ const stateOk = a.length === b.length && (0, node_crypto_1.timingSafeEqual)(a, b);
103
+ if (!stateOk) {
104
+ res.statusCode = 400;
105
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
106
+ res.end(FAILURE_HTML('State mismatch — not the expected login attempt.'));
107
+ clearTimeout(timeout);
108
+ server.close();
109
+ reject(new Error('State mismatch; aborting login.'));
110
+ return;
111
+ }
112
+ if (!key.startsWith('fml_')) {
113
+ res.statusCode = 400;
114
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
115
+ res.end(FAILURE_HTML('Received malformed API key.'));
116
+ clearTimeout(timeout);
117
+ server.close();
118
+ reject(new Error('Malformed key received from server.'));
119
+ return;
120
+ }
121
+ res.statusCode = 200;
122
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
123
+ res.end(SUCCESS_HTML);
124
+ clearTimeout(timeout);
125
+ // Give the browser a beat to render the success page before the
126
+ // socket closes.
127
+ setTimeout(() => server.close(), 150);
128
+ resolve({
129
+ api_key: key,
130
+ key_prefix: key.slice(0, 8),
131
+ });
132
+ });
133
+ server.on('error', (err) => {
134
+ clearTimeout(timeout);
135
+ reject(err);
136
+ });
137
+ });
138
+ }
139
+ async function cmdLogin() {
140
+ if (process.env.FRAMLIT_API_KEY) {
141
+ console.log('⚠ FRAMLIT_API_KEY is set in your environment — it overrides any\n' +
142
+ ' key saved by `framlit login`. Unset it first if you want `login`\n' +
143
+ ' to take effect:\n' +
144
+ ' unset FRAMLIT_API_KEY');
145
+ }
146
+ const state = (0, node_crypto_1.randomBytes)(16).toString('hex');
147
+ const server = (0, node_http_1.createServer)();
148
+ await new Promise((resolve, reject) => {
149
+ server.once('error', reject);
150
+ server.listen(0, '127.0.0.1', () => resolve());
151
+ });
152
+ const addr = server.address();
153
+ if (typeof addr !== 'object' || !addr) {
154
+ server.close();
155
+ throw new Error('Failed to get localhost server address');
156
+ }
157
+ const port = addr.port;
158
+ const callback = `http://127.0.0.1:${port}`;
159
+ const authorizeUrl = `${getWebBaseUrl()}${AUTHORIZE_PATH}?cli_callback=${encodeURIComponent(callback)}&state=${encodeURIComponent(state)}`;
160
+ console.log('Opening your browser to authorize the framlit CLI…');
161
+ console.log('If it does not open automatically, copy this URL:');
162
+ console.log(` ${authorizeUrl}\n`);
163
+ openBrowser(authorizeUrl);
164
+ let outcome;
165
+ try {
166
+ outcome = await waitForCallback(server, port, state);
167
+ }
168
+ catch (err) {
169
+ server.close();
170
+ console.error('\n✗ Login failed: ' +
171
+ (err instanceof Error ? err.message : 'Unknown error'));
172
+ console.error(' Retry with `framlit login`, or create a key manually at', 'https://framlit.app/developers');
173
+ process.exit(exit_codes_js_1.EXIT.AUTH_REQUIRED);
174
+ }
175
+ // Fetch user info so we can print a helpful confirmation and cache the
176
+ // email in the config file.
177
+ let email;
178
+ let plan;
179
+ let creditsRemaining;
180
+ try {
181
+ const client = new client_js_1.FramlitClient(outcome.api_key);
182
+ const info = (await client.getUserInfo());
183
+ email = info.email;
184
+ plan = info.plan;
185
+ creditsRemaining = info.creditsRemaining;
186
+ }
187
+ catch {
188
+ // Non-fatal — the key is already saved; whoami will try again.
189
+ }
190
+ (0, config_js_1.saveConfig)({
191
+ api_key: outcome.api_key,
192
+ key_prefix: outcome.key_prefix,
193
+ user_email: email,
194
+ created_at: new Date().toISOString(),
195
+ });
196
+ console.log('');
197
+ console.log('✓ Logged in' + (email ? ` as ${email}` : ''));
198
+ if (creditsRemaining !== undefined) {
199
+ const planLabel = plan ? `· ${plan} plan` : '';
200
+ console.log(` ${creditsRemaining} credits remaining ${planLabel}`.trim());
201
+ }
202
+ console.log(` Key ${outcome.key_prefix}… saved to ~/.framlit/config`);
203
+ }
204
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `framlit logout` — remove the saved API key config.
3
+ *
4
+ * Prints a note if FRAMLIT_API_KEY is still set, since the env var takes
5
+ * precedence and would otherwise silently keep the user "logged in".
6
+ *
7
+ * Issue #63.
8
+ */
9
+ export declare function cmdLogout(): void;
10
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,wBAAgB,SAAS,IAAI,IAAI,CAahC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /**
3
+ * `framlit logout` — remove the saved API key config.
4
+ *
5
+ * Prints a note if FRAMLIT_API_KEY is still set, since the env var takes
6
+ * precedence and would otherwise silently keep the user "logged in".
7
+ *
8
+ * Issue #63.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.cmdLogout = cmdLogout;
12
+ const config_js_1 = require("../config.js");
13
+ function cmdLogout() {
14
+ const removed = (0, config_js_1.clearConfig)();
15
+ if (removed) {
16
+ console.log(`Logged out — removed ${(0, config_js_1.getConfigPath)()}`);
17
+ }
18
+ else {
19
+ console.log('Not logged in — no config file to remove.');
20
+ }
21
+ if (process.env.FRAMLIT_API_KEY) {
22
+ console.log('\nNote: FRAMLIT_API_KEY is still set in your environment. Unset it\n' +
23
+ 'with `unset FRAMLIT_API_KEY` to fully sign out.');
24
+ }
25
+ }
26
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAIH,8BAaC;AAfD,4CAA0D;AAE1D,SAAgB,SAAS;IACvB,MAAM,OAAO,GAAG,IAAA,uBAAW,GAAE,CAAC;IAC9B,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAA,yBAAa,GAAE,EAAE,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CACT,sEAAsE;YACpE,iDAAiD,CACpD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `framlit whoami` — show the currently-authenticated account.
3
+ *
4
+ * Resolves the API key the same way the rest of the CLI does
5
+ * (env var wins over saved config), then calls `/api/mcp/user` for
6
+ * email + credits + plan tier.
7
+ *
8
+ * Issue #63.
9
+ */
10
+ export declare function cmdWhoami(options?: Record<string, unknown>): Promise<void>;
11
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,wBAAsB,SAAS,CAC7B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,OAAO,CAAC,IAAI,CAAC,CAwDf"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * `framlit whoami` — show the currently-authenticated account.
4
+ *
5
+ * Resolves the API key the same way the rest of the CLI does
6
+ * (env var wins over saved config), then calls `/api/mcp/user` for
7
+ * email + credits + plan tier.
8
+ *
9
+ * Issue #63.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.cmdWhoami = cmdWhoami;
13
+ const client_js_1 = require("../../api/client.js");
14
+ const config_js_1 = require("../config.js");
15
+ const output_js_1 = require("../output.js");
16
+ const exit_codes_js_1 = require("../exit-codes.js");
17
+ async function cmdWhoami(options = {}) {
18
+ const outputMode = (0, output_js_1.detectOutputMode)(options.output);
19
+ const envKey = process.env.FRAMLIT_API_KEY;
20
+ const cfg = (0, config_js_1.loadConfig)();
21
+ const apiKey = envKey || cfg?.api_key;
22
+ if (!apiKey) {
23
+ console.error((0, output_js_1.formatError)('Not logged in. Run: framlit login', outputMode, 'AUTH_REQUIRED'));
24
+ process.exit(exit_codes_js_1.EXIT.AUTH_REQUIRED);
25
+ }
26
+ const source = envKey ? 'FRAMLIT_API_KEY env var' : '~/.framlit/config';
27
+ const prefix = apiKey.slice(0, 8);
28
+ let info = {};
29
+ try {
30
+ const client = new client_js_1.FramlitClient(apiKey);
31
+ info = (await client.getUserInfo());
32
+ }
33
+ catch (err) {
34
+ console.error((0, output_js_1.formatError)(`Failed to load user info: ${err instanceof Error ? err.message : 'unknown'}`, outputMode, 'API_ERROR'));
35
+ process.exit(exit_codes_js_1.EXIT.API_ERROR);
36
+ }
37
+ const payload = {
38
+ email: info.email ?? cfg?.user_email ?? null,
39
+ plan: info.plan ?? null,
40
+ creditsRemaining: info.creditsRemaining ?? null,
41
+ creditsTotal: info.creditsTotal ?? null,
42
+ keyPrefix: `${prefix}…`,
43
+ keySource: source,
44
+ };
45
+ const lines = [];
46
+ if (payload.email)
47
+ lines.push(`Email: ${payload.email}`);
48
+ if (payload.plan)
49
+ lines.push(`Plan: ${payload.plan}`);
50
+ if (payload.creditsRemaining !== null) {
51
+ const total = payload.creditsTotal !== null ? ` / ${payload.creditsTotal}` : '';
52
+ lines.push(`Credits: ${payload.creditsRemaining}${total}`);
53
+ }
54
+ lines.push(`Key: ${payload.keyPrefix} (from ${source})`);
55
+ console.log((0, output_js_1.formatOutput)(payload, lines.join('\n'), outputMode));
56
+ }
57
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../../src/cli/commands/whoami.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAcH,8BA0DC;AAtED,mDAAoD;AACpD,4CAA0C;AAC1C,4CAA2E;AAC3E,oDAAwC;AASjC,KAAK,UAAU,SAAS,CAC7B,UAAmC,EAAE;IAErC,MAAM,UAAU,GAAG,IAAA,4BAAgB,EAAC,OAAO,CAAC,MAA4B,CAAC,CAAC;IAE1E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAA,sBAAU,GAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,EAAE,OAAO,CAAC;IAEtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CACX,IAAA,uBAAW,EACT,mCAAmC,EACnC,UAAU,EACV,eAAe,CAChB,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,oBAAI,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAElC,IAAI,IAAI,GAAoB,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,yBAAa,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAoB,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,IAAA,uBAAW,EACT,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,EAC7E,UAAU,EACV,WAAW,CACZ,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,oBAAI,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,GAAG,EAAE,UAAU,IAAI,IAAI;QAC5C,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;QACvB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI;QAC/C,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;QACvC,SAAS,EAAE,GAAG,MAAM,GAAG;QACvB,SAAS,EAAE,MAAM;KAClB,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,KAAK,GACT,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,gBAAgB,GAAG,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,SAAS,UAAU,MAAM,GAAG,CAAC,CAAC;IAE7D,OAAO,CAAC,GAAG,CAAC,IAAA,wBAAY,EAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * CLI config file persistence.
3
+ *
4
+ * `framlit login` writes the issued API key here so subsequent commands
5
+ * on the same machine don't need the env var. File lives at
6
+ * `~/.framlit/config` with mode 0600 so other users on a shared box
7
+ * can't read it.
8
+ *
9
+ * Issue #63.
10
+ */
11
+ export interface CliConfig {
12
+ /** Raw API key (fml_…). Hashed form stored server-side; this value is secret. */
13
+ api_key: string;
14
+ /** First 8 chars of the API key for display purposes. */
15
+ key_prefix: string;
16
+ /** Email of the Framlit user the key belongs to. Set after the first whoami/login round-trip. */
17
+ user_email?: string;
18
+ /** ISO timestamp of when this config was written. */
19
+ created_at: string;
20
+ }
21
+ export declare function getConfigPath(): string;
22
+ /**
23
+ * Read the config file. Returns null if missing or unparseable —
24
+ * callers treat that identically.
25
+ */
26
+ export declare function loadConfig(): CliConfig | null;
27
+ /**
28
+ * Write the config file with 0600 perms (owner-only read/write) so other
29
+ * users on a multi-tenant machine can't peek at the API key.
30
+ */
31
+ export declare function saveConfig(cfg: CliConfig): void;
32
+ /**
33
+ * Remove the config file. Returns true if a file was actually deleted
34
+ * (distinguishes "logged out" from "nothing to do").
35
+ */
36
+ export declare function clearConfig(): boolean;
37
+ //# sourceMappingURL=config.d.ts.map