@dr.pogodin/react-utils 1.17.7 → 1.17.10

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.
@@ -34,7 +34,7 @@ var _server2 = require("react-router-dom/server");
34
34
 
35
35
  var _serializeJavascript = _interopRequireDefault(require("serialize-javascript"));
36
36
 
37
- var _time = _interopRequireDefault(require("../shared/utils/time"));
37
+ var _time = require("../shared/utils/time");
38
38
 
39
39
  var _winston = _interopRequireDefault(require("winston"));
40
40
 
@@ -369,31 +369,32 @@ function factory(webpackConfig, options) {
369
369
  });
370
370
  };
371
371
 
372
- for (let round = 0; round < ops.maxSsrRounds; ++round) {
372
+ let ssrRound = 0;
373
+ let bailed = false;
374
+
375
+ for (; ssrRound < ops.maxSsrRounds; ++ssrRound) {
373
376
  stream = await renderPass(); // eslint-disable-line no-await-in-loop
374
377
 
375
- if (!ssrContext.dirty) {
376
- ops.logger.info(`SSR completed in ${round + 1} rounds`);
377
- break;
378
- }
378
+ if (!ssrContext.dirty) break;
379
379
  /* eslint-disable no-await-in-loop */
380
380
 
381
-
382
381
  const timeout = ops.ssrTimeout + ssrStart - Date.now();
383
- const ok = timeout > 0 && (await Promise.race([Promise.allSettled(ssrContext.pending), _time.default.timer(timeout).then(() => false)]));
384
-
385
- if (!ok) {
386
- ops.logger.warn(`SSR timed out (${ops.ssrTimeout}sec)`);
387
- break;
388
- }
382
+ bailed = timeout <= 0 || !(await Promise.race([Promise.allSettled(ssrContext.pending), (0, _time.timer)(timeout).then(() => false)]));
383
+ if (bailed) break;
389
384
  /* eslint-enable no-await-in-loop */
385
+ }
390
386
 
387
+ let logMsg;
391
388
 
392
- if (round + 1 === ops.maxSsrRounds) {
393
- ops.logger.warn(`SSR reached max number of rounds ${ops.maxSsrRounds}`);
394
- }
395
- }
389
+ if (ssrContext.dirty) {
390
+ // NOTE: In the case of incomplete SSR one more round is necessary
391
+ // to ensure the correct hydration when some pending promises have
392
+ // resolved and placed their data into the initial global state.
393
+ stream = await renderPass();
394
+ logMsg = bailed ? `SSR timed out after ${ops.ssrTimeout} second(s)` : `SSR bailed out after ${ops.maxSsrRounds} round(s)`;
395
+ } else logMsg = `SSR completed in ${ssrRound + 1} round(s)`;
396
396
 
397
+ ops.logger.log(ssrContext.dirty ? 'warn' : 'info', logMsg);
397
398
  App = '';
