@figma/code-connect 1.4.3 → 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 (53) hide show
  1. package/README.md +2 -22
  2. package/dist/commands/connect.d.ts.map +1 -1
  3. package/dist/commands/connect.js +61 -10
  4. package/dist/commands/connect.js.map +1 -1
  5. package/dist/commands/connect_template.d.ts +36 -0
  6. package/dist/commands/connect_template.d.ts.map +1 -0
  7. package/dist/commands/connect_template.js +324 -0
  8. package/dist/commands/connect_template.js.map +1 -0
  9. package/dist/commands/preview_utils.d.ts +49 -0
  10. package/dist/commands/preview_utils.d.ts.map +1 -0
  11. package/dist/commands/preview_utils.js +390 -0
  12. package/dist/commands/preview_utils.js.map +1 -0
  13. package/dist/connect/batch_templates.d.ts +11 -0
  14. package/dist/connect/batch_templates.d.ts.map +1 -0
  15. package/dist/connect/batch_templates.js +70 -0
  16. package/dist/connect/batch_templates.js.map +1 -0
  17. package/dist/connect/create.d.ts.map +1 -1
  18. package/dist/connect/create.js +13 -0
  19. package/dist/connect/create.js.map +1 -1
  20. package/dist/connect/create_template.d.ts +22 -0
  21. package/dist/connect/create_template.d.ts.map +1 -0
  22. package/dist/connect/create_template.js +195 -0
  23. package/dist/connect/create_template.js.map +1 -0
  24. package/dist/connect/delete_docs.d.ts +2 -1
  25. package/dist/connect/delete_docs.d.ts.map +1 -1
  26. package/dist/connect/delete_docs.js +2 -2
  27. package/dist/connect/delete_docs.js.map +1 -1
  28. package/dist/connect/figma_rest_api.d.ts +1 -5
  29. package/dist/connect/figma_rest_api.d.ts.map +1 -1
  30. package/dist/connect/figma_rest_api.js +9 -3
  31. package/dist/connect/figma_rest_api.js.map +1 -1
  32. package/dist/connect/project.d.ts +9 -7
  33. package/dist/connect/project.d.ts.map +1 -1
  34. package/dist/connect/project.js +39 -25
  35. package/dist/connect/project.js.map +1 -1
  36. package/dist/connect/raw_templates.d.ts +8 -1
  37. package/dist/connect/raw_templates.d.ts.map +1 -1
  38. package/dist/connect/raw_templates.js +20 -7
  39. package/dist/connect/raw_templates.js.map +1 -1
  40. package/dist/connect/upload.d.ts +3 -1
  41. package/dist/connect/upload.d.ts.map +1 -1
  42. package/dist/connect/upload.js +23 -8
  43. package/dist/connect/upload.js.map +1 -1
  44. package/dist/connect/validation.d.ts +2 -2
  45. package/dist/connect/validation.d.ts.map +1 -1
  46. package/dist/connect/validation.js +4 -4
  47. package/dist/connect/validation.js.map +1 -1
  48. package/dist/connect/wizard/helpers.js.map +1 -1
  49. package/dist/storybook/convert.d.ts.map +1 -1
  50. package/dist/storybook/convert.js +1 -1
  51. package/dist/storybook/convert.js.map +1 -1
  52. package/figma-types.d.ts +3 -0
  53. package/package.json +6 -2
@@ -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"]}
@@ -33,7 +33,7 @@ export type BaseCodeConnectConfig = {
33
33
  /**
34
34
  * The parser name, if using an internal parser.
35
35
  */
36
- parser: CodeConnectParser;
36
+ parser?: CodeConnectParser;
37
37
  /**
38
38
  * Label to use for the uploaded code examples
39
39
  */
@@ -98,12 +98,14 @@ export type CodeConnectReactConfig = BaseCodeConnectConfig & {
98
98
  };
99
99
  };
100
100
  export type CodeConnectHtmlConfig = BaseCodeConnectConfig & {};
