@verdaccio/middleware 9.0.0-next-9.4 → 9.0.0-next-9.6

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/README.md CHANGED
@@ -29,16 +29,16 @@ If you want to report a security vulnerability, please follow the steps which we
29
29
 
30
30
  Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio/contribute)]
31
31
 
32
- [![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)
33
- [![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)
34
- [![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)
35
- [![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)
36
- [![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)
37
- [![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)
38
- [![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)
39
- [![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)
40
- [![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
41
- [![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
32
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.png)](https://opencollective.com/verdaccio/sponsor/0/website)
33
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.png)](https://opencollective.com/verdaccio/sponsor/1/website)
34
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.png)](https://opencollective.com/verdaccio/sponsor/2/website)
35
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.png)](https://opencollective.com/verdaccio/sponsor/3/website)
36
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.png)](https://opencollective.com/verdaccio/sponsor/4/website)
37
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.png)](https://opencollective.com/verdaccio/sponsor/5/website)
38
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.png)](https://opencollective.com/verdaccio/sponsor/6/website)
39
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.png)](https://opencollective.com/verdaccio/sponsor/7/website)
40
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.png)](https://opencollective.com/verdaccio/sponsor/8/website)
41
+ [![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.png)](https://opencollective.com/verdaccio/sponsor/9/website)
42
42
 
43
43
  ## Open Collective Backers
44
44
 
package/build/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { antiLoop } from './middlewares/antiLoop';
10
10
  export { final } from './middlewares/final';
11
11
  export { allow } from './middlewares/allow';
12
12
  export { rateLimit } from './middlewares/rate-limit';
13
+ export { registerBodyParser } from './middlewares/body-parser';
13
14
  export { userAgent } from './middlewares/user-agent';
14
15
  export { webMiddleware, renderWebMiddleware, setSecurityWebHeaders } from './middlewares/web';
15
16
  export { errorReportingMiddleware, handleError } from './middlewares/error';
package/build/index.js CHANGED
@@ -13,6 +13,7 @@ const require_antiLoop = require("./middlewares/antiLoop.js");
13
13
  const require_final = require("./middlewares/final.js");
14
14
  const require_allow = require("./middlewares/allow.js");
15
15
  const require_rate_limit = require("./middlewares/rate-limit.js");
16
+ const require_body_parser = require("./middlewares/body-parser.js");
16
17
  const require_user_agent = require("./middlewares/user-agent.js");
17
18
  const require_security = require("./middlewares/web/security.js");
18
19
  const require_web_urls = require("./middlewares/web/web-urls.js");
@@ -52,6 +53,7 @@ exports.makeURLrelative = require_make_url_relative.makeURLrelative;
52
53
  exports.match = require_match.match;
53
54
  exports.media = require_media.media;
54
55
  exports.rateLimit = require_rate_limit.rateLimit;
56
+ exports.registerBodyParser = require_body_parser.registerBodyParser;
55
57
  exports.renderWebMiddleware = require_render_web.renderWebMiddleware;
56
58
  exports.setSecurityWebHeaders = require_security.setSecurityWebHeaders;
57
59
  exports.userAgent = require_user_agent.userAgent;
package/build/index.mjs CHANGED
@@ -9,6 +9,7 @@ import { antiLoop } from "./middlewares/antiLoop.mjs";
9
9
  import { final } from "./middlewares/final.mjs";
10
10
  import { allow } from "./middlewares/allow.mjs";
11
11
  import { rateLimit } from "./middlewares/rate-limit.mjs";
12
+ import { registerBodyParser } from "./middlewares/body-parser.mjs";
12
13
  import { userAgent } from "./middlewares/user-agent.mjs";
13
14
  import { setSecurityWebHeaders } from "./middlewares/web/security.mjs";
14
15
  import { WebUrls, WebUrlsNamespace } from "./middlewares/web/web-urls.mjs";
@@ -19,4 +20,4 @@ import { errorReportingMiddleware, handleError } from "./middlewares/error.mjs";
19
20
  import { getRequestOptions } from "./middlewares/request-options.mjs";
20
21
  import { LOG_STATUS_MESSAGE, LOG_VERDACCIO_BYTES, LOG_VERDACCIO_ERROR, log } from "./middlewares/log.mjs";
21
22
  import { DIST_TAGS_API_ENDPOINTS, LOGIN_API_ENDPOINTS, PACKAGE_API_ENDPOINTS, PING_API_ENDPOINTS, PROFILE_API_ENDPOINTS, PUBLISH_API_ENDPOINTS, SEARCH_API_ENDPOINTS, STARS_API_ENDPOINTS, TOKEN_API_ENDPOINTS, USER_API_ENDPOINTS } from "./middlewares/api_urls.mjs";
22
- export { DIST_TAGS_API_ENDPOINTS, LOGIN_API_ENDPOINTS, LOG_STATUS_MESSAGE, LOG_VERDACCIO_BYTES, LOG_VERDACCIO_ERROR, PACKAGE_API_ENDPOINTS, PING_API_ENDPOINTS, PROFILE_API_ENDPOINTS, PUBLISH_API_ENDPOINTS, SEARCH_API_ENDPOINTS, STARS_API_ENDPOINTS, TOKEN_API_ENDPOINTS, USER_API_ENDPOINTS, WebUrls, WebUrlsNamespace, allow, antiLoop, dotfiles, encodeScopePackage, errorReportingMiddleware, expectJson, final, getRequestOptions, handleError, log, makeURLrelative, match, media, rateLimit, renderWebMiddleware, setSecurityWebHeaders, userAgent, validateName, validatePackage, web_middleware_default as webMiddleware };
23
+ export { DIST_TAGS_API_ENDPOINTS, LOGIN_API_ENDPOINTS, LOG_STATUS_MESSAGE, LOG_VERDACCIO_BYTES, LOG_VERDACCIO_ERROR, PACKAGE_API_ENDPOINTS, PING_API_ENDPOINTS, PROFILE_API_ENDPOINTS, PUBLISH_API_ENDPOINTS, SEARCH_API_ENDPOINTS, STARS_API_ENDPOINTS, TOKEN_API_ENDPOINTS, USER_API_ENDPOINTS, WebUrls, WebUrlsNamespace, allow, antiLoop, dotfiles, encodeScopePackage, errorReportingMiddleware, expectJson, final, getRequestOptions, handleError, log, makeURLrelative, match, media, rateLimit, registerBodyParser, renderWebMiddleware, setSecurityWebHeaders, userAgent, validateName, validatePackage, web_middleware_default as webMiddleware };
@@ -0,0 +1,8 @@
1
+ import { Application, Router } from 'express';
2
+ import { Config } from '@verdaccio/types';
3
+ /**
4
+ * Register JSON body parser on a router if not already registered
5
+ * @param app Express router instance
6
+ * @param config Verdaccio config
7
+ */
8
+ export declare function registerBodyParser(app: Router | Application, config: Config): void;
@@ -0,0 +1,31 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ let debug = require("debug");
3
+ debug = require_runtime.__toESM(debug);
4
+ let express = require("express");
5
+ express = require_runtime.__toESM(express);
6
+ //#region src/middlewares/body-parser.ts
7
+ var debug$1 = (0, debug.default)("verdaccio:middleware:body-parser");
8
+ /**
9
+ * Check if a body parser is already registered on the router
10
+ */
11
+ function hasBodyParser(app) {
12
+ return (app.stack || app._router?.stack || []).some((middleware) => {
13
+ return middleware.handle?.name === "jsonParser" || middleware.name === "jsonParser";
14
+ });
15
+ }
16
+ /**
17
+ * Register JSON body parser on a router if not already registered
18
+ * @param app Express router instance
19
+ * @param config Verdaccio config
20
+ */
21
+ function registerBodyParser(app, config) {
22
+ if (hasBodyParser(app)) debug$1("json parser already registered");
23
+ else app.use(express.default.json({
24
+ strict: false,
25
+ limit: config.max_body_size || "10mb"
26
+ }));
27
+ }
28
+ //#endregion
29
+ exports.registerBodyParser = registerBodyParser;
30
+
31
+ //# sourceMappingURL=body-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-parser.js","names":[],"sources":["../../src/middlewares/body-parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Application, Router } from 'express';\nimport express from 'express';\n\nimport type { Config } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:middleware:body-parser');\n\n/**\n * Check if a body parser is already registered on the router\n */\nfunction hasBodyParser(app: Router | Application): boolean {\n // @ts-ignore - Express internals: app.stack is not part of the public API\n const stack = (app as any).stack || (app as any)._router?.stack || [];\n return stack.some((middleware: any) => {\n return middleware.handle?.name === 'jsonParser' || middleware.name === 'jsonParser';\n });\n}\n\n/**\n * Register JSON body parser on a router if not already registered\n * @param app Express router instance\n * @param config Verdaccio config\n */\nexport function registerBodyParser(app: Router | Application, config: Config): void {\n // middleware might have registered a json parser already\n if (hasBodyParser(app)) {\n debug('json parser already registered');\n } else {\n app.use(\n express.json({\n strict: false,\n limit: config.max_body_size || '10mb',\n })\n );\n }\n}\n"],"mappings":";;;;;;AAMA,IAAM,WAAA,GAAA,MAAA,SAAmB,mCAAmC;;;;AAK5D,SAAS,cAAc,KAAoC;AAGzD,SADe,IAAY,SAAU,IAAY,SAAS,SAAS,EAAE,EACxD,MAAM,eAAoB;AACrC,SAAO,WAAW,QAAQ,SAAS,gBAAgB,WAAW,SAAS;GACvE;;;;;;;AAQJ,SAAgB,mBAAmB,KAA2B,QAAsB;AAElF,KAAI,cAAc,IAAI,CACpB,SAAM,iCAAiC;KAEvC,KAAI,IACF,QAAA,QAAQ,KAAK;EACX,QAAQ;EACR,OAAO,OAAO,iBAAiB;EAChC,CAAC,CACH"}
@@ -0,0 +1,28 @@
1
+ import buildDebug from "debug";
2
+ import express from "express";
3
+ //#region src/middlewares/body-parser.ts
4
+ var debug = buildDebug("verdaccio:middleware:body-parser");
5
+ /**
6
+ * Check if a body parser is already registered on the router
7
+ */
8
+ function hasBodyParser(app) {
9
+ return (app.stack || app._router?.stack || []).some((middleware) => {
10
+ return middleware.handle?.name === "jsonParser" || middleware.name === "jsonParser";
11
+ });
12
+ }
13
+ /**
14
+ * Register JSON body parser on a router if not already registered
15
+ * @param app Express router instance
16
+ * @param config Verdaccio config
17
+ */
18
+ function registerBodyParser(app, config) {
19
+ if (hasBodyParser(app)) debug("json parser already registered");
20
+ else app.use(express.json({
21
+ strict: false,
22
+ limit: config.max_body_size || "10mb"
23
+ }));
24
+ }
25
+ //#endregion
26
+ export { registerBodyParser };
27
+
28
+ //# sourceMappingURL=body-parser.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-parser.mjs","names":[],"sources":["../../src/middlewares/body-parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Application, Router } from 'express';\nimport express from 'express';\n\nimport type { Config } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:middleware:body-parser');\n\n/**\n * Check if a body parser is already registered on the router\n */\nfunction hasBodyParser(app: Router | Application): boolean {\n // @ts-ignore - Express internals: app.stack is not part of the public API\n const stack = (app as any).stack || (app as any)._router?.stack || [];\n return stack.some((middleware: any) => {\n return middleware.handle?.name === 'jsonParser' || middleware.name === 'jsonParser';\n });\n}\n\n/**\n * Register JSON body parser on a router if not already registered\n * @param app Express router instance\n * @param config Verdaccio config\n */\nexport function registerBodyParser(app: Router | Application, config: Config): void {\n // middleware might have registered a json parser already\n if (hasBodyParser(app)) {\n debug('json parser already registered');\n } else {\n app.use(\n express.json({\n strict: false,\n limit: config.max_body_size || '10mb',\n })\n );\n }\n}\n"],"mappings":";;;AAMA,IAAM,QAAQ,WAAW,mCAAmC;;;;AAK5D,SAAS,cAAc,KAAoC;AAGzD,SADe,IAAY,SAAU,IAAY,SAAS,SAAS,EAAE,EACxD,MAAM,eAAoB;AACrC,SAAO,WAAW,QAAQ,SAAS,gBAAgB,WAAW,SAAS;GACvE;;;;;;;AAQJ,SAAgB,mBAAmB,KAA2B,QAAsB;AAElF,KAAI,cAAc,IAAI,CACpB,OAAM,iCAAiC;KAEvC,KAAI,IACF,QAAQ,KAAK;EACX,QAAQ;EACR,OAAO,OAAO,iBAAiB;EAChC,CAAC,CACH"}
@@ -1,6 +1,7 @@
1
1
  const require_runtime = require("../../_virtual/_rolldown/runtime.js");
2
2
  const require_security = require("./security.js");
3
3
  const require_renderHTML = require("./utils/renderHTML.js");
4
+ const require_ui_options = require("./utils/ui-options.js");
4
5
  const require_web_urls = require("./web-urls.js");
5
6
  let _verdaccio_core = require("@verdaccio/core");
6
7
  let debug = require("debug");
@@ -68,12 +69,19 @@ function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {
68
69
  if (config?.web?.logo) config.web.logo = logo;
69
70
  const logoDark = renderLogo(config?.web?.logoDark);
70
71
  if (config?.web?.logoDark) config.web.logoDark = logoDark;
72
+ router.get(require_web_urls.WebUrlsNamespace.static + "ui-options.js", function(req, res) {
73
+ const options = require_ui_options.getUIOptions(config, req, res);
74
+ const script = `window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(options)};`;
75
+ res.setHeader(_verdaccio_core.HEADERS.CACHE_CONTROL, _verdaccio_core.HEADERS.NO_CACHE);
76
+ res.setHeader(_verdaccio_core.HEADERS.CONTENT_TYPE, _verdaccio_core.HEADERS.JAVASCRIPT_CHARSET);
77
+ res.send(script);
78
+ });
71
79
  router.get(require_web_urls.WebUrlsNamespace.web, function(req, res) {
72
- require_renderHTML.default(config, manifest, manifestFiles, req, res);
80
+ require_renderHTML.default(config, manifest, manifestFiles, require_ui_options.getUIOptions(config, req, res), res);
73
81
  debug$1("render html section");
74
82
  });
75
83
  router.get(require_web_urls.WebUrlsNamespace.root, function(req, res) {
76
- require_renderHTML.default(config, manifest, manifestFiles, req, res);
84
+ require_renderHTML.default(config, manifest, manifestFiles, require_ui_options.getUIOptions(config, req, res), res);
77
85
  debug$1("render root");
78
86
  });
79
87
  return router;
@@ -1 +1 @@
1
- {"version":3,"file":"render-web.js","names":[],"sources":["../../../src/middlewares/web/render-web.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { HTTP_STATUS } from '@verdaccio/core';\nimport { isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { setSecurityWebHeaders } from './security';\nimport renderHTML from './utils/renderHTML';\nimport { WebUrlsNamespace } from './web-urls';\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst sendFileCallback = (next) => (err) => {\n if (!err) {\n return;\n }\n if (err.status === HTTP_STATUS.NOT_FOUND) {\n next();\n } else {\n next(err);\n }\n};\n\nexport function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {\n const { staticPath, manifest, manifestFiles } = pluginOptions;\n debug('static path %o', staticPath);\n\n /* eslint new-cap:off */\n const router = express.Router();\n if (typeof tokenMiddleware === 'function') {\n router.use(tokenMiddleware);\n }\n\n router.use(setSecurityWebHeaders);\n\n // any match within the static is routed to the file system\n router.get(\n WebUrlsNamespace.static,\n function (req: express.Request<{ all: string | string[] }>, res, next) {\n const filename = Array.isArray(req.params.all) ? req.params.all.join('/') : req.params.all;\n if (filename === 'favicon.ico' && config?.web?.favicon) {\n const file = config?.web?.favicon;\n if (isURLhasValidProtocol(file)) {\n debug('redirect to favicon %s', file);\n req.url = file;\n return next();\n }\n debug('render custom favicon %o', file);\n res.sendFile(file, sendFileCallback(next));\n return;\n }\n debug('render static file %o', filename);\n res.sendFile(filename, { root: staticPath }, sendFileCallback(next));\n }\n );\n\n function renderLogo(logo: string | undefined): string | undefined {\n // check the origin of the logo\n if (logo && !isURLhasValidProtocol(logo)) {\n // URI related to a local file\n const absoluteLocalFile = path.posix.resolve(logo);\n debug('serve local logo %s', absoluteLocalFile);\n try {\n // TODO: replace existsSync by async alternative\n if (\n fs.existsSync(absoluteLocalFile) &&\n typeof fs.accessSync(absoluteLocalFile, fs.constants.R_OK) === 'undefined'\n ) {\n // Note: `path.join` will break on Windows, because it transforms `/` to `\\`\n // Use POSIX version `path.posix.join` instead.\n logo = `/-/static/${path.basename(logo)}`;\n router.get(logo, function (_req, res, next) {\n // @ts-ignore\n debug('serve custom logo web:%s - local:%s', logo, absoluteLocalFile);\n res.sendFile(\n path.basename(absoluteLocalFile),\n { root: path.dirname(absoluteLocalFile) },\n sendFileCallback(next)\n );\n });\n debug('enabled custom logo %s', logo);\n } else {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n } catch {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n }\n return logo;\n }\n\n const logo = renderLogo(config?.web?.logo);\n if (config?.web?.logo) {\n config.web.logo = logo;\n }\n const logoDark = renderLogo(config?.web?.logoDark);\n if (config?.web?.logoDark) {\n config.web.logoDark = logoDark;\n }\n\n // Handle all web routes including security routes\n router.get(WebUrlsNamespace.web, function (req, res) {\n renderHTML(config, manifest, manifestFiles, req, res);\n debug('render html section');\n });\n\n router.get(WebUrlsNamespace.root, function (req, res) {\n renderHTML(config, manifest, manifestFiles, req, res);\n debug('render root');\n });\n\n return router;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAYA,IAAM,WAAA,GAAA,MAAA,SAAmB,uBAAuB;AAEhD,IAAM,oBAAoB,UAAU,QAAQ;AAC1C,KAAI,CAAC,IACH;AAEF,KAAI,IAAI,WAAW,gBAAA,YAAY,UAC7B,OAAM;KAEN,MAAK,IAAI;;AAIb,SAAgB,oBAAoB,QAAQ,iBAAiB,eAAe;CAC1E,MAAM,EAAE,YAAY,UAAU,kBAAkB;AAChD,SAAM,kBAAkB,WAAW;CAGnC,MAAM,SAAS,QAAA,QAAQ,QAAQ;AAC/B,KAAI,OAAO,oBAAoB,WAC7B,QAAO,IAAI,gBAAgB;AAG7B,QAAO,IAAI,iBAAA,sBAAsB;AAGjC,QAAO,IACL,iBAAA,iBAAiB,QACjB,SAAU,KAAkD,KAAK,MAAM;EACrE,MAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI,GAAG,IAAI,OAAO;AACvF,MAAI,aAAa,iBAAiB,QAAQ,KAAK,SAAS;GACtD,MAAM,OAAO,QAAQ,KAAK;AAC1B,QAAA,GAAA,eAAA,uBAA0B,KAAK,EAAE;AAC/B,YAAM,0BAA0B,KAAK;AACrC,QAAI,MAAM;AACV,WAAO,MAAM;;AAEf,WAAM,4BAA4B,KAAK;AACvC,OAAI,SAAS,MAAM,iBAAiB,KAAK,CAAC;AAC1C;;AAEF,UAAM,yBAAyB,SAAS;AACxC,MAAI,SAAS,UAAU,EAAE,MAAM,YAAY,EAAE,iBAAiB,KAAK,CAAC;GAEvE;CAED,SAAS,WAAW,MAA8C;AAEhE,MAAI,QAAQ,EAAA,GAAA,eAAA,uBAAuB,KAAK,EAAE;GAExC,MAAM,oBAAoB,UAAA,QAAK,MAAM,QAAQ,KAAK;AAClD,WAAM,uBAAuB,kBAAkB;AAC/C,OAAI;AAEF,QACE,QAAA,QAAG,WAAW,kBAAkB,IAChC,OAAO,QAAA,QAAG,WAAW,mBAAmB,QAAA,QAAG,UAAU,KAAK,KAAK,aAC/D;AAGA,YAAO,aAAa,UAAA,QAAK,SAAS,KAAK;AACvC,YAAO,IAAI,MAAM,SAAU,MAAM,KAAK,MAAM;AAE1C,cAAM,wCAAwC,MAAM,kBAAkB;AACtE,UAAI,SACF,UAAA,QAAK,SAAS,kBAAkB,EAChC,EAAE,MAAM,UAAA,QAAK,QAAQ,kBAAkB,EAAE,EACzC,iBAAiB,KAAK,CACvB;OACD;AACF,aAAM,0BAA0B,KAAK;WAChC;AACL,YAAO,KAAA;AACP,aAAM,2BAA2B,kBAAkB,oCAAoC;;WAEnF;AACN,WAAO,KAAA;AACP,YAAM,2BAA2B,kBAAkB,oCAAoC;;;AAG3F,SAAO;;CAGT,MAAM,OAAO,WAAW,QAAQ,KAAK,KAAK;AAC1C,KAAI,QAAQ,KAAK,KACf,QAAO,IAAI,OAAO;CAEpB,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;AAClD,KAAI,QAAQ,KAAK,SACf,QAAO,IAAI,WAAW;AAIxB,QAAO,IAAI,iBAAA,iBAAiB,KAAK,SAAU,KAAK,KAAK;AACnD,qBAAA,QAAW,QAAQ,UAAU,eAAe,KAAK,IAAI;AACrD,UAAM,sBAAsB;GAC5B;AAEF,QAAO,IAAI,iBAAA,iBAAiB,MAAM,SAAU,KAAK,KAAK;AACpD,qBAAA,QAAW,QAAQ,UAAU,eAAe,KAAK,IAAI;AACrD,UAAM,cAAc;GACpB;AAEF,QAAO"}
1
+ {"version":3,"file":"render-web.js","names":[],"sources":["../../../src/middlewares/web/render-web.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { HEADERS, HTTP_STATUS } from '@verdaccio/core';\nimport { isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { setSecurityWebHeaders } from './security';\nimport renderHTML from './utils/renderHTML';\nimport { getUIOptions } from './utils/ui-options';\nimport { WebUrlsNamespace } from './web-urls';\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst sendFileCallback = (next) => (err) => {\n if (!err) {\n return;\n }\n if (err.status === HTTP_STATUS.NOT_FOUND) {\n next();\n } else {\n next(err);\n }\n};\n\nexport function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {\n const { staticPath, manifest, manifestFiles } = pluginOptions;\n debug('static path %o', staticPath);\n\n /* eslint new-cap:off */\n const router = express.Router();\n if (typeof tokenMiddleware === 'function') {\n router.use(tokenMiddleware);\n }\n\n router.use(setSecurityWebHeaders);\n\n // any match within the static is routed to the file system\n router.get(\n WebUrlsNamespace.static,\n function (req: express.Request<{ all: string | string[] }>, res, next) {\n const filename = Array.isArray(req.params.all) ? req.params.all.join('/') : req.params.all;\n if (filename === 'favicon.ico' && config?.web?.favicon) {\n const file = config?.web?.favicon;\n if (isURLhasValidProtocol(file)) {\n debug('redirect to favicon %s', file);\n req.url = file;\n return next();\n }\n debug('render custom favicon %o', file);\n res.sendFile(file, sendFileCallback(next));\n return;\n }\n debug('render static file %o', filename);\n res.sendFile(filename, { root: staticPath }, sendFileCallback(next));\n }\n );\n\n function renderLogo(logo: string | undefined): string | undefined {\n // check the origin of the logo\n if (logo && !isURLhasValidProtocol(logo)) {\n // URI related to a local file\n const absoluteLocalFile = path.posix.resolve(logo);\n debug('serve local logo %s', absoluteLocalFile);\n try {\n // TODO: replace existsSync by async alternative\n if (\n fs.existsSync(absoluteLocalFile) &&\n typeof fs.accessSync(absoluteLocalFile, fs.constants.R_OK) === 'undefined'\n ) {\n // Note: `path.join` will break on Windows, because it transforms `/` to `\\`\n // Use POSIX version `path.posix.join` instead.\n logo = `/-/static/${path.basename(logo)}`;\n router.get(logo, function (_req, res, next) {\n // @ts-ignore\n debug('serve custom logo web:%s - local:%s', logo, absoluteLocalFile);\n res.sendFile(\n path.basename(absoluteLocalFile),\n { root: path.dirname(absoluteLocalFile) },\n sendFileCallback(next)\n );\n });\n debug('enabled custom logo %s', logo);\n } else {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n } catch {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n }\n return logo;\n }\n\n const logo = renderLogo(config?.web?.logo);\n if (config?.web?.logo) {\n config.web.logo = logo;\n }\n const logoDark = renderLogo(config?.web?.logoDark);\n if (config?.web?.logoDark) {\n config.web.logoDark = logoDark;\n }\n\n // Serve external script that loads UI options\n router.get(WebUrlsNamespace.static + 'ui-options.js', function (req, res) {\n const options = getUIOptions(config, req, res);\n const script = `window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(options)};`;\n res.setHeader(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JAVASCRIPT_CHARSET);\n res.send(script);\n });\n\n // Handle all web routes including security routes\n router.get(WebUrlsNamespace.web, function (req, res) {\n const options = getUIOptions(config, req, res);\n renderHTML(config, manifest, manifestFiles, options, res);\n debug('render html section');\n });\n\n router.get(WebUrlsNamespace.root, function (req, res) {\n const options = getUIOptions(config, req, res);\n renderHTML(config, manifest, manifestFiles, options, res);\n debug('render root');\n });\n\n return router;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,IAAM,WAAA,GAAA,MAAA,SAAmB,uBAAuB;AAEhD,IAAM,oBAAoB,UAAU,QAAQ;AAC1C,KAAI,CAAC,IACH;AAEF,KAAI,IAAI,WAAW,gBAAA,YAAY,UAC7B,OAAM;KAEN,MAAK,IAAI;;AAIb,SAAgB,oBAAoB,QAAQ,iBAAiB,eAAe;CAC1E,MAAM,EAAE,YAAY,UAAU,kBAAkB;AAChD,SAAM,kBAAkB,WAAW;CAGnC,MAAM,SAAS,QAAA,QAAQ,QAAQ;AAC/B,KAAI,OAAO,oBAAoB,WAC7B,QAAO,IAAI,gBAAgB;AAG7B,QAAO,IAAI,iBAAA,sBAAsB;AAGjC,QAAO,IACL,iBAAA,iBAAiB,QACjB,SAAU,KAAkD,KAAK,MAAM;EACrE,MAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI,GAAG,IAAI,OAAO;AACvF,MAAI,aAAa,iBAAiB,QAAQ,KAAK,SAAS;GACtD,MAAM,OAAO,QAAQ,KAAK;AAC1B,QAAA,GAAA,eAAA,uBAA0B,KAAK,EAAE;AAC/B,YAAM,0BAA0B,KAAK;AACrC,QAAI,MAAM;AACV,WAAO,MAAM;;AAEf,WAAM,4BAA4B,KAAK;AACvC,OAAI,SAAS,MAAM,iBAAiB,KAAK,CAAC;AAC1C;;AAEF,UAAM,yBAAyB,SAAS;AACxC,MAAI,SAAS,UAAU,EAAE,MAAM,YAAY,EAAE,iBAAiB,KAAK,CAAC;GAEvE;CAED,SAAS,WAAW,MAA8C;AAEhE,MAAI,QAAQ,EAAA,GAAA,eAAA,uBAAuB,KAAK,EAAE;GAExC,MAAM,oBAAoB,UAAA,QAAK,MAAM,QAAQ,KAAK;AAClD,WAAM,uBAAuB,kBAAkB;AAC/C,OAAI;AAEF,QACE,QAAA,QAAG,WAAW,kBAAkB,IAChC,OAAO,QAAA,QAAG,WAAW,mBAAmB,QAAA,QAAG,UAAU,KAAK,KAAK,aAC/D;AAGA,YAAO,aAAa,UAAA,QAAK,SAAS,KAAK;AACvC,YAAO,IAAI,MAAM,SAAU,MAAM,KAAK,MAAM;AAE1C,cAAM,wCAAwC,MAAM,kBAAkB;AACtE,UAAI,SACF,UAAA,QAAK,SAAS,kBAAkB,EAChC,EAAE,MAAM,UAAA,QAAK,QAAQ,kBAAkB,EAAE,EACzC,iBAAiB,KAAK,CACvB;OACD;AACF,aAAM,0BAA0B,KAAK;WAChC;AACL,YAAO,KAAA;AACP,aAAM,2BAA2B,kBAAkB,oCAAoC;;WAEnF;AACN,WAAO,KAAA;AACP,YAAM,2BAA2B,kBAAkB,oCAAoC;;;AAG3F,SAAO;;CAGT,MAAM,OAAO,WAAW,QAAQ,KAAK,KAAK;AAC1C,KAAI,QAAQ,KAAK,KACf,QAAO,IAAI,OAAO;CAEpB,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;AAClD,KAAI,QAAQ,KAAK,SACf,QAAO,IAAI,WAAW;AAIxB,QAAO,IAAI,iBAAA,iBAAiB,SAAS,iBAAiB,SAAU,KAAK,KAAK;EACxE,MAAM,UAAU,mBAAA,aAAa,QAAQ,KAAK,IAAI;EAC9C,MAAM,SAAS,0CAA0C,KAAK,UAAU,QAAQ,CAAC;AACjF,MAAI,UAAU,gBAAA,QAAQ,eAAe,gBAAA,QAAQ,SAAS;AACtD,MAAI,UAAU,gBAAA,QAAQ,cAAc,gBAAA,QAAQ,mBAAmB;AAC/D,MAAI,KAAK,OAAO;GAChB;AAGF,QAAO,IAAI,iBAAA,iBAAiB,KAAK,SAAU,KAAK,KAAK;AAEnD,qBAAA,QAAW,QAAQ,UAAU,eADb,mBAAA,aAAa,QAAQ,KAAK,IAAI,EACO,IAAI;AACzD,UAAM,sBAAsB;GAC5B;AAEF,QAAO,IAAI,iBAAA,iBAAiB,MAAM,SAAU,KAAK,KAAK;AAEpD,qBAAA,QAAW,QAAQ,UAAU,eADb,mBAAA,aAAa,QAAQ,KAAK,IAAI,EACO,IAAI;AACzD,UAAM,cAAc;GACpB;AAEF,QAAO"}
@@ -1,7 +1,8 @@
1
1
  import { setSecurityWebHeaders } from "./security.mjs";
2
2
  import renderHTML from "./utils/renderHTML.mjs";
3
+ import { getUIOptions } from "./utils/ui-options.mjs";
3
4
  import { WebUrlsNamespace } from "./web-urls.mjs";
4
- import { HTTP_STATUS } from "@verdaccio/core";
5
+ import { HEADERS, HTTP_STATUS } from "@verdaccio/core";
5
6
  import buildDebug from "debug";
6
7
  import express from "express";
7
8
  import fs from "node:fs";
@@ -63,12 +64,19 @@ function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {
63
64
  if (config?.web?.logo) config.web.logo = logo;
64
65
  const logoDark = renderLogo(config?.web?.logoDark);
65
66
  if (config?.web?.logoDark) config.web.logoDark = logoDark;
67
+ router.get(WebUrlsNamespace.static + "ui-options.js", function(req, res) {
68
+ const options = getUIOptions(config, req, res);
69
+ const script = `window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(options)};`;
70
+ res.setHeader(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);
71
+ res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JAVASCRIPT_CHARSET);
72
+ res.send(script);
73
+ });
66
74
  router.get(WebUrlsNamespace.web, function(req, res) {
67
- renderHTML(config, manifest, manifestFiles, req, res);
75
+ renderHTML(config, manifest, manifestFiles, getUIOptions(config, req, res), res);
68
76
  debug("render html section");
69
77
  });
70
78
  router.get(WebUrlsNamespace.root, function(req, res) {
71
- renderHTML(config, manifest, manifestFiles, req, res);
79
+ renderHTML(config, manifest, manifestFiles, getUIOptions(config, req, res), res);
72
80
  debug("render root");
73
81
  });
74
82
  return router;
@@ -1 +1 @@
1
- {"version":3,"file":"render-web.mjs","names":[],"sources":["../../../src/middlewares/web/render-web.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { HTTP_STATUS } from '@verdaccio/core';\nimport { isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { setSecurityWebHeaders } from './security';\nimport renderHTML from './utils/renderHTML';\nimport { WebUrlsNamespace } from './web-urls';\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst sendFileCallback = (next) => (err) => {\n if (!err) {\n return;\n }\n if (err.status === HTTP_STATUS.NOT_FOUND) {\n next();\n } else {\n next(err);\n }\n};\n\nexport function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {\n const { staticPath, manifest, manifestFiles } = pluginOptions;\n debug('static path %o', staticPath);\n\n /* eslint new-cap:off */\n const router = express.Router();\n if (typeof tokenMiddleware === 'function') {\n router.use(tokenMiddleware);\n }\n\n router.use(setSecurityWebHeaders);\n\n // any match within the static is routed to the file system\n router.get(\n WebUrlsNamespace.static,\n function (req: express.Request<{ all: string | string[] }>, res, next) {\n const filename = Array.isArray(req.params.all) ? req.params.all.join('/') : req.params.all;\n if (filename === 'favicon.ico' && config?.web?.favicon) {\n const file = config?.web?.favicon;\n if (isURLhasValidProtocol(file)) {\n debug('redirect to favicon %s', file);\n req.url = file;\n return next();\n }\n debug('render custom favicon %o', file);\n res.sendFile(file, sendFileCallback(next));\n return;\n }\n debug('render static file %o', filename);\n res.sendFile(filename, { root: staticPath }, sendFileCallback(next));\n }\n );\n\n function renderLogo(logo: string | undefined): string | undefined {\n // check the origin of the logo\n if (logo && !isURLhasValidProtocol(logo)) {\n // URI related to a local file\n const absoluteLocalFile = path.posix.resolve(logo);\n debug('serve local logo %s', absoluteLocalFile);\n try {\n // TODO: replace existsSync by async alternative\n if (\n fs.existsSync(absoluteLocalFile) &&\n typeof fs.accessSync(absoluteLocalFile, fs.constants.R_OK) === 'undefined'\n ) {\n // Note: `path.join` will break on Windows, because it transforms `/` to `\\`\n // Use POSIX version `path.posix.join` instead.\n logo = `/-/static/${path.basename(logo)}`;\n router.get(logo, function (_req, res, next) {\n // @ts-ignore\n debug('serve custom logo web:%s - local:%s', logo, absoluteLocalFile);\n res.sendFile(\n path.basename(absoluteLocalFile),\n { root: path.dirname(absoluteLocalFile) },\n sendFileCallback(next)\n );\n });\n debug('enabled custom logo %s', logo);\n } else {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n } catch {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n }\n return logo;\n }\n\n const logo = renderLogo(config?.web?.logo);\n if (config?.web?.logo) {\n config.web.logo = logo;\n }\n const logoDark = renderLogo(config?.web?.logoDark);\n if (config?.web?.logoDark) {\n config.web.logoDark = logoDark;\n }\n\n // Handle all web routes including security routes\n router.get(WebUrlsNamespace.web, function (req, res) {\n renderHTML(config, manifest, manifestFiles, req, res);\n debug('render html section');\n });\n\n router.get(WebUrlsNamespace.root, function (req, res) {\n renderHTML(config, manifest, manifestFiles, req, res);\n debug('render root');\n });\n\n return router;\n}\n"],"mappings":";;;;;;;;;;AAYA,IAAM,QAAQ,WAAW,uBAAuB;AAEhD,IAAM,oBAAoB,UAAU,QAAQ;AAC1C,KAAI,CAAC,IACH;AAEF,KAAI,IAAI,WAAW,YAAY,UAC7B,OAAM;KAEN,MAAK,IAAI;;AAIb,SAAgB,oBAAoB,QAAQ,iBAAiB,eAAe;CAC1E,MAAM,EAAE,YAAY,UAAU,kBAAkB;AAChD,OAAM,kBAAkB,WAAW;CAGnC,MAAM,SAAS,QAAQ,QAAQ;AAC/B,KAAI,OAAO,oBAAoB,WAC7B,QAAO,IAAI,gBAAgB;AAG7B,QAAO,IAAI,sBAAsB;AAGjC,QAAO,IACL,iBAAiB,QACjB,SAAU,KAAkD,KAAK,MAAM;EACrE,MAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI,GAAG,IAAI,OAAO;AACvF,MAAI,aAAa,iBAAiB,QAAQ,KAAK,SAAS;GACtD,MAAM,OAAO,QAAQ,KAAK;AAC1B,OAAI,sBAAsB,KAAK,EAAE;AAC/B,UAAM,0BAA0B,KAAK;AACrC,QAAI,MAAM;AACV,WAAO,MAAM;;AAEf,SAAM,4BAA4B,KAAK;AACvC,OAAI,SAAS,MAAM,iBAAiB,KAAK,CAAC;AAC1C;;AAEF,QAAM,yBAAyB,SAAS;AACxC,MAAI,SAAS,UAAU,EAAE,MAAM,YAAY,EAAE,iBAAiB,KAAK,CAAC;GAEvE;CAED,SAAS,WAAW,MAA8C;AAEhE,MAAI,QAAQ,CAAC,sBAAsB,KAAK,EAAE;GAExC,MAAM,oBAAoB,KAAK,MAAM,QAAQ,KAAK;AAClD,SAAM,uBAAuB,kBAAkB;AAC/C,OAAI;AAEF,QACE,GAAG,WAAW,kBAAkB,IAChC,OAAO,GAAG,WAAW,mBAAmB,GAAG,UAAU,KAAK,KAAK,aAC/D;AAGA,YAAO,aAAa,KAAK,SAAS,KAAK;AACvC,YAAO,IAAI,MAAM,SAAU,MAAM,KAAK,MAAM;AAE1C,YAAM,wCAAwC,MAAM,kBAAkB;AACtE,UAAI,SACF,KAAK,SAAS,kBAAkB,EAChC,EAAE,MAAM,KAAK,QAAQ,kBAAkB,EAAE,EACzC,iBAAiB,KAAK,CACvB;OACD;AACF,WAAM,0BAA0B,KAAK;WAChC;AACL,YAAO,KAAA;AACP,WAAM,2BAA2B,kBAAkB,oCAAoC;;WAEnF;AACN,WAAO,KAAA;AACP,UAAM,2BAA2B,kBAAkB,oCAAoC;;;AAG3F,SAAO;;CAGT,MAAM,OAAO,WAAW,QAAQ,KAAK,KAAK;AAC1C,KAAI,QAAQ,KAAK,KACf,QAAO,IAAI,OAAO;CAEpB,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;AAClD,KAAI,QAAQ,KAAK,SACf,QAAO,IAAI,WAAW;AAIxB,QAAO,IAAI,iBAAiB,KAAK,SAAU,KAAK,KAAK;AACnD,aAAW,QAAQ,UAAU,eAAe,KAAK,IAAI;AACrD,QAAM,sBAAsB;GAC5B;AAEF,QAAO,IAAI,iBAAiB,MAAM,SAAU,KAAK,KAAK;AACpD,aAAW,QAAQ,UAAU,eAAe,KAAK,IAAI;AACrD,QAAM,cAAc;GACpB;AAEF,QAAO"}
1
+ {"version":3,"file":"render-web.mjs","names":[],"sources":["../../../src/middlewares/web/render-web.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { HEADERS, HTTP_STATUS } from '@verdaccio/core';\nimport { isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { setSecurityWebHeaders } from './security';\nimport renderHTML from './utils/renderHTML';\nimport { getUIOptions } from './utils/ui-options';\nimport { WebUrlsNamespace } from './web-urls';\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst sendFileCallback = (next) => (err) => {\n if (!err) {\n return;\n }\n if (err.status === HTTP_STATUS.NOT_FOUND) {\n next();\n } else {\n next(err);\n }\n};\n\nexport function renderWebMiddleware(config, tokenMiddleware, pluginOptions) {\n const { staticPath, manifest, manifestFiles } = pluginOptions;\n debug('static path %o', staticPath);\n\n /* eslint new-cap:off */\n const router = express.Router();\n if (typeof tokenMiddleware === 'function') {\n router.use(tokenMiddleware);\n }\n\n router.use(setSecurityWebHeaders);\n\n // any match within the static is routed to the file system\n router.get(\n WebUrlsNamespace.static,\n function (req: express.Request<{ all: string | string[] }>, res, next) {\n const filename = Array.isArray(req.params.all) ? req.params.all.join('/') : req.params.all;\n if (filename === 'favicon.ico' && config?.web?.favicon) {\n const file = config?.web?.favicon;\n if (isURLhasValidProtocol(file)) {\n debug('redirect to favicon %s', file);\n req.url = file;\n return next();\n }\n debug('render custom favicon %o', file);\n res.sendFile(file, sendFileCallback(next));\n return;\n }\n debug('render static file %o', filename);\n res.sendFile(filename, { root: staticPath }, sendFileCallback(next));\n }\n );\n\n function renderLogo(logo: string | undefined): string | undefined {\n // check the origin of the logo\n if (logo && !isURLhasValidProtocol(logo)) {\n // URI related to a local file\n const absoluteLocalFile = path.posix.resolve(logo);\n debug('serve local logo %s', absoluteLocalFile);\n try {\n // TODO: replace existsSync by async alternative\n if (\n fs.existsSync(absoluteLocalFile) &&\n typeof fs.accessSync(absoluteLocalFile, fs.constants.R_OK) === 'undefined'\n ) {\n // Note: `path.join` will break on Windows, because it transforms `/` to `\\`\n // Use POSIX version `path.posix.join` instead.\n logo = `/-/static/${path.basename(logo)}`;\n router.get(logo, function (_req, res, next) {\n // @ts-ignore\n debug('serve custom logo web:%s - local:%s', logo, absoluteLocalFile);\n res.sendFile(\n path.basename(absoluteLocalFile),\n { root: path.dirname(absoluteLocalFile) },\n sendFileCallback(next)\n );\n });\n debug('enabled custom logo %s', logo);\n } else {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n } catch {\n logo = undefined;\n debug(`web logo is wrong, path ${absoluteLocalFile} does not exist or is not readable`);\n }\n }\n return logo;\n }\n\n const logo = renderLogo(config?.web?.logo);\n if (config?.web?.logo) {\n config.web.logo = logo;\n }\n const logoDark = renderLogo(config?.web?.logoDark);\n if (config?.web?.logoDark) {\n config.web.logoDark = logoDark;\n }\n\n // Serve external script that loads UI options\n router.get(WebUrlsNamespace.static + 'ui-options.js', function (req, res) {\n const options = getUIOptions(config, req, res);\n const script = `window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(options)};`;\n res.setHeader(HEADERS.CACHE_CONTROL, HEADERS.NO_CACHE);\n res.setHeader(HEADERS.CONTENT_TYPE, HEADERS.JAVASCRIPT_CHARSET);\n res.send(script);\n });\n\n // Handle all web routes including security routes\n router.get(WebUrlsNamespace.web, function (req, res) {\n const options = getUIOptions(config, req, res);\n renderHTML(config, manifest, manifestFiles, options, res);\n debug('render html section');\n });\n\n router.get(WebUrlsNamespace.root, function (req, res) {\n const options = getUIOptions(config, req, res);\n renderHTML(config, manifest, manifestFiles, options, res);\n debug('render root');\n });\n\n return router;\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,QAAQ,WAAW,uBAAuB;AAEhD,IAAM,oBAAoB,UAAU,QAAQ;AAC1C,KAAI,CAAC,IACH;AAEF,KAAI,IAAI,WAAW,YAAY,UAC7B,OAAM;KAEN,MAAK,IAAI;;AAIb,SAAgB,oBAAoB,QAAQ,iBAAiB,eAAe;CAC1E,MAAM,EAAE,YAAY,UAAU,kBAAkB;AAChD,OAAM,kBAAkB,WAAW;CAGnC,MAAM,SAAS,QAAQ,QAAQ;AAC/B,KAAI,OAAO,oBAAoB,WAC7B,QAAO,IAAI,gBAAgB;AAG7B,QAAO,IAAI,sBAAsB;AAGjC,QAAO,IACL,iBAAiB,QACjB,SAAU,KAAkD,KAAK,MAAM;EACrE,MAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI,GAAG,IAAI,OAAO;AACvF,MAAI,aAAa,iBAAiB,QAAQ,KAAK,SAAS;GACtD,MAAM,OAAO,QAAQ,KAAK;AAC1B,OAAI,sBAAsB,KAAK,EAAE;AAC/B,UAAM,0BAA0B,KAAK;AACrC,QAAI,MAAM;AACV,WAAO,MAAM;;AAEf,SAAM,4BAA4B,KAAK;AACvC,OAAI,SAAS,MAAM,iBAAiB,KAAK,CAAC;AAC1C;;AAEF,QAAM,yBAAyB,SAAS;AACxC,MAAI,SAAS,UAAU,EAAE,MAAM,YAAY,EAAE,iBAAiB,KAAK,CAAC;GAEvE;CAED,SAAS,WAAW,MAA8C;AAEhE,MAAI,QAAQ,CAAC,sBAAsB,KAAK,EAAE;GAExC,MAAM,oBAAoB,KAAK,MAAM,QAAQ,KAAK;AAClD,SAAM,uBAAuB,kBAAkB;AAC/C,OAAI;AAEF,QACE,GAAG,WAAW,kBAAkB,IAChC,OAAO,GAAG,WAAW,mBAAmB,GAAG,UAAU,KAAK,KAAK,aAC/D;AAGA,YAAO,aAAa,KAAK,SAAS,KAAK;AACvC,YAAO,IAAI,MAAM,SAAU,MAAM,KAAK,MAAM;AAE1C,YAAM,wCAAwC,MAAM,kBAAkB;AACtE,UAAI,SACF,KAAK,SAAS,kBAAkB,EAChC,EAAE,MAAM,KAAK,QAAQ,kBAAkB,EAAE,EACzC,iBAAiB,KAAK,CACvB;OACD;AACF,WAAM,0BAA0B,KAAK;WAChC;AACL,YAAO,KAAA;AACP,WAAM,2BAA2B,kBAAkB,oCAAoC;;WAEnF;AACN,WAAO,KAAA;AACP,UAAM,2BAA2B,kBAAkB,oCAAoC;;;AAG3F,SAAO;;CAGT,MAAM,OAAO,WAAW,QAAQ,KAAK,KAAK;AAC1C,KAAI,QAAQ,KAAK,KACf,QAAO,IAAI,OAAO;CAEpB,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;AAClD,KAAI,QAAQ,KAAK,SACf,QAAO,IAAI,WAAW;AAIxB,QAAO,IAAI,iBAAiB,SAAS,iBAAiB,SAAU,KAAK,KAAK;EACxE,MAAM,UAAU,aAAa,QAAQ,KAAK,IAAI;EAC9C,MAAM,SAAS,0CAA0C,KAAK,UAAU,QAAQ,CAAC;AACjF,MAAI,UAAU,QAAQ,eAAe,QAAQ,SAAS;AACtD,MAAI,UAAU,QAAQ,cAAc,QAAQ,mBAAmB;AAC/D,MAAI,KAAK,OAAO;GAChB;AAGF,QAAO,IAAI,iBAAiB,KAAK,SAAU,KAAK,KAAK;AAEnD,aAAW,QAAQ,UAAU,eADb,aAAa,QAAQ,KAAK,IAAI,EACO,IAAI;AACzD,QAAM,sBAAsB;GAC5B;AAEF,QAAO,IAAI,iBAAiB,MAAM,SAAU,KAAK,KAAK;AAEpD,aAAW,QAAQ,UAAU,eADb,aAAa,QAAQ,KAAK,IAAI,EACO,IAAI;AACzD,QAAM,cAAc;GACpB;AAEF,QAAO"}
@@ -1,7 +1,5 @@
1
1
  import { Response } from 'express';
2
- import { ConfigYaml } from '@verdaccio/types';
3
- import { RequestOptions } from '@verdaccio/url';
2
+ import { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';
4
3
  import { Manifest } from './manifest';
5
4
  import { AssetManifest } from './template';
6
- export declare function resolveLogo(logo: string | undefined, url_prefix: string | undefined, requestOptions: RequestOptions): string;
7
- export default function renderHTML(config: ConfigYaml, manifest: AssetManifest, manifestFiles: Manifest | null | undefined, requestOptions: RequestOptions, res: Response): void;
5
+ export default function renderHTML(config: ConfigYaml, manifest: AssetManifest, manifestFiles: Manifest | null | undefined, options: TemplateUIOptions, res: Response): void;
@@ -1,18 +1,10 @@
1
1
  const require_runtime = require("../../../_virtual/_rolldown/runtime.js");
2
2
  const require_template = require("./template.js");
3
- const require_web_utils = require("./web-utils.js");
4
3
  let _verdaccio_core = require("@verdaccio/core");
5
4
  let debug = require("debug");
6
5
  debug = require_runtime.__toESM(debug);
7
- let node_url = require("node:url");
8
- let _verdaccio_config = require("@verdaccio/config");
9
- let node_path = require("node:path");
10
- node_path = require_runtime.__toESM(node_path);
11
- let _verdaccio_url = require("@verdaccio/url");
12
- let lru_cache = require("lru-cache");
13
6
  //#region src/middlewares/web/utils/renderHTML.ts
14
- var DEFAULT_LANGUAGE = "es-US";
15
- var cache = new lru_cache.LRUCache({
7
+ var cache = new (require("lru-cache")).LRUCache({
16
8
  max: 500,
17
9
  ttl: 1e3 * 60 * 60
18
10
  });
@@ -22,70 +14,11 @@ var defaultManifestFiles = {
22
14
  ico: "favicon.ico",
23
15
  css: []
24
16
  };
25
- function resolveLogo(logo, url_prefix, requestOptions) {
26
- if (typeof logo !== "string") return "";
27
- if (logo && !(0, _verdaccio_url.isURLhasValidProtocol)(logo)) return `${(0, _verdaccio_url.getPublicUrl)(url_prefix, requestOptions)}-/static/${node_path.default.basename(logo)}`;
28
- else if ((0, _verdaccio_url.isURLhasValidProtocol)(logo)) return logo;
29
- else return "";
30
- }
31
- function renderHTML(config, manifest, manifestFiles, requestOptions, res) {
32
- const { url_prefix } = config;
33
- const base = (0, _verdaccio_url.getPublicUrl)(config?.url_prefix, requestOptions);
34
- const basename = node_url.URL.canParse(base) ? new node_url.URL(base).pathname : base;
35
- const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
36
- const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;
17
+ function renderHTML(config, manifest, manifestFiles, options, res) {
37
18
  const needHtmlCache = [void 0, null].includes(config?.web?.html_cache) ? true : config?.web?.html_cache;
38
- const darkMode = config?.web?.darkMode ?? false;
39
- const title = config?.web?.title ?? _verdaccio_config.WEB_TITLE;
40
- const login = require_web_utils.hasLogin(config);
41
- const scope = config?.web?.scope ?? "";
42
- const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);
43
- const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);
44
- const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);
45
- const pkgManagers = config?.web?.pkgManagers ?? [
46
- "yarn",
47
- "pnpm",
48
- "npm"
49
- ];
50
- const version = res.locals.app_version ?? "";
51
- const flags = {
52
- ...config.flags,
53
- ...config.experiments
54
- };
55
- const primaryColor = require_web_utils.validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? "#4b5e40";
56
- const { scriptsBodyAfter, metaScripts, scriptsbodyBefore, showInfo, showSettings, showThemeSwitch, showFooter, showSearch, showDownloadTarball, showRaw, showUplinks } = Object.assign({}, {
57
- scriptsBodyAfter: [],
58
- bodyBefore: [],
59
- metaScripts: []
60
- }, config?.web);
61
- let scriptsBodyBefore = config?.web?.scriptsBodyBefore;
62
- if (scriptsbodyBefore && !scriptsBodyBefore) scriptsBodyBefore = scriptsbodyBefore;
63
- const options = {
64
- showInfo,
65
- showSettings,
66
- showThemeSwitch,
67
- showFooter,
68
- showSearch,
69
- showDownloadTarball,
70
- showRaw,
71
- showUplinks,
72
- darkMode,
73
- url_prefix,
74
- basename,
75
- base,
76
- primaryColor,
77
- version,
78
- logo,
79
- logoDark,
80
- favicon,
81
- flags,
82
- login,
83
- pkgManagers,
84
- title,
85
- scope,
86
- language,
87
- hideDeprecatedVersions
88
- };
19
+ const scriptsBodyBefore = config?.web?.scriptsBodyBefore || config?.web?.scriptsbodyBefore || [];
20
+ const scriptsBodyAfter = config?.web?.scriptsBodyAfter || [];
21
+ const metaScripts = config?.web?.metaScripts || [];
89
22
  let webPage;
90
23
  const cacheKey = `template:${JSON.stringify(options)}`;
91
24
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"renderHTML.js","names":[],"sources":["../../../../src/middlewares/web/utils/renderHTML.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response } from 'express';\nimport { LRUCache } from 'lru-cache';\nimport path from 'node:path';\nimport { URL } from 'node:url';\n\nimport { WEB_TITLE } from '@verdaccio/config';\nimport { HEADERS } from '@verdaccio/core';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\nimport type { RequestOptions } from '@verdaccio/url';\nimport { getPublicUrl, isURLhasValidProtocol } from '@verdaccio/url';\n\nimport type { Manifest } from './manifest';\nimport renderTemplate from './template';\nimport type { AssetManifest } from './template';\nimport { hasLogin, validatePrimaryColor } from './web-utils';\n\nconst DEFAULT_LANGUAGE = 'es-US';\n// Cache for rendered HTML templates: max 500 entries, 1 hour TTL\nconst cache = new LRUCache({ max: 500, ttl: 1000 * 60 * 60 });\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst defaultManifestFiles: Manifest = {\n js: ['vendors.js', 'main.js'],\n ico: 'favicon.ico',\n css: [],\n};\n\nexport function resolveLogo(\n logo: string | undefined,\n url_prefix: string | undefined,\n requestOptions: RequestOptions\n) {\n if (typeof logo !== 'string') {\n return '';\n }\n const isLocalFile = logo && !isURLhasValidProtocol(logo);\n\n if (isLocalFile) {\n return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;\n } else if (isURLhasValidProtocol(logo)) {\n return logo;\n } else {\n return '';\n }\n}\n\nexport default function renderHTML(\n config: ConfigYaml,\n manifest: AssetManifest,\n manifestFiles: Manifest | null | undefined,\n requestOptions: RequestOptions,\n res: Response\n) {\n const { url_prefix } = config;\n const base = getPublicUrl(config?.url_prefix, requestOptions);\n const basename = URL.canParse(base) ? new URL(base).pathname : base;\n const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;\n const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;\n // @ts-ignore\n const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)\n ? true\n : config?.web?.html_cache;\n const darkMode = config?.web?.darkMode ?? false;\n const title = config?.web?.title ?? WEB_TITLE;\n const login = hasLogin(config);\n const scope = config?.web?.scope ?? '';\n const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);\n const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);\n const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);\n const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];\n const version = res.locals.app_version ?? '';\n const flags = {\n ...config.flags,\n // legacy from 5.x\n ...config.experiments,\n };\n const primaryColor =\n validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? '#4b5e40';\n const {\n scriptsBodyAfter,\n metaScripts,\n scriptsbodyBefore, // deprecated\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n } = Object.assign(\n {},\n {\n scriptsBodyAfter: [],\n bodyBefore: [],\n metaScripts: [],\n },\n config?.web\n );\n // Fallback\n let scriptsBodyBefore = config?.web?.scriptsBodyBefore;\n if (scriptsbodyBefore && !scriptsBodyBefore) {\n scriptsBodyBefore = scriptsbodyBefore;\n }\n const options: TemplateUIOptions = {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n darkMode,\n url_prefix,\n basename,\n base,\n primaryColor,\n version,\n logo,\n logoDark,\n favicon,\n flags,\n login,\n pkgManagers,\n title,\n scope,\n language,\n hideDeprecatedVersions,\n };\n\n let webPage;\n\n const cacheKey = `template:${JSON.stringify(options)}`;\n\n try {\n webPage = cache.get(cacheKey);\n if (!webPage) {\n webPage = renderTemplate(\n {\n manifest: manifestFiles ?? defaultManifestFiles,\n options,\n scriptsBodyAfter,\n metaScripts,\n scriptsBodyBefore,\n },\n manifest\n );\n\n if (needHtmlCache) {\n cache.set(cacheKey, webPage);\n debug('set template cache');\n }\n } else {\n debug('reuse template cache');\n }\n } catch (error: any) {\n throw new Error(`theme could not be load, stack ${error.stack}`);\n }\n res.setHeader('Content-Type', HEADERS.TEXT_HTML);\n res.send(webPage);\n debug('web rendered');\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,IAAM,mBAAmB;AAEzB,IAAM,QAAQ,IAAI,UAAA,SAAS;CAAE,KAAK;CAAK,KAAK,MAAO,KAAK;CAAI,CAAC;AAE7D,IAAM,WAAA,GAAA,MAAA,SAAmB,uBAAuB;AAEhD,IAAM,uBAAiC;CACrC,IAAI,CAAC,cAAc,UAAU;CAC7B,KAAK;CACL,KAAK,EAAE;CACR;AAED,SAAgB,YACd,MACA,YACA,gBACA;AACA,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,KAFoB,QAAQ,EAAA,GAAA,eAAA,uBAAuB,KAAK,CAGtD,QAAO,IAAA,GAAA,eAAA,cAAgB,YAAY,eAAe,CAAC,WAAW,UAAA,QAAK,SAAS,KAAK;oDAClD,KAAK,CACpC,QAAO;KAEP,QAAO;;AAIX,SAAwB,WACtB,QACA,UACA,eACA,gBACA,KACA;CACA,MAAM,EAAE,eAAe;CACvB,MAAM,QAAA,GAAA,eAAA,cAAoB,QAAQ,YAAY,eAAe;CAC7D,MAAM,WAAW,SAAA,IAAI,SAAS,KAAK,GAAG,IAAI,SAAA,IAAI,KAAK,CAAC,WAAW;CAC/D,MAAM,WAAW,QAAQ,MAAM,OAAO;CACtC,MAAM,yBAAyB,QAAQ,KAAK,0BAA0B;CAEtE,MAAM,gBAAgB,CAAC,KAAA,GAAW,KAAK,CAAC,SAAS,QAAQ,KAAK,WAAW,GACrE,OACA,QAAQ,KAAK;CACjB,MAAM,WAAW,QAAQ,KAAK,YAAY;CAC1C,MAAM,QAAQ,QAAQ,KAAK,SAAS,kBAAA;CACpC,MAAM,QAAQ,kBAAA,SAAS,OAAO;CAC9B,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,UAAU,YAAY,QAAQ,KAAK,SAAS,QAAQ,YAAY,eAAe;CACrF,MAAM,OAAO,YAAY,QAAQ,KAAK,MAAM,QAAQ,YAAY,eAAe;CAC/E,MAAM,WAAW,YAAY,QAAQ,KAAK,UAAU,QAAQ,YAAY,eAAe;CACvF,MAAM,cAAc,QAAQ,KAAK,eAAe;EAAC;EAAQ;EAAQ;EAAM;CACvE,MAAM,UAAU,IAAI,OAAO,eAAe;CAC1C,MAAM,QAAQ;EACZ,GAAG,OAAO;EAEV,GAAG,OAAO;EACX;CACD,MAAM,eACJ,kBAAA,qBAAqB,QAAQ,KAAK,iBAAiB,QAAQ,KAAK,aAAa,IAAI;CACnF,MAAM,EACJ,kBACA,aACA,mBACA,UACA,cACA,iBACA,YACA,YACA,qBACA,SACA,gBACE,OAAO,OACT,EAAE,EACF;EACE,kBAAkB,EAAE;EACpB,YAAY,EAAE;EACd,aAAa,EAAE;EAChB,EACD,QAAQ,IACT;CAED,IAAI,oBAAoB,QAAQ,KAAK;AACrC,KAAI,qBAAqB,CAAC,kBACxB,qBAAoB;CAEtB,MAAM,UAA6B;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAED,IAAI;CAEJ,MAAM,WAAW,YAAY,KAAK,UAAU,QAAQ;AAEpD,KAAI;AACF,YAAU,MAAM,IAAI,SAAS;AAC7B,MAAI,CAAC,SAAS;AACZ,aAAU,iBAAA,QACR;IACE,UAAU,iBAAiB;IAC3B;IACA;IACA;IACA;IACD,EACD,SACD;AAED,OAAI,eAAe;AACjB,UAAM,IAAI,UAAU,QAAQ;AAC5B,YAAM,qBAAqB;;QAG7B,SAAM,uBAAuB;UAExB,OAAY;AACnB,QAAM,IAAI,MAAM,kCAAkC,MAAM,QAAQ;;AAElE,KAAI,UAAU,gBAAgB,gBAAA,QAAQ,UAAU;AAChD,KAAI,KAAK,QAAQ;AACjB,SAAM,eAAe"}
1
+ {"version":3,"file":"renderHTML.js","names":[],"sources":["../../../../src/middlewares/web/utils/renderHTML.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response } from 'express';\nimport { LRUCache } from 'lru-cache';\n\nimport { HEADERS } from '@verdaccio/core';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport renderTemplate from './template';\nimport type { AssetManifest } from './template';\n\n// Cache for rendered HTML templates: max 500 entries, 1 hour TTL\nconst cache = new LRUCache({ max: 500, ttl: 1000 * 60 * 60 });\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst defaultManifestFiles: Manifest = {\n js: ['vendors.js', 'main.js'],\n ico: 'favicon.ico',\n css: [],\n};\n\nexport default function renderHTML(\n config: ConfigYaml,\n manifest: AssetManifest,\n manifestFiles: Manifest | null | undefined,\n options: TemplateUIOptions,\n res: Response\n) {\n // @ts-ignore\n const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)\n ? true\n : config?.web?.html_cache;\n\n const scriptsBodyBefore = config?.web?.scriptsBodyBefore || config?.web?.scriptsbodyBefore || [];\n const scriptsBodyAfter = config?.web?.scriptsBodyAfter || [];\n const metaScripts = config?.web?.metaScripts || [];\n\n let webPage;\n\n const cacheKey = `template:${JSON.stringify(options)}`;\n\n try {\n webPage = cache.get(cacheKey);\n if (!webPage) {\n webPage = renderTemplate(\n {\n manifest: manifestFiles ?? defaultManifestFiles,\n options,\n scriptsBodyAfter,\n metaScripts,\n scriptsBodyBefore,\n },\n manifest\n );\n\n if (needHtmlCache) {\n cache.set(cacheKey, webPage);\n debug('set template cache');\n }\n } else {\n debug('reuse template cache');\n }\n } catch (error: any) {\n throw new Error(`theme could not be load, stack ${error.stack}`);\n }\n res.setHeader('Content-Type', HEADERS.TEXT_HTML);\n res.send(webPage);\n debug('web rendered');\n}\n"],"mappings":";;;;;;AAYA,IAAM,QAAQ,2BAAI,SAAS;CAAE,KAAK;CAAK,KAAK,MAAO,KAAK;CAAI,CAAC;AAE7D,IAAM,WAAA,GAAA,MAAA,SAAmB,uBAAuB;AAEhD,IAAM,uBAAiC;CACrC,IAAI,CAAC,cAAc,UAAU;CAC7B,KAAK;CACL,KAAK,EAAE;CACR;AAED,SAAwB,WACtB,QACA,UACA,eACA,SACA,KACA;CAEA,MAAM,gBAAgB,CAAC,KAAA,GAAW,KAAK,CAAC,SAAS,QAAQ,KAAK,WAAW,GACrE,OACA,QAAQ,KAAK;CAEjB,MAAM,oBAAoB,QAAQ,KAAK,qBAAqB,QAAQ,KAAK,qBAAqB,EAAE;CAChG,MAAM,mBAAmB,QAAQ,KAAK,oBAAoB,EAAE;CAC5D,MAAM,cAAc,QAAQ,KAAK,eAAe,EAAE;CAElD,IAAI;CAEJ,MAAM,WAAW,YAAY,KAAK,UAAU,QAAQ;AAEpD,KAAI;AACF,YAAU,MAAM,IAAI,SAAS;AAC7B,MAAI,CAAC,SAAS;AACZ,aAAU,iBAAA,QACR;IACE,UAAU,iBAAiB;IAC3B;IACA;IACA;IACA;IACD,EACD,SACD;AAED,OAAI,eAAe;AACjB,UAAM,IAAI,UAAU,QAAQ;AAC5B,YAAM,qBAAqB;;QAG7B,SAAM,uBAAuB;UAExB,OAAY;AACnB,QAAM,IAAI,MAAM,kCAAkC,MAAM,QAAQ;;AAElE,KAAI,UAAU,gBAAgB,gBAAA,QAAQ,UAAU;AAChD,KAAI,KAAK,QAAQ;AACjB,SAAM,eAAe"}
@@ -1,14 +1,8 @@
1
1
  import renderTemplate from "./template.mjs";
2
- import { hasLogin, validatePrimaryColor } from "./web-utils.mjs";
3
2
  import { HEADERS } from "@verdaccio/core";
4
3
  import buildDebug from "debug";
5
- import { URL } from "node:url";
6
- import { WEB_TITLE } from "@verdaccio/config";
7
- import path from "node:path";
8
- import { getPublicUrl, isURLhasValidProtocol } from "@verdaccio/url";
9
4
  import { LRUCache } from "lru-cache";
10
5
  //#region src/middlewares/web/utils/renderHTML.ts
11
- var DEFAULT_LANGUAGE = "es-US";
12
6
  var cache = new LRUCache({
13
7
  max: 500,
14
8
  ttl: 1e3 * 60 * 60
@@ -19,70 +13,11 @@ var defaultManifestFiles = {
19
13
  ico: "favicon.ico",
20
14
  css: []
21
15
  };
22
- function resolveLogo(logo, url_prefix, requestOptions) {
23
- if (typeof logo !== "string") return "";
24
- if (logo && !isURLhasValidProtocol(logo)) return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;
25
- else if (isURLhasValidProtocol(logo)) return logo;
26
- else return "";
27
- }
28
- function renderHTML(config, manifest, manifestFiles, requestOptions, res) {
29
- const { url_prefix } = config;
30
- const base = getPublicUrl(config?.url_prefix, requestOptions);
31
- const basename = URL.canParse(base) ? new URL(base).pathname : base;
32
- const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
33
- const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;
16
+ function renderHTML(config, manifest, manifestFiles, options, res) {
34
17
  const needHtmlCache = [void 0, null].includes(config?.web?.html_cache) ? true : config?.web?.html_cache;
35
- const darkMode = config?.web?.darkMode ?? false;
36
- const title = config?.web?.title ?? WEB_TITLE;
37
- const login = hasLogin(config);
38
- const scope = config?.web?.scope ?? "";
39
- const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);
40
- const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);
41
- const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);
42
- const pkgManagers = config?.web?.pkgManagers ?? [
43
- "yarn",
44
- "pnpm",
45
- "npm"
46
- ];
47
- const version = res.locals.app_version ?? "";
48
- const flags = {
49
- ...config.flags,
50
- ...config.experiments
51
- };
52
- const primaryColor = validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? "#4b5e40";
53
- const { scriptsBodyAfter, metaScripts, scriptsbodyBefore, showInfo, showSettings, showThemeSwitch, showFooter, showSearch, showDownloadTarball, showRaw, showUplinks } = Object.assign({}, {
54
- scriptsBodyAfter: [],
55
- bodyBefore: [],
56
- metaScripts: []
57
- }, config?.web);
58
- let scriptsBodyBefore = config?.web?.scriptsBodyBefore;
59
- if (scriptsbodyBefore && !scriptsBodyBefore) scriptsBodyBefore = scriptsbodyBefore;
60
- const options = {
61
- showInfo,
62
- showSettings,
63
- showThemeSwitch,
64
- showFooter,
65
- showSearch,
66
- showDownloadTarball,
67
- showRaw,
68
- showUplinks,
69
- darkMode,
70
- url_prefix,
71
- basename,
72
- base,
73
- primaryColor,
74
- version,
75
- logo,
76
- logoDark,
77
- favicon,
78
- flags,
79
- login,
80
- pkgManagers,
81
- title,
82
- scope,
83
- language,
84
- hideDeprecatedVersions
85
- };
18
+ const scriptsBodyBefore = config?.web?.scriptsBodyBefore || config?.web?.scriptsbodyBefore || [];
19
+ const scriptsBodyAfter = config?.web?.scriptsBodyAfter || [];
20
+ const metaScripts = config?.web?.metaScripts || [];
86
21
  let webPage;
87
22
  const cacheKey = `template:${JSON.stringify(options)}`;
88
23
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"renderHTML.mjs","names":[],"sources":["../../../../src/middlewares/web/utils/renderHTML.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response } from 'express';\nimport { LRUCache } from 'lru-cache';\nimport path from 'node:path';\nimport { URL } from 'node:url';\n\nimport { WEB_TITLE } from '@verdaccio/config';\nimport { HEADERS } from '@verdaccio/core';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\nimport type { RequestOptions } from '@verdaccio/url';\nimport { getPublicUrl, isURLhasValidProtocol } from '@verdaccio/url';\n\nimport type { Manifest } from './manifest';\nimport renderTemplate from './template';\nimport type { AssetManifest } from './template';\nimport { hasLogin, validatePrimaryColor } from './web-utils';\n\nconst DEFAULT_LANGUAGE = 'es-US';\n// Cache for rendered HTML templates: max 500 entries, 1 hour TTL\nconst cache = new LRUCache({ max: 500, ttl: 1000 * 60 * 60 });\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst defaultManifestFiles: Manifest = {\n js: ['vendors.js', 'main.js'],\n ico: 'favicon.ico',\n css: [],\n};\n\nexport function resolveLogo(\n logo: string | undefined,\n url_prefix: string | undefined,\n requestOptions: RequestOptions\n) {\n if (typeof logo !== 'string') {\n return '';\n }\n const isLocalFile = logo && !isURLhasValidProtocol(logo);\n\n if (isLocalFile) {\n return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;\n } else if (isURLhasValidProtocol(logo)) {\n return logo;\n } else {\n return '';\n }\n}\n\nexport default function renderHTML(\n config: ConfigYaml,\n manifest: AssetManifest,\n manifestFiles: Manifest | null | undefined,\n requestOptions: RequestOptions,\n res: Response\n) {\n const { url_prefix } = config;\n const base = getPublicUrl(config?.url_prefix, requestOptions);\n const basename = URL.canParse(base) ? new URL(base).pathname : base;\n const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;\n const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;\n // @ts-ignore\n const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)\n ? true\n : config?.web?.html_cache;\n const darkMode = config?.web?.darkMode ?? false;\n const title = config?.web?.title ?? WEB_TITLE;\n const login = hasLogin(config);\n const scope = config?.web?.scope ?? '';\n const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);\n const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);\n const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);\n const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];\n const version = res.locals.app_version ?? '';\n const flags = {\n ...config.flags,\n // legacy from 5.x\n ...config.experiments,\n };\n const primaryColor =\n validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? '#4b5e40';\n const {\n scriptsBodyAfter,\n metaScripts,\n scriptsbodyBefore, // deprecated\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n } = Object.assign(\n {},\n {\n scriptsBodyAfter: [],\n bodyBefore: [],\n metaScripts: [],\n },\n config?.web\n );\n // Fallback\n let scriptsBodyBefore = config?.web?.scriptsBodyBefore;\n if (scriptsbodyBefore && !scriptsBodyBefore) {\n scriptsBodyBefore = scriptsbodyBefore;\n }\n const options: TemplateUIOptions = {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n darkMode,\n url_prefix,\n basename,\n base,\n primaryColor,\n version,\n logo,\n logoDark,\n favicon,\n flags,\n login,\n pkgManagers,\n title,\n scope,\n language,\n hideDeprecatedVersions,\n };\n\n let webPage;\n\n const cacheKey = `template:${JSON.stringify(options)}`;\n\n try {\n webPage = cache.get(cacheKey);\n if (!webPage) {\n webPage = renderTemplate(\n {\n manifest: manifestFiles ?? defaultManifestFiles,\n options,\n scriptsBodyAfter,\n metaScripts,\n scriptsBodyBefore,\n },\n manifest\n );\n\n if (needHtmlCache) {\n cache.set(cacheKey, webPage);\n debug('set template cache');\n }\n } else {\n debug('reuse template cache');\n }\n } catch (error: any) {\n throw new Error(`theme could not be load, stack ${error.stack}`);\n }\n res.setHeader('Content-Type', HEADERS.TEXT_HTML);\n res.send(webPage);\n debug('web rendered');\n}\n"],"mappings":";;;;;;;;;;AAiBA,IAAM,mBAAmB;AAEzB,IAAM,QAAQ,IAAI,SAAS;CAAE,KAAK;CAAK,KAAK,MAAO,KAAK;CAAI,CAAC;AAE7D,IAAM,QAAQ,WAAW,uBAAuB;AAEhD,IAAM,uBAAiC;CACrC,IAAI,CAAC,cAAc,UAAU;CAC7B,KAAK;CACL,KAAK,EAAE;CACR;AAED,SAAgB,YACd,MACA,YACA,gBACA;AACA,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,KAFoB,QAAQ,CAAC,sBAAsB,KAAK,CAGtD,QAAO,GAAG,aAAa,YAAY,eAAe,CAAC,WAAW,KAAK,SAAS,KAAK;UACxE,sBAAsB,KAAK,CACpC,QAAO;KAEP,QAAO;;AAIX,SAAwB,WACtB,QACA,UACA,eACA,gBACA,KACA;CACA,MAAM,EAAE,eAAe;CACvB,MAAM,OAAO,aAAa,QAAQ,YAAY,eAAe;CAC7D,MAAM,WAAW,IAAI,SAAS,KAAK,GAAG,IAAI,IAAI,KAAK,CAAC,WAAW;CAC/D,MAAM,WAAW,QAAQ,MAAM,OAAO;CACtC,MAAM,yBAAyB,QAAQ,KAAK,0BAA0B;CAEtE,MAAM,gBAAgB,CAAC,KAAA,GAAW,KAAK,CAAC,SAAS,QAAQ,KAAK,WAAW,GACrE,OACA,QAAQ,KAAK;CACjB,MAAM,WAAW,QAAQ,KAAK,YAAY;CAC1C,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,QAAQ,SAAS,OAAO;CAC9B,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,UAAU,YAAY,QAAQ,KAAK,SAAS,QAAQ,YAAY,eAAe;CACrF,MAAM,OAAO,YAAY,QAAQ,KAAK,MAAM,QAAQ,YAAY,eAAe;CAC/E,MAAM,WAAW,YAAY,QAAQ,KAAK,UAAU,QAAQ,YAAY,eAAe;CACvF,MAAM,cAAc,QAAQ,KAAK,eAAe;EAAC;EAAQ;EAAQ;EAAM;CACvE,MAAM,UAAU,IAAI,OAAO,eAAe;CAC1C,MAAM,QAAQ;EACZ,GAAG,OAAO;EAEV,GAAG,OAAO;EACX;CACD,MAAM,eACJ,qBAAqB,QAAQ,KAAK,iBAAiB,QAAQ,KAAK,aAAa,IAAI;CACnF,MAAM,EACJ,kBACA,aACA,mBACA,UACA,cACA,iBACA,YACA,YACA,qBACA,SACA,gBACE,OAAO,OACT,EAAE,EACF;EACE,kBAAkB,EAAE;EACpB,YAAY,EAAE;EACd,aAAa,EAAE;EAChB,EACD,QAAQ,IACT;CAED,IAAI,oBAAoB,QAAQ,KAAK;AACrC,KAAI,qBAAqB,CAAC,kBACxB,qBAAoB;CAEtB,MAAM,UAA6B;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAED,IAAI;CAEJ,MAAM,WAAW,YAAY,KAAK,UAAU,QAAQ;AAEpD,KAAI;AACF,YAAU,MAAM,IAAI,SAAS;AAC7B,MAAI,CAAC,SAAS;AACZ,aAAU,eACR;IACE,UAAU,iBAAiB;IAC3B;IACA;IACA;IACA;IACD,EACD,SACD;AAED,OAAI,eAAe;AACjB,UAAM,IAAI,UAAU,QAAQ;AAC5B,UAAM,qBAAqB;;QAG7B,OAAM,uBAAuB;UAExB,OAAY;AACnB,QAAM,IAAI,MAAM,kCAAkC,MAAM,QAAQ;;AAElE,KAAI,UAAU,gBAAgB,QAAQ,UAAU;AAChD,KAAI,KAAK,QAAQ;AACjB,OAAM,eAAe"}
1
+ {"version":3,"file":"renderHTML.mjs","names":[],"sources":["../../../../src/middlewares/web/utils/renderHTML.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { Response } from 'express';\nimport { LRUCache } from 'lru-cache';\n\nimport { HEADERS } from '@verdaccio/core';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport renderTemplate from './template';\nimport type { AssetManifest } from './template';\n\n// Cache for rendered HTML templates: max 500 entries, 1 hour TTL\nconst cache = new LRUCache({ max: 500, ttl: 1000 * 60 * 60 });\n\nconst debug = buildDebug('verdaccio:web:render');\n\nconst defaultManifestFiles: Manifest = {\n js: ['vendors.js', 'main.js'],\n ico: 'favicon.ico',\n css: [],\n};\n\nexport default function renderHTML(\n config: ConfigYaml,\n manifest: AssetManifest,\n manifestFiles: Manifest | null | undefined,\n options: TemplateUIOptions,\n res: Response\n) {\n // @ts-ignore\n const needHtmlCache = [undefined, null].includes(config?.web?.html_cache)\n ? true\n : config?.web?.html_cache;\n\n const scriptsBodyBefore = config?.web?.scriptsBodyBefore || config?.web?.scriptsbodyBefore || [];\n const scriptsBodyAfter = config?.web?.scriptsBodyAfter || [];\n const metaScripts = config?.web?.metaScripts || [];\n\n let webPage;\n\n const cacheKey = `template:${JSON.stringify(options)}`;\n\n try {\n webPage = cache.get(cacheKey);\n if (!webPage) {\n webPage = renderTemplate(\n {\n manifest: manifestFiles ?? defaultManifestFiles,\n options,\n scriptsBodyAfter,\n metaScripts,\n scriptsBodyBefore,\n },\n manifest\n );\n\n if (needHtmlCache) {\n cache.set(cacheKey, webPage);\n debug('set template cache');\n }\n } else {\n debug('reuse template cache');\n }\n } catch (error: any) {\n throw new Error(`theme could not be load, stack ${error.stack}`);\n }\n res.setHeader('Content-Type', HEADERS.TEXT_HTML);\n res.send(webPage);\n debug('web rendered');\n}\n"],"mappings":";;;;;AAYA,IAAM,QAAQ,IAAI,SAAS;CAAE,KAAK;CAAK,KAAK,MAAO,KAAK;CAAI,CAAC;AAE7D,IAAM,QAAQ,WAAW,uBAAuB;AAEhD,IAAM,uBAAiC;CACrC,IAAI,CAAC,cAAc,UAAU;CAC7B,KAAK;CACL,KAAK,EAAE;CACR;AAED,SAAwB,WACtB,QACA,UACA,eACA,SACA,KACA;CAEA,MAAM,gBAAgB,CAAC,KAAA,GAAW,KAAK,CAAC,SAAS,QAAQ,KAAK,WAAW,GACrE,OACA,QAAQ,KAAK;CAEjB,MAAM,oBAAoB,QAAQ,KAAK,qBAAqB,QAAQ,KAAK,qBAAqB,EAAE;CAChG,MAAM,mBAAmB,QAAQ,KAAK,oBAAoB,EAAE;CAC5D,MAAM,cAAc,QAAQ,KAAK,eAAe,EAAE;CAElD,IAAI;CAEJ,MAAM,WAAW,YAAY,KAAK,UAAU,QAAQ;AAEpD,KAAI;AACF,YAAU,MAAM,IAAI,SAAS;AAC7B,MAAI,CAAC,SAAS;AACZ,aAAU,eACR;IACE,UAAU,iBAAiB;IAC3B;IACA;IACA;IACA;IACD,EACD,SACD;AAED,OAAI,eAAe;AACjB,UAAM,IAAI,UAAU,QAAQ;AAC5B,UAAM,qBAAqB;;QAG7B,OAAM,uBAAuB;UAExB,OAAY;AACnB,QAAM,IAAI,MAAM,kCAAkC,MAAM,QAAQ;;AAElE,KAAI,UAAU,gBAAgB,QAAQ,UAAU;AAChD,KAAI,KAAK,QAAQ;AACjB,OAAM,eAAe"}
@@ -16,9 +16,7 @@ function renderTemplate(template, manifest) {
16
16
  <title>${template?.options?.title ?? ""}</title>
17
17
  <link rel="icon" href="${template?.options.base}-/static/favicon.ico">
18
18
  <meta name="viewport" content="width=device-width, initial-scale=1">
19
- <script>
20
- window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(template.options)}
21
- <\/script>
19
+ <script src="${template?.options.base}-/static/ui-options.js"><\/script>
22
20
  ${template.manifest.css?.length ? require_manifest.getManifestValue(template.manifest.css, manifest, template?.options.base).map((item) => `<link rel="stylesheet" href="${item}">`).join("\n ") : ""}
23
21
  ${template?.metaScripts ? template.metaScripts.join("") : ""}
24
22
  </head>
@@ -1 +1 @@
1
- {"version":3,"file":"template.js","names":[],"sources":["../../../../src/middlewares/web/utils/template.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport { getManifestValue } from './manifest';\n\nconst debug = buildDebug('verdaccio:web:render:template');\n\nexport type Template = {\n manifest: Manifest;\n options: TemplateUIOptions;\n metaScripts?: string[];\n scriptsBodyAfter?: string[];\n scriptsBodyBefore?: string[];\n};\n\nexport interface AssetManifest {\n [key: string]: string;\n}\n\nexport default function renderTemplate(template: Template, manifest: AssetManifest) {\n debug('template %o', template);\n debug('manifest %o', manifest);\n\n return `\n <!DOCTYPE html>\n <html lang=\"en-us\">\n <head>\n <meta charset=\"utf-8\">\n <base href=\"${template?.options.base}\">\n <title>${template?.options?.title ?? ''}</title>\n <link rel=\"icon\" href=\"${template?.options.base}-/static/favicon.ico\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script>\n window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(template.options)}\n </script>\n ${\n template.manifest.css?.length\n ? getManifestValue(template.manifest.css, manifest, template?.options.base)\n .map((item) => `<link rel=\"stylesheet\" href=\"${item}\">`)\n .join('\\n ')\n : ''\n }\n ${template?.metaScripts ? template.metaScripts.join('') : ''}\n </head>\n <body class=\"body\">\n ${template?.scriptsBodyBefore ? template.scriptsBodyBefore.join('') : ''}\n <div id=\"root\"></div>\n ${getManifestValue(template.manifest.js, manifest, template?.options.base)\n .map((item) => `<script type=\"module\" src=\"${item}\"></script>`)\n .join(`\\n `)}\n ${template?.scriptsBodyAfter ? template.scriptsBodyAfter.join('') : ''}\n </body>\n </html>\n `;\n}\n"],"mappings":";;;;;AAOA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AAczD,SAAwB,eAAe,UAAoB,UAAyB;AAClF,SAAM,eAAe,SAAS;AAC9B,SAAM,eAAe,SAAS;AAE9B,QAAO;;;;;sBAKa,UAAU,QAAQ,KAAK;iBAC5B,UAAU,SAAS,SAAS,GAAG;iCACf,UAAU,QAAQ,KAAK;;;qDAGH,KAAK,UAAU,SAAS,QAAQ,CAAC;;UAG5E,SAAS,SAAS,KAAK,SACnB,iBAAA,iBAAiB,SAAS,SAAS,KAAK,UAAU,UAAU,QAAQ,KAAK,CACtE,KAAK,SAAS,gCAAgC,KAAK,IAAI,CACvD,KAAK,aAAa,GACrB,GACL;UACC,UAAU,cAAc,SAAS,YAAY,KAAK,GAAG,GAAG,GAAG;;;UAG3D,UAAU,oBAAoB,SAAS,kBAAkB,KAAK,GAAG,GAAG,GAAG;;UAEvE,iBAAA,iBAAiB,SAAS,SAAS,IAAI,UAAU,UAAU,QAAQ,KAAK,CACvE,KAAK,SAAS,8BAA8B,KAAK,cAAa,CAC9D,KAAK,aAAa,CAAC;UACpB,UAAU,mBAAmB,SAAS,iBAAiB,KAAK,GAAG,GAAG,GAAG"}
1
+ {"version":3,"file":"template.js","names":[],"sources":["../../../../src/middlewares/web/utils/template.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport { getManifestValue } from './manifest';\n\nconst debug = buildDebug('verdaccio:web:render:template');\n\nexport type Template = {\n manifest: Manifest;\n options: TemplateUIOptions;\n metaScripts?: string[];\n scriptsBodyAfter?: string[];\n scriptsBodyBefore?: string[];\n};\n\nexport interface AssetManifest {\n [key: string]: string;\n}\n\nexport default function renderTemplate(template: Template, manifest: AssetManifest) {\n debug('template %o', template);\n debug('manifest %o', manifest);\n\n return `\n <!DOCTYPE html>\n <html lang=\"en-us\">\n <head>\n <meta charset=\"utf-8\">\n <base href=\"${template?.options.base}\">\n <title>${template?.options?.title ?? ''}</title>\n <link rel=\"icon\" href=\"${template?.options.base}-/static/favicon.ico\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script src=\"${template?.options.base}-/static/ui-options.js\"></script>\n ${\n template.manifest.css?.length\n ? getManifestValue(template.manifest.css, manifest, template?.options.base)\n .map((item) => `<link rel=\"stylesheet\" href=\"${item}\">`)\n .join('\\n ')\n : ''\n }\n ${template?.metaScripts ? template.metaScripts.join('') : ''}\n </head>\n <body class=\"body\">\n ${template?.scriptsBodyBefore ? template.scriptsBodyBefore.join('') : ''}\n <div id=\"root\"></div>\n ${getManifestValue(template.manifest.js, manifest, template?.options.base)\n .map((item) => `<script type=\"module\" src=\"${item}\"></script>`)\n .join(`\\n `)}\n ${template?.scriptsBodyAfter ? template.scriptsBodyAfter.join('') : ''}\n </body>\n </html>\n `;\n}\n"],"mappings":";;;;;AAOA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AAczD,SAAwB,eAAe,UAAoB,UAAyB;AAClF,SAAM,eAAe,SAAS;AAC9B,SAAM,eAAe,SAAS;AAE9B,QAAO;;;;;sBAKa,UAAU,QAAQ,KAAK;iBAC5B,UAAU,SAAS,SAAS,GAAG;iCACf,UAAU,QAAQ,KAAK;;uBAEjC,UAAU,QAAQ,KAAK;UAEpC,SAAS,SAAS,KAAK,SACnB,iBAAA,iBAAiB,SAAS,SAAS,KAAK,UAAU,UAAU,QAAQ,KAAK,CACtE,KAAK,SAAS,gCAAgC,KAAK,IAAI,CACvD,KAAK,aAAa,GACrB,GACL;UACC,UAAU,cAAc,SAAS,YAAY,KAAK,GAAG,GAAG,GAAG;;;UAG3D,UAAU,oBAAoB,SAAS,kBAAkB,KAAK,GAAG,GAAG,GAAG;;UAEvE,iBAAA,iBAAiB,SAAS,SAAS,IAAI,UAAU,UAAU,QAAQ,KAAK,CACvE,KAAK,SAAS,8BAA8B,KAAK,cAAa,CAC9D,KAAK,aAAa,CAAC;UACpB,UAAU,mBAAmB,SAAS,iBAAiB,KAAK,GAAG,GAAG,GAAG"}
@@ -14,9 +14,7 @@ function renderTemplate(template, manifest) {
14
14
  <title>${template?.options?.title ?? ""}</title>
15
15
  <link rel="icon" href="${template?.options.base}-/static/favicon.ico">
16
16
  <meta name="viewport" content="width=device-width, initial-scale=1">
17
- <script>
18
- window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(template.options)}
19
- <\/script>
17
+ <script src="${template?.options.base}-/static/ui-options.js"><\/script>
20
18
  ${template.manifest.css?.length ? getManifestValue(template.manifest.css, manifest, template?.options.base).map((item) => `<link rel="stylesheet" href="${item}">`).join("\n ") : ""}
21
19
  ${template?.metaScripts ? template.metaScripts.join("") : ""}
22
20
  </head>
@@ -1 +1 @@
1
- {"version":3,"file":"template.mjs","names":[],"sources":["../../../../src/middlewares/web/utils/template.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport { getManifestValue } from './manifest';\n\nconst debug = buildDebug('verdaccio:web:render:template');\n\nexport type Template = {\n manifest: Manifest;\n options: TemplateUIOptions;\n metaScripts?: string[];\n scriptsBodyAfter?: string[];\n scriptsBodyBefore?: string[];\n};\n\nexport interface AssetManifest {\n [key: string]: string;\n}\n\nexport default function renderTemplate(template: Template, manifest: AssetManifest) {\n debug('template %o', template);\n debug('manifest %o', manifest);\n\n return `\n <!DOCTYPE html>\n <html lang=\"en-us\">\n <head>\n <meta charset=\"utf-8\">\n <base href=\"${template?.options.base}\">\n <title>${template?.options?.title ?? ''}</title>\n <link rel=\"icon\" href=\"${template?.options.base}-/static/favicon.ico\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script>\n window.__VERDACCIO_BASENAME_UI_OPTIONS=${JSON.stringify(template.options)}\n </script>\n ${\n template.manifest.css?.length\n ? getManifestValue(template.manifest.css, manifest, template?.options.base)\n .map((item) => `<link rel=\"stylesheet\" href=\"${item}\">`)\n .join('\\n ')\n : ''\n }\n ${template?.metaScripts ? template.metaScripts.join('') : ''}\n </head>\n <body class=\"body\">\n ${template?.scriptsBodyBefore ? template.scriptsBodyBefore.join('') : ''}\n <div id=\"root\"></div>\n ${getManifestValue(template.manifest.js, manifest, template?.options.base)\n .map((item) => `<script type=\"module\" src=\"${item}\"></script>`)\n .join(`\\n `)}\n ${template?.scriptsBodyAfter ? template.scriptsBodyAfter.join('') : ''}\n </body>\n </html>\n `;\n}\n"],"mappings":";;;AAOA,IAAM,QAAQ,WAAW,gCAAgC;AAczD,SAAwB,eAAe,UAAoB,UAAyB;AAClF,OAAM,eAAe,SAAS;AAC9B,OAAM,eAAe,SAAS;AAE9B,QAAO;;;;;sBAKa,UAAU,QAAQ,KAAK;iBAC5B,UAAU,SAAS,SAAS,GAAG;iCACf,UAAU,QAAQ,KAAK;;;qDAGH,KAAK,UAAU,SAAS,QAAQ,CAAC;;UAG5E,SAAS,SAAS,KAAK,SACnB,iBAAiB,SAAS,SAAS,KAAK,UAAU,UAAU,QAAQ,KAAK,CACtE,KAAK,SAAS,gCAAgC,KAAK,IAAI,CACvD,KAAK,aAAa,GACrB,GACL;UACC,UAAU,cAAc,SAAS,YAAY,KAAK,GAAG,GAAG,GAAG;;;UAG3D,UAAU,oBAAoB,SAAS,kBAAkB,KAAK,GAAG,GAAG,GAAG;;UAEvE,iBAAiB,SAAS,SAAS,IAAI,UAAU,UAAU,QAAQ,KAAK,CACvE,KAAK,SAAS,8BAA8B,KAAK,cAAa,CAC9D,KAAK,aAAa,CAAC;UACpB,UAAU,mBAAmB,SAAS,iBAAiB,KAAK,GAAG,GAAG,GAAG"}
1
+ {"version":3,"file":"template.mjs","names":[],"sources":["../../../../src/middlewares/web/utils/template.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { TemplateUIOptions } from '@verdaccio/types';\n\nimport type { Manifest } from './manifest';\nimport { getManifestValue } from './manifest';\n\nconst debug = buildDebug('verdaccio:web:render:template');\n\nexport type Template = {\n manifest: Manifest;\n options: TemplateUIOptions;\n metaScripts?: string[];\n scriptsBodyAfter?: string[];\n scriptsBodyBefore?: string[];\n};\n\nexport interface AssetManifest {\n [key: string]: string;\n}\n\nexport default function renderTemplate(template: Template, manifest: AssetManifest) {\n debug('template %o', template);\n debug('manifest %o', manifest);\n\n return `\n <!DOCTYPE html>\n <html lang=\"en-us\">\n <head>\n <meta charset=\"utf-8\">\n <base href=\"${template?.options.base}\">\n <title>${template?.options?.title ?? ''}</title>\n <link rel=\"icon\" href=\"${template?.options.base}-/static/favicon.ico\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <script src=\"${template?.options.base}-/static/ui-options.js\"></script>\n ${\n template.manifest.css?.length\n ? getManifestValue(template.manifest.css, manifest, template?.options.base)\n .map((item) => `<link rel=\"stylesheet\" href=\"${item}\">`)\n .join('\\n ')\n : ''\n }\n ${template?.metaScripts ? template.metaScripts.join('') : ''}\n </head>\n <body class=\"body\">\n ${template?.scriptsBodyBefore ? template.scriptsBodyBefore.join('') : ''}\n <div id=\"root\"></div>\n ${getManifestValue(template.manifest.js, manifest, template?.options.base)\n .map((item) => `<script type=\"module\" src=\"${item}\"></script>`)\n .join(`\\n `)}\n ${template?.scriptsBodyAfter ? template.scriptsBodyAfter.join('') : ''}\n </body>\n </html>\n `;\n}\n"],"mappings":";;;AAOA,IAAM,QAAQ,WAAW,gCAAgC;AAczD,SAAwB,eAAe,UAAoB,UAAyB;AAClF,OAAM,eAAe,SAAS;AAC9B,OAAM,eAAe,SAAS;AAE9B,QAAO;;;;;sBAKa,UAAU,QAAQ,KAAK;iBAC5B,UAAU,SAAS,SAAS,GAAG;iCACf,UAAU,QAAQ,KAAK;;uBAEjC,UAAU,QAAQ,KAAK;UAEpC,SAAS,SAAS,KAAK,SACnB,iBAAiB,SAAS,SAAS,KAAK,UAAU,UAAU,QAAQ,KAAK,CACtE,KAAK,SAAS,gCAAgC,KAAK,IAAI,CACvD,KAAK,aAAa,GACrB,GACL;UACC,UAAU,cAAc,SAAS,YAAY,KAAK,GAAG,GAAG,GAAG;;;UAG3D,UAAU,oBAAoB,SAAS,kBAAkB,KAAK,GAAG,GAAG,GAAG;;UAEvE,iBAAiB,SAAS,SAAS,IAAI,UAAU,UAAU,QAAQ,KAAK,CACvE,KAAK,SAAS,8BAA8B,KAAK,cAAa,CAC9D,KAAK,aAAa,CAAC;UACpB,UAAU,mBAAmB,SAAS,iBAAiB,KAAK,GAAG,GAAG,GAAG"}
@@ -0,0 +1,4 @@
1
+ import { Response } from 'express';
2
+ import { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';
3
+ import { RequestOptions } from '@verdaccio/url';
4
+ export declare function getUIOptions(config: ConfigYaml, requestOptions: RequestOptions, res: Response): TemplateUIOptions;
@@ -0,0 +1,71 @@
1
+ const require_runtime = require("../../../_virtual/_rolldown/runtime.js");
2
+ const require_web_utils = require("./web-utils.js");
3
+ let node_url = require("node:url");
4
+ let _verdaccio_config = require("@verdaccio/config");
5
+ let node_path = require("node:path");
6
+ node_path = require_runtime.__toESM(node_path);
7
+ let _verdaccio_url = require("@verdaccio/url");
8
+ //#region src/middlewares/web/utils/ui-options.ts
9
+ var DEFAULT_LANGUAGE = "en-US";
10
+ function resolveLogo(logo, url_prefix, requestOptions) {
11
+ if (typeof logo !== "string") return "";
12
+ if (logo && !(0, _verdaccio_url.isURLhasValidProtocol)(logo)) return `${(0, _verdaccio_url.getPublicUrl)(url_prefix, requestOptions)}-/static/${node_path.default.basename(logo)}`;
13
+ else if ((0, _verdaccio_url.isURLhasValidProtocol)(logo)) return logo;
14
+ else return "";
15
+ }
16
+ function getUIOptions(config, requestOptions, res) {
17
+ const { url_prefix } = config;
18
+ const base = (0, _verdaccio_url.getPublicUrl)(config?.url_prefix, requestOptions);
19
+ const basename = node_url.URL.canParse(base) ? new node_url.URL(base).pathname : base;
20
+ const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
21
+ const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;
22
+ const darkMode = config?.web?.darkMode ?? false;
23
+ const title = config?.web?.title ?? _verdaccio_config.WEB_TITLE;
24
+ const login = require_web_utils.hasLogin(config);
25
+ const scope = config?.web?.scope ?? "";
26
+ const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);
27
+ const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);
28
+ const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);
29
+ const pkgManagers = config?.web?.pkgManagers ?? [
30
+ "yarn",
31
+ "pnpm",
32
+ "npm"
33
+ ];
34
+ const version = res.locals.app_version ?? "";
35
+ const flags = {
36
+ ...config.flags,
37
+ ...config.experiments
38
+ };
39
+ const primaryColor = require_web_utils.validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? "#4b5e40";
40
+ const { showInfo, showSettings, showThemeSwitch, showFooter, showSearch, showDownloadTarball, showRaw, showUplinks } = Object.assign({}, config?.web);
41
+ return {
42
+ showInfo,
43
+ showSettings,
44
+ showThemeSwitch,
45
+ showFooter,
46
+ showSearch,
47
+ showDownloadTarball,
48
+ showRaw,
49
+ showUplinks,
50
+ darkMode,
51
+ url_prefix,
52
+ basename,
53
+ base,
54
+ primaryColor,
55
+ version,
56
+ logo,
57
+ logoDark,
58
+ favicon,
59
+ flags,
60
+ login,
61
+ pkgManagers,
62
+ title,
63
+ scope,
64
+ language,
65
+ hideDeprecatedVersions
66
+ };
67
+ }
68
+ //#endregion
69
+ exports.getUIOptions = getUIOptions;
70
+
71
+ //# sourceMappingURL=ui-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-options.js","names":[],"sources":["../../../../src/middlewares/web/utils/ui-options.ts"],"sourcesContent":["import type { Response } from 'express';\nimport path from 'node:path';\nimport { URL } from 'node:url';\n\nimport { WEB_TITLE } from '@verdaccio/config';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\nimport { type RequestOptions, getPublicUrl, isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { hasLogin, validatePrimaryColor } from './web-utils';\n\nconst DEFAULT_LANGUAGE = 'en-US';\n\nfunction resolveLogo(\n logo: string | undefined,\n url_prefix: string | undefined,\n requestOptions: RequestOptions\n) {\n if (typeof logo !== 'string') {\n return '';\n }\n const isLocalFile = logo && !isURLhasValidProtocol(logo);\n\n if (isLocalFile) {\n return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;\n } else if (isURLhasValidProtocol(logo)) {\n return logo;\n } else {\n return '';\n }\n}\n\nexport function getUIOptions(\n config: ConfigYaml,\n requestOptions: RequestOptions,\n res: Response\n): TemplateUIOptions {\n const { url_prefix } = config;\n const base = getPublicUrl(config?.url_prefix, requestOptions);\n const basename = URL.canParse(base) ? new URL(base).pathname : base;\n const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;\n const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;\n const darkMode = config?.web?.darkMode ?? false;\n const title = config?.web?.title ?? WEB_TITLE;\n const login = hasLogin(config);\n const scope = config?.web?.scope ?? '';\n const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);\n const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);\n const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);\n const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];\n const version = res.locals.app_version ?? '';\n const flags = {\n ...config.flags,\n // legacy from 5.x\n ...config.experiments,\n };\n const primaryColor =\n validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? '#4b5e40';\n const {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n } = Object.assign({}, config?.web);\n\n return {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n darkMode,\n url_prefix,\n basename,\n base,\n primaryColor,\n version,\n logo,\n logoDark,\n favicon,\n flags,\n login,\n pkgManagers,\n title,\n scope,\n language,\n hideDeprecatedVersions,\n };\n}\n"],"mappings":";;;;;;;;AAUA,IAAM,mBAAmB;AAEzB,SAAS,YACP,MACA,YACA,gBACA;AACA,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,KAFoB,QAAQ,EAAA,GAAA,eAAA,uBAAuB,KAAK,CAGtD,QAAO,IAAA,GAAA,eAAA,cAAgB,YAAY,eAAe,CAAC,WAAW,UAAA,QAAK,SAAS,KAAK;oDAClD,KAAK,CACpC,QAAO;KAEP,QAAO;;AAIX,SAAgB,aACd,QACA,gBACA,KACmB;CACnB,MAAM,EAAE,eAAe;CACvB,MAAM,QAAA,GAAA,eAAA,cAAoB,QAAQ,YAAY,eAAe;CAC7D,MAAM,WAAW,SAAA,IAAI,SAAS,KAAK,GAAG,IAAI,SAAA,IAAI,KAAK,CAAC,WAAW;CAC/D,MAAM,WAAW,QAAQ,MAAM,OAAO;CACtC,MAAM,yBAAyB,QAAQ,KAAK,0BAA0B;CACtE,MAAM,WAAW,QAAQ,KAAK,YAAY;CAC1C,MAAM,QAAQ,QAAQ,KAAK,SAAS,kBAAA;CACpC,MAAM,QAAQ,kBAAA,SAAS,OAAO;CAC9B,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,UAAU,YAAY,QAAQ,KAAK,SAAS,QAAQ,YAAY,eAAe;CACrF,MAAM,OAAO,YAAY,QAAQ,KAAK,MAAM,QAAQ,YAAY,eAAe;CAC/E,MAAM,WAAW,YAAY,QAAQ,KAAK,UAAU,QAAQ,YAAY,eAAe;CACvF,MAAM,cAAc,QAAQ,KAAK,eAAe;EAAC;EAAQ;EAAQ;EAAM;CACvE,MAAM,UAAU,IAAI,OAAO,eAAe;CAC1C,MAAM,QAAQ;EACZ,GAAG,OAAO;EAEV,GAAG,OAAO;EACX;CACD,MAAM,eACJ,kBAAA,qBAAqB,QAAQ,KAAK,iBAAiB,QAAQ,KAAK,aAAa,IAAI;CACnF,MAAM,EACJ,UACA,cACA,iBACA,YACA,YACA,qBACA,SACA,gBACE,OAAO,OAAO,EAAE,EAAE,QAAQ,IAAI;AAElC,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
@@ -0,0 +1,69 @@
1
+ import { hasLogin, validatePrimaryColor } from "./web-utils.mjs";
2
+ import { URL } from "node:url";
3
+ import { WEB_TITLE } from "@verdaccio/config";
4
+ import path from "node:path";
5
+ import { getPublicUrl, isURLhasValidProtocol } from "@verdaccio/url";
6
+ //#region src/middlewares/web/utils/ui-options.ts
7
+ var DEFAULT_LANGUAGE = "en-US";
8
+ function resolveLogo(logo, url_prefix, requestOptions) {
9
+ if (typeof logo !== "string") return "";
10
+ if (logo && !isURLhasValidProtocol(logo)) return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;
11
+ else if (isURLhasValidProtocol(logo)) return logo;
12
+ else return "";
13
+ }
14
+ function getUIOptions(config, requestOptions, res) {
15
+ const { url_prefix } = config;
16
+ const base = getPublicUrl(config?.url_prefix, requestOptions);
17
+ const basename = URL.canParse(base) ? new URL(base).pathname : base;
18
+ const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;
19
+ const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;
20
+ const darkMode = config?.web?.darkMode ?? false;
21
+ const title = config?.web?.title ?? WEB_TITLE;
22
+ const login = hasLogin(config);
23
+ const scope = config?.web?.scope ?? "";
24
+ const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);
25
+ const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);
26
+ const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);
27
+ const pkgManagers = config?.web?.pkgManagers ?? [
28
+ "yarn",
29
+ "pnpm",
30
+ "npm"
31
+ ];
32
+ const version = res.locals.app_version ?? "";
33
+ const flags = {
34
+ ...config.flags,
35
+ ...config.experiments
36
+ };
37
+ const primaryColor = validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? "#4b5e40";
38
+ const { showInfo, showSettings, showThemeSwitch, showFooter, showSearch, showDownloadTarball, showRaw, showUplinks } = Object.assign({}, config?.web);
39
+ return {
40
+ showInfo,
41
+ showSettings,
42
+ showThemeSwitch,
43
+ showFooter,
44
+ showSearch,
45
+ showDownloadTarball,
46
+ showRaw,
47
+ showUplinks,
48
+ darkMode,
49
+ url_prefix,
50
+ basename,
51
+ base,
52
+ primaryColor,
53
+ version,
54
+ logo,
55
+ logoDark,
56
+ favicon,
57
+ flags,
58
+ login,
59
+ pkgManagers,
60
+ title,
61
+ scope,
62
+ language,
63
+ hideDeprecatedVersions
64
+ };
65
+ }
66
+ //#endregion
67
+ export { getUIOptions };
68
+
69
+ //# sourceMappingURL=ui-options.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-options.mjs","names":[],"sources":["../../../../src/middlewares/web/utils/ui-options.ts"],"sourcesContent":["import type { Response } from 'express';\nimport path from 'node:path';\nimport { URL } from 'node:url';\n\nimport { WEB_TITLE } from '@verdaccio/config';\nimport type { ConfigYaml, TemplateUIOptions } from '@verdaccio/types';\nimport { type RequestOptions, getPublicUrl, isURLhasValidProtocol } from '@verdaccio/url';\n\nimport { hasLogin, validatePrimaryColor } from './web-utils';\n\nconst DEFAULT_LANGUAGE = 'en-US';\n\nfunction resolveLogo(\n logo: string | undefined,\n url_prefix: string | undefined,\n requestOptions: RequestOptions\n) {\n if (typeof logo !== 'string') {\n return '';\n }\n const isLocalFile = logo && !isURLhasValidProtocol(logo);\n\n if (isLocalFile) {\n return `${getPublicUrl(url_prefix, requestOptions)}-/static/${path.basename(logo)}`;\n } else if (isURLhasValidProtocol(logo)) {\n return logo;\n } else {\n return '';\n }\n}\n\nexport function getUIOptions(\n config: ConfigYaml,\n requestOptions: RequestOptions,\n res: Response\n): TemplateUIOptions {\n const { url_prefix } = config;\n const base = getPublicUrl(config?.url_prefix, requestOptions);\n const basename = URL.canParse(base) ? new URL(base).pathname : base;\n const language = config?.i18n?.web ?? DEFAULT_LANGUAGE;\n const hideDeprecatedVersions = config?.web?.hideDeprecatedVersions ?? false;\n const darkMode = config?.web?.darkMode ?? false;\n const title = config?.web?.title ?? WEB_TITLE;\n const login = hasLogin(config);\n const scope = config?.web?.scope ?? '';\n const favicon = resolveLogo(config?.web?.favicon, config?.url_prefix, requestOptions);\n const logo = resolveLogo(config?.web?.logo, config?.url_prefix, requestOptions);\n const logoDark = resolveLogo(config?.web?.logoDark, config?.url_prefix, requestOptions);\n const pkgManagers = config?.web?.pkgManagers ?? ['yarn', 'pnpm', 'npm'];\n const version = res.locals.app_version ?? '';\n const flags = {\n ...config.flags,\n // legacy from 5.x\n ...config.experiments,\n };\n const primaryColor =\n validatePrimaryColor(config?.web?.primary_color ?? config?.web?.primaryColor) ?? '#4b5e40';\n const {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n } = Object.assign({}, config?.web);\n\n return {\n showInfo,\n showSettings,\n showThemeSwitch,\n showFooter,\n showSearch,\n showDownloadTarball,\n showRaw,\n showUplinks,\n darkMode,\n url_prefix,\n basename,\n base,\n primaryColor,\n version,\n logo,\n logoDark,\n favicon,\n flags,\n login,\n pkgManagers,\n title,\n scope,\n language,\n hideDeprecatedVersions,\n };\n}\n"],"mappings":";;;;;;AAUA,IAAM,mBAAmB;AAEzB,SAAS,YACP,MACA,YACA,gBACA;AACA,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,KAFoB,QAAQ,CAAC,sBAAsB,KAAK,CAGtD,QAAO,GAAG,aAAa,YAAY,eAAe,CAAC,WAAW,KAAK,SAAS,KAAK;UACxE,sBAAsB,KAAK,CACpC,QAAO;KAEP,QAAO;;AAIX,SAAgB,aACd,QACA,gBACA,KACmB;CACnB,MAAM,EAAE,eAAe;CACvB,MAAM,OAAO,aAAa,QAAQ,YAAY,eAAe;CAC7D,MAAM,WAAW,IAAI,SAAS,KAAK,GAAG,IAAI,IAAI,KAAK,CAAC,WAAW;CAC/D,MAAM,WAAW,QAAQ,MAAM,OAAO;CACtC,MAAM,yBAAyB,QAAQ,KAAK,0BAA0B;CACtE,MAAM,WAAW,QAAQ,KAAK,YAAY;CAC1C,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,QAAQ,SAAS,OAAO;CAC9B,MAAM,QAAQ,QAAQ,KAAK,SAAS;CACpC,MAAM,UAAU,YAAY,QAAQ,KAAK,SAAS,QAAQ,YAAY,eAAe;CACrF,MAAM,OAAO,YAAY,QAAQ,KAAK,MAAM,QAAQ,YAAY,eAAe;CAC/E,MAAM,WAAW,YAAY,QAAQ,KAAK,UAAU,QAAQ,YAAY,eAAe;CACvF,MAAM,cAAc,QAAQ,KAAK,eAAe;EAAC;EAAQ;EAAQ;EAAM;CACvE,MAAM,UAAU,IAAI,OAAO,eAAe;CAC1C,MAAM,QAAQ;EACZ,GAAG,OAAO;EAEV,GAAG,OAAO;EACX;CACD,MAAM,eACJ,qBAAqB,QAAQ,KAAK,iBAAiB,QAAQ,KAAK,aAAa,IAAI;CACnF,MAAM,EACJ,UACA,cACA,iBACA,YACA,YACA,qBACA,SACA,gBACE,OAAO,OAAO,EAAE,EAAE,QAAQ,IAAI;AAElC,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/middleware",
3
- "version": "9.0.0-next-9.4",
3
+ "version": "9.0.0-next-9.6",
4
4
  "description": "Verdaccio Express Middleware",
5
5
  "main": "./build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -33,9 +33,9 @@
33
33
  "node": ">=24"
34
34
  },
35
35
  "dependencies": {
36
- "@verdaccio/config": "9.0.0-next-9.4",
37
- "@verdaccio/core": "9.0.0-next-9.4",
38
- "@verdaccio/url": "14.0.0-next-9.4",
36
+ "@verdaccio/config": "9.0.0-next-9.6",
37
+ "@verdaccio/core": "9.0.0-next-9.6",
38
+ "@verdaccio/url": "14.0.0-next-9.6",
39
39
  "debug": "4.4.3",
40
40
  "express": "5.2.1",
41
41
  "express-rate-limit": "8.2.1",
@@ -47,12 +47,11 @@
47
47
  "url": "https://opencollective.com/verdaccio"
48
48
  },
49
49
  "devDependencies": {
50
- "@verdaccio/logger": "9.0.0-next-9.4",
51
- "@verdaccio/types": "14.0.0-next-9.1",
50
+ "@verdaccio/logger": "9.0.0-next-9.6",
51
+ "@verdaccio/types": "14.0.0-next-9.3",
52
52
  "http-errors": "2.0.1",
53
53
  "supertest": "7.1.4",
54
- "jsdom": "28.1.0",
55
- "vitest": "3.2.4"
54
+ "vitest": "4.1.0"
56
55
  },
57
56
  "module": "./build/index.mjs",
58
57
  "exports": {