@servicetitan/startup 37.0.2 → 38.1.0

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 (433) hide show
  1. package/bin/js-yaml.js +2 -2
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/build.js +22 -9
  4. package/dist/cli/commands/build.js.map +1 -1
  5. package/dist/cli/commands/bundle-package.d.ts +6 -0
  6. package/dist/cli/commands/bundle-package.d.ts.map +1 -0
  7. package/dist/cli/commands/bundle-package.js +59 -0
  8. package/dist/cli/commands/bundle-package.js.map +1 -0
  9. package/dist/cli/commands/bundle-vite.js +13 -4
  10. package/dist/cli/commands/bundle-vite.js.map +1 -1
  11. package/dist/cli/commands/bundle-webpack.js +13 -4
  12. package/dist/cli/commands/bundle-webpack.js.map +1 -1
  13. package/dist/cli/commands/clean.js +13 -4
  14. package/dist/cli/commands/clean.js.map +1 -1
  15. package/dist/cli/commands/command.d.ts +9 -0
  16. package/dist/cli/commands/command.d.ts.map +1 -0
  17. package/dist/cli/commands/command.js +35 -0
  18. package/dist/cli/commands/command.js.map +1 -0
  19. package/dist/cli/commands/convert-eslint-config.js +14 -7
  20. package/dist/cli/commands/convert-eslint-config.js.map +1 -1
  21. package/dist/cli/commands/eslint.js +13 -4
  22. package/dist/cli/commands/eslint.js.map +1 -1
  23. package/dist/cli/commands/init.js +13 -4
  24. package/dist/cli/commands/init.js.map +1 -1
  25. package/dist/cli/commands/install.js +13 -4
  26. package/dist/cli/commands/install.js.map +1 -1
  27. package/dist/cli/commands/kendo-ui-license.js +13 -4
  28. package/dist/cli/commands/kendo-ui-license.js.map +1 -1
  29. package/dist/cli/commands/lint.js +13 -4
  30. package/dist/cli/commands/lint.js.map +1 -1
  31. package/dist/cli/commands/mfe-check.d.ts.map +1 -1
  32. package/dist/cli/commands/mfe-check.js +15 -7
  33. package/dist/cli/commands/mfe-check.js.map +1 -1
  34. package/dist/cli/commands/mfe-generate-metadata.js +13 -4
  35. package/dist/cli/commands/mfe-generate-metadata.js.map +1 -1
  36. package/dist/cli/commands/mfe-list.js +13 -4
  37. package/dist/cli/commands/mfe-list.js.map +1 -1
  38. package/dist/cli/commands/mfe-package-clean.js +13 -4
  39. package/dist/cli/commands/mfe-package-clean.js.map +1 -1
  40. package/dist/cli/commands/mfe-package-publish.js +13 -4
  41. package/dist/cli/commands/mfe-package-publish.js.map +1 -1
  42. package/dist/cli/commands/mfe-package-rollback.js +13 -4
  43. package/dist/cli/commands/mfe-package-rollback.js.map +1 -1
  44. package/dist/cli/commands/mfe-publish.js +13 -4
  45. package/dist/cli/commands/mfe-publish.js.map +1 -1
  46. package/dist/cli/commands/mfe-purge-cache.js +13 -4
  47. package/dist/cli/commands/mfe-purge-cache.js.map +1 -1
  48. package/dist/cli/commands/prepare-package.js +13 -4
  49. package/dist/cli/commands/prepare-package.js.map +1 -1
  50. package/dist/cli/commands/registry/build.d.ts +1 -1
  51. package/dist/cli/commands/registry/build.d.ts.map +1 -1
  52. package/dist/cli/commands/registry/build.js +3 -5
  53. package/dist/cli/commands/registry/build.js.map +1 -1
  54. package/dist/cli/commands/registry/bundle-package.d.ts +41 -0
  55. package/dist/cli/commands/registry/bundle-package.d.ts.map +1 -0
  56. package/dist/cli/commands/registry/bundle-package.js +54 -0
  57. package/dist/cli/commands/registry/bundle-package.js.map +1 -0
  58. package/dist/cli/commands/registry/command-registry.d.ts +42 -2
  59. package/dist/cli/commands/registry/command-registry.d.ts.map +1 -1
  60. package/dist/cli/commands/registry/command-registry.js +10 -19
  61. package/dist/cli/commands/registry/command-registry.js.map +1 -1
  62. package/dist/cli/commands/registry/start.d.ts +1 -1
  63. package/dist/cli/commands/registry/start.d.ts.map +1 -1
  64. package/dist/cli/commands/registry/start.js +3 -5
  65. package/dist/cli/commands/registry/start.js.map +1 -1
  66. package/dist/cli/commands/review/review.js +14 -7
  67. package/dist/cli/commands/review/review.js.map +1 -1
  68. package/dist/cli/commands/review/rules/no-deprecated-content-base.js +1 -3
  69. package/dist/cli/commands/review/rules/no-deprecated-content-base.js.map +1 -1
  70. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.js +1 -3
  71. package/dist/cli/commands/review/rules/no-direct-peer-dependencies.js.map +1 -1
  72. package/dist/cli/commands/review/rules/no-typescript-entry-point.js +1 -3
  73. package/dist/cli/commands/review/rules/no-typescript-entry-point.js.map +1 -1
  74. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.js +5 -12
  75. package/dist/cli/commands/review/rules/prefer-open-ended-peer-dependencies.js.map +1 -1
  76. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.js +5 -12
  77. package/dist/cli/commands/review/rules/require-compatible-launch-darkly-sdk.js.map +1 -1
  78. package/dist/cli/commands/review/rules/require-explicit-side-effects.js +1 -3
  79. package/dist/cli/commands/review/rules/require-explicit-side-effects.js.map +1 -1
  80. package/dist/cli/commands/review/rules/require-one-collection-version.js +1 -3
  81. package/dist/cli/commands/review/rules/require-one-collection-version.js.map +1 -1
  82. package/dist/cli/commands/review/rules/require-servicetitan-scope.js +1 -3
  83. package/dist/cli/commands/review/rules/require-servicetitan-scope.js.map +1 -1
  84. package/dist/cli/commands/review/rules/require-tsconfig-references.js +1 -3
  85. package/dist/cli/commands/review/rules/require-tsconfig-references.js.map +1 -1
  86. package/dist/cli/commands/review/types.d.ts.map +1 -1
  87. package/dist/cli/commands/review/types.js.map +1 -1
  88. package/dist/cli/commands/review/utils/compare-version.js +8 -19
  89. package/dist/cli/commands/review/utils/compare-version.js.map +1 -1
  90. package/dist/cli/commands/run-task.d.ts +1 -0
  91. package/dist/cli/commands/run-task.d.ts.map +1 -1
  92. package/dist/cli/commands/run-task.js +20 -6
  93. package/dist/cli/commands/run-task.js.map +1 -1
  94. package/dist/cli/commands/start.d.ts.map +1 -1
  95. package/dist/cli/commands/start.js +28 -13
  96. package/dist/cli/commands/start.js.map +1 -1
  97. package/dist/cli/commands/stylelint.js +13 -4
  98. package/dist/cli/commands/stylelint.js.map +1 -1
  99. package/dist/cli/commands/styles-check.js +13 -4
  100. package/dist/cli/commands/styles-check.js.map +1 -1
  101. package/dist/cli/commands/test/runners/jest.js +1 -3
  102. package/dist/cli/commands/test/runners/jest.js.map +1 -1
  103. package/dist/cli/commands/test/tests.js +13 -4
  104. package/dist/cli/commands/test/tests.js.map +1 -1
  105. package/dist/cli/commands/types.d.ts +1 -6
  106. package/dist/cli/commands/types.d.ts.map +1 -1
  107. package/dist/cli/commands/types.js +2 -20
  108. package/dist/cli/commands/types.js.map +1 -1
  109. package/dist/cli/commands/upload-sourcemaps.js +17 -13
  110. package/dist/cli/commands/upload-sourcemaps.js.map +1 -1
  111. package/dist/cli/index.js +1 -0
  112. package/dist/cli/index.js.map +1 -1
  113. package/dist/cli/tasks/cli-task.d.ts +3 -0
  114. package/dist/cli/tasks/cli-task.d.ts.map +1 -1
  115. package/dist/cli/tasks/cli-task.js +41 -9
  116. package/dist/cli/tasks/cli-task.js.map +1 -1
  117. package/dist/cli/tasks/swc-compile-package/get-swc-options.d.ts +9 -1
  118. package/dist/cli/tasks/swc-compile-package/get-swc-options.d.ts.map +1 -1
  119. package/dist/cli/tasks/swc-compile-package/get-swc-options.js +18 -2
  120. package/dist/cli/tasks/swc-compile-package/get-swc-options.js.map +1 -1
  121. package/dist/cli/tasks/swc-compile-package/swc-compile-package.d.ts +3 -1
  122. package/dist/cli/tasks/swc-compile-package/swc-compile-package.d.ts.map +1 -1
  123. package/dist/cli/tasks/swc-compile-package/swc-compile-package.js +17 -3
  124. package/dist/cli/tasks/swc-compile-package/swc-compile-package.js.map +1 -1
  125. package/dist/cli/tasks/task.d.ts +2 -1
  126. package/dist/cli/tasks/task.d.ts.map +1 -1
  127. package/dist/cli/tasks/task.js +6 -3
  128. package/dist/cli/tasks/task.js.map +1 -1
  129. package/dist/cli/tasks/tsc-compile/tsc-compile.js +1 -3
  130. package/dist/cli/tasks/tsc-compile/tsc-compile.js.map +1 -1
  131. package/dist/cli/utils/cli-npm.d.ts.map +1 -1
  132. package/dist/cli/utils/cli-npm.js +8 -1
  133. package/dist/cli/utils/cli-npm.js.map +1 -1
  134. package/dist/cli/utils/cli-os.d.ts +1 -0
  135. package/dist/cli/utils/cli-os.d.ts.map +1 -1
  136. package/dist/cli/utils/cli-os.js +20 -0
  137. package/dist/cli/utils/cli-os.js.map +1 -1
  138. package/dist/cli/utils/compile.d.ts.map +1 -1
  139. package/dist/cli/utils/compile.js +7 -4
  140. package/dist/cli/utils/compile.js.map +1 -1
  141. package/dist/cli/utils/copy-files.js +1 -0
  142. package/dist/cli/utils/copy-files.js.map +1 -1
  143. package/dist/cli/utils/index.d.ts +1 -1
  144. package/dist/cli/utils/index.d.ts.map +1 -1
  145. package/dist/cli/utils/index.js +1 -1
  146. package/dist/cli/utils/index.js.map +1 -1
  147. package/dist/cli/utils/process-tree.js +2 -6
  148. package/dist/cli/utils/process-tree.js.map +1 -1
  149. package/dist/cli/utils/resolve-bundler.d.ts.map +1 -1
  150. package/dist/cli/utils/resolve-bundler.js +2 -1
  151. package/dist/cli/utils/resolve-bundler.js.map +1 -1
  152. package/dist/cli/utils/ts-config.d.ts +1 -1
  153. package/dist/cli/utils/ts-config.d.ts.map +1 -1
  154. package/dist/cli/utils/ts-config.js +1 -3
  155. package/dist/cli/utils/ts-config.js.map +1 -1
  156. package/dist/cli/utils/with-exponential-backoff.d.ts +7 -0
  157. package/dist/cli/utils/with-exponential-backoff.d.ts.map +1 -0
  158. package/dist/cli/utils/with-exponential-backoff.js +28 -0
  159. package/dist/cli/utils/with-exponential-backoff.js.map +1 -0
  160. package/dist/core/constants.d.ts +2 -0
  161. package/dist/core/constants.d.ts.map +1 -1
  162. package/dist/core/constants.js +6 -1
  163. package/dist/core/constants.js.map +1 -1
  164. package/dist/cypress/config/vite-config.d.ts.map +1 -1
  165. package/dist/cypress/config/vite-config.js +23 -3
  166. package/dist/cypress/config/vite-config.js.map +1 -1
  167. package/dist/cypress/config/webpack-config.d.ts.map +1 -1
  168. package/dist/cypress/config/webpack-config.js +5 -0
  169. package/dist/cypress/config/webpack-config.js.map +1 -1
  170. package/dist/postinstall.js +118 -0
  171. package/dist/scripts/generate-bin-wrappers.js +203 -0
  172. package/dist/storybook-config/swc.d.ts +6 -0
  173. package/dist/storybook-config/swc.d.ts.map +1 -1
  174. package/dist/storybook-config/vite-final.d.ts.map +1 -1
  175. package/dist/storybook-config/vite-final.js +32 -6
  176. package/dist/storybook-config/vite-final.js.map +1 -1
  177. package/dist/storybook-config/webpack-final.d.ts.map +1 -1
  178. package/dist/storybook-config/webpack-final.js +3 -1
  179. package/dist/storybook-config/webpack-final.js.map +1 -1
  180. package/dist/utils/exit-when-parent-exits.d.ts +6 -0
  181. package/dist/utils/exit-when-parent-exits.d.ts.map +1 -0
  182. package/dist/utils/exit-when-parent-exits.js +37 -0
  183. package/dist/utils/exit-when-parent-exits.js.map +1 -0
  184. package/dist/utils/find-up.d.ts +1 -1
  185. package/dist/utils/find-up.d.ts.map +1 -1
  186. package/dist/utils/find-up.js +2 -2
  187. package/dist/utils/find-up.js.map +1 -1
  188. package/dist/utils/get-configuration.d.ts +6 -3
  189. package/dist/utils/get-configuration.d.ts.map +1 -1
  190. package/dist/utils/get-configuration.js +10 -2
  191. package/dist/utils/get-configuration.js.map +1 -1
  192. package/dist/utils/index.d.ts +1 -0
  193. package/dist/utils/index.d.ts.map +1 -1
  194. package/dist/utils/index.js +1 -0
  195. package/dist/utils/index.js.map +1 -1
  196. package/dist/utils/log.js +1 -3
  197. package/dist/utils/log.js.map +1 -1
  198. package/dist/vite/build-shared-dependencies.d.ts.map +1 -1
  199. package/dist/vite/build-shared-dependencies.js +2 -0
  200. package/dist/vite/build-shared-dependencies.js.map +1 -1
  201. package/dist/vite/config/base-config.d.ts.map +1 -1
  202. package/dist/vite/config/base-config.js +14 -1
  203. package/dist/vite/config/base-config.js.map +1 -1
  204. package/dist/vite/config/create-filtering-logger.d.ts.map +1 -1
  205. package/dist/vite/config/create-filtering-logger.js +12 -1
  206. package/dist/vite/config/create-filtering-logger.js.map +1 -1
  207. package/dist/vite/config/create-vite-build-context.d.ts.map +1 -1
  208. package/dist/vite/config/create-vite-build-context.js +4 -1
  209. package/dist/vite/config/create-vite-build-context.js.map +1 -1
  210. package/dist/vite/config/create-vite-config.js +7 -2
  211. package/dist/vite/config/create-vite-config.js.map +1 -1
  212. package/dist/vite/config/load-config-file.js +8 -19
  213. package/dist/vite/config/load-config-file.js.map +1 -1
  214. package/dist/vite/index.d.ts +2 -0
  215. package/dist/vite/index.d.ts.map +1 -1
  216. package/dist/vite/index.html +2 -2
  217. package/dist/vite/index.js +16 -0
  218. package/dist/vite/index.js.map +1 -1
  219. package/dist/vite/plugins/chain-source-maps-plugin.js +1 -1
  220. package/dist/vite/plugins/chain-source-maps-plugin.js.map +1 -1
  221. package/dist/vite/plugins/clean-plugin.js +1 -1
  222. package/dist/vite/plugins/clean-plugin.js.map +1 -1
  223. package/dist/vite/plugins/css-injector-plugin.js +1 -1
  224. package/dist/vite/plugins/css-injector-plugin.js.map +1 -1
  225. package/dist/vite/plugins/design-system-guard-plugin.d.ts.map +1 -1
  226. package/dist/vite/plugins/design-system-guard-plugin.js +10 -5
  227. package/dist/vite/plugins/design-system-guard-plugin.js.map +1 -1
  228. package/dist/vite/plugins/dev-server-routing-plugin.d.ts +1 -1
  229. package/dist/vite/plugins/dev-server-routing-plugin.d.ts.map +1 -1
  230. package/dist/vite/plugins/dev-server-routing-plugin.js +4 -3
  231. package/dist/vite/plugins/dev-server-routing-plugin.js.map +1 -1
  232. package/dist/vite/plugins/externals-plugin.d.ts.map +1 -1
  233. package/dist/vite/plugins/externals-plugin.js +11 -5
  234. package/dist/vite/plugins/externals-plugin.js.map +1 -1
  235. package/dist/vite/plugins/html-plugin.d.ts.map +1 -1
  236. package/dist/vite/plugins/html-plugin.js +5 -3
  237. package/dist/vite/plugins/html-plugin.js.map +1 -1
  238. package/dist/vite/plugins/ignore-modules-plugin.d.ts +2 -2
  239. package/dist/vite/plugins/ignore-modules-plugin.d.ts.map +1 -1
  240. package/dist/vite/plugins/ignore-modules-plugin.js +36 -24
  241. package/dist/vite/plugins/ignore-modules-plugin.js.map +1 -1
  242. package/dist/vite/plugins/index.d.ts +3 -0
  243. package/dist/vite/plugins/index.d.ts.map +1 -1
  244. package/dist/vite/plugins/index.js +3 -0
  245. package/dist/vite/plugins/index.js.map +1 -1
  246. package/dist/vite/plugins/istanbul-plugin.d.ts.map +1 -1
  247. package/dist/vite/plugins/istanbul-plugin.js +33 -1
  248. package/dist/vite/plugins/istanbul-plugin.js.map +1 -1
  249. package/dist/vite/plugins/less-tilde-plugin.d.ts +8 -0
  250. package/dist/vite/plugins/less-tilde-plugin.d.ts.map +1 -0
  251. package/dist/vite/plugins/less-tilde-plugin.js +53 -0
  252. package/dist/vite/plugins/less-tilde-plugin.js.map +1 -0
  253. package/dist/vite/plugins/magic-comments-plugin/magic-comments-plugin.js +1 -1
  254. package/dist/vite/plugins/magic-comments-plugin/magic-comments-plugin.js.map +1 -1
  255. package/dist/vite/plugins/metadata-plugin.js +1 -1
  256. package/dist/vite/plugins/metadata-plugin.js.map +1 -1
  257. package/dist/vite/plugins/moment-locales-plugin.d.ts +1 -1
  258. package/dist/vite/plugins/moment-locales-plugin.d.ts.map +1 -1
  259. package/dist/vite/plugins/moment-locales-plugin.js +30 -14
  260. package/dist/vite/plugins/moment-locales-plugin.js.map +1 -1
  261. package/dist/vite/plugins/react-refresh-plugin/index.d.ts +2 -0
  262. package/dist/vite/plugins/react-refresh-plugin/index.d.ts.map +1 -0
  263. package/dist/vite/plugins/react-refresh-plugin/index.js +20 -0
  264. package/dist/vite/plugins/react-refresh-plugin/index.js.map +1 -0
  265. package/dist/vite/plugins/react-refresh-plugin/react-refresh-plugin.d.ts +4 -0
  266. package/dist/vite/plugins/react-refresh-plugin/react-refresh-plugin.d.ts.map +1 -0
  267. package/dist/vite/plugins/react-refresh-plugin/react-refresh-plugin.js +143 -0
  268. package/dist/vite/plugins/react-refresh-plugin/react-refresh-plugin.js.map +1 -0
  269. package/dist/vite/plugins/react-refresh-plugin/refresh-runtime.js +113 -0
  270. package/dist/vite/plugins/shared-dependencies-plugin/shared-dependencies-plugin.d.ts.map +1 -1
  271. package/dist/vite/plugins/shared-dependencies-plugin/shared-dependencies-plugin.js +14 -11
  272. package/dist/vite/plugins/shared-dependencies-plugin/shared-dependencies-plugin.js.map +1 -1
  273. package/dist/vite/plugins/style-urls-plugin.js +1 -1
  274. package/dist/vite/plugins/style-urls-plugin.js.map +1 -1
  275. package/dist/vite/plugins/virtual-modules-plugin.d.ts.map +1 -1
  276. package/dist/vite/plugins/virtual-modules-plugin.js +9 -6
  277. package/dist/vite/plugins/virtual-modules-plugin.js.map +1 -1
  278. package/dist/vite/plugins/window-externals-plugin.d.ts +22 -0
  279. package/dist/vite/plugins/window-externals-plugin.d.ts.map +1 -0
  280. package/dist/vite/plugins/window-externals-plugin.js +74 -0
  281. package/dist/vite/plugins/window-externals-plugin.js.map +1 -0
  282. package/dist/vite/types.d.ts +4 -1
  283. package/dist/vite/types.d.ts.map +1 -1
  284. package/dist/webpack/bundle-webpack.d.ts.map +1 -1
  285. package/dist/webpack/bundle-webpack.js +6 -1
  286. package/dist/webpack/bundle-webpack.js.map +1 -1
  287. package/dist/webpack/configs/optimization-config.js +4 -4
  288. package/dist/webpack/configs/optimization-config.js.map +1 -1
  289. package/dist/webpack/configs/output-config.js +1 -1
  290. package/dist/webpack/configs/output-config.js.map +1 -1
  291. package/dist/webpack/configs/plugins/ignore-plugin/ignore-plugin.js +1 -3
  292. package/dist/webpack/configs/plugins/ignore-plugin/ignore-plugin.js.map +1 -1
  293. package/dist/webpack/loaders/expose-loader/__tests__/__mocks__/configuration.expose-loader.js +13 -0
  294. package/dist/webpack/loaders/expose-loader/__tests__/__mocks__/index.js +1 -0
  295. package/dist/webpack/utils/index.d.ts +1 -0
  296. package/dist/webpack/utils/index.d.ts.map +1 -1
  297. package/dist/webpack/utils/index.js +1 -0
  298. package/dist/webpack/utils/index.js.map +1 -1
  299. package/dist/webpack/utils/normalize-proxy-config.d.ts +6 -0
  300. package/dist/webpack/utils/normalize-proxy-config.d.ts.map +1 -0
  301. package/dist/webpack/utils/normalize-proxy-config.js +52 -0
  302. package/dist/webpack/utils/normalize-proxy-config.js.map +1 -0
  303. package/package.json +25 -22
  304. package/src/cli/commands/__tests__/build.test.ts +33 -19
  305. package/src/cli/commands/__tests__/bundle-package.test.ts +65 -0
  306. package/src/cli/commands/__tests__/bundle-vite.test.ts +1 -0
  307. package/src/cli/commands/__tests__/command.test.ts +42 -0
  308. package/src/cli/commands/__tests__/mfe-check.test.ts +26 -5
  309. package/src/cli/commands/__tests__/run-task.test.ts +20 -1
  310. package/src/cli/commands/__tests__/start.test.ts +35 -15
  311. package/src/cli/commands/build.ts +6 -5
  312. package/src/cli/commands/bundle-package.ts +20 -0
  313. package/src/cli/commands/command.ts +14 -0
  314. package/src/cli/commands/mfe-check.ts +6 -10
  315. package/src/cli/commands/registry/build.ts +3 -2
  316. package/src/cli/commands/registry/bundle-package.ts +22 -0
  317. package/src/cli/commands/registry/command-registry.ts +2 -0
  318. package/src/cli/commands/registry/start.ts +3 -2
  319. package/src/cli/commands/review/types.ts +1 -3
  320. package/src/cli/commands/run-task.ts +8 -2
  321. package/src/cli/commands/start.ts +9 -5
  322. package/src/cli/commands/types.ts +2 -6
  323. package/src/cli/index.ts +3 -0
  324. package/src/cli/tasks/__tests__/cli-task.test.ts +181 -69
  325. package/src/cli/tasks/__tests__/task.test.ts +40 -45
  326. package/src/cli/tasks/cli-task.ts +43 -2
  327. package/src/cli/tasks/swc-compile-package/__tests__/get-swc-options.test.ts +46 -4
  328. package/src/cli/tasks/swc-compile-package/__tests__/swc-compile-package.test.ts +25 -4
  329. package/src/cli/tasks/swc-compile-package/get-swc-options.ts +14 -1
  330. package/src/cli/tasks/swc-compile-package/swc-compile-package.ts +6 -2
  331. package/src/cli/tasks/task.ts +8 -2
  332. package/src/cli/tasks/tsc-compile/__tests__/tsc-compile.test.ts +8 -32
  333. package/src/cli/tasks/tsc-compile-package/__tests__/tsc-compile-package.test.ts +10 -19
  334. package/src/cli/utils/__tests__/cli-npm.test.ts +33 -0
  335. package/src/cli/utils/__tests__/cli-os.test.ts +86 -3
  336. package/src/cli/utils/__tests__/compile.test.ts +37 -2
  337. package/src/cli/utils/__tests__/copy-files.test.ts +1 -1
  338. package/src/cli/utils/__tests__/with-exponential-backoff.test.ts +119 -0
  339. package/src/cli/utils/cli-npm.ts +19 -4
  340. package/src/cli/utils/cli-os.ts +14 -0
  341. package/src/cli/utils/compile.ts +8 -1
  342. package/src/cli/utils/copy-files.ts +1 -1
  343. package/src/cli/utils/index.ts +1 -1
  344. package/src/cli/utils/resolve-bundler.ts +2 -1
  345. package/src/cli/utils/ts-config.ts +1 -1
  346. package/src/cli/utils/with-exponential-backoff.ts +28 -0
  347. package/src/core/constants.ts +2 -0
  348. package/src/cypress/config/__tests__/vite-config.test.ts +21 -11
  349. package/src/cypress/config/__tests__/webpack-config.test.ts +17 -0
  350. package/src/cypress/config/vite-config.ts +18 -3
  351. package/src/cypress/config/webpack-config.ts +2 -0
  352. package/src/storybook-config/__tests__/vite-final.test.ts +71 -11
  353. package/src/storybook-config/__tests__/webpack-final.test.ts +30 -6
  354. package/src/storybook-config/vite-final.ts +23 -2
  355. package/src/storybook-config/webpack-final.ts +10 -2
  356. package/src/utils/__tests__/exit-when-parent-exits.test.ts +87 -0
  357. package/src/utils/__tests__/find-up.test.ts +49 -0
  358. package/src/utils/__tests__/get-configuration.test.ts +62 -0
  359. package/src/utils/exit-when-parent-exits.ts +33 -0
  360. package/src/utils/find-up.ts +2 -2
  361. package/src/utils/get-configuration.ts +14 -5
  362. package/src/utils/index.ts +1 -0
  363. package/src/vite/__tests__/build-shared-dependencies.test.ts +39 -5
  364. package/src/vite/build-shared-dependencies.ts +2 -1
  365. package/src/vite/config/__tests__/base-config.test.ts +16 -4
  366. package/src/vite/config/__tests__/create-css-config.test.ts +2 -6
  367. package/src/vite/config/__tests__/create-filtering-logger.test.ts +9 -0
  368. package/src/vite/config/__tests__/create-vite-build-context.test.ts +25 -0
  369. package/src/vite/config/__tests__/create-vite-config.test.ts +6 -3
  370. package/src/vite/config/base-config.ts +18 -2
  371. package/src/vite/config/create-filtering-logger.ts +13 -2
  372. package/src/vite/config/create-vite-build-context.ts +1 -0
  373. package/src/vite/config/create-vite-config.ts +6 -3
  374. package/src/vite/index.html +2 -2
  375. package/src/vite/index.ts +2 -0
  376. package/src/vite/plugins/__tests__/chain-source-maps-plugin.test.ts +1 -1
  377. package/src/vite/plugins/__tests__/clean-plugin.test.ts +1 -1
  378. package/src/vite/plugins/__tests__/css-injector-plugin.test.ts +1 -1
  379. package/src/vite/plugins/__tests__/design-system-guard-plugin.test.ts +15 -3
  380. package/src/vite/plugins/__tests__/dev-server-routing-plugin.test.ts +121 -99
  381. package/src/vite/plugins/__tests__/externals-plugin.test.ts +24 -3
  382. package/src/vite/plugins/__tests__/html-plugin.test.ts +10 -3
  383. package/src/vite/plugins/__tests__/html-template.test.ts +10 -2
  384. package/src/vite/plugins/__tests__/ignore-modules-plugin.test.ts +30 -6
  385. package/src/vite/plugins/__tests__/istanbul-plugin.test.ts +42 -1
  386. package/src/vite/plugins/__tests__/less-tilde-plugin.test.ts +91 -0
  387. package/src/vite/plugins/__tests__/metadata-plugin.test.ts +1 -1
  388. package/src/vite/plugins/__tests__/moment-locales-plugin.test.ts +35 -25
  389. package/src/vite/plugins/__tests__/style-urls-plugin.test.ts +1 -1
  390. package/src/vite/plugins/__tests__/virtual-modules-plugin.test.ts +20 -9
  391. package/src/vite/plugins/__tests__/window-externals-plugin.test.ts +128 -0
  392. package/src/vite/plugins/chain-source-maps-plugin.ts +1 -1
  393. package/src/vite/plugins/clean-plugin.ts +1 -1
  394. package/src/vite/plugins/css-injector-plugin.ts +1 -1
  395. package/src/vite/plugins/design-system-guard-plugin.ts +11 -8
  396. package/src/vite/plugins/dev-server-routing-plugin.ts +4 -4
  397. package/src/vite/plugins/externals-plugin.ts +15 -6
  398. package/src/vite/plugins/html-plugin.ts +4 -2
  399. package/src/vite/plugins/ignore-modules-plugin.ts +32 -23
  400. package/src/vite/plugins/index.ts +3 -0
  401. package/src/vite/plugins/istanbul-plugin.ts +28 -1
  402. package/src/vite/plugins/less-tilde-plugin.ts +64 -0
  403. package/src/vite/plugins/magic-comments-plugin/magic-comments-plugin.ts +1 -1
  404. package/src/vite/plugins/metadata-plugin.ts +1 -1
  405. package/src/vite/plugins/moment-locales-plugin.ts +24 -14
  406. package/src/vite/plugins/react-refresh-plugin/README.md +165 -0
  407. package/src/vite/plugins/react-refresh-plugin/__tests__/react-refresh-plugin.test.ts +366 -0
  408. package/src/vite/plugins/react-refresh-plugin/__tests__/refresh-runtime.test.ts +193 -0
  409. package/src/vite/plugins/react-refresh-plugin/index.ts +1 -0
  410. package/src/vite/plugins/react-refresh-plugin/react-refresh-plugin.ts +144 -0
  411. package/src/vite/plugins/react-refresh-plugin/refresh-runtime.js +113 -0
  412. package/src/vite/plugins/shared-dependencies-plugin/__tests__/shared-dependencies-plugin.test.ts +21 -16
  413. package/src/vite/plugins/shared-dependencies-plugin/shared-dependencies-plugin.ts +13 -12
  414. package/src/vite/plugins/style-urls-plugin.ts +1 -1
  415. package/src/vite/plugins/virtual-modules-plugin.ts +8 -7
  416. package/src/vite/plugins/window-externals-plugin.ts +94 -0
  417. package/src/vite/types.ts +4 -1
  418. package/src/webpack/__tests__/bundle-webpack.test.ts +32 -0
  419. package/src/webpack/__tests__/create-webpack-config-web-component.test.ts +17 -5
  420. package/src/webpack/__tests__/create-webpack-config.test.ts +10 -6
  421. package/src/webpack/bundle-webpack.ts +7 -1
  422. package/src/webpack/configs/optimization-config.ts +3 -3
  423. package/src/webpack/configs/output-config.ts +1 -1
  424. package/src/webpack/utils/__tests__/normalize-proxy-config.test.ts +121 -0
  425. package/src/webpack/utils/index.ts +1 -0
  426. package/src/webpack/utils/normalize-proxy-config.ts +59 -0
  427. package/tsconfig/types.d.ts +10 -0
  428. package/dist/cli/utils/get-bundle-command.d.ts +0 -3
  429. package/dist/cli/utils/get-bundle-command.d.ts.map +0 -1
  430. package/dist/cli/utils/get-bundle-command.js +0 -16
  431. package/dist/cli/utils/get-bundle-command.js.map +0 -1
  432. package/src/cli/utils/__tests__/get-bundle-command.test.ts +0 -23
  433. package/src/cli/utils/get-bundle-command.ts +0 -5