101
- export type CodeConnectParserlessConfig = Omit<BaseCodeConnectConfig, 'parser'>;
102
- export type CodeConnectConfig = CodeConnectReactConfig | CodeConnectExecutableParserConfig | CodeConnectCustomExecutableParserConfig | CodeConnectHtmlConfig | BaseCodeConnectConfig;
101
+ export type CodeConnectParserlessConfig = BaseCodeConnectConfig & {
102
+ parser: undefined;
103
+ };
104
+ export type CodeConnectConfig = CodeConnectReactConfig | CodeConnectExecutableParserConfig | CodeConnectCustomExecutableParserConfig | CodeConnectHtmlConfig | BaseCodeConnectConfig | CodeConnectParserlessConfig;
103
105
  interface FigmaConfig {
104
106
  codeConnect?: CodeConnectConfig;
105
107
  }
106
- export declare function determineConfigFromProject(dir: string, exitOnError?: boolean): FigmaConfig | undefined;
108
+ export declare function determineConfigFromProject(dir: string, exitOnError?: boolean, isTemplatesOnlyCLI?: boolean): FigmaConfig | undefined;
107
109
  export declare function determineLabelFromProject(dir: string): string | undefined;
108
110
  export declare function getGitRemoteURL(repoPath: string): string;
109
111
  /**
@@ -148,7 +150,7 @@ export type ReactProjectInfo = ProjectInfo<CodeConnectReactConfig> & {
148
150
  };
149
151
  export declare function getDefaultConfigPath(dir: string): string;
150
152
  export declare function getEnvPath(dir: string): string;
151
- export declare function parseOrDetermineConfig(dir: string, configPath: string): Promise<{
153
+ export declare function parseOrDetermineConfig(dir: string, configPath: string, isTemplatesOnlyCLI?: boolean): Promise<{
152
154
  config: CodeConnectConfig;
153
155
  hasConfigFile: boolean;
154
156
  }>;
@@ -166,7 +168,7 @@ export declare function checkForEnvAndToken(dir: string): Promise<{
166
168
  * @param config Code Connect config
167
169
  * @returns Object containing information about the project
168
170
  */
169
- export declare function getProjectInfoFromConfig(dir: string, config: CodeConnectConfig): Promise<ProjectInfo>;
171
+ export declare function getProjectInfoFromConfig(dir: string, config: CodeConnectConfig, isTemplatesOnlyCLI?: boolean): Promise<ProjectInfo>;
170
172
  /**
171
173
  * Gets information about a project from a directory.
172
174
  *
@@ -174,7 +176,7 @@ export declare function getProjectInfoFromConfig(dir: string, config: CodeConnec
174
176
  * @param configPath Optional path to Code Connect config file
175
177
  * @returns Object containing information about the project
176
178
  */
177
- export declare function getProjectInfo(dir: string, configPath: string): Promise<ProjectInfo>;
179
+ export declare function getProjectInfo(dir: string, configPath: string, isTemplatesOnlyCLI?: boolean): Promise<ProjectInfo>;
178
180
  export declare function getReactProjectInfo(projectInfo: ProjectInfo<CodeConnectReactConfig>): ReactProjectInfo;
179
181
  export declare function getTsProgram(projectInfo: ProjectInfo<CodeConnectConfig>): ts.Program;
