source: frontend/node_modules/tsconfig-paths/src/match-path-async.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 13 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.6 KB
Line 
1import * as path from "path";
2import * as TryPath from "./try-path";
3import * as MappingEntry from "./mapping-entry";
4import * as Filesystem from "./filesystem";
5
6/**
7 * Function that can match a path async
8 */
9export interface MatchPathAsync {
10 (
11 requestedModule: string,
12 readJson: Filesystem.ReadJsonAsync | undefined,
13 fileExists: Filesystem.FileExistsAsync | undefined,
14 extensions: ReadonlyArray<string> | undefined,
15 callback: MatchPathAsyncCallback
16 ): void;
17}
18
19export interface MatchPathAsyncCallback {
20 (err?: Error, path?: string): void;
21}
22
23/**
24 * See the sync version for docs.
25 */
26export function createMatchPathAsync(
27 absoluteBaseUrl: string,
28 paths: { [key: string]: Array<string> },
29 mainFields: string[] = ["main"],
30 addMatchAll: boolean = true
31): MatchPathAsync {
32 const absolutePaths = MappingEntry.getAbsoluteMappingEntries(
33 absoluteBaseUrl,
34 paths,
35 addMatchAll
36 );
37
38 return (
39 requestedModule: string,
40 readJson: Filesystem.ReadJsonAsync | undefined,
41 fileExists: Filesystem.FileExistsAsync | undefined,
42 extensions: ReadonlyArray<string> | undefined,
43 callback: MatchPathAsyncCallback
44 ) =>
45 matchFromAbsolutePathsAsync(
46 absolutePaths,
47 requestedModule,
48 readJson,
49 fileExists,
50 extensions,
51 callback,
52 mainFields
53 );
54}
55
56/**
57 * See the sync version for docs.
58 */
59export function matchFromAbsolutePathsAsync(
60 absolutePathMappings: ReadonlyArray<MappingEntry.MappingEntry>,
61 requestedModule: string,
62 readJson: Filesystem.ReadJsonAsync = Filesystem.readJsonFromDiskAsync,
63 fileExists: Filesystem.FileExistsAsync = Filesystem.fileExistsAsync,
64 extensions: ReadonlyArray<string> = Object.keys(require.extensions),
65 callback: MatchPathAsyncCallback,
66 mainFields: string[] = ["main"]
67): void {
68 const tryPaths = TryPath.getPathsToTry(
69 extensions,
70 absolutePathMappings,
71 requestedModule
72 );
73
74 if (!tryPaths) {
75 return callback();
76 }
77
78 findFirstExistingPath(
79 tryPaths,
80 readJson,
81 fileExists,
82 callback,
83 0,
84 mainFields
85 );
86}
87
88function findFirstExistingMainFieldMappedFile(
89 packageJson: Filesystem.PackageJson,
90 mainFields: string[],
91 packageJsonPath: string,
92 fileExistsAsync: Filesystem.FileExistsAsync,
93 doneCallback: (err?: Error, filepath?: string) => void,
94 index: number = 0
95): void {
96 if (index >= mainFields.length) {
97 return doneCallback(undefined, undefined);
98 }
99
100 const tryNext = () =>
101 findFirstExistingMainFieldMappedFile(
102 packageJson,
103 mainFields,
104 packageJsonPath,
105 fileExistsAsync,
106 doneCallback,
107 index + 1
108 );
109
110 const mainFieldMapping = packageJson[mainFields[index]];
111 if (typeof mainFieldMapping !== "string") {
112 // Skip mappings that are not pointers to replacement files
113 return tryNext();
114 }
115
116 const mappedFilePath = path.join(
117 path.dirname(packageJsonPath),
118 mainFieldMapping
119 );
120 fileExistsAsync(mappedFilePath, (err?: Error, exists?: boolean) => {
121 if (err) {
122 return doneCallback(err);
123 }
124 if (exists) {
125 return doneCallback(undefined, mappedFilePath);
126 }
127 return tryNext();
128 });
129}
130
131// Recursive loop to probe for physical files
132function findFirstExistingPath(
133 tryPaths: ReadonlyArray<TryPath.TryPath>,
134 readJson: Filesystem.ReadJsonAsync,
135 fileExists: Filesystem.FileExistsAsync,
136 doneCallback: MatchPathAsyncCallback,
137 index: number = 0,
138 mainFields: string[] = ["main"]
139): void {
140 const tryPath = tryPaths[index];
141 if (
142 tryPath.type === "file" ||
143 tryPath.type === "extension" ||
144 tryPath.type === "index"
145 ) {
146 fileExists(tryPath.path, (err: Error, exists: boolean) => {
147 if (err) {
148 return doneCallback(err);
149 }
150 if (exists) {
151 return doneCallback(undefined, TryPath.getStrippedPath(tryPath));
152 }
153 if (index === tryPaths.length - 1) {
154 return doneCallback();
155 }
156 // Continue with the next path
157 return findFirstExistingPath(
158 tryPaths,
159 readJson,
160 fileExists,
161 doneCallback,
162 index + 1,
163 mainFields
164 );
165 });
166 } else if (tryPath.type === "package") {
167 readJson(tryPath.path, (err, packageJson) => {
168 if (err) {
169 return doneCallback(err);
170 }
171 if (packageJson) {
172 return findFirstExistingMainFieldMappedFile(
173 packageJson,
174 mainFields,
175 tryPath.path,
176 fileExists,
177 (mainFieldErr?: Error, mainFieldMappedFile?: string) => {
178 if (mainFieldErr) {
179 return doneCallback(mainFieldErr);
180 }
181 if (mainFieldMappedFile) {
182 return doneCallback(undefined, mainFieldMappedFile);
183 }
184
185 // No field in package json was a valid option. Continue with the next path.
186 return findFirstExistingPath(
187 tryPaths,
188 readJson,
189 fileExists,
190 doneCallback,
191 index + 1,
192 mainFields
193 );
194 }
195 );
196 }
197
198 // This is async code, we need to return unconditionally, otherwise the code still falls
199 // through and keeps recursing. While this might work in general, libraries that use neo-async
200 // like Webpack will actually not allow you to call the same callback twice.
201 //
202 // An example of where this caused issues:
203 // https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/11
204 //
205 // Continue with the next path
206 return findFirstExistingPath(
207 tryPaths,
208 readJson,
209 fileExists,
210 doneCallback,
211 index + 1,
212 mainFields
213 );
214 });
215 } else {
216 TryPath.exhaustiveTypeException(tryPath.type);
217 }
218}
Note: See TracBrowser for help on using the repository browser.