@dr.pogodin/react-utils 1.18.2 → 1.18.3

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.
@@ -33,7 +33,6 @@ if (!window.TRU_KEEP_INJ_SCRIPT) {
33
33
 
34
34
 
35
35
  const {
36
- publicPath,
37
36
  useServiceWorker
38
37
  } = window.TRU_BUILD_INFO;
39
38
 
@@ -45,7 +44,11 @@ if (useServiceWorker) {
45
44
  if ('serviceWorker' in navigator) {
46
45
  window.addEventListener('load', async () => {
47
46
  try {
48
- const reg = await navigator.serviceWorker.register("".concat(publicPath, "/__service-worker.js"));
47
+ // Note: no matter the "publicPath", we want to serve the service worker
48
+ // from the web app root, to allow it control any and all pages of the
49
+ // web app (otherwise, it will be restricted to the scope of its path).
50
+ // The server takes it into account.
51
+ const reg = await navigator.serviceWorker.register('/__service-worker.js');
49
52
  console.log('SW registered:', reg);
50
53
  } catch (err) {
51
54
  console.log('SW registration failed:', err);
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","names":["BUILD_INFO","window","TRU_BUILD_INFO","TRU_KEEP_INJ_SCRIPT","block","document","querySelector","getElementsByTagName","removeChild","publicPath","useServiceWorker","navigator","addEventListener","reg","serviceWorker","register","console","log","err","INJ","key","data","forge","util","decode64","decipher","cipher","createDecipher","start","iv","slice","update","createBuffer","finish","decodeUtf8","output","eval","CHUNK_GROUPS","CONFIG","ISTATE"],"sources":["../../../src/client/init.js"],"sourcesContent":["/**\n * Initialization of client-side environment.\n */\n\n/* global BUILD_INFO, document, window */\n\n// Note: this way, only required part of \"node-forge\": AES, and some utils,\n// is bundled into client-side code.\nimport forge from 'node-forge/lib/forge';\nimport 'node-forge/lib/aes';\n\n/* `BUILD_INFO` is always injected by Webpack build, but this check is needed\n * to adopt the code for usage in tests. */\nif (typeof BUILD_INFO !== 'undefined') {\n window.TRU_BUILD_INFO = BUILD_INFO;\n}\n\n/* Removes data injection script out of the document.\n * The if block is here for test purposes. */\nif (!window.TRU_KEEP_INJ_SCRIPT) {\n const block = document.querySelector('script[id=\"inj\"]');\n if (block) document.getElementsByTagName('body')[0].removeChild(block);\n}\n\n/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */\n/* eslint-disable no-console */\nconst { publicPath, useServiceWorker } = window.TRU_BUILD_INFO;\nif (useServiceWorker) {\n const { navigator } = window;\n if ('serviceWorker' in navigator) {\n window.addEventListener('load', async () => {\n try {\n const reg = await navigator\n .serviceWorker.register(`${publicPath}/__service-worker.js`);\n console.log('SW registered:', reg);\n } catch (err) {\n console.log('SW registration failed:', err);\n }\n });\n }\n}\n/* eslint-enable no-console */\n\n/* Decodes data injected at the server side. */\nif (window.INJ) {\n const { key } = window.TRU_BUILD_INFO;\n let data = forge.util.decode64(window.INJ);\n const decipher = forge.cipher.createDecipher('AES-CBC', key);\n decipher.start({ iv: data.slice(0, 32) });\n decipher.update(forge.util.createBuffer(data.slice(32)));\n decipher.finish();\n\n data = forge.util.decodeUtf8(decipher.output.data);\n data = eval(`(${data})`); // eslint-disable-line no-eval\n\n window.CHUNK_GROUPS = data.CHUNK_GROUPS;\n window.CONFIG = data.CONFIG;\n window.ISTATE = data.ISTATE;\n} else {\n // This is possible when the client-side bundle is launched as a stand-alone\n // precompiled website, rather than served by react-utils' based server.\n window.CHUNK_GROUPS = {};\n window.CONFIG = {};\n}\n"],"mappings":";;;;AAQA;;AACA;;AATA;AACA;AACA;;AAEA;AAEA;AACA;;AAIA;AACA;AACA,IAAI,OAAOA,UAAP,KAAsB,WAA1B,EAAuC;EACrCC,MAAM,CAACC,cAAP,GAAwBF,UAAxB;AACD;AAED;AACA;;;AACA,IAAI,CAACC,MAAM,CAACE,mBAAZ,EAAiC;EAC/B,MAAMC,KAAK,GAAGC,QAAQ,CAACC,aAAT,CAAuB,kBAAvB,CAAd;EACA,IAAIF,KAAJ,EAAWC,QAAQ,CAACE,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,EAAyCC,WAAzC,CAAqDJ,KAArD;AACZ;AAED;;AACA;;;AACA,MAAM;EAAEK,UAAF;EAAcC;AAAd,IAAmCT,MAAM,CAACC,cAAhD;;AACA,IAAIQ,gBAAJ,EAAsB;EACpB,MAAM;IAAEC;EAAF,IAAgBV,MAAtB;;EACA,IAAI,mBAAmBU,SAAvB,EAAkC;IAChCV,MAAM,CAACW,gBAAP,CAAwB,MAAxB,EAAgC,YAAY;MAC1C,IAAI;QACF,MAAMC,GAAG,GAAG,MAAMF,SAAS,CACxBG,aADe,CACDC,QADC,WACWN,UADX,0BAAlB;QAEAO,OAAO,CAACC,GAAR,CAAY,gBAAZ,EAA8BJ,GAA9B;MACD,CAJD,CAIE,OAAOK,GAAP,EAAY;QACZF,OAAO,CAACC,GAAR,CAAY,yBAAZ,EAAuCC,GAAvC;MACD;IACF,CARD;EASD;AACF;AACD;;AAEA;;;AACA,IAAIjB,MAAM,CAACkB,GAAX,EAAgB;EACd,MAAM;IAAEC;EAAF,IAAUnB,MAAM,CAACC,cAAvB;;EACA,IAAImB,IAAI,GAAGC,cAAA,CAAMC,IAAN,CAAWC,QAAX,CAAoBvB,MAAM,CAACkB,GAA3B,CAAX;;EACA,MAAMM,QAAQ,GAAGH,cAAA,CAAMI,MAAN,CAAaC,cAAb,CAA4B,SAA5B,EAAuCP,GAAvC,CAAjB;;EACAK,QAAQ,CAACG,KAAT,CAAe;IAAEC,EAAE,EAAER,IAAI,CAACS,KAAL,CAAW,CAAX,EAAc,EAAd;EAAN,CAAf;EACAL,QAAQ,CAACM,MAAT,CAAgBT,cAAA,CAAMC,IAAN,CAAWS,YAAX,CAAwBX,IAAI,CAACS,KAAL,CAAW,EAAX,CAAxB,CAAhB;EACAL,QAAQ,CAACQ,MAAT;EAEAZ,IAAI,GAAGC,cAAA,CAAMC,IAAN,CAAWW,UAAX,CAAsBT,QAAQ,CAACU,MAAT,CAAgBd,IAAtC,CAAP;EACAA,IAAI,GAAGe,IAAI,YAAKf,IAAL,OAAX,CATc,CASY;;EAE1BpB,MAAM,CAACoC,YAAP,GAAsBhB,IAAI,CAACgB,YAA3B;EACApC,MAAM,CAACqC,MAAP,GAAgBjB,IAAI,CAACiB,MAArB;EACArC,MAAM,CAACsC,MAAP,GAAgBlB,IAAI,CAACkB,MAArB;AACD,CAdD,MAcO;EACL;EACA;EACAtC,MAAM,CAACoC,YAAP,GAAsB,EAAtB;EACApC,MAAM,CAACqC,MAAP,GAAgB,EAAhB;AACD"}
1
+ {"version":3,"file":"init.js","names":["BUILD_INFO","window","TRU_BUILD_INFO","TRU_KEEP_INJ_SCRIPT","block","document","querySelector","getElementsByTagName","removeChild","useServiceWorker","navigator","addEventListener","reg","serviceWorker","register","console","log","err","INJ","key","data","forge","util","decode64","decipher","cipher","createDecipher","start","iv","slice","update","createBuffer","finish","decodeUtf8","output","eval","CHUNK_GROUPS","CONFIG","ISTATE"],"sources":["../../../src/client/init.js"],"sourcesContent":["/**\n * Initialization of client-side environment.\n */\n\n/* global BUILD_INFO, document, window */\n\n// Note: this way, only required part of \"node-forge\": AES, and some utils,\n// is bundled into client-side code.\nimport forge from 'node-forge/lib/forge';\nimport 'node-forge/lib/aes';\n\n/* `BUILD_INFO` is always injected by Webpack build, but this check is needed\n * to adopt the code for usage in tests. */\nif (typeof BUILD_INFO !== 'undefined') {\n window.TRU_BUILD_INFO = BUILD_INFO;\n}\n\n/* Removes data injection script out of the document.\n * The if block is here for test purposes. */\nif (!window.TRU_KEEP_INJ_SCRIPT) {\n const block = document.querySelector('script[id=\"inj\"]');\n if (block) document.getElementsByTagName('body')[0].removeChild(block);\n}\n\n/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */\n/* eslint-disable no-console */\nconst { useServiceWorker } = window.TRU_BUILD_INFO;\nif (useServiceWorker) {\n const { navigator } = window;\n if ('serviceWorker' in navigator) {\n window.addEventListener('load', async () => {\n try {\n // Note: no matter the \"publicPath\", we want to serve the service worker\n // from the web app root, to allow it control any and all pages of the\n // web app (otherwise, it will be restricted to the scope of its path).\n // The server takes it into account.\n const reg = await navigator\n .serviceWorker.register('/__service-worker.js');\n console.log('SW registered:', reg);\n } catch (err) {\n console.log('SW registration failed:', err);\n }\n });\n }\n}\n/* eslint-enable no-console */\n\n/* Decodes data injected at the server side. */\nif (window.INJ) {\n const { key } = window.TRU_BUILD_INFO;\n let data = forge.util.decode64(window.INJ);\n const decipher = forge.cipher.createDecipher('AES-CBC', key);\n decipher.start({ iv: data.slice(0, 32) });\n decipher.update(forge.util.createBuffer(data.slice(32)));\n decipher.finish();\n\n data = forge.util.decodeUtf8(decipher.output.data);\n data = eval(`(${data})`); // eslint-disable-line no-eval\n\n window.CHUNK_GROUPS = data.CHUNK_GROUPS;\n window.CONFIG = data.CONFIG;\n window.ISTATE = data.ISTATE;\n} else {\n // This is possible when the client-side bundle is launched as a stand-alone\n // precompiled website, rather than served by react-utils' based server.\n window.CHUNK_GROUPS = {};\n window.CONFIG = {};\n}\n"],"mappings":";;;;AAQA;;AACA;;AATA;AACA;AACA;;AAEA;AAEA;AACA;;AAIA;AACA;AACA,IAAI,OAAOA,UAAP,KAAsB,WAA1B,EAAuC;EACrCC,MAAM,CAACC,cAAP,GAAwBF,UAAxB;AACD;AAED;AACA;;;AACA,IAAI,CAACC,MAAM,CAACE,mBAAZ,EAAiC;EAC/B,MAAMC,KAAK,GAAGC,QAAQ,CAACC,aAAT,CAAuB,kBAAvB,CAAd;EACA,IAAIF,KAAJ,EAAWC,QAAQ,CAACE,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,EAAyCC,WAAzC,CAAqDJ,KAArD;AACZ;AAED;;AACA;;;AACA,MAAM;EAAEK;AAAF,IAAuBR,MAAM,CAACC,cAApC;;AACA,IAAIO,gBAAJ,EAAsB;EACpB,MAAM;IAAEC;EAAF,IAAgBT,MAAtB;;EACA,IAAI,mBAAmBS,SAAvB,EAAkC;IAChCT,MAAM,CAACU,gBAAP,CAAwB,MAAxB,EAAgC,YAAY;MAC1C,IAAI;QACF;QACA;QACA;QACA;QACA,MAAMC,GAAG,GAAG,MAAMF,SAAS,CACxBG,aADe,CACDC,QADC,CACQ,sBADR,CAAlB;QAEAC,OAAO,CAACC,GAAR,CAAY,gBAAZ,EAA8BJ,GAA9B;MACD,CARD,CAQE,OAAOK,GAAP,EAAY;QACZF,OAAO,CAACC,GAAR,CAAY,yBAAZ,EAAuCC,GAAvC;MACD;IACF,CAZD;EAaD;AACF;AACD;;AAEA;;;AACA,IAAIhB,MAAM,CAACiB,GAAX,EAAgB;EACd,MAAM;IAAEC;EAAF,IAAUlB,MAAM,CAACC,cAAvB;;EACA,IAAIkB,IAAI,GAAGC,cAAA,CAAMC,IAAN,CAAWC,QAAX,CAAoBtB,MAAM,CAACiB,GAA3B,CAAX;;EACA,MAAMM,QAAQ,GAAGH,cAAA,CAAMI,MAAN,CAAaC,cAAb,CAA4B,SAA5B,EAAuCP,GAAvC,CAAjB;;EACAK,QAAQ,CAACG,KAAT,CAAe;IAAEC,EAAE,EAAER,IAAI,CAACS,KAAL,CAAW,CAAX,EAAc,EAAd;EAAN,CAAf;EACAL,QAAQ,CAACM,MAAT,CAAgBT,cAAA,CAAMC,IAAN,CAAWS,YAAX,CAAwBX,IAAI,CAACS,KAAL,CAAW,EAAX,CAAxB,CAAhB;EACAL,QAAQ,CAACQ,MAAT;EAEAZ,IAAI,GAAGC,cAAA,CAAMC,IAAN,CAAWW,UAAX,CAAsBT,QAAQ,CAACU,MAAT,CAAgBd,IAAtC,CAAP;EACAA,IAAI,GAAGe,IAAI,YAAKf,IAAL,OAAX,CATc,CASY;;EAE1BnB,MAAM,CAACmC,YAAP,GAAsBhB,IAAI,CAACgB,YAA3B;EACAnC,MAAM,CAACoC,MAAP,GAAgBjB,IAAI,CAACiB,MAArB;EACApC,MAAM,CAACqC,MAAP,GAAgBlB,IAAI,CAACkB,MAArB;AACD,CAdD,MAcO;EACL;EACA;EACArC,MAAM,CAACmC,YAAP,GAAsB,EAAtB;EACAnC,MAAM,CAACoC,MAAP,GAAgB,EAAhB;AACD"}
@@ -153,13 +153,14 @@ async function factory(webpackConfig, options) {
153
153
  stream: {
154
154
  write: options.logger.info.bind(options.logger)
155
155
  }
156
- }));
157
- /* Ensures no caching for the service worker script. */
156
+ })); // Note: no matter the "public path", we want the service worker, if any,
157
+ // to be served from the root, to have all web app pages in its scope.
158
+ // Thus, this setup to serve it. Probably, need some more configuration
159
+ // for special cases, but this will do for now.
158
160
 
159
- server.use(`${publicPath}service-worker.js`, (req, res, next) => {
160
- res.header('Cache-Control', 'no-cache');
161
- next();
162
- });
161
+ server.get('/__service-worker.js', _express.default.static(webpackConfig.output.path, {
162
+ setHeaders: res => res.set('Cache-Control', 'no-cache')
163
+ }));
163
164
  /* Setup of Hot Module Reloading for development environment.
164
165
  * These dependencies are not used, nor installed for production use,
165
166
  * hence we should violate some import-related lint rules. */
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":["defaultCspSettings","directives","mapValues","helmet","contentSecurityPolicy","getDefaultDirectives","array","filter","item","push","getDefaultCspSettings","cloneDeep","factory","webpackConfig","options","rendererOps","pick","renderer","rendererFactory","publicPath","output","server","express","beforeExpressJsSetup","logger","httpsRedirect","use","req","res","next","schema","headers","url","host","originalUrl","redirect","compression","crossOriginEmbedderPolicy","crossOriginOpenerPolicy","crossOriginResourcePolicy","noCsp","nonce","uuid","cspNonce","cspSettings","cspSettingsHook","favicon","send","json","limit","urlencoded","extended","cookieParser","requestIp","mw","loggerMiddleware","token","clientIp","FORMAT","stream","write","info","bind","header","devMode","global","location","href","pathToFileURL","process","cwd","sep","webpack","require","webpackDevMiddleware","webpackHotMiddleware","compiler","serverSideRender","static","path","onExpressJsSetup","newError","ERRORS","NOT_FOUND","CODES","dontAttachDefaultErrorHandler","beforeExpressJsError","error","headersSent","status","INTERNAL_SERVER_ERROR","serverSide","log","message","getErrorForCode","env","NODE_ENV","undefined"],"sources":["../../../src/server/server.js"],"sourcesContent":["/**\n * Creation of standard ExpressJS server for ReactJS apps.\n */\n\nimport { sep } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport {\n cloneDeep,\n mapValues,\n pick,\n} from 'lodash';\n\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport express from 'express';\nimport favicon from 'serve-favicon';\nimport helmet from 'helmet';\nimport loggerMiddleware from 'morgan';\nimport requestIp from 'request-ip';\nimport { v4 as uuid } from 'uuid';\n\nimport rendererFactory from './renderer';\n\nimport {\n CODES,\n ERRORS,\n getErrorForCode,\n newError,\n} from './utils/errors';\n\n/**\n * Default Content Security Policy settings.\n * @ignore\n */\nconst defaultCspSettings = {\n directives: mapValues(\n helmet.contentSecurityPolicy.getDefaultDirectives(),\n\n // 'https:' options (automatic re-write of insecure URLs to secure ones)\n // is removed to facilitate local development with HTTP server. In cloud\n // deployments we assume Apache or Nginx server in front of out app takes\n // care about such re-writes.\n (array) => array.filter((item) => item !== 'https:'),\n ),\n};\ndefaultCspSettings.directives['frame-src'] = [\n \"'self'\",\n\n // YouTube domain is whitelisted to allow <YouTubeVideo> component to work\n // out of box.\n 'https://*.youtube.com',\n];\ndefaultCspSettings.directives['script-src'].push(\"'unsafe-eval'\");\n\n// No need for automatic re-writes via Content Security Policy settings:\n// the forefront Apache or Nginx server is supposed to take care of this\n// in production cloud deployments.\ndelete defaultCspSettings.directives['upgrade-insecure-requests'];\n\n/**\n * @category Utilities\n * @func server/getDefaultCspSettings\n * @global\n * @desc\n * ```js\n * import { server } from '@dr.pogodin/react-utils';\n * const { getDefaultCspSettings } from '@dr.pogodin/react-utils';\n * ```\n * @return {{\n * directives: object\n * }} A deep copy of default CSP settings object used by `react-utils`,\n * with the exception of `nonce-xxx` clause in `script-src` directive,\n * which is added dynamically for each request.\n */\nexport function getDefaultCspSettings() {\n return cloneDeep(defaultCspSettings);\n}\n\nexport default async function factory(webpackConfig, options) {\n const rendererOps = pick(options, [\n 'Application',\n 'beforeRender',\n 'favicon',\n 'logger',\n 'maxSsrRounds',\n 'noCsp',\n 'ssrTimeout',\n 'staticCacheController',\n 'staticCacheSize',\n ]);\n const renderer = rendererFactory(webpackConfig, rendererOps);\n const { publicPath } = webpackConfig.output;\n\n const server = express();\n\n if (options.beforeExpressJsSetup) {\n await options.beforeExpressJsSetup(server);\n }\n\n server.logger = options.logger;\n\n if (options.httpsRedirect) {\n server.use((req, res, next) => {\n const schema = req.headers['x-forwarded-proto'];\n if (schema === 'http') {\n let url = `https://${req.headers.host}`;\n if (req.originalUrl !== '/') url += req.originalUrl;\n return res.redirect(url);\n }\n return next();\n });\n }\n\n server.use(compression());\n server.use(\n helmet({\n contentSecurityPolicy: false,\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n }),\n );\n\n if (!options.noCsp) {\n server.use((req, res, next) => {\n req.nonce = uuid();\n\n // TODO: This is deprecated, but it is kept for now for backward\n // compatibility. Should be removed sometime later.\n req.cspNonce = req.nonce;\n\n // The deep clone is necessary here to ensure that default value can't be\n // mutated during request processing.\n let cspSettings = cloneDeep(defaultCspSettings);\n cspSettings.directives['script-src'].push(`'nonce-${req.nonce}'`);\n if (options.cspSettingsHook) {\n cspSettings = options.cspSettingsHook(cspSettings, req);\n }\n helmet.contentSecurityPolicy(cspSettings)(req, res, next);\n });\n }\n\n if (options.favicon) {\n server.use(favicon(options.favicon));\n }\n\n server.use('/robots.txt', (req, res) => res.send('User-agent: *\\nDisallow:'));\n\n server.use(express.json({ limit: '300kb' }));\n server.use(express.urlencoded({ extended: false }));\n server.use(cookieParser());\n server.use(requestIp.mw());\n\n loggerMiddleware.token('ip', (req) => req.clientIp);\n const FORMAT = ':ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent';\n server.use(loggerMiddleware(FORMAT, {\n stream: {\n write: options.logger.info.bind(options.logger),\n },\n }));\n\n /* Ensures no caching for the service worker script. */\n server.use(`${publicPath}service-worker.js`, (req, res, next) => {\n res.header('Cache-Control', 'no-cache');\n next();\n });\n\n /* Setup of Hot Module Reloading for development environment.\n * These dependencies are not used, nor installed for production use,\n * hence we should violate some import-related lint rules. */\n /* eslint-disable global-require */\n /* eslint-disable import/no-extraneous-dependencies */\n /* eslint-disable import/no-unresolved */\n if (options.devMode) {\n // This is a workaround for SASS bug:\n // https://github.com/dart-lang/sdk/issues/27979\n // which manifests itself sometimes when webpack dev middleware is used\n // (in dev mode), and app modules are imported in some unfortunate ways.\n if (!global.location) {\n global.location = {\n href: `${pathToFileURL(process.cwd()).href}${sep}`,\n };\n }\n\n const webpack = require('webpack');\n const webpackDevMiddleware = require('webpack-dev-middleware');\n const webpackHotMiddleware = require('webpack-hot-middleware');\n const compiler = webpack(webpackConfig);\n server.use(webpackDevMiddleware(compiler, {\n publicPath,\n serverSideRender: true,\n }));\n server.use(webpackHotMiddleware(compiler));\n }\n /* eslint-enable global-require */\n /* eslint-enable import/no-extraneous-dependencies */\n /* eslint-enable import/no-unresolved */\n\n server.use(publicPath, express.static(webpackConfig.output.path));\n\n if (options.onExpressJsSetup) {\n await options.onExpressJsSetup(server);\n }\n server.use(renderer);\n\n /* Detects 404 errors, and forwards them to the error handler. */\n server.use((req, res, next) => {\n next(newError(ERRORS.NOT_FOUND, CODES.NOT_FOUND));\n });\n\n let dontAttachDefaultErrorHandler;\n if (options.beforeExpressJsError) {\n dontAttachDefaultErrorHandler = await options.beforeExpressJsError(server);\n }\n\n /* Error handler. */\n if (!dontAttachDefaultErrorHandler) {\n // TODO: Do we need this error handler at all? It actually seems to do\n // what the default ExpressJS error handler does anyway, see:\n // https://expressjs.com/en/guide/error-handling.html\n //\n // TODO: It is better to move the default error handler definition\n // to a stand-alone function at top-level, but the use of options.logger\n // prevents to do it without some extra refactoring. Should be done sometime\n // though.\n server.use((error, req, res, next) => {\n // TODO: This is needed to correctly handled any errors thrown after\n // sending initial response to the client.\n if (res.headersSent) return next(error);\n\n const status = error.status || CODES.INTERNAL_SERVER_ERROR;\n const serverSide = status >= CODES.INTERNAL_SERVER_ERROR;\n\n // Log server-side errors always, client-side at debug level only.\n options.logger.log(serverSide ? 'error' : 'debug', error);\n\n let message = error.message || getErrorForCode(status);\n if (serverSide && process.env.NODE_ENV === 'production') {\n message = ERRORS.INTERNAL_SERVER_ERROR;\n }\n\n res.status(status).send(message);\n return undefined;\n });\n }\n\n return server;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.js","names":["defaultCspSettings","directives","mapValues","helmet","contentSecurityPolicy","getDefaultDirectives","array","filter","item","push","getDefaultCspSettings","cloneDeep","factory","webpackConfig","options","rendererOps","pick","renderer","rendererFactory","publicPath","output","server","express","beforeExpressJsSetup","logger","httpsRedirect","use","req","res","next","schema","headers","url","host","originalUrl","redirect","compression","crossOriginEmbedderPolicy","crossOriginOpenerPolicy","crossOriginResourcePolicy","noCsp","nonce","uuid","cspNonce","cspSettings","cspSettingsHook","favicon","send","json","limit","urlencoded","extended","cookieParser","requestIp","mw","loggerMiddleware","token","clientIp","FORMAT","stream","write","info","bind","get","static","path","setHeaders","set","devMode","global","location","href","pathToFileURL","process","cwd","sep","webpack","require","webpackDevMiddleware","webpackHotMiddleware","compiler","serverSideRender","onExpressJsSetup","newError","ERRORS","NOT_FOUND","CODES","dontAttachDefaultErrorHandler","beforeExpressJsError","error","headersSent","status","INTERNAL_SERVER_ERROR","serverSide","log","message","getErrorForCode","env","NODE_ENV","undefined"],"sources":["../../../src/server/server.js"],"sourcesContent":["/**\n * Creation of standard ExpressJS server for ReactJS apps.\n */\n\nimport { sep } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport {\n cloneDeep,\n mapValues,\n pick,\n} from 'lodash';\n\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport express from 'express';\nimport favicon from 'serve-favicon';\nimport helmet from 'helmet';\nimport loggerMiddleware from 'morgan';\nimport requestIp from 'request-ip';\nimport { v4 as uuid } from 'uuid';\n\nimport rendererFactory from './renderer';\n\nimport {\n CODES,\n ERRORS,\n getErrorForCode,\n newError,\n} from './utils/errors';\n\n/**\n * Default Content Security Policy settings.\n * @ignore\n */\nconst defaultCspSettings = {\n directives: mapValues(\n helmet.contentSecurityPolicy.getDefaultDirectives(),\n\n // 'https:' options (automatic re-write of insecure URLs to secure ones)\n // is removed to facilitate local development with HTTP server. In cloud\n // deployments we assume Apache or Nginx server in front of out app takes\n // care about such re-writes.\n (array) => array.filter((item) => item !== 'https:'),\n ),\n};\ndefaultCspSettings.directives['frame-src'] = [\n \"'self'\",\n\n // YouTube domain is whitelisted to allow <YouTubeVideo> component to work\n // out of box.\n 'https://*.youtube.com',\n];\ndefaultCspSettings.directives['script-src'].push(\"'unsafe-eval'\");\n\n// No need for automatic re-writes via Content Security Policy settings:\n// the forefront Apache or Nginx server is supposed to take care of this\n// in production cloud deployments.\ndelete defaultCspSettings.directives['upgrade-insecure-requests'];\n\n/**\n * @category Utilities\n * @func server/getDefaultCspSettings\n * @global\n * @desc\n * ```js\n * import { server } from '@dr.pogodin/react-utils';\n * const { getDefaultCspSettings } from '@dr.pogodin/react-utils';\n * ```\n * @return {{\n * directives: object\n * }} A deep copy of default CSP settings object used by `react-utils`,\n * with the exception of `nonce-xxx` clause in `script-src` directive,\n * which is added dynamically for each request.\n */\nexport function getDefaultCspSettings() {\n return cloneDeep(defaultCspSettings);\n}\n\nexport default async function factory(webpackConfig, options) {\n const rendererOps = pick(options, [\n 'Application',\n 'beforeRender',\n 'favicon',\n 'logger',\n 'maxSsrRounds',\n 'noCsp',\n 'ssrTimeout',\n 'staticCacheController',\n 'staticCacheSize',\n ]);\n const renderer = rendererFactory(webpackConfig, rendererOps);\n const { publicPath } = webpackConfig.output;\n\n const server = express();\n\n if (options.beforeExpressJsSetup) {\n await options.beforeExpressJsSetup(server);\n }\n\n server.logger = options.logger;\n\n if (options.httpsRedirect) {\n server.use((req, res, next) => {\n const schema = req.headers['x-forwarded-proto'];\n if (schema === 'http') {\n let url = `https://${req.headers.host}`;\n if (req.originalUrl !== '/') url += req.originalUrl;\n return res.redirect(url);\n }\n return next();\n });\n }\n\n server.use(compression());\n server.use(\n helmet({\n contentSecurityPolicy: false,\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n }),\n );\n\n if (!options.noCsp) {\n server.use((req, res, next) => {\n req.nonce = uuid();\n\n // TODO: This is deprecated, but it is kept for now for backward\n // compatibility. Should be removed sometime later.\n req.cspNonce = req.nonce;\n\n // The deep clone is necessary here to ensure that default value can't be\n // mutated during request processing.\n let cspSettings = cloneDeep(defaultCspSettings);\n cspSettings.directives['script-src'].push(`'nonce-${req.nonce}'`);\n if (options.cspSettingsHook) {\n cspSettings = options.cspSettingsHook(cspSettings, req);\n }\n helmet.contentSecurityPolicy(cspSettings)(req, res, next);\n });\n }\n\n if (options.favicon) {\n server.use(favicon(options.favicon));\n }\n\n server.use('/robots.txt', (req, res) => res.send('User-agent: *\\nDisallow:'));\n\n server.use(express.json({ limit: '300kb' }));\n server.use(express.urlencoded({ extended: false }));\n server.use(cookieParser());\n server.use(requestIp.mw());\n\n loggerMiddleware.token('ip', (req) => req.clientIp);\n const FORMAT = ':ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent';\n server.use(loggerMiddleware(FORMAT, {\n stream: {\n write: options.logger.info.bind(options.logger),\n },\n }));\n\n // Note: no matter the \"public path\", we want the service worker, if any,\n // to be served from the root, to have all web app pages in its scope.\n // Thus, this setup to serve it. Probably, need some more configuration\n // for special cases, but this will do for now.\n server.get('/__service-worker.js', express.static(\n webpackConfig.output.path,\n {\n setHeaders: (res) => res.set('Cache-Control', 'no-cache'),\n },\n ));\n\n /* Setup of Hot Module Reloading for development environment.\n * These dependencies are not used, nor installed for production use,\n * hence we should violate some import-related lint rules. */\n /* eslint-disable global-require */\n /* eslint-disable import/no-extraneous-dependencies */\n /* eslint-disable import/no-unresolved */\n if (options.devMode) {\n // This is a workaround for SASS bug:\n // https://github.com/dart-lang/sdk/issues/27979\n // which manifests itself sometimes when webpack dev middleware is used\n // (in dev mode), and app modules are imported in some unfortunate ways.\n if (!global.location) {\n global.location = {\n href: `${pathToFileURL(process.cwd()).href}${sep}`,\n };\n }\n\n const webpack = require('webpack');\n const webpackDevMiddleware = require('webpack-dev-middleware');\n const webpackHotMiddleware = require('webpack-hot-middleware');\n const compiler = webpack(webpackConfig);\n server.use(webpackDevMiddleware(compiler, {\n publicPath,\n serverSideRender: true,\n }));\n server.use(webpackHotMiddleware(compiler));\n }\n /* eslint-enable global-require */\n /* eslint-enable import/no-extraneous-dependencies */\n /* eslint-enable import/no-unresolved */\n\n server.use(publicPath, express.static(webpackConfig.output.path));\n\n if (options.onExpressJsSetup) {\n await options.onExpressJsSetup(server);\n }\n server.use(renderer);\n\n /* Detects 404 errors, and forwards them to the error handler. */\n server.use((req, res, next) => {\n next(newError(ERRORS.NOT_FOUND, CODES.NOT_FOUND));\n });\n\n let dontAttachDefaultErrorHandler;\n if (options.beforeExpressJsError) {\n dontAttachDefaultErrorHandler = await options.beforeExpressJsError(server);\n }\n\n /* Error handler. */\n if (!dontAttachDefaultErrorHandler) {\n // TODO: Do we need this error handler at all? It actually seems to do\n // what the default ExpressJS error handler does anyway, see:\n // https://expressjs.com/en/guide/error-handling.html\n //\n // TODO: It is better to move the default error handler definition\n // to a stand-alone function at top-level, but the use of options.logger\n // prevents to do it without some extra refactoring. Should be done sometime\n // though.\n server.use((error, req, res, next) => {\n // TODO: This is needed to correctly handled any errors thrown after\n // sending initial response to the client.\n if (res.headersSent) return next(error);\n\n const status = error.status || CODES.INTERNAL_SERVER_ERROR;\n const serverSide = status >= CODES.INTERNAL_SERVER_ERROR;\n\n // Log server-side errors always, client-side at debug level only.\n options.logger.log(serverSide ? 'error' : 'debug', error);\n\n let message = error.message || getErrorForCode(status);\n if (serverSide && process.env.NODE_ENV === 'production') {\n message = ERRORS.INTERNAL_SERVER_ERROR;\n }\n\n res.status(status).send(message);\n return undefined;\n });\n }\n\n return server;\n}\n"],"mappings":"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"}
@@ -4,7 +4,11 @@
4
4
  // is bundled into client-side code.
5
5
  /* `BUILD_INFO` is always injected by Webpack build, but this check is needed
6
6
  * to adopt the code for usage in tests. */if(typeof BUILD_INFO!=="undefined"){window.TRU_BUILD_INFO=BUILD_INFO}/* Removes data injection script out of the document.
7
- * The if block is here for test purposes. */if(!window.TRU_KEEP_INJ_SCRIPT){const block=document.querySelector("script[id=\"inj\"]");if(block)document.getElementsByTagName("body")[0].removeChild(block)}/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */ /* eslint-disable no-console */const{publicPath,useServiceWorker}=window.TRU_BUILD_INFO;if(useServiceWorker){const{navigator}=window;if("serviceWorker"in navigator){window.addEventListener("load",async()=>{try{const reg=await navigator.serviceWorker.register("".concat(publicPath,"/__service-worker.js"));console.log("SW registered:",reg)}catch(err){console.log("SW registration failed:",err)}})}}/* eslint-enable no-console */ /* Decodes data injected at the server side. */if(window.INJ){const{key}=window.TRU_BUILD_INFO;let data=_forge.default.util.decode64(window.INJ);const decipher=_forge.default.cipher.createDecipher("AES-CBC",key);decipher.start({iv:data.slice(0,32)});decipher.update(_forge.default.util.createBuffer(data.slice(32)));decipher.finish();data=_forge.default.util.decodeUtf8(decipher.output.data);data=eval("(".concat(data,")"));// eslint-disable-line no-eval
7
+ * The if block is here for test purposes. */if(!window.TRU_KEEP_INJ_SCRIPT){const block=document.querySelector("script[id=\"inj\"]");if(block)document.getElementsByTagName("body")[0].removeChild(block)}/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */ /* eslint-disable no-console */const{useServiceWorker}=window.TRU_BUILD_INFO;if(useServiceWorker){const{navigator}=window;if("serviceWorker"in navigator){window.addEventListener("load",async()=>{try{// Note: no matter the "publicPath", we want to serve the service worker
8
+ // from the web app root, to allow it control any and all pages of the
9
+ // web app (otherwise, it will be restricted to the scope of its path).
10
+ // The server takes it into account.
11
+ const reg=await navigator.serviceWorker.register("/__service-worker.js");console.log("SW registered:",reg)}catch(err){console.log("SW registration failed:",err)}})}}/* eslint-enable no-console */ /* Decodes data injected at the server side. */if(window.INJ){const{key}=window.TRU_BUILD_INFO;let data=_forge.default.util.decode64(window.INJ);const decipher=_forge.default.cipher.createDecipher("AES-CBC",key);decipher.start({iv:data.slice(0,32)});decipher.update(_forge.default.util.createBuffer(data.slice(32)));decipher.finish();data=_forge.default.util.decodeUtf8(decipher.output.data);data=eval("(".concat(data,")"));// eslint-disable-line no-eval
8
12
  window.CHUNK_GROUPS=data.CHUNK_GROUPS;window.CONFIG=data.CONFIG;window.ISTATE=data.ISTATE}else{// This is possible when the client-side bundle is launched as a stand-alone
9
13
  // precompiled website, rather than served by react-utils' based server.
10
14
  window.CHUNK_GROUPS={};window.CONFIG={}}
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","names":["BUILD_INFO","window","TRU_BUILD_INFO","TRU_KEEP_INJ_SCRIPT","block","document","querySelector","getElementsByTagName","removeChild","publicPath","useServiceWorker","navigator","addEventListener","reg","serviceWorker","register","console","log","err","INJ","key","data","forge","util","decode64","decipher","cipher","createDecipher","start","iv","slice","update","createBuffer","finish","decodeUtf8","output","eval","CHUNK_GROUPS","CONFIG","ISTATE"],"sources":["../../../src/client/init.js"],"sourcesContent":["/**\n * Initialization of client-side environment.\n */\n\n/* global BUILD_INFO, document, window */\n\n// Note: this way, only required part of \"node-forge\": AES, and some utils,\n// is bundled into client-side code.\nimport forge from 'node-forge/lib/forge';\nimport 'node-forge/lib/aes';\n\n/* `BUILD_INFO` is always injected by Webpack build, but this check is needed\n * to adopt the code for usage in tests. */\nif (typeof BUILD_INFO !== 'undefined') {\n window.TRU_BUILD_INFO = BUILD_INFO;\n}\n\n/* Removes data injection script out of the document.\n * The if block is here for test purposes. */\nif (!window.TRU_KEEP_INJ_SCRIPT) {\n const block = document.querySelector('script[id=\"inj\"]');\n if (block) document.getElementsByTagName('body')[0].removeChild(block);\n}\n\n/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */\n/* eslint-disable no-console */\nconst { publicPath, useServiceWorker } = window.TRU_BUILD_INFO;\nif (useServiceWorker) {\n const { navigator } = window;\n if ('serviceWorker' in navigator) {\n window.addEventListener('load', async () => {\n try {\n const reg = await navigator\n .serviceWorker.register(`${publicPath}/__service-worker.js`);\n console.log('SW registered:', reg);\n } catch (err) {\n console.log('SW registration failed:', err);\n }\n });\n }\n}\n/* eslint-enable no-console */\n\n/* Decodes data injected at the server side. */\nif (window.INJ) {\n const { key } = window.TRU_BUILD_INFO;\n let data = forge.util.decode64(window.INJ);\n const decipher = forge.cipher.createDecipher('AES-CBC', key);\n decipher.start({ iv: data.slice(0, 32) });\n decipher.update(forge.util.createBuffer(data.slice(32)));\n decipher.finish();\n\n data = forge.util.decodeUtf8(decipher.output.data);\n data = eval(`(${data})`); // eslint-disable-line no-eval\n\n window.CHUNK_GROUPS = data.CHUNK_GROUPS;\n window.CONFIG = data.CONFIG;\n window.ISTATE = data.ISTATE;\n} else {\n // This is possible when the client-side bundle is launched as a stand-alone\n // precompiled website, rather than served by react-utils' based server.\n window.CHUNK_GROUPS = {};\n window.CONFIG = {};\n}\n"],"mappings":"gGAQA,mEACA,8BATA;AACA;AACA,G,CAEA,yC,CAEA;AACA;AAIA;AACA,2CACA,GAAI,MAAOA,WAAP,GAAsB,WAA1B,CAAuC,CACrCC,MAAM,CAACC,cAAP,CAAwBF,UACzB,CAED;AACA,6CACA,GAAI,CAACC,MAAM,CAACE,mBAAZ,CAAiC,CAC/B,KAAMC,MAAK,CAAGC,QAAQ,CAACC,aAAT,CAAuB,oBAAvB,CAAd,CACA,GAAIF,KAAJ,CAAWC,QAAQ,CAACE,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,EAAyCC,WAAzC,CAAqDJ,KAArD,CACZ,CAED,yE,CACA,+BACA,KAAM,CAAEK,UAAF,CAAcC,gBAAd,EAAmCT,MAAM,CAACC,cAAhD,CACA,GAAIQ,gBAAJ,CAAsB,CACpB,KAAM,CAAEC,SAAF,EAAgBV,MAAtB,CACA,GAAI,iBAAmBU,UAAvB,CAAkC,CAChCV,MAAM,CAACW,gBAAP,CAAwB,MAAxB,CAAgC,SAAY,CAC1C,GAAI,CACF,KAAMC,IAAG,CAAG,KAAMF,UAAS,CACxBG,aADe,CACDC,QADC,WACWN,UADX,yBAAlB,CAEAO,OAAO,CAACC,GAAR,CAAY,gBAAZ,CAA8BJ,GAA9B,CACD,CAAC,MAAOK,GAAP,CAAY,CACZF,OAAO,CAACC,GAAR,CAAY,yBAAZ,CAAuCC,GAAvC,CACD,CACF,CARD,CASD,CACF,CACD,8B,CAEA,+CACA,GAAIjB,MAAM,CAACkB,GAAX,CAAgB,CACd,KAAM,CAAEC,GAAF,EAAUnB,MAAM,CAACC,cAAvB,CACA,GAAImB,KAAI,CAAGC,cAAA,CAAMC,IAAN,CAAWC,QAAX,CAAoBvB,MAAM,CAACkB,GAA3B,CAAX,CACA,KAAMM,SAAQ,CAAGH,cAAA,CAAMI,MAAN,CAAaC,cAAb,CAA4B,SAA5B,CAAuCP,GAAvC,CAAjB,CACAK,QAAQ,CAACG,KAAT,CAAe,CAAEC,EAAE,CAAER,IAAI,CAACS,KAAL,CAAW,CAAX,CAAc,EAAd,CAAN,CAAf,EACAL,QAAQ,CAACM,MAAT,CAAgBT,cAAA,CAAMC,IAAN,CAAWS,YAAX,CAAwBX,IAAI,CAACS,KAAL,CAAW,EAAX,CAAxB,CAAhB,EACAL,QAAQ,CAACQ,MAAT,GAEAZ,IAAI,CAAGC,cAAA,CAAMC,IAAN,CAAWW,UAAX,CAAsBT,QAAQ,CAACU,MAAT,CAAgBd,IAAtC,CAAP,CACAA,IAAI,CAAGe,IAAI,YAAKf,IAAL,MAAX,CAA0B;AAE1BpB,MAAM,CAACoC,YAAP,CAAsBhB,IAAI,CAACgB,YAA3B,CACApC,MAAM,CAACqC,MAAP,CAAgBjB,IAAI,CAACiB,MAArB,CACArC,MAAM,CAACsC,MAAP,CAAgBlB,IAAI,CAACkB,MACtB,CAdD,IAcO,CACL;AACA;AACAtC,MAAM,CAACoC,YAAP,CAAsB,EAAtB,CACApC,MAAM,CAACqC,MAAP,CAAgB,EACjB"}
1
+ {"version":3,"file":"init.js","names":["BUILD_INFO","window","TRU_BUILD_INFO","TRU_KEEP_INJ_SCRIPT","block","document","querySelector","getElementsByTagName","removeChild","useServiceWorker","navigator","addEventListener","reg","serviceWorker","register","console","log","err","INJ","key","data","forge","util","decode64","decipher","cipher","createDecipher","start","iv","slice","update","createBuffer","finish","decodeUtf8","output","eval","CHUNK_GROUPS","CONFIG","ISTATE"],"sources":["../../../src/client/init.js"],"sourcesContent":["/**\n * Initialization of client-side environment.\n */\n\n/* global BUILD_INFO, document, window */\n\n// Note: this way, only required part of \"node-forge\": AES, and some utils,\n// is bundled into client-side code.\nimport forge from 'node-forge/lib/forge';\nimport 'node-forge/lib/aes';\n\n/* `BUILD_INFO` is always injected by Webpack build, but this check is needed\n * to adopt the code for usage in tests. */\nif (typeof BUILD_INFO !== 'undefined') {\n window.TRU_BUILD_INFO = BUILD_INFO;\n}\n\n/* Removes data injection script out of the document.\n * The if block is here for test purposes. */\nif (!window.TRU_KEEP_INJ_SCRIPT) {\n const block = document.querySelector('script[id=\"inj\"]');\n if (block) document.getElementsByTagName('body')[0].removeChild(block);\n}\n\n/* TODO: A proper logger should be moved to `@dr.pogodin/react-utils`. */\n/* eslint-disable no-console */\nconst { useServiceWorker } = window.TRU_BUILD_INFO;\nif (useServiceWorker) {\n const { navigator } = window;\n if ('serviceWorker' in navigator) {\n window.addEventListener('load', async () => {\n try {\n // Note: no matter the \"publicPath\", we want to serve the service worker\n // from the web app root, to allow it control any and all pages of the\n // web app (otherwise, it will be restricted to the scope of its path).\n // The server takes it into account.\n const reg = await navigator\n .serviceWorker.register('/__service-worker.js');\n console.log('SW registered:', reg);\n } catch (err) {\n console.log('SW registration failed:', err);\n }\n });\n }\n}\n/* eslint-enable no-console */\n\n/* Decodes data injected at the server side. */\nif (window.INJ) {\n const { key } = window.TRU_BUILD_INFO;\n let data = forge.util.decode64(window.INJ);\n const decipher = forge.cipher.createDecipher('AES-CBC', key);\n decipher.start({ iv: data.slice(0, 32) });\n decipher.update(forge.util.createBuffer(data.slice(32)));\n decipher.finish();\n\n data = forge.util.decodeUtf8(decipher.output.data);\n data = eval(`(${data})`); // eslint-disable-line no-eval\n\n window.CHUNK_GROUPS = data.CHUNK_GROUPS;\n window.CONFIG = data.CONFIG;\n window.ISTATE = data.ISTATE;\n} else {\n // This is possible when the client-side bundle is launched as a stand-alone\n // precompiled website, rather than served by react-utils' based server.\n window.CHUNK_GROUPS = {};\n window.CONFIG = {};\n}\n"],"mappings":"gGAQA,mEACA,8BATA;AACA;AACA,G,CAEA,yC,CAEA;AACA;AAIA;AACA,2CACA,GAAI,MAAOA,WAAP,GAAsB,WAA1B,CAAuC,CACrCC,MAAM,CAACC,cAAP,CAAwBF,UACzB,CAED;AACA,6CACA,GAAI,CAACC,MAAM,CAACE,mBAAZ,CAAiC,CAC/B,KAAMC,MAAK,CAAGC,QAAQ,CAACC,aAAT,CAAuB,oBAAvB,CAAd,CACA,GAAIF,KAAJ,CAAWC,QAAQ,CAACE,oBAAT,CAA8B,MAA9B,EAAsC,CAAtC,EAAyCC,WAAzC,CAAqDJ,KAArD,CACZ,CAED,yE,CACA,+BACA,KAAM,CAAEK,gBAAF,EAAuBR,MAAM,CAACC,cAApC,CACA,GAAIO,gBAAJ,CAAsB,CACpB,KAAM,CAAEC,SAAF,EAAgBT,MAAtB,CACA,GAAI,iBAAmBS,UAAvB,CAAkC,CAChCT,MAAM,CAACU,gBAAP,CAAwB,MAAxB,CAAgC,SAAY,CAC1C,GAAI,CACF;AACA;AACA;AACA;AACA,KAAMC,IAAG,CAAG,KAAMF,UAAS,CACxBG,aADe,CACDC,QADC,CACQ,sBADR,CAAlB,CAEAC,OAAO,CAACC,GAAR,CAAY,gBAAZ,CAA8BJ,GAA9B,CACD,CAAC,MAAOK,GAAP,CAAY,CACZF,OAAO,CAACC,GAAR,CAAY,yBAAZ,CAAuCC,GAAvC,CACD,CACF,CAZD,CAaD,CACF,CACD,8B,CAEA,+CACA,GAAIhB,MAAM,CAACiB,GAAX,CAAgB,CACd,KAAM,CAAEC,GAAF,EAAUlB,MAAM,CAACC,cAAvB,CACA,GAAIkB,KAAI,CAAGC,cAAA,CAAMC,IAAN,CAAWC,QAAX,CAAoBtB,MAAM,CAACiB,GAA3B,CAAX,CACA,KAAMM,SAAQ,CAAGH,cAAA,CAAMI,MAAN,CAAaC,cAAb,CAA4B,SAA5B,CAAuCP,GAAvC,CAAjB,CACAK,QAAQ,CAACG,KAAT,CAAe,CAAEC,EAAE,CAAER,IAAI,CAACS,KAAL,CAAW,CAAX,CAAc,EAAd,CAAN,CAAf,EACAL,QAAQ,CAACM,MAAT,CAAgBT,cAAA,CAAMC,IAAN,CAAWS,YAAX,CAAwBX,IAAI,CAACS,KAAL,CAAW,EAAX,CAAxB,CAAhB,EACAL,QAAQ,CAACQ,MAAT,GAEAZ,IAAI,CAAGC,cAAA,CAAMC,IAAN,CAAWW,UAAX,CAAsBT,QAAQ,CAACU,MAAT,CAAgBd,IAAtC,CAAP,CACAA,IAAI,CAAGe,IAAI,YAAKf,IAAL,MAAX,CAA0B;AAE1BnB,MAAM,CAACmC,YAAP,CAAsBhB,IAAI,CAACgB,YAA3B,CACAnC,MAAM,CAACoC,MAAP,CAAgBjB,IAAI,CAACiB,MAArB,CACApC,MAAM,CAACqC,MAAP,CAAgBlB,IAAI,CAACkB,MACtB,CAdD,IAcO,CACL;AACA;AACArC,MAAM,CAACmC,YAAP,CAAsB,EAAtB,CACAnC,MAAM,CAACoC,MAAP,CAAgB,EACjB"}
@@ -30,7 +30,11 @@ delete defaultCspSettings.directives["upgrade-insecure-requests"];/**
30
30
  // compatibility. Should be removed sometime later.
31
31
  req.cspNonce=req.nonce;// The deep clone is necessary here to ensure that default value can't be
32
32
  // mutated during request processing.
33
- let cspSettings=(0,_lodash.cloneDeep)(defaultCspSettings);cspSettings.directives["script-src"].push(`'nonce-${req.nonce}'`);if(options.cspSettingsHook){cspSettings=options.cspSettingsHook(cspSettings,req)}_helmet.default.contentSecurityPolicy(cspSettings)(req,res,next)})}if(options.favicon){server.use((0,_serveFavicon.default)(options.favicon))}server.use("/robots.txt",(req,res)=>res.send("User-agent: *\nDisallow:"));server.use(_express.default.json({limit:"300kb"}));server.use(_express.default.urlencoded({extended:false}));server.use((0,_cookieParser.default)());server.use(_requestIp.default.mw());_morgan.default.token("ip",req=>req.clientIp);const FORMAT=":ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent";server.use((0,_morgan.default)(FORMAT,{stream:{write:options.logger.info.bind(options.logger)}}));/* Ensures no caching for the service worker script. */server.use(`${publicPath}service-worker.js`,(req,res,next)=>{res.header("Cache-Control","no-cache");next()});/* Setup of Hot Module Reloading for development environment.
33
+ let cspSettings=(0,_lodash.cloneDeep)(defaultCspSettings);cspSettings.directives["script-src"].push(`'nonce-${req.nonce}'`);if(options.cspSettingsHook){cspSettings=options.cspSettingsHook(cspSettings,req)}_helmet.default.contentSecurityPolicy(cspSettings)(req,res,next)})}if(options.favicon){server.use((0,_serveFavicon.default)(options.favicon))}server.use("/robots.txt",(req,res)=>res.send("User-agent: *\nDisallow:"));server.use(_express.default.json({limit:"300kb"}));server.use(_express.default.urlencoded({extended:false}));server.use((0,_cookieParser.default)());server.use(_requestIp.default.mw());_morgan.default.token("ip",req=>req.clientIp);const FORMAT=":ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent";server.use((0,_morgan.default)(FORMAT,{stream:{write:options.logger.info.bind(options.logger)}}));// Note: no matter the "public path", we want the service worker, if any,
34
+ // to be served from the root, to have all web app pages in its scope.
35
+ // Thus, this setup to serve it. Probably, need some more configuration
36
+ // for special cases, but this will do for now.
37
+ server.get("/__service-worker.js",_express.default.static(webpackConfig.output.path,{setHeaders:res=>res.set("Cache-Control","no-cache")}));/* Setup of Hot Module Reloading for development environment.
34
38
  * These dependencies are not used, nor installed for production use,
35
39
  * hence we should violate some import-related lint rules. */ /* eslint-disable global-require */ /* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/no-unresolved */if(options.devMode){// This is a workaround for SASS bug:
36
40
  // https://github.com/dart-lang/sdk/issues/27979
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":["defaultCspSettings","directives","mapValues","helmet","contentSecurityPolicy","getDefaultDirectives","array","filter","item","push","getDefaultCspSettings","cloneDeep","factory","webpackConfig","options","rendererOps","pick","renderer","rendererFactory","publicPath","output","server","express","beforeExpressJsSetup","logger","httpsRedirect","use","req","res","next","schema","headers","url","host","originalUrl","redirect","compression","crossOriginEmbedderPolicy","crossOriginOpenerPolicy","crossOriginResourcePolicy","noCsp","nonce","uuid","cspNonce","cspSettings","cspSettingsHook","favicon","send","json","limit","urlencoded","extended","cookieParser","requestIp","mw","loggerMiddleware","token","clientIp","FORMAT","stream","write","info","bind","header","devMode","global","location","href","pathToFileURL","process","cwd","sep","webpack","require","webpackDevMiddleware","webpackHotMiddleware","compiler","serverSideRender","static","path","onExpressJsSetup","newError","ERRORS","NOT_FOUND","CODES","dontAttachDefaultErrorHandler","beforeExpressJsError","error","headersSent","status","INTERNAL_SERVER_ERROR","serverSide","log","message","getErrorForCode","env","NODE_ENV","undefined"],"sources":["../../../src/server/server.js"],"sourcesContent":["/**\n * Creation of standard ExpressJS server for ReactJS apps.\n */\n\nimport { sep } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport {\n cloneDeep,\n mapValues,\n pick,\n} from 'lodash';\n\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport express from 'express';\nimport favicon from 'serve-favicon';\nimport helmet from 'helmet';\nimport loggerMiddleware from 'morgan';\nimport requestIp from 'request-ip';\nimport { v4 as uuid } from 'uuid';\n\nimport rendererFactory from './renderer';\n\nimport {\n CODES,\n ERRORS,\n getErrorForCode,\n newError,\n} from './utils/errors';\n\n/**\n * Default Content Security Policy settings.\n * @ignore\n */\nconst defaultCspSettings = {\n directives: mapValues(\n helmet.contentSecurityPolicy.getDefaultDirectives(),\n\n // 'https:' options (automatic re-write of insecure URLs to secure ones)\n // is removed to facilitate local development with HTTP server. In cloud\n // deployments we assume Apache or Nginx server in front of out app takes\n // care about such re-writes.\n (array) => array.filter((item) => item !== 'https:'),\n ),\n};\ndefaultCspSettings.directives['frame-src'] = [\n \"'self'\",\n\n // YouTube domain is whitelisted to allow <YouTubeVideo> component to work\n // out of box.\n 'https://*.youtube.com',\n];\ndefaultCspSettings.directives['script-src'].push(\"'unsafe-eval'\");\n\n// No need for automatic re-writes via Content Security Policy settings:\n// the forefront Apache or Nginx server is supposed to take care of this\n// in production cloud deployments.\ndelete defaultCspSettings.directives['upgrade-insecure-requests'];\n\n/**\n * @category Utilities\n * @func server/getDefaultCspSettings\n * @global\n * @desc\n * ```js\n * import { server } from '@dr.pogodin/react-utils';\n * const { getDefaultCspSettings } from '@dr.pogodin/react-utils';\n * ```\n * @return {{\n * directives: object\n * }} A deep copy of default CSP settings object used by `react-utils`,\n * with the exception of `nonce-xxx` clause in `script-src` directive,\n * which is added dynamically for each request.\n */\nexport function getDefaultCspSettings() {\n return cloneDeep(defaultCspSettings);\n}\n\nexport default async function factory(webpackConfig, options) {\n const rendererOps = pick(options, [\n 'Application',\n 'beforeRender',\n 'favicon',\n 'logger',\n 'maxSsrRounds',\n 'noCsp',\n 'ssrTimeout',\n 'staticCacheController',\n 'staticCacheSize',\n ]);\n const renderer = rendererFactory(webpackConfig, rendererOps);\n const { publicPath } = webpackConfig.output;\n\n const server = express();\n\n if (options.beforeExpressJsSetup) {\n await options.beforeExpressJsSetup(server);\n }\n\n server.logger = options.logger;\n\n if (options.httpsRedirect) {\n server.use((req, res, next) => {\n const schema = req.headers['x-forwarded-proto'];\n if (schema === 'http') {\n let url = `https://${req.headers.host}`;\n if (req.originalUrl !== '/') url += req.originalUrl;\n return res.redirect(url);\n }\n return next();\n });\n }\n\n server.use(compression());\n server.use(\n helmet({\n contentSecurityPolicy: false,\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n }),\n );\n\n if (!options.noCsp) {\n server.use((req, res, next) => {\n req.nonce = uuid();\n\n // TODO: This is deprecated, but it is kept for now for backward\n // compatibility. Should be removed sometime later.\n req.cspNonce = req.nonce;\n\n // The deep clone is necessary here to ensure that default value can't be\n // mutated during request processing.\n let cspSettings = cloneDeep(defaultCspSettings);\n cspSettings.directives['script-src'].push(`'nonce-${req.nonce}'`);\n if (options.cspSettingsHook) {\n cspSettings = options.cspSettingsHook(cspSettings, req);\n }\n helmet.contentSecurityPolicy(cspSettings)(req, res, next);\n });\n }\n\n if (options.favicon) {\n server.use(favicon(options.favicon));\n }\n\n server.use('/robots.txt', (req, res) => res.send('User-agent: *\\nDisallow:'));\n\n server.use(express.json({ limit: '300kb' }));\n server.use(express.urlencoded({ extended: false }));\n server.use(cookieParser());\n server.use(requestIp.mw());\n\n loggerMiddleware.token('ip', (req) => req.clientIp);\n const FORMAT = ':ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent';\n server.use(loggerMiddleware(FORMAT, {\n stream: {\n write: options.logger.info.bind(options.logger),\n },\n }));\n\n /* Ensures no caching for the service worker script. */\n server.use(`${publicPath}service-worker.js`, (req, res, next) => {\n res.header('Cache-Control', 'no-cache');\n next();\n });\n\n /* Setup of Hot Module Reloading for development environment.\n * These dependencies are not used, nor installed for production use,\n * hence we should violate some import-related lint rules. */\n /* eslint-disable global-require */\n /* eslint-disable import/no-extraneous-dependencies */\n /* eslint-disable import/no-unresolved */\n if (options.devMode) {\n // This is a workaround for SASS bug:\n // https://github.com/dart-lang/sdk/issues/27979\n // which manifests itself sometimes when webpack dev middleware is used\n // (in dev mode), and app modules are imported in some unfortunate ways.\n if (!global.location) {\n global.location = {\n href: `${pathToFileURL(process.cwd()).href}${sep}`,\n };\n }\n\n const webpack = require('webpack');\n const webpackDevMiddleware = require('webpack-dev-middleware');\n const webpackHotMiddleware = require('webpack-hot-middleware');\n const compiler = webpack(webpackConfig);\n server.use(webpackDevMiddleware(compiler, {\n publicPath,\n serverSideRender: true,\n }));\n server.use(webpackHotMiddleware(compiler));\n }\n /* eslint-enable global-require */\n /* eslint-enable import/no-extraneous-dependencies */\n /* eslint-enable import/no-unresolved */\n\n server.use(publicPath, express.static(webpackConfig.output.path));\n\n if (options.onExpressJsSetup) {\n await options.onExpressJsSetup(server);\n }\n server.use(renderer);\n\n /* Detects 404 errors, and forwards them to the error handler. */\n server.use((req, res, next) => {\n next(newError(ERRORS.NOT_FOUND, CODES.NOT_FOUND));\n });\n\n let dontAttachDefaultErrorHandler;\n if (options.beforeExpressJsError) {\n dontAttachDefaultErrorHandler = await options.beforeExpressJsError(server);\n }\n\n /* Error handler. */\n if (!dontAttachDefaultErrorHandler) {\n // TODO: Do we need this error handler at all? It actually seems to do\n // what the default ExpressJS error handler does anyway, see:\n // https://expressjs.com/en/guide/error-handling.html\n //\n // TODO: It is better to move the default error handler definition\n // to a stand-alone function at top-level, but the use of options.logger\n // prevents to do it without some extra refactoring. Should be done sometime\n // though.\n server.use((error, req, res, next) => {\n // TODO: This is needed to correctly handled any errors thrown after\n // sending initial response to the client.\n if (res.headersSent) return next(error);\n\n const status = error.status || CODES.INTERNAL_SERVER_ERROR;\n const serverSide = status >= CODES.INTERNAL_SERVER_ERROR;\n\n // Log server-side errors always, client-side at debug level only.\n options.logger.log(serverSide ? 'error' : 'debug', error);\n\n let message = error.message || getErrorForCode(status);\n if (serverSide && process.env.NODE_ENV === 'production') {\n message = ERRORS.INTERNAL_SERVER_ERROR;\n }\n\n res.status(status).send(message);\n return undefined;\n });\n }\n\n return server;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.js","names":["defaultCspSettings","directives","mapValues","helmet","contentSecurityPolicy","getDefaultDirectives","array","filter","item","push","getDefaultCspSettings","cloneDeep","factory","webpackConfig","options","rendererOps","pick","renderer","rendererFactory","publicPath","output","server","express","beforeExpressJsSetup","logger","httpsRedirect","use","req","res","next","schema","headers","url","host","originalUrl","redirect","compression","crossOriginEmbedderPolicy","crossOriginOpenerPolicy","crossOriginResourcePolicy","noCsp","nonce","uuid","cspNonce","cspSettings","cspSettingsHook","favicon","send","json","limit","urlencoded","extended","cookieParser","requestIp","mw","loggerMiddleware","token","clientIp","FORMAT","stream","write","info","bind","get","static","path","setHeaders","set","devMode","global","location","href","pathToFileURL","process","cwd","sep","webpack","require","webpackDevMiddleware","webpackHotMiddleware","compiler","serverSideRender","onExpressJsSetup","newError","ERRORS","NOT_FOUND","CODES","dontAttachDefaultErrorHandler","beforeExpressJsError","error","headersSent","status","INTERNAL_SERVER_ERROR","serverSide","log","message","getErrorForCode","env","NODE_ENV","undefined"],"sources":["../../../src/server/server.js"],"sourcesContent":["/**\n * Creation of standard ExpressJS server for ReactJS apps.\n */\n\nimport { sep } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport {\n cloneDeep,\n mapValues,\n pick,\n} from 'lodash';\n\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport express from 'express';\nimport favicon from 'serve-favicon';\nimport helmet from 'helmet';\nimport loggerMiddleware from 'morgan';\nimport requestIp from 'request-ip';\nimport { v4 as uuid } from 'uuid';\n\nimport rendererFactory from './renderer';\n\nimport {\n CODES,\n ERRORS,\n getErrorForCode,\n newError,\n} from './utils/errors';\n\n/**\n * Default Content Security Policy settings.\n * @ignore\n */\nconst defaultCspSettings = {\n directives: mapValues(\n helmet.contentSecurityPolicy.getDefaultDirectives(),\n\n // 'https:' options (automatic re-write of insecure URLs to secure ones)\n // is removed to facilitate local development with HTTP server. In cloud\n // deployments we assume Apache or Nginx server in front of out app takes\n // care about such re-writes.\n (array) => array.filter((item) => item !== 'https:'),\n ),\n};\ndefaultCspSettings.directives['frame-src'] = [\n \"'self'\",\n\n // YouTube domain is whitelisted to allow <YouTubeVideo> component to work\n // out of box.\n 'https://*.youtube.com',\n];\ndefaultCspSettings.directives['script-src'].push(\"'unsafe-eval'\");\n\n// No need for automatic re-writes via Content Security Policy settings:\n// the forefront Apache or Nginx server is supposed to take care of this\n// in production cloud deployments.\ndelete defaultCspSettings.directives['upgrade-insecure-requests'];\n\n/**\n * @category Utilities\n * @func server/getDefaultCspSettings\n * @global\n * @desc\n * ```js\n * import { server } from '@dr.pogodin/react-utils';\n * const { getDefaultCspSettings } from '@dr.pogodin/react-utils';\n * ```\n * @return {{\n * directives: object\n * }} A deep copy of default CSP settings object used by `react-utils`,\n * with the exception of `nonce-xxx` clause in `script-src` directive,\n * which is added dynamically for each request.\n */\nexport function getDefaultCspSettings() {\n return cloneDeep(defaultCspSettings);\n}\n\nexport default async function factory(webpackConfig, options) {\n const rendererOps = pick(options, [\n 'Application',\n 'beforeRender',\n 'favicon',\n 'logger',\n 'maxSsrRounds',\n 'noCsp',\n 'ssrTimeout',\n 'staticCacheController',\n 'staticCacheSize',\n ]);\n const renderer = rendererFactory(webpackConfig, rendererOps);\n const { publicPath } = webpackConfig.output;\n\n const server = express();\n\n if (options.beforeExpressJsSetup) {\n await options.beforeExpressJsSetup(server);\n }\n\n server.logger = options.logger;\n\n if (options.httpsRedirect) {\n server.use((req, res, next) => {\n const schema = req.headers['x-forwarded-proto'];\n if (schema === 'http') {\n let url = `https://${req.headers.host}`;\n if (req.originalUrl !== '/') url += req.originalUrl;\n return res.redirect(url);\n }\n return next();\n });\n }\n\n server.use(compression());\n server.use(\n helmet({\n contentSecurityPolicy: false,\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n }),\n );\n\n if (!options.noCsp) {\n server.use((req, res, next) => {\n req.nonce = uuid();\n\n // TODO: This is deprecated, but it is kept for now for backward\n // compatibility. Should be removed sometime later.\n req.cspNonce = req.nonce;\n\n // The deep clone is necessary here to ensure that default value can't be\n // mutated during request processing.\n let cspSettings = cloneDeep(defaultCspSettings);\n cspSettings.directives['script-src'].push(`'nonce-${req.nonce}'`);\n if (options.cspSettingsHook) {\n cspSettings = options.cspSettingsHook(cspSettings, req);\n }\n helmet.contentSecurityPolicy(cspSettings)(req, res, next);\n });\n }\n\n if (options.favicon) {\n server.use(favicon(options.favicon));\n }\n\n server.use('/robots.txt', (req, res) => res.send('User-agent: *\\nDisallow:'));\n\n server.use(express.json({ limit: '300kb' }));\n server.use(express.urlencoded({ extended: false }));\n server.use(cookieParser());\n server.use(requestIp.mw());\n\n loggerMiddleware.token('ip', (req) => req.clientIp);\n const FORMAT = ':ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent';\n server.use(loggerMiddleware(FORMAT, {\n stream: {\n write: options.logger.info.bind(options.logger),\n },\n }));\n\n // Note: no matter the \"public path\", we want the service worker, if any,\n // to be served from the root, to have all web app pages in its scope.\n // Thus, this setup to serve it. Probably, need some more configuration\n // for special cases, but this will do for now.\n server.get('/__service-worker.js', express.static(\n webpackConfig.output.path,\n {\n setHeaders: (res) => res.set('Cache-Control', 'no-cache'),\n },\n ));\n\n /* Setup of Hot Module Reloading for development environment.\n * These dependencies are not used, nor installed for production use,\n * hence we should violate some import-related lint rules. */\n /* eslint-disable global-require */\n /* eslint-disable import/no-extraneous-dependencies */\n /* eslint-disable import/no-unresolved */\n if (options.devMode) {\n // This is a workaround for SASS bug:\n // https://github.com/dart-lang/sdk/issues/27979\n // which manifests itself sometimes when webpack dev middleware is used\n // (in dev mode), and app modules are imported in some unfortunate ways.\n if (!global.location) {\n global.location = {\n href: `${pathToFileURL(process.cwd()).href}${sep}`,\n };\n }\n\n const webpack = require('webpack');\n const webpackDevMiddleware = require('webpack-dev-middleware');\n const webpackHotMiddleware = require('webpack-hot-middleware');\n const compiler = webpack(webpackConfig);\n server.use(webpackDevMiddleware(compiler, {\n publicPath,\n serverSideRender: true,\n }));\n server.use(webpackHotMiddleware(compiler));\n }\n /* eslint-enable global-require */\n /* eslint-enable import/no-extraneous-dependencies */\n /* eslint-enable import/no-unresolved */\n\n server.use(publicPath, express.static(webpackConfig.output.path));\n\n if (options.onExpressJsSetup) {\n await options.onExpressJsSetup(server);\n }\n server.use(renderer);\n\n /* Detects 404 errors, and forwards them to the error handler. */\n server.use((req, res, next) => {\n next(newError(ERRORS.NOT_FOUND, CODES.NOT_FOUND));\n });\n\n let dontAttachDefaultErrorHandler;\n if (options.beforeExpressJsError) {\n dontAttachDefaultErrorHandler = await options.beforeExpressJsError(server);\n }\n\n /* Error handler. */\n if (!dontAttachDefaultErrorHandler) {\n // TODO: Do we need this error handler at all? It actually seems to do\n // what the default ExpressJS error handler does anyway, see:\n // https://expressjs.com/en/guide/error-handling.html\n //\n // TODO: It is better to move the default error handler definition\n // to a stand-alone function at top-level, but the use of options.logger\n // prevents to do it without some extra refactoring. Should be done sometime\n // though.\n server.use((error, req, res, next) => {\n // TODO: This is needed to correctly handled any errors thrown after\n // sending initial response to the client.\n if (res.headersSent) return next(error);\n\n const status = error.status || CODES.INTERNAL_SERVER_ERROR;\n const serverSide = status >= CODES.INTERNAL_SERVER_ERROR;\n\n // Log server-side errors always, client-side at debug level only.\n options.logger.log(serverSide ? 'error' : 'debug', error);\n\n let message = error.message || getErrorForCode(status);\n if (serverSide && process.env.NODE_ENV === 'production') {\n message = ERRORS.INTERNAL_SERVER_ERROR;\n }\n\n res.status(status).send(message);\n return undefined;\n });\n }\n\n return server;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.18.2",
2
+ "version": "1.18.3",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"