180
182
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,YAAY,CAAA;AAO3B,OAAO,EAAoB,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAKpF,eAAO,MAAM,+BAA+B;;;;;;;CAQ3C,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAG/E,CAAA;AAGD,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAA;AAK1F,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,2BAA2B,CAAA;AAE9E,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjD;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAA;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAElC;;OAEG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IAErC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,iCAAiC,GAAG,qBAAqB,GAAG;IACtE,MAAM,EAAE,2BAA2B,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,uCAAuC,GAAG,qBAAqB,GAAG;IAC5E,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG;IAC3D,MAAM,EAAE,OAAO,CAAA;IACf;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAChC;;OAEG;IACH,SAAS,CAAC,EAAE;QACV;;WAEG;QACH,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,GAAG,EAAE,CAAA;AAE9D,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,iCAAiC,GACjC,uCAAuC,GACvC,qBAAqB,GACrB,qBAAqB,CAAA;AAEzB,UAAU,WAAW;IACnB,WAAW,CAAC,EAAE,iBAAiB,CAAA;CAChC;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,EACX,WAAW,UAAO,GACjB,WAAW,GAAG,SAAS,CAgBzB;AAgFD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuCzE;AAsID,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,UAW/C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,UAkBtD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,UA8CzF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,UAmD1F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAoBrE;AAED,MAAM,MAAM,WAAW,CAAC,OAAO,GAAG,iBAAiB,IAAI;IACrD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,sBAAsB,CAAC,GAAG;IACnE;;OAEG;IACH,SAAS,EAAE,EAAE,CAAC,OAAO,CAAA;CACtB,CAAA;AAOD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,UAE/C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,UAErC;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;;;GAyC3E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM;;;GAoCpD;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAoDtB;AAoBD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAO1F;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,CAAC,sBAAsB,CAAC,GAC/C,gBAAgB,CAOlB;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,OAAO,CAcpF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAoD7F;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,sBAAsB,GAC7B,MAAM,GAAG,IAAI,CAoBf"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"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"}
@@ -48,7 +48,11 @@ exports.DEFAULT_LABEL_PER_PARSER = {
48
48
  react: label_language_mapping_1.CodeConnectLabel.React,
49
49
  html: label_language_mapping_1.CodeConnectLabel.WebComponents,
50
50
  };
