@figma/code-connect 1.4.2 → 1.4.4

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.
Files changed (79) hide show
  1. package/README.md +2 -22
  2. package/dist/commands/connect.d.ts +5 -2
  3. package/dist/commands/connect.d.ts.map +1 -1
  4. package/dist/commands/connect.js +93 -29
  5. package/dist/commands/connect.js.map +1 -1
  6. package/dist/commands/connect_template.d.ts +36 -0
  7. package/dist/commands/connect_template.d.ts.map +1 -0
  8. package/dist/commands/connect_template.js +324 -0
  9. package/dist/commands/connect_template.js.map +1 -0
  10. package/dist/commands/filter_project_info.d.ts +7 -0
  11. package/dist/commands/filter_project_info.d.ts.map +1 -0
  12. package/dist/commands/filter_project_info.js +32 -0
  13. package/dist/commands/filter_project_info.js.map +1 -0
  14. package/dist/commands/preview_utils.d.ts +49 -0
  15. package/dist/commands/preview_utils.d.ts.map +1 -0
  16. package/dist/commands/preview_utils.js +390 -0
  17. package/dist/commands/preview_utils.js.map +1 -0
  18. package/dist/connect/batch_templates.d.ts +11 -0
  19. package/dist/connect/batch_templates.d.ts.map +1 -0
  20. package/dist/connect/batch_templates.js +70 -0
  21. package/dist/connect/batch_templates.js.map +1 -0
  22. package/dist/connect/create.d.ts.map +1 -1
  23. package/dist/connect/create.js +13 -0
  24. package/dist/connect/create.js.map +1 -1
  25. package/dist/connect/create_template.d.ts +22 -0
  26. package/dist/connect/create_template.d.ts.map +1 -0
  27. package/dist/connect/create_template.js +195 -0
  28. package/dist/connect/create_template.js.map +1 -0
  29. package/dist/connect/delete_docs.d.ts +2 -1
  30. package/dist/connect/delete_docs.d.ts.map +1 -1
  31. package/dist/connect/delete_docs.js +2 -2
  32. package/dist/connect/delete_docs.js.map +1 -1
  33. package/dist/connect/figma_rest_api.d.ts +1 -5
  34. package/dist/connect/figma_rest_api.d.ts.map +1 -1
  35. package/dist/connect/figma_rest_api.js +9 -3
  36. package/dist/connect/figma_rest_api.js.map +1 -1
  37. package/dist/connect/intrinsics.d.ts +3 -3
  38. package/dist/connect/intrinsics.d.ts.map +1 -1
  39. package/dist/connect/intrinsics.js +21 -10
  40. package/dist/connect/intrinsics.js.map +1 -1
  41. package/dist/connect/migration_helpers.d.ts +10 -3
  42. package/dist/connect/migration_helpers.d.ts.map +1 -1
  43. package/dist/connect/migration_helpers.js +43 -22
  44. package/dist/connect/migration_helpers.js.map +1 -1
  45. package/dist/connect/parser_common.d.ts +3 -2
  46. package/dist/connect/parser_common.d.ts.map +1 -1
  47. package/dist/connect/parser_common.js +2 -2
  48. package/dist/connect/parser_common.js.map +1 -1
  49. package/dist/connect/project.d.ts +9 -7
  50. package/dist/connect/project.d.ts.map +1 -1
  51. package/dist/connect/project.js +39 -25
  52. package/dist/connect/project.js.map +1 -1
  53. package/dist/connect/raw_templates.d.ts +8 -1
  54. package/dist/connect/raw_templates.d.ts.map +1 -1
  55. package/dist/connect/raw_templates.js +20 -7
  56. package/dist/connect/raw_templates.js.map +1 -1
  57. package/dist/connect/upload.d.ts +3 -1
  58. package/dist/connect/upload.d.ts.map +1 -1
  59. package/dist/connect/upload.js +23 -8
  60. package/dist/connect/upload.js.map +1 -1
  61. package/dist/connect/validation.d.ts +2 -2
  62. package/dist/connect/validation.d.ts.map +1 -1
  63. package/dist/connect/validation.js +4 -4
  64. package/dist/connect/validation.js.map +1 -1
  65. package/dist/connect/wizard/helpers.js.map +1 -1
  66. package/dist/html/parser.d.ts +2 -2
  67. package/dist/html/parser.d.ts.map +1 -1
  68. package/dist/html/parser.js +7 -5
  69. package/dist/html/parser.js.map +1 -1
  70. package/dist/react/parser.d.ts +3 -3
  71. package/dist/react/parser.d.ts.map +1 -1
  72. package/dist/react/parser.js +9 -7
  73. package/dist/react/parser.js.map +1 -1
  74. package/dist/storybook/convert.d.ts +7 -1
  75. package/dist/storybook/convert.d.ts.map +1 -1
  76. package/dist/storybook/convert.js +11 -4
  77. package/dist/storybook/convert.js.map +1 -1
  78. package/{figma-module.d.ts → figma-types.d.ts} +13 -3
  79. package/package.json +8 -4
