UNPKG

@tokens-studio/sdk

Version:
158 lines 5.86 kB
/* eslint-disable no-console */ import path from 'node:path'; import fs from 'node:fs/promises'; import { tasks, prompt } from '@tokens-studio/cli-kit'; import { convertTokenData } from 'style-dictionary/utils'; import { error, info, success } from './messages.js'; import chalk from 'chalk'; import { createClient } from './client.js'; import { configFileName } from './utils.js'; import { getSets } from './queries.js'; async function fetchSets(client, config) { let sets = []; await tasks({ start: 'Fetching token data', end: 'Done!', }, [ { pending: 'tokens', start: 'Getting tokensets', end: 'Fetched tokensets', while: async () => { const fetchPage = async (page) => { return await getSets(client, { org: config.org, project: config.project, branch: config.branch, page, }); }; const addSets = (added) => { sets = [...sets, ...added]; }; const firstBatch = await fetchPage(1); addSets(firstBatch.data); if (firstBatch.totalPages > 1) { const subsequentBatches = await Promise.all(Array(firstBatch.totalPages - 1) .fill(null) .map((_, i) => fetchPage(i + 2))); const setData = subsequentBatches.flatMap((batch) => batch.data); addSets(setData); } }, onError(e) { error(e); throw e; }, }, ]); return sets; } async function writeSetsToFs(sets, args, config) { let yesToAll = !!process.env.CI; // in CI we always want to override const writeSetToFs = async (set) => { const filePath = `${path.resolve( // assume the "output" in config is configured relative to the config path args['--config'] ?? '', config.output, set.name.replace(/\//g, path.sep))}.json`; const dirPath = path.dirname(filePath); try { await fs.lstat(dirPath); } catch (_err) { await fs.mkdir(dirPath, { recursive: true }); } let fileExists = false; try { const stats = await fs.lstat(filePath); if (stats) fileExists = true; } catch (_e) { // } let shouldWrite = true; if (fileExists && !yesToAll) { const { overwriteFile } = await prompt([ { name: 'overwriteFile', type: 'select', label: '', message: `File ${chalk.cyanBright(filePath)} already exists, do you want to overwrite it?`, choices: [ { value: 'all', label: 'Yes to all', }, { value: 'yes', label: 'Yes', }, { value: 'no', label: 'No', }, ], initial: 'all', }, ]); if (overwriteFile === 'all') { yesToAll = true; } if (overwriteFile === 'no' || overwriteFile === 'yes') { shouldWrite = false; } } if (shouldWrite) { await fs.writeFile(filePath, JSON.stringify(set.raw, null, '\t')); } }; // This could be done in parallel but due to the synchronous nature of prompts // this is a rather big pain in the butt to parallelize because you have to set up a queuing/interrupt system.. // so not really worth it for the code complexity // If needed, we can break out of the for loop if the user hits "Yes to all" // and parallelize the remaining sets if performance is an issue. let setsDoneIndex = 0; for (const set of sets) { await writeSetToFs(set); setsDoneIndex++; if (yesToAll) { // we can now parallelize the remaining sets break; } } if (setsDoneIndex !== sets.length && yesToAll) { await Promise.all(sets.slice(setsDoneIndex).map(writeSetToFs)); // we still have some remaining sets but we can parallize them } } export async function pull(args) { const client = createClient(args); const resolvedConfigPath = path.resolve(args['--config'] ?? '', configFileName); let raw; try { raw = await fs.readFile(resolvedConfigPath, 'utf-8'); } catch (e) { error(`Could not find config file at: ${chalk.cyan(resolvedConfigPath)}`); throw e; } const config = JSON.parse(raw); console.log('\r'); const sets = await fetchSets(client, config); if (sets.length === 0) { error(`No sets found for project with id: ${config.project}.`); return; } console.log('\r'); const tokensCount = sets.reduce((acc, curr) => acc + convertTokenData(curr.raw, { output: 'array', usesDtcg: true }).length, 0); success(`Found ${sets.length} sets with ${tokensCount} tokens in total.`); sets.forEach((set) => { info(`${set.name}.json`, '', 1); }); await writeSetsToFs(sets, args, config); console.log(`\nSuccessfully pulled tokens into ${chalk.cyan(path.resolve( // assume the "output" in config is configured relative to the config path args['--config'] ?? '', config.output))}`); } //# sourceMappingURL=pull.js.map