UNPKG

6.98 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
12}) : (function(o, m, k, k2) {
13 if (k2 === undefined) k2 = k;
14 o[k2] = m[k];
15}));
16var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17 Object.defineProperty(o, "default", { enumerable: true, value: v });
18}) : function(o, v) {
19 o["default"] = v;
20});
21var __importStar = (this && this.__importStar) || function (mod) {
22 if (mod && mod.__esModule) return mod;
23 var result = {};
24 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25 __setModuleDefault(result, mod);
26 return result;
27};
28Object.defineProperty(exports, "__esModule", { value: true });
29exports.TypeScriptPathsPlugin = void 0;
30const path = __importStar(require("path"));
31const getInnerRequest = require('enhanced-resolve/lib/getInnerRequest');
32class TypeScriptPathsPlugin {
33 constructor(options) {
34 this.options = options;
35 }
36 update(options) {
37 this.options = options;
38 }
39 // eslint-disable-next-line @typescript-eslint/no-explicit-any
40 apply(resolver) {
41 const target = resolver.ensureHook('resolve');
42 resolver.getHook('described-resolve').tapAsync('TypeScriptPathsPlugin',
43 // eslint-disable-next-line @typescript-eslint/no-explicit-any
44 (request, resolveContext, callback) => {
45 if (!this.options) {
46 callback();
47 return;
48 }
49 if (!request || request.typescriptPathMapped) {
50 callback();
51 return;
52 }
53 const originalRequest = getInnerRequest(resolver, request);
54 if (!originalRequest) {
55 callback();
56 return;
57 }
58 // Only work on Javascript/TypeScript issuers.
59 if (!request.context.issuer || !request.context.issuer.match(/\.[jt]sx?$/)) {
60 callback();
61 return;
62 }
63 // Relative or absolute requests are not mapped
64 if (originalRequest.startsWith('.') || originalRequest.startsWith('/')) {
65 callback();
66 return;
67 }
68 // Ignore all webpack special requests
69 if (originalRequest.startsWith('!!')) {
70 callback();
71 return;
72 }
73 const replacements = findReplacements(originalRequest, this.options.paths || {});
74 const tryResolve = () => {
75 var _a;
76 const potential = replacements.shift();
77 if (!potential) {
78 callback();
79 return;
80 }
81 const potentialRequest = {
82 ...request,
83 request: path.resolve(((_a = this.options) === null || _a === void 0 ? void 0 : _a.baseUrl) || '', potential),
84 typescriptPathMapped: true,
85 };
86 resolver.doResolve(target, potentialRequest, '', resolveContext,
87 // eslint-disable-next-line @typescript-eslint/no-explicit-any
88 (error, result) => {
89 if (error) {
90 callback(error);
91 }
92 else if (result) {
93 callback(undefined, result);
94 }
95 else {
96 tryResolve();
97 }
98 });
99 };
100 tryResolve();
101 });
102 }
103}
104exports.TypeScriptPathsPlugin = TypeScriptPathsPlugin;
105function findReplacements(originalRequest, paths) {
106 // check if any path mapping rules are relevant
107 const pathMapOptions = [];
108 for (const pattern in paths) {
109 // get potentials and remove duplicates; JS Set maintains insertion order
110 const potentials = Array.from(new Set(paths[pattern]));
111 if (potentials.length === 0) {
112 // no potential replacements so skip
113 continue;
114 }
115 // can only contain zero or one
116 const starIndex = pattern.indexOf('*');
117 if (starIndex === -1) {
118 if (pattern === originalRequest) {
119 pathMapOptions.push({
120 starIndex,
121 partial: '',
122 potentials,
123 });
124 }
125 }
126 else if (starIndex === 0 && pattern.length === 1) {
127 if (potentials.length === 1 && potentials[0] === '*') {
128 // identity mapping -> noop
129 continue;
130 }
131 pathMapOptions.push({
132 starIndex,
133 partial: originalRequest,
134 potentials,
135 });
136 }
137 else if (starIndex === pattern.length - 1) {
138 if (originalRequest.startsWith(pattern.slice(0, -1))) {
139 pathMapOptions.push({
140 starIndex,
141 partial: originalRequest.slice(pattern.length - 1),
142 potentials,
143 });
144 }
145 }
146 else {
147 const [prefix, suffix] = pattern.split('*');
148 if (originalRequest.startsWith(prefix) && originalRequest.endsWith(suffix)) {
149 pathMapOptions.push({
150 starIndex,
151 partial: originalRequest.slice(prefix.length).slice(0, -suffix.length),
152 potentials,
153 });
154 }
155 }
156 }
157 if (pathMapOptions.length === 0) {
158 return [];
159 }
160 // exact matches take priority then largest prefix match
161 pathMapOptions.sort((a, b) => {
162 if (a.starIndex === -1) {
163 return -1;
164 }
165 else if (b.starIndex === -1) {
166 return 1;
167 }
168 else {
169 return b.starIndex - a.starIndex;
170 }
171 });
172 const replacements = [];
173 pathMapOptions.forEach((option) => {
174 for (const potential of option.potentials) {
175 let replacement;
176 const starIndex = potential.indexOf('*');
177 if (starIndex === -1) {
178 replacement = potential;
179 }
180 else if (starIndex === potential.length - 1) {
181 replacement = potential.slice(0, -1) + option.partial;
182 }
183 else {
184 const [prefix, suffix] = potential.split('*');
185 replacement = prefix + option.partial + suffix;
186 }
187 replacements.push(replacement);
188 }
189 });
190 return replacements;
191}