@frontfriend/tailwind 2.1.6 → 2.2.0

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../lib/core/constants.js", "../../../lib/core/errors.js", "../../../lib/core/api-client.js"],
4
- "sourcesContent": ["/**\n * Configuration constants for FrontFriend Tailwind v2\n */\n\n// API Configuration\nconst DEFAULT_API_URL = 'https://app.frontfriend.dev';\nconst LEGACY_API_URL = 'https://tokens-studio-donux.up.railway.app/api';\n\n// Cache Configuration\nconst CACHE_DIR_NAME = '.cache/frontfriend';\nconst CACHE_TTL_DAYS = 7;\nconst CACHE_TTL_MS = CACHE_TTL_DAYS * 24 * 60 * 60 * 1000;\n\n// File names\nconst CACHE_FILES = {\n JS: [\n 'tokens.js',\n 'variables.js',\n 'semanticVariables.js',\n 'semanticDarkVariables.js',\n 'cls.js',\n 'custom.js'\n ],\n JSON: [\n 'fonts.json',\n 'icons.json',\n 'components-config.json',\n 'version.json',\n 'metadata.json'\n ]\n};\n\n// Environment variables\nconst ENV_VARS = {\n FF_ID: 'FF_ID',\n FF_API_URL: 'FF_API_URL'\n};\n\nmodule.exports = {\n DEFAULT_API_URL,\n LEGACY_API_URL,\n CACHE_DIR_NAME,\n CACHE_TTL_DAYS,\n CACHE_TTL_MS,\n CACHE_FILES,\n ENV_VARS\n};", "class APIError extends Error {\n constructor(message, statusCode, url) {\n super(message);\n this.name = 'APIError';\n this.statusCode = statusCode;\n this.url = url;\n this.code = `API_${statusCode}`;\n }\n}\n\nclass CacheError extends Error {\n constructor(message, operation) {\n super(message);\n this.name = 'CacheError';\n this.operation = operation;\n this.code = `CACHE_${operation.toUpperCase()}`;\n }\n}\n\nclass ConfigError extends Error {\n constructor(message, field) {\n super(message);\n this.name = 'ConfigError';\n this.field = field;\n this.code = `CONFIG_${field.toUpperCase()}`;\n }\n}\n\nclass ProcessingError extends Error {\n constructor(message, token) {\n super(message);\n this.name = 'ProcessingError';\n this.token = token;\n this.code = 'PROCESSING_ERROR';\n }\n}\n\nmodule.exports = {\n APIError,\n CacheError,\n ConfigError,\n ProcessingError\n};", "const https = require('https');\nconst http = require('http');\nconst { URL } = require('url');\nconst { DEFAULT_API_URL, LEGACY_API_URL, ENV_VARS } = require('./constants');\nconst { APIError } = require('./errors');\n\nclass APIClient {\n constructor(ffId, options = {}) {\n this.ffId = ffId;\n this.baseURL = options.baseURL || process.env[ENV_VARS.FF_API_URL] || DEFAULT_API_URL;\n }\n\n /**\n * Fetch JSON data from a URL using native https module\n * @param {string} url - The URL to fetch\n * @returns {Promise<any>} Parsed JSON data\n */\n fetchJson(url) {\n return new Promise((resolve, reject) => {\n // Determine if we should use http or https\n const protocol = url.startsWith('https') ? https : http;\n \n protocol.get(url, (response) => {\n let data = '';\n \n // Check for HTTP errors\n if (response.statusCode >= 400) {\n reject(new APIError(\n `HTTP ${response.statusCode}: ${response.statusMessage}`,\n response.statusCode,\n url\n ));\n return;\n }\n\n // Collect response chunks\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n // Parse JSON when complete\n response.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n resolve(parsed);\n } catch (error) {\n reject(new APIError(\n `Invalid JSON response: ${error.message}`,\n response.statusCode,\n url\n ));\n }\n });\n\n // Handle response errors\n response.on('error', (error) => {\n reject(new APIError(\n `Response error: ${error.message}`,\n response.statusCode,\n url\n ));\n });\n }).on('error', (error) => {\n // Handle network errors\n reject(new APIError(\n `Network error: ${error.message}`,\n 0,\n url\n ));\n });\n });\n }\n\n /**\n * Fetch raw content from a URL\n * @param {string} url - The URL to fetch\n * @returns {Promise<string>} Raw text content\n */\n fetchRaw(url) {\n return new Promise((resolve, reject) => {\n // Determine if we should use http or https\n const protocol = url.startsWith('https') ? https : http;\n \n protocol.get(url, (response) => {\n let data = '';\n \n // Check for HTTP errors\n if (response.statusCode >= 400) {\n reject(new APIError(\n `HTTP ${response.statusCode}: ${response.statusMessage}`,\n response.statusCode,\n url\n ));\n return;\n }\n\n // Collect response chunks\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n // Return raw data when complete\n response.on('end', () => {\n resolve(data);\n });\n\n // Handle response errors\n response.on('error', (error) => {\n reject(new APIError(\n `Response error: ${error.message}`,\n response.statusCode,\n url\n ));\n });\n }).on('error', (error) => {\n // Handle network errors\n reject(new APIError(\n `Network error: ${error.message}`,\n 0,\n url\n ));\n });\n });\n }\n\n /**\n * Fetch all token files (global, colors, semantic)\n * @returns {Promise<Object>} Object with all token data\n */\n async fetchTokens() {\n // First try the new design system endpoint\n try {\n const designSystemUrl = `${this.baseURL}/api/design-systems/${this.ffId}/tokens`;\n const tokensData = await this.fetchJson(designSystemUrl);\n \n // If we have the new format, parse it\n if (tokensData && tokensData.tokens) {\n const tokens = tokensData.tokens;\n \n // Extract specific token sets from the new format\n return {\n global: tokens['Global Tokens/Default'] || tokens['global'] || null,\n colors: tokens['Global Colors/Default'] || tokens['colors'] || null,\n semantic: tokens['Semantic/Light'] || tokens['semantic/light'] || null,\n semanticDark: tokens['Semantic/Dark'] || tokens['semantic/dark'] || null\n };\n }\n } catch (err) {\n // If design system is not synced (400 error), throw with clear message\n if (err.statusCode === 400) {\n throw new APIError(\n 'Design system not synced with Figma. Please sync tokens from Figma before using this design system.',\n 400,\n `${this.baseURL}/api/design-systems/${this.ffId}/tokens`\n );\n }\n // Failed to fetch from design system endpoint, falling back to legacy URLs\n }\n \n // Fall back to legacy token URLs\n // Use legacy API URL for backward compatibility\n const legacyBaseURL = LEGACY_API_URL;\n const urls = {\n global: `${legacyBaseURL}/${this.ffId}/global-tokens/default.json`,\n colors: `${legacyBaseURL}/${this.ffId}/global-colors/default.json`,\n semantic: `${legacyBaseURL}/${this.ffId}/semantic/light.json`,\n semanticDark: `${legacyBaseURL}/${this.ffId}/semantic/dark.json`\n };\n\n const results = await Promise.all([\n this.fetchJson(urls.global).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.colors).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.semantic).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.semanticDark).catch(err => err.statusCode === 404 ? null : Promise.reject(err))\n ]);\n\n return {\n global: results[0],\n colors: results[1],\n semantic: results[2],\n semanticDark: results[3]\n };\n }\n\n /**\n * Fetch pre-processed tokens from the design system endpoint\n * @returns {Promise<Object|null>} Processed tokens ready for caching or null if not found\n */\n async fetchProcessedTokens() {\n const processedUrl = `${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`;\n try {\n return await this.fetchJson(processedUrl);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n // If design system is not synced (400 error), throw with clear message\n if (error.statusCode === 400) {\n throw new APIError(\n 'Design system not synced with Figma. Please sync tokens from Figma before using this design system.',\n 400,\n processedUrl\n );\n }\n throw error;\n }\n }\n\n /**\n * Fetch components configuration\n * @returns {Promise<Object|null>} Components config or null if not found\n */\n async fetchComponentsConfig() {\n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/components-config.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch fonts configuration\n * @returns {Promise<Object|null>} Fonts object with font1, font2, etc. URLs or null\n */\n async fetchFonts() {\n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/font.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch icons configuration\n * @returns {Promise<Object|null>} Icons data or null if not found\n */\n async fetchIcons() {\n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/icons.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch version information\n * @returns {Promise<Object|null>} Version data or null if not found\n */\n async fetchVersion() {\n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/version.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch custom CSS\n * @returns {Promise<string|null>} Custom CSS string or null if not found\n */\n async fetchCustomCss() {\n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/custom.css`;\n try {\n return await this.fetchRaw(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n}\n\nmodule.exports = { APIClient };"],
5
- "mappings": "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",
6
- "names": ["require_constants", "__commonJSMin", "exports", "module", "DEFAULT_API_URL", "LEGACY_API_URL", "CACHE_DIR_NAME", "CACHE_FILES", "ENV_VARS", "require_errors", "__commonJSMin", "exports", "module", "APIError", "message", "statusCode", "url", "CacheError", "operation", "ConfigError", "field", "ProcessingError", "token", "https", "http", "URL", "DEFAULT_API_URL", "LEGACY_API_URL", "ENV_VARS", "APIError", "APIClient", "ffId", "options", "url", "resolve", "reject", "response", "data", "chunk", "parsed", "error", "designSystemUrl", "tokensData", "tokens", "err", "legacyBaseURL", "urls", "results", "processedUrl"]
3
+ "sources": ["../../../lib/core/constants.js", "../../../lib/core/errors.js", "../../../lib/core/file-utils.js", "../../../lib/core/path-utils.js", "../../../lib/core/local-token-reader.js", "../../../lib/core/api-client.js"],
4
+ "sourcesContent": ["/**\n * Configuration constants for FrontFriend Tailwind v2\n */\n\n// API Configuration\nconst DEFAULT_API_URL = 'https://app.frontfriend.dev';\nconst LEGACY_API_URL = 'https://tokens-studio-donux.up.railway.app/api';\n\n// Cache Configuration\nconst CACHE_DIR_NAME = '.cache/frontfriend';\nconst CACHE_TTL_DAYS = 7;\nconst CACHE_TTL_MS = CACHE_TTL_DAYS * 24 * 60 * 60 * 1000;\n\n// File names\nconst CACHE_FILES = {\n JS: [\n 'tokens.js',\n 'variables.js',\n 'semanticVariables.js',\n 'semanticDarkVariables.js',\n 'cls.js',\n 'custom.js'\n ],\n JSON: [\n 'fonts.json',\n 'icons.json',\n 'components-config.json',\n 'version.json',\n 'metadata.json'\n ]\n};\n\n// Environment variables\nconst ENV_VARS = {\n FF_ID: 'FF_ID',\n FF_API_URL: 'FF_API_URL',\n FF_USE_LOCAL: 'FF_USE_LOCAL',\n FF_USE_LOCAL_REGISTRY: 'FF_USE_LOCAL_REGISTRY'\n};\n\nmodule.exports = {\n DEFAULT_API_URL,\n LEGACY_API_URL,\n CACHE_DIR_NAME,\n CACHE_TTL_DAYS,\n CACHE_TTL_MS,\n CACHE_FILES,\n ENV_VARS\n};", "class APIError extends Error {\n constructor(message, statusCode, url) {\n super(message);\n this.name = 'APIError';\n this.statusCode = statusCode;\n this.url = url;\n this.code = `API_${statusCode}`;\n }\n}\n\nclass CacheError extends Error {\n constructor(message, operation) {\n super(message);\n this.name = 'CacheError';\n this.operation = operation;\n this.code = `CACHE_${operation.toUpperCase()}`;\n }\n}\n\nclass ConfigError extends Error {\n constructor(message, field) {\n super(message);\n this.name = 'ConfigError';\n this.field = field;\n this.code = `CONFIG_${field.toUpperCase()}`;\n }\n}\n\nclass ProcessingError extends Error {\n constructor(message, token) {\n super(message);\n this.name = 'ProcessingError';\n this.token = token;\n this.code = 'PROCESSING_ERROR';\n }\n}\n\nmodule.exports = {\n APIError,\n CacheError,\n ConfigError,\n ProcessingError\n};", "const fs = require('fs');\n\n/**\n * Read a JSON file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the JSON file\n * @returns {Object|null} Parsed JSON or null if file not found\n * @throws {Error} If JSON is invalid\n */\nfunction readJsonFileSafe(filepath) {\n try {\n const content = fs.readFileSync(filepath, 'utf8');\n return JSON.parse(content);\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found, return null like API would return 404\n }\n throw error;\n }\n}\n\n/**\n * Read a file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the file\n * @returns {string|null} File content or null if file not found\n * @throws {Error} For other file system errors\n */\nfunction readFileSafe(filepath) {\n try {\n return fs.readFileSync(filepath, 'utf8');\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file with proper formatting\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to write\n * @param {number} indent - Indentation level (default: 2)\n */\nfunction writeJsonFile(filepath, data, indent = 2) {\n const content = JSON.stringify(data, null, indent);\n fs.writeFileSync(filepath, content, 'utf8');\n}\n\n/**\n * Write module.exports file with JSON data\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to export\n */\nfunction writeModuleExportsFile(filepath, data) {\n // Handle empty data cases\n if (data === null || data === undefined || \n (typeof data === 'object' && Object.keys(data).length === 0) ||\n (Array.isArray(data) && data.length === 0)) {\n const emptyContent = Array.isArray(data) ? '[]' : '{}';\n const content = `module.exports = ${emptyContent};`;\n fs.writeFileSync(filepath, content, 'utf8');\n } else {\n const content = `module.exports = ${JSON.stringify(data, null, 2)};`;\n fs.writeFileSync(filepath, content, 'utf8');\n }\n}\n\n/**\n * Check if a file exists\n * @param {string} filepath - Path to check\n * @returns {boolean} True if file exists\n */\nfunction fileExists(filepath) {\n return fs.existsSync(filepath);\n}\n\n/**\n * Create directory recursively\n * @param {string} dirpath - Directory path to create\n */\nfunction ensureDirectoryExists(dirpath) {\n fs.mkdirSync(dirpath, { recursive: true });\n}\n\n/**\n * Remove directory recursively\n * @param {string} dirpath - Directory path to remove\n */\nfunction removeDirectory(dirpath) {\n fs.rmSync(dirpath, { recursive: true, force: true });\n}\n\nmodule.exports = {\n readJsonFileSafe,\n readFileSafe,\n writeJsonFile,\n writeModuleExportsFile,\n fileExists,\n ensureDirectoryExists,\n removeDirectory\n};", "const path = require('path');\nconst { fileExists } = require('./file-utils');\n\n/**\n * Find a file by traversing up the directory tree\n * @param {string} filename - Name of the file to find\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @returns {string|null} Full path to the file or null if not found\n */\nfunction findFileUpward(filename, startDir = process.cwd()) {\n let currentDir = startDir;\n \n while (currentDir !== path.parse(currentDir).root) {\n const filePath = path.join(currentDir, filename);\n \n if (fileExists(filePath)) {\n return filePath;\n }\n \n currentDir = path.dirname(currentDir);\n }\n \n return null;\n}\n\n/**\n * Find a directory by traversing up and checking multiple possible paths\n * @param {string} dirname - Name of the directory to find\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @param {Function} validator - Optional function to validate the directory\n * @returns {string|null} Full path to the directory or null if not found\n */\nfunction findDirectoryUpward(dirname, startDir = process.cwd(), validator = null) {\n const possiblePaths = [];\n let currentDir = startDir;\n const maxLevels = 10; // Prevent infinite loop\n \n // Build list of possible paths\n for (let i = 0; i < maxLevels; i++) {\n // Direct path\n possiblePaths.push(path.join(currentDir, dirname));\n \n // Relative paths up to 3 levels\n if (i < 3) {\n possiblePaths.push(path.join(currentDir, '../'.repeat(i + 1) + dirname));\n }\n \n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) break; // Reached root\n currentDir = parentDir;\n }\n \n // Also check from module directory (for when running from node_modules)\n possiblePaths.push(path.join(__dirname, '../../../', dirname));\n \n // Find first existing directory that passes validation\n for (const dirPath of possiblePaths) {\n if (fileExists(dirPath)) {\n if (!validator || validator(dirPath)) {\n return dirPath;\n }\n }\n }\n \n return null;\n}\n\n/**\n * Find a directory with multiple possible relative paths\n * @param {string[]} possiblePaths - Array of possible paths to check\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @returns {string|null} Full path to the directory or null if not found\n */\nfunction findDirectoryWithPaths(possiblePaths, startDir = process.cwd()) {\n // Build absolute paths from the start directory\n const absolutePaths = possiblePaths.map(p => {\n if (path.isAbsolute(p)) {\n return p;\n }\n return path.join(startDir, p);\n });\n \n // Find first existing path\n for (const dirPath of absolutePaths) {\n if (fileExists(dirPath)) {\n return dirPath;\n }\n }\n \n return null;\n}\n\nmodule.exports = {\n findFileUpward,\n findDirectoryUpward,\n findDirectoryWithPaths\n};", "const path = require('path');\nconst { findDirectoryUpward } = require('./path-utils');\nconst { readJsonFileSafe, readFileSafe, fileExists } = require('./file-utils');\n\n/**\n * LocalTokenReader - Reads tokens directly from the local file system\n * Mimics the APIClient interface but reads from apps/tokens directory\n */\nclass LocalTokenReader {\n constructor(ffId, options = {}) {\n this.ffId = ffId;\n this.tokensBasePath = options.tokensBasePath || this.findTokensPath();\n this.folderMap = this.loadFolderMap();\n this.projectFolder = this.folderMap[ffId];\n \n if (!this.projectFolder) {\n throw new Error(`No folder mapping found for ff-id: ${ffId}`);\n }\n \n this.projectPath = path.join(this.tokensBasePath, this.projectFolder);\n }\n\n /**\n * Find the tokens directory by looking for apps/tokens in parent directories\n */\n findTokensPath() {\n // Try to find apps/tokens first\n let tokensPath = findDirectoryUpward('apps/tokens', process.cwd(), (dir) => {\n return fileExists(path.join(dir, 'folderMap.json'));\n });\n \n // If not found, try just 'tokens'\n if (!tokensPath) {\n tokensPath = findDirectoryUpward('tokens', process.cwd(), (dir) => {\n return fileExists(path.join(dir, 'folderMap.json'));\n });\n }\n \n if (!tokensPath) {\n throw new Error('Could not find tokens directory with folderMap.json');\n }\n \n return tokensPath;\n }\n\n /**\n * Load the folder mapping from folderMap.json\n */\n loadFolderMap() {\n const folderMapPath = path.join(this.tokensBasePath, 'folderMap.json');\n const folderMap = readJsonFileSafe(folderMapPath);\n \n if (!folderMap) {\n throw new Error(`Failed to load folderMap.json: File not found`);\n }\n \n return folderMap;\n }\n\n /**\n * Fetch all token files (global, colors, semantic)\n * Mimics the APIClient.fetchTokens() method\n */\n async fetchTokens() {\n const figmaPath = path.join(this.projectPath, 'figma');\n \n // Try different possible paths for tokens\n const tokenPaths = {\n global: [\n path.join(figmaPath, 'Global Tokens', 'Default.json'),\n path.join(figmaPath, 'global.json')\n ],\n colors: [\n path.join(figmaPath, 'Global Colors', 'Default.json'),\n path.join(figmaPath, 'Global Colors', 'Light.json')\n ],\n semantic: [\n path.join(figmaPath, 'Semantic', 'Light.json'),\n path.join(figmaPath, 'Semantic', 'Default.json')\n ],\n semanticDark: [\n path.join(figmaPath, 'Semantic', 'Dark.json')\n ]\n };\n\n const results = {};\n \n // Try each possible path for each token type\n for (const [key, paths] of Object.entries(tokenPaths)) {\n for (const tokenPath of paths) {\n const content = readJsonFileSafe(tokenPath);\n if (content !== null) {\n results[key] = content;\n break; // Found it, no need to try other paths\n }\n }\n // If not found in any path, set to null\n if (!results[key]) {\n results[key] = null;\n }\n }\n\n return results;\n }\n\n /**\n * Fetch pre-processed tokens (if available in cache folder)\n */\n async fetchProcessedTokens() {\n const cachePath = path.join(this.projectPath, 'cache');\n \n if (!fileExists(cachePath)) {\n return null;\n }\n\n // Read all the cache files that would be in processed tokens\n const cacheFiles = {\n 'tokens.js': 'hashedTokens.js',\n 'variables.js': 'hashedVariables.js', \n 'semanticVariables.js': 'hashedSemanticVariables.js',\n 'semanticDarkVariables.js': 'hashedSemanticDarkVariables.js',\n 'cls.js': 'cls.js',\n 'custom.js': 'custom.js',\n 'fonts.json': 'fonts.json',\n 'icons.json': 'icons.json',\n 'components-config.json': 'encoded-config.json',\n 'version.json': 'version.json'\n };\n\n const processedData = {};\n \n for (const [key, fileName] of Object.entries(cacheFiles)) {\n const filePath = path.join(cachePath, fileName);\n if (key.endsWith('.js')) {\n processedData[key] = readFileSafe(filePath);\n } else {\n processedData[key] = readJsonFileSafe(filePath);\n }\n }\n\n // Only return if we have at least some data\n const hasData = Object.values(processedData).some(val => val !== null);\n return hasData ? processedData : null;\n }\n\n /**\n * Fetch components configuration\n */\n async fetchComponentsConfig() {\n return readJsonFileSafe(path.join(this.projectPath, 'components-config.json'));\n }\n\n /**\n * Fetch fonts configuration\n */\n async fetchFonts() {\n return readJsonFileSafe(path.join(this.projectPath, 'font.json'));\n }\n\n /**\n * Fetch icons configuration\n */\n async fetchIcons() {\n return readJsonFileSafe(path.join(this.projectPath, 'icons.json'));\n }\n\n /**\n * Fetch version information\n */\n async fetchVersion() {\n return readJsonFileSafe(path.join(this.projectPath, 'version.json'));\n }\n\n /**\n * Fetch custom CSS\n */\n async fetchCustomCss() {\n return readFileSafe(path.join(this.projectPath, 'custom.css'));\n }\n\n // Compatibility methods to match APIClient interface\n fetchJson() {\n throw new Error('fetchJson is not implemented in LocalTokenReader. Use specific fetch methods.');\n }\n\n fetchRaw() {\n throw new Error('fetchRaw is not implemented in LocalTokenReader. Use specific fetch methods.');\n }\n}\n\nmodule.exports = { LocalTokenReader };", "const https = require('https');\nconst http = require('http');\nconst { URL } = require('url');\nconst { DEFAULT_API_URL, LEGACY_API_URL, ENV_VARS } = require('./constants');\nconst { APIError } = require('./errors');\nconst { LocalTokenReader } = require('./local-token-reader');\n\nclass APIClient {\n constructor(ffId, options = {}) {\n this.ffId = ffId;\n this.baseURL = options.baseURL || process.env[ENV_VARS.FF_API_URL] || DEFAULT_API_URL;\n \n // Check if we should use local token reader\n if (process.env[ENV_VARS.FF_USE_LOCAL] === 'true') {\n console.log(' \uD83C\uDFE0 Using local token reader');\n this.localReader = new LocalTokenReader(ffId, options);\n }\n }\n\n /**\n * Fetch JSON data from a URL using native https module\n * @param {string} url - The URL to fetch\n * @returns {Promise<any>} Parsed JSON data\n */\n fetchJson(url) {\n return new Promise((resolve, reject) => {\n // Determine if we should use http or https\n const protocol = url.startsWith('https') ? https : http;\n \n protocol.get(url, (response) => {\n let data = '';\n \n // Check for HTTP errors\n if (response.statusCode >= 400) {\n reject(new APIError(\n `HTTP ${response.statusCode}: ${response.statusMessage}`,\n response.statusCode,\n url\n ));\n return;\n }\n\n // Collect response chunks\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n // Parse JSON when complete\n response.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n resolve(parsed);\n } catch (error) {\n reject(new APIError(\n `Invalid JSON response: ${error.message}`,\n response.statusCode,\n url\n ));\n }\n });\n\n // Handle response errors\n response.on('error', (error) => {\n reject(new APIError(\n `Response error: ${error.message}`,\n response.statusCode,\n url\n ));\n });\n }).on('error', (error) => {\n // Handle network errors\n reject(new APIError(\n `Network error: ${error.message}`,\n 0,\n url\n ));\n });\n });\n }\n\n /**\n * Fetch raw content from a URL\n * @param {string} url - The URL to fetch\n * @returns {Promise<string>} Raw text content\n */\n fetchRaw(url) {\n return new Promise((resolve, reject) => {\n // Determine if we should use http or https\n const protocol = url.startsWith('https') ? https : http;\n \n protocol.get(url, (response) => {\n let data = '';\n \n // Check for HTTP errors\n if (response.statusCode >= 400) {\n reject(new APIError(\n `HTTP ${response.statusCode}: ${response.statusMessage}`,\n response.statusCode,\n url\n ));\n return;\n }\n\n // Collect response chunks\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n // Return raw data when complete\n response.on('end', () => {\n resolve(data);\n });\n\n // Handle response errors\n response.on('error', (error) => {\n reject(new APIError(\n `Response error: ${error.message}`,\n response.statusCode,\n url\n ));\n });\n }).on('error', (error) => {\n // Handle network errors\n reject(new APIError(\n `Network error: ${error.message}`,\n 0,\n url\n ));\n });\n });\n }\n\n /**\n * Fetch all token files (global, colors, semantic)\n * @returns {Promise<Object>} Object with all token data\n */\n async fetchTokens() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchTokens();\n }\n \n // First try the new design system endpoint\n try {\n const designSystemUrl = `${this.baseURL}/api/design-systems/${this.ffId}/tokens`;\n const tokensData = await this.fetchJson(designSystemUrl);\n \n // If we have the new format, parse it\n if (tokensData && tokensData.tokens) {\n const tokens = tokensData.tokens;\n \n // Extract specific token sets from the new format\n return {\n global: tokens['Global Tokens/Default'] || tokens['global'] || null,\n colors: tokens['Global Colors/Default'] || tokens['colors'] || null,\n semantic: tokens['Semantic/Light'] || tokens['semantic/light'] || null,\n semanticDark: tokens['Semantic/Dark'] || tokens['semantic/dark'] || null\n };\n }\n } catch (err) {\n // If design system is not synced (400 error), throw with clear message\n if (err.statusCode === 400) {\n throw new APIError(\n 'Design system not synced with Figma. Please sync tokens from Figma before using this design system.',\n 400,\n `${this.baseURL}/api/design-systems/${this.ffId}/tokens`\n );\n }\n // Failed to fetch from design system endpoint, falling back to legacy URLs\n }\n \n // Fall back to legacy token URLs\n // Use legacy API URL for backward compatibility\n const legacyBaseURL = LEGACY_API_URL;\n const urls = {\n global: `${legacyBaseURL}/${this.ffId}/global-tokens/default.json`,\n colors: `${legacyBaseURL}/${this.ffId}/global-colors/default.json`,\n semantic: `${legacyBaseURL}/${this.ffId}/semantic/light.json`,\n semanticDark: `${legacyBaseURL}/${this.ffId}/semantic/dark.json`\n };\n\n const results = await Promise.all([\n this.fetchJson(urls.global).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.colors).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.semantic).catch(err => err.statusCode === 404 ? null : Promise.reject(err)),\n this.fetchJson(urls.semanticDark).catch(err => err.statusCode === 404 ? null : Promise.reject(err))\n ]);\n\n return {\n global: results[0],\n colors: results[1],\n semantic: results[2],\n semanticDark: results[3]\n };\n }\n\n /**\n * Fetch pre-processed tokens from the design system endpoint\n * @returns {Promise<Object|null>} Processed tokens ready for caching or null if not found\n */\n async fetchProcessedTokens() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchProcessedTokens();\n }\n \n const processedUrl = `${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`;\n try {\n return await this.fetchJson(processedUrl);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n // If design system is not synced (400 error), throw with clear message\n if (error.statusCode === 400) {\n throw new APIError(\n 'Design system not synced with Figma. Please sync tokens from Figma before using this design system.',\n 400,\n processedUrl\n );\n }\n throw error;\n }\n }\n\n /**\n * Fetch components configuration\n * @returns {Promise<Object|null>} Components config or null if not found\n */\n async fetchComponentsConfig() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchComponentsConfig();\n }\n \n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/components-config.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch fonts configuration\n * @returns {Promise<Object|null>} Fonts object with font1, font2, etc. URLs or null\n */\n async fetchFonts() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchFonts();\n }\n \n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/font.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch icons configuration\n * @returns {Promise<Object|null>} Icons data or null if not found\n */\n async fetchIcons() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchIcons();\n }\n \n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/icons.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch version information\n * @returns {Promise<Object|null>} Version data or null if not found\n */\n async fetchVersion() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchVersion();\n }\n \n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/version.json`;\n try {\n return await this.fetchJson(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch custom CSS\n * @returns {Promise<string|null>} Custom CSS string or null if not found\n */\n async fetchCustomCss() {\n // Use local reader if available\n if (this.localReader) {\n return this.localReader.fetchCustomCss();\n }\n \n // Always use legacy URL for these endpoints\n const url = `${LEGACY_API_URL}/${this.ffId}/custom.css`;\n try {\n return await this.fetchRaw(url);\n } catch (error) {\n if (error.statusCode === 404) {\n return null;\n }\n throw error;\n }\n }\n}\n\nmodule.exports = { APIClient };"],
5
+ "mappings": "8DAAA,IAAAA,EAAAC,EAAA,CAAAC,GAAAC,IAAA,CAKA,IAAMC,EAAkB,8BAClBC,EAAiB,iDAGjBC,EAAiB,qBAKjBC,EAAc,CAClB,GAAI,CACF,YACA,eACA,uBACA,2BACA,SACA,WACF,EACA,KAAM,CACJ,aACA,aACA,yBACA,eACA,eACF,CACF,EAGMC,EAAW,CACf,MAAO,QACP,WAAY,aACZ,aAAc,eACd,sBAAuB,uBACzB,EAEAL,EAAO,QAAU,CACf,gBAAAC,EACA,eAAAC,EACA,eAAAC,EACA,iBACA,oBACA,YAAAC,EACA,SAAAC,CACF,IChDA,IAAAC,EAAAC,EAAA,CAAAC,GAAAC,IAAA,KAAMC,EAAN,cAAuB,KAAM,CAC3B,YAAYC,EAASC,EAAYC,EAAK,CACpC,MAAMF,CAAO,EACb,KAAK,KAAO,WACZ,KAAK,WAAaC,EAClB,KAAK,IAAMC,EACX,KAAK,KAAO,OAAOD,CAAU,EAC/B,CACF,EAEME,EAAN,cAAyB,KAAM,CAC7B,YAAYH,EAASI,EAAW,CAC9B,MAAMJ,CAAO,EACb,KAAK,KAAO,aACZ,KAAK,UAAYI,EACjB,KAAK,KAAO,SAASA,EAAU,YAAY,CAAC,EAC9C,CACF,EAEMC,EAAN,cAA0B,KAAM,CAC9B,YAAYL,EAASM,EAAO,CAC1B,MAAMN,CAAO,EACb,KAAK,KAAO,cACZ,KAAK,MAAQM,EACb,KAAK,KAAO,UAAUA,EAAM,YAAY,CAAC,EAC3C,CACF,EAEMC,EAAN,cAA8B,KAAM,CAClC,YAAYP,EAASQ,EAAO,CAC1B,MAAMR,CAAO,EACb,KAAK,KAAO,kBACZ,KAAK,MAAQQ,EACb,KAAK,KAAO,kBACd,CACF,EAEAV,EAAO,QAAU,CACf,SAAAC,EACA,WAAAI,EACA,YAAAE,EACA,gBAAAE,CACF,IC1CA,IAAAE,EAAAC,EAAA,CAAAC,GAAAC,IAAA,KAAMC,EAAK,QAAQ,IAAI,EAQvB,SAASC,EAAiBC,EAAU,CAClC,GAAI,CACF,IAAMC,EAAUH,EAAG,aAAaE,EAAU,MAAM,EAChD,OAAO,KAAK,MAAMC,CAAO,CAC3B,OAASC,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASC,EAAaH,EAAU,CAC9B,GAAI,CACF,OAAOF,EAAG,aAAaE,EAAU,MAAM,CACzC,OAASE,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASE,EAAcJ,EAAUK,EAAMC,EAAS,EAAG,CACjD,IAAML,EAAU,KAAK,UAAUI,EAAM,KAAMC,CAAM,EACjDR,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CAOA,SAASM,EAAuBP,EAAUK,EAAM,CAE9C,GAAIA,GAAS,MACR,OAAOA,GAAS,UAAY,OAAO,KAAKA,CAAI,EAAE,SAAW,GACzD,MAAM,QAAQA,CAAI,GAAKA,EAAK,SAAW,EAAI,CAE9C,IAAMJ,EAAU,oBADK,MAAM,QAAQI,CAAI,EAAI,KAAO,IACF,IAChDP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,KAAO,CACL,IAAMA,EAAU,oBAAoB,KAAK,UAAUI,EAAM,KAAM,CAAC,CAAC,IACjEP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CACF,CAOA,SAASO,EAAWR,EAAU,CAC5B,OAAOF,EAAG,WAAWE,CAAQ,CAC/B,CAMA,SAASS,EAAsBC,EAAS,CACtCZ,EAAG,UAAUY,EAAS,CAAE,UAAW,EAAK,CAAC,CAC3C,CAMA,SAASC,EAAgBD,EAAS,CAChCZ,EAAG,OAAOY,EAAS,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,CACrD,CAEAb,EAAO,QAAU,CACf,iBAAAE,EACA,aAAAI,EACA,cAAAC,EACA,uBAAAG,EACA,WAAAC,EACA,sBAAAC,EACA,gBAAAE,CACF,ICpGA,IAAAC,EAAAC,EAAA,CAAAC,GAAAC,IAAA,KAAMC,EAAO,QAAQ,MAAM,EACrB,CAAE,WAAAC,CAAW,EAAI,IAQvB,SAASC,EAAeC,EAAUC,EAAW,QAAQ,IAAI,EAAG,CAC1D,IAAIC,EAAaD,EAEjB,KAAOC,IAAeL,EAAK,MAAMK,CAAU,EAAE,MAAM,CACjD,IAAMC,EAAWN,EAAK,KAAKK,EAAYF,CAAQ,EAE/C,GAAIF,EAAWK,CAAQ,EACrB,OAAOA,EAGTD,EAAaL,EAAK,QAAQK,CAAU,CACtC,CAEA,OAAO,IACT,CASA,SAASE,EAAoBC,EAASJ,EAAW,QAAQ,IAAI,EAAGK,EAAY,KAAM,CAChF,IAAMC,EAAgB,CAAC,EACnBL,EAAaD,EACXO,EAAY,GAGlB,QAAS,EAAI,EAAG,EAAIA,EAAW,IAAK,CAElCD,EAAc,KAAKV,EAAK,KAAKK,EAAYG,CAAO,CAAC,EAG7C,EAAI,GACNE,EAAc,KAAKV,EAAK,KAAKK,EAAY,MAAM,OAAO,EAAI,CAAC,EAAIG,CAAO,CAAC,EAGzE,IAAMI,EAAYZ,EAAK,QAAQK,CAAU,EACzC,GAAIO,IAAcP,EAAY,MAC9BA,EAAaO,CACf,CAGAF,EAAc,KAAKV,EAAK,KAAK,UAAW,YAAaQ,CAAO,CAAC,EAG7D,QAAWK,KAAWH,EACpB,GAAIT,EAAWY,CAAO,IAChB,CAACJ,GAAaA,EAAUI,CAAO,GACjC,OAAOA,EAKb,OAAO,IACT,CAQA,SAASC,EAAuBJ,EAAeN,EAAW,QAAQ,IAAI,EAAG,CAEvE,IAAMW,EAAgBL,EAAc,IAAIM,GAClChB,EAAK,WAAWgB,CAAC,EACZA,EAEFhB,EAAK,KAAKI,EAAUY,CAAC,CAC7B,EAGD,QAAWH,KAAWE,EACpB,GAAId,EAAWY,CAAO,EACpB,OAAOA,EAIX,OAAO,IACT,CAEAd,EAAO,QAAU,CACf,eAAAG,EACA,oBAAAK,EACA,uBAAAO,CACF,IChGA,IAAAG,EAAAC,EAAA,CAAAC,GAAAC,IAAA,KAAMC,EAAO,QAAQ,MAAM,EACrB,CAAE,oBAAAC,CAAoB,EAAI,IAC1B,CAAE,iBAAAC,EAAkB,aAAAC,EAAc,WAAAC,CAAW,EAAI,IAMjDC,EAAN,KAAuB,CACrB,YAAYC,EAAMC,EAAU,CAAC,EAAG,CAM9B,GALA,KAAK,KAAOD,EACZ,KAAK,eAAiBC,EAAQ,gBAAkB,KAAK,eAAe,EACpE,KAAK,UAAY,KAAK,cAAc,EACpC,KAAK,cAAgB,KAAK,UAAUD,CAAI,EAEpC,CAAC,KAAK,cACR,MAAM,IAAI,MAAM,sCAAsCA,CAAI,EAAE,EAG9D,KAAK,YAAcN,EAAK,KAAK,KAAK,eAAgB,KAAK,aAAa,CACtE,CAKA,gBAAiB,CAEf,IAAIQ,EAAaP,EAAoB,cAAe,QAAQ,IAAI,EAAIQ,GAC3DL,EAAWJ,EAAK,KAAKS,EAAK,gBAAgB,CAAC,CACnD,EASD,GANKD,IACHA,EAAaP,EAAoB,SAAU,QAAQ,IAAI,EAAIQ,GAClDL,EAAWJ,EAAK,KAAKS,EAAK,gBAAgB,CAAC,CACnD,GAGC,CAACD,EACH,MAAM,IAAI,MAAM,qDAAqD,EAGvE,OAAOA,CACT,CAKA,eAAgB,CACd,IAAME,EAAgBV,EAAK,KAAK,KAAK,eAAgB,gBAAgB,EAC/DW,EAAYT,EAAiBQ,CAAa,EAEhD,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,+CAA+C,EAGjE,OAAOA,CACT,CAMA,MAAM,aAAc,CAClB,IAAMC,EAAYZ,EAAK,KAAK,KAAK,YAAa,OAAO,EAG/Ca,EAAa,CACjB,OAAQ,CACNb,EAAK,KAAKY,EAAW,gBAAiB,cAAc,EACpDZ,EAAK,KAAKY,EAAW,aAAa,CACpC,EACA,OAAQ,CACNZ,EAAK,KAAKY,EAAW,gBAAiB,cAAc,EACpDZ,EAAK,KAAKY,EAAW,gBAAiB,YAAY,CACpD,EACA,SAAU,CACRZ,EAAK,KAAKY,EAAW,WAAY,YAAY,EAC7CZ,EAAK,KAAKY,EAAW,WAAY,cAAc,CACjD,EACA,aAAc,CACZZ,EAAK,KAAKY,EAAW,WAAY,WAAW,CAC9C,CACF,EAEME,EAAU,CAAC,EAGjB,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQH,CAAU,EAAG,CACrD,QAAWI,KAAaD,EAAO,CAC7B,IAAME,EAAUhB,EAAiBe,CAAS,EAC1C,GAAIC,IAAY,KAAM,CACpBJ,EAAQC,CAAG,EAAIG,EACf,KACF,CACF,CAEKJ,EAAQC,CAAG,IACdD,EAAQC,CAAG,EAAI,KAEnB,CAEA,OAAOD,CACT,CAKA,MAAM,sBAAuB,CAC3B,IAAMK,EAAYnB,EAAK,KAAK,KAAK,YAAa,OAAO,EAErD,GAAI,CAACI,EAAWe,CAAS,EACvB,OAAO,KAIT,IAAMC,EAAa,CACjB,YAAa,kBACb,eAAgB,qBAChB,uBAAwB,6BACxB,2BAA4B,iCAC5B,SAAU,SACV,YAAa,YACb,aAAc,aACd,aAAc,aACd,yBAA0B,sBAC1B,eAAgB,cAClB,EAEMC,EAAgB,CAAC,EAEvB,OAAW,CAACN,EAAKO,CAAQ,IAAK,OAAO,QAAQF,CAAU,EAAG,CACxD,IAAMG,EAAWvB,EAAK,KAAKmB,EAAWG,CAAQ,EAC1CP,EAAI,SAAS,KAAK,EACpBM,EAAcN,CAAG,EAAIZ,EAAaoB,CAAQ,EAE1CF,EAAcN,CAAG,EAAIb,EAAiBqB,CAAQ,CAElD,CAIA,OADgB,OAAO,OAAOF,CAAa,EAAE,KAAKG,GAAOA,IAAQ,IAAI,EACpDH,EAAgB,IACnC,CAKA,MAAM,uBAAwB,CAC5B,OAAOnB,EAAiBF,EAAK,KAAK,KAAK,YAAa,wBAAwB,CAAC,CAC/E,CAKA,MAAM,YAAa,CACjB,OAAOE,EAAiBF,EAAK,KAAK,KAAK,YAAa,WAAW,CAAC,CAClE,CAKA,MAAM,YAAa,CACjB,OAAOE,EAAiBF,EAAK,KAAK,KAAK,YAAa,YAAY,CAAC,CACnE,CAKA,MAAM,cAAe,CACnB,OAAOE,EAAiBF,EAAK,KAAK,KAAK,YAAa,cAAc,CAAC,CACrE,CAKA,MAAM,gBAAiB,CACrB,OAAOG,EAAaH,EAAK,KAAK,KAAK,YAAa,YAAY,CAAC,CAC/D,CAGA,WAAY,CACV,MAAM,IAAI,MAAM,+EAA+E,CACjG,CAEA,UAAW,CACT,MAAM,IAAI,MAAM,8EAA8E,CAChG,CACF,EAEAD,EAAO,QAAU,CAAE,iBAAAM,CAAiB,IC9LpC,IAAMoB,EAAQ,QAAQ,OAAO,EACvBC,EAAO,QAAQ,MAAM,EACrB,CAAE,IAAAC,EAAI,EAAI,QAAQ,KAAK,EACvB,CAAE,gBAAAC,EAAiB,eAAAC,EAAgB,SAAAC,CAAS,EAAI,IAChD,CAAE,SAAAC,CAAS,EAAI,IACf,CAAE,iBAAAC,EAAiB,EAAI,IAEvBC,EAAN,KAAgB,CACd,YAAYC,EAAMC,EAAU,CAAC,EAAG,CAC9B,KAAK,KAAOD,EACZ,KAAK,QAAUC,EAAQ,SAAW,QAAQ,IAAIL,EAAS,UAAU,GAAKF,EAGlE,QAAQ,IAAIE,EAAS,YAAY,IAAM,SACzC,QAAQ,IAAI,uCAAgC,EAC5C,KAAK,YAAc,IAAIE,GAAiBE,EAAMC,CAAO,EAEzD,CAOA,UAAUC,EAAK,CACb,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,EAErBF,EAAI,WAAW,OAAO,EAAIX,EAAQC,GAE1C,IAAIU,EAAMG,GAAa,CAC9B,IAAIC,EAAO,GAGX,GAAID,EAAS,YAAc,IAAK,CAC9BD,EAAO,IAAIP,EACT,QAAQQ,EAAS,UAAU,KAAKA,EAAS,aAAa,GACtDA,EAAS,WACTH,CACF,CAAC,EACD,MACF,CAGAG,EAAS,GAAG,OAASE,GAAU,CAC7BD,GAAQC,CACV,CAAC,EAGDF,EAAS,GAAG,MAAO,IAAM,CACvB,GAAI,CACF,IAAMG,EAAS,KAAK,MAAMF,CAAI,EAC9BH,EAAQK,CAAM,CAChB,OAASC,EAAO,CACdL,EAAO,IAAIP,EACT,0BAA0BY,EAAM,OAAO,GACvCJ,EAAS,WACTH,CACF,CAAC,CACH,CACF,CAAC,EAGDG,EAAS,GAAG,QAAUI,GAAU,CAC9BL,EAAO,IAAIP,EACT,mBAAmBY,EAAM,OAAO,GAChCJ,EAAS,WACTH,CACF,CAAC,CACH,CAAC,CACH,CAAC,EAAE,GAAG,QAAUO,GAAU,CAExBL,EAAO,IAAIP,EACT,kBAAkBY,EAAM,OAAO,GAC/B,EACAP,CACF,CAAC,CACH,CAAC,CACH,CAAC,CACH,CAOA,SAASA,EAAK,CACZ,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,EAErBF,EAAI,WAAW,OAAO,EAAIX,EAAQC,GAE1C,IAAIU,EAAMG,GAAa,CAC9B,IAAIC,EAAO,GAGX,GAAID,EAAS,YAAc,IAAK,CAC9BD,EAAO,IAAIP,EACT,QAAQQ,EAAS,UAAU,KAAKA,EAAS,aAAa,GACtDA,EAAS,WACTH,CACF,CAAC,EACD,MACF,CAGAG,EAAS,GAAG,OAASE,GAAU,CAC7BD,GAAQC,CACV,CAAC,EAGDF,EAAS,GAAG,MAAO,IAAM,CACvBF,EAAQG,CAAI,CACd,CAAC,EAGDD,EAAS,GAAG,QAAUI,GAAU,CAC9BL,EAAO,IAAIP,EACT,mBAAmBY,EAAM,OAAO,GAChCJ,EAAS,WACTH,CACF,CAAC,CACH,CAAC,CACH,CAAC,EAAE,GAAG,QAAUO,GAAU,CAExBL,EAAO,IAAIP,EACT,kBAAkBY,EAAM,OAAO,GAC/B,EACAP,CACF,CAAC,CACH,CAAC,CACH,CAAC,CACH,CAMA,MAAM,aAAc,CAElB,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,YAAY,EAItC,GAAI,CACF,IAAMQ,EAAkB,GAAG,KAAK,OAAO,uBAAuB,KAAK,IAAI,UACjEC,EAAa,MAAM,KAAK,UAAUD,CAAe,EAGvD,GAAIC,GAAcA,EAAW,OAAQ,CACnC,IAAMC,EAASD,EAAW,OAG1B,MAAO,CACL,OAAQC,EAAO,uBAAuB,GAAKA,EAAO,QAAa,KAC/D,OAAQA,EAAO,uBAAuB,GAAKA,EAAO,QAAa,KAC/D,SAAUA,EAAO,gBAAgB,GAAKA,EAAO,gBAAgB,GAAK,KAClE,aAAcA,EAAO,eAAe,GAAKA,EAAO,eAAe,GAAK,IACtE,CACF,CACF,OAASC,EAAK,CAEZ,GAAIA,EAAI,aAAe,IACrB,MAAM,IAAIhB,EACR,sGACA,IACA,GAAG,KAAK,OAAO,uBAAuB,KAAK,IAAI,SACjD,CAGJ,CAIA,IAAMiB,EAAgBnB,EAChBoB,EAAO,CACX,OAAQ,GAAGD,CAAa,IAAI,KAAK,IAAI,8BACrC,OAAQ,GAAGA,CAAa,IAAI,KAAK,IAAI,8BACrC,SAAU,GAAGA,CAAa,IAAI,KAAK,IAAI,uBACvC,aAAc,GAAGA,CAAa,IAAI,KAAK,IAAI,qBAC7C,EAEME,EAAU,MAAM,QAAQ,IAAI,CAChC,KAAK,UAAUD,EAAK,MAAM,EAAE,MAAMF,GAAOA,EAAI,aAAe,IAAM,KAAO,QAAQ,OAAOA,CAAG,CAAC,EAC5F,KAAK,UAAUE,EAAK,MAAM,EAAE,MAAMF,GAAOA,EAAI,aAAe,IAAM,KAAO,QAAQ,OAAOA,CAAG,CAAC,EAC5F,KAAK,UAAUE,EAAK,QAAQ,EAAE,MAAMF,GAAOA,EAAI,aAAe,IAAM,KAAO,QAAQ,OAAOA,CAAG,CAAC,EAC9F,KAAK,UAAUE,EAAK,YAAY,EAAE,MAAMF,GAAOA,EAAI,aAAe,IAAM,KAAO,QAAQ,OAAOA,CAAG,CAAC,CACpG,CAAC,EAED,MAAO,CACL,OAAQG,EAAQ,CAAC,EACjB,OAAQA,EAAQ,CAAC,EACjB,SAAUA,EAAQ,CAAC,EACnB,aAAcA,EAAQ,CAAC,CACzB,CACF,CAMA,MAAM,sBAAuB,CAE3B,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,qBAAqB,EAG/C,IAAMC,EAAe,GAAG,KAAK,OAAO,uBAAuB,KAAK,IAAI,oBACpE,GAAI,CACF,OAAO,MAAM,KAAK,UAAUA,CAAY,CAC1C,OAASR,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAGT,MAAIA,EAAM,aAAe,IACjB,IAAIZ,EACR,sGACA,IACAoB,CACF,EAEIR,CACR,CACF,CAMA,MAAM,uBAAwB,CAE5B,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,sBAAsB,EAIhD,IAAMP,EAAM,GAAGP,CAAc,IAAI,KAAK,IAAI,0BAC1C,GAAI,CACF,OAAO,MAAM,KAAK,UAAUO,CAAG,CACjC,OAASO,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAET,MAAMA,CACR,CACF,CAMA,MAAM,YAAa,CAEjB,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,WAAW,EAIrC,IAAMP,EAAM,GAAGP,CAAc,IAAI,KAAK,IAAI,aAC1C,GAAI,CACF,OAAO,MAAM,KAAK,UAAUO,CAAG,CACjC,OAASO,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAET,MAAMA,CACR,CACF,CAMA,MAAM,YAAa,CAEjB,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,WAAW,EAIrC,IAAMP,EAAM,GAAGP,CAAc,IAAI,KAAK,IAAI,cAC1C,GAAI,CACF,OAAO,MAAM,KAAK,UAAUO,CAAG,CACjC,OAASO,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAET,MAAMA,CACR,CACF,CAMA,MAAM,cAAe,CAEnB,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,aAAa,EAIvC,IAAMP,EAAM,GAAGP,CAAc,IAAI,KAAK,IAAI,gBAC1C,GAAI,CACF,OAAO,MAAM,KAAK,UAAUO,CAAG,CACjC,OAASO,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAET,MAAMA,CACR,CACF,CAMA,MAAM,gBAAiB,CAErB,GAAI,KAAK,YACP,OAAO,KAAK,YAAY,eAAe,EAIzC,IAAMP,EAAM,GAAGP,CAAc,IAAI,KAAK,IAAI,cAC1C,GAAI,CACF,OAAO,MAAM,KAAK,SAASO,CAAG,CAChC,OAASO,EAAO,CACd,GAAIA,EAAM,aAAe,IACvB,OAAO,KAET,MAAMA,CACR,CACF,CACF,EAEA,OAAO,QAAU,CAAE,UAAAV,CAAU",
6
+ "names": ["require_constants", "__commonJSMin", "exports", "module", "DEFAULT_API_URL", "LEGACY_API_URL", "CACHE_DIR_NAME", "CACHE_FILES", "ENV_VARS", "require_errors", "__commonJSMin", "exports", "module", "APIError", "message", "statusCode", "url", "CacheError", "operation", "ConfigError", "field", "ProcessingError", "token", "require_file_utils", "__commonJSMin", "exports", "module", "fs", "readJsonFileSafe", "filepath", "content", "error", "readFileSafe", "writeJsonFile", "data", "indent", "writeModuleExportsFile", "fileExists", "ensureDirectoryExists", "dirpath", "removeDirectory", "require_path_utils", "__commonJSMin", "exports", "module", "path", "fileExists", "findFileUpward", "filename", "startDir", "currentDir", "filePath", "findDirectoryUpward", "dirname", "validator", "possiblePaths", "maxLevels", "parentDir", "dirPath", "findDirectoryWithPaths", "absolutePaths", "p", "require_local_token_reader", "__commonJSMin", "exports", "module", "path", "findDirectoryUpward", "readJsonFileSafe", "readFileSafe", "fileExists", "LocalTokenReader", "ffId", "options", "tokensPath", "dir", "folderMapPath", "folderMap", "figmaPath", "tokenPaths", "results", "key", "paths", "tokenPath", "content", "cachePath", "cacheFiles", "processedData", "fileName", "filePath", "val", "https", "http", "URL", "DEFAULT_API_URL", "LEGACY_API_URL", "ENV_VARS", "APIError", "LocalTokenReader", "APIClient", "ffId", "options", "url", "resolve", "reject", "response", "data", "chunk", "parsed", "error", "designSystemUrl", "tokensData", "tokens", "err", "legacyBaseURL", "urls", "results", "processedUrl"]
7
7
  }
