Skip to content

Commit 088a565

Browse files
committed
fix(docs-infra): Cannot find module message
Fixed the import error message in the editor section. The build would complete successfully, but an error message would be incorrectly reported.
1 parent 25e8bcb commit 088a565

3 files changed

Lines changed: 63 additions & 8 deletions

File tree

adev/src/app/editor/code-editor/code-mirror-editor.service.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,17 @@ export class CodeMirrorEditor {
218218
return;
219219
}
220220

221-
// Send message to tsVfsWorker only when current file is TypeScript file.
222-
if (!this.currentFile()?.filename.endsWith('.ts')) return;
221+
// Always allow infrastructure/setup requests to go through, regardless of current file type.
222+
const infraActions = new Set<unknown>([
223+
TsVfsWorkerActions.CREATE_VFS_ENV_REQUEST,
224+
TsVfsWorkerActions.UPDATE_VFS_ENV_REQUEST,
225+
TsVfsWorkerActions.DEFINE_TYPES_REQUEST,
226+
]);
227+
228+
if (!infraActions.has(request.action)) {
229+
// For language-service operations, ensure the current file is a TypeScript file.
230+
if (!this.currentFile()?.filename.endsWith('.ts')) return;
231+
}
223232

224233
this.tsVfsWorker.postMessage(request);
225234
};

adev/src/app/editor/typings-loader.service.ts

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ export class TypingsLoader {
7676

7777
for (const library of this.librariesToGetTypesFrom) {
7878
// The library's package.json is where the type definitions are defined
79+
const packageJsonFsPath = `./node_modules/${library}/package.json`;
7980
const packageJsonContent = await this.webContainer.fs
80-
.readFile(`./node_modules/${library}/package.json`, 'utf-8')
81+
.readFile(packageJsonFsPath, 'utf-8')
8182
.catch((error) => {
8283
// Note: "ENOENT" errors occurs:
8384
// - While resetting the NodeRuntimeSandbox.
@@ -94,15 +95,31 @@ export class TypingsLoader {
9495
// if the package.json content is empty, skip this library
9596
if (!packageJsonContent) continue;
9697

98+
// Ensure the worker VFS also receives the package.json file so NodeNext resolution
99+
// can read "exports"/"types" information when resolving imports like '@angular/core'.
100+
filesToRead.push(`/node_modules/${library}/package.json`);
101+
97102
const packageJson = JSON.parse(packageJsonContent);
98103

99-
// If the package.json doesn't have `exports`, skip this library
104+
// If the package exposes a top-level types entry, include that directory as a fallback
105+
const topLevelTypes: string | undefined = packageJson.types ?? packageJson.typings;
106+
if (!packageJson?.exports && topLevelTypes) {
107+
const path = `/node_modules/${library}/${this.normalizePath(topLevelTypes)}`;
108+
const directory = path.substring(0, path.lastIndexOf('/'));
109+
directoriesToRead.push(directory);
110+
continue;
111+
}
112+
100113
if (!packageJson?.exports) continue;
101114

102115
// Based on `exports` we can identify paths to the types definition files
103116
for (const exportKey of Object.keys(packageJson.exports)) {
104117
const exportEntry = packageJson.exports[exportKey];
105-
const types: string | undefined = exportEntry.typings ?? exportEntry.types;
118+
// Handle both object and string entries; for strings we can't infer types, so skip
119+
const types: string | undefined =
120+
exportEntry && typeof exportEntry === 'object'
121+
? (exportEntry.typings ?? exportEntry.types)
122+
: undefined;
106123

107124
if (types) {
108125
const path = `/node_modules/${library}/${this.normalizePath(types)}`;
@@ -131,9 +148,38 @@ export class TypingsLoader {
131148
private async getTypeDefinitionFilesFromDirectory(directory: string): Promise<string[]> {
132149
if (!this.webContainer) throw new Error('this.webContainer is not defined');
133150

134-
const files = await this.webContainer.fs.readdir(directory);
151+
return this.getTypeDefinitionFilesRecursively(directory);
152+
}
153+
154+
private async getTypeDefinitionFilesRecursively(directory: string): Promise<string[]> {
155+
if (!this.webContainer) throw new Error('this.webContainer is not defined');
156+
157+
const results: string[] = [];
158+
const entries = await this.webContainer.fs.readdir(directory).catch((error) => {
159+
// Directory may not exist (e.g., optional export) — ignore.
160+
if (error?.message.startsWith('ENOENT')) return [];
161+
throw error;
162+
});
163+
164+
for (const entry of entries) {
165+
const fullPath = `${directory}/${entry}`;
166+
// Try to read as directory; if it fails, treat as file
167+
const children = await this.webContainer.fs.readdir(fullPath).catch((err) => {
168+
// Not a directory or doesn't exist
169+
return null;
170+
});
171+
172+
if (Array.isArray(children)) {
173+
const nested = await this.getTypeDefinitionFilesRecursively(fullPath);
174+
results.push(...nested);
175+
} else {
176+
if (this.isTypeDefinitionFile(fullPath)) {
177+
results.push(fullPath);
178+
}
179+
}
180+
}
135181

136-
return files.filter(this.isTypeDefinitionFile).map((file) => `${directory}/${file}`);
182+
return results;
137183
}
138184

139185
private isTypeDefinitionFile(path: string): boolean {

adev/src/content/tutorials/learn-angular/intro/src/app/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Component} from '@angular/core';
33
@Component({
44
selector: 'app-root',
55
template: `
6-
Welcome to Angular!
6+
Welcomes to Angular!
77
`,
88
})
99
export class App {}

0 commit comments

Comments
 (0)