Skip to content

Commit 2a907aa

Browse files
author
figma-bot
committed
Code Connect v1.3.7
1 parent 6c94935 commit 2a907aa

File tree

16 files changed

+634
-40
lines changed

16 files changed

+634
-40
lines changed

CHANGELOG.md

Lines changed: 81 additions & 2 deletions
Large diffs are not rendered by default.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let package = Package(
1515
.executable(name: "figma-swift", targets: ["CodeConnectCLI"]),
1616
],
1717
dependencies: [
18-
.package(url: "https://github.com/swiftlang/swift-syntax", "510.0.3"..<"602.0.0"),
18+
.package(url: "https://github.com/swiftlang/swift-syntax", "510.0.3"..<"603.0.0"),
1919
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
2020
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.55.3"),
2121
],

cli/npm_catalog.toml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,25 @@
9696
"@babel/template" = "7.27.2"
9797
"@babel/traverse" = "7.28.0"
9898
"@babel/types" = "7.28.2"
99-
"eslint" = "^9.23.0"
99+
"eslint" = "^9.36.0"
100100
"eslint-config-prettier" = "^9.1.0"
101101
"eslint-plugin-import" = "^2.31.0"
102102
"eslint-plugin-jest" = "^28.8.3"
103103
"eslint-plugin-react" = "^7.37.5"
104104
"eslint-plugin-react-hooks" = "^5.2.0"
105105
"eslint-plugin-simple-import-sort" = "^12.1.1"
106106
"eslint-plugin-unused-imports" = "^4.1.4"
107-
"@typescript-eslint/eslint-plugin" = "8.41.0"
108-
"@typescript-eslint/parser" = "8.41.0"
109-
"@typescript-eslint/rule-tester" = "8.41.0"
110-
"@typescript-eslint/scope-manager" = "8.41.0"
111-
"@typescript-eslint/types" = "8.41.0"
112-
"@typescript-eslint/typescript-estree" = "8.41.0"
113-
"@typescript-eslint/utils" = "8.41.0"
114-
"@typescript-eslint/visitor-keys" = "8.41.0"
115-
"typescript-eslint" = "8.41.0"
107+
"eslint-plugin-testing-library" = "^7.12.0"
108+
"@eslint/config-helpers" = "^0.4.0"
109+
"@typescript-eslint/eslint-plugin" = "8.45.0"
110+
"@typescript-eslint/parser" = "8.45.0"
111+
"@typescript-eslint/rule-tester" = "8.45.0"
112+
"@typescript-eslint/scope-manager" = "8.45.0"
113+
"@typescript-eslint/types" = "8.45.0"
114+
"@typescript-eslint/typescript-estree" = "8.45.0"
115+
"@typescript-eslint/utils" = "8.45.0"
116+
"@typescript-eslint/visitor-keys" = "8.45.0"
117+
"typescript-eslint" = "8.45.0"
116118
"@jest/core" = "^29.7.0"
117119
"@jest/create-cache-key-function" = "^29.7.0"
118120
"@jest/fake-timers" = "^29.7.0"
@@ -129,6 +131,7 @@
129131
"@types/lodash-es" = "4.17.12"
130132
"lodash" = "4.17.21"
131133
"lodash-es" = "4.17.21"
134+
"@oclif/core" = "3.27.0"
132135
"@storybook/addon-actions" = "8.5.1"
133136
"@storybook/addon-a11y" = "8.5.1"
134137
"@storybook/addon-essentials" = "8.5.1"
@@ -152,9 +155,9 @@
152155
"@storybook/test" = "8.5.1"
153156
"@storybook/theming" = "8.5.1"
154157
"storybook" = "8.5.1"
155-
"@stylexjs/stylex" = "0.15.3"
156-
"@stylexjs/babel-plugin" = "0.15.3"
157-
"@stylexjs/eslint-plugin" = "0.15.3"
158+
"@stylexjs/stylex" = "0.16.2"
159+
"@stylexjs/babel-plugin" = "0.16.2"
160+
"@stylexjs/eslint-plugin" = "0.16.2"
158161
"@stylextras/stylex-include" = "0.1.1"
159162
"@tailwindcss/oxide" = "4.1.3"
160163
"@tailwindcss/postcss" = "4.1.3"
@@ -165,7 +168,7 @@
165168
"@vitest/coverage-v8" = "3.2.4"
166169
"@vitest/runner" = "3.2.4"
167170
"@vitest/ui" = "3.2.4"
168-
"vite" = "6.3.5"
171+
"vite" = "6.3.6"
169172
"vitest" = "3.2.4"
170173
"webpack" = "5.91.0"
171174
"webpack-cli" = "5.1.4"
@@ -176,7 +179,10 @@
176179
"@types/react" = "18.0.26"
177180
"@types/react-dom" = "18.2.15"
178181
"@types/sinon" = "17.0.4"
182+
"aws-crt" = "1.21.3"
179183
"aws-sdk-client-mock" = "4.1.0"
184+
"axe-core" = "4.10.3"
185+
"@axe-core/playwright" = "4.10.1"
180186
"axios-retry" = "^4.5.0"
181187
"esbuild" = "0.25.0"
182188
"postcss" = "8.5.2"
@@ -189,9 +195,9 @@
189195
"react-dom" = "18.3.1"
190196
"sharp" = "0.33.5"
191197
"sinon" = "^17.0.1"
192-
"ts-morph" = "^26.0.0"
198+
"ts-morph" = "^27.0.0"
193199
"ts-node" = "^10.9.2"
194-
"typescript" = "5.9.2"
200+
"typescript" = "5.9.3"
195201
"yaml" = "2.8.0"
196202
"zod" = "3.25.58"
197203
"zod-to-json-schema" = "^3.23.5"