398
399
  stream.pipe(new _stream.Writable({
399
400
  write: (chunk, _, done) => {
@@ -439,8 +440,6 @@ function factory(webpackConfig, options) {
439
440
 
440
441
  const INJ = _nodeForge.default.util.encode64(`${iv}${cipher.output.data}`);
441
442
 
442
- const status = ssrContext.status || 200;
443
- if (status !== 200) res.status(status);
444
443
  const chunkSet = new Set(); // TODO: "main" chunk has to be added explicitly,
445
444
  // because unlike all other chunks they are not managed by <CodeSplit>
446
445
  // component, thus they are not added to the ssrContext.chunks
@@ -497,6 +496,8 @@ function factory(webpackConfig, options) {
497
496
  ${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}
498
497
  </body>
499
498
  </html>`;
499
+ const status = ssrContext.status || 200;
500
+ if (status !== 200) res.status(status);
500
501
  res.send(html);
501
502
 
502
503
  if (cacheRef && status < 500) {
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","names":["sanitizedConfig","omit","config","SCRIPT_LOCATIONS","BODY_OPEN","DEFAULT","HEAD_OPEN","getBuildInfo","context","url","path","resolve","JSON","parse","fs","readFileSync","readChunkGroupsJson","buildDir","res","err","prepareCipher","key","Promise","reject","forge","random","getBytes","iv","cipher","createCipher","start","isBrotliAcceptable","req","acceptable","get","ops","split","i","length","type","priority","trim","parseFloat","groupExtraScripts","scripts","script","isString","code","location","undefined","Error","newDefaultLogger","defaultLogLevel","format","transports","winston","createLogger","level","combine","splat","timestamp","colorize","printf","message","stack","rest","Object","keys","stringify","Console","factory","webpackConfig","options","defaults","clone","beforeRender","maxSsrRounds","ssrTimeout","staticCacheSize","logger","defaultLoggerLogLevel","buildInfo","global","TRU_BUILD_INFO","publicPath","outputPath","output","manifestLink","existsSync","cache","staticCacheController","Cache","CHUNK_GROUPS","next","set","cacheRef","data","buffer","status","noCsp","send","done","failed","brotliDecompress","error","html","h","toString","regex","RegExp","nonce","replace","configToInject","extraScripts","initialState","all","helmet","App","Application","ssrContext","state","cloneDeep","chunks","stream","ssrStart","Date","now","renderPass","pipeableStream","renderToPipeableStream","onAllReady","onError","round","dirty","info","timeout","ok","race","allSettled","pending","time","timer","then","warn","pipe","Writable","write","chunk","_","Helmet","renderStatic","chunkGroups","webpackStats","locals","mapValues","toJson","namedChunkGroups","item","assets","map","name","dr_pogodin_react_utils___split_components","payload","serializeJs","CONFIG","ISTATE","ignoreFunction","unsafe","update","util","createBuffer","finish","INJ","encode64","chunkSet","Set","forEach","asset","add","styleChunkString","scriptChunkString","endsWith","grouppedExtraScripts","faviconLink","favicon","title","meta","brotliCompress"],"sources":["../../../src/server/renderer.jsx"],"sourcesContent":["/**\n * ExpressJS middleware for server-side rendering of a ReactJS app.\n */\n\nimport { Writable } from 'stream';\n\nimport { GlobalStateProvider } from '@dr.pogodin/react-global-state';\n\nimport {\n clone,\n cloneDeep,\n defaults,\n isString,\n get,\n mapValues,\n omit,\n} from 'lodash';\n\nimport config from 'config';\nimport forge from 'node-forge';\nimport fs from 'fs';\nimport path from 'path';\nimport { brotliCompress, brotliDecompress } from 'zlib';\n\nimport { renderToPipeableStream } from 'react-dom/server';\nimport { Helmet } from 'react-helmet';\nimport { StaticRouter } from 'react-router-dom/server';\nimport serializeJs from 'serialize-javascript';\nimport time from 'utils/time';\nimport winston from 'winston';\n\nimport Cache from './Cache';\n\nconst sanitizedConfig = omit(config, 'SECRET');\n\nexport const SCRIPT_LOCATIONS = {\n BODY_OPEN: 'BODY_OPEN',\n DEFAULT: 'DEFAULT',\n HEAD_OPEN: 'HEAD_OPEN',\n};\n\n/**\n * Reads build-time information about the app. This information is generated\n * by our standard Webpack config for apps, and it is written into\n * \".build-info\" file in the context folder specified in Webpack config.\n * At the moment, that file contains build timestamp and a random 32-bit key,\n * suitable for cryptographical use.\n * @ignore\n * @param {String} context Webpack context path used during the build.\n * @return {Object} Resolves to the build-time information.\n */\nfunction getBuildInfo(context) {\n const url = path.resolve(context, '.build-info');\n return JSON.parse(fs.readFileSync(url));\n}\n\n/**\n * Attempts to read from disk the named chunk groups mapping generated\n * by Webpack during the compilation.\n * It will not work for development builds, where these stats should be captured\n * via compilator callback.\n * @ignore\n * @param {string} buildDir\n * @return {object}\n */\nfunction readChunkGroupsJson(buildDir) {\n const url = path.resolve(buildDir, '__chunk_groups__.json');\n let res;\n try {\n res = JSON.parse(fs.readFileSync(url));\n } catch (err) {\n res = null;\n }\n return res;\n}\n\n/**\n * Prepares a new Cipher for data encryption.\n * @ignore\n * @param {String} key Encryption key (32-bit random key is expected, see\n * node-forge documentation, in case of doubts).\n * @return {Promise} Resolves to the object with two fields:\n * 1. cipher - a new Cipher, ready for encryption;\n * 2. iv - initial vector used by the cipher.\n */\nfunction prepareCipher(key) {\n return new Promise((resolve, reject) => {\n forge.random.getBytes(32, (err, iv) => {\n if (err) reject(err);\n else {\n const cipher = forge.cipher.createCipher('AES-CBC', key);\n cipher.start({ iv });\n resolve({ cipher, iv });\n }\n });\n });\n}\n\n/**\n * Given an incoming HTTP requests, it deduces whether Brotli-encoded responses\n * are acceptable to the caller.\n * @param {object} req\n * @return {boolean}\n * @ignore\n */\nexport function isBrotliAcceptable(req) {\n const acceptable = req.get('accept-encoding');\n if (acceptable) {\n const ops = acceptable.split(',');\n for (let i = 0; i < ops.length; ++i) {\n const [type, priority] = ops[i].trim().split(';q=');\n if ((type === '*' || type === 'br')\n && (!priority || parseFloat(priority) > 0)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Given an array of extra script strings / objects, it returns an object with\n * arrays of scripts to inject in different HTML template locations. During\n * the script groupping it also filters out any empty scripts.\n * @param {({\n * code: string;\n * location: string;\n * }|string)[]} [scripts=[]]\n * @return {{\n * BODY_OPEN: string[];\n * DEFAULT: string[];\n * HEAD_OPEN: string[];\n * }}\n */\nfunction groupExtraScripts(scripts = []) {\n const res = {\n [SCRIPT_LOCATIONS.BODY_OPEN]: '',\n [SCRIPT_LOCATIONS.DEFAULT]: '',\n [SCRIPT_LOCATIONS.HEAD_OPEN]: '',\n };\n for (let i = 0; i < scripts.length; ++i) {\n const script = scripts[i];\n if (isString(script)) {\n if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;\n } else if (script.code) {\n if (res[script.location] !== undefined) {\n res[script.location] += script.code;\n } else throw Error(`Invalid location \"${script.location}\"`);\n }\n }\n return res;\n}\n\n/**\n * Creates a new default (Winston) logger.\n * @param {object} [options={}]\n * @param {string} [options.defaultLogLevel='info']\n * @return {object}\n */\nexport function newDefaultLogger({\n defaultLogLevel = 'info',\n} = {}) {\n const { format, transports } = winston;\n return winston.createLogger({\n level: defaultLogLevel,\n format: format.combine(\n format.splat(),\n format.timestamp(),\n format.colorize(),\n format.printf(\n ({\n level,\n message,\n timestamp,\n stack,\n ...rest\n }) => {\n let res = `${level}\\t(at ${timestamp}):\\t${message}`;\n if (Object.keys(rest).length) {\n res += `\\n${JSON.stringify(rest, null, 2)}`;\n }\n if (stack) res += `\\n${stack}`;\n return res;\n },\n ),\n ),\n transports: [new transports.Console()],\n });\n}\n\n/**\n * Creates the middleware.\n * @param {object} webpackConfig\n * @param {object} options Additional options:\n * @param {Component} [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param {object} [options.buildInfo] \"Build info\" object to use. If provided,\n * it will be used, instead of trying to load from the filesystem the one\n * generated by the Webpack build. It is intended for test environments,\n * where passing this stuff via file system is no bueno.\n * @param {boolean} [options.favicon] `true` will include favicon\n * link into the rendered HTML templates.\n * @param {boolean} [options.noCsp] `true` means that no\n * Content-Security-Policy (CSP) is used by server, thus the renderer\n * may cut a few corners.\n * @param {number} [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param {number} [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @param {number} [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param {function} [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` &ndash; the cache key for the response;\n * - `maxage?: number` &ndash; the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @return {function} Created middleware.\n */\nexport default function factory(webpackConfig, options) {\n const ops = defaults(clone(options), {\n beforeRender: () => Promise.resolve({}),\n maxSsrRounds: 10,\n ssrTimeout: 1000,\n staticCacheSize: 1.e7,\n });\n\n // Note: in normal use the default logger is created and set in the root\n // server function, and this initialization is for testing uses, where\n // renderer is imported directly.\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n const buildInfo = ops.buildInfo || getBuildInfo(webpackConfig.context);\n global.TRU_BUILD_INFO = buildInfo;\n\n // publicPath from webpack.output has a trailing slash at the end.\n const { publicPath, path: outputPath } = webpackConfig.output;\n\n const manifestLink = fs.existsSync(`${outputPath}/manifest.json`)\n ? `<link rel=\"manifest\" href=\"${publicPath}manifest.json\">` : '';\n\n const cache = ops.staticCacheController\n ? new Cache(ops.staticCacheSize) : null;\n\n const CHUNK_GROUPS = readChunkGroupsJson(outputPath);\n\n return async (req, res, next) => {\n try {\n // Ensures any caches always revalidate HTML markup before reuse.\n res.set('Cache-Control', 'no-cache');\n\n let cacheRef;\n if (cache) {\n cacheRef = ops.staticCacheController(req);\n if (cacheRef) {\n const data = cache.get(cacheRef);\n if (data !== null) {\n const { buffer, status } = data;\n if (ops.noCsp && isBrotliAcceptable(req)) {\n res.set('Content-Type', 'text/html');\n res.set('Content-Encoding', 'br');\n if (status !== 200) res.status(status);\n res.send(buffer);\n } else {\n await new Promise((done, failed) => {\n brotliDecompress(buffer, (error, html) => {\n if (error) failed(error);\n else {\n let h = html.toString();\n if (!ops.noCsp) {\n // TODO: Starting from Node v15 we'll be able to use string's\n // .replaceAll() method instead relying on reg. expression for\n // global matching.\n const regex = new RegExp(buffer.nonce, 'g');\n h = h.replace(regex, req.nonce);\n }\n if (status !== 200) res.status(status);\n res.send(h);\n done();\n }\n });\n });\n }\n return;\n }\n }\n }\n\n const [{\n configToInject,\n extraScripts,\n initialState,\n }, {\n cipher,\n iv,\n }] = await Promise.all([\n ops.beforeRender(req, sanitizedConfig),\n prepareCipher(buildInfo.key),\n ]);\n\n let helmet;\n\n /* Optional server-side rendering. */\n let App = ops.Application;\n const ssrContext = {\n req,\n state: cloneDeep(initialState || {}),\n\n // Array of chunk names encountered during the rendering.\n chunks: [],\n };\n let stream;\n if (App) {\n const ssrStart = Date.now();\n\n const renderPass = async () => {\n ssrContext.chunks = [];\n return new Promise((resolve, reject) => {\n const pipeableStream = renderToPipeableStream(\n <GlobalStateProvider\n initialState={ssrContext.state}\n ssrContext={ssrContext}\n >\n <StaticRouter location={req.url}>\n <App />\n </StaticRouter>\n </GlobalStateProvider>,\n {\n onAllReady: () => resolve(pipeableStream),\n onError: reject,\n },\n );\n });\n };\n\n for (let round = 0; round < ops.maxSsrRounds; ++round) {\n stream = await renderPass(); // eslint-disable-line no-await-in-loop\n\n if (!ssrContext.dirty) {\n ops.logger.info(`SSR completed in ${round + 1} rounds`);\n break;\n }\n\n /* eslint-disable no-await-in-loop */\n const timeout = ops.ssrTimeout + ssrStart - Date.now();\n const ok = timeout > 0 && await Promise.race([\n Promise.allSettled(ssrContext.pending),\n time.timer(timeout).then(() => false),\n ]);\n if (!ok) {\n ops.logger.warn(`SSR timed out (${ops.ssrTimeout}sec)`);\n break;\n }\n /* eslint-enable no-await-in-loop */\n\n if (round + 1 === ops.maxSsrRounds) {\n ops.logger.warn(\n `SSR reached max number of rounds ${ops.maxSsrRounds}`,\n );\n }\n }\n\n App = '';\n stream.pipe(new Writable({\n write: (chunk, _, done) => {\n App += chunk.toString();\n done();\n },\n }));\n\n /* This takes care about server-side rendering of page title and meta tags\n * (still demands injection into HTML template, which happens below). */\n helmet = Helmet.renderStatic();\n }\n\n let chunkGroups;\n const webpackStats = get(res.locals, 'webpack.devMiddleware.stats');\n if (webpackStats) {\n chunkGroups = mapValues(\n webpackStats.toJson({\n all: false,\n chunkGroups: true,\n }).namedChunkGroups,\n (item) => item.assets.map(({ name }) => name),\n );\n } else if (CHUNK_GROUPS) chunkGroups = CHUNK_GROUPS;\n else chunkGroups = {};\n\n /* Encrypts data to be injected into HTML.\n * Keep in mind, that this encryption is no way secure: as the JS bundle\n * contains decryption key and is able to decode it at the client side.\n * Hovewer, for a number of reasons, encryption of injected data is still\n * better than injection of a plain text. */\n delete ssrContext.state.dr_pogodin_react_utils___split_components;\n\n const payload = serializeJs({\n CHUNK_GROUPS: chunkGroups,\n CONFIG: configToInject || sanitizedConfig,\n ISTATE: ssrContext.state,\n }, {\n ignoreFunction: true,\n unsafe: true,\n });\n cipher.update(forge.util.createBuffer(payload, 'utf8'));\n cipher.finish();\n const INJ = forge.util.encode64(`${iv}${cipher.output.data}`);\n\n const status = ssrContext.status || 200;\n if (status !== 200) res.status(status);\n\n const chunkSet = new Set();\n\n // TODO: \"main\" chunk has to be added explicitly,\n // because unlike all other chunks they are not managed by <CodeSplit>\n // component, thus they are not added to the ssrContext.chunks\n // automatically. Actually, names of these entry chunks should be\n // read from Wepback config, as the end user may customize them,\n // remove or add other entry points, but it requires additional\n // efforts to figure out how to automatically order them right,\n // thus for now this handles the default config.\n [\n 'main',\n ...ssrContext.chunks,\n ].forEach((chunk) => {\n const assets = chunkGroups[chunk];\n if (assets) assets.forEach((asset) => chunkSet.add(asset));\n });\n\n let styleChunkString = '';\n let scriptChunkString = '';\n chunkSet.forEach((chunk) => {\n if (chunk.endsWith('.css')) {\n styleChunkString += `<link href=\"${publicPath}${chunk}\" rel=\"stylesheet\">`;\n } else if (\n chunk.endsWith('.js')\n // In dev mode HMR adds JS updates into asset arrays,\n // and they (updates) should be ignored.\n && !chunk.endsWith('.hot-update.js')\n ) {\n scriptChunkString += `<script src=\"${publicPath}${chunk}\" type=\"application/javascript\"></script>`;\n }\n });\n\n const grouppedExtraScripts = groupExtraScripts(extraScripts);\n\n const faviconLink = ops.favicon ? (\n '<link rel=\"shortcut icon\" href=\"/favicon.ico\">'\n ) : '';\n\n const html = `<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.HEAD_OPEN]}\n ${helmet ? helmet.title.toString() : ''}\n ${helmet ? helmet.meta.toString() : ''}\n <meta name=\"theme-color\" content=\"#FFFFFF\">\n ${manifestLink}\n ${styleChunkString}\n ${faviconLink}\n <meta charset=\"utf-8\">\n <meta\n content=\"width=device-width,initial-scale=1.0\"\n name=\"viewport\"\n >\n </head>\n <body>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.BODY_OPEN]}\n <div id=\"react-view\">${App || ''}</div>\n <script\n id=\"inj\"\n type=\"application/javascript\"\n ${ops.noCsp ? '' : `nonce=\"${req.nonce}\"`}\n >\n window.INJ=\"${INJ}\"\n </script>\n ${scriptChunkString}\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}\n </body>\n </html>`;\n\n res.send(html);\n\n if (cacheRef && status < 500) {\n // Note: waiting for the caching to complete is not strictly necessary,\n // but it greately simplifies testing, and error reporting.\n await new Promise((done, failed) => {\n brotliCompress(html, (error, buffer) => {\n if (error) failed(error);\n else {\n buffer.nonce = req.nonce; // eslint-disable-line no-param-reassign\n cache.add({ buffer, status }, cacheRef.key);\n done();\n }\n });\n });\n }\n } catch (error) {\n next(error);\n }\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","names":["sanitizedConfig","omit","config","SCRIPT_LOCATIONS","BODY_OPEN","DEFAULT","HEAD_OPEN","getBuildInfo","context","url","path","resolve","JSON","parse","fs","readFileSync","readChunkGroupsJson","buildDir","res","err","prepareCipher","key","Promise","reject","forge","random","getBytes","iv","cipher","createCipher","start","isBrotliAcceptable","req","acceptable","get","ops","split","i","length","type","priority","trim","parseFloat","groupExtraScripts","scripts","script","isString","code","location","undefined","Error","newDefaultLogger","defaultLogLevel","format","transports","winston","createLogger","level","combine","splat","timestamp","colorize","printf","message","stack","rest","Object","keys","stringify","Console","factory","webpackConfig","options","defaults","clone","beforeRender","maxSsrRounds","ssrTimeout","staticCacheSize","logger","defaultLoggerLogLevel","buildInfo","global","TRU_BUILD_INFO","publicPath","outputPath","output","manifestLink","existsSync","cache","staticCacheController","Cache","CHUNK_GROUPS","next","set","cacheRef","data","buffer","status","noCsp","send","done","failed","brotliDecompress","error","html","h","toString","regex","RegExp","nonce","replace","configToInject","extraScripts","initialState","all","helmet","App","Application","ssrContext","state","cloneDeep","chunks","stream","ssrStart","Date","now","renderPass","pipeableStream","renderToPipeableStream","onAllReady","onError","ssrRound","bailed","dirty","timeout","race","allSettled","pending","timer","then","logMsg","log","pipe","Writable","write","chunk","_","Helmet","renderStatic","chunkGroups","webpackStats","locals","mapValues","toJson","namedChunkGroups","item","assets","map","name","dr_pogodin_react_utils___split_components","payload","serializeJs","CONFIG","ISTATE","ignoreFunction","unsafe","update","util","createBuffer","finish","INJ","encode64","chunkSet","Set","forEach","asset","add","styleChunkString","scriptChunkString","endsWith","grouppedExtraScripts","faviconLink","favicon","title","meta","brotliCompress"],"sources":["../../../src/server/renderer.jsx"],"sourcesContent":["/**\n * ExpressJS middleware for server-side rendering of a ReactJS app.\n */\n\nimport { Writable } from 'stream';\n\nimport { GlobalStateProvider } from '@dr.pogodin/react-global-state';\n\nimport {\n clone,\n cloneDeep,\n defaults,\n isString,\n get,\n mapValues,\n omit,\n} from 'lodash';\n\nimport config from 'config';\nimport forge from 'node-forge';\nimport fs from 'fs';\nimport path from 'path';\nimport { brotliCompress, brotliDecompress } from 'zlib';\n\nimport { renderToPipeableStream } from 'react-dom/server';\nimport { Helmet } from 'react-helmet';\nimport { StaticRouter } from 'react-router-dom/server';\nimport serializeJs from 'serialize-javascript';\nimport { timer } from 'utils/time';\nimport winston from 'winston';\n\nimport Cache from './Cache';\n\nconst sanitizedConfig = omit(config, 'SECRET');\n\nexport const SCRIPT_LOCATIONS = {\n BODY_OPEN: 'BODY_OPEN',\n DEFAULT: 'DEFAULT',\n HEAD_OPEN: 'HEAD_OPEN',\n};\n\n/**\n * Reads build-time information about the app. This information is generated\n * by our standard Webpack config for apps, and it is written into\n * \".build-info\" file in the context folder specified in Webpack config.\n * At the moment, that file contains build timestamp and a random 32-bit key,\n * suitable for cryptographical use.\n * @ignore\n * @param {String} context Webpack context path used during the build.\n * @return {Object} Resolves to the build-time information.\n */\nfunction getBuildInfo(context) {\n const url = path.resolve(context, '.build-info');\n return JSON.parse(fs.readFileSync(url));\n}\n\n/**\n * Attempts to read from disk the named chunk groups mapping generated\n * by Webpack during the compilation.\n * It will not work for development builds, where these stats should be captured\n * via compilator callback.\n * @ignore\n * @param {string} buildDir\n * @return {object}\n */\nfunction readChunkGroupsJson(buildDir) {\n const url = path.resolve(buildDir, '__chunk_groups__.json');\n let res;\n try {\n res = JSON.parse(fs.readFileSync(url));\n } catch (err) {\n res = null;\n }\n return res;\n}\n\n/**\n * Prepares a new Cipher for data encryption.\n * @ignore\n * @param {String} key Encryption key (32-bit random key is expected, see\n * node-forge documentation, in case of doubts).\n * @return {Promise} Resolves to the object with two fields:\n * 1. cipher - a new Cipher, ready for encryption;\n * 2. iv - initial vector used by the cipher.\n */\nfunction prepareCipher(key) {\n return new Promise((resolve, reject) => {\n forge.random.getBytes(32, (err, iv) => {\n if (err) reject(err);\n else {\n const cipher = forge.cipher.createCipher('AES-CBC', key);\n cipher.start({ iv });\n resolve({ cipher, iv });\n }\n });\n });\n}\n\n/**\n * Given an incoming HTTP requests, it deduces whether Brotli-encoded responses\n * are acceptable to the caller.\n * @param {object} req\n * @return {boolean}\n * @ignore\n */\nexport function isBrotliAcceptable(req) {\n const acceptable = req.get('accept-encoding');\n if (acceptable) {\n const ops = acceptable.split(',');\n for (let i = 0; i < ops.length; ++i) {\n const [type, priority] = ops[i].trim().split(';q=');\n if ((type === '*' || type === 'br')\n && (!priority || parseFloat(priority) > 0)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Given an array of extra script strings / objects, it returns an object with\n * arrays of scripts to inject in different HTML template locations. During\n * the script groupping it also filters out any empty scripts.\n * @param {({\n * code: string;\n * location: string;\n * }|string)[]} [scripts=[]]\n * @return {{\n * BODY_OPEN: string[];\n * DEFAULT: string[];\n * HEAD_OPEN: string[];\n * }}\n */\nfunction groupExtraScripts(scripts = []) {\n const res = {\n [SCRIPT_LOCATIONS.BODY_OPEN]: '',\n [SCRIPT_LOCATIONS.DEFAULT]: '',\n [SCRIPT_LOCATIONS.HEAD_OPEN]: '',\n };\n for (let i = 0; i < scripts.length; ++i) {\n const script = scripts[i];\n if (isString(script)) {\n if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;\n } else if (script.code) {\n if (res[script.location] !== undefined) {\n res[script.location] += script.code;\n } else throw Error(`Invalid location \"${script.location}\"`);\n }\n }\n return res;\n}\n\n/**\n * Creates a new default (Winston) logger.\n * @param {object} [options={}]\n * @param {string} [options.defaultLogLevel='info']\n * @return {object}\n */\nexport function newDefaultLogger({\n defaultLogLevel = 'info',\n} = {}) {\n const { format, transports } = winston;\n return winston.createLogger({\n level: defaultLogLevel,\n format: format.combine(\n format.splat(),\n format.timestamp(),\n format.colorize(),\n format.printf(\n ({\n level,\n message,\n timestamp,\n stack,\n ...rest\n }) => {\n let res = `${level}\\t(at ${timestamp}):\\t${message}`;\n if (Object.keys(rest).length) {\n res += `\\n${JSON.stringify(rest, null, 2)}`;\n }\n if (stack) res += `\\n${stack}`;\n return res;\n },\n ),\n ),\n transports: [new transports.Console()],\n });\n}\n\n/**\n * Creates the middleware.\n * @param {object} webpackConfig\n * @param {object} options Additional options:\n * @param {Component} [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param {object} [options.buildInfo] \"Build info\" object to use. If provided,\n * it will be used, instead of trying to load from the filesystem the one\n * generated by the Webpack build. It is intended for test environments,\n * where passing this stuff via file system is no bueno.\n * @param {boolean} [options.favicon] `true` will include favicon\n * link into the rendered HTML templates.\n * @param {boolean} [options.noCsp] `true` means that no\n * Content-Security-Policy (CSP) is used by server, thus the renderer\n * may cut a few corners.\n * @param {number} [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param {number} [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @param {number} [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param {function} [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` &ndash; the cache key for the response;\n * - `maxage?: number` &ndash; the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @return {function} Created middleware.\n */\nexport default function factory(webpackConfig, options) {\n const ops = defaults(clone(options), {\n beforeRender: () => Promise.resolve({}),\n maxSsrRounds: 10,\n ssrTimeout: 1000,\n staticCacheSize: 1.e7,\n });\n\n // Note: in normal use the default logger is created and set in the root\n // server function, and this initialization is for testing uses, where\n // renderer is imported directly.\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n const buildInfo = ops.buildInfo || getBuildInfo(webpackConfig.context);\n global.TRU_BUILD_INFO = buildInfo;\n\n // publicPath from webpack.output has a trailing slash at the end.\n const { publicPath, path: outputPath } = webpackConfig.output;\n\n const manifestLink = fs.existsSync(`${outputPath}/manifest.json`)\n ? `<link rel=\"manifest\" href=\"${publicPath}manifest.json\">` : '';\n\n const cache = ops.staticCacheController\n ? new Cache(ops.staticCacheSize) : null;\n\n const CHUNK_GROUPS = readChunkGroupsJson(outputPath);\n\n return async (req, res, next) => {\n try {\n // Ensures any caches always revalidate HTML markup before reuse.\n res.set('Cache-Control', 'no-cache');\n\n let cacheRef;\n if (cache) {\n cacheRef = ops.staticCacheController(req);\n if (cacheRef) {\n const data = cache.get(cacheRef);\n if (data !== null) {\n const { buffer, status } = data;\n if (ops.noCsp && isBrotliAcceptable(req)) {\n res.set('Content-Type', 'text/html');\n res.set('Content-Encoding', 'br');\n if (status !== 200) res.status(status);\n res.send(buffer);\n } else {\n await new Promise((done, failed) => {\n brotliDecompress(buffer, (error, html) => {\n if (error) failed(error);\n else {\n let h = html.toString();\n if (!ops.noCsp) {\n // TODO: Starting from Node v15 we'll be able to use string's\n // .replaceAll() method instead relying on reg. expression for\n // global matching.\n const regex = new RegExp(buffer.nonce, 'g');\n h = h.replace(regex, req.nonce);\n }\n if (status !== 200) res.status(status);\n res.send(h);\n done();\n }\n });\n });\n }\n return;\n }\n }\n }\n\n const [{\n configToInject,\n extraScripts,\n initialState,\n }, {\n cipher,\n iv,\n }] = await Promise.all([\n ops.beforeRender(req, sanitizedConfig),\n prepareCipher(buildInfo.key),\n ]);\n\n let helmet;\n\n /* Optional server-side rendering. */\n let App = ops.Application;\n const ssrContext = {\n req,\n state: cloneDeep(initialState || {}),\n\n // Array of chunk names encountered during the rendering.\n chunks: [],\n };\n let stream;\n if (App) {\n const ssrStart = Date.now();\n\n const renderPass = async () => {\n ssrContext.chunks = [];\n return new Promise((resolve, reject) => {\n const pipeableStream = renderToPipeableStream(\n <GlobalStateProvider\n initialState={ssrContext.state}\n ssrContext={ssrContext}\n >\n <StaticRouter location={req.url}>\n <App />\n </StaticRouter>\n </GlobalStateProvider>,\n {\n onAllReady: () => resolve(pipeableStream),\n onError: reject,\n },\n );\n });\n };\n\n let ssrRound = 0;\n let bailed = false;\n for (; ssrRound < ops.maxSsrRounds; ++ssrRound) {\n stream = await renderPass(); // eslint-disable-line no-await-in-loop\n\n if (!ssrContext.dirty) break;\n\n /* eslint-disable no-await-in-loop */\n const timeout = ops.ssrTimeout + ssrStart - Date.now();\n bailed = timeout <= 0 || !await Promise.race([\n Promise.allSettled(ssrContext.pending),\n timer(timeout).then(() => false),\n ]);\n if (bailed) break;\n /* eslint-enable no-await-in-loop */\n }\n\n let logMsg;\n if (ssrContext.dirty) {\n // NOTE: In the case of incomplete SSR one more round is necessary\n // to ensure the correct hydration when some pending promises have\n // resolved and placed their data into the initial global state.\n stream = await renderPass();\n\n logMsg = bailed ? `SSR timed out after ${ops.ssrTimeout} second(s)`\n : `SSR bailed out after ${ops.maxSsrRounds} round(s)`;\n } else logMsg = `SSR completed in ${ssrRound + 1} round(s)`;\n\n ops.logger.log(ssrContext.dirty ? 'warn' : 'info', logMsg);\n\n App = '';\n stream.pipe(new Writable({\n write: (chunk, _, done) => {\n App += chunk.toString();\n done();\n },\n }));\n\n /* This takes care about server-side rendering of page title and meta tags\n * (still demands injection into HTML template, which happens below). */\n helmet = Helmet.renderStatic();\n }\n\n let chunkGroups;\n const webpackStats = get(res.locals, 'webpack.devMiddleware.stats');\n if (webpackStats) {\n chunkGroups = mapValues(\n webpackStats.toJson({\n all: false,\n chunkGroups: true,\n }).namedChunkGroups,\n (item) => item.assets.map(({ name }) => name),\n );\n } else if (CHUNK_GROUPS) chunkGroups = CHUNK_GROUPS;\n else chunkGroups = {};\n\n /* Encrypts data to be injected into HTML.\n * Keep in mind, that this encryption is no way secure: as the JS bundle\n * contains decryption key and is able to decode it at the client side.\n * Hovewer, for a number of reasons, encryption of injected data is still\n * better than injection of a plain text. */\n delete ssrContext.state.dr_pogodin_react_utils___split_components;\n\n const payload = serializeJs({\n CHUNK_GROUPS: chunkGroups,\n CONFIG: configToInject || sanitizedConfig,\n ISTATE: ssrContext.state,\n }, {\n ignoreFunction: true,\n unsafe: true,\n });\n cipher.update(forge.util.createBuffer(payload, 'utf8'));\n cipher.finish();\n const INJ = forge.util.encode64(`${iv}${cipher.output.data}`);\n\n const chunkSet = new Set();\n\n // TODO: \"main\" chunk has to be added explicitly,\n // because unlike all other chunks they are not managed by <CodeSplit>\n // component, thus they are not added to the ssrContext.chunks\n // automatically. Actually, names of these entry chunks should be\n // read from Wepback config, as the end user may customize them,\n // remove or add other entry points, but it requires additional\n // efforts to figure out how to automatically order them right,\n // thus for now this handles the default config.\n [\n 'main',\n ...ssrContext.chunks,\n ].forEach((chunk) => {\n const assets = chunkGroups[chunk];\n if (assets) assets.forEach((asset) => chunkSet.add(asset));\n });\n\n let styleChunkString = '';\n let scriptChunkString = '';\n chunkSet.forEach((chunk) => {\n if (chunk.endsWith('.css')) {\n styleChunkString += `<link href=\"${publicPath}${chunk}\" rel=\"stylesheet\">`;\n } else if (\n chunk.endsWith('.js')\n // In dev mode HMR adds JS updates into asset arrays,\n // and they (updates) should be ignored.\n && !chunk.endsWith('.hot-update.js')\n ) {\n scriptChunkString += `<script src=\"${publicPath}${chunk}\" type=\"application/javascript\"></script>`;\n }\n });\n\n const grouppedExtraScripts = groupExtraScripts(extraScripts);\n\n const faviconLink = ops.favicon ? (\n '<link rel=\"shortcut icon\" href=\"/favicon.ico\">'\n ) : '';\n\n const html = `<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.HEAD_OPEN]}\n ${helmet ? helmet.title.toString() : ''}\n ${helmet ? helmet.meta.toString() : ''}\n <meta name=\"theme-color\" content=\"#FFFFFF\">\n ${manifestLink}\n ${styleChunkString}\n ${faviconLink}\n <meta charset=\"utf-8\">\n <meta\n content=\"width=device-width,initial-scale=1.0\"\n name=\"viewport\"\n >\n </head>\n <body>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.BODY_OPEN]}\n <div id=\"react-view\">${App || ''}</div>\n <script\n id=\"inj\"\n type=\"application/javascript\"\n ${ops.noCsp ? '' : `nonce=\"${req.nonce}\"`}\n >\n window.INJ=\"${INJ}\"\n </script>\n ${scriptChunkString}\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}\n </body>\n </html>`;\n\n const status = ssrContext.status || 200;\n if (status !== 200) res.status(status);\n res.send(html);\n\n if (cacheRef && status < 500) {\n // Note: waiting for the caching to complete is not strictly necessary,\n // but it greately simplifies testing, and error reporting.\n await new Promise((done, failed) => {\n brotliCompress(html, (error, buffer) => {\n if (error) failed(error);\n else {\n buffer.nonce = req.nonce; // eslint-disable-line no-param-reassign\n cache.add({ buffer, status }, cacheRef.key);\n done();\n }\n });\n });\n }\n } catch (error) {\n next(error);\n }\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["BaseModal","children","onCancel","theme","containerRef","useRef","overlayRef","portal","setPortal","useState","useEffect","p","document","createElement","body","classList","add","appendChild","remove","removeChild","focusLast","useMemo","elems","current","querySelectorAll","i","length","focus","activeElement","ReactDom","createPortal","overlay","e","key","node","container","event","stopPropagation","ThemedModal","themed","baseTheme","propTypes","PT","func","themeType","isRequired","defaultProps","noop"],"sources":["../../../../../src/shared/components/Modal/index.jsx"],"sourcesContent":["/* global document */\n\nimport { noop } from 'lodash';\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ReactDom from 'react-dom';\nimport PT from 'prop-types';\nimport themed from '@dr.pogodin/react-themes';\n\nimport baseTheme from './base-theme.scss';\nimport './styles.scss';\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nfunction BaseModal({\n children,\n onCancel,\n theme,\n}) {\n const containerRef = useRef();\n const overlayRef = useRef();\n const [portal, setPortal] = useState();\n\n useEffect(() => {\n const p = document.createElement('div');\n document.body.classList.add('scrolling-disabled-by-modal');\n document.body.appendChild(p);\n setPortal(p);\n return () => {\n document.body.classList.remove('scrolling-disabled-by-modal');\n document.body.removeChild(p);\n };\n }, []);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n elems[i].focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex=\"0\"\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n ), []);\n\n return portal ? ReactDom.createPortal(\n (\n <>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n onClick={() => onCancel()}\n onKeyDown={(e) => {\n if (e.key === 'Escape') onCancel();\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n tabIndex=\"0\"\n />\n <div\n aria-modal=\"true\"\n className={theme.container}\n onWheel={(event) => event.stopPropagation()}\n ref={containerRef}\n role=\"dialog\"\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex=\"0\"\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n {focusLast}\n </>\n ),\n portal,\n ) : null;\n}\n\nconst ThemedModal = themed(\n 'Modal',\n [\n 'container',\n 'overlay',\n ],\n baseTheme,\n)(BaseModal);\n\nBaseModal.propTypes = {\n onCancel: PT.func,\n children: PT.node,\n theme: ThemedModal.themeType.isRequired,\n};\n\nBaseModal.defaultProps = {\n onCancel: noop,\n children: null,\n};\n\nexport default ThemedModal;\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["BaseModal","children","onCancel","theme","containerRef","useRef","overlayRef","portal","setPortal","useState","useEffect","p","document","createElement","body","classList","add","appendChild","remove","removeChild","focusLast","useMemo","elems","current","querySelectorAll","i","length","focus","activeElement","ReactDom","createPortal","overlay","e","key","node","container","event","stopPropagation","ThemedModal","themed","baseTheme","propTypes","PT","func","themeType","isRequired","defaultProps","noop"],"sources":["../../../../../src/shared/components/Modal/index.jsx"],"sourcesContent":["/* global document */\n\nimport { noop } from 'lodash';\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport ReactDom from 'react-dom';\nimport PT from 'prop-types';\nimport themed from '@dr.pogodin/react-themes';\n\nimport baseTheme from './base-theme.scss';\nimport './styles.scss';\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nfunction BaseModal({\n children,\n onCancel,\n theme,\n}) {\n const containerRef = useRef();\n const overlayRef = useRef();\n const [portal, setPortal] = useState();\n\n useEffect(() => {\n const p = document.createElement('div');\n document.body.classList.add('scrolling-disabled-by-modal');\n document.body.appendChild(p);\n setPortal(p);\n return () => {\n document.body.classList.remove('scrolling-disabled-by-modal');\n document.body.removeChild(p);\n };\n }, []);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n elems[i].focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex=\"0\"\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n ), []);\n\n return portal ? ReactDom.createPortal(\n (\n <>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n onClick={() => onCancel()}\n onKeyDown={(e) => {\n if (e.key === 'Escape') onCancel();\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n tabIndex=\"0\"\n />\n <div\n aria-modal=\"true\"\n className={theme.container}\n onWheel={(event) => event.stopPropagation()}\n ref={containerRef}\n role=\"dialog\"\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex=\"0\"\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n {focusLast}\n </>\n ),\n portal,\n ) : null;\n}\n\nconst ThemedModal = themed(\n 'Modal',\n [\n 'container',\n 'overlay',\n ],\n baseTheme,\n)(BaseModal);\n\nBaseModal.propTypes = {\n onCancel: PT.func,\n children: PT.node,\n theme: ThemedModal.themeType.isRequired,\n};\n\nBaseModal.defaultProps = {\n onCancel: noop,\n children: null,\n};\n\nexport default ThemedModal;\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n"],"mappings":"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"}
@@ -43,6 +43,7 @@ class Semaphore {
43
43
  const barrier = (0, _Barrier.newBarrier)();
44
44
  this.#queue.push(barrier);
45
45
  await barrier;
46
+ this.#queue.shift();
46
47
  }
47
48
  } // Private members below this point.
48
49
 
@@ -56,8 +57,7 @@ class Semaphore {
56
57
 
57
58
  #drainQueue() {
58
59
  if (this.#ready && this.#queue.length) {
59
- const next = this.#queue.shift();
60
- next.resolve(); // Re-schedules itself for the next event loop iteration.
60
+ this.#queue[0].resolve(); // Re-schedules itself for the next event loop iteration.
61
61
 
62
62
  if (this.#queue.length) {
63
63
  setTimeout(this.#drainQueue.bind(this));
@@ -1 +1 @@
1
- {"version":3,"file":"Semaphore.js","names":["Semaphore","constructor","ready","setReady","bool","draining","drainQueue","seize","waitReady","queue","length","barrier","newBarrier","push","next","shift","resolve","setTimeout","bind"],"sources":["../../../../src/shared/utils/Semaphore.js"],"sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n constructor(ready) {\n this.#ready = !!ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n const bool = !!ready;\n if (this.#ready !== bool) {\n this.#ready = bool;\n if (bool && !this.#draining) this.#drainQueue();\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n async seize() {\n await this.waitReady();\n this.setReady(false);\n }\n\n async waitReady() {\n if (!this.#ready || this.#queue.length) {\n const barrier = newBarrier();\n this.#queue.push(barrier);\n await barrier;\n }\n }\n\n // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n #drainQueue() {\n if (this.#ready && this.#queue.length) {\n const next = this.#queue.shift();\n next.resolve();\n\n // Re-schedules itself for the next event loop iteration.\n if (this.#queue.length) {\n setTimeout(this.#drainQueue.bind(this));\n this.#draining = true;\n return; // Exit here to avoid the drain loop termination below.\n }\n }\n\n // Cleans up for the drain loop termination.\n this.#draining = false;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n #draining = false;\n\n // The array of barriers set for each async code flow awaiting for\n // the Semaphore to become ready.\n #queue = [];\n\n #ready;\n}\n"],"mappings":";;;;;;;AAAA;;AAEA;AACA;AACA;AACe,MAAMA,SAAN,CAAgB;EAC7BC,WAAW,CAACC,KAAD,EAAQ;IACjB,KAAK,CAACA,KAAN,GAAc,CAAC,CAACA,KAAhB;EACD;;EAEQ,IAALA,KAAK,GAAG;IAAE,OAAO,KAAK,CAACA,KAAb;EAAqB;;EAEnCC,QAAQ,CAACD,KAAD,EAAQ;IACd,MAAME,IAAI,GAAG,CAAC,CAACF,KAAf;;IACA,IAAI,KAAK,CAACA,KAAN,KAAgBE,IAApB,EAA0B;MACxB,KAAK,CAACF,KAAN,GAAcE,IAAd;MACA,IAAIA,IAAI,IAAI,CAAC,KAAK,CAACC,QAAnB,EAA6B,KAAK,CAACC,UAAN;IAC9B;EACF;EAED;AACF;AACA;AACA;;;EACa,MAALC,KAAK,GAAG;IACZ,MAAM,KAAKC,SAAL,EAAN;IACA,KAAKL,QAAL,CAAc,KAAd;EACD;;EAEc,MAATK,SAAS,GAAG;IAChB,IAAI,CAAC,KAAK,CAACN,KAAP,IAAgB,KAAK,CAACO,KAAN,CAAYC,MAAhC,EAAwC;MACtC,MAAMC,OAAO,GAAG,IAAAC,mBAAA,GAAhB;MACA,KAAK,CAACH,KAAN,CAAYI,IAAZ,CAAiBF,OAAjB;MACA,MAAMA,OAAN;IACD;EACF,CA9B4B,CAgC7B;;EAEA;AACF;AACA;AACA;AACA;AACA;;;EACE,CAACL,UAAU,GAAG;IACZ,IAAI,KAAK,CAACJ,KAAN,IAAe,KAAK,CAACO,KAAN,CAAYC,MAA/B,EAAuC;MACrC,MAAMI,IAAI,GAAG,KAAK,CAACL,KAAN,CAAYM,KAAZ,EAAb;MACAD,IAAI,CAACE,OAAL,GAFqC,CAIrC;;MACA,IAAI,KAAK,CAACP,KAAN,CAAYC,MAAhB,EAAwB;QACtBO,UAAU,CAAC,KAAK,CAACX,UAAN,CAAiBY,IAAjB,CAAsB,IAAtB,CAAD,CAAV;QACA,KAAK,CAACb,QAAN,GAAiB,IAAjB;QACA,OAHsB,CAGd;MACT;IACF,CAXW,CAaZ;;;IACA,KAAK,CAACA,QAAN,GAAiB,KAAjB;EACD,CAvD4B,CAyD7B;EACA;;;EACA,CAACA,QAAD,GAAY,KAAZ,CA3D6B,CA6D7B;EACA;;EACA,CAACI,KAAD,GAAS,EAAT;EAEA,CAACP,KAAD;AAjE6B"}
1
+ {"version":3,"file":"Semaphore.js","names":["Semaphore","constructor","ready","setReady","bool","draining","drainQueue","seize","waitReady","queue","length","barrier","newBarrier","push","shift","resolve","setTimeout","bind"],"sources":["../../../../src/shared/utils/Semaphore.js"],"sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n constructor(ready) {\n this.#ready = !!ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n const bool = !!ready;\n if (this.#ready !== bool) {\n this.#ready = bool;\n if (bool && !this.#draining) this.#drainQueue();\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n async seize() {\n await this.waitReady();\n this.setReady(false);\n }\n\n async waitReady() {\n if (!this.#ready || this.#queue.length) {\n const barrier = newBarrier();\n this.#queue.push(barrier);\n await barrier;\n this.#queue.shift();\n }\n }\n\n // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n #drainQueue() {\n if (this.#ready && this.#queue.length) {\n this.#queue[0].resolve();\n\n // Re-schedules itself for the next event loop iteration.\n if (this.#queue.length) {\n setTimeout(this.#drainQueue.bind(this));\n this.#draining = true;\n return; // Exit here to avoid the drain loop termination below.\n }\n }\n\n // Cleans up for the drain loop termination.\n this.#draining = false;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n #draining = false;\n\n // The array of barriers set for each async code flow awaiting for\n // the Semaphore to become ready.\n #queue = [];\n\n #ready;\n}\n"],"mappings":";;;;;;;AAAA;;AAEA;AACA;AACA;AACe,MAAMA,SAAN,CAAgB;EAC7BC,WAAW,CAACC,KAAD,EAAQ;IACjB,KAAK,CAACA,KAAN,GAAc,CAAC,CAACA,KAAhB;EACD;;EAEQ,IAALA,KAAK,GAAG;IAAE,OAAO,KAAK,CAACA,KAAb;EAAqB;;EAEnCC,QAAQ,CAACD,KAAD,EAAQ;IACd,MAAME,IAAI,GAAG,CAAC,CAACF,KAAf;;IACA,IAAI,KAAK,CAACA,KAAN,KAAgBE,IAApB,EAA0B;MACxB,KAAK,CAACF,KAAN,GAAcE,IAAd;MACA,IAAIA,IAAI,IAAI,CAAC,KAAK,CAACC,QAAnB,EAA6B,KAAK,CAACC,UAAN;IAC9B;EACF;EAED;AACF;AACA;AACA;;;EACa,MAALC,KAAK,GAAG;IACZ,MAAM,KAAKC,SAAL,EAAN;IACA,KAAKL,QAAL,CAAc,KAAd;EACD;;EAEc,MAATK,SAAS,GAAG;IAChB,IAAI,CAAC,KAAK,CAACN,KAAP,IAAgB,KAAK,CAACO,KAAN,CAAYC,MAAhC,EAAwC;MACtC,MAAMC,OAAO,GAAG,IAAAC,mBAAA,GAAhB;MACA,KAAK,CAACH,KAAN,CAAYI,IAAZ,CAAiBF,OAAjB;MACA,MAAMA,OAAN;MACA,KAAK,CAACF,KAAN,CAAYK,KAAZ;IACD;EACF,CA/B4B,CAiC7B;;EAEA;AACF;AACA;AACA;AACA;AACA;;;EACE,CAACR,UAAU,GAAG;IACZ,IAAI,KAAK,CAACJ,KAAN,IAAe,KAAK,CAACO,KAAN,CAAYC,MAA/B,EAAuC;MACrC,KAAK,CAACD,KAAN,CAAY,CAAZ,EAAeM,OAAf,GADqC,CAGrC;;MACA,IAAI,KAAK,CAACN,KAAN,CAAYC,MAAhB,EAAwB;QACtBM,UAAU,CAAC,KAAK,CAACV,UAAN,CAAiBW,IAAjB,CAAsB,IAAtB,CAAD,CAAV;QACA,KAAK,CAACZ,QAAN,GAAiB,IAAjB;QACA,OAHsB,CAGd;MACT;IACF,CAVW,CAYZ;;;IACA,KAAK,CAACA,QAAN,GAAiB,KAAjB;EACD,CAvD4B,CAyD7B;EACA;;;EACA,CAACA,QAAD,GAAY,KAAZ,CA3D6B,CA6D7B;EACA;;EACA,CAACI,KAAD,GAAS,EAAT;EAEA,CAACP,KAAD;AAjE6B"}
@@ -73,7 +73,7 @@ var isomorphy = _interopRequireWildcard(require("./isomorphy"));
73
73
 
74
74
  exports.isomorphy = isomorphy;
75
75
 
76
- var _time = _interopRequireDefault(require("./time"));
76
+ var _time = _interopRequireWildcard(require("./time"));
77
77
 
78
78
  var webpack = _interopRequireWildcard(require("./webpack"));
79
79
 
@@ -162,7 +162,7 @@ async function withRetries(action, maxRetries = 5, interval = 1000) {
162
162
  try {
163
163
  return await action();
164
164
  } catch (error) {
165
- if (n < maxRetries) await _time.default.timer(interval);else throw error;
165
+ if (n < maxRetries) await (0, _time.timer)(interval);else throw error;
166
166
  }
167
167
  }
168
168
  /* eslint-enable no-await-in-loop */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["themed","COMPOSE","PRIORITY","NODE_CONFIG_ENV","process","env","NODE_ENV","JU","webpack","requireWeak","__dirname","withRetries","action","maxRetries","interval","n","error","time","timer"],"sources":["../../../../src/shared/utils/index.js"],"sourcesContent":["import themed, {\n COMPOSE,\n PRIORITY,\n ThemeProvider,\n} from '@dr.pogodin/react-themes';\n\nimport config from './config';\nimport * as isomorphy from './isomorphy';\nimport time from './time';\nimport * as webpack from './webpack';\n\nexport * from './Barrier';\nexport { default as Emitter } from './Emitter';\nexport { default as Semaphore } from './Semaphore';\nexport { default as splitComponent } from './splitComponent';\n\nthemed.COMPOSE = COMPOSE;\nthemed.PRIORITY = PRIORITY;\n\n// Note: it should be done this way, as in some environments\n// \"process\" might not exist, and process.env.NODE_CONFIG_ENV\n// not injected by Webpack.\nlet NODE_CONFIG_ENV;\ntry {\n NODE_CONFIG_ENV = process.env.NODE_CONFIG_ENV;\n} catch { /* noop */ }\n\nconst env = NODE_CONFIG_ENV || process.env.NODE_ENV;\nconst JU = env !== 'production' && webpack.requireWeak('./jest', __dirname);\n\n/**\n * @category Utilities\n * @global\n * @func withRetries\n * @desc\n * ```js\n * import { withRetries } from '@dr.pogodin/react-utils';\n * ```\n * Attempts to perform given asynchronous `action` up to `maxRetries` times,\n * with the given `interval` between attempts. If any attempt is successful,\n * the result is returned immediately, with no further attempts done;\n * otherwise, if all attempts fail, the result Promise rejects after the last\n * attempt.\n * @param {function} action\n * @param {number} [maxRetries=5] Optional. Maximum number of retries. Defaults\n * to 5 attempts.\n * @param {number} [interval=1000] Optional. Interval between retries [ms].\n * Defaults to 1 second.\n * @return {Promise} Resolves to the result of successful operation, or\n * rejects with the error from the latst failed attempt.\n * @example\n * import { withRetries } from '@dr.pogodin/react-utils';\n *\n * let firstCall = true;\n *\n * function sampleAction() {\n * if (!firstCall) return 'success';\n * firstCall = false;\n * throw Error('The first call to this method fails');\n * }\n *\n * withRetries(sampleAction).then(console.log);\n * // It will print 'success' after one second, once the second attempt\n * // is performed.\n */\nexport async function withRetries(action, maxRetries = 5, interval = 1000) {\n /* eslint-disable no-await-in-loop */\n for (let n = 1; ; ++n) {\n try {\n return await action();\n } catch (error) {\n if (n < maxRetries) await time.timer(interval);\n else throw error;\n }\n }\n /* eslint-enable no-await-in-loop */\n}\n\nexport {\n config,\n isomorphy,\n JU,\n themed,\n ThemeProvider,\n time,\n webpack,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAMA;;AACA;;;;AACA;;AACA;;;;AAEA;;AAAA;EAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AACA;;AACA;;;;;;AAEAA,oBAAA,CAAOC,OAAP,GAAiBA,oBAAjB;AACAD,oBAAA,CAAOE,QAAP,GAAkBA,qBAAlB,C,CAEA;AACA;AACA;;AACA,IAAIC,eAAJ;;AACA,IAAI;EACFA,eAAe,GAAGC,OAAO,CAACC,GAAR,CAAYF,eAA9B;AACD,CAFD,CAEE,MAAM;EAAE;AAAY;;AAEtB,MAAME,GAAG,GAAGF,eAAe,IAAIC,OAAO,CAACC,GAAR,CAAYC,QAA3C;AACA,MAAMC,EAAE,GAAGF,GAAG,KAAK,YAAR,IAAwBG,OAAO,CAACC,WAAR,WAA8BC,SAA9B,CAAnC;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AACO,eAAeC,WAAf,CAA2BC,MAA3B,EAAmCC,UAAU,GAAG,CAAhD,EAAmDC,QAAQ,GAAG,IAA9D,EAAoE;EACzE;EACA,KAAK,IAAIC,CAAC,GAAG,CAAb,GAAkB,EAAEA,CAApB,EAAuB;IACrB,IAAI;MACF,OAAO,MAAMH,MAAM,EAAnB;IACD,CAFD,CAEE,OAAOI,KAAP,EAAc;MACd,IAAID,CAAC,GAAGF,UAAR,EAAoB,MAAMI,aAAA,CAAKC,KAAL,CAAWJ,QAAX,CAAN,CAApB,KACK,MAAME,KAAN;IACN;EACF;EACD;;AACD"}
1
+ {"version":3,"file":"index.js","names":["themed","COMPOSE","PRIORITY","NODE_CONFIG_ENV","process","env","NODE_ENV","JU","webpack","requireWeak","__dirname","withRetries","action","maxRetries","interval","n","error","timer"],"sources":["../../../../src/shared/utils/index.js"],"sourcesContent":["import themed, {\n COMPOSE,\n PRIORITY,\n ThemeProvider,\n} from '@dr.pogodin/react-themes';\n\nimport config from './config';\nimport * as isomorphy from './isomorphy';\nimport time, { timer } from './time';\nimport * as webpack from './webpack';\n\nexport * from './Barrier';\nexport { default as Emitter } from './Emitter';\nexport { default as Semaphore } from './Semaphore';\nexport { default as splitComponent } from './splitComponent';\n\nthemed.COMPOSE = COMPOSE;\nthemed.PRIORITY = PRIORITY;\n\n// Note: it should be done this way, as in some environments\n// \"process\" might not exist, and process.env.NODE_CONFIG_ENV\n// not injected by Webpack.\nlet NODE_CONFIG_ENV;\ntry {\n NODE_CONFIG_ENV = process.env.NODE_CONFIG_ENV;\n} catch { /* noop */ }\n\nconst env = NODE_CONFIG_ENV || process.env.NODE_ENV;\nconst JU = env !== 'production' && webpack.requireWeak('./jest', __dirname);\n\n/**\n * @category Utilities\n * @global\n * @func withRetries\n * @desc\n * ```js\n * import { withRetries } from '@dr.pogodin/react-utils';\n * ```\n * Attempts to perform given asynchronous `action` up to `maxRetries` times,\n * with the given `interval` between attempts. If any attempt is successful,\n * the result is returned immediately, with no further attempts done;\n * otherwise, if all attempts fail, the result Promise rejects after the last\n * attempt.\n * @param {function} action\n * @param {number} [maxRetries=5] Optional. Maximum number of retries. Defaults\n * to 5 attempts.\n * @param {number} [interval=1000] Optional. Interval between retries [ms].\n * Defaults to 1 second.\n * @return {Promise} Resolves to the result of successful operation, or\n * rejects with the error from the latst failed attempt.\n * @example\n * import { withRetries } from '@dr.pogodin/react-utils';\n *\n * let firstCall = true;\n *\n * function sampleAction() {\n * if (!firstCall) return 'success';\n * firstCall = false;\n * throw Error('The first call to this method fails');\n * }\n *\n * withRetries(sampleAction).then(console.log);\n * // It will print 'success' after one second, once the second attempt\n * // is performed.\n */\nexport async function withRetries(action, maxRetries = 5, interval = 1000) {\n /* eslint-disable no-await-in-loop */\n for (let n = 1; ; ++n) {\n try {\n return await action();\n } catch (error) {\n if (n < maxRetries) await timer(interval);\n else throw error;\n }\n }\n /* eslint-enable no-await-in-loop */\n}\n\nexport {\n config,\n isomorphy,\n JU,\n themed,\n ThemeProvider,\n time,\n webpack,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAMA;;AACA;;;;AACA;;AACA;;;;AAEA;;AAAA;EAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AACA;;AACA;;;;;;AAEAA,oBAAA,CAAOC,OAAP,GAAiBA,oBAAjB;AACAD,oBAAA,CAAOE,QAAP,GAAkBA,qBAAlB,C,CAEA;AACA;AACA;;AACA,IAAIC,eAAJ;;AACA,IAAI;EACFA,eAAe,GAAGC,OAAO,CAACC,GAAR,CAAYF,eAA9B;AACD,CAFD,CAEE,MAAM;EAAE;AAAY;;AAEtB,MAAME,GAAG,GAAGF,eAAe,IAAIC,OAAO,CAACC,GAAR,CAAYC,QAA3C;AACA,MAAMC,EAAE,GAAGF,GAAG,KAAK,YAAR,IAAwBG,OAAO,CAACC,WAAR,WAA8BC,SAA9B,CAAnC;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AACO,eAAeC,WAAf,CAA2BC,MAA3B,EAAmCC,UAAU,GAAG,CAAhD,EAAmDC,QAAQ,GAAG,IAA9D,EAAoE;EACzE;EACA,KAAK,IAAIC,CAAC,GAAG,CAAb,GAAkB,EAAEA,CAApB,EAAuB;IACrB,IAAI;MACF,OAAO,MAAMH,MAAM,EAAnB;IACD,CAFD,CAEE,OAAOI,KAAP,EAAc;MACd,IAAID,CAAC,GAAGF,UAAR,EAAoB,MAAM,IAAAI,WAAA,EAAMH,QAAN,CAAN,CAApB,KACK,MAAME,KAAN;IACN;EACF;EACD;;AACD"}
@@ -96,7 +96,9 @@ class E2eSsrEnv extends _jestEnvironmentJsdom.default {
96
96
  if (options.logger === undefined) {
97
97
  options.logger = {
98
98
  debug: _lodash.noop,
99
- info: _lodash.noop
99
+ info: _lodash.noop,
100
+ log: _lodash.noop,
101
+ warn: _lodash.noop
100
102
  };
101
103
  }
102
104
 
@@ -1 +1 @@
1
- {"version":3,"file":"E2eSsrEnv.js","names":["E2eSsrEnv","JsdomEnv","loadWebpackConfig","options","pragmas","JSON","parse","defaults","context","testFolder","fs","global","webpackOutputFs","factory","require","path","resolve","rootDir","webpackConfig","buildInfo","existsSync","readFileSync","runWebpack","compiler","webpack","outputFileSystem","Promise","done","fail","run","err","stats","webpackStats","toJson","runSsr","logger","undefined","debug","noop","info","root","process","cwd","register","envName","babelEnv","extensions","entry","p","Application","entryExportName","renderer","ssrFactory","status","markup","ssrRequest","send","set","value","locals","devMiddleware","error","ssrMarkup","ssrOptions","ssrStatus","constructor","config","docblockPragmas","request","url","projectConfig","dom","createFsFromVolume","Volume","dirname","testPath","withSsr","setup","REACT_UTILS_FORCE_CLIENT_SIDE","teardown","Object","keys","cache","forEach","key","revert"],"sources":["../../../../../src/shared/utils/jest/E2eSsrEnv.js"],"sourcesContent":["/**\n * Jest environment for end-to-end SSR and client-side testing. It relies on\n * the standard react-utils mechanics to execute SSR of given scene, and also\n * Webpack build of the code for client-side execution, it further exposes\n * Jsdom environment for the client-side testing of the outcomes.\n */\n/* eslint-disable global-require, import/no-dynamic-require */\n\n// BEWARE: The module is not imported into the JU module / the main assembly of\n// the library, because doing so easily breaks stuff:\n// 1) This module depends on Node-specific modules, which would make JU\n// incompatible with JsDom if included into JU.\n// 2) If this module is weakly imported from somewhere else in the lib,\n// it seems to randomly break tests using it for a different reason,\n// probably some sort of a require-loop, or some issues with weak\n// require in that scenario.\n\nimport path from 'path';\nimport ssrFactory from 'server/renderer';\n\nimport { defaults, noop, set } from 'lodash';\n\n// As this environment is a part of the Jest testing utils,\n// we assume development dependencies are available when it is used.\n/* eslint-disable import/no-extraneous-dependencies */\nimport register from '@babel/register';\nimport JsdomEnv from 'jest-environment-jsdom';\nimport { createFsFromVolume, Volume } from 'memfs';\nimport webpack from 'webpack';\n/* eslint-enable import/no-extraneous-dependencies */\n\nexport default class E2eSsrEnv extends JsdomEnv {\n /**\n * Loads Webpack config, and exposes it to the environment via global\n * webpackConfig object.\n */\n loadWebpackConfig() {\n let options = this.pragmas['webpack-config-options'];\n options = options ? JSON.parse(options) : {};\n defaults(options, {\n context: this.testFolder,\n fs: this.global.webpackOutputFs,\n });\n\n let factory = this.pragmas['webpack-config-factory'] || '';\n factory = require(path.resolve(this.rootDir, factory));\n this.global.webpackConfig = factory(options);\n\n const fs = this.global.webpackOutputFs;\n let buildInfo = `${options.context}/.build-info`;\n if (fs.existsSync(buildInfo)) {\n buildInfo = fs.readFileSync(buildInfo, 'utf8');\n this.global.buildInfo = JSON.parse(buildInfo);\n }\n }\n\n /**\n * Executes Webpack build.\n * @return {Promise}\n */\n async runWebpack() {\n this.loadWebpackConfig();\n\n const compiler = webpack(this.global.webpackConfig);\n compiler.outputFileSystem = this.global.webpackOutputFs;\n return new Promise((done, fail) => {\n compiler.run((err, stats) => {\n if (err) fail(err);\n\n this.global.webpackStats = stats.toJson();\n\n // Keeps reference to the raw Webpack stats object, which should be\n // explicitly passed to the server-side renderer alongside the request,\n // so that it can to pick up asset paths for different named chunks.\n this.webpackStats = stats;\n\n done();\n });\n });\n }\n\n async runSsr() {\n let options = this.pragmas['ssr-options'];\n options = options ? JSON.parse(options) : {};\n\n // TODO: This is temporary to shortcut the logging added to SSR.\n if (options.logger === undefined) {\n options.logger = { debug: noop, info: noop };\n }\n\n let root;\n switch (options.root) {\n case 'TEST': root = this.testFolder; break;\n default: root = process.cwd();\n }\n\n // Note: This enables Babel transformation for the code dynamically loaded\n // below, as the usual Jest Babel setup does not seem to apply to\n // the environment code, and imports from it.\n register({\n envName: options.babelEnv,\n extensions: ['.js', '.jsx', '.svg'],\n root,\n });\n\n if (!options.buildInfo) options.buildInfo = this.global.buildInfo;\n\n if (options.entry) {\n const p = path.resolve(this.testFolder, options.entry);\n options.Application = require(p)[options.entryExportName || 'default'];\n }\n\n const renderer = ssrFactory(this.global.webpackConfig, options);\n let status = 200; // OK\n const markup = await new Promise((done, fail) => {\n renderer(\n this.ssrRequest,\n\n // TODO: This will do for now, with the current implementation of\n // the renderer, but it will require a rework once the renderer is\n // updated to do streaming.\n {\n send: done,\n set: noop,\n status: (value) => {\n status = value;\n },\n\n // This is how up-to-date Webpack stats are passed to the server in\n // development mode, and we use this here always, instead of having\n // to pass some information via filesystem.\n locals: {\n webpack: {\n devMiddleware: {\n stats: this.webpackStats,\n },\n },\n },\n },\n\n (error) => {\n if (error) fail(error);\n else done('');\n },\n );\n });\n\n this.global.ssrMarkup = markup;\n this.global.ssrOptions = options;\n this.global.ssrStatus = status;\n }\n\n constructor(config, context) {\n const pragmas = context.docblockPragmas;\n let request = pragmas['ssr-request'];\n request = request ? JSON.parse(request) : {};\n if (!request.url) request.url = '/';\n\n // This ensures the initial JsDom URL matches the value we use for SSR.\n set(\n config.projectConfig,\n 'testEnvironmentOptions.url',\n `http://localhost${request.url}`,\n );\n\n super(config, context);\n\n this.global.dom = this.dom;\n this.global.webpackOutputFs = createFsFromVolume(new Volume());\n\n // Extracts necessary settings from config and context.\n const { projectConfig } = config;\n this.rootDir = projectConfig.rootDir;\n this.testFolder = path.dirname(context.testPath);\n this.withSsr = !pragmas['no-ssr'];\n this.ssrRequest = request;\n this.pragmas = pragmas;\n }\n\n async setup() {\n await super.setup();\n await this.runWebpack();\n if (this.withSsr) await this.runSsr();\n this.global.REACT_UTILS_FORCE_CLIENT_SIDE = true;\n }\n\n async teardown() {\n delete this.global.REACT_UTILS_FORCE_CLIENT_SIDE;\n\n // Resets module cache and @babel/register. Effectively this ensures that\n // the next time an instance of this environment is set up, all modules are\n // transformed by Babel from scratch, thus taking into account the latest\n // Babel config (which may change between different environment instances,\n // which does not seem to be taken into account by Babel / Node caches\n // automatically).\n Object.keys(require.cache).forEach((key) => {\n delete require.cache[key];\n });\n register.revert();\n super.teardown();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"E2eSsrEnv.js","names":["E2eSsrEnv","JsdomEnv","loadWebpackConfig","options","pragmas","JSON","parse","defaults","context","testFolder","fs","global","webpackOutputFs","factory","require","path","resolve","rootDir","webpackConfig","buildInfo","existsSync","readFileSync","runWebpack","compiler","webpack","outputFileSystem","Promise","done","fail","run","err","stats","webpackStats","toJson","runSsr","logger","undefined","debug","noop","info","log","warn","root","process","cwd","register","envName","babelEnv","extensions","entry","p","Application","entryExportName","renderer","ssrFactory","status","markup","ssrRequest","send","set","value","locals","devMiddleware","error","ssrMarkup","ssrOptions","ssrStatus","constructor","config","docblockPragmas","request","url","projectConfig","dom","createFsFromVolume","Volume","dirname","testPath","withSsr","setup","REACT_UTILS_FORCE_CLIENT_SIDE","teardown","Object","keys","cache","forEach","key","revert"],"sources":["../../../../../src/shared/utils/jest/E2eSsrEnv.js"],"sourcesContent":["/**\n * Jest environment for end-to-end SSR and client-side testing. It relies on\n * the standard react-utils mechanics to execute SSR of given scene, and also\n * Webpack build of the code for client-side execution, it further exposes\n * Jsdom environment for the client-side testing of the outcomes.\n */\n/* eslint-disable global-require, import/no-dynamic-require */\n\n// BEWARE: The module is not imported into the JU module / the main assembly of\n// the library, because doing so easily breaks stuff:\n// 1) This module depends on Node-specific modules, which would make JU\n// incompatible with JsDom if included into JU.\n// 2) If this module is weakly imported from somewhere else in the lib,\n// it seems to randomly break tests using it for a different reason,\n// probably some sort of a require-loop, or some issues with weak\n// require in that scenario.\n\nimport path from 'path';\nimport ssrFactory from 'server/renderer';\n\nimport { defaults, noop, set } from 'lodash';\n\n// As this environment is a part of the Jest testing utils,\n// we assume development dependencies are available when it is used.\n/* eslint-disable import/no-extraneous-dependencies */\nimport register from '@babel/register';\nimport JsdomEnv from 'jest-environment-jsdom';\nimport { createFsFromVolume, Volume } from 'memfs';\nimport webpack from 'webpack';\n/* eslint-enable import/no-extraneous-dependencies */\n\nexport default class E2eSsrEnv extends JsdomEnv {\n /**\n * Loads Webpack config, and exposes it to the environment via global\n * webpackConfig object.\n */\n loadWebpackConfig() {\n let options = this.pragmas['webpack-config-options'];\n options = options ? JSON.parse(options) : {};\n defaults(options, {\n context: this.testFolder,\n fs: this.global.webpackOutputFs,\n });\n\n let factory = this.pragmas['webpack-config-factory'] || '';\n factory = require(path.resolve(this.rootDir, factory));\n this.global.webpackConfig = factory(options);\n\n const fs = this.global.webpackOutputFs;\n let buildInfo = `${options.context}/.build-info`;\n if (fs.existsSync(buildInfo)) {\n buildInfo = fs.readFileSync(buildInfo, 'utf8');\n this.global.buildInfo = JSON.parse(buildInfo);\n }\n }\n\n /**\n * Executes Webpack build.\n * @return {Promise}\n */\n async runWebpack() {\n this.loadWebpackConfig();\n\n const compiler = webpack(this.global.webpackConfig);\n compiler.outputFileSystem = this.global.webpackOutputFs;\n return new Promise((done, fail) => {\n compiler.run((err, stats) => {\n if (err) fail(err);\n\n this.global.webpackStats = stats.toJson();\n\n // Keeps reference to the raw Webpack stats object, which should be\n // explicitly passed to the server-side renderer alongside the request,\n // so that it can to pick up asset paths for different named chunks.\n this.webpackStats = stats;\n\n done();\n });\n });\n }\n\n async runSsr() {\n let options = this.pragmas['ssr-options'];\n options = options ? JSON.parse(options) : {};\n\n // TODO: This is temporary to shortcut the logging added to SSR.\n if (options.logger === undefined) {\n options.logger = {\n debug: noop,\n info: noop,\n log: noop,\n warn: noop,\n };\n }\n\n let root;\n switch (options.root) {\n case 'TEST': root = this.testFolder; break;\n default: root = process.cwd();\n }\n\n // Note: This enables Babel transformation for the code dynamically loaded\n // below, as the usual Jest Babel setup does not seem to apply to\n // the environment code, and imports from it.\n register({\n envName: options.babelEnv,\n extensions: ['.js', '.jsx', '.svg'],\n root,\n });\n\n if (!options.buildInfo) options.buildInfo = this.global.buildInfo;\n\n if (options.entry) {\n const p = path.resolve(this.testFolder, options.entry);\n options.Application = require(p)[options.entryExportName || 'default'];\n }\n\n const renderer = ssrFactory(this.global.webpackConfig, options);\n let status = 200; // OK\n const markup = await new Promise((done, fail) => {\n renderer(\n this.ssrRequest,\n\n // TODO: This will do for now, with the current implementation of\n // the renderer, but it will require a rework once the renderer is\n // updated to do streaming.\n {\n send: done,\n set: noop,\n status: (value) => {\n status = value;\n },\n\n // This is how up-to-date Webpack stats are passed to the server in\n // development mode, and we use this here always, instead of having\n // to pass some information via filesystem.\n locals: {\n webpack: {\n devMiddleware: {\n stats: this.webpackStats,\n },\n },\n },\n },\n\n (error) => {\n if (error) fail(error);\n else done('');\n },\n );\n });\n\n this.global.ssrMarkup = markup;\n this.global.ssrOptions = options;\n this.global.ssrStatus = status;\n }\n\n constructor(config, context) {\n const pragmas = context.docblockPragmas;\n let request = pragmas['ssr-request'];\n request = request ? JSON.parse(request) : {};\n if (!request.url) request.url = '/';\n\n // This ensures the initial JsDom URL matches the value we use for SSR.\n set(\n config.projectConfig,\n 'testEnvironmentOptions.url',\n `http://localhost${request.url}`,\n );\n\n super(config, context);\n\n this.global.dom = this.dom;\n this.global.webpackOutputFs = createFsFromVolume(new Volume());\n\n // Extracts necessary settings from config and context.\n const { projectConfig } = config;\n this.rootDir = projectConfig.rootDir;\n this.testFolder = path.dirname(context.testPath);\n this.withSsr = !pragmas['no-ssr'];\n this.ssrRequest = request;\n this.pragmas = pragmas;\n }\n\n async setup() {\n await super.setup();\n await this.runWebpack();\n if (this.withSsr) await this.runSsr();\n this.global.REACT_UTILS_FORCE_CLIENT_SIDE = true;\n }\n\n async teardown() {\n delete this.global.REACT_UTILS_FORCE_CLIENT_SIDE;\n\n // Resets module cache and @babel/register. Effectively this ensures that\n // the next time an instance of this environment is set up, all modules are\n // transformed by Babel from scratch, thus taking into account the latest\n // Babel config (which may change between different environment instances,\n // which does not seem to be taken into account by Babel / Node caches\n // automatically).\n Object.keys(require.cache).forEach((key) => {\n delete require.cache[key];\n });\n register.revert();\n super.teardown();\n }\n}\n"],"mappings":"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"}
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.default = void 0;
9
+ exports.timer = timer;
9
10
 
10
11
  var _dayjs = _interopRequireDefault(require("dayjs"));
11
12
 
@@ -80,15 +81,16 @@ _dayjs.default.now = Date.now;
80
81
  * (without resolving or rejecting the barrier).
81
82
  */
82
83
 
83
- _dayjs.default.timer = async function timer(timeout) {
84
+ async function timer(timeout) {
84
85
  const res = new _Barrier.Barrier();
85
86
  const id = setTimeout(res.resolve.bind(res), timeout);
86
87
 
87
88
  res.abort = () => clearTimeout(id);
88
89
 
89
90
  return res;
90
- };
91
+ }
91
92
 
93
+ _dayjs.default.timer = timer;
92
94
  var _default = _dayjs.default;
93
95
  exports.default = _default;
94
96
  //# sourceMappingURL=time.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"time.js","names":["dayjs","SEC_MS","MIN_MS","HOUR_MS","DAY_MS","YEAR_MS","now","Date","timer","timeout","res","Barrier","id","setTimeout","resolve","bind","abort","clearTimeout"],"sources":["../../../../src/shared/utils/time.js"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Barrier } from './Barrier';\n\n/**\n * @static\n * @const SEC_MS\n * @desc One second, expressed in milliseconds (equals 1000 ms).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.SEC_MS); // Prints: 1000\n */\ndayjs.SEC_MS = 1000;\n\n/**\n * @static\n * @const MIN_MS\n * @desc One minute, expressed in milliseconds (equals 60 &times; `SEC_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.MIN_MS); // Prints: 60000\n */\ndayjs.MIN_MS = 60 * dayjs.SEC_MS;\n\n/**\n * @static\n * @const HOUR_MS\n * @desc One hour, expressed in milliseconds (equals 60 &times; `MIN_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.HOUR_MS); // Prints: 3600000\n */\ndayjs.HOUR_MS = 60 * dayjs.MIN_MS;\n\n/**\n * @static\n * @const DAY_MS\n * @desc One day, expressed in milliseconds (equals 24 &times; `HOUR_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.DAY_MS); // Prints: 86400000\n */\ndayjs.DAY_MS = 24 * dayjs.HOUR_MS;\n\n/**\n * @static\n * @const YEAR_MS\n * @desc One year, expressed in milliseconds (equals 365 &times; `DAY_MS`,\n * thus a normal, non-leap year).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.YEAR_MS); // Prints: 31536000000\n */\ndayjs.YEAR_MS = 365 * dayjs.DAY_MS;\n\n/**\n * @static\n * @func now\n * @desc Returns Unix timestamp [ms] (thus, it is just an alias for `Date.now`).\n * @return {number}\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.now()); // Prints the current timestamp, e.g. 1618608761000.\n */\ndayjs.now = Date.now;\n\n/**\n * Creates a Promise, which resolves after the given timeout.\n * @param {number} timeout Timeout [ms].\n * @return {Barrier} Resolves after the timeout. It has additional\n * .abort() method attached, which cancels the pending timer resolution\n * (without resolving or rejecting the barrier).\n */\ndayjs.timer = async function timer(timeout) {\n const res = new Barrier();\n const id = setTimeout(res.resolve.bind(res), timeout);\n res.abort = () => clearTimeout(id);\n return res;\n};\n\nexport default dayjs;\n"],"mappings":";;;;;;;;;AAAA;;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAA,cAAA,CAAMC,MAAN,GAAe,IAAf;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAD,cAAA,CAAME,MAAN,GAAe,KAAKF,cAAA,CAAMC,MAA1B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAD,cAAA,CAAMG,OAAN,GAAgB,KAAKH,cAAA,CAAME,MAA3B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAF,cAAA,CAAMI,MAAN,GAAe,KAAKJ,cAAA,CAAMG,OAA1B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAH,cAAA,CAAMK,OAAN,GAAgB,MAAML,cAAA,CAAMI,MAA5B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAJ,cAAA,CAAMM,GAAN,GAAYC,IAAI,CAACD,GAAjB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAN,cAAA,CAAMQ,KAAN,GAAc,eAAeA,KAAf,CAAqBC,OAArB,EAA8B;EAC1C,MAAMC,GAAG,GAAG,IAAIC,gBAAJ,EAAZ;EACA,MAAMC,EAAE,GAAGC,UAAU,CAACH,GAAG,CAACI,OAAJ,CAAYC,IAAZ,CAAiBL,GAAjB,CAAD,EAAwBD,OAAxB,CAArB;;EACAC,GAAG,CAACM,KAAJ,GAAY,MAAMC,YAAY,CAACL,EAAD,CAA9B;;EACA,OAAOF,GAAP;AACD,CALD;;eAOeV,c"}
1
+ {"version":3,"file":"time.js","names":["dayjs","SEC_MS","MIN_MS","HOUR_MS","DAY_MS","YEAR_MS","now","Date","timer","timeout","res","Barrier","id","setTimeout","resolve","bind","abort","clearTimeout"],"sources":["../../../../src/shared/utils/time.js"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Barrier } from './Barrier';\n\n/**\n * @static\n * @const SEC_MS\n * @desc One second, expressed in milliseconds (equals 1000 ms).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.SEC_MS); // Prints: 1000\n */\ndayjs.SEC_MS = 1000;\n\n/**\n * @static\n * @const MIN_MS\n * @desc One minute, expressed in milliseconds (equals 60 &times; `SEC_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.MIN_MS); // Prints: 60000\n */\ndayjs.MIN_MS = 60 * dayjs.SEC_MS;\n\n/**\n * @static\n * @const HOUR_MS\n * @desc One hour, expressed in milliseconds (equals 60 &times; `MIN_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.HOUR_MS); // Prints: 3600000\n */\ndayjs.HOUR_MS = 60 * dayjs.MIN_MS;\n\n/**\n * @static\n * @const DAY_MS\n * @desc One day, expressed in milliseconds (equals 24 &times; `HOUR_MS`).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.DAY_MS); // Prints: 86400000\n */\ndayjs.DAY_MS = 24 * dayjs.HOUR_MS;\n\n/**\n * @static\n * @const YEAR_MS\n * @desc One year, expressed in milliseconds (equals 365 &times; `DAY_MS`,\n * thus a normal, non-leap year).\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.YEAR_MS); // Prints: 31536000000\n */\ndayjs.YEAR_MS = 365 * dayjs.DAY_MS;\n\n/**\n * @static\n * @func now\n * @desc Returns Unix timestamp [ms] (thus, it is just an alias for `Date.now`).\n * @return {number}\n * @example\n * import { time } from '@dr.pogodin/react-utils';\n * console.log(time.now()); // Prints the current timestamp, e.g. 1618608761000.\n */\ndayjs.now = Date.now;\n\n/**\n * Creates a Promise, which resolves after the given timeout.\n * @param {number} timeout Timeout [ms].\n * @return {Barrier} Resolves after the timeout. It has additional\n * .abort() method attached, which cancels the pending timer resolution\n * (without resolving or rejecting the barrier).\n */\nexport async function timer(timeout) {\n const res = new Barrier();\n const id = setTimeout(res.resolve.bind(res), timeout);\n res.abort = () => clearTimeout(id);\n return res;\n}\n\ndayjs.timer = timer;\n\nexport default dayjs;\n"],"mappings":";;;;;;;;;;AAAA;;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAA,cAAA,CAAMC,MAAN,GAAe,IAAf;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAD,cAAA,CAAME,MAAN,GAAe,KAAKF,cAAA,CAAMC,MAA1B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAD,cAAA,CAAMG,OAAN,GAAgB,KAAKH,cAAA,CAAME,MAA3B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAF,cAAA,CAAMI,MAAN,GAAe,KAAKJ,cAAA,CAAMG,OAA1B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAH,cAAA,CAAMK,OAAN,GAAgB,MAAML,cAAA,CAAMI,MAA5B;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAJ,cAAA,CAAMM,GAAN,GAAYC,IAAI,CAACD,GAAjB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,eAAeE,KAAf,CAAqBC,OAArB,EAA8B;EACnC,MAAMC,GAAG,GAAG,IAAIC,gBAAJ,EAAZ;EACA,MAAMC,EAAE,GAAGC,UAAU,CAACH,GAAG,CAACI,OAAJ,CAAYC,IAAZ,CAAiBL,GAAjB,CAAD,EAAwBD,OAAxB,CAArB;;EACAC,GAAG,CAACM,KAAJ,GAAY,MAAMC,YAAY,CAACL,EAAD,CAA9B;;EACA,OAAOF,GAAP;AACD;;AAEDV,cAAA,CAAMQ,KAAN,GAAcA,KAAd;eAEeR,c"}