{"version":3,"file":"prop_mapping_helpers.js","sourceRoot":"","sources":["../../../src/connect/wizard/prop_mapping_helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { BaseCommand } from '../../commands/connect'\nimport { logger } from '../../common/logging'\nimport { ComponentTypeSignature } from '../../react/parser'\nimport { FigmaRestApi } from '../figma_rest_api'\nimport { ProjectInfo } from '../project'\nimport { parseFilepathExport } from './helpers'\nimport { MatchableName, buildMatchableNamesMap, generatePropMapping } from './prop_mapping'\nimport { extractSignature } from './signature_extraction'\nimport { PropMapping } from '../parser_executable_types'\nimport { EmbeddingsResponse, fetchEmbeddings } from './embeddings'\nimport { isFetchError } from '../../common/fetch'\n\nexport type MatchableNamesMap = Record\n\nexport type PropMappingData = {\n [filepathExport: string]: {\n signature: ComponentTypeSignature\n matchableNamesMap: MatchableNamesMap\n componentPropertyDefinitions: FigmaRestApi.Component['componentPropertyDefinitions']\n }\n}\n\n/**\n * Preprocess signatures and matchable names for all components\n */\nexport function getPropMappingData({\n filepathExportsToComponents,\n projectInfo,\n cmd,\n}: {\n filepathExportsToComponents: Record\n projectInfo: ProjectInfo\n cmd: BaseCommand\n}) {\n const propMappingData: PropMappingData = {}\n\n for (const [filepathExport, { componentPropertyDefinitions }] of Object.entries(\n filepathExportsToComponents,\n )) {\n const { filepath, exportName } = parseFilepathExport(filepathExport)\n\n if (projectInfo.config.parser === 'react' && filepath && exportName) {\n try {\n const signature = extractSignature({\n nameToFind: exportName,\n sourceFilePath: filepath,\n })\n if (cmd.verbose && Object.keys(signature).length === 0) {\n logger.warn(`No TS signature found for \"${exportName}\" in ${filepath}`)\n }\n propMappingData[filepathExport] = {\n signature,\n componentPropertyDefinitions,\n matchableNamesMap: buildMatchableNamesMap(componentPropertyDefinitions),\n }\n } catch (e) {\n if (cmd.verbose) {\n logger.warn(`Could not extract signature for \"${exportName}\" in ${filepath}`)\n }\n }\n }\n }\n\n return propMappingData\n}\n\nexport function getUniqueMatchableNames(propMappingData: PropMappingData) {\n const allNames = Object.values(propMappingData).flatMap((d) => [\n ...Object.keys(d.signature),\n ...Object.keys(d.matchableNamesMap),\n ])\n return Array.from(new Set(allNames))\n}\n\nexport type PropMatchResult = { item: string; score: number }\n\nexport type ComponentMatchResults = {\n [propName: string]: PropMatchResult[]\n}\n\ntype AllMatchResults = {\n [filepathExport: string]: ComponentMatchResults\n}\n\ntype MatchableNameEmbeddings = {\n [matchableName: string]: number[]\n}\n\nfunction cosineSimilarity(a: number[], b: number[]) {\n const dot_product = a.reduce((acc, val, i) => acc + val * b[i], 0)\n const magnitude_a = Math.sqrt(a.reduce((acc, val) => acc + val * val, 0))\n const magnitude_b = Math.sqrt(b.reduce((acc, val) => acc + val * val, 0))\n return dot_product / (magnitude_a * magnitude_b)\n}\n\nexport function buildAllEmbeddingsMatchResults(\n propMappingData: PropMappingData,\n matchableNameEmbeddings: MatchableNameEmbeddings,\n) {\n const allMatchResults: AllMatchResults = {}\n\n Object.entries(propMappingData).forEach(([filepathExport, { signature, matchableNamesMap }]) => {\n allMatchResults[filepathExport] = {}\n Object.keys(signature).forEach((propName) => {\n allMatchResults[filepathExport][propName] = Object.keys(matchableNamesMap)\n .map((item) => ({\n item,\n score: cosineSimilarity(matchableNameEmbeddings[propName], matchableNameEmbeddings[item]),\n }))\n .sort((a, b) => b.score - a.score)\n })\n })\n\n return allMatchResults\n}\n\nasync function getMockEmbeddingsResponse(uniqueMatchableNames: string[], mockResponseName: string) {\n /**\n * Refetch and write local mock responses.\n * This should be done whenever any upstream changes are made to e.g. TS signature extraction\n */\n const updateMockFiles = false\n\n // Return mock response or update local mocks\n const mockResponsePath =\n mockResponseName &&\n path.join(\n __dirname,\n `__test__/prop_mapping/test_cases/embeddings_responses/${mockResponseName}.json`,\n )\n if (updateMockFiles) {\n if (!process.env.FIGMA_ACCESS_TOKEN) {\n throw new Error('process.env.FIGMA_ACCESS_TOKEN required to fetch embeddings')\n }\n if (!process.env.FILE_URL) {\n throw new Error(\n \"process.env.FILE_URL required to fetch embeddings (note: contents of file don't matter)\",\n )\n }\n const res = await fetchEmbeddings({\n uniqueMatchableNames,\n accessToken: process.env.FIGMA_ACCESS_TOKEN,\n figmaUrl: process.env.FILE_URL,\n })\n fs.writeFileSync(mockResponsePath, JSON.stringify(res))\n return res\n } else {\n return JSON.parse(fs.readFileSync(mockResponsePath, 'utf-8')) as EmbeddingsResponse\n }\n}\n\nasync function getEmbeddingsMatchResults({\n propMappingData,\n accessToken,\n figmaUrl,\n mockResponseName,\n apiUrlOverride,\n}: {\n propMappingData: PropMappingData\n accessToken: string\n figmaUrl: string\n mockResponseName?: string\n apiUrlOverride?: string\n}) {\n const uniqueMatchableNames = getUniqueMatchableNames(propMappingData)\n\n const matchableNamesEmbeddings: MatchableNameEmbeddings = {}\n\n if (uniqueMatchableNames.length > 0) {\n const res = mockResponseName\n ? await getMockEmbeddingsResponse(uniqueMatchableNames, mockResponseName)\n : await fetchEmbeddings({ uniqueMatchableNames, accessToken, figmaUrl, apiUrlOverride })\n\n res?.meta.embeddings.forEach((embedding: number[], index: number) => {\n matchableNamesEmbeddings[uniqueMatchableNames[index]] = embedding\n })\n }\n\n return buildAllEmbeddingsMatchResults(propMappingData, matchableNamesEmbeddings)\n}\n\nexport async function generateAllPropsMappings({\n propMappingData,\n accessToken,\n figmaUrl,\n useAi,\n mockResponseName,\n apiUrlOverride,\n}: {\n propMappingData: PropMappingData\n accessToken: string\n figmaUrl: string\n useAi: boolean\n mockResponseName?: string\n apiUrlOverride?: string\n}) {\n let allMatchResults: AllMatchResults = {}\n\n if (useAi) {\n try {\n allMatchResults = await getEmbeddingsMatchResults({\n propMappingData,\n accessToken,\n figmaUrl,\n mockResponseName,\n apiUrlOverride,\n })\n } catch (e) {\n if (isFetchError(e)) {\n logger.error(`Failed to fetch embeddings: ${e.data?.message || e.response?.status}`)\n } else {\n logger.error(`Failed to compute embeddings: ${e}`)\n }\n logger.info('Falling back to using fuzzy matching')\n }\n }\n\n const propMappings: { [filepathExport: string]: PropMapping } = {}\n\n Object.entries(propMappingData).forEach(\n ([filepathExport, { signature, componentPropertyDefinitions, matchableNamesMap }]) => {\n propMappings[filepathExport] = generatePropMapping({\n matchableNamesMap,\n componentPropertyDefinitions,\n signature,\n componentMatchResults: allMatchResults[filepathExport],\n })\n },\n )\n\n return propMappings\n}\n\n/**\n * This is the top level function that takes a map of filepathExports to components and generates prop mappings.\n * It does the following:\n *\n * 1. For each component we want to match, extract their TS signature and all figma properties\n * 2. Make an array of all strings we want embeddings for (react props, figma properties, variant values)\n * 3. Call embeddings endpoint with above and create a map of names => embeddings\n * 4. For each component, build a map of code props to an list of matchable names + scores, sorted by their calculated embedding distance to the code prop\n * 5. Finally, pass those name matches and component data to the prop mapping algorithm to generate the mapping\n */\nexport async function extractDataAndGenerateAllPropsMappings({\n filepathExportsToComponents,\n projectInfo,\n cmd,\n figmaUrl,\n accessToken,\n useAi,\n}: {\n filepathExportsToComponents: Record\n projectInfo: ProjectInfo\n cmd: BaseCommand\n figmaUrl: string\n accessToken: string\n useAi: boolean\n}) {\n const propMappingData = getPropMappingData({\n filepathExportsToComponents,\n projectInfo,\n cmd,\n })\n return {\n propMappingData,\n propMappings: await generateAllPropsMappings({\n propMappingData,\n accessToken,\n figmaUrl,\n useAi,\n apiUrlOverride: cmd.apiUrl || projectInfo.config.apiUrl,\n }),\n }\n}\n"]}