@vltpkg/cli-js 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/{access-SXQICNAN.js → access-DB347PPG.js} +4 -4
  2. package/{bugs-OOPMFRCI.js → bugs-QBKI62J6.js} +10 -10
  3. package/{build-HDXI5OA7.js → build-EFJ3FFGU.js} +6 -6
  4. package/{cache-RW4Y4XNQ.js → cache-BQJCMDJN.js} +8 -8
  5. package/{chunk-U6DM3ROE.js → chunk-3HUTU5SO.js} +1 -1
  6. package/{chunk-F2FKLPZD.js → chunk-3MBSXZ62.js} +1 -1
  7. package/{chunk-UCD3RJYG.js → chunk-42UTZKAU.js} +5 -5
  8. package/{chunk-E5YE7UTZ.js → chunk-47IR6Z6C.js} +33 -16
  9. package/{chunk-4ZXA6RLP.js → chunk-5OGQND6H.js} +1 -1
  10. package/{chunk-3SQ5Y324.js → chunk-5PFGKHIS.js} +5 -7
  11. package/{chunk-EFWPI6IY.js → chunk-BSB4XGBB.js} +1 -1
  12. package/{chunk-EQ633HIM.js → chunk-CTDFRLS4.js} +3 -3
  13. package/{chunk-CCQYIYTA.js → chunk-DEMBZY23.js} +6 -6
  14. package/{chunk-ICJRCXSG.js → chunk-F2GLBPGQ.js} +8 -7
  15. package/{chunk-MT76WHSM.js → chunk-FM5DQZVN.js} +12 -6
  16. package/{chunk-MU7Y4R5E.js → chunk-L34LR5DV.js} +2 -2
  17. package/chunk-NS4VFXHX.js +49 -0
  18. package/{chunk-FAG776ZD.js → chunk-ONVLPT73.js} +1 -1
  19. package/{chunk-2PLIV3N3.js → chunk-Q46JRSZU.js} +718 -3
  20. package/{chunk-D5CP6O6G.js → chunk-TM4LHSZV.js} +4 -4
  21. package/{chunk-EHEVBLDB.js → chunk-ULCDRVY2.js} +4 -4
  22. package/{chunk-4RZDJQ5U.js → chunk-UVZJFBYE.js} +1 -1
  23. package/{chunk-WXMYKCQW.js → chunk-WAFERMRI.js} +39 -16
  24. package/{chunk-VM2RMMY4.js → chunk-YDUHQU7N.js} +3 -3
  25. package/{chunk-VZ7UNZHR.js → chunk-YRMICBI4.js} +2 -2
  26. package/chunk-ZLZ4XF46.js +75 -0
  27. package/{ci-MTYU2K2A.js → ci-A22A6TCQ.js} +7 -7
  28. package/cli-package.json +1 -1
  29. package/{config-TVAXCTQO.js → config-JL4TW2AV.js} +7 -7
  30. package/{config-6NXV2BXW.js → config-VOLRKFYD.js} +8 -8
  31. package/{create-LXI5DCDW.js → create-SL7HEXCS.js} +14 -14
  32. package/{deprecate-2AQBL5XT.js → deprecate-ZK525LQW.js} +8 -8
  33. package/{dist-tag-BFSYLRIH.js → dist-tag-FY3FB5VH.js} +5 -5
  34. package/{docs-ADPJ4B4C.js → docs-6BPWZJFW.js} +10 -10
  35. package/{exec-GMS54RAC.js → exec-JZ5J7DI7.js} +14 -14
  36. package/{exec-cache-R5LVZL5Z.js → exec-cache-VGSXKZVF.js} +12 -12
  37. package/{exec-local-TVCLZGIM.js → exec-local-GPZUSOSM.js} +11 -11
  38. package/{help-6CECUD6C.js → help-XI7TNIRU.js} +1 -1
  39. package/{init-XXFLGYVP.js → init-6KWM7CDI.js} +7 -7
  40. package/{install-6KMXYSF5.js → install-4VLOKCWH.js} +8 -8
  41. package/{list-RUO3SUKY.js → list-3VLGWGKU.js} +11 -11
  42. package/{login-6I2CGO7I.js → login-3DGPSWCG.js} +4 -4
  43. package/{logout-JTU4BJKH.js → logout-DBFMZC6J.js} +4 -4
  44. package/{pack-NCWH2TUA.js → pack-LHNYEZ5W.js} +8 -8
  45. package/package.json +6 -6
  46. package/{ping-4MEAC2WD.js → ping-VLLX5LIH.js} +4 -4
  47. package/{pkg-ENSKG6G7.js → pkg-FYPUMX7U.js} +8 -8
  48. package/{profile-62YHNFSO.js → profile-FOQ74TB7.js} +4 -4
  49. package/{publish-PPY724N2.js → publish-DFURU7DW.js} +10 -10
  50. package/{query-NLWXKOOT.js → query-NC3EABMW.js} +11 -11
  51. package/{registry-QGI44LG4.js → registry-5DUFCPD6.js} +3 -3
  52. package/registry-client-package.json +1 -1
  53. package/registry-client-src-revalidate.js +1679 -23
  54. package/{repo-BFRAXIVU.js → repo-IZXACKQ2.js} +10 -10
  55. package/{reporter-2XBYWAVU.js → reporter-UU654STB.js} +2 -2
  56. package/{run-7O65747G.js → run-RDFVO7FY.js} +11 -11
  57. package/{run-exec-2OYWHL6K.js → run-exec-OGMXEVN5.js} +11 -11
  58. package/security-archive-src-update-expired.js +28 -2
  59. package/{setup-MMIDAIJI.js → setup-KTJQPDJB.js} +17 -10
  60. package/{src-OK3KHDYR.js → src-BJU7XZNK.js} +12 -12
  61. package/{token-VLVXUW54.js → token-SKICECA4.js} +4 -4
  62. package/{uninstall-TAG6QIAG.js → uninstall-MTZJ33TO.js} +8 -8
  63. package/{unpublish-Y4L5J2IA.js → unpublish-3QBJZFHQ.js} +5 -5
  64. package/{update-RYH4RKBS.js → update-TH477PKA.js} +7 -7
  65. package/{version-COHB32ON.js → version-YIBQZLQS.js} +7 -7
  66. package/{view-P7U4MF43.js → view-FG74OAOV.js} +8 -8
  67. package/vlr.js +1 -1
  68. package/vlrx.js +1 -1
  69. package/vlt.js +1 -1
  70. package/vlx.js +1 -1
  71. package/vlxl.js +1 -1
  72. package/{whoami-47MVFMZC.js → whoami-LHJ4PRJQ.js} +4 -4
  73. package/chunk-HB7CKTYO.js +0 -75
  74. package/chunk-PW6S6AIO.js +0 -716
