@dr.pogodin/react-utils 1.47.0-alpha.1 → 1.47.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) 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 +9 -18
  6. package/build/development/client/getInj.js.map +1 -1
  7. package/build/development/client/index.js +14 -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 +9 -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 +56 -67
  18. package/build/development/server/renderer.js.map +1 -1
  19. package/build/development/server/server.js +52 -62
  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 +8 -17
  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 +35 -46
  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 +5 -5
  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 +2 -3
  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 +21 -19
  102. package/build/production/server/renderer.js.map +1 -1
  103. package/build/production/server/server.js +9 -11
  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 +3 -5
  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 -22
  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 -1
  174. package/build/types-code/index.d.ts +2 -2
  175. package/build/types-code/server/index.d.ts +2 -2
  176. package/build/web/client/getInj.js +9 -16
  177. package/build/web/client/getInj.js.map +1 -1
  178. package/build/web/client/index.js +14 -21
  179. package/build/web/client/index.js.map +1 -1
  180. package/build/web/client/init.js +2 -4
  181. package/build/web/client/init.js.map +1 -1
  182. package/build/web/index.js +2 -4
  183. package/build/web/index.js.map +1 -1
  184. package/build/web/server/index.js +9 -15
  185. package/build/web/server/index.js.map +1 -1
  186. package/build/web/server/renderer.js +12 -10
  187. package/build/web/server/renderer.js.map +1 -1
  188. package/build/web/server/server.js +11 -11
  189. package/build/web/server/server.js.map +1 -1
  190. package/build/web/shared/utils/config.js +4 -6
  191. package/build/web/shared/utils/config.js.map +1 -1
  192. package/build/web/shared/utils/jest/E2eSsrEnv.js +1 -2
  193. package/build/web/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  194. package/build/web/shared/utils/splitComponent.js +17 -20
  195. package/build/web/shared/utils/splitComponent.js.map +1 -1
  196. package/build/web/shared/utils/webpack.js +11 -7
  197. package/build/web/shared/utils/webpack.js.map +1 -1
  198. package/config/babel/node-ssr.js +5 -5
  199. package/config/jest/default.js +8 -2
  200. package/config/webpack/app-base.js +11 -10
  201. package/config/webpack/app-development.js +3 -3
  202. package/config/webpack/lib-base.js +1 -1
  203. package/package.json +15 -12
  204. package/src/client/getInj.ts +2 -2
  205. package/src/index.ts +3 -7
  206. package/src/server/index.ts +9 -15
  207. package/src/server/renderer.tsx +11 -10
  208. package/src/server/server.ts +11 -13
  209. package/src/shared/utils/config.ts +5 -10
  210. package/src/shared/utils/jest/E2eSsrEnv.ts +1 -2
  211. package/src/shared/utils/splitComponent.tsx +17 -20
  212. package/src/shared/utils/webpack.ts +14 -8
  213. package/types.d.ts +1 -1
  214. package/node-entry.js +0 -15
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.47.0-alpha.1",
2
+ "version": "1.47.0-alpha.3",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"
@@ -12,7 +12,7 @@
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.20.1",
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",
@@ -23,11 +23,11 @@
23
23
  "cookie": "^1.0.2",
24
24
  "cookie-parser": "^1.4.7",
25
25
  "cross-env": "^10.1.0",
26
- "dayjs": "^1.11.18",
26
+ "dayjs": "^1.11.19",
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
32
  "node-forge": "^1.3.1",
33
33
  "qs": "^6.14.0",
@@ -36,7 +36,7 @@
36
36
  "react-dom": "^19.2.0",
37
37
  "react-router": "^7.9.5",
38
38
  "request-ip": "^3.3.0",
39
- "rimraf": "^6.0.0",
39
+ "rimraf": "^6.1.0",
40
40
  "serialize-javascript": "^7.0.0",
41
41
  "serve-favicon": "^2.5.1",
