@cedarjs/cli 5.0.0-canary.2379 → 5.0.0-canary.2383

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/cfw.js CHANGED
@@ -34,10 +34,9 @@ try {
34
34
  execa.sync("yarn", [...command], {
35
35
  stdio: "inherit",
36
36
  cwd: absCfwPath,
37
- env: {
38
- CEDAR_CWD: projectPath
39
- }
37
+ // @ts-expect-error - testUtils.d.ts augments ProcessEnv with REDWOOD_DISABLE_TELEMETRY
38
+ env: { CEDAR_CWD: projectPath }
40
39
  });
41
- } catch (e) {
40
+ } catch {
42
41
  console.log();
43
42
  }
@@ -37,26 +37,26 @@ const forcePluralizeWord = (word) => {
37
37
  }
38
38
  return pluralize(word);
39
39
  };
40
+ const routeParamToTsType = {
41
+ Int: "number",
42
+ Float: "number",
43
+ Boolean: "boolean",
44
+ String: "string"
45
+ };
40
46
  const mapRouteParamTypeToTsType = (paramType) => {
41
- const routeParamToTsType = {
42
- Int: "number",
43
- Float: "number",
44
- Boolean: "boolean",
45
- String: "string"
46
- };
47
47
  return routeParamToTsType[paramType] || "unknown";
48
48
  };
49
+ const prismaScalarToTsType = {
50
+ String: "string",
51
+ Boolean: "boolean",
52
+ Int: "number",
53
+ BigInt: "number",
54
+ Float: "number",
55
+ Decimal: "number",
56
+ DateTime: "string",
57
+ Bytes: "Uint8Array"
58
+ };
49
59
  const mapPrismaScalarToPagePropTsType = (scalarType) => {
50
- const prismaScalarToTsType = {
51
- String: "string",
52
- Boolean: "boolean",
53
- Int: "number",
54
- BigInt: "number",
55
- Float: "number",
56
- Decimal: "number",
57
- DateTime: "string",
58
- Bytes: "Uint8Array"
59
- };
60
60
  return prismaScalarToTsType[scalarType] || "unknown";
61
61
  };
62
62
  export {
@@ -1,7 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import * as parser from "@babel/parser";
4
+ import * as t from "@babel/types";
3
5
  import execa from "execa";
4
6
  import { Listr } from "listr2";
7
+ import * as recast from "recast";
5
8
  import { getConfigPath, getConfig } from "@cedarjs/project-config";
6
9
  import { getPaths, writeFilesTask } from "../../../../lib/index.js";
7
10
  const updateApiURLTask = (apiUrl) => {
@@ -84,6 +87,91 @@ const verifyUDSetupTask = () => {
84
87
  }
85
88
  };
86
89
  };
