import { isToken } from '@preply/ds-core'; import { TOKEN_COLOR_SCHEME_AWARE_FIELD, TOKEN_ID_FIELD, Token } from '@preply/ds-core-types'; import { FlatToken } from './tokenFilter'; export type ResolveValue = (token: Token) => string; export function flatten( node: Record, prefix: string, resolveValue: ResolveValue, ): FlatToken[] { const result: FlatToken[] = []; for (const [key, child] of Object.entries(node)) { const path = prefix ? `${prefix}.${key}` : key; if (isToken(child)) { result.push({ name: path, id: child[TOKEN_ID_FIELD], value: resolveValue(child), colorSchemeAware: !!child[TOKEN_COLOR_SCHEME_AWARE_FIELD], }); } else if (typeof child === 'object' && child !== null) { result.push(...flatten(child as Record, path, resolveValue)); } } return result; } export interface CollectTokensOptions { allTokens: Record; resolveValue: ResolveValue; category?: string; categories?: string[]; nameFilter?: string; allowedTokens?: string[]; } export function collectTokens(options: CollectTokensOptions): FlatToken[] { const { allTokens, resolveValue, category, categories, nameFilter, allowedTokens } = options; let source: Record; if (categories) { source = {}; for (const cat of categories) { source[cat] = allTokens[cat]; } } else if (category) { source = { [category]: allTokens[category] }; } else { source = allTokens; } let result = flatten(source, '', resolveValue); if (nameFilter) { result = result.filter(t => t.name.includes(nameFilter)); } if (allowedTokens) { const allowed = new Set(allowedTokens); result = result.filter(t => allowed.has(t.name)); } return result; }