42
42
  "source-map-support": "^0.5.21",
@@ -69,6 +69,7 @@
69
69
  "@types/express": "^5.0.5",
70
70
  "@types/jest": "^30.0.0",
71
71
  "@types/lodash": "^4.17.20",
72
+ "@types/lodash-es": "^4.17.12",
72
73
  "@types/morgan": "^1.9.10",
73
74
  "@types/node-forge": "^1.3.14",
74
75
  "@types/pretty": "^2.0.3",
@@ -83,6 +84,7 @@
83
84
  "autoprefixer": "^10.4.21",
84
85
  "babel-jest": "^30.2.0",
85
86
  "babel-loader": "^10.0.0",
87
+ "babel-plugin-add-import-extension": "^1.6.0",
86
88
  "babel-plugin-module-resolver": "^5.0.2",
87
89
  "babel-plugin-transform-import-meta": "^2.3.3",
88
90
  "core-js": "^3.46.0",
@@ -102,9 +104,9 @@
102
104
  "react-refresh": "^0.18.0",
103
105
  "regenerator-runtime": "^0.14.1",
104
106
  "resolve-url-loader": "^5.0.0",
105
- "sass": "^1.93.2",
107
+ "sass": "^1.93.3",
106
108
  "sass-loader": "^16.0.6",
107
- "sitemap": "^8.0.2",
109
+ "sitemap": "^9.0.0",
108
110
  "source-map-loader": "^5.0.0",
109
111
  "stylelint": "^16.25.0",
110
112
  "stylelint-config-standard-scss": "^16.0.0",
@@ -125,7 +127,7 @@
125
127
  "node": ">=20",
126
128
  "npm": ">=10"
127
129
  },
128
- "main": "./node-entry.js",
130
+ "main": "./build/production/index.js",
129
131
  "source": "./src/index.ts",
130
132
  "types": "./build/types-code/index.d.ts",
131
133
  "exports": {
@@ -133,10 +135,11 @@
133
135
  "browser": "./build/web/index.js",
134
136
  "node": {
135
137
  "webpack": "./build/web/index.js",
136
- "default": "./node-entry.js"
138
+ "development": "./build/development/index.js",
139
+ "default": "./build/production/index.js"
137
140
  },
138
141
  "react-native": {
139
- "default": "./node-entry.js",
142
+ "default": "./build/production/index.js",
140
143
  "types": "./build/types-code/index.d.ts"
141
144
  }
142
145
  },
@@ -176,8 +179,8 @@
176
179
  "scripts": {
177
180
  "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",
178
181
  "build:configs": "tsc --project tsconfig.configs.json",
179
- "build:dev": "node bin/build -i build/web -t development --lib --webpack-config webpack.config.ts --no-webpack",
180
- "build:prod": "node bin/build -i build/web -t production --lib --webpack-config webpack.config.ts --no-webpack",
182
+ "build:dev": "node bin/build -i build/web -t development --lib --babel-config babel.module.config.js --webpack-config webpack.config.ts --no-webpack",
183
+ "build:prod": "node bin/build -i build/web -t production --lib --babel-config babel.module.config.js --webpack-config webpack.config.ts --no-webpack",
181
184
  "build:types-code": "rimraf build/types-code && tsc --project tsconfig.types.json && tsc-alias -p tsconfig.types.json",
182
185
  "build:types-scss": "rimraf build/types-scss && typed-scss-modules .",
183
186
  "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",
@@ -4,10 +4,10 @@
4
4
 
5
5
  // Note: this way, only required part of "node-forge": AES, and some utils,
6
6
  // is bundled into client-side code.
7
- import forge from 'node-forge/lib/forge';
7
+ import forge from 'node-forge/lib/forge.js';
8
8
 
9
9
  // eslint-disable-next-line import/no-unassigned-import
10
- import 'node-forge/lib/aes';
10
+ import 'node-forge/lib/aes.js';
11
11
 
12
12
  import type { InjT } from 'utils/globalState';
13
13
 
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import 'styles/global.scss';
2
2
 
3
- import { webpack } from 'utils';
3
+ import clientModule from './client';
4
+ import { webpack } from './shared/utils';
4
5
 
5
- import type * as ClientM from './client';
6
6
  import type * as ServerFactoryM from './server';
7
7
 
8
8
  // It is a safeguard against multiple instances / versions of the library
@@ -21,11 +21,7 @@ dirname = dirname.slice(5, dirname.lastIndexOf('/'));
21
21
 
22
22
  const server = webpack.requireWeak<typeof ServerFactoryM>('./server', dirname);
23
23
 
24
- const client = server
25
- ? undefined
26
-
27
- // eslint-disable-next-line @typescript-eslint/no-require-imports
28
- : (require('./client') as typeof ClientM).default;
24
+ const client = server ? undefined : clientModule;
29
25
 
30
26
  export {
31
27
  type AsyncCollectionT,
@@ -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
  });
