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