@@ -1,7 +1,7 @@
1
- const fs = require('fs');
2
1
  const path = require('path');
3
- const { CACHE_DIR_NAME, CACHE_TTL_MS, CACHE_FILES } = require('../core/constants');
4
- const { CacheError } = require('../core/errors');
2
+ const { CACHE_DIR_NAME, CACHE_TTL_MS, CACHE_FILES } = require('./constants');
3
+ const { CacheError } = require('./errors');
4
+ const { readJsonFileSafe, readFileSafe, writeJsonFile, writeModuleExportsFile, fileExists, ensureDirectoryExists, removeDirectory } = require('./file-utils');
5
5
 
6
6
  class CacheManager {
7
7
  constructor(appRoot = process.cwd()) {
@@ -24,7 +24,7 @@ class CacheManager {
24
24
  * @returns {boolean} True if cache exists
25
25
  */
26
26
  exists() {
27
- return fs.existsSync(this.cacheDir);
27
+ return fileExists(this.cacheDir);
28
28
  }
29
29
 
30
30
  /**
@@ -37,11 +37,11 @@ class CacheManager {
37
37
  }
38
38
 
39
39
  try {
40
- if (!fs.existsSync(this.metadataFile)) {
40
+ const metadata = readJsonFileSafe(this.metadataFile);
41
+ if (!metadata) {
41
42
  return false;
42
43
  }
43
44
 
44
- const metadata = JSON.parse(fs.readFileSync(this.metadataFile, 'utf-8'));
45
45
  const timestamp = new Date(metadata.timestamp).getTime();
46
46
  const now = Date.now();
47
47
 
@@ -66,21 +66,23 @@ class CacheManager {
66
66
  // Load all .js files
67
67
  for (const file of CACHE_FILES.JS) {
68
68
  const filePath = path.join(this.cacheDir, file);
69
- if (fs.existsSync(filePath)) {
69
+ if (fileExists(filePath)) {
70
70
  // Remove .js extension for key
71
71
  const key = file.replace('.js', '');
72
72
  try {
73
73
  // Use a more secure approach - parse the exported data
74
- const content = fs.readFileSync(filePath, 'utf-8');
75
- // Create a safe evaluation context
76
- const moduleExports = {};
77
- const fakeModule = { exports: moduleExports };
78
-
79
- // Use Function constructor to evaluate in isolated scope
80
- const evalFunc = new Function('module', 'exports', content);
81
- evalFunc(fakeModule, moduleExports);
82
-
83
- data[key] = fakeModule.exports;
74
+ const content = readFileSafe(filePath);
75
+ if (content !== null) {
76
+ // Create a safe evaluation context
77
+ const moduleExports = {};
78
+ const fakeModule = { exports: moduleExports };
79
+
80
+ // Use Function constructor to evaluate in isolated scope
81
+ const evalFunc = new Function('module', 'exports', content);
82
+ evalFunc(fakeModule, moduleExports);
83
+
84
+ data[key] = fakeModule.exports;
85
+ }
84
86
  } catch (e) {
85
87
  // Skip files that can't be parsed
86
88
  }
@@ -90,10 +92,10 @@ class CacheManager {
90
92
  // Load all .json files
91
93
  for (const file of CACHE_FILES.JSON) {
92
94
  const filePath = path.join(this.cacheDir, file);
93
- if (fs.existsSync(filePath)) {
94
- const key = file.replace('.json', '');
95
- const content = fs.readFileSync(filePath, 'utf-8');
96
- data[key] = JSON.parse(content);
95
+ const key = file.replace('.json', '');
96
+ const content = readJsonFileSafe(filePath);
97
+ if (content !== null) {
98
+ data[key] = content;
97
99
  }
98
100
  }
99
101
 
@@ -117,7 +119,7 @@ class CacheManager {
117
119
  save(data) {
118
120
  try {
119
121
  // Create cache directory
120
- fs.mkdirSync(this.cacheDir, { recursive: true });
122
+ ensureDirectoryExists(this.cacheDir);
121
123
 
122
124
  // Save metadata first
123
125
  const metadata = {
@@ -125,10 +127,7 @@ class CacheManager {
125
127
  version: data.metadata?.version || '2.0.0',
126
128
  ffId: data.metadata?.ffId
127
129
  };
128
- fs.writeFileSync(
129
- this.metadataFile,
130
- JSON.stringify(metadata, null, 2)
131
- );
130
+ writeJsonFile(this.metadataFile, metadata);
132
131
 
133
132
  // Save .js files
134
133
  const jsFiles = [
@@ -143,20 +142,7 @@ class CacheManager {
143
142
  for (const key of jsFiles) {
144
143
  if (data[key] !== undefined) {
145
144
  const filePath = path.join(this.cacheDir, `${key}.js`);
146
- const value = data[key];
147
-
148
- // Ensure we have actual data to save
149
- if (value === null || value === undefined ||
150
- (typeof value === 'object' && Object.keys(value).length === 0) ||
151
- (Array.isArray(value) && value.length === 0)) {
152
- // For empty objects/arrays, save a proper empty structure
153
- const emptyContent = Array.isArray(value) ? '[]' : '{}';
154
- const content = `module.exports = ${emptyContent};`;
155
- fs.writeFileSync(filePath, content);
156
- } else {
157
- const content = `module.exports = ${JSON.stringify(value, null, 2)};`;
158
- fs.writeFileSync(filePath, content);
159
- }
145
+ writeModuleExportsFile(filePath, data[key]);
160
146
  }
161
147
  }
162
148
 
@@ -171,7 +157,7 @@ class CacheManager {
171
157
  for (const [key, value] of Object.entries(jsonData)) {
172
158
  if (value !== undefined) {
173
159
  const filePath = path.join(this.cacheDir, `${key}.json`);
174
- fs.writeFileSync(filePath, JSON.stringify(value, null, 2));
160
+ writeJsonFile(filePath, value);
175
161
  }
176
162
  }
177
163
  } catch (error) {
@@ -184,7 +170,7 @@ class CacheManager {
184
170
  */
185
171
  clear() {
186
172
  if (this.exists()) {
187
- fs.rmSync(this.cacheDir, { recursive: true, force: true });
173
+ removeDirectory(this.cacheDir);
188
174
  }
189
175
  }
190
176
  }
@@ -1,3 +1,3 @@
1
- var u=require("https"),a=require("fs"),i=require("path"),{URL:w}=require("url"),l=require("os"),c=process.env.FF_REGISTRY_URL||"https://ff-registry.up.railway.app",p=process.env.FF_USE_LOCAL_REGISTRY==="true",d=class{constructor(e={}){this.appRoot=e.appRoot||process.cwd(),this.framework=e.framework||this.detectFramework(),this.config=e.config||{},this.outputPath=e.outputPath||this.getDefaultOutputPath(),this.overwrite=e.overwrite||!1,this.downloadedComponents=new Set,this.ffId=this.config.ffId||this.config["ff-id"]||null}detectFramework(){let e=i.join(this.appRoot,"package.json");if(a.existsSync(e)){let t=JSON.parse(a.readFileSync(e,"utf8")),s={...t.dependencies,...t.devDependencies};if(s.vue)return"vue";if(s.react)return"react"}return"react"}getDefaultOutputPath(){if(this.config.aliases&&this.config.aliases.ui){let t=this.config.aliases.ui.replace(/^@\//,"");return i.join(this.appRoot,t)}return this.framework==="vue"?i.join(this.appRoot,"src/components/ui"):i.join(this.appRoot,"components/ui")}fetchJson(e){if(p){let t,s=[i.join(process.cwd(),"../../packages/registry"),i.join(process.cwd(),"../../../packages/registry"),i.join(process.cwd(),"../../../../packages/registry"),i.join(__dirname,"../../../registry"),i.join(process.cwd(),"packages/registry")];if(t=s.find(n=>a.existsSync(n)),!t)return Promise.reject(new Error(`Local registry not found. Tried paths: ${s.join(", ")}`));let r=e.replace(c,"").replace(/^\//,""),o=i.join(t,...r.split("/"));try{let n=a.readFileSync(o,"utf8");return Promise.resolve(JSON.parse(n))}catch(n){return n.code==="ENOENT"?Promise.reject(new Error("HTTP 404: Not Found")):Promise.reject(new Error(`Failed to read local file: ${n.message}`))}}return new Promise((t,s)=>{u.get(e,r=>{let o="";if(r.statusCode>=400){s(new Error(`HTTP ${r.statusCode}: ${r.statusMessage}`));return}r.on("data",n=>{o+=n}),r.on("end",()=>{try{t(JSON.parse(o))}catch(n){s(new Error(`Invalid JSON response: ${n.message}`))}})}).on("error",r=>{s(r)})})}async getAllComponents(){try{let e=`${c}/components/${this.framework}/index.json`;return(await this.fetchJson(e)).components||[]}catch(e){return console.error("Failed to fetch component index:",e.message),[]}}async getCustomComponents(){if(!this.ffId)return[];try{let e=`${c}/custom/${this.ffId}/${this.framework}/index.json`;return(await this.fetchJson(e)).components||[]}catch{return[]}}async downloadComponents(e){let t={successful:[],failed:[],dependencies:new Set};for(let s of e)try{let r=await this.downloadComponent(s);t.successful.push(s),r.forEach(o=>t.dependencies.add(o))}catch(r){t.failed.push({component:s,error:r.message})}return{successful:t.successful,failed:t.failed,dependencies:Array.from(t.dependencies)}}async downloadComponent(e){if(this.downloadedComponents.has(e))return[];console.log(`\u{1F4E5} Downloading ${e}...`);let t,s=!1;if(this.ffId){let o=`${c}/custom/${this.ffId}/${this.framework}/${e}.json`;try{t=await this.fetchJson(o),s=!0}catch{}}if(!t){let o=`${c}/components/${this.framework}/${e}.json`;try{t=await this.fetchJson(o)}catch(n){throw n.message.includes("404")?new Error(`Component "${e}" not found`):new Error(`Failed to fetch ${e}: ${n.message}`)}}if(!t.files||!Array.isArray(t.files))throw new Error(`Invalid component data for ${e}`);for(let o of t.files)await this.writeComponentFile(o);this.downloadedComponents.add(e),console.log(` \u2713 ${e} downloaded`);let r=[...t.dependencies||[]];if(t.registryDependencies&&t.registryDependencies.length>0){console.log(` \u{1F4E6} Installing registry dependencies: ${t.registryDependencies.join(", ")}`);for(let o of t.registryDependencies)try{(await this.downloadComponent(o)).forEach(f=>r.push(f))}catch(n){console.warn(` \u26A0\uFE0F Failed to download dependency ${o}: ${n.message}`)}}return r}async writeComponentFile(e){let t=e.name.split("/").join(i.sep),s=i.join(this.outputPath,t),r=i.dirname(s);if(a.existsSync(r)||a.mkdirSync(r,{recursive:!0}),a.existsSync(s)&&!this.overwrite){console.log(` \u26A0\uFE0F Skipping ${e.name} (already exists)`);return}let o=e.content;l.EOL!==`
2
- `&&(o=e.content.replace(/\n/g,l.EOL)),a.writeFileSync(s,o,"utf8")}};module.exports={ComponentDownloader:d};
1
+ var d=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var m=d((ee,g)=>{var j="https://app.frontfriend.dev",P="https://tokens-studio-donux.up.railway.app/api",D=".cache/frontfriend",R={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","cls.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},$={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_USE_LOCAL_REGISTRY:"FF_USE_LOCAL_REGISTRY"};g.exports={DEFAULT_API_URL:j,LEGACY_API_URL:P,CACHE_DIR_NAME:D,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:R,ENV_VARS:$}});var p=d((te,E)=>{var u=require("fs");function v(r){try{let e=u.readFileSync(r,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function x(r){try{return u.readFileSync(r,"utf8")}catch(e){if(e.code==="ENOENT")return null;throw e}}function T(r,e,t=2){let n=JSON.stringify(e,null,t);u.writeFileSync(r,n,"utf8")}function k(r,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let n=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;u.writeFileSync(r,n,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;u.writeFileSync(r,t,"utf8")}}function I(r){return u.existsSync(r)}function O(r){u.mkdirSync(r,{recursive:!0})}function J(r){u.rmSync(r,{recursive:!0,force:!0})}E.exports={readJsonFileSafe:v,readFileSafe:x,writeJsonFile:T,writeModuleExportsFile:k,fileExists:I,ensureDirectoryExists:O,removeDirectory:J}});var F=d((ne,_)=>{var c=require("path"),{fileExists:h}=p();function U(r,e=process.cwd()){let t=e;for(;t!==c.parse(t).root;){let n=c.join(t,r);if(h(n))return n;t=c.dirname(t)}return null}function q(r,e=process.cwd(),t=null){let n=[],s=e,i=10;for(let o=0;o<i;o++){n.push(c.join(s,r)),o<3&&n.push(c.join(s,"../".repeat(o+1)+r));let f=c.dirname(s);if(f===s)break;s=f}n.push(c.join(__dirname,"../../../",r));for(let o of n)if(h(o)&&(!t||t(o)))return o;return null}function b(r,e=process.cwd()){let t=r.map(n=>c.isAbsolute(n)?n:c.join(e,n));for(let n of t)if(h(n))return n;return null}_.exports={findFileUpward:U,findDirectoryUpward:q,findDirectoryWithPaths:b}});var C=d((re,S)=>{var Y=require("path"),{fileExists:H}=p();function N(r=process.cwd()){let e=Y.join(r,".env.local");return H(e)?(require("dotenv").config({path:e}),console.log("\u{1F4C4} Loaded .env.local"),!0):!1}function G(r,e=void 0){return process.env[r]||e}function V(r){return process.env[r]==="true"}S.exports={loadEnvLocal:N,getEnvVar:G,isEnvTrue:V}});var M=require("https"),w=require("fs"),a=require("path"),{URL:se}=require("url"),A=require("os"),{ENV_VARS:z}=m(),{findDirectoryWithPaths:W}=F(),{readJsonFileSafe:B,fileExists:K,ensureDirectoryExists:Q}=p(),{isEnvTrue:L}=C(),l=process.env.FF_REGISTRY_URL||"https://ff-registry.up.railway.app",X=L("FF_USE_LOCAL_REGISTRY")||L(z.FF_USE_LOCAL),y=class{constructor(e={}){this.appRoot=e.appRoot||process.cwd(),this.framework=e.framework||this.detectFramework(),this.config=e.config||{},this.outputPath=e.outputPath||this.getDefaultOutputPath(),this.overwrite=e.overwrite||!1,this.downloadedComponents=new Set,this.ffId=this.config.ffId||this.config["ff-id"]||null}detectFramework(){let e=a.join(this.appRoot,"package.json");if(w.existsSync(e)){let t=JSON.parse(w.readFileSync(e,"utf8")),n={...t.dependencies,...t.devDependencies};if(n.vue)return"vue";if(n.react)return"react"}return"react"}getDefaultOutputPath(){if(this.config.aliases&&this.config.aliases.ui){let t=this.config.aliases.ui.replace(/^@\//,"");return a.join(this.appRoot,t)}return this.framework==="vue"?a.join(this.appRoot,"src/components/ui"):a.join(this.appRoot,"components/ui")}fetchJson(e){if(X){let t=["../../packages/registry","../../../packages/registry","../../../../packages/registry",a.join(__dirname,"../../../registry"),"packages/registry"],n=W(t,process.cwd());if(!n)return Promise.reject(new Error(`Local registry not found. Tried paths: ${t.join(", ")}`));let s=e.replace(l,"").replace(/^\//,""),i=a.join(n,...s.split("/")),o=B(i);return o===null?Promise.reject(new Error("HTTP 404: Not Found")):Promise.resolve(o)}return new Promise((t,n)=>{M.get(e,s=>{let i="";if(s.statusCode>=400){n(new Error(`HTTP ${s.statusCode}: ${s.statusMessage}`));return}s.on("data",o=>{i+=o}),s.on("end",()=>{try{t(JSON.parse(i))}catch(o){n(new Error(`Invalid JSON response: ${o.message}`))}})}).on("error",s=>{n(s)})})}async getAllComponents(){try{let e=`${l}/components/${this.framework}/index.json`;return(await this.fetchJson(e)).components||[]}catch(e){return console.error("Failed to fetch component index:",e.message),[]}}async getCustomComponents(){if(!this.ffId)return[];try{let e=`${l}/custom/${this.ffId}/${this.framework}/index.json`;return(await this.fetchJson(e)).components||[]}catch{return[]}}async downloadComponents(e){let t={successful:[],failed:[],dependencies:new Set};for(let n of e)try{let s=await this.downloadComponent(n);t.successful.push(n),s.forEach(i=>t.dependencies.add(i))}catch(s){t.failed.push({component:n,error:s.message})}return{successful:t.successful,failed:t.failed,dependencies:Array.from(t.dependencies)}}async downloadComponent(e){if(this.downloadedComponents.has(e))return[];console.log(`\u{1F4E5} Downloading ${e}...`);let t,n=!1;if(this.ffId){let i=`${l}/custom/${this.ffId}/${this.framework}/${e}.json`;try{t=await this.fetchJson(i),n=!0}catch{}}if(!t){let i=`${l}/components/${this.framework}/${e}.json`;try{t=await this.fetchJson(i)}catch(o){throw o.message.includes("404")?new Error(`Component "${e}" not found`):new Error(`Failed to fetch ${e}: ${o.message}`)}}if(!t.files||!Array.isArray(t.files))throw new Error(`Invalid component data for ${e}`);for(let i of t.files)await this.writeComponentFile(i);this.downloadedComponents.add(e),console.log(` \u2713 ${e} downloaded`);let s=[...t.dependencies||[]];if(t.registryDependencies&&t.registryDependencies.length>0){console.log(` \u{1F4E6} Installing registry dependencies: ${t.registryDependencies.join(", ")}`);for(let i of t.registryDependencies)try{(await this.downloadComponent(i)).forEach(f=>s.push(f))}catch(o){console.warn(` \u26A0\uFE0F Failed to download dependency ${i}: ${o.message}`)}}return s}async writeComponentFile(e){let t=e.name.split("/").join(a.sep),n=a.join(this.outputPath,t),s=a.dirname(n);if(Q(s),K(n)&&!this.overwrite){console.log(` \u26A0\uFE0F Skipping ${e.name} (already exists)`);return}let i=e.content;A.EOL!==`
2
+ `&&(i=e.content.replace(/\n/g,A.EOL)),w.writeFileSync(n,i,"utf8")}};module.exports={ComponentDownloader:y};
3
3
  //# sourceMappingURL=component-downloader.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../lib/core/component-downloader.js"],
4
- "sourcesContent": ["const https = require('https');\nconst fs = require('fs');\nconst path = require('path');\nconst { URL } = require('url');\nconst os = require('os');\n\nconst REGISTRY_URL = process.env.FF_REGISTRY_URL || 'https://ff-registry.up.railway.app';\nconst USE_LOCAL_REGISTRY = process.env.FF_USE_LOCAL_REGISTRY === 'true';\n\nclass ComponentDownloader {\n constructor(options = {}) {\n this.appRoot = options.appRoot || process.cwd();\n this.framework = options.framework || this.detectFramework();\n this.config = options.config || {};\n this.outputPath = options.outputPath || this.getDefaultOutputPath();\n this.overwrite = options.overwrite || false;\n this.downloadedComponents = new Set();\n this.ffId = this.config.ffId || this.config['ff-id'] || null;\n }\n\n /**\n * Detect framework from package.json\n */\n detectFramework() {\n const packageJsonPath = path.join(this.appRoot, 'package.json');\n \n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n \n if (deps.vue) {\n return 'vue';\n } else if (deps.react) {\n return 'react';\n }\n }\n \n // Default to React if can't detect\n return 'react';\n }\n\n /**\n * Get default output path based on framework and config\n */\n getDefaultOutputPath() {\n // Check if config has ui alias\n if (this.config.aliases && this.config.aliases.ui) {\n const uiAlias = this.config.aliases.ui;\n // Convert alias to actual path (e.g., @/components/ui -> components/ui)\n const cleanPath = uiAlias.replace(/^@\\//, '');\n return path.join(this.appRoot, cleanPath);\n }\n \n // Fallback to default paths\n if (this.framework === 'vue') {\n return path.join(this.appRoot, 'src/components/ui');\n }\n return path.join(this.appRoot, 'components/ui');\n }\n\n /**\n * Fetch JSON from URL or local file\n */\n fetchJson(url) {\n // If using local registry, read from file system\n if (USE_LOCAL_REGISTRY) {\n // Try to find the registry in the monorepo structure\n let registryPath;\n \n // Try multiple paths to find the registry\n const possiblePaths = [\n // From apps/prj to packages/registry\n path.join(process.cwd(), '../../packages/registry'),\n // From any deep directory in monorepo\n path.join(process.cwd(), '../../../packages/registry'),\n path.join(process.cwd(), '../../../../packages/registry'),\n // From the package itself\n path.join(__dirname, '../../../registry'),\n // Direct path if running from monorepo root\n path.join(process.cwd(), 'packages/registry')\n ];\n \n registryPath = possiblePaths.find(p => fs.existsSync(p));\n \n if (!registryPath) {\n return Promise.reject(new Error(`Local registry not found. Tried paths: ${possiblePaths.join(', ')}`));\n }\n \n // Extract the path from the URL and construct proper local path\n const urlPath = url.replace(REGISTRY_URL, '').replace(/^\\//, '');\n const localPath = path.join(registryPath, ...urlPath.split('/'));\n \n try {\n const content = fs.readFileSync(localPath, 'utf8');\n return Promise.resolve(JSON.parse(content));\n } catch (error) {\n // Return 404-like error for missing files\n if (error.code === 'ENOENT') {\n return Promise.reject(new Error('HTTP 404: Not Found'));\n }\n return Promise.reject(new Error(`Failed to read local file: ${error.message}`));\n }\n }\n\n return new Promise((resolve, reject) => {\n https.get(url, (response) => {\n let data = '';\n \n if (response.statusCode >= 400) {\n reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));\n return;\n }\n\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n response.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch (error) {\n reject(new Error(`Invalid JSON response: ${error.message}`));\n }\n });\n\n }).on('error', (error) => {\n reject(error);\n });\n });\n }\n\n /**\n * Get all available components from registry\n */\n async getAllComponents() {\n try {\n const url = `${REGISTRY_URL}/components/${this.framework}/index.json`;\n const index = await this.fetchJson(url);\n return index.components || [];\n } catch (error) {\n console.error('Failed to fetch component index:', error.message);\n return [];\n }\n }\n\n /**\n * Get all custom components for this ff-id\n */\n async getCustomComponents() {\n if (!this.ffId) {\n return [];\n }\n \n try {\n const url = `${REGISTRY_URL}/custom/${this.ffId}/${this.framework}/index.json`;\n const index = await this.fetchJson(url);\n return index.components || [];\n } catch (error) {\n // Custom components might not exist, that's ok\n return [];\n }\n }\n\n /**\n * Download multiple components\n */\n async downloadComponents(components) {\n const results = {\n successful: [],\n failed: [],\n dependencies: new Set()\n };\n\n for (const component of components) {\n try {\n const deps = await this.downloadComponent(component);\n results.successful.push(component);\n \n // Add dependencies\n deps.forEach(dep => results.dependencies.add(dep));\n } catch (error) {\n results.failed.push({\n component,\n error: error.message\n });\n }\n }\n\n return {\n successful: results.successful,\n failed: results.failed,\n dependencies: Array.from(results.dependencies)\n };\n }\n\n /**\n * Download a single component and its registry dependencies\n */\n async downloadComponent(componentName) {\n // Avoid downloading the same component twice\n if (this.downloadedComponents.has(componentName)) {\n return [];\n }\n\n console.log(`\uD83D\uDCE5 Downloading ${componentName}...`);\n\n // Try to fetch from custom components first if ff-id is available\n let componentData;\n let isCustom = false;\n \n if (this.ffId) {\n const customUrl = `${REGISTRY_URL}/custom/${this.ffId}/${this.framework}/${componentName}.json`;\n try {\n componentData = await this.fetchJson(customUrl);\n isCustom = true;\n } catch (error) {\n // Custom component not found, try standard registry\n }\n }\n \n // If not found in custom, try standard registry\n if (!componentData) {\n const url = `${REGISTRY_URL}/components/${this.framework}/${componentName}.json`;\n \n try {\n componentData = await this.fetchJson(url);\n } catch (error) {\n // Check if it's a 404 (component not found)\n if (error.message.includes('404')) {\n throw new Error(`Component \"${componentName}\" not found`);\n }\n throw new Error(`Failed to fetch ${componentName}: ${error.message}`);\n }\n }\n\n // Validate component data\n if (!componentData.files || !Array.isArray(componentData.files)) {\n throw new Error(`Invalid component data for ${componentName}`);\n }\n\n // Write component files\n for (const file of componentData.files) {\n await this.writeComponentFile(file);\n }\n\n this.downloadedComponents.add(componentName);\n console.log(` \u2713 ${componentName} downloaded`);\n\n // Download registry dependencies\n const allDependencies = [...(componentData.dependencies || [])];\n \n if (componentData.registryDependencies && componentData.registryDependencies.length > 0) {\n console.log(` \uD83D\uDCE6 Installing registry dependencies: ${componentData.registryDependencies.join(', ')}`);\n \n for (const dep of componentData.registryDependencies) {\n try {\n const depDeps = await this.downloadComponent(dep);\n depDeps.forEach(d => allDependencies.push(d));\n } catch (error) {\n console.warn(` \u26A0\uFE0F Failed to download dependency ${dep}: ${error.message}`);\n }\n }\n }\n\n return allDependencies;\n }\n\n /**\n * Write component file to disk\n */\n async writeComponentFile(file) {\n // Normalize the file path for the current platform\n // Convert forward slashes to the platform-specific separator\n const normalizedFileName = file.name.split('/').join(path.sep);\n const filePath = path.join(this.outputPath, normalizedFileName);\n const dir = path.dirname(filePath);\n\n // Create directory if it doesn't exist\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Check if file exists and overwrite setting\n if (fs.existsSync(filePath) && !this.overwrite) {\n console.log(` \u26A0\uFE0F Skipping ${file.name} (already exists)`);\n return;\n }\n\n // Normalize line endings to match the platform\n // This prevents git from showing every line as changed\n let normalizedContent = file.content;\n if (os.EOL !== '\\n') {\n // On Windows, replace LF with CRLF\n normalizedContent = file.content.replace(/\\n/g, os.EOL);\n }\n\n // Write file\n fs.writeFileSync(filePath, normalizedContent, 'utf8');\n }\n}\n\nmodule.exports = { ComponentDownloader };"],
5
- "mappings": "AAAA,IAAMA,EAAQ,QAAQ,OAAO,EACvBC,EAAK,QAAQ,IAAI,EACjBC,EAAO,QAAQ,MAAM,EACrB,CAAE,IAAAC,CAAI,EAAI,QAAQ,KAAK,EACvBC,EAAK,QAAQ,IAAI,EAEjBC,EAAe,QAAQ,IAAI,iBAAmB,qCAC9CC,EAAqB,QAAQ,IAAI,wBAA0B,OAE3DC,EAAN,KAA0B,CACxB,YAAYC,EAAU,CAAC,EAAG,CACxB,KAAK,QAAUA,EAAQ,SAAW,QAAQ,IAAI,EAC9C,KAAK,UAAYA,EAAQ,WAAa,KAAK,gBAAgB,EAC3D,KAAK,OAASA,EAAQ,QAAU,CAAC,EACjC,KAAK,WAAaA,EAAQ,YAAc,KAAK,qBAAqB,EAClE,KAAK,UAAYA,EAAQ,WAAa,GACtC,KAAK,qBAAuB,IAAI,IAChC,KAAK,KAAO,KAAK,OAAO,MAAQ,KAAK,OAAO,OAAO,GAAK,IAC1D,CAKA,iBAAkB,CAChB,IAAMC,EAAkBP,EAAK,KAAK,KAAK,QAAS,cAAc,EAE9D,GAAID,EAAG,WAAWQ,CAAe,EAAG,CAClC,IAAMC,EAAc,KAAK,MAAMT,EAAG,aAAaQ,EAAiB,MAAM,CAAC,EACjEE,EAAO,CAAE,GAAGD,EAAY,aAAc,GAAGA,EAAY,eAAgB,EAE3E,GAAIC,EAAK,IACP,MAAO,MACF,GAAIA,EAAK,MACd,MAAO,OAEX,CAGA,MAAO,OACT,CAKA,sBAAuB,CAErB,GAAI,KAAK,OAAO,SAAW,KAAK,OAAO,QAAQ,GAAI,CAGjD,IAAMC,EAFU,KAAK,OAAO,QAAQ,GAEV,QAAQ,OAAQ,EAAE,EAC5C,OAAOV,EAAK,KAAK,KAAK,QAASU,CAAS,CAC1C,CAGA,OAAI,KAAK,YAAc,MACdV,EAAK,KAAK,KAAK,QAAS,mBAAmB,EAE7CA,EAAK,KAAK,KAAK,QAAS,eAAe,CAChD,CAKA,UAAUW,EAAK,CAEb,GAAIP,EAAoB,CAEtB,IAAIQ,EAGEC,EAAgB,CAEpBb,EAAK,KAAK,QAAQ,IAAI,EAAG,yBAAyB,EAElDA,EAAK,KAAK,QAAQ,IAAI,EAAG,4BAA4B,EACrDA,EAAK,KAAK,QAAQ,IAAI,EAAG,+BAA+B,EAExDA,EAAK,KAAK,UAAW,mBAAmB,EAExCA,EAAK,KAAK,QAAQ,IAAI,EAAG,mBAAmB,CAC9C,EAIA,GAFAY,EAAeC,EAAc,KAAKC,GAAKf,EAAG,WAAWe,CAAC,CAAC,EAEnD,CAACF,EACH,OAAO,QAAQ,OAAO,IAAI,MAAM,0CAA0CC,EAAc,KAAK,IAAI,CAAC,EAAE,CAAC,EAIvG,IAAME,EAAUJ,EAAI,QAAQR,EAAc,EAAE,EAAE,QAAQ,MAAO,EAAE,EACzDa,EAAYhB,EAAK,KAAKY,EAAc,GAAGG,EAAQ,MAAM,GAAG,CAAC,EAE/D,GAAI,CACF,IAAME,EAAUlB,EAAG,aAAaiB,EAAW,MAAM,EACjD,OAAO,QAAQ,QAAQ,KAAK,MAAMC,CAAO,CAAC,CAC5C,OAASC,EAAO,CAEd,OAAIA,EAAM,OAAS,SACV,QAAQ,OAAO,IAAI,MAAM,qBAAqB,CAAC,EAEjD,QAAQ,OAAO,IAAI,MAAM,8BAA8BA,EAAM,OAAO,EAAE,CAAC,CAChF,CACF,CAEA,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtCtB,EAAM,IAAIa,EAAMU,GAAa,CAC3B,IAAIC,EAAO,GAEX,GAAID,EAAS,YAAc,IAAK,CAC9BD,EAAO,IAAI,MAAM,QAAQC,EAAS,UAAU,KAAKA,EAAS,aAAa,EAAE,CAAC,EAC1E,MACF,CAEAA,EAAS,GAAG,OAASE,GAAU,CAC7BD,GAAQC,CACV,CAAC,EAEDF,EAAS,GAAG,MAAO,IAAM,CACvB,GAAI,CACFF,EAAQ,KAAK,MAAMG,CAAI,CAAC,CAC1B,OAASJ,EAAO,CACdE,EAAO,IAAI,MAAM,0BAA0BF,EAAM,OAAO,EAAE,CAAC,CAC7D,CACF,CAAC,CAEH,CAAC,EAAE,GAAG,QAAUA,GAAU,CACxBE,EAAOF,CAAK,CACd,CAAC,CACH,CAAC,CACH,CAKA,MAAM,kBAAmB,CACvB,GAAI,CACF,IAAMP,EAAM,GAAGR,CAAY,eAAe,KAAK,SAAS,cAExD,OADc,MAAM,KAAK,UAAUQ,CAAG,GACzB,YAAc,CAAC,CAC9B,OAASO,EAAO,CACd,eAAQ,MAAM,mCAAoCA,EAAM,OAAO,EACxD,CAAC,CACV,CACF,CAKA,MAAM,qBAAsB,CAC1B,GAAI,CAAC,KAAK,KACR,MAAO,CAAC,EAGV,GAAI,CACF,IAAMP,EAAM,GAAGR,CAAY,WAAW,KAAK,IAAI,IAAI,KAAK,SAAS,cAEjE,OADc,MAAM,KAAK,UAAUQ,CAAG,GACzB,YAAc,CAAC,CAC9B,MAAgB,CAEd,MAAO,CAAC,CACV,CACF,CAKA,MAAM,mBAAmBa,EAAY,CACnC,IAAMC,EAAU,CACd,WAAY,CAAC,EACb,OAAQ,CAAC,EACT,aAAc,IAAI,GACpB,EAEA,QAAWC,KAAaF,EACtB,GAAI,CACF,IAAMf,EAAO,MAAM,KAAK,kBAAkBiB,CAAS,EACnDD,EAAQ,WAAW,KAAKC,CAAS,EAGjCjB,EAAK,QAAQkB,GAAOF,EAAQ,aAAa,IAAIE,CAAG,CAAC,CACnD,OAAST,EAAO,CACdO,EAAQ,OAAO,KAAK,CAClB,UAAAC,EACA,MAAOR,EAAM,OACf,CAAC,CACH,CAGF,MAAO,CACL,WAAYO,EAAQ,WACpB,OAAQA,EAAQ,OAChB,aAAc,MAAM,KAAKA,EAAQ,YAAY,CAC/C,CACF,CAKA,MAAM,kBAAkBG,EAAe,CAErC,GAAI,KAAK,qBAAqB,IAAIA,CAAa,EAC7C,MAAO,CAAC,EAGV,QAAQ,IAAI,yBAAkBA,CAAa,KAAK,EAGhD,IAAIC,EACAC,EAAW,GAEf,GAAI,KAAK,KAAM,CACb,IAAMC,EAAY,GAAG5B,CAAY,WAAW,KAAK,IAAI,IAAI,KAAK,SAAS,IAAIyB,CAAa,QACxF,GAAI,CACFC,EAAgB,MAAM,KAAK,UAAUE,CAAS,EAC9CD,EAAW,EACb,MAAgB,CAEhB,CACF,CAGA,GAAI,CAACD,EAAe,CAClB,IAAMlB,EAAM,GAAGR,CAAY,eAAe,KAAK,SAAS,IAAIyB,CAAa,QAEzE,GAAI,CACFC,EAAgB,MAAM,KAAK,UAAUlB,CAAG,CAC1C,OAASO,EAAO,CAEd,MAAIA,EAAM,QAAQ,SAAS,KAAK,EACxB,IAAI,MAAM,cAAcU,CAAa,aAAa,EAEpD,IAAI,MAAM,mBAAmBA,CAAa,KAAKV,EAAM,OAAO,EAAE,CACtE,CACF,CAGA,GAAI,CAACW,EAAc,OAAS,CAAC,MAAM,QAAQA,EAAc,KAAK,EAC5D,MAAM,IAAI,MAAM,8BAA8BD,CAAa,EAAE,EAI/D,QAAWI,KAAQH,EAAc,MAC/B,MAAM,KAAK,mBAAmBG,CAAI,EAGpC,KAAK,qBAAqB,IAAIJ,CAAa,EAC3C,QAAQ,IAAI,aAAQA,CAAa,aAAa,EAG9C,IAAMK,EAAkB,CAAC,GAAIJ,EAAc,cAAgB,CAAC,CAAE,EAE9D,GAAIA,EAAc,sBAAwBA,EAAc,qBAAqB,OAAS,EAAG,CACvF,QAAQ,IAAI,kDAA2CA,EAAc,qBAAqB,KAAK,IAAI,CAAC,EAAE,EAEtG,QAAWF,KAAOE,EAAc,qBAC9B,GAAI,EACc,MAAM,KAAK,kBAAkBF,CAAG,GACxC,QAAQO,GAAKD,EAAgB,KAAKC,CAAC,CAAC,CAC9C,OAAShB,EAAO,CACd,QAAQ,KAAK,kDAAwCS,CAAG,KAAKT,EAAM,OAAO,EAAE,CAC9E,CAEJ,CAEA,OAAOe,CACT,CAKA,MAAM,mBAAmBD,EAAM,CAG7B,IAAMG,EAAqBH,EAAK,KAAK,MAAM,GAAG,EAAE,KAAKhC,EAAK,GAAG,EACvDoC,EAAWpC,EAAK,KAAK,KAAK,WAAYmC,CAAkB,EACxDE,EAAMrC,EAAK,QAAQoC,CAAQ,EAQjC,GALKrC,EAAG,WAAWsC,CAAG,GACpBtC,EAAG,UAAUsC,EAAK,CAAE,UAAW,EAAK,CAAC,EAInCtC,EAAG,WAAWqC,CAAQ,GAAK,CAAC,KAAK,UAAW,CAC9C,QAAQ,IAAI,6BAAmBJ,EAAK,IAAI,mBAAmB,EAC3D,MACF,CAIA,IAAIM,EAAoBN,EAAK,QACzB9B,EAAG,MAAQ;AAAA,IAEboC,EAAoBN,EAAK,QAAQ,QAAQ,MAAO9B,EAAG,GAAG,GAIxDH,EAAG,cAAcqC,EAAUE,EAAmB,MAAM,CACtD,CACF,EAEA,OAAO,QAAU,CAAE,oBAAAjC,CAAoB",
6
- "names": ["https", "fs", "path", "URL", "os", "REGISTRY_URL", "USE_LOCAL_REGISTRY", "ComponentDownloader", "options", "packageJsonPath", "packageJson", "deps", "cleanPath", "url", "registryPath", "possiblePaths", "p", "urlPath", "localPath", "content", "error", "resolve", "reject", "response", "data", "chunk", "components", "results", "component", "dep", "componentName", "componentData", "isCustom", "customUrl", "file", "allDependencies", "d", "normalizedFileName", "filePath", "dir", "normalizedContent"]
3
+ "sources": ["../../../lib/core/constants.js", "../../../lib/core/file-utils.js", "../../../lib/core/path-utils.js", "../../../lib/core/env-utils.js", "../../../lib/core/component-downloader.js"],
4
+ "sourcesContent": ["/**\n * Configuration constants for FrontFriend Tailwind v2\n */\n\n// API Configuration\nconst DEFAULT_API_URL = 'https://app.frontfriend.dev';\nconst LEGACY_API_URL = 'https://tokens-studio-donux.up.railway.app/api';\n\n// Cache Configuration\nconst CACHE_DIR_NAME = '.cache/frontfriend';\nconst CACHE_TTL_DAYS = 7;\nconst CACHE_TTL_MS = CACHE_TTL_DAYS * 24 * 60 * 60 * 1000;\n\n// File names\nconst CACHE_FILES = {\n JS: [\n 'tokens.js',\n 'variables.js',\n 'semanticVariables.js',\n 'semanticDarkVariables.js',\n 'cls.js',\n 'custom.js'\n ],\n JSON: [\n 'fonts.json',\n 'icons.json',\n 'components-config.json',\n 'version.json',\n 'metadata.json'\n ]\n};\n\n// Environment variables\nconst ENV_VARS = {\n FF_ID: 'FF_ID',\n FF_API_URL: 'FF_API_URL',\n FF_USE_LOCAL: 'FF_USE_LOCAL',\n FF_USE_LOCAL_REGISTRY: 'FF_USE_LOCAL_REGISTRY'\n};\n\nmodule.exports = {\n DEFAULT_API_URL,\n LEGACY_API_URL,\n CACHE_DIR_NAME,\n CACHE_TTL_DAYS,\n CACHE_TTL_MS,\n CACHE_FILES,\n ENV_VARS\n};", "const fs = require('fs');\n\n/**\n * Read a JSON file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the JSON file\n * @returns {Object|null} Parsed JSON or null if file not found\n * @throws {Error} If JSON is invalid\n */\nfunction readJsonFileSafe(filepath) {\n try {\n const content = fs.readFileSync(filepath, 'utf8');\n return JSON.parse(content);\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found, return null like API would return 404\n }\n throw error;\n }\n}\n\n/**\n * Read a file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the file\n * @returns {string|null} File content or null if file not found\n * @throws {Error} For other file system errors\n */\nfunction readFileSafe(filepath) {\n try {\n return fs.readFileSync(filepath, 'utf8');\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file with proper formatting\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to write\n * @param {number} indent - Indentation level (default: 2)\n */\nfunction writeJsonFile(filepath, data, indent = 2) {\n const content = JSON.stringify(data, null, indent);\n fs.writeFileSync(filepath, content, 'utf8');\n}\n\n/**\n * Write module.exports file with JSON data\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to export\n */\nfunction writeModuleExportsFile(filepath, data) {\n // Handle empty data cases\n if (data === null || data === undefined || \n (typeof data === 'object' && Object.keys(data).length === 0) ||\n (Array.isArray(data) && data.length === 0)) {\n const emptyContent = Array.isArray(data) ? '[]' : '{}';\n const content = `module.exports = ${emptyContent};`;\n fs.writeFileSync(filepath, content, 'utf8');\n } else {\n const content = `module.exports = ${JSON.stringify(data, null, 2)};`;\n fs.writeFileSync(filepath, content, 'utf8');\n }\n}\n\n/**\n * Check if a file exists\n * @param {string} filepath - Path to check\n * @returns {boolean} True if file exists\n */\nfunction fileExists(filepath) {\n return fs.existsSync(filepath);\n}\n\n/**\n * Create directory recursively\n * @param {string} dirpath - Directory path to create\n */\nfunction ensureDirectoryExists(dirpath) {\n fs.mkdirSync(dirpath, { recursive: true });\n}\n\n/**\n * Remove directory recursively\n * @param {string} dirpath - Directory path to remove\n */\nfunction removeDirectory(dirpath) {\n fs.rmSync(dirpath, { recursive: true, force: true });\n}\n\nmodule.exports = {\n readJsonFileSafe,\n readFileSafe,\n writeJsonFile,\n writeModuleExportsFile,\n fileExists,\n ensureDirectoryExists,\n removeDirectory\n};", "const path = require('path');\nconst { fileExists } = require('./file-utils');\n\n/**\n * Find a file by traversing up the directory tree\n * @param {string} filename - Name of the file to find\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @returns {string|null} Full path to the file or null if not found\n */\nfunction findFileUpward(filename, startDir = process.cwd()) {\n let currentDir = startDir;\n \n while (currentDir !== path.parse(currentDir).root) {\n const filePath = path.join(currentDir, filename);\n \n if (fileExists(filePath)) {\n return filePath;\n }\n \n currentDir = path.dirname(currentDir);\n }\n \n return null;\n}\n\n/**\n * Find a directory by traversing up and checking multiple possible paths\n * @param {string} dirname - Name of the directory to find\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @param {Function} validator - Optional function to validate the directory\n * @returns {string|null} Full path to the directory or null if not found\n */\nfunction findDirectoryUpward(dirname, startDir = process.cwd(), validator = null) {\n const possiblePaths = [];\n let currentDir = startDir;\n const maxLevels = 10; // Prevent infinite loop\n \n // Build list of possible paths\n for (let i = 0; i < maxLevels; i++) {\n // Direct path\n possiblePaths.push(path.join(currentDir, dirname));\n \n // Relative paths up to 3 levels\n if (i < 3) {\n possiblePaths.push(path.join(currentDir, '../'.repeat(i + 1) + dirname));\n }\n \n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) break; // Reached root\n currentDir = parentDir;\n }\n \n // Also check from module directory (for when running from node_modules)\n possiblePaths.push(path.join(__dirname, '../../../', dirname));\n \n // Find first existing directory that passes validation\n for (const dirPath of possiblePaths) {\n if (fileExists(dirPath)) {\n if (!validator || validator(dirPath)) {\n return dirPath;\n }\n }\n }\n \n return null;\n}\n\n/**\n * Find a directory with multiple possible relative paths\n * @param {string[]} possiblePaths - Array of possible paths to check\n * @param {string} startDir - Starting directory (defaults to cwd)\n * @returns {string|null} Full path to the directory or null if not found\n */\nfunction findDirectoryWithPaths(possiblePaths, startDir = process.cwd()) {\n // Build absolute paths from the start directory\n const absolutePaths = possiblePaths.map(p => {\n if (path.isAbsolute(p)) {\n return p;\n }\n return path.join(startDir, p);\n });\n \n // Find first existing path\n for (const dirPath of absolutePaths) {\n if (fileExists(dirPath)) {\n return dirPath;\n }\n }\n \n return null;\n}\n\nmodule.exports = {\n findFileUpward,\n findDirectoryUpward,\n findDirectoryWithPaths\n};", "const path = require('path');\nconst { fileExists } = require('./file-utils');\n\n/**\n * Load .env.local file if it exists in the current working directory\n * @param {string} cwd - Current working directory (defaults to process.cwd())\n * @returns {boolean} True if .env.local was loaded\n */\nfunction loadEnvLocal(cwd = process.cwd()) {\n const envLocalPath = path.join(cwd, '.env.local');\n \n if (fileExists(envLocalPath)) {\n require('dotenv').config({ path: envLocalPath });\n console.log('\uD83D\uDCC4 Loaded .env.local');\n return true;\n }\n \n return false;\n}\n\n/**\n * Get an environment variable with optional default value\n * @param {string} name - Environment variable name\n * @param {string} defaultValue - Default value if not set\n * @returns {string|undefined} Environment variable value or default\n */\nfunction getEnvVar(name, defaultValue = undefined) {\n return process.env[name] || defaultValue;\n}\n\n/**\n * Check if an environment variable is set to 'true'\n * @param {string} name - Environment variable name\n * @returns {boolean} True if the env var is set to 'true'\n */\nfunction isEnvTrue(name) {\n return process.env[name] === 'true';\n}\n\nmodule.exports = {\n loadEnvLocal,\n getEnvVar,\n isEnvTrue\n};", "const https = require('https');\nconst fs = require('fs');\nconst path = require('path');\nconst { URL } = require('url');\nconst os = require('os');\nconst { ENV_VARS } = require('./constants');\nconst { findDirectoryWithPaths } = require('./path-utils');\nconst { readJsonFileSafe, fileExists, ensureDirectoryExists } = require('./file-utils');\nconst { isEnvTrue } = require('./env-utils');\n\nconst REGISTRY_URL = process.env.FF_REGISTRY_URL || 'https://ff-registry.up.railway.app';\nconst USE_LOCAL_REGISTRY = isEnvTrue('FF_USE_LOCAL_REGISTRY') || isEnvTrue(ENV_VARS.FF_USE_LOCAL);\n\nclass ComponentDownloader {\n constructor(options = {}) {\n this.appRoot = options.appRoot || process.cwd();\n this.framework = options.framework || this.detectFramework();\n this.config = options.config || {};\n this.outputPath = options.outputPath || this.getDefaultOutputPath();\n this.overwrite = options.overwrite || false;\n this.downloadedComponents = new Set();\n this.ffId = this.config.ffId || this.config['ff-id'] || null;\n }\n\n /**\n * Detect framework from package.json\n */\n detectFramework() {\n const packageJsonPath = path.join(this.appRoot, 'package.json');\n \n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n \n if (deps.vue) {\n return 'vue';\n } else if (deps.react) {\n return 'react';\n }\n }\n \n // Default to React if can't detect\n return 'react';\n }\n\n /**\n * Get default output path based on framework and config\n */\n getDefaultOutputPath() {\n // Check if config has ui alias\n if (this.config.aliases && this.config.aliases.ui) {\n const uiAlias = this.config.aliases.ui;\n // Convert alias to actual path (e.g., @/components/ui -> components/ui)\n const cleanPath = uiAlias.replace(/^@\\//, '');\n return path.join(this.appRoot, cleanPath);\n }\n \n // Fallback to default paths\n if (this.framework === 'vue') {\n return path.join(this.appRoot, 'src/components/ui');\n }\n return path.join(this.appRoot, 'components/ui');\n }\n\n /**\n * Fetch JSON from URL or local file\n */\n fetchJson(url) {\n // If using local registry, read from file system\n if (USE_LOCAL_REGISTRY) {\n // Try multiple paths to find the registry\n const possiblePaths = [\n '../../packages/registry',\n '../../../packages/registry',\n '../../../../packages/registry',\n path.join(__dirname, '../../../registry'),\n 'packages/registry'\n ];\n \n const registryPath = findDirectoryWithPaths(possiblePaths, process.cwd());\n \n if (!registryPath) {\n return Promise.reject(new Error(`Local registry not found. Tried paths: ${possiblePaths.join(', ')}`));\n }\n \n // Extract the path from the URL and construct proper local path\n const urlPath = url.replace(REGISTRY_URL, '').replace(/^\\//, '');\n const localPath = path.join(registryPath, ...urlPath.split('/'));\n \n const content = readJsonFileSafe(localPath);\n if (content === null) {\n return Promise.reject(new Error('HTTP 404: Not Found'));\n }\n \n return Promise.resolve(content);\n }\n\n return new Promise((resolve, reject) => {\n https.get(url, (response) => {\n let data = '';\n \n if (response.statusCode >= 400) {\n reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));\n return;\n }\n\n response.on('data', (chunk) => {\n data += chunk;\n });\n\n response.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch (error) {\n reject(new Error(`Invalid JSON response: ${error.message}`));\n }\n });\n\n }).on('error', (error) => {\n reject(error);\n });\n });\n }\n\n /**\n * Get all available components from registry\n */\n async getAllComponents() {\n try {\n const url = `${REGISTRY_URL}/components/${this.framework}/index.json`;\n const index = await this.fetchJson(url);\n return index.components || [];\n } catch (error) {\n console.error('Failed to fetch component index:', error.message);\n return [];\n }\n }\n\n /**\n * Get all custom components for this ff-id\n */\n async getCustomComponents() {\n if (!this.ffId) {\n return [];\n }\n \n try {\n const url = `${REGISTRY_URL}/custom/${this.ffId}/${this.framework}/index.json`;\n const index = await this.fetchJson(url);\n return index.components || [];\n } catch (error) {\n // Custom components might not exist, that's ok\n return [];\n }\n }\n\n /**\n * Download multiple components\n */\n async downloadComponents(components) {\n const results = {\n successful: [],\n failed: [],\n dependencies: new Set()\n };\n\n for (const component of components) {\n try {\n const deps = await this.downloadComponent(component);\n results.successful.push(component);\n \n // Add dependencies\n deps.forEach(dep => results.dependencies.add(dep));\n } catch (error) {\n results.failed.push({\n component,\n error: error.message\n });\n }\n }\n\n return {\n successful: results.successful,\n failed: results.failed,\n dependencies: Array.from(results.dependencies)\n };\n }\n\n /**\n * Download a single component and its registry dependencies\n */\n async downloadComponent(componentName) {\n // Avoid downloading the same component twice\n if (this.downloadedComponents.has(componentName)) {\n return [];\n }\n\n console.log(`\uD83D\uDCE5 Downloading ${componentName}...`);\n\n // Try to fetch from custom components first if ff-id is available\n let componentData;\n let isCustom = false;\n \n if (this.ffId) {\n const customUrl = `${REGISTRY_URL}/custom/${this.ffId}/${this.framework}/${componentName}.json`;\n try {\n componentData = await this.fetchJson(customUrl);\n isCustom = true;\n } catch (error) {\n // Custom component not found, try standard registry\n }\n }\n \n // If not found in custom, try standard registry\n if (!componentData) {\n const url = `${REGISTRY_URL}/components/${this.framework}/${componentName}.json`;\n \n try {\n componentData = await this.fetchJson(url);\n } catch (error) {\n // Check if it's a 404 (component not found)\n if (error.message.includes('404')) {\n throw new Error(`Component \"${componentName}\" not found`);\n }\n throw new Error(`Failed to fetch ${componentName}: ${error.message}`);\n }\n }\n\n // Validate component data\n if (!componentData.files || !Array.isArray(componentData.files)) {\n throw new Error(`Invalid component data for ${componentName}`);\n }\n\n // Write component files\n for (const file of componentData.files) {\n await this.writeComponentFile(file);\n }\n\n this.downloadedComponents.add(componentName);\n console.log(` \u2713 ${componentName} downloaded`);\n\n // Download registry dependencies\n const allDependencies = [...(componentData.dependencies || [])];\n \n if (componentData.registryDependencies && componentData.registryDependencies.length > 0) {\n console.log(` \uD83D\uDCE6 Installing registry dependencies: ${componentData.registryDependencies.join(', ')}`);\n \n for (const dep of componentData.registryDependencies) {\n try {\n const depDeps = await this.downloadComponent(dep);\n depDeps.forEach(d => allDependencies.push(d));\n } catch (error) {\n console.warn(` \u26A0\uFE0F Failed to download dependency ${dep}: ${error.message}`);\n }\n }\n }\n\n return allDependencies;\n }\n\n /**\n * Write component file to disk\n */\n async writeComponentFile(file) {\n // Normalize the file path for the current platform\n // Convert forward slashes to the platform-specific separator\n const normalizedFileName = file.name.split('/').join(path.sep);\n const filePath = path.join(this.outputPath, normalizedFileName);\n const dir = path.dirname(filePath);\n\n // Create directory if it doesn't exist\n ensureDirectoryExists(dir);\n\n // Check if file exists and overwrite setting\n if (fileExists(filePath) && !this.overwrite) {\n console.log(` \u26A0\uFE0F Skipping ${file.name} (already exists)`);\n return;\n }\n\n // Normalize line endings to match the platform\n // This prevents git from showing every line as changed\n let normalizedContent = file.content;\n if (os.EOL !== '\\n') {\n // On Windows, replace LF with CRLF\n normalizedContent = file.content.replace(/\\n/g, os.EOL);\n }\n\n // Write file\n fs.writeFileSync(filePath, normalizedContent, 'utf8');\n }\n}\n\nmodule.exports = { ComponentDownloader };"],
5
+ "mappings": "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",
6
+ "names": ["require_constants", "__commonJSMin", "exports", "module", "DEFAULT_API_URL", "LEGACY_API_URL", "CACHE_DIR_NAME", "CACHE_FILES", "ENV_VARS", "require_file_utils", "__commonJSMin", "exports", "module", "fs", "readJsonFileSafe", "filepath", "content", "error", "readFileSafe", "writeJsonFile", "data", "indent", "writeModuleExportsFile", "fileExists", "ensureDirectoryExists", "dirpath", "removeDirectory", "require_path_utils", "__commonJSMin", "exports", "module", "path", "fileExists", "findFileUpward", "filename", "startDir", "currentDir", "filePath", "findDirectoryUpward", "dirname", "validator", "possiblePaths", "maxLevels", "i", "parentDir", "dirPath", "findDirectoryWithPaths", "absolutePaths", "p", "require_env_utils", "__commonJSMin", "exports", "module", "path", "fileExists", "loadEnvLocal", "cwd", "envLocalPath", "getEnvVar", "name", "defaultValue", "isEnvTrue", "https", "fs", "path", "URL", "os", "ENV_VARS", "findDirectoryWithPaths", "readJsonFileSafe", "fileExists", "ensureDirectoryExists", "isEnvTrue", "REGISTRY_URL", "USE_LOCAL_REGISTRY", "ComponentDownloader", "options", "packageJsonPath", "packageJson", "deps", "cleanPath", "url", "possiblePaths", "registryPath", "urlPath", "localPath", "content", "resolve", "reject", "response", "data", "chunk", "error", "components", "results", "component", "dep", "componentName", "componentData", "isCustom", "customUrl", "file", "allDependencies", "d", "normalizedFileName", "filePath", "dir", "normalizedContent"]
7
7
  }
@@ -1,5 +1,6 @@
1
- const fs = require('fs');
2
1
  const path = require('path');
2
+ const { findFileUpward } = require('./path-utils');
3
+ const { fileExists, readJsonFileSafe } = require('./file-utils');
3
4
 
4
5
  class ConfigLoader {
5
6
  /**
@@ -8,18 +9,7 @@ class ConfigLoader {
8
9
  * @returns {string|null} Path to config file or null
9
10
  */
10
11
  findConfigFile(startDir = process.cwd()) {
11
- let currentDir = startDir;
12
-
13
- while (currentDir !== path.parse(currentDir).root) {
14
- const configPath = path.join(currentDir, 'frontfriend.config.js');
15
-
16
- if (fs.existsSync(configPath)) {
17
- return configPath;
18
- }
19
- currentDir = path.dirname(currentDir);
20
- }
21
-
22
- return null;
12
+ return findFileUpward('frontfriend.config.js', startDir);
23
13
  }
24
14
 
25
15
  /**
@@ -30,8 +20,8 @@ class ConfigLoader {
30
20
  isESModule(dir) {
31
21
  try {
32
22
  const packageJsonPath = path.join(dir, 'package.json');
33
- if (fs.existsSync(packageJsonPath)) {
34
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
23
+ const packageJson = readJsonFileSafe(packageJsonPath);
24
+ if (packageJson) {
35
25
  return packageJson.type === 'module';
36
26
  }
37
27
  } catch (error) {
@@ -1,2 +1,2 @@
1
- var s="https://app.frontfriend.dev",n="https://tokens-studio-donux.up.railway.app/api",o=".cache/frontfriend";var t={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","cls.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},_={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL"};module.exports={DEFAULT_API_URL:s,LEGACY_API_URL:n,CACHE_DIR_NAME:o,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:t,ENV_VARS:_};
1
+ var s="https://app.frontfriend.dev",_="https://tokens-studio-donux.up.railway.app/api",n=".cache/frontfriend";var o={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","cls.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},t={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_USE_LOCAL_REGISTRY:"FF_USE_LOCAL_REGISTRY"};module.exports={DEFAULT_API_URL:s,LEGACY_API_URL:_,CACHE_DIR_NAME:n,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:o,ENV_VARS:t};
2
2
  //# sourceMappingURL=constants.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../lib/core/constants.js"],
4
- "sourcesContent": ["/**\n * Configuration constants for FrontFriend Tailwind v2\n */\n\n// API Configuration\nconst DEFAULT_API_URL = 'https://app.frontfriend.dev';\nconst LEGACY_API_URL = 'https://tokens-studio-donux.up.railway.app/api';\n\n// Cache Configuration\nconst CACHE_DIR_NAME = '.cache/frontfriend';\nconst CACHE_TTL_DAYS = 7;\nconst CACHE_TTL_MS = CACHE_TTL_DAYS * 24 * 60 * 60 * 1000;\n\n// File names\nconst CACHE_FILES = {\n JS: [\n 'tokens.js',\n 'variables.js',\n 'semanticVariables.js',\n 'semanticDarkVariables.js',\n 'cls.js',\n 'custom.js'\n ],\n JSON: [\n 'fonts.json',\n 'icons.json',\n 'components-config.json',\n 'version.json',\n 'metadata.json'\n ]\n};\n\n// Environment variables\nconst ENV_VARS = {\n FF_ID: 'FF_ID',\n FF_API_URL: 'FF_API_URL'\n};\n\nmodule.exports = {\n DEFAULT_API_URL,\n LEGACY_API_URL,\n CACHE_DIR_NAME,\n CACHE_TTL_DAYS,\n CACHE_TTL_MS,\n CACHE_FILES,\n ENV_VARS\n};"],
5
- "mappings": "AAKA,IAAMA,EAAkB,8BAClBC,EAAiB,iDAGjBC,EAAiB,qBAKvB,IAAMC,EAAc,CAClB,GAAI,CACF,YACA,eACA,uBACA,2BACA,SACA,WACF,EACA,KAAM,CACJ,aACA,aACA,yBACA,eACA,eACF,CACF,EAGMC,EAAW,CACf,MAAO,QACP,WAAY,YACd,EAEA,OAAO,QAAU,CACf,gBAAAC,EACA,eAAAC,EACA,eAAAC,EACA,iBACA,oBACA,YAAAJ,EACA,SAAAC,CACF",
4
+ "sourcesContent": ["/**\n * Configuration constants for FrontFriend Tailwind v2\n */\n\n// API Configuration\nconst DEFAULT_API_URL = 'https://app.frontfriend.dev';\nconst LEGACY_API_URL = 'https://tokens-studio-donux.up.railway.app/api';\n\n// Cache Configuration\nconst CACHE_DIR_NAME = '.cache/frontfriend';\nconst CACHE_TTL_DAYS = 7;\nconst CACHE_TTL_MS = CACHE_TTL_DAYS * 24 * 60 * 60 * 1000;\n\n// File names\nconst CACHE_FILES = {\n JS: [\n 'tokens.js',\n 'variables.js',\n 'semanticVariables.js',\n 'semanticDarkVariables.js',\n 'cls.js',\n 'custom.js'\n ],\n JSON: [\n 'fonts.json',\n 'icons.json',\n 'components-config.json',\n 'version.json',\n 'metadata.json'\n ]\n};\n\n// Environment variables\nconst ENV_VARS = {\n FF_ID: 'FF_ID',\n FF_API_URL: 'FF_API_URL',\n FF_USE_LOCAL: 'FF_USE_LOCAL',\n FF_USE_LOCAL_REGISTRY: 'FF_USE_LOCAL_REGISTRY'\n};\n\nmodule.exports = {\n DEFAULT_API_URL,\n LEGACY_API_URL,\n CACHE_DIR_NAME,\n CACHE_TTL_DAYS,\n CACHE_TTL_MS,\n CACHE_FILES,\n ENV_VARS\n};"],
5
+ "mappings": "AAKA,IAAMA,EAAkB,8BAClBC,EAAiB,iDAGjBC,EAAiB,qBAKvB,IAAMC,EAAc,CAClB,GAAI,CACF,YACA,eACA,uBACA,2BACA,SACA,WACF,EACA,KAAM,CACJ,aACA,aACA,yBACA,eACA,eACF,CACF,EAGMC,EAAW,CACf,MAAO,QACP,WAAY,aACZ,aAAc,eACd,sBAAuB,uBACzB,EAEA,OAAO,QAAU,CACf,gBAAAC,EACA,eAAAC,EACA,eAAAC,EACA,iBACA,oBACA,YAAAJ,EACA,SAAAC,CACF",
6
6
  "names": ["DEFAULT_API_URL", "LEGACY_API_URL", "CACHE_DIR_NAME", "CACHE_FILES", "ENV_VARS", "DEFAULT_API_URL", "LEGACY_API_URL", "CACHE_DIR_NAME"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ var u=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports);var i=u((w,c)=>{var r=require("fs");function s(n){try{let e=r.readFileSync(n,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function l(n){try{return r.readFileSync(n,"utf8")}catch(e){if(e.code==="ENOENT")return null;throw e}}function f(n,e,t=2){let o=JSON.stringify(e,null,t);r.writeFileSync(n,o,"utf8")}function y(n,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let o=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;r.writeFileSync(n,o,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;r.writeFileSync(n,t,"utf8")}}function p(n){return r.existsSync(n)}function S(n){r.mkdirSync(n,{recursive:!0})}function d(n){r.rmSync(n,{recursive:!0,force:!0})}c.exports={readJsonFileSafe:s,readFileSafe:l,writeJsonFile:f,writeModuleExportsFile:y,fileExists:p,ensureDirectoryExists:S,removeDirectory:d}});var v=require("path"),{fileExists:E}=i();function a(n=process.cwd()){let e=v.join(n,".env.local");return E(e)?(require("dotenv").config({path:e}),console.log("\u{1F4C4} Loaded .env.local"),!0):!1}function x(n,e=void 0){return process.env[n]||e}function F(n){return process.env[n]==="true"}module.exports={loadEnvLocal:a,getEnvVar:x,isEnvTrue:F};
2
+ //# sourceMappingURL=env-utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../lib/core/file-utils.js", "../../../lib/core/env-utils.js"],
4
+ "sourcesContent": ["const fs = require('fs');\n\n/**\n * Read a JSON file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the JSON file\n * @returns {Object|null} Parsed JSON or null if file not found\n * @throws {Error} If JSON is invalid\n */\nfunction readJsonFileSafe(filepath) {\n try {\n const content = fs.readFileSync(filepath, 'utf8');\n return JSON.parse(content);\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found, return null like API would return 404\n }\n throw error;\n }\n}\n\n/**\n * Read a file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the file\n * @returns {string|null} File content or null if file not found\n * @throws {Error} For other file system errors\n */\nfunction readFileSafe(filepath) {\n try {\n return fs.readFileSync(filepath, 'utf8');\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file with proper formatting\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to write\n * @param {number} indent - Indentation level (default: 2)\n */\nfunction writeJsonFile(filepath, data, indent = 2) {\n const content = JSON.stringify(data, null, indent);\n fs.writeFileSync(filepath, content, 'utf8');\n}\n\n/**\n * Write module.exports file with JSON data\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to export\n */\nfunction writeModuleExportsFile(filepath, data) {\n // Handle empty data cases\n if (data === null || data === undefined || \n (typeof data === 'object' && Object.keys(data).length === 0) ||\n (Array.isArray(data) && data.length === 0)) {\n const emptyContent = Array.isArray(data) ? '[]' : '{}';\n const content = `module.exports = ${emptyContent};`;\n fs.writeFileSync(filepath, content, 'utf8');\n } else {\n const content = `module.exports = ${JSON.stringify(data, null, 2)};`;\n fs.writeFileSync(filepath, content, 'utf8');\n }\n}\n\n/**\n * Check if a file exists\n * @param {string} filepath - Path to check\n * @returns {boolean} True if file exists\n */\nfunction fileExists(filepath) {\n return fs.existsSync(filepath);\n}\n\n/**\n * Create directory recursively\n * @param {string} dirpath - Directory path to create\n */\nfunction ensureDirectoryExists(dirpath) {\n fs.mkdirSync(dirpath, { recursive: true });\n}\n\n/**\n * Remove directory recursively\n * @param {string} dirpath - Directory path to remove\n */\nfunction removeDirectory(dirpath) {\n fs.rmSync(dirpath, { recursive: true, force: true });\n}\n\nmodule.exports = {\n readJsonFileSafe,\n readFileSafe,\n writeJsonFile,\n writeModuleExportsFile,\n fileExists,\n ensureDirectoryExists,\n removeDirectory\n};", "const path = require('path');\nconst { fileExists } = require('./file-utils');\n\n/**\n * Load .env.local file if it exists in the current working directory\n * @param {string} cwd - Current working directory (defaults to process.cwd())\n * @returns {boolean} True if .env.local was loaded\n */\nfunction loadEnvLocal(cwd = process.cwd()) {\n const envLocalPath = path.join(cwd, '.env.local');\n \n if (fileExists(envLocalPath)) {\n require('dotenv').config({ path: envLocalPath });\n console.log('\uD83D\uDCC4 Loaded .env.local');\n return true;\n }\n \n return false;\n}\n\n/**\n * Get an environment variable with optional default value\n * @param {string} name - Environment variable name\n * @param {string} defaultValue - Default value if not set\n * @returns {string|undefined} Environment variable value or default\n */\nfunction getEnvVar(name, defaultValue = undefined) {\n return process.env[name] || defaultValue;\n}\n\n/**\n * Check if an environment variable is set to 'true'\n * @param {string} name - Environment variable name\n * @returns {boolean} True if the env var is set to 'true'\n */\nfunction isEnvTrue(name) {\n return process.env[name] === 'true';\n}\n\nmodule.exports = {\n loadEnvLocal,\n getEnvVar,\n isEnvTrue\n};"],
5
+ "mappings": "8DAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,KAAMC,EAAK,QAAQ,IAAI,EAQvB,SAASC,EAAiBC,EAAU,CAClC,GAAI,CACF,IAAMC,EAAUH,EAAG,aAAaE,EAAU,MAAM,EAChD,OAAO,KAAK,MAAMC,CAAO,CAC3B,OAASC,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASC,EAAaH,EAAU,CAC9B,GAAI,CACF,OAAOF,EAAG,aAAaE,EAAU,MAAM,CACzC,OAASE,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASE,EAAcJ,EAAUK,EAAMC,EAAS,EAAG,CACjD,IAAML,EAAU,KAAK,UAAUI,EAAM,KAAMC,CAAM,EACjDR,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CAOA,SAASM,EAAuBP,EAAUK,EAAM,CAE9C,GAAIA,GAAS,MACR,OAAOA,GAAS,UAAY,OAAO,KAAKA,CAAI,EAAE,SAAW,GACzD,MAAM,QAAQA,CAAI,GAAKA,EAAK,SAAW,EAAI,CAE9C,IAAMJ,EAAU,oBADK,MAAM,QAAQI,CAAI,EAAI,KAAO,IACF,IAChDP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,KAAO,CACL,IAAMA,EAAU,oBAAoB,KAAK,UAAUI,EAAM,KAAM,CAAC,CAAC,IACjEP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CACF,CAOA,SAASO,EAAWR,EAAU,CAC5B,OAAOF,EAAG,WAAWE,CAAQ,CAC/B,CAMA,SAASS,EAAsBC,EAAS,CACtCZ,EAAG,UAAUY,EAAS,CAAE,UAAW,EAAK,CAAC,CAC3C,CAMA,SAASC,EAAgBD,EAAS,CAChCZ,EAAG,OAAOY,EAAS,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,CACrD,CAEAb,EAAO,QAAU,CACf,iBAAAE,EACA,aAAAI,EACA,cAAAC,EACA,uBAAAG,EACA,WAAAC,EACA,sBAAAC,EACA,gBAAAE,CACF,ICpGA,IAAMC,EAAO,QAAQ,MAAM,EACrB,CAAE,WAAAC,CAAW,EAAI,IAOvB,SAASC,EAAaC,EAAM,QAAQ,IAAI,EAAG,CACzC,IAAMC,EAAeJ,EAAK,KAAKG,EAAK,YAAY,EAEhD,OAAIF,EAAWG,CAAY,GACzB,QAAQ,QAAQ,EAAE,OAAO,CAAE,KAAMA,CAAa,CAAC,EAC/C,QAAQ,IAAI,6BAAsB,EAC3B,IAGF,EACT,CAQA,SAASC,EAAUC,EAAMC,EAAe,OAAW,CACjD,OAAO,QAAQ,IAAID,CAAI,GAAKC,CAC9B,CAOA,SAASC,EAAUF,EAAM,CACvB,OAAO,QAAQ,IAAIA,CAAI,IAAM,MAC/B,CAEA,OAAO,QAAU,CACf,aAAAJ,EACA,UAAAG,EACA,UAAAG,CACF",
6
+ "names": ["require_file_utils", "__commonJSMin", "exports", "module", "fs", "readJsonFileSafe", "filepath", "content", "error", "readFileSafe", "writeJsonFile", "data", "indent", "writeModuleExportsFile", "fileExists", "ensureDirectoryExists", "dirpath", "removeDirectory", "path", "fileExists", "loadEnvLocal", "cwd", "envLocalPath", "getEnvVar", "name", "defaultValue", "isEnvTrue"]
7
+ }
@@ -0,0 +1,2 @@
1
+ var n=require("fs");function o(r){try{let e=n.readFileSync(r,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function c(r){try{return n.readFileSync(r,"utf8")}catch(e){if(e.code==="ENOENT")return null;throw e}}function u(r,e,t=2){let i=JSON.stringify(e,null,t);n.writeFileSync(r,i,"utf8")}function s(r,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let i=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;n.writeFileSync(r,i,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;n.writeFileSync(r,t,"utf8")}}function l(r){return n.existsSync(r)}function f(r){n.mkdirSync(r,{recursive:!0})}function y(r){n.rmSync(r,{recursive:!0,force:!0})}module.exports={readJsonFileSafe:o,readFileSafe:c,writeJsonFile:u,writeModuleExportsFile:s,fileExists:l,ensureDirectoryExists:f,removeDirectory:y};
2
+ //# sourceMappingURL=file-utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../lib/core/file-utils.js"],
4
+ "sourcesContent": ["const fs = require('fs');\n\n/**\n * Read a JSON file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the JSON file\n * @returns {Object|null} Parsed JSON or null if file not found\n * @throws {Error} If JSON is invalid\n */\nfunction readJsonFileSafe(filepath) {\n try {\n const content = fs.readFileSync(filepath, 'utf8');\n return JSON.parse(content);\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found, return null like API would return 404\n }\n throw error;\n }\n}\n\n/**\n * Read a file safely, returning null if file doesn't exist\n * @param {string} filepath - Path to the file\n * @returns {string|null} File content or null if file not found\n * @throws {Error} For other file system errors\n */\nfunction readFileSafe(filepath) {\n try {\n return fs.readFileSync(filepath, 'utf8');\n } catch (error) {\n if (error.code === 'ENOENT') {\n return null; // File not found\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file with proper formatting\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to write\n * @param {number} indent - Indentation level (default: 2)\n */\nfunction writeJsonFile(filepath, data, indent = 2) {\n const content = JSON.stringify(data, null, indent);\n fs.writeFileSync(filepath, content, 'utf8');\n}\n\n/**\n * Write module.exports file with JSON data\n * @param {string} filepath - Path to write the file\n * @param {Object} data - Data to export\n */\nfunction writeModuleExportsFile(filepath, data) {\n // Handle empty data cases\n if (data === null || data === undefined || \n (typeof data === 'object' && Object.keys(data).length === 0) ||\n (Array.isArray(data) && data.length === 0)) {\n const emptyContent = Array.isArray(data) ? '[]' : '{}';\n const content = `module.exports = ${emptyContent};`;\n fs.writeFileSync(filepath, content, 'utf8');\n } else {\n const content = `module.exports = ${JSON.stringify(data, null, 2)};`;\n fs.writeFileSync(filepath, content, 'utf8');\n }\n}\n\n/**\n * Check if a file exists\n * @param {string} filepath - Path to check\n * @returns {boolean} True if file exists\n */\nfunction fileExists(filepath) {\n return fs.existsSync(filepath);\n}\n\n/**\n * Create directory recursively\n * @param {string} dirpath - Directory path to create\n */\nfunction ensureDirectoryExists(dirpath) {\n fs.mkdirSync(dirpath, { recursive: true });\n}\n\n/**\n * Remove directory recursively\n * @param {string} dirpath - Directory path to remove\n */\nfunction removeDirectory(dirpath) {\n fs.rmSync(dirpath, { recursive: true, force: true });\n}\n\nmodule.exports = {\n readJsonFileSafe,\n readFileSafe,\n writeJsonFile,\n writeModuleExportsFile,\n fileExists,\n ensureDirectoryExists,\n removeDirectory\n};"],
5
+ "mappings": "AAAA,IAAMA,EAAK,QAAQ,IAAI,EAQvB,SAASC,EAAiBC,EAAU,CAClC,GAAI,CACF,IAAMC,EAAUH,EAAG,aAAaE,EAAU,MAAM,EAChD,OAAO,KAAK,MAAMC,CAAO,CAC3B,OAASC,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASC,EAAaH,EAAU,CAC9B,GAAI,CACF,OAAOF,EAAG,aAAaE,EAAU,MAAM,CACzC,OAASE,EAAO,CACd,GAAIA,EAAM,OAAS,SACjB,OAAO,KAET,MAAMA,CACR,CACF,CAQA,SAASE,EAAcJ,EAAUK,EAAMC,EAAS,EAAG,CACjD,IAAML,EAAU,KAAK,UAAUI,EAAM,KAAMC,CAAM,EACjDR,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CAOA,SAASM,EAAuBP,EAAUK,EAAM,CAE9C,GAAIA,GAAS,MACR,OAAOA,GAAS,UAAY,OAAO,KAAKA,CAAI,EAAE,SAAW,GACzD,MAAM,QAAQA,CAAI,GAAKA,EAAK,SAAW,EAAI,CAE9C,IAAMJ,EAAU,oBADK,MAAM,QAAQI,CAAI,EAAI,KAAO,IACF,IAChDP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,KAAO,CACL,IAAMA,EAAU,oBAAoB,KAAK,UAAUI,EAAM,KAAM,CAAC,CAAC,IACjEP,EAAG,cAAcE,EAAUC,EAAS,MAAM,CAC5C,CACF,CAOA,SAASO,EAAWR,EAAU,CAC5B,OAAOF,EAAG,WAAWE,CAAQ,CAC/B,CAMA,SAASS,EAAsBC,EAAS,CACtCZ,EAAG,UAAUY,EAAS,CAAE,UAAW,EAAK,CAAC,CAC3C,CAMA,SAASC,EAAgBD,EAAS,CAChCZ,EAAG,OAAOY,EAAS,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,CACrD,CAEA,OAAO,QAAU,CACf,iBAAAX,EACA,aAAAI,EACA,cAAAC,EACA,uBAAAG,EACA,WAAAC,EACA,sBAAAC,EACA,gBAAAE,CACF",
6
+ "names": ["fs", "readJsonFileSafe", "filepath", "content", "error", "readFileSafe", "writeJsonFile", "data", "indent", "writeModuleExportsFile", "fileExists", "ensureDirectoryExists", "dirpath", "removeDirectory"]
7
+ }
@@ -0,0 +1,2 @@
1
+ var m=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports);var u=m((v,y)=>{var f=require("fs");function F(o){try{let e=f.readFileSync(o,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function S(o){try{return f.readFileSync(o,"utf8")}catch(e){if(e.code==="ENOENT")return null;throw e}}function D(o,e,t=2){let n=JSON.stringify(e,null,t);f.writeFileSync(o,n,"utf8")}function g(o,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let n=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;f.writeFileSync(o,n,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;f.writeFileSync(o,t,"utf8")}}function E(o){return f.existsSync(o)}function x(o){f.mkdirSync(o,{recursive:!0})}function M(o){f.rmSync(o,{recursive:!0,force:!0})}y.exports={readJsonFileSafe:F,readFileSafe:S,writeJsonFile:D,writeModuleExportsFile:g,fileExists:E,ensureDirectoryExists:x,removeDirectory:M}});var k=m((J,w)=>{var a=require("path"),{fileExists:j}=u();function C(o,e=process.cwd()){let t=e;for(;t!==a.parse(t).root;){let n=a.join(t,o);if(j(n))return n;t=a.dirname(t)}return null}function N(o,e=process.cwd(),t=null){let n=[],i=e,c=10;for(let r=0;r<c;r++){n.push(a.join(i,o)),r<3&&n.push(a.join(i,"../".repeat(r+1)+o));let l=a.dirname(i);if(l===i)break;i=l}n.push(a.join(__dirname,"../../../",o));for(let r of n)if(j(r)&&(!t||t(r)))return r;return null}function O(o,e=process.cwd()){let t=o.map(n=>a.isAbsolute(n)?n:a.join(e,n));for(let n of t)if(j(n))return n;return null}w.exports={findFileUpward:C,findDirectoryUpward:N,findDirectoryWithPaths:O}});var s=require("path"),{findDirectoryUpward:P}=k(),{readJsonFileSafe:h,readFileSafe:b,fileExists:d}=u(),p=class{constructor(e,t={}){if(this.ffId=e,this.tokensBasePath=t.tokensBasePath||this.findTokensPath(),this.folderMap=this.loadFolderMap(),this.projectFolder=this.folderMap[e],!this.projectFolder)throw new Error(`No folder mapping found for ff-id: ${e}`);this.projectPath=s.join(this.tokensBasePath,this.projectFolder)}findTokensPath(){let e=P("apps/tokens",process.cwd(),t=>d(s.join(t,"folderMap.json")));if(e||(e=P("tokens",process.cwd(),t=>d(s.join(t,"folderMap.json")))),!e)throw new Error("Could not find tokens directory with folderMap.json");return e}loadFolderMap(){let e=s.join(this.tokensBasePath,"folderMap.json"),t=h(e);if(!t)throw new Error("Failed to load folderMap.json: File not found");return t}async fetchTokens(){let e=s.join(this.projectPath,"figma"),t={global:[s.join(e,"Global Tokens","Default.json"),s.join(e,"global.json")],colors:[s.join(e,"Global Colors","Default.json"),s.join(e,"Global Colors","Light.json")],semantic:[s.join(e,"Semantic","Light.json"),s.join(e,"Semantic","Default.json")],semanticDark:[s.join(e,"Semantic","Dark.json")]},n={};for(let[i,c]of Object.entries(t)){for(let r of c){let l=h(r);if(l!==null){n[i]=l;break}}n[i]||(n[i]=null)}return n}async fetchProcessedTokens(){let e=s.join(this.projectPath,"cache");if(!d(e))return null;let t={"tokens.js":"hashedTokens.js","variables.js":"hashedVariables.js","semanticVariables.js":"hashedSemanticVariables.js","semanticDarkVariables.js":"hashedSemanticDarkVariables.js","cls.js":"cls.js","custom.js":"custom.js","fonts.json":"fonts.json","icons.json":"icons.json","components-config.json":"encoded-config.json","version.json":"version.json"},n={};for(let[c,r]of Object.entries(t)){let l=s.join(e,r);c.endsWith(".js")?n[c]=b(l):n[c]=h(l)}return Object.values(n).some(c=>c!==null)?n:null}async fetchComponentsConfig(){return h(s.join(this.projectPath,"components-config.json"))}async fetchFonts(){return h(s.join(this.projectPath,"font.json"))}async fetchIcons(){return h(s.join(this.projectPath,"icons.json"))}async fetchVersion(){return h(s.join(this.projectPath,"version.json"))}async fetchCustomCss(){return b(s.join(this.projectPath,"custom.css"))}fetchJson(){throw new Error("fetchJson is not implemented in LocalTokenReader. Use specific fetch methods.")}fetchRaw(){throw new Error("fetchRaw is not implemented in LocalTokenReader. Use specific fetch methods.")}};module.exports={LocalTokenReader:p};
2
+ //# sourceMappingURL=local-token-reader.js.map