@@ -0,0 +1,22 @@
1
+ import { type FigmaConnectionComponent } from './parser_executable_types';
2
+ import { ProjectInfo } from './project';
3
+ import { BaseCommand } from '../commands/connect_template';
4
+ interface GenerateDocsArgs {
5
+ accessToken: string;
6
+ figmaNodeUrl: string;
7
+ outFile: string;
8
+ outDir: string;
9
+ projectInfo: ProjectInfo;
10
+ cmd: BaseCommand;
11
+ }
12
+ export declare function normalizeComponentName(name: string): string;
13
+ export declare function createCodeConnectFromUrl({ accessToken, figmaNodeUrl, outFile, outDir, projectInfo, cmd, }: GenerateDocsArgs): Promise<void>;
14
+ interface CreateTemplateArgs {
15
+ component: FigmaConnectionComponent;
16
+ normalizedName: string;
17
+ destinationDir: string;
18
+ destinationFile: string | undefined;
19
+ }
20
+ export declare function createTemplateCodeConnect(args: CreateTemplateArgs): string;
21
+ export {};
22
+ //# sourceMappingURL=create_template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_template.d.ts","sourceRoot":"","sources":["../../src/connect/create_template.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAA;AAWlC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAE1D,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,EAAE,WAAW,CAAA;CACjB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,UAQlD;AAED,wBAAsB,wBAAwB,CAAC,EAC7C,WAAW,EACX,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,GAAG,GACJ,EAAE,gBAAgB,iBAgFlB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,wBAAwB,CAAA;IACnC,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;CACpC;AA8ED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA8C1E"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.normalizeComponentName = normalizeComponentName;
7
+ exports.createCodeConnectFromUrl = createCodeConnectFromUrl;
8
+ exports.createTemplateCodeConnect = createTemplateCodeConnect;
9
+ const lodash_1 = require("lodash");
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const create_common_1 = require("./create_common");
13
+ const helpers_1 = require("./helpers");
14
+ const figma_rest_api_1 = require("./figma_rest_api");
15
+ const logging_1 = require("../common/logging");
16
+ const fetch_1 = require("../common/fetch");
17
+ function normalizeComponentName(name) {
18
+ // Convert the string to PascalCase and ensure first character is not a digit
19
+ return name
20
+ .replace(/[^a-zA-Z0-9]/g, ' ')
21
+ .split(' ')
22
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
23
+ .join('')
24
+ .replace(/^[0-9]/, '_$&');
25
+ }
26
+ async function createCodeConnectFromUrl({ accessToken, figmaNodeUrl, outFile, outDir, projectInfo, cmd, }) {
27
+ try {
28
+ const fileKey = (0, helpers_1.parseFileKey)(figmaNodeUrl);
29
+ const nodeIds = (0, helpers_1.parseNodeIds)([figmaNodeUrl]);
30
+ const apiUrl = (0, figma_rest_api_1.getApiUrl)(figmaNodeUrl ?? '', cmd.apiUrl || projectInfo.config.apiUrl) +
31
+ `/code_connect/${fileKey}/cli_data?ids=${nodeIds.join(',')}`;
32
+ if (nodeIds.length === 0) {
33
+ (0, logging_1.exitWithError)(`Invalid figma node URL: the provided url "${figmaNodeUrl}" does not contain a node-id`);
34
+ }
35
+ else if (nodeIds.length > 1) {
36
+ (0, logging_1.exitWithError)(`Invalid figma node URL: the provided url "${figmaNodeUrl}" contains more than one node-id`);
37
+ }
38
+ logging_1.logger.info('Fetching component information from Figma...');
39
+ const response = process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE
40
+ ? {
41
+ response: { status: 200 },
42
+ data: JSON.parse(fs_1.default.readFileSync(process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE, 'utf-8')),
43
+ }
44
+ : await fetch_1.request.get(apiUrl, {
45
+ headers: (0, figma_rest_api_1.getHeaders)(accessToken),
46
+ });
47
+ if (response.response.status === 200) {
48
+ logging_1.logger.info('Parsing response');
49
+ const component = (0, helpers_1.findComponentsInDocument)(response.data.document, nodeIds)[0];
50
+ if (component === undefined) {
51
+ (0, logging_1.exitWithError)('Could not find a component in the provided URL');
52
+ }
53
+ const normalizedName = normalizeComponentName(component.name);
54
+ const componentPayload = {
55
+ figmaNodeUrl,
56
+ id: component.id,
57
+ name: component.name,
58
+ normalizedName,
59
+ type: component.type,
60
+ componentPropertyDefinitions: component.componentPropertyDefinitions,
61
+ };
62
+ logging_1.logger.info('Generating Code Connect files...');
63
+ const filename = createTemplateCodeConnect({
64
+ component: componentPayload,
65
+ normalizedName,
66
+ destinationDir: outDir ?? process.env.INIT_CWD ?? process.cwd(),
67
+ destinationFile: outFile,
68
+ });
69
+ logging_1.logger.info('Code Connect file generated successfully:');
70
+ logging_1.logger.info(`${filename}`);
71
+ }
72
+ else {
73
+ logging_1.logger.error(`Failed to get node information from Figma with status: ${response.response.status}`);
74
+ logging_1.logger.debug('Failed to get node information from Figma with Body:', response.data);
75
+ }
76
+ }
77
+ catch (err) {
78
+ if ((0, fetch_1.isFetchError)(err)) {
79
+ if (err.response) {
80
+ logging_1.logger.error(`Failed to get node data from Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`);
81
+ }
82
+ else {
83
+ logging_1.logger.error(`Failed to get node data from Figma: ${err.message}`);
84
+ }
85
+ logging_1.logger.debug(JSON.stringify(err.data));
86
+ }
87
+ else {
88
+ logging_1.logger.error(`Failed to create: ${err}`);
89
+ }
90
+ (0, helpers_1.exitWithFeedbackMessage)(1);
91
+ }
92
+ }
93
+ function normalizePropName(name) {
94
+ return name.replace(/#[0-9:]*/g, '');
95
+ }
96
+ function normalizePropValue(name) {
97
+ return name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
98
+ }
99
+ function generateCodePropName(name) {
100
+ return (0, lodash_1.camelCase)(name.replace(/#[0-9:]+$/g, '').replace(/[^a-zA-Z0-9\s]/g, ''));
101
+ }
102
+ function isBooleanKind(propValue) {
103
+ const normalized = propValue.toLowerCase();
104
+ return (normalized === 'true' ||
105
+ normalized === 'false' ||
106
+ normalized === 'yes' ||
107
+ normalized === 'no' ||
108
+ normalized === 'on' ||
109
+ normalized === 'off');
110
+ }
111
+ function isValidIdentifier(name) {
112
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
113
+ }
114
+ function generatePropDeclaration(propName, propDef) {
115
+ const codePropName = generateCodePropName(propName);
116
+ const figmaPropName = normalizePropName(propName);
117
+ if (propDef.type === 'BOOLEAN') {
118
+ return `const ${codePropName} = figma.selectedInstance.getBoolean("${figmaPropName}")`;
119
+ }
120
+ if (propDef.type === 'TEXT') {
121
+ return `const ${codePropName} = figma.selectedInstance.getString("${figmaPropName}")`;
122
+ }
123
+ if (propDef.type === 'VARIANT') {
124
+ const isBooleanVariant = propDef.variantOptions?.length === 2 && propDef.variantOptions.every(isBooleanKind);
125
+ if (isBooleanVariant) {
126
+ return `const ${codePropName} = figma.selectedInstance.getBoolean("${figmaPropName}")`;
127
+ }
128
+ else {
129
+ const options = (propDef.variantOptions || [])
130
+ .map((v) => {
131
+ const key = isValidIdentifier(v) ? v : `"${v}"`;
132
+ return ` ${key}: "${normalizePropValue(v)}"`;
133
+ })
134
+ .join(',\n');
135
+ return `const ${codePropName} = figma.selectedInstance.getEnum("${figmaPropName}", {\n${options},\n})`;
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ function generateTemplateBody(component) {
141
+ const defs = component.componentPropertyDefinitions || {};
142
+ const declarations = [];
143
+ for (const [propName, propDef] of Object.entries(defs)) {
144
+ const decl = generatePropDeclaration(propName, propDef);
145
+ if (decl) {
146
+ declarations.push(decl);
147
+ }
148
+ }
149
+ return {
150
+ declarations: declarations.join('\n'),
151
+ };
152
+ }
153
+ function createTemplateCodeConnect(args) {
154
+ const { component, normalizedName, destinationDir, destinationFile } = args;
155
+ const filePath = (0, create_common_1.getOutFileName)({
156
+ outFile: destinationFile,
157
+ outDir: destinationDir,
158
+ sourceFilename: normalizedName,
159
+ extension: 'ts',
160
+ });
161
+ const { declarations } = generateTemplateBody(component);
162
+ const codeConnect = [
163
+ `// url=${component.figmaNodeUrl}`,
164
+ `import figma from "figma"`,
165
+ '',
166
+ `/**`,
167
+ ` * NEXT STEPS:`,
168
+ ` * - Replace the \`example\` with the actual code snippet you want to show`,
169
+ ` * (e.g. figma.code\`<Button label="\${propertyValue}" />\`)`,
170
+ ` * - Update the \`imports\` array with any lines of code that should be displayed`,
171
+ ` * at the top (e.g. imports: ['import { Button } from "./Button"'])`,
172
+ ` */`,
173
+ '',
174
+ declarations || null,
175
+ declarations ? '' : null,
176
+ `export default {`,
177
+ ` example: figma.code\`\`,`,
178
+ ` imports: [],`,
179
+ ` id: "${normalizedName}",`,
180
+ ` metadata: {`,
181
+ ` nestable: true,`,
182
+ ` },`,
183
+ `}`,
184
+ '',
185
+ ]
186
+ .filter((line) => line !== null)
187
+ .join('\n');
188
+ if (fs_1.default.existsSync(filePath)) {
189
+ (0, logging_1.exitWithError)(`File ${filePath} already exists, skipping creation`);
190
+ }
191
+ fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
192
+ fs_1.default.writeFileSync(filePath, codeConnect);
193
+ return filePath;
194
+ }
195
+ //# sourceMappingURL=create_template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_template.js","sourceRoot":"","sources":["../../src/connect/create_template.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase } from 'lodash'\nimport fs from 'fs'\nimport {\n type ComponentPropertyDefinition,\n type FigmaConnectionComponent,\n} from './parser_executable_types'\nimport path from 'path'\nimport { getOutFileName } from './create_common'\nimport {\n exitWithFeedbackMessage,\n findComponentsInDocument,\n parseFileKey,\n parseNodeIds,\n} from './helpers'\nimport { FigmaRestApi, getApiUrl, getHeaders } from './figma_rest_api'\nimport { exitWithError, logger } from '../common/logging'\nimport { ProjectInfo } from './project'\nimport { isFetchError, request } from '../common/fetch'\nimport { BaseCommand } from '../commands/connect_template'\n\ninterface GenerateDocsArgs {\n accessToken: string\n figmaNodeUrl: string\n outFile: string\n outDir: string\n projectInfo: ProjectInfo\n cmd: BaseCommand\n}\n\nexport function normalizeComponentName(name: string) {\n // Convert the string to PascalCase and ensure first character is not a digit\n return name\n .replace(/[^a-zA-Z0-9]/g, ' ')\n .split(' ')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('')\n .replace(/^[0-9]/, '_$&')\n}\n\nexport async function createCodeConnectFromUrl({\n accessToken,\n figmaNodeUrl,\n outFile,\n outDir,\n projectInfo,\n cmd,\n}: GenerateDocsArgs) {\n try {\n const fileKey = parseFileKey(figmaNodeUrl)\n const nodeIds = parseNodeIds([figmaNodeUrl])\n\n const apiUrl =\n getApiUrl(figmaNodeUrl ?? '', cmd.apiUrl || projectInfo.config.apiUrl) +\n `/code_connect/${fileKey}/cli_data?ids=${nodeIds.join(',')}`\n\n if (nodeIds.length === 0) {\n exitWithError(\n `Invalid figma node URL: the provided url \"${figmaNodeUrl}\" does not contain a node-id`,\n )\n } else if (nodeIds.length > 1) {\n exitWithError(\n `Invalid figma node URL: the provided url \"${figmaNodeUrl}\" contains more than one node-id`,\n )\n }\n\n logger.info('Fetching component information from Figma...')\n const response = process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE\n ? {\n response: { status: 200 },\n data: JSON.parse(\n fs.readFileSync(process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE, 'utf-8'),\n ) as { document: FigmaRestApi.Node },\n }\n : await request.get<{ document: FigmaRestApi.Node }>(apiUrl, {\n headers: getHeaders(accessToken),\n })\n\n if (response.response.status === 200) {\n logger.info('Parsing response')\n const component = findComponentsInDocument(response.data.document, nodeIds)[0]\n if (component === undefined) {\n exitWithError('Could not find a component in the provided URL')\n }\n const normalizedName = normalizeComponentName(component.name)\n\n const componentPayload = {\n figmaNodeUrl,\n id: component.id,\n name: component.name,\n normalizedName,\n type: component.type,\n componentPropertyDefinitions: component.componentPropertyDefinitions,\n }\n\n logger.info('Generating Code Connect files...')\n\n const filename = createTemplateCodeConnect({\n component: componentPayload,\n normalizedName,\n destinationDir: outDir ?? process.env.INIT_CWD ?? process.cwd(),\n destinationFile: outFile,\n })\n\n logger.info('Code Connect file generated successfully:')\n logger.info(`${filename}`)\n } else {\n logger.error(\n `Failed to get node information from Figma with status: ${response.response.status}`,\n )\n logger.debug('Failed to get node information from Figma with Body:', response.data)\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n logger.error(\n `Failed to get node data from Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`,\n )\n } else {\n logger.error(`Failed to get node data from Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err.data))\n } else {\n logger.error(`Failed to create: ${err}`)\n }\n exitWithFeedbackMessage(1)\n }\n}\n\ninterface CreateTemplateArgs {\n component: FigmaConnectionComponent\n normalizedName: string\n destinationDir: string\n destinationFile: string | undefined\n}\n\nfunction normalizePropName(name: string) {\n return name.replace(/#[0-9:]*/g, '')\n}\n\nfunction normalizePropValue(name: string) {\n return name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase()\n}\n\nfunction generateCodePropName(name: string) {\n return camelCase(name.replace(/#[0-9:]+$/g, '').replace(/[^a-zA-Z0-9\\s]/g, ''))\n}\n\nfunction isBooleanKind(propValue: string) {\n const normalized = propValue.toLowerCase()\n return (\n normalized === 'true' ||\n normalized === 'false' ||\n normalized === 'yes' ||\n normalized === 'no' ||\n normalized === 'on' ||\n normalized === 'off'\n )\n}\n\nfunction isValidIdentifier(name: string): boolean {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n\nfunction generatePropDeclaration(\n propName: string,\n propDef: ComponentPropertyDefinition,\n): string | null {\n const codePropName = generateCodePropName(propName)\n const figmaPropName = normalizePropName(propName)\n\n if (propDef.type === 'BOOLEAN') {\n return `const ${codePropName} = figma.selectedInstance.getBoolean(\"${figmaPropName}\")`\n }\n if (propDef.type === 'TEXT') {\n return `const ${codePropName} = figma.selectedInstance.getString(\"${figmaPropName}\")`\n }\n if (propDef.type === 'VARIANT') {\n const isBooleanVariant =\n propDef.variantOptions?.length === 2 && propDef.variantOptions.every(isBooleanKind)\n if (isBooleanVariant) {\n return `const ${codePropName} = figma.selectedInstance.getBoolean(\"${figmaPropName}\")`\n } else {\n const options = (propDef.variantOptions || [])\n .map((v) => {\n const key = isValidIdentifier(v) ? v : `\"${v}\"`\n return ` ${key}: \"${normalizePropValue(v)}\"`\n })\n .join(',\\n')\n return `const ${codePropName} = figma.selectedInstance.getEnum(\"${figmaPropName}\", {\\n${options},\\n})`\n }\n }\n return null\n}\n\nfunction generateTemplateBody(component: FigmaConnectionComponent) {\n const defs = component.componentPropertyDefinitions || {}\n\n const declarations: string[] = []\n\n for (const [propName, propDef] of Object.entries(defs)) {\n const decl = generatePropDeclaration(propName, propDef)\n if (decl) {\n declarations.push(decl)\n }\n }\n\n return {\n declarations: declarations.join('\\n'),\n }\n}\n\nexport function createTemplateCodeConnect(args: CreateTemplateArgs): string {\n const { component, normalizedName, destinationDir, destinationFile } = args\n\n const filePath = getOutFileName({\n outFile: destinationFile,\n outDir: destinationDir,\n sourceFilename: normalizedName,\n extension: 'ts',\n })\n\n const { declarations } = generateTemplateBody(component)\n\n const codeConnect = [\n `// url=${component.figmaNodeUrl}`,\n `import figma from \"figma\"`,\n '',\n `/**`,\n ` * NEXT STEPS:`,\n ` * - Replace the \\`example\\` with the actual code snippet you want to show`,\n ` * (e.g. figma.code\\`<Button label=\"\\${propertyValue}\" />\\`)`,\n ` * - Update the \\`imports\\` array with any lines of code that should be displayed`,\n ` * at the top (e.g. imports: ['import { Button } from \"./Button\"'])`,\n ` */`,\n '',\n declarations || null,\n declarations ? '' : null,\n `export default {`,\n ` example: figma.code\\`\\`,`,\n ` imports: [],`,\n ` id: \"${normalizedName}\",`,\n ` metadata: {`,\n ` nestable: true,`,\n ` },`,\n `}`,\n '',\n ]\n .filter((line) => line !== null)\n .join('\\n')\n\n if (fs.existsSync(filePath)) {\n exitWithError(`File ${filePath} already exists, skipping creation`)\n }\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, codeConnect)\n\n return filePath\n}\n"]}
@@ -4,9 +4,10 @@ interface NodesToDeleteInfo {
4
4
  }
5
5
  interface Args {
6
6
  accessToken: string;
7
+ useOAuth?: boolean;
7
8
  docs: NodesToDeleteInfo[];
8
9
  apiUrl?: string;
9
10
  }
10
- export declare function delete_docs({ accessToken, docs, apiUrl: apiUrlOverride }: Args): Promise<void>;
11
+ export declare function delete_docs({ accessToken, useOAuth, docs, apiUrl: apiUrlOverride, }: Args): Promise<void>;
11
12
  export {};
12
13
  //# sourceMappingURL=delete_docs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delete_docs.d.ts","sourceRoot":"","sources":["../../src/connect/delete_docs.ts"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,IAAI;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,iBAAiB,EAAE,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAsB,WAAW,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,IAAI,iBA+EpF"}
1
+ {"version":3,"file":"delete_docs.d.ts","sourceRoot":"","sources":["../../src/connect/delete_docs.ts"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,IAAI;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,iBAAiB,EAAE,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAsB,WAAW,CAAC,EAChC,WAAW,EACX,QAAgB,EAChB,IAAI,EACJ,MAAM,EAAE,cAAc,GACvB,EAAE,IAAI,iBA+EN"}
@@ -5,12 +5,12 @@ const fetch_1 = require("../common/fetch");
5
5
  const logging_1 = require("../common/logging");
6
6
  const figma_rest_api_1 = require("./figma_rest_api");
7
7
  const helpers_1 = require("./helpers");
8
- async function delete_docs({ accessToken, docs, apiUrl: apiUrlOverride }) {
8
+ async function delete_docs({ accessToken, useOAuth = false, docs, apiUrl: apiUrlOverride, }) {
9
9
  const apiUrl = (0, figma_rest_api_1.getApiUrl)(docs?.[0]?.figmaNode ?? '', apiUrlOverride) + '/code_connect';
10
10
  try {
11
11
  logging_1.logger.info(`Unpublishing Code Connect files from Figma...`);
12
12
  const response = await fetch_1.request.delete(apiUrl, { nodes_to_delete: docs }, {
13
- headers: (0, figma_rest_api_1.getHeaders)(accessToken),
13
+ headers: (0, figma_rest_api_1.getHeaders)(accessToken, useOAuth),
14
14
  });
15
15
  const responseData = response.data;
16
16
  const result = responseData.meta ?? response.data;
@@ -1 +1 @@
1
- {"version":3,"file":"delete_docs.js","sourceRoot":"","sources":["../../src/connect/delete_docs.ts"],"names":[],"mappings":"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","sourcesContent":["import { isFetchError, request } from '../common/fetch'\nimport { logger } from '../common/logging'\nimport { getApiUrl, getHeaders } from './figma_rest_api'\nimport { exitWithFeedbackMessage } from './helpers'\n\ninterface NodesToDeleteInfo {\n figmaNode: string\n label: string\n}\n\ninterface Args {\n accessToken: string\n docs: NodesToDeleteInfo[]\n apiUrl?: string\n}\n\nexport async function delete_docs({ accessToken, docs, apiUrl: apiUrlOverride }: Args) {\n const apiUrl = getApiUrl(docs?.[0]?.figmaNode ?? '', apiUrlOverride) + '/code_connect'\n\n try {\n logger.info(`Unpublishing Code Connect files from Figma...`)\n\n const response = await request.delete(\n apiUrl,\n { nodes_to_delete: docs },\n {\n headers: getHeaders(accessToken),\n },\n )\n\n interface DeleteResult {\n success: boolean\n deleted_count: number\n failed_count: number\n deleted_nodes: Array<{ figmaNode: string; label: string }>\n failed_nodes: Array<{ figmaNode: string; label: string; reason: string }>\n }\n\n const responseData = response.data as {\n meta?: DeleteResult\n }\n\n const result: DeleteResult = responseData.meta ?? (response.data as DeleteResult)\n\n if (result.deleted_count > 0) {\n logger.info(\n `\\nSuccessfully deleted ${\n result.deleted_count\n } Code Connect mapping(s):\\n${result.deleted_nodes\n .map((doc) => `${doc.figmaNode} (${doc.label})`)\n .join('\\n')}`,\n )\n }\n\n if (result.failed_count > 0) {\n logger.error(\n `\\nFailed to delete ${result.failed_count} Code Connect mapping(s):\\n${result.failed_nodes\n .map((doc) => `✗ ${doc.figmaNode} (${doc.label}): ${doc.reason}`)\n .join('\\n')}`,\n )\n exitWithFeedbackMessage(1)\n }\n\n if (result.deleted_count === 0 && result.failed_count === 0) {\n logger.warn('No Code Connect mappings were found to delete.')\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n // Provide more specific error message based on status code\n if (err.response.status === 400) {\n const errorMsg = err.data?.err ?? err.data?.message ?? 'Bad request'\n if (errorMsg.includes('insufficient permissions')) {\n logger.error(`Insufficient permissions to unpublish Code Connect for this file.`)\n } else if (errorMsg.includes('Failed to parse')) {\n logger.error(`Invalid Figma URL format in the request.`)\n } else {\n logger.error(`Failed to unpublish from Figma: ${errorMsg}`)\n }\n } else {\n logger.error(\n `Failed to unpublish from Figma (${err.response.status}): ${\n err.data?.err ?? err.data?.message ?? 'Unknown error'\n }`,\n )\n }\n } else {\n logger.error(`Failed to unpublish from Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err.data))\n } else {\n logger.error(`Failed to delete docs: ${err}`)\n }\n exitWithFeedbackMessage(1)\n }\n}\n"]}
1
+ {"version":3,"file":"delete_docs.js","sourceRoot":"","sources":["../../src/connect/delete_docs.ts"],"names":[],"mappings":"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","sourcesContent":["import { isFetchError, request } from '../common/fetch'\nimport { logger } from '../common/logging'\nimport { getApiUrl, getHeaders } from './figma_rest_api'\nimport { exitWithFeedbackMessage } from './helpers'\n\ninterface NodesToDeleteInfo {\n figmaNode: string\n label: string\n}\n\ninterface Args {\n accessToken: string\n useOAuth?: boolean\n docs: NodesToDeleteInfo[]\n apiUrl?: string\n}\n\nexport async function delete_docs({\n accessToken,\n useOAuth = false,\n docs,\n apiUrl: apiUrlOverride,\n}: Args) {\n const apiUrl = getApiUrl(docs?.[0]?.figmaNode ?? '', apiUrlOverride) + '/code_connect'\n\n try {\n logger.info(`Unpublishing Code Connect files from Figma...`)\n\n const response = await request.delete(\n apiUrl,\n { nodes_to_delete: docs },\n {\n headers: getHeaders(accessToken, useOAuth),\n },\n )\n\n interface DeleteResult {\n success: boolean\n deleted_count: number\n failed_count: number\n deleted_nodes: Array<{ figmaNode: string; label: string }>\n failed_nodes: Array<{ figmaNode: string; label: string; reason: string }>\n }\n\n const responseData = response.data as {\n meta?: DeleteResult\n }\n\n const result: DeleteResult = responseData.meta ?? (response.data as DeleteResult)\n\n if (result.deleted_count > 0) {\n logger.info(\n `\\nSuccessfully deleted ${\n result.deleted_count\n } Code Connect mapping(s):\\n${result.deleted_nodes\n .map((doc) => `${doc.figmaNode} (${doc.label})`)\n .join('\\n')}`,\n )\n }\n\n if (result.failed_count > 0) {\n logger.error(\n `\\nFailed to delete ${result.failed_count} Code Connect mapping(s):\\n${result.failed_nodes\n .map((doc) => `✗ ${doc.figmaNode} (${doc.label}): ${doc.reason}`)\n .join('\\n')}`,\n )\n exitWithFeedbackMessage(1)\n }\n\n if (result.deleted_count === 0 && result.failed_count === 0) {\n logger.warn('No Code Connect mappings were found to delete.')\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n // Provide more specific error message based on status code\n if (err.response.status === 400) {\n const errorMsg = err.data?.err ?? err.data?.message ?? 'Bad request'\n if (errorMsg.includes('insufficient permissions')) {\n logger.error(`Insufficient permissions to unpublish Code Connect for this file.`)\n } else if (errorMsg.includes('Failed to parse')) {\n logger.error(`Invalid Figma URL format in the request.`)\n } else {\n logger.error(`Failed to unpublish from Figma: ${errorMsg}`)\n }\n } else {\n logger.error(\n `Failed to unpublish from Figma (${err.response.status}): ${\n err.data?.err ?? err.data?.message ?? 'Unknown error'\n }`,\n )\n }\n } else {\n logger.error(`Failed to unpublish from Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err.data))\n } else {\n logger.error(`Failed to delete docs: ${err}`)\n }\n exitWithFeedbackMessage(1)\n }\n}\n"]}
@@ -1,9 +1,5 @@
1
1
  export declare function getApiUrl(figmaNode: string, apiUrlOverride?: string): string;
2
- export declare function getHeaders(accessToken: string): {
3
- 'X-Figma-Token': string;
4
- 'Content-Type': string;
5
- 'User-Agent': string;
6
- };
2
+ export declare function getHeaders(token: string, useOAuth?: boolean): Record<string, string>;
7
3
  export declare namespace FigmaRestApi {
8
4
  enum ComponentPropertyType {
9
5
  Boolean = "BOOLEAN",
@@ -1 +1 @@
1
- {"version":3,"file":"figma_rest_api.d.ts","sourceRoot":"","sources":["../../src/connect/figma_rest_api.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,UAMnE;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM;;;;EAM7C;AAGD,yBAAiB,YAAY,CAAC;IAC5B,KAAY,qBAAqB;QAC/B,OAAO,YAAY;QACnB,YAAY,kBAAkB;QAC9B,IAAI,SAAS;QACb,OAAO,YAAY;KACpB;IAED,UAAiB,2BAA2B;QAC1C,YAAY,EAAE,OAAO,GAAG,MAAM,CAAA;QAC9B,IAAI,EAAE,qBAAqB,CAAA;QAC3B;;WAEG;QACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;QACzB;;WAEG;QACH,eAAe,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAClD;IAED,UAAiB,IAAI;QAEnB,IAAI,EAAE,WAAW,GAAG,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAA;QACxD,IAAI,EAAE,MAAM,CAAA;QACZ,EAAE,EAAE,MAAM,CAAA;QACV,QAAQ,EAAE,IAAI,EAAE,CAAA;KACjB;IAED,UAAiB,gBAAiB,SAAQ,IAAI;QAC5C,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;KACjB;IAED,UAAiB,SAAU,SAAQ,gBAAgB;QACjD,IAAI,EAAE,WAAW,GAAG,eAAe,CAAA;QACnC,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAA;KAC1E;CACF;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAgC9F"}
1
+ {"version":3,"file":"figma_rest_api.d.ts","sourceRoot":"","sources":["../../src/connect/figma_rest_api.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,UAMnE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWlF;AAGD,yBAAiB,YAAY,CAAC;IAC5B,KAAY,qBAAqB;QAC/B,OAAO,YAAY;QACnB,YAAY,kBAAkB;QAC9B,IAAI,SAAS;QACb,OAAO,YAAY;KACpB;IAED,UAAiB,2BAA2B;QAC1C,YAAY,EAAE,OAAO,GAAG,MAAM,CAAA;QAC9B,IAAI,EAAE,qBAAqB,CAAA;QAC3B;;WAEG;QACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;QACzB;;WAEG;QACH,eAAe,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAClD;IAED,UAAiB,IAAI;QAEnB,IAAI,EAAE,WAAW,GAAG,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAA;QACxD,IAAI,EAAE,MAAM,CAAA;QACZ,EAAE,EAAE,MAAM,CAAA;QACV,QAAQ,EAAE,IAAI,EAAE,CAAA;KACjB;IAED,UAAiB,gBAAiB,SAAQ,IAAI;QAC5C,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;KACjB;IAED,UAAiB,SAAU,SAAQ,gBAAgB;QACjD,IAAI,EAAE,WAAW,GAAG,eAAe,CAAA;QACnC,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAA;KAC1E;CACF;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAgC9F"}
@@ -14,12 +14,18 @@ function getApiUrl(figmaNode, apiUrlOverride) {
14
14
  }
15
15
  return 'https://api.figma.com/v1';
16
16
  }
17
- function getHeaders(accessToken) {
18
- return {
19
- 'X-Figma-Token': accessToken,
17
+ function getHeaders(token, useOAuth = false) {
18
+ const headers = {
20
19
  'Content-Type': 'application/json',
21
20
  'User-Agent': `code-connect-cli/${version}`,
22
21
  };
22
+ if (useOAuth) {
23
+ headers['Authorization'] = `Bearer ${token}`;
24
+ }
25
+ else {
26
+ headers['X-Figma-Token'] = token;
27
+ }
28
+ return headers;
23
29
  }
24
30
  // These typings are a subset of the Figma REST API
25
31
  var FigmaRestApi;
@@ -1 +1 @@
1
- {"version":3,"file":"figma_rest_api.js","sourceRoot":"","sources":["../../src/connect/figma_rest_api.ts"],"names":[],"mappings":";;;AAKA,8BAMC;AAED,gCAMC;AA2CD,kCAgCC;AA9FD,2CAAuD;AACvD,+CAA0C;AAE1C,MAAM,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAA;AAErD,SAAgB,SAAS,CAAC,SAAiB,EAAE,cAAuB;IAClE,IAAI,cAAc,EAAE,CAAC;QACnB,gBAAM,CAAC,KAAK,CAAC,yBAAyB,cAAc,EAAE,CAAC,CAAA;QACvD,OAAO,cAAc,CAAA;IACvB,CAAC;IACD,OAAO,0BAA0B,CAAA;AACnC,CAAC;AAED,SAAgB,UAAU,CAAC,WAAmB;IAC5C,OAAO;QACL,eAAe,EAAE,WAAW;QAC5B,cAAc,EAAE,kBAAkB;QAClC,YAAY,EAAE,oBAAoB,OAAO,EAAE;KAC5C,CAAA;AACH,CAAC;AAED,mDAAmD;AACnD,IAAiB,YAAY,CAsC5B;AAtCD,WAAiB,YAAY;IAC3B,IAAY,qBAKX;IALD,WAAY,qBAAqB;QAC/B,4CAAmB,CAAA;QACnB,uDAA8B,CAAA;QAC9B,sCAAa,CAAA;QACb,4CAAmB,CAAA;IACrB,CAAC,EALW,qBAAqB,GAArB,kCAAqB,KAArB,kCAAqB,QAKhC;AAgCH,CAAC,EAtCgB,YAAY,4BAAZ,YAAY,QAsC5B;AAEM,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,WAAmB;IAChE,IAAI,CAAC;QACH,gBAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAA;QAC3D,MAAM,QAAQ,GAAG,MAAM,eAAO,CAAC,GAAG,CAAkC,GAAG,EAAE;YACvE,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC;SACjC,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACrC,gBAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAA;YACpE,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAA;QAC/B,CAAC;aAAM,CAAC;YACN,gBAAM,CAAC,KAAK,CACV,0DAA0D,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CACrF,CAAA;YACD,gBAAM,CAAC,KAAK,CAAC,sDAAsD,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;YACnF,OAAO,OAAO,CAAC,MAAM,EAAE,CAAA;QACzB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,IAAA,oBAAY,EAAC,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACjB,gBAAM,CAAC,KAAK,CACV,uCAAuC,GAAG,CAAC,QAAQ,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,CAC5H,CAAA;YACH,CAAC;iBAAM,CAAC;gBACN,gBAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACpE,CAAC;YACD,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,gBAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAA;QAC1C,CAAC;QACD,OAAO,OAAO,CAAC,MAAM,EAAE,CAAA;IACzB,CAAC;AACH,CAAC","sourcesContent":["import { isFetchError, request } from '../common/fetch'\nimport { logger } from '../common/logging'\n\nconst version = require('../../package.json').version\n\nexport function getApiUrl(figmaNode: string, apiUrlOverride?: string) {\n if (apiUrlOverride) {\n logger.debug(`Using custom API URL: ${apiUrlOverride}`)\n return apiUrlOverride\n }\n return 'https://api.figma.com/v1'\n}\n\nexport function getHeaders(accessToken: string) {\n return {\n 'X-Figma-Token': accessToken,\n 'Content-Type': 'application/json',\n 'User-Agent': `code-connect-cli/${version}`,\n }\n}\n\n// These typings are a subset of the Figma REST API\nexport namespace FigmaRestApi {\n export enum ComponentPropertyType {\n Boolean = 'BOOLEAN',\n InstanceSwap = 'INSTANCE_SWAP',\n Text = 'TEXT',\n Variant = 'VARIANT',\n }\n\n export interface ComponentPropertyDefinition {\n defaultValue: boolean | string\n type: ComponentPropertyType\n /**\n * All possible values for this property. Only exists on VARIANT properties\n */\n variantOptions?: string[]\n /**\n * Only exists on INSTANCE_SWAP properties\n */\n preferredValues?: { type: string; key: string }[]\n }\n\n export interface Node {\n // we don't care about other node types\n type: 'COMPONENT' | 'COMPONENT_SET' | 'OTHER' | 'CANVAS'\n name: string\n id: string\n children: Node[]\n }\n\n export interface NodeWithPageInfo extends Node {\n pageId: string\n pageName: string\n }\n\n export interface Component extends NodeWithPageInfo {\n type: 'COMPONENT' | 'COMPONENT_SET'\n componentPropertyDefinitions: Record<string, ComponentPropertyDefinition>\n }\n}\n\nexport async function getDocument(url: string, accessToken: string): Promise<FigmaRestApi.Node> {\n try {\n logger.info('Fetching component information from Figma...')\n const response = await request.get<{ document: FigmaRestApi.Node }>(url, {\n headers: getHeaders(accessToken),\n })\n\n if (response.response.status === 200) {\n logger.info('Successfully fetched component information from Figma')\n return response.data.document\n } else {\n logger.error(\n `Failed to get node information from Figma with status: ${response.response.status}`,\n )\n logger.debug('Failed to get node information from Figma with Body:', response.data)\n return Promise.reject()\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n logger.error(\n `Failed to get node data from Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`,\n )\n } else {\n logger.error(`Failed to get node data from Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err.data))\n } else {\n logger.error(`Failed to create: ${err}`)\n }\n return Promise.reject()\n }\n}\n"]}
1
+ {"version":3,"file":"figma_rest_api.js","sourceRoot":"","sources":["../../src/connect/figma_rest_api.ts"],"names":[],"mappings":"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","sourcesContent":["import { isFetchError, request } from '../common/fetch'\nimport { logger } from '../common/logging'\n\nconst version = require('../../package.json').version\n\nexport function getApiUrl(figmaNode: string, apiUrlOverride?: string) {\n if (apiUrlOverride) {\n logger.debug(`Using custom API URL: ${apiUrlOverride}`)\n return apiUrlOverride\n }\n return 'https://api.figma.com/v1'\n}\n\nexport function getHeaders(token: string, useOAuth = false): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'User-Agent': `code-connect-cli/${version}`,\n }\n if (useOAuth) {\n headers['Authorization'] = `Bearer ${token}`\n } else {\n headers['X-Figma-Token'] = token\n }\n return headers\n}\n\n// These typings are a subset of the Figma REST API\nexport namespace FigmaRestApi {\n export enum ComponentPropertyType {\n Boolean = 'BOOLEAN',\n InstanceSwap = 'INSTANCE_SWAP',\n Text = 'TEXT',\n Variant = 'VARIANT',\n }\n\n export interface ComponentPropertyDefinition {\n defaultValue: boolean | string\n type: ComponentPropertyType\n /**\n * All possible values for this property. Only exists on VARIANT properties\n */\n variantOptions?: string[]\n /**\n * Only exists on INSTANCE_SWAP properties\n */\n preferredValues?: { type: string; key: string }[]\n }\n\n export interface Node {\n // we don't care about other node types\n type: 'COMPONENT' | 'COMPONENT_SET' | 'OTHER' | 'CANVAS'\n name: string\n id: string\n children: Node[]\n }\n\n export interface NodeWithPageInfo extends Node {\n pageId: string\n pageName: string\n }\n\n export interface Component extends NodeWithPageInfo {\n type: 'COMPONENT' | 'COMPONENT_SET'\n componentPropertyDefinitions: Record<string, ComponentPropertyDefinition>\n }\n}\n\nexport async function getDocument(url: string, accessToken: string): Promise<FigmaRestApi.Node> {\n try {\n logger.info('Fetching component information from Figma...')\n const response = await request.get<{ document: FigmaRestApi.Node }>(url, {\n headers: getHeaders(accessToken),\n })\n\n if (response.response.status === 200) {\n logger.info('Successfully fetched component information from Figma')\n return response.data.document\n } else {\n logger.error(\n `Failed to get node information from Figma with status: ${response.response.status}`,\n )\n logger.debug('Failed to get node information from Figma with Body:', response.data)\n return Promise.reject()\n }\n } catch (err) {\n if (isFetchError(err)) {\n if (err.response) {\n logger.error(\n `Failed to get node data from Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`,\n )\n } else {\n logger.error(`Failed to get node data from Figma: ${err.message}`)\n }\n logger.debug(JSON.stringify(err.data))\n } else {\n logger.error(`Failed to create: ${err}`)\n }\n return Promise.reject()\n }\n}\n"]}
@@ -88,9 +88,9 @@ export type Intrinsic = FigmaBoolean | FigmaEnum | FigmaString | FigmaInstance |
88
88
  * @returns
89
89
  */
90
90
  export declare function parseIntrinsic(exp: ts.CallExpression, parserContext: ParserContext): Intrinsic;
91
- export declare function valueToString(value: ValueMappingKind, childLayer?: string): string;
92
- export declare function valueMappingToString(valueMapping: ValueMapping, childLayer?: string): string;
93
- export declare function intrinsicToString({ kind, args, modifiers }: Intrinsic, childLayer?: string): string;
91
+ export declare function valueToString(value: ValueMappingKind, childLayer?: string, isForMigration?: boolean): string;
92
+ export declare function valueMappingToString(valueMapping: ValueMapping, childLayer?: string, isForMigration?: boolean): string;
93
+ export declare function intrinsicToString({ kind, args, modifiers }: Intrinsic, childLayer?: string, isForMigration?: boolean): string;
94
94
  /**
95
95
  * Parses the `props` field in a `figma.connect()` call, returning a mapping of
96
96
  * prop names to their respective intrinsic types
@@ -1 +1 @@
1
- {"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../../src/connect/intrinsics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../../src/connect/intrinsics.ts"],"names":[],"mappings":"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"}
@@ -322,7 +322,7 @@ function parseIntrinsic(exp, parserContext) {
322
322
  function replaceNewlines(str) {
323
323
  return str.toString().replaceAll('\n', '\\n').replaceAll("'", "\\'");
324
324
  }
325
- function valueToString(value, childLayer) {
325
+ function valueToString(value, childLayer, isForMigration) {
326
326
  if (typeof value === 'boolean' || typeof value === 'number' || typeof value === 'undefined') {
327
327
  return `${value}`;
328
328
  }
@@ -331,7 +331,7 @@ function valueToString(value, childLayer) {
331
331
  }
332
332
  if ('kind' in value) {
333
333
  // Mappings can be nested, e.g. an enum value can be figma.instance(...)
334
- return `${intrinsicToString(value, childLayer)}`;
334
+ return `${intrinsicToString(value, childLayer, isForMigration)}`;
335
335
  }
336
336
  // Convert objects to strings
337
337
  const str = typeof value.$value === 'string' ? value.$value : `${JSON.stringify(value.$value)}`;
@@ -355,19 +355,19 @@ function valueToString(value, childLayer) {
355
355
  throw new parser_common_1.InternalError(`Unknown helper type: ${value}`);
356
356
  }
357
357
  }
358
- function valueMappingToString(valueMapping, childLayer) {
358
+ function valueMappingToString(valueMapping, childLayer, isForMigration) {
359
359
  // For enums (and booleans with a valueMapping provided), convert the
360
360
  // value mapping to an object.
361
361
  return ('{\n' +
362
362
  Object.entries(valueMapping)
363
363
  .map(([key, value]) => {
364
- return `"${key}": ${valueToString(value, childLayer)}`;
364
+ return `"${key}": ${valueToString(value, childLayer, isForMigration)}`;
365
365
  })
366
366
  .join(',\n') +
367
367
  '}');
368
368
  }
369
369
  let nestedLayerCount = 0;
370
- function intrinsicToString({ kind, args, modifiers = [] }, childLayer) {
370
+ function intrinsicToString({ kind, args, modifiers = [] }, childLayer, isForMigration) {
371
371
  const selector = childLayer ?? `figma.currentLayer`;
372
372
  switch (kind) {
373
373
  case IntrinsicKind.String:
@@ -387,14 +387,14 @@ function intrinsicToString({ kind, args, modifiers = [] }, childLayer) {
387
387
  }
388
388
  case IntrinsicKind.Boolean: {
389
389
  if (args.valueMapping) {
390
- const mappingString = valueMappingToString(args.valueMapping, childLayer);
390
+ const mappingString = valueMappingToString(args.valueMapping, childLayer, isForMigration);
391
391
  // Outputs: `const propName = figma.properties.boolean('propName', { ... mapping object from above ... })`
392
392
  return `${selector}.__properties__.boolean('${args.figmaPropName}', ${mappingString})`;
393
393
  }
394
394
  return `${selector}.__properties__.boolean('${args.figmaPropName}')`;
395
395
  }
396
396
  case IntrinsicKind.Enum: {
397
- const mappingString = valueMappingToString(args.valueMapping, childLayer);
397
+ const mappingString = valueMappingToString(args.valueMapping, childLayer, isForMigration);
398
398
  // Outputs: `const propName = figma.properties.enum('propName', { ... mapping object from above ... })`
399
399
  return `${selector}.__properties__.enum('${args.figmaPropName}', ${mappingString})`;
400
400
  }
@@ -407,7 +407,7 @@ function intrinsicToString({ kind, args, modifiers = [] }, childLayer) {
407
407
  }
408
408
  case IntrinsicKind.ClassName: {
409
409
  // Outputs: `const propName = ['btn-base', figma.currentLayer.__properties__.enum('Size, { Large: 'btn-large' })].join(" ")`
410
- return `[${args.className.map((className) => (typeof className === 'string' ? `"${className}"` : `${intrinsicToString(className, childLayer)}`)).join(', ')}].filter(v => !!v).join(' ')`;
410
+ return `[${args.className.map((className) => (typeof className === 'string' ? `"${className}"` : `${intrinsicToString(className, childLayer, isForMigration)}`)).join(', ')}].filter(v => !!v).join(' ')`;
411
411
  }
412
412
  case IntrinsicKind.TextContent: {
413
413
  return `${selector}.__findChildWithCriteria__({ name: '${args.layer}', type: "TEXT" }).__render__()`;
@@ -421,9 +421,20 @@ function intrinsicToString({ kind, args, modifiers = [] }, childLayer) {
421
421
  // currently is to keep the error checking out of global scope
422
422
  const nestedLayerRef = `nestedLayer${nestedLayerCount++}`;
423
423
  body += `const ${nestedLayerRef} = figma.currentLayer.__find__("${args.layer}")\n`;
424
- body += `return ${nestedLayerRef}.type === "ERROR" ? ${nestedLayerRef} : {
425
- ${Object.entries(args.props).map(([key, intrinsic]) => `${key}: ${intrinsicToString(intrinsic, nestedLayerRef)}\n`)}
424
+ if (isForMigration) {
425
+ // Generate a TypeScript-safe pattern that always returns the object shape.
426
+ // The error case uses `undefined` per-property so the result is always
427
+ // `{ key: T | undefined }`, avoiding the `ErrorHandle | { key: T }` union
428
+ // that would require optional chaining at every call site.
429
+ body += `return {\n${Object.entries(args.props)
430
+ .map(([key, intrinsic]) => `${key}: ${nestedLayerRef}.type !== "ERROR" ? ${intrinsicToString(intrinsic, nestedLayerRef, isForMigration)} : undefined,\n`)
431
+ .join('')}\n }\n`;
432
+ }
433
+ else {
434
+ body += `return ${nestedLayerRef}.type === "ERROR" ? ${nestedLayerRef} : {
435
+ ${Object.entries(args.props).map(([key, intrinsic]) => `${key}: ${intrinsicToString(intrinsic, nestedLayerRef, isForMigration)}\n`)}
426
436
  }\n`;
437
+ }
427
438
  return `(function () {${body}})()`;
428
439
  }
429
440
  default: