import{endpointForProtocol}from"../connections/catalog.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"./package-json.js";import{join}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const CONNECT_PACKAGE_NAME=`@vercel/connect`,USER_AUTHORED_CONNECTION_DIR=`agent/connections`;function resolveAuth(e){return e.auth??{kind:`none`}}function envKeysForAuth(e){switch(e.kind){case`bearer-env`:return[e.envVar];case`header`:return e.headers.map(e=>e.envVar);case`connect`:case`none`:return[]}}function assertStampedVersion(e,t){if(t.startsWith(`__`))throw Error(`Connection scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`)}function authBlock(e){switch(e.kind){case`connect`:return`  auth: connect("${e.connector}"),\n`;case`bearer-env`:return`  auth: { getToken: async () => ({ token: process.env.${e.envVar}! }) },\n`;case`header`:return`  headers: () => ({\n${e.headers.map(e=>`    "${e.header}": process.env.${e.envVar}!,`).join(`
`)}\n  }),\n`;case`none`:return``}}function renderMcpTemplate(e,t,n){return`${n.kind===`connect`?`import { connect } from "@vercel/connect/eve";
import { defineMcpClientConnection } from "eve/connections";
`:`import { defineMcpClientConnection } from "eve/connections";
`}
export default defineMcpClientConnection({
  url: "${e.url}",
  description: "${t}",
${authBlock(n)}});
`}function renderOpenApiTemplate(e,t,n){let r=n.kind===`connect`?`import { connect } from "@vercel/connect/eve";
import { defineOpenAPIConnection } from "eve/connections";
`:`import { defineOpenAPIConnection } from "eve/connections";
`,i=e.baseUrl?`  baseUrl: "${e.baseUrl}",\n`:``;return`${r}
export default defineOpenAPIConnection({
  spec: "${e.spec}",
${i}  description: "${t}",
${authBlock(n)}});
`}function renderTemplate(e,t,n,r){return e===`mcp`?renderMcpTemplate(t,n,r):renderOpenApiTemplate(t,n,r)}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function ensureConnectDependency(e,t){if(!await pathExists(e))return[];let n=JSON.parse(await readFile(e,`utf8`));return(isJsonObject(n)&&isJsonObject(n.dependencies)?n.dependencies[CONNECT_PACKAGE_NAME]:void 0)===t?[]:(await patchPackageJson(e,{dependencies:{[CONNECT_PACKAGE_NAME]:t}}),[{path:e,dependencies:[CONNECT_PACKAGE_NAME],devDependencies:[],scripts:[]}])}function envKeyPresent(e,t){return RegExp(`^\\s*(?:export\\s+)?${t}\\s*=`,`m`).test(e)}async function seedEnvPlaceholders(e,t){if(t.length===0)return[];let n=``;await pathExists(e)&&(n=await readFile(e,`utf8`));let i=t.filter(e=>!envKeyPresent(n,e));if(i.length===0)return[];let a=`${n.length>0&&!n.endsWith(`
`)?`
`:``}${i.map(e=>`${e}=`).join(`
`)}\n`;return await writeFile(e,n+a,`utf8`),i}async function ensureConnection(t){let n=t.slug??t.entry.slug,a=resolveAuth(t.entry),o=endpointForProtocol(t.entry,t.protocol);if(o===null)throw Error(`Connection "${n}" is missing a ${t.protocol===`mcp`?`mcp.url`:`openapi.spec`} endpoint for protocol "${t.protocol}".`);let s=join(t.projectRoot,USER_AUTHORED_CONNECTION_DIR,`${n}.ts`),c=envKeysForAuth(a),l=await pathExists(s);if(!t.force&&l)return{slug:n,protocol:t.protocol,action:`skipped`,filePath:s,filesWritten:[],filesSkipped:[s],packageJsonUpdated:[],envKeysAdded:[],envKeysRequired:c};let u=[];if(a.kind===`connect`){let e=t.connectPackageVersion??`0.2.2`;assertStampedVersion(`connectPackageVersion`,e),u.push(...await ensureConnectDependency(join(t.projectRoot,`package.json`),e))}await writeTextFile(s,renderTemplate(t.protocol,o,t.entry.description,a),{force:!0});let d=await seedEnvPlaceholders(join(t.projectRoot,`.env.local`),c),f={slug:n,protocol:t.protocol,action:l?`overwritten`:`created`,filePath:s,filesWritten:[s],filesSkipped:[],packageJsonUpdated:u,envKeysAdded:d,envKeysRequired:c};return l&&(f.filesOverwritten=[s]),f}async function listAuthoredConnections(e){let r=join(e,USER_AUTHORED_CONNECTION_DIR),i;try{i=await readdir(r,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let a=[];for(let e of i){if(e.isFile()){let n=getSupportedModuleBaseName(e.name);n!==null&&a.push(n);continue}if(e.isDirectory())try{(await readdir(join(r,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&a.push(e.name)}catch{}}return a.sort()}export{ensureConnection,listAuthoredConnections};