@@ -15,13 +15,12 @@ import winston from 'winston';
15
15
  import { GlobalStateProvider, SsrContext } from '@dr.pogodin/react-global-state';
16
16
  import { timer } from '@dr.pogodin/js-utils';
17
17
 
18
- import clone from 'lodash/clone';
19
- import cloneDeep from 'lodash/cloneDeep';
20
- import defaults from 'lodash/defaults';
21
- import get from 'lodash/get';
22
- import isString from 'lodash/isString';
23
- import mapValues from 'lodash/mapValues';
24
- import omit from 'lodash/omit';
18
+ import {
19
+ cloneDeep,
20
+ defaults,
21
+ get,
22
+ mapValues,
23
+ } from 'lodash-es';
25
24
 
26
25
  import config from 'config';
27
26
  import forge from 'node-forge';
@@ -36,7 +35,9 @@ import type { ChunkGroupsT, SsrContextT } from 'utils/globalState';
36
35
 
37
36
  import Cache from './Cache';
38
37
 
39
- const sanitizedConfig = omit(config, 'SECRET');
38
+ // @ts-expect-error "Property 'SECRET' does not exist on type 'IConfig'."
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ const { SECRET, ...sanitizedConfig } = config;
40
41
 
41
42
  // Note: These type definitions for logger are copied from Winston logger,
42
43
  // then simplified to make it easier to fit an alternative logger into this
@@ -196,7 +197,7 @@ function groupExtraScripts(scripts: Array<string | ScriptT> = []) {
196
197
  [SCRIPT_LOCATIONS.HEAD_OPEN]: '',
197
198
  };
