normalizePackageData.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. //# sourceMappingURL=normalizePackageData.js.map