@verdaccio/core 9.0.0-next-9.20 → 9.0.0-next-9.22

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 (70) hide show
  1. package/build/auth-utils.d.ts +1 -1
  2. package/build/auth-utils.js +5 -0
  3. package/build/auth-utils.js.map +1 -1
  4. package/build/auth-utils.mjs +1 -1
  5. package/build/auth-utils.mjs.map +1 -1
  6. package/build/constants.d.ts +6 -2
  7. package/build/constants.js +16 -2
  8. package/build/constants.js.map +1 -1
  9. package/build/constants.mjs +9 -3
  10. package/build/constants.mjs.map +1 -1
  11. package/build/crypto-utils.d.ts +1 -1
  12. package/build/crypto-utils.js +5 -0
  13. package/build/crypto-utils.js.map +1 -1
  14. package/build/crypto-utils.mjs +1 -1
  15. package/build/crypto-utils.mjs.map +1 -1
  16. package/build/error-utils.d.ts +1 -1
  17. package/build/error-utils.js +9 -0
  18. package/build/error-utils.js.map +1 -1
  19. package/build/error-utils.mjs +1 -1
  20. package/build/file-utils.js +5 -0
  21. package/build/file-utils.js.map +1 -1
  22. package/build/file-utils.mjs +1 -1
  23. package/build/file-utils.mjs.map +1 -1
  24. package/build/index.d.ts +2 -1
  25. package/build/index.js +7 -0
  26. package/build/index.mjs +2 -1
  27. package/build/ip-utils.js +4 -0
  28. package/build/ip-utils.js.map +1 -1
  29. package/build/ip-utils.mjs +1 -1
  30. package/build/ip-utils.mjs.map +1 -1
  31. package/build/pkg-utils.d.ts +1 -1
  32. package/build/pkg-utils.js +4 -0
  33. package/build/pkg-utils.js.map +1 -1
  34. package/build/pkg-utils.mjs +1 -1
  35. package/build/pkg-utils.mjs.map +1 -1
  36. package/build/plugin-utils.d.ts +4 -4
  37. package/build/plugin-utils.js +5 -0
  38. package/build/plugin-utils.mjs +1 -1
  39. package/build/req-utils.d.ts +8 -0
  40. package/build/req-utils.js +22 -0
  41. package/build/req-utils.js.map +1 -0
  42. package/build/req-utils.mjs +17 -0
  43. package/build/req-utils.mjs.map +1 -0
  44. package/build/schemes/publish-manifest.js.map +1 -1
  45. package/build/schemes/publish-manifest.mjs.map +1 -1
  46. package/build/schemes/unpublish-manifest.js.map +1 -1
  47. package/build/schemes/unpublish-manifest.mjs.map +1 -1
  48. package/build/search-utils.js +1 -0
  49. package/build/search-utils.mjs +1 -1
  50. package/build/stream-utils.d.ts +2 -1
  51. package/build/stream-utils.js +2 -0
  52. package/build/stream-utils.js.map +1 -1
  53. package/build/stream-utils.mjs +1 -1
  54. package/build/stream-utils.mjs.map +1 -1
  55. package/build/string-utils.js +1 -0
  56. package/build/string-utils.js.map +1 -1
  57. package/build/string-utils.mjs +1 -1
  58. package/build/string-utils.mjs.map +1 -1
  59. package/build/tarball-utils.js +3 -0
  60. package/build/tarball-utils.js.map +1 -1
  61. package/build/tarball-utils.mjs +1 -1
  62. package/build/tarball-utils.mjs.map +1 -1
  63. package/build/validation-utils.d.ts +1 -1
  64. package/build/validation-utils.js +9 -0
  65. package/build/validation-utils.js.map +1 -1
  66. package/build/validation-utils.mjs +1 -1
  67. package/build/validation-utils.mjs.map +1 -1
  68. package/build/warning-utils.js +2 -0
  69. package/build/warning-utils.mjs +1 -1
  70. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- import { PackageAccess, PackageList } from '@verdaccio/types';
1
+ import type { PackageAccess, PackageList } from '@verdaccio/types';
2
2
  export interface CookieSessionToken {
3
3
  expires: Date;
4
4
  }
@@ -33,5 +33,10 @@ Object.defineProperty(exports, "auth_utils_exports", {
33
33
  return auth_utils_exports;
34
34
  }
35
35
  });
36
+ exports.buildToken = buildToken;
37
+ exports.buildUserBuffer = buildUserBuffer;
38
+ exports.createSessionToken = createSessionToken;
39
+ exports.getAuthenticatedMessage = getAuthenticatedMessage;
40
+ exports.getMatchedPackagesSpec = getMatchedPackagesSpec;
36
41
 
37
42
  //# sourceMappingURL=auth-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-utils.js","names":[],"sources":["../src/auth-utils.ts"],"sourcesContent":["import type { MMRegExp } from 'minimatch';\nimport { minimatch } from 'minimatch';\n\nimport type { PackageAccess, PackageList } from '@verdaccio/types';\n\nexport interface CookieSessionToken {\n expires: Date;\n}\n\nexport function createSessionToken(): CookieSessionToken {\n const tenHoursTime = 10 * 60 * 60 * 1000;\n\n return {\n // npmjs.org sets 10h expire\n expires: new Date(Date.now() + tenHoursTime),\n };\n}\n\nexport function getAuthenticatedMessage(user: string): string {\n return `you are authenticated as '${user}'`;\n}\n\nexport function buildUserBuffer(name: string, password: string): Buffer {\n return Buffer.from(`${name}:${password}`, 'utf8');\n}\n\nexport function buildToken(type: string, token: string): string {\n return `${capitalize(type)} ${token}`;\n}\n\nexport function getMatchedPackagesSpec(\n pkgName: string,\n packages: PackageList\n): PackageAccess | void {\n for (const i in packages) {\n if ((minimatch.makeRe(i) as MMRegExp).exec(pkgName)) {\n return packages[i];\n }\n }\n return;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,qBAAyC;CAGvD,OAAO,EAEL,SAAS,IAAI,KAAK,KAAK,IAAI,IAJR,MAAU,KAAK,GAIS,EAC7C;AACF;AAEA,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,6BAA6B,KAAK;AAC3C;AAEA,SAAgB,gBAAgB,MAAc,UAA0B;CACtE,OAAO,OAAO,KAAK,GAAG,KAAK,GAAG,YAAY,MAAM;AAClD;AAEA,SAAgB,WAAW,MAAc,OAAuB;CAC9D,OAAO,GAAG,WAAW,IAAI,EAAE,GAAG;AAChC;AAEA,SAAgB,uBACd,SACA,UACsB;CACtB,KAAK,MAAM,KAAK,UACd,IAAK,UAAA,UAAU,OAAO,CAAC,EAAe,KAAK,OAAO,GAChD,OAAO,SAAS;AAItB;AAEA,SAAS,WAAW,KAAqB;CACvC,OAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AAChE"}
