@openedx/frontend-base 1.0.0-alpha.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 (356) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +112 -0
  3. package/config/babel/babel.config.js +28 -0
  4. package/config/config-helpers/createConfig.js +13 -0
  5. package/config/config-helpers/createLintConfig.js +16 -0
  6. package/config/config-helpers/getBaseConfig.js +12 -0
  7. package/config/defaultConfigPaths.js +35 -0
  8. package/config/eslint/base.eslint.config.js +113 -0
  9. package/config/index.js +12 -0
  10. package/config/jest/jest.config.js +30 -0
  11. package/config/tsconfig.json +32 -0
  12. package/config/types.js +25 -0
  13. package/config/webpack/common-config/all/getCodeRules.js +52 -0
  14. package/config/webpack/common-config/all/getFileLoaderRules.js +26 -0
  15. package/config/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  16. package/config/webpack/common-config/all/getImageMinimizer.js +25 -0
  17. package/config/webpack/common-config/all/getStylesheetRule.js +112 -0
  18. package/config/webpack/common-config/dev/getDevServer.js +38 -0
  19. package/config/webpack/common-config/index.js +18 -0
  20. package/config/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  21. package/config/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  22. package/config/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  23. package/config/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  24. package/config/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  25. package/config/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  26. package/config/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  27. package/config/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  28. package/config/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  29. package/config/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  30. package/config/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  31. package/config/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  32. package/config/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  33. package/config/webpack/types.js +2 -0
  34. package/config/webpack/utils/getLocalAliases.js +65 -0
  35. package/config/webpack/utils/getPublicPath.js +6 -0
  36. package/config/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  37. package/config/webpack/utils/paragonUtils.js +138 -0
  38. package/config/webpack/webpack.config.build.js +80 -0
  39. package/config/webpack/webpack.config.dev.js +76 -0
  40. package/config/webpack/webpack.config.dev.shell.js +110 -0
  41. package/eslint.config.js +18 -0
  42. package/frontend-base.d.ts +8 -0
  43. package/index.ts +7 -0
  44. package/jest.config.js +7 -0
  45. package/openedx-frontend-base.tgz +0 -0
  46. package/package.json +149 -0
  47. package/runtime/analytics/MockAnalyticsService.js +71 -0
  48. package/runtime/analytics/SegmentAnalyticsService.js +243 -0
  49. package/runtime/analytics/index.ts +12 -0
  50. package/runtime/analytics/interface.js +145 -0
  51. package/runtime/auth/AxiosCsrfTokenService.js +60 -0
  52. package/runtime/auth/AxiosJwtAuthService.js +363 -0
  53. package/runtime/auth/AxiosJwtTokenService.js +134 -0
  54. package/runtime/auth/LocalForageCache.js +76 -0
  55. package/runtime/auth/MockAuthService.js +278 -0
  56. package/runtime/auth/index.ts +19 -0
  57. package/runtime/auth/interceptors/createCsrfTokenProviderInterceptor.js +36 -0
  58. package/runtime/auth/interceptors/createJwtTokenProviderInterceptor.js +37 -0
  59. package/runtime/auth/interceptors/createProcessAxiosRequestErrorInterceptor.js +20 -0
  60. package/runtime/auth/interceptors/createRetryInterceptor.js +74 -0
  61. package/runtime/auth/interface.js +309 -0
  62. package/runtime/auth/utils.js +105 -0
  63. package/runtime/babel.config.js +3 -0
  64. package/runtime/config/index.ts +295 -0
  65. package/runtime/constants.ts +68 -0
  66. package/runtime/i18n/index.js +118 -0
  67. package/runtime/i18n/injectIntlWithShim.jsx +48 -0
  68. package/runtime/i18n/lib.ts +272 -0
  69. package/runtime/index.ts +134 -0
  70. package/runtime/initialize.js +352 -0
  71. package/runtime/jest.config.js +32 -0
  72. package/runtime/logging/MockLoggingService.js +31 -0
  73. package/runtime/logging/NewRelicLoggingService.js +184 -0
  74. package/runtime/logging/index.ts +9 -0
  75. package/runtime/logging/interface.js +109 -0
  76. package/runtime/logging/types.ts +4 -0
  77. package/runtime/react/AuthenticatedPageRoute.jsx +43 -0
  78. package/runtime/react/CombinedAppProvider.tsx +46 -0
  79. package/runtime/react/CurrentAppContext.tsx +25 -0
  80. package/runtime/react/CurrentAppProvider.tsx +46 -0
  81. package/runtime/react/Divider.tsx +5 -0
  82. package/runtime/react/ErrorBoundary.jsx +47 -0
  83. package/runtime/react/ErrorPage.jsx +72 -0
  84. package/runtime/react/LoginRedirect.jsx +16 -0
  85. package/runtime/react/PageWrap.jsx +24 -0
  86. package/runtime/react/SiteContext.tsx +32 -0
  87. package/runtime/react/SiteProvider.tsx +78 -0
  88. package/runtime/react/hooks.ts +106 -0
  89. package/runtime/react/index.ts +19 -0
  90. package/runtime/routing/index.ts +1 -0
  91. package/runtime/routing/utils.ts +34 -0
  92. package/runtime/scripts/GoogleAnalyticsLoader.ts +59 -0
  93. package/runtime/scripts/index.ts +1 -0
  94. package/runtime/setupTest.js +49 -0
  95. package/runtime/slots/Slot.tsx +32 -0
  96. package/runtime/slots/SlotContext.tsx +8 -0
  97. package/runtime/slots/hooks.ts +35 -0
  98. package/runtime/slots/index.ts +7 -0
  99. package/runtime/slots/layout/DefaultSlotLayout.tsx +9 -0
  100. package/runtime/slots/layout/hooks.ts +65 -0
  101. package/runtime/slots/layout/index.ts +5 -0
  102. package/runtime/slots/layout/types.ts +45 -0
  103. package/runtime/slots/layout/utils.ts +14 -0
  104. package/runtime/slots/types.ts +23 -0
  105. package/runtime/slots/utils.ts +59 -0
  106. package/runtime/slots/widget/WidgetContext.tsx +9 -0
  107. package/runtime/slots/widget/WidgetProvider.tsx +30 -0
  108. package/runtime/slots/widget/hooks.ts +105 -0
  109. package/runtime/slots/widget/iframe/IFrameContentWrapper.messages.tsx +16 -0
  110. package/runtime/slots/widget/iframe/IFrameContentWrapper.tsx +84 -0
  111. package/runtime/slots/widget/iframe/IFrameWidget.tsx +59 -0
  112. package/runtime/slots/widget/iframe/constants.ts +19 -0
  113. package/runtime/slots/widget/iframe/hooks.ts +179 -0
  114. package/runtime/slots/widget/iframe/index.ts +6 -0
  115. package/runtime/slots/widget/iframe/types.ts +7 -0
  116. package/runtime/slots/widget/index.ts +6 -0
  117. package/runtime/slots/widget/types.ts +134 -0
  118. package/runtime/slots/widget/utils.tsx +201 -0
  119. package/runtime/subscriptions.ts +60 -0
  120. package/runtime/testing/index.ts +9 -0
  121. package/runtime/testing/initializeMockApp.ts +81 -0
  122. package/runtime/testing/mockMessages.ts +23 -0
  123. package/runtime/utils.js +178 -0
  124. package/shell/DefaultLayout.tsx +18 -0
  125. package/shell/DefaultMain.tsx +7 -0
  126. package/shell/Logo.tsx +28 -0
  127. package/shell/Shell.messages.ts +61 -0
  128. package/shell/Shell.tsx +18 -0
  129. package/shell/app.scss +149 -0
  130. package/shell/app.ts +24 -0
  131. package/shell/babel.config.js +3 -0
  132. package/shell/dev/devFooter/app.tsx +43 -0
  133. package/shell/dev/devFooter/index.ts +1 -0
  134. package/shell/dev/devHeader/BarContext.tsx +13 -0
  135. package/shell/dev/devHeader/BarLink.tsx +16 -0
  136. package/shell/dev/devHeader/BarProvider.tsx +25 -0
  137. package/shell/dev/devHeader/CoursesLink.tsx +16 -0
  138. package/shell/dev/devHeader/FooContext.tsx +13 -0
  139. package/shell/dev/devHeader/FooLink.tsx +16 -0
  140. package/shell/dev/devHeader/FooProvider.tsx +25 -0
  141. package/shell/dev/devHeader/app.tsx +53 -0
  142. package/shell/dev/devHeader/index.ts +1 -0
  143. package/shell/dev/devHeader/providers.tsx +11 -0
  144. package/shell/dev/devHome/HomePage.tsx +28 -0
  145. package/shell/dev/devHome/app.ts +18 -0
  146. package/shell/dev/devHome/i18n/index.ts +27 -0
  147. package/shell/dev/devHome/index.ts +1 -0
  148. package/shell/dev/devHome/messages.ts +11 -0
  149. package/shell/dev/devUser/app.tsx +24 -0
  150. package/shell/dev/devUser/index.ts +1 -0
  151. package/shell/dev/index.ts +5 -0
  152. package/shell/dev/slotShowcase/HorizontalSlotLayout.tsx +11 -0
  153. package/shell/dev/slotShowcase/LayoutWithOptions.tsx +17 -0
  154. package/shell/dev/slotShowcase/SlotShowcasePage.tsx +66 -0
  155. package/shell/dev/slotShowcase/WidgetWithOptions.tsx +11 -0
  156. package/shell/dev/slotShowcase/app.tsx +373 -0
  157. package/shell/dev/slotShowcase/index.ts +1 -0
  158. package/shell/footer/CenterLinks.tsx +11 -0
  159. package/shell/footer/CopyrightNotice.tsx +36 -0
  160. package/shell/footer/Footer.tsx +34 -0
  161. package/shell/footer/LabeledLinkColumn.tsx +19 -0
  162. package/shell/footer/LanguageMenu.tsx +35 -0
  163. package/shell/footer/LanguageMenuItem.tsx +23 -0
  164. package/shell/footer/LeftLinks.tsx +11 -0
  165. package/shell/footer/LegalNotices.tsx +17 -0
  166. package/shell/footer/PoweredBy.tsx +17 -0
  167. package/shell/footer/RevealLinks.tsx +43 -0
  168. package/shell/footer/RightLinks.tsx +11 -0
  169. package/shell/footer/app.tsx +73 -0
  170. package/shell/footer/data/api.ts +48 -0
  171. package/shell/footer/index.ts +2 -0
  172. package/shell/header/AuthenticatedMenu.tsx +32 -0
  173. package/shell/header/Header.tsx +17 -0
  174. package/shell/header/anonymous-menu/AnonymousMenu.tsx +14 -0
  175. package/shell/header/anonymous-menu/LoginButton.tsx +14 -0
  176. package/shell/header/anonymous-menu/RegisterButton.tsx +15 -0
  177. package/shell/header/app.tsx +142 -0
  178. package/shell/header/desktop/DesktopLayout.tsx +22 -0
  179. package/shell/header/desktop/PrimaryNavLinks.tsx +10 -0
  180. package/shell/header/desktop/SecondaryNavLinks.tsx +10 -0
  181. package/shell/header/index.ts +2 -0
  182. package/shell/header/mobile/MobileLayout.tsx +47 -0
  183. package/shell/header/mobile/MobileNavLinks.tsx +10 -0
  184. package/shell/i18n/index.ts +25 -0
  185. package/shell/index.ts +7 -0
  186. package/shell/jest.config.js +30 -0
  187. package/shell/menus/LinkMenuItem.tsx +64 -0
  188. package/shell/menus/NavDropdownMenuSlot.tsx +29 -0
  189. package/shell/menus/ProfileLinkMenuItem.tsx +33 -0
  190. package/shell/menus/data/utils.ts +19 -0
  191. package/shell/public/index.html +10 -0
  192. package/shell/router/createRouter.ts +17 -0
  193. package/shell/router/getAppRoutes.ts +21 -0
  194. package/shell/setupTest.js +48 -0
  195. package/shell/site.config.dev.tsx +49 -0
  196. package/shell/site.tsx +41 -0
  197. package/test-site/app.d.ts +15 -0
  198. package/test-site/dist/176.436443549ebb858db483.js +2 -0
  199. package/test-site/dist/176.436443549ebb858db483.js.map +1 -0
  200. package/test-site/dist/362.536eff787d2380fe246c.js +2 -0
  201. package/test-site/dist/362.536eff787d2380fe246c.js.map +1 -0
  202. package/test-site/dist/653.486966b108d224551296.js +2 -0
  203. package/test-site/dist/653.486966b108d224551296.js.map +1 -0
  204. package/test-site/dist/74e025d3fe9a7b7f8503054e2563b353.jpg +0 -0
  205. package/test-site/dist/806.323cf6496ad0a7fe73a7.js +3 -0
  206. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.LICENSE.txt +106 -0
  207. package/test-site/dist/806.323cf6496ad0a7fe73a7.js.map +1 -0
  208. package/test-site/dist/95ec738c0b7faac5b5c9126794446bbd.svg +4 -0
  209. package/test-site/dist/app.612058b36c74787759ac.css +61 -0
  210. package/test-site/dist/app.612058b36c74787759ac.css.map +1 -0
  211. package/test-site/dist/app.612058b36c74787759ac.js +2 -0
  212. package/test-site/dist/app.612058b36c74787759ac.js.map +1 -0
  213. package/test-site/dist/cb28cdb1468c915e27e5cec9af64f22f.svg +1 -0
  214. package/test-site/dist/index.html +1 -0
  215. package/test-site/dist/report.html +39 -0
  216. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js +2 -0
  217. package/test-site/dist/runtime.c7aeaf7b967496cb076f.js.map +1 -0
  218. package/test-site/eslint.config.js +12 -0
  219. package/test-site/package-lock.json +19226 -0
  220. package/test-site/package.json +29 -0
  221. package/test-site/public/index.html +10 -0
  222. package/test-site/site.config.build.tsx +27 -0
  223. package/test-site/site.config.dev.tsx +27 -0
  224. package/test-site/src/authenticated-page/AuthenticatedPage.tsx +18 -0
  225. package/test-site/src/authenticated-page/i18n/index.ts +27 -0
  226. package/test-site/src/authenticated-page/index.tsx +28 -0
  227. package/test-site/src/example-page/ExamplePage.tsx +79 -0
  228. package/test-site/src/example-page/Image.tsx +11 -0
  229. package/test-site/src/example-page/ParagonPreview.jsx +66 -0
  230. package/test-site/src/example-page/apple.jpg +0 -0
  231. package/test-site/src/example-page/apple.svg +1 -0
  232. package/test-site/src/example-page/index.ts +16 -0
  233. package/test-site/src/i18n/README.md +3 -0
  234. package/test-site/src/i18n/messages/frontend-app-sample/ar.json +4 -0
  235. package/test-site/src/i18n/messages/frontend-app-sample/eo.json +1 -0
  236. package/test-site/src/i18n/messages/frontend-app-sample/es_419.json +4 -0
  237. package/test-site/src/i18n/messages/frontend-component-emptylangs/ar.json +1 -0
  238. package/test-site/src/i18n/messages/frontend-component-singlelang/ar.json +3 -0
  239. package/test-site/src/iframe-widget/IframeWidget.tsx +14 -0
  240. package/test-site/src/iframe-widget/index.ts +16 -0
  241. package/test-site/src/index.tsx +3 -0
  242. package/test-site/src/messages.js +11 -0
  243. package/test-site/src/site.scss +11 -0
  244. package/test-site/tsconfig.json +14 -0
  245. package/tools/babel/babel.config.js +27 -0
  246. package/tools/babel.config.js +3 -0
  247. package/tools/cli/README.md +29 -0
  248. package/tools/cli/commands/pack.ts +9 -0
  249. package/tools/cli/commands/release.ts +27 -0
  250. package/tools/cli/commands/serve.ts +43 -0
  251. package/tools/cli/intl-imports.ts +274 -0
  252. package/tools/cli/openedx.ts +101 -0
  253. package/tools/cli/transifex-utils.ts +75 -0
  254. package/tools/cli/utils/ensureConfigFilenameOption.ts +40 -0
  255. package/tools/cli/utils/formatter.ts +10 -0
  256. package/tools/cli/utils/getResolvedConfigPath.ts +23 -0
  257. package/tools/cli/utils/prettyPrintTitle.ts +15 -0
  258. package/tools/cli/utils/printUsage.ts +53 -0
  259. package/tools/config-helpers/createConfig.ts +8 -0
  260. package/tools/config-helpers/createLintConfig.ts +14 -0
  261. package/tools/config-helpers/getBaseConfig.ts +11 -0
  262. package/tools/defaultConfigPaths.ts +30 -0
  263. package/tools/dist/babel/babel.config.js +28 -0
  264. package/tools/dist/cli/commands/pack.js +14 -0
  265. package/tools/dist/cli/commands/release.js +28 -0
  266. package/tools/dist/cli/commands/serve.js +44 -0
  267. package/tools/dist/cli/intl-imports.js +233 -0
  268. package/tools/dist/cli/openedx.js +100 -0
  269. package/tools/dist/cli/transifex-utils.js +68 -0
  270. package/tools/dist/cli/utils/ensureConfigFilenameOption.js +42 -0
  271. package/tools/dist/cli/utils/formatter.js +10 -0
  272. package/tools/dist/cli/utils/getResolvedConfigPath.js +28 -0
  273. package/tools/dist/cli/utils/prettyPrintTitle.js +17 -0
  274. package/tools/dist/cli/utils/printUsage.js +48 -0
  275. package/tools/dist/config-helpers/createConfig.js +13 -0
  276. package/tools/dist/config-helpers/createLintConfig.js +16 -0
  277. package/tools/dist/config-helpers/getBaseConfig.js +12 -0
  278. package/tools/dist/defaultConfigPaths.js +35 -0
  279. package/tools/dist/eslint/base.eslint.config.js +113 -0
  280. package/tools/dist/eslint.config.js +11 -0
  281. package/tools/dist/index.js +12 -0
  282. package/tools/dist/jest/jest.config.js +30 -0
  283. package/tools/dist/jest.config.js +20 -0
  284. package/tools/dist/types.js +25 -0
  285. package/tools/dist/typescript/tsconfig.json +32 -0
  286. package/tools/dist/webpack/common-config/all/getCodeRules.js +52 -0
  287. package/tools/dist/webpack/common-config/all/getFileLoaderRules.js +26 -0
  288. package/tools/dist/webpack/common-config/all/getIgnoreWarnings.js +14 -0
  289. package/tools/dist/webpack/common-config/all/getImageMinimizer.js +25 -0
  290. package/tools/dist/webpack/common-config/all/getStylesheetRule.js +112 -0
  291. package/tools/dist/webpack/common-config/dev/getDevServer.js +38 -0
  292. package/tools/dist/webpack/common-config/index.js +18 -0
  293. package/tools/dist/webpack/common-config/site/getHtmlWebpackPlugin.js +16 -0
  294. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.js +91 -0
  295. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/index.js +7 -0
  296. package/tools/dist/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +3 -0
  297. package/tools/dist/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.js +108 -0
  298. package/tools/dist/webpack/plugins/paragon-webpack-plugin/index.js +7 -0
  299. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.js +64 -0
  300. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.js +53 -0
  301. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/index.js +9 -0
  302. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.js +114 -0
  303. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.js +146 -0
  304. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.js +126 -0
  305. package/tools/dist/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.js +57 -0
  306. package/tools/dist/webpack/types.js +2 -0
  307. package/tools/dist/webpack/utils/getLocalAliases.js +65 -0
  308. package/tools/dist/webpack/utils/getPublicPath.js +6 -0
  309. package/tools/dist/webpack/utils/getResolvedSiteConfigPath.js +32 -0
  310. package/tools/dist/webpack/utils/paragonUtils.js +138 -0
  311. package/tools/dist/webpack/webpack.config.build.js +80 -0
  312. package/tools/dist/webpack/webpack.config.dev.js +76 -0
  313. package/tools/dist/webpack/webpack.config.dev.shell.js +110 -0
  314. package/tools/eslint/base.eslint.config.js +124 -0
  315. package/tools/eslint/modules.d.ts +5 -0
  316. package/tools/eslint.config.js +15 -0
  317. package/tools/index.ts +3 -0
  318. package/tools/jest/jest.config.js +30 -0
  319. package/tools/jest.config.js +19 -0
  320. package/tools/tsconfig.json +24 -0
  321. package/tools/types.ts +21 -0
  322. package/tools/typescript/tsconfig.json +32 -0
  323. package/tools/webpack/common-config/README.md +15 -0
  324. package/tools/webpack/common-config/all/getCodeRules.ts +51 -0
  325. package/tools/webpack/common-config/all/getFileLoaderRules.ts +23 -0
  326. package/tools/webpack/common-config/all/getIgnoreWarnings.ts +13 -0
  327. package/tools/webpack/common-config/all/getImageMinimizer.ts +26 -0
  328. package/tools/webpack/common-config/all/getStylesheetRule.ts +111 -0
  329. package/tools/webpack/common-config/dev/getDevServer.ts +35 -0
  330. package/tools/webpack/common-config/index.ts +6 -0
  331. package/tools/webpack/common-config/site/getHtmlWebpackPlugin.ts +11 -0
  332. package/tools/webpack/modules.d.ts +6 -0
  333. package/tools/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.ts +102 -0
  334. package/tools/webpack/plugins/html-webpack-new-relic-plugin/LICENSE +21 -0
  335. package/tools/webpack/plugins/html-webpack-new-relic-plugin/README.md +7 -0
  336. package/tools/webpack/plugins/html-webpack-new-relic-plugin/index.js +3 -0
  337. package/tools/webpack/plugins/html-webpack-new-relic-plugin/test/fixtures/entry.js +1 -0
  338. package/tools/webpack/plugins/paragon-webpack-plugin/ParagonWebpackPlugin.ts +134 -0
  339. package/tools/webpack/plugins/paragon-webpack-plugin/index.ts +3 -0
  340. package/tools/webpack/plugins/paragon-webpack-plugin/utils/assetUtils.ts +71 -0
  341. package/tools/webpack/plugins/paragon-webpack-plugin/utils/htmlUtils.ts +72 -0
  342. package/tools/webpack/plugins/paragon-webpack-plugin/utils/index.ts +6 -0
  343. package/tools/webpack/plugins/paragon-webpack-plugin/utils/paragonStylesheetUtils.ts +131 -0
  344. package/tools/webpack/plugins/paragon-webpack-plugin/utils/scriptUtils.ts +144 -0
  345. package/tools/webpack/plugins/paragon-webpack-plugin/utils/stylesheetUtils.ts +106 -0
  346. package/tools/webpack/plugins/paragon-webpack-plugin/utils/tagUtils.ts +54 -0
  347. package/tools/webpack/types.ts +69 -0
  348. package/tools/webpack/utils/getLocalAliases.ts +65 -0
  349. package/tools/webpack/utils/getPublicPath.ts +3 -0
  350. package/tools/webpack/utils/getResolvedSiteConfigPath.ts +28 -0
  351. package/tools/webpack/utils/paragonUtils.ts +152 -0
  352. package/tools/webpack/webpack.config.build.ts +93 -0
  353. package/tools/webpack/webpack.config.dev.shell.ts +122 -0
  354. package/tools/webpack/webpack.config.dev.ts +90 -0
  355. package/tsconfig.json +23 -0
  356. package/types.ts +99 -0
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * This Babel configuration file is for Jest. The Webpack build does not use Babel.
4
+ */
5
+ module.exports = {
6
+ presets: [
7
+ [
8
+ require.resolve('@babel/preset-env'), {
9
+ targets: { node: 'current' },
10
+ },
11
+ ],
12
+ [
13
+ require.resolve('@babel/preset-react'), {
14
+ runtime: 'automatic',
15
+ },
16
+ ],
17
+ require.resolve('@babel/preset-typescript'),
18
+ ],
19
+ env: {
20
+ i18n: {
21
+ plugins: [
22
+ [
23
+ 'formatjs',
24
+ ],
25
+ ],
26
+ },
27
+ },
28
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = pack;
7
+ const child_process_1 = require("child_process");
8
+ const path_1 = __importDefault(require("path"));
9
+ function pack() {
10
+ const destination = process.argv[2];
11
+ (0, child_process_1.execSync)('npm run release', { stdio: 'inherit' });
12
+ const { filename } = JSON.parse((0, child_process_1.execSync)('npm pack --json').toString())[0];
13
+ (0, child_process_1.execSync)(`npm --prefix ../${destination} install ${path_1.default.resolve(process.cwd(), filename)}`, { stdio: 'inherit' });
14
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = release;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const child_process_1 = require("child_process");
9
+ const fs_1 = require("fs");
10
+ const path_1 = __importDefault(require("path"));
11
+ function release() {
12
+ const tsconfigPath = path_1.default.resolve(process.cwd(), './tsconfig.build.json');
13
+ if (!(0, fs_1.existsSync)(tsconfigPath)) {
14
+ console.error(chalk_1.default.red('openedx release: the library must include a tsconfig.build.json. Aborting.'));
15
+ process.exit(1);
16
+ }
17
+ // Clean up our dist folder.
18
+ (0, fs_1.rmSync)(path_1.default.resolve(process.cwd(), 'dist'), { recursive: true, force: true });
19
+ (0, child_process_1.execSync)(`tsc --project ${path_1.default.resolve(process.cwd(), './tsconfig.build.json')}`, { stdio: 'inherit' });
20
+ // Copy all non JS/TS files from src into dist. This is so imports of our assets still work.
21
+ (0, child_process_1.execSync)(`rsync -aR src/**/* --exclude='*.tsx' --exclude='*.ts' --exclude='*.js' --exclude='*.jsx' dist/`);
22
+ // The above rsync command will put the files in dist/src - move them up a folder into dist,
23
+ // merging them into the compiled code there, and then delete dist/src.
24
+ if ((0, fs_1.existsSync)(path_1.default.resolve(process.cwd(), 'dist/src'))) {
25
+ (0, child_process_1.execSync)('cp -R dist/src/* dist');
26
+ (0, child_process_1.execSync)('rm -rf dist/src');
27
+ }
28
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const chalk_1 = __importDefault(require("chalk"));
7
+ const compression_1 = __importDefault(require("compression"));
8
+ const express_1 = __importDefault(require("express"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ function isDirectoryEmpty(directoryPath) {
12
+ try {
13
+ const files = fs_1.default.readdirSync(directoryPath);
14
+ return files.length === 0;
15
+ }
16
+ catch (error) {
17
+ if (error.code === 'ENOENT') {
18
+ // Directory does not exist, so treat it as empty.
19
+ return true;
20
+ }
21
+ throw error; // Throw the error for other cases
22
+ }
23
+ }
24
+ const buildPath = path_1.default.join(process.cwd(), 'dist');
25
+ const buildPathIndex = path_1.default.join(buildPath, 'index.html');
26
+ if (isDirectoryEmpty(buildPath)) {
27
+ const formattedBuildCmd = chalk_1.default.bold.redBright('``npm run build``');
28
+ console.log(chalk_1.default.bold.red(`ERROR: No build found. Please run ${formattedBuildCmd} first.`));
29
+ }
30
+ else {
31
+ const app = (0, express_1.default)();
32
+ app.use((0, compression_1.default)());
33
+ app.use(express_1.default.static(buildPath));
34
+ app.use('*', (req, res) => {
35
+ res.sendFile(buildPathIndex);
36
+ });
37
+ // Fallback to standard example port if no PORT config is set.
38
+ const PORT = process.env.PORT ?? 8080;
39
+ app.listen(PORT, () => {
40
+ const formattedServedFile = chalk_1.default.bold.cyanBright(buildPathIndex);
41
+ const formattedPort = chalk_1.default.bold.cyanBright(PORT);
42
+ console.log(chalk_1.default.greenBright(`Serving ${formattedServedFile} on port ${formattedPort}...`));
43
+ });
44
+ }
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.main = main;
8
+ const scriptHelpDocument = `
9
+ NAME
10
+ intl-imports.js — Script to generate the src/i18n/index.js file that exports messages from all the languages for Micro-frontends.
11
+
12
+ SYNOPSIS
13
+ intl-imports.js [DIRECTORY ...]
14
+
15
+ DESCRIPTION
16
+ This script is intended to run after 'atlas' has pulled the files.
17
+
18
+ This expects to run inside a Micro-frontend root directory with the following structure:
19
+
20
+ frontend-app-learning $ tree src/i18n/
21
+ src/i18n/
22
+ ├── index.js
23
+ └── messages
24
+ ├── frontend-app-example
25
+ │ ├── ar.json
26
+ │ ├── es_419.json
27
+ │ └── zh_CN.json
28
+ ├── frontend-component-footer
29
+ │ ├── ar.json
30
+ │ ├── es_419.json
31
+ │ └── zh_CN.json
32
+ └── frontend-component-header (empty directory)
33
+
34
+
35
+
36
+ With the structure above it's expected to run with the following command in Makefile:
37
+
38
+
39
+ $ node_modules/.bin/intl-imports.js frontend-component-footer frontend-component-header frontend-app-example
40
+
41
+
42
+ It will generate two type of files:
43
+
44
+ - Main src/i18n/index.js which overrides the Micro-frontend provided with a sample output of:
45
+
46
+ """
47
+ import messagesFromFrontendComponentFooter from './messages/frontend-component-footer';
48
+ // Skipped import due to missing './messages/frontend-component-footer/index.js' likely due to empty translations.
49
+ import messagesFromFrontendAppExample from './messages/frontend-app-example';
50
+
51
+ export default [
52
+ messagesFromFrontendComponentFooter,
53
+ messagesFromFrontendAppExample,
54
+ ];
55
+ """
56
+
57
+ - Each sub-directory has src/i18n/messages/frontend-component-header/index.js which is imported by the main file.:
58
+
59
+ """
60
+ import messagesOfArLanguage from './ar.json';
61
+ import messagesOfDeLanguage from './de.json';
62
+ import messagesOfEs419Language from './es_419.json';
63
+ export default {
64
+ 'ar': messagesOfArLanguage,
65
+ 'de': messagesOfDeLanguage,
66
+ 'es-419': messagesOfEs419Language,
67
+ };
68
+ """
69
+ `;
70
+ const fs_1 = __importDefault(require("fs"));
71
+ const lodash_camelcase_1 = __importDefault(require("lodash.camelcase"));
72
+ const path_1 = __importDefault(require("path"));
73
+ const loggingPrefix = path_1.default.basename(`${__filename}`); // the name of this JS file
74
+ // Header note for generated src/i18n/index.js file
75
+ const filesCodeGeneratorNoticeHeader = `// This file is generated by the openedx/frontend-base's "intl-import.js" script.
76
+ //
77
+ // Refer to the i18n documents in https://docs.openedx.org/en/latest/developers/references/i18n.html to update
78
+ // the file and use the Micro-frontend i18n pattern in new repositories.
79
+ //
80
+ `;
81
+ /**
82
+ * Create frontend-app-example/index.js file with proper imports.
83
+ *
84
+ * @param directory - a directory name containing .json files from Transifex e.g. "frontend-app-example".
85
+ * @param log - Mockable process.stdout.write
86
+ * @param writeFileSync - Mockable fs.writeFileSync
87
+ * @param i18nDir - Path to `src/i18n` directory
88
+ *
89
+ * @return object - An object containing directory name and whether its "index.js" file was successfully written.
90
+ */
91
+ function generateSubdirectoryMessageFile({ directory, log, writeFileSync, i18nDir, }) {
92
+ const importLines = [];
93
+ const messagesLines = [];
94
+ const counter = { nonEmptyLanguages: 0 };
95
+ const messagesDir = `${i18nDir}/messages`; // The directory of Micro-frontend i18n messages
96
+ try {
97
+ const files = fs_1.default.readdirSync(`${messagesDir}/${directory}`, { withFileTypes: true });
98
+ files.sort(); // Sorting ensures a consistent generated `index.js` order of imports cross-platforms.
99
+ const jsonFiles = files.filter(file => file.isFile() && file.name.endsWith('.json'));
100
+ if (!jsonFiles.length) {
101
+ log(`${loggingPrefix}: Not creating '${directory}/index.js' because no .json translation files were found.\n`);
102
+ return {
103
+ directory,
104
+ isWritten: false,
105
+ };
106
+ }
107
+ jsonFiles.forEach((file) => {
108
+ const filename = file.name;
109
+ // Gets `fr_CA` from `fr_CA.json`
110
+ const languageCode = filename.replace(/\.json$/, '');
111
+ // React-friendly language code fr_CA --> fr-ca
112
+ const reactIntlLanguageCode = languageCode.toLowerCase().replace(/_/g, '-');
113
+ // camelCase variable name
114
+ const messagesCamelCaseVar = (0, lodash_camelcase_1.default)(`messages_Of_${languageCode}_Language`);
115
+ const filePath = `${messagesDir}/${directory}/${filename}`;
116
+ try {
117
+ const entries = JSON.parse(fs_1.default.readFileSync(filePath, { encoding: 'utf8' }));
118
+ if (!Object.keys(entries).length) {
119
+ importLines.push(`// Note: Skipped empty '${filename}' messages file.`);
120
+ return; // Skip the language
121
+ }
122
+ }
123
+ catch (e) {
124
+ importLines.push(`// Error: unable to parse '${filename}' messages file.`);
125
+ log(`${loggingPrefix}: NOTICE: Skipping '${directory}/${filename}' due to error: ${e}.\n`);
126
+ return; // Skip the language
127
+ }
128
+ counter.nonEmptyLanguages += 1;
129
+ importLines.push(`import ${messagesCamelCaseVar} from './${filename}';`);
130
+ messagesLines.splice(1, 0, ` '${reactIntlLanguageCode}': ${messagesCamelCaseVar},`);
131
+ });
132
+ if (counter.nonEmptyLanguages) {
133
+ // See the help message above for sample output.
134
+ const messagesFileContent = [
135
+ filesCodeGeneratorNoticeHeader,
136
+ importLines.join('\n'),
137
+ '\nexport default {',
138
+ messagesLines.join('\n'),
139
+ '};\n',
140
+ ].join('\n');
141
+ writeFileSync(`${messagesDir}/${directory}/index.js`, messagesFileContent);
142
+ return {
143
+ directory,
144
+ isWritten: true,
145
+ };
146
+ }
147
+ log(`${loggingPrefix}: Skipping '${directory}' because no languages were found.\n`);
148
+ }
149
+ catch (e) {
150
+ log(`${loggingPrefix}: NOTICE: Skipping '${directory}' due to error: ${e}.\n`);
151
+ }
152
+ return {
153
+ directory,
154
+ isWritten: false,
155
+ };
156
+ }
157
+ /**
158
+ * Create main `src/i18n/index.js` messages import file.
159
+ *
160
+ *
161
+ * @param processedDirectories - List of directories with a boolean flag whether its "index.js" file is written
162
+ * The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]"
163
+ * @param log - Mockable process.stdout.write
164
+ * @param writeFileSync - Mockable fs.writeFileSync
165
+ * @param i18nDir` - Path to `src/i18n` directory
166
+ */
167
+ function generateMainMessagesFile({ processedDirectories, log, writeFileSync, i18nDir, }) {
168
+ const importLines = [];
169
+ const exportLines = [];
170
+ processedDirectories.forEach(processedDirectory => {
171
+ const { directory, isWritten } = processedDirectory;
172
+ if (isWritten) {
173
+ const moduleCamelCaseVariableName = (0, lodash_camelcase_1.default)(`messages_from_${directory}`);
174
+ importLines.push(`import ${moduleCamelCaseVariableName} from './messages/${directory}';`);
175
+ exportLines.push(` ${moduleCamelCaseVariableName},`);
176
+ }
177
+ else {
178
+ const skipMessage = `Skipped import due to missing '${directory}/index.js' likely due to empty translations.`;
179
+ importLines.push(`// ${skipMessage}.`);
180
+ log(`${loggingPrefix}: ${skipMessage}\n`);
181
+ }
182
+ });
183
+ // See the help message above for sample output.
184
+ const indexFileContent = [
185
+ filesCodeGeneratorNoticeHeader,
186
+ importLines.join('\n'),
187
+ '\nexport default [',
188
+ exportLines.join('\n'),
189
+ '];\n',
190
+ ].join('\n');
191
+ writeFileSync(`${i18nDir}/index.js`, indexFileContent);
192
+ }
193
+ /*
194
+ * Main function of the file.
195
+ */
196
+ function main({ directories, log, writeFileSync, pwd, }) {
197
+ const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory
198
+ if (directories.includes('--help') || directories.includes('-h')) {
199
+ log(scriptHelpDocument);
200
+ }
201
+ else if (!directories.length) {
202
+ log(scriptHelpDocument);
203
+ log(`${loggingPrefix}: Error: A list of directories is required.\n`);
204
+ }
205
+ else if (!fs_1.default.existsSync(i18nDir) || !fs_1.default.lstatSync(i18nDir).isDirectory()) {
206
+ log(scriptHelpDocument);
207
+ log(`${loggingPrefix}: Error: src/i18n directory was not found.\n`);
208
+ }
209
+ else {
210
+ // If we're here, we know that directories is an array, so cast it as one.
211
+ const processedDirectories = directories.map((directory) => generateSubdirectoryMessageFile({
212
+ directory,
213
+ log,
214
+ writeFileSync,
215
+ i18nDir,
216
+ }));
217
+ generateMainMessagesFile({
218
+ processedDirectories,
219
+ log,
220
+ writeFileSync,
221
+ i18nDir,
222
+ });
223
+ }
224
+ }
225
+ if (require.main === module) {
226
+ // Run the main() function if called from the command line.
227
+ main({
228
+ directories: process.argv.slice(2),
229
+ log: text => process.stdout.write(text),
230
+ writeFileSync: fs_1.default.writeFileSync,
231
+ pwd: process.env.PWD ?? '.',
232
+ });
233
+ }
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_1 = require("fs");
9
+ const path_1 = __importDefault(require("path"));
10
+ const types_1 = require("../types");
11
+ const pack_1 = __importDefault(require("./commands/pack"));
12
+ const release_1 = __importDefault(require("./commands/release"));
13
+ const ensureConfigFilenameOption_1 = require("./utils/ensureConfigFilenameOption");
14
+ const prettyPrintTitle_1 = __importDefault(require("./utils/prettyPrintTitle"));
15
+ const printUsage_1 = __importDefault(require("./utils/printUsage"));
16
+ // commandName is the third argument after node and 'openedx'
17
+ const commandName = process.argv[2];
18
+ // remove 'openedx' from process.argv to allow subcommands to read options properly
19
+ process.argv.splice(1, 1);
20
+ let version;
21
+ if ((0, fs_1.existsSync)(path_1.default.resolve(__dirname, '../../package.json'))) {
22
+ version = require('../../package.json').version;
23
+ }
24
+ else if ((0, fs_1.existsSync)(path_1.default.resolve(__dirname, '../../../package.json'))) {
25
+ version = require('../../../package.json').version;
26
+ }
27
+ (0, prettyPrintTitle_1.default)(`Open edX CLI v${version}`);
28
+ switch (commandName) {
29
+ case types_1.CommandTypes.RELEASE:
30
+ (0, release_1.default)();
31
+ break;
32
+ case types_1.CommandTypes.PACK:
33
+ if (process.argv[2] === undefined) {
34
+ console.log(chalk_1.default.red(`${chalk_1.default.bold.red(commandName)} command usage: specify a peer folder where the command should install the package:
35
+
36
+ npm run pack my-project`));
37
+ process.exit(1);
38
+ }
39
+ (0, pack_1.default)();
40
+ break;
41
+ case types_1.CommandTypes.LINT:
42
+ (0, ensureConfigFilenameOption_1.ensureConfigFilenameOption)(types_1.ConfigTypes.LINT, ['-c', '--config']);
43
+ require('.bin/eslint');
44
+ break;
45
+ case types_1.CommandTypes.TEST:
46
+ (0, ensureConfigFilenameOption_1.ensureConfigFilenameOption)(types_1.ConfigTypes.TEST, ['-c', '--config']);
47
+ require('jest/bin/jest');
48
+ break;
49
+ case types_1.CommandTypes.BUILD:
50
+ (0, ensureConfigFilenameOption_1.ensureConfigFilenameOption)(types_1.ConfigTypes.WEBPACK_BUILD, ['-c', '--config']);
51
+ require('webpack/bin/webpack');
52
+ break;
53
+ case types_1.CommandTypes.DEV:
54
+ (0, ensureConfigFilenameOption_1.ensureConfigFilenameOption)(types_1.ConfigTypes.WEBPACK_DEV, ['-c', '--config']);
55
+ require('webpack-dev-server/bin/webpack-dev-server');
56
+ break;
57
+ case types_1.CommandTypes.DEV_SHELL:
58
+ (0, ensureConfigFilenameOption_1.ensureConfigFilenameOption)(types_1.ConfigTypes.WEBPACK_DEV_SHELL, ['-c', '--config']);
59
+ require('webpack-dev-server/bin/webpack-dev-server');
60
+ break;
61
+ case types_1.CommandTypes.FORMAT_JS: {
62
+ /* The include option is used to specify which additional source folders to extract messages from.
63
+ * To extract more messages on other source folders use: --include=plugins --include=plugins2
64
+ * The intention use case is to allow extraction from the 'plugins' directory on 'frontend-app-authoring'.
65
+ * That plugins folder were kept outside the src folder to ensure they remain independent and
66
+ * can function without relying on the MFE environment's special features.
67
+ * This approach allows them to be packaged separately as NPM packages. */
68
+ const additionalSrcFolders = [];
69
+ process.argv.forEach((val, index) => {
70
+ if (val.startsWith('--include=')) {
71
+ additionalSrcFolders.push(val.split('=')[1]);
72
+ process.argv.splice(index, 1);
73
+ }
74
+ });
75
+ const srcFolders = ['src'].concat(additionalSrcFolders);
76
+ let srcFoldersString = srcFolders.join(',');
77
+ if (srcFolders.length > 1) {
78
+ srcFoldersString = `{${srcFoldersString}}`;
79
+ }
80
+ process.argv = process.argv.concat([
81
+ '--format', 'node_modules/@openedx/frontend-base/dist/tools/cli/utils/formatter.js',
82
+ '--ignore', `${srcFoldersString}/**/*.json`,
83
+ '--ignore', `${srcFoldersString}/**/*.d.ts`,
84
+ '--out-file', './temp/formatjs/Default.messages.json',
85
+ '--', `${srcFoldersString}/**/*.{j,t}s*`,
86
+ ]);
87
+ require('@formatjs/cli/bin/formatjs');
88
+ break;
89
+ }
90
+ case types_1.CommandTypes.SERVE:
91
+ require('./commands/serve');
92
+ break;
93
+ case types_1.CommandTypes.HELP:
94
+ (0, printUsage_1.default)();
95
+ break;
96
+ default:
97
+ console.log(`The command ${chalk_1.default.bold(commandName)} doesn't exist.`);
98
+ console.log('');
99
+ (0, printUsage_1.default)();
100
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const glob_1 = __importDefault(require("glob"));
9
+ const path_1 = __importDefault(require("path"));
10
+ /*
11
+ * See the Makefile for how the required hash file is downloaded from Transifex.
12
+ */
13
+ /*
14
+ * Expected input: a directory, possibly containing subdirectories, with .json files. Each .json
15
+ * file is an array of translation triplets (id, description, defaultMessage).
16
+ *
17
+ *
18
+ */
19
+ function gatherJson(dir) {
20
+ const ret = [];
21
+ const files = glob_1.default.sync(`${dir}/**/*.json`);
22
+ files.forEach((filename) => {
23
+ const messages = JSON.parse(fs_1.default.readFileSync(filename, { encoding: 'utf8' }));
24
+ ret.push(...messages);
25
+ });
26
+ return ret;
27
+ }
28
+ // the hash file returns ids whose periods are "escaped" (sort of), like this:
29
+ // "key": "profile\\.sociallinks\\.social\\.links"
30
+ // so our regular messageIds won't match them out of the box
31
+ function escapeDots(messageId) {
32
+ return messageId.replace(/\./g, '\\.');
33
+ }
34
+ const jsonDir = process.argv[2];
35
+ const messageObjects = gatherJson(jsonDir);
36
+ if (messageObjects.length === 0) {
37
+ process.exitCode = 1;
38
+ throw new Error('Found no messages');
39
+ }
40
+ if (process.argv[3] === '--comments') { // prepare to handle the translator notes
41
+ const loggingPrefix = path_1.default.basename(`${__filename}`); // the name of this JS file
42
+ const bashScriptsPath = (process.argv[4] && process.argv[4] === '--v3-scripts-path'
43
+ ? './node_modules/@edx/reactifex/bash_scripts'
44
+ : './node_modules/reactifex/bash_scripts');
45
+ const hashFile = `${bashScriptsPath}/hashmap.json`;
46
+ process.stdout.write(`${loggingPrefix}: reading hash file ${hashFile}\n`);
47
+ const messageInfo = JSON.parse(fs_1.default.readFileSync(hashFile, { encoding: 'utf8' }));
48
+ const outputFile = `${bashScriptsPath}/hashed_data.txt`;
49
+ process.stdout.write(`${loggingPrefix}: writing to output file ${outputFile}\n`);
50
+ fs_1.default.writeFileSync(outputFile, '');
51
+ messageObjects.forEach((message) => {
52
+ const transifexFormatId = escapeDots(message.id);
53
+ const info = messageInfo.find((mi) => mi.key === transifexFormatId);
54
+ if (info) {
55
+ fs_1.default.appendFileSync(outputFile, `${info.string_hash}|${message.description}\n`);
56
+ }
57
+ else {
58
+ process.stdout.write(`${loggingPrefix}: string ${message.id} does not yet exist on transifex!\n`);
59
+ }
60
+ });
61
+ }
62
+ else {
63
+ const output = {};
64
+ messageObjects.forEach((message) => {
65
+ output[message.id] = message.defaultMessage;
66
+ });
67
+ fs_1.default.writeFileSync(process.argv[3], JSON.stringify(output, null, 2));
68
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ensureConfigFilenameOption = ensureConfigFilenameOption;
7
+ const path_1 = __importDefault(require("path"));
8
+ const getResolvedConfigPath_1 = __importDefault(require("./getResolvedConfigPath"));
9
+ function ensureConfigFilenameOption(configType, keys) {
10
+ let configFileName = null;
11
+ let fileNameIndex = null;
12
+ for (const key of keys) {
13
+ const index = process.argv.indexOf(key);
14
+ if (index !== -1) {
15
+ fileNameIndex = index + 1;
16
+ if (process.argv.length > fileNameIndex) {
17
+ configFileName = process.argv[fileNameIndex];
18
+ }
19
+ else {
20
+ console.error(`You must specify a config filename as the next argument when using the ${key} flag. Aborting.`);
21
+ process.exit(1);
22
+ }
23
+ }
24
+ }
25
+ let customConfigFilePath = null;
26
+ if (configFileName !== null) {
27
+ customConfigFilePath = path_1.default.resolve(process.cwd(), configFileName);
28
+ }
29
+ const resolvedConfigPath = (0, getResolvedConfigPath_1.default)(customConfigFilePath, configType);
30
+ if (resolvedConfigPath === null) {
31
+ console.error(`No valid config file was found. Did you forget to create a config file? You may specify a custom path with the ${keys.join(' or ')} flag(s).`);
32
+ process.exit(1);
33
+ }
34
+ // If there wasn't a config flag on the command line, add one.
35
+ if (fileNameIndex === null) {
36
+ process.argv.push(keys[0]);
37
+ process.argv.push(resolvedConfigPath);
38
+ }
39
+ else {
40
+ process.argv[fileNameIndex] = resolvedConfigPath;
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.format = (messages) => {
4
+ const results = Object.entries(messages).map(([id, message]) => ({
5
+ id,
6
+ defaultMessage: message.defaultMessage,
7
+ description: message.description,
8
+ }));
9
+ return results;
10
+ };
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getResolvedConfigPath;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const defaultConfigPaths_1 = require("../../defaultConfigPaths");
9
+ function getResolvedConfigPath(customConfigPath, configType) {
10
+ const configPaths = defaultConfigPaths_1.defaultConfigPaths[configType];
11
+ if (customConfigPath !== null) {
12
+ if (fs_1.default.existsSync(customConfigPath)) {
13
+ return customConfigPath;
14
+ }
15
+ else {
16
+ console.error(`The custom config file at ${customConfigPath} does not exist. Aborting.`);
17
+ return null;
18
+ }
19
+ }
20
+ else {
21
+ for (const configPath of configPaths) {
22
+ if (fs_1.default.existsSync(configPath)) {
23
+ return configPath;
24
+ }
25
+ }
26
+ }
27
+ return null;
28
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = prettyPrintTitle;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const gradient_string_1 = __importDefault(require("gradient-string"));
9
+ function prettyPrintTitle(title) {
10
+ const openedxGradient = (0, gradient_string_1.default)(['#B82669', '#22358C']);
11
+ const borderedTitle = `█ ${title} █`;
12
+ const whitespace = Array.from({ length: borderedTitle.length }, () => '█').join('');
13
+ console.log(chalk_1.default.bgWhite(openedxGradient(whitespace)));
14
+ console.log(chalk_1.default.bold.bgWhite(openedxGradient(borderedTitle)));
15
+ console.log(chalk_1.default.bgWhite(openedxGradient(whitespace)));
16
+ console.log('');
17
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = printUsage;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ function printUsage() {
9
+ console.log('CLI Usage:\n');
10
+ console.group();
11
+ console.log('openedx <command> <options>\n');
12
+ console.groupEnd();
13
+ console.log('Commands:\n');
14
+ console.group();
15
+ console.log(`${chalk_1.default.bold('release')}\n`);
16
+ console.group();
17
+ console.log(`Compile source code for release as a library. Compiled code is put into the dist folder.\n`);
18
+ console.groupEnd();
19
+ console.log(`${chalk_1.default.bold('pack')} <peer folder>\n`);
20
+ console.group();
21
+ console.log(`Package the dist folder as an NPM-compatible .tgz file suitable for use with npm install, then install it in the specified peer folder. The folder is assumed to be a peer of this repository, do not include a path.\n`);
22
+ console.groupEnd();
23
+ console.log(`${chalk_1.default.bold('lint')} <eslint options>\n`);
24
+ console.group();
25
+ console.log(`Runs ESLint on the source code. Requires an ${chalk_1.default.bold('eslint.config.js')} file.\n`);
26
+ console.groupEnd();
27
+ console.log(`${chalk_1.default.bold('test')} <jest options>\n`);
28
+ console.group();
29
+ console.log(`Runs Jest on the source code test suite. Requires a ${chalk_1.default.bold('jest.config.js')} file.\n`);
30
+ console.groupEnd();
31
+ console.log(`${chalk_1.default.bold('build')}\n`);
32
+ console.group();
33
+ console.log(`Compiles the source code for deployment as a frontend site. Requires a ${chalk_1.default.bold('site.config.build.tsx')} file.\n`);
34
+ console.groupEnd();
35
+ console.log(`${chalk_1.default.bold('dev')}\n`);
36
+ console.group();
37
+ console.log(`Compiles the source code and serves it in Webpack dev server as a frontend site. Requires a ${chalk_1.default.bold('site.config.dev.tsx')} file.\n`);
38
+ console.groupEnd();
39
+ console.log(`${chalk_1.default.bold('formatjs')}\n`);
40
+ console.group();
41
+ console.log(`Runs formatjs on the source code to extract internationalization messages.\n`);
42
+ console.groupEnd();
43
+ console.log(`${chalk_1.default.bold('serve')}\n`);
44
+ console.group();
45
+ console.log(`Serves the dist folder with an express server. Used to locally test production assets.\n`);
46
+ console.groupEnd();
47
+ console.groupEnd();
48
+ }