{"version":3,"sources":["../src/cli/commands/pull.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { PromptConverter } from \"@/cli/utils/promptConverter\";\nimport {\n  PromptsApiService,\n  PromptsError,\n} from \"@/client-sdk/services/prompts\";\nimport type { PromptsConfig, PromptsLock, SyncResult } from \"../types\";\nimport { FileManager } from \"../utils/fileManager\";\nimport { ensureProjectInitialized } from \"../utils/init\";\nimport { checkApiKey } from \"../utils/apiKey\";\nimport { formatApiErrorMessage } from \"@/client-sdk/services/_shared/format-api-error\";\n\n/**\n * Core pull logic: fetches remote prompts and materializes them locally.\n * Returns the result and mutates the lock object in place.\n */\nexport const pullPrompts = async ({\n  config,\n  lock,\n  promptsApiService,\n  result,\n  tag,\n}: {\n  config: PromptsConfig;\n  lock: PromptsLock;\n  promptsApiService: PromptsApiService;\n  result: SyncResult;\n  tag?: string;\n}): Promise<void> => {\n  const remoteDeps = Object.entries(config.prompts).filter(\n    ([, dependency]) => {\n      if (typeof dependency === \"object\" && dependency.file) {\n        return false;\n      }\n      if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n        return false;\n      }\n      return true;\n    }\n  );\n\n  if (remoteDeps.length > 0) {\n    const fetchSpinner = ora(\n      `Checking ${remoteDeps.length} remote prompts...`\n    ).start();\n\n    for (const [name, dependency] of remoteDeps) {\n      try {\n        const versionSpec =\n          typeof dependency === \"string\"\n            ? dependency\n            : dependency.version ?? \"latest\";\n\n        const displaySpec = tag ?? versionSpec;\n\n        const lockEntry = lock.prompts[name];\n\n        const prompt = tag\n          ? await promptsApiService.get(name, { tag })\n          : await promptsApiService.get(name, { version: versionSpec });\n\n        if (prompt) {\n          const needsUpdate =\n            lockEntry?.version !== prompt.version ||\n            !lockEntry.materialized ||\n            !fs.existsSync(path.resolve(lockEntry.materialized));\n\n          if (needsUpdate) {\n            const materializedPrompt =\n              PromptConverter.fromApiToMaterialized(prompt);\n\n            const savedPath = FileManager.saveMaterializedPrompt(\n              name,\n              materializedPrompt\n            );\n            const relativePath = path.relative(process.cwd(), savedPath);\n            result.fetched.push({\n              name,\n              version: prompt.version,\n              versionSpec: displaySpec,\n            });\n\n            FileManager.updateLockEntry(\n              lock,\n              name,\n              materializedPrompt,\n              savedPath\n            );\n\n            fetchSpinner.text = `Fetched ${chalk.cyan(\n              `${name}@${displaySpec}`\n            )} ${chalk.gray(`(version ${prompt.version})`)} → ${chalk.gray(\n              relativePath\n            )}`;\n          } else {\n            result.unchanged.push(name);\n          }\n        } else {\n          result.errors.push({ name, error: \"Prompt not found\" });\n        }\n      } catch (error) {\n        const errorMessage =\n          formatApiErrorMessage({ error });\n        result.errors.push({ name, error: errorMessage });\n      }\n    }\n\n    fetchSpinner.stop();\n  }\n\n  // Cleanup orphaned materialized files\n  const currentDependencies = new Set(\n    Object.keys(config.prompts).filter((name) => {\n      const dependency = config.prompts[name];\n      if (typeof dependency === \"object\" && dependency.file) {\n        return false;\n      }\n      if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n        return false;\n      }\n      return true;\n    })\n  );\n\n  const cleanedFiles =\n    FileManager.cleanupOrphanedMaterializedFiles(currentDependencies);\n  if (cleanedFiles.length > 0) {\n    result.cleaned = cleanedFiles;\n    FileManager.removeFromLock(lock, cleanedFiles);\n  }\n};\n\nconst printPullResults = ({\n  result,\n  lock,\n  duration,\n}: {\n  result: SyncResult;\n  lock: PromptsLock;\n  duration: string;\n}): void => {\n  if (result.fetched.length > 0) {\n    for (const { name, version, versionSpec } of result.fetched) {\n      const lockEntry = lock.prompts[name];\n      const displayPath = lockEntry?.materialized\n        ? `./${lockEntry.materialized}`\n        : `./prompts/.materialized/${name}.prompt.yaml`;\n\n      console.log(\n        chalk.green(\n          `✓ Pulled ${chalk.cyan(`${name}@${versionSpec}`)} ${chalk.gray(\n            `(version ${version})`\n          )} → ${chalk.gray(displayPath)}`\n        )\n      );\n    }\n  }\n\n  if (result.cleaned.length > 0) {\n    for (const name of result.cleaned) {\n      console.log(\n        chalk.yellow(\n          `✓ Cleaned ${chalk.cyan(name)} (no longer in dependencies)`\n        )\n      );\n    }\n  }\n\n  if (result.errors.length > 0) {\n    for (const { name, error } of result.errors) {\n      console.error(chalk.red(`✗ Failed ${chalk.cyan(name)}: ${error}`));\n    }\n  }\n\n  const totalActions = result.fetched.length + result.cleaned.length;\n\n  if (totalActions === 0 && result.errors.length === 0) {\n    console.log(chalk.gray(`Pulled in ${duration}s, no changes`));\n  } else {\n    const summary = [];\n    if (result.fetched.length > 0)\n      summary.push(`${result.fetched.length} fetched`);\n    if (result.cleaned.length > 0)\n      summary.push(`${result.cleaned.length} cleaned`);\n    if (result.errors.length > 0)\n      summary.push(`${result.errors.length} errors`);\n\n    console.log(chalk.gray(`Pulled ${summary.join(\", \")} in ${duration}s`));\n  }\n};\n\nexport const pullCommand = async (options?: { tag?: string }): Promise<void> => {\n  console.log(\"⬇️  Pulling remote prompts...\");\n\n  const startTime = Date.now();\n\n  try {\n    checkApiKey();\n\n    const promptsApiService = new PromptsApiService();\n\n    await ensureProjectInitialized(false);\n\n    const config = FileManager.loadPromptsConfig();\n    const lock = FileManager.loadPromptsLock();\n\n    const result: SyncResult = {\n      fetched: [],\n      pushed: [],\n      unchanged: [],\n      cleaned: [],\n      errors: [],\n    };\n\n    await pullPrompts({ config, lock, promptsApiService, result, tag: options?.tag });\n\n    FileManager.savePromptsLock(lock);\n\n    const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n    printPullResults({ result, lock, duration });\n\n    if (result.errors.length > 0) {\n      process.exit(1);\n    }\n  } catch (error) {\n    if (error instanceof PromptsError) {\n      console.error(chalk.red(`Error: ${error.message}`));\n    } else {\n      console.error(\n        chalk.red(\n          `Unexpected error: ${\n            formatApiErrorMessage({ error })\n          }`\n        )\n      );\n    }\n    process.exit(1);\n  }\n};\n"],"mappings":"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","names":[]}