@cedarjs/cli 5.0.0-canary.2479 → 5.0.0-canary.2481

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.
@@ -7,6 +7,7 @@ import * as toml from "smol-toml";
7
7
  import { env as envInterpolation } from "string-env-interpolation";
8
8
  import { titleCase } from "title-case";
9
9
  import { colors as c } from "@cedarjs/cli-helpers";
10
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
10
11
  import { getPaths } from "../../../lib/index.js";
11
12
  const CONFIG_FILENAME = "deploy.toml";
12
13
  const SYMLINK_FLAGS = "-nsf";
@@ -30,7 +31,7 @@ const throwMissingConfig = (name) => {
30
31
  const verifyConfig = (config, yargs) => {
31
32
  if (!yargs.environment) {
32
33
  throw new Error(
33
- "Must specify an environment to deploy to, ex: `yarn cedar deploy baremetal production`"
34
+ `Must specify an environment to deploy to, ex: \`${formatCedarCommand(["deploy", "baremetal", "production"])}\``
34
35
  );
35
36
  }
36
37
  if (!config[yargs.environment]) {
@@ -535,7 +536,7 @@ const handler = async (yargs) => {
535
536
  const ecosystemPath = path.join(getPaths().base, "ecosystem.config.js");
536
537
  if (!fs.existsSync(tomlPath) || !fs.existsSync(ecosystemPath)) {
537
538
  console.error(
538
- c.error("\nError: Baremetal deploy has not been properly setup.\n") + "Please run `yarn cedar setup deploy baremetal` before deploying"
539
+ c.error("\nError: Baremetal deploy has not been properly setup.\n") + `Please run \`${formatCedarCommand(["setup", "deploy", "baremetal"])}\` before deploying`
539
540
  );
540
541
  process.exit(1);
541
542
  }
@@ -2,7 +2,18 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import execa from "execa";
4
4
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
5
+ import {
6
+ getNodeRunnerArgs,
7
+ runBin
8
+ } from "@cedarjs/cli-helpers/packageManager/exec";
5
9
  import { getPaths } from "@cedarjs/project-config";
10
+ async function runBinWithError(bin, args, options) {
11
+ const result = await runBin(bin, args, options);
12
+ if (result.failed) {
13
+ throw new Error(`Command (${bin} ${args.join(" ")}) failed`);
14
+ }
15
+ return result;
16
+ }
6
17
  const handler = async ({
7
18
  side,
8
19
  serve,
@@ -22,33 +33,27 @@ const handler = async ({
22
33
  shell: true,
23
34
  stdio: "inherit"
24
35
  };
25
- async function runExecaCommand(command) {
26
- const result = await execa.command(command, execaConfig);
27
- if (result.failed) {
28
- throw new Error(`Command (${command}) failed`);
29
- }
30
- return result;
31
- }
32
36
  async function runApiCommands() {
33
37
  if (!serve) {
34
38
  console.log("Building api...");
35
- await runExecaCommand("yarn cedar build api --verbose");
39
+ await runBinWithError("cedar", ["build", "api", "--verbose"], execaConfig);
36
40
  if (prisma) {
37
41
  console.log("Running database migrations...");
38
- await runExecaCommand(
39
- `node_modules/.bin/prisma migrate deploy --config "${cedarPaths.api.prismaConfig}"`
42
+ await execa.command(
43
+ `node_modules/.bin/prisma migrate deploy --config "${cedarPaths.api.prismaConfig}"`,
44
+ execaConfig
40
45
  );
41
46
  }
42
47
  if (dataMigrate) {
43
48
  console.log("Running data migrations...");
44
- await runExecaCommand("yarn cedar dataMigrate up");
49
+ await runBinWithError("cedar", ["dataMigrate", "up"], execaConfig);
45
50
  }
46
51
  return;
47
52
  }
48
53
  const serverFilePath = path.join(cedarPaths.api.dist, "server.js");
49
54
  const hasServerFile = fs.existsSync(serverFilePath);
50
55
  if (hasServerFile) {
51
- execa(`yarn node ${serverFilePath}`, execaConfig);
56
+ execa(...getNodeRunnerArgs(serverFilePath), execaConfig);
52
57
  } else {
53
58
  const { handler: handler2 } = await import("@cedarjs/api-server/apiCliConfigHandler");
54
59
  handler2();
@@ -56,7 +61,7 @@ const handler = async ({
56
61
  }
57
62
  async function runWebCommands() {
58
63
  console.log("Building web...");
59
- await runExecaCommand("yarn cedar build web --verbose");
64
+ await runBinWithError("cedar", ["build", "web", "--verbose"], execaConfig);
60
65
  }
61
66
  if (side === "api") {
62
67
  await runApiCommands();
@@ -1,17 +1,18 @@
1
1
  import execa from "execa";
2
2
  import { colors as c } from "@cedarjs/cli-helpers";
3
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
3
4
  import { getPaths } from "@cedarjs/project-config";
4
5
  const deployHandler = ({ build, prisma, dm: dataMigrate }) => {
5
6
  const paths = getPaths();
6
7
  let commandSet = [];
7
8
  if (build) {
8
- commandSet.push("yarn cedar build --verbose");
9
+ commandSet.push(formatCedarCommand(["build", "--verbose"]));
9
10
  }
10
11
  if (prisma) {
11
- commandSet.push("yarn cedar prisma migrate deploy");
12
+ commandSet.push(formatCedarCommand(["prisma", "migrate", "deploy"]));
12
13
  }
13
14
  if (dataMigrate) {
14
- commandSet.push("yarn cedar data-migrate up");
15
+ commandSet.push(formatCedarCommand(["data-migrate", "up"]));
15
16
  }
16
17
  const joinedCommands = commandSet.join(" && ");
17
18
  console.log(c.note("\nRunning:\n") + `${joinedCommands}
@@ -2,6 +2,12 @@ import fs from "node:fs";
2
2
  import path from "path";
3
3
  import execa from "execa";
4
4
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
5
+ import { formatAddRootPackagesCommand } from "@cedarjs/cli-helpers/packageManager/display";
6
+ import {
7
+ getNodeRunnerArgs,
8
+ runBinSync
9
+ } from "@cedarjs/cli-helpers/packageManager/exec";
10
+ import { installPackages } from "@cedarjs/cli-helpers/packageManager/packages";
5
11
  import { getPaths } from "@cedarjs/project-config";
6
12
  const handler = async ({ side, prisma, dataMigrate }) => {
7
13
  recordTelemetryAttributes({
@@ -38,26 +44,26 @@ const handler = async ({ side, prisma, dataMigrate }) => {
38
44
  "If you want to run data migrations, add the package to your project's root package.json and deploy again:",
39
45
  "",
40
46
  "```",
41
- "yarn add -D @cedarjs/cli-data-migrate",
47
+ formatAddRootPackagesCommand(["@cedarjs/cli-data-migrate"], true),
42
48
  "```"
43
49
  ].join("\n")
44
50
  );
45
51
  } else {
46
- execa.commandSync("yarn cedar dataMigrate up", execaConfig);
52
+ runBinSync("cedar", ["dataMigrate", "up"], execaConfig);
47
53
  }
48
54
  }
49
55
  const serverFilePath = path.join(cedarPaths.api.dist, "server.js");
50
56
  const hasServerFile = fs.existsSync(serverFilePath);
51
57
  if (hasServerFile) {
52
- execa(`yarn node ${serverFilePath}`, execaConfig);
58
+ execa(...getNodeRunnerArgs(serverFilePath), execaConfig);
53
59
  } else {
54
60
  const { handler: handler2 } = await import("@cedarjs/api-server/apiCliConfigHandler");
55
61
  handler2();
56
62
  }
57
63
  }
58
64
  async function runWebCommands() {
59
- execa.commandSync("yarn install", execaConfig);
60
- execa.commandSync("yarn cedar build web --verbose", execaConfig);
65
+ await installPackages(execaConfig);
66
+ runBinSync("cedar", ["build", "web", "--verbose"], execaConfig);
61
67
  }
62
68
  if (side === "api") {
63
69
  runApiCommands();
@@ -7,22 +7,36 @@ import execa from "execa";
7
7
  import { Listr } from "listr2";
8
8
  import prompts from "prompts";
9
9
  import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
10
+ import {
11
+ formatAddRootPackagesCommand,
12
+ formatRunBinCommand
13
+ } from "@cedarjs/cli-helpers/packageManager/display";
14
+ import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
10
15
  import { getPaths } from "../../lib/index.js";
11
16
  const preRequisites = () => [
12
17
  {
13
18
  title: "Checking if Serverless framework is installed...",
14
- command: ["yarn serverless", ["--version"]],
15
- errorMessage: [
16
- "Looks like Serverless is not installed.",
17
- "Please run yarn add -W --dev serverless."
18
- ]
19
+ task: async () => {
20
+ try {
21
+ await runBin("serverless", ["--version"], { shell: true });
22
+ } catch (error) {
23
+ const msg = error instanceof Error ? error.message : String(error);
24
+ throw new Error(
25
+ `${msg}
26
+ Looks like Serverless is not installed.
27
+ Please run ${formatAddRootPackagesCommand(["serverless"], true)}.`
28
+ );
29
+ }
30
+ }
19
31
  }
20
32
  ];
21
33
  const buildCommands = ({ sides }) => {
22
34
  return [
23
35
  {
24
36
  title: `Building ${sides.join(" & ")}...`,
25
- command: ["yarn", ["cedar", "build", ...sides]]
37
+ task: async () => {
38
+ await runBin("cedar", ["build", ...sides], { shell: true });
39
+ }
26
40
  },
27
41
  {
28
42
  title: "Packing Functions...",
@@ -40,7 +54,7 @@ const deployCommands = ({ stage, sides, firstRun, packOnly }) => {
40
54
  return {
41
55
  title: `Deploying ${side}....`,
42
56
  task: async () => {
43
- await execa("yarn", ["serverless", "deploy", ...slsStage], {
57
+ await runBin("serverless", ["deploy", ...slsStage], {
44
58
  cwd: path.join(getPaths().base, side),
45
59
  shell: true,
46
60
  stdio: "inherit",
@@ -93,8 +107,9 @@ const handler = async (yargs) => {
93
107
  const SETUP_MARKER = ansis.bgBlue.black("First Setup ");
94
108
  console.log();
95
109
  console.log(SETUP_MARKER, c.success("Starting first setup wizard..."));
96
- const { stdout: slsInfo } = await execa(
97
- `yarn serverless info --verbose --stage=${yargs.stage}`,
110
+ const { stdout: slsInfo } = await runBin(
111
+ "serverless",
112
+ ["info", "--verbose", `--stage=${yargs.stage}`],
98
113
  {
99
114
  shell: true,
100
115
  cwd: getPaths().api.base
@@ -139,8 +154,9 @@ const handler = async (yargs) => {
139
154
  }
140
155
  );
141
156
  await webDeployTasks.run();
142
- const { stdout: slsInfo2 } = await execa(
143
- `yarn serverless info --verbose --stage=${yargs.stage}`,
157
+ const { stdout: slsInfo2 } = await runBin(
158
+ "serverless",
159
+ ["info", "--verbose", `--stage=${yargs.stage}`],
144
160
  {
145
161
  shell: true,
146
162
  cwd: getPaths().web.base
@@ -153,7 +169,7 @@ const handler = async (yargs) => {
153
169
  `View your deployed site at: ${c.success(deployedWebUrl)}`,
154
170
  "",
155
171
  "You can use serverless.com CI/CD by connecting/creating an app",
156
- "To do this run `yarn serverless` on each of the sides, and connect your account",
172
+ `To do this run \`${formatRunBinCommand("serverless")}\` on each of the sides, and connect your account`,
157
173
  "",
158
174
  "Find more information in our docs:",
159
175
  c.underline("https://cedarjs.com/docs/deploy#serverless")
@@ -13,19 +13,16 @@ import {
13
13
  EXPERIMENTAL_TOPIC_ID
14
14
  } from "./setupReactCompiler.js";
15
15
  import { printTaskEpilogue } from "./util.js";
16
- const handler = async ({
17
- force,
18
- verbose
19
- }) => {
16
+ const handler = async (options) => {
20
17
  const rwPaths = getPaths();
21
18
  const configTomlPath = getConfigPath();
22
19
  const configFileName = path.basename(configTomlPath);
23
20
  const configContent = fs.readFileSync(configTomlPath, "utf-8");
24
- const tasks = new Listr(
25
- [
21
+ function buildTaskData() {
22
+ return [
26
23
  {
27
24
  title: "Check prerequisites",
28
- skip: force,
25
+ skip: options.force,
29
26
  task: () => {
30
27
  if (!rwPaths.web.entryClient || !rwPaths.web.viteConfig) {
31
28
  throw new Error(
@@ -62,7 +59,7 @@ const handler = async ({
62
59
  }
63
60
  );
64
61
  } else {
65
- if (force) {
62
+ if (options.force) {
66
63
  task.output = `Overwriting config in ${configFileName}`;
67
64
  writeFile(
68
65
  configTomlPath,
@@ -82,11 +79,10 @@ const handler = async ({
82
79
  );
83
80
  }
84
81
  }
85
- },
86
- rendererOptions: { persistentOutput: true }
82
+ }
87
83
  },
88
- // We are using two different yarn commands here which is fine because they're operating on different
89
- // workspaces - web and the root
84
+ // We are using two different yarn commands here which is fine because
85
+ // they're operating on different workspaces - web and the root
90
86
  {
91
87
  title: "Installing eslint-plugin-react-compiler",
92
88
  task: async () => {
@@ -112,14 +108,26 @@ const handler = async ({
112
108
  printTaskEpilogue(command, description, EXPERIMENTAL_TOPIC_ID);
113
109
  }
114
110
  }
115
- ],
116
- {
117
- rendererOptions: { collapseSubtasks: false, persistentOutput: true },
118
- renderer: verbose ? "verbose" : "default"
119
- }
120
- );
111
+ ];
112
+ }
121
113
  try {
122
- await tasks.run();
114
+ if (options.verbose) {
115
+ await new Listr(buildTaskData(), {
116
+ exitOnError: true,
117
+ renderer: "verbose"
118
+ }).run();
119
+ } else {
120
+ await new Listr(
121
+ buildTaskData().map((t) => ({
122
+ ...t,
123
+ rendererOptions: { persistentOutput: true }
124
+ })),
125
+ {
126
+ exitOnError: true,
127
+ rendererOptions: { collapseSubtasks: false }
128
+ }
129
+ ).run();
130
+ }
123
131
  } catch (e) {
124
132
  const message = e instanceof Error ? e.message : String(e);
125
133
  const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
@@ -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",
@@ -13,21 +13,18 @@ import {
13
13
  EXPERIMENTAL_TOPIC_ID
14
14
  } from "./setupStreamingSsr.js";
15
15
  import { printTaskEpilogue } from "./util.js";
16
- const handler = async ({
17
- force,
18
- verbose
19
- }) => {
20
- const rwPaths = getPaths();
16
+ const handler = async (options) => {
17
+ const cedarPaths = getPaths();
21
18
  const configPath = getConfigPath();
22
19
  const configContent = fs.readFileSync(configPath, "utf-8");
23
20
  const ts = isTypeScriptProject();
24
- const ext = path.extname(rwPaths.web.entryClient || "");
25
- const tasks = new Listr(
26
- [
21
+ const ext = path.extname(cedarPaths.web.entryClient || "");
22
+ function buildTaskData() {
23
+ return [
27
24
  {
28
25
  title: "Check prerequisites",
29
26
  task: () => {
30
- if (!rwPaths.web.entryClient || !rwPaths.web.viteConfig) {
27
+ if (!cedarPaths.web.entryClient || !cedarPaths.web.viteConfig) {
31
28
  throw new Error(
32
29
  "Vite needs to be setup before you can enable Streaming SSR"
33
30
  );
@@ -52,7 +49,7 @@ const handler = async ({
52
49
  }
53
50
  );
54
51
  } else {
55
- if (force) {
52
+ if (options.force) {
56
53
  task.output = "Overwriting config in cedar.toml";
57
54
  writeFile(
58
55
  configPath,
@@ -78,8 +75,7 @@ const handler = async ({
78
75
  );
79
76
  }
80
77
  }
81
- },
82
- rendererOptions: { persistentOutput: true }
78
+ }
83
79
  },
84
80
  {
85
81
  title: `Adding entry.client${ext}...`,
@@ -93,10 +89,13 @@ const handler = async ({
93
89
  ),
94
90
  "utf-8"
95
91
  );
96
- let entryClientPath = rwPaths.web.entryClient;
92
+ let entryClientPath = cedarPaths.web.entryClient;
93
+ if (!entryClientPath) {
94
+ throw new Error("entryClient is not set");
95
+ }
97
96
  const entryClientContent = ts ? entryClientTemplate : await transformTSToJS(entryClientPath, entryClientTemplate);
98
- let overwriteExisting = force;
99
- if (!force) {
97
+ let overwriteExisting = options.force;
98
+ if (!options.force) {
100
99
  const prompt = task.prompt(ListrEnquirerPromptAdapter);
101
100
  overwriteExisting = await prompt.run({
102
101
  type: "Confirm",
@@ -109,8 +108,7 @@ You'll manually need to merge it with your existing entry.client${ext} file.`;
109
108
  }
110
109
  }
111
110
  writeFile(entryClientPath, entryClientContent, { overwriteExisting });
112
- },
113
- rendererOptions: { persistentOutput: true }
111
+ }
114
112
  },
115
113
  {
116
114
  title: `Adding entry.server${ext}...`,
@@ -125,12 +123,12 @@ You'll manually need to merge it with your existing entry.client${ext} file.`;
125
123
  "utf-8"
126
124
  );
127
125
  const entryServerPath = path.join(
128
- rwPaths.web.src,
126
+ cedarPaths.web.src,
129
127
  `entry.server${ext}`
130
128
  );
131
129
  const entryServerContent = ts ? entryServerTemplate : await transformTSToJS(entryServerPath, entryServerTemplate);
132
130
  writeFile(entryServerPath, entryServerContent, {
133
- overwriteExisting: force
131
+ overwriteExisting: options.force
134
132
  });
135
133
  }
136
134
  },
@@ -146,10 +144,10 @@ You'll manually need to merge it with your existing entry.client${ext} file.`;
146
144
  ),
147
145
  "utf-8"
148
146
  );
149
- const documentPath = path.join(rwPaths.web.src, `Document${ext}`);
147
+ const documentPath = path.join(cedarPaths.web.src, `Document${ext}`);
150
148
  const documentContent = ts ? documentTemplate : await transformTSToJS(documentPath, documentTemplate);
151
149
  writeFile(documentPath, documentContent, {
152
- overwriteExisting: force
150
+ overwriteExisting: options.force
153
151
  });
154
152
  }
155
153
  },
@@ -166,18 +164,18 @@ You'll manually need to merge it with your existing entry.client${ext} file.`;
166
164
  "utf-8"
167
165
  );
168
166
  const tsconfigPath = path.join(
169
- rwPaths.web.base,
167
+ cedarPaths.web.base,
170
168
  ts ? "tsconfig.json" : "jsconfig.json"
171
169
  );
172
170
  writeFile(tsconfigPath, tsconfigTemplate, {
173
- overwriteExisting: force
171
+ overwriteExisting: options.force
174
172
  });
175
173
  }
176
174
  },
177
175
  {
178
176
  title: 'Adding resolution for "@apollo/client-react-streaming/superjson"',
179
177
  task: () => {
180
- const pkgJsonPath = path.join(rwPaths.base, "package.json");
178
+ const pkgJsonPath = path.join(cedarPaths.base, "package.json");
181
179
  const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
182
180
  const resolutions = pkgJson.resolutions || {};
183
181
  resolutions["@apollo/client-react-streaming/superjson"] = "^1.12.2";
@@ -191,14 +189,26 @@ You'll manually need to merge it with your existing entry.client${ext} file.`;
191
189
  printTaskEpilogue(command, description, EXPERIMENTAL_TOPIC_ID);
192
190
  }
193
191
  }
194
- ],
195
- {
196
- rendererOptions: { collapseSubtasks: false, persistentOutput: true },
197
- renderer: verbose ? "verbose" : "default"
198
- }
199
- );
192
+ ];
193
+ }
200
194
  try {
201
- await tasks.run();
195
+ if (options.verbose) {
196
+ await new Listr(buildTaskData(), {
197
+ exitOnError: true,
198
+ renderer: "verbose"
199
+ }).run();
200
+ } else {
201
+ await new Listr(
202
+ buildTaskData().map((t) => ({
203
+ ...t,
204
+ rendererOptions: { persistentOutput: true }
205
+ })),
206
+ {
207
+ exitOnError: true,
208
+ rendererOptions: { collapseSubtasks: false }
209
+ }
210
+ ).run();
211
+ }
202
212
  } catch (e) {
203
213
  const message = e instanceof Error ? e.message : String(e);
204
214
  const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
@@ -66,8 +66,8 @@ async function handler({
66
66
  });
67
67
  functionType = response.functionType;
68
68
  }
69
- const tasks = new Listr(
70
- [
69
+ function buildTaskData() {
70
+ return [
71
71
  {
72
72
  title: "Checking for realtime environment prerequisites ...",
73
73
  task: () => {
@@ -207,14 +207,31 @@ async function handler({
207
207
  );
208
208
  }
209
209
  }
210
- ],
211
- {
212
- rendererOptions: { collapseSubtasks: false, persistentOutput: true },
213
- renderer: silent ? "silent" : verbose ? "verbose" : "default"
214
- }
215
- );
210
+ ];
211
+ }
216
212
  try {
217
- await tasks.run();
213
+ if (silent) {
214
+ await new Listr(buildTaskData(), {
215
+ exitOnError: true,
216
+ renderer: "silent"
217
+ }).run();
218
+ } else if (verbose) {
219
+ await new Listr(buildTaskData(), {
220
+ exitOnError: true,
221
+ renderer: "verbose"
222
+ }).run();
223
+ } else {
224
+ await new Listr(
225
+ buildTaskData().map((t) => ({
226
+ ...t,
227
+ rendererOptions: { persistentOutput: true }
228
+ })),
229
+ {
230
+ exitOnError: true,
231
+ rendererOptions: { collapseSubtasks: false }
232
+ }
233
+ ).run();
234
+ }
218
235
  } catch (e) {
219
236
  const message = e instanceof Error ? e.message : String(e);
220
237
  const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import https from "https";
2
1
  import fs from "node:fs";
3
- import path from "path";
2
+ import https from "node:https";
3
+ import path from "node:path";
4
4
  import * as babel from "@babel/core";
5
5
  import boxen from "boxen";
6
6
  import camelcase from "camelcase";
@@ -14,8 +14,12 @@ import pascalcase from "pascalcase";
14
14
  import { format } from "prettier";
15
15
  import { colors as c } from "@cedarjs/cli-helpers";
16
16
  import {
17
- getConfig as getRedwoodConfig,
18
- getPaths as getRedwoodPaths,
17
+ addRootPackages,
18
+ addWorkspacePackages
19
+ } from "@cedarjs/cli-helpers/packageManager/packages";
20
+ import {
21
+ getConfig as getCedarConfig,
22
+ getPaths as getCedarPaths,
19
23
  resolveFile as internalResolveFile,
20
24
  findUp
21
25
  } from "@cedarjs/project-config";
@@ -46,6 +50,7 @@ const generateTemplate = (templateFilename, { name, ...rest }) => {
46
50
  });
47
51
  return prettify(templateFilename, renderedTemplate);
48
52
  } catch (error) {
53
+ ;
49
54
  error.message = `Error applying template at ${templateFilename} for ${name}: ${error.message}`;
50
55
  throw error;
51
56
  }
@@ -127,17 +132,17 @@ async function getInstalledCedarVersion() {
127
132
  try {
128
133
  const packageJson = await import("../../package.json", { with: { type: "json" } });
129
134
  return packageJson.default.version;
130
- } catch (e) {
135
+ } catch {
131
136
  console.error(c.error("Could not find installed Cedar version"));
132
137
  process.exit(1);
133
138
  }
134
139
  }
135
- const bytes = (contents) => Buffer.byteLength(contents, "utf8");
136
140
  const _getPaths = () => {
137
141
  try {
138
- return getRedwoodPaths();
142
+ return getCedarPaths();
139
143
  } catch (e) {
140
- console.error(c.error(e.message));
144
+ const message = e instanceof Error ? e.message : String(e);
145
+ console.error(c.error(message));
141
146
  process.exit(1);
142
147
  }
143
148
  };
@@ -145,13 +150,15 @@ const getPaths = memoize(_getPaths);
145
150
  const resolveFile = internalResolveFile;
146
151
  const getGraphqlPath = () => resolveFile(path.join(getPaths().api.functions, "graphql"));
147
152
  const graphFunctionDoesExist = () => {
148
- return fs.existsSync(getGraphqlPath());
153
+ const graphqlPath = getGraphqlPath();
154
+ return graphqlPath ? fs.existsSync(graphqlPath) : false;
149
155
  };
150
156
  const getConfig = () => {
151
157
  try {
152
- return getRedwoodConfig();
158
+ return getCedarConfig();
153
159
  } catch (e) {
154
- console.error(c.error(e.message));
160
+ const message = e instanceof Error ? e.message : String(e);
161
+ console.error(c.error(message));
155
162
  process.exit(1);
156
163
  }
157
164
  };
@@ -162,7 +169,7 @@ const getPrettierOptions = async () => {
162
169
  const prettierConfigPath = fs.existsSync(cjsPath) ? cjsPath : mjsPath;
163
170
  const { default: prettierOptions } = await import(`file://${prettierConfigPath}`);
164
171
  return prettierOptions;
165
- } catch (e) {
172
+ } catch {
166
173
  if (process.env.VITEST_POOL_ID !== void 0) {
167
174
  return {
168
175
  trailingComma: "es5",
@@ -185,10 +192,10 @@ const getPrettierOptions = async () => {
185
192
  }
186
193
  };
187
194
  const transformTSToJS = async (filename, content) => {
188
- const { code } = babel.transform(content, {
195
+ const result = babel.transform(content, {
189
196
  filename,
190
- // If you ran `yarn cedar generate` in `./web` transformSync would import the `.babelrc.js` file,
191
- // in `./web`? despite us setting `configFile: false`.
197
+ // If you ran `yarn cedar generate` in `./web` transformSync would import
198
+ // the `.babelrc.js` file, in `./web` despite us setting `configFile: false`
192
199
  cwd: process.env.NODE_ENV === "test" ? void 0 : getPaths().base,
193
200
  configFile: false,
194
201
  plugins: [
@@ -202,6 +209,7 @@ const transformTSToJS = async (filename, content) => {
202
209
  ],
203
210
  retainLines: true
204
211
  });
212
+ const code = result?.code ?? "";
205
213
  return prettify(filename.replace(/\.ts(x)?$/, ".js$1"), code);
206
214
  };
207
215
  const writeFilesTask = (files, options) => {
@@ -211,7 +219,7 @@ const writeFilesTask = (files, options) => {
211
219
  const contents = files[file];
212
220
  return {
213
221
  title: `...waiting to write file \`./${path.relative(base, file)}\`...`,
214
- task: (ctx, task) => writeFile(file, contents, options, task)
222
+ task: (_ctx, task) => writeFile(file, contents, options, task)
215
223
  };
216
224
  })
217
225
  );
@@ -269,7 +277,7 @@ const cleanupEmptyDirsTask = (files) => {
269
277
  const wrapWithSet = (routesContent, layout, routes, newLineAndIndent, props = {}) => {
270
278
  const [_, indentOne, indentTwo] = routesContent.match(
271
279
  /([ \t]*)<Router.*?>[^<]*[\r\n]+([ \t]+)/
272
- ) || ["", 0, 2];
280
+ ) || ["", "", ""];
273
281
  const oneLevelIndent = indentTwo.slice(0, indentTwo.length - indentOne.length);
274
282
  const newRoutesWithExtraIndent = routes.map((route) => oneLevelIndent + route);
275
283
  const propsString = Object.entries(props).map((values) => `${values[0]}="${values[1]}"`).join(" ");
@@ -279,7 +287,7 @@ const wrapWithSet = (routesContent, layout, routes, newLineAndIndent, props = {}
279
287
  `</Set>`
280
288
  ].join(newLineAndIndent);
281
289
  };
282
- const addRoutesToRouterTask = (routes, layout, setProps = {}) => {
290
+ function addRoutesToRouterTask(routes, layout, setProps = {}) {
283
291
  const cedarPaths = getPaths();
284
292
  const routesContent = readFile(cedarPaths.web.routes).toString();
285
293
  let newRoutes = routes.filter((route) => !routesContent.match(route));
@@ -311,7 +319,7 @@ ${route}`);
311
319
  overwriteExisting: true
312
320
  });
313
321
  }
314
- };
322
+ }
315
323
  const addScaffoldImport = () => {
316
324
  const appJsPath = getPaths().web.app;
317
325
  let appJsContents = readFile(appJsPath).toString();
@@ -325,7 +333,7 @@ const addScaffoldImport = () => {
325
333
  writeFile(appJsPath, appJsContents, { overwriteExisting: true });
326
334
  return "Added scaffold import to App.{jsx,tsx}";
327
335
  };
328
- const removeEmtpySet = (routesContent, layout) => {
336
+ function removeEmtpySet(routesContent, layout) {
329
337
  const setWithLayoutReg = new RegExp(
330
338
  `\\s*<Set[^>]*wrap={${layout}}[^<]*>([^<]*)</Set>`
331
339
  );
@@ -338,8 +346,8 @@ const removeEmtpySet = (routesContent, layout) => {
338
346
  return routesContent;
339
347
  }
340
348
  return routesContent.replace(setWithLayoutReg, "");
341
- };
342
- const removeRoutesFromRouterTask = (routes, layout) => {
349
+ }
350
+ function removeRoutesFromRouterTask(routes, layout) {
343
351
  const cedarPaths = getPaths();
344
352
  const routesContent = readFile(cedarPaths.web.routes).toString();
345
353
  const newRoutesContent = routes.reduce((content, route) => {
@@ -350,7 +358,7 @@ const removeRoutesFromRouterTask = (routes, layout) => {
350
358
  writeFile(cedarPaths.web.routes, routesWithoutEmptySet, {
351
359
  overwriteExisting: true
352
360
  });
353
- };
361
+ }
354
362
  const addPackagesTask = async ({
355
363
  packages,
356
364
  side = "project",
@@ -364,30 +372,18 @@ const addPackagesTask = async ({
364
372
  return pkg;
365
373
  }
366
374
  });
367
- let installCommand;
368
- if (side !== "project") {
369
- installCommand = [
370
- "yarn",
371
- [
372
- "workspace",
373
- side,
374
- "add",
375
- devDependency && "--dev",
376
- ...packagesWithSameRWVersion
377
- ].filter(Boolean)
378
- ];
379
- } else {
380
- installCommand = [
381
- "yarn",
382
- ["add", devDependency && "--dev", ...packagesWithSameRWVersion].filter(
383
- Boolean
384
- )
385
- ];
386
- }
387
375
  return {
388
376
  title: `Adding dependencies to ${side}`,
389
377
  task: async () => {
390
- await execa(...installCommand);
378
+ if (side !== "project") {
379
+ await addWorkspacePackages(side, packagesWithSameRWVersion, {
380
+ dev: devDependency
381
+ });
382
+ } else {
383
+ await addRootPackages(packagesWithSameRWVersion, {
384
+ dev: devDependency
385
+ });
386
+ }
391
387
  }
392
388
  };
393
389
  };
@@ -407,7 +403,7 @@ const runCommandTask = async (commands, { verbose, silent }) => {
407
403
  })),
408
404
  {
409
405
  renderer: silent ? "silent" : verbose ? "verbose" : "default",
410
- rendererOptions: { collapseSubtasks: false, dateFormat: false }
406
+ rendererOptions: { collapseSubtasks: false }
411
407
  }
412
408
  );
413
409
  try {
@@ -441,7 +437,7 @@ const printSetupNotes = (notes) => {
441
437
  ${boxen(notes.join("\n"), {
442
438
  padding: { top: 1, bottom: 1, right: 1, left: 1 },
443
439
  margin: 1,
444
- borderColour: "gray"
440
+ borderColor: "gray"
445
441
  })}
446
442
  `;
447
443
  }
@@ -452,7 +448,6 @@ export {
452
448
  addPackagesTask,
453
449
  addRoutesToRouterTask,
454
450
  addScaffoldImport,
455
- bytes,
456
451
  cleanupEmptyDirsTask,
457
452
  deleteFile,
458
453
  deleteFilesTask,
@@ -51,16 +51,23 @@ const PLUGIN_CACHE_BUILTIN = [
51
51
  "tc",
52
52
  "upgrade"
53
53
  ];
54
+ function isErrorWithCode(error, code) {
55
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
56
+ }
54
57
  function loadCommandCache() {
55
- let pluginCommandCache = PLUGIN_CACHE_DEFAULT;
58
+ let pluginCommandCache = { ...PLUGIN_CACHE_DEFAULT };
56
59
  const commandCachePath = path.join(
57
60
  getPaths().generated.base,
58
61
  PLUGIN_CACHE_FILENAME
59
62
  );
60
63
  try {
61
- const localCommandCache = JSON.parse(fs.readFileSync(commandCachePath));
64
+ const localCommandCache = JSON.parse(
65
+ fs.readFileSync(commandCachePath, "utf8")
66
+ );
62
67
  let valid = true;
63
- for (const [key, value] of Object.entries(localCommandCache)) {
68
+ for (const [key, value] of Object.entries(
69
+ localCommandCache
70
+ )) {
64
71
  if (key === "_builtin") {
65
72
  continue;
66
73
  }
@@ -73,7 +80,7 @@ function loadCommandCache() {
73
80
  };
74
81
  }
75
82
  } catch (error) {
76
- if (error.code !== "ENOENT") {
83
+ if (!isErrorWithCode(error, "ENOENT")) {
77
84
  console.error(`Error loading plugin command cache at ${commandCachePath}`);
78
85
  console.error(error);
79
86
  }
@@ -162,7 +169,7 @@ async function installPluginPackage(packageName, packageVersion) {
162
169
  console.log(
163
170
  "The following error occurred while checking plugin compatibility for automatic installation:"
164
171
  );
165
- const errorMessage = error.message ?? error;
172
+ const errorMessage = error instanceof Error ? error.message : String(error);
166
173
  console.log(errorMessage);
167
174
  if (errorMessage.includes("does not have a tag") || errorMessage.includes("does not have a version")) {
168
175
  process.exit(1);
@@ -4,6 +4,8 @@ import ansis from "ansis";
4
4
  import boxen from "boxen";
5
5
  import latestVersion from "latest-version";
6
6
  import semver from "semver";
7
+ import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
8
+ import { getNodeRunnerArgs } from "@cedarjs/cli-helpers/packageManager/exec";
7
9
  import { getConfig } from "@cedarjs/project-config";
8
10
  import { spawnBackgroundProcess } from "./background.js";
9
11
  import { isLockSet, setLock, unsetLock } from "./locking.js";
@@ -88,7 +90,7 @@ function getUpdateMessage() {
88
90
  const data = readUpdateDataFile();
89
91
  const localTag = extractTagFromVersion(data.localVersion) || "latest";
90
92
  let updateCount = 0;
91
- let message = " New updates to Cedar are available via `yarn cedar upgrade#REPLACEME#` ";
93
+ let message = ` New updates to Cedar are available via \`${formatCedarCommand(["upgrade#REPLACEME#"])}\` `;
92
94
  data.remoteVersions.forEach((version, tag) => {
93
95
  if (semver.gt(version, data.localVersion)) {
94
96
  updateCount += 1;
@@ -182,10 +184,10 @@ function updateCheckMiddleware(argv) {
182
184
  }
183
185
  if (shouldCheck()) {
184
186
  setLock(CHECK_LOCK_IDENTIFIER);
185
- spawnBackgroundProcess("updateCheck", "yarn", [
186
- "node",
187
+ const [bgCmd, bgArgs] = getNodeRunnerArgs(
187
188
  path.join(import.meta.dirname, "updateCheckExecute.js")
188
- ]);
189
+ );
190
+ spawnBackgroundProcess("updateCheck", bgCmd, bgArgs);
189
191
  } else if (shouldShow()) {
190
192
  setLock(SHOW_LOCK_IDENTIFIER);
191
193
  process.on("exit", () => {
package/dist/plugin.js CHANGED
@@ -59,8 +59,6 @@ async function loadPlugins(yargs) {
59
59
  yargs.command({
60
60
  command: `${namespace} <command>`,
61
61
  describe: `Commands from ${namespace}`,
62
- builder: () => {
63
- },
64
62
  handler: () => {
65
63
  }
66
64
  });
@@ -97,6 +95,7 @@ async function loadPlugins(yargs) {
97
95
  describe: `Commands from ${namespaceInUse}`,
98
96
  builder: (yargs2) => {
99
97
  yargs2.command(commands).demandCommand();
98
+ return yargs2;
100
99
  },
101
100
  handler: () => {
102
101
  }
@@ -108,13 +107,11 @@ async function loadPlugins(yargs) {
108
107
  }
109
108
  const packagesToLoad = /* @__PURE__ */ new Set();
110
109
  for (const [packageName, cacheEntry] of Object.entries(pluginCommandCache)) {
111
- if (packageName === "_builtin") {
110
+ if (packageName === "_builtin" || Array.isArray(cacheEntry)) {
112
111
  continue;
113
112
  }
114
113
  const commandFirstWords = [];
115
- for (const [command, info] of Object.entries(
116
- cacheEntry
117
- )) {
114
+ for (const [command, info] of Object.entries(cacheEntry)) {
118
115
  commandFirstWords.push(command.split(" ")[0]);
119
116
  commandFirstWords.push(
120
117
  ...info.aliases?.map((a) => a.split(" ")[0]) ?? []
@@ -136,6 +133,9 @@ async function loadPlugins(yargs) {
136
133
  const commandsToRegister = [];
137
134
  if (foundMatchingPackage) {
138
135
  const packageToLoad = packagesToLoad.values().next().value;
136
+ if (!packageToLoad) {
137
+ throw new Error(`Invalid first value in ${packagesToLoad}`);
138
+ }
139
139
  const commands = await loadCommandsFromCacheOrPackage(
140
140
  packageToLoad,
141
141
  pluginCommandCache,
@@ -162,6 +162,7 @@ async function loadPlugins(yargs) {
162
162
  describe: `Commands from ${namespaceInUse}`,
163
163
  builder: (yargs2) => {
164
164
  yargs2.command(commandsToRegister).demandCommand();
165
+ return yargs2;
165
166
  },
166
167
  handler: () => {
167
168
  }
@@ -175,8 +176,6 @@ async function loadPlugins(yargs) {
175
176
  yargs.command({
176
177
  command: `${namespace} <command>`,
177
178
  describe: `Commands from ${namespace}`,
178
- builder: () => {
179
- },
180
179
  handler: () => {
181
180
  }
182
181
  });
@@ -187,8 +186,11 @@ async function loadPlugins(yargs) {
187
186
  }
188
187
  async function loadCommandsFromCacheOrPackage(packageName, cache, autoInstall, readFromCache) {
189
188
  let cacheEntry = void 0;
190
- if (readFromCache) {
191
- cacheEntry = cache !== void 0 ? cache[packageName] : void 0;
189
+ if (readFromCache && cache) {
190
+ const entry = cache[packageName];
191
+ if (entry && !Array.isArray(entry)) {
192
+ cacheEntry = entry;
193
+ }
192
194
  }
193
195
  if (cacheEntry !== void 0) {
194
196
  const commands = Object.entries(cacheEntry).map(([command, info]) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli",
3
- "version": "5.0.0-canary.2479",
3
+ "version": "5.0.0-canary.2481",
4
4
  "description": "The CedarJS Command Line",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,17 +33,17 @@
33
33
  "dependencies": {
34
34
  "@babel/parser": "7.29.3",
35
35
  "@babel/preset-typescript": "7.28.5",
36
- "@cedarjs/api-server": "5.0.0-canary.2479",
37
- "@cedarjs/cli-helpers": "5.0.0-canary.2479",
38
- "@cedarjs/fastify-web": "5.0.0-canary.2479",
39
- "@cedarjs/internal": "5.0.0-canary.2479",
40
- "@cedarjs/prerender": "5.0.0-canary.2479",
41
- "@cedarjs/project-config": "5.0.0-canary.2479",
42
- "@cedarjs/structure": "5.0.0-canary.2479",
43
- "@cedarjs/telemetry": "5.0.0-canary.2479",
44
- "@cedarjs/utils": "5.0.0-canary.2479",
45
- "@cedarjs/vite": "5.0.0-canary.2479",
46
- "@cedarjs/web-server": "5.0.0-canary.2479",
36
+ "@cedarjs/api-server": "5.0.0-canary.2481",
37
+ "@cedarjs/cli-helpers": "5.0.0-canary.2481",
38
+ "@cedarjs/fastify-web": "5.0.0-canary.2481",
39
+ "@cedarjs/internal": "5.0.0-canary.2481",
40
+ "@cedarjs/prerender": "5.0.0-canary.2481",
41
+ "@cedarjs/project-config": "5.0.0-canary.2481",
42
+ "@cedarjs/structure": "5.0.0-canary.2481",
43
+ "@cedarjs/telemetry": "5.0.0-canary.2481",
44
+ "@cedarjs/utils": "5.0.0-canary.2481",
45
+ "@cedarjs/vite": "5.0.0-canary.2481",
46
+ "@cedarjs/web-server": "5.0.0-canary.2481",
47
47
  "@listr2/prompt-adapter-enquirer": "4.2.1",
48
48
  "@opentelemetry/api": "1.9.1",
49
49
  "@opentelemetry/core": "1.30.1",