@dr.pogodin/react-utils 1.47.0-alpha.2 → 1.47.0-alpha.4

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.
Files changed (223) hide show
  1. package/babel.config.js +1 -1
  2. package/babel.module.config.js +11 -0
  3. package/bin/build.js +8 -4
  4. package/bin/setup.js +2 -3
  5. package/build/development/client/getInj.js +47 -45
  6. package/build/development/client/getInj.js.map +1 -1
  7. package/build/development/client/index.js +15 -21
  8. package/build/development/client/index.js.map +1 -1
  9. package/build/development/client/init.js +2 -6
  10. package/build/development/client/init.js.map +1 -1
  11. package/build/development/index.js +10 -179
  12. package/build/development/index.js.map +1 -1
  13. package/build/development/server/Cache.js +1 -8
  14. package/build/development/server/Cache.js.map +1 -1
  15. package/build/development/server/index.js +25 -50
  16. package/build/development/server/index.js.map +1 -1
  17. package/build/development/server/renderer.js +63 -92
  18. package/build/development/server/renderer.js.map +1 -1
  19. package/build/development/server/server.js +47 -58
  20. package/build/development/server/server.js.map +1 -1
  21. package/build/development/server/utils/errors.js +8 -31
  22. package/build/development/server/utils/errors.js.map +1 -1
  23. package/build/development/server/utils/index.js +2 -9
  24. package/build/development/server/utils/index.js.map +1 -1
  25. package/build/development/shared/components/Button/index.js +9 -16
  26. package/build/development/shared/components/Button/index.js.map +1 -1
  27. package/build/development/shared/components/Checkbox/index.js +6 -13
  28. package/build/development/shared/components/Checkbox/index.js.map +1 -1
  29. package/build/development/shared/components/GenericLink/index.js +4 -10
  30. package/build/development/shared/components/GenericLink/index.js.map +1 -1
  31. package/build/development/shared/components/Input/index.js +11 -18
  32. package/build/development/shared/components/Input/index.js.map +1 -1
  33. package/build/development/shared/components/Link.js +6 -13
  34. package/build/development/shared/components/Link.js.map +1 -1
  35. package/build/development/shared/components/Modal/index.js +16 -22
  36. package/build/development/shared/components/Modal/index.js.map +1 -1
  37. package/build/development/shared/components/NavLink.js +6 -13
  38. package/build/development/shared/components/NavLink.js.map +1 -1
  39. package/build/development/shared/components/PageLayout/index.js +7 -14
  40. package/build/development/shared/components/PageLayout/index.js.map +1 -1
  41. package/build/development/shared/components/TextArea/index.js +15 -22
  42. package/build/development/shared/components/TextArea/index.js.map +1 -1
  43. package/build/development/shared/components/Throbber/index.js +7 -14
  44. package/build/development/shared/components/Throbber/index.js.map +1 -1
  45. package/build/development/shared/components/WithTooltip/Tooltip.js +12 -18
  46. package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
  47. package/build/development/shared/components/WithTooltip/index.js +16 -23
  48. package/build/development/shared/components/WithTooltip/index.js.map +1 -1
  49. package/build/development/shared/components/YouTubeVideo/index.js +10 -17
  50. package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
  51. package/build/development/shared/components/index.js +16 -130
  52. package/build/development/shared/components/index.js.map +1 -1
  53. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js +12 -19
  54. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  55. package/build/development/shared/components/selectors/CustomDropdown/index.js +20 -28
  56. package/build/development/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  57. package/build/development/shared/components/selectors/NativeDropdown/index.js +13 -19
  58. package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  59. package/build/development/shared/components/selectors/Switch/index.js +10 -17
  60. package/build/development/shared/components/selectors/Switch/index.js.map +1 -1
  61. package/build/development/shared/components/selectors/common.js +1 -7
  62. package/build/development/shared/components/selectors/common.js.map +1 -1
  63. package/build/development/shared/components/selectors/index.js +3 -27
  64. package/build/development/shared/components/selectors/index.js.map +1 -1
  65. package/build/development/shared/utils/config.js +40 -20
  66. package/build/development/shared/utils/config.js.map +1 -1
  67. package/build/development/shared/utils/globalState.js +3 -8
  68. package/build/development/shared/utils/globalState.js.map +1 -1
  69. package/build/development/shared/utils/index.js +12 -89
  70. package/build/development/shared/utils/index.js.map +1 -1
  71. package/build/development/shared/utils/isomorphy/buildInfo.js +2 -9
  72. package/build/development/shared/utils/isomorphy/buildInfo.js.map +1 -1
  73. package/build/development/shared/utils/isomorphy/environment-check.js +2 -8
  74. package/build/development/shared/utils/isomorphy/environment-check.js.map +1 -1
  75. package/build/development/shared/utils/isomorphy/index.js +7 -32
  76. package/build/development/shared/utils/isomorphy/index.js.map +1 -1
  77. package/build/development/shared/utils/jest/E2eSsrEnv.js +20 -31
  78. package/build/development/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  79. package/build/development/shared/utils/jest/global.js +1 -7
  80. package/build/development/shared/utils/jest/global.js.map +1 -1
  81. package/build/development/shared/utils/jest/index.js +20 -44
  82. package/build/development/shared/utils/jest/index.js.map +1 -1
  83. package/build/development/shared/utils/splitComponent.js +24 -30
  84. package/build/development/shared/utils/splitComponent.js.map +1 -1
  85. package/build/development/shared/utils/time.js +22 -31
  86. package/build/development/shared/utils/time.js.map +1 -1
  87. package/build/development/shared/utils/webpack.js +13 -16
  88. package/build/development/shared/utils/webpack.js.map +1 -1
  89. package/build/production/client/getInj.js +13 -11
  90. package/build/production/client/getInj.js.map +1 -1
  91. package/build/production/client/index.js +3 -3
  92. package/build/production/client/index.js.map +1 -1
  93. package/build/production/client/init.js +2 -2
  94. package/build/production/client/init.js.map +1 -1
  95. package/build/production/index.js +3 -2
  96. package/build/production/index.js.map +1 -1
  97. package/build/production/server/Cache.js +3 -3
  98. package/build/production/server/Cache.js.map +1 -1
  99. package/build/production/server/index.js +8 -8
  100. package/build/production/server/index.js.map +1 -1
  101. package/build/production/server/renderer.js +24 -25
  102. package/build/production/server/renderer.js.map +1 -1
  103. package/build/production/server/server.js +9 -9
  104. package/build/production/server/server.js.map +1 -1
  105. package/build/production/server/utils/errors.js +9 -9
  106. package/build/production/server/utils/errors.js.map +1 -1
  107. package/build/production/server/utils/index.js +2 -1
  108. package/build/production/server/utils/index.js.map +1 -1
  109. package/build/production/shared/components/Button/index.js +4 -4
  110. package/build/production/shared/components/Button/index.js.map +1 -1
  111. package/build/production/shared/components/Checkbox/index.js +1 -1
  112. package/build/production/shared/components/Checkbox/index.js.map +1 -1
  113. package/build/production/shared/components/GenericLink/index.js +4 -4
  114. package/build/production/shared/components/GenericLink/index.js.map +1 -1
  115. package/build/production/shared/components/Input/index.js +5 -5
  116. package/build/production/shared/components/Input/index.js.map +1 -1
  117. package/build/production/shared/components/Link.js +3 -3
  118. package/build/production/shared/components/Link.js.map +1 -1
  119. package/build/production/shared/components/Modal/index.js +7 -7
  120. package/build/production/shared/components/Modal/index.js.map +1 -1
  121. package/build/production/shared/components/NavLink.js +2 -2
  122. package/build/production/shared/components/NavLink.js.map +1 -1
  123. package/build/production/shared/components/PageLayout/index.js +2 -2
  124. package/build/production/shared/components/PageLayout/index.js.map +1 -1
  125. package/build/production/shared/components/TextArea/index.js +5 -5
  126. package/build/production/shared/components/TextArea/index.js.map +1 -1
  127. package/build/production/shared/components/Throbber/index.js +2 -2
  128. package/build/production/shared/components/Throbber/index.js.map +1 -1
  129. package/build/production/shared/components/WithTooltip/Tooltip.js +4 -4
  130. package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
  131. package/build/production/shared/components/WithTooltip/index.js +4 -4
  132. package/build/production/shared/components/WithTooltip/index.js.map +1 -1
  133. package/build/production/shared/components/YouTubeVideo/index.js +4 -4
  134. package/build/production/shared/components/YouTubeVideo/index.js.map +1 -1
  135. package/build/production/shared/components/index.js +3 -1
  136. package/build/production/shared/components/index.js.map +1 -1
  137. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js +2 -2
  138. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  139. package/build/production/shared/components/selectors/CustomDropdown/index.js +2 -2
  140. package/build/production/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  141. package/build/production/shared/components/selectors/NativeDropdown/index.js +4 -4
  142. package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  143. package/build/production/shared/components/selectors/Switch/index.js +1 -1
  144. package/build/production/shared/components/selectors/Switch/index.js.map +1 -1
  145. package/build/production/shared/components/selectors/common.js +2 -2
  146. package/build/production/shared/components/selectors/common.js.map +1 -1
  147. package/build/production/shared/components/selectors/index.js +1 -1
  148. package/build/production/shared/components/selectors/index.js.map +1 -1
  149. package/build/production/shared/utils/config.js +8 -4
  150. package/build/production/shared/utils/config.js.map +1 -1
  151. package/build/production/shared/utils/globalState.js +2 -2
  152. package/build/production/shared/utils/globalState.js.map +1 -1
  153. package/build/production/shared/utils/index.js +1 -1
  154. package/build/production/shared/utils/index.js.map +1 -1
  155. package/build/production/shared/utils/isomorphy/buildInfo.js +3 -3
  156. package/build/production/shared/utils/isomorphy/buildInfo.js.map +1 -1
  157. package/build/production/shared/utils/isomorphy/environment-check.js +3 -3
  158. package/build/production/shared/utils/isomorphy/environment-check.js.map +1 -1
  159. package/build/production/shared/utils/isomorphy/index.js +4 -4
  160. package/build/production/shared/utils/isomorphy/index.js.map +1 -1
  161. package/build/production/shared/utils/jest/E2eSsrEnv.js +14 -14
  162. package/build/production/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  163. package/build/production/shared/utils/jest/global.js +1 -1
  164. package/build/production/shared/utils/jest/global.js.map +1 -1
  165. package/build/production/shared/utils/jest/index.js +11 -11
  166. package/build/production/shared/utils/jest/index.js.map +1 -1
  167. package/build/production/shared/utils/splitComponent.js +11 -11
  168. package/build/production/shared/utils/splitComponent.js.map +1 -1
  169. package/build/production/shared/utils/time.js +3 -3
  170. package/build/production/shared/utils/time.js.map +1 -1
  171. package/build/production/shared/utils/webpack.js +6 -6
  172. package/build/production/shared/utils/webpack.js.map +1 -1
  173. package/build/types-code/client/getInj.d.ts +1 -2
  174. package/build/types-code/client/index.d.ts +1 -1
  175. package/build/types-code/index.d.ts +1 -1
  176. package/build/types-code/server/index.d.ts +2 -2
  177. package/build/types-code/shared/utils/config.d.ts +4 -2
  178. package/build/types-code/shared/utils/index.d.ts +2 -2
  179. package/build/types-code/shared/utils/splitComponent.d.ts +6 -4
  180. package/build/web/client/getInj.js +48 -37
  181. package/build/web/client/getInj.js.map +1 -1
  182. package/build/web/client/index.js +3 -2
  183. package/build/web/client/index.js.map +1 -1
  184. package/build/web/index.js +3 -3
  185. package/build/web/index.js.map +1 -1
  186. package/build/web/server/index.js +9 -15
  187. package/build/web/server/index.js.map +1 -1
  188. package/build/web/server/renderer.js +24 -40
  189. package/build/web/server/renderer.js.map +1 -1
  190. package/build/web/server/server.js +2 -4
  191. package/build/web/server/server.js.map +1 -1
  192. package/build/web/shared/components/Modal/index.js +2 -2
  193. package/build/web/shared/components/Modal/index.js.map +1 -1
  194. package/build/web/shared/utils/config.js +36 -10
  195. package/build/web/shared/utils/config.js.map +1 -1
  196. package/build/web/shared/utils/index.js +2 -2
  197. package/build/web/shared/utils/index.js.map +1 -1
  198. package/build/web/shared/utils/jest/E2eSsrEnv.js +1 -2
  199. package/build/web/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  200. package/build/web/shared/utils/splitComponent.js +2 -1
  201. package/build/web/shared/utils/splitComponent.js.map +1 -1
  202. package/build/web/shared/utils/webpack.js +11 -7
  203. package/build/web/shared/utils/webpack.js.map +1 -1
  204. package/config/babel/node-ssr.js +5 -5
  205. package/config/jest/default.js +1 -0
  206. package/config/jest/setup.js +8 -1
  207. package/config/webpack/app-base.js +13 -12
  208. package/config/webpack/app-development.js +3 -3
  209. package/config/webpack/lib-base.js +1 -2
  210. package/package.json +9 -9
  211. package/src/client/getInj.ts +60 -40
  212. package/src/client/index.tsx +5 -3
  213. package/src/index.ts +3 -3
  214. package/src/server/index.ts +9 -15
  215. package/src/server/renderer.tsx +27 -45
  216. package/src/server/server.ts +2 -4
  217. package/src/shared/components/Modal/index.tsx +2 -2
  218. package/src/shared/utils/config.ts +48 -12
  219. package/src/shared/utils/index.ts +2 -2
  220. package/src/shared/utils/jest/E2eSsrEnv.ts +1 -2
  221. package/src/shared/utils/splitComponent.tsx +14 -2
  222. package/src/shared/utils/webpack.ts +14 -8
  223. package/types.d.ts +1 -6
