UNPKG

@figma/code-connect

Version:

A tool for connecting your design system components in code with your design system in Figma

137 lines 6.71 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.normalizeComponentName = normalizeComponentName; exports.createCodeConnectFromUrl = createCodeConnectFromUrl; const helpers_1 = require("./helpers"); const fs_1 = __importDefault(require("fs")); const figma_rest_api_1 = require("./figma_rest_api"); const logging_1 = require("../common/logging"); const parser_executables_1 = require("./parser_executables"); const create_1 = require("../react/create"); const parser_executable_types_1 = require("./parser_executable_types"); const zod_validation_error_1 = require("zod-validation-error"); const create_2 = require("../html/create"); const fetch_1 = require("../common/fetch"); function normalizeComponentName(name) { // Convert the string to PascalCase and ensure first character is not a digit return name .replace(/[^a-zA-Z0-9]/g, ' ') .split(' ') .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join('') .replace(/^[0-9]/, '_$&'); } async function createCodeConnectFromUrl({ accessToken, figmaNodeUrl, outFile, outDir, projectInfo, cmd, }) { try { const fileKey = (0, helpers_1.parseFileKey)(figmaNodeUrl); const nodeIds = (0, helpers_1.parseNodeIds)([figmaNodeUrl]); const apiUrl = (0, figma_rest_api_1.getApiUrl)(figmaNodeUrl ?? '', cmd.apiUrl || projectInfo.config.apiUrl) + `/code_connect/${fileKey}/cli_data?ids=${nodeIds.join(',')}`; if (nodeIds.length === 0) { (0, logging_1.exitWithError)(`Invalid figma node URL: the provided url "${figmaNodeUrl}" does not contain a node-id`); } else if (nodeIds.length > 1) { (0, logging_1.exitWithError)(`Invalid figma node URL: the provided url "${figmaNodeUrl}" contains more than one node-id`); } logging_1.logger.info('Fetching component information from Figma...'); const response = process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE ? { response: { status: 200 }, data: JSON.parse(fs_1.default.readFileSync(process.env.CODE_CONNECT_MOCK_CREATE_API_RESPONSE, 'utf-8')), } : await fetch_1.request.get(apiUrl, { headers: (0, figma_rest_api_1.getHeaders)(accessToken), }); if (response.response.status === 200) { logging_1.logger.info('Parsing response'); const component = (0, helpers_1.findComponentsInDocument)(response.data.document, nodeIds)[0]; if (component === undefined) { (0, logging_1.exitWithError)('Could not find a component in the provided URL'); } const normalizedName = normalizeComponentName(component.name); const componentPayload = { figmaNodeUrl, id: component.id, name: component.name, normalizedName, type: component.type, componentPropertyDefinitions: component.componentPropertyDefinitions, }; logging_1.logger.info('Generating Code Connect files...'); let result; if (projectInfo.config.parser === 'react') { const payload = { mode: 'CREATE', destinationDir: outDir ?? process.env.INIT_CWD ?? process.cwd(), destinationFile: outFile, normalizedName, figmaConnections: [{ component: componentPayload }], config: projectInfo.config, }; result = await (0, create_1.createReactCodeConnect)(payload); } else if (projectInfo.config.parser === 'html') { const payload = { mode: 'CREATE', destinationDir: outDir ?? process.env.INIT_CWD ?? process.cwd(), destinationFile: outFile, normalizedName, figmaConnections: [{ component: componentPayload }], config: projectInfo.config, }; result = await (0, create_2.createHtmlCodeConnect)(payload); } else { try { const payload = { mode: 'CREATE', destinationDir: outDir ?? process.env.INIT_CWD ?? process.cwd(), destinationFile: outFile, component: componentPayload, config: projectInfo.config, verbose: cmd.verbose, }; const stdout = await (0, parser_executables_1.callParser)( // We use `as` because the React parser makes the types difficult // TODO remove once React is an executable parser projectInfo.config, payload, projectInfo.absPath); result = parser_executable_types_1.CreateResponsePayload.parse(stdout); } catch (e) { throw (0, zod_validation_error_1.fromError)(e); } } const { hasErrors } = (0, parser_executables_1.handleMessages)(result.messages); if (hasErrors) { (0, logging_1.exitWithError)('Errors encountered calling parser, exiting'); } logging_1.logger.info('Code Connect files generated successfully:'); result.createdFiles.forEach((file) => { logging_1.logger.info(`${file.filePath}`); }); } else { logging_1.logger.error(`Failed to get node information from Figma with status: ${response.response.status}`); logging_1.logger.debug('Failed to get node information from Figma with Body:', response.data); } } catch (err) { if ((0, fetch_1.isFetchError)(err)) { if (err.response) { logging_1.logger.error(`Failed to get node data from Figma (${err.response.status}): ${err.response.status} ${err.data?.err ?? err.data?.message}`); } else { logging_1.logger.error(`Failed to get node data from Figma: ${err.message}`); } logging_1.logger.debug(JSON.stringify(err.data)); } else { logging_1.logger.error(`Failed to create: ${err}`); } (0, helpers_1.exitWithFeedbackMessage)(1); } } //# sourceMappingURL=create.js.map