faux-studio 0.3.6 → 0.3.8
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/index.js +53 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11012,13 +11012,31 @@ async function isCdpAlive(port) {
|
|
|
11012
11012
|
});
|
|
11013
11013
|
clearTimeout(timeout);
|
|
11014
11014
|
if (!res.ok) return { alive: false, isFigma: false };
|
|
11015
|
-
|
|
11016
|
-
const ua = data["User-Agent"] || data.Browser || "";
|
|
11017
|
-
return { alive: true, isFigma: ua.includes("Figma/") };
|
|
11015
|
+
return { alive: true, isFigma: isPortOwnedByFigma(port) };
|
|
11018
11016
|
} catch {
|
|
11019
11017
|
return { alive: false, isFigma: false };
|
|
11020
11018
|
}
|
|
11021
11019
|
}
|
|
11020
|
+
function isPortOwnedByFigma(port) {
|
|
11021
|
+
try {
|
|
11022
|
+
if (process.platform === "win32") {
|
|
11023
|
+
const output = execSync(
|
|
11024
|
+
`netstat -ano | findstr "LISTENING" | findstr ":${port} "`,
|
|
11025
|
+
{ encoding: "utf-8" }
|
|
11026
|
+
);
|
|
11027
|
+
const pid2 = output.trim().split(/\s+/).pop();
|
|
11028
|
+
if (!pid2) return false;
|
|
11029
|
+
const tasks = execSync(`tasklist /FI "PID eq ${pid2}" /NH`, { encoding: "utf-8" });
|
|
11030
|
+
return tasks.includes("Figma");
|
|
11031
|
+
}
|
|
11032
|
+
const pid = execSync(`lsof -iTCP:${port} -sTCP:LISTEN -t`, { encoding: "utf-8" }).trim().split("\n")[0];
|
|
11033
|
+
if (!pid) return false;
|
|
11034
|
+
const comm = execSync(`ps -p ${pid} -o comm=`, { encoding: "utf-8" }).trim();
|
|
11035
|
+
return comm.endsWith("Figma") || comm.endsWith("/Figma");
|
|
11036
|
+
} catch {
|
|
11037
|
+
return false;
|
|
11038
|
+
}
|
|
11039
|
+
}
|
|
11022
11040
|
function isPortAvailable(port) {
|
|
11023
11041
|
return new Promise((resolve) => {
|
|
11024
11042
|
const server2 = createServer();
|
|
@@ -11041,7 +11059,7 @@ async function listTargets(port) {
|
|
|
11041
11059
|
}
|
|
11042
11060
|
var FIGMA_DESIGN_URL_RE = /figma\.com\/(file|design)\//;
|
|
11043
11061
|
function findFigmaDesignTarget(targets) {
|
|
11044
|
-
return targets.find((t) => t.type === "page" && FIGMA_DESIGN_URL_RE.test(t.url)) || null;
|
|
11062
|
+
return targets.find((t) => t.type === "page" && FIGMA_DESIGN_URL_RE.test(t.url)) || targets.find((t) => t.type === "page") || null;
|
|
11045
11063
|
}
|
|
11046
11064
|
async function probeCdpPorts() {
|
|
11047
11065
|
for (const port of KNOWN_CDP_PORTS) {
|
|
@@ -11096,7 +11114,8 @@ async function launchFigmaWithCdp() {
|
|
|
11096
11114
|
}
|
|
11097
11115
|
function launchFigmaProcess(figmaPath, port) {
|
|
11098
11116
|
if (process.platform === "darwin") {
|
|
11099
|
-
|
|
11117
|
+
const binary = `${figmaPath}/Contents/MacOS/Figma`;
|
|
11118
|
+
spawn2(binary, [`--remote-debugging-port=${port}`], {
|
|
11100
11119
|
detached: true,
|
|
11101
11120
|
stdio: "ignore"
|
|
11102
11121
|
}).unref();
|
|
@@ -25469,23 +25488,29 @@ var RESOURCES = [
|
|
|
25469
25488
|
description: "All variable collections and their variables (colors, spacing, typography tokens)",
|
|
25470
25489
|
mimeType: "application/json",
|
|
25471
25490
|
script: `
|
|
25472
|
-
const collections = figma.variables.
|
|
25473
|
-
|
|
25474
|
-
|
|
25475
|
-
|
|
25476
|
-
|
|
25477
|
-
|
|
25478
|
-
|
|
25479
|
-
|
|
25480
|
-
if (!v) return null;
|
|
25481
|
-
return {
|
|
25491
|
+
const collections = await figma.variables.getLocalVariableCollectionsAsync();
|
|
25492
|
+
const result = [];
|
|
25493
|
+
for (const c of collections) {
|
|
25494
|
+
const variables = [];
|
|
25495
|
+
for (const vid of c.variableIds) {
|
|
25496
|
+
const v = await figma.variables.getVariableByIdAsync(vid);
|
|
25497
|
+
if (!v) continue;
|
|
25498
|
+
variables.push({
|
|
25482
25499
|
id: v.id,
|
|
25483
25500
|
name: v.name,
|
|
25484
25501
|
resolvedType: v.resolvedType,
|
|
25485
25502
|
valuesByMode: v.valuesByMode,
|
|
25486
|
-
};
|
|
25487
|
-
}
|
|
25488
|
-
|
|
25503
|
+
});
|
|
25504
|
+
}
|
|
25505
|
+
result.push({
|
|
25506
|
+
id: c.id,
|
|
25507
|
+
name: c.name,
|
|
25508
|
+
modes: c.modes,
|
|
25509
|
+
variableCount: c.variableIds.length,
|
|
25510
|
+
variables,
|
|
25511
|
+
});
|
|
25512
|
+
}
|
|
25513
|
+
return result;
|
|
25489
25514
|
`
|
|
25490
25515
|
},
|
|
25491
25516
|
{
|
|
@@ -25494,7 +25519,7 @@ var RESOURCES = [
|
|
|
25494
25519
|
description: "Local components and component sets in the file",
|
|
25495
25520
|
mimeType: "application/json",
|
|
25496
25521
|
script: `
|
|
25497
|
-
const nodes = figma.
|
|
25522
|
+
const nodes = figma.currentPage.findAllWithCriteria({ types: ['COMPONENT', 'COMPONENT_SET'] });
|
|
25498
25523
|
return nodes.map(c => ({
|
|
25499
25524
|
id: c.id,
|
|
25500
25525
|
name: c.name,
|
|
@@ -25510,9 +25535,9 @@ var RESOURCES = [
|
|
|
25510
25535
|
description: "Text styles, paint styles, and effect styles defined in the file",
|
|
25511
25536
|
mimeType: "application/json",
|
|
25512
25537
|
script: `
|
|
25513
|
-
const textStyles = figma.
|
|
25514
|
-
const paintStyles = figma.
|
|
25515
|
-
const effectStyles = figma.
|
|
25538
|
+
const textStyles = await figma.getLocalTextStylesAsync();
|
|
25539
|
+
const paintStyles = await figma.getLocalPaintStylesAsync();
|
|
25540
|
+
const effectStyles = await figma.getLocalEffectStylesAsync();
|
|
25516
25541
|
return {
|
|
25517
25542
|
textStyles: textStyles.map(s => ({
|
|
25518
25543
|
id: s.id, name: s.name, fontSize: s.fontSize, fontName: s.fontName,
|
|
@@ -25566,7 +25591,7 @@ Resources provide quick read-only access to Figma state without tool calls:
|
|
|
25566
25591
|
- Create components for reusable UI patterns.`;
|
|
25567
25592
|
function createMcpServer(deps) {
|
|
25568
25593
|
const server2 = new Server(
|
|
25569
|
-
{ name: "faux-studio", version: "0.3.
|
|
25594
|
+
{ name: "faux-studio", version: "0.3.8" },
|
|
25570
25595
|
{
|
|
25571
25596
|
capabilities: { tools: { listChanged: true }, resources: {}, logging: {} },
|
|
25572
25597
|
instructions: INSTRUCTIONS
|
|
@@ -25722,7 +25747,11 @@ Run the \`login\` tool to re-authenticate.` : `Error: ${message}`
|
|
|
25722
25747
|
throw new Error(`Unknown resource: ${uri}`);
|
|
25723
25748
|
}
|
|
25724
25749
|
log(`Reading resource: ${uri}`);
|
|
25725
|
-
const
|
|
25750
|
+
const wrapped = `
|
|
25751
|
+
const __res = await (async () => {${resource.script}})();
|
|
25752
|
+
return { success: true, result: __res };
|
|
25753
|
+
`;
|
|
25754
|
+
const result = await deps.executeScript(wrapped);
|
|
25726
25755
|
const text = result === void 0 || result === null ? "{}" : typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
25727
25756
|
return {
|
|
25728
25757
|
contents: [{ uri, mimeType: resource.mimeType, text }]
|