@cedarjs/cli 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +706 -0
  3. package/dist/commands/build.js +54 -0
  4. package/dist/commands/buildHandler.js +134 -0
  5. package/dist/commands/check.js +28 -0
  6. package/dist/commands/console.js +13 -0
  7. package/dist/commands/consoleHandler.js +68 -0
  8. package/dist/commands/deploy/baremetal/SshExecutor.js +41 -0
  9. package/dist/commands/deploy/baremetal/baremetalHandler.js +558 -0
  10. package/dist/commands/deploy/baremetal.js +89 -0
  11. package/dist/commands/deploy/flightcontrol.js +40 -0
  12. package/dist/commands/deploy/flightcontrolHandler.js +58 -0
  13. package/dist/commands/deploy/helpers/deployBuilder.js +25 -0
  14. package/dist/commands/deploy/helpers/deployHandler.js +31 -0
  15. package/dist/commands/deploy/netlify.js +21 -0
  16. package/dist/commands/deploy/packing/nft.js +61 -0
  17. package/dist/commands/deploy/render.js +37 -0
  18. package/dist/commands/deploy/renderHandler.js +70 -0
  19. package/dist/commands/deploy/serverless.js +51 -0
  20. package/dist/commands/deploy/serverlessHandler.js +211 -0
  21. package/dist/commands/deploy/vercel.js +21 -0
  22. package/dist/commands/deploy.js +21 -0
  23. package/dist/commands/destroy/cell/cell.js +12 -0
  24. package/dist/commands/destroy/cell/cellHandler.js +10 -0
  25. package/dist/commands/destroy/component/component.js +15 -0
  26. package/dist/commands/destroy/component/componentHandler.js +10 -0
  27. package/dist/commands/destroy/directive/directive.js +14 -0
  28. package/dist/commands/destroy/directive/directiveHandler.js +12 -0
  29. package/dist/commands/destroy/function/function.js +20 -0
  30. package/dist/commands/destroy/function/functionHandler.js +10 -0
  31. package/dist/commands/destroy/handlerHelpers.js +34 -0
  32. package/dist/commands/destroy/helpers.js +22 -0
  33. package/dist/commands/destroy/layout/layout.js +12 -0
  34. package/dist/commands/destroy/layout/layoutHandler.js +10 -0
  35. package/dist/commands/destroy/page/page.js +20 -0
  36. package/dist/commands/destroy/page/pageHandler.js +51 -0
  37. package/dist/commands/destroy/scaffold/scaffold.js +16 -0
  38. package/dist/commands/destroy/scaffold/scaffoldHandler.js +105 -0
  39. package/dist/commands/destroy/sdl/sdl.js +16 -0
  40. package/dist/commands/destroy/sdl/sdlHandler.js +33 -0
  41. package/dist/commands/destroy/service/service.js +10 -0
  42. package/dist/commands/destroy/service/serviceHandler.js +17 -0
  43. package/dist/commands/destroy.js +25 -0
  44. package/dist/commands/dev.js +47 -0
  45. package/dist/commands/devHandler.js +202 -0
  46. package/dist/commands/exec.js +38 -0
  47. package/dist/commands/execHandler.js +180 -0
  48. package/dist/commands/experimental/setupInngest.js +28 -0
  49. package/dist/commands/experimental/setupInngestHandler.js +46 -0
  50. package/dist/commands/experimental/setupOpentelemetry.js +34 -0
  51. package/dist/commands/experimental/setupOpentelemetryHandler.js +215 -0
  52. package/dist/commands/experimental/setupReactCompiler.js +28 -0
  53. package/dist/commands/experimental/setupReactCompilerHandler.js +124 -0
  54. package/dist/commands/experimental/setupRsc.js +28 -0
  55. package/dist/commands/experimental/setupRscHandler.js +408 -0
  56. package/dist/commands/experimental/setupStreamingSsr.js +28 -0
  57. package/dist/commands/experimental/setupStreamingSsrHandler.js +208 -0
  58. package/dist/commands/experimental/templates/opentelemetry.ts.template +55 -0
  59. package/dist/commands/experimental/templates/rsc/AboutCounter.tsx.template +20 -0
  60. package/dist/commands/experimental/templates/rsc/AboutPage.css.template +2 -0
  61. package/dist/commands/experimental/templates/rsc/AboutPage.tsx.template +17 -0
  62. package/dist/commands/experimental/templates/rsc/Counter.css.template +7 -0
  63. package/dist/commands/experimental/templates/rsc/Counter.module.css.template +3 -0
  64. package/dist/commands/experimental/templates/rsc/Counter.tsx.template +18 -0
  65. package/dist/commands/experimental/templates/rsc/Document.tsx.template +27 -0
  66. package/dist/commands/experimental/templates/rsc/HomePage.css.template +2 -0
  67. package/dist/commands/experimental/templates/rsc/HomePage.module.css.template +3 -0
  68. package/dist/commands/experimental/templates/rsc/HomePage.tsx.template +19 -0
  69. package/dist/commands/experimental/templates/rsc/NavigationLayout.css.template +32 -0
  70. package/dist/commands/experimental/templates/rsc/NavigationLayout.tsx.template +31 -0
  71. package/dist/commands/experimental/templates/rsc/Routes.tsx.template +29 -0
  72. package/dist/commands/experimental/templates/rsc/entry.client.tsx.template +35 -0
  73. package/dist/commands/experimental/templates/rsc/entry.server.tsx.template +20 -0
  74. package/dist/commands/experimental/templates/rsc/index.css.template +4 -0
  75. package/dist/commands/experimental/templates/streamingSsr/Document.tsx.template +27 -0
  76. package/dist/commands/experimental/templates/streamingSsr/entry.client.tsx.template +40 -0
  77. package/dist/commands/experimental/templates/streamingSsr/entry.server.tsx.template +20 -0
  78. package/dist/commands/experimental/templates/streamingSsr/tsconfig.json.template +54 -0
  79. package/dist/commands/experimental/util.js +69 -0
  80. package/dist/commands/experimental.js +22 -0
  81. package/dist/commands/generate/cell/cell.js +35 -0
  82. package/dist/commands/generate/cell/cellHandler.js +153 -0
  83. package/dist/commands/generate/cell/templates/cell.tsx.template +34 -0
  84. package/dist/commands/generate/cell/templates/cellList.tsx.template +40 -0
  85. package/dist/commands/generate/cell/templates/mock.ts.template +7 -0
  86. package/dist/commands/generate/cell/templates/mockList.ts.template +14 -0
  87. package/dist/commands/generate/cell/templates/stories.tsx.template +35 -0
  88. package/dist/commands/generate/cell/templates/test.js.template +42 -0
  89. package/dist/commands/generate/cell/utils/utils.js +43 -0
  90. package/dist/commands/generate/component/component.js +15 -0
  91. package/dist/commands/generate/component/componentHandler.js +55 -0
  92. package/dist/commands/generate/component/templates/component.tsx.template +10 -0
  93. package/dist/commands/generate/component/templates/stories.jsx.template +17 -0
  94. package/dist/commands/generate/component/templates/stories.tsx.template +26 -0
  95. package/dist/commands/generate/component/templates/test.tsx.template +14 -0
  96. package/dist/commands/generate/dataMigration/dataMigration.js +105 -0
  97. package/dist/commands/generate/dataMigration/templates/dataMigration.js.template +7 -0
  98. package/dist/commands/generate/dataMigration/templates/dataMigration.ts.template +5 -0
  99. package/dist/commands/generate/dbAuth/dbAuth.js +55 -0
  100. package/dist/commands/generate/dbAuth/dbAuthHandler.js +375 -0
  101. package/dist/commands/generate/dbAuth/templates/forgotPassword.tsx.template +94 -0
  102. package/dist/commands/generate/dbAuth/templates/login.tsx.template +130 -0
  103. package/dist/commands/generate/dbAuth/templates/login.webAuthn.tsx.template +264 -0
  104. package/dist/commands/generate/dbAuth/templates/resetPassword.tsx.template +121 -0
  105. package/dist/commands/generate/dbAuth/templates/signup.tsx.template +123 -0
  106. package/dist/commands/generate/directive/directive.js +15 -0
  107. package/dist/commands/generate/directive/directiveHandler.js +159 -0
  108. package/dist/commands/generate/directive/templates/transformer.directive.test.ts.template +18 -0
  109. package/dist/commands/generate/directive/templates/transformer.directive.ts.template +38 -0
  110. package/dist/commands/generate/directive/templates/validator.directive.test.ts.template +17 -0
  111. package/dist/commands/generate/directive/templates/validator.directive.ts.template +39 -0
  112. package/dist/commands/generate/function/function.js +29 -0
  113. package/dist/commands/generate/function/functionHandler.js +131 -0
  114. package/dist/commands/generate/function/templates/function.ts.template +33 -0
  115. package/dist/commands/generate/function/templates/scenarios.ts.template +8 -0
  116. package/dist/commands/generate/function/templates/test.ts.template +30 -0
  117. package/dist/commands/generate/helpers.js +71 -0
  118. package/dist/commands/generate/job/job.js +39 -0
  119. package/dist/commands/generate/job/jobHandler.js +138 -0
  120. package/dist/commands/generate/job/templates/job.ts.template +8 -0
  121. package/dist/commands/generate/job/templates/scenarios.ts.template +8 -0
  122. package/dist/commands/generate/job/templates/test.ts.template +7 -0
  123. package/dist/commands/generate/layout/layout.js +25 -0
  124. package/dist/commands/generate/layout/layoutHandler.js +59 -0
  125. package/dist/commands/generate/layout/templates/layout.tsx.a11y.template +27 -0
  126. package/dist/commands/generate/layout/templates/layout.tsx.template +9 -0
  127. package/dist/commands/generate/layout/templates/stories.tsx.template +13 -0
  128. package/dist/commands/generate/layout/templates/test.tsx.template +14 -0
  129. package/dist/commands/generate/model/model.js +29 -0
  130. package/dist/commands/generate/model/modelHandler.js +63 -0
  131. package/dist/commands/generate/model/templates/model.js.template +3 -0
  132. package/dist/commands/generate/ogImage/ogImage.js +43 -0
  133. package/dist/commands/generate/ogImage/ogImageHandler.js +111 -0
  134. package/dist/commands/generate/ogImage/templates/ogImage.og.tsx.template +13 -0
  135. package/dist/commands/generate/page/page.js +22 -0
  136. package/dist/commands/generate/page/pageHandler.js +227 -0
  137. package/dist/commands/generate/page/templates/page.tsx.template +35 -0
  138. package/dist/commands/generate/page/templates/stories.tsx.parameters.template +13 -0
  139. package/dist/commands/generate/page/templates/stories.tsx.template +13 -0
  140. package/dist/commands/generate/page/templates/test.tsx.template +14 -0
  141. package/dist/commands/generate/realtime/realtime.js +41 -0
  142. package/dist/commands/generate/realtime/realtimeHandler.js +215 -0
  143. package/dist/commands/generate/realtime/templates/liveQueries/blank/blank.sdl.ts.template +27 -0
  144. package/dist/commands/generate/realtime/templates/liveQueries/blank/blank.service.ts.template +73 -0
  145. package/dist/commands/generate/realtime/templates/realtime.ts.template +42 -0
  146. package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.sdl.ts.template +20 -0
  147. package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.service.ts.template +19 -0
  148. package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +58 -0
  149. package/dist/commands/generate/scaffold/scaffold.js +38 -0
  150. package/dist/commands/generate/scaffold/scaffoldHandler.js +663 -0
  151. package/dist/commands/generate/scaffold/templates/assets/scaffold.css.template +398 -0
  152. package/dist/commands/generate/scaffold/templates/assets/scaffold.tailwind.css.template +243 -0
  153. package/dist/commands/generate/scaffold/templates/components/EditNameCell.tsx.template +74 -0
  154. package/dist/commands/generate/scaffold/templates/components/Name.tsx.template +79 -0
  155. package/dist/commands/generate/scaffold/templates/components/NameCell.tsx.template +32 -0
  156. package/dist/commands/generate/scaffold/templates/components/NameForm.tsx.template +123 -0
  157. package/dist/commands/generate/scaffold/templates/components/Names.tsx.template +88 -0
  158. package/dist/commands/generate/scaffold/templates/components/NamesCell.tsx.template +45 -0
  159. package/dist/commands/generate/scaffold/templates/components/NewName.tsx.template +55 -0
  160. package/dist/commands/generate/scaffold/templates/layouts/ScaffoldLayout.tsx.template +37 -0
  161. package/dist/commands/generate/scaffold/templates/lib/formatters.test.tsx.template +192 -0
  162. package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +58 -0
  163. package/dist/commands/generate/scaffold/templates/pages/EditNamePage.tsx.template +11 -0
  164. package/dist/commands/generate/scaffold/templates/pages/NamePage.tsx.template +11 -0
  165. package/dist/commands/generate/scaffold/templates/pages/NamesPage.tsx.template +7 -0
  166. package/dist/commands/generate/scaffold/templates/pages/NewNamePage.tsx.template +7 -0
  167. package/dist/commands/generate/script/script.js +29 -0
  168. package/dist/commands/generate/script/scriptHandler.js +85 -0
  169. package/dist/commands/generate/script/templates/script.ts.template +15 -0
  170. package/dist/commands/generate/script/templates/tsconfig.json.template +33 -0
  171. package/dist/commands/generate/sdl/sdl.js +48 -0
  172. package/dist/commands/generate/sdl/sdlHandler.js +282 -0
  173. package/dist/commands/generate/sdl/templates/sdl.js.template +70 -0
  174. package/dist/commands/generate/sdl/templates/sdl.ts.template +70 -0
  175. package/dist/commands/generate/secret/secret.js +52 -0
  176. package/dist/commands/generate/service/service.js +50 -0
  177. package/dist/commands/generate/service/serviceHandler.js +301 -0
  178. package/dist/commands/generate/service/templates/scenarios.ts.template +7 -0
  179. package/dist/commands/generate/service/templates/service.ts.template +38 -0
  180. package/dist/commands/generate/service/templates/test.ts.template +84 -0
  181. package/dist/commands/generate/yargsCommandHelpers.js +77 -0
  182. package/dist/commands/generate/yargsHandlerHelpers.js +155 -0
  183. package/dist/commands/generate.js +44 -0
  184. package/dist/commands/info.js +36 -0
  185. package/dist/commands/jobs.js +17 -0
  186. package/dist/commands/jobsHandler.js +30 -0
  187. package/dist/commands/lint.js +57 -0
  188. package/dist/commands/prerender.js +34 -0
  189. package/dist/commands/prerenderHandler.js +282 -0
  190. package/dist/commands/prisma.js +17 -0
  191. package/dist/commands/prismaHandler.js +90 -0
  192. package/dist/commands/record/init.js +11 -0
  193. package/dist/commands/record.js +19 -0
  194. package/dist/commands/serve.js +139 -0
  195. package/dist/commands/serveApiHandler.js +15 -0
  196. package/dist/commands/serveBothHandler.js +95 -0
  197. package/dist/commands/serveWebHandler.js +17 -0
  198. package/dist/commands/setup/auth/auth.js +265 -0
  199. package/dist/commands/setup/cache/cache.js +37 -0
  200. package/dist/commands/setup/cache/cacheHandler.js +69 -0
  201. package/dist/commands/setup/cache/templates/memcached.ts.template +30 -0
  202. package/dist/commands/setup/cache/templates/redis.ts.template +24 -0
  203. package/dist/commands/setup/deploy/deploy.js +26 -0
  204. package/dist/commands/setup/deploy/helpers/helpers.js +9 -0
  205. package/dist/commands/setup/deploy/helpers/index.js +110 -0
  206. package/dist/commands/setup/deploy/providers/baremetal.js +9 -0
  207. package/dist/commands/setup/deploy/providers/baremetalHandler.js +64 -0
  208. package/dist/commands/setup/deploy/providers/coherence.js +24 -0
  209. package/dist/commands/setup/deploy/providers/coherenceHandler.js +203 -0
  210. package/dist/commands/setup/deploy/providers/flightcontrol.js +19 -0
  211. package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +294 -0
  212. package/dist/commands/setup/deploy/providers/netlify.js +9 -0
  213. package/dist/commands/setup/deploy/providers/netlifyHandler.js +42 -0
  214. package/dist/commands/setup/deploy/providers/render.js +17 -0
  215. package/dist/commands/setup/deploy/providers/renderHandler.js +111 -0
  216. package/dist/commands/setup/deploy/providers/serverless.js +11 -0
  217. package/dist/commands/setup/deploy/providers/serverlessHandler.js +141 -0
  218. package/dist/commands/setup/deploy/providers/vercel.js +9 -0
  219. package/dist/commands/setup/deploy/providers/vercelHandler.js +56 -0
  220. package/dist/commands/setup/deploy/templates/baremetal.js +128 -0
  221. package/dist/commands/setup/deploy/templates/flightcontrol.js +85 -0
  222. package/dist/commands/setup/deploy/templates/netlify.js +32 -0
  223. package/dist/commands/setup/deploy/templates/render.js +72 -0
  224. package/dist/commands/setup/deploy/templates/serverless/api.js +78 -0
  225. package/dist/commands/setup/deploy/templates/serverless/web.js +32 -0
  226. package/dist/commands/setup/docker/docker.js +26 -0
  227. package/dist/commands/setup/docker/dockerHandler.js +265 -0
  228. package/dist/commands/setup/docker/templates/Dockerfile +154 -0
  229. package/dist/commands/setup/docker/templates/docker-compose.dev.yml +58 -0
  230. package/dist/commands/setup/docker/templates/docker-compose.prod.yml +63 -0
  231. package/dist/commands/setup/docker/templates/dockerignore +18 -0
  232. package/dist/commands/setup/generator/generator.js +49 -0
  233. package/dist/commands/setup/generator/generatorHandler.js +55 -0
  234. package/dist/commands/setup/graphql/features/fragments/appGqlConfigTransform.js +117 -0
  235. package/dist/commands/setup/graphql/features/fragments/appImportTransform.js +20 -0
  236. package/dist/commands/setup/graphql/features/fragments/fragments.js +25 -0
  237. package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +89 -0
  238. package/dist/commands/setup/graphql/features/trustedDocuments/graphqlTransform.js +51 -0
  239. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +25 -0
  240. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +74 -0
  241. package/dist/commands/setup/graphql/graphql.js +18 -0
  242. package/dist/commands/setup/i18n/i18n.js +25 -0
  243. package/dist/commands/setup/i18n/i18nHandler.js +169 -0
  244. package/dist/commands/setup/i18n/templates/en.json.template +11 -0
  245. package/dist/commands/setup/i18n/templates/fr.json.template +11 -0
  246. package/dist/commands/setup/i18n/templates/i18n.js.template +52 -0
  247. package/dist/commands/setup/i18n/templates/storybook.preview.tsx.template +43 -0
  248. package/dist/commands/setup/jobs/jobs.js +31 -0
  249. package/dist/commands/setup/jobs/jobsHandler.js +122 -0
  250. package/dist/commands/setup/jobs/templates/jobs.ts.template +32 -0
  251. package/dist/commands/setup/mailer/mailer.js +30 -0
  252. package/dist/commands/setup/mailer/mailerHandler.js +106 -0
  253. package/dist/commands/setup/mailer/templates/mailer.ts.template +30 -0
  254. package/dist/commands/setup/mailer/templates/re-example.tsx.template +40 -0
  255. package/dist/commands/setup/middleware/middleware.js +17 -0
  256. package/dist/commands/setup/middleware/ogImage/__codemod_tests__/middleware.js +15 -0
  257. package/dist/commands/setup/middleware/ogImage/__codemod_tests__/vitePlugin.js +6 -0
  258. package/dist/commands/setup/middleware/ogImage/codemodMiddleware.js +97 -0
  259. package/dist/commands/setup/middleware/ogImage/codemodVitePlugin.js +65 -0
  260. package/dist/commands/setup/middleware/ogImage/ogImage.js +27 -0
  261. package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +121 -0
  262. package/dist/commands/setup/monitoring/monitoring.js +17 -0
  263. package/dist/commands/setup/monitoring/sentry/sentry.js +25 -0
  264. package/dist/commands/setup/monitoring/sentry/sentryHandler.js +163 -0
  265. package/dist/commands/setup/monitoring/sentry/templates/sentryApi.ts.template +15 -0
  266. package/dist/commands/setup/monitoring/sentry/templates/sentryWeb.ts.template +31 -0
  267. package/dist/commands/setup/package/package.js +33 -0
  268. package/dist/commands/setup/package/packageHandler.js +134 -0
  269. package/dist/commands/setup/realtime/realtime.js +37 -0
  270. package/dist/commands/setup/realtime/realtimeHandler.js +309 -0
  271. package/dist/commands/setup/realtime/templates/defer/fastAndSlowFields/fastAndSlowFields.sdl.template +14 -0
  272. package/dist/commands/setup/realtime/templates/defer/fastAndSlowFields/fastAndSlowFields.ts.template +14 -0
  273. package/dist/commands/setup/realtime/templates/liveQueries/auctions/auctions.sdl.ts.template +27 -0
  274. package/dist/commands/setup/realtime/templates/liveQueries/auctions/auctions.ts.template +73 -0
  275. package/dist/commands/setup/realtime/templates/realtime.ts.template +46 -0
  276. package/dist/commands/setup/realtime/templates/stream/alphabet/alphabet.sdl.template +9 -0
  277. package/dist/commands/setup/realtime/templates/stream/alphabet/alphabet.ts.template +31 -0
  278. package/dist/commands/setup/realtime/templates/subscriptions/countdown/countdown.ts.template +58 -0
  279. package/dist/commands/setup/realtime/templates/subscriptions/newMessage/newMessage.ts.template +57 -0
  280. package/dist/commands/setup/realtime/templates/subscriptions/newMessage/rooms.sdl.ts.template +20 -0
  281. package/dist/commands/setup/realtime/templates/subscriptions/newMessage/rooms.ts.template +20 -0
  282. package/dist/commands/setup/server-file/serverFile.js +31 -0
  283. package/dist/commands/setup/server-file/serverFileHandler.js +56 -0
  284. package/dist/commands/setup/server-file/templates/server.ts.template +13 -0
  285. package/dist/commands/setup/tsconfig/tsconfig.js +25 -0
  286. package/dist/commands/setup/tsconfig/tsconfigHandler.js +59 -0
  287. package/dist/commands/setup/ui/helpers/helpers.js +9 -0
  288. package/dist/commands/setup/ui/libraries/chakra-ui.js +24 -0
  289. package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +98 -0
  290. package/dist/commands/setup/ui/libraries/mantine.js +32 -0
  291. package/dist/commands/setup/ui/libraries/mantineHandler.js +138 -0
  292. package/dist/commands/setup/ui/libraries/tailwindcss.js +26 -0
  293. package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +386 -0
  294. package/dist/commands/setup/ui/templates/chakra.storybook.preview.tsx.template +20 -0
  295. package/dist/commands/setup/ui/templates/mantine-postcss.config.js.template +35 -0
  296. package/dist/commands/setup/ui/templates/mantine.storybook.preview.tsx.template +18 -0
  297. package/dist/commands/setup/ui/templates/postcss.config.js.template +9 -0
  298. package/dist/commands/setup/ui/ui.js +17 -0
  299. package/dist/commands/setup/uploads/dbCodemod.js +28 -0
  300. package/dist/commands/setup/uploads/templates/signedUrl.ts.template +21 -0
  301. package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +25 -0
  302. package/dist/commands/setup/uploads/uploads.js +26 -0
  303. package/dist/commands/setup/uploads/uploadsHandler.js +147 -0
  304. package/dist/commands/setup/vite/templates/vite.config.ts.template +19 -0
  305. package/dist/commands/setup/vite/vite.js +38 -0
  306. package/dist/commands/setup/vite/viteHandler.js +83 -0
  307. package/dist/commands/setup.js +33 -0
  308. package/dist/commands/studio.js +23 -0
  309. package/dist/commands/studioHandler.js +61 -0
  310. package/dist/commands/test.js +44 -0
  311. package/dist/commands/testHandler.js +138 -0
  312. package/dist/commands/ts-to-js.js +20 -0
  313. package/dist/commands/type-check.js +41 -0
  314. package/dist/commands/type-checkHandler.js +71 -0
  315. package/dist/commands/upgrade.js +441 -0
  316. package/dist/index.d.js +0 -0
  317. package/dist/index.js +146 -0
  318. package/dist/lib/background.js +45 -0
  319. package/dist/lib/colors.js +18 -0
  320. package/dist/lib/configureStorybook.js +50 -0
  321. package/dist/lib/exec.js +85 -0
  322. package/dist/lib/exit.js +44 -0
  323. package/dist/lib/extendFile.js +114 -0
  324. package/dist/lib/generatePrismaClient.js +60 -0
  325. package/dist/lib/index.js +485 -0
  326. package/dist/lib/loadEnvFiles.js +12 -0
  327. package/dist/lib/locking.js +60 -0
  328. package/dist/lib/merge/algorithms.js +30 -0
  329. package/dist/lib/merge/index.js +163 -0
  330. package/dist/lib/merge/semanticIdentity.js +18 -0
  331. package/dist/lib/merge/strategy.js +136 -0
  332. package/dist/lib/mockTelemetry.js +7 -0
  333. package/dist/lib/packages.js +77 -0
  334. package/dist/lib/plugin.js +206 -0
  335. package/dist/lib/pluralHelpers.js +50 -0
  336. package/dist/lib/ports.js +17 -0
  337. package/dist/lib/project.js +30 -0
  338. package/dist/lib/rollback.js +72 -0
  339. package/dist/lib/runTransform.js +66 -0
  340. package/dist/lib/rwPluralize.js +56 -0
  341. package/dist/lib/schemaHelpers.js +95 -0
  342. package/dist/lib/templates/storybook.preview.tsx.template +19 -0
  343. package/dist/lib/test.js +106 -0
  344. package/dist/lib/updateCheck.js +202 -0
  345. package/dist/lib/updateCheckExecute.js +2 -0
  346. package/dist/middleware/checkNodeVersion.js +23 -0
  347. package/dist/middleware/detectProjectRxVersion.js +12 -0
  348. package/dist/plugin.js +223 -0
  349. package/dist/rwfw.js +47 -0
  350. package/dist/telemetry/exporter.js +63 -0
  351. package/dist/telemetry/index.js +84 -0
  352. package/dist/telemetry/resource.js +98 -0
  353. package/dist/telemetry/send.js +80 -0
  354. package/dist/testLib/cells.js +188 -0
  355. package/dist/testLib/fetchFileFromTemplate.js +9 -0
  356. package/dist/testLib/getFilesWithPattern.js +21 -0
  357. package/dist/testLib/getRootPackageJSON.js +14 -0
  358. package/dist/testLib/isTSProject.js +9 -0
  359. package/dist/testLib/runTransform.js +42 -0
  360. package/package.json +102 -0