cli/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@figma/code-connect",
3-
"version": "1.3.6",
3+
"version": "1.3.7",
44
"description": "A tool for connecting your design system components in code with your design system in Figma",
55
"keywords": [],
66
"author": "Figma",
@@ -42,6 +42,8 @@
4242
"test": "npm run test:no-coverage -- --coverage",
4343
"test:no-coverage": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-deprecation --max-old-space-size=10240\" npx jest --logHeapUsage --workerIdleMemoryLimit=1.5G",
4444
"test:fast": "npm run test -- --testPathIgnorePatterns=template_rendering.test.ts --testPathIgnorePatterns=e2e_parse_command_swift.test.ts --testPathIgnorePatterns=e2e_wizard_swift.test.ts",
45+
"test:compose": "cd ../compose && ./gradlew test",
46+
"test:all": "npm run test && npm run test:compose",
4547
"test:ci": "npm run test:non-mac -- --runInBand",
4648
"test:wizard": "npm run test -- --runInBand --testPathPattern=e2e_wizard_react.test.ts --testPathPattern=e2e_wizard_swift.test.ts",
4749
"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",
@@ -106,8 +108,8 @@
106108
"prettier": "^2.8.8",
107109
"prompts": "^2.4.2",
108110
"strip-ansi": "^6.0.0",
109-
"ts-morph": "^26.0.0",
110-
"typescript": "5.9.2",
111+
"ts-morph": "^27.0.0",
112+
"typescript": "5.9.3",
111113
"undici": "^5.29.0",
112114
"zod": "3.25.58",
113115
"zod-validation-error": "^3.2.0"