90
+ function posToIndex(str, line, column) {
91
+ const lines = str.split("\n");
92
+ let index = 0;
93
+ for (let i = 0; i < line - 1; i++) {
94
+ index += lines[i].length + 1;
95
+ }
96
+ return index + column;
97
+ }
98
+ function insertPluginsBeforeCedar({ content, pluginCodes }) {
99
+ const ast = recast.parse(content, {
100
+ parser: {
101
+ parse(source) {
102
+ return parser.parse(source, {
103
+ sourceType: "module",
104
+ plugins: ["typescript", "jsx"]
105
+ });
106
+ }
107
+ }
108
+ });
109
+ const defaultExport = ast.program.body.find(
110
+ (node) => t.isExportDefaultDeclaration(node) && t.isCallExpression(node.declaration) && t.isIdentifier(node.declaration.callee) && node.declaration.callee.name === "defineConfig"
111
+ );
112
+ if (!defaultExport) {
113
+ return null;
114
+ }
115
+ const configArg = defaultExport.declaration.arguments[0];
116
+ if (!t.isObjectExpression(configArg)) {
117
+ return null;
118
+ }
119
+ const pluginsProp = configArg.properties.find(
120
+ (prop) => t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name === "plugins" && t.isArrayExpression(prop.value)
121
+ );
122
+ if (!pluginsProp) {
123
+ return null;
124
+ }
125
+ const elements = pluginsProp.value.elements;
126
+ const cedarIndex = elements.findIndex(
127
+ (el) => t.isCallExpression(el) && t.isIdentifier(el.callee) && el.callee.name === "cedar"
128
+ );
129
+ if (cedarIndex === -1) {
130
+ return null;
131
+ }
132
+ const cedarNode = elements[cedarIndex];
133
+ const arrayNode = pluginsProp.value;
134
+ const isInline = cedarNode.loc.start.line === arrayNode.loc.start.line;
135
+ if (isInline) {
136
+ const startPos = posToIndex(
137
+ content,
138
+ arrayNode.loc.start.line,
139
+ arrayNode.loc.start.column
140
+ );
141
+ const endPos = posToIndex(
142
+ content,
143
+ arrayNode.loc.end.line,
144
+ arrayNode.loc.end.column
145
+ );
146
+ const precedingText = content.slice(0, startPos);
147
+ const followingText = content.slice(endPos);
148
+ const existingCodes = elements.map(
149
+ (el) => content.slice(
150
+ posToIndex(content, el.loc.start.line, el.loc.start.column),
151
+ posToIndex(content, el.loc.end.line, el.loc.end.column)
152
+ )
153
+ );
154
+ const lines2 = content.split("\n");
155
+ const pluginsLine = pluginsProp.loc.start.line;
156
+ const pluginsIndent = lines2[pluginsLine - 1].match(/^\s*/)[0];
157
+ const elemIndent = pluginsIndent + " ";
158
+ const allCodes = [...existingCodes];
159
+ allCodes.splice(cedarIndex, 0, ...pluginCodes);
160
+ const multiline = [
161
+ "[",
162
+ ...allCodes.map((code) => `${elemIndent}${code},`),
163
+ `${pluginsIndent}]`
164
+ ].join("\n");
165
+ return precedingText + multiline + followingText;
166
+ }
167
+ const cedarLine = cedarNode.loc.start.line;
168
+ const insertPos = posToIndex(content, cedarLine, 0);
169
+ const lines = content.split("\n");
170
+ const indent = lines[cedarLine - 1].match(/^\s*/)[0];
171
+ const insertion = pluginCodes.map((code) => `${indent}${code},
172
+ `).join("");
173
+ return content.slice(0, insertPos) + insertion + content.slice(insertPos);
174
+ }
87
175
  const addToGitIgnoreTask = ({ paths }) => {
88
176
  return {
89
177
  title: "Updating .gitignore...",
@@ -125,6 +213,7 @@ export {
125
213
  addToDotEnvTask,
126
214
  addToGitIgnoreTask,
127
215
  getUserApiUrl,
216
+ insertPluginsBeforeCedar,
128
217
  preRequisiteCheckTask,
129
218
  updateApiURLTask,
130
219
  verifyUDSetupTask
@@ -10,6 +10,7 @@ import {
10
10
  } from "../../../../lib/index.js";
11
11
  import {
12
12
  addFilesTask,
13
+ insertPluginsBeforeCedar,
13
14
  updateApiURLTask,
14
15
  verifyUDSetupTask
15
16
  } from "../helpers/index.js";
@@ -87,17 +88,16 @@ ${result}`;
87
88
  }
88
89
  }
89
90
  if (!content.includes("netlifyCompat(")) {
90
- content = content.replace(
91
- /(\s*)(plugins:\s*\[)([\s\S]*?)(cedar\s*\()/,
92
- (_match, leadingWs, prefix, beforeCedar, cedarCall) => {
93
- const indent = beforeCedar.includes("\n") ? beforeCedar.match(/\n(\s*)$/)?.[1] || leadingWs + " " : leadingWs + " ";
94
- const before = beforeCedar.replace(/\s*$/, "");
95
- return `${leadingWs}${prefix}
96
- ${indent}netlify({ build: { enabled: true } }),
97
- ${indent}netlifyCompat(),${before}
98
- ${indent}${cedarCall}`;
99
- }
100
- );
91
+ const result = insertPluginsBeforeCedar({
92
+ content,
93
+ pluginCodes: [
94
+ "netlify({ build: { enabled: true } })",
95
+ "netlifyCompat()"
96
+ ]
97
+ });
98
+ if (result) {
99
+ content = result;
100
+ }
101
101
  }
102
102
  fs.writeFileSync(viteConfigPath, content);
103
103
  }
@@ -9,7 +9,11 @@ import {
9
9
  printSetupNotes,
10
10
  writeFile
11
11
  } from "../../../../lib/index.js";
12
- import { updateApiURLTask, verifyUDSetupTask } from "../helpers/index.js";
12
+ import {
13
+ insertPluginsBeforeCedar,
14
+ updateApiURLTask,
15
+ verifyUDSetupTask
16
+ } from "../helpers/index.js";
13
17
  async function handler({ force, ud }) {
14
18
  recordTelemetryAttributes({
15
19
  command: "setup deploy vercel",
@@ -67,16 +71,13 @@ function addVercelPluginToViteConfigTask() {
67
71
  }
68
72
  }
69
73
  if (!content.includes("vercel(")) {
70
- content = content.replace(
71
- /(\s*)(plugins:\s*\[)([\s\S]*?)(cedar\s*\()/,
72
- (_match, leadingWs, prefix, beforeCedar, cedarCall) => {
73
- const indent = beforeCedar.includes("\n") ? beforeCedar.match(/\n(\s*)$/)?.[1] || leadingWs + " " : leadingWs + " ";
74
- const before = beforeCedar.replace(/\s*$/, "");
75
- return `${leadingWs}${prefix}
76
- ${indent}vercel(),${before}
77
- ${indent}${cedarCall}`;
78
- }
79
- );
74
+ const result = insertPluginsBeforeCedar({
75
+ content,
76
+ pluginCodes: ["vercel()"]
77
+ });
78
+ if (result) {
79
+ content = result;
80
+ }
80
81
  }
81
82
  fs.writeFileSync(viteConfigPath, content);
82
83
  }
@@ -8,7 +8,7 @@ publish = "web/dist"
8
8
  NODE_VERSION = "24"
9
9
 
10
10
  [functions]
11
- directory = "api/dist/functions"
11
+ directory = "api/dist/ud"
12
12
 
13
13
  # To use Netlify Dev, install Netlify's CLI (\`netlify-cli\`) from NPM and use
14
14
  # \`netlify link\` to connect your local project to a site on Netlify. Then run
package/dist/lib/exit.js CHANGED
@@ -12,12 +12,27 @@ const DEFAULT_ERROR_EPILOGUE = [
12
12
  ` - Not sure about something or need advice? Reach out on our ${discordLink}`,
13
13
  ` - Think you've found a bug? Open an issue on our ${githubLink}`
14
14
  ].join("\n");
15
- function exitWithError(error, { exitCode, message, epilogue, includeEpilogue, includeReferenceCode } = {}) {
16
- exitCode ??= error?.exitCode ?? 1;
15
+ function exitWithError(error, {
16
+ exitCode,
17
+ message,
18
+ epilogue,
19
+ includeEpilogue,
20
+ includeReferenceCode
21
+ } = {}) {
22
+ if (error && typeof error === "object" && "exitCode" in error) {
23
+ exitCode ??= typeof error.exitCode === "number" ? error.exitCode : 1;
24
+ }
25
+ exitCode ??= 1;
17
26
  epilogue ??= DEFAULT_ERROR_EPILOGUE;
18
27
  includeEpilogue ??= true;
19
28
  includeReferenceCode ??= true;
20
- message ??= error.stack ?? (error.toString() || "Unknown error");
29
+ if (message === void 0) {
30
+ if (error instanceof Error && error.stack) {
31
+ message = error.stack;
32
+ } else {
33
+ message = String(error) || "Unknown error";
34
+ }
35
+ }
21
36
  const errorReferenceCode = uuidv4();
22
37
  const line = ansis.red("-".repeat(process.stderr.columns - 4));
23
38
  const content = !includeEpilogue ? message : [
@@ -31,7 +46,7 @@ ${line}`,
31
46
  line
32
47
  ].filter(Boolean).join("\n");
33
48
  console.error(content);
34
- recordTelemetryError(error ?? new Error(message));
49
+ recordTelemetryError(error ?? new Error(message ?? ""));
35
50
  recordTelemetryAttributes({ errorReferenceCode });
36
51
  process.exit(exitCode);
37
52
  }
@@ -35,10 +35,12 @@ async function installRedwoodModule(module) {
35
35
  }
36
36
  } catch (error) {
37
37
  throw new Error(
38
- `Couldn't fetch packument for ${module}: ${error.message}`
38
+ `Couldn't fetch packument for ${module}: ${error instanceof Error ? error.message : String(error)}`
39
39
  );
40
40
  }
41
- const versionIsPublished = Object.keys(packument.versions).includes(version);
41
+ const versionIsPublished = Object.keys(packument.versions ?? {}).includes(
42
+ version
43
+ );
42
44
  if (!versionIsPublished) {
43
45
  version = "canary";
44
46
  }
@@ -66,9 +68,9 @@ function isModuleInstalled(module) {
66
68
  return true;
67
69
  }
68
70
  const createdRequire = createRequire(import.meta.url);
69
- return createdRequire.resolve.paths(`${module}/package.json`).some((requireResolvePath) => {
71
+ return createdRequire.resolve.paths(`${module}/package.json`)?.some((requireResolvePath) => {
70
72
  return fs.existsSync(path.join(requireResolvePath, module));
71
- });
73
+ }) ?? false;
72
74
  }
73
75
  export {
74
76
  installModule,
@@ -33,7 +33,7 @@ To continue, the generator requires a unique plural form:`;
33
33
  const destroyMessage = `Cannot determine the plural of "${model}" originally used to generate the files.
34
34
  To continue, the destroy command requires the plural form:`;
35
35
  const promptMessage = isDestroyer ? destroyMessage : generateMessage;
36
- const initialPlural = model.slice(-1) === "s" ? `${model}es` : `${model}s`;
36
+ const initialPlural = model.endsWith("s") ? `${model}es` : `${model}s`;
37
37
  const promptResult = await prompts({
38
38
  type: "text",
39
39
  name: "plural",
@@ -5,7 +5,9 @@ const isTypeScriptProject = () => {
5
5
  const paths = getPaths();
6
6
  return fs.existsSync(path.join(paths.web.base, "tsconfig.json")) || fs.existsSync(path.join(paths.api.base, "tsconfig.json"));
7
7
  };
8
- function workspaces({ includePackages = false } = {}) {
8
+ function workspaces({
9
+ includePackages = false
10
+ } = {}) {
9
11
  const cedarPaths = getPaths();
10
12
  let workspaces2 = [];
11
13
  if (fs.existsSync(path.join(cedarPaths.web.base, "package.json"))) {
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "path";
3
- let rollback = [];
3
+ const rollback = [];
4
4
  function addFunctionToRollback(func, atEnd = false) {
5
5
  const step = { type: "func", func };
6
6
  if (atEnd) {
@@ -9,11 +9,11 @@ function addFunctionToRollback(func, atEnd = false) {
9
9
  rollback.push(step);
10
10
  }
11
11
  }
12
- function addFileToRollback(path2, atEnd = false) {
12
+ function addFileToRollback(filePath, atEnd = false) {
13
13
  const step = {
14
14
  type: "file",
15
- path: path2,
16
- content: fs.existsSync(path2) ? fs.readFileSync(path2) : null
15
+ path: filePath,
16
+ content: fs.existsSync(filePath) ? fs.readFileSync(filePath) : null
17
17
  };
18
18
  if (atEnd) {
19
19
  rollback.unshift(step);
@@ -51,7 +51,7 @@ async function executeRollback(_ = null, task = null) {
51
51
  }
52
52
  }
53
53
  if (task) {
54
- task.title = `Reverted because: ${task.task.message.error}`;
54
+ task.title = `Reverted because: ${task.task.message?.error ?? "unknown error"}`;
55
55
  }
56
56
  }
57
57
  function resetRollback() {
@@ -32,12 +32,19 @@ class CustomFileExporter {
32
32
  * @param spans the list of sampled Spans to be exported.
33
33
  */
34
34
  export(spans, resultCallback) {
35
- for (let i = 0; i < spans.length; i++) {
36
- const span = spans[i];
37
- delete span["_spanProcessor"];
35
+ for (const span of spans) {
38
36
  fs.appendFileSync(
39
37
  this.#storageFilePath,
40
- JSON.stringify(span, void 0, 2)
38
+ JSON.stringify(
39
+ span,
40
+ (key, value) => {
41
+ if (key === "_spanProcessor") {
42
+ return void 0;
43
+ }
44
+ return value;
45
+ },
46
+ 2
47
+ )
41
48
  );
42
49
  fs.appendFileSync(this.#storageFilePath, ",");
43
50
  }
@@ -8,9 +8,11 @@ import { v4 as uuidv4, validate as validateUUID } from "uuid";
8
8
  import { getPaths, getRawConfig } from "@cedarjs/project-config";
9
9
  import { RWProject } from "@cedarjs/structure/dist/model/RWProject";
10
10
  import {
11
- name as packageName,
12
- version as packageVersion
11
+ name as _packageName,
12
+ version as _packageVersion
13
13
  } from "../../package.js";
14
+ const packageName = _packageName;
15
+ const packageVersion = _packageVersion;
14
16
  async function getResources() {
15
17
  let UID = uuidv4();
16
18
  try {
@@ -29,7 +31,7 @@ async function getResources() {
29
31
  fs.writeFileSync(telemetryFile, UID);
30
32
  }
31
33
  }
32
- } catch (_error) {
34
+ } catch {
33
35
  }
34
36
  const info = JSON.parse(
35
37
  await envinfo.run(
@@ -57,7 +59,9 @@ async function getResources() {
57
59
  const experiments = Object.keys(getRawConfig()["experimental"] || {});
58
60
  const project = new RWProject();
59
61
  const routes = project.getRouter().routes;
60
- const prerenderedRoutes = routes.filter((route) => route.hasPrerender);
62
+ const prerenderedRoutes = routes.filter(
63
+ (route) => route.hasPrerender
64
+ );
61
65
  const complexity = [
62
66
  routes.length,
63
67
  prerenderedRoutes.length,
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "path";
3
+ import { ExportResultCode } from "@opentelemetry/core";
3
4
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
4
5
  import { Resource } from "@opentelemetry/resources";
5
6
  import { getPaths } from "@cedarjs/project-config";
@@ -53,14 +54,17 @@ async function main() {
53
54
  span.spanContext = () => span._spanContext;
54
55
  span.events = [];
55
56
  }
56
- traceExporter.export(spans, ({ code, error }) => {
57
- if (code !== 0) {
58
- console.error("Encountered:");
59
- console.error(error);
60
- console.error("while exporting the following spans:");
61
- console.error(spans);
57
+ traceExporter.export(
58
+ spans,
59
+ ({ code, error }) => {
60
+ if (code !== ExportResultCode.SUCCESS) {
61
+ console.error("Encountered:");
62
+ console.error(error);
63
+ console.error("while exporting the following spans:");
64
+ console.error(spans);
65
+ }
62
66
  }
63
- });
67
+ );
64
68
  fs.writeFileSync(
65
69
  path.join(telemetryDir, `_${file}`),
66
70
  JSON.stringify(spans, null, 2)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli",
3
- "version": "5.0.0-canary.2379",
3
+ "version": "5.0.0-canary.2383",
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.2379",
37
- "@cedarjs/cli-helpers": "5.0.0-canary.2379",
38
- "@cedarjs/fastify-web": "5.0.0-canary.2379",
39
- "@cedarjs/internal": "5.0.0-canary.2379",
40
- "@cedarjs/prerender": "5.0.0-canary.2379",
41
- "@cedarjs/project-config": "5.0.0-canary.2379",
42
- "@cedarjs/structure": "5.0.0-canary.2379",
43
- "@cedarjs/telemetry": "5.0.0-canary.2379",
44
- "@cedarjs/utils": "5.0.0-canary.2379",
45
- "@cedarjs/vite": "5.0.0-canary.2379",
46
- "@cedarjs/web-server": "5.0.0-canary.2379",
36
+ "@cedarjs/api-server": "5.0.0-canary.2383",
37
+ "@cedarjs/cli-helpers": "5.0.0-canary.2383",
38
+ "@cedarjs/fastify-web": "5.0.0-canary.2383",
39
+ "@cedarjs/internal": "5.0.0-canary.2383",
40
+ "@cedarjs/prerender": "5.0.0-canary.2383",
41
+ "@cedarjs/project-config": "5.0.0-canary.2383",
42
+ "@cedarjs/structure": "5.0.0-canary.2383",
43
+ "@cedarjs/telemetry": "5.0.0-canary.2383",
44
+ "@cedarjs/utils": "5.0.0-canary.2383",
45
+ "@cedarjs/vite": "5.0.0-canary.2383",
46
+ "@cedarjs/web-server": "5.0.0-canary.2383",
47
47
  "@listr2/prompt-adapter-enquirer": "4.2.1",
48
48
  "@opentelemetry/api": "1.9.0",
49
49
  "@opentelemetry/core": "1.30.1",