Skip to content

Commit e75c2df

Browse files
Better handle of directory imports
1 parent 9758e1c commit e75c2df

File tree

2 files changed

+94
-16
lines changed

2 files changed

+94
-16
lines changed

packages/cli-kit/src/public/node/import-extractor.test.ts

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,67 @@ describe('extractImportPaths', () => {
112112
)
113113

114114
const imports = extractImportPaths(mainFile)
115-
// The import extractor resolves './utils' to the directory path
115+
// The import extractor resolves './utils' to the index file
116116
expect(imports).toHaveLength(1)
117-
expect(imports[0]).toBe(utilsDir)
117+
expect(imports[0]).toBe(utilsIndex)
118+
})
119+
})
120+
121+
test('resolves directory imports to various index file types', async () => {
122+
await inTemporaryDirectory(async (tmpDir) => {
123+
// Test with index.jsx
124+
const jsxDir = joinPath(tmpDir, 'jsx-component')
125+
const jsxIndex = joinPath(jsxDir, 'index.jsx')
126+
await mkdir(jsxDir)
127+
await writeFile(jsxIndex, 'export default () => <div />')
128+
129+
// Test with index.tsx
130+
const tsxDir = joinPath(tmpDir, 'tsx-component')
131+
const tsxIndex = joinPath(tsxDir, 'index.tsx')
132+
await mkdir(tsxDir)
133+
await writeFile(tsxIndex, 'export default () => <div />')
134+
135+
// Test with index.js (when importing from TypeScript)
136+
const jsDir = joinPath(tmpDir, 'js-module')
137+
const jsIndex = joinPath(jsDir, 'index.js')
138+
await mkdir(jsDir)
139+
await writeFile(jsIndex, 'module.exports = {}')
140+
const mainFile = joinPath(tmpDir, 'main.ts')
141+
await writeFile(
142+
mainFile,
143+
`
144+
import jsxComponent from './jsx-component'
145+
import tsxComponent from './tsx-component'
146+
import jsModule from './js-module'
147+
`,
148+
)
149+
150+
const imports = extractImportPaths(mainFile)
151+
expect(imports).toHaveLength(3)
152+
expect(imports).toContain(jsxIndex)
153+
expect(imports).toContain(tsxIndex)
154+
expect(imports).toContain(jsIndex)
155+
})
156+
})
157+
158+
test('returns empty array when directory has no index file', async () => {
159+
await inTemporaryDirectory(async (tmpDir) => {
160+
const mainFile = joinPath(tmpDir, 'main.js')
161+
const emptyDir = joinPath(tmpDir, 'empty-dir')
162+
163+
await mkdir(emptyDir)
164+
// Don't create any index file in the directory
165+
166+
await writeFile(
167+
mainFile,
168+
`
169+
import something from './empty-dir'
170+
`,
171+
)
172+
173+
const imports = extractImportPaths(mainFile)
174+
// Should return empty array since no index file exists
175+
expect(imports).toHaveLength(0)
118176
})
119177
})
120178
})
@@ -501,12 +559,12 @@ describe('extractImportPathsRecursively', () => {
501559

502560
const imports = extractImportPathsRecursively(mainFile)
503561

504-
// When importing from './components', the resolveJSImport function returns the directory path
505-
// The recursive function doesn't currently handle following imports from directories
506-
// This is a known limitation of the current implementation
562+
// When importing from './components', it should resolve to index.js and recursively extract all imports
507563
expect(imports).toContain(mainFile)
508-
expect(imports).toContain(componentsDir)
509-
expect(imports).toHaveLength(2)
564+
expect(imports).toContain(componentsIndex)
565+
expect(imports).toContain(buttonFile)
566+
expect(imports).toContain(inputFile)
567+
expect(imports).toHaveLength(4)
510568
})
511569
})
512570

packages/cli-kit/src/public/node/import-extractor.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export function extractImportPathsRecursively(filePath: string, visited: Set<str
5252
// Recursively process each imported file
5353
for (const importedFile of directImports) {
5454
try {
55+
// Only process files that exist and are not directories
56+
// Note: resolveJSImport already resolves directory imports to their index files
5557
if (fileExistsSync(importedFile) && !isDirectorySync(importedFile)) {
5658
const nestedImports = extractImportPathsRecursively(importedFile, visited)
5759
allImports.push(...nestedImports)
@@ -148,19 +150,37 @@ function extractRustImports(content: string, filePath: string): string[] {
148150

149151
function resolveJSImport(importPath: string, fromFile: string): string | null {
150152
const basePath = fileExistsSync(fromFile) && isDirectorySync(fromFile) ? fromFile : dirname(fromFile)
153+
const resolvedPath = joinPath(basePath, importPath)
154+
155+
// If the import path resolves to a directory, look for index files
156+
if (fileExistsSync(resolvedPath) && isDirectorySync(resolvedPath)) {
157+
const indexPaths = [
158+
joinPath(resolvedPath, 'index.js'),
159+
joinPath(resolvedPath, 'index.ts'),
160+
joinPath(resolvedPath, 'index.tsx'),
161+
joinPath(resolvedPath, 'index.jsx'),
162+
]
163+
164+
for (const indexPath of indexPaths) {
165+
if (fileExistsSync(indexPath) && !isDirectorySync(indexPath)) {
166+
return indexPath
167+
}
168+
}
169+
// If no index file found, don't return the directory
170+
return null
171+
}
172+
173+
// Check for file with extensions
151174
const possiblePaths = [
152-
joinPath(basePath, importPath),
153-
joinPath(basePath, `${importPath}.js`),
154-
joinPath(basePath, `${importPath}.ts`),
155-
joinPath(basePath, `${importPath}.tsx`),
156-
joinPath(basePath, `${importPath}.jsx`),
157-
joinPath(basePath, importPath, 'index.js'),
158-
joinPath(basePath, importPath, 'index.ts'),
159-
joinPath(basePath, importPath, 'index.tsx'),
175+
resolvedPath,
176+
`${resolvedPath}.js`,
177+
`${resolvedPath}.ts`,
178+
`${resolvedPath}.tsx`,
179+
`${resolvedPath}.jsx`,
160180
]
161181

162182
for (const path of possiblePaths) {
163-
if (fileExistsSync(path)) {
183+
if (fileExistsSync(path) && !isDirectorySync(path)) {
164184
return path
165185
}
166186
}

0 commit comments

Comments
 (0)