@@ -920,7 +920,685 @@ var comparatorNone = {
920
920
  test: (_) => false
921
921
  };
922
922
 
923
+ // ../../src/spec/src/valid-name.ts
924
+ var pathSafeName = /^(?!(?:node_modules|\.vlt)$)(?![A-Za-z]:)(?:@(?!\.\.?\/)[^/\\\x00-\x1f\x7f]+\/)?(?!\.\.?$)[^/\\\x00-\x1f\x7f]+$/i;
925
+ var isPathSafeName = (name) => typeof name === "string" && pathSafeName.test(name);
926
+ var assertPathSafeName = (name, from) => {
927
+ if (isPathSafeName(name)) return;
928
+ throw error(
929
+ "Invalid package name: not usable as a path segment",
930
+ {
931
+ code: "EINVALIDNAME",
932
+ found: name,
933
+ from,
934
+ wanted: "a single path segment, or a well-formed @scope/name"
935
+ },
936
+ assertPathSafeName
937
+ );
938
+ };
939
+
940
+ // ../../src/spec/src/browser.ts
941
+ var kCustomInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
942
+ var defaultRegistryName = "npm";
943
+ var defaultRegistries = {
944
+ gh: "https://npm.pkg.github.com/"
945
+ };
946
+ var defaultJsrRegistries = { jsr: "https://npm.jsr.io/" };
947
+ var defaultGitHosts = {
948
+ github: "git+ssh://git@github.com:$1/$2.git",
949
+ bitbucket: "git+ssh://git@bitbucket.org:$1/$2.git",
950
+ gitlab: "git+ssh://git@gitlab.com:$1/$2.git",
951
+ gist: "git+ssh://git@gist.github.com/$1.git"
952
+ };
953
+ var defaultGitHostArchives = {
954
+ github: "https://api.github.com/repos/$1/$2/tarball/$committish",
955
+ bitbucket: "https://bitbucket.org/$1/$2/get/$committish.tar.gz",
956
+ gist: "https://codeload.github.com/gist/$1/tar.gz/$committish",
957
+ gitlab: "https://gitlab.com/$1/$2/repository/archive.tar.gz?ref=$committish"
958
+ };
959
+ var gitHostWebsites = {
960
+ github: "https://github.com/",
961
+ bitbucket: "https://bitbucket.org/",
962
+ gist: "https://gist.github.com/",
963
+ gitlab: "https://gitlab.com/"
964
+ };
965
+ var defaultScopeRegistries = {
966
+ "@jsr": "https://npm.jsr.io/"
967
+ };
968
+ var getOptions = (options) => ({
969
+ catalog: {},
970
+ catalogs: {},
971
+ ...options,
972
+ // built-in aliases are user/service-overridable: user config wins
973
+ "jsr-registries": {
974
+ ...defaultJsrRegistries,
975
+ ...options?.["jsr-registries"] ?? {}
976
+ },
977
+ registry: options?.registry,
978
+ "default-registry-alias": options?.["default-registry-alias"] ?? defaultRegistryName,
979
+ "scoped-registries": options?.["scoped-registries"] ?? {},
980
+ "git-hosts": options?.["git-hosts"] ? {
981
+ ...defaultGitHosts,
982
+ ...options["git-hosts"]
983
+ } : defaultGitHosts,
984
+ registries: {
985
+ ...defaultRegistries,
986
+ ...options?.registries ?? {}
987
+ },
988
+ "git-host-archives": options?.["git-host-archives"] ? {
989
+ ...defaultGitHostArchives,
990
+ ...options["git-host-archives"]
991
+ } : defaultGitHostArchives
992
+ });
993
+ var startsWithSpecIdentifier = (spec, options) => spec.startsWith("/") || spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("file:") || spec.startsWith("http:") || spec.startsWith("https:") || spec.startsWith("workspace:") || spec.startsWith("catalog:") || spec.startsWith("git@") || spec.startsWith("git://") || spec.startsWith("git+ssh://") || spec.startsWith("git+http://") || spec.startsWith("git+https://") || spec.startsWith("git+file://") || spec.startsWith("git@github.com") || spec.startsWith("registry:") || spec.startsWith("npm:") || spec.startsWith("jsr:") || spec.startsWith("gh:") || // anything that starts with a known git host key, or a
994
+ // custom registered registry protocol e.g: `github:`, `custom:`
995
+ [
996
+ ...Object.keys(options["git-hosts"]),
997
+ ...Object.keys(options.registries),
998
+ ...Object.keys(options["jsr-registries"])
999
+ ].some((key) => spec.startsWith(`${key}:`));
1000
+ var findFirstAt = (spec, hasScope) => spec.indexOf("@", hasScope ? 1 : 0);
1001
+ var findGitIdentifier = (spec) => spec.indexOf("#") > 2;
1002
+ var findFileIdentifier = (spec) => spec.includes("/");
1003
+ var isSpec = (spec) => typeof spec === "object" && spec !== null && "spec" in spec && "bareSpec" in spec && "name" in spec && "type" in spec && "options" in spec && typeof spec.spec === "string" && typeof spec.bareSpec === "string" && typeof spec.name === "string";
1004
+ var currentDefaultRegistryName = (registry, options) => {
1005
+ for (const [name, url] of Object.entries(
1006
+ options.registries ?? {}
1007
+ )) {
1008
+ const specRegURL = registry.endsWith("/") ? registry : registry + "/";
1009
+ const knownRegURL = url.endsWith("/") ? url : url + "/";
1010
+ if (specRegURL === knownRegURL) {
1011
+ return name;
1012
+ }
1013
+ }
1014
+ };
1015
+ var Spec = class _Spec {
1016
+ static parse(spec, bareOrOptions, options) {
1017
+ return typeof spec === "object" ? spec : new this(spec, bareOrOptions, options);
1018
+ }
1019
+ static parseArgs(specOrBareSpec, opts) {
1020
+ const options = getOptions(opts ?? {});
1021
+ if (startsWithSpecIdentifier(specOrBareSpec, options)) {
1022
+ const parsed = this.parse("(unknown)", specOrBareSpec, options);
1023
+ if (parsed.subspec) {
1024
+ const { namedJsrRegistry: jsrHost } = parsed;
1025
+ if (!jsrHost) {
1026
+ parsed.name = parsed.subspec.name;
1027
+ }
1028
+ parsed.spec = `${parsed.name}@${parsed.bareSpec}`;
1029
+ assertPathSafeName(parsed.name, parsed.spec);
1030
+ }
1031
+ return parsed;
1032
+ } else {
1033
+ const hasScope = specOrBareSpec.startsWith("@");
1034
+ const at = findFirstAt(specOrBareSpec, hasScope);
1035
+ if (at > -1) {
1036
+ return this.parse(
1037
+ specOrBareSpec.substring(0, at),
1038
+ specOrBareSpec.substring(at + 1),
1039
+ options
1040
+ );
1041
+ } else if (findGitIdentifier(specOrBareSpec) || !hasScope && findFileIdentifier(specOrBareSpec)) {
1042
+ return this.parse("(unknown)", specOrBareSpec, options);
1043
+ } else {
1044
+ return this.parse(`${specOrBareSpec}@`, options);
1045
+ }
1046
+ }
1047
+ }
1048
+ static nodejsDependencies;
1049
+ type;
1050
+ spec;
1051
+ options;
1052
+ name;
1053
+ scope;
1054
+ scopeRegistry;
1055
+ bareSpec;
1056
+ gitRemote;
1057
+ gitSelector;
1058
+ gitSelectorParsed;
1059
+ gitCommittish;
1060
+ namedGitHost;
1061
+ namedGitHostPath;
1062
+ workspaceSpec;
1063
+ workspace;
1064
+ namedRegistry;
1065
+ namedJsrRegistry;
1066
+ registry;
1067
+ registrySpec;
1068
+ conventionalRegistryTarball;
1069
+ semver;
1070
+ range;
1071
+ distTag;
1072
+ remoteURL;
1073
+ file;
1074
+ catalog;
1075
+ subspec;
1076
+ overridden = false;
1077
+ #final;
1078
+ #toString;
1079
+ /**
1080
+ * Return the final entry in the chain of subspecs
1081
+ * When deciding which thing to actually fetch, spec.final is the thing
1082
+ * to look at.
1083
+ */
1084
+ get final() {
1085
+ if (this.#final) return this.#final;
1086
+ const final = this.subspec ? this.subspec.final : this;
1087
+ if (final.type === "catalog") {
1088
+ throw error('invalid Spec.final value, type is "catalog"');
1089
+ }
1090
+ return this.#final = final;
1091
+ }
1092
+ /**
1093
+ * Normally, the string value of a Spec is just the string passed in to
1094
+ * be parsed. However, in the case of a chain of subspecs, like
1095
+ * `foo@npm:bar@npm:baz@npm:quux@latest`, this simplifies out the middle
1096
+ * parts of the chain, returning just `foo@npm:quux@latest`
1097
+ */
1098
+ toString() {
1099
+ if (this.#toString !== void 0) return this.#toString;
1100
+ let sub = this;
1101
+ while (sub.subspec?.subspec) sub = sub.subspec;
1102
+ if (sub.subspec && sub.subspec.type !== "registry")
1103
+ sub = sub.subspec;
1104
+ return this.#toString = this.name + "@" + sub.bareSpec;
1105
+ }
1106
+ constructor(spec, bareOrOptions, options = {}) {
1107
+ if (bareOrOptions && typeof bareOrOptions === "object") {
1108
+ options = bareOrOptions;
1109
+ bareOrOptions = void 0;
1110
+ }
1111
+ this.options = getOptions(options);
1112
+ if (typeof bareOrOptions === "string") {
1113
+ this.name = spec;
1114
+ this.#parseScope(spec);
1115
+ this.bareSpec = bareOrOptions;
1116
+ this.spec = `${this.name}@${bareOrOptions}`;
1117
+ assertPathSafeName(this.name, this.spec);
1118
+ } else {
1119
+ this.spec = spec;
1120
+ if (!spec.startsWith("git@") && startsWithSpecIdentifier(spec, this.options) && spec.includes(":") && [
1121
+ ...Object.keys(this.options.registries),
1122
+ ...Object.keys(defaultRegistries)
1123
+ ].some((key) => spec.startsWith(`${key}:`))) {
1124
+ this.name = spec;
1125
+ this.bareSpec = spec;
1126
+ } else {
1127
+ const hasScope = spec.startsWith("@");
1128
+ let at = findFirstAt(spec, hasScope);
1129
+ if (at === -1) {
1130
+ at = spec.length;
1131
+ spec += "@";
1132
+ }
1133
+ this.name = spec.substring(0, at);
1134
+ assertPathSafeName(this.name, spec);
1135
+ if (hasScope) this.#parseScope(this.name);
1136
+ this.bareSpec = spec.substring(at + 1);
1137
+ }
1138
+ }
1139
+ if (this.bareSpec.startsWith("catalog:")) {
1140
+ this.catalog = this.bareSpec.substring("catalog:".length);
1141
+ const catalog = this.catalog ? this.options.catalogs?.[this.catalog] : this.options.catalog;
1142
+ if (!catalog) {
1143
+ throw this.#error("Named catalog not found", {
1144
+ name: this.catalog,
1145
+ validOptions: this.options.catalogs && Object.keys(this.options.catalogs)
1146
+ });
1147
+ }
1148
+ const sub = catalog[this.name];
1149
+ if (!sub) {
1150
+ throw this.#error("Name not found in catalog", {
1151
+ name: this.name,
1152
+ validOptions: Object.keys(catalog)
1153
+ });
1154
+ }
1155
+ this.subspec = _Spec.parse(this.name, sub, this.options);
1156
+ this.type = "catalog";
1157
+ this.registry = this.subspec.final.registry;
1158
+ return;
1159
+ }
1160
+ if (this.bareSpec.startsWith("https://")) {
1161
+ for (const [name, origin] of Object.entries(gitHostWebsites)) {
1162
+ if (this.bareSpec.startsWith(origin)) {
1163
+ const parsed = new URL(this.bareSpec);
1164
+ const [user, project] = parsed.pathname.replace(/\.git$/, "").replace(/\/+/g, " ").trim().split(" ");
1165
+ if (user && project) {
1166
+ this.bareSpec = `${name}:${user}/${project}${parsed.hash}`;
1167
+ this.spec = `${this.name}@${this.bareSpec}`;
1168
+ break;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+ if (this.bareSpec.startsWith("workspace:")) {
1174
+ this.type = "workspace";
1175
+ const ws = this.bareSpec.substring("workspace:".length).trim();
1176
+ const w = ws.lastIndexOf("@");
1177
+ if (w === -1) {
1178
+ this.workspace = this.name;
1179
+ } else {
1180
+ const wsName = ws.substring(0, w);
1181
+ if (!wsName || wsName === "*" || wsName === "~" || wsName === "^" || (wsName.startsWith("@") ? wsName.split("/").length !== 2 || wsName.substring(1).includes("@") : wsName.includes("@"))) {
1182
+ throw this.#error(
1183
+ "workspace: name must be a path or valid package name",
1184
+ { found: wsName }
1185
+ );
1186
+ }
1187
+ this.workspace = wsName;
1188
+ }
1189
+ const wss = w === -1 ? ws : ws.substring(w + 1) || "*";
1190
+ const range2 = wss === "*" ? void 0 : parseRange(wss);
1191
+ if (wss !== "*" && wss !== "~" && wss !== "^" && !range2) {
1192
+ throw this.#error(
1193
+ "workspace: spec must be one of *, ~, or ^, or a valid semver range",
1194
+ {
1195
+ found: wss,
1196
+ wanted: `'*'|'~'|'^'|SemverRange`
1197
+ }
1198
+ );
1199
+ }
1200
+ this.workspaceSpec = wss;
1201
+ if (range2) {
1202
+ this.semver = wss;
1203
+ this.range = range2;
1204
+ }
1205
+ return;
1206
+ }
1207
+ if (this.bareSpec.startsWith("git://") || this.bareSpec.startsWith("git+ssh://") || this.bareSpec.startsWith("git+http://") || this.bareSpec.startsWith("git+https://") || this.bareSpec.startsWith("git+file://") || // legacy affordance
1208
+ this.bareSpec.startsWith("git@github.com")) {
1209
+ if (this.bareSpec.startsWith("git@")) {
1210
+ this.bareSpec = `git+ssh://${this.bareSpec}`;
1211
+ this.spec = `${this.name}@${this.bareSpec}`;
1212
+ }
1213
+ this.type = "git";
1214
+ for (const [name, host] of Object.entries(
1215
+ this.options["git-hosts"]
1216
+ )) {
1217
+ const s = host.indexOf("$");
1218
+ if (s > 0 && this.bareSpec.startsWith(host.substring(0, s))) {
1219
+ const p = this.bareSpec.substring(s).replace(/\.git(#.*)?$/, "$1");
1220
+ this.bareSpec = `${name}:${p}`;
1221
+ this.spec = `${this.name}@${this.bareSpec}`;
1222
+ this.#parseHostedGit(name, host);
1223
+ this.type = "git";
1224
+ return;
1225
+ }
1226
+ }
1227
+ this.#parseGitSelector(this.bareSpec);
1228
+ return;
1229
+ }
1230
+ const regs = Object.entries(this.options.registries);
1231
+ if (this.bareSpec.startsWith("registry:")) {
1232
+ const reg = this.bareSpec.substring("registry:".length);
1233
+ const h = reg.indexOf("#");
1234
+ if (h === -1) {
1235
+ throw this.#error("registry: must include name/version");
1236
+ }
1237
+ this.type = "registry";
1238
+ let url = reg.substring(0, h);
1239
+ if (!url.endsWith("/")) url += "/";
1240
+ const regSpec = reg.substring(h + 1);
1241
+ for (let [name, u] of regs) {
1242
+ if (!u.endsWith("/")) {
1243
+ u += "/";
1244
+ this.options.registries[name] = u;
1245
+ }
1246
+ if (u === url) this.namedRegistry = name;
1247
+ }
1248
+ this.#parseRegistrySpec(regSpec, url);
1249
+ this.#guessRegistryTarball();
1250
+ return;
1251
+ }
1252
+ for (const [host, url] of regs) {
1253
+ const h = `${host}:`;
1254
+ if (this.bareSpec.startsWith(h)) {
1255
+ this.type = "registry";
1256
+ this.namedRegistry = host;
1257
+ this.#parseRegistrySpec(
1258
+ this.bareSpec.substring(h.length),
1259
+ url
1260
+ ).namedRegistry ??= host;
1261
+ if (this.subspec && this.name === this.bareSpec) {
1262
+ this.name = this.subspec.name;
1263
+ this.spec = `${this.name}@${this.bareSpec}`;
1264
+ assertPathSafeName(this.name, this.spec);
1265
+ }
1266
+ this.#guessRegistryTarball();
1267
+ return;
1268
+ }
1269
+ }
1270
+ const ghosts = Object.entries(this.options["git-hosts"]);
1271
+ for (const [name, template] of ghosts) {
1272
+ if (this.#parseHostedGit(name, template)) {
1273
+ this.type = "git";
1274
+ return;
1275
+ }
1276
+ }
1277
+ const jsrs = Object.entries(this.options["jsr-registries"]);
1278
+ for (const [host, url] of jsrs) {
1279
+ const h = `${host}:`;
1280
+ if (this.bareSpec.startsWith(h)) {
1281
+ this.type = "registry";
1282
+ this.namedJsrRegistry = host;
1283
+ this.#parseJsrRegistrySpec(
1284
+ this.bareSpec.substring(h.length),
1285
+ url
1286
+ ).namedJsrRegistry ??= host;
1287
+ return;
1288
+ }
1289
+ }
1290
+ if (this.bareSpec.startsWith("https://") || this.bareSpec.startsWith("http://")) {
1291
+ this.remoteURL = this.bareSpec;
1292
+ this.type = "remote";
1293
+ return;
1294
+ }
1295
+ if (this.bareSpec.startsWith("file:")) {
1296
+ this.type = "file";
1297
+ const [path, uri] = getNormalizeFile(
1298
+ this.constructor.nodejsDependencies
1299
+ )(this.bareSpec, this);
1300
+ this.file = path;
1301
+ this.bareSpec = uri.replace(/\/+$/, "");
1302
+ this.spec = `${this.name}@${this.bareSpec}`;
1303
+ return;
1304
+ }
1305
+ if (!this.bareSpec.startsWith("./") && !this.bareSpec.startsWith("../") && this.options["git-hosts"].github) {
1306
+ const hash = this.bareSpec.indexOf("#");
1307
+ const up = hash === -1 ? this.bareSpec : this.bareSpec.substring(0, hash);
1308
+ if (up.split("/").length === 2) {
1309
+ this.bareSpec = `github:${this.bareSpec}`;
1310
+ this.spec = `${this.name}@${this.bareSpec}`;
1311
+ this.#parseHostedGit(
1312
+ "github",
1313
+ this.options["git-hosts"].github
1314
+ );
1315
+ this.type = "git";
1316
+ return;
1317
+ }
1318
+ }
1319
+ if (this.bareSpec.includes("/") || this.bareSpec === "." || this.bareSpec === "..") {
1320
+ this.type = "file";
1321
+ const [file, uri] = getNormalizeFile(
1322
+ this.constructor.nodejsDependencies
1323
+ )(`file:${this.bareSpec}`, this);
1324
+ this.bareSpec = uri;
1325
+ this.spec = `${this.name}@${this.bareSpec}`;
1326
+ this.file = file;
1327
+ return;
1328
+ }
1329
+ this.type = "registry";
1330
+ const range = parseRange(this.bareSpec);
1331
+ if (range) {
1332
+ this.semver = this.bareSpec.trim();
1333
+ this.range = range;
1334
+ } else {
1335
+ this.distTag = this.bareSpec;
1336
+ }
1337
+ this.registrySpec = this.bareSpec;
1338
+ const {
1339
+ "scoped-registries": scopeRegs,
1340
+ registry,
1341
+ registries,
1342
+ "default-registry-alias": defaultAlias
1343
+ } = this.options;
1344
+ const scopeReg = this.scope && scopeRegs[this.scope];
1345
+ this.registry = scopeReg ?? registry ?? registries[defaultAlias];
1346
+ for (const r of Object.values(this.options["jsr-registries"])) {
1347
+ if (this.registry === r) return;
1348
+ }
1349
+ this.#guessRegistryTarball();
1350
+ }
1351
+ #parseScope(name) {
1352
+ if (!name.startsWith("@")) return;
1353
+ const s = name.indexOf("/");
1354
+ if (s > 1 && s < name.length - 1) {
1355
+ const scope = name.substring(0, s);
1356
+ this.registry = this.scopeRegistry = this.options["scoped-registries"][scope];
1357
+ this.scope = scope;
1358
+ }
1359
+ }
1360
+ #parseHostedGit(name, template) {
1361
+ if (this.bareSpec.startsWith(`${name}:`)) {
1362
+ const h = this.bareSpec.indexOf("#");
1363
+ const bare = h === -1 ? this.bareSpec : this.bareSpec.substring(0, h);
1364
+ const hash = h === -1 ? "" : this.bareSpec.substring(h);
1365
+ const hostPath = bare.substring(name.length + 1);
1366
+ if (!hostPath) {
1367
+ throw this.#error("invalid named git host specifier");
1368
+ }
1369
+ const split = hostPath.split("/");
1370
+ let t = template;
1371
+ for (let i = 0; i < split.length; i++) {
1372
+ t = t.split(`$${i + 1}`).join(split[i]);
1373
+ }
1374
+ t += hash;
1375
+ this.namedGitHost = name;
1376
+ this.namedGitHostPath = hostPath;
1377
+ this.#parseGitSelector(t);
1378
+ if (this.gitCommittish && !this.gitSelectorParsed?.path) {
1379
+ const archiveHost = this.options["git-host-archives"][name];
1380
+ if (name === "github" && this.gitCommittish.startsWith("pull/") && this.gitCommittish.match(/\//g)?.length === 1) {
1381
+ this.gitCommittish += "/head";
1382
+ }
1383
+ if (archiveHost) {
1384
+ this.type = "remote";
1385
+ let t2 = archiveHost;
1386
+ t2 = t2.split("$committish").join(this.gitCommittish);
1387
+ for (let i = 0; i < split.length; i++) {
1388
+ t2 = t2.split(`$${i + 1}`).join(split[i]);
1389
+ }
1390
+ this.remoteURL = t2;
1391
+ }
1392
+ }
1393
+ return true;
1394
+ }
1395
+ return false;
1396
+ }
1397
+ /* c8 ignore start */
1398
+ [kCustomInspect]() {
1399
+ return `@vltpkg/spec.Spec ${String(this)}`;
1400
+ }
1401
+ /* c8 ignore stop */
1402
+ #guessRegistryTarball() {
1403
+ const { name, registry, range } = this.final;
1404
+ if (!registry || !range?.isSingle) return;
1405
+ const stripScope = /^@[^/]+\//;
1406
+ const base = registry.endsWith("/") ? registry : registry + "/";
1407
+ this.conventionalRegistryTarball = String(
1408
+ new URL(
1409
+ `${name}/-/${name.replace(stripScope, "")}-${range}.tgz`,
1410
+ base
1411
+ )
1412
+ );
1413
+ }
1414
+ #parseRegistrySpec(s, url) {
1415
+ this.registry = url;
1416
+ this.subspec = this.constructor.parse(s, {
1417
+ ...this.options,
1418
+ registry: url
1419
+ });
1420
+ return this.subspec;
1421
+ }
1422
+ #parseJsrRegistrySpec(s, url) {
1423
+ this.registry = url;
1424
+ if (!s.startsWith("@")) s = `${this.name}@${s}`;
1425
+ const name = s.startsWith("@jsr/") ? s : `@jsr/${s.replace(/^@/, "").replace(/\//, "__")}`;
1426
+ this.subspec = this.constructor.parse(name, {
1427
+ ...this.options,
1428
+ "scoped-registries": {
1429
+ ...this.options["scoped-registries"],
1430
+ "@jsr": url
1431
+ }
1432
+ });
1433
+ if (this.name === "(unknown)") {
1434
+ const nextAt = s.indexOf("@", 1);
1435
+ if (nextAt === -1) {
1436
+ this.name = s;
1437
+ } else {
1438
+ this.name = s.substring(0, s.indexOf("@", 1));
1439
+ }
1440
+ assertPathSafeName(this.name, s);
1441
+ }
1442
+ const reg = `${this.namedJsrRegistry}:`;
1443
+ const n = `${reg}${this.name}`;
1444
+ if (this.bareSpec.startsWith(n + "@")) {
1445
+ this.bareSpec = reg + this.bareSpec.substring(n.length + 1);
1446
+ } else if (this.bareSpec === n) {
1447
+ this.bareSpec = reg;
1448
+ }
1449
+ this.spec = this.name + "@" + this.bareSpec;
1450
+ return this.subspec;
1451
+ }
1452
+ #error(message, extra = {}) {
1453
+ return error(message, { spec: this.spec, ...extra }, this.#error);
1454
+ }
1455
+ #parseGitSelector(s) {
1456
+ const h = s.indexOf("#");
1457
+ if (h === -1) {
1458
+ this.gitRemote = s;
1459
+ return;
1460
+ }
1461
+ this.gitRemote = s.substring(0, h);
1462
+ this.gitSelector = s.substring(h + 1);
1463
+ const [selectorParsed, committish, range] = this.constructor.parseGitSelector(this.gitSelector, this);
1464
+ this.range = range;
1465
+ this.gitCommittish = committish;
1466
+ this.gitSelectorParsed = selectorParsed;
1467
+ }
1468
+ /**
1469
+ * Should only ever be called with the bit that comes AFTER the #
1470
+ * in the git remote url.
1471
+ */
1472
+ static parseGitSelector(selector, spec) {
1473
+ if (!selector) return [{}];
1474
+ const split = selector.split("::");
1475
+ const first = split[0];
1476
+ let committish = void 0;
1477
+ let range = void 0;
1478
+ const parsed = {};
1479
+ if (typeof first !== "string") {
1480
+ throw typeError("impossible", {
1481
+ found: first,
1482
+ wanted: String
1483
+ });
1484
+ }
1485
+ if (!first.includes(":")) {
1486
+ committish = first;
1487
+ split.shift();
1488
+ }
1489
+ for (const kv of split) {
1490
+ const c = kv.indexOf(":");
1491
+ if (c === -1) continue;
1492
+ const k = kv.substring(0, c);
1493
+ const v = kv.substring(c + 1);
1494
+ if (k === "semver") {
1495
+ if (committish) {
1496
+ throw error(
1497
+ "Cannot specify a semver range and committish value",
1498
+ { spec }
1499
+ );
1500
+ }
1501
+ range = parseRange(v);
1502
+ if (!range) {
1503
+ throw error(`Invalid git tag semver range: ${v}`, { spec });
1504
+ }
1505
+ }
1506
+ if (k === "semver" || k === "path") {
1507
+ if (k === "path") {
1508
+ if (
1509
+ /* c8 ignore next */
1510
+ this.nodejsDependencies?.isAbsolute(
1511
+ v
1512
+ ) || /(^|\/|\\)\.\.($|\\|\/)/.test(v)
1513
+ ) {
1514
+ throw error("Invalid path in git selector", { spec });
1515
+ }
1516
+ parsed.path = (this.nodejsDependencies ? this.nodejsDependencies.join("/", v).substring(1) : v).replace(/\\/g, "/");
1517
+ } else {
1518
+ parsed[k] = v;
1519
+ }
1520
+ }
1521
+ }
1522
+ return [parsed, committish, range];
1523
+ }
1524
+ };
1525
+ var getNormalizeFile = (opts) => (bareSpec, spec) => {
1526
+ const slashes = bareSpec.substring(
1527
+ "file:".length,
1528
+ "file://".length
1529
+ );
1530
+ const pref = `file:${slashes === "//" ? slashes : ""}`;
1531
+ const rest = bareSpec.substring(pref.length);
1532
+ const [a = "", b = "/", c = "/", d = "/"] = rest.split("", 4);
1533
+ if (!a) {
1534
+ return [".", "file:."];
1535
+ }
1536
+ if (a === "/" && b === "~" && c !== "/" || a === "~" && b !== "/") {
1537
+ throw error(
1538
+ `invalid file: specifier. '~username' not supported`,
1539
+ { spec }
1540
+ );
1541
+ }
1542
+ if (a === "~") {
1543
+ return (
1544
+ /* c8 ignore start */
1545
+ opts ? [
1546
+ opts.resolve(opts.homedir(), rest.substring(2)),
1547
+ `file:${rest}`
1548
+ ] : [rest, `file:${rest}`]
1549
+ );
1550
+ }
1551
+ if (a === "/" && b === "~") {
1552
+ return opts ? [
1553
+ opts.resolve(opts.homedir(), rest.substring(3)),
1554
+ `file:${rest.substring(1)}`
1555
+ ] : (
1556
+ /* c8 ignore stop */
1557
+ [rest.substring(1), `file:${rest.substring(1)}`]
1558
+ );
1559
+ }
1560
+ if (a === "/" && b === "." && (c === "/" || c === "." && d === "/")) {
1561
+ return [rest.substring(1), `file:${rest.substring(1)}`];
1562
+ }
1563
+ if (a === "." && (b === "/" || b === "." && c === "/")) {
1564
+ return [rest, `file:${rest}`];
1565
+ }
1566
+ if (slashes === "//") {
1567
+ try {
1568
+ const parsed = new URL(bareSpec);
1569
+ if (parsed.host) {
1570
+ if (parsed.host !== "localhost") {
1571
+ throw error(
1572
+ `invalid file:// specifier. host must be empty or 'localhost'`,
1573
+ {
1574
+ spec,
1575
+ found: parsed.host,
1576
+ validOptions: ["", "localhost"]
1577
+ }
1578
+ );
1579
+ }
1580
+ }
1581
+ return [
1582
+ parsed.pathname.replace(/^\/([a-zA-Z]:\/)/, "$1"),
1583
+ `file://${parsed.pathname}`
1584
+ ];
1585
+ } catch (er) {
1586
+ throw error("invalid file:// specifier", {
1587
+ spec,
1588
+ cause: er
1589
+ });
1590
+ }
1591
+ }
1592
+ if (opts?.winPath.isAbsolute(rest)) {
1593
+ return [rest, `file://${rest}`];
1594
+ }
1595
+ return [`./${rest}`, `file:./${rest}`];
1596
+ };
1597
+
923
1598
  // ../../src/types/src/index.ts
