@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.
- package/build/auth-utils.d.ts +1 -1
- package/build/auth-utils.js +5 -0
- package/build/auth-utils.js.map +1 -1
- package/build/auth-utils.mjs +1 -1
- package/build/auth-utils.mjs.map +1 -1
- package/build/constants.d.ts +6 -2
- package/build/constants.js +16 -2
- package/build/constants.js.map +1 -1
- package/build/constants.mjs +9 -3
- package/build/constants.mjs.map +1 -1
- package/build/crypto-utils.d.ts +1 -1
- package/build/crypto-utils.js +5 -0
- package/build/crypto-utils.js.map +1 -1
- package/build/crypto-utils.mjs +1 -1
- package/build/crypto-utils.mjs.map +1 -1
- package/build/error-utils.d.ts +1 -1
- package/build/error-utils.js +9 -0
- package/build/error-utils.js.map +1 -1
- package/build/error-utils.mjs +1 -1
- package/build/file-utils.js +5 -0
- package/build/file-utils.js.map +1 -1
- package/build/file-utils.mjs +1 -1
- package/build/file-utils.mjs.map +1 -1
- package/build/index.d.ts +2 -1
- package/build/index.js +7 -0
- package/build/index.mjs +2 -1
- package/build/ip-utils.js +4 -0
- package/build/ip-utils.js.map +1 -1
- package/build/ip-utils.mjs +1 -1
- package/build/ip-utils.mjs.map +1 -1
- package/build/pkg-utils.d.ts +1 -1
- package/build/pkg-utils.js +4 -0
- package/build/pkg-utils.js.map +1 -1
- package/build/pkg-utils.mjs +1 -1
- package/build/pkg-utils.mjs.map +1 -1
- package/build/plugin-utils.d.ts +4 -4
- package/build/plugin-utils.js +5 -0
- package/build/plugin-utils.mjs +1 -1
- package/build/req-utils.d.ts +8 -0
- package/build/req-utils.js +22 -0
- package/build/req-utils.js.map +1 -0
- package/build/req-utils.mjs +17 -0
- package/build/req-utils.mjs.map +1 -0
- package/build/schemes/publish-manifest.js.map +1 -1
- package/build/schemes/publish-manifest.mjs.map +1 -1
- package/build/schemes/unpublish-manifest.js.map +1 -1
- package/build/schemes/unpublish-manifest.mjs.map +1 -1
- package/build/search-utils.js +1 -0
- package/build/search-utils.mjs +1 -1
- package/build/stream-utils.d.ts +2 -1
- package/build/stream-utils.js +2 -0
- package/build/stream-utils.js.map +1 -1
- package/build/stream-utils.mjs +1 -1
- package/build/stream-utils.mjs.map +1 -1
- package/build/string-utils.js +1 -0
- package/build/string-utils.js.map +1 -1
- package/build/string-utils.mjs +1 -1
- package/build/string-utils.mjs.map +1 -1
- package/build/tarball-utils.js +3 -0
- package/build/tarball-utils.js.map +1 -1
- package/build/tarball-utils.mjs +1 -1
- package/build/tarball-utils.mjs.map +1 -1
- package/build/validation-utils.d.ts +1 -1
- package/build/validation-utils.js +9 -0
- package/build/validation-utils.js.map +1 -1
- package/build/validation-utils.mjs +1 -1
- package/build/validation-utils.mjs.map +1 -1
- package/build/warning-utils.js +2 -0
- package/build/warning-utils.mjs +1 -1
- package/package.json +4 -4
package/build/auth-utils.d.ts
CHANGED
package/build/auth-utils.js
CHANGED
|
@@ -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
|
package/build/auth-utils.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/auth-utils.mjs
CHANGED
|
@@ -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
|
package/build/auth-utils.mjs.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/constants.d.ts
CHANGED
|
@@ -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;
|
package/build/constants.js
CHANGED
|
@@ -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;
|
package/build/constants.js.map
CHANGED
|
@@ -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 /**
|
|
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"}
|
package/build/constants.mjs
CHANGED
|
@@ -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
|
package/build/constants.mjs.map
CHANGED
|
@@ -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 /**
|
|
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"}
|
package/build/crypto-utils.d.ts
CHANGED
package/build/crypto-utils.js
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/crypto-utils.mjs
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/error-utils.d.ts
CHANGED
package/build/error-utils.js
CHANGED
|
@@ -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
|
package/build/error-utils.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/error-utils.mjs
CHANGED
|
@@ -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
|
package/build/file-utils.js
CHANGED
|
@@ -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
|
package/build/file-utils.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/file-utils.mjs
CHANGED
|
@@ -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
|
package/build/file-utils.mjs.map
CHANGED
|
@@ -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,
|
|
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
|
package/build/ip-utils.js.map
CHANGED
|
@@ -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,
|
|
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"}
|