@cedarjs/cli 9.0.0-canary.1784 → 9.0.0-canary.3124

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 (277) hide show
  1. package/README.md +7 -10
  2. package/dist/cfw.js +10 -6
  3. package/dist/commands/build/buildHandler.js +220 -45
  4. package/dist/commands/build/buildPackagesTask.js +21 -20
  5. package/dist/commands/build.js +13 -2
  6. package/dist/commands/check.js +4 -6
  7. package/dist/commands/console.js +6 -4
  8. package/dist/commands/deploy/baremetal/SshExecutor.js +13 -4
  9. package/dist/commands/deploy/baremetal/baremetalHandler.js +116 -50
  10. package/dist/commands/deploy/baremetal.js +11 -4
  11. package/dist/commands/deploy/flightcontrolHandler.js +28 -15
  12. package/dist/commands/deploy/helpers/deployHandler.js +11 -6
  13. package/dist/commands/deploy/netlify.js +1 -1
  14. package/dist/commands/deploy/packing/nft.js +1 -2
  15. package/dist/commands/deploy/render.js +1 -1
  16. package/dist/commands/deploy/renderHandler.js +24 -13
  17. package/dist/commands/deploy/serverlessHandler.js +69 -27
  18. package/dist/commands/deploy/vercel.js +1 -1
  19. package/dist/commands/destroy/component/component.js +2 -3
  20. package/dist/commands/destroy/directive/directive.js +1 -3
  21. package/dist/commands/destroy/directive/directiveHandler.js +2 -4
  22. package/dist/commands/destroy/function/function.js +1 -3
  23. package/dist/commands/destroy/handlerHelpers.js +17 -17
  24. package/dist/commands/destroy/helpers.js +8 -2
  25. package/dist/commands/destroy/layout/layout.js +1 -2
  26. package/dist/commands/destroy/page/pageHandler.js +3 -3
  27. package/dist/commands/destroy/scaffold/scaffoldHandler.js +31 -12
  28. package/dist/commands/destroy/sdl/sdlHandler.js +3 -3
  29. package/dist/commands/dev/apiDebugFlag.js +5 -4
  30. package/dist/commands/dev/devHandler.js +219 -68
  31. package/dist/commands/dev/packageWatchCommands.js +8 -3
  32. package/dist/commands/dev.js +16 -6
  33. package/dist/commands/execHandler.js +49 -29
  34. package/dist/commands/experimental/live-queries/liveQueries.js +32 -0
  35. package/dist/commands/experimental/live-queries/liveQueriesHandler.js +448 -0
  36. package/dist/commands/experimental/live-queries/templates/liveQueriesListener.ts.template +153 -0
  37. package/dist/commands/experimental/live-queries/templates/migration.sql.template +100 -0
  38. package/dist/commands/experimental/setupInngest.js +2 -2
  39. package/dist/commands/experimental/setupInngestHandler.js +13 -12
  40. package/dist/commands/experimental/setupOpentelemetry.js +2 -2
  41. package/dist/commands/experimental/setupOpentelemetryHandler.js +14 -10
  42. package/dist/commands/experimental/setupReactCompiler.js +2 -2
  43. package/dist/commands/experimental/setupReactCompilerHandler.js +48 -33
  44. package/dist/commands/experimental/setupRsc.js +1 -1
  45. package/dist/commands/experimental/setupRscHandler.js +20 -16
  46. package/dist/commands/experimental/setupStreamingSsr.js +2 -2
  47. package/dist/commands/experimental/setupStreamingSsrHandler.js +49 -34
  48. package/dist/commands/experimental/templates/opentelemetry.ts.template +2 -1
  49. package/dist/commands/experimental/templates/rsc/Document.tsx.template +1 -1
  50. package/dist/commands/experimental/templates/rsc/entry.client.tsx.template +8 -8
  51. package/dist/commands/experimental/templates/streamingSsr/Document.tsx.template +1 -1
  52. package/dist/commands/experimental/templates/streamingSsr/entry.client.tsx.template +6 -6
  53. package/dist/commands/experimental/templates/streamingSsr/tsconfig.json.template +6 -6
  54. package/dist/commands/experimental/util.js +27 -25
  55. package/dist/commands/experimental.js +3 -2
  56. package/dist/commands/generate/cell/cell.js +20 -0
  57. package/dist/commands/generate/cell/cellHandler.js +89 -40
  58. package/dist/commands/generate/cell/templates/cell.tsx.template +21 -2
  59. package/dist/commands/generate/cell/templates/cellFragment.tsx.template +43 -0
  60. package/dist/commands/generate/cell/templates/cellList.tsx.template +21 -2
  61. package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +23 -0
  62. package/dist/commands/generate/cell/templates/test.js.template +1 -1
  63. package/dist/commands/generate/cell/templates/testFragment.js.template +30 -0
  64. package/dist/commands/generate/component/componentHandler.js +14 -16
  65. package/dist/commands/generate/dataMigration/dataMigration.js +36 -18
  66. package/dist/commands/generate/dataMigration/templates/dataMigration.js.template +1 -1
  67. package/dist/commands/generate/dataMigration/templates/dataMigration.ts.template +1 -1
  68. package/dist/commands/generate/dbAuth/dbAuth.js +1 -0
  69. package/dist/commands/generate/dbAuth/dbAuthHandler.js +63 -34
  70. package/dist/commands/generate/dbAuth/templates/login.oauth.tsx.template +164 -0
  71. package/dist/commands/generate/dbAuth/templates/signup.oauth.tsx.template +147 -0
  72. package/dist/commands/generate/directive/directiveHandler.js +14 -16
  73. package/dist/commands/generate/function/function.js +1 -0
  74. package/dist/commands/generate/function/functionHandler.js +14 -19
  75. package/dist/commands/generate/helpers.js +34 -18
  76. package/dist/commands/generate/job/job.js +1 -0
  77. package/dist/commands/generate/job/jobHandler.js +20 -24
  78. package/dist/commands/generate/layout/layoutHandler.js +13 -16
  79. package/dist/commands/generate/model/model.js +1 -0
  80. package/dist/commands/generate/model/modelHandler.js +11 -5
  81. package/dist/commands/generate/ogImage/ogImage.js +1 -0
  82. package/dist/commands/generate/ogImage/ogImageHandler.js +18 -11
  83. package/dist/commands/generate/package/filesTask.js +9 -0
  84. package/dist/commands/generate/package/packageHandler.js +50 -61
  85. package/dist/commands/generate/package/templates/test.ts.template +2 -2
  86. package/dist/commands/generate/package/templates/vitest.config.ts.template +9 -0
  87. package/dist/commands/generate/page/pageHandler.js +27 -24
  88. package/dist/commands/generate/realtime/realtime.js +2 -2
  89. package/dist/commands/generate/realtime/realtimeHandler.js +51 -32
  90. package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +1 -1
  91. package/dist/commands/generate/scaffold/scaffold.js +1 -0
  92. package/dist/commands/generate/scaffold/scaffoldHandler.js +176 -49
  93. package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +1 -1
  94. package/dist/commands/generate/script/script.js +1 -0
  95. package/dist/commands/generate/script/scriptHandler.js +10 -6
  96. package/dist/commands/generate/script/templates/script.ts.template +9 -4
  97. package/dist/commands/generate/script/templates/tsconfig.json.template +16 -2
  98. package/dist/commands/generate/sdl/sdl.js +4 -3
  99. package/dist/commands/generate/sdl/sdlHandler.js +135 -46
  100. package/dist/commands/generate/sdl/stubFiles.js +132 -0
  101. package/dist/commands/generate/sdl/templates/sdl.js.template +2 -1
  102. package/dist/commands/generate/sdl/templates/sdl.ts.template +2 -1
  103. package/dist/commands/generate/secret/secret.js +20 -20
  104. package/dist/commands/generate/service/service.js +5 -5
  105. package/dist/commands/generate/service/serviceHandler.js +126 -61
  106. package/dist/commands/generate/service/templates/scenarios.ts.template +4 -2
  107. package/dist/commands/generate/service/templates/service.ts.template +22 -8
  108. package/dist/commands/generate/service/templates/test.ts.template +2 -2
  109. package/dist/commands/generate/yargsCommandHelpers.js +7 -2
  110. package/dist/commands/generate/yargsHandlerHelpers.js +20 -18
  111. package/dist/commands/generate.js +4 -4
  112. package/dist/commands/info.js +2 -2
  113. package/dist/commands/jobsHandler.js +7 -4
  114. package/dist/commands/lint.js +26 -69
  115. package/dist/commands/prerenderHandler.js +95 -58
  116. package/dist/commands/prismaHandler.js +51 -26
  117. package/dist/commands/record/init.js +2 -2
  118. package/dist/commands/record.js +4 -3
  119. package/dist/commands/serve.js +245 -31
  120. package/dist/commands/serveApiHandler.js +7 -6
  121. package/dist/commands/serveBothHandler.js +22 -13
  122. package/dist/commands/serveWebHandler.js +3 -2
  123. package/dist/commands/setup/auth/auth.js +15 -11
  124. package/dist/commands/setup/cache/cache.js +1 -1
  125. package/dist/commands/setup/cache/cacheHandler.js +15 -9
  126. package/dist/commands/setup/database/database.js +15 -0
  127. package/dist/commands/setup/database/postgres.js +19 -0
  128. package/dist/commands/setup/database/postgresHandler.js +196 -0
  129. package/dist/commands/setup/database/templates/db.ts.template +32 -0
  130. package/dist/commands/setup/deploy/deploy.js +4 -3
  131. package/dist/commands/setup/deploy/helpers/helpers.js +5 -1
  132. package/dist/commands/setup/deploy/helpers/index.js +132 -6
  133. package/dist/commands/setup/deploy/providers/baremetalHandler.js +28 -6
  134. package/dist/commands/setup/deploy/providers/coherence.js +1 -1
  135. package/dist/commands/setup/deploy/providers/coherenceHandler.js +60 -31
  136. package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +69 -51
  137. package/dist/commands/setup/deploy/providers/netlify.js +6 -0
  138. package/dist/commands/setup/deploy/providers/netlifyHandler.js +114 -13
  139. package/dist/commands/setup/deploy/providers/renderHandler.js +44 -41
  140. package/dist/commands/setup/deploy/providers/serverlessHandler.js +7 -5
  141. package/dist/commands/setup/deploy/providers/universal-deploy.js +11 -0
  142. package/dist/commands/setup/deploy/providers/universalDeployHandler.js +186 -0
  143. package/dist/commands/setup/deploy/providers/vercel.js +6 -0
  144. package/dist/commands/setup/deploy/providers/vercelHandler.js +115 -14
  145. package/dist/commands/setup/deploy/templates/baremetal.js +3 -2
  146. package/dist/commands/setup/deploy/templates/flightcontrol.js +60 -49
  147. package/dist/commands/setup/deploy/templates/netlify.js +2 -1
  148. package/dist/commands/setup/deploy/templates/netlifyUD.js +31 -0
  149. package/dist/commands/setup/deploy/templates/render.js +32 -17
  150. package/dist/commands/setup/docker/docker.js +2 -2
  151. package/dist/commands/setup/docker/dockerHandler.js +74 -39
  152. package/dist/commands/setup/docker/templates/Dockerfile.npm +119 -0
  153. package/dist/commands/setup/docker/templates/Dockerfile.pnpm +112 -0
  154. package/dist/commands/setup/docker/templates/{Dockerfile → Dockerfile.yarn} +4 -7
  155. package/dist/commands/setup/docker/templates/docker-compose.dev.yml +3 -3
  156. package/dist/commands/setup/docker/templates/docker-compose.prod.yml +2 -5
  157. package/dist/commands/setup/docker/templates/dockerignore +1 -0
  158. package/dist/commands/setup/generator/generator.js +1 -1
  159. package/dist/commands/setup/generator/generatorHandler.js +5 -4
  160. package/dist/commands/setup/graphql/features/fragments/appGqlConfigTransform.js +6 -3
  161. package/dist/commands/setup/graphql/features/fragments/fragments.js +1 -1
  162. package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +5 -7
  163. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +1 -1
  164. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +4 -3
  165. package/dist/commands/setup/i18n/i18n.js +1 -1
  166. package/dist/commands/setup/i18n/i18nHandler.js +21 -17
  167. package/dist/commands/setup/jobs/jobs.js +1 -1
  168. package/dist/commands/setup/jobs/jobsHandler.js +17 -12
  169. package/dist/commands/setup/mailer/mailer.js +1 -1
  170. package/dist/commands/setup/mailer/mailerHandler.js +13 -11
  171. package/dist/commands/setup/middleware/ogImage/ogImage.js +1 -1
  172. package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +2 -1
  173. package/dist/commands/setup/monitoring/sentry/sentry.js +1 -1
  174. package/dist/commands/setup/monitoring/sentry/sentryHandler.js +18 -12
  175. package/dist/commands/setup/neon/neon.js +35 -0
  176. package/dist/commands/setup/neon/neonHandler.js +264 -0
  177. package/dist/commands/setup/package/package.js +1 -1
  178. package/dist/commands/setup/package/packageHandler.js +18 -14
  179. package/dist/commands/setup/realtime/addRealtimeToGraphql.js +1 -1
  180. package/dist/commands/setup/realtime/realtime.js +1 -1
  181. package/dist/commands/setup/realtime/realtimeHandler.js +26 -37
  182. package/dist/commands/setup/realtime/templates/realtime.ts.template +1 -1
  183. package/dist/commands/setup/realtime/templates/subscriptions/countdown/countdown.ts.template +1 -1
  184. package/dist/commands/setup/realtime/templates/subscriptions/newMessage/newMessage.ts.template +1 -1
  185. package/dist/commands/setup/server-file/serverFile.js +1 -1
  186. package/dist/commands/setup/server-file/serverFileHandler.js +18 -10
  187. package/dist/commands/setup/tenancy/authCodemod.js +66 -0
  188. package/dist/commands/setup/tenancy/dbCodemod.js +64 -0
  189. package/dist/commands/setup/tenancy/graphqlCodemod.js +88 -0
  190. package/dist/commands/setup/tenancy/preflight.js +49 -0
  191. package/dist/commands/setup/tenancy/schemaPrisma.js +81 -0
  192. package/dist/commands/setup/tenancy/signupCodemod.js +153 -0
  193. package/dist/commands/setup/tenancy/templates/InvitePage.tsx.template +63 -0
  194. package/dist/commands/setup/tenancy/templates/OrgScope.tsx.template +40 -0
  195. package/dist/commands/setup/tenancy/templates/ensureDefaultOrganizations.dataMigration.ts.template +39 -0
  196. package/dist/commands/setup/tenancy/templates/organizations.scenarios.ts.template +59 -0
  197. package/dist/commands/setup/tenancy/templates/organizations.sdl.ts.template +89 -0
  198. package/dist/commands/setup/tenancy/templates/organizations.test.ts.template +389 -0
  199. package/dist/commands/setup/tenancy/templates/organizations.ts.template +394 -0
  200. package/dist/commands/setup/tenancy/templates/requireMembership.test.ts.template +35 -0
  201. package/dist/commands/setup/tenancy/templates/requireMembership.ts.template +25 -0
  202. package/dist/commands/setup/tenancy/tenancy.js +30 -0
  203. package/dist/commands/setup/tenancy/tenancyHandler.js +425 -0
  204. package/dist/commands/setup/ui/helpers/helpers.js +5 -1
  205. package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +16 -8
  206. package/dist/commands/setup/ui/libraries/mantineHandler.js +26 -16
  207. package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +40 -29
  208. package/dist/commands/setup/uploads/schemaPrisma.js +41 -0
  209. package/dist/commands/setup/uploads/serverFile.js +151 -0
  210. package/dist/commands/setup/uploads/templates/requireUploadToken.ts.template +15 -0
  211. package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +23 -24
  212. package/dist/commands/setup/uploads/templates/uploads.sdl.ts.template +79 -0
  213. package/dist/commands/setup/uploads/templates/uploads.ts.template +89 -0
  214. package/dist/commands/setup/uploads/templates/withDataUri.ts.template +14 -0
  215. package/dist/commands/setup/uploads/templates/withSignedUrl.ts.template +16 -0
  216. package/dist/commands/setup/uploads/uploads.js +49 -7
  217. package/dist/commands/setup/uploads/uploadsHandler.js +266 -72
  218. package/dist/commands/setup.js +5 -4
  219. package/dist/commands/studio.js +1 -1
  220. package/dist/commands/studioHandler.js +2 -2
  221. package/dist/commands/test/datasourceWarning.js +42 -0
  222. package/dist/commands/test/testHandler.js +104 -0
  223. package/dist/commands/test/viteVersionCheck.js +75 -0
  224. package/dist/commands/test.js +16 -19
  225. package/dist/commands/type-check.js +2 -1
  226. package/dist/commands/type-checkHandler.js +25 -18
  227. package/dist/commands/upgrade/preUpgradeScripts.js +11 -11
  228. package/dist/commands/upgrade/upgrade.js +4 -2
  229. package/dist/commands/upgrade/upgradeHandler.js +97 -73
  230. package/dist/index.js +15 -11
  231. package/dist/lib/background.js +22 -1
  232. package/dist/lib/configureStorybook.js +2 -2
  233. package/dist/lib/exec.js +68 -63
  234. package/dist/lib/exit.js +20 -5
  235. package/dist/lib/extendFile.js +23 -13
  236. package/dist/lib/generatePrismaClient.js +48 -12
  237. package/dist/lib/index.js +137 -106
  238. package/dist/lib/loadEnvFiles.js +1 -1
  239. package/dist/lib/locking.js +8 -4
  240. package/dist/lib/merge/algorithms.js +4 -1
  241. package/dist/lib/merge/index.js +78 -41
  242. package/dist/lib/merge/semanticIdentity.js +18 -6
  243. package/dist/lib/merge/strategy.js +86 -36
  244. package/dist/lib/packages.js +23 -13
  245. package/dist/lib/plugin.js +13 -7
  246. package/dist/lib/pluralHelpers.js +6 -2
  247. package/dist/lib/project.js +3 -1
  248. package/dist/lib/rollback.js +7 -7
  249. package/dist/lib/schemaHelpers.js +16 -19
  250. package/dist/lib/test.js +20 -5
  251. package/dist/lib/updateCheck.js +47 -18
  252. package/dist/middleware/checkNodeVersion.js +9 -4
  253. package/dist/middleware/{detectProjectRxVersion.js → detectProjectCedarVersion.js} +2 -2
  254. package/dist/plugin.js +18 -12
  255. package/dist/telemetry/exporter.js +12 -5
  256. package/dist/telemetry/index.js +4 -3
  257. package/dist/telemetry/resource.js +9 -12
  258. package/dist/telemetry/send.js +14 -10
  259. package/dist/testLib/cells.js +5 -3
  260. package/package.json +44 -41
  261. package/LICENSE +0 -21
  262. package/dist/commands/consoleHandler.js +0 -68
  263. package/dist/commands/setup/tsconfig/tsconfig.js +0 -25
  264. package/dist/commands/setup/tsconfig/tsconfigHandler.js +0 -59
  265. package/dist/commands/setup/uploads/dbCodemod.js +0 -28
  266. package/dist/commands/setup/uploads/templates/signedUrl.ts.template +0 -21
  267. package/dist/commands/setup/vite/templates/vite.config.ts.template +0 -19
  268. package/dist/commands/setup/vite/vite.js +0 -38
  269. package/dist/commands/setup/vite/viteHandler.js +0 -83
  270. package/dist/commands/testEsm.js +0 -36
  271. package/dist/commands/testHandler.js +0 -137
  272. package/dist/commands/testHandlerEsm.js +0 -85
  273. package/dist/commands/ts-to-js.js +0 -20
  274. package/dist/lib/cedarPluralize.js +0 -56
  275. package/dist/lib/colors.js +0 -18
  276. package/dist/testLib/getFilesWithPattern.js +0 -21
  277. /package/dist/{index.d.js → global.d.js} +0 -0
@@ -5,21 +5,21 @@ import { Document } from './Document'
5
5
  import Routes from './Routes'
6
6
 
7
7
  /**
8
- * When `#redwood-app` isn't empty then it's very likely that you're using
8
+ * When `#cedar-app` isn't empty then it's very likely that you're using
9
9
  * prerendering. So React attaches event listeners to the existing markup
10
10
  * rather than replacing it.
11
11
  * https://react.dev/reference/react-dom/client/hydrateRoot
12
12
  */
13
- const redwoodAppElement = document.getElementById('redwood-app')
13
+ const cedarAppElement = document.getElementById('cedar-app')
14
14
 
15
- if (!redwoodAppElement) {
15
+ if (!cedarAppElement) {
16
16
  throw new Error(
17
- "Could not find an element with ID 'redwood-app'. Please ensure it " +
18
- "exists in your 'web/src/index.html' file."
17
+ 'Could not find an element with ID "cedar-app". Please ensure it exists ' +
18
+ 'in your `web/index.html` file.'
19
19
  )
20
20
  }
21
21
 
22
- if (redwoodAppElement.children?.length > 0) {
22
+ if (cedarAppElement.children?.length > 0) {
23
23
  hydrateRoot(
24
24
  document,
25
25
  <Document css={window.__assetMap?.()?.css}>
@@ -9,16 +9,16 @@
9
9
  "skipLibCheck": false,
10
10
  "rootDirs": [
11
11
  "./src",
12
- "../.redwood/types/mirror/web/src",
12
+ "../.cedar/types/mirror/web/src",
13
13
  "../api/src",
14
- "../.redwood/types/mirror/api/src"
14
+ "../.cedar/types/mirror/api/src"
15
15
  ],
16
16
  "paths": {
17
17
  "src/*": [
18
18
  "./src/*",
19
- "../.redwood/types/mirror/web/src/*",
19
+ "../.cedar/types/mirror/web/src/*",
20
20
  "../api/src/*",
21
- "../.redwood/types/mirror/api/src/*"
21
+ "../.cedar/types/mirror/api/src/*"
22
22
  ],
23
23
  "$api/*": [
24
24
  "../api/*"
@@ -46,8 +46,8 @@
46
46
  "include": [
47
47
  "src",
48
48
  "config",
49
- "../.redwood/types/includes/all-*",
50
- "../.redwood/types/includes/web-*",
49
+ "../.cedar/types/includes/all-*",
50
+ "../.cedar/types/includes/web-*",
51
51
  "../types",
52
52
  "./types"
53
53
  ]
@@ -2,45 +2,47 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import ansis from "ansis";
4
4
  import { terminalLink } from "termi-link";
5
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
5
6
  import { getPaths } from "../../lib/index.js";
6
7
  import { isTypeScriptProject, serverFileExists } from "../../lib/project.js";
7
- const link = (topicId, isTerminal = false) => {
8
+ function link(topicId, isTerminal = false) {
8
9
  const communityLink = `https://community.redwoodjs.com/t/${topicId}`;
9
10
  if (isTerminal) {
10
11
  return terminalLink(communityLink, communityLink);
11
12
  } else {
12
13
  return communityLink;
13
14
  }
14
- };
15
- const getEpilogue = (command, description, topicId, isTerminal = false) => `This is an experimental feature to: ${description}.
15
+ }
16
+ function getEpilogue(command, description, topicId, isTerminal = false) {
17
+ let epilogue = `This is an experimental feature to: ${description}.
18
+
19
+ If you need help with ${command}, please join our Discord community.
20
+ -> ${terminalLink("", "https://cedarjs.com/discord")}`;
21
+ if (topicId) {
22
+ epilogue += `
16
23
 
17
- Please find documentation and links to provide feedback for ${command} at:
18
- -> ${link(
19
- topicId,
20
- isTerminal
21
- )}`;
22
- const printTaskEpilogue = (command, description, topicId) => {
24
+ You might also be able to find some information at:
25
+ -> ${link(topicId, isTerminal)}`;
26
+ }
27
+ return epilogue;
28
+ }
29
+ function printTaskEpilogue(command, description, topicId) {
30
+ const orangeLine = ansis.hex("#ff845e")("-".repeat(64));
23
31
  console.log(
24
- `${ansis.hex("#ff845e")(
25
- `------------------------------------------------------------------
26
- \u{1F9EA} ${ansis.green(
27
- "Experimental Feature"
28
- )} \u{1F9EA}
29
- ------------------------------------------------------------------`
30
- )}`
32
+ [
33
+ orangeLine,
34
+ `\u{1F9EA} ${ansis.green("Experimental Feature")} \u{1F9EA}`,
35
+ orangeLine
36
+ ].join("\n")
31
37
  );
32
38
  console.log(getEpilogue(command, description, topicId, false));
33
- console.log(
34
- `${ansis.hex("#ff845e")(
35
- "------------------------------------------------------------------"
36
- )}
37
- `
38
- );
39
- };
39
+ console.log(`${orangeLine}
40
+ `);
41
+ }
40
42
  const isServerFileSetup = () => {
41
43
  if (!serverFileExists()) {
42
44
  throw new Error(
43
- "CedarJS Realtime requires a serverful environment. Please run `yarn cedarjs setup server-file` first."
45
+ `CedarJS Realtime requires a serverful environment. Please run \`${formatCedarCommand(["setup", "server-file"])}\` first.`
44
46
  );
45
47
  }
46
48
  return true;
@@ -55,7 +57,7 @@ const realtimeExists = () => {
55
57
  const isRealtimeSetup = () => {
56
58
  if (!realtimeExists()) {
57
59
  throw new Error(
58
- "Adding realtime events requires that CedarJS Realtime is setup. Please run `yarn cedar setup realtime` first."
60
+ `Adding realtime events requires that CedarJS Realtime is setup. Please run \`${formatCedarCommand(["setup", "realtime"])}\` first.`
59
61
  );
60
62
  }
61
63
  return true;
@@ -1,5 +1,6 @@
1
1
  import { terminalLink } from "termi-link";
2
- import detectRxVersion from "../middleware/detectProjectRxVersion.js";
2
+ import { detectCedarVersion } from "../middleware/detectProjectCedarVersion.js";
3
+ import * as experimentalLiveQueries from "./experimental/live-queries/liveQueries.js";
3
4
  import * as experimentalInngest from "./experimental/setupInngest.js";
4
5
  import * as experimentalOpenTelemetry from "./experimental/setupOpentelemetry.js";
5
6
  import * as experimentalReactCompiler from "./experimental/setupReactCompiler.js";
@@ -8,7 +9,7 @@ import * as experimentalStreamingSsr from "./experimental/setupStreamingSsr.js";
8
9
  const command = "experimental <command>";
9
10
  const aliases = ["exp"];
10
11
  const description = "Run or setup experimental features";
11
- const builder = (yargs) => yargs.command(experimentalInngest).command(experimentalOpenTelemetry).command(experimentalReactCompiler).command(experimentalRsc).command(experimentalStreamingSsr).demandCommand().middleware(detectRxVersion).epilogue(
12
+ const builder = (yargs) => yargs.command(experimentalInngest).command(experimentalLiveQueries).command(experimentalOpenTelemetry).command(experimentalReactCompiler).command(experimentalRsc).command(experimentalStreamingSsr).demandCommand().middleware(detectCedarVersion).epilogue(
12
13
  `Also see the ${terminalLink(
13
14
  "CedarJS CLI Reference",
14
15
  "https://cedarjs.com/docs/cli-commands#experimental"
@@ -22,6 +22,26 @@ const builder = createBuilder({
22
22
  default: "",
23
23
  description: "Use to enforce a specific query name within the generated cell - must be unique.",
24
24
  type: "string"
25
+ },
26
+ beforeQuery: {
27
+ default: false,
28
+ description: "Include a typed `beforeQuery` stub for configuring the query (e.g. variables, fetch policy).",
29
+ type: "boolean"
30
+ },
31
+ afterQuery: {
32
+ default: false,
33
+ description: "Include a typed `afterQuery` stub for sanitizing data returned from the query.",
34
+ type: "boolean"
35
+ },
36
+ isEmpty: {
37
+ default: false,
38
+ description: "Include a typed `isEmpty` stub for overriding the default check for the Empty component.",
39
+ type: "boolean"
40
+ },
41
+ fragment: {
42
+ default: "",
43
+ description: "Generate a fragment cell (exports FRAGMENT instead of QUERY) that reads its data from a parent Cell, given the GraphQL type it selects from - e.g. --fragment User.",
44
+ type: "string"
25
45
  }
26
46
  };
27
47
  }
@@ -1,7 +1,8 @@
1
1
  import pascalcase from "pascalcase";
2
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
2
3
  import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
3
- import { isPlural, singularize } from "../../../lib/cedarPluralize.js";
4
- import { nameVariants, transformTSToJS } from "../../../lib/index.js";
4
+ import { isPlural, singularize } from "@cedarjs/utils/cedarPluralize";
5
+ import { nameVariants, transformTSToJSMap } from "../../../lib/index.js";
5
6
  import { isWordPluralizable } from "../../../lib/pluralHelpers.js";
6
7
  import { addFunctionToRollback } from "../../../lib/rollback.js";
7
8
  import { getSchema } from "../../../lib/schemaHelpers.js";
@@ -18,8 +19,19 @@ import {
18
19
  uniqueOperationName
19
20
  } from "./utils/utils.js";
20
21
  const COMPONENT_SUFFIX = "Cell";
21
- const REDWOOD_WEB_PATH_NAME = "components";
22
- const files = async ({ name, typescript, ...argv }) => {
22
+ const CEDAR_WEB_PATH_NAME = "components";
23
+ const files = async ({
24
+ name,
25
+ typescript = false,
26
+ list = false,
27
+ query,
28
+ stories,
29
+ tests,
30
+ beforeQuery = false,
31
+ afterQuery = false,
32
+ isEmpty = false,
33
+ fragment = ""
34
+ }) => {
23
35
  let cellName = removeGeneratorName(name, "cell");
24
36
  let idName = "id";
25
37
  let idType;
@@ -27,22 +39,49 @@ const files = async ({ name, typescript, ...argv }) => {
27
39
  let model = null;
28
40
  let templateNameSuffix = "";
29
41
  let typeName = cellName;
30
- const shouldGenerateList = (isWordPluralizable(cellName) ? isPlural(cellName) : argv.list) || argv.list;
31
- try {
32
- model = await getSchema(pascalcase(singularize(cellName)));
33
- idName = getIdName(model);
34
- idType = getIdType(model);
35
- typeName = model.name;
36
- mockIdValues = idType === "String" ? mockIdValues.map((value) => `'${value}'`) : mockIdValues;
37
- } catch {
38
- idType = "Int";
42
+ if (fragment) {
43
+ if (list) {
44
+ throw new Error(
45
+ "The --list flag cannot be combined with --fragment; fragment cells always render a single item."
46
+ );
47
+ }
48
+ if (beforeQuery) {
49
+ throw new Error(
50
+ "The --before-query flag cannot be combined with --fragment; fragment cells never fire a query of their own."
51
+ );
52
+ }
53
+ if (query) {
54
+ throw new Error(
55
+ "The --query flag cannot be combined with --fragment; fragment cells don't have an operation name."
56
+ );
57
+ }
58
+ }
59
+ const shouldGenerateList = !fragment && ((isWordPluralizable(cellName) ? isPlural(cellName) : list) || list);
60
+ if (!fragment) {
61
+ try {
62
+ model = await getSchema(pascalcase(singularize(cellName)));
63
+ idName = getIdName(model);
64
+ idType = getIdType(model);
65
+ typeName = model.name;
66
+ mockIdValues = idType === "String" ? mockIdValues.map((value) => `'${value}'`) : mockIdValues;
67
+ } catch {
68
+ idType = "Int";
69
+ }
39
70
  }
40
71
  if (shouldGenerateList) {
41
72
  cellName = forcePluralizeWord(cellName);
42
73
  templateNameSuffix = "List";
43
74
  }
44
- let operationName = argv.query;
45
- if (operationName) {
75
+ let operationName = query;
76
+ let fragmentName;
77
+ let fragmentOnType;
78
+ let fragmentPropName;
79
+ if (fragment) {
80
+ const fragmentTypeVariants = nameVariants(fragment);
81
+ fragmentOnType = fragmentTypeVariants.pascalName;
82
+ fragmentPropName = fragmentTypeVariants.camelName;
83
+ fragmentName = `${nameVariants(cellName).pascalName}Cell_${fragmentPropName}`;
84
+ } else if (operationName) {
46
85
  const userSpecifiedOperationNameIsUnique = await operationNameIsUnique(operationName);
47
86
  if (!userSpecifiedOperationNameIsUnique) {
48
87
  throw new Error(`Specified query name: "${operationName}" is not unique!`);
@@ -57,23 +96,32 @@ const files = async ({ name, typescript, ...argv }) => {
57
96
  name: cellName,
58
97
  suffix: COMPONENT_SUFFIX,
59
98
  extension,
60
- webPathSection: REDWOOD_WEB_PATH_NAME,
99
+ webPathSection: CEDAR_WEB_PATH_NAME,
61
100
  generator: "cell",
62
- templatePath: `cell${templateNameSuffix}.tsx.template`,
63
- templateVars: {
101
+ templatePath: fragment ? "cellFragment.tsx.template" : `cell${templateNameSuffix}.tsx.template`,
102
+ templateVars: fragment ? {
103
+ fragmentName,
104
+ fragmentOnType,
105
+ camelName: fragmentPropName,
106
+ afterQuery,
107
+ isEmpty
108
+ } : {
64
109
  operationName,
65
110
  idName,
66
- idType
111
+ idType,
112
+ beforeQuery,
113
+ afterQuery,
114
+ isEmpty
67
115
  }
68
116
  });
69
117
  const testFile = await templateForComponentFile({
70
118
  name: cellName,
71
119
  suffix: COMPONENT_SUFFIX,
72
120
  extension: `.test${extension}`,
73
- webPathSection: REDWOOD_WEB_PATH_NAME,
121
+ webPathSection: CEDAR_WEB_PATH_NAME,
74
122
  generator: "cell",
75
- templatePath: "test.js.template",
76
- templateVars: {
123
+ templatePath: fragment ? "testFragment.js.template" : "test.js.template",
124
+ templateVars: fragment ? { camelName: fragmentPropName } : {
77
125
  idName: shouldGenerateList ? void 0 : idName,
78
126
  mockIdValues: shouldGenerateList ? void 0 : mockIdValues
79
127
  }
@@ -82,46 +130,47 @@ const files = async ({ name, typescript, ...argv }) => {
82
130
  name: cellName,
83
131
  suffix: COMPONENT_SUFFIX,
84
132
  extension: `.stories${extension}`,
85
- webPathSection: REDWOOD_WEB_PATH_NAME,
133
+ webPathSection: CEDAR_WEB_PATH_NAME,
86
134
  generator: "cell",
87
- templatePath: "stories.tsx.template"
135
+ templatePath: fragment ? "storiesFragment.tsx.template" : "stories.tsx.template"
88
136
  });
89
137
  const mockFile = await templateForComponentFile({
90
138
  name: cellName,
91
139
  suffix: COMPONENT_SUFFIX,
92
140
  extension: typescript ? ".mock.ts" : ".mock.js",
93
- webPathSection: REDWOOD_WEB_PATH_NAME,
141
+ webPathSection: CEDAR_WEB_PATH_NAME,
94
142
  generator: "cell",
95
143
  templatePath: `mock${templateNameSuffix}.ts.template`,
96
- templateVars: {
144
+ templateVars: fragment ? {
145
+ idName,
146
+ mockIdValues,
147
+ typeName: fragmentOnType,
148
+ camelName: fragmentPropName
149
+ } : {
97
150
  idName,
98
151
  mockIdValues,
99
152
  typeName
100
153
  }
101
154
  });
102
155
  const files2 = [cellFile];
103
- if (argv.stories) {
156
+ if (stories) {
104
157
  files2.push(storiesFile);
105
158
  }
106
- if (argv.tests) {
159
+ if (tests) {
107
160
  files2.push(testFile);
108
161
  }
109
- if (argv.stories || argv.tests) {
162
+ if (stories || tests) {
110
163
  files2.push(mockFile);
111
164
  }
112
- return files2.reduce(async (accP, [outputPath, content]) => {
113
- const acc = await accP;
114
- const template = typescript ? content : await transformTSToJS(outputPath, content);
115
- return {
116
- [outputPath]: template,
117
- ...acc
118
- };
119
- }, Promise.resolve({}));
165
+ return transformTSToJSMap(files2, typescript);
120
166
  };
121
167
  const handler = createHandler({
122
168
  componentName: "cell",
123
169
  filesFn: files,
124
- includeAdditionalTasks: ({ name: cellName }) => {
170
+ includeAdditionalTasks: ({
171
+ name: cellName,
172
+ fragment
173
+ }) => {
125
174
  return [
126
175
  {
127
176
  title: `Generating types ...`,
@@ -129,7 +178,7 @@ const handler = createHandler({
129
178
  const queryFieldName = nameVariants(
130
179
  removeGeneratorName(cellName, "cell")
131
180
  ).camelName;
132
- const projectHasSdl = await checkProjectForQueryField(queryFieldName);
181
+ const projectHasSdl = Boolean(fragment) || await checkProjectForQueryField(queryFieldName);
133
182
  if (projectHasSdl) {
134
183
  const { errors } = await generateTypes();
135
184
  for (const { message, error } of errors) {
@@ -141,7 +190,7 @@ const handler = createHandler({
141
190
  addFunctionToRollback(generateTypes, true);
142
191
  } else {
143
192
  task.skip(
144
- `Skipping type generation: no SDL defined for "${queryFieldName}". To generate types, run 'yarn cedar generate sdl ${queryFieldName}'.`
193
+ `Skipping type generation: no SDL defined for "${queryFieldName}". To generate types, run '${formatCedarCommand(["generate", "sdl", queryFieldName])}'.`
145
194
  );
146
195
  }
147
196
  }
@@ -6,7 +6,9 @@ import type {
6
6
  import type {
7
7
  CellSuccessProps,
8
8
  CellFailureProps,
9
- TypedDocumentNode,
9
+ TypedDocumentNode,<% if (beforeQuery) { %>
10
+ CellBeforeQueryResult,<% } %><% if (afterQuery || isEmpty) { %>
11
+ DataObject,<% } %>
10
12
  } from '@cedarjs/web'
11
13
 
12
14
  export const QUERY: TypedDocumentNode<
@@ -19,7 +21,24 @@ export const QUERY: TypedDocumentNode<
19
21
  }
20
22
  }
21
23
  `
22
-
24
+ <% if (beforeQuery) { %>
25
+ export const beforeQuery = (
26
+ props: ${operationName}Variables,
27
+ ): CellBeforeQueryResult<${operationName}Variables> => {
28
+ return { variables: props, fetchPolicy: 'cache-and-network' }
29
+ }
30
+ <% } %><% if (isEmpty) { %>
31
+ export const isEmpty = (
32
+ data: DataObject,
33
+ { isDataEmpty }: { isDataEmpty: (data: DataObject) => boolean },
34
+ ) => {
35
+ return isDataEmpty(data)
36
+ }
37
+ <% } %><% if (afterQuery) { %>
38
+ export const afterQuery = (data: DataObject): DataObject => {
39
+ return data
40
+ }
41
+ <% } %>
23
42
  export const Loading = () => <div>Loading...</div>
24
43
 
25
44
  export const Empty = () => <div>Empty</div>
@@ -0,0 +1,43 @@
1
+ import type { ${fragmentName} } from 'types/graphql'
2
+
3
+ import type {
4
+ CellSuccessProps,<% if (afterQuery || isEmpty) { %>
5
+ DataObject,<% } %>
6
+ } from '@cedarjs/web'
7
+
8
+ // A parent Cell spreads this fragment by name in its own QUERY, and passes
9
+ // the matching field down as the `${camelName}` prop - no import needed,
10
+ // just render <${pascalName}Cell />:
11
+ //
12
+ // query FindSomething($id: Int!) {
13
+ // something(id: $id) {
14
+ // id
15
+ // ...${fragmentName}
16
+ // }
17
+ // }
18
+ //
19
+ // <${pascalName}Cell ${camelName}={something} />
20
+ export const FRAGMENT = gql`
21
+ fragment ${fragmentName} on ${fragmentOnType} {
22
+ id
23
+ }
24
+ `
25
+ <% if (isEmpty) { %>
26
+ export const isEmpty = (
27
+ data: DataObject,
28
+ { isDataEmpty }: { isDataEmpty: (data: DataObject) => boolean },
29
+ ) => {
30
+ return isDataEmpty(data)
31
+ }
32
+ <% } %><% if (afterQuery) { %>
33
+ export const afterQuery = (data: DataObject): DataObject => {
34
+ return data
35
+ }
36
+ <% } %>
37
+ export const Empty = () => <div>Empty</div>
38
+
39
+ export const Success = ({
40
+ ${camelName},
41
+ }: CellSuccessProps<{ ${camelName}: ${fragmentName} }>) => {
42
+ return <div>{JSON.stringify(${camelName})}</div>
43
+ }
@@ -3,7 +3,9 @@ import type { ${operationName}, ${operationName}Variables } from 'types/graphql
3
3
  import type {
4
4
  CellSuccessProps,
5
5
  CellFailureProps,
6
- TypedDocumentNode,
6
+ TypedDocumentNode,<% if (beforeQuery) { %>
7
+ CellBeforeQueryResult,<% } %><% if (afterQuery || isEmpty) { %>
8
+ DataObject,<% } %>
7
9
  } from '@cedarjs/web'
8
10
 
9
11
  export const QUERY: TypedDocumentNode<
@@ -16,7 +18,24 @@ export const QUERY: TypedDocumentNode<
16
18
  }
17
19
  }
18
20
  `
19
-
21
+ <% if (beforeQuery) { %>
22
+ export const beforeQuery = (
23
+ props: ${operationName}Variables,
24
+ ): CellBeforeQueryResult<${operationName}Variables> => {
25
+ return { variables: props, fetchPolicy: 'cache-and-network' }
26
+ }
27
+ <% } %><% if (isEmpty) { %>
28
+ export const isEmpty = (
29
+ data: DataObject,
30
+ { isDataEmpty }: { isDataEmpty: (data: DataObject) => boolean },
31
+ ) => {
32
+ return isDataEmpty(data)
33
+ }
34
+ <% } %><% if (afterQuery) { %>
35
+ export const afterQuery = (data: DataObject): DataObject => {
36
+ return data
37
+ }
38
+ <% } %>
20
39
  export const Loading = () => <div>Loading...</div>
21
40
 
22
41
  export const Empty = () => <div>Empty</div>
@@ -0,0 +1,23 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+
3
+ import { Empty, Success } from './${pascalName}Cell'
4
+ import { standard } from './${pascalName}Cell.mock'
5
+
6
+ const meta: Meta = {
7
+ title: 'Cells/${pascalName}Cell',
8
+ tags: ['autodocs']
9
+ }
10
+
11
+ export default meta
12
+
13
+ export const empty: StoryObj<typeof Empty> = {
14
+ render: () => {
15
+ return Empty ? <Empty /> : <></>
16
+ }
17
+ }
18
+
19
+ export const success: StoryObj<typeof Success> = {
20
+ render: (args) => {
21
+ return Success ? <Success {...standard()} {...args} /> : <></>
22
+ }
23
+ }
@@ -7,7 +7,7 @@ import { standard } from './${pascalName}Cell.mock'
7
7
  // and can fail without adjustments, e.g. Float and DateTime types.
8
8
  // Please refer to the RedwoodJS Testing Docs:
9
9
  // https://cedarjs.com/docs/testing#testing-cells
10
- // https://cedarjs.com/docs/testing#jest-expect-type-considerations
10
+ // https://cedarjs.com/docs/testing#expect-type-considerations
11
11
 
12
12
  describe('${pascalName}Cell', () => {
13
13
  it('renders Loading successfully', () => {
@@ -0,0 +1,30 @@
1
+ import { render } from '@cedarjs/testing/web'
2
+
3
+ import { Empty, Success } from './${pascalName}Cell'
4
+ import { standard } from './${pascalName}Cell.mock'
5
+
6
+ // Generated boilerplate tests do not account for all circumstances
7
+ // and can fail without adjustments, e.g. Float and DateTime types.
8
+ // Please refer to the RedwoodJS Testing Docs:
9
+ // https://cedarjs.com/docs/testing#testing-cells
10
+ // https://cedarjs.com/docs/testing#expect-type-considerations
11
+
12
+ describe('${pascalName}Cell', () => {
13
+ it('renders Empty successfully', async () => {
14
+ expect(() => {
15
+ render(<Empty />)
16
+ }).not.toThrow()
17
+ })
18
+
19
+ // When you're ready to test the actual output of your component render
20
+ // you could test that, for example, certain text is present:
21
+ //
22
+ // 1. import { screen } from '@cedarjs/testing/web'
23
+ // 2. Add test: expect(screen.getByText('Hello, world')).toBeInTheDocument()
24
+
25
+ it('renders Success successfully', async () => {
26
+ expect(() => {
27
+ render(<Success ${camelName}={standard().${camelName}} />)
28
+ }).not.toThrow()
29
+ })
30
+ })
@@ -1,14 +1,19 @@
1
- import { transformTSToJS } from "../../../lib/index.js";
1
+ import { transformTSToJSMap } from "../../../lib/index.js";
2
2
  import {
3
3
  createHandler,
4
4
  templateForComponentFile
5
5
  } from "../yargsHandlerHelpers.js";
6
- const REDWOOD_WEB_PATH_NAME = "components";
7
- const files = async ({ name, typescript = false, ...argv }) => {
6
+ const CEDAR_WEB_PATH_NAME = "components";
7
+ const files = async ({
8
+ name,
9
+ typescript = false,
10
+ stories,
11
+ tests
12
+ }) => {
8
13
  const extension = typescript ? ".tsx" : ".jsx";
9
14
  const componentFile = await templateForComponentFile({
10
15
  name,
11
- webPathSection: REDWOOD_WEB_PATH_NAME,
16
+ webPathSection: CEDAR_WEB_PATH_NAME,
12
17
  extension,
13
18
  generator: "component",
14
19
  templatePath: "component.tsx.template"
@@ -16,34 +21,27 @@ const files = async ({ name, typescript = false, ...argv }) => {
16
21
  const testFile = await templateForComponentFile({
17
22
  name,
18
23
  extension: `.test${extension}`,
19
- webPathSection: REDWOOD_WEB_PATH_NAME,
24
+ webPathSection: CEDAR_WEB_PATH_NAME,
20
25
  generator: "component",
21
26
  templatePath: "test.tsx.template"
22
27
  });
23
28
  const storiesFile = await templateForComponentFile({
24
29
  name,
25
30
  extension: `.stories${extension}`,
26
- webPathSection: REDWOOD_WEB_PATH_NAME,
31
+ webPathSection: CEDAR_WEB_PATH_NAME,
27
32
  generator: "component",
28
33
  // Using two different template files here because we have a TS-specific
29
34
  // information in a comment in the .tsx template
30
35
  templatePath: typescript ? "stories.tsx.template" : "stories.jsx.template"
31
36
  });
32
37
  const files2 = [componentFile];
33
- if (argv.stories) {
38
+ if (stories) {
34
39
  files2.push(storiesFile);
35
40
  }
36
- if (argv.tests) {
41
+ if (tests) {
37
42
  files2.push(testFile);
38
43
  }
39
- return files2.reduce(async (accP, [outputPath, content]) => {
40
- const acc = await accP;
41
- const template = typescript ? content : await transformTSToJS(outputPath, content);
42
- return {
43
- [outputPath]: template,
44
- ...acc
45
- };
46
- }, Promise.resolve({}));
44
+ return transformTSToJSMap(files2, typescript);
47
45
  };
48
46
  const handler = createHandler({
49
47
  componentName: "component",