eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 8 kB
JavaScript
import{existsSync}from"node:fs";import{dirname,join,relative,resolve,sep}from"node:path";import{lstat,readlink,realpath}from"node:fs/promises";import{parseTsConfigObject,readTextFileIfExists,resolveTsConfigDependencyPaths}from"#internal/application/tsconfig-dependencies.js";const DEV_RUNTIME_SOURCE_DIRECTORY=`source`,SOURCE_ROOT_MARKER_NAMES=[`.git`,`pnpm-workspace.yaml`],WORKSPACE_METADATA_FILE_NAMES=[`package.json`,`pnpm-workspace.yaml`,`pnpm-lock.yaml`,`package-lock.json`,`yarn.lock`,`bun.lock`,`bun.lockb`,`.npmrc`],PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];var DevelopmentRuntimeSourceSnapshotError=class extends Error{constructor(e){super(e),this.name=`DevelopmentRuntimeSourceSnapshotError`}};async function createDevelopmentSourceSnapshotPlan(e){let t=resolve(e.appRoot),r=resolve(e.snapshotRoot),a=resolveDevelopmentSourceRoot(t),o=join(r,DEV_RUNTIME_SOURCE_DIRECTORY),s={appRoot:t,copyFiles:new Set,copyRoots:new Set,dependencyMountsByPath:new Map,localRootsToProcess:[t],processedLocalRoots:new Set,snapshotRoot:r,snapshotSourceRoot:o,sourceRoot:a,tsconfigPaths:new Set};for(addWorkspaceMetadataFiles(s);s.localRootsToProcess.length>0;){let e=s.localRootsToProcess.shift();if(e===void 0)continue;let t=resolve(e);s.processedLocalRoots.has(t)||!isAuthoredSourcePath(t,a)||(s.processedLocalRoots.add(t),s.copyRoots.add(t),await addTsConfigDependenciesForRoot(s,t),await addDependencyMountsForRoot(s,t))}let c=normalizeCopyRoots([...s.copyRoots]),l=[...s.copyFiles].filter(e=>isPathInsideOrEqual(e,a)).sort((e,t)=>e.localeCompare(t)),u=[...s.tsconfigPaths].filter(e=>isPathInsideOrEqual(e,a)).sort((e,t)=>e.localeCompare(t)),d=[...s.dependencyMountsByPath.values()].sort((e,t)=>e.mountPath.localeCompare(t.mountPath)),f=createWatchPaths({appRoot:t,copyFiles:l,copyRoots:c,dependencyMounts:d,sourceRoot:a,tsconfigPaths:u});return{appRoot:t,copyFiles:l,copyRoots:c,dependencyMounts:d,runtimeAppRoot:toSnapshotPath({sourcePath:t,sourceRoot:a,snapshotSourceRoot:o}),snapshotRoot:r,snapshotSourceRoot:o,sourceRoot:a,tsconfigPaths:u,watchPaths:f}}async function resolveDevelopmentSourceSnapshotWatchPaths(e){return[...(await createDevelopmentSourceSnapshotPlan({appRoot:e,snapshotRoot:join(resolve(e),`.eve`,`dev-runtime`,`__watch-plan__`)})).watchPaths]}function toDevelopmentSourceSnapshotPath(e){return toSnapshotPath(e)}function resolveDevelopmentSourceRoot(r){let a=resolve(r);for(;;){if(SOURCE_ROOT_MARKER_NAMES.some(t=>existsSync(join(a,t))))return a;let o=dirname(a);if(o===a)return resolve(r);a=o}}function addWorkspaceMetadataFiles(t){for(let r of WORKSPACE_METADATA_FILE_NAMES){let i=join(t.sourceRoot,r);existsSync(i)&&t.copyFiles.add(i)}}async function addTsConfigDependenciesForRoot(e,t){let n=await resolveTsConfigDependencyPaths(t);for(let t of n)if(isPathInsideOrEqual(t,e.sourceRoot)){e.tsconfigPaths.add(t),e.copyFiles.add(t);for(let n of await resolveLocalTsConfigPathTargetRoots({configPath:t,sourceRoot:e.sourceRoot}))enqueueLocalRoot(e,n)}}async function addDependencyMountsForRoot(e,t){let n=await readPackageDependencyNames(t);for(let r of n)for(let n of[t,e.sourceRoot])await addDependencyMount(e,joinNodeModulesPackagePath(n,r))}async function addDependencyMount(t,n){let r;try{r=await lstat(n)}catch{return}if(!r.isDirectory()&&!r.isSymbolicLink())return;let a=await resolveDependencySourcePathCandidates(n),s=a.find(e=>isAuthoredSourcePath(e,t.sourceRoot));if(s!==void 0){await addWorkspaceDependencyMount({mountPath:n,state:t,sourcePath:s});return}let c=a.find(t=>existsSync(t));c!==void 0&&t.dependencyMountsByPath.set(resolve(n),{mountPath:resolve(n),sourceKind:`installed`,sourcePath:c})}async function addWorkspaceDependencyMount(e){let t=await resolveNearestPackageRoot(e.sourcePath,e.state.sourceRoot);if(t===void 0||!isAuthoredSourcePath(t,e.state.sourceRoot))return;let{state:n}=e;enqueueLocalRoot(n,t),n.dependencyMountsByPath.set(resolve(e.mountPath),{mountPath:resolve(e.mountPath),sourceKind:`workspace`,sourcePath:t})}async function resolveDependencySourcePathCandidates(e){let n=new Set;try{let r=await readlink(e);n.add(resolve(dirname(e),r))}catch{}try{n.add(await realpath(e))}catch{}return[...n]}function enqueueLocalRoot(e,t){let n=resolve(t);e.processedLocalRoots.has(n)||e.localRootsToProcess.includes(n)||!isAuthoredSourcePath(n,e.sourceRoot)||e.localRootsToProcess.push(n)}async function readPackageDependencyNames(e){let t=await readTextFileIfExists(join(e,`package.json`));if(t===void 0)return[];let r;try{r=JSON.parse(t)}catch{return[]}if(!isObjectRecord(r))return[];let i=new Set;for(let e of PACKAGE_DEPENDENCY_FIELDS){let t=r[e];if(isObjectRecord(t))for(let e of Object.keys(t))i.add(e)}return[...i].sort((e,t)=>e.localeCompare(t))}async function resolveLocalTsConfigPathTargetRoots(e){let n=await readTextFileIfExists(e.configPath);if(n===void 0)return[];let r=parseTsConfigObject(n),a=isObjectRecord(r?.compilerOptions)?r.compilerOptions:void 0,o=isObjectRecord(a?.paths)?a.paths:void 0;if(a===void 0||o===void 0)return[];let s=typeof a.baseUrl==`string`?resolve(dirname(e.configPath),a.baseUrl):dirname(e.configPath),c=new Set;for(let t of Object.values(o))if(Array.isArray(t))for(let n of t){if(typeof n!=`string`||n.length===0)continue;let t=await resolveLocalTsConfigPathTargetRoot({baseDirectory:s,sourceRoot:e.sourceRoot,target:n});t!==void 0&&c.add(t)}return[...c].sort((e,t)=>e.localeCompare(t))}async function resolveLocalTsConfigPathTargetRoot(e){let t=e.target.includes(`*`),n=t?e.target.slice(0,e.target.indexOf(`*`)):e.target;if(n.length===0||n===`.`||n===`./`)return;let r=resolve(e.baseDirectory,n);if(!isAuthoredSourcePath(r,e.sourceRoot))return;let a=await resolveExistingPathOrAncestor({path:r,stopDirectory:e.sourceRoot});if(a===void 0)return;let o=await resolveNearestPackageRoot(a,e.sourceRoot);if(o!==void 0&&o!==e.sourceRoot)return o;if(!t)return a===e.sourceRoot?void 0:a}async function resolveExistingPathOrAncestor(n){let r=resolve(n.path);for(;isAuthoredSourcePath(r,n.stopDirectory);){if(existsSync(r))return r;let n=dirname(r);if(n===r)return;r=n}}async function resolveNearestPackageRoot(r,a){let s=resolve(r);try{(await lstat(s)).isDirectory()||(s=dirname(s))}catch{s=dirname(s)}for(;isAuthoredSourcePath(s,a);){if(existsSync(join(s,`package.json`)))return s;let r=dirname(s);if(r===s)return;s=r}}function normalizeCopyRoots(e){let t=[...new Set(e.map(e=>resolve(e)))].sort((e,t)=>{let n=e.length-t.length;return n===0?e.localeCompare(t):n}),n=[];for(let e of t)n.some(t=>isPathInsideOrEqual(e,t))||n.push(e);return n.sort((e,t)=>e.localeCompare(t))}function createWatchPaths(t){let r=new Set([join(t.appRoot,`package.json`),...t.copyFiles,...t.tsconfigPaths]);for(let e of t.copyRoots)e!==t.appRoot&&r.add(e);for(let e of t.dependencyMounts)e.sourceKind===`workspace`&&e.sourcePath!==t.appRoot&&r.add(e.sourcePath);if(t.sourceRoot!==t.appRoot)for(let i of WORKSPACE_METADATA_FILE_NAMES){let a=join(t.sourceRoot,i);existsSync(a)&&r.add(a)}return[...r].sort((e,t)=>e.localeCompare(t))}function joinNodeModulesPackagePath(e,t){return join(e,`node_modules`,...t.split(`/`))}function toSnapshotPath(e){if(!isPathInsideOrEqual(e.sourcePath,e.sourceRoot))throw new DevelopmentRuntimeSourceSnapshotError(`Cannot map source path "${e.sourcePath}" into a development runtime snapshot because it is outside source root "${e.sourceRoot}".`);return join(e.snapshotSourceRoot,relative(e.sourceRoot,e.sourcePath))}function isPathInsideOrEqual(e,t){let n=resolve(e),r=resolve(t);return n===r||n.startsWith(`${r}${sep}`)}function isAuthoredSourcePath(e,t){return isPathInsideOrEqual(e,t)?!relative(t,e).split(/[\\/]/).includes(`node_modules`):!1}function isObjectRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{DEV_RUNTIME_SOURCE_DIRECTORY,DevelopmentRuntimeSourceSnapshotError,createDevelopmentSourceSnapshotPlan,isAuthoredSourcePath,resolveDevelopmentSourceRoot,resolveDevelopmentSourceSnapshotWatchPaths,toDevelopmentSourceSnapshotPath};