@@ -1 +1 @@
1
- {"version":3,"file":"splitComponent.js","names":["Suspense","lazy","useInsertionEffect","Barrier","getSsrContext","IS_CLIENT_SIDE","IS_SERVER_SIDE","getBuildInfo","jsx","_jsx","getClientChunkGroups","undefined","default","getInj","CHUNK_GROUPS","refCounts","getPublicPath","publicPath","bookStyleSheet","name","loadedSheets","refCount","res","path","fullPath","document","location","origin","has","link","querySelector","createElement","setAttribute","head","appendChild","addEventListener","Error","resolve","current","getLoadedStyleSheets","Set","styleSheets","href","add","assertChunkName","chunkName","chunkGroups","bookStyleSheets","promises","assets","Promise","asset","endsWith","promise","push","length","allSettled","then","freeStyleSheets","pathRefCount","remove","usedChunkNames","splitComponent","getComponent","placeholder","LazyComponent","clientChunkGroups","resolved","Component","Wrapper","children","ref","rest","chunks","includes","CodeSplit","fallback"],"sources":["../../../../src/shared/utils/splitComponent.tsx"],"sourcesContent":["/* global document */\n\nimport {\n type ComponentType,\n type FunctionComponent,\n type ReactNode,\n type RefObject,\n Suspense,\n lazy,\n useInsertionEffect,\n} from 'react';\n\nimport { Barrier } from '@dr.pogodin/js-utils';\n\nimport { type ChunkGroupsT, getSsrContext } from './globalState';\n\nimport {\n IS_CLIENT_SIDE,\n IS_SERVER_SIDE,\n getBuildInfo,\n} from './isomorphy';\n\nfunction getClientChunkGroups(): Promise<ChunkGroupsT> | undefined {\n if (!IS_CLIENT_SIDE) return undefined;\n\n return (async () => {\n const { default: getInj } = await import(/* webpackChunkName: \"react-utils-client-side-code\" */ '../../client/getInj');\n return getInj().CHUNK_GROUPS ?? {};\n })();\n}\n\nconst refCounts: Record<string, number> = {};\n\nfunction getPublicPath() {\n return getBuildInfo().publicPath;\n}\n\n/**\n * Client-side only! Ensures the specified CSS stylesheet is loaded into\n * the document; loads if it is missing; and does simple reference counting\n * to facilitate future clean-up.\n * @param name\n * @param loadedSheets\n * @param refCount\n * @return\n */\nfunction bookStyleSheet(\n name: string,\n loadedSheets: Set<string>,\n refCount: boolean,\n): Promise<void> | undefined {\n let res: Barrier<void> | undefined;\n const path = `${getPublicPath()}/${name}`;\n const fullPath = `${document.location.origin}${path}`;\n\n if (!loadedSheets.has(fullPath)) {\n let link = document.querySelector(`link[href=\"${path}\"]`);\n\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('rel', 'stylesheet');\n link.setAttribute('href', path);\n document.head.appendChild(link);\n }\n\n res = new Barrier<void>();\n link.addEventListener('load', () => {\n if (!res) throw Error('Internal error');\n void res.resolve();\n });\n link.addEventListener('error', () => {\n if (!res) throw Error('Internal error');\n void res.resolve();\n });\n }\n\n if (refCount) {\n const current = refCounts[path] ?? 0;\n refCounts[path] = 1 + current;\n }\n\n return res;\n}\n\n/**\n * Generates the set of URLs for currently loaded, linked stylesheets.\n * @return\n */\nfunction getLoadedStyleSheets(): Set<string> {\n const res = new Set<string>();\n const { styleSheets } = document;\n for (const { href } of styleSheets) {\n if (href) res.add(href);\n }\n return res;\n}\n\nfunction assertChunkName(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n) {\n if (chunkGroups[chunkName]) return;\n throw Error(`Unknown chunk name \"${chunkName}\"`);\n}\n\n/**\n * Client-side only! Ensures all CSS stylesheets required for the specified\n * code chunk are loaded into the document; loads the missing ones; and does\n * simple reference counting to facilitate future clean-up.\n * @param chunkName Chunk name.\n * @param refCount\n * @return Resolves once all pending stylesheets, necessary for\n * the chunk, are either loaded, or failed to load.\n */\nexport async function bookStyleSheets(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n refCount: boolean,\n): Promise<void> {\n const promises = [];\n const assets = chunkGroups[chunkName];\n if (!assets) return Promise.resolve();\n\n const loadedSheets = getLoadedStyleSheets();\n\n for (const asset of assets) {\n if (asset.endsWith('.css')) {\n const promise = bookStyleSheet(asset, loadedSheets, refCount);\n if (promise) promises.push(promise);\n }\n }\n\n return promises.length\n ? Promise.allSettled(promises).then()\n : Promise.resolve();\n}\n\n/**\n * Client-side only! Frees from the document all CSS stylesheets that are\n * required by the specified chunk, and have reference counter equal to one\n * (for chunks with larger reference counter values, it just decrements\n * the reference counter).\n * @param {string} chunkName\n */\nexport function freeStyleSheets(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n): void {\n const assets = chunkGroups[chunkName];\n if (!assets) return;\n\n for (const asset of assets) {\n if (asset.endsWith('.css')) {\n const path = `${getPublicPath()}/${asset}`;\n\n const pathRefCount = refCounts[path];\n if (pathRefCount) {\n if (pathRefCount <= 1) {\n document.head.querySelector(`link[href=\"${path}\"]`)!.remove();\n delete refCounts[path];\n } else refCounts[path] = pathRefCount - 1;\n }\n }\n }\n}\n\n// Holds the set of chunk names already used for splitComponent() calls.\nconst usedChunkNames = new Set();\n\ntype ComponentOrModule<PropsT> = ComponentType<PropsT> | {\n default: ComponentType<PropsT>;\n};\n\n/**\n * Given an async component retrieval function `getComponent()` it creates\n * a special \"code split\" component, which uses <Suspense> to asynchronously\n * load on demand the code required by `getComponent()`.\n * @param options\n * @param options.chunkName\n * @param {function} options.getComponent\n * @param {React.Element} [options.placeholder]\n * @return {React.ElementType}\n */\nexport default function splitComponent<\n ComponentPropsT extends { children?: ReactNode; ref?: RefObject<unknown> },\n>({\n chunkName,\n getComponent,\n placeholder,\n}: {\n chunkName: string;\n getComponent: () => Promise<ComponentOrModule<ComponentPropsT>>;\n placeholder?: ReactNode;\n}): FunctionComponent<ComponentPropsT> {\n // The correct usage of splitComponent() assumes a single call per chunk.\n if (usedChunkNames.has(chunkName)) {\n throw Error(`Repeated splitComponent() call for the chunk \"${chunkName}\"`);\n } else usedChunkNames.add(chunkName);\n\n const LazyComponent = lazy(async () => {\n const clientChunkGroups = await getClientChunkGroups();\n\n // On the client side we can check right away if the chunk name is known.\n if (IS_CLIENT_SIDE) {\n if (!clientChunkGroups) throw Error('Internal error');\n assertChunkName(chunkName, clientChunkGroups);\n }\n\n const resolved = await getComponent();\n const Component = 'default' in resolved ? resolved.default : resolved;\n\n // This pre-loads necessary stylesheets prior to the first mount of\n // the component (the lazy load function is executed by React one at\n // the frist mount).\n if (IS_CLIENT_SIDE) {\n if (!clientChunkGroups) throw Error('Internal error');\n await bookStyleSheets(chunkName, clientChunkGroups, false);\n }\n\n const Wrapper: FunctionComponent<ComponentPropsT> = ({\n children,\n ref,\n ...rest\n }) => {\n // On the server side we'll assert the chunk name here,\n // and also push it to the SSR chunks array.\n if (IS_SERVER_SIDE) {\n const { chunkGroups, chunks } = getSsrContext()!;\n assertChunkName(chunkName, chunkGroups);\n if (!chunks.includes(chunkName)) chunks.push(chunkName);\n }\n\n // This takes care about stylesheets management every time an instance of\n // this component is mounted / unmounted.\n useInsertionEffect(() => {\n if (!clientChunkGroups) throw Error('Internal error');\n void bookStyleSheets(chunkName, clientChunkGroups, true);\n return () => {\n freeStyleSheets(chunkName, clientChunkGroups);\n };\n }, []);\n\n return (\n <Component\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...(rest as unknown as ComponentPropsT)}\n ref={ref}\n >\n {children}\n </Component>\n );\n };\n\n return { default: Wrapper };\n });\n\n const CodeSplit: React.FunctionComponent<ComponentPropsT> = ({\n children,\n ...rest\n }: ComponentPropsT) => (\n <Suspense fallback={placeholder}>\n <LazyComponent\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...rest as Parameters<typeof LazyComponent>[0]}\n >\n {children}\n </LazyComponent>\n </Suspense>\n );\n\n return CodeSplit;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"splitComponent.js","names":["Suspense","lazy","useInsertionEffect","Barrier","getSsrContext","IS_CLIENT_SIDE","IS_SERVER_SIDE","getBuildInfo","jsx","_jsx","getClientChunkGroups","undefined","default","getInj","inj","CHUNK_GROUPS","refCounts","getPublicPath","publicPath","bookStyleSheet","name","loadedSheets","refCount","res","path","fullPath","document","location","origin","has","link","querySelector","createElement","setAttribute","head","appendChild","addEventListener","Error","resolve","current","getLoadedStyleSheets","Set","styleSheets","href","add","assertChunkName","chunkName","chunkGroups","bookStyleSheets","promises","assets","Promise","asset","endsWith","promise","push","length","allSettled","then","freeStyleSheets","pathRefCount","remove","usedChunkNames","splitComponent","getComponent","placeholder","LazyComponent","clientChunkGroups","resolved","Component","Wrapper","children","ref","rest","chunks","includes","CodeSplit","fallback"],"sources":["../../../../src/shared/utils/splitComponent.tsx"],"sourcesContent":["/* global document */\n\nimport {\n type ComponentType,\n type FunctionComponent,\n type ReactNode,\n type RefObject,\n Suspense,\n lazy,\n useInsertionEffect,\n} from 'react';\n\nimport { Barrier } from '@dr.pogodin/js-utils';\n\nimport { type ChunkGroupsT, getSsrContext } from './globalState';\n\nimport {\n IS_CLIENT_SIDE,\n IS_SERVER_SIDE,\n getBuildInfo,\n} from './isomorphy';\n\nfunction getClientChunkGroups(): Promise<ChunkGroupsT> | undefined {\n if (!IS_CLIENT_SIDE) return undefined;\n\n return (async () => {\n const { default: getInj } = await import(/* webpackChunkName: \"react-utils-client-side-code\" */ '../../client/getInj');\n\n const inj = await getInj();\n return inj.CHUNK_GROUPS ?? {};\n })();\n}\n\nconst refCounts: Record<string, number> = {};\n\nfunction getPublicPath() {\n return getBuildInfo().publicPath;\n}\n\n/**\n * Client-side only! Ensures the specified CSS stylesheet is loaded into\n * the document; loads if it is missing; and does simple reference counting\n * to facilitate future clean-up.\n * @param name\n * @param loadedSheets\n * @param refCount\n * @return\n */\nfunction bookStyleSheet(\n name: string,\n loadedSheets: Set<string>,\n refCount: boolean,\n): Promise<void> | undefined {\n let res: Barrier<void> | undefined;\n const path = `${getPublicPath()}/${name}`;\n const fullPath = `${document.location.origin}${path}`;\n\n if (!loadedSheets.has(fullPath)) {\n let link = document.querySelector(`link[href=\"${path}\"]`);\n\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('rel', 'stylesheet');\n link.setAttribute('href', path);\n document.head.appendChild(link);\n }\n\n res = new Barrier<void>();\n link.addEventListener('load', () => {\n if (!res) throw Error('Internal error');\n void res.resolve();\n });\n link.addEventListener('error', () => {\n if (!res) throw Error('Internal error');\n void res.resolve();\n });\n }\n\n if (refCount) {\n const current = refCounts[path] ?? 0;\n refCounts[path] = 1 + current;\n }\n\n return res;\n}\n\n/**\n * Generates the set of URLs for currently loaded, linked stylesheets.\n * @return\n */\nfunction getLoadedStyleSheets(): Set<string> {\n const res = new Set<string>();\n const { styleSheets } = document;\n for (const { href } of styleSheets) {\n if (href) res.add(href);\n }\n return res;\n}\n\nfunction assertChunkName(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n) {\n if (chunkGroups[chunkName]) return;\n throw Error(`Unknown chunk name \"${chunkName}\"`);\n}\n\n/**\n * Client-side only! Ensures all CSS stylesheets required for the specified\n * code chunk are loaded into the document; loads the missing ones; and does\n * simple reference counting to facilitate future clean-up.\n * @param chunkName Chunk name.\n * @param refCount\n * @return Resolves once all pending stylesheets, necessary for\n * the chunk, are either loaded, or failed to load.\n */\nexport async function bookStyleSheets(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n refCount: boolean,\n): Promise<void> {\n const promises = [];\n const assets = chunkGroups[chunkName];\n if (!assets) return Promise.resolve();\n\n const loadedSheets = getLoadedStyleSheets();\n\n for (const asset of assets) {\n if (asset.endsWith('.css')) {\n const promise = bookStyleSheet(asset, loadedSheets, refCount);\n if (promise) promises.push(promise);\n }\n }\n\n return promises.length\n ? Promise.allSettled(promises).then()\n : Promise.resolve();\n}\n\n/**\n * Client-side only! Frees from the document all CSS stylesheets that are\n * required by the specified chunk, and have reference counter equal to one\n * (for chunks with larger reference counter values, it just decrements\n * the reference counter).\n * @param {string} chunkName\n */\nexport function freeStyleSheets(\n chunkName: string,\n chunkGroups: ChunkGroupsT,\n): void {\n const assets = chunkGroups[chunkName];\n if (!assets) return;\n\n for (const asset of assets) {\n if (asset.endsWith('.css')) {\n const path = `${getPublicPath()}/${asset}`;\n\n const pathRefCount = refCounts[path];\n if (pathRefCount) {\n if (pathRefCount <= 1) {\n document.head.querySelector(`link[href=\"${path}\"]`)!.remove();\n delete refCounts[path];\n } else refCounts[path] = pathRefCount - 1;\n }\n }\n }\n}\n\n// Holds the set of chunk names already used for splitComponent() calls.\nconst usedChunkNames = new Set();\n\ntype ComponentOrModule<PropsT> = ComponentType<PropsT> | {\n default: ComponentType<PropsT>;\n};\n\ntype GenericComponentPropsT = {\n children?: ReactNode;\n ref?: RefObject<unknown>;\n\n // NOTE: This is necessary, as without it this type (with only optional\n // fields) will be conisdered as \"weak\" by TypeScript, and it will be\n // a error to assign to it any type that does not use \"children\", or \"ref\".\n [propName: string]: unknown;\n};\n\n/**\n * Given an async component retrieval function `getComponent()` it creates\n * a special \"code split\" component, which uses <Suspense> to asynchronously\n * load on demand the code required by `getComponent()`.\n * @param options\n * @param options.chunkName\n * @param {function} options.getComponent\n * @param {React.Element} [options.placeholder]\n * @return {React.ElementType}\n */\nexport default function splitComponent<\n ComponentPropsT extends GenericComponentPropsT,\n>({\n chunkName,\n getComponent,\n placeholder,\n}: {\n chunkName: string;\n getComponent: () => Promise<ComponentOrModule<ComponentPropsT>>;\n placeholder?: ReactNode;\n}): FunctionComponent<ComponentPropsT> {\n // The correct usage of splitComponent() assumes a single call per chunk.\n if (usedChunkNames.has(chunkName)) {\n throw Error(`Repeated splitComponent() call for the chunk \"${chunkName}\"`);\n } else usedChunkNames.add(chunkName);\n\n const LazyComponent = lazy(async () => {\n const clientChunkGroups = await getClientChunkGroups();\n\n // On the client side we can check right away if the chunk name is known.\n if (IS_CLIENT_SIDE) {\n if (!clientChunkGroups) throw Error('Internal error');\n assertChunkName(chunkName, clientChunkGroups);\n }\n\n const resolved = await getComponent();\n const Component = 'default' in resolved ? resolved.default : resolved;\n\n // This pre-loads necessary stylesheets prior to the first mount of\n // the component (the lazy load function is executed by React one at\n // the frist mount).\n if (IS_CLIENT_SIDE) {\n if (!clientChunkGroups) throw Error('Internal error');\n await bookStyleSheets(chunkName, clientChunkGroups, false);\n }\n\n const Wrapper: FunctionComponent<ComponentPropsT> = ({\n children,\n ref,\n ...rest\n }) => {\n // On the server side we'll assert the chunk name here,\n // and also push it to the SSR chunks array.\n if (IS_SERVER_SIDE) {\n const { chunkGroups, chunks } = getSsrContext()!;\n assertChunkName(chunkName, chunkGroups);\n if (!chunks.includes(chunkName)) chunks.push(chunkName);\n }\n\n // This takes care about stylesheets management every time an instance of\n // this component is mounted / unmounted.\n useInsertionEffect(() => {\n if (!clientChunkGroups) throw Error('Internal error');\n void bookStyleSheets(chunkName, clientChunkGroups, true);\n return () => {\n freeStyleSheets(chunkName, clientChunkGroups);\n };\n }, []);\n\n return (\n <Component\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...(rest as unknown as ComponentPropsT)}\n ref={ref}\n >\n {children}\n </Component>\n );\n };\n\n return { default: Wrapper };\n });\n\n const CodeSplit: React.FunctionComponent<ComponentPropsT> = ({\n children,\n ...rest\n }: ComponentPropsT) => (\n <Suspense fallback={placeholder}>\n <LazyComponent\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...rest as Parameters<typeof LazyComponent>[0]}\n >\n {children}\n </LazyComponent>\n </Suspense>\n );\n\n return CodeSplit;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,9 @@
1
- import { IS_CLIENT_SIDE } from "./isomorphy";
1
+ // eslint-disable-next-line import/enforce-node-protocol-usage
2
+ import { createRequire } from 'module';
3
+ import { IS_CLIENT_SIDE, IS_SERVER_SIDE } from "./isomorphy";
4
+ let require;
5
+ if (IS_SERVER_SIDE) require = createRequire(import.meta.url);
6
+
2
7
  /**
3
8
  * Requires the specified module without including it into the bundle during
4
9
  * Webpack build.
@@ -23,15 +28,12 @@ basePathOrOptions) {
23
28
  } = ops);
24
29
  }
25
30
 
26
- // eslint-disable-next-line no-eval
27
- const req = eval('require');
28
-
29
31
  // eslint-disable-next-line @typescript-eslint/unbound-method
30
32
  const {
31
33
  resolve
32
- } = req('path');
34
+ } = require('node:path');
33
35
  const path = basePath ? resolve(basePath, modulePath) : modulePath;
34
- const module = req(path);
36
+ const module = require(path);
35
37
  if (!('default' in module) || !module.default) return module;
36
38
  const {
37
39
  default: def,
@@ -40,7 +42,9 @@ basePathOrOptions) {
40
42
  const res = def;
41
43
  Object.entries(named).forEach(([name, value]) => {
42
44
  const assigned = res[name];
43
- if (assigned) res[name] = value;else if (assigned !== value) {
45
+ if (assigned === undefined) {
46
+ res[name] = value;
47
+ } else if (assigned !== value) {
44
48
  throw Error('Conflict between default and named exports');
45
49
  }
46
50
  });
@@ -1 +1 @@
1
- {"version":3,"file":"webpack.js","names":["IS_CLIENT_SIDE","requireWeak","modulePath","basePathOrOptions","basePath","ops","req","eval","resolve","path","module","default","def","named","res","Object","entries","forEach","name","value","assigned","Error","resolveWeak"],"sources":["../../../../src/shared/utils/webpack.ts"],"sourcesContent":["import type PathNS from 'node:path';\n\nimport { IS_CLIENT_SIDE } from './isomorphy';\n\ntype RequireWeakOptionsT = {\n basePath?: string;\n};\n\ntype RequireWeakResT<T> = T extends { default: infer D }\n ? (D extends null | undefined ? T : D & Omit<T, 'default'>)\n : T;\n\n/**\n * Requires the specified module without including it into the bundle during\n * Webpack build.\n * @param modulePath\n * @param [basePath]\n * @return Required module.\n */\nexport function requireWeak<T extends object>(\n modulePath: string,\n\n // TODO: For now `basePath` can be provided directly as a string here,\n // for backward compatibility. Deprecate it in future, if any other\n // breaking changes are done for requireWeak().\n basePathOrOptions?: string | RequireWeakOptionsT,\n): RequireWeakResT<T> | null {\n if (IS_CLIENT_SIDE) return null;\n\n let basePath: string | undefined;\n let ops: RequireWeakOptionsT;\n if (typeof basePathOrOptions === 'string') {\n basePath = basePathOrOptions;\n } else {\n ops = basePathOrOptions ?? {};\n ({ basePath } = ops);\n }\n\n // eslint-disable-next-line no-eval\n const req = eval('require') as (path: string) => unknown;\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const { resolve } = req('path') as typeof PathNS;\n\n const path = basePath ? resolve(basePath, modulePath) : modulePath;\n const module = req(path) as T;\n\n if (!('default' in module) || !module.default) return module as RequireWeakResT<T>;\n\n const { default: def, ...named } = module;\n\n const res = def as RequireWeakResT<T>;\n\n Object.entries(named).forEach(([name, value]) => {\n const assigned = res[name as keyof RequireWeakResT<T>];\n if (assigned) (res[name as keyof RequireWeakResT<T>] as unknown) = value;\n else if (assigned !== value) {\n throw Error('Conflict between default and named exports');\n }\n });\n return res;\n}\n\n/**\n * Resolves specified module path with help of Babel's module resolver.\n * Yes, the function itself just returns its argument to the caller, but Babel\n * is configured to resolve the first argument of resolveWeak(..) function, thus\n * the result will be the resolved path.\n * @param {string} modulePath\n * @return {string} Absolute or relative path to the module.\n */\nexport function resolveWeak(modulePath: string): string {\n return modulePath;\n}\n"],"mappings":"AAEA,SAASA,cAAc;AAUvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CACzBC,UAAkB;AAElB;AACA;AACA;AACAC,iBAAgD,EACrB;EAC3B,IAAIH,cAAc,EAAE,OAAO,IAAI;EAE/B,IAAII,QAA4B;EAChC,IAAIC,GAAwB;EAC5B,IAAI,OAAOF,iBAAiB,KAAK,QAAQ,EAAE;IACzCC,QAAQ,GAAGD,iBAAiB;EAC9B,CAAC,MAAM;IACLE,GAAG,GAAGF,iBAAiB,IAAI,CAAC,CAAC;IAC7B,CAAC;MAAEC;IAAS,CAAC,GAAGC,GAAG;EACrB;;EAEA;EACA,MAAMC,GAAG,GAAGC,IAAI,CAAC,SAAS,CAA8B;;EAExD;EACA,MAAM;IAAEC;EAAQ,CAAC,GAAGF,GAAG,CAAC,MAAM,CAAkB;EAEhD,MAAMG,IAAI,GAAGL,QAAQ,GAAGI,OAAO,CAACJ,QAAQ,EAAEF,UAAU,CAAC,GAAGA,UAAU;EAClE,MAAMQ,MAAM,GAAGJ,GAAG,CAACG,IAAI,CAAM;EAE7B,IAAI,EAAE,SAAS,IAAIC,MAAM,CAAC,IAAI,CAACA,MAAM,CAACC,OAAO,EAAE,OAAOD,MAAM;EAE5D,MAAM;IAAEC,OAAO,EAAEC,GAAG;IAAE,GAAGC;EAAM,CAAC,GAAGH,MAAM;EAEzC,MAAMI,GAAG,GAAGF,GAAyB;EAErCG,MAAM,CAACC,OAAO,CAACH,KAAK,CAAC,CAACI,OAAO,CAAC,CAAC,CAACC,IAAI,EAAEC,KAAK,CAAC,KAAK;IAC/C,MAAMC,QAAQ,GAAGN,GAAG,CAACI,IAAI,CAA6B;IACtD,IAAIE,QAAQ,EAAGN,GAAG,CAACI,IAAI,CAA6B,GAAeC,KAAK,CAAC,KACpE,IAAIC,QAAQ,KAAKD,KAAK,EAAE;MAC3B,MAAME,KAAK,CAAC,4CAA4C,CAAC;IAC3D;EACF,CAAC,CAAC;EACF,OAAOP,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASQ,WAAWA,CAACpB,UAAkB,EAAU;EACtD,OAAOA,UAAU;AACnB","ignoreList":[]}
1
+ {"version":3,"file":"webpack.js","names":["createRequire","IS_CLIENT_SIDE","IS_SERVER_SIDE","require","import","meta","url","requireWeak","modulePath","basePathOrOptions","basePath","ops","resolve","path","module","default","def","named","res","Object","entries","forEach","name","value","assigned","undefined","Error","resolveWeak"],"sources":["../../../../src/shared/utils/webpack.ts"],"sourcesContent":["import type PathNS from 'node:path';\n\n// eslint-disable-next-line import/enforce-node-protocol-usage\nimport { createRequire } from 'module';\n\nimport { IS_CLIENT_SIDE, IS_SERVER_SIDE } from './isomorphy';\n\ntype RequireWeakOptionsT = {\n basePath?: string;\n};\n\ntype RequireWeakResT<T> = T extends { default: infer D }\n ? (D extends null | undefined ? T : D & Omit<T, 'default'>)\n : T;\n\nlet require: ((url: string) => unknown) | undefined;\n\nif (IS_SERVER_SIDE) require = createRequire(import.meta.url);\n\n/**\n * Requires the specified module without including it into the bundle during\n * Webpack build.\n * @param modulePath\n * @param [basePath]\n * @return Required module.\n */\nexport function requireWeak<T extends object>(\n modulePath: string,\n\n // TODO: For now `basePath` can be provided directly as a string here,\n // for backward compatibility. Deprecate it in future, if any other\n // breaking changes are done for requireWeak().\n basePathOrOptions?: string | RequireWeakOptionsT,\n): RequireWeakResT<T> | null {\n if (IS_CLIENT_SIDE) return null;\n\n let basePath: string | undefined;\n let ops: RequireWeakOptionsT;\n if (typeof basePathOrOptions === 'string') {\n basePath = basePathOrOptions;\n } else {\n ops = basePathOrOptions ?? {};\n ({ basePath } = ops);\n }\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const { resolve } = require!('node:path') as typeof PathNS;\n\n const path = basePath ? resolve(basePath, modulePath) : modulePath;\n\n const module = require!(path) as T;\n\n if (!('default' in module) || !module.default) return module as RequireWeakResT<T>;\n\n const { default: def, ...named } = module;\n\n const res = def as RequireWeakResT<T>;\n\n Object.entries(named).forEach(([name, value]) => {\n const assigned = res[name as keyof RequireWeakResT<T>];\n if (assigned === undefined) {\n (res[name as keyof RequireWeakResT<T>] as unknown) = value;\n } else if (assigned !== value) {\n throw Error('Conflict between default and named exports');\n }\n });\n return res;\n}\n\n/**\n * Resolves specified module path with help of Babel's module resolver.\n * Yes, the function itself just returns its argument to the caller, but Babel\n * is configured to resolve the first argument of resolveWeak(..) function, thus\n * the result will be the resolved path.\n * @param {string} modulePath\n * @return {string} Absolute or relative path to the module.\n */\nexport function resolveWeak(modulePath: string): string {\n return modulePath;\n}\n"],"mappings":"AAEA;AACA,SAASA,aAAa,QAAQ,QAAQ;AAEtC,SAASC,cAAc,EAAEC,cAAc;AAUvC,IAAIC,OAA+C;AAEnD,IAAID,cAAc,EAAEC,OAAO,GAAGH,aAAa,CAACI,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC;;AAE5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CACzBC,UAAkB;AAElB;AACA;AACA;AACAC,iBAAgD,EACrB;EAC3B,IAAIR,cAAc,EAAE,OAAO,IAAI;EAE/B,IAAIS,QAA4B;EAChC,IAAIC,GAAwB;EAC5B,IAAI,OAAOF,iBAAiB,KAAK,QAAQ,EAAE;IACzCC,QAAQ,GAAGD,iBAAiB;EAC9B,CAAC,MAAM;IACLE,GAAG,GAAGF,iBAAiB,IAAI,CAAC,CAAC;IAC7B,CAAC;MAAEC;IAAS,CAAC,GAAGC,GAAG;EACrB;;EAEA;EACA,MAAM;IAAEC;EAAQ,CAAC,GAAGT,OAAO,CAAE,WAAW,CAAkB;EAE1D,MAAMU,IAAI,GAAGH,QAAQ,GAAGE,OAAO,CAACF,QAAQ,EAAEF,UAAU,CAAC,GAAGA,UAAU;EAElE,MAAMM,MAAM,GAAGX,OAAO,CAAEU,IAAI,CAAM;EAElC,IAAI,EAAE,SAAS,IAAIC,MAAM,CAAC,IAAI,CAACA,MAAM,CAACC,OAAO,EAAE,OAAOD,MAAM;EAE5D,MAAM;IAAEC,OAAO,EAAEC,GAAG;IAAE,GAAGC;EAAM,CAAC,GAAGH,MAAM;EAEzC,MAAMI,GAAG,GAAGF,GAAyB;EAErCG,MAAM,CAACC,OAAO,CAACH,KAAK,CAAC,CAACI,OAAO,CAAC,CAAC,CAACC,IAAI,EAAEC,KAAK,CAAC,KAAK;IAC/C,MAAMC,QAAQ,GAAGN,GAAG,CAACI,IAAI,CAA6B;IACtD,IAAIE,QAAQ,KAAKC,SAAS,EAAE;MACzBP,GAAG,CAACI,IAAI,CAA6B,GAAeC,KAAK;IAC5D,CAAC,MAAM,IAAIC,QAAQ,KAAKD,KAAK,EAAE;MAC7B,MAAMG,KAAK,CAAC,4CAA4C,CAAC;IAC3D;EACF,CAAC,CAAC;EACF,OAAOR,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASS,WAAWA,CAACnB,UAAkB,EAAU;EACtD,OAAOA,UAAU;AACnB","ignoreList":[]}
@@ -32,12 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.default = getConfig;
40
- const pull_1 = __importDefault(require("lodash/pull"));
37
+ const lodash_es_1 = require("lodash-es");
41
38
  const webpack_1 = __importStar(require("./webpack"));
42
39
  /**
43
40
  * Creates a new base config.
@@ -57,6 +54,9 @@ function newBase(babel, options = {}) {
57
54
  extensions: ['gif', 'jpeg', 'jpg', 'png'],
58
55
  name: `${baseAssetsOutputPath}/images/[md4:hash:20].[ext]`,
59
56
  }]);
57
+ if (options.modules === false) {
58
+ config.plugins.push('babel-plugin-add-import-extension');
59
+ }
60
60
  const moduleResolverPluginOps = config.plugins.find((x) => Array.isArray(x) && x[0] === 'module-resolver')[1];
61
61
  moduleResolverPluginOps.transformFunctions = [
62
62
  'requireWeak',
@@ -65,7 +65,7 @@ function newBase(babel, options = {}) {
65
65
  'webpack.resolveWeak',
66
66
  ];
67
67
  if (babel.env() === webpack_1.ENVIRONMENTS.DEV) {
68
- (0, pull_1.default)(config.plugins, 'react-refresh/babel');
68
+ (0, lodash_es_1.pull)(config.plugins, 'react-refresh/babel');
69
69
  }
70
70
  return config;
71
71
  }
@@ -8,6 +8,7 @@ const globalLibDir = path.resolve(process.execPath, '../../lib/node_modules');
8
8
  const modulesToTransform = [
9
9
  '@dr.pogodin/react-global-state',
10
10
  '@dr.pogodin/react-utils',
11
+ 'lodash-es',
11
12
  'uuid',
12
13
  ];
13
14
 
@@ -1,4 +1,6 @@
1
- /* global globalThis, require */
1
+ /* global globalThis, require, window */
2
+
3
+ import { subtle } from 'node:crypto';
2
4
 
3
5
  // eslint-disable-next-line import/no-unassigned-import
4
6
  import 'raf/polyfill';
@@ -11,3 +13,8 @@ if (!globalThis.TextEncoder || !globalThis.TextDecoder) {
11
13
  globalThis.TextEncoder = TextEncoder;
12
14
  globalThis.TextDecoder = TextDecoder;
13
15
  }
16
+
17
+ // Polyfill of crypto.subtle in JSDOM environments.
18
+ if (typeof window !== 'undefined') {
19
+ window.crypto.subtle = subtle;
20
+ }
@@ -5,16 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.default = configFactory;
8
+ const node_crypto_1 = require("node:crypto");
8
9
  const node_fs_1 = __importDefault(require("node:fs"));
9
10
  const node_path_1 = __importDefault(require("node:path"));
10
- const sitemap_1 = __importDefault(require("sitemap"));
11
- const clone_1 = __importDefault(require("lodash/clone"));
12
- const defaults_1 = __importDefault(require("lodash/defaults"));
13
- const isFunction_1 = __importDefault(require("lodash/isFunction"));
14
- const isObject_1 = __importDefault(require("lodash/isObject"));
11
+ const sitemap_1 = require("sitemap");
12
+ const clone_js_1 = __importDefault(require("lodash/clone.js"));
13
+ const defaults_js_1 = __importDefault(require("lodash/defaults.js"));
14
+ const isFunction_js_1 = __importDefault(require("lodash/isFunction.js"));
15
+ const isObject_js_1 = __importDefault(require("lodash/isObject.js"));
15
16
  const autoprefixer_1 = __importDefault(require("autoprefixer"));
16
17
  const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
17
- const node_forge_1 = __importDefault(require("node-forge"));
18
18
  const webpack_1 = require("webpack");
19
19
  const workbox_webpack_plugin_1 = __importDefault(require("workbox-webpack-plugin"));
20
20
  const utils_1 = require("@dr.pogodin/babel-plugin-react-css-modules/utils");
@@ -129,7 +129,7 @@ const utils_1 = require("@dr.pogodin/babel-plugin-react-css-modules/utils");
129
129
  */
130
130
  function configFactory(ops) {
131
131
  var _a, _b;
132
- const o = (0, defaults_1.default)((0, clone_1.default)(ops), {
132
+ const o = (0, defaults_js_1.default)((0, clone_js_1.default)(ops), {
133
133
  babelLoaderOptions: {},
134
134
  cssLocalIdent: '[hash:base64:6]',
135
135
  outputPath: 'build/web-public',
@@ -144,12 +144,12 @@ function configFactory(ops) {
144
144
  const sitemapUrl = node_path_1.default.resolve(o.context, o.sitemap);
145
145
  // eslint-disable-next-line import/no-dynamic-require, @typescript-eslint/no-require-imports
146
146
  let source = require(sitemapUrl);
147
- if ((0, isFunction_1.default)(source))
147
+ if ((0, isFunction_js_1.default)(source))
148
148
  source = source();
149
- const sm = new sitemap_1.default.SitemapStream();
149
+ const sm = new sitemap_1.SitemapStream();
150
150
  source.forEach((item) => sm.write(item));
151
151
  sm.end();
152
- void sitemap_1.default.streamToPromise(sm).then((sitemap) => {
152
+ void (0, sitemap_1.streamToPromise)(sm).then((sitemap) => {
153
153
  const outUrl = node_path_1.default.resolve(o.context, o.outputPath);
154
154
  if (!fs.existsSync(outUrl))
155
155
  fs.mkdirSync(outUrl);
@@ -179,7 +179,7 @@ function configFactory(ops) {
179
179
  // build info object in case nothing could be loaded.
180
180
  buildInfo !== null && buildInfo !== void 0 ? buildInfo : (buildInfo = Object.freeze({
181
181
  /* A random 32-bit key, that can be used for encryption. */
182
- key: node_forge_1.default.random.getBytesSync(32),
182
+ key: (0, node_crypto_1.randomBytes)(32).toString('base64'),
183
183
  /* Public path used during build. */
184
184
  publicPath: o.publicPath,
185
185
  /* `true` if client-side code should setup a service worker. */
@@ -210,7 +210,7 @@ function configFactory(ops) {
210
210
  plugins.push(new webpack_1.ProgressPlugin());
211
211
  /* Adds InjectManifest plugin from WorkBox, if opted to. */
212
212
  if (o.workbox) {
213
- if (!(0, isObject_1.default)(o.workbox))
213
+ if (!(0, isObject_js_1.default)(o.workbox))
214
214
  o.workbox = {};
215
215
  plugins.push(new workbox_webpack_plugin_1.default.InjectManifest(Object.assign(Object.assign({ swSrc: node_path_1.default.resolve(__dirname, '../workbox/default.js') }, o.workbox), { swDest: '__service-worker.js' })));
216
216
  }
@@ -323,6 +323,7 @@ function configFactory(ops) {
323
323
  '.json',
324
324
  '.scss',
325
325
  ],
326
+ fallback: { module: false },
326
327
  symlinks: false,
327
328
  },
328
329
  };
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.default = configFactory;
8
- const clone_1 = __importDefault(require("lodash/clone"));
9
- const defaults_1 = __importDefault(require("lodash/defaults"));
8
+ const clone_js_1 = __importDefault(require("lodash/clone.js"));
9
+ const defaults_js_1 = __importDefault(require("lodash/defaults.js"));
10
10
  const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
11
11
  const react_refresh_webpack_plugin_1 = __importDefault(require("@pmmmwh/react-refresh-webpack-plugin"));
12
12
  const webpack_1 = __importDefault(require("webpack"));
@@ -18,7 +18,7 @@ const app_base_1 = __importDefault(require("./app-base"));
18
18
  * @param [ops.dontUseHmr]
19
19
  */
20
20
  function configFactory(ops) {
21
- const o = (0, defaults_1.default)((0, clone_1.default)(ops), {
21
+ const o = (0, defaults_js_1.default)((0, clone_js_1.default)(ops), {
22
22
  cssLocalIdent: '[package]___[path][name]___[local]___[hash:base64:6]',
23
23
  });
24
24
  const entry = ['@dr.pogodin/react-utils/build/development/client/init'];
@@ -42,8 +42,7 @@ function configFactory(ops) {
42
42
  'axios',
43
43
  'cookie',
44
44
  'dayjs',
45
- 'lodash',
46
- /node-forge/,
45
+ 'lodash-es',
47
46
  'qs',
48
47
  'react',
49
48
  /react-dom/,
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.47.0-alpha.2",
2
+ "version": "1.47.0-alpha.4",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"
@@ -12,11 +12,11 @@
12
12
  "@dr.pogodin/babel-plugin-react-css-modules": "^6.13.8",
13
13
  "@dr.pogodin/csurf": "^1.16.6",
14
14
  "@dr.pogodin/js-utils": "^0.1.4",
15
- "@dr.pogodin/react-global-state": "^0.21.0",
15
+ "@dr.pogodin/react-global-state": "^0.21.1",
16
16
  "@dr.pogodin/react-helmet": "^3.0.4",
17
17
  "@dr.pogodin/react-themes": "^1.9.3",
18
18
  "@jest/environment": "^30.2.0",
19
- "axios": "^1.13.1",
19
+ "axios": "^1.13.2",
20
20
  "commander": "^14.0.2",
21
21
  "compression": "^1.8.1",
22
22
  "config": "^4.1.1",
@@ -27,9 +27,8 @@
27
27
  "express": "^5.1.0",
28
28
  "helmet": "^8.1.0",
29
29
  "http-status-codes": "^2.3.0",
30
- "lodash": "^4.17.21",
30
+ "lodash-es": "^4.17.21",
31
31
  "morgan": "^1.10.1",
32
- "node-forge": "^1.3.1",
33
32
  "qs": "^6.14.0",
34
33
  "raf": "^3.4.1",
35
34
  "react": "^19.2.0",
@@ -69,8 +68,8 @@
69
68
  "@types/express": "^5.0.5",
70
69
  "@types/jest": "^30.0.0",
71
70
  "@types/lodash": "^4.17.20",
71
+ "@types/lodash-es": "^4.17.12",
72
72
  "@types/morgan": "^1.9.10",
73
- "@types/node-forge": "^1.3.14",
74
73
  "@types/pretty": "^2.0.3",
75
74
  "@types/react": "^19.2.2",
76
75
  "@types/react-dom": "^19.2.2",
@@ -83,6 +82,7 @@
83
82
  "autoprefixer": "^10.4.21",
84
83
  "babel-jest": "^30.2.0",
85
84
  "babel-loader": "^10.0.0",
85
+ "babel-plugin-add-import-extension": "^1.6.0",
86
86
  "babel-plugin-module-resolver": "^5.0.2",
87
87
  "babel-plugin-transform-import-meta": "^2.3.3",
88
88
  "core-js": "^3.46.0",
@@ -104,7 +104,7 @@
104
104
  "resolve-url-loader": "^5.0.0",
105
105
  "sass": "^1.93.3",
106
106
  "sass-loader": "^16.0.6",
107
- "sitemap": "^8.0.2",
107
+ "sitemap": "^9.0.0",
108
108
  "source-map-loader": "^5.0.0",
109
109
  "stylelint": "^16.25.0",
110
110
  "stylelint-config-standard-scss": "^16.0.0",
@@ -177,8 +177,8 @@
177
177
  "scripts": {
178
178
  "build": "rimraf build && npm run build:configs && npm run build:types-scss && npm run build:types-code && npm run build:web && npm run build:dev && npm run build:prod",
179
179
  "build:configs": "tsc --project tsconfig.configs.json",
180
- "build:dev": "node bin/build -i build/web -t development --lib --webpack-config webpack.config.ts --no-webpack",
181
- "build:prod": "node bin/build -i build/web -t production --lib --webpack-config webpack.config.ts --no-webpack",
180
+ "build:dev": "node bin/build -i build/web -t development --lib --babel-config babel.module.config.js --webpack-config webpack.config.ts --no-webpack",
181
+ "build:prod": "node bin/build -i build/web -t production --lib --babel-config babel.module.config.js --webpack-config webpack.config.ts --no-webpack",
182
182
  "build:types-code": "rimraf build/types-code && tsc --project tsconfig.types.json && tsc-alias -p tsconfig.types.json",
183
183
  "build:types-scss": "rimraf build/types-scss && typed-scss-modules .",
184
184
  "build:web": "rimraf build/web && babel ./src --config-file ./babel.libweb.config.js --out-dir build/web -x .js,.jsx,.ts,.tsx --source-maps --copy-files",
@@ -2,50 +2,70 @@
2
2
 
3
3
  /* global document */
4
4
 
5
- // Note: this way, only required part of "node-forge": AES, and some utils,
6
- // is bundled into client-side code.
7
- import forge from 'node-forge/lib/forge';
8
-
9
- // eslint-disable-next-line import/no-unassigned-import
10
- import 'node-forge/lib/aes';
11
-
12
5
  import type { InjT } from 'utils/globalState';
13
6
 
14
7
  import { getBuildInfo } from 'utils/isomorphy/buildInfo';
15
8
 
16
- // Safeguard is needed here, because the server-side version of Docusaurus docs
17
- // is compiled (at least now) with settings suggesting it is a client-side
18
- // environment, but there is no document.
19
- let inj: InjT = {};
20
-
21
- const metaElement: HTMLMetaElement | null = typeof document === 'undefined'
22
- ? null : document.querySelector('meta[itemprop="drpruinj"]');
23
-
24
- if (metaElement) {
25
- metaElement.remove();
26
- let data = forge.util.decode64(metaElement.content);
27
-
28
- const { key } = getBuildInfo();
29
- const d = forge.cipher.createDecipher('AES-CBC', key);
30
- d.start({ iv: data.slice(0, key.length) });
31
- d.update(forge.util.createBuffer(data.slice(key.length)));
32
- d.finish();
33
-
34
- data = forge.util.decodeUtf8(d.output.data);
35
-
36
- // TODO: Double-check, if there is a safer alternative to parse it?
37
- // eslint-disable-next-line no-eval
38
- inj = eval(`(${data})`) as InjT;
39
- } else if (typeof window !== 'undefined' && window.REACT_UTILS_INJECTION) {
40
- inj = window.REACT_UTILS_INJECTION;
41
- delete window.REACT_UTILS_INJECTION;
42
- } else {
43
- // Otherwise, a bunch of dependent stuff will easily fail in non-standard
44
- // environments, where no client-side initialization is performed. Like tests,
45
- // Docusaurus examples, etc.
46
- inj = {};
47
- }
9
+ let inj: InjT | Promise<InjT> | undefined;
10
+
11
+ export default function getInj(): InjT | Promise<InjT> {
12
+ inj ??= (async () => {
13
+ const metaElement: HTMLMetaElement | null = typeof document === 'undefined'
14
+ ? null : document.querySelector('meta[itemprop="drpruinj"]');
15
+
16
+ if (metaElement) {
17
+ metaElement.remove();
18
+
19
+ // NOTE: Since 2025 there is Uint8Array.fromBase64(), which should be
20
+ // preferred, but it is not supported by older environments yet.
21
+ const data = atob(metaElement.content);
22
+
23
+ // TODO: Our current handling of this encryption / decryption follows
24
+ // a legacy approach, and can be enhanced by using Crypto features.
25
+ // Though, this is not strictly intended to be secure (it is more
26
+ // to obfurscate injected data, rather than really keeping them
27
+ // secure), thus it is fine like this for now.
28
+ const { key } = getBuildInfo();
29
+
30
+ const code = (x: string) => x.charCodeAt(0);
31
+ const dataBuffer = Uint8Array.from(data.slice(16), code);
32
+ const ivBuffer = Uint8Array.from(data.slice(0, 16), code);
33
+ const keyBuffer = Uint8Array.from(atob(key), code);
34
+
35
+ const cKey = await window.crypto.subtle.importKey(
36
+ 'raw',
37
+ keyBuffer,
38
+ { name: 'AES-CBC' },
39
+ false,
40
+ ['decrypt'],
41
+ );
42
+
43
+ const buffer = await window.crypto.subtle.decrypt({
44
+ iv: ivBuffer,
45
+ name: 'AES-CBC',
46
+ }, cKey, dataBuffer);
47
+
48
+ const decoder = new TextDecoder();
49
+
50
+ // eslint-disable-next-line no-eval
51
+ const res = eval(`(${decoder.decode(buffer)})`) as InjT;
52
+
53
+ // NOTE: This is important, to be able to return the injection
54
+ // synchronously once it is initialized.
55
+ inj = res;
56
+
57
+ return res;
58
+ } else if (typeof window !== 'undefined' && window.REACT_UTILS_INJECTION) {
59
+ const res = window.REACT_UTILS_INJECTION;
60
+ delete window.REACT_UTILS_INJECTION;
61
+ return res;
62
+ }
63
+
64
+ // Otherwise, a bunch of dependent stuff will easily fail in non-standard
65
+ // environments, where no client-side initialization is performed. Like tests,
66
+ // Docusaurus examples, etc.
67
+ return {};
68
+ })();
48
69
 
49
- export default function getInj(): InjT {
50
70
  return inj;
51
71
  }
@@ -20,14 +20,16 @@ type OptionsT = {
20
20
  * @param Application Root application component
21
21
  * @param [options={}] Optional. Additional settings.
22
22
  */
23
- export default function Launch(
23
+ export default async function Launch(
24
24
  Application: ComponentType,
25
25
  options: OptionsT = {},
26
- ): void {
26
+ ): Promise<void> {
27
+ const inj = await getInj();
28
+
27
29
  const container = document.getElementById('react-view');
28
30
  if (!container) throw Error('Failed to find container for React app');
29
31
  const scene = (
30
- <GlobalStateProvider initialState={getInj().ISTATE ?? options.initialState}>
32
+ <GlobalStateProvider initialState={inj.ISTATE ?? options.initialState}>
31
33
  <BrowserRouter>
32
34
  <HelmetProvider>
33
35
  <Application />
package/src/index.ts CHANGED
@@ -16,8 +16,8 @@ if (global.REACT_UTILS_LIBRARY_LOADED) {
16
16
  // TODO: This is a rapid workaround to get rid of __dirname. I guess, later
17
17
  // we'll re-implement requireWeak() to accept import.meta.url directly, and
18
18
  // this workaround won't be needed.
19
- let dirname = import.meta.url;
20
- dirname = dirname.slice(5, dirname.lastIndexOf('/'));
19
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
20
+ const dirname = import.meta.dirname;
21
21
 
22
22
  const server = webpack.requireWeak<typeof ServerFactoryM>('./server', dirname);
23
23
 
@@ -54,10 +54,10 @@ export {
54
54
 
55
55
  export {
56
56
  assertEmptyObject,
57
- config,
58
57
  Barrier,
59
58
  Cached,
60
59
  Emitter,
60
+ getConfig,
61
61
  isomorphy,
62
62
  getSsrContext,
63
63
  type Listener,
@@ -1,20 +1,15 @@
1
1
  // eslint-disable-next-line import/no-unassigned-import
2
- import 'source-map-support/register';
2
+ import 'source-map-support/register.js';
3
3
 
4
4
  import http from 'node:http';
5
5
  import https from 'node:https';
6
6
 
7
- import cloneDeep from 'lodash/cloneDeep';
8
- import defaults from 'lodash/defaults';
9
- import isFinite from 'lodash/isFinite';
10
- import isNumber from 'lodash/isNumber';
11
- import isString from 'lodash/isString';
12
- import toNumber from 'lodash/toNumber';
7
+ import { cloneDeep, defaults } from 'lodash-es';
13
8
 
14
9
  // Polyfill required by ReactJS.
15
10
  // TODO: Double-check, if it is still required by React v19?
16
11
  // eslint-disable-next-line import/no-unassigned-import
17
- import 'raf/polyfill';
12
+ import 'raf/polyfill.js';
18
13
 
19
14
  import type { Configuration } from 'webpack';
20
15
 
@@ -41,13 +36,12 @@ export { errors, getDefaultCspSettings, type ServerT };
41
36
  * Normalizes a port into a number, string, or false.
42
37
  * TODO: Drop this function?
43
38
  * @param value Port name or number.
44
- * @return Port number (Number), name (String), or false.
39
+ * @return Port number (Number), name (String).
45
40
  */
46
41
  function normalizePort(value: number | string) {
47
- const port = toNumber(value);
48
- if (isFinite(port)) return port; /* port number */
49
- if (!isNumber(port)) return value; /* named pipe */
50
- return false;
42
+ const port = typeof value === 'string' ? parseInt(value) : value;
43
+ if (Number.isFinite(port)) return port; /* port number */
44
+ return value; /* named pipe */
51
45
  }
52
46
 
53
47
  type OptionsT = ServerOptionsT & {
@@ -212,7 +206,7 @@ export default async function launchServer(
212
206
  /* Sets error handler for HTTP(S) server. */
213
207
  httpServer.on('error', (error: Error) => {
214
208
  if ((error as { syscall?: string }).syscall !== 'listen') throw error;
215
- const bind = isString(ops.port) ? `Pipe ${ops.port}` : `Port ${ops.port}`;
209
+ const bind = typeof ops.port === 'string' ? `Pipe ${ops.port}` : `Port ${ops.port}`;
216
210
 
217
211
  /* Human-readable message for some specific listen errors. */
218
212
  switch ((error as { code?: string }).code) {
@@ -231,7 +225,7 @@ export default async function launchServer(
231
225
  /* Listening event handler for HTTP(S) server. */
232
226
  httpServer.on('listening', () => {
233
227
  const addr = httpServer.address()!;
234
- const bind = isString(addr) ? `pipe ${addr}` : `port ${addr.port}`;
228
+ const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`;
235
229
  ops.logger!.info(`Server listening on ${bind} in ${
236
230
  process.env.NODE_ENV} mode`);
237
231
  });