198
199
  for (const script of scripts) {
199
- if (isString(script)) {
200
+ if (typeof script === 'string') {
200
201
  if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;
201
202
  } else if (script.code) {
202
203
  if (script.location in res) res[script.location] += script.code;
@@ -312,7 +313,7 @@ export default function factory(
312
313
  webpackConfig: Configuration,
313
314
  options: OptionsT,
314
315
  ): RequestHandler {
315
- const ops: OptionsT = defaults(clone(options), {
316
+ const ops: OptionsT = defaults({ ...options }, {
316
317
  beforeRender: async () => Promise.resolve({}),
317
318
  maxSsrRounds: 10,
318
319
  ssrTimeout: 1000,
@@ -5,9 +5,7 @@
5
5
  import { sep } from 'node:path';
6
6
  import { pathToFileURL } from 'node:url';
7
7
 
8
- import cloneDeep from 'lodash/cloneDeep';
9
- import mapValues from 'lodash/mapValues';
10
- import pick from 'lodash/pick';
8
+ import { cloneDeep, mapValues, pick } from 'lodash-es';
11
9
 
12
10
  import compression from 'compression';
13
11
  import cookieParser from 'cookie-parser';
@@ -16,7 +14,6 @@ import csrf from '@dr.pogodin/csurf';
16
14
  import express, {
17
15
  type Express,
18
16
  type NextFunction,
19
- type RequestHandler,
20
17
  type Request,
21
18
  type Response,
22
19
  } from 'express';
@@ -27,7 +24,7 @@ import loggerMiddleware from 'morgan';
27
24
  import requestIp from 'request-ip';
28
25
  import { v4 as uuid } from 'uuid';
29
26
 
30
- import type { Compiler, Configuration } from 'webpack';
27
+ import type { Configuration } from 'webpack';
31
28
 
32
29
  import rendererFactory, {
33
30
  type LoggerI,
@@ -251,18 +248,19 @@ export default async function factory(
251
248
  } as Location;
252
249
  }
253
250
 
254
- /* eslint-disable @typescript-eslint/no-require-imports */
255
- const webpack = require('webpack') as (ops: Configuration) => Compiler;
251
+ const { default: webpack } = await import(/* webpackChunkName: "server-side-code" */ 'webpack');
256
252
 
257
- // TODO: Figure out the exact type for options, don't wanna waste time on it
258
- // right now.
259
- const webpackDevMiddleware = require('webpack-dev-middleware') as
260
- (c: Compiler, ops: unknown) => RequestHandler;
253
+ const { default: webpackDevMiddleware } = await import(
254
+ /* webpackChunkName: "server-side-code" */ 'webpack-dev-middleware'
255
+ );
261
256
 
262
- const webpackHotMiddleware = require('webpack-hot-middleware') as
263
- (c: Compiler) => RequestHandler;
257
+ const { default: webpackHotMiddleware } = await import(
258
+ /* webpackChunkName: "server-side-code" */ 'webpack-hot-middleware'
259
+ );
264
260
 
265
261
  const compiler = webpack(webpackConfig);
262
+ if (!compiler) throw Error('Internal error');
263
+
266
264
  server.use(webpackDevMiddleware(compiler, {
267
265
  publicPath,
268
266
  serverSideRender: true,
@@ -1,6 +1,8 @@
1
1
  /* global document */
2
2
 
3
- import type CookieM from 'cookie';
3
+ import { parse } from 'cookie';
4
+
5
+ import clientGetInj from '../../client/getInj';
4
6
 
5
7
  import { IS_CLIENT_SIDE } from './isomorphy/environment-check';
6
8
  import { requireWeak } from './webpack';
@@ -8,21 +10,14 @@ import { requireWeak } from './webpack';
8
10
  // TODO: The internal type casting is somewhat messed up here,
9
11
  // to be corrected later.
10
12
  const config: Record<string, unknown> = (
11
- IS_CLIENT_SIDE
12
- // eslint-disable-next-line @typescript-eslint/no-require-imports
13
- ? (require('client/getInj') as {
14
- default: () => Record<string, unknown>;
15
- }).default().CONFIG
16
- : requireWeak('config')
13
+ IS_CLIENT_SIDE ? clientGetInj().CONFIG : requireWeak('config')
17
14
  ) as (Record<string, unknown> | undefined) ?? ({} as Record<string, unknown>);
18
15
 
19
16
  // The safeguard for "document" is necessary because in non-Node environments,
20
17
  // like React Native, IS_CLIENT_SIDE is "true", however "document" and a bunch
21
18
  // of other browser-world features are not available.
22
19
  if (IS_CLIENT_SIDE && typeof document !== 'undefined') {
23
- // eslint-disable-next-line @typescript-eslint/no-require-imports
24
- const cookie = require('cookie') as typeof CookieM;
25
- config.CSRF = cookie.parse(document.cookie).csrfToken;
20
+ config.CSRF = parse(document.cookie).csrfToken;
26
21
  }
27
22
 
28
23
  export default config;
@@ -20,8 +20,7 @@ import path from 'node:path';
20
20
 
21
21
  import type { Request, Response } from 'express';
22
22
 
23
- import defaults from 'lodash/defaults';
24
- import set from 'lodash/set';
23
+ import { defaults, set } from 'lodash-es';
25
24
 
26
25
  import type { ReactNode } from 'react';
27
26
 
@@ -20,23 +20,13 @@ import {
20
20
  getBuildInfo,
21
21
  } from './isomorphy';
22
22
 
23
- // Note: At the client side we can get chunk groups immediately when loading
24
- // the module; at the server-side we only can get them within React render flow.
25
- // Thus, we set and use the following variable at the client-side, and then when
26
- // needed on the server side, we'll fetch it differently.
27
- let clientChunkGroups: ChunkGroupsT;
28
-
29
- if (IS_CLIENT_SIDE) {
30
- // TODO: Rewrite to avoid these overrides of ESLint rules.
31
- /* eslint-disable @typescript-eslint/no-unsafe-assignment,
32
- @typescript-eslint/no-require-imports,
33
- @typescript-eslint/no-unsafe-call,
34
- @typescript-eslint/no-unsafe-member-access */
35
- clientChunkGroups = require('client/getInj').default().CHUNK_GROUPS ?? {};
36
- /* eslint-enable @typescript-eslint/no-unsafe-assignment,
37
- @typescript-eslint/no-require-imports,
38
- @typescript-eslint/no-unsafe-call,
39
- @typescript-eslint/no-unsafe-member-access */
23
+ function getClientChunkGroups(): Promise<ChunkGroupsT> | undefined {
24
+ if (!IS_CLIENT_SIDE) return undefined;
25
+
26
+ return (async () => {
27
+ const { default: getInj } = await import(/* webpackChunkName: "react-utils-client-side-code" */ '../../client/getInj');
28
+ return getInj().CHUNK_GROUPS ?? {};
29
+ })();
40
30
  }
41
31
 
42
32
  const refCounts: Record<string, number> = {};
@@ -202,15 +192,20 @@ export default function splitComponent<
202
192
  getComponent: () => Promise<ComponentOrModule<ComponentPropsT>>;
203
193
  placeholder?: ReactNode;
204
194
  }): FunctionComponent<ComponentPropsT> {
205
- // On the client side we can check right away if the chunk name is known.
206
- if (IS_CLIENT_SIDE) assertChunkName(chunkName, clientChunkGroups);
207
-
208
195
  // The correct usage of splitComponent() assumes a single call per chunk.
209
196
  if (usedChunkNames.has(chunkName)) {
210
197
  throw Error(`Repeated splitComponent() call for the chunk "${chunkName}"`);
211
198
  } else usedChunkNames.add(chunkName);
212
199
 
213
200
  const LazyComponent = lazy(async () => {
201
+ const clientChunkGroups = await getClientChunkGroups();
202
+
203
+ // On the client side we can check right away if the chunk name is known.
204
+ if (IS_CLIENT_SIDE) {
205
+ if (!clientChunkGroups) throw Error('Internal error');
206
+ assertChunkName(chunkName, clientChunkGroups);
207
+ }
208
+
214
209
  const resolved = await getComponent();
215
210
  const Component = 'default' in resolved ? resolved.default : resolved;
216
211
 
@@ -218,6 +213,7 @@ export default function splitComponent<
218
213
  // the component (the lazy load function is executed by React one at
219
214
  // the frist mount).
220
215
  if (IS_CLIENT_SIDE) {
216
+ if (!clientChunkGroups) throw Error('Internal error');
221
217
  await bookStyleSheets(chunkName, clientChunkGroups, false);
222
218
  }
223
219
 
@@ -237,6 +233,7 @@ export default function splitComponent<
237
233
  // This takes care about stylesheets management every time an instance of
238
234
  // this component is mounted / unmounted.
239
235
  useInsertionEffect(() => {
236
+ if (!clientChunkGroups) throw Error('Internal error');
240
237
  void bookStyleSheets(chunkName, clientChunkGroups, true);
241
238
  return () => {
242
239
  freeStyleSheets(chunkName, clientChunkGroups);
@@ -1,6 +1,9 @@
1
1
  import type PathNS from 'node:path';
2
2
 
3
- import { IS_CLIENT_SIDE } from './isomorphy';
3
+ // eslint-disable-next-line import/enforce-node-protocol-usage
4
+ import { createRequire } from 'module';
5
+
6
+ import { IS_CLIENT_SIDE, IS_SERVER_SIDE } from './isomorphy';
4
7
 
5
8
  type RequireWeakOptionsT = {
6
9
  basePath?: string;
@@ -10,6 +13,10 @@ type RequireWeakResT<T> = T extends { default: infer D }
10
13
  ? (D extends null | undefined ? T : D & Omit<T, 'default'>)
11
14
  : T;
12
15
 
16
+ let require: ((url: string) => unknown) | undefined;
17
+
18
+ if (IS_SERVER_SIDE) require = createRequire(import.meta.url);
19
+
13
20
  /**
14
21
  * Requires the specified module without including it into the bundle during
15
22
  * Webpack build.
@@ -36,14 +43,12 @@ export function requireWeak<T extends object>(
36
43
  ({ basePath } = ops);
37
44
  }
38
45
 
39
- // eslint-disable-next-line no-eval
40
- const req = eval('require') as (path: string) => unknown;
41
-
42
46
  // eslint-disable-next-line @typescript-eslint/unbound-method
43
- const { resolve } = req('path') as typeof PathNS;
47
+ const { resolve } = require!('node:path') as typeof PathNS;
44
48
 
45
49
  const path = basePath ? resolve(basePath, modulePath) : modulePath;
46
- const module = req(path) as T;
50
+
51
+ const module = require!(path) as T;
47
52
 
48
53
  if (!('default' in module) || !module.default) return module as RequireWeakResT<T>;
49
54
 
@@ -53,8 +58,9 @@ export function requireWeak<T extends object>(
53
58
 
54
59
  Object.entries(named).forEach(([name, value]) => {
55
60
  const assigned = res[name as keyof RequireWeakResT<T>];
56
- if (assigned) (res[name as keyof RequireWeakResT<T>] as unknown) = value;
57
- else if (assigned !== value) {
61
+ if (assigned === undefined) {
62
+ (res[name as keyof RequireWeakResT<T>] as unknown) = value;
63
+ } else if (assigned !== value) {
58
64
  throw Error('Conflict between default and named exports');
59
65
  }
60
66
  });
package/types.d.ts CHANGED
@@ -19,7 +19,7 @@ declare module '@babel/register/experimental-worker' {
19
19
  export default register;
20
20
  }
21
21
 
22
- declare module 'node-forge/lib/forge' {
22
+ declare module 'node-forge/lib/forge.js' {
23
23
  import F from 'node-forge';
24
24
 
25
25
  export default F;
package/node-entry.js DELETED
@@ -1,15 +0,0 @@
1
- // TODO: We should re-visit, if this can be simplified / optimized?
2
- /* global global, module, process, require */
3
-
4
- // This permits to load the library in react-native, or other environment that
5
- // does not have __dirname global. It probably breaks a few node-specific lib
6
- // pieces, but that does not seem to prevent more relevant parts from working.
7
- if (typeof __dirname === 'undefined') {
8
- global.__dirname = ''; // eslint-disable-line no-underscore-dangle
9
- }
10
-
11
- // Again, for react-native, and maybe some other environments, we need
12
- // to have no dynamic requires below (i.e. can't do require(`./build/${env}`)).
13
- // eslint-disable-next-line import/no-commonjs
14
- module.exports = process.env.NODE_ENV === 'production'
15
- ? require('./build/production') : require('./build/development');