@@ -0,0 +1,55 @@
1
+ import terminalLink from "terminal-link";
2
+ import { getYargsDefaults, createHandler } from "../yargsCommandHelpers.js";
3
+ const command = "dbAuth";
4
+ const description = "Generate Login, Signup and Forgot Password pages for dbAuth";
5
+ const builder = (yargs) => {
6
+ yargs.option("skip-forgot", {
7
+ description: "Skip generating the Forgot Password page",
8
+ type: "boolean",
9
+ default: false
10
+ }).option("skip-login", {
11
+ description: "Skip generating the login page",
12
+ type: "boolean",
13
+ default: false
14
+ }).option("skip-reset", {
15
+ description: "Skip generating the Reset Password page",
16
+ type: "boolean",
17
+ default: false
18
+ }).option("skip-signup", {
19
+ description: "Skip generating the signup page",
20
+ type: "boolean",
21
+ default: false
22
+ }).option("webauthn", {
23
+ alias: "w",
24
+ default: null,
25
+ description: "Include WebAuthn support (TouchID/FaceID)",
26
+ type: "boolean"
27
+ }).option("username-label", {
28
+ default: null,
29
+ description: "Override default form label for username field",
30
+ type: "string"
31
+ }).option("password-label", {
32
+ default: null,
33
+ description: "Override default form label for password field",
34
+ type: "string"
35
+ }).option("rollback", {
36
+ description: "Revert all generator actions if an error occurs",
37
+ type: "boolean",
38
+ default: true
39
+ }).epilogue(
40
+ `Also see the ${terminalLink(
41
+ "Redwood CLI Reference",
42
+ "https://redwoodjs.com/docs/authentication#self-hosted-auth-installation-and-setup"
43
+ )}`
44
+ );
45
+ Object.entries(getYargsDefaults()).forEach(([option, config]) => {
46
+ yargs.option(option, config);
47
+ });
48
+ };
49
+ const handler = createHandler("dbAuth");
50
+ export {
51
+ builder,
52
+ command,
53
+ description,
54
+ handler
55
+ };
@@ -0,0 +1,375 @@
1
+ import path from "path";
2
+ import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
3
+ import { camelCase } from "camel-case";
4
+ import execa from "execa";
5
+ import fs from "fs-extra";
6
+ import { Listr } from "listr2";
7
+ import { titleCase } from "title-case";
8
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
9
+ import c from "../../../lib/colors.js";
10
+ import {
11
+ addRoutesToRouterTask,
12
+ addScaffoldImport,
13
+ generateTemplate,
14
+ getPaths,
15
+ transformTSToJS,
16
+ writeFilesTask
17
+ } from "../../../lib/index.js";
18
+ import { prepareForRollback } from "../../../lib/rollback.js";
19
+ import { templateForComponentFile } from "../yargsHandlerHelpers.js";
20
+ const ROUTES = [
21
+ `<Route path="/login" page={LoginPage} name="login" />`,
22
+ `<Route path="/signup" page={SignupPage} name="signup" />`,
23
+ `<Route path="/forgot-password" page={ForgotPasswordPage} name="forgotPassword" />`,
24
+ `<Route path="/reset-password" page={ResetPasswordPage} name="resetPassword" />`
25
+ ];
26
+ function getPostInstallMessage(isDbAuthSetup2) {
27
+ return [
28
+ ` ${c.warning("Pages created! But you're not done yet:")}
29
+ `,
30
+ " You'll need to tell your pages where to redirect after a user has logged in,",
31
+ " signed up, or reset their password. Look in LoginPage, SignupPage,",
32
+ " ForgotPasswordPage and ResetPasswordPage for these lines: \n",
33
+ " if (isAuthenticated) {",
34
+ " navigate(routes.home())",
35
+ " }\n",
36
+ " and change the route to where you want them to go if the user is already",
37
+ " logged in. Also take a look in the onSubmit() functions in ForgotPasswordPage",
38
+ " and ResetPasswordPage to change where the user redirects to after submitting",
39
+ " those forms.\n",
40
+ !isDbAuthSetup2 && " Oh, and if you haven't already, add the necessary dbAuth functions and\n app setup by running:\n\n yarn rw setup auth dbAuth\n",
41
+ " Happy authenticating!"
42
+ ].filter(Boolean).join("\n");
43
+ }
44
+ function getPostInstallWebauthnMessage(isDbAuthSetup2) {
45
+ return [
46
+ ` ${c.warning("Pages created! But you're not done yet:")}
47
+ `,
48
+ " You'll need to tell your pages where to redirect after a user has logged in,",
49
+ " signed up, or reset their password. In LoginPage, look for the `REDIRECT`",
50
+ " constant and change the route if it's something other than home().",
51
+ " In SignupPage, ForgotPasswordPage and ResetPasswordPage look for these lines:\n",
52
+ " if (isAuthenticated) {",
53
+ " navigate(routes.home())",
54
+ " }\n",
55
+ " and change the route to where you want them to go if the user is already",
56
+ " logged in. Also take a look in the onSubmit() functions in ForgotPasswordPage",
57
+ " and ResetPasswordPage to change where the user redirects to after submitting",
58
+ " those forms.\n",
59
+ !isDbAuthSetup2 && " Oh, and if you haven't already, add the necessary dbAuth functions and\n app setup by running:\n\n yarn rw setup auth dbAuth\n",
60
+ " Happy authenticating!"
61
+ ].filter(Boolean).join("\n");
62
+ }
63
+ const files = async ({
64
+ _tests,
65
+ typescript,
66
+ skipForgot,
67
+ skipLogin,
68
+ skipReset,
69
+ skipSignup,
70
+ webauthn,
71
+ usernameLabel,
72
+ passwordLabel
73
+ }) => {
74
+ const files2 = [];
75
+ usernameLabel = usernameLabel || "username";
76
+ passwordLabel = passwordLabel || "password";
77
+ const templateVars = {
78
+ usernameLowerCase: usernameLabel.toLowerCase(),
79
+ usernameCamelCase: camelCase(usernameLabel),
80
+ usernameTitleCase: titleCase(usernameLabel),
81
+ passwordLowerCase: passwordLabel.toLowerCase(),
82
+ passwordCamelCase: camelCase(passwordLabel),
83
+ passwordTitleCase: titleCase(passwordLabel)
84
+ };
85
+ if (!skipForgot) {
86
+ files2.push(
87
+ await templateForComponentFile({
88
+ name: "ForgotPassword",
89
+ suffix: "Page",
90
+ extension: typescript ? ".tsx" : ".jsx",
91
+ webPathSection: "pages",
92
+ generator: "dbAuth",
93
+ templatePath: "forgotPassword.tsx.template",
94
+ templateVars
95
+ })
96
+ );
97
+ }
98
+ if (!skipLogin) {
99
+ files2.push(
100
+ await templateForComponentFile({
101
+ name: "Login",
102
+ suffix: "Page",
103
+ extension: typescript ? ".tsx" : ".jsx",
104
+ webPathSection: "pages",
105
+ generator: "dbAuth",
106
+ templatePath: webauthn ? "login.webAuthn.tsx.template" : "login.tsx.template",
107
+ templateVars
108
+ })
109
+ );
110
+ }
111
+ if (!skipReset) {
112
+ files2.push(
113
+ await templateForComponentFile({
114
+ name: "ResetPassword",
115
+ suffix: "Page",
116
+ extension: typescript ? ".tsx" : ".jsx",
117
+ webPathSection: "pages",
118
+ generator: "dbAuth",
119
+ templatePath: "resetPassword.tsx.template",
120
+ templateVars
121
+ })
122
+ );
123
+ }
124
+ if (!skipSignup) {
125
+ files2.push(
126
+ await templateForComponentFile({
127
+ name: "Signup",
128
+ suffix: "Page",
129
+ extension: typescript ? ".tsx" : ".jsx",
130
+ webPathSection: "pages",
131
+ generator: "dbAuth",
132
+ templatePath: "signup.tsx.template",
133
+ templateVars
134
+ })
135
+ );
136
+ }
137
+ if (files2.length === 0) {
138
+ console.info(c.error("\nNo files to generate.\n"));
139
+ process.exit(0);
140
+ }
141
+ const scaffoldOutputPath = path.join(getPaths().web.src, "scaffold.css");
142
+ if (!fs.existsSync(scaffoldOutputPath)) {
143
+ const scaffoldTemplate = await generateTemplate(
144
+ path.join(
145
+ import.meta.dirname,
146
+ "../scaffold/templates/assets/scaffold.css.template"
147
+ ),
148
+ { name: "scaffold" }
149
+ );
150
+ files2.push([scaffoldOutputPath, scaffoldTemplate]);
151
+ }
152
+ return files2.reduce(async (accP, [outputPath, content]) => {
153
+ const acc = await accP;
154
+ let template = content;
155
+ if (outputPath.match(/\.[jt]sx?/) && !typescript) {
156
+ template = await transformTSToJS(outputPath, content);
157
+ }
158
+ return {
159
+ [outputPath]: template,
160
+ ...acc
161
+ };
162
+ }, Promise.resolve({}));
163
+ };
164
+ const tasks = ({
165
+ enquirer,
166
+ listr2,
167
+ force,
168
+ tests,
169
+ typescript,
170
+ skipForgot,
171
+ skipLogin,
172
+ skipReset,
173
+ skipSignup,
174
+ webauthn,
175
+ usernameLabel,
176
+ passwordLabel
177
+ }) => {
178
+ return new Listr(
179
+ [
180
+ {
181
+ title: "Determining UI labels...",
182
+ skip: () => {
183
+ return !!(usernameLabel && passwordLabel);
184
+ },
185
+ task: async (ctx, task) => {
186
+ return task.newListr(
187
+ [
188
+ {
189
+ title: "Username label",
190
+ task: async (subCtx, subtask) => {
191
+ if (usernameLabel) {
192
+ subtask.skip(
193
+ `Argument username-label is set, using: "${usernameLabel}"`
194
+ );
195
+ return;
196
+ }
197
+ const prompt = subtask.prompt(ListrEnquirerPromptAdapter);
198
+ usernameLabel = await prompt.run(
199
+ {
200
+ type: "input",
201
+ name: "username",
202
+ message: "What would you like the username label to be:",
203
+ default: "Username"
204
+ },
205
+ { enquirer: subCtx.enquirer || ctx.enquirer }
206
+ );
207
+ subtask.title = `Username label: "${usernameLabel}"`;
208
+ }
209
+ },
210
+ {
211
+ title: "Password label",
212
+ task: async (subCtx, subtask) => {
213
+ if (passwordLabel) {
214
+ subtask.skip(
215
+ `Argument password-label passed, using: "${passwordLabel}"`
216
+ );
217
+ return;
218
+ }
219
+ const prompt = subtask.prompt(ListrEnquirerPromptAdapter);
220
+ passwordLabel = await prompt.run(
221
+ {
222
+ type: "input",
223
+ name: "password",
224
+ message: "What would you like the password label to be:",
225
+ default: "Password"
226
+ },
227
+ { enquirer: subCtx.enquirer || ctx.enquirer }
228
+ );
229
+ subtask.title = `Password label: "${passwordLabel}"`;
230
+ }
231
+ }
232
+ ],
233
+ { ctx: { enquirer } }
234
+ );
235
+ }
236
+ },
237
+ {
238
+ title: "Querying WebAuthn addition...",
239
+ task: async (ctx, task) => {
240
+ if (webauthn != null) {
241
+ ctx.webauthn = webauthn;
242
+ task.skip(
243
+ `Querying WebAuthn addition: argument webauthn passed, WebAuthn${webauthn ? "" : " not"} included`
244
+ );
245
+ return;
246
+ }
247
+ if (isDbAuthSetup()) {
248
+ if (isWebAuthnEnabled()) {
249
+ ctx.webauthn = webauthn = true;
250
+ task.skip(
251
+ "Querying WebAuthn addition: WebAuthn setup detected - support will be included in pages"
252
+ );
253
+ } else {
254
+ ctx.webauthn = webauthn = false;
255
+ task.skip(
256
+ "Querying WebAuthn addition: No WebAuthn setup detected - support will not be included in pages"
257
+ );
258
+ }
259
+ return;
260
+ }
261
+ const prompt = task.prompt(ListrEnquirerPromptAdapter);
262
+ const response = await prompt.run(
263
+ {
264
+ type: "confirm",
265
+ name: "answer",
266
+ message: "Enable WebAuthn support (TouchID/FaceID) on LoginPage? See https://redwoodjs.com/docs/auth/dbAuth#webAuthn",
267
+ default: false
268
+ },
269
+ { enquirer: ctx.enquirer }
270
+ );
271
+ ctx.webauthn = webauthn = response;
272
+ task.title = `Querying WebAuthn addition: WebAuthn addition${webauthn ? "" : " not"} included`;
273
+ }
274
+ },
275
+ {
276
+ title: "Creating pages...",
277
+ task: async () => {
278
+ const filesObj = await files({
279
+ tests,
280
+ typescript,
281
+ skipForgot,
282
+ skipLogin,
283
+ skipReset,
284
+ skipSignup,
285
+ webauthn,
286
+ usernameLabel,
287
+ passwordLabel
288
+ });
289
+ return writeFilesTask(filesObj, {
290
+ overwriteExisting: force
291
+ });
292
+ }
293
+ },
294
+ {
295
+ title: "Adding routes...",
296
+ task: async () => {
297
+ addRoutesToRouterTask(ROUTES);
298
+ }
299
+ },
300
+ {
301
+ title: "Adding scaffold import...",
302
+ task: () => addScaffoldImport()
303
+ },
304
+ {
305
+ title: "Generate types...",
306
+ task: () => {
307
+ execa.commandSync("yarn rw g types");
308
+ }
309
+ },
310
+ {
311
+ title: "One more thing...",
312
+ task: () => {
313
+ }
314
+ }
315
+ ],
316
+ {
317
+ silentRendererCondition: () => listr2?.silentRendererCondition,
318
+ rendererOptions: { collapseSubtasks: false },
319
+ ctx: { enquirer },
320
+ exitOnError: true
321
+ }
322
+ );
323
+ };
324
+ const handler = async (yargs) => {
325
+ recordTelemetryAttributes({
326
+ command: "generate dbAuth",
327
+ skipForgot: yargs.skipForgot,
328
+ skipLogin: yargs.skipLogin,
329
+ skipReset: yargs.skipReset,
330
+ skipSignup: yargs.skipSignup,
331
+ webauthn: yargs.webauthn,
332
+ force: yargs.force,
333
+ rollback: yargs.rollback
334
+ });
335
+ const t = tasks({ ...yargs });
336
+ try {
337
+ if (yargs.rollback && !yargs.force) {
338
+ prepareForRollback(t);
339
+ }
340
+ await t.run();
341
+ console.log("");
342
+ console.log(
343
+ yargs.webauthn || t.ctx.webauthn ? getPostInstallWebauthnMessage(isDbAuthSetup()) : getPostInstallMessage(isDbAuthSetup())
344
+ );
345
+ } catch (e) {
346
+ console.log(c.error(e.message));
347
+ }
348
+ };
349
+ function isDbAuthSetup() {
350
+ const extensions = ["ts", "js", "tsx", "jsx"];
351
+ const webAuthExtension = extensions.find(
352
+ (ext) => fs.existsSync(path.join(getPaths().web.src, "auth." + ext))
353
+ );
354
+ if (webAuthExtension) {
355
+ const webAuthPath = path.join(
356
+ getPaths().web.src,
357
+ "auth." + webAuthExtension
358
+ );
359
+ return /^import (.*) from ['"]@cedarjs\/auth-dbauth-web['"]/m.test(
360
+ fs.readFileSync(webAuthPath)
361
+ );
362
+ }
363
+ return false;
364
+ }
365
+ function isWebAuthnEnabled() {
366
+ const webPackageJson = fs.readFileSync(
367
+ path.join(getPaths().web.base, "package.json"),
368
+ "utf-8"
369
+ );
370
+ return webPackageJson.includes('"@simplewebauthn/browser": ');
371
+ }
372
+ export {
373
+ files,
374
+ handler
375
+ };
@@ -0,0 +1,94 @@
1
+ import { useEffect, useRef } from 'react'
2
+
3
+ import { Form, Label, TextField, Submit, FieldError } from '@cedarjs/forms'
4
+ import { navigate, routes } from '@cedarjs/router'
5
+ import { Metadata } from '@cedarjs/web'
6
+ import { toast, Toaster } from '@cedarjs/web/toast'
7
+
8
+ import { useAuth } from 'src/auth'
9
+
10
+ const ForgotPasswordPage = () => {
11
+ const { isAuthenticated, forgotPassword } = useAuth()
12
+
13
+ useEffect(() => {
14
+ if (isAuthenticated) {
15
+ navigate(routes.home())
16
+ }
17
+ }, [isAuthenticated])
18
+
19
+ const ${usernameCamelCase}Ref = useRef<HTMLInputElement>(null)
20
+ useEffect(() => {
21
+ ${usernameCamelCase}Ref?.current?.focus()
22
+ }, [])
23
+
24
+ const onSubmit = async (data: { ${usernameCamelCase}: string }) => {
25
+ const response = await forgotPassword(data.${usernameCamelCase})
26
+
27
+ if (response.error) {
28
+ toast.error(response.error)
29
+ } else {
30
+ // The function `forgotPassword.handler` in api/src/functions/auth.js has
31
+ // been invoked, let the user know how to get the link to reset their
32
+ // password (sent in email, perhaps?)
33
+ toast.success(
34
+ 'A link to reset your ${passwordLowerCase} was sent to ' + response.email
35
+ )
36
+ navigate(routes.login())
37
+ }
38
+ }
39
+
40
+ return (
41
+ <>
42
+ <Metadata title="Forgot ${passwordTitleCase}" />
43
+
44
+ <main className="rw-main">
45
+ <Toaster toastOptions={{ className: 'rw-toast', duration: 6000 }} />
46
+ <div className="rw-scaffold rw-login-container">
47
+ <div className="rw-segment">
48
+ <header className="rw-segment-header">
49
+ <h2 className="rw-heading rw-heading-secondary">
50
+ Forgot ${passwordTitleCase}
51
+ </h2>
52
+ </header>
53
+
54
+ <div className="rw-segment-main">
55
+ <div className="rw-form-wrapper">
56
+ <Form onSubmit={onSubmit} className="rw-form-wrapper">
57
+ <div className="text-left">
58
+ <Label
59
+ name="${usernameCamelCase}"
60
+ className="rw-label"
61
+ errorClassName="rw-label rw-label-error"
62
+ >
63
+ ${usernameTitleCase}
64
+ </Label>
65
+ <TextField
66
+ name="${usernameCamelCase}"
67
+ className="rw-input"
68
+ errorClassName="rw-input rw-input-error"
69
+ ref={${usernameCamelCase}Ref}
70
+ validation={{
71
+ required: {
72
+ value: true,
73
+ message: '${usernameTitleCase} is required',
74
+ },
75
+ }}
76
+ />
77
+
78
+ <FieldError name="${usernameCamelCase}" className="rw-field-error" />
79
+ </div>
80
+
81
+ <div className="rw-button-group">
82
+ <Submit className="rw-button rw-button-blue">Submit</Submit>
83
+ </div>
84
+ </Form>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </main>
90
+ </>
91
+ )
92
+ }
93
+
94
+ export default ForgotPasswordPage
@@ -0,0 +1,130 @@
1
+ import { useEffect, useRef } from 'react'
2
+
3
+ import {
4
+ Form,
5
+ Label,
6
+ TextField,
7
+ PasswordField,
8
+ Submit,
9
+ FieldError,
10
+ } from '@cedarjs/forms'
11
+ import { Link, navigate, routes } from '@cedarjs/router'
12
+ import { Metadata } from '@cedarjs/web'
13
+ import { toast, Toaster } from '@cedarjs/web/toast'
14
+
15
+ import { useAuth } from 'src/auth'
16
+
17
+ const LoginPage = () => {
18
+ const { isAuthenticated, logIn } = useAuth()
19
+
20
+ useEffect(() => {
21
+ if (isAuthenticated) {
22
+ navigate(routes.home())
23
+ }
24
+ }, [isAuthenticated])
25
+
26
+ const ${usernameCamelCase}Ref = useRef<HTMLInputElement>(null)
27
+ useEffect(() => {
28
+ ${usernameCamelCase}Ref.current?.focus()
29
+ }, [])
30
+
31
+ const onSubmit = async (data: Record<string, string>) => {
32
+ const response = await logIn({ username: data.${usernameCamelCase}, password: data.${passwordCamelCase} })
33
+
34
+ if (response.message) {
35
+ toast(response.message)
36
+ } else if (response.error) {
37
+ toast.error(response.error)
38
+ } else {
39
+ toast.success('Welcome back!')
40
+ }
41
+ }
42
+
43
+ return (
44
+ <>
45
+ <Metadata title="Login" />
46
+
47
+ <main className="rw-main">
48
+ <Toaster toastOptions={{ className: 'rw-toast', duration: 6000 }} />
49
+ <div className="rw-scaffold rw-login-container">
50
+ <div className="rw-segment">
51
+ <header className="rw-segment-header">
52
+ <h2 className="rw-heading rw-heading-secondary">Login</h2>
53
+ </header>
54
+
55
+ <div className="rw-segment-main">
56
+ <div className="rw-form-wrapper">
57
+ <Form onSubmit={onSubmit} className="rw-form-wrapper">
58
+ <Label
59
+ name="${usernameCamelCase}"
60
+ className="rw-label"
61
+ errorClassName="rw-label rw-label-error"
62
+ >
63
+ ${usernameTitleCase}
64
+ </Label>
65
+ <TextField
66
+ name="${usernameCamelCase}"
67
+ className="rw-input"
68
+ errorClassName="rw-input rw-input-error"
69
+ ref={${usernameCamelCase}Ref}
70
+ validation={{
71
+ required: {
72
+ value: true,
73
+ message: '${usernameTitleCase} is required',
74
+ },
75
+ }}
76
+ />
77
+
78
+ <FieldError name="${usernameCamelCase}" className="rw-field-error" />
79
+
80
+ <Label
81
+ name="${passwordCamelCase}"
82
+ className="rw-label"
83
+ errorClassName="rw-label rw-label-error"
84
+ >
85
+ ${passwordTitleCase}
86
+ </Label>
87
+ <PasswordField
88
+ name="${passwordCamelCase}"
89
+ className="rw-input"
90
+ errorClassName="rw-input rw-input-error"
91
+ autoComplete="current-password"
92
+ validation={{
93
+ required: {
94
+ value: true,
95
+ message: '${passwordTitleCase} is required',
96
+ },
97
+ }}
98
+ />
99
+
100
+ <div className="rw-forgot-link">
101
+ <Link
102
+ to={routes.forgotPassword()}
103
+ className="rw-forgot-link"
104
+ >
105
+ Forgot ${passwordTitleCase}?
106
+ </Link>
107
+ </div>
108
+
109
+ <FieldError name="${passwordCamelCase}" className="rw-field-error" />
110
+
111
+ <div className="rw-button-group">
112
+ <Submit className="rw-button rw-button-blue">Login</Submit>
113
+ </div>
114
+ </Form>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ <div className="rw-login-link">
119
+ <span>Don&apos;t have an account?</span>{' '}
120
+ <Link to={routes.signup()} className="rw-link">
121
+ Sign up!
122
+ </Link>
123
+ </div>
124
+ </div>
125
+ </main>
126
+ </>
127
+ )
128
+ }
129
+
130
+ export default LoginPage