51
- function determineConfigFromProject(dir, exitOnError = true) {
51
+ function determineConfigFromProject(dir, exitOnError = true, isTemplatesOnlyCLI = false) {
52
+ if (isTemplatesOnlyCLI) {
53
+ const label = determineLabelFromProject(dir);
54
+ return { codeConnect: label ? { label } : {} };
55
+ }
52
56
  const parser = determineParserFromProject(dir);
53
57
  if (parser) {
54
58
  const label = determineLabelFromProject(dir);
@@ -215,12 +219,12 @@ Please raise an issue at https://github.com/figma/code-connect/issues if you hav
215
219
  }
216
220
  return config;
217
221
  }
218
- async function parseConfig(configFilePath, dir) {
222
+ async function parseConfig(configFilePath, dir, isTemplatesOnlyCLI = false) {
219
223
  try {
220
224
  const rawData = fs_1.default.readFileSync(configFilePath, 'utf-8');
221
225
  const rawConfig = JSON.parse(rawData);
222
226
  const config = await checkForLegacyConfig(rawConfig, configFilePath);
223
- if (!config.codeConnect?.parser) {
227
+ if (!isTemplatesOnlyCLI && !config.codeConnect?.parser) {
224
228
  const parser = determineParserFromProject(dir);
225
229
  if (!parser) {
226
230
  logging_1.logger.error(`Code Connect was not able to determine your project type, and no \`parser\` was specified. Please ensure you are running Code Connect from your project root. You may need to add a \`parser\` key to your config file, specifying which parser to use. See https://github.com/figma/code-connect/ for instructions.`);
@@ -235,7 +239,7 @@ async function parseConfig(configFilePath, dir) {
235
239
  if (!config.codeConnect?.label) {
236
240
  const label = determineLabelFromProject(dir);
237
241
  if (label) {
238
- config.codeConnect.label = label;
242
+ config.codeConnect = { ...config.codeConnect, label };
239
243
  }
240
244
  }
241
245
  return config;
@@ -410,7 +414,7 @@ function getDefaultConfigPath(dir) {
410
414
  function getEnvPath(dir) {
411
415
  return path_1.default.resolve(path_1.default.join(dir, ENV_FILE_NAME));
412
416
  }
413
- async function parseOrDetermineConfig(dir, configPath) {
417
+ async function parseOrDetermineConfig(dir, configPath, isTemplatesOnlyCLI = false) {
414
418
  const configFilePath = configPath ? path_1.default.resolve(configPath) : getDefaultConfigPath(dir);
415
419
  const hasConfigFile = fs_1.default.existsSync(configFilePath);
416
420
  if (!hasConfigFile) {
@@ -422,8 +426,8 @@ async function parseOrDetermineConfig(dir, configPath) {
422
426
  }
423
427
  }
424
428
  const globalConfig = hasConfigFile
425
- ? await parseConfig(configFilePath, dir)
426
- : determineConfigFromProject(dir);
429
+ ? await parseConfig(configFilePath, dir, isTemplatesOnlyCLI)
430
+ : determineConfigFromProject(dir, true, isTemplatesOnlyCLI);
427
431
  if (!globalConfig) {
428
432
  throw new Error(`Error parsing config file: ${configFilePath}`);
429
433
  }
@@ -481,23 +485,33 @@ async function checkForEnvAndToken(dir) {
481
485
  * @param config Code Connect config
482
486
  * @returns Object containing information about the project
483
487
  */
484
- async function getProjectInfoFromConfig(dir, config) {
488
+ async function getProjectInfoFromConfig(dir, config, isTemplatesOnlyCLI = false) {
485
489
  const absPath = path_1.default.resolve(dir);
486
490
  const remoteUrl = getGitRemoteURL(absPath);
487
- const defaultIncludeGlobs = config.parser
488
- ? exports.DEFAULT_INCLUDE_GLOBS_BY_PARSER[config.parser]
489
- : undefined;
490
- // always ignore any `node_modules` folders in react projects
491
- const defaultExcludeGlobs = config.parser
492
- ? ({
493
- react: ['node_modules/**'],
494
- html: ['node_modules/**'],
495
- swift: ['**/__test__/**'],
496
- compose: [],
497
- custom: [],
498
- __unit_test__: [],
499
- }[config.parser] ?? [])
500
- : [];
491
+ const defaultIncludeGlobs = isTemplatesOnlyCLI
492
+ ? [
493
+ '**/*.figma.ts',
494
+ '**/*.figma.js',
495
+ '**/*.figma.template.ts',
496
+ '**/*.figma.template.js',
497
+ '**/*.figma.batch.json',
498
+ ]
499
+ : config.parser
500
+ ? exports.DEFAULT_INCLUDE_GLOBS_BY_PARSER[config.parser]
501
+ : undefined;
502
+ // always ignore node_modules; for parsers, apply parser-specific exclusions
503
+ const defaultExcludeGlobs = isTemplatesOnlyCLI
504
+ ? ['node_modules/**']
505
+ : config.parser
506
+ ? ({
507
+ react: ['node_modules/**'],
508
+ html: ['node_modules/**'],
509
+ swift: ['**/__test__/**'],
510
+ compose: [],
511
+ custom: [],
512
+ __unit_test__: [],
513
+ }[config.parser] ?? [])
514
+ : [];
501
515
  const includeGlobs = config.include || defaultIncludeGlobs;
502
516
  const excludeGlobs = config.exclude
503
517
  ? [...config.exclude, ...defaultExcludeGlobs]
@@ -546,11 +560,11 @@ function validateLanguage(language) {
546
560
  * @param configPath Optional path to Code Connect config file
547
561
  * @returns Object containing information about the project
548
562
  */
549
- async function getProjectInfo(dir, configPath) {
550
- const { config } = await parseOrDetermineConfig(dir, configPath);
563
+ async function getProjectInfo(dir, configPath, isTemplatesOnlyCLI = false) {
564
+ const { config } = await parseOrDetermineConfig(dir, configPath, isTemplatesOnlyCLI);
551
565
  // Validate language field if present
552
566
  validateLanguage(config.language);
553
- return getProjectInfoFromConfig(dir, config);
567
+ return getProjectInfoFromConfig(dir, config, isTemplatesOnlyCLI);
554
568
  }
555
569
  function getReactProjectInfo(projectInfo) {
556
570
  const tsProgram = getTsProgram(projectInfo);