figmanage 1.2.3 → 1.2.5
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/dist/auth/cookie.d.ts +10 -0
- package/dist/auth/cookie.js +37 -1
- package/dist/cli/login.js +6 -3
- package/dist/setup.js +6 -4
- package/package.json +1 -1
package/dist/auth/cookie.d.ts
CHANGED
|
@@ -23,10 +23,20 @@ export interface SessionInfo {
|
|
|
23
23
|
}
|
|
24
24
|
export declare function validateSession(cookieValue: string, userId: string): Promise<SessionInfo>;
|
|
25
25
|
export declare function validatePat(pat: string): Promise<string>;
|
|
26
|
+
export interface ProfileInfo {
|
|
27
|
+
profileName: string;
|
|
28
|
+
figmaEmail?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve display info for a Figma account: Figma email via API + Chrome profile name.
|
|
32
|
+
* The API call is best-effort -- falls back to userId if it fails.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveAccountInfo(account: FigmaAccount): Promise<ProfileInfo>;
|
|
26
35
|
export interface FigmaAccount {
|
|
27
36
|
userId: string;
|
|
28
37
|
cookieValue: string;
|
|
29
38
|
profile: string;
|
|
39
|
+
profilePath: string;
|
|
30
40
|
}
|
|
31
41
|
/**
|
|
32
42
|
* Extract Figma auth cookies from all Chrome profiles.
|
package/dist/auth/cookie.js
CHANGED
|
@@ -263,6 +263,42 @@ export async function validatePat(pat) {
|
|
|
263
263
|
});
|
|
264
264
|
return res.data.handle || res.data.email || 'valid';
|
|
265
265
|
}
|
|
266
|
+
function readChromeProfileName(profilePath) {
|
|
267
|
+
try {
|
|
268
|
+
const prefsPath = join(profilePath, 'Preferences');
|
|
269
|
+
if (!existsSync(prefsPath))
|
|
270
|
+
return profilePath.split(/[/\\]/).pop();
|
|
271
|
+
const prefs = JSON.parse(readFileSync(prefsPath, 'utf-8'));
|
|
272
|
+
return prefs?.profile?.name || profilePath.split(/[/\\]/).pop();
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return profilePath.split(/[/\\]/).pop();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Resolve display info for a Figma account: Figma email via API + Chrome profile name.
|
|
280
|
+
* The API call is best-effort -- falls back to userId if it fails.
|
|
281
|
+
*/
|
|
282
|
+
export async function resolveAccountInfo(account) {
|
|
283
|
+
const profileName = readChromeProfileName(account.profilePath);
|
|
284
|
+
try {
|
|
285
|
+
const headers = {
|
|
286
|
+
'Cookie': `${COOKIE_NAME}=${account.cookieValue}`,
|
|
287
|
+
'X-CSRF-Bypass': 'yes',
|
|
288
|
+
'X-Figma-User-Id': account.userId,
|
|
289
|
+
};
|
|
290
|
+
const res = await axios.get('https://www.figma.com/api/user/state', {
|
|
291
|
+
headers,
|
|
292
|
+
timeout: 5000,
|
|
293
|
+
});
|
|
294
|
+
const meta = res.data?.meta || {};
|
|
295
|
+
const email = meta.email || meta.user?.email;
|
|
296
|
+
return { profileName, figmaEmail: email };
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return { profileName };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
266
302
|
/**
|
|
267
303
|
* Extract Figma auth cookies from all Chrome profiles.
|
|
268
304
|
* Returns an array of accounts found (may be empty on Windows failure).
|
|
@@ -275,7 +311,7 @@ export function extractCookies() {
|
|
|
275
311
|
try {
|
|
276
312
|
const rawCookie = extractCookieFromProfile(profilePath);
|
|
277
313
|
const { userId, cookieValue } = parseCookieValue(rawCookie);
|
|
278
|
-
accounts.push({ userId, cookieValue, profile: profilePath.split(/[/\\]/).pop() });
|
|
314
|
+
accounts.push({ userId, cookieValue, profile: profilePath.split(/[/\\]/).pop(), profilePath });
|
|
279
315
|
}
|
|
280
316
|
catch {
|
|
281
317
|
// Profile doesn't have a Figma cookie
|
package/dist/cli/login.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createInterface } from 'node:readline';
|
|
2
2
|
import { platform } from 'node:os';
|
|
3
3
|
import { setActiveWorkspace, deleteConfig, getConfigPath } from '../config.js';
|
|
4
|
-
import { extractCookies, validateSession, validatePat } from '../auth/cookie.js';
|
|
4
|
+
import { extractCookies, validateSession, validatePat, resolveAccountInfo } from '../auth/cookie.js';
|
|
5
5
|
async function prompt(question) {
|
|
6
6
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7
7
|
const answer = await new Promise(resolve => rl.question(question, resolve));
|
|
@@ -33,9 +33,12 @@ export async function handleLogin(options = {}) {
|
|
|
33
33
|
// Pick account if multiple
|
|
34
34
|
let selected = accounts[0];
|
|
35
35
|
if (accounts.length > 1) {
|
|
36
|
-
console.log(`\n Found ${accounts.length} Figma accounts
|
|
36
|
+
console.log(`\n Found ${accounts.length} Figma accounts. Identifying...\n`);
|
|
37
|
+
const infos = await Promise.all(accounts.map(a => resolveAccountInfo(a)));
|
|
37
38
|
for (let i = 0; i < accounts.length; i++) {
|
|
38
|
-
|
|
39
|
+
const info = infos[i];
|
|
40
|
+
const label = info.figmaEmail || `User ${accounts[i].userId}`;
|
|
41
|
+
console.log(` [${i + 1}] ${label} (Chrome: ${info.profileName})`);
|
|
39
42
|
}
|
|
40
43
|
const answer = await prompt(`\n Select account [1-${accounts.length}]: `);
|
|
41
44
|
const idx = parseInt(answer, 10) - 1;
|
package/dist/setup.js
CHANGED
|
@@ -3,7 +3,7 @@ import { execFileSync } from 'child_process';
|
|
|
3
3
|
import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir, platform } from 'os';
|
|
6
|
-
import { extractCookies, validateSession, validatePat } from './auth/cookie.js';
|
|
6
|
+
import { extractCookies, validateSession, validatePat, resolveAccountInfo } from './auth/cookie.js';
|
|
7
7
|
// --- MCP client detection and registration ---
|
|
8
8
|
function claudeCliAvailable() {
|
|
9
9
|
try {
|
|
@@ -187,10 +187,12 @@ async function setup() {
|
|
|
187
187
|
// If multiple accounts, let user pick
|
|
188
188
|
let selected = accounts[0];
|
|
189
189
|
if (accounts.length > 1) {
|
|
190
|
-
console.log(`\n Found ${accounts.length} Figma accounts
|
|
190
|
+
console.log(`\n Found ${accounts.length} Figma accounts. Identifying...\n`);
|
|
191
|
+
const infos = await Promise.all(accounts.map(a => resolveAccountInfo(a)));
|
|
191
192
|
for (let i = 0; i < accounts.length; i++) {
|
|
192
|
-
const
|
|
193
|
-
|
|
193
|
+
const info = infos[i];
|
|
194
|
+
const label = info.figmaEmail || `User ${accounts[i].userId}`;
|
|
195
|
+
console.log(` [${i + 1}] ${label} (Chrome: ${info.profileName})`);
|
|
194
196
|
}
|
|
195
197
|
const { createInterface } = await import('readline');
|
|
196
198
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
package/package.json
CHANGED