1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.normalizePackageData = void 0;
|
4 | const semver = require("semver");
|
5 | const hosted_git_info_1 = require("hosted-git-info");
|
6 | const url = require("url");
|
7 | function normalizePackageData(data) {
|
8 | for (const it of check) {
|
9 | it(data);
|
10 | }
|
11 | }
|
12 | exports.normalizePackageData = normalizePackageData;
|
13 | const depTypes = ["dependencies", "devDependencies", "optionalDependencies"];
|
14 | const check = [
|
15 | function (data) {
|
16 | if (data.repositories) {
|
17 | data.repository = data.repositories[0];
|
18 | }
|
19 | if (typeof data.repository === "string") {
|
20 | data.repository = {
|
21 | type: "git",
|
22 | url: data.repository,
|
23 | };
|
24 | }
|
25 | if (data.repository != null && data.repository.url) {
|
26 | const hosted = (0, hosted_git_info_1.fromUrl)(data.repository.url);
|
27 | if (hosted) {
|
28 | data.repository.url = hosted.getDefaultRepresentation() == "shortcut" ? hosted.https() : hosted.toString();
|
29 | }
|
30 | }
|
31 | },
|
32 | function (data) {
|
33 | const files = data.files;
|
34 | if (files && !Array.isArray(files)) {
|
35 | delete data.files;
|
36 | }
|
37 | else if (data.files) {
|
38 | data.files = data.files.filter(function (file) {
|
39 | return !(!file || typeof file !== "string");
|
40 | });
|
41 | }
|
42 | },
|
43 | function (data) {
|
44 | if (!data.bin) {
|
45 | return;
|
46 | }
|
47 | if (typeof data.bin === "string") {
|
48 | const b = {};
|
49 | const match = data.name.match(/^@[^/]+[/](.*)$/);
|
50 | if (match) {
|
51 | b[match[1]] = data.bin;
|
52 | }
|
53 | else {
|
54 | b[data.name] = data.bin;
|
55 | }
|
56 | data.bin = b;
|
57 | }
|
58 | },
|
59 | function (data) {
|
60 | if (data.description && typeof data.description !== "string") {
|
61 | delete data.description;
|
62 | }
|
63 | if (data.description === undefined) {
|
64 | delete data.description;
|
65 | }
|
66 | },
|
67 | fixBundleDependenciesField,
|
68 | function fixDependencies(data) {
|
69 | objectifyDeps(data);
|
70 | fixBundleDependenciesField(data);
|
71 | for (const deps of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
72 | if (!(deps in data)) {
|
73 | continue;
|
74 | }
|
75 | if (!data[deps] || typeof data[deps] !== "object") {
|
76 | delete data[deps];
|
77 | continue;
|
78 | }
|
79 | Object.keys(data[deps]).forEach(function (d) {
|
80 | const r = data[deps][d];
|
81 | if (typeof r !== "string") {
|
82 | delete data[deps][d];
|
83 | }
|
84 | const hosted = (0, hosted_git_info_1.fromUrl)(data[deps][d]);
|
85 | if (hosted) {
|
86 | data[deps][d] = hosted.toString();
|
87 | }
|
88 | });
|
89 | }
|
90 | },
|
91 | function fixBugsField(data) {
|
92 | if (!data.bugs && data.repository && data.repository.url) {
|
93 | const hosted = (0, hosted_git_info_1.fromUrl)(data.repository.url);
|
94 | if (hosted && hosted.bugs()) {
|
95 | data.bugs = { url: hosted.bugs() };
|
96 | }
|
97 | }
|
98 | else if (data.bugs) {
|
99 | const emailRe = /^.+@.*\..+$/;
|
100 | if (typeof data.bugs == "string") {
|
101 | if (emailRe.test(data.bugs)) {
|
102 | data.bugs = { email: data.bugs };
|
103 | }
|
104 | else if (url.parse(data.bugs).protocol) {
|
105 | data.bugs = { url: data.bugs };
|
106 | }
|
107 | }
|
108 | else {
|
109 | bugsTypos(data.bugs);
|
110 | const oldBugs = data.bugs;
|
111 | data.bugs = {};
|
112 | if (oldBugs.url) {
|
113 | if (typeof oldBugs.url == "string" && url.parse(oldBugs.url).protocol) {
|
114 | data.bugs.url = oldBugs.url;
|
115 | }
|
116 | }
|
117 | if (oldBugs.email) {
|
118 | if (typeof oldBugs.email == "string" && emailRe.test(oldBugs.email)) {
|
119 | data.bugs.email = oldBugs.email;
|
120 | }
|
121 | }
|
122 | }
|
123 | if (!data.bugs.email && !data.bugs.url) {
|
124 | delete data.bugs;
|
125 | }
|
126 | }
|
127 | },
|
128 | function fixModulesField(data) {
|
129 | if (data.modules) {
|
130 | delete data.modules;
|
131 | }
|
132 | },
|
133 | function fixKeywordsField(data) {
|
134 | if (typeof data.keywords === "string") {
|
135 | data.keywords = data.keywords.split(/,\s+/);
|
136 | }
|
137 | if (data.keywords && !Array.isArray(data.keywords)) {
|
138 | delete data.keywords;
|
139 | }
|
140 | else if (data.keywords) {
|
141 | data.keywords = data.keywords.filter(function (kw) {
|
142 | return !(typeof kw !== "string" || !kw);
|
143 | });
|
144 | }
|
145 | },
|
146 | function fixVersionField(data) {
|
147 | const loose = true;
|
148 | if (!data.version) {
|
149 | data.version = "";
|
150 | return true;
|
151 | }
|
152 | if (!semver.valid(data.version, loose)) {
|
153 | throw new Error(`Invalid version: "${data.version}"`);
|
154 | }
|
155 | data.version = semver.clean(data.version, loose);
|
156 | return true;
|
157 | },
|
158 | function fixPeople(data) {
|
159 | modifyPeople(data, unParsePerson);
|
160 | modifyPeople(data, parsePerson);
|
161 | },
|
162 | function fixNameField(data) {
|
163 | if (!data.name) {
|
164 | data.name = "";
|
165 | return;
|
166 | }
|
167 | if (typeof data.name !== "string") {
|
168 | throw new Error("name field must be a string.");
|
169 | }
|
170 | data.name = data.name.trim();
|
171 | ensureValidName(data.name);
|
172 | },
|
173 | function fixHomepageField(data) {
|
174 | if (!data.homepage && data.repository && data.repository.url) {
|
175 | const hosted = (0, hosted_git_info_1.fromUrl)(data.repository.url);
|
176 | if (hosted && hosted.docs()) {
|
177 | data.homepage = hosted.docs();
|
178 | }
|
179 | }
|
180 | if (!data.homepage) {
|
181 | return;
|
182 | }
|
183 | if (typeof data.homepage !== "string") {
|
184 | delete data.homepage;
|
185 | }
|
186 | if (!url.parse(data.homepage).protocol) {
|
187 | data.homepage = `https://${data.homepage}`;
|
188 | }
|
189 | return;
|
190 | },
|
191 | ];
|
192 | function fixBundleDependenciesField(data) {
|
193 | const bdd = "bundledDependencies";
|
194 | const bd = "bundleDependencies";
|
195 | if (data[bdd] && !data[bd]) {
|
196 | data[bd] = data[bdd];
|
197 | delete data[bdd];
|
198 | }
|
199 | if (data[bd] && !Array.isArray(data[bd])) {
|
200 | delete data[bd];
|
201 | }
|
202 | else if (data[bd]) {
|
203 | data[bd] = data[bd].filter(function (bd) {
|
204 | if (!bd || typeof bd !== "string") {
|
205 | return false;
|
206 | }
|
207 | else {
|
208 | if (!data.dependencies) {
|
209 | data.dependencies = {};
|
210 | }
|
211 | if (!("bd" in data.dependencies)) {
|
212 | data.dependencies[bd] = "*";
|
213 | }
|
214 | return true;
|
215 | }
|
216 | });
|
217 | }
|
218 | }
|
219 | function isValidScopedPackageName(spec) {
|
220 | if (spec.charAt(0) !== "@") {
|
221 | return false;
|
222 | }
|
223 | const rest = spec.slice(1).split("/");
|
224 | if (rest.length !== 2) {
|
225 | return false;
|
226 | }
|
227 | return rest[0] !== "" && rest[1] !== "" && rest[0] != null && rest[1] != null && rest[0] === encodeURIComponent(rest[0]) && rest[1] === encodeURIComponent(rest[1]);
|
228 | }
|
229 | function isCorrectlyEncodedName(spec) {
|
230 | return !/[/@\s+%:]/.test(spec) && spec === encodeURIComponent(spec);
|
231 | }
|
232 | function ensureValidName(name) {
|
233 | if (name.charAt(0) === "." ||
|
234 | !(isValidScopedPackageName(name) || isCorrectlyEncodedName(name)) ||
|
235 | name.toLowerCase() === "node_modules" ||
|
236 | name.toLowerCase() === "favicon.ico") {
|
237 | throw new Error("Invalid name: " + JSON.stringify(name));
|
238 | }
|
239 | }
|
240 | function modifyPeople(data, fn) {
|
241 | if (data.author) {
|
242 | data.author = fn(data.author);
|
243 | }
|
244 | for (const set of ["maintainers", "contributors"]) {
|
245 | if (!Array.isArray(data[set])) {
|
246 | continue;
|
247 | }
|
248 | data[set] = data[set].map(fn);
|
249 | }
|
250 | return data;
|
251 | }
|
252 | function unParsePerson(person) {
|
253 | if (typeof person === "string") {
|
254 | return person;
|
255 | }
|
256 | const name = person.name || "";
|
257 | const u = person.url || person.web;
|
258 | const url = u ? ` (${u})` : "";
|
259 | const e = person.email || person.mail;
|
260 | const email = e ? ` <${e}>` : "";
|
261 | return `${name}${email}${url}`;
|
262 | }
|
263 | function parsePerson(person) {
|
264 | if (typeof person !== "string") {
|
265 | return person;
|
266 | }
|
267 | const name = /^([^(<]+)/.exec(person);
|
268 | const url = /\(([^)]+)\)/.exec(person);
|
269 | const email = /<([^>]+)>/.exec(person);
|
270 | const obj = {};
|
271 | if (name && name[0].trim()) {
|
272 | obj.name = name[0].trim();
|
273 | }
|
274 | if (email) {
|
275 | obj.email = email[1];
|
276 | }
|
277 | if (url) {
|
278 | obj.url = url[1];
|
279 | }
|
280 | return obj;
|
281 | }
|
282 | function depObjectify(deps) {
|
283 | if (!deps) {
|
284 | return {};
|
285 | }
|
286 | if (typeof deps === "string") {
|
287 | deps = deps.trim().split(/[\n\r\s\t ,]+/);
|
288 | }
|
289 | if (!Array.isArray(deps)) {
|
290 | return deps;
|
291 | }
|
292 | const o = {};
|
293 | deps
|
294 | .filter(function (d) {
|
295 | return typeof d === "string";
|
296 | })
|
297 | .forEach(function (d) {
|
298 | d = d.trim().split(/(:?[@\s><=])/);
|
299 | const dn = d.shift();
|
300 | let dv = d.join("");
|
301 | dv = dv.trim();
|
302 | dv = dv.replace(/^@/, "");
|
303 | o[dn] = dv;
|
304 | });
|
305 | return o;
|
306 | }
|
307 | function objectifyDeps(data) {
|
308 | depTypes.forEach(function (type) {
|
309 | if (!data[type]) {
|
310 | return;
|
311 | }
|
312 | data[type] = depObjectify(data[type]);
|
313 | });
|
314 | }
|
315 | const typoBugs = { web: "url", name: "url" };
|
316 | function bugsTypos(bugs) {
|
317 | if (!bugs) {
|
318 | return;
|
319 | }
|
320 | Object.keys(bugs).forEach(function (k) {
|
321 | if (typoBugs[k]) {
|
322 | bugs[typoBugs[k]] = bugs[k];
|
323 | delete bugs[k];
|
324 | }
|
325 | });
|
326 | }
|
327 |
|
\ | No newline at end of file |