@figma/code-connect 1.4.4 → 1.4.7

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.
@@ -8,30 +8,46 @@ const helpers_1 = require("./helpers");
8
8
  const validation_1 = require("./validation");
9
9
  const fetch_1 = require("../common/fetch");
10
10
  const COMPONENT_BROWSER_CONFLICT_REASON = 'Code Connect UI mapping already exists';
11
- const RETRY_DELAYS_MS = [5_000, 15_000, 30_000];
11
+ // 429 (rate limit): extended schedule, ignore Retry-After to keep waits predictable.
12
+ const RETRY_DELAYS_MS_429 = [5_000, 15_000, 30_000, 45_000, 60_000, 75_000];
13
+ // 5xx (server error): original shorter schedule, still honoring Retry-After if provided.
14
+ const RETRY_DELAYS_MS_5XX = [5_000, 15_000, 30_000];
12
15
  async function postWithRetry(apiUrl, batch, accessToken, useOAuth = false) {
13
- for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
16
+ let attempt429 = 0;
17
+ let attempt5xx = 0;
18
+ // eslint-disable-next-line no-constant-condition
19
+ while (true) {
14
20
  try {
15
21
  return await fetch_1.request.post(apiUrl, batch, { headers: (0, figma_rest_api_1.getHeaders)(accessToken, useOAuth) });
16
22
  }
17
23
  catch (err) {
18
- if ((0, fetch_1.isFetchError)(err) && (err.response.status === 429 || err.response.status >= 500)) {
19
- if (attempt === RETRY_DELAYS_MS.length) {
24
+ if (!(0, fetch_1.isFetchError)(err))
25
+ throw err;
26
+ const status = err.response.status;
27
+ if (status === 429) {
28
+ if (attempt429 === RETRY_DELAYS_MS_429.length)
29
+ throw err;
30
+ const delayMs = RETRY_DELAYS_MS_429[attempt429];
31
+ logging_1.logger.warn(`Received 429, retrying in ${delayMs / 1000}s (attempt ${attempt429 + 1}/${RETRY_DELAYS_MS_429.length})...`);
32
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
33
+ attempt429++;
34
+ }
35
+ else if (status >= 500) {
36
+ if (attempt5xx === RETRY_DELAYS_MS_5XX.length)
20
37
  throw err;
21
- }
22
38
  const retryAfterSec = err.response.headers.get('Retry-After');
23
39
  const delayMs = retryAfterSec
24
40
  ? parseInt(retryAfterSec, 10) * 1_000
25
- : RETRY_DELAYS_MS[attempt];
26
- logging_1.logger.warn(`Received ${err.response.status}, retrying in ${delayMs / 1000}s (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})...`);
41
+ : RETRY_DELAYS_MS_5XX[attempt5xx];
42
+ logging_1.logger.warn(`Received ${status}, retrying in ${delayMs / 1000}s (attempt ${attempt5xx + 1}/${RETRY_DELAYS_MS_5XX.length})...`);
27
43
  await new Promise((resolve) => setTimeout(resolve, delayMs));
44
+ attempt5xx++;
28
45
  }
29
46
  else {
30
47
  throw err;
31
48
  }
32
49
  }
33
50
  }
34
- throw new Error('Unreachable');
35
51
  }
36
52
  /**
37
53
  * Returns a string representation of the code connect JSON
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/connect/upload.ts"],"names":[],"mappings":"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","sourcesContent":["import { CodeConnectJSON } from '../connect/figma_connect'\nimport { logger, underline, highlight, warn } from '../common/logging'\nimport { getApiUrl, getHeaders } from './figma_rest_api'\nimport { exitWithFeedbackMessage } from './helpers'\nimport { parseFigmaNode } from './validation'\nimport { isFetchError, request } from '../common/fetch'\n\nconst COMPONENT_BROWSER_CONFLICT_REASON = 'Code Connect UI mapping already exists'\n\nconst RETRY_DELAYS_MS = [5_000, 15_000, 30_000]\n\nasync function postWithRetry<T>(\n apiUrl: string,\n batch: CodeConnectJSON[],\n accessToken: string,\n useOAuth = false,\n): Promise<{ data: T }> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n try {\n return await request.post<T>(apiUrl, batch, { headers: getHeaders(accessToken, useOAuth) })\n } catch (err) {\n if (isFetchError(err) && (err.response.status === 429 || err.response.status >= 500)) {\n if (attempt === RETRY_DELAYS_MS.length) {\n throw err\n }\n const retryAfterSec = err.response.headers.get('Retry-After')\n const delayMs = retryAfterSec\n ? parseInt(retryAfterSec, 10) * 1_000\n : RETRY_DELAYS_MS[attempt]\n logger.warn(\n `Received ${err.response.status}, retrying in ${delayMs / 1000}s (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})...`,\n )\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n } else {\n throw err\n }\n }\n }\n throw new Error('Unreachable')\n}\n\ninterface Args {\n accessToken: string\n useOAuth?: boolean\n docs: CodeConnectJSON[]\n batchSize?: number\n verbose: boolean\n apiUrl?: string\n force?: boolean\n}\n\ninterface UploadResponse {\n status: number\n error: boolean\n meta: {\n success: boolean\n published_count: number\n failed_count: number\n published_nodes: Array<{ figmaNode: string; label: string }>\n failed_nodes: Array<{ figmaNode: string; label: string; reason: string }>\n }\n}\n\n/**\n * Returns a string representation of the code connect JSON\n * @param doc - The code connect JSON\n * @returns A string representation of the code connect JSON\n */\nfunction codeConnectStr(doc: CodeConnectJSON): string {\n return `${highlight(doc.component ?? '')}${doc.variant ? `(${Object.entries(doc.variant).map(([key, value]) => `${key}=${value}`)})` : ''} ${underline(doc.figmaNode)}`\n}\n\n/**\n * Extracts the fileKey and nodeId from the Figma node URL and returns a key in the format of fileKey-nodeId\n * @param figmaNode - The Figma node URL\n * @returns The key in the format of fileKey-nodeId\n */\nfunction getKeyFromFigmaNode(figmaNode: string): string {\n const url = new URL(figmaNode)\n\n // Extract fileKey from path (after /file/ or /design/)\n const pathMatch = url.pathname.match(/\\/(file|design)\\/([A-Za-z0-9]+)/)\n const fileKey = pathMatch ? pathMatch[2] : ''\n\n // Extract nodeId from query parameter and convert format (1-24 -> 1:24)\n const nodeIdParam = url.searchParams.get('node-id') || ''\n const nodeId = nodeIdParam.replace(/-/g, ':')\n\n return `${fileKey}-${nodeId}`\n}\n\n/**\n * Creates a map from fileKey-nodeId to original docs for easy lookup\n */\nexport function createDocsMap(\n docs: CodeConnectJSON[],\n verbose: boolean,\n): Map<string, CodeConnectJSON[]> {\n const docsMap = new Map<string, CodeConnectJSON[]>()\n\n for (const doc of docs) {\n const parsedData = parseFigmaNode(verbose, doc)\n if (!parsedData) {\n continue\n }\n\n const mapKey = `${parsedData.fileKey}-${parsedData.nodeId}`\n if (!docsMap.has(mapKey)) {\n docsMap.set(mapKey, [])\n }\n\n docsMap.get(mapKey)?.push(doc)\n }\n\n return docsMap\n}\n\nexport async function upload({\n accessToken,\n useOAuth = false,\n docs,\n batchSize,\n verbose,\n apiUrl: apiUrlOverride,\n force,\n}: Args) {\n const apiUrl =\n getApiUrl(docs?.[0]?.figmaNode ?? '', apiUrlOverride) +\n '/code_connect' +\n (force ? '?force=true' : '')\n\n // Strip internal fields before uploading to Figma\n const cleanedDocs = docs.map((doc) => {\n const { _codeConnectFilePath, ...cleanDoc } = doc\n return cleanDoc as CodeConnectJSON\n })\n\n try {\n logger.info(`Uploading to Figma...`)\n\n // Create a map from fileKey-nodeId to original docs for detailed output\n const docsMap = createDocsMap(cleanedDocs, verbose)\n\n let allUploadedNodes = new Set<string>()\n let allFailedNodes = new Map<string, string>() // key -> failure reason\n\n if (batchSize) {\n if (typeof batchSize !== 'number') {\n logger.error('Batch size must be a number')\n exitWithFeedbackMessage(1)\n }\n\n // batch together based on fileKey + nodeId as all variants etc of the same node should be uploaded together\n // Otherwise, the server will overwrite the previous upload\n const groupedDocs = cleanedDocs.reduce(\n (acc, doc) => {\n const parsedData = parseFigmaNode(verbose, doc)\n\n if (!parsedData) {\n exitWithFeedbackMessage(1)\n }\n\n const { fileKey, nodeId } = parsedData\n const accKey = fileKey + ',' + nodeId\n if (!acc[accKey]) {\n acc[accKey] = []\n }\n acc[accKey].push(doc)\n return acc\n },\n {} as Record<string, CodeConnectJSON[]>,\n )\n\n const batchedDocs: CodeConnectJSON[][] = []\n const nodeKeys = Object.keys(groupedDocs)\n\n for (let i = 0; i < nodeKeys.length; i += batchSize) {\n const batch: CodeConnectJSON[] = []\n for (let j = i; j < i + batchSize && j < nodeKeys.length; j++) {\n const nodeKey = nodeKeys[j]\n batch.push(...groupedDocs[nodeKey])\n }\n batchedDocs.push(batch)\n }\n\n let currentBatch = 1\n const noOfBatches = batchedDocs.length\n for (const batch of batchedDocs) {\n process.stderr.write('\\x1b[2K\\x1b[0G')\n process.stderr.write(`Uploading batch ${currentBatch}/${noOfBatches}`)\n\n var size = Buffer.byteLength(JSON.stringify(batch)) / (1024 * 1024)\n\n // Server has a limit of 5mb\n if (size > 5) {\n logger.error(\n `Failed to upload to Figma: The request is too large (${size.toFixed(2)}mb).`,\n )\n logger.error(\n 'Please try reducing the size of uploads by splitting them into smaller requests by running again and decreasing the --batch-size parameter.',\n )\n exitWithFeedbackMessage(1)\n }\n\n logger.debug(`Uploading ${size.toFixed(2)}mb to Figma`)\n\n const response = await postWithRetry<UploadResponse>(apiUrl, batch, accessToken, useOAuth)\n\n const data = response.data\n\n if (data.meta?.published_nodes) {\n data.meta.published_nodes.forEach((node) =>\n allUploadedNodes.add(getKeyFromFigmaNode(node.figmaNode)),\n )\n }\n if (data.meta?.failed_nodes) {\n data.meta.failed_nodes.forEach((node) =>\n allFailedNodes.set(getKeyFromFigmaNode(node.figmaNode), node.reason),\n )\n }\n\n currentBatch++\n }\n process.stderr.write(`\\n`)\n } else {\n var size = Buffer.byteLength(JSON.stringify(cleanedDocs)) / (1024 * 1024)\n\n // Server has a limit of 5mb\n if (size > 5) {\n logger.error(`Failed to upload to Figma: The request is too large (${size.toFixed(2)}mb).`)\n logger.error(\n 'Please try reducing the size of uploads by splitting them into smaller requests by running again with the --batch-size parameter. You can do also this by running on different subdirectories using the --dir flag or by iteratively adjusting the includes field in the configuration.',\n )\n exitWithFeedbackMessage(1)\n }\n\n logger.debug(`Uploading ${size.toFixed(2)}mb to Figma`)\n logger.info(`Uploading to ${apiUrl}`)\n\n const response = await postWithRetry<UploadResponse>(\n apiUrl,\n cleanedDocs,\n accessToken,\n useOAuth,\n )\n\n const data = response.data\n\n if (data.meta?.published_nodes) {\n data.meta.published_nodes.forEach((node) =>\n allUploadedNodes.add(getKeyFromFigmaNode(node.figmaNode)),\n )\n }\n if (data.meta?.failed_nodes) {\n data.meta.failed_nodes.forEach((node) =>\n allFailedNodes.set(getKeyFromFigmaNode(node.figmaNode), node.reason),\n )\n }\n }\n\n // Separate successful and failed uploads\n const successfulDocsByLabel: Record<string, CodeConnectJSON[]> = {}\n const failedDocsByLabel: Record<string, Array<{ doc: CodeConnectJSON; reason: string }>> = {}\n\n for (const [mapKey, nodeDocs] of docsMap.entries()) {\n for (const doc of nodeDocs) {\n const label = doc.label\n const docKey = getKeyFromFigmaNode(doc.figmaNode)\n const isUploaded = allUploadedNodes.has(docKey)\n const failureReason = allFailedNodes.get(docKey)\n\n if (isUploaded) {\n if (!successfulDocsByLabel[label]) {\n successfulDocsByLabel[label] = []\n }\n successfulDocsByLabel[label].push(doc)\n } else if (failureReason) {\n if (!failedDocsByLabel[label]) {\n failedDocsByLabel[label] = []\n }\n failedDocsByLabel[label].push({ doc, reason: failureReason })\n }\n }\n }\n\n for (const [label, docs] of Object.entries(successfulDocsByLabel)) {\n logger.info(\n `Successfully uploaded to Figma, for ${label}:\\n${docs.map((doc) => `-> ${codeConnectStr(doc)}`).join('\\n')}`,\n )\n }\n\n if (Object.keys(failedDocsByLabel).length > 0) {\n let hasComponentBrowserConflicts = false\n for (const [label, failedItems] of Object.entries(failedDocsByLabel)) {\n const conflicts = failedItems.filter((item) =>\n item.reason.includes(COMPONENT_BROWSER_CONFLICT_REASON),\n )\n const otherFailures = failedItems.filter(\n (item) => !item.reason.includes(COMPONENT_BROWSER_CONFLICT_REASON),\n )\n\n if (conflicts.length > 0) {\n hasComponentBrowserConflicts = true\n logger.warn(\n warn(\n `Warning: ${conflicts.length} node(s) already have UI-created Code Connect mappings in Figma for label \"${label}\":\\n${conflicts.map((item) => `-> ${codeConnectStr(item.doc)}`).join('\\n')}`,\n ),\n )\n }\n\n if (otherFailures.length > 0) {\n logger.error(\n `Failed to upload to Figma, for ${label}:\\n${otherFailures.map((item) => `-> ${codeConnectStr(item.doc)} (${item.reason})`).join('\\n')}`,\n )\n }\n }\n\n if (hasComponentBrowserConflicts && !force) {\n logger.warn(\n warn(\n `Re-run with --force to overwrite the existing UI-created mappings with your Code Connect files.`,\n ),\n )\n }\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n logger.error(\n `Failed to upload to Figma (${err.response.status}): ${err.response.status} ${err.data?.message}`,\n )\n } else {\n logger.error(`Failed to upload to Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err?.data))\n } else {\n logger.error(`Failed to upload to Figma: ${err}`)\n }\n exitWithFeedbackMessage(1)\n }\n}\n"]}
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/connect/upload.ts"],"names":[],"mappings":"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","sourcesContent":["import { CodeConnectJSON } from '../connect/figma_connect'\nimport { logger, underline, highlight, warn } from '../common/logging'\nimport { getApiUrl, getHeaders } from './figma_rest_api'\nimport { exitWithFeedbackMessage } from './helpers'\nimport { parseFigmaNode } from './validation'\nimport { isFetchError, request } from '../common/fetch'\n\nconst COMPONENT_BROWSER_CONFLICT_REASON = 'Code Connect UI mapping already exists'\n\n// 429 (rate limit): extended schedule, ignore Retry-After to keep waits predictable.\nconst RETRY_DELAYS_MS_429 = [5_000, 15_000, 30_000, 45_000, 60_000, 75_000]\n// 5xx (server error): original shorter schedule, still honoring Retry-After if provided.\nconst RETRY_DELAYS_MS_5XX = [5_000, 15_000, 30_000]\n\nasync function postWithRetry<T>(\n apiUrl: string,\n batch: CodeConnectJSON[],\n accessToken: string,\n useOAuth = false,\n): Promise<{ data: T }> {\n let attempt429 = 0\n let attempt5xx = 0\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await request.post<T>(apiUrl, batch, { headers: getHeaders(accessToken, useOAuth) })\n } catch (err) {\n if (!isFetchError(err)) throw err\n\n const status = err.response.status\n\n if (status === 429) {\n if (attempt429 === RETRY_DELAYS_MS_429.length) throw err\n const delayMs = RETRY_DELAYS_MS_429[attempt429]\n logger.warn(\n `Received 429, retrying in ${delayMs / 1000}s (attempt ${attempt429 + 1}/${RETRY_DELAYS_MS_429.length})...`,\n )\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n attempt429++\n } else if (status >= 500) {\n if (attempt5xx === RETRY_DELAYS_MS_5XX.length) throw err\n const retryAfterSec = err.response.headers.get('Retry-After')\n const delayMs = retryAfterSec\n ? parseInt(retryAfterSec, 10) * 1_000\n : RETRY_DELAYS_MS_5XX[attempt5xx]\n logger.warn(\n `Received ${status}, retrying in ${delayMs / 1000}s (attempt ${attempt5xx + 1}/${RETRY_DELAYS_MS_5XX.length})...`,\n )\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n attempt5xx++\n } else {\n throw err\n }\n }\n }\n}\n\ninterface Args {\n accessToken: string\n useOAuth?: boolean\n docs: CodeConnectJSON[]\n batchSize?: number\n verbose: boolean\n apiUrl?: string\n force?: boolean\n}\n\ninterface UploadResponse {\n status: number\n error: boolean\n meta: {\n success: boolean\n published_count: number\n failed_count: number\n published_nodes: Array<{ figmaNode: string; label: string }>\n failed_nodes: Array<{ figmaNode: string; label: string; reason: string }>\n }\n}\n\n/**\n * Returns a string representation of the code connect JSON\n * @param doc - The code connect JSON\n * @returns A string representation of the code connect JSON\n */\nfunction codeConnectStr(doc: CodeConnectJSON): string {\n return `${highlight(doc.component ?? '')}${doc.variant ? `(${Object.entries(doc.variant).map(([key, value]) => `${key}=${value}`)})` : ''} ${underline(doc.figmaNode)}`\n}\n\n/**\n * Extracts the fileKey and nodeId from the Figma node URL and returns a key in the format of fileKey-nodeId\n * @param figmaNode - The Figma node URL\n * @returns The key in the format of fileKey-nodeId\n */\nfunction getKeyFromFigmaNode(figmaNode: string): string {\n const url = new URL(figmaNode)\n\n // Extract fileKey from path (after /file/ or /design/)\n const pathMatch = url.pathname.match(/\\/(file|design)\\/([A-Za-z0-9]+)/)\n const fileKey = pathMatch ? pathMatch[2] : ''\n\n // Extract nodeId from query parameter and convert format (1-24 -> 1:24)\n const nodeIdParam = url.searchParams.get('node-id') || ''\n const nodeId = nodeIdParam.replace(/-/g, ':')\n\n return `${fileKey}-${nodeId}`\n}\n\n/**\n * Creates a map from fileKey-nodeId to original docs for easy lookup\n */\nexport function createDocsMap(\n docs: CodeConnectJSON[],\n verbose: boolean,\n): Map<string, CodeConnectJSON[]> {\n const docsMap = new Map<string, CodeConnectJSON[]>()\n\n for (const doc of docs) {\n const parsedData = parseFigmaNode(verbose, doc)\n if (!parsedData) {\n continue\n }\n\n const mapKey = `${parsedData.fileKey}-${parsedData.nodeId}`\n if (!docsMap.has(mapKey)) {\n docsMap.set(mapKey, [])\n }\n\n docsMap.get(mapKey)?.push(doc)\n }\n\n return docsMap\n}\n\nexport async function upload({\n accessToken,\n useOAuth = false,\n docs,\n batchSize,\n verbose,\n apiUrl: apiUrlOverride,\n force,\n}: Args) {\n const apiUrl =\n getApiUrl(docs?.[0]?.figmaNode ?? '', apiUrlOverride) +\n '/code_connect' +\n (force ? '?force=true' : '')\n\n // Strip internal fields before uploading to Figma\n const cleanedDocs = docs.map((doc) => {\n const { _codeConnectFilePath, ...cleanDoc } = doc\n return cleanDoc as CodeConnectJSON\n })\n\n try {\n logger.info(`Uploading to Figma...`)\n\n // Create a map from fileKey-nodeId to original docs for detailed output\n const docsMap = createDocsMap(cleanedDocs, verbose)\n\n let allUploadedNodes = new Set<string>()\n let allFailedNodes = new Map<string, string>() // key -> failure reason\n\n if (batchSize) {\n if (typeof batchSize !== 'number') {\n logger.error('Batch size must be a number')\n exitWithFeedbackMessage(1)\n }\n\n // batch together based on fileKey + nodeId as all variants etc of the same node should be uploaded together\n // Otherwise, the server will overwrite the previous upload\n const groupedDocs = cleanedDocs.reduce(\n (acc, doc) => {\n const parsedData = parseFigmaNode(verbose, doc)\n\n if (!parsedData) {\n exitWithFeedbackMessage(1)\n }\n\n const { fileKey, nodeId } = parsedData\n const accKey = fileKey + ',' + nodeId\n if (!acc[accKey]) {\n acc[accKey] = []\n }\n acc[accKey].push(doc)\n return acc\n },\n {} as Record<string, CodeConnectJSON[]>,\n )\n\n const batchedDocs: CodeConnectJSON[][] = []\n const nodeKeys = Object.keys(groupedDocs)\n\n for (let i = 0; i < nodeKeys.length; i += batchSize) {\n const batch: CodeConnectJSON[] = []\n for (let j = i; j < i + batchSize && j < nodeKeys.length; j++) {\n const nodeKey = nodeKeys[j]\n batch.push(...groupedDocs[nodeKey])\n }\n batchedDocs.push(batch)\n }\n\n let currentBatch = 1\n const noOfBatches = batchedDocs.length\n for (const batch of batchedDocs) {\n process.stderr.write('\\x1b[2K\\x1b[0G')\n process.stderr.write(`Uploading batch ${currentBatch}/${noOfBatches}`)\n\n var size = Buffer.byteLength(JSON.stringify(batch)) / (1024 * 1024)\n\n // Server has a limit of 5mb\n if (size > 5) {\n logger.error(\n `Failed to upload to Figma: The request is too large (${size.toFixed(2)}mb).`,\n )\n logger.error(\n 'Please try reducing the size of uploads by splitting them into smaller requests by running again and decreasing the --batch-size parameter.',\n )\n exitWithFeedbackMessage(1)\n }\n\n logger.debug(`Uploading ${size.toFixed(2)}mb to Figma`)\n\n const response = await postWithRetry<UploadResponse>(apiUrl, batch, accessToken, useOAuth)\n\n const data = response.data\n\n if (data.meta?.published_nodes) {\n data.meta.published_nodes.forEach((node) =>\n allUploadedNodes.add(getKeyFromFigmaNode(node.figmaNode)),\n )\n }\n if (data.meta?.failed_nodes) {\n data.meta.failed_nodes.forEach((node) =>\n allFailedNodes.set(getKeyFromFigmaNode(node.figmaNode), node.reason),\n )\n }\n\n currentBatch++\n }\n process.stderr.write(`\\n`)\n } else {\n var size = Buffer.byteLength(JSON.stringify(cleanedDocs)) / (1024 * 1024)\n\n // Server has a limit of 5mb\n if (size > 5) {\n logger.error(`Failed to upload to Figma: The request is too large (${size.toFixed(2)}mb).`)\n logger.error(\n 'Please try reducing the size of uploads by splitting them into smaller requests by running again with the --batch-size parameter. You can do also this by running on different subdirectories using the --dir flag or by iteratively adjusting the includes field in the configuration.',\n )\n exitWithFeedbackMessage(1)\n }\n\n logger.debug(`Uploading ${size.toFixed(2)}mb to Figma`)\n logger.info(`Uploading to ${apiUrl}`)\n\n const response = await postWithRetry<UploadResponse>(\n apiUrl,\n cleanedDocs,\n accessToken,\n useOAuth,\n )\n\n const data = response.data\n\n if (data.meta?.published_nodes) {\n data.meta.published_nodes.forEach((node) =>\n allUploadedNodes.add(getKeyFromFigmaNode(node.figmaNode)),\n )\n }\n if (data.meta?.failed_nodes) {\n data.meta.failed_nodes.forEach((node) =>\n allFailedNodes.set(getKeyFromFigmaNode(node.figmaNode), node.reason),\n )\n }\n }\n\n // Separate successful and failed uploads\n const successfulDocsByLabel: Record<string, CodeConnectJSON[]> = {}\n const failedDocsByLabel: Record<string, Array<{ doc: CodeConnectJSON; reason: string }>> = {}\n\n for (const [mapKey, nodeDocs] of docsMap.entries()) {\n for (const doc of nodeDocs) {\n const label = doc.label\n const docKey = getKeyFromFigmaNode(doc.figmaNode)\n const isUploaded = allUploadedNodes.has(docKey)\n const failureReason = allFailedNodes.get(docKey)\n\n if (isUploaded) {\n if (!successfulDocsByLabel[label]) {\n successfulDocsByLabel[label] = []\n }\n successfulDocsByLabel[label].push(doc)\n } else if (failureReason) {\n if (!failedDocsByLabel[label]) {\n failedDocsByLabel[label] = []\n }\n failedDocsByLabel[label].push({ doc, reason: failureReason })\n }\n }\n }\n\n for (const [label, docs] of Object.entries(successfulDocsByLabel)) {\n logger.info(\n `Successfully uploaded to Figma, for ${label}:\\n${docs.map((doc) => `-> ${codeConnectStr(doc)}`).join('\\n')}`,\n )\n }\n\n if (Object.keys(failedDocsByLabel).length > 0) {\n let hasComponentBrowserConflicts = false\n for (const [label, failedItems] of Object.entries(failedDocsByLabel)) {\n const conflicts = failedItems.filter((item) =>\n item.reason.includes(COMPONENT_BROWSER_CONFLICT_REASON),\n )\n const otherFailures = failedItems.filter(\n (item) => !item.reason.includes(COMPONENT_BROWSER_CONFLICT_REASON),\n )\n\n if (conflicts.length > 0) {\n hasComponentBrowserConflicts = true\n logger.warn(\n warn(\n `Warning: ${conflicts.length} node(s) already have UI-created Code Connect mappings in Figma for label \"${label}\":\\n${conflicts.map((item) => `-> ${codeConnectStr(item.doc)}`).join('\\n')}`,\n ),\n )\n }\n\n if (otherFailures.length > 0) {\n logger.error(\n `Failed to upload to Figma, for ${label}:\\n${otherFailures.map((item) => `-> ${codeConnectStr(item.doc)} (${item.reason})`).join('\\n')}`,\n )\n }\n }\n\n if (hasComponentBrowserConflicts && !force) {\n logger.warn(\n warn(\n `Re-run with --force to overwrite the existing UI-created mappings with your Code Connect files.`,\n ),\n )\n }\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n logger.error(\n `Failed to upload to Figma (${err.response.status}): ${err.response.status} ${err.data?.message}`,\n )\n } else {\n logger.error(`Failed to upload to Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err?.data))\n } else {\n logger.error(`Failed to upload to Figma: ${err}`)\n }\n exitWithFeedbackMessage(1)\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@figma/code-connect",
3
- "version": "1.4.4",
3
+ "version": "1.4.7",
4
4
  "description": "A tool for connecting your design system components in code with your design system in Figma",
5
5
  "keywords": [],
6
6
  "author": "Figma",
@@ -46,7 +46,7 @@
46
46
  "dev": "tsx src/cli.ts",
47
47
  "build": "rm -rf dist && tsc --noCheck",
48
48
  "build:web": "pnpm build",
49
- "build:webpack": "node scripts/resolve-dependencies.js && cross-env NODE_OPTIONS=\"--max-old-space-size=8196\" webpack --mode production",
49
+ "build:webpack": "cross-env NODE_OPTIONS=\"--max-old-space-size=8196\" webpack --mode production",
50
50
  "test": "npm run test:no-coverage -- --coverage",
51
51
  "test:no-coverage": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-deprecation --max-old-space-size=10240\" npx jest --logHeapUsage --workerIdleMemoryLimit=1.5G",
52
52
  "test:fast": "npm run test -- --testPathIgnorePatterns=template_rendering.test.ts --testPathIgnorePatterns=e2e_parse_command_swift.test.ts --testPathIgnorePatterns=e2e_wizard_swift.test.ts",
@@ -57,7 +57,7 @@
57
57
  "test:swift": "npm run test -- --runInBand --testPathPattern=e2e_parse_command_swift.test.ts --testPathPattern=e2e_wizard_swift.test.ts --testPathPattern=e2e_parse_command_swift_xcodeproj.test.ts",
58
58
  "test:non-mac": "npm run test -- --testPathIgnorePatterns=e2e_parse_command_swift.test.ts --testPathIgnorePatterns=e2e_wizard_swift.test.ts --testPathIgnorePatterns=e2e_parse_command_swift_xcodeproj.test.ts",
59
59
  "bundle": "npm run build && npm pack && mkdir -p bundle && mv figma-code-connect*.tgz bundle",
60
- "bundle:local": "cp package.json package.json.bak && node scripts/resolve-dependencies.js && npm run build && npm pack && mkdir -p bundle-local && mv figma-code-connect*.tgz bundle-local; mv package.json.bak package.json",
60
+ "bundle:local": "npm run build && mkdir -p bundle-local && pnpm pack --pack-destination bundle-local",
61
61
  "bundle:npm-readme:prepare": "mv README.md ../cli-README.md.bak && cp ../README.md . && npx tsx ../scripts/make_readme_links_absolute.ts",
62
62
  "bundle:npm-readme:restore": "mv ../cli-README.md.bak README.md",
63
63
  "bundle:npm": "npm run build && npm run bundle:npm-readme:prepare && npm pack && mkdir -p bundle-npm && mv figma-code-connect*.tgz bundle-npm; npm run bundle:npm-readme:restore",
@@ -76,6 +76,8 @@
76
76
  "@babel/parser": "7.28.5",
77
77
  "@babel/types": "7.28.5",
78
78
 
79
+
80
+
79
81
  "@storybook/csf-tools": "8.5.1",
80
82
  "@types/cross-spawn": "^6.0.6",
81
83
  "@types/jest": "^29.5.13",
@@ -89,15 +91,13 @@
89
91
  "jest": "^29.7.0",
90
92
  "patch-package": "^8.0.0",
91
93
  "pkg": "^5.8.1",
92
- "ts-jest": "^29.2.5",
94
+ "ts-jest": "^29.4.9",
93
95
  "ts-loader": "^9.5.1",
94
96
  "tsx": "4.21.0",
95
97
  "webpack": "5.91.0",
96
98
  "webpack-cli": "5.1.4"
97
99
  },
98
100
  "dependencies": {
99
-
100
-
101
101
  "boxen": "5.1.1",
102
102
 
103
103
 
@@ -118,7 +118,7 @@
118
118
  "prompts": "^2.4.2",
119
119
  "strip-ansi": "^6.0.0",
120
120
  "ts-morph": "^27.0.0",
121
- "typescript": "5.9.3",
121
+ "typescript": "6.0.3",
122
122
 
123
123
  "undici": "^7.19.1",
124
124
  "zod": "3.25.58",