1
+ {"version":3,"file":"auth-utils.js","names":[],"sources":["../src/auth-utils.ts"],"sourcesContent":["import type { MMRegExp } from 'minimatch';\nimport { minimatch } from 'minimatch';\n\nimport type { PackageAccess, PackageList } from '@verdaccio/types';\n\nexport interface CookieSessionToken {\n expires: Date;\n}\n\nexport function createSessionToken(): CookieSessionToken {\n const tenHoursTime = 10 * 60 * 60 * 1000;\n\n return {\n // npmjs.org sets 10h expire\n expires: new Date(Date.now() + tenHoursTime),\n };\n}\n\nexport function getAuthenticatedMessage(user: string): string {\n return `you are authenticated as '${user}'`;\n}\n\nexport function buildUserBuffer(name: string, password: string): Buffer {\n return Buffer.from(`${name}:${password}`, 'utf8');\n}\n\nexport function buildToken(type: string, token: string): string {\n return `${capitalize(type)} ${token}`;\n}\n\nexport function getMatchedPackagesSpec(\n pkgName: string,\n packages: PackageList\n): PackageAccess | void {\n for (const i in packages) {\n if ((minimatch.makeRe(i) as MMRegExp).exec(pkgName)) {\n return packages[i];\n }\n }\n return;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,qBAAyC;CAGvD,OAAO,EAEL,SAAS,IAAI,KAAK,KAAK,IAAI,IAJR,MAAU,KAAK,GAIS,EAC7C;AACF;AAEA,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,6BAA6B,KAAK;AAC3C;AAEA,SAAgB,gBAAgB,MAAc,UAA0B;CACtE,OAAO,OAAO,KAAK,GAAG,KAAK,GAAG,YAAY,MAAM;AAClD;AAEA,SAAgB,WAAW,MAAc,OAAuB;CAC9D,OAAO,GAAG,WAAW,IAAI,EAAE,GAAG;AAChC;AAEA,SAAgB,uBACd,SACA,UACsB;CACtB,KAAK,MAAM,KAAK,UACd,IAAK,UAAA,UAAU,OAAO,CAAC,CAAC,CAAc,KAAK,OAAO,GAChD,OAAO,SAAS;AAItB;AAEA,SAAS,WAAW,KAAqB;CACvC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY;AAChE"}
@@ -27,6 +27,6 @@ function capitalize(str) {
27
27
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
28
28
  }
29
29
  //#endregion
30
- export { auth_utils_exports };
30
+ export { auth_utils_exports, buildToken, buildUserBuffer, createSessionToken, getAuthenticatedMessage, getMatchedPackagesSpec };
31
31
 
32
32
  //# sourceMappingURL=auth-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-utils.mjs","names":[],"sources":["../src/auth-utils.ts"],"sourcesContent":["import type { MMRegExp } from 'minimatch';\nimport { minimatch } from 'minimatch';\n\nimport type { PackageAccess, PackageList } from '@verdaccio/types';\n\nexport interface CookieSessionToken {\n expires: Date;\n}\n\nexport function createSessionToken(): CookieSessionToken {\n const tenHoursTime = 10 * 60 * 60 * 1000;\n\n return {\n // npmjs.org sets 10h expire\n expires: new Date(Date.now() + tenHoursTime),\n };\n}\n\nexport function getAuthenticatedMessage(user: string): string {\n return `you are authenticated as '${user}'`;\n}\n\nexport function buildUserBuffer(name: string, password: string): Buffer {\n return Buffer.from(`${name}:${password}`, 'utf8');\n}\n\nexport function buildToken(type: string, token: string): string {\n return `${capitalize(type)} ${token}`;\n}\n\nexport function getMatchedPackagesSpec(\n pkgName: string,\n packages: PackageList\n): PackageAccess | void {\n for (const i in packages) {\n if ((minimatch.makeRe(i) as MMRegExp).exec(pkgName)) {\n return packages[i];\n }\n }\n return;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,qBAAyC;CAGvD,OAAO,EAEL,SAAS,IAAI,KAAK,KAAK,IAAI,IAJR,MAAU,KAAK,GAIS,EAC7C;AACF;AAEA,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,6BAA6B,KAAK;AAC3C;AAEA,SAAgB,gBAAgB,MAAc,UAA0B;CACtE,OAAO,OAAO,KAAK,GAAG,KAAK,GAAG,YAAY,MAAM;AAClD;AAEA,SAAgB,WAAW,MAAc,OAAuB;CAC9D,OAAO,GAAG,WAAW,IAAI,EAAE,GAAG;AAChC;AAEA,SAAgB,uBACd,SACA,UACsB;CACtB,KAAK,MAAM,KAAK,UACd,IAAK,UAAU,OAAO,CAAC,EAAe,KAAK,OAAO,GAChD,OAAO,SAAS;AAItB;AAEA,SAAS,WAAW,KAAqB;CACvC,OAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AAChE"}
1
+ {"version":3,"file":"auth-utils.mjs","names":[],"sources":["../src/auth-utils.ts"],"sourcesContent":["import type { MMRegExp } from 'minimatch';\nimport { minimatch } from 'minimatch';\n\nimport type { PackageAccess, PackageList } from '@verdaccio/types';\n\nexport interface CookieSessionToken {\n expires: Date;\n}\n\nexport function createSessionToken(): CookieSessionToken {\n const tenHoursTime = 10 * 60 * 60 * 1000;\n\n return {\n // npmjs.org sets 10h expire\n expires: new Date(Date.now() + tenHoursTime),\n };\n}\n\nexport function getAuthenticatedMessage(user: string): string {\n return `you are authenticated as '${user}'`;\n}\n\nexport function buildUserBuffer(name: string, password: string): Buffer {\n return Buffer.from(`${name}:${password}`, 'utf8');\n}\n\nexport function buildToken(type: string, token: string): string {\n return `${capitalize(type)} ${token}`;\n}\n\nexport function getMatchedPackagesSpec(\n pkgName: string,\n packages: PackageList\n): PackageAccess | void {\n for (const i in packages) {\n if ((minimatch.makeRe(i) as MMRegExp).exec(pkgName)) {\n return packages[i];\n }\n }\n return;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,qBAAyC;CAGvD,OAAO,EAEL,SAAS,IAAI,KAAK,KAAK,IAAI,IAJR,MAAU,KAAK,GAIS,EAC7C;AACF;AAEA,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,6BAA6B,KAAK;AAC3C;AAEA,SAAgB,gBAAgB,MAAc,UAA0B;CACtE,OAAO,OAAO,KAAK,GAAG,KAAK,GAAG,YAAY,MAAM;AAClD;AAEA,SAAgB,WAAW,MAAc,OAAuB;CAC9D,OAAO,GAAG,WAAW,IAAI,EAAE,GAAG;AAChC;AAEA,SAAgB,uBACd,SACA,UACsB;CACtB,KAAK,MAAM,KAAK,UACd,IAAK,UAAU,OAAO,CAAC,CAAC,CAAc,KAAK,OAAO,GAChD,OAAO,SAAS;AAItB;AAEA,SAAS,WAAW,KAAqB;CACvC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY;AAChE"}
@@ -59,12 +59,12 @@ export declare const HEADERS: {
59
59
  * HTTP status codes used throughout Verdaccio.
60
60
  */
61
61
  export declare const HTTP_STATUS: {
62
- /** 202: The request has been accepted for processing, but the processing is not yet complete. */
63
- ACCEPTED: number;
64
62
  /** 200: Standard response for successful HTTP requests. */
65
63
  OK: number;
66
64
  /** 201: The request has been fulfilled and resulted in a new resource being created. */
67
65
  CREATED: number;
66
+ /** 202: The request has been accepted for processing, but the processing is not yet complete. */
67
+ ACCEPTED: number;
68
68
  /** 300: Indicates multiple options for the resource from which the client may choose. */
69
69
  MULTIPLE_CHOICES: number;
70
70
  /** 304: Indicates that the resource has not been modified since the last request. */
@@ -85,6 +85,8 @@ export declare const HTTP_STATUS: {
85
85
  UNSUPPORTED_MEDIA: number;
86
86
  /** 422: The request was well-formed but was unable to be followed due to semantic errors. */
87
87
  BAD_DATA: number;
88
+ /** 499: The request was aborted by the client. */
89
+ CLIENT_CLOSED_REQUEST: number;
88
90
  /** 500: The server has encountered a situation it doesn't know how to handle. */
89
91
  INTERNAL_ERROR: number;
90
92
  /** 501: The request method is not supported by the server and cannot be handled. */
@@ -119,6 +121,8 @@ export declare const API_MESSAGE: {
119
121
  export declare const LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'";
120
122
  export declare const LOG_VERDACCIO_ERROR = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', error: @{!error}";
121
123
  export declare const LOG_VERDACCIO_BYTES = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}";
124
+ export declare const LOG_VERDACCIO_ABORT = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', request aborted by client";
125
+ export declare const LOG_REQUEST_MESSAGE = "@{ip} requested '@{req.method} @{req.url}'";
122
126
  export declare const ROLES: {
123
127
  $ALL: string;
124
128
  ALL: string;
@@ -18,7 +18,9 @@ var constants_exports = /* @__PURE__ */ require_runtime.__exportAll({
18
18
  HTTP_STATUS: () => HTTP_STATUS,
19
19
  HtpasswdHashAlgorithm: () => HtpasswdHashAlgorithm,
20
20
  LATEST: () => LATEST,
21
+ LOG_REQUEST_MESSAGE: () => LOG_REQUEST_MESSAGE,
21
22
  LOG_STATUS_MESSAGE: () => LOG_STATUS_MESSAGE,
23
+ LOG_VERDACCIO_ABORT: () => LOG_VERDACCIO_ABORT,
22
24
  LOG_VERDACCIO_BYTES: () => LOG_VERDACCIO_BYTES,
23
25
  LOG_VERDACCIO_ERROR: () => LOG_VERDACCIO_ERROR,
24
26
  MAINTAINERS: () => MAINTAINERS,
@@ -90,12 +92,12 @@ var HEADERS = {
90
92
  * HTTP status codes used throughout Verdaccio.
91
93
  */
92
94
  var HTTP_STATUS = {
93
- /** 202: The request has been accepted for processing, but the processing is not yet complete. */
94
- ACCEPTED: http_status_codes.default.ACCEPTED,
95
95
  /** 200: Standard response for successful HTTP requests. */
96
96
  OK: http_status_codes.default.OK,
97
97
  /** 201: The request has been fulfilled and resulted in a new resource being created. */
98
98
  CREATED: http_status_codes.default.CREATED,
99
+ /** 202: The request has been accepted for processing, but the processing is not yet complete. */
100
+ ACCEPTED: http_status_codes.default.ACCEPTED,
99
101
  /** 300: Indicates multiple options for the resource from which the client may choose. */
100
102
  MULTIPLE_CHOICES: http_status_codes.default.MULTIPLE_CHOICES,
101
103
  /** 304: Indicates that the resource has not been modified since the last request. */
@@ -116,6 +118,8 @@ var HTTP_STATUS = {
116
118
  UNSUPPORTED_MEDIA: http_status_codes.default.UNSUPPORTED_MEDIA_TYPE,
117
119
  /** 422: The request was well-formed but was unable to be followed due to semantic errors. */
118
120
  BAD_DATA: http_status_codes.default.UNPROCESSABLE_ENTITY,
121
+ /** 499: The request was aborted by the client. */
122
+ CLIENT_CLOSED_REQUEST: 499,
119
123
  /** 500: The server has encountered a situation it doesn't know how to handle. */
120
124
  INTERNAL_ERROR: http_status_codes.default.INTERNAL_SERVER_ERROR,
121
125
  /** 501: The request method is not supported by the server and cannot be handled. */
@@ -148,6 +152,8 @@ var API_MESSAGE = {
148
152
  var LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'";
149
153
  var LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;
150
154
  var LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;
155
+ var LOG_VERDACCIO_ABORT = `${LOG_STATUS_MESSAGE}, request aborted by client`;
156
+ var LOG_REQUEST_MESSAGE = "@{ip} requested '@{req.method} @{req.url}'";
151
157
  var ROLES = {
152
158
  $ALL: "$all",
153
159
  ALL: "all",
@@ -190,15 +196,23 @@ exports.DEFAULT_PORT = DEFAULT_PORT;
190
196
  exports.DEFAULT_PROTOCOL = DEFAULT_PROTOCOL;
191
197
  exports.DEFAULT_USER = DEFAULT_USER;
192
198
  exports.DIST_TAGS = DIST_TAGS;
199
+ exports.ERROR_CODE = ERROR_CODE;
193
200
  exports.HEADERS = HEADERS;
194
201
  exports.HEADER_TYPE = HEADER_TYPE;
195
202
  exports.HTTP_STATUS = HTTP_STATUS;
196
203
  exports.HtpasswdHashAlgorithm = HtpasswdHashAlgorithm;
197
204
  exports.LATEST = LATEST;
205
+ exports.LOG_REQUEST_MESSAGE = LOG_REQUEST_MESSAGE;
206
+ exports.LOG_STATUS_MESSAGE = LOG_STATUS_MESSAGE;
207
+ exports.LOG_VERDACCIO_ABORT = LOG_VERDACCIO_ABORT;
208
+ exports.LOG_VERDACCIO_BYTES = LOG_VERDACCIO_BYTES;
209
+ exports.LOG_VERDACCIO_ERROR = LOG_VERDACCIO_ERROR;
198
210
  exports.MAINTAINERS = MAINTAINERS;
211
+ exports.PACKAGE_ACCESS = PACKAGE_ACCESS;
199
212
  exports.PLUGIN_CATEGORY = PLUGIN_CATEGORY;
200
213
  exports.PLUGIN_PREFIX = PLUGIN_PREFIX;
201
214
  exports.PLUGIN_UI_PREFIX = PLUGIN_UI_PREFIX;
215
+ exports.ROLES = ROLES;
202
216
  exports.TOKEN_BASIC = TOKEN_BASIC;
203
217
  exports.TOKEN_BEARER = TOKEN_BEARER;
204
218
  exports.USERS = USERS;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import httpCodes from 'http-status-codes';\n\nexport const DEFAULT_PASSWORD_VALIDATION = /.{3}$/;\nexport const TIME_EXPIRATION_24H = '24h';\nexport const TIME_EXPIRATION_1H = '1h';\nexport const DIST_TAGS = 'dist-tags';\nexport const LATEST = 'latest';\nexport const USERS = 'users';\nexport const MAINTAINERS = 'maintainers';\nexport const DEFAULT_USER = 'Anonymous'; // for display purposes\nexport const ANONYMOUS_USER = 'anonymous'; // for username purposes\n\nexport const HEADER_TYPE = {\n CONTENT_ENCODING: 'content-encoding',\n CONTENT_TYPE: 'content-type',\n CONTENT_LENGTH: 'content-length',\n ACCEPT_ENCODING: 'accept-encoding',\n AUTHORIZATION: 'authorization',\n};\n\nexport const CHARACTER_ENCODING = {\n UTF8: 'utf8',\n};\n\n// @deprecated use Bearer instead\nexport const TOKEN_BASIC = 'Basic';\nexport const TOKEN_BEARER = 'Bearer';\n\nexport const HEADERS = {\n ACCEPT: 'Accept',\n ACCEPT_ENCODING: 'Accept-Encoding',\n USER_AGENT: 'User-Agent',\n JSON: 'application/json',\n CONTENT_TYPE: 'Content-type',\n CONTENT_LENGTH: 'content-length',\n TEXT_PLAIN: 'text/plain',\n TEXT_PLAIN_UTF8: 'text/plain; charset=utf-8',\n TEXT_HTML_UTF8: 'text/html; charset=utf-8',\n TEXT_HTML: 'text/html',\n AUTHORIZATION: 'authorization',\n CACHE_CONTROL: 'Cache-Control',\n NO_CACHE: 'no-cache, no-store',\n RETRY_AFTER: 'Retry-After',\n // only set with proxy that setup HTTPS\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n FORWARDED_PROTO: 'X-Forwarded-Proto',\n FORWARDED_FOR: 'X-Forwarded-For',\n FRAMES_OPTIONS: 'X-Frame-Options',\n CSP: 'Content-Security-Policy',\n CTO: 'X-Content-Type-Options',\n XSS: 'X-XSS-Protection',\n CLIENT: 'X-Client',\n POWERED_BY: 'X-Powered-By',\n RATELIMIT_LIMIT: 'X-RateLimit-Limit',\n RATELIMIT_REMAINING: 'X-RateLimit-Remaining',\n NONE_MATCH: 'If-None-Match',\n ETAG: 'ETag',\n JSON_CHARSET: 'application/json; charset=utf-8',\n JSON_INSTALL_CHARSET: 'application/vnd.npm.install-v1+json; charset=utf-8',\n OCTET_STREAM: 'application/octet-stream; charset=utf-8',\n TEXT_CHARSET: 'text/plain; charset=utf-8',\n JAVASCRIPT_CHARSET: 'application/javascript; charset=utf-8',\n WWW_AUTH: 'WWW-Authenticate',\n GZIP: 'gzip',\n HOST: 'host',\n};\n\n/**\n * HTTP status codes used throughout Verdaccio.\n */\nexport const HTTP_STATUS = {\n /** 202: The request has been accepted for processing, but the processing is not yet complete. */\n ACCEPTED: httpCodes.ACCEPTED,\n /** 200: Standard response for successful HTTP requests. */\n OK: httpCodes.OK,\n /** 201: The request has been fulfilled and resulted in a new resource being created. */\n CREATED: httpCodes.CREATED,\n /** 300: Indicates multiple options for the resource from which the client may choose. */\n MULTIPLE_CHOICES: httpCodes.MULTIPLE_CHOICES,\n /** 304: Indicates that the resource has not been modified since the last request. */\n NOT_MODIFIED: httpCodes.NOT_MODIFIED,\n /** 400: The server could not understand the request due to invalid syntax. */\n BAD_REQUEST: httpCodes.BAD_REQUEST,\n /** 401: The client must authenticate itself to get the requested response. */\n UNAUTHORIZED: httpCodes.UNAUTHORIZED,\n /** 403: The client does not have access rights to the content. */\n FORBIDDEN: httpCodes.FORBIDDEN,\n /** 404: The server can not find the requested resource. */\n NOT_FOUND: httpCodes.NOT_FOUND,\n /** 408: The server timed out waiting for the request. */\n REQUEST_TIMEOUT: httpCodes.REQUEST_TIMEOUT,\n /** 409: The request could not be completed due to a conflict with the current state of the resource. */\n CONFLICT: httpCodes.CONFLICT,\n /** 415: The media format of the requested data is not supported by the server. */\n UNSUPPORTED_MEDIA: httpCodes.UNSUPPORTED_MEDIA_TYPE,\n /** 422: The request was well-formed but was unable to be followed due to semantic errors. */\n BAD_DATA: httpCodes.UNPROCESSABLE_ENTITY,\n /** 500: The server has encountered a situation it doesn't know how to handle. */\n INTERNAL_ERROR: httpCodes.INTERNAL_SERVER_ERROR,\n /** 501: The request method is not supported by the server and cannot be handled. */\n NOT_IMPLEMENTED: httpCodes.NOT_IMPLEMENTED,\n /** 502: The server, while acting as a gateway or proxy, received an invalid response from the upstream server. */\n BAD_GATEWAY: httpCodes.BAD_GATEWAY,\n /** 503: The server is not ready to handle the request. */\n SERVICE_UNAVAILABLE: httpCodes.SERVICE_UNAVAILABLE,\n /** 504: The server, while acting as a gateway or proxy, did not get a response in time from the upstream server. */\n GATEWAY_TIMEOUT: httpCodes.GATEWAY_TIMEOUT,\n /** 508: The server detected an infinite loop while processing the request. */\n LOOP_DETECTED: 508,\n /** 590: Custom Verdaccio code indicating the server cannot handle the request. */\n CANNOT_HANDLE: 590,\n};\n\nexport const ERROR_CODE = {\n token_required: 'token is required',\n};\n\nexport const API_MESSAGE = {\n PKG_CREATED: 'created new package',\n PKG_CHANGED: 'package changed',\n PKG_REMOVED: 'package removed',\n PKG_PUBLISHED: 'package published',\n TARBALL_UPLOADED: 'tarball uploaded successfully',\n TARBALL_REMOVED: 'tarball removed',\n TAG_UPDATED: 'tags updated',\n TAG_REMOVED: 'tag removed',\n TAG_ADDED: 'package tagged',\n OK: 'ok',\n LOGGED_OUT: 'Logged out',\n};\n\nexport const LOG_STATUS_MESSAGE =\n \"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'\";\nexport const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;\nexport const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;\n\nexport const ROLES = {\n $ALL: '$all',\n ALL: 'all',\n $AUTH: '$authenticated',\n $ANONYMOUS: '$anonymous',\n DEPRECATED_ALL: '@all',\n DEPRECATED_AUTH: '@authenticated',\n DEPRECATED_ANONYMOUS: '@anonymous',\n};\n\nexport const PACKAGE_ACCESS = {\n SCOPE: '@*/*',\n ALL: '**',\n};\n\nexport enum HtpasswdHashAlgorithm {\n md5 = 'md5',\n sha1 = 'sha1',\n crypt = 'crypt',\n bcrypt = 'bcrypt',\n}\n\nexport const PLUGIN_PREFIX = 'verdaccio';\nexport const PLUGIN_UI_PREFIX = 'verdaccio-theme';\n\nexport const PLUGIN_CATEGORY = {\n AUTHENTICATION: 'authentication',\n MIDDLEWARE: 'middleware',\n STORAGE: 'storage',\n FILTER: 'filter',\n THEME: 'theme',\n};\n\nexport const DEFAULT_PORT = '4873';\nexport const DEFAULT_PROTOCOL = 'http';\nexport const DEFAULT_DOMAIN = 'localhost';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAa,8BAA8B;AAG3C,IAAa,YAAY;AACzB,IAAa,SAAS;AACtB,IAAa,QAAQ;AACrB,IAAa,cAAc;AAC3B,IAAa,eAAe;AAC5B,IAAa,iBAAiB;AAE9B,IAAa,cAAc;CACzB,kBAAkB;CAClB,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;AACjB;AAEA,IAAa,qBAAqB,EAChC,MAAM,OACR;AAGA,IAAa,cAAc;AAC3B,IAAa,eAAe;AAE5B,IAAa,UAAU;CACrB,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,YAAY;CACZ,iBAAiB;CACjB,gBAAgB;CAChB,WAAW;CACX,eAAe;CACf,eAAe;CACf,UAAU;CACV,aAAa;CAGb,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,KAAK;CACL,KAAK;CACL,KAAK;CACL,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,UAAU;CACV,MAAM;CACN,MAAM;AACR;;;;AAKA,IAAa,cAAc;;CAEzB,UAAU,kBAAA,QAAU;;CAEpB,IAAI,kBAAA,QAAU;;CAEd,SAAS,kBAAA,QAAU;;CAEnB,kBAAkB,kBAAA,QAAU;;CAE5B,cAAc,kBAAA,QAAU;;CAExB,aAAa,kBAAA,QAAU;;CAEvB,cAAc,kBAAA,QAAU;;CAExB,WAAW,kBAAA,QAAU;;CAErB,WAAW,kBAAA,QAAU;;CAErB,iBAAiB,kBAAA,QAAU;;CAE3B,UAAU,kBAAA,QAAU;;CAEpB,mBAAmB,kBAAA,QAAU;;CAE7B,UAAU,kBAAA,QAAU;;CAEpB,gBAAgB,kBAAA,QAAU;;CAE1B,iBAAiB,kBAAA,QAAU;;CAE3B,aAAa,kBAAA,QAAU;;CAEvB,qBAAqB,kBAAA,QAAU;;CAE/B,iBAAiB,kBAAA,QAAU;;CAE3B,eAAe;;CAEf,eAAe;AACjB;AAEA,IAAa,aAAa,EACxB,gBAAgB,oBAClB;AAEA,IAAa,cAAc;CACzB,aAAa;CACb,aAAa;CACb,aAAa;CACb,eAAe;CACf,kBAAkB;CAClB,iBAAiB;CACjB,aAAa;CACb,aAAa;CACb,WAAW;CACX,IAAI;CACJ,YAAY;AACd;AAEA,IAAa,qBACX;AACF,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AAEzD,IAAa,QAAQ;CACnB,MAAM;CACN,KAAK;CACL,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,iBAAiB;CACjB,sBAAsB;AACxB;AAEA,IAAa,iBAAiB;CAC5B,OAAO;CACP,KAAK;AACP;AAEA,IAAY,wBAAL,yBAAA,uBAAA;CACL,sBAAA,SAAA;CACA,sBAAA,UAAA;CACA,sBAAA,WAAA;CACA,sBAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,gBAAgB;AAC7B,IAAa,mBAAmB;AAEhC,IAAa,kBAAkB;CAC7B,gBAAgB;CAChB,YAAY;CACZ,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,eAAe;AAC5B,IAAa,mBAAmB;AAChC,IAAa,iBAAiB"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import httpCodes from 'http-status-codes';\n\nexport const DEFAULT_PASSWORD_VALIDATION = /.{3}$/;\nexport const TIME_EXPIRATION_24H = '24h';\nexport const TIME_EXPIRATION_1H = '1h';\nexport const DIST_TAGS = 'dist-tags';\nexport const LATEST = 'latest';\nexport const USERS = 'users';\nexport const MAINTAINERS = 'maintainers';\nexport const DEFAULT_USER = 'Anonymous'; // for display purposes\nexport const ANONYMOUS_USER = 'anonymous'; // for username purposes\n\nexport const HEADER_TYPE = {\n CONTENT_ENCODING: 'content-encoding',\n CONTENT_TYPE: 'content-type',\n CONTENT_LENGTH: 'content-length',\n ACCEPT_ENCODING: 'accept-encoding',\n AUTHORIZATION: 'authorization',\n};\n\nexport const CHARACTER_ENCODING = {\n UTF8: 'utf8',\n};\n\n// @deprecated use Bearer instead\nexport const TOKEN_BASIC = 'Basic';\nexport const TOKEN_BEARER = 'Bearer';\n\nexport const HEADERS = {\n ACCEPT: 'Accept',\n ACCEPT_ENCODING: 'Accept-Encoding',\n USER_AGENT: 'User-Agent',\n JSON: 'application/json',\n CONTENT_TYPE: 'Content-type',\n CONTENT_LENGTH: 'content-length',\n TEXT_PLAIN: 'text/plain',\n TEXT_PLAIN_UTF8: 'text/plain; charset=utf-8',\n TEXT_HTML_UTF8: 'text/html; charset=utf-8',\n TEXT_HTML: 'text/html',\n AUTHORIZATION: 'authorization',\n CACHE_CONTROL: 'Cache-Control',\n NO_CACHE: 'no-cache, no-store',\n RETRY_AFTER: 'Retry-After',\n // only set with proxy that setup HTTPS\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n FORWARDED_PROTO: 'X-Forwarded-Proto',\n FORWARDED_FOR: 'X-Forwarded-For',\n FRAMES_OPTIONS: 'X-Frame-Options',\n CSP: 'Content-Security-Policy',\n CTO: 'X-Content-Type-Options',\n XSS: 'X-XSS-Protection',\n CLIENT: 'X-Client',\n POWERED_BY: 'X-Powered-By',\n RATELIMIT_LIMIT: 'X-RateLimit-Limit',\n RATELIMIT_REMAINING: 'X-RateLimit-Remaining',\n NONE_MATCH: 'If-None-Match',\n ETAG: 'ETag',\n JSON_CHARSET: 'application/json; charset=utf-8',\n JSON_INSTALL_CHARSET: 'application/vnd.npm.install-v1+json; charset=utf-8',\n OCTET_STREAM: 'application/octet-stream; charset=utf-8',\n TEXT_CHARSET: 'text/plain; charset=utf-8',\n JAVASCRIPT_CHARSET: 'application/javascript; charset=utf-8',\n WWW_AUTH: 'WWW-Authenticate',\n GZIP: 'gzip',\n HOST: 'host',\n};\n\n/**\n * HTTP status codes used throughout Verdaccio.\n */\nexport const HTTP_STATUS = {\n /** 200: Standard response for successful HTTP requests. */\n OK: httpCodes.OK,\n /** 201: The request has been fulfilled and resulted in a new resource being created. */\n CREATED: httpCodes.CREATED,\n /** 202: The request has been accepted for processing, but the processing is not yet complete. */\n ACCEPTED: httpCodes.ACCEPTED,\n /** 300: Indicates multiple options for the resource from which the client may choose. */\n MULTIPLE_CHOICES: httpCodes.MULTIPLE_CHOICES,\n /** 304: Indicates that the resource has not been modified since the last request. */\n NOT_MODIFIED: httpCodes.NOT_MODIFIED,\n /** 400: The server could not understand the request due to invalid syntax. */\n BAD_REQUEST: httpCodes.BAD_REQUEST,\n /** 401: The client must authenticate itself to get the requested response. */\n UNAUTHORIZED: httpCodes.UNAUTHORIZED,\n /** 403: The client does not have access rights to the content. */\n FORBIDDEN: httpCodes.FORBIDDEN,\n /** 404: The server can not find the requested resource. */\n NOT_FOUND: httpCodes.NOT_FOUND,\n /** 408: The server timed out waiting for the request. */\n REQUEST_TIMEOUT: httpCodes.REQUEST_TIMEOUT,\n /** 409: The request could not be completed due to a conflict with the current state of the resource. */\n CONFLICT: httpCodes.CONFLICT,\n /** 415: The media format of the requested data is not supported by the server. */\n UNSUPPORTED_MEDIA: httpCodes.UNSUPPORTED_MEDIA_TYPE,\n /** 422: The request was well-formed but was unable to be followed due to semantic errors. */\n BAD_DATA: httpCodes.UNPROCESSABLE_ENTITY,\n /** 499: The request was aborted by the client. */\n CLIENT_CLOSED_REQUEST: 499,\n /** 500: The server has encountered a situation it doesn't know how to handle. */\n INTERNAL_ERROR: httpCodes.INTERNAL_SERVER_ERROR,\n /** 501: The request method is not supported by the server and cannot be handled. */\n NOT_IMPLEMENTED: httpCodes.NOT_IMPLEMENTED,\n /** 502: The server, while acting as a gateway or proxy, received an invalid response from the upstream server. */\n BAD_GATEWAY: httpCodes.BAD_GATEWAY,\n /** 503: The server is not ready to handle the request. */\n SERVICE_UNAVAILABLE: httpCodes.SERVICE_UNAVAILABLE,\n /** 504: The server, while acting as a gateway or proxy, did not get a response in time from the upstream server. */\n GATEWAY_TIMEOUT: httpCodes.GATEWAY_TIMEOUT,\n /** 508: The server detected an infinite loop while processing the request. */\n LOOP_DETECTED: 508,\n /** 590: Custom Verdaccio code indicating the server cannot handle the request. */\n CANNOT_HANDLE: 590,\n};\n\nexport const ERROR_CODE = {\n token_required: 'token is required',\n};\n\nexport const API_MESSAGE = {\n PKG_CREATED: 'created new package',\n PKG_CHANGED: 'package changed',\n PKG_REMOVED: 'package removed',\n PKG_PUBLISHED: 'package published',\n TARBALL_UPLOADED: 'tarball uploaded successfully',\n TARBALL_REMOVED: 'tarball removed',\n TAG_UPDATED: 'tags updated',\n TAG_REMOVED: 'tag removed',\n TAG_ADDED: 'package tagged',\n OK: 'ok',\n LOGGED_OUT: 'Logged out',\n};\n\nexport const LOG_STATUS_MESSAGE =\n \"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'\";\nexport const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;\nexport const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;\nexport const LOG_VERDACCIO_ABORT = `${LOG_STATUS_MESSAGE}, request aborted by client`;\nexport const LOG_REQUEST_MESSAGE = \"@{ip} requested '@{req.method} @{req.url}'\";\n\nexport const ROLES = {\n $ALL: '$all',\n ALL: 'all',\n $AUTH: '$authenticated',\n $ANONYMOUS: '$anonymous',\n DEPRECATED_ALL: '@all',\n DEPRECATED_AUTH: '@authenticated',\n DEPRECATED_ANONYMOUS: '@anonymous',\n};\n\nexport const PACKAGE_ACCESS = {\n SCOPE: '@*/*',\n ALL: '**',\n};\n\nexport enum HtpasswdHashAlgorithm {\n md5 = 'md5',\n sha1 = 'sha1',\n crypt = 'crypt',\n bcrypt = 'bcrypt',\n}\n\nexport const PLUGIN_PREFIX = 'verdaccio';\nexport const PLUGIN_UI_PREFIX = 'verdaccio-theme';\n\nexport const PLUGIN_CATEGORY = {\n AUTHENTICATION: 'authentication',\n MIDDLEWARE: 'middleware',\n STORAGE: 'storage',\n FILTER: 'filter',\n THEME: 'theme',\n};\n\nexport const DEFAULT_PORT = '4873';\nexport const DEFAULT_PROTOCOL = 'http';\nexport const DEFAULT_DOMAIN = 'localhost';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAa,8BAA8B;AAG3C,IAAa,YAAY;AACzB,IAAa,SAAS;AACtB,IAAa,QAAQ;AACrB,IAAa,cAAc;AAC3B,IAAa,eAAe;AAC5B,IAAa,iBAAiB;AAE9B,IAAa,cAAc;CACzB,kBAAkB;CAClB,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;AACjB;AAEA,IAAa,qBAAqB,EAChC,MAAM,OACR;AAGA,IAAa,cAAc;AAC3B,IAAa,eAAe;AAE5B,IAAa,UAAU;CACrB,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,YAAY;CACZ,iBAAiB;CACjB,gBAAgB;CAChB,WAAW;CACX,eAAe;CACf,eAAe;CACf,UAAU;CACV,aAAa;CAGb,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,KAAK;CACL,KAAK;CACL,KAAK;CACL,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,UAAU;CACV,MAAM;CACN,MAAM;AACR;;;;AAKA,IAAa,cAAc;;CAEzB,IAAI,kBAAA,QAAU;;CAEd,SAAS,kBAAA,QAAU;;CAEnB,UAAU,kBAAA,QAAU;;CAEpB,kBAAkB,kBAAA,QAAU;;CAE5B,cAAc,kBAAA,QAAU;;CAExB,aAAa,kBAAA,QAAU;;CAEvB,cAAc,kBAAA,QAAU;;CAExB,WAAW,kBAAA,QAAU;;CAErB,WAAW,kBAAA,QAAU;;CAErB,iBAAiB,kBAAA,QAAU;;CAE3B,UAAU,kBAAA,QAAU;;CAEpB,mBAAmB,kBAAA,QAAU;;CAE7B,UAAU,kBAAA,QAAU;;CAEpB,uBAAuB;;CAEvB,gBAAgB,kBAAA,QAAU;;CAE1B,iBAAiB,kBAAA,QAAU;;CAE3B,aAAa,kBAAA,QAAU;;CAEvB,qBAAqB,kBAAA,QAAU;;CAE/B,iBAAiB,kBAAA,QAAU;;CAE3B,eAAe;;CAEf,eAAe;AACjB;AAEA,IAAa,aAAa,EACxB,gBAAgB,oBAClB;AAEA,IAAa,cAAc;CACzB,aAAa;CACb,aAAa;CACb,aAAa;CACb,eAAe;CACf,kBAAkB;CAClB,iBAAiB;CACjB,aAAa;CACb,aAAa;CACb,WAAW;CACX,IAAI;CACJ,YAAY;AACd;AAEA,IAAa,qBACX;AACF,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB;AAEnC,IAAa,QAAQ;CACnB,MAAM;CACN,KAAK;CACL,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,iBAAiB;CACjB,sBAAsB;AACxB;AAEA,IAAa,iBAAiB;CAC5B,OAAO;CACP,KAAK;AACP;AAEA,IAAY,wBAAL,yBAAA,uBAAA;CACL,sBAAA,SAAA;CACA,sBAAA,UAAA;CACA,sBAAA,WAAA;CACA,sBAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,gBAAgB;AAC7B,IAAa,mBAAmB;AAEhC,IAAa,kBAAkB;CAC7B,gBAAgB;CAChB,YAAY;CACZ,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,eAAe;AAC5B,IAAa,mBAAmB;AAChC,IAAa,iBAAiB"}
@@ -17,7 +17,9 @@ var constants_exports = /* @__PURE__ */ __exportAll({
17
17
  HTTP_STATUS: () => HTTP_STATUS,
18
18
  HtpasswdHashAlgorithm: () => HtpasswdHashAlgorithm,
19
19
  LATEST: () => LATEST,
20
+ LOG_REQUEST_MESSAGE: () => LOG_REQUEST_MESSAGE,
20
21
  LOG_STATUS_MESSAGE: () => LOG_STATUS_MESSAGE,
22
+ LOG_VERDACCIO_ABORT: () => LOG_VERDACCIO_ABORT,
21
23
  LOG_VERDACCIO_BYTES: () => LOG_VERDACCIO_BYTES,
22
24
  LOG_VERDACCIO_ERROR: () => LOG_VERDACCIO_ERROR,
23
25
  MAINTAINERS: () => MAINTAINERS,
@@ -89,12 +91,12 @@ var HEADERS = {
89
91
  * HTTP status codes used throughout Verdaccio.
90
92
  */
91
93
  var HTTP_STATUS = {
92
- /** 202: The request has been accepted for processing, but the processing is not yet complete. */
93
- ACCEPTED: httpCodes.ACCEPTED,
94
94
  /** 200: Standard response for successful HTTP requests. */
95
95
  OK: httpCodes.OK,
96
96
  /** 201: The request has been fulfilled and resulted in a new resource being created. */
97
97
  CREATED: httpCodes.CREATED,
98
+ /** 202: The request has been accepted for processing, but the processing is not yet complete. */
99
+ ACCEPTED: httpCodes.ACCEPTED,
98
100
  /** 300: Indicates multiple options for the resource from which the client may choose. */
99
101
  MULTIPLE_CHOICES: httpCodes.MULTIPLE_CHOICES,
100
102
  /** 304: Indicates that the resource has not been modified since the last request. */
@@ -115,6 +117,8 @@ var HTTP_STATUS = {
115
117
  UNSUPPORTED_MEDIA: httpCodes.UNSUPPORTED_MEDIA_TYPE,
116
118
  /** 422: The request was well-formed but was unable to be followed due to semantic errors. */
117
119
  BAD_DATA: httpCodes.UNPROCESSABLE_ENTITY,
120
+ /** 499: The request was aborted by the client. */
121
+ CLIENT_CLOSED_REQUEST: 499,
118
122
  /** 500: The server has encountered a situation it doesn't know how to handle. */
119
123
  INTERNAL_ERROR: httpCodes.INTERNAL_SERVER_ERROR,
120
124
  /** 501: The request method is not supported by the server and cannot be handled. */
@@ -147,6 +151,8 @@ var API_MESSAGE = {
147
151
  var LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'";
148
152
  var LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;
149
153
  var LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;
154
+ var LOG_VERDACCIO_ABORT = `${LOG_STATUS_MESSAGE}, request aborted by client`;
155
+ var LOG_REQUEST_MESSAGE = "@{ip} requested '@{req.method} @{req.url}'";
150
156
  var ROLES = {
151
157
  $ALL: "$all",
152
158
  ALL: "all",
@@ -180,6 +186,6 @@ var DEFAULT_PORT = "4873";
180
186
  var DEFAULT_PROTOCOL = "http";
181
187
  var DEFAULT_DOMAIN = "localhost";
182
188
  //#endregion
183
- export { ANONYMOUS_USER, API_MESSAGE, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, TOKEN_BASIC, TOKEN_BEARER, USERS, constants_exports };
189
+ export { ANONYMOUS_USER, API_MESSAGE, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, ERROR_CODE, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, LOG_REQUEST_MESSAGE, LOG_STATUS_MESSAGE, LOG_VERDACCIO_ABORT, LOG_VERDACCIO_BYTES, LOG_VERDACCIO_ERROR, MAINTAINERS, PACKAGE_ACCESS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, ROLES, TOKEN_BASIC, TOKEN_BEARER, USERS, constants_exports };
184
190
 
185
191
  //# sourceMappingURL=constants.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import httpCodes from 'http-status-codes';\n\nexport const DEFAULT_PASSWORD_VALIDATION = /.{3}$/;\nexport const TIME_EXPIRATION_24H = '24h';\nexport const TIME_EXPIRATION_1H = '1h';\nexport const DIST_TAGS = 'dist-tags';\nexport const LATEST = 'latest';\nexport const USERS = 'users';\nexport const MAINTAINERS = 'maintainers';\nexport const DEFAULT_USER = 'Anonymous'; // for display purposes\nexport const ANONYMOUS_USER = 'anonymous'; // for username purposes\n\nexport const HEADER_TYPE = {\n CONTENT_ENCODING: 'content-encoding',\n CONTENT_TYPE: 'content-type',\n CONTENT_LENGTH: 'content-length',\n ACCEPT_ENCODING: 'accept-encoding',\n AUTHORIZATION: 'authorization',\n};\n\nexport const CHARACTER_ENCODING = {\n UTF8: 'utf8',\n};\n\n// @deprecated use Bearer instead\nexport const TOKEN_BASIC = 'Basic';\nexport const TOKEN_BEARER = 'Bearer';\n\nexport const HEADERS = {\n ACCEPT: 'Accept',\n ACCEPT_ENCODING: 'Accept-Encoding',\n USER_AGENT: 'User-Agent',\n JSON: 'application/json',\n CONTENT_TYPE: 'Content-type',\n CONTENT_LENGTH: 'content-length',\n TEXT_PLAIN: 'text/plain',\n TEXT_PLAIN_UTF8: 'text/plain; charset=utf-8',\n TEXT_HTML_UTF8: 'text/html; charset=utf-8',\n TEXT_HTML: 'text/html',\n AUTHORIZATION: 'authorization',\n CACHE_CONTROL: 'Cache-Control',\n NO_CACHE: 'no-cache, no-store',\n RETRY_AFTER: 'Retry-After',\n // only set with proxy that setup HTTPS\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n FORWARDED_PROTO: 'X-Forwarded-Proto',\n FORWARDED_FOR: 'X-Forwarded-For',\n FRAMES_OPTIONS: 'X-Frame-Options',\n CSP: 'Content-Security-Policy',\n CTO: 'X-Content-Type-Options',\n XSS: 'X-XSS-Protection',\n CLIENT: 'X-Client',\n POWERED_BY: 'X-Powered-By',\n RATELIMIT_LIMIT: 'X-RateLimit-Limit',\n RATELIMIT_REMAINING: 'X-RateLimit-Remaining',\n NONE_MATCH: 'If-None-Match',\n ETAG: 'ETag',\n JSON_CHARSET: 'application/json; charset=utf-8',\n JSON_INSTALL_CHARSET: 'application/vnd.npm.install-v1+json; charset=utf-8',\n OCTET_STREAM: 'application/octet-stream; charset=utf-8',\n TEXT_CHARSET: 'text/plain; charset=utf-8',\n JAVASCRIPT_CHARSET: 'application/javascript; charset=utf-8',\n WWW_AUTH: 'WWW-Authenticate',\n GZIP: 'gzip',\n HOST: 'host',\n};\n\n/**\n * HTTP status codes used throughout Verdaccio.\n */\nexport const HTTP_STATUS = {\n /** 202: The request has been accepted for processing, but the processing is not yet complete. */\n ACCEPTED: httpCodes.ACCEPTED,\n /** 200: Standard response for successful HTTP requests. */\n OK: httpCodes.OK,\n /** 201: The request has been fulfilled and resulted in a new resource being created. */\n CREATED: httpCodes.CREATED,\n /** 300: Indicates multiple options for the resource from which the client may choose. */\n MULTIPLE_CHOICES: httpCodes.MULTIPLE_CHOICES,\n /** 304: Indicates that the resource has not been modified since the last request. */\n NOT_MODIFIED: httpCodes.NOT_MODIFIED,\n /** 400: The server could not understand the request due to invalid syntax. */\n BAD_REQUEST: httpCodes.BAD_REQUEST,\n /** 401: The client must authenticate itself to get the requested response. */\n UNAUTHORIZED: httpCodes.UNAUTHORIZED,\n /** 403: The client does not have access rights to the content. */\n FORBIDDEN: httpCodes.FORBIDDEN,\n /** 404: The server can not find the requested resource. */\n NOT_FOUND: httpCodes.NOT_FOUND,\n /** 408: The server timed out waiting for the request. */\n REQUEST_TIMEOUT: httpCodes.REQUEST_TIMEOUT,\n /** 409: The request could not be completed due to a conflict with the current state of the resource. */\n CONFLICT: httpCodes.CONFLICT,\n /** 415: The media format of the requested data is not supported by the server. */\n UNSUPPORTED_MEDIA: httpCodes.UNSUPPORTED_MEDIA_TYPE,\n /** 422: The request was well-formed but was unable to be followed due to semantic errors. */\n BAD_DATA: httpCodes.UNPROCESSABLE_ENTITY,\n /** 500: The server has encountered a situation it doesn't know how to handle. */\n INTERNAL_ERROR: httpCodes.INTERNAL_SERVER_ERROR,\n /** 501: The request method is not supported by the server and cannot be handled. */\n NOT_IMPLEMENTED: httpCodes.NOT_IMPLEMENTED,\n /** 502: The server, while acting as a gateway or proxy, received an invalid response from the upstream server. */\n BAD_GATEWAY: httpCodes.BAD_GATEWAY,\n /** 503: The server is not ready to handle the request. */\n SERVICE_UNAVAILABLE: httpCodes.SERVICE_UNAVAILABLE,\n /** 504: The server, while acting as a gateway or proxy, did not get a response in time from the upstream server. */\n GATEWAY_TIMEOUT: httpCodes.GATEWAY_TIMEOUT,\n /** 508: The server detected an infinite loop while processing the request. */\n LOOP_DETECTED: 508,\n /** 590: Custom Verdaccio code indicating the server cannot handle the request. */\n CANNOT_HANDLE: 590,\n};\n\nexport const ERROR_CODE = {\n token_required: 'token is required',\n};\n\nexport const API_MESSAGE = {\n PKG_CREATED: 'created new package',\n PKG_CHANGED: 'package changed',\n PKG_REMOVED: 'package removed',\n PKG_PUBLISHED: 'package published',\n TARBALL_UPLOADED: 'tarball uploaded successfully',\n TARBALL_REMOVED: 'tarball removed',\n TAG_UPDATED: 'tags updated',\n TAG_REMOVED: 'tag removed',\n TAG_ADDED: 'package tagged',\n OK: 'ok',\n LOGGED_OUT: 'Logged out',\n};\n\nexport const LOG_STATUS_MESSAGE =\n \"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'\";\nexport const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;\nexport const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;\n\nexport const ROLES = {\n $ALL: '$all',\n ALL: 'all',\n $AUTH: '$authenticated',\n $ANONYMOUS: '$anonymous',\n DEPRECATED_ALL: '@all',\n DEPRECATED_AUTH: '@authenticated',\n DEPRECATED_ANONYMOUS: '@anonymous',\n};\n\nexport const PACKAGE_ACCESS = {\n SCOPE: '@*/*',\n ALL: '**',\n};\n\nexport enum HtpasswdHashAlgorithm {\n md5 = 'md5',\n sha1 = 'sha1',\n crypt = 'crypt',\n bcrypt = 'bcrypt',\n}\n\nexport const PLUGIN_PREFIX = 'verdaccio';\nexport const PLUGIN_UI_PREFIX = 'verdaccio-theme';\n\nexport const PLUGIN_CATEGORY = {\n AUTHENTICATION: 'authentication',\n MIDDLEWARE: 'middleware',\n STORAGE: 'storage',\n FILTER: 'filter',\n THEME: 'theme',\n};\n\nexport const DEFAULT_PORT = '4873';\nexport const DEFAULT_PROTOCOL = 'http';\nexport const DEFAULT_DOMAIN = 'localhost';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAa,8BAA8B;AAG3C,IAAa,YAAY;AACzB,IAAa,SAAS;AACtB,IAAa,QAAQ;AACrB,IAAa,cAAc;AAC3B,IAAa,eAAe;AAC5B,IAAa,iBAAiB;AAE9B,IAAa,cAAc;CACzB,kBAAkB;CAClB,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;AACjB;AAEA,IAAa,qBAAqB,EAChC,MAAM,OACR;AAGA,IAAa,cAAc;AAC3B,IAAa,eAAe;AAE5B,IAAa,UAAU;CACrB,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,YAAY;CACZ,iBAAiB;CACjB,gBAAgB;CAChB,WAAW;CACX,eAAe;CACf,eAAe;CACf,UAAU;CACV,aAAa;CAGb,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,KAAK;CACL,KAAK;CACL,KAAK;CACL,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,UAAU;CACV,MAAM;CACN,MAAM;AACR;;;;AAKA,IAAa,cAAc;;CAEzB,UAAU,UAAU;;CAEpB,IAAI,UAAU;;CAEd,SAAS,UAAU;;CAEnB,kBAAkB,UAAU;;CAE5B,cAAc,UAAU;;CAExB,aAAa,UAAU;;CAEvB,cAAc,UAAU;;CAExB,WAAW,UAAU;;CAErB,WAAW,UAAU;;CAErB,iBAAiB,UAAU;;CAE3B,UAAU,UAAU;;CAEpB,mBAAmB,UAAU;;CAE7B,UAAU,UAAU;;CAEpB,gBAAgB,UAAU;;CAE1B,iBAAiB,UAAU;;CAE3B,aAAa,UAAU;;CAEvB,qBAAqB,UAAU;;CAE/B,iBAAiB,UAAU;;CAE3B,eAAe;;CAEf,eAAe;AACjB;AAEA,IAAa,aAAa,EACxB,gBAAgB,oBAClB;AAEA,IAAa,cAAc;CACzB,aAAa;CACb,aAAa;CACb,aAAa;CACb,eAAe;CACf,kBAAkB;CAClB,iBAAiB;CACjB,aAAa;CACb,aAAa;CACb,WAAW;CACX,IAAI;CACJ,YAAY;AACd;AAEA,IAAa,qBACX;AACF,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AAEzD,IAAa,QAAQ;CACnB,MAAM;CACN,KAAK;CACL,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,iBAAiB;CACjB,sBAAsB;AACxB;AAEA,IAAa,iBAAiB;CAC5B,OAAO;CACP,KAAK;AACP;AAEA,IAAY,wBAAL,yBAAA,uBAAA;CACL,sBAAA,SAAA;CACA,sBAAA,UAAA;CACA,sBAAA,WAAA;CACA,sBAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,gBAAgB;AAC7B,IAAa,mBAAmB;AAEhC,IAAa,kBAAkB;CAC7B,gBAAgB;CAChB,YAAY;CACZ,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,eAAe;AAC5B,IAAa,mBAAmB;AAChC,IAAa,iBAAiB"}
1
+ {"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import httpCodes from 'http-status-codes';\n\nexport const DEFAULT_PASSWORD_VALIDATION = /.{3}$/;\nexport const TIME_EXPIRATION_24H = '24h';\nexport const TIME_EXPIRATION_1H = '1h';\nexport const DIST_TAGS = 'dist-tags';\nexport const LATEST = 'latest';\nexport const USERS = 'users';\nexport const MAINTAINERS = 'maintainers';\nexport const DEFAULT_USER = 'Anonymous'; // for display purposes\nexport const ANONYMOUS_USER = 'anonymous'; // for username purposes\n\nexport const HEADER_TYPE = {\n CONTENT_ENCODING: 'content-encoding',\n CONTENT_TYPE: 'content-type',\n CONTENT_LENGTH: 'content-length',\n ACCEPT_ENCODING: 'accept-encoding',\n AUTHORIZATION: 'authorization',\n};\n\nexport const CHARACTER_ENCODING = {\n UTF8: 'utf8',\n};\n\n// @deprecated use Bearer instead\nexport const TOKEN_BASIC = 'Basic';\nexport const TOKEN_BEARER = 'Bearer';\n\nexport const HEADERS = {\n ACCEPT: 'Accept',\n ACCEPT_ENCODING: 'Accept-Encoding',\n USER_AGENT: 'User-Agent',\n JSON: 'application/json',\n CONTENT_TYPE: 'Content-type',\n CONTENT_LENGTH: 'content-length',\n TEXT_PLAIN: 'text/plain',\n TEXT_PLAIN_UTF8: 'text/plain; charset=utf-8',\n TEXT_HTML_UTF8: 'text/html; charset=utf-8',\n TEXT_HTML: 'text/html',\n AUTHORIZATION: 'authorization',\n CACHE_CONTROL: 'Cache-Control',\n NO_CACHE: 'no-cache, no-store',\n RETRY_AFTER: 'Retry-After',\n // only set with proxy that setup HTTPS\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n FORWARDED_PROTO: 'X-Forwarded-Proto',\n FORWARDED_FOR: 'X-Forwarded-For',\n FRAMES_OPTIONS: 'X-Frame-Options',\n CSP: 'Content-Security-Policy',\n CTO: 'X-Content-Type-Options',\n XSS: 'X-XSS-Protection',\n CLIENT: 'X-Client',\n POWERED_BY: 'X-Powered-By',\n RATELIMIT_LIMIT: 'X-RateLimit-Limit',\n RATELIMIT_REMAINING: 'X-RateLimit-Remaining',\n NONE_MATCH: 'If-None-Match',\n ETAG: 'ETag',\n JSON_CHARSET: 'application/json; charset=utf-8',\n JSON_INSTALL_CHARSET: 'application/vnd.npm.install-v1+json; charset=utf-8',\n OCTET_STREAM: 'application/octet-stream; charset=utf-8',\n TEXT_CHARSET: 'text/plain; charset=utf-8',\n JAVASCRIPT_CHARSET: 'application/javascript; charset=utf-8',\n WWW_AUTH: 'WWW-Authenticate',\n GZIP: 'gzip',\n HOST: 'host',\n};\n\n/**\n * HTTP status codes used throughout Verdaccio.\n */\nexport const HTTP_STATUS = {\n /** 200: Standard response for successful HTTP requests. */\n OK: httpCodes.OK,\n /** 201: The request has been fulfilled and resulted in a new resource being created. */\n CREATED: httpCodes.CREATED,\n /** 202: The request has been accepted for processing, but the processing is not yet complete. */\n ACCEPTED: httpCodes.ACCEPTED,\n /** 300: Indicates multiple options for the resource from which the client may choose. */\n MULTIPLE_CHOICES: httpCodes.MULTIPLE_CHOICES,\n /** 304: Indicates that the resource has not been modified since the last request. */\n NOT_MODIFIED: httpCodes.NOT_MODIFIED,\n /** 400: The server could not understand the request due to invalid syntax. */\n BAD_REQUEST: httpCodes.BAD_REQUEST,\n /** 401: The client must authenticate itself to get the requested response. */\n UNAUTHORIZED: httpCodes.UNAUTHORIZED,\n /** 403: The client does not have access rights to the content. */\n FORBIDDEN: httpCodes.FORBIDDEN,\n /** 404: The server can not find the requested resource. */\n NOT_FOUND: httpCodes.NOT_FOUND,\n /** 408: The server timed out waiting for the request. */\n REQUEST_TIMEOUT: httpCodes.REQUEST_TIMEOUT,\n /** 409: The request could not be completed due to a conflict with the current state of the resource. */\n CONFLICT: httpCodes.CONFLICT,\n /** 415: The media format of the requested data is not supported by the server. */\n UNSUPPORTED_MEDIA: httpCodes.UNSUPPORTED_MEDIA_TYPE,\n /** 422: The request was well-formed but was unable to be followed due to semantic errors. */\n BAD_DATA: httpCodes.UNPROCESSABLE_ENTITY,\n /** 499: The request was aborted by the client. */\n CLIENT_CLOSED_REQUEST: 499,\n /** 500: The server has encountered a situation it doesn't know how to handle. */\n INTERNAL_ERROR: httpCodes.INTERNAL_SERVER_ERROR,\n /** 501: The request method is not supported by the server and cannot be handled. */\n NOT_IMPLEMENTED: httpCodes.NOT_IMPLEMENTED,\n /** 502: The server, while acting as a gateway or proxy, received an invalid response from the upstream server. */\n BAD_GATEWAY: httpCodes.BAD_GATEWAY,\n /** 503: The server is not ready to handle the request. */\n SERVICE_UNAVAILABLE: httpCodes.SERVICE_UNAVAILABLE,\n /** 504: The server, while acting as a gateway or proxy, did not get a response in time from the upstream server. */\n GATEWAY_TIMEOUT: httpCodes.GATEWAY_TIMEOUT,\n /** 508: The server detected an infinite loop while processing the request. */\n LOOP_DETECTED: 508,\n /** 590: Custom Verdaccio code indicating the server cannot handle the request. */\n CANNOT_HANDLE: 590,\n};\n\nexport const ERROR_CODE = {\n token_required: 'token is required',\n};\n\nexport const API_MESSAGE = {\n PKG_CREATED: 'created new package',\n PKG_CHANGED: 'package changed',\n PKG_REMOVED: 'package removed',\n PKG_PUBLISHED: 'package published',\n TARBALL_UPLOADED: 'tarball uploaded successfully',\n TARBALL_REMOVED: 'tarball removed',\n TAG_UPDATED: 'tags updated',\n TAG_REMOVED: 'tag removed',\n TAG_ADDED: 'package tagged',\n OK: 'ok',\n LOGGED_OUT: 'Logged out',\n};\n\nexport const LOG_STATUS_MESSAGE =\n \"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'\";\nexport const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;\nexport const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;\nexport const LOG_VERDACCIO_ABORT = `${LOG_STATUS_MESSAGE}, request aborted by client`;\nexport const LOG_REQUEST_MESSAGE = \"@{ip} requested '@{req.method} @{req.url}'\";\n\nexport const ROLES = {\n $ALL: '$all',\n ALL: 'all',\n $AUTH: '$authenticated',\n $ANONYMOUS: '$anonymous',\n DEPRECATED_ALL: '@all',\n DEPRECATED_AUTH: '@authenticated',\n DEPRECATED_ANONYMOUS: '@anonymous',\n};\n\nexport const PACKAGE_ACCESS = {\n SCOPE: '@*/*',\n ALL: '**',\n};\n\nexport enum HtpasswdHashAlgorithm {\n md5 = 'md5',\n sha1 = 'sha1',\n crypt = 'crypt',\n bcrypt = 'bcrypt',\n}\n\nexport const PLUGIN_PREFIX = 'verdaccio';\nexport const PLUGIN_UI_PREFIX = 'verdaccio-theme';\n\nexport const PLUGIN_CATEGORY = {\n AUTHENTICATION: 'authentication',\n MIDDLEWARE: 'middleware',\n STORAGE: 'storage',\n FILTER: 'filter',\n THEME: 'theme',\n};\n\nexport const DEFAULT_PORT = '4873';\nexport const DEFAULT_PROTOCOL = 'http';\nexport const DEFAULT_DOMAIN = 'localhost';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAa,8BAA8B;AAG3C,IAAa,YAAY;AACzB,IAAa,SAAS;AACtB,IAAa,QAAQ;AACrB,IAAa,cAAc;AAC3B,IAAa,eAAe;AAC5B,IAAa,iBAAiB;AAE9B,IAAa,cAAc;CACzB,kBAAkB;CAClB,cAAc;CACd,gBAAgB;CAChB,iBAAiB;CACjB,eAAe;AACjB;AAEA,IAAa,qBAAqB,EAChC,MAAM,OACR;AAGA,IAAa,cAAc;AAC3B,IAAa,eAAe;AAE5B,IAAa,UAAU;CACrB,QAAQ;CACR,iBAAiB;CACjB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,gBAAgB;CAChB,YAAY;CACZ,iBAAiB;CACjB,gBAAgB;CAChB,WAAW;CACX,eAAe;CACf,eAAe;CACf,UAAU;CACV,aAAa;CAGb,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,KAAK;CACL,KAAK;CACL,KAAK;CACL,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,YAAY;CACZ,MAAM;CACN,cAAc;CACd,sBAAsB;CACtB,cAAc;CACd,cAAc;CACd,oBAAoB;CACpB,UAAU;CACV,MAAM;CACN,MAAM;AACR;;;;AAKA,IAAa,cAAc;;CAEzB,IAAI,UAAU;;CAEd,SAAS,UAAU;;CAEnB,UAAU,UAAU;;CAEpB,kBAAkB,UAAU;;CAE5B,cAAc,UAAU;;CAExB,aAAa,UAAU;;CAEvB,cAAc,UAAU;;CAExB,WAAW,UAAU;;CAErB,WAAW,UAAU;;CAErB,iBAAiB,UAAU;;CAE3B,UAAU,UAAU;;CAEpB,mBAAmB,UAAU;;CAE7B,UAAU,UAAU;;CAEpB,uBAAuB;;CAEvB,gBAAgB,UAAU;;CAE1B,iBAAiB,UAAU;;CAE3B,aAAa,UAAU;;CAEvB,qBAAqB,UAAU;;CAE/B,iBAAiB,UAAU;;CAE3B,eAAe;;CAEf,eAAe;AACjB;AAEA,IAAa,aAAa,EACxB,gBAAgB,oBAClB;AAEA,IAAa,cAAc;CACzB,aAAa;CACb,aAAa;CACb,aAAa;CACb,eAAe;CACf,kBAAkB;CAClB,iBAAiB;CACjB,aAAa;CACb,aAAa;CACb,WAAW;CACX,IAAI;CACJ,YAAY;AACd;AAEA,IAAa,qBACX;AACF,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB,GAAG,mBAAmB;AACzD,IAAa,sBAAsB;AAEnC,IAAa,QAAQ;CACnB,MAAM;CACN,KAAK;CACL,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,iBAAiB;CACjB,sBAAsB;AACxB;AAEA,IAAa,iBAAiB;CAC5B,OAAO;CACP,KAAK;AACP;AAEA,IAAY,wBAAL,yBAAA,uBAAA;CACL,sBAAA,SAAA;CACA,sBAAA,UAAA;CACA,sBAAA,WAAA;CACA,sBAAA,YAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,gBAAgB;AAC7B,IAAa,mBAAmB;AAEhC,IAAa,kBAAkB;CAC7B,gBAAgB;CAChB,YAAY;CACZ,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAEA,IAAa,eAAe;AAC5B,IAAa,mBAAmB;AAChC,IAAa,iBAAiB"}
@@ -1,4 +1,4 @@
1
- import { Hash } from 'node:crypto';
1
+ import type { Hash } from 'node:crypto';
2
2
  export declare const defaultTarballHashAlgorithm = "sha1";
3
3
  export declare function createTarballHash(): Hash;
4
4
  /**
@@ -35,11 +35,16 @@ function mask(str, charNum = 3) {
35
35
  return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;
36
36
  }
37
37
  //#endregion
38
+ exports.createTarballHash = createTarballHash;
38
39
  Object.defineProperty(exports, "crypto_utils_exports", {
39
40
  enumerable: true,
40
41
  get: function() {
41
42
  return crypto_utils_exports;
42
43
  }
43
44
  });
45
+ exports.defaultTarballHashAlgorithm = defaultTarballHashAlgorithm;
46
+ exports.generateRandomHexString = generateRandomHexString;
47
+ exports.mask = mask;
48
+ exports.stringToMD5 = stringToMD5;
44
49
 
45
50
  //# sourceMappingURL=crypto-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-utils.js","names":[],"sources":["../src/crypto-utils.ts"],"sourcesContent":["import type { Hash } from 'node:crypto';\nimport { createHash, randomBytes } from 'node:crypto';\n\nexport const defaultTarballHashAlgorithm = 'sha1';\n\nexport function createTarballHash(): Hash {\n return createHash(defaultTarballHashAlgorithm);\n}\n\n/**\n * Express doesn't do ETAGS with requests <= 1024b\n * we use md5 here, it works well on 1k+ bytes, but sucks with fewer data\n * could improve performance using crc32 after benchmarks.\n * @param {Object} data\n * @return {String}\n */\nexport function stringToMD5(data: Buffer | string): string {\n // @ts-ignore update method accepts Buffer or string\n return createHash('md5').update(data).digest('hex');\n}\n\nexport function generateRandomHexString(length = 8): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * return a masquerade string with its first and last {charNum} and three dots in between.\n * @param {String} str\n * @param {Number} charNum\n * @returns {String}\n */\nexport function mask(str: string, charNum = 3): string {\n return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;\n}\n"],"mappings":";;;;;;;;;;AAGA,IAAa,8BAA8B;AAE3C,SAAgB,oBAA0B;CACxC,QAAA,GAAA,YAAA,YAAkB,2BAA2B;AAC/C;;;;;;;;AASA,SAAgB,YAAY,MAA+B;CAEzD,QAAA,GAAA,YAAA,YAAkB,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACpD;AAEA,SAAgB,wBAAwB,SAAS,GAAW;CAC1D,QAAA,GAAA,YAAA,aAAmB,MAAM,EAAE,SAAS,KAAK;AAC3C;;;;;;;AAQA,SAAgB,KAAK,KAAa,UAAU,GAAW;CACrD,OAAO,GAAG,IAAI,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO;AACzD"}
1
+ {"version":3,"file":"crypto-utils.js","names":[],"sources":["../src/crypto-utils.ts"],"sourcesContent":["import type { Hash } from 'node:crypto';\nimport { createHash, randomBytes } from 'node:crypto';\n\nexport const defaultTarballHashAlgorithm = 'sha1';\n\nexport function createTarballHash(): Hash {\n return createHash(defaultTarballHashAlgorithm);\n}\n\n/**\n * Express doesn't do ETAGS with requests <= 1024b\n * we use md5 here, it works well on 1k+ bytes, but sucks with fewer data\n * could improve performance using crc32 after benchmarks.\n * @param {Object} data\n * @return {String}\n */\nexport function stringToMD5(data: Buffer | string): string {\n // @ts-ignore update method accepts Buffer or string\n return createHash('md5').update(data).digest('hex');\n}\n\nexport function generateRandomHexString(length = 8): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * return a masquerade string with its first and last {charNum} and three dots in between.\n * @param {String} str\n * @param {Number} charNum\n * @returns {String}\n */\nexport function mask(str: string, charNum = 3): string {\n return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;\n}\n"],"mappings":";;;;;;;;;;AAGA,IAAa,8BAA8B;AAE3C,SAAgB,oBAA0B;CACxC,QAAA,GAAA,YAAA,WAAA,CAAkB,2BAA2B;AAC/C;;;;;;;;AASA,SAAgB,YAAY,MAA+B;CAEzD,QAAA,GAAA,YAAA,WAAA,CAAkB,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK;AACpD;AAEA,SAAgB,wBAAwB,SAAS,GAAW;CAC1D,QAAA,GAAA,YAAA,YAAA,CAAmB,MAAM,CAAC,CAAC,SAAS,KAAK;AAC3C;;;;;;;AAQA,SAAgB,KAAK,KAAa,UAAU,GAAW;CACrD,OAAO,GAAG,IAAI,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO;AACzD"}
@@ -35,6 +35,6 @@ function mask(str, charNum = 3) {
35
35
  return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;
36
36
  }
37
37
  //#endregion
38
- export { crypto_utils_exports };
38
+ export { createTarballHash, crypto_utils_exports, defaultTarballHashAlgorithm, generateRandomHexString, mask, stringToMD5 };
39
39
 
40
40
  //# sourceMappingURL=crypto-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-utils.mjs","names":[],"sources":["../src/crypto-utils.ts"],"sourcesContent":["import type { Hash } from 'node:crypto';\nimport { createHash, randomBytes } from 'node:crypto';\n\nexport const defaultTarballHashAlgorithm = 'sha1';\n\nexport function createTarballHash(): Hash {\n return createHash(defaultTarballHashAlgorithm);\n}\n\n/**\n * Express doesn't do ETAGS with requests <= 1024b\n * we use md5 here, it works well on 1k+ bytes, but sucks with fewer data\n * could improve performance using crc32 after benchmarks.\n * @param {Object} data\n * @return {String}\n */\nexport function stringToMD5(data: Buffer | string): string {\n // @ts-ignore update method accepts Buffer or string\n return createHash('md5').update(data).digest('hex');\n}\n\nexport function generateRandomHexString(length = 8): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * return a masquerade string with its first and last {charNum} and three dots in between.\n * @param {String} str\n * @param {Number} charNum\n * @returns {String}\n */\nexport function mask(str: string, charNum = 3): string {\n return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;\n}\n"],"mappings":";;;;;;;;;;AAGA,IAAa,8BAA8B;AAE3C,SAAgB,oBAA0B;CACxC,OAAO,WAAW,2BAA2B;AAC/C;;;;;;;;AASA,SAAgB,YAAY,MAA+B;CAEzD,OAAO,WAAW,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACpD;AAEA,SAAgB,wBAAwB,SAAS,GAAW;CAC1D,OAAO,YAAY,MAAM,EAAE,SAAS,KAAK;AAC3C;;;;;;;AAQA,SAAgB,KAAK,KAAa,UAAU,GAAW;CACrD,OAAO,GAAG,IAAI,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO;AACzD"}
1
+ {"version":3,"file":"crypto-utils.mjs","names":[],"sources":["../src/crypto-utils.ts"],"sourcesContent":["import type { Hash } from 'node:crypto';\nimport { createHash, randomBytes } from 'node:crypto';\n\nexport const defaultTarballHashAlgorithm = 'sha1';\n\nexport function createTarballHash(): Hash {\n return createHash(defaultTarballHashAlgorithm);\n}\n\n/**\n * Express doesn't do ETAGS with requests <= 1024b\n * we use md5 here, it works well on 1k+ bytes, but sucks with fewer data\n * could improve performance using crc32 after benchmarks.\n * @param {Object} data\n * @return {String}\n */\nexport function stringToMD5(data: Buffer | string): string {\n // @ts-ignore update method accepts Buffer or string\n return createHash('md5').update(data).digest('hex');\n}\n\nexport function generateRandomHexString(length = 8): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * return a masquerade string with its first and last {charNum} and three dots in between.\n * @param {String} str\n * @param {Number} charNum\n * @returns {String}\n */\nexport function mask(str: string, charNum = 3): string {\n return `${str.slice(0, charNum)}...${str.slice(-charNum)}`;\n}\n"],"mappings":";;;;;;;;;;AAGA,IAAa,8BAA8B;AAE3C,SAAgB,oBAA0B;CACxC,OAAO,WAAW,2BAA2B;AAC/C;;;;;;;;AASA,SAAgB,YAAY,MAA+B;CAEzD,OAAO,WAAW,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK;AACpD;AAEA,SAAgB,wBAAwB,SAAS,GAAW;CAC1D,OAAO,YAAY,MAAM,CAAC,CAAC,SAAS,KAAK;AAC3C;;;;;;;AAQA,SAAgB,KAAK,KAAa,UAAU,GAAW;CACrD,OAAO,GAAG,IAAI,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO;AACzD"}
@@ -1,4 +1,4 @@
1
- import { HttpError } from 'http-errors';
1
+ import type { HttpError } from 'http-errors';
2
2
  export declare const API_ERROR: {
3
3
  PASSWORD_SHORT: string;
4
4
  MUST_BE_LOGGED: string;
@@ -112,5 +112,14 @@ Object.defineProperty(exports, "error_utils_exports", {
112
112
  return error_utils_exports;
113
113
  }
114
114
  });
115
+ exports.getBadData = getBadData;
116
+ exports.getBadRequest = getBadRequest;
117
+ exports.getCode = getCode;
118
+ exports.getConflict = getConflict;
119
+ exports.getForbidden = getForbidden;
120
+ exports.getInternalError = getInternalError;
121
+ exports.getNotFound = getNotFound;
122
+ exports.getServiceUnavailable = getServiceUnavailable;
123
+ exports.getUnauthorized = getUnauthorized;
115
124
 
116
125
  //# sourceMappingURL=error-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-utils.js","names":[],"sources":["../src/error-utils.ts"],"sourcesContent":["import type { HttpError } from 'http-errors';\nimport createError from 'http-errors';\n\nimport { HTTP_STATUS } from './constants';\n\nexport const API_ERROR = {\n PASSWORD_SHORT: 'The provided password does not pass the validation',\n MUST_BE_LOGGED: 'You must be logged in to publish packages.',\n PLUGIN_ERROR: 'bug in the auth plugin system',\n CONFIG_BAD_FORMAT: 'config file must be an object',\n BAD_USERNAME_PASSWORD: 'bad username/password, access denied',\n NO_PACKAGE: 'no such package available',\n PACKAGE_CANNOT_BE_ADDED: 'this package cannot be added',\n BAD_DATA: 'bad data',\n NOT_ALLOWED: 'not allowed to access package',\n NOT_ALLOWED_PUBLISH: 'not allowed to publish package',\n INTERNAL_SERVER_ERROR: 'internal server error',\n UNKNOWN_ERROR: 'unknown error',\n NOT_PACKAGE_UPLINK: 'package does not exist on uplink',\n UPLINK_OFFLINE_PUBLISH: 'one of the uplinks is down, refuse to publish',\n UPLINK_OFFLINE: 'uplink is offline',\n NOT_MODIFIED_NO_DATA: 'no data',\n CONTENT_MISMATCH: 'content length mismatch',\n NOT_FILE_UPLINK: \"file doesn't exist on uplink\",\n MAX_USERS_REACHED: 'maximum amount of users reached',\n VERSION_NOT_EXIST: \"this version doesn't exist\",\n NO_SUCH_FILE: 'no such file available',\n UNSUPORTED_REGISTRY_CALL: 'unsupported registry call',\n FILE_NOT_FOUND: 'File not found',\n REGISTRATION_DISABLED: 'user registration disabled',\n UNAUTHORIZED_ACCESS: 'unauthorized access',\n BAD_STATUS_CODE: 'bad status code',\n SERVER_TIME_OUT: 'looks like the server is taking to long to respond',\n PACKAGE_EXIST: 'this package is already present',\n BAD_AUTH_HEADER: 'bad authorization header',\n WEB_DISABLED: 'Web interface is disabled in the config file',\n DEPRECATED_BASIC_HEADER: 'basic authentication is deprecated, please use JWT instead',\n BAD_FORMAT_USER_GROUP: 'user groups is different than an array',\n RESOURCE_UNAVAILABLE: 'resource unavailable',\n BAD_PACKAGE_DATA: 'bad incoming package data',\n USERNAME_PASSWORD_REQUIRED: 'username and password is required',\n USERNAME_ALREADY_REGISTERED: 'username is already registered',\n USERNAME_MISMATCH: 'username does not match logged in user',\n SESSION_ID_REQUIRED: 'session id is required',\n SESSION_ID_INVALID: 'session id is invalid',\n SESSION_TOKEN_EXPIRED: 'session token expired',\n};\n\nexport const SUPPORT_ERRORS = {\n PLUGIN_MISSING_INTERFACE: 'the plugin does not provide implementation of the requested feature',\n TFA_DISABLED: 'the two-factor authentication is not yet supported',\n STORAGE_NOT_IMPLEMENT: 'the storage does not support token saving',\n PARAMETERS_NOT_VALID: 'the parameters are not valid',\n};\n\nexport const APP_ERROR = {\n CONFIG_NOT_VALID: 'CONFIG: it does not look like a valid config file',\n PROFILE_ERROR: 'profile unexpected error',\n PASSWORD_VALIDATION: 'not valid password',\n};\n\nexport type VerdaccioError = HttpError & { code: number };\n\nfunction getError(code: number, message: string): VerdaccioError {\n const httpError = createError(code, message);\n\n httpError.code = code;\n\n return httpError as VerdaccioError;\n}\n\nexport function getConflict(message: string = API_ERROR.PACKAGE_EXIST): VerdaccioError {\n return getError(HTTP_STATUS.CONFLICT, message);\n}\n\nexport function getBadData(customMessage?: string): VerdaccioError {\n return getError(HTTP_STATUS.BAD_DATA, customMessage || API_ERROR.BAD_DATA);\n}\n\nexport function getBadRequest(customMessage: string): VerdaccioError {\n return getError(HTTP_STATUS.BAD_REQUEST, customMessage);\n}\n\nexport function getInternalError(customMessage?: string): VerdaccioError {\n return customMessage\n ? getError(HTTP_STATUS.INTERNAL_ERROR, customMessage)\n : getError(HTTP_STATUS.INTERNAL_ERROR, API_ERROR.UNKNOWN_ERROR);\n}\n\nexport function getUnauthorized(message = 'no credentials provided'): VerdaccioError {\n return getError(HTTP_STATUS.UNAUTHORIZED, message);\n}\n\nexport function getForbidden(message = \"can't use this filename\"): VerdaccioError {\n return getError(HTTP_STATUS.FORBIDDEN, message);\n}\n\nexport function getServiceUnavailable(\n message: string = API_ERROR.RESOURCE_UNAVAILABLE\n): VerdaccioError {\n return getError(HTTP_STATUS.SERVICE_UNAVAILABLE, message);\n}\n\nexport function getNotFound(customMessage?: string): VerdaccioError {\n return getError(HTTP_STATUS.NOT_FOUND, customMessage || API_ERROR.NO_PACKAGE);\n}\n\nexport function getCode(statusCode: number, customMessage: string): VerdaccioError {\n return getError(statusCode, customMessage);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAKA,IAAa,YAAY;CACvB,gBAAgB;CAChB,gBAAgB;CAChB,cAAc;CACd,mBAAmB;CACnB,uBAAuB;CACvB,YAAY;CACZ,yBAAyB;CACzB,UAAU;CACV,aAAa;CACb,qBAAqB;CACrB,uBAAuB;CACvB,eAAe;CACf,oBAAoB;CACpB,wBAAwB;CACxB,gBAAgB;CAChB,sBAAsB;CACtB,kBAAkB;CAClB,iBAAiB;CACjB,mBAAmB;CACnB,mBAAmB;CACnB,cAAc;CACd,0BAA0B;CAC1B,gBAAgB;CAChB,uBAAuB;CACvB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,eAAe;CACf,iBAAiB;CACjB,cAAc;CACd,yBAAyB;CACzB,uBAAuB;CACvB,sBAAsB;CACtB,kBAAkB;CAClB,4BAA4B;CAC5B,6BAA6B;CAC7B,mBAAmB;CACnB,qBAAqB;CACrB,oBAAoB;CACpB,uBAAuB;AACzB;AAEA,IAAa,iBAAiB;CAC5B,0BAA0B;CAC1B,cAAc;CACd,uBAAuB;CACvB,sBAAsB;AACxB;AAEA,IAAa,YAAY;CACvB,kBAAkB;CAClB,eAAe;CACf,qBAAqB;AACvB;AAIA,SAAS,SAAS,MAAc,SAAiC;CAC/D,MAAM,aAAA,GAAA,YAAA,SAAwB,MAAM,OAAO;CAE3C,UAAU,OAAO;CAEjB,OAAO;AACT;AAEA,SAAgB,YAAY,UAAkB,UAAU,eAA+B;CACrF,OAAO,SAAS,kBAAA,YAAY,UAAU,OAAO;AAC/C;AAEA,SAAgB,WAAW,eAAwC;CACjE,OAAO,SAAS,kBAAA,YAAY,UAAU,iBAAiB,UAAU,QAAQ;AAC3E;AAEA,SAAgB,cAAc,eAAuC;CACnE,OAAO,SAAS,kBAAA,YAAY,aAAa,aAAa;AACxD;AAEA,SAAgB,iBAAiB,eAAwC;CACvE,OAAO,gBACH,SAAS,kBAAA,YAAY,gBAAgB,aAAa,IAClD,SAAS,kBAAA,YAAY,gBAAgB,UAAU,aAAa;AAClE;AAEA,SAAgB,gBAAgB,UAAU,2BAA2C;CACnF,OAAO,SAAS,kBAAA,YAAY,cAAc,OAAO;AACnD;AAEA,SAAgB,aAAa,UAAU,2BAA2C;CAChF,OAAO,SAAS,kBAAA,YAAY,WAAW,OAAO;AAChD;AAEA,SAAgB,sBACd,UAAkB,UAAU,sBACZ;CAChB,OAAO,SAAS,kBAAA,YAAY,qBAAqB,OAAO;AAC1D;AAEA,SAAgB,YAAY,eAAwC;CAClE,OAAO,SAAS,kBAAA,YAAY,WAAW,iBAAiB,UAAU,UAAU;AAC9E;AAEA,SAAgB,QAAQ,YAAoB,eAAuC;CACjF,OAAO,SAAS,YAAY,aAAa;AAC3C"}
1
+ {"version":3,"file":"error-utils.js","names":[],"sources":["../src/error-utils.ts"],"sourcesContent":["import type { HttpError } from 'http-errors';\nimport createError from 'http-errors';\n\nimport { HTTP_STATUS } from './constants';\n\nexport const API_ERROR = {\n PASSWORD_SHORT: 'The provided password does not pass the validation',\n MUST_BE_LOGGED: 'You must be logged in to publish packages.',\n PLUGIN_ERROR: 'bug in the auth plugin system',\n CONFIG_BAD_FORMAT: 'config file must be an object',\n BAD_USERNAME_PASSWORD: 'bad username/password, access denied',\n NO_PACKAGE: 'no such package available',\n PACKAGE_CANNOT_BE_ADDED: 'this package cannot be added',\n BAD_DATA: 'bad data',\n NOT_ALLOWED: 'not allowed to access package',\n NOT_ALLOWED_PUBLISH: 'not allowed to publish package',\n INTERNAL_SERVER_ERROR: 'internal server error',\n UNKNOWN_ERROR: 'unknown error',\n NOT_PACKAGE_UPLINK: 'package does not exist on uplink',\n UPLINK_OFFLINE_PUBLISH: 'one of the uplinks is down, refuse to publish',\n UPLINK_OFFLINE: 'uplink is offline',\n NOT_MODIFIED_NO_DATA: 'no data',\n CONTENT_MISMATCH: 'content length mismatch',\n NOT_FILE_UPLINK: \"file doesn't exist on uplink\",\n MAX_USERS_REACHED: 'maximum amount of users reached',\n VERSION_NOT_EXIST: \"this version doesn't exist\",\n NO_SUCH_FILE: 'no such file available',\n UNSUPORTED_REGISTRY_CALL: 'unsupported registry call',\n FILE_NOT_FOUND: 'File not found',\n REGISTRATION_DISABLED: 'user registration disabled',\n UNAUTHORIZED_ACCESS: 'unauthorized access',\n BAD_STATUS_CODE: 'bad status code',\n SERVER_TIME_OUT: 'looks like the server is taking to long to respond',\n PACKAGE_EXIST: 'this package is already present',\n BAD_AUTH_HEADER: 'bad authorization header',\n WEB_DISABLED: 'Web interface is disabled in the config file',\n DEPRECATED_BASIC_HEADER: 'basic authentication is deprecated, please use JWT instead',\n BAD_FORMAT_USER_GROUP: 'user groups is different than an array',\n RESOURCE_UNAVAILABLE: 'resource unavailable',\n BAD_PACKAGE_DATA: 'bad incoming package data',\n USERNAME_PASSWORD_REQUIRED: 'username and password is required',\n USERNAME_ALREADY_REGISTERED: 'username is already registered',\n USERNAME_MISMATCH: 'username does not match logged in user',\n SESSION_ID_REQUIRED: 'session id is required',\n SESSION_ID_INVALID: 'session id is invalid',\n SESSION_TOKEN_EXPIRED: 'session token expired',\n};\n\nexport const SUPPORT_ERRORS = {\n PLUGIN_MISSING_INTERFACE: 'the plugin does not provide implementation of the requested feature',\n TFA_DISABLED: 'the two-factor authentication is not yet supported',\n STORAGE_NOT_IMPLEMENT: 'the storage does not support token saving',\n PARAMETERS_NOT_VALID: 'the parameters are not valid',\n};\n\nexport const APP_ERROR = {\n CONFIG_NOT_VALID: 'CONFIG: it does not look like a valid config file',\n PROFILE_ERROR: 'profile unexpected error',\n PASSWORD_VALIDATION: 'not valid password',\n};\n\nexport type VerdaccioError = HttpError & { code: number };\n\nfunction getError(code: number, message: string): VerdaccioError {\n const httpError = createError(code, message);\n\n httpError.code = code;\n\n return httpError as VerdaccioError;\n}\n\nexport function getConflict(message: string = API_ERROR.PACKAGE_EXIST): VerdaccioError {\n return getError(HTTP_STATUS.CONFLICT, message);\n}\n\nexport function getBadData(customMessage?: string): VerdaccioError {\n return getError(HTTP_STATUS.BAD_DATA, customMessage || API_ERROR.BAD_DATA);\n}\n\nexport function getBadRequest(customMessage: string): VerdaccioError {\n return getError(HTTP_STATUS.BAD_REQUEST, customMessage);\n}\n\nexport function getInternalError(customMessage?: string): VerdaccioError {\n return customMessage\n ? getError(HTTP_STATUS.INTERNAL_ERROR, customMessage)\n : getError(HTTP_STATUS.INTERNAL_ERROR, API_ERROR.UNKNOWN_ERROR);\n}\n\nexport function getUnauthorized(message = 'no credentials provided'): VerdaccioError {\n return getError(HTTP_STATUS.UNAUTHORIZED, message);\n}\n\nexport function getForbidden(message = \"can't use this filename\"): VerdaccioError {\n return getError(HTTP_STATUS.FORBIDDEN, message);\n}\n\nexport function getServiceUnavailable(\n message: string = API_ERROR.RESOURCE_UNAVAILABLE\n): VerdaccioError {\n return getError(HTTP_STATUS.SERVICE_UNAVAILABLE, message);\n}\n\nexport function getNotFound(customMessage?: string): VerdaccioError {\n return getError(HTTP_STATUS.NOT_FOUND, customMessage || API_ERROR.NO_PACKAGE);\n}\n\nexport function getCode(statusCode: number, customMessage: string): VerdaccioError {\n return getError(statusCode, customMessage);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAKA,IAAa,YAAY;CACvB,gBAAgB;CAChB,gBAAgB;CAChB,cAAc;CACd,mBAAmB;CACnB,uBAAuB;CACvB,YAAY;CACZ,yBAAyB;CACzB,UAAU;CACV,aAAa;CACb,qBAAqB;CACrB,uBAAuB;CACvB,eAAe;CACf,oBAAoB;CACpB,wBAAwB;CACxB,gBAAgB;CAChB,sBAAsB;CACtB,kBAAkB;CAClB,iBAAiB;CACjB,mBAAmB;CACnB,mBAAmB;CACnB,cAAc;CACd,0BAA0B;CAC1B,gBAAgB;CAChB,uBAAuB;CACvB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,eAAe;CACf,iBAAiB;CACjB,cAAc;CACd,yBAAyB;CACzB,uBAAuB;CACvB,sBAAsB;CACtB,kBAAkB;CAClB,4BAA4B;CAC5B,6BAA6B;CAC7B,mBAAmB;CACnB,qBAAqB;CACrB,oBAAoB;CACpB,uBAAuB;AACzB;AAEA,IAAa,iBAAiB;CAC5B,0BAA0B;CAC1B,cAAc;CACd,uBAAuB;CACvB,sBAAsB;AACxB;AAEA,IAAa,YAAY;CACvB,kBAAkB;CAClB,eAAe;CACf,qBAAqB;AACvB;AAIA,SAAS,SAAS,MAAc,SAAiC;CAC/D,MAAM,aAAA,GAAA,YAAA,QAAA,CAAwB,MAAM,OAAO;CAE3C,UAAU,OAAO;CAEjB,OAAO;AACT;AAEA,SAAgB,YAAY,UAAkB,UAAU,eAA+B;CACrF,OAAO,SAAS,kBAAA,YAAY,UAAU,OAAO;AAC/C;AAEA,SAAgB,WAAW,eAAwC;CACjE,OAAO,SAAS,kBAAA,YAAY,UAAU,iBAAiB,UAAU,QAAQ;AAC3E;AAEA,SAAgB,cAAc,eAAuC;CACnE,OAAO,SAAS,kBAAA,YAAY,aAAa,aAAa;AACxD;AAEA,SAAgB,iBAAiB,eAAwC;CACvE,OAAO,gBACH,SAAS,kBAAA,YAAY,gBAAgB,aAAa,IAClD,SAAS,kBAAA,YAAY,gBAAgB,UAAU,aAAa;AAClE;AAEA,SAAgB,gBAAgB,UAAU,2BAA2C;CACnF,OAAO,SAAS,kBAAA,YAAY,cAAc,OAAO;AACnD;AAEA,SAAgB,aAAa,UAAU,2BAA2C;CAChF,OAAO,SAAS,kBAAA,YAAY,WAAW,OAAO;AAChD;AAEA,SAAgB,sBACd,UAAkB,UAAU,sBACZ;CAChB,OAAO,SAAS,kBAAA,YAAY,qBAAqB,OAAO;AAC1D;AAEA,SAAgB,YAAY,eAAwC;CAClE,OAAO,SAAS,kBAAA,YAAY,WAAW,iBAAiB,UAAU,UAAU;AAC9E;AAEA,SAAgB,QAAQ,YAAoB,eAAuC;CACjF,OAAO,SAAS,YAAY,aAAa;AAC3C"}
@@ -102,6 +102,6 @@ function getCode(statusCode, customMessage) {
102
102
  return getError(statusCode, customMessage);
103
103
  }
104
104
  //#endregion
105
- export { API_ERROR, APP_ERROR, SUPPORT_ERRORS, error_utils_exports };
105
+ export { API_ERROR, APP_ERROR, SUPPORT_ERRORS, error_utils_exports, getBadData, getBadRequest, getCode, getConflict, getForbidden, getInternalError, getNotFound, getServiceUnavailable, getUnauthorized };
106
106
 
107
107
  //# sourceMappingURL=error-utils.mjs.map
@@ -91,11 +91,16 @@ function sanitizeFilename(filename) {
91
91
  }).join("/");
92
92
  }
93
93
  //#endregion
94
+ exports.Files = Files;
95
+ exports.createTempFolder = createTempFolder;
96
+ exports.createTempStorageFolder = createTempStorageFolder;
94
97
  Object.defineProperty(exports, "file_utils_exports", {
95
98
  enumerable: true,
96
99
  get: function() {
97
100
  return file_utils_exports;
98
101
  }
99
102
  });
103
+ exports.resolveSafePath = resolveSafePath;
104
+ exports.sanitizeFilename = sanitizeFilename;
100
105
 
101
106
  //# sourceMappingURL=file-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-utils.js","names":[],"sources":["../src/file-utils.ts"],"sourcesContent":["import { mkdir, mkdtemp } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport sanitize from 'sanitize-filename';\n\nexport const Files = {\n DatabaseName: '.verdaccio-db.json',\n};\n\n/**\n * Create a temporary folder.\n * @param prefix The prefix of the folder name.\n * @returns string\n */\nexport async function createTempFolder(prefix: string): Promise<string> {\n return await mkdtemp(path.join(os.tmpdir(), 'verdaccio-' + prefix + '-'));\n}\n\n/**\n * Create temporary folder for an asset.\n * @param prefix\n * @param folder name\n * @returns\n */\nexport async function createTempStorageFolder(prefix: string, folder = 'storage'): Promise<string> {\n const tempFolder = await createTempFolder(prefix);\n const storageFolder = path.join(tempFolder, folder);\n await mkdir(storageFolder);\n return storageFolder;\n}\n\n/**\n * Resolve a safe path within a base directory, preventing directory traversal attacks.\n *\n * This function provides security against path traversal by:\n * - URL decoding the input path\n * - Resolving the full absolute path\n * - Checking that the resolved path stays within the base directory\n * - Rejecting paths containing '..' that would escape the base directory\n * - Rejecting absolute paths that bypass the base directory\n *\n * @param basePath The base directory that constrains file access\n * @param requestPath The requested path from user input (may be URL-encoded)\n * @returns The resolved safe absolute path or null if the path is unsafe/invalid\n * @security Prevents directory traversal attacks by validating resolved paths\n */\nexport function resolveSafePath(basePath: string, requestPath?: string): string | null {\n try {\n if (!requestPath || requestPath === '') {\n return null;\n }\n\n const decoded = decodeURIComponent(requestPath);\n // Prevent absolute paths (should not start from '/')\n if (path.isAbsolute(decoded)) {\n return null;\n }\n\n // Resolve against the base directory without requiring the target to exist.\n const baseResolved = path.resolve(basePath);\n const reqResolved = path.resolve(baseResolved, decoded);\n\n // Normalize for Windows case-insensitive filesystem comparisons.\n const baseComparable = process.platform === 'win32' ? baseResolved.toLowerCase() : baseResolved;\n const reqComparable = process.platform === 'win32' ? reqResolved.toLowerCase() : reqResolved;\n\n // Ensure the resolved path is within basePath (subdirectory or exactly the base).\n if (reqComparable !== baseComparable && !reqComparable.startsWith(baseComparable + path.sep)) {\n return null;\n }\n\n return reqResolved;\n } catch {\n // error resolving path (e.g., path does not exist or permission denied)\n return null;\n }\n}\n\n/**\n * Sanitize a user-provided path while preserving directory separators.\n *\n * The web middleware uses this for `/-/assets/{*all}` which may include\n * subfolders (e.g. `logos/verdaccio.svg`). We sanitize each path segment\n * independently so `/` remains a real directory boundary.\n *\n * TODO: `sanitize-filename` silently rewrites segments instead of rejecting\n * them (`file\\0.txt` -> `file.txt`, `CON.svg` -> `.svg`, oversized segments\n * truncated). Not exploitable today, but surprising; prefer 404 on destructive\n * rewrite.\n * TODO: `=== '..'` check is whitespace-strict — ` ..` / `.. ` slips past it.\n * Use `path.normalize` before splitting, or `segment.trim() === '..'`.\n * TODO: largely redundant with `resolveSafePath` on POSIX; the dep mainly earns\n * its keep on Windows. Consider an inline `[<>:\"|?*\\0]` regex to drop the dep.\n *\n * @param filename The user-provided filename/path to sanitize.\n * @returns The sanitized filename/path.\n */\nexport function sanitizeFilename(filename: string): string {\n // normalize windows path separator so the result is stable across platforms\n const normalized = filename.replace(/\\\\/g, '/');\n const segments = normalized.split('/').map((segment) => {\n // Keep traversal markers intact so `resolveSafePath()` can correctly\n // reject paths escaping the base directory.\n if (segment === '.' || segment === '..') {\n return segment;\n }\n return sanitize(segment);\n });\n return segments.join('/');\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAKA,IAAa,QAAQ,EACnB,cAAc,qBAChB;;;;;;AAOA,eAAsB,iBAAiB,QAAiC;CACtE,OAAO,OAAA,GAAA,iBAAA,SAAc,UAAA,QAAK,KAAK,QAAA,QAAG,OAAO,GAAG,eAAe,SAAS,GAAG,CAAC;AAC1E;;;;;;;AAQA,eAAsB,wBAAwB,QAAgB,SAAS,WAA4B;CACjG,MAAM,aAAa,MAAM,iBAAiB,MAAM;CAChD,MAAM,gBAAgB,UAAA,QAAK,KAAK,YAAY,MAAM;CAClD,OAAA,GAAA,iBAAA,OAAY,aAAa;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,UAAkB,aAAqC;CACrF,IAAI;EACF,IAAI,CAAC,eAAe,gBAAgB,IAClC,OAAO;EAGT,MAAM,UAAU,mBAAmB,WAAW;EAE9C,IAAI,UAAA,QAAK,WAAW,OAAO,GACzB,OAAO;EAIT,MAAM,eAAe,UAAA,QAAK,QAAQ,QAAQ;EAC1C,MAAM,cAAc,UAAA,QAAK,QAAQ,cAAc,OAAO;EAGtD,MAAM,iBAAiB,QAAQ,aAAa,UAAU,aAAa,YAAY,IAAI;EACnF,MAAM,gBAAgB,QAAQ,aAAa,UAAU,YAAY,YAAY,IAAI;EAGjF,IAAI,kBAAkB,kBAAkB,CAAC,cAAc,WAAW,iBAAiB,UAAA,QAAK,GAAG,GACzF,OAAO;EAGT,OAAO;CACT,QAAQ;EAEN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,UAA0B;CAWzD,OATmB,SAAS,QAAQ,OAAO,GAC1B,EAAW,MAAM,GAAG,EAAE,KAAK,YAAY;EAGtD,IAAI,YAAY,OAAO,YAAY,MACjC,OAAO;EAET,QAAA,GAAA,kBAAA,SAAgB,OAAO;CACzB,CACO,EAAS,KAAK,GAAG;AAC1B"}
1
+ {"version":3,"file":"file-utils.js","names":[],"sources":["../src/file-utils.ts"],"sourcesContent":["import { mkdir, mkdtemp } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport sanitize from 'sanitize-filename';\n\nexport const Files = {\n DatabaseName: '.verdaccio-db.json',\n};\n\n/**\n * Create a temporary folder.\n * @param prefix The prefix of the folder name.\n * @returns string\n */\nexport async function createTempFolder(prefix: string): Promise<string> {\n return await mkdtemp(path.join(os.tmpdir(), 'verdaccio-' + prefix + '-'));\n}\n\n/**\n * Create temporary folder for an asset.\n * @param prefix\n * @param folder name\n * @returns\n */\nexport async function createTempStorageFolder(prefix: string, folder = 'storage'): Promise<string> {\n const tempFolder = await createTempFolder(prefix);\n const storageFolder = path.join(tempFolder, folder);\n await mkdir(storageFolder);\n return storageFolder;\n}\n\n/**\n * Resolve a safe path within a base directory, preventing directory traversal attacks.\n *\n * This function provides security against path traversal by:\n * - URL decoding the input path\n * - Resolving the full absolute path\n * - Checking that the resolved path stays within the base directory\n * - Rejecting paths containing '..' that would escape the base directory\n * - Rejecting absolute paths that bypass the base directory\n *\n * @param basePath The base directory that constrains file access\n * @param requestPath The requested path from user input (may be URL-encoded)\n * @returns The resolved safe absolute path or null if the path is unsafe/invalid\n * @security Prevents directory traversal attacks by validating resolved paths\n */\nexport function resolveSafePath(basePath: string, requestPath?: string): string | null {\n try {\n if (!requestPath || requestPath === '') {\n return null;\n }\n\n const decoded = decodeURIComponent(requestPath);\n // Prevent absolute paths (should not start from '/')\n if (path.isAbsolute(decoded)) {\n return null;\n }\n\n // Resolve against the base directory without requiring the target to exist.\n const baseResolved = path.resolve(basePath);\n const reqResolved = path.resolve(baseResolved, decoded);\n\n // Normalize for Windows case-insensitive filesystem comparisons.\n const baseComparable = process.platform === 'win32' ? baseResolved.toLowerCase() : baseResolved;\n const reqComparable = process.platform === 'win32' ? reqResolved.toLowerCase() : reqResolved;\n\n // Ensure the resolved path is within basePath (subdirectory or exactly the base).\n if (reqComparable !== baseComparable && !reqComparable.startsWith(baseComparable + path.sep)) {\n return null;\n }\n\n return reqResolved;\n } catch {\n // error resolving path (e.g., path does not exist or permission denied)\n return null;\n }\n}\n\n/**\n * Sanitize a user-provided path while preserving directory separators.\n *\n * The web middleware uses this for `/-/assets/{*all}` which may include\n * subfolders (e.g. `logos/verdaccio.svg`). We sanitize each path segment\n * independently so `/` remains a real directory boundary.\n *\n * TODO: `sanitize-filename` silently rewrites segments instead of rejecting\n * them (`file\\0.txt` -> `file.txt`, `CON.svg` -> `.svg`, oversized segments\n * truncated). Not exploitable today, but surprising; prefer 404 on destructive\n * rewrite.\n * TODO: `=== '..'` check is whitespace-strict — ` ..` / `.. ` slips past it.\n * Use `path.normalize` before splitting, or `segment.trim() === '..'`.\n * TODO: largely redundant with `resolveSafePath` on POSIX; the dep mainly earns\n * its keep on Windows. Consider an inline `[<>:\"|?*\\0]` regex to drop the dep.\n *\n * @param filename The user-provided filename/path to sanitize.\n * @returns The sanitized filename/path.\n */\nexport function sanitizeFilename(filename: string): string {\n // normalize windows path separator so the result is stable across platforms\n const normalized = filename.replace(/\\\\/g, '/');\n const segments = normalized.split('/').map((segment) => {\n // Keep traversal markers intact so `resolveSafePath()` can correctly\n // reject paths escaping the base directory.\n if (segment === '.' || segment === '..') {\n return segment;\n }\n return sanitize(segment);\n });\n return segments.join('/');\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAKA,IAAa,QAAQ,EACnB,cAAc,qBAChB;;;;;;AAOA,eAAsB,iBAAiB,QAAiC;CACtE,OAAO,OAAA,GAAA,iBAAA,QAAA,CAAc,UAAA,QAAK,KAAK,QAAA,QAAG,OAAO,GAAG,eAAe,SAAS,GAAG,CAAC;AAC1E;;;;;;;AAQA,eAAsB,wBAAwB,QAAgB,SAAS,WAA4B;CACjG,MAAM,aAAa,MAAM,iBAAiB,MAAM;CAChD,MAAM,gBAAgB,UAAA,QAAK,KAAK,YAAY,MAAM;CAClD,OAAA,GAAA,iBAAA,MAAA,CAAY,aAAa;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,UAAkB,aAAqC;CACrF,IAAI;EACF,IAAI,CAAC,eAAe,gBAAgB,IAClC,OAAO;EAGT,MAAM,UAAU,mBAAmB,WAAW;EAE9C,IAAI,UAAA,QAAK,WAAW,OAAO,GACzB,OAAO;EAIT,MAAM,eAAe,UAAA,QAAK,QAAQ,QAAQ;EAC1C,MAAM,cAAc,UAAA,QAAK,QAAQ,cAAc,OAAO;EAGtD,MAAM,iBAAiB,QAAQ,aAAa,UAAU,aAAa,YAAY,IAAI;EACnF,MAAM,gBAAgB,QAAQ,aAAa,UAAU,YAAY,YAAY,IAAI;EAGjF,IAAI,kBAAkB,kBAAkB,CAAC,cAAc,WAAW,iBAAiB,UAAA,QAAK,GAAG,GACzF,OAAO;EAGT,OAAO;CACT,QAAQ;EAEN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,UAA0B;CAWzD,OATmB,SAAS,QAAQ,OAAO,GAC1B,CAAA,CAAW,MAAM,GAAG,CAAC,CAAC,KAAK,YAAY;EAGtD,IAAI,YAAY,OAAO,YAAY,MACjC,OAAO;EAET,QAAA,GAAA,kBAAA,QAAA,CAAgB,OAAO;CACzB,CACO,CAAA,CAAS,KAAK,GAAG;AAC1B"}
@@ -88,6 +88,6 @@ function sanitizeFilename(filename) {
88
88
  }).join("/");
89
89
  }
90
90
  //#endregion
91
- export { file_utils_exports };
91
+ export { Files, createTempFolder, createTempStorageFolder, file_utils_exports, resolveSafePath, sanitizeFilename };
92
92
 
93
93
  //# sourceMappingURL=file-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-utils.mjs","names":[],"sources":["../src/file-utils.ts"],"sourcesContent":["import { mkdir, mkdtemp } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport sanitize from 'sanitize-filename';\n\nexport const Files = {\n DatabaseName: '.verdaccio-db.json',\n};\n\n/**\n * Create a temporary folder.\n * @param prefix The prefix of the folder name.\n * @returns string\n */\nexport async function createTempFolder(prefix: string): Promise<string> {\n return await mkdtemp(path.join(os.tmpdir(), 'verdaccio-' + prefix + '-'));\n}\n\n/**\n * Create temporary folder for an asset.\n * @param prefix\n * @param folder name\n * @returns\n */\nexport async function createTempStorageFolder(prefix: string, folder = 'storage'): Promise<string> {\n const tempFolder = await createTempFolder(prefix);\n const storageFolder = path.join(tempFolder, folder);\n await mkdir(storageFolder);\n return storageFolder;\n}\n\n/**\n * Resolve a safe path within a base directory, preventing directory traversal attacks.\n *\n * This function provides security against path traversal by:\n * - URL decoding the input path\n * - Resolving the full absolute path\n * - Checking that the resolved path stays within the base directory\n * - Rejecting paths containing '..' that would escape the base directory\n * - Rejecting absolute paths that bypass the base directory\n *\n * @param basePath The base directory that constrains file access\n * @param requestPath The requested path from user input (may be URL-encoded)\n * @returns The resolved safe absolute path or null if the path is unsafe/invalid\n * @security Prevents directory traversal attacks by validating resolved paths\n */\nexport function resolveSafePath(basePath: string, requestPath?: string): string | null {\n try {\n if (!requestPath || requestPath === '') {\n return null;\n }\n\n const decoded = decodeURIComponent(requestPath);\n // Prevent absolute paths (should not start from '/')\n if (path.isAbsolute(decoded)) {\n return null;\n }\n\n // Resolve against the base directory without requiring the target to exist.\n const baseResolved = path.resolve(basePath);\n const reqResolved = path.resolve(baseResolved, decoded);\n\n // Normalize for Windows case-insensitive filesystem comparisons.\n const baseComparable = process.platform === 'win32' ? baseResolved.toLowerCase() : baseResolved;\n const reqComparable = process.platform === 'win32' ? reqResolved.toLowerCase() : reqResolved;\n\n // Ensure the resolved path is within basePath (subdirectory or exactly the base).\n if (reqComparable !== baseComparable && !reqComparable.startsWith(baseComparable + path.sep)) {\n return null;\n }\n\n return reqResolved;\n } catch {\n // error resolving path (e.g., path does not exist or permission denied)\n return null;\n }\n}\n\n/**\n * Sanitize a user-provided path while preserving directory separators.\n *\n * The web middleware uses this for `/-/assets/{*all}` which may include\n * subfolders (e.g. `logos/verdaccio.svg`). We sanitize each path segment\n * independently so `/` remains a real directory boundary.\n *\n * TODO: `sanitize-filename` silently rewrites segments instead of rejecting\n * them (`file\\0.txt` -> `file.txt`, `CON.svg` -> `.svg`, oversized segments\n * truncated). Not exploitable today, but surprising; prefer 404 on destructive\n * rewrite.\n * TODO: `=== '..'` check is whitespace-strict — ` ..` / `.. ` slips past it.\n * Use `path.normalize` before splitting, or `segment.trim() === '..'`.\n * TODO: largely redundant with `resolveSafePath` on POSIX; the dep mainly earns\n * its keep on Windows. Consider an inline `[<>:\"|?*\\0]` regex to drop the dep.\n *\n * @param filename The user-provided filename/path to sanitize.\n * @returns The sanitized filename/path.\n */\nexport function sanitizeFilename(filename: string): string {\n // normalize windows path separator so the result is stable across platforms\n const normalized = filename.replace(/\\\\/g, '/');\n const segments = normalized.split('/').map((segment) => {\n // Keep traversal markers intact so `resolveSafePath()` can correctly\n // reject paths escaping the base directory.\n if (segment === '.' || segment === '..') {\n return segment;\n }\n return sanitize(segment);\n });\n return segments.join('/');\n}\n"],"mappings":";;;;;;;;;;;;;AAKA,IAAa,QAAQ,EACnB,cAAc,qBAChB;;;;;;AAOA,eAAsB,iBAAiB,QAAiC;CACtE,OAAO,MAAM,QAAQ,KAAK,KAAK,GAAG,OAAO,GAAG,eAAe,SAAS,GAAG,CAAC;AAC1E;;;;;;;AAQA,eAAsB,wBAAwB,QAAgB,SAAS,WAA4B;CACjG,MAAM,aAAa,MAAM,iBAAiB,MAAM;CAChD,MAAM,gBAAgB,KAAK,KAAK,YAAY,MAAM;CAClD,MAAM,MAAM,aAAa;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,UAAkB,aAAqC;CACrF,IAAI;EACF,IAAI,CAAC,eAAe,gBAAgB,IAClC,OAAO;EAGT,MAAM,UAAU,mBAAmB,WAAW;EAE9C,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO;EAIT,MAAM,eAAe,KAAK,QAAQ,QAAQ;EAC1C,MAAM,cAAc,KAAK,QAAQ,cAAc,OAAO;EAGtD,MAAM,iBAAiB,QAAQ,aAAa,UAAU,aAAa,YAAY,IAAI;EACnF,MAAM,gBAAgB,QAAQ,aAAa,UAAU,YAAY,YAAY,IAAI;EAGjF,IAAI,kBAAkB,kBAAkB,CAAC,cAAc,WAAW,iBAAiB,KAAK,GAAG,GACzF,OAAO;EAGT,OAAO;CACT,QAAQ;EAEN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,UAA0B;CAWzD,OATmB,SAAS,QAAQ,OAAO,GAC1B,EAAW,MAAM,GAAG,EAAE,KAAK,YAAY;EAGtD,IAAI,YAAY,OAAO,YAAY,MACjC,OAAO;EAET,OAAO,SAAS,OAAO;CACzB,CACO,EAAS,KAAK,GAAG;AAC1B"}
1
+ {"version":3,"file":"file-utils.mjs","names":[],"sources":["../src/file-utils.ts"],"sourcesContent":["import { mkdir, mkdtemp } from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport sanitize from 'sanitize-filename';\n\nexport const Files = {\n DatabaseName: '.verdaccio-db.json',\n};\n\n/**\n * Create a temporary folder.\n * @param prefix The prefix of the folder name.\n * @returns string\n */\nexport async function createTempFolder(prefix: string): Promise<string> {\n return await mkdtemp(path.join(os.tmpdir(), 'verdaccio-' + prefix + '-'));\n}\n\n/**\n * Create temporary folder for an asset.\n * @param prefix\n * @param folder name\n * @returns\n */\nexport async function createTempStorageFolder(prefix: string, folder = 'storage'): Promise<string> {\n const tempFolder = await createTempFolder(prefix);\n const storageFolder = path.join(tempFolder, folder);\n await mkdir(storageFolder);\n return storageFolder;\n}\n\n/**\n * Resolve a safe path within a base directory, preventing directory traversal attacks.\n *\n * This function provides security against path traversal by:\n * - URL decoding the input path\n * - Resolving the full absolute path\n * - Checking that the resolved path stays within the base directory\n * - Rejecting paths containing '..' that would escape the base directory\n * - Rejecting absolute paths that bypass the base directory\n *\n * @param basePath The base directory that constrains file access\n * @param requestPath The requested path from user input (may be URL-encoded)\n * @returns The resolved safe absolute path or null if the path is unsafe/invalid\n * @security Prevents directory traversal attacks by validating resolved paths\n */\nexport function resolveSafePath(basePath: string, requestPath?: string): string | null {\n try {\n if (!requestPath || requestPath === '') {\n return null;\n }\n\n const decoded = decodeURIComponent(requestPath);\n // Prevent absolute paths (should not start from '/')\n if (path.isAbsolute(decoded)) {\n return null;\n }\n\n // Resolve against the base directory without requiring the target to exist.\n const baseResolved = path.resolve(basePath);\n const reqResolved = path.resolve(baseResolved, decoded);\n\n // Normalize for Windows case-insensitive filesystem comparisons.\n const baseComparable = process.platform === 'win32' ? baseResolved.toLowerCase() : baseResolved;\n const reqComparable = process.platform === 'win32' ? reqResolved.toLowerCase() : reqResolved;\n\n // Ensure the resolved path is within basePath (subdirectory or exactly the base).\n if (reqComparable !== baseComparable && !reqComparable.startsWith(baseComparable + path.sep)) {\n return null;\n }\n\n return reqResolved;\n } catch {\n // error resolving path (e.g., path does not exist or permission denied)\n return null;\n }\n}\n\n/**\n * Sanitize a user-provided path while preserving directory separators.\n *\n * The web middleware uses this for `/-/assets/{*all}` which may include\n * subfolders (e.g. `logos/verdaccio.svg`). We sanitize each path segment\n * independently so `/` remains a real directory boundary.\n *\n * TODO: `sanitize-filename` silently rewrites segments instead of rejecting\n * them (`file\\0.txt` -> `file.txt`, `CON.svg` -> `.svg`, oversized segments\n * truncated). Not exploitable today, but surprising; prefer 404 on destructive\n * rewrite.\n * TODO: `=== '..'` check is whitespace-strict — ` ..` / `.. ` slips past it.\n * Use `path.normalize` before splitting, or `segment.trim() === '..'`.\n * TODO: largely redundant with `resolveSafePath` on POSIX; the dep mainly earns\n * its keep on Windows. Consider an inline `[<>:\"|?*\\0]` regex to drop the dep.\n *\n * @param filename The user-provided filename/path to sanitize.\n * @returns The sanitized filename/path.\n */\nexport function sanitizeFilename(filename: string): string {\n // normalize windows path separator so the result is stable across platforms\n const normalized = filename.replace(/\\\\/g, '/');\n const segments = normalized.split('/').map((segment) => {\n // Keep traversal markers intact so `resolveSafePath()` can correctly\n // reject paths escaping the base directory.\n if (segment === '.' || segment === '..') {\n return segment;\n }\n return sanitize(segment);\n });\n return segments.join('/');\n}\n"],"mappings":";;;;;;;;;;;;;AAKA,IAAa,QAAQ,EACnB,cAAc,qBAChB;;;;;;AAOA,eAAsB,iBAAiB,QAAiC;CACtE,OAAO,MAAM,QAAQ,KAAK,KAAK,GAAG,OAAO,GAAG,eAAe,SAAS,GAAG,CAAC;AAC1E;;;;;;;AAQA,eAAsB,wBAAwB,QAAgB,SAAS,WAA4B;CACjG,MAAM,aAAa,MAAM,iBAAiB,MAAM;CAChD,MAAM,gBAAgB,KAAK,KAAK,YAAY,MAAM;CAClD,MAAM,MAAM,aAAa;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,UAAkB,aAAqC;CACrF,IAAI;EACF,IAAI,CAAC,eAAe,gBAAgB,IAClC,OAAO;EAGT,MAAM,UAAU,mBAAmB,WAAW;EAE9C,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO;EAIT,MAAM,eAAe,KAAK,QAAQ,QAAQ;EAC1C,MAAM,cAAc,KAAK,QAAQ,cAAc,OAAO;EAGtD,MAAM,iBAAiB,QAAQ,aAAa,UAAU,aAAa,YAAY,IAAI;EACnF,MAAM,gBAAgB,QAAQ,aAAa,UAAU,YAAY,YAAY,IAAI;EAGjF,IAAI,kBAAkB,kBAAkB,CAAC,cAAc,WAAW,iBAAiB,KAAK,GAAG,GACzF,OAAO;EAGT,OAAO;CACT,QAAQ;EAEN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,iBAAiB,UAA0B;CAWzD,OATmB,SAAS,QAAQ,OAAO,GAC1B,CAAA,CAAW,MAAM,GAAG,CAAC,CAAC,KAAK,YAAY;EAGtD,IAAI,YAAY,OAAO,YAAY,MACjC,OAAO;EAET,OAAO,SAAS,OAAO;CACzB,CACO,CAAA,CAAS,KAAK,GAAG;AAC1B"}
package/build/index.d.ts CHANGED
@@ -6,6 +6,7 @@ import * as fileUtils from './file-utils';
6
6
  import * as ipUtils from './ip-utils';
7
7
  import * as pkgUtils from './pkg-utils';
8
8
  import * as pluginUtils from './plugin-utils';
9
+ import * as reqUtils from './req-utils';
9
10
  import * as searchUtils from './search-utils';
10
11
  import * as streamUtils from './stream-utils';
11
12
  import * as stringUtils from './string-utils';
@@ -15,4 +16,4 @@ import * as warningUtils from './warning-utils';
15
16
  export type { VerdaccioError } from './error-utils';
16
17
  export { API_ERROR, SUPPORT_ERRORS, APP_ERROR } from './error-utils';
17
18
  export { TOKEN_BASIC, TOKEN_BEARER, HTTP_STATUS, API_MESSAGE, HEADERS, DIST_TAGS, CHARACTER_ENCODING, HEADER_TYPE, LATEST, DEFAULT_PASSWORD_VALIDATION, DEFAULT_USER, ANONYMOUS_USER, USERS, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, HtpasswdHashAlgorithm, DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL, } from './constants';
18
- export { authUtils, cryptoUtils, fileUtils, ipUtils, pkgUtils, searchUtils, streamUtils, errorUtils, validationUtils, stringUtils, constants, pluginUtils, warningUtils, tarballUtils, };
19
+ export { authUtils, cryptoUtils, fileUtils, ipUtils, pkgUtils, searchUtils, streamUtils, errorUtils, validationUtils, stringUtils, constants, pluginUtils, warningUtils, tarballUtils, reqUtils, };
package/build/index.js CHANGED
@@ -10,6 +10,7 @@ const require_file_utils = require("./file-utils.js");
10
10
  const require_ip_utils = require("./ip-utils.js");
11
11
  const require_pkg_utils = require("./pkg-utils.js");
12
12
  const require_plugin_utils = require("./plugin-utils.js");
13
+ const require_req_utils = require("./req-utils.js");
13
14
  const require_search_utils = require("./search-utils.js");
14
15
  const require_stream_utils = require("./stream-utils.js");
15
16
  const require_string_utils = require("./string-utils.js");
@@ -88,6 +89,12 @@ Object.defineProperty(exports, "pluginUtils", {
88
89
  return require_plugin_utils.plugin_utils_exports;
89
90
  }
90
91
  });
92
+ Object.defineProperty(exports, "reqUtils", {
93
+ enumerable: true,
94
+ get: function() {
95
+ return require_req_utils.req_utils_exports;
96
+ }
97
+ });
91
98
  Object.defineProperty(exports, "searchUtils", {
92
99
  enumerable: true,
93
100
  get: function() {
package/build/index.mjs CHANGED
@@ -6,10 +6,11 @@ import { file_utils_exports } from "./file-utils.mjs";
6
6
  import { ip_utils_exports } from "./ip-utils.mjs";
7
7
  import { pkg_utils_exports } from "./pkg-utils.mjs";
8
8
  import { plugin_utils_exports } from "./plugin-utils.mjs";
9
+ import { req_utils_exports } from "./req-utils.mjs";
9
10
  import { search_utils_exports } from "./search-utils.mjs";
10
11
  import { stream_utils_exports } from "./stream-utils.mjs";
11
12
  import { string_utils_exports } from "./string-utils.mjs";
12
13
  import { tarball_utils_exports } from "./tarball-utils.mjs";
13
14
  import { validation_utils_exports } from "./validation-utils.mjs";
14
15
  import { warning_utils_exports } from "./warning-utils.mjs";
15
- export { ANONYMOUS_USER, API_ERROR, API_MESSAGE, APP_ERROR, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER, USERS, auth_utils_exports as authUtils, constants_exports as constants, crypto_utils_exports as cryptoUtils, error_utils_exports as errorUtils, file_utils_exports as fileUtils, ip_utils_exports as ipUtils, pkg_utils_exports as pkgUtils, plugin_utils_exports as pluginUtils, search_utils_exports as searchUtils, stream_utils_exports as streamUtils, string_utils_exports as stringUtils, tarball_utils_exports as tarballUtils, validation_utils_exports as validationUtils, warning_utils_exports as warningUtils };
16
+ export { ANONYMOUS_USER, API_ERROR, API_MESSAGE, APP_ERROR, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER, USERS, auth_utils_exports as authUtils, constants_exports as constants, crypto_utils_exports as cryptoUtils, error_utils_exports as errorUtils, file_utils_exports as fileUtils, ip_utils_exports as ipUtils, pkg_utils_exports as pkgUtils, plugin_utils_exports as pluginUtils, req_utils_exports as reqUtils, search_utils_exports as searchUtils, stream_utils_exports as streamUtils, string_utils_exports as stringUtils, tarball_utils_exports as tarballUtils, validation_utils_exports as validationUtils, warning_utils_exports as warningUtils };
package/build/ip-utils.js CHANGED
@@ -62,5 +62,9 @@ Object.defineProperty(exports, "ip_utils_exports", {
62
62
  return ip_utils_exports;
63
63
  }
64
64
  });
65
+ exports.isAddressAllowed = isAddressAllowed;
66
+ exports.isIPv4InCIDR = isIPv4InCIDR;
67
+ exports.normalizeAddress = normalizeAddress;
68
+ exports.parseIPv4 = parseIPv4;
65
69
 
66
70
  //# sourceMappingURL=ip-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ip-utils.js","names":[],"sources":["../src/ip-utils.ts"],"sourcesContent":["import net from 'node:net';\n\nconst IPV4_MAPPED_PREFIX = '::ffff:';\n\n/**\n * Trim an address and strip the IPv4-mapped IPv6 prefix (`::ffff:`) so that\n * mapped addresses are compared as plain IPv4.\n */\nexport function normalizeAddress(address?: string): string | undefined {\n if (!address) {\n return;\n }\n\n const trimmedAddress = address.trim();\n\n if (trimmedAddress.startsWith(IPV4_MAPPED_PREFIX)) {\n return trimmedAddress.slice(IPV4_MAPPED_PREFIX.length);\n }\n\n return trimmedAddress;\n}\n\n/**\n * Convert a dotted-quad IPv4 address into its unsigned 32-bit integer value.\n */\nexport function parseIPv4(address: string): number | undefined {\n if (net.isIP(address) !== 4) {\n return;\n }\n\n return (\n address\n .split('.')\n .map(Number)\n .reduce((accumulator, octet) => (accumulator << 8) + octet, 0) >>> 0\n );\n}\n\n/**\n * Whether an IPv4 `address` falls inside the `range`/`prefix` CIDR block.\n */\nexport function isIPv4InCIDR(address: string, range: string, prefix: number): boolean {\n const addressNumber = parseIPv4(address);\n const rangeNumber = parseIPv4(range);\n\n if (addressNumber === undefined || rangeNumber === undefined || prefix < 0 || prefix > 32) {\n return false;\n }\n\n const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;\n\n return (addressNumber & mask) === (rangeNumber & mask);\n}\n\n/**\n * Whether `address` is allowed by the provided `cidr` whitelist. An empty or\n * missing whitelist allows every address; an unparseable address is rejected.\n */\nexport function isAddressAllowed(address: string | undefined, cidr: string[] | undefined): boolean {\n if (!cidr || cidr.length === 0) {\n return true;\n }\n\n const normalizedAddress = normalizeAddress(address);\n\n if (!normalizedAddress) {\n return false;\n }\n\n return cidr.some((entry) => {\n const [range, prefixValue] = entry.split('/');\n const normalizedRange = normalizeAddress(range);\n\n if (!normalizedRange) {\n return false;\n }\n\n if (typeof prefixValue === 'undefined') {\n return normalizedAddress === normalizedRange;\n }\n\n const prefix = Number(prefixValue);\n\n if (Number.isInteger(prefix) === false) {\n return false;\n }\n\n if (net.isIP(normalizedAddress) === 4 && net.isIP(normalizedRange) === 4) {\n return isIPv4InCIDR(normalizedAddress, normalizedRange, prefix);\n }\n\n return prefix === 128 && normalizedAddress === normalizedRange;\n });\n}\n"],"mappings":";;;;;;;;;;AAEA,IAAM,qBAAqB;;;;;AAM3B,SAAgB,iBAAiB,SAAsC;CACrE,IAAI,CAAC,SACH;CAGF,MAAM,iBAAiB,QAAQ,KAAK;CAEpC,IAAI,eAAe,WAAW,kBAAkB,GAC9C,OAAO,eAAe,MAAM,CAAyB;CAGvD,OAAO;AACT;;;;AAKA,SAAgB,UAAU,SAAqC;CAC7D,IAAI,SAAA,QAAI,KAAK,OAAO,MAAM,GACxB;CAGF,OACE,QACG,MAAM,GAAG,EACT,IAAI,MAAM,EACV,QAAQ,aAAa,WAAW,eAAe,KAAK,OAAO,CAAC,MAAM;AAEzE;;;;AAKA,SAAgB,aAAa,SAAiB,OAAe,QAAyB;CACpF,MAAM,gBAAgB,UAAU,OAAO;CACvC,MAAM,cAAc,UAAU,KAAK;CAEnC,IAAI,kBAAkB,KAAA,KAAa,gBAAgB,KAAA,KAAa,SAAS,KAAK,SAAS,IACrF,OAAO;CAGT,MAAM,OAAO,WAAW,IAAI,IAAK,cAAe,KAAK,WAAa;CAElE,QAAQ,gBAAgB,WAAW,cAAc;AACnD;;;;;AAMA,SAAgB,iBAAiB,SAA6B,MAAqC;CACjG,IAAI,CAAC,QAAQ,KAAK,WAAW,GAC3B,OAAO;CAGT,MAAM,oBAAoB,iBAAiB,OAAO;CAElD,IAAI,CAAC,mBACH,OAAO;CAGT,OAAO,KAAK,MAAM,UAAU;EAC1B,MAAM,CAAC,OAAO,eAAe,MAAM,MAAM,GAAG;EAC5C,MAAM,kBAAkB,iBAAiB,KAAK;EAE9C,IAAI,CAAC,iBACH,OAAO;EAGT,IAAI,OAAO,gBAAgB,aACzB,OAAO,sBAAsB;EAG/B,MAAM,SAAS,OAAO,WAAW;EAEjC,IAAI,OAAO,UAAU,MAAM,MAAM,OAC/B,OAAO;EAGT,IAAI,SAAA,QAAI,KAAK,iBAAiB,MAAM,KAAK,SAAA,QAAI,KAAK,eAAe,MAAM,GACrE,OAAO,aAAa,mBAAmB,iBAAiB,MAAM;EAGhE,OAAO,WAAW,OAAO,sBAAsB;CACjD,CAAC;AACH"}
1
+ {"version":3,"file":"ip-utils.js","names":[],"sources":["../src/ip-utils.ts"],"sourcesContent":["import net from 'node:net';\n\nconst IPV4_MAPPED_PREFIX = '::ffff:';\n\n/**\n * Trim an address and strip the IPv4-mapped IPv6 prefix (`::ffff:`) so that\n * mapped addresses are compared as plain IPv4.\n */\nexport function normalizeAddress(address?: string): string | undefined {\n if (!address) {\n return;\n }\n\n const trimmedAddress = address.trim();\n\n if (trimmedAddress.startsWith(IPV4_MAPPED_PREFIX)) {\n return trimmedAddress.slice(IPV4_MAPPED_PREFIX.length);\n }\n\n return trimmedAddress;\n}\n\n/**\n * Convert a dotted-quad IPv4 address into its unsigned 32-bit integer value.\n */\nexport function parseIPv4(address: string): number | undefined {\n if (net.isIP(address) !== 4) {\n return;\n }\n\n return (\n address\n .split('.')\n .map(Number)\n .reduce((accumulator, octet) => (accumulator << 8) + octet, 0) >>> 0\n );\n}\n\n/**\n * Whether an IPv4 `address` falls inside the `range`/`prefix` CIDR block.\n */\nexport function isIPv4InCIDR(address: string, range: string, prefix: number): boolean {\n const addressNumber = parseIPv4(address);\n const rangeNumber = parseIPv4(range);\n\n if (addressNumber === undefined || rangeNumber === undefined || prefix < 0 || prefix > 32) {\n return false;\n }\n\n const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;\n\n return (addressNumber & mask) === (rangeNumber & mask);\n}\n\n/**\n * Whether `address` is allowed by the provided `cidr` whitelist. An empty or\n * missing whitelist allows every address; an unparseable address is rejected.\n */\nexport function isAddressAllowed(address: string | undefined, cidr: string[] | undefined): boolean {\n if (!cidr || cidr.length === 0) {\n return true;\n }\n\n const normalizedAddress = normalizeAddress(address);\n\n if (!normalizedAddress) {\n return false;\n }\n\n return cidr.some((entry) => {\n const [range, prefixValue] = entry.split('/');\n const normalizedRange = normalizeAddress(range);\n\n if (!normalizedRange) {\n return false;\n }\n\n if (typeof prefixValue === 'undefined') {\n return normalizedAddress === normalizedRange;\n }\n\n const prefix = Number(prefixValue);\n\n if (Number.isInteger(prefix) === false) {\n return false;\n }\n\n if (net.isIP(normalizedAddress) === 4 && net.isIP(normalizedRange) === 4) {\n return isIPv4InCIDR(normalizedAddress, normalizedRange, prefix);\n }\n\n return prefix === 128 && normalizedAddress === normalizedRange;\n });\n}\n"],"mappings":";;;;;;;;;;AAEA,IAAM,qBAAqB;;;;;AAM3B,SAAgB,iBAAiB,SAAsC;CACrE,IAAI,CAAC,SACH;CAGF,MAAM,iBAAiB,QAAQ,KAAK;CAEpC,IAAI,eAAe,WAAW,kBAAkB,GAC9C,OAAO,eAAe,MAAM,CAAyB;CAGvD,OAAO;AACT;;;;AAKA,SAAgB,UAAU,SAAqC;CAC7D,IAAI,SAAA,QAAI,KAAK,OAAO,MAAM,GACxB;CAGF,OACE,QACG,MAAM,GAAG,CAAC,CACV,IAAI,MAAM,CAAC,CACX,QAAQ,aAAa,WAAW,eAAe,KAAK,OAAO,CAAC,MAAM;AAEzE;;;;AAKA,SAAgB,aAAa,SAAiB,OAAe,QAAyB;CACpF,MAAM,gBAAgB,UAAU,OAAO;CACvC,MAAM,cAAc,UAAU,KAAK;CAEnC,IAAI,kBAAkB,KAAA,KAAa,gBAAgB,KAAA,KAAa,SAAS,KAAK,SAAS,IACrF,OAAO;CAGT,MAAM,OAAO,WAAW,IAAI,IAAK,cAAe,KAAK,WAAa;CAElE,QAAQ,gBAAgB,WAAW,cAAc;AACnD;;;;;AAMA,SAAgB,iBAAiB,SAA6B,MAAqC;CACjG,IAAI,CAAC,QAAQ,KAAK,WAAW,GAC3B,OAAO;CAGT,MAAM,oBAAoB,iBAAiB,OAAO;CAElD,IAAI,CAAC,mBACH,OAAO;CAGT,OAAO,KAAK,MAAM,UAAU;EAC1B,MAAM,CAAC,OAAO,eAAe,MAAM,MAAM,GAAG;EAC5C,MAAM,kBAAkB,iBAAiB,KAAK;EAE9C,IAAI,CAAC,iBACH,OAAO;EAGT,IAAI,OAAO,gBAAgB,aACzB,OAAO,sBAAsB;EAG/B,MAAM,SAAS,OAAO,WAAW;EAEjC,IAAI,OAAO,UAAU,MAAM,MAAM,OAC/B,OAAO;EAGT,IAAI,SAAA,QAAI,KAAK,iBAAiB,MAAM,KAAK,SAAA,QAAI,KAAK,eAAe,MAAM,GACrE,OAAO,aAAa,mBAAmB,iBAAiB,MAAM;EAGhE,OAAO,WAAW,OAAO,sBAAsB;CACjD,CAAC;AACH"}