1599
+ import { posix } from "node:path";
1600
+ import { debuglog } from "node:util";
1601
+ var debug = debuglog("vlt");
924
1602
  var normalizeFundingEntry = (item) => {
925
1603
  const getTypeFromUrl = (url) => {
926
1604
  try {
@@ -1199,14 +1877,35 @@ var isNormalizedLibc = (o) => {
1199
1877
  (item) => typeof item === "string" && !!item && !item.startsWith(" ") && !item.endsWith(" ")
1200
1878
  );
1201
1879
  };
1880
+ var unixify = (ref) => ref.replace(/[\\:]/g, "/");
1881
+ var secure = (ref) => {
1882
+ const s = unixify(posix.join(".", posix.join("/", unixify(ref))));
1883
+ return s === "./" ? "" : s;
1884
+ };
1885
+ var secureBinPaths = (bin) => {
1886
+ const res = {};
1887
+ for (const [key, val] of Object.entries(bin)) {
1888
+ const v = typeof val === "string" ? secure(val) : "";
1889
+ const k = posix.basename(secure(key));
1890
+ if (!k || !v) {
1891
+ debug("dropped unusable bin entry", key, val);
1892
+ continue;
1893
+ }
1894
+ if (k !== key || v !== val) {
1895
+ debug("rewrote unsafe bin entry", key, val, "->", k, v);
1896
+ }
1897
+ res[k] = v;
1898
+ }
1899
+ return res;
1900
+ };
1202
1901
  var normalizeBinPaths = (manifest) => {
1203
1902
  const { name, bin } = manifest;
1204
1903
  if (bin) {
1205
1904
  if (name && typeof bin === "string") {
1206
1905
  const [_scope, pkg] = parseScope(name);
1207
- return { [pkg]: bin };
1906
+ return secureBinPaths({ [pkg]: bin });
1208
1907
  } else if (typeof bin === "object") {
1209
- return bin;
1908
+ return secureBinPaths(bin);
1210
1909
  }
1211
1910
  }
1212
1911
  };
@@ -1250,11 +1949,14 @@ var asManifest = (m, from) => {
1250
1949
  return m;
1251
1950
  };
1252
1951
  var normalizeManifestCache = /* @__PURE__ */ new WeakMap();
1253
- var normalizeManifest = (manifest) => {
1952
+ var normalizeManifest = (manifest, from) => {
1254
1953
  const cached = normalizeManifestCache.get(manifest);
1255
1954
  if (cached) {
1256
1955
  return cached;
1257
1956
  }
1957
+ if (manifest.name !== void 0) {
1958
+ assertPathSafeName(manifest.name, from);
1959
+ }
1258
1960
  manifest = fixManifestVersion(manifest);
1259
1961
  const normalizedAuthor = parsePerson(manifest.author);
1260
1962
  const normalizedFunding = normalizeFunding(manifest.funding);
@@ -1738,6 +2440,19 @@ export {
1738
2440
  patch,
1739
2441
  intersects,
1740
2442
  subset,
2443
+ assertPathSafeName,
2444
+ kCustomInspect,
2445
+ defaultRegistryName,
2446
+ defaultRegistries,
2447
+ defaultJsrRegistries,
2448
+ defaultGitHosts,
2449
+ defaultGitHostArchives,
2450
+ gitHostWebsites,
2451
+ defaultScopeRegistries,
2452
+ getOptions,
2453
+ isSpec,
2454
+ currentDefaultRegistryName,
2455
+ Spec,
1741
2456
  asError,
1742
2457
  isError,
1743
2458
  isErrorWithCause,