@cedarjs/cli 2.3.1-next.0 → 2.3.1-next.79
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.
- package/dist/commands/{buildHandler.js → build/buildHandler.js} +42 -34
- package/dist/commands/build/buildPackagesTask.js +46 -0
- package/dist/commands/build.js +22 -8
- package/dist/commands/dev/apiDebugFlag.js +18 -0
- package/dist/commands/{devHandler.js → dev/devHandler.js} +60 -64
- package/dist/commands/dev/packageWatchCommands.js +54 -0
- package/dist/commands/dev.js +25 -7
- package/dist/commands/generate/cell/cellHandler.js +3 -1
- package/dist/commands/generate/component/templates/test.tsx.template +1 -1
- package/dist/commands/generate/function/functionHandler.js +1 -1
- package/dist/commands/generate/function/templates/function.ts.template +1 -1
- package/dist/commands/generate/function/templates/test.ts.template +11 -11
- package/dist/commands/generate/layout/templates/test.tsx.template +1 -1
- package/dist/commands/generate/package/packageHandler.js +23 -0
- package/dist/commands/generate/package/templates/README.md.template +1 -1
- package/dist/commands/generate/package/templates/package.json.template +7 -0
- package/dist/commands/generate/package/templates/tsconfig.json.template +1 -0
- package/dist/commands/generate/page/templates/test.tsx.template +1 -1
- package/dist/commands/setup/deploy/templates/netlify.js +7 -6
- package/dist/commands/setup/mailer/templates/mailer.ts.template +2 -1
- package/dist/commands/studio.js +1 -1
- package/dist/commands/studioHandler.js +1 -29
- package/dist/commands/test.js +2 -2
- package/dist/commands/testEsm.js +2 -2
- package/dist/commands/testHandler.js +3 -3
- package/dist/commands/testHandlerEsm.js +3 -3
- package/dist/commands/type-check.js +2 -2
- package/dist/index.js +39 -18
- package/dist/lib/generatePrismaClient.js +6 -2
- package/dist/lib/index.js +2 -3
- package/dist/lib/merge/algorithms.js +1 -1
- package/dist/lib/merge/index.js +3 -2
- package/dist/lib/merge/strategy.js +4 -4
- package/dist/lib/project.js +24 -10
- package/dist/lib/test.js +1 -1
- package/package.json +13 -12
|
@@ -10,28 +10,37 @@ import { generate } from "@cedarjs/internal/dist/generate/generate";
|
|
|
10
10
|
import { loadAndValidateSdls } from "@cedarjs/internal/dist/validateSchema";
|
|
11
11
|
import { detectPrerenderRoutes } from "@cedarjs/prerender/detection";
|
|
12
12
|
import { timedTelemetry } from "@cedarjs/telemetry";
|
|
13
|
-
import { generatePrismaCommand } from "
|
|
14
|
-
import { getPaths, getConfig } from "
|
|
13
|
+
import { generatePrismaCommand } from "../../lib/generatePrismaClient.js";
|
|
14
|
+
import { getPaths, getConfig } from "../../lib/index.js";
|
|
15
|
+
import { buildPackagesTask } from "./buildPackagesTask.js";
|
|
15
16
|
const handler = async ({
|
|
16
|
-
|
|
17
|
+
workspace = ["api", "web", "packages/*"],
|
|
17
18
|
verbose = false,
|
|
18
19
|
prisma = true,
|
|
19
|
-
prerender
|
|
20
|
+
prerender = true
|
|
20
21
|
}) => {
|
|
21
22
|
recordTelemetryAttributes({
|
|
22
23
|
command: "build",
|
|
23
|
-
|
|
24
|
+
workspace: JSON.stringify(workspace),
|
|
24
25
|
verbose,
|
|
25
26
|
prisma,
|
|
26
27
|
prerender
|
|
27
28
|
});
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const useFragments =
|
|
31
|
-
const useTrustedDocuments =
|
|
32
|
-
const prismaSchemaExists = fs.existsSync(
|
|
33
|
-
const prerenderRoutes = prerender &&
|
|
34
|
-
const shouldGeneratePrismaClient = prisma && prismaSchemaExists && (
|
|
29
|
+
const cedarPaths = getPaths();
|
|
30
|
+
const cedarConfig = getConfig();
|
|
31
|
+
const useFragments = cedarConfig.graphql?.fragments;
|
|
32
|
+
const useTrustedDocuments = cedarConfig.graphql?.trustedDocuments;
|
|
33
|
+
const prismaSchemaExists = fs.existsSync(cedarPaths.api.prismaConfig);
|
|
34
|
+
const prerenderRoutes = prerender && workspace.includes("web") ? detectPrerenderRoutes() : [];
|
|
35
|
+
const shouldGeneratePrismaClient = prisma && prismaSchemaExists && (workspace.includes("api") || prerenderRoutes.length > 0);
|
|
36
|
+
const packageJsonPath = path.join(cedarPaths.base, "package.json");
|
|
37
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
38
|
+
const packageJsonWorkspaces = packageJson.workspaces;
|
|
39
|
+
const nonApiWebWorkspaces = Array.isArray(packageJsonWorkspaces) && packageJsonWorkspaces.length > 2 ? workspace.filter((w) => w !== "api" && w !== "web") : [];
|
|
40
|
+
const gqlFeaturesTaskTitle = `Generating types needed for ${[
|
|
41
|
+
useFragments && "GraphQL Fragments",
|
|
42
|
+
useTrustedDocuments && "Trusted Documents"
|
|
43
|
+
].filter(Boolean).join(" and ")} support...`;
|
|
35
44
|
const tasks = [
|
|
36
45
|
shouldGeneratePrismaClient && {
|
|
37
46
|
title: "Generating Prisma Client...",
|
|
@@ -39,28 +48,26 @@ const handler = async ({
|
|
|
39
48
|
const { cmd, args } = await generatePrismaCommand();
|
|
40
49
|
return execa(cmd, args, {
|
|
41
50
|
stdio: verbose ? "inherit" : "pipe",
|
|
42
|
-
|
|
43
|
-
cwd: rwjsPaths.api.base
|
|
51
|
+
cwd: cedarPaths.api.base
|
|
44
52
|
});
|
|
45
53
|
}
|
|
46
54
|
},
|
|
55
|
+
nonApiWebWorkspaces.length > 0 && {
|
|
56
|
+
title: "Building Packages...",
|
|
57
|
+
task: () => buildPackagesTask(nonApiWebWorkspaces)
|
|
58
|
+
},
|
|
47
59
|
// If using GraphQL Fragments or Trusted Documents, then we need to use
|
|
48
|
-
// codegen to generate the types needed for possible types and the
|
|
49
|
-
//
|
|
60
|
+
// codegen to generate the types needed for possible types and the trusted
|
|
61
|
+
// document store hashes
|
|
50
62
|
(useFragments || useTrustedDocuments) && {
|
|
51
|
-
title:
|
|
52
|
-
|
|
53
|
-
useTrustedDocuments && "Trusted Documents"
|
|
54
|
-
].filter(Boolean).join(" and ")} support...`,
|
|
55
|
-
task: async () => {
|
|
56
|
-
await generate();
|
|
57
|
-
}
|
|
63
|
+
title: gqlFeaturesTaskTitle,
|
|
64
|
+
task: generate
|
|
58
65
|
},
|
|
59
|
-
|
|
66
|
+
workspace.includes("api") && {
|
|
60
67
|
title: "Verifying graphql schema...",
|
|
61
68
|
task: loadAndValidateSdls
|
|
62
69
|
},
|
|
63
|
-
|
|
70
|
+
workspace.includes("api") && {
|
|
64
71
|
title: "Building API...",
|
|
65
72
|
task: async () => {
|
|
66
73
|
await cleanApiBuild();
|
|
@@ -73,22 +80,23 @@ const handler = async ({
|
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
},
|
|
76
|
-
|
|
83
|
+
workspace.includes("web") && {
|
|
77
84
|
title: "Building Web...",
|
|
78
85
|
task: async () => {
|
|
79
86
|
process.env.VITE_CJS_IGNORE_WARNING = "true";
|
|
80
87
|
const createdRequire = createRequire(import.meta.url);
|
|
88
|
+
const buildBinPath = createdRequire.resolve(
|
|
89
|
+
"@cedarjs/vite/bins/rw-vite-build.mjs"
|
|
90
|
+
);
|
|
81
91
|
await execa(
|
|
82
|
-
`node ${
|
|
83
|
-
"@cedarjs/vite/bins/rw-vite-build.mjs"
|
|
84
|
-
)} --webDir="${rwjsPaths.web.base}" --verbose=${verbose}`,
|
|
92
|
+
`node ${buildBinPath} --webDir="${cedarPaths.web.base}" --verbose=${verbose}`,
|
|
85
93
|
{
|
|
86
94
|
stdio: verbose ? "inherit" : "pipe",
|
|
87
95
|
shell: true,
|
|
88
96
|
// `cwd` is needed for yarn to find the rw-vite-build binary
|
|
89
97
|
// It won't change process.cwd for anything else here, in this
|
|
90
98
|
// process
|
|
91
|
-
cwd:
|
|
99
|
+
cwd: cedarPaths.web.base
|
|
92
100
|
}
|
|
93
101
|
);
|
|
94
102
|
if (!getConfig().experimental?.streamingSsr?.enabled) {
|
|
@@ -108,7 +116,7 @@ const handler = async ({
|
|
|
108
116
|
console.log(
|
|
109
117
|
`You have not marked any routes to "prerender" in your ${terminalLink(
|
|
110
118
|
"Routes",
|
|
111
|
-
"file://" +
|
|
119
|
+
"file://" + cedarPaths.web.routes
|
|
112
120
|
)}.`
|
|
113
121
|
);
|
|
114
122
|
return;
|
|
@@ -116,15 +124,15 @@ const handler = async ({
|
|
|
116
124
|
await execa("yarn cedar prerender", {
|
|
117
125
|
stdio: "inherit",
|
|
118
126
|
shell: true,
|
|
119
|
-
cwd:
|
|
127
|
+
cwd: cedarPaths.web.base
|
|
120
128
|
});
|
|
121
129
|
};
|
|
122
130
|
const jobs = new Listr(tasks, {
|
|
123
|
-
renderer: verbose
|
|
131
|
+
renderer: verbose ? "verbose" : void 0
|
|
124
132
|
});
|
|
125
133
|
await timedTelemetry(process.argv, { type: "build" }, async () => {
|
|
126
134
|
await jobs.run();
|
|
127
|
-
if (
|
|
135
|
+
if (workspace.includes("web") && prerender && prismaSchemaExists) {
|
|
128
136
|
await triggerPrerender();
|
|
129
137
|
}
|
|
130
138
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import concurrently from "concurrently";
|
|
4
|
+
import { importStatementPath } from "@cedarjs/project-config";
|
|
5
|
+
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
6
|
+
import { exitWithError } from "../../lib/exit.js";
|
|
7
|
+
import { getPaths } from "../../lib/index.js";
|
|
8
|
+
async function buildPackagesTask(nonApiWebWorkspaces) {
|
|
9
|
+
const cedarPaths = getPaths();
|
|
10
|
+
const globPattern = path.join(cedarPaths.packages, "*").replaceAll("\\", "/");
|
|
11
|
+
const workspacePaths = nonApiWebWorkspaces.some((w) => w === "packages/*") ? await Array.fromAsync(fs.promises.glob(globPattern)) : nonApiWebWorkspaces.map((w) => {
|
|
12
|
+
const workspacePath = path.join(
|
|
13
|
+
cedarPaths.packages,
|
|
14
|
+
w.split("/").at(-1)
|
|
15
|
+
);
|
|
16
|
+
if (!fs.existsSync(workspacePath)) {
|
|
17
|
+
throw new Error(`Workspace not found: ${workspacePath}`);
|
|
18
|
+
}
|
|
19
|
+
return importStatementPath(workspacePath);
|
|
20
|
+
});
|
|
21
|
+
const { result } = concurrently(
|
|
22
|
+
workspacePaths.map((workspacePath) => {
|
|
23
|
+
return {
|
|
24
|
+
command: `yarn build`,
|
|
25
|
+
name: workspacePath.split("/").at(-1),
|
|
26
|
+
cwd: workspacePath
|
|
27
|
+
};
|
|
28
|
+
}),
|
|
29
|
+
{
|
|
30
|
+
prefix: "{name} |",
|
|
31
|
+
timestampFormat: "HH:mm:ss"
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
await result.catch((e) => {
|
|
35
|
+
if (e?.message) {
|
|
36
|
+
errorTelemetry(
|
|
37
|
+
process.argv,
|
|
38
|
+
`Error concurrently building sides: ${e.message}`
|
|
39
|
+
);
|
|
40
|
+
exitWithError(e);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
buildPackagesTask
|
|
46
|
+
};
|
package/dist/commands/build.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { terminalLink } from "termi-link";
|
|
2
2
|
import c from "../lib/colors.js";
|
|
3
3
|
import { exitWithError } from "../lib/exit.js";
|
|
4
|
-
import {
|
|
4
|
+
import { workspaces } from "../lib/project.js";
|
|
5
5
|
import { checkNodeVersion } from "../middleware/checkNodeVersion.js";
|
|
6
|
-
const command = "build [
|
|
6
|
+
const command = "build [workspace..]";
|
|
7
7
|
const description = "Build for production";
|
|
8
8
|
const builder = (yargs) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
default: choices,
|
|
13
|
-
description: "Which side(s) to build",
|
|
9
|
+
yargs.positional("workspace", {
|
|
10
|
+
default: ["api", "web", "packages/*"],
|
|
11
|
+
description: "What workspace(s) to build. Valid values are: web, api, packages/*, <package-name>",
|
|
14
12
|
type: "array"
|
|
15
13
|
}).option("verbose", {
|
|
16
14
|
alias: "v",
|
|
@@ -35,6 +33,22 @@ const builder = (yargs) => {
|
|
|
35
33
|
message: `${c.error("Error")}: ${check.message}`,
|
|
36
34
|
includeEpilogue: false
|
|
37
35
|
});
|
|
36
|
+
}).check((argv) => {
|
|
37
|
+
const workspacesArg = argv.workspace;
|
|
38
|
+
if (!Array.isArray(workspacesArg)) {
|
|
39
|
+
return "Workspace must be an array";
|
|
40
|
+
}
|
|
41
|
+
const filtered = workspacesArg.filter(
|
|
42
|
+
(item) => item !== "api" && item !== "web" && item !== "packages/*"
|
|
43
|
+
);
|
|
44
|
+
if (filtered.length === 0) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
const workspaceNames = workspaces({ includePackages: true });
|
|
48
|
+
if (!workspacesArg.every((item) => workspaceNames.includes(item))) {
|
|
49
|
+
return c.error(`Unknown workspace(s) ${workspacesArg.join(" ")}`) + "\n\nValid values are: " + workspaceNames.join(", ");
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
38
52
|
}).epilogue(
|
|
39
53
|
`Also see the ${terminalLink(
|
|
40
54
|
"CedarJS CLI Reference",
|
|
@@ -43,7 +57,7 @@ const builder = (yargs) => {
|
|
|
43
57
|
);
|
|
44
58
|
};
|
|
45
59
|
const handler = async (options) => {
|
|
46
|
-
const { handler: handler2 } = await import("./buildHandler.js");
|
|
60
|
+
const { handler: handler2 } = await import("./build/buildHandler.js");
|
|
47
61
|
return handler2(options);
|
|
48
62
|
};
|
|
49
63
|
export {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { argv } from "node:process";
|
|
2
|
+
import { getConfig } from "@cedarjs/project-config";
|
|
3
|
+
const defaultApiDebugPort = 18911;
|
|
4
|
+
function getApiDebugFlag(apiDebugPort) {
|
|
5
|
+
if (apiDebugPort) {
|
|
6
|
+
return `--debug-port ${apiDebugPort}`;
|
|
7
|
+
} else if (argv.includes("--apiDebugPort")) {
|
|
8
|
+
return `--debug-port ${defaultApiDebugPort}`;
|
|
9
|
+
}
|
|
10
|
+
const apiDebugPortInConfig = getConfig().api.debugPort;
|
|
11
|
+
if (apiDebugPortInConfig) {
|
|
12
|
+
return `--debug-port ${apiDebugPortInConfig}`;
|
|
13
|
+
}
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
getApiDebugFlag
|
|
18
|
+
};
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { argv } from "node:process";
|
|
4
3
|
import concurrently from "concurrently";
|
|
5
4
|
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
6
5
|
import { shutdownPort } from "@cedarjs/internal/dist/dev";
|
|
7
6
|
import { getConfig, getConfigPath } from "@cedarjs/project-config";
|
|
8
7
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
9
|
-
import c from "
|
|
10
|
-
import { exitWithError } from "
|
|
11
|
-
import { generatePrismaClient } from "
|
|
12
|
-
import { getPaths } from "
|
|
13
|
-
import { getFreePort } from "
|
|
14
|
-
import { serverFileExists } from "
|
|
15
|
-
|
|
8
|
+
import c from "../../lib/colors.js";
|
|
9
|
+
import { exitWithError } from "../../lib/exit.js";
|
|
10
|
+
import { generatePrismaClient } from "../../lib/generatePrismaClient.js";
|
|
11
|
+
import { getPaths } from "../../lib/index.js";
|
|
12
|
+
import { getFreePort } from "../../lib/ports.js";
|
|
13
|
+
import { serverFileExists } from "../../lib/project.js";
|
|
14
|
+
import { getApiDebugFlag } from "./apiDebugFlag.js";
|
|
15
|
+
import { getPackageWatchCommands } from "./packageWatchCommands.js";
|
|
16
16
|
const handler = async ({
|
|
17
|
-
|
|
17
|
+
workspace = ["api", "web", "packages/*"],
|
|
18
18
|
forward = "",
|
|
19
19
|
generate = true,
|
|
20
20
|
apiDebugPort
|
|
21
21
|
}) => {
|
|
22
22
|
recordTelemetryAttributes({
|
|
23
23
|
command: "dev",
|
|
24
|
-
|
|
24
|
+
workspace: JSON.stringify(workspace),
|
|
25
25
|
generate
|
|
26
26
|
});
|
|
27
|
-
const
|
|
27
|
+
const cedarPaths = getPaths();
|
|
28
28
|
const serverFile = serverFileExists();
|
|
29
29
|
const apiPreferredPort = parseInt(String(getConfig().api.port));
|
|
30
30
|
let webPreferredPort = parseInt(
|
|
@@ -34,7 +34,7 @@ const handler = async ({
|
|
|
34
34
|
let apiPortChangeNeeded = false;
|
|
35
35
|
let webAvailablePort = webPreferredPort;
|
|
36
36
|
let webPortChangeNeeded = false;
|
|
37
|
-
if (
|
|
37
|
+
if (workspace.includes("api") && !serverFile) {
|
|
38
38
|
apiAvailablePort = await getFreePort(apiPreferredPort);
|
|
39
39
|
if (apiAvailablePort === -1) {
|
|
40
40
|
exitWithError(void 0, {
|
|
@@ -43,7 +43,7 @@ const handler = async ({
|
|
|
43
43
|
}
|
|
44
44
|
apiPortChangeNeeded = apiAvailablePort !== apiPreferredPort;
|
|
45
45
|
}
|
|
46
|
-
if (
|
|
46
|
+
if (workspace.includes("web")) {
|
|
47
47
|
const forwardedPortMatches = [
|
|
48
48
|
...forward.matchAll(/\-\-port(\=|\s)(?<port>[^\s]*)/g)
|
|
49
49
|
];
|
|
@@ -80,14 +80,14 @@ const handler = async ({
|
|
|
80
80
|
].filter(Boolean).join(" ");
|
|
81
81
|
exitWithError(void 0, { message });
|
|
82
82
|
}
|
|
83
|
-
if (
|
|
83
|
+
if (workspace.includes("api")) {
|
|
84
84
|
try {
|
|
85
85
|
await generatePrismaClient({
|
|
86
86
|
verbose: false,
|
|
87
87
|
force: false
|
|
88
88
|
});
|
|
89
89
|
} catch (e) {
|
|
90
|
-
const message =
|
|
90
|
+
const message = getErrorMessage(e);
|
|
91
91
|
errorTelemetry(process.argv, `Error generating prisma client: ${message}`);
|
|
92
92
|
console.error(c.error(message));
|
|
93
93
|
}
|
|
@@ -95,7 +95,7 @@ const handler = async ({
|
|
|
95
95
|
try {
|
|
96
96
|
await shutdownPort(apiAvailablePort);
|
|
97
97
|
} catch (e) {
|
|
98
|
-
const message =
|
|
98
|
+
const message = getErrorMessage(e);
|
|
99
99
|
errorTelemetry(process.argv, `Error shutting down "api": ${message}`);
|
|
100
100
|
console.error(
|
|
101
101
|
`Error whilst shutting down "api" port: ${c.error(message)}`
|
|
@@ -103,51 +103,41 @@ const handler = async ({
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
if (
|
|
106
|
+
if (workspace.includes("web")) {
|
|
107
107
|
try {
|
|
108
108
|
await shutdownPort(webAvailablePort);
|
|
109
109
|
} catch (e) {
|
|
110
|
-
const message =
|
|
110
|
+
const message = getErrorMessage(e);
|
|
111
111
|
errorTelemetry(process.argv, `Error shutting down "web": ${message}`);
|
|
112
112
|
console.error(
|
|
113
113
|
`Error whilst shutting down "web" port: ${c.error(message)}`
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
const
|
|
118
|
-
if (apiDebugPort) {
|
|
119
|
-
return `--debug-port ${apiDebugPort}`;
|
|
120
|
-
} else if (argv.includes("--apiDebugPort")) {
|
|
121
|
-
return `--debug-port ${defaultApiDebugPort}`;
|
|
122
|
-
}
|
|
123
|
-
const apiDebugPortInToml = getConfig().api.debugPort;
|
|
124
|
-
if (apiDebugPortInToml) {
|
|
125
|
-
return `--debug-port ${apiDebugPortInToml}`;
|
|
126
|
-
}
|
|
127
|
-
return "";
|
|
128
|
-
};
|
|
129
|
-
const redwoodConfigPath = getConfigPath();
|
|
117
|
+
const cedarConfigPath = getConfigPath();
|
|
130
118
|
const streamingSsrEnabled = getConfig().experimental?.streamingSsr?.enabled;
|
|
131
119
|
process.env.VITE_CJS_IGNORE_WARNING = "true";
|
|
132
120
|
let webCommand = `yarn cross-env NODE_ENV=development rw-vite-dev ${forward}`;
|
|
133
121
|
if (streamingSsrEnabled) {
|
|
134
122
|
webCommand = `yarn cross-env NODE_ENV=development rw-dev-fe ${forward}`;
|
|
135
123
|
}
|
|
124
|
+
const rootPackageJsonPath = path.join(cedarPaths.base, "package.json");
|
|
136
125
|
const rootPackageJson = JSON.parse(
|
|
137
|
-
fs.readFileSync(
|
|
126
|
+
fs.readFileSync(rootPackageJsonPath, "utf8")
|
|
138
127
|
);
|
|
139
128
|
const isEsm = rootPackageJson.type === "module";
|
|
140
129
|
const serverWatchCommand = isEsm ? `cedarjs-api-server-watch` : `rw-api-server-watch`;
|
|
141
|
-
const jobs =
|
|
142
|
-
|
|
130
|
+
const jobs = [];
|
|
131
|
+
if (workspace.includes("api")) {
|
|
132
|
+
jobs.push({
|
|
143
133
|
name: "api",
|
|
144
134
|
command: [
|
|
145
135
|
"yarn nodemon",
|
|
146
136
|
" --quiet",
|
|
147
|
-
` --watch "${
|
|
137
|
+
` --watch "${cedarConfigPath}"`,
|
|
148
138
|
` --exec "yarn ${serverWatchCommand}`,
|
|
149
139
|
` --port ${apiAvailablePort}`,
|
|
150
|
-
` ${getApiDebugFlag()}`,
|
|
140
|
+
` ${getApiDebugFlag(apiDebugPort)}`,
|
|
151
141
|
' | rw-log-formatter"'
|
|
152
142
|
].join(" ").replace(/\s+/g, " "),
|
|
153
143
|
env: {
|
|
@@ -155,45 +145,48 @@ const handler = async ({
|
|
|
155
145
|
NODE_OPTIONS: getDevNodeOptions()
|
|
156
146
|
},
|
|
157
147
|
prefixColor: "cyan",
|
|
158
|
-
runWhen: () => fs.existsSync(
|
|
159
|
-
}
|
|
160
|
-
|
|
148
|
+
runWhen: () => fs.existsSync(cedarPaths.api.src)
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (workspace.includes("web")) {
|
|
152
|
+
jobs.push({
|
|
161
153
|
name: "web",
|
|
162
154
|
command: webCommand,
|
|
163
155
|
prefixColor: "blue",
|
|
164
|
-
cwd:
|
|
165
|
-
runWhen: () => fs.existsSync(
|
|
166
|
-
}
|
|
167
|
-
|
|
156
|
+
cwd: cedarPaths.web.base,
|
|
157
|
+
runWhen: () => fs.existsSync(cedarPaths.web.src)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (generate) {
|
|
161
|
+
jobs.push({
|
|
168
162
|
name: "gen",
|
|
169
163
|
command: "yarn rw-gen-watch",
|
|
170
|
-
prefixColor: "green"
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
164
|
+
prefixColor: "green"
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const packageWorkspaces = workspace.filter(
|
|
168
|
+
(w) => w !== "api" && w !== "web" && w !== "gen"
|
|
169
|
+
);
|
|
170
|
+
if (packageWorkspaces.length > 0) {
|
|
171
|
+
const hasPackageJsonWorkspaces = Array.isArray(rootPackageJson.workspaces) && rootPackageJson.workspaces.some(
|
|
172
|
+
(workspace2) => workspace2.startsWith("packages/")
|
|
173
|
+
);
|
|
174
|
+
if (hasPackageJsonWorkspaces && fs.existsSync(cedarPaths.packages)) {
|
|
175
|
+
const pkgCommands = await getPackageWatchCommands(packageWorkspaces);
|
|
176
|
+
jobs.push(...pkgCommands);
|
|
177
177
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
}
|
|
179
|
+
const filteredJobs = jobs.filter((job) => !job.runWhen || job.runWhen());
|
|
180
|
+
const { result } = concurrently(filteredJobs, {
|
|
181
|
+
prefix: "{name} |",
|
|
182
|
+
timestampFormat: "HH:mm:ss",
|
|
183
|
+
handleInput: true
|
|
183
184
|
});
|
|
184
|
-
const { result } = concurrently(
|
|
185
|
-
mappedJobs.filter((job) => job.runWhen()),
|
|
186
|
-
{
|
|
187
|
-
prefix: "{name} |",
|
|
188
|
-
timestampFormat: "HH:mm:ss",
|
|
189
|
-
handleInput: true
|
|
190
|
-
}
|
|
191
|
-
);
|
|
192
185
|
result.catch((e) => {
|
|
193
186
|
if (e?.message) {
|
|
194
187
|
errorTelemetry(
|
|
195
188
|
process.argv,
|
|
196
|
-
`Error concurrently starting
|
|
189
|
+
`Error concurrently starting workspaces: ${e.message}`
|
|
197
190
|
);
|
|
198
191
|
exitWithError(e);
|
|
199
192
|
}
|
|
@@ -210,6 +203,9 @@ function getDevNodeOptions() {
|
|
|
210
203
|
}
|
|
211
204
|
return `${NODE_OPTIONS} ${enableSourceMapsOption}`;
|
|
212
205
|
}
|
|
206
|
+
function getErrorMessage(error) {
|
|
207
|
+
return error instanceof Object && "message" in error ? error.message : String(error);
|
|
208
|
+
}
|
|
213
209
|
export {
|
|
214
210
|
getDevNodeOptions,
|
|
215
211
|
handler
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { importStatementPath } from "@cedarjs/project-config";
|
|
4
|
+
import c from "../../lib/colors.js";
|
|
5
|
+
import { getPaths } from "../../lib/index.js";
|
|
6
|
+
async function getPackageWatchCommands(packageWorkspaces) {
|
|
7
|
+
const cedarPaths = getPaths();
|
|
8
|
+
const globPattern = path.join(cedarPaths.packages, "*").replaceAll("\\", "/");
|
|
9
|
+
const workspacePaths = packageWorkspaces.some((w) => w === "packages/*") ? await Array.fromAsync(fs.promises.glob(globPattern)) : packageWorkspaces.map((w) => {
|
|
10
|
+
const packageFolderName = w.split("/").at(-1);
|
|
11
|
+
if (!packageFolderName) {
|
|
12
|
+
throw new Error(`Invalid package workspace: ${w}`);
|
|
13
|
+
}
|
|
14
|
+
const workspacePath = path.join(cedarPaths.packages, packageFolderName);
|
|
15
|
+
if (!fs.existsSync(workspacePath)) {
|
|
16
|
+
throw new Error(`Workspace not found: ${workspacePath}`);
|
|
17
|
+
}
|
|
18
|
+
return importStatementPath(workspacePath);
|
|
19
|
+
});
|
|
20
|
+
const watchablePackages = [];
|
|
21
|
+
const packagesWithoutWatch = [];
|
|
22
|
+
for (const workspacePath of workspacePaths) {
|
|
23
|
+
const packageJsonPath = path.join(workspacePath, "package.json");
|
|
24
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
28
|
+
const packageName = workspacePath.split("/").at(-1);
|
|
29
|
+
if (packageJson.scripts?.watch) {
|
|
30
|
+
watchablePackages.push(workspacePath);
|
|
31
|
+
} else {
|
|
32
|
+
packagesWithoutWatch.push(packageName);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (packagesWithoutWatch.length > 0) {
|
|
36
|
+
console.warn(
|
|
37
|
+
`${c.warning("Warning: ")} The following package(s) do not have a "watch" script and will be skipped: ` + packagesWithoutWatch.join(", ")
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return watchablePackages.map((workspacePath) => {
|
|
41
|
+
const name = workspacePath.split("/").at(-1);
|
|
42
|
+
if (!name) {
|
|
43
|
+
throw new Error(`Invalid package path: ${workspacePath}`);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
name,
|
|
47
|
+
command: "yarn watch",
|
|
48
|
+
cwd: workspacePath
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
getPackageWatchCommands
|
|
54
|
+
};
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { terminalLink } from "termi-link";
|
|
2
2
|
import c from "../lib/colors.js";
|
|
3
|
+
import { workspaces } from "../lib/project.js";
|
|
3
4
|
import { checkNodeVersion } from "../middleware/checkNodeVersion.js";
|
|
4
|
-
const command = "dev [
|
|
5
|
-
const description = "Start development servers for api, and
|
|
5
|
+
const command = "dev [workspace..]";
|
|
6
|
+
const description = "Start development servers for api, web, and packages";
|
|
6
7
|
const builder = (yargs) => {
|
|
7
|
-
yargs.positional("
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
description: "Which dev server(s) to start",
|
|
8
|
+
yargs.positional("workspace", {
|
|
9
|
+
default: ["api", "web", "packages/*"],
|
|
10
|
+
description: "Which dev server(s) to start. Valid values: api, web, packages/*, <package-name>",
|
|
11
11
|
type: "string",
|
|
12
12
|
array: true
|
|
13
13
|
}).option("forward", {
|
|
14
14
|
alias: "fwd",
|
|
15
15
|
description: 'String of one or more vite dev server config options, for example: `--fwd="--port=1234 --open=false"`',
|
|
16
16
|
type: "string",
|
|
17
|
+
// The reason `forward` is hidden is that it's been broken with Vite and
|
|
18
|
+
// it's not clear how to fix it.
|
|
17
19
|
hidden: true
|
|
18
20
|
}).option("generate", {
|
|
19
21
|
type: "boolean",
|
|
@@ -29,6 +31,22 @@ const builder = (yargs) => {
|
|
|
29
31
|
}
|
|
30
32
|
console.warn(`${c.warning("Warning")}: ${check.message}
|
|
31
33
|
`);
|
|
34
|
+
}).check((argv) => {
|
|
35
|
+
const workspaceArg = argv.workspace;
|
|
36
|
+
if (!Array.isArray(workspaceArg)) {
|
|
37
|
+
return "Workspace must be an array";
|
|
38
|
+
}
|
|
39
|
+
const filtered = workspaceArg.filter(
|
|
40
|
+
(item) => item !== "api" && item !== "web" && item !== "packages/*"
|
|
41
|
+
);
|
|
42
|
+
if (filtered.length === 0) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
const workspaceNames = workspaces({ includePackages: true });
|
|
46
|
+
if (!filtered.every((item) => workspaceNames.includes(item))) {
|
|
47
|
+
return c.error(`Unknown workspace(s) ${filtered.join(" ")}`) + "\n\nValid values are: " + workspaceNames.join(", ");
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
32
50
|
}).epilogue(
|
|
33
51
|
`Also see the ${terminalLink(
|
|
34
52
|
"CedarJS CLI Reference",
|
|
@@ -37,7 +55,7 @@ const builder = (yargs) => {
|
|
|
37
55
|
);
|
|
38
56
|
};
|
|
39
57
|
const handler = async (options) => {
|
|
40
|
-
const { handler: handler2 } = await import("./devHandler.js");
|
|
58
|
+
const { handler: handler2 } = await import("./dev/devHandler.js");
|
|
41
59
|
return handler2(options);
|
|
42
60
|
};
|
|
43
61
|
export {
|
|
@@ -22,7 +22,9 @@ const REDWOOD_WEB_PATH_NAME = "components";
|
|
|
22
22
|
const files = async ({ name, typescript, ...argv }) => {
|
|
23
23
|
let cellName = removeGeneratorName(name, "cell");
|
|
24
24
|
let idName = "id";
|
|
25
|
-
let idType
|
|
25
|
+
let idType;
|
|
26
|
+
let mockIdValues = [42, 43, 44];
|
|
27
|
+
let model = null;
|
|
26
28
|
let templateNameSuffix = "";
|
|
27
29
|
let typeName = cellName;
|
|
28
30
|
const shouldGenerateList = (isWordPluralizable(cellName) ? isPlural(cellName) : argv.list) || argv.list;
|
|
@@ -2,7 +2,7 @@ import { render } from '@cedarjs/testing/web'
|
|
|
2
2
|
|
|
3
3
|
import ${pascalName} from './${pascalName}'
|
|
4
4
|
|
|
5
|
-
// Improve this test with help from the
|
|
5
|
+
// Improve this test with help from the CedarJS Testing Doc:
|
|
6
6
|
// https://cedarjs.com/docs/testing#testing-components
|
|
7
7
|
|
|
8
8
|
describe('${pascalName}', () => {
|
|
@@ -91,7 +91,7 @@ const handler = async ({ name, force, ...rest }) => {
|
|
|
91
91
|
`Please consult the ${terminalLink(
|
|
92
92
|
"Serverless Function Considerations",
|
|
93
93
|
"https://cedarjs.com/docs/serverless-functions#security-considerations"
|
|
94
|
-
)} in the
|
|
94
|
+
)} in the CedarJS documentation for more information.`
|
|
95
95
|
);
|
|
96
96
|
console.info("");
|
|
97
97
|
} catch (e) {
|
|
@@ -10,7 +10,7 @@ import { logger } from 'src/lib/logger'
|
|
|
10
10
|
* is your responsibility to secure appropriately.
|
|
11
11
|
*
|
|
12
12
|
* @see {@link https://cedarjs.com/docs/serverless-functions#security-considerations|Serverless Function Considerations}
|
|
13
|
-
* in the
|
|
13
|
+
* in the CedarJS documentation for more information.
|
|
14
14
|
*<% if (!typescript) { %>
|
|
15
15
|
* @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent
|
|
16
16
|
* @typedef { import('aws-lambda').Context } Context<% } %>
|