@@ -10,6 +10,18 @@ import * as path from 'node:path';
1010import { extract } from '@openpkg-ts/sdk' ;
1111import { normalize } from '@openpkg-ts/spec' ;
1212
13+ /**
14+ * Get the git repository root directory.
15+ */
16+ function getGitRoot ( cwd : string ) : string {
17+ return execSync ( 'git rev-parse --show-toplevel' , {
18+ encoding : 'utf-8' ,
19+ cwd,
20+ timeout : 5000 ,
21+ stdio : [ 'pipe' , 'pipe' , 'pipe' ] ,
22+ } ) . trim ( ) ;
23+ }
24+
1325/**
1426 * List all source files tracked at a given ref under a directory prefix.
1527 */
@@ -74,9 +86,11 @@ export async function extractSpecFromRef(
7486 entry : string ,
7587 cwd = process . cwd ( ) ,
7688) : Promise < ReturnType < typeof normalize > > {
77- // Resolve entry relative to cwd
78- const relEntry = path . relative ( cwd , path . resolve ( cwd , entry ) ) ;
79- const entryDir = path . dirname ( relEntry ) ;
89+ // Git paths are always repo-root-relative, so resolve against git root
90+ const gitRoot = getGitRoot ( cwd ) ;
91+ const absEntry = path . resolve ( cwd , entry ) ;
92+ const repoRelEntry = path . relative ( gitRoot , absEntry ) ;
93+ const entryDir = path . dirname ( repoRelEntry ) ;
8094
8195 // Determine source prefix to checkout (the directory containing the entry)
8296 // For monorepos: packages/sdk/src/index.ts → packages/sdk/
@@ -86,17 +100,15 @@ export async function extractSpecFromRef(
86100 const tmpDir = mkdtempSync ( path . join ( os . tmpdir ( ) , 'drift-git-' ) ) ;
87101
88102 try {
89- // List and checkout all source files at ref
103+ // List and checkout all source files at ref (paths must be repo-root-relative)
90104 const prefixes = srcPrefix === '.' ? [ '' ] : [ srcPrefix ] ;
91- // Always include root config files
92105 const rootFiles = [ 'tsconfig.json' , 'tsconfig.base.json' , 'package.json' ] ;
93106
94107 for ( const prefix of prefixes ) {
95- const files = listFilesAtRef ( ref , prefix || '.' , cwd ) ;
108+ const files = listFilesAtRef ( ref , prefix || '.' , gitRoot ) ;
96109 for ( const file of files ) {
97- // Only checkout .ts/.tsx/.json files
98110 if ( ! file . match ( / \. ( t s | t s x | j s o n | j s | m j s | c j s ) $ / ) ) continue ;
99- const content = getFileAtRef ( ref , file , cwd ) ;
111+ const content = getFileAtRef ( ref , file , gitRoot ) ;
100112 if ( content === null ) continue ;
101113 const destPath = path . join ( tmpDir , file ) ;
102114 mkdirSync ( path . dirname ( destPath ) , { recursive : true } ) ;
@@ -108,7 +120,7 @@ export async function extractSpecFromRef(
108120 for ( const rootFile of rootFiles ) {
109121 const dest = path . join ( tmpDir , rootFile ) ;
110122 if ( ! existsSync ( dest ) ) {
111- const content = getFileAtRef ( ref , rootFile , cwd ) ;
123+ const content = getFileAtRef ( ref , rootFile , gitRoot ) ;
112124 if ( content ) {
113125 writeFileSync ( dest , content ) ;
114126 }
@@ -122,9 +134,18 @@ export async function extractSpecFromRef(
122134 symlinkSync ( nmSrc , nmDest , 'dir' ) ;
123135 }
124136
137+ // Also try root node_modules if cwd differs from git root
138+ if ( cwd !== gitRoot ) {
139+ const rootNm = path . join ( gitRoot , 'node_modules' ) ;
140+ const rootNmDest = path . join ( tmpDir , 'node_modules' ) ;
141+ if ( existsSync ( rootNm ) && ! existsSync ( rootNmDest ) ) {
142+ symlinkSync ( rootNm , rootNmDest , 'dir' ) ;
143+ }
144+ }
145+
125146 // If entry is inside a nested package, also symlink its node_modules
126147 if ( srcPrefix !== '.' ) {
127- const nestedNm = path . join ( cwd , srcPrefix , 'node_modules' ) ;
148+ const nestedNm = path . join ( gitRoot , srcPrefix , 'node_modules' ) ;
128149 const nestedDest = path . join ( tmpDir , srcPrefix , 'node_modules' ) ;
129150 if ( existsSync ( nestedNm ) && ! existsSync ( nestedDest ) ) {
130151 symlinkSync ( nestedNm , nestedDest , 'dir' ) ;
@@ -139,9 +160,9 @@ export async function extractSpecFromRef(
139160 }
140161
141162 // Extract
142- const entryFile = path . join ( tmpDir , relEntry ) ;
163+ const entryFile = path . join ( tmpDir , repoRelEntry ) ;
143164 if ( ! existsSync ( entryFile ) ) {
144- throw new Error ( `Entry file not found at ref ${ ref } : ${ relEntry } ` ) ;
165+ throw new Error ( `Entry file not found at ref ${ ref } : ${ repoRelEntry } ` ) ;
145166 }
146167
147168 const result = await extract ( { entryFile } ) ;
0 commit comments