@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.
- package/README.md +2 -22
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +61 -10
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect_template.d.ts +36 -0
- package/dist/commands/connect_template.d.ts.map +1 -0
- package/dist/commands/connect_template.js +324 -0
- package/dist/commands/connect_template.js.map +1 -0
- package/dist/commands/preview_utils.d.ts +49 -0
- package/dist/commands/preview_utils.d.ts.map +1 -0
- package/dist/commands/preview_utils.js +390 -0
- package/dist/commands/preview_utils.js.map +1 -0
- package/dist/connect/batch_templates.d.ts +11 -0
- package/dist/connect/batch_templates.d.ts.map +1 -0
- package/dist/connect/batch_templates.js +70 -0
- package/dist/connect/batch_templates.js.map +1 -0
- package/dist/connect/create.d.ts.map +1 -1
- package/dist/connect/create.js +13 -0
- package/dist/connect/create.js.map +1 -1
- package/dist/connect/create_template.d.ts +22 -0
- package/dist/connect/create_template.d.ts.map +1 -0
- package/dist/connect/create_template.js +195 -0
- package/dist/connect/create_template.js.map +1 -0
- package/dist/connect/delete_docs.d.ts +2 -1
- package/dist/connect/delete_docs.d.ts.map +1 -1
- package/dist/connect/delete_docs.js +2 -2
- package/dist/connect/delete_docs.js.map +1 -1
- package/dist/connect/figma_rest_api.d.ts +1 -5
- package/dist/connect/figma_rest_api.d.ts.map +1 -1
- package/dist/connect/figma_rest_api.js +9 -3
- package/dist/connect/figma_rest_api.js.map +1 -1
- package/dist/connect/project.d.ts +9 -7
- package/dist/connect/project.d.ts.map +1 -1
- package/dist/connect/project.js +39 -25
- package/dist/connect/project.js.map +1 -1
- package/dist/connect/raw_templates.d.ts +8 -1
- package/dist/connect/raw_templates.d.ts.map +1 -1
- package/dist/connect/raw_templates.js +20 -7
- package/dist/connect/raw_templates.js.map +1 -1
- package/dist/connect/upload.d.ts +3 -1
- package/dist/connect/upload.d.ts.map +1 -1
- package/dist/connect/upload.js +23 -8
- package/dist/connect/upload.js.map +1 -1
- package/dist/connect/validation.d.ts +2 -2
- package/dist/connect/validation.d.ts.map +1 -1
- package/dist/connect/validation.js +4 -4
- package/dist/connect/validation.js.map +1 -1
- package/dist/connect/wizard/helpers.js.map +1 -1
- package/dist/storybook/convert.d.ts.map +1 -1
- package/dist/storybook/convert.js +1 -1
- package/dist/storybook/convert.js.map +1 -1
- package/figma-types.d.ts +3 -0
- 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,
|
|
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":";;
|
|
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(
|
|
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,
|
|
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(
|
|
18
|
-
|
|
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,
|
|
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
|
|
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 =
|
|
102
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"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"}
|
package/dist/connect/project.js
CHANGED
|
@@ -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
|
|
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 =
|
|
488
|
-
?
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
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);
|