@atezer/figma-mcp-bridge 1.2.0 → 1.2.2
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/CHANGELOG.md +62 -0
- package/README.md +99 -9
- package/dist/cloudflare/cloud-cors.js +40 -0
- package/dist/cloudflare/cloud-mode-kv.js +86 -0
- package/dist/cloudflare/cloud-mode-routes.js +97 -0
- package/dist/cloudflare/cloud-relay-session.js +141 -0
- package/dist/cloudflare/core/config.js +1 -1
- package/dist/cloudflare/core/figma-url.js +48 -0
- package/dist/cloudflare/core/plugin-bridge-connector.js +52 -43
- package/dist/cloudflare/core/plugin-bridge-server.js +211 -87
- package/dist/cloudflare/index.js +243 -4
- package/dist/core/config.js +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/figma-url.d.ts +10 -0
- package/dist/core/figma-url.d.ts.map +1 -0
- package/dist/core/figma-url.js +49 -0
- package/dist/core/figma-url.js.map +1 -0
- package/dist/core/plugin-bridge-connector.d.ts +6 -1
- package/dist/core/plugin-bridge-connector.d.ts.map +1 -1
- package/dist/core/plugin-bridge-connector.js +52 -43
- package/dist/core/plugin-bridge-connector.js.map +1 -1
- package/dist/core/plugin-bridge-server.d.ts +47 -14
- package/dist/core/plugin-bridge-server.d.ts.map +1 -1
- package/dist/core/plugin-bridge-server.js +211 -87
- package/dist/core/plugin-bridge-server.js.map +1 -1
- package/dist/local-plugin-only.d.ts.map +1 -1
- package/dist/local-plugin-only.js +163 -43
- package/dist/local-plugin-only.js.map +1 -1
- package/f-mcp-plugin/README.md +13 -5
- package/f-mcp-plugin/code.js +216 -2
- package/f-mcp-plugin/manifest.json +6 -2
- package/f-mcp-plugin/ui.html +694 -213
- package/package.json +7 -6
package/dist/cloudflare/index.js
CHANGED
|
@@ -17,7 +17,11 @@ import { createChildLogger } from "./core/logger.js";
|
|
|
17
17
|
import { testBrowserRendering } from "./test-browser.js";
|
|
18
18
|
import { FigmaAPI, extractFileKey } from "./core/figma-api.js";
|
|
19
19
|
import { registerFigmaAPITools } from "./core/figma-tools.js";
|
|
20
|
+
import { FmcpRelaySession } from "./cloud-relay-session.js";
|
|
21
|
+
import { handleCloudModeRoutes, maybeTightenMcpCors } from "./cloud-mode-routes.js";
|
|
22
|
+
import { clientIp, deleteBind, deletePairing, FMCP_RL_PREFIX, generatePairingCode, generatePairingSecret, getBind, getPairing, PAIRING_TTL_SEC, putBind, putPairing, rateLimitAllow, } from "./cloud-mode-kv.js";
|
|
20
23
|
const logger = createChildLogger({ component: "mcp-server" });
|
|
24
|
+
export { FmcpRelaySession };
|
|
21
25
|
/**
|
|
22
26
|
* F-MCP ATezer Agent
|
|
23
27
|
* Extends McpAgent to provide Figma-specific debugging tools
|
|
@@ -25,6 +29,8 @@ const logger = createChildLogger({ component: "mcp-server" });
|
|
|
25
29
|
export class FigmaMCP extends McpAgent {
|
|
26
30
|
constructor() {
|
|
27
31
|
super(...arguments);
|
|
32
|
+
// Root @modelcontextprotocol/sdk vs agents' nested copy — types diverge; runtime is compatible.
|
|
33
|
+
// @ts-expect-error TS2416 — McpServer duplicate package resolution
|
|
28
34
|
this.server = new McpServer({
|
|
29
35
|
name: "F-MCP ATezer",
|
|
30
36
|
version: "0.1.0",
|
|
@@ -135,6 +141,44 @@ export class FigmaMCP extends McpAgent {
|
|
|
135
141
|
}
|
|
136
142
|
return this.sessionId;
|
|
137
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Streamable HTTP transport session id (isolated per MCP client). Distinct from OAuth FIXED_SESSION_ID.
|
|
146
|
+
*/
|
|
147
|
+
getMcpTransportSessionId() {
|
|
148
|
+
const raw = this.name;
|
|
149
|
+
if (!raw?.includes(":"))
|
|
150
|
+
return null;
|
|
151
|
+
const [prefix, sid] = raw.split(":");
|
|
152
|
+
if (prefix !== "streamable-http" || !sid)
|
|
153
|
+
return null;
|
|
154
|
+
return sid;
|
|
155
|
+
}
|
|
156
|
+
async relayPluginRpc(options) {
|
|
157
|
+
const env = this.env;
|
|
158
|
+
const sid = this.getMcpTransportSessionId();
|
|
159
|
+
if (!sid) {
|
|
160
|
+
throw new Error("Cloud relay requires streamable HTTP MCP session (e.g. claude.ai remote connector).");
|
|
161
|
+
}
|
|
162
|
+
const bind = await getBind(env.OAUTH_STATE, sid);
|
|
163
|
+
if (!bind?.code) {
|
|
164
|
+
throw new Error("No cloud relay bound. Run fmcp_generate_pairing_code, enter code+secret in the Figma plugin (Cloud Mode), then call fmcp_cloud_bind with the same code and secret.");
|
|
165
|
+
}
|
|
166
|
+
const stub = env.FMCP_RELAY.get(env.FMCP_RELAY.idFromName(`pair:${bind.code}`));
|
|
167
|
+
const res = await stub.fetch(new Request("http://relay/rpc", {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "Content-Type": "application/json" },
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
method: options.method,
|
|
172
|
+
params: options.params ?? {},
|
|
173
|
+
fileKey: options.fileKey,
|
|
174
|
+
}),
|
|
175
|
+
}));
|
|
176
|
+
const j = (await res.json());
|
|
177
|
+
if (!res.ok || !j.ok) {
|
|
178
|
+
throw new Error(j.error || "relay_rpc_failed");
|
|
179
|
+
}
|
|
180
|
+
return j.result;
|
|
181
|
+
}
|
|
138
182
|
/**
|
|
139
183
|
* Get or create Figma API client with OAuth token from session
|
|
140
184
|
*/
|
|
@@ -650,6 +694,176 @@ export class FigmaMCP extends McpAgent {
|
|
|
650
694
|
};
|
|
651
695
|
}
|
|
652
696
|
});
|
|
697
|
+
// ---- FMCP Cloud Mode (plugin relay via FMCP_RELAY Durable Object) ----
|
|
698
|
+
this.server.tool("fmcp_generate_pairing_code", "Generate a 6-character pairing code and secret for Cloud Mode. User pastes code + secret into the F-MCP Bridge plugin (Cloud Mode) so the plugin connects to this deployment via WebSocket. Then call fmcp_cloud_bind with the same values. Codes expire in 5 minutes. Isolated per MCP streamable-http session after bind.", {}, async () => {
|
|
699
|
+
const env = this.env;
|
|
700
|
+
const sid = this.getMcpTransportSessionId();
|
|
701
|
+
if (!sid) {
|
|
702
|
+
return {
|
|
703
|
+
content: [
|
|
704
|
+
{
|
|
705
|
+
type: "text",
|
|
706
|
+
text: JSON.stringify({
|
|
707
|
+
error: "Pairing tool requires streamable HTTP MCP session (remote connector).",
|
|
708
|
+
}),
|
|
709
|
+
},
|
|
710
|
+
],
|
|
711
|
+
isError: true,
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
const rlOk = await rateLimitAllow(env.OAUTH_STATE, `${FMCP_RL_PREFIX}tool_pair:${sid}`, 15, 3600);
|
|
715
|
+
if (!rlOk) {
|
|
716
|
+
return {
|
|
717
|
+
content: [
|
|
718
|
+
{
|
|
719
|
+
type: "text",
|
|
720
|
+
text: JSON.stringify({ error: "Rate limited: too many pairing codes for this session." }),
|
|
721
|
+
},
|
|
722
|
+
],
|
|
723
|
+
isError: true,
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
const code = generatePairingCode();
|
|
727
|
+
const secret = generatePairingSecret();
|
|
728
|
+
const record = { secret, createdAt: Date.now() };
|
|
729
|
+
await putPairing(env.OAUTH_STATE, code, record);
|
|
730
|
+
let origin = (env.MCP_OAUTH_BASE_URL || "").replace(/\/$/, "").trim();
|
|
731
|
+
if (!origin)
|
|
732
|
+
origin = "https://your-worker.workers.dev";
|
|
733
|
+
const wsOrigin = origin.startsWith("https://")
|
|
734
|
+
? `wss://${origin.slice("https://".length)}`
|
|
735
|
+
: origin.startsWith("http://")
|
|
736
|
+
? `ws://${origin.slice("http://".length)}`
|
|
737
|
+
: `wss://${origin}`;
|
|
738
|
+
const pluginWsUrl = `${wsOrigin}/fmcp-cloud/plugin?code=${encodeURIComponent(code)}&secret=${encodeURIComponent(secret)}`;
|
|
739
|
+
return {
|
|
740
|
+
content: [
|
|
741
|
+
{
|
|
742
|
+
type: "text",
|
|
743
|
+
text: JSON.stringify({
|
|
744
|
+
success: true,
|
|
745
|
+
code,
|
|
746
|
+
secret,
|
|
747
|
+
expiresInSeconds: PAIRING_TTL_SEC,
|
|
748
|
+
pluginWebSocketUrl: pluginWsUrl,
|
|
749
|
+
nextStep: "1) Open F-MCP Bridge plugin → enable Cloud Mode → paste code and secret. 2) Call fmcp_cloud_bind with the same code and secret.",
|
|
750
|
+
}, null, 2),
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
};
|
|
754
|
+
});
|
|
755
|
+
this.server.tool("fmcp_cloud_bind", "Bind this MCP session to a pairing code after the Figma plugin has connected (or is about to connect) using fmcp_generate_pairing_code output. Validates secret; pairing slot is consumed.", {
|
|
756
|
+
code: z.string().min(4).max(8).describe("6-character pairing code (case-insensitive)"),
|
|
757
|
+
secret: z.string().min(8).describe("Secret string returned with the pairing code"),
|
|
758
|
+
}, async ({ code, secret }) => {
|
|
759
|
+
const env = this.env;
|
|
760
|
+
const sid = this.getMcpTransportSessionId();
|
|
761
|
+
if (!sid) {
|
|
762
|
+
return {
|
|
763
|
+
content: [{ type: "text", text: JSON.stringify({ error: "Requires streamable HTTP session." }) }],
|
|
764
|
+
isError: true,
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
const c = code.trim().toUpperCase();
|
|
768
|
+
const pair = await getPairing(env.OAUTH_STATE, c);
|
|
769
|
+
if (!pair || pair.secret !== secret) {
|
|
770
|
+
return {
|
|
771
|
+
content: [
|
|
772
|
+
{
|
|
773
|
+
type: "text",
|
|
774
|
+
text: JSON.stringify({ error: "Invalid or expired pairing code / secret." }),
|
|
775
|
+
},
|
|
776
|
+
],
|
|
777
|
+
isError: true,
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
await putBind(env.OAUTH_STATE, sid, { code: c, boundAt: Date.now() });
|
|
781
|
+
await deletePairing(env.OAUTH_STATE, c);
|
|
782
|
+
return {
|
|
783
|
+
content: [
|
|
784
|
+
{
|
|
785
|
+
type: "text",
|
|
786
|
+
text: JSON.stringify({
|
|
787
|
+
success: true,
|
|
788
|
+
message: "Session bound to relay. Use fmcp_cloud_status or fmcp_plugin_bridge_request / REST tools as needed.",
|
|
789
|
+
}),
|
|
790
|
+
},
|
|
791
|
+
],
|
|
792
|
+
};
|
|
793
|
+
});
|
|
794
|
+
this.server.tool("fmcp_cloud_status", "Return whether this MCP session is bound to a cloud relay and whether the Figma plugin WebSocket is connected.", {}, async () => {
|
|
795
|
+
const env = this.env;
|
|
796
|
+
const sid = this.getMcpTransportSessionId();
|
|
797
|
+
if (!sid) {
|
|
798
|
+
return {
|
|
799
|
+
content: [{ type: "text", text: JSON.stringify({ bound: false, reason: "not_streamable_http" }) }],
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
const bind = await getBind(env.OAUTH_STATE, sid);
|
|
803
|
+
if (!bind?.code) {
|
|
804
|
+
return {
|
|
805
|
+
content: [{ type: "text", text: JSON.stringify({ bound: false, pluginConnected: false }) }],
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
const stub = env.FMCP_RELAY.get(env.FMCP_RELAY.idFromName(`pair:${bind.code}`));
|
|
809
|
+
const res = await stub.fetch(new Request("http://relay/status", { method: "GET" }));
|
|
810
|
+
const st = (await res.json());
|
|
811
|
+
return {
|
|
812
|
+
content: [
|
|
813
|
+
{
|
|
814
|
+
type: "text",
|
|
815
|
+
text: JSON.stringify({
|
|
816
|
+
bound: true,
|
|
817
|
+
pairingCodeSuffix: bind.code.slice(-2),
|
|
818
|
+
pluginConnected: !!st.pluginConnected,
|
|
819
|
+
}),
|
|
820
|
+
},
|
|
821
|
+
],
|
|
822
|
+
};
|
|
823
|
+
});
|
|
824
|
+
this.server.tool("fmcp_cloud_disconnect", "Unbind this MCP session from the cloud relay and ask the relay to close plugin WebSockets.", {}, async () => {
|
|
825
|
+
const env = this.env;
|
|
826
|
+
const sid = this.getMcpTransportSessionId();
|
|
827
|
+
if (!sid) {
|
|
828
|
+
return {
|
|
829
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: "not_streamable_http" }) }],
|
|
830
|
+
isError: true,
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
const bind = await getBind(env.OAUTH_STATE, sid);
|
|
834
|
+
if (bind?.code) {
|
|
835
|
+
const stub = env.FMCP_RELAY.get(env.FMCP_RELAY.idFromName(`pair:${bind.code}`));
|
|
836
|
+
await stub.fetch(new Request("http://relay/disconnect", { method: "POST" }));
|
|
837
|
+
}
|
|
838
|
+
await deleteBind(env.OAUTH_STATE, sid);
|
|
839
|
+
return {
|
|
840
|
+
content: [
|
|
841
|
+
{
|
|
842
|
+
type: "text",
|
|
843
|
+
text: JSON.stringify({ success: true, message: "Cloud relay unbound." }),
|
|
844
|
+
},
|
|
845
|
+
],
|
|
846
|
+
};
|
|
847
|
+
});
|
|
848
|
+
this.server.tool("fmcp_plugin_bridge_request", "Forward a single Plugin Bridge RPC to the connected Figma plugin (same protocol as local WebSocket bridge). Requires fmcp_cloud_bind and an active plugin connection. Example methods: getVariables, executeCodeViaUI, getDocumentStructure — see PluginBridgeConnector.", {
|
|
849
|
+
method: z.string().describe("Bridge method name, e.g. getVariables, executeCodeViaUI"),
|
|
850
|
+
params: z.record(z.unknown()).optional().describe("Method parameters object"),
|
|
851
|
+
fileKey: z.string().optional().describe("Optional file key for multi-file routing (same as local bridge)"),
|
|
852
|
+
}, async ({ method, params, fileKey }) => {
|
|
853
|
+
try {
|
|
854
|
+
const result = await this.relayPluginRpc({ method, params: params ?? {}, fileKey });
|
|
855
|
+
return {
|
|
856
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, result }, null, 2) }],
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
catch (e) {
|
|
860
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
861
|
+
return {
|
|
862
|
+
content: [{ type: "text", text: JSON.stringify({ success: false, error: msg }) }],
|
|
863
|
+
isError: true,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
});
|
|
653
867
|
// Register Figma API tools (Tools 8-14)
|
|
654
868
|
registerFigmaAPITools(this.server, async () => await this.getFigmaAPI(), () => this.browserManager?.getCurrentUrl() || null, () => this.consoleMonitor || null, () => this.browserManager || null, () => this.ensureInitialized());
|
|
655
869
|
}
|
|
@@ -661,13 +875,29 @@ export class FigmaMCP extends McpAgent {
|
|
|
661
875
|
export default {
|
|
662
876
|
async fetch(request, env, ctx) {
|
|
663
877
|
const url = new URL(request.url);
|
|
878
|
+
const cloudRes = await handleCloudModeRoutes(request, env);
|
|
879
|
+
if (cloudRes)
|
|
880
|
+
return cloudRes;
|
|
664
881
|
// SSE endpoint for remote MCP clients
|
|
665
882
|
if (url.pathname === "/sse" || url.pathname === "/sse/message") {
|
|
666
|
-
|
|
883
|
+
const r = await FigmaMCP.serveSSE("/sse").fetch(request, env, ctx);
|
|
884
|
+
return maybeTightenMcpCors(request, r);
|
|
667
885
|
}
|
|
668
|
-
// HTTP endpoint for direct MCP communication
|
|
886
|
+
// HTTP endpoint for direct MCP communication (Streamable HTTP — default in agents McpAgent.serve)
|
|
669
887
|
if (url.pathname === "/mcp") {
|
|
670
|
-
|
|
888
|
+
if (request.method === "POST" || request.method === "GET") {
|
|
889
|
+
const ip = clientIp(request);
|
|
890
|
+
const mcpOk = await rateLimitAllow(env.OAUTH_STATE, `${FMCP_RL_PREFIX}mcp:${ip}`, 180, 60);
|
|
891
|
+
if (!mcpOk) {
|
|
892
|
+
return new Response(JSON.stringify({
|
|
893
|
+
jsonrpc: "2.0",
|
|
894
|
+
error: { code: -32_603, message: "Rate limited" },
|
|
895
|
+
id: null,
|
|
896
|
+
}), { status: 429, headers: { "Content-Type": "application/json" } });
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
const r = await FigmaMCP.serve("/mcp").fetch(request, env, ctx);
|
|
900
|
+
return maybeTightenMcpCors(request, r);
|
|
671
901
|
}
|
|
672
902
|
// OAuth authorization initiation
|
|
673
903
|
if (url.pathname === "/oauth/authorize") {
|
|
@@ -898,7 +1128,16 @@ export default {
|
|
|
898
1128
|
status: "healthy",
|
|
899
1129
|
service: "F-MCP ATezer",
|
|
900
1130
|
version: "0.1.0",
|
|
901
|
-
endpoints: [
|
|
1131
|
+
endpoints: [
|
|
1132
|
+
"/sse",
|
|
1133
|
+
"/mcp",
|
|
1134
|
+
"/fmcp-cloud/plugin",
|
|
1135
|
+
"/fmcp-cloud/pairing",
|
|
1136
|
+
"/fmcp-cloud/health",
|
|
1137
|
+
"/test-browser",
|
|
1138
|
+
"/oauth/authorize",
|
|
1139
|
+
"/oauth/callback",
|
|
1140
|
+
],
|
|
902
1141
|
oauth_configured: !!env.FIGMA_OAUTH_CLIENT_ID
|
|
903
1142
|
}), {
|
|
904
1143
|
headers: { "Content-Type": "application/json" },
|
package/dist/core/config.js
CHANGED
|
@@ -51,7 +51,7 @@ const DEFAULT_CONFIG = {
|
|
|
51
51
|
local: {
|
|
52
52
|
debugHost: process.env.FIGMA_DEBUG_HOST || 'localhost',
|
|
53
53
|
debugPort: parseInt(process.env.FIGMA_DEBUG_PORT || '9222', 10),
|
|
54
|
-
pluginBridgePort: parseInt(process.env.FIGMA_PLUGIN_BRIDGE_PORT || '5454', 10),
|
|
54
|
+
pluginBridgePort: parseInt(process.env.FIGMA_MCP_BRIDGE_PORT || process.env.FIGMA_PLUGIN_BRIDGE_PORT || '5454', 10),
|
|
55
55
|
auditLogPath: process.env.FIGMA_MCP_AUDIT_LOG_PATH || undefined,
|
|
56
56
|
},
|
|
57
57
|
};
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B;;GAEG;AACH,SAAS,UAAU;IACjB,uDAAuD;IACvD,IAAI,OAAO,UAAU,KAAK,WAAW,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;QAChE,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,4BAA4B;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,EAAE,CAAC;IAC1D,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,4CAA4C;IAC5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,cAAc,GAAiB;IACnC,IAAI,EAAE,UAAU,EAAE;IAClB,OAAO,EAAE;QACP,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE;YACJ,+CAA+C;YAC/C,yBAAyB;YACzB,cAAc,EAAE,yCAAyC;SAC1D;KACF;IACD,OAAO,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QACvD,UAAU,EAAE;YACV,eAAe,EAAE,GAAG;YACpB,cAAc,EAAE,EAAE;YAClB,cAAc,EAAE,CAAC;YACjB,gBAAgB,EAAE,IAAI;SACvB;KACF;IACD,WAAW,EAAE;QACX,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,EAAE,kBAAkB,EAAE,aAAa,CAAC;KACjF;IACD,KAAK,EAAE;QACL,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW;QACtD,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,MAAM,EAAE,EAAE,CAAC;QAC/D,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,MAAM,EAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Figma and FigJam URLs to extract fileKey and optional nodeId.
|
|
3
|
+
* Used for link-based routing in multi-client scenarios.
|
|
4
|
+
*/
|
|
5
|
+
export interface ParsedFigmaUrl {
|
|
6
|
+
fileKey: string;
|
|
7
|
+
nodeId?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseFigmaUrl(url: string): ParsedFigmaUrl | null;
|
|
10
|
+
//# sourceMappingURL=figma-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figma-url.d.ts","sourceRoot":"","sources":["../../src/core/figma-url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAkChE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Figma and FigJam URLs to extract fileKey and optional nodeId.
|
|
3
|
+
* Used for link-based routing in multi-client scenarios.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Supported URL patterns:
|
|
7
|
+
* - https://www.figma.com/design/<fileKey>/...
|
|
8
|
+
* - https://www.figma.com/board/<fileKey>/... (FigJam)
|
|
9
|
+
* - https://www.figma.com/jam/<fileKey>/...
|
|
10
|
+
* - https://www.figma.com/proto/<fileKey>/...
|
|
11
|
+
* - https://figma.com/... (no www)
|
|
12
|
+
* Query: ?node-id=0-1 or ?node-id=0:1 → nodeId "0:1"
|
|
13
|
+
*/
|
|
14
|
+
const FIGMA_PATH_REGEX = /^https?:\/\/(www\.)?figma\.com\/(design|board|jam|proto|file)\/([a-zA-Z0-9_-]{10,128})(?:\/|$)/i;
|
|
15
|
+
export function parseFigmaUrl(url) {
|
|
16
|
+
if (!url || typeof url !== "string")
|
|
17
|
+
return null;
|
|
18
|
+
const trimmed = url.trim();
|
|
19
|
+
if (!trimmed)
|
|
20
|
+
return null;
|
|
21
|
+
let fileKey = null;
|
|
22
|
+
// Try path-based match: /design/KEY, /board/KEY, /jam/KEY, /proto/KEY, /file/KEY
|
|
23
|
+
const pathMatch = trimmed.match(FIGMA_PATH_REGEX);
|
|
24
|
+
if (pathMatch) {
|
|
25
|
+
fileKey = pathMatch[3];
|
|
26
|
+
}
|
|
27
|
+
// Fallback: some Figma links use /file/KEY or just KEY in path
|
|
28
|
+
if (!fileKey) {
|
|
29
|
+
const fileKeyFromPath = trimmed.match(/figma\.com\/(?:design|board|jam|proto|file)\/([a-zA-Z0-9_-]{10,128})/i);
|
|
30
|
+
if (fileKeyFromPath)
|
|
31
|
+
fileKey = fileKeyFromPath[1];
|
|
32
|
+
}
|
|
33
|
+
if (!fileKey)
|
|
34
|
+
return null;
|
|
35
|
+
let nodeId;
|
|
36
|
+
try {
|
|
37
|
+
const parsed = new URL(trimmed);
|
|
38
|
+
const nodeIdParam = parsed.searchParams.get("node-id");
|
|
39
|
+
if (nodeIdParam) {
|
|
40
|
+
// Figma uses 0-1 or 0:1 format; plugin API expects "0:1"
|
|
41
|
+
nodeId = nodeIdParam.replace(/-/g, ":");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// URL constructor failed, ignore query parsing
|
|
46
|
+
}
|
|
47
|
+
return { fileKey, nodeId };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=figma-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figma-url.js","sourceRoot":"","sources":["../../src/core/figma-url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAG,iGAAiG,CAAC;AAE3H,MAAM,UAAU,aAAa,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,IAAI,OAAO,GAAkB,IAAI,CAAC;IAElC,iFAAiF;IACjF,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACf,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,+DAA+D;IAC/D,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC/G,IAAI,eAAe;YAAE,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,IAAI,MAA0B,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,WAAW,EAAE,CAAC;YACjB,yDAAyD;YACzD,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,+CAA+C;IAChD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Implements the same interface as FigmaDesktopConnector but talks to the
|
|
5
5
|
* Figma plugin over WebSocket (PluginBridgeServer). No CDP / debug port needed.
|
|
6
|
+
* Supports optional fileKey routing for multi-client scenarios.
|
|
6
7
|
*/
|
|
7
8
|
import type { PluginBridgeServer } from "./plugin-bridge-server.js";
|
|
8
9
|
export declare class PluginBridgeConnector {
|
|
9
10
|
private bridge;
|
|
10
|
-
|
|
11
|
+
private fileKey?;
|
|
12
|
+
constructor(bridge: PluginBridgeServer, fileKey?: string);
|
|
13
|
+
setFileKey(fileKey: string | undefined): void;
|
|
11
14
|
initialize(): Promise<void>;
|
|
12
15
|
getVariablesFromPluginUI(fileKey?: string): Promise<any>;
|
|
13
16
|
getComponentFromPluginUI(nodeId: string): Promise<any>;
|
|
@@ -77,6 +80,7 @@ export declare class PluginBridgeConnector {
|
|
|
77
80
|
}): Promise<any>;
|
|
78
81
|
setInstanceProperties(nodeId: string, properties: Record<string, unknown>): Promise<any>;
|
|
79
82
|
getDocumentStructure(depth?: number, verbosity?: string, opts?: {
|
|
83
|
+
excludeScreenshot?: boolean;
|
|
80
84
|
includeLayout?: boolean;
|
|
81
85
|
includeVisual?: boolean;
|
|
82
86
|
includeTypography?: boolean;
|
|
@@ -84,6 +88,7 @@ export declare class PluginBridgeConnector {
|
|
|
84
88
|
outputHint?: "react" | "tailwind";
|
|
85
89
|
}): Promise<any>;
|
|
86
90
|
getNodeContext(nodeId: string, depth?: number, verbosity?: string, opts?: {
|
|
91
|
+
excludeScreenshot?: boolean;
|
|
87
92
|
includeLayout?: boolean;
|
|
88
93
|
includeVisual?: boolean;
|
|
89
94
|
includeTypography?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-bridge-connector.d.ts","sourceRoot":"","sources":["../../src/core/plugin-bridge-connector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"plugin-bridge-connector.d.ts","sourceRoot":"","sources":["../../src/core/plugin-bridge-connector.ts"],"names":[],"mappings":"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"}
|