@@ -0,0 +1,20 @@
1
+ import { bundleConstants } from '../../core';
2
+ import { getConfiguration } from '../../utils';
3
+ import { entry } from './registry/bundle-package';
4
+ import { Command } from './types';
5
+
6
+ export class BundlePackage extends Command<typeof entry> {
7
+ async execute() {
8
+ // Local cli.bundler overrides project-wide default in this.args.bundler
9
+ const bundler =
10
+ getConfiguration().bundler ?? this.args.bundler ?? bundleConstants.defaultBundler;
11
+
12
+ if (bundler === 'vite') {
13
+ const { BundleVite } = await import('./bundle-vite');
14
+ await new BundleVite(this.args).execute();
15
+ } else {
16
+ const { BundleWebpack } = await import('./bundle-webpack');
17
+ await new BundleWebpack(this.args).execute();
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,14 @@
1
+ import { CommandName, exitWhenParentExits } from '../../utils';
2
+ import { CommandEntry, InferArgs } from './types';
3
+
4
+ export abstract class Command<T extends CommandEntry = CommandEntry, U = unknown> {
5
+ constructor(protected readonly args: InferArgs<NonNullable<T['options']>, U>) {}
6
+
7
+ watchForParentExit(name: CommandName): void {
8
+ if ('watch' in this.args && this.args.watch === true) {
9
+ exitWhenParentExits(name);
10
+ }
11
+ }
12
+
13
+ abstract execute(): Promise<void>;
14
+ }
@@ -2,7 +2,10 @@ import { getPackageManager } from '@servicetitan/install';
2
2
  import { getVersionMismatches } from '@servicetitan/startup-utils';
3
3
  import path from 'node:path';
4
4
  import { getExposedDependencies, Metadata } from '../../core';
5
+ import type { Configuration } from '../../utils';
5
6
  import {
7
+ getSharedDependencies,
8
+ isExposeSharedDependencies,
6
9
  isWebComponent,
7
10
  loadSharedDependencies,
8
11
  log,
@@ -16,13 +19,7 @@ import { Command } from './types';
16
19
  interface HostPackageJSON {
17
20
  name: string;
18
21
  dependencies: Record<string, string>;
19
- cli?: {
20
- 'web-component'?: boolean | string | object;
21
- 'webpack'?: {
22
- 'expose-shared-dependencies'?: boolean;
23
- 'shared-dependencies'?: Record<string, string>;
24
- };
25
- };
22
+ cli?: Configuration;
26
23
  }
27
24
 
28
25
  interface HostData extends HostPackageJSON {
@@ -82,7 +79,7 @@ export class MfeCheck extends Command<typeof entry> {
82
79
  const mfeSharedDependencies = mfeMetadata.sharedDependencies;
83
80
  const hostSharedDependencies = loadSharedDependencies(
84
81
  hostData.dependencies,
85
- hostData.cli?.webpack?.['shared-dependencies']
82
+ getSharedDependencies(hostData)
86
83
  );
87
84
  const packageManager = getPackageManager();
88
85
  const workspacePackage = packageManager.getWorkspacePackage(hostData.location);
@@ -99,8 +96,7 @@ export class MfeCheck extends Command<typeof entry> {
99
96
  );
100
97
 
101
98
  const isHostMfe = isWebComponent(hostData);
102
- const isSharedDependenciesEnabled =
103
- hostData.cli?.webpack?.['expose-shared-dependencies'] === true;
99
+ const isSharedDependenciesEnabled = isExposeSharedDependencies(hostData);
104
100
  const compatible = !isHostMfe && !mismatchResult && isSharedDependenciesEnabled;
105
101
 
106
102
  return {
@@ -1,3 +1,4 @@
1
+ import { bundleConstants } from '../../../core';
1
2
  import type { CommandEntry } from '../types';
2
3
  import { defineEntry } from './define-entry';
3
4
 
@@ -6,9 +7,9 @@ export const entry = defineEntry({
6
7
  greedy: true,
7
8
  options: {
8
9
  bundler: {
9
- choices: ['vite', 'webpack'] as const,
10
+ choices: bundleConstants.bundlers,
10
11
  description: 'Bundler',
11
- defaultDescription: 'webpack',
12
+ defaultDescription: bundleConstants.defaultBundler,
12
13
  },
13
14
  cdnPath: { string: true, description: 'Base url for application assets' },
14
15
  codeCoverage: { boolean: true, description: 'Instrument code for coverage analysis?' },
@@ -0,0 +1,22 @@
1
+ import { bundleConstants } from '../../../core';
2
+ import type { CommandEntry } from '../types';
3
+ import { defineEntry } from './define-entry';
4
+
5
+ /*
6
+ * Internal dispatcher invoked by `start`/`build` per package. Its options are the union of
7
+ * bundle-vite and bundle-webpack so it can forward them to whichever bundler it delegates to,
8
+ * plus the run's --bundler default.
9
+ */
10
+ export const entry = defineEntry({
11
+ options: {
12
+ bundler: { choices: bundleConstants.bundlers, hidden: true },
13
+ codeCoverage: { boolean: true, hidden: true },
14
+ config: { string: true, hidden: true },
15
+ exposedDependencies: { boolean: true, hidden: true },
16
+ preview: { boolean: true, hidden: true },
17
+ printConfig: { boolean: true, hidden: true },
18
+ stat: { boolean: true, hidden: true },
19
+ useWatchConfig: { boolean: true, hidden: true },
20
+ watch: { boolean: true, hidden: true },
21
+ },
22
+ } satisfies CommandEntry);
@@ -1,6 +1,7 @@
1
1
  import { CommandName } from '../../../utils';
2
2
  import { Command, CommandEntry, Newable } from '../types';
3
3
  import { entry as build } from './build';
4
+ import { entry as bundlePackage } from './bundle-package';
4
5
  import { entry as bundleVite } from './bundle-vite';
5
6
  import { entry as bundleWebpack } from './bundle-webpack';
6
7
  import { entry as clean } from './clean';
@@ -64,6 +65,7 @@ function makeEntry<K extends CommandName, T extends CommandEntry>(
64
65
  */
65
66
  export const commandRegistry = {
66
67
  ...makeEntry(CommandName.build, build),
68
+ ...makeEntry(CommandName['bundle-package'], bundlePackage),
67
69
  ...makeEntry(CommandName['bundle-vite'], bundleVite),
68
70
  ...makeEntry(CommandName['bundle-webpack'], bundleWebpack),
69
71
  ...makeEntry(CommandName.clean, clean),
@@ -1,3 +1,4 @@
1
+ import { bundleConstants } from '../../../core';
1
2
  import type { CommandEntry } from '../types';
2
3
  import { defineEntry } from './define-entry';
3
4
 
@@ -6,9 +7,9 @@ export const entry = defineEntry({
6
7
  greedy: true,
7
8
  options: {
8
9
  bundler: {
9
- choices: ['vite', 'webpack'] as const,
10
+ choices: bundleConstants.bundlers,
10
11
  description: 'Bundler',
11
- defaultDescription: 'webpack',
12
+ defaultDescription: bundleConstants.defaultBundler,
12
13
  },
13
14
  codeCoverage: { boolean: true, description: 'Instrument code for coverage analysis?' },
14
15
  config: { string: true, hidden: true, description: 'Use specified configuration' },
@@ -71,8 +71,6 @@ export interface ReviewConfiguration {
71
71
  }
72
72
 
73
73
  export type RuleConfiguration =
74
- | Level
75
- | [Level]
76
- | [Level, { exclude?: string[] | Record<string, string[]> }];
74
+ Level | [Level] | [Level, { exclude?: string[] | Record<string, string[]> }];
77
75
 
78
76
  export type Level = 'warn' | 'error' | 'off';
@@ -12,15 +12,21 @@ const tasks: Record<string, new (args: { [key: string]: unknown }) => Task> = {
12
12
  };
13
13
 
14
14
  export class RunTask extends Command<typeof entry> {
15
+ watchForParentExit(): void {
16
+ // No-op: the task being run handles its own parent-exit watch.
17
+ }
18
+
15
19
  @logErrors
16
20
  async execute() {
17
21
  const { _ = [], taskName = this.args._?.[0], taskArgs = [], ...restOptions } = this.args;
18
22
 
19
23
  if (taskName && taskName in tasks) {
20
- await new tasks[taskName]({
24
+ const task = new tasks[taskName]({
21
25
  _: [..._, ...taskArgs],
22
26
  ...restOptions,
23
- }).execute();
27
+ });
28
+ task.watchForParentExit();
29
+ await task.execute();
24
30
  return;
25
31
  }
26
32
 
@@ -2,10 +2,10 @@ import { getPackages, logErrors, PackageType } from '../../utils';
2
2
  import {
3
3
  checkArgs,
4
4
  compile,
5
- getBundleCommand,
6
5
  lernaExec,
7
6
  pipeStdout,
8
7
  ProcessTree,
8
+ resolveBundler,
9
9
  typeCheck,
10
10
  watchStdout,
11
11
  } from '../utils';
@@ -28,6 +28,9 @@ export class Start extends Command<typeof entry> {
28
28
  async execute() {
29
29
  checkArgs(this.args, { obsolete: ['--esbuild', '--experimental-bundlers'] });
30
30
 
31
+ // Used by sub-processes to detect this process dying
32
+ process.env.STARTUP_PARENT_PID = String(process.pid);
33
+
31
34
  const useTsc = this.args.useTsc;
32
35
 
33
36
  const packages = getPackages({
@@ -43,7 +46,7 @@ export class Start extends Command<typeof entry> {
43
46
  const bundleScope = packages
44
47
  .filter(({ type }) => type === PackageType.Bundle)
45
48
  .map(({ name }) => name);
46
- const bundleCmd = getBundleCommand(this.args);
49
+ const bundlerArg = [`--bundler ${resolveBundler(this.args)}`];
47
50
  const precompileScope = packages
48
51
  .filter(({ scripts }) => !!scripts?.precompile)
49
52
  .map(({ name }) => name);
@@ -126,11 +129,11 @@ export class Start extends Command<typeof entry> {
126
129
  return Promise.resolve();
127
130
  }
128
131
  return lernaExec({
129
- 'cmd': bundleCmd,
132
+ 'cmd': 'startup bundle-package',
130
133
  'scope': bundleScope,
131
134
  'parallel': true,
132
135
  'stream': true,
133
- '--': ['--exposed-dependencies', '--use-watch-config'],
136
+ '--': ['--exposed-dependencies', '--use-watch-config', ...bundlerArg],
134
137
  });
135
138
  },
136
139
  { dependsOn: [StartProcesses.Compile, StartProcesses.PreparePackage] }
@@ -142,7 +145,7 @@ export class Start extends Command<typeof entry> {
142
145
  return Promise.resolve();
143
146
  }
144
147
  return lernaExec({
145
- 'cmd': bundleCmd,
148
+ 'cmd': 'startup bundle-package',
146
149
  'scope': bundleScope,
147
150
  'parallel': true,
148
151
  'stream': true,
@@ -150,6 +153,7 @@ export class Start extends Command<typeof entry> {
150
153
  '--watch',
151
154
  this.args.config ? `--config "${this.args.config}"` : undefined,
152
155
  this.args.codeCoverage ? '--code-coverage' : undefined,
156
+ ...bundlerArg,
153
157
  ].filter(item => !!item) as string[],
154
158
  });
155
159
  },
@@ -56,10 +56,6 @@ export interface CommandEntry {
56
56
  options?: CommandOptions;
57
57
  }
58
58
 
59
- export abstract class Command<T extends CommandEntry = CommandEntry, U = unknown> {
60
- constructor(protected readonly args: InferArgs<NonNullable<T['options']>, U>) {}
61
-
62
- abstract execute(): Promise<void>;
63
- }
64
-
65
59
  export type Newable<T> = new (...args: any[]) => T;
60
+
61
+ export { Command } from './command';
package/src/cli/index.ts CHANGED
@@ -69,6 +69,9 @@ async function handleCommand(name: CommandName, argv: any) {
69
69
  const CommandClass = await entry.load();
70
70
  // eslint-disable-next-line @typescript-eslint/naming-convention
71
71
  const command = new CommandClass({ ...argv, _: argv._.slice(1) });
72
+
73
+ command.watchForParentExit(name);
74
+
72
75
  command.execute().catch(() => {
73
76
  process.exit(1);
74
77
  });
@@ -1,30 +1,17 @@
1
- import { log } from '../../../utils';
2
- import { pipeStdout, watchStdout } from '../../utils';
1
+ import execa from 'execa';
2
+ import { exitWhenParentExits, getFolders, log, readJsonSafe } from '../../../utils';
3
+ import { killProcessTree, pipeStdout, watchStdout } from '../../utils';
3
4
  import { CliTask, Indicators } from '../cli-task';
4
5
 
5
- jest.mock('execa', () =>
6
- jest.fn().mockReturnValue(
7
- Object.assign(Promise.resolve(), {
8
- stdout: {
9
- on: jest.fn(),
10
- },
11
- })
12
- )
13
- );
14
-
15
- jest.mock('../../utils', () => ({
16
- pipeStdout: jest.fn(),
17
- watchStdout: jest.fn(),
18
- }));
6
+ jest.mock('execa', () => jest.fn());
7
+ jest.mock('../../utils');
19
8
 
20
9
  jest.mock('../../../utils', () => ({
21
10
  ...jest.requireActual('../../../utils'),
22
- getFolders: jest.fn().mockReturnValue({
23
- source: 'src',
24
- destination: 'dist',
25
- }),
11
+ exitWhenParentExits: jest.fn(),
12
+ getFolders: jest.fn(),
26
13
  log: { info: jest.fn() },
27
- readJsonSafe: jest.fn().mockReturnValue({}),
14
+ readJsonSafe: jest.fn(),
28
15
  }));
29
16
 
30
17
  const taskName = 'cli-task-impl';
@@ -35,7 +22,11 @@ const indicators: Required<Indicators> = {
35
22
  };
36
23
 
37
24
  class CliTaskImpl extends CliTask {
38
- constructor({ watch }: { watch: boolean }) {
25
+ constructor(
26
+ private command: string,
27
+ private args: string[],
28
+ { watch }: { watch: boolean }
29
+ ) {
39
30
  super({ name: taskName, global: false, watch, indicators });
40
31
  }
41
32
 
@@ -44,83 +35,204 @@ class CliTaskImpl extends CliTask {
44
35
  }
45
36
 
46
37
  async execute(): Promise<void> {
47
- await this.runChildProcess('', []);
38
+ await this.runChildProcess(this.command, this.args);
48
39
  }
49
40
  }
50
41
 
51
- describe(`[startup] ${CliTask.name} task`, () => {
42
+ describe(`[startup] ${CliTask.name}`, () => {
43
+ const command = 'foo';
44
+ const args = ['bar'];
45
+
52
46
  beforeEach(() => {
53
- globalThis.performance.clearMarks();
54
- globalThis.performance.clearMeasures();
55
47
  jest.clearAllMocks();
48
+ jest.mocked(readJsonSafe).mockReturnValue({});
56
49
  });
57
50
 
58
- let watch = false;
59
-
60
- const subject = () => new CliTaskImpl({ watch }).execute();
51
+ describe('watchForParentExit', () => {
52
+ const subject = () => new CliTaskImpl(command, args, { watch: true }).watchForParentExit();
61
53
 
62
- test('logs completion message', async () => {
63
- await subject();
54
+ test('does not watch for the parent process to exit', () => {
55
+ subject();
64
56
 
65
- expect(log.info).toHaveBeenCalledWith(
66
- expect.stringContaining(`${taskName} task completed in`)
67
- );
57
+ expect(exitWhenParentExits).not.toHaveBeenCalled();
58
+ });
68
59
  });
69
60
 
70
- describe('in watch mode', () => {
71
- beforeEach(() => (watch = true));
61
+ describe('runChildProcess', () => {
62
+ const childPid = 4321;
63
+ let watch = false;
64
+
65
+ beforeEach(() => {
66
+ globalThis.performance.clearMarks();
67
+ globalThis.performance.clearMeasures();
68
+ jest.mocked(getFolders).mockReturnValue({ source: 'src', destination: 'dist' });
69
+ jest.mocked(execa).mockReturnValue(
70
+ Object.assign(Promise.resolve(), {
71
+ pid: childPid,
72
+ stdout: { on: jest.fn() },
73
+ }) as any
74
+ );
75
+ });
72
76
 
73
- test('it calls pipeStdout', () => {
74
- subject();
75
- expect(pipeStdout).toHaveBeenCalled();
77
+ const subject = () => new CliTaskImpl(command, args, { watch }).execute();
78
+
79
+ test('runs command', async () => {
80
+ await subject();
81
+
82
+ expect(execa).toHaveBeenCalledWith(command, args, { stdio: 'inherit' });
76
83
  });
77
84
 
78
- describe('onData handler', () => {
79
- beforeEach(() => subject());
85
+ test('logs completion message', async () => {
86
+ await subject();
80
87
 
81
- const onDataHandler = (data: string) => {
82
- const handler = jest
83
- .mocked(watchStdout)
84
- .mock.calls.find(([_process, indicator]) => indicator === data)![2];
85
- handler(1);
86
- };
88
+ expect(log.info).toHaveBeenCalledWith(
89
+ expect.stringContaining(`${taskName} task completed in`)
90
+ );
91
+ });
92
+
93
+ describe('in watch mode', () => {
94
+ const originalPlatform = process.platform;
95
+ let onceSpy: jest.SpyInstance;
96
+ let killSpy: jest.SpyInstance;
97
+
98
+ beforeEach(() => {
99
+ watch = true;
100
+ onceSpy = jest.spyOn(process, 'once');
101
+ killSpy = jest.spyOn(process, 'kill').mockImplementation(jest.fn());
102
+ });
87
103
 
88
- function itLogsInitialBuild(event: keyof Indicators) {
89
- test('logs duration of initial build', () => {
90
- onDataHandler(indicators[event]);
104
+ afterEach(() => {
105
+ process.removeAllListeners('SIGINT');
106
+ process.removeAllListeners('SIGTERM');
107
+ });
91
108
 
92
- expect(log.info).toHaveBeenCalledWith(
93
- expect.stringContaining(`Initial ${taskName} task completed in`)
94
- );
109
+ function mockPlatform(platform: NodeJS.Platform) {
110
+ Object.defineProperty(process, 'platform', {
111
+ value: platform,
112
+ configurable: true,
95
113
  });
96
114
  }
97
115
 
98
- function itLogsSubsequentBuild(event: keyof Indicators) {
99
- test('logs duration of subsequent build', () => {
100
- onDataHandler(indicators[event]!);
116
+ test('pipes stdout and conditionally runs command in own process', async () => {
117
+ await subject();
101
118
 
102
- expect(log.info).toHaveBeenCalledWith(
103
- expect.stringContaining(`Subsequent ${taskName} task completed in`)
104
- );
119
+ expect(execa).toHaveBeenCalledWith(command, args, {
120
+ stdio: ['inherit', 'pipe', 'inherit'],
121
+ detached: process.platform !== 'win32',
105
122
  });
106
- }
123
+ });
124
+
125
+ test('calls pipeStdout', () => {
126
+ subject();
107
127
 
108
- itLogsInitialBuild('end');
128
+ expect(pipeStdout).toHaveBeenCalled();
129
+ });
130
+
131
+ test('watches for the parent process to exit', () => {
132
+ subject();
133
+
134
+ expect(exitWhenParentExits).toHaveBeenCalledWith(taskName, expect.any(Function));
135
+ });
136
+
137
+ describe('on POSIX', () => {
138
+ beforeEach(() => mockPlatform('darwin'));
139
+
140
+ afterEach(() => mockPlatform(originalPlatform));
141
+
142
+ describe.each<NodeJS.Signals>(['SIGINT', 'SIGTERM'])(
143
+ 'when the process receives %s',
144
+ signal => {
145
+ beforeEach(() => {
146
+ subject();
147
+ onceSpy.mock.calls.find(([registered]) => registered === signal)![1](
148
+ signal
149
+ );
150
+ });
151
+
152
+ test(`forwards ${signal} to the child process tree`, () => {
153
+ expect(killProcessTree).toHaveBeenCalledWith(childPid, signal);
154
+ });
155
+
156
+ test(`re-raises ${signal}`, () => {
157
+ expect(killSpy).toHaveBeenCalledWith(process.pid, signal);
158
+ });
159
+ }
160
+ );
161
+ });
162
+
163
+ describe('on Windows', () => {
164
+ beforeEach(() => mockPlatform('win32'));
165
+
166
+ afterEach(() => mockPlatform(originalPlatform));
167
+
168
+ test('does not intercept signals', () => {
169
+ subject();
170
+
171
+ expect(onceSpy).not.toHaveBeenCalled();
172
+ });
173
+ });
174
+
175
+ describe('when the parent process exits', () => {
176
+ const triggerParentExit = () =>
177
+ jest.mocked(exitWhenParentExits).mock.calls[0][1]!();
109
178
 
110
- describe('when subsequent build starts after initial build ends', () => {
111
179
  beforeEach(() => {
112
- onDataHandler(indicators.end);
113
- onDataHandler(indicators.watchStart);
180
+ subject();
181
+ triggerParentExit();
114
182
  });
115
183
 
116
- itLogsSubsequentBuild('end');
117
- itLogsSubsequentBuild('watchEnd');
184
+ test('kills the child process tree', () => {
185
+ expect(killProcessTree).toHaveBeenCalledWith(childPid);
186
+ });
118
187
  });
119
188
 
120
- describe('when subsequent build starts before initial build ends', () => {
121
- beforeEach(() => onDataHandler(indicators.watchStart));
189
+ describe('onData handler', () => {
190
+ beforeEach(() => subject());
191
+
192
+ const onDataHandler = (data: string) => {
193
+ const handler = jest
194
+ .mocked(watchStdout)
195
+ .mock.calls.find(([_process, indicator]) => indicator === data)![2];
196
+ handler(1);
197
+ };
198
+
199
+ function itLogsInitialBuild(event: keyof Indicators) {
200
+ test('logs duration of initial build', () => {
201
+ onDataHandler(indicators[event]);
202
+
203
+ expect(log.info).toHaveBeenCalledWith(
204
+ expect.stringContaining(`Initial ${taskName} task completed in`)
205
+ );
206
+ });
207
+ }
208
+
209
+ function itLogsSubsequentBuild(event: keyof Indicators) {
210
+ test('logs duration of subsequent build', () => {
211
+ onDataHandler(indicators[event]!);
212
+
213
+ expect(log.info).toHaveBeenCalledWith(
214
+ expect.stringContaining(`Subsequent ${taskName} task completed in`)
215
+ );
216
+ });
217
+ }
218
+
219
+ itLogsInitialBuild('end');
220
+
221
+ describe('when subsequent build starts after initial build ends', () => {
222
+ beforeEach(() => {
223
+ onDataHandler(indicators.end);
224
+ onDataHandler(indicators.watchStart);
225
+ });
226
+
227
+ itLogsSubsequentBuild('end');
228
+ itLogsSubsequentBuild('watchEnd');
229
+ });
230
+
231
+ describe('when subsequent build starts before initial build ends', () => {
232
+ beforeEach(() => onDataHandler(indicators.watchStart));
122
233
 
123
- itLogsSubsequentBuild('watchEnd');
234
+ itLogsSubsequentBuild('watchEnd');
235
+ });
124
236
  });
125
237
  });
126
238
  });