cli/src/connect/delete_docs.ts

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,72 @@ export async function delete_docs({ accessToken, docs }: Args) {
1919
try {
2020
logger.info(`Unpublishing Code Connect files from Figma...`)
2121

22-
await request.delete(
22+
const response = await request.delete(
2323
apiUrl,
2424
{ nodes_to_delete: docs },
2525
{
2626
headers: getHeaders(accessToken),
2727
},
2828
)
2929

30-
logger.info(
31-
`Successfully deleted:\n${docs.map((doc) => `-> ${doc.figmaNode} (${doc.label})`).join('\n')}`,
32-
)
30+
interface DeleteResult {
31+
success: boolean
32+
deleted_count: number
33+
failed_count: number
34+
deleted_nodes: Array<{ figmaNode: string; label: string }>
35+
failed_nodes: Array<{ figmaNode: string; label: string; reason: string }>
36+
}
37+
38+
const responseData = response.data as {
39+
meta?: DeleteResult
40+
}
41+
42+
const result: DeleteResult = responseData.meta ?? (response.data as DeleteResult)
43+
44+
if (result.deleted_count > 0) {
45+
logger.info(
46+
`\nSuccessfully deleted ${
47+
result.deleted_count
48+
} Code Connect mapping(s):\n${result.deleted_nodes
49+
.map((doc) => `${doc.figmaNode} (${doc.label})`)
50+
.join('\n')}`,
51+
)
52+
}
53+
54+
if (result.failed_count > 0) {
55+
logger.error(
56+
`\nFailed to delete ${result.failed_count} Code Connect mapping(s):\n${result.failed_nodes
57+
.map((doc) => `✗ ${doc.figmaNode} (${doc.label}): ${doc.reason}`)
58+
.join('\n')}`,
59+
)
60+
exitWithFeedbackMessage(1)
61+
}
62+
63+
if (result.deleted_count === 0 && result.failed_count === 0) {
64+
logger.warn('No Code Connect mappings were found to delete.')
65+
}
3366
} catch (err) {
3467
if (isFetchError(err)) {
3568
if (err.response) {
36-
logger.error(
37-
`Failed to upload to Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`,
38-
)
69+
// Provide more specific error message based on status code
70+
if (err.response.status === 400) {
71+
const errorMsg = err.data?.err ?? err.data?.message ?? 'Bad request'
72+
if (errorMsg.includes('insufficient permissions')) {
73+
logger.error(`Insufficient permissions to unpublish Code Connect for this file.`)
74+
} else if (errorMsg.includes('Failed to parse')) {
75+
logger.error(`Invalid Figma URL format in the request.`)
76+
} else {
77+
logger.error(`Failed to unpublish from Figma: ${errorMsg}`)
78+
}
79+
} else {
80+
logger.error(
81+
`Failed to unpublish from Figma (${err.response.status}): ${
82+
err.data?.err ?? err.data?.message ?? 'Unknown error'
83+
}`,
84+
)
85+
}
3986
} else {
40-
logger.error(`Failed to upload to Figma: ${err.message}`)
87+
logger.error(`Failed to unpublish from Figma: ${err.message}`)
4188
}
4289
logger.debug(JSON.stringify(err.data))
4390
} else {

cli/src/react/__test__/parser.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,30 @@ describe('Parser (JS templates)', () => {
574574
])
575575
})
576576

577+
it('Handles path aliases with importPaths transformation', async () => {
578+
// This test covers the bug where path aliases with special characters like @ were not
579+
// being transformed because the regex didn't match them
580+
const result = await testParse('PathAliasImport.figma.tsx', [], {
581+
paths: {
582+
'@components/*': [path.join(__dirname, 'components', '*')],
583+
},
584+
importPaths: {
585+
'components/*': '@acme/package/*',
586+
},
587+
})
588+
expect(result).toMatchObject([
589+
{
590+
component: 'Button',
591+
source: expect.stringMatching(
592+
getFileInRepositoryRegex('cli/src/react/__test__/components/TestComponents.tsx'),
593+
),
594+
templateData: {
595+
imports: ["import { Button } from '@acme/package/TestComponents'"],
596+
},
597+
},
598+
])
599+
})
600+
577601
it('Can parse a varible reference for figmaNode', async () => {
578602
const result = await testParse('VariableRefFigmaNode.figma.tsx')
579603

cli/src/react/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ export async function parseReactDoc(
939939
if (config) {
940940
const mappedPath = mapImportPath(imp.file, config)
941941
if (mappedPath) {
942-
return imp.statement.replace(/['"]([\.\/a-zA-Z0-9_-]*)['"]/, `'${mappedPath}'`)
942+
return imp.statement.replace(/['"]([@\.\/a-zA-Z0-9_-]*)['"]/, `'${mappedPath}'`)
943943
}
944944
}
945945
return imp.statement

compose/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/.idea/assetWizardSettings.xml
1010
.DS_Store
1111
/build
12+
bin/
1213
/captures
1314
.externalNativeBuild
1415
.cxx

compose/annotations/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ plugins {
88
id("org.jetbrains.dokka") version "1.9.20"
99
}
1010

11+
java {
12+
toolchain {
13+
languageVersion.set(JavaLanguageVersion.of(17))
14+
}
15+
}
1116

1217
mavenPublishing {
1318
configure(

compose/plugin/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ plugins {
2626
id("com.gradle.plugin-publish") version "1.2.1"
2727
}
2828

29+
java {
30+
toolchain {
31+
languageVersion.set(JavaLanguageVersion.of(17))
32+
}
33+
}
34+
2935
repositories {
3036
mavenCentral()
3137
}

0 commit comments

Comments
 (0)