@cedarjs/cli 4.2.1-next.0 → 4.2.1-next.269

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 (153) hide show
  1. package/dist/cfw.js +8 -6
  2. package/dist/commands/build/buildHandler.js +43 -42
  3. package/dist/commands/build/buildPackagesTask.js +6 -6
  4. package/dist/commands/build.js +7 -1
  5. package/dist/commands/deploy/baremetal/SshExecutor.js +13 -4
  6. package/dist/commands/deploy/baremetal/baremetalHandler.js +117 -65
  7. package/dist/commands/deploy/baremetal.js +24 -3
  8. package/dist/commands/deploy/flightcontrolHandler.js +16 -14
  9. package/dist/commands/deploy/helpers/deployHandler.js +10 -5
  10. package/dist/commands/deploy/packing/nft.js +1 -2
  11. package/dist/commands/deploy/render.js +1 -1
  12. package/dist/commands/deploy/renderHandler.js +22 -12
  13. package/dist/commands/deploy/serverlessHandler.js +67 -25
  14. package/dist/commands/destroy/component/component.js +2 -3
  15. package/dist/commands/destroy/directive/directive.js +1 -3
  16. package/dist/commands/destroy/directive/directiveHandler.js +2 -4
  17. package/dist/commands/destroy/function/function.js +1 -3
  18. package/dist/commands/destroy/handlerHelpers.js +16 -16
  19. package/dist/commands/destroy/helpers.js +8 -2
  20. package/dist/commands/destroy/layout/layout.js +1 -2
  21. package/dist/commands/destroy/page/pageHandler.js +1 -1
  22. package/dist/commands/destroy/scaffold/scaffoldHandler.js +28 -9
  23. package/dist/commands/destroy/sdl/sdlHandler.js +1 -1
  24. package/dist/commands/dev/devHandler.js +25 -25
  25. package/dist/commands/dev.js +3 -0
  26. package/dist/commands/experimental/live-queries/liveQueriesHandler.js +110 -4
  27. package/dist/commands/experimental/setupInngest.js +1 -1
  28. package/dist/commands/experimental/setupInngestHandler.js +12 -11
  29. package/dist/commands/experimental/setupOpentelemetry.js +1 -1
  30. package/dist/commands/experimental/setupOpentelemetryHandler.js +11 -7
  31. package/dist/commands/experimental/setupReactCompiler.js +1 -1
  32. package/dist/commands/experimental/setupReactCompilerHandler.js +45 -30
  33. package/dist/commands/experimental/setupRscHandler.js +14 -11
  34. package/dist/commands/experimental/setupStreamingSsr.js +1 -1
  35. package/dist/commands/experimental/setupStreamingSsrHandler.js +46 -31
  36. package/dist/commands/experimental/templates/rsc/Document.tsx.template +1 -1
  37. package/dist/commands/experimental/templates/rsc/entry.client.tsx.template +8 -8
  38. package/dist/commands/experimental/templates/streamingSsr/Document.tsx.template +1 -1
  39. package/dist/commands/experimental/templates/streamingSsr/entry.client.tsx.template +6 -6
  40. package/dist/commands/experimental/util.js +3 -2
  41. package/dist/commands/generate/cell/cellHandler.js +22 -21
  42. package/dist/commands/generate/component/componentHandler.js +14 -16
  43. package/dist/commands/generate/dataMigration/dataMigration.js +24 -13
  44. package/dist/commands/generate/dbAuth/dbAuth.js +1 -0
  45. package/dist/commands/generate/dbAuth/dbAuthHandler.js +40 -30
  46. package/dist/commands/generate/directive/directiveHandler.js +12 -14
  47. package/dist/commands/generate/function/function.js +1 -0
  48. package/dist/commands/generate/function/functionHandler.js +12 -17
  49. package/dist/commands/generate/helpers.js +17 -17
  50. package/dist/commands/generate/job/job.js +1 -0
  51. package/dist/commands/generate/job/jobHandler.js +15 -17
  52. package/dist/commands/generate/layout/layoutHandler.js +13 -16
  53. package/dist/commands/generate/model/model.js +1 -0
  54. package/dist/commands/generate/model/modelHandler.js +9 -3
  55. package/dist/commands/generate/ogImage/ogImage.js +1 -0
  56. package/dist/commands/generate/ogImage/ogImageHandler.js +16 -9
  57. package/dist/commands/generate/package/packageHandler.js +32 -49
  58. package/dist/commands/generate/page/pageHandler.js +25 -22
  59. package/dist/commands/generate/realtime/realtime.js +1 -1
  60. package/dist/commands/generate/realtime/realtimeHandler.js +46 -20
  61. package/dist/commands/generate/scaffold/scaffold.js +1 -0
  62. package/dist/commands/generate/scaffold/scaffoldHandler.js +35 -27
  63. package/dist/commands/generate/script/script.js +1 -0
  64. package/dist/commands/generate/script/templates/tsconfig.json.template +14 -0
  65. package/dist/commands/generate/sdl/sdl.js +4 -3
  66. package/dist/commands/generate/sdl/sdlHandler.js +38 -18
  67. package/dist/commands/generate/secret/secret.js +19 -19
  68. package/dist/commands/generate/service/service.js +5 -5
  69. package/dist/commands/generate/service/serviceHandler.js +59 -22
  70. package/dist/commands/generate/yargsCommandHelpers.js +6 -1
  71. package/dist/commands/generate/yargsHandlerHelpers.js +18 -10
  72. package/dist/commands/generate.js +3 -10
  73. package/dist/commands/jobsHandler.js +3 -2
  74. package/dist/commands/prismaHandler.js +10 -9
  75. package/dist/commands/serve.js +84 -137
  76. package/dist/commands/serveApiHandler.js +5 -5
  77. package/dist/commands/serveBothHandler.js +10 -7
  78. package/dist/commands/serveWebHandler.js +2 -2
  79. package/dist/commands/setup/auth/auth.js +12 -6
  80. package/dist/commands/setup/cache/cacheHandler.js +11 -6
  81. package/dist/commands/setup/deploy/deploy.js +4 -3
  82. package/dist/commands/setup/deploy/helpers/helpers.js +5 -1
  83. package/dist/commands/setup/deploy/helpers/index.js +157 -5
  84. package/dist/commands/setup/deploy/providers/baremetalHandler.js +26 -4
  85. package/dist/commands/setup/deploy/providers/coherenceHandler.js +53 -25
  86. package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +33 -23
  87. package/dist/commands/setup/deploy/providers/netlify.js +6 -0
  88. package/dist/commands/setup/deploy/providers/netlifyHandler.js +112 -11
  89. package/dist/commands/setup/deploy/providers/renderHandler.js +10 -5
  90. package/dist/commands/setup/deploy/providers/serverlessHandler.js +5 -3
  91. package/dist/commands/setup/deploy/providers/universal-deploy.js +11 -0
  92. package/dist/commands/setup/deploy/providers/universalDeployHandler.js +188 -0
  93. package/dist/commands/setup/deploy/providers/vercel.js +6 -0
  94. package/dist/commands/setup/deploy/providers/vercelHandler.js +113 -12
  95. package/dist/commands/setup/deploy/templates/baremetal.js +3 -2
  96. package/dist/commands/setup/deploy/templates/flightcontrol.js +60 -49
  97. package/dist/commands/setup/deploy/templates/netlify.js +2 -1
  98. package/dist/commands/setup/deploy/templates/netlifyUD.js +31 -0
  99. package/dist/commands/setup/docker/docker.js +1 -1
  100. package/dist/commands/setup/docker/dockerHandler.js +72 -37
  101. package/dist/commands/setup/docker/templates/Dockerfile.npm +119 -0
  102. package/dist/commands/setup/docker/templates/Dockerfile.pnpm +112 -0
  103. package/dist/commands/setup/docker/templates/{Dockerfile → Dockerfile.yarn} +1 -1
  104. package/dist/commands/setup/docker/templates/docker-compose.dev.yml +2 -2
  105. package/dist/commands/setup/generator/generatorHandler.js +4 -3
  106. package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +2 -2
  107. package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +2 -2
  108. package/dist/commands/setup/i18n/i18nHandler.js +18 -15
  109. package/dist/commands/setup/jobs/jobsHandler.js +10 -5
  110. package/dist/commands/setup/mailer/mailerHandler.js +11 -9
  111. package/dist/commands/setup/package/packageHandler.js +14 -10
  112. package/dist/commands/setup/realtime/realtimeHandler.js +22 -20
  113. package/dist/commands/setup/server-file/serverFileHandler.js +16 -8
  114. package/dist/commands/setup/tsconfig/tsconfigHandler.js +5 -3
  115. package/dist/commands/setup/ui/helpers/helpers.js +5 -1
  116. package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +11 -5
  117. package/dist/commands/setup/ui/libraries/mantineHandler.js +21 -13
  118. package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +38 -26
  119. package/dist/commands/setup/uploads/uploadsHandler.js +7 -4
  120. package/dist/commands/setup.js +1 -2
  121. package/dist/commands/test/testHandler.js +2 -1
  122. package/dist/commands/test/testHandlerEsm.js +2 -2
  123. package/dist/commands/type-checkHandler.js +4 -6
  124. package/dist/commands/upgrade/upgradeHandler.js +2 -4
  125. package/dist/index.js +10 -4
  126. package/dist/lib/configureStorybook.js +2 -2
  127. package/dist/lib/exec.js +36 -24
  128. package/dist/lib/exit.js +19 -4
  129. package/dist/lib/extendFile.js +22 -12
  130. package/dist/lib/index.js +119 -85
  131. package/dist/lib/merge/algorithms.js +4 -1
  132. package/dist/lib/merge/index.js +76 -41
  133. package/dist/lib/merge/semanticIdentity.js +18 -6
  134. package/dist/lib/merge/strategy.js +86 -36
  135. package/dist/lib/packages.js +23 -13
  136. package/dist/lib/plugin.js +12 -5
  137. package/dist/lib/pluralHelpers.js +1 -1
  138. package/dist/lib/project.js +3 -1
  139. package/dist/lib/rollback.js +7 -7
  140. package/dist/lib/schemaHelpers.js +12 -12
  141. package/dist/lib/test.js +4 -0
  142. package/dist/lib/updateCheck.js +6 -4
  143. package/dist/middleware/checkNodeVersion.js +5 -0
  144. package/dist/plugin.js +18 -12
  145. package/dist/telemetry/exporter.js +12 -5
  146. package/dist/telemetry/index.js +4 -3
  147. package/dist/telemetry/resource.js +9 -5
  148. package/dist/telemetry/send.js +14 -10
  149. package/package.json +15 -13
  150. package/dist/commands/setup/vite/templates/vite.config.ts.template +0 -19
  151. package/dist/commands/setup/vite/vite.js +0 -38
  152. package/dist/commands/setup/vite/viteHandler.js +0 -82
  153. /package/dist/{index.d.js → global.d.js} +0 -0
@@ -23,7 +23,7 @@ const handler = async ({ model }) => {
23
23
  const { name } = await verifyModelName({ name: model, isDestroyer: true });
24
24
  await tasks({ model: name }).run();
25
25
  } catch (e) {
26
- console.log(c.error(e.message));
26
+ console.log(c.error(e instanceof Error ? e.message : String(e)));
27
27
  }
28
28
  };
29
29
  export {
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { Writable } from "node:stream";
4
4
  import concurrently from "concurrently";
5
5
  import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
6
+ import { formatRunBinCommand } from "@cedarjs/cli-helpers/packageManager/display";
6
7
  import { shutdownPort } from "@cedarjs/internal/dist/dev";
7
8
  import { generateGqlormArtifacts } from "@cedarjs/internal/dist/generate/gqlormSchema";
8
9
  import { getConfig, getConfigPath } from "@cedarjs/project-config";
@@ -19,6 +20,7 @@ const handler = async ({
19
20
  forward = "",
20
21
  generate = true,
21
22
  apiDebugPort,
23
+ debugBrk,
22
24
  ud = false
23
25
  }) => {
24
26
  recordTelemetryAttributes({
@@ -29,20 +31,16 @@ const handler = async ({
29
31
  const cedarPaths = getPaths();
30
32
  const serverFile = serverFileExists();
31
33
  const apiPreferredPort = parseInt(String(getConfig().api.port));
32
- let apiAvailablePort;
34
+ let apiAvailablePort = apiPreferredPort;
33
35
  let apiPortChangeNeeded = false;
34
- if (workspace.includes("api")) {
35
- if (!serverFile) {
36
- apiAvailablePort = await getFreePort(apiPreferredPort);
37
- if (apiAvailablePort === -1) {
38
- exitWithError(void 0, {
39
- message: `Could not determine a free port for the api server`
40
- });
41
- }
42
- apiPortChangeNeeded = apiAvailablePort !== apiPreferredPort;
43
- } else {
44
- apiAvailablePort = apiPreferredPort;
36
+ if (workspace.includes("api") && !serverFile) {
37
+ apiAvailablePort = await getFreePort(apiPreferredPort);
38
+ if (apiAvailablePort === -1) {
39
+ exitWithError(void 0, {
40
+ message: `Could not determine a free port for the api server`
41
+ });
45
42
  }
43
+ apiPortChangeNeeded = apiAvailablePort !== apiPreferredPort;
46
44
  }
47
45
  let webPreferredPort = parseInt(
48
46
  String(getConfig().web.port)
@@ -117,6 +115,11 @@ const handler = async ({
117
115
  }
118
116
  }
119
117
  if (!ud && !serverFile) {
118
+ if (typeof apiAvailablePort === "undefined" || apiAvailablePort === -1) {
119
+ exitWithError(void 0, {
120
+ message: `Could not determine a free port for the api server`
121
+ });
122
+ }
120
123
  try {
121
124
  await shutdownPort(apiAvailablePort);
122
125
  } catch (e) {
@@ -171,10 +174,11 @@ const handler = async ({
171
174
  return null;
172
175
  }
173
176
  return [
174
- `yarn cross-env NODE_ENV=development cedar-unified-dev`,
177
+ `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-unified-dev"])}`,
175
178
  ` --port ${webAvailablePort}`,
176
179
  ` --apiPort ${apiAvailablePort}`,
177
180
  getApiDebugFlag(apiDebugPort, apiAvailablePort),
181
+ debugBrk ? "--debug-brk" : "",
178
182
  forward
179
183
  ].join(" ").replace(/\s+/g, " ").trim();
180
184
  };
@@ -212,15 +216,11 @@ const handler = async ({
212
216
  const cedarConfigPath = getConfigPath();
213
217
  jobs.push({
214
218
  name: "api",
215
- command: [
216
- "yarn nodemon",
217
- " --quiet",
218
- ` --watch "${cedarConfigPath}"`,
219
- ` --exec "yarn ${serverWatchCommand}`,
220
- ` --port ${apiAvailablePort}`,
221
- ` ${getApiDebugFlag(apiDebugPort, apiAvailablePort)}`,
222
- ` | cedar-log-formatter"`
223
- ].join(" ").replace(/\s+/g, " "),
219
+ command: formatRunBinCommand("nodemon", [
220
+ "--quiet",
221
+ `--watch "${cedarConfigPath}"`,
222
+ `--exec "${formatRunBinCommand(serverWatchCommand)} --port ${apiAvailablePort} ${getApiDebugFlag(apiDebugPort, apiAvailablePort)} | ${formatRunBinCommand("cedar-log-formatter")}"`
223
+ ]),
224
224
  env: {
225
225
  NODE_ENV: "development",
226
226
  NODE_OPTIONS: getDevNodeOptions()
@@ -230,9 +230,9 @@ const handler = async ({
230
230
  });
231
231
  }
232
232
  if (workspace.includes("web")) {
233
- let webCommand = `yarn cross-env NODE_ENV=development cedar-vite-dev ${forward}`;
233
+ let webCommand = `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-vite-dev"])} ${forward}`;
234
234
  if (streamingSsrEnabled) {
235
- webCommand = `yarn cross-env NODE_ENV=development cedar-dev-fe ${forward}`;
235
+ webCommand = `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-dev-fe"])} ${forward}`;
236
236
  }
237
237
  jobs.push({
238
238
  name: "web",
@@ -246,7 +246,7 @@ const handler = async ({
246
246
  if (generate) {
247
247
  jobs.push({
248
248
  name: "gen",
249
- command: "yarn cedar-gen-watch",
249
+ command: formatRunBinCommand("cedar-gen-watch"),
250
250
  prefixColor: "green"
251
251
  });
252
252
  }
@@ -24,6 +24,9 @@ const builder = (yargs) => {
24
24
  }).option("apiDebugPort", {
25
25
  type: "number",
26
26
  description: "Port on which to expose API server debugger. If you supply the flag with no value it defaults to 1 prepended to the api port (e.g. api port 8913 -> debug port 18913)."
27
+ }).option("debugBrk", {
28
+ type: "boolean",
29
+ description: "Wait for a debugger to connect before starting the API dev server, similar to Node.js --inspect-brk. Only works in --ud mode."
27
30
  }).option("ud", {
28
31
  type: "boolean",
29
32
  default: false,
@@ -1,7 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { Listr } from "listr2";
4
- import { addApiPackages, colors as c } from "@cedarjs/cli-helpers";
4
+ import {
5
+ addApiPackages,
6
+ addWebPackages,
7
+ colors as c
8
+ } from "@cedarjs/cli-helpers";
9
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
5
10
  import {
6
11
  getConfigPath,
7
12
  getMigrationsPath,
@@ -14,6 +19,10 @@ function getApiPackageJson() {
14
19
  const apiPackageJsonPath = path.join(getPaths().api.base, "package.json");
15
20
  return JSON.parse(fs.readFileSync(apiPackageJsonPath, "utf-8"));
16
21
  }
22
+ function getWebPackageJson() {
23
+ const webPackageJsonPath = path.join(getPaths().web.base, "package.json");
24
+ return JSON.parse(fs.readFileSync(webPackageJsonPath, "utf-8"));
25
+ }
17
26
  function hasPackage(packageJson, packageName) {
18
27
  return Boolean(
19
28
  packageJson.dependencies?.[packageName] || packageJson.devDependencies?.[packageName]
@@ -147,12 +156,88 @@ function addLiveQueryListenerToGraphqlHandler({ force }) {
147
156
  skipped: false
148
157
  };
149
158
  }
159
+ function addConfigureGqlormToApp({ force }) {
160
+ const appPath = getPaths().web.app;
161
+ if (!fs.existsSync(appPath)) {
162
+ return {
163
+ skipped: true,
164
+ reason: `${path.basename(appPath)} not found`
165
+ };
166
+ }
167
+ const content = fs.readFileSync(appPath, "utf-8");
168
+ const contentLines = content.split("\n");
169
+ const hasGqlormImport = contentLines.some(
170
+ (line) => line.includes("from '@cedarjs/gqlorm/setup'")
171
+ );
172
+ const hasSchemaImport = contentLines.some(
173
+ (line) => line.includes("from '../../.cedar/gqlorm-schema.json'")
174
+ );
175
+ const hasConfigureCall = contentLines.some(
176
+ (line) => line.includes("configureGqlorm({ schema })")
177
+ );
178
+ if (hasGqlormImport && hasSchemaImport && hasConfigureCall && !force) {
179
+ return {
180
+ skipped: true,
181
+ reason: "configureGqlorm is already wired into App"
182
+ };
183
+ }
184
+ if (!hasGqlormImport) {
185
+ const redwoodWebImportIndex = contentLines.findIndex(
186
+ (line) => line.includes("from '@cedarjs/web'")
187
+ );
188
+ if (redwoodWebImportIndex === -1) {
189
+ return {
190
+ skipped: true,
191
+ reason: "Unexpected syntax. Could not find @cedarjs/web import to insert gqlorm import"
192
+ };
193
+ }
194
+ contentLines.splice(
195
+ redwoodWebImportIndex,
196
+ 0,
197
+ "import { configureGqlorm } from '@cedarjs/gqlorm/setup'"
198
+ );
199
+ }
200
+ if (!hasSchemaImport) {
201
+ const fatalErrorPageIndex = contentLines.findIndex(
202
+ (line) => line.includes("import FatalErrorPage from 'src/pages/FatalErrorPage'")
203
+ );
204
+ if (fatalErrorPageIndex === -1) {
205
+ return {
206
+ skipped: true,
207
+ reason: "Unexpected syntax. Could not find FatalErrorPage import to insert schema import"
208
+ };
209
+ }
210
+ contentLines.splice(
211
+ fatalErrorPageIndex + 1,
212
+ 0,
213
+ "import schema from '../../.cedar/gqlorm-schema.json' with { type: 'json' }"
214
+ );
215
+ }
216
+ if (!hasConfigureCall) {
217
+ const appComponentIndex = contentLines.findIndex(
218
+ (line) => /^const App\s*=/.test(line)
219
+ );
220
+ if (appComponentIndex === -1) {
221
+ return {
222
+ skipped: true,
223
+ reason: "Unexpected syntax. Could not find `const App =` to insert configureGqlorm call"
224
+ };
225
+ }
226
+ contentLines.splice(appComponentIndex, 0, "configureGqlorm({ schema })", "");
227
+ }
228
+ fs.writeFileSync(appPath, contentLines.join("\n"));
229
+ return {
230
+ skipped: false
231
+ };
232
+ }
150
233
  async function handler({ force, verbose }) {
151
234
  const projectIsTypescript = isTypeScriptProject();
152
235
  const apiPackageJson = getApiPackageJson();
153
236
  const migrationsPath = await getMigrationsPath(getPaths().api.prismaConfig);
154
237
  const hasRealtimeDependency = hasPackage(apiPackageJson, "@cedarjs/realtime");
155
238
  const hasPgDependency = hasPackage(apiPackageJson, "pg");
239
+ const webPackageJson = getWebPackageJson();
240
+ const hasGqlormDependency = hasPackage(webPackageJson, "@cedarjs/gqlorm");
156
241
  const ext = projectIsTypescript ? "ts" : "js";
157
242
  const migrationTemplatePath = path.resolve(
158
243
  import.meta.dirname,
@@ -181,7 +266,7 @@ async function handler({ force, verbose }) {
181
266
  task: () => {
182
267
  if (!hasRealtimeDependency) {
183
268
  throw new Error(
184
- `@cedarjs/realtime is not installed in your api workspace. Please run ${c.highlight("yarn cedar setup realtime")} first.`
269
+ `@cedarjs/realtime is not installed in your api workspace. Please run ${c.highlight(formatCedarCommand(["setup", "realtime"]))} first.`
185
270
  );
186
271
  }
187
272
  }
@@ -244,7 +329,7 @@ async function handler({ force, verbose }) {
244
329
  },
245
330
  {
246
331
  ...addApiPackages(["pg@^8.18.0"]),
247
- title: "Adding pg dependency to your api side...",
332
+ title: "Adding pg dependency to your api workspace...",
248
333
  skip: () => {
249
334
  if (hasPgDependency) {
250
335
  return "pg is already installed";
@@ -297,6 +382,25 @@ async function handler({ force, verbose }) {
297
382
  }
298
383
  }
299
384
  },
385
+ {
386
+ ...addWebPackages(["@cedarjs/gqlorm"]),
387
+ title: "Adding @cedarjs/gqlorm to your web workspace...",
388
+ skip: () => {
389
+ if (hasGqlormDependency) {
390
+ return "@cedarjs/gqlorm is already installed";
391
+ }
392
+ return false;
393
+ }
394
+ },
395
+ {
396
+ title: "Wiring configureGqlorm into App.tsx...",
397
+ task: (_ctx, task) => {
398
+ const result = addConfigureGqlormToApp({ force });
399
+ if (result.skipped) {
400
+ task.skip(result.reason);
401
+ }
402
+ }
403
+ },
300
404
  {
301
405
  title: "One more thing...",
302
406
  task: (_ctx, task) => {
@@ -305,7 +409,9 @@ async function handler({ force, verbose }) {
305
409
  ${c.success("\nLive query notifications configured!\n")}
306
410
 
307
411
  Apply the migration to activate Postgres notifications:
308
- ${c.highlight("\n\xA0\xA0yarn cedar prisma migrate dev\n")}
412
+ ${c.highlight(`
413
+ \xA0\xA0${formatCedarCommand(["prisma", "migrate", "dev"])}
414
+ `)}
309
415
 
310
416
  You're then ready to use @live queries to get real-time updates as
311
417
  soon as something in your database changes.
@@ -2,7 +2,7 @@ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
2
  import { getEpilogue } from "./util.js";
3
3
  const command = "setup-inngest";
4
4
  const description = "Setup Inngest for background, scheduled, delayed, multi-step, and fan-out jobs";
5
- const EXPERIMENTAL_TOPIC_ID = 4866;
5
+ const EXPERIMENTAL_TOPIC_ID = "4866";
6
6
  const builder = (yargs) => {
7
7
  yargs.option("force", {
8
8
  alias: "f",
@@ -1,6 +1,7 @@
1
- import execa from "execa";
2
1
  import { Listr } from "listr2";
3
2
  import { colors as c } from "@cedarjs/cli-helpers";
3
+ import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
4
+ import { addRootPackages } from "@cedarjs/cli-helpers/packageManager/packages";
4
5
  import { errorTelemetry } from "@cedarjs/telemetry";
5
6
  import { getPaths } from "../../lib/index.js";
6
7
  import { command, description, EXPERIMENTAL_TOPIC_ID } from "./setupInngest.js";
@@ -10,18 +11,16 @@ const handler = async ({ force }) => {
10
11
  {
11
12
  title: `Adding Inngest setup packages for RedwoodJS ...`,
12
13
  task: async () => {
13
- await execa("yarn", ["add", "-D", "inngest-setup-redwoodjs"], {
14
- cwd: getPaths().base
14
+ await addRootPackages(["inngest-setup-redwoodjs"], {
15
+ cwd: getPaths().base,
16
+ dev: true
15
17
  });
16
18
  }
17
19
  },
18
20
  {
19
21
  task: async () => {
20
- const pluginCommands = ["inngest-setup-redwoodjs", "plugin"];
21
- if (force) {
22
- pluginCommands.push("--force");
23
- }
24
- await execa("yarn", [...pluginCommands], {
22
+ const pluginArgs = force ? ["--force"] : [];
23
+ await runBin("inngest-setup-redwoodjs", ["plugin", ...pluginArgs], {
25
24
  stdout: "inherit",
26
25
  cwd: getPaths().base
27
26
  });
@@ -36,9 +35,11 @@ const handler = async ({ force }) => {
36
35
  try {
37
36
  await tasks.run();
38
37
  } catch (e) {
39
- errorTelemetry(process.argv, e.message);
40
- console.error(c.error(e.message));
41
- process.exit(e?.exitCode || 1);
38
+ const message = e instanceof Error ? e.message : String(e);
39
+ const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
40
+ errorTelemetry(process.argv, message);
41
+ console.error(c.error(message));
42
+ process.exit(exitCode);
42
43
  }
43
44
  };
44
45
  export {
@@ -2,7 +2,7 @@ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
2
  import { getEpilogue } from "./util.js";
3
3
  const command = "setup-opentelemetry";
4
4
  const description = "Setup OpenTelemetry within the API side";
5
- const EXPERIMENTAL_TOPIC_ID = 4772;
5
+ const EXPERIMENTAL_TOPIC_ID = "4772";
6
6
  const builder = (yargs) => {
7
7
  yargs.option("force", {
8
8
  alias: "f",
@@ -1,9 +1,9 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
4
- import execa from "execa";
5
4
  import { Listr } from "listr2";
6
5
  import { addApiPackages, colors as c } from "@cedarjs/cli-helpers";
6
+ import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
7
7
  import {
8
8
  getConfigPath,
9
9
  resolveFile,
@@ -18,7 +18,10 @@ import {
18
18
  EXPERIMENTAL_TOPIC_ID
19
19
  } from "./setupOpentelemetry.js";
20
20
  import { printTaskEpilogue } from "./util.js";
21
- const handler = async ({ force, verbose }) => {
21
+ const handler = async ({
22
+ force,
23
+ verbose
24
+ }) => {
22
25
  const ts = isTypeScriptProject();
23
26
  const configTomlPath = getConfigPath();
24
27
  const configFileName = path.basename(configTomlPath);
@@ -170,9 +173,8 @@ const handler = async ({ force, verbose }) => {
170
173
  {
171
174
  title: "Regenerate the Prisma client...",
172
175
  task: (_ctx, _task) => {
173
- return execa(`yarn cedar prisma generate`, {
176
+ return runBin("cedar", ["prisma", "generate"], {
174
177
  stdio: "inherit",
175
- shell: true,
176
178
  cwd: getPaths().web.base
177
179
  });
178
180
  }
@@ -209,9 +211,11 @@ const handler = async ({ force, verbose }) => {
209
211
  try {
210
212
  await tasks.run();
211
213
  } catch (e) {
212
- errorTelemetry(process.argv, e.message);
213
- console.error(c.error(e.message));
214
- process.exit(e?.exitCode || 1);
214
+ const message = e instanceof Error ? e.message : String(e);
215
+ const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
216
+ errorTelemetry(process.argv, message);
217
+ console.error(c.error(message));
218
+ process.exit(exitCode);
215
219
  }
216
220
  };
217
221
  export {
@@ -2,7 +2,7 @@ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
2
  import { getEpilogue } from "./util.js";
3
3
  const command = "setup-react-compiler";
4
4
  const description = "Enable the experimental React Compiler";
5
- const EXPERIMENTAL_TOPIC_ID = 7128;
5
+ const EXPERIMENTAL_TOPIC_ID = "7128";
6
6
  const builder = (yargs) => {
7
7
  yargs.option("force", {
8
8
  alias: "f",
@@ -1,9 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import execa from "execa";
4
3
  import { Listr } from "listr2";
5
4
  import semver from "semver";
6
5
  import { colors as c } from "@cedarjs/cli-helpers";
6
+ import {
7
+ addRootPackages,
8
+ addWorkspacePackages
9
+ } from "@cedarjs/cli-helpers/packageManager/packages";
7
10
  import { getConfigPath } from "@cedarjs/project-config";
8
11
  import { errorTelemetry } from "@cedarjs/telemetry";
9
12
  import { getPaths, writeFile } from "../../lib/index.js";
@@ -13,16 +16,16 @@ import {
13
16
  EXPERIMENTAL_TOPIC_ID
14
17
  } from "./setupReactCompiler.js";
15
18
  import { printTaskEpilogue } from "./util.js";
16
- const handler = async ({ force, verbose }) => {
19
+ const handler = async (options) => {
17
20
  const rwPaths = getPaths();
18
21
  const configTomlPath = getConfigPath();
19
22
  const configFileName = path.basename(configTomlPath);
20
23
  const configContent = fs.readFileSync(configTomlPath, "utf-8");
21
- const tasks = new Listr(
22
- [
24
+ function buildTaskData() {
25
+ return [
23
26
  {
24
27
  title: "Check prerequisites",
25
- skip: force,
28
+ skip: options.force,
26
29
  task: () => {
27
30
  if (!rwPaths.web.entryClient || !rwPaths.web.viteConfig) {
28
31
  throw new Error(
@@ -37,7 +40,7 @@ const handler = async ({ force, verbose }) => {
37
40
  );
38
41
  const reactVersion = webPkgJson["dependencies"]["react"];
39
42
  const coercedReactVersion = semver.coerce(reactVersion);
40
- if (!semver.gte(coercedReactVersion, "19.0.0")) {
43
+ if (!coercedReactVersion || !semver.gte(coercedReactVersion, "19.0.0")) {
41
44
  throw new Error(
42
45
  "You need to be using at least React version 19 to enable the React Compiler"
43
46
  );
@@ -59,7 +62,7 @@ const handler = async ({ force, verbose }) => {
59
62
  }
60
63
  );
61
64
  } else {
62
- if (force) {
65
+ if (options.force) {
63
66
  task.output = `Overwriting config in ${configFileName}`;
64
67
  writeFile(
65
68
  configTomlPath,
@@ -79,29 +82,27 @@ const handler = async ({ force, verbose }) => {
79
82
  );
80
83
  }
81
84
  }
82
- },
83
- rendererOptions: { persistentOutput: true }
85
+ }
84
86
  },
85
- // We are using two different yarn commands here which is fine because they're operating on different
86
- // workspaces - web and the root
87
+ // We are using two different package manager commands here which is
88
+ // fine because they're operating on different workspaces - web and the
89
+ // root
87
90
  {
88
91
  title: "Installing eslint-plugin-react-compiler",
89
92
  task: async () => {
90
- await execa("yarn", ["add", "-D", "eslint-plugin-react-compiler"], {
91
- cwd: getPaths().base
93
+ await addRootPackages(["eslint-plugin-react-compiler"], {
94
+ cwd: getPaths().base,
95
+ dev: true
92
96
  });
93
97
  }
94
98
  },
95
99
  {
96
100
  title: "Installing babel-plugin-react-compiler",
97
101
  task: async () => {
98
- await execa(
99
- "yarn",
100
- ["web/", "add", "-D", "babel-plugin-react-compiler"],
101
- {
102
- cwd: getPaths().base
103
- }
104
- );
102
+ await addWorkspacePackages("web", ["babel-plugin-react-compiler"], {
103
+ cwd: getPaths().base,
104
+ dev: true
105
+ });
105
106
  }
106
107
  },
107
108
  {
@@ -109,18 +110,32 @@ const handler = async ({ force, verbose }) => {
109
110
  printTaskEpilogue(command, description, EXPERIMENTAL_TOPIC_ID);
110
111
  }
111
112
  }
112
- ],
113
- {
114
- rendererOptions: { collapseSubtasks: false, persistentOutput: true },
115
- renderer: verbose ? "verbose" : "default"
116
- }
117
- );
113
+ ];
114
+ }
118
115
  try {
119
- await tasks.run();
116
+ if (options.verbose) {
117
+ await new Listr(buildTaskData(), {
118
+ exitOnError: true,
119
+ renderer: "verbose"
120
+ }).run();
121
+ } else {
122
+ await new Listr(
123
+ buildTaskData().map((t) => ({
124
+ ...t,
125
+ rendererOptions: { persistentOutput: true }
126
+ })),
127
+ {
128
+ exitOnError: true,
129
+ rendererOptions: { collapseSubtasks: false }
130
+ }
131
+ ).run();
132
+ }
120
133
  } catch (e) {
121
- errorTelemetry(process.argv, e.message);
122
- console.error(c.error(e.message));
123
- process.exit(e?.exitCode || 1);
134
+ const message = e instanceof Error ? e.message : String(e);
135
+ const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
136
+ errorTelemetry(process.argv, message);
137
+ console.error(c.error(message));
138
+ process.exit(exitCode);
124
139
  }
125
140
  };
126
141
  export {
@@ -11,7 +11,10 @@ import { getPaths, transformTSToJS, writeFile } from "../../lib/index.js";
11
11
  import { isTypeScriptProject } from "../../lib/project.js";
12
12
  import { command, description, EXPERIMENTAL_TOPIC_ID } from "./setupRsc.js";
13
13
  import { printTaskEpilogue } from "./util.js";
14
- const handler = async ({ force, verbose }) => {
14
+ const handler = async ({
15
+ force,
16
+ verbose
17
+ }) => {
15
18
  const rwPaths = getPaths();
16
19
  const configTomlPath = getConfigPath();
17
20
  const configContent = fs.readFileSync(configTomlPath, "utf-8");
@@ -84,11 +87,9 @@ const handler = async ({ force, verbose }) => {
84
87
  ),
85
88
  "utf-8"
86
89
  );
87
- const entryClientContent = isTypeScriptProject() ? entryClientTemplate : await transformTSToJS(
88
- rwPaths.web.entryClient,
89
- entryClientTemplate
90
- );
91
- writeFile(rwPaths.web.entryClient, entryClientContent, {
90
+ const entryClient = rwPaths.web.entryClient ?? "";
91
+ const entryClientContent = isTypeScriptProject() ? entryClientTemplate : await transformTSToJS(entryClient, entryClientTemplate);
92
+ writeFile(entryClient, entryClientContent, {
92
93
  overwriteExisting: true
93
94
  });
94
95
  }
@@ -220,7 +221,7 @@ const handler = async ({ force, verbose }) => {
220
221
  {
221
222
  title: "Adding CSS files...",
222
223
  task: async () => {
223
- const files = [
224
+ const cssFiles = [
224
225
  {
225
226
  template: "Counter.css.template",
226
227
  path: ["components", "Counter", "Counter.css"]
@@ -242,7 +243,7 @@ const handler = async ({ force, verbose }) => {
242
243
  path: ["pages", "AboutPage", "AboutPage.css"]
243
244
  }
244
245
  ];
245
- files.forEach((file) => {
246
+ cssFiles.forEach((file) => {
246
247
  const template = fs.readFileSync(
247
248
  path.resolve(
248
249
  import.meta.dirname,
@@ -398,9 +399,11 @@ const handler = async ({ force, verbose }) => {
398
399
  try {
399
400
  await tasks.run();
400
401
  } catch (e) {
401
- errorTelemetry(process.argv, e.message);
402
- console.error(c.error(e.message));
403
- process.exit(e?.exitCode || 1);
402
+ const message = e instanceof Error ? e.message : String(e);
403
+ const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
404
+ errorTelemetry(process.argv, message);
405
+ console.error(c.error(message));
406
+ process.exit(exitCode);
404
407
  }
405
408
  };
406
409
  export {
@@ -2,7 +2,7 @@ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
2
  import { getEpilogue } from "./util.js";
3
3
  const command = "setup-streaming-ssr";
4
4
  const description = "Enable React Streaming and Server Side Rendering (SSR)";
5
- const EXPERIMENTAL_TOPIC_ID = 5052;
5
+ const EXPERIMENTAL_TOPIC_ID = "5052";
6
6
  const builder = (yargs) => {
7
7
  yargs.option("force", {
8
8
  alias: "f",