@cedarjs/cli 5.0.6-rc.4 → 5.0.7-next.186

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/README.md CHANGED
@@ -238,12 +238,9 @@ export const builder = (yargs) => {
238
238
 
239
239
  ...
240
240
 
241
- .option('stats', {
242
- default: false,
243
- description: `Use ${terminalLink(
244
- 'Webpack Bundle Analyzer',
245
- 'https://github.com/webpack-contrib/webpack-bundle-analyzer'
246
- )}`,
241
+ .option('prerender', {
242
+ default: true,
243
+ description: 'Prerender after building web',
247
244
  type: 'boolean',
248
245
  })
249
246
  .option('verbose', {
@@ -258,11 +255,11 @@ export const builder = (yargs) => {
258
255
  }
259
256
  ```
260
257
 
261
- These two calls to `options` configure this command to have options `--stats` and `--verbose`:
258
+ These two calls to `options` configure this command to have options `--prerender` and `--verbose`:
262
259
 
263
260
  ```terminal
264
- yarn rw build --stats
265
- yarn rw build --verbose
261
+ yarn cedar build --no-prerender
262
+ yarn cedar build --verbose
266
263
  ```
267
264
 
268
265
  For the full list of what properties you can use to compose the options object, see [options(key, [opt])](https://yargs.js.org/docs/#api-optionskey-opt).
@@ -280,8 +277,8 @@ While `build`'s `handler` is too long to reproduce here in full, to get the poin
280
277
 
281
278
  export const handler = async ({
282
279
  side = ['api', 'web'],
280
+ prerender = true,
283
281
  verbose = false,
284
- stats = false,
285
282
  }) => {
286
283
 
287
284
  ...
package/dist/cfw.js CHANGED
@@ -40,6 +40,8 @@ try {
40
40
  // CEDAR_DISABLE_TELEMETRY
41
41
  env: { CEDAR_CWD: projectPath }
42
42
  });
43
- } catch {
43
+ } catch (e) {
44
44
  console.log();
45
+ const exitCode = e && typeof e === "object" && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
46
+ process.exit(exitCode);
45
47
  }
@@ -181,10 +181,14 @@ Run ` + c.info(formatCedarCommand(["build"])) + " (without specifying a workspac
181
181
  "@cedarjs/vite/bins/cedar-vite-build.mjs"
182
182
  );
183
183
  await execa(
184
- `node ${buildBinPath} --webDir="${cedarPaths.web.base}" --verbose=${verbose}`,
184
+ "node",
185
+ [
186
+ buildBinPath,
187
+ `--webDir=${cedarPaths.web.base}`,
188
+ `--verbose=${verbose}`
189
+ ],
185
190
  {
186
191
  stdio: verbose ? "inherit" : "pipe",
187
- shell: true,
188
192
  cwd: cedarPaths.web.base
189
193
  }
190
194
  );
@@ -223,12 +227,16 @@ Run ` + c.info(formatCedarCommand(["build"])) + " (without specifying a workspac
223
227
  "@cedarjs/vite/bins/cedar-vite-build.mjs"
224
228
  );
225
229
  await execa(
226
- `node ${buildBinPath} --webDir="${cedarPaths.web.base}" --verbose=${verbose}`,
230
+ "node",
231
+ [
232
+ buildBinPath,
233
+ `--webDir=${cedarPaths.web.base}`,
234
+ `--verbose=${verbose}`
235
+ ],
227
236
  {
228
237
  stdio: verbose ? "inherit" : "pipe",
229
- shell: true,
230
- // `cwd` is needed for the package manager (e.g. yarn) to find the
231
- // cedar-vite-build binary
238
+ // `cwd` makes postcss/tailwind config resolution work (see the
239
+ // @NOTE above)
232
240
  // It won't change process.cwd for anything else here, in this
233
241
  // process
234
242
  cwd: cedarPaths.web.base
@@ -1,9 +1,11 @@
1
1
  const command = "console";
2
2
  const aliases = ["c"];
3
- const description = "Launch an interactive Redwood shell (experimental)";
3
+ const description = "Launch an interactive Cedar shell";
4
4
  const handler = async () => {
5
- const { handler: handler2 } = await import("./consoleHandler.js");
6
- return handler2();
5
+ console.log(
6
+ "`cedar console` has been removed from the Cedar CLI.\nRun it as a standalone tool instead:\n\n yarn dlx @cedarjs/console\n npx @cedarjs/console\n pnpm dlx @cedarjs/console\n"
7
+ );
8
+ process.exit(1);
7
9
  };
8
10
  export {
9
11
  aliases,
@@ -1,4 +1,5 @@
1
1
  import fs from "node:fs";
2
+ import { createRequire } from "node:module";
2
3
  import path from "node:path";
3
4
  import { Writable } from "node:stream";
4
5
  import concurrently from "concurrently";
@@ -7,6 +8,7 @@ import { formatRunBinCommand } from "@cedarjs/cli-helpers/packageManager/display
7
8
  import { shutdownPort } from "@cedarjs/internal/dist/dev";
8
9
  import { generateGqlormArtifacts } from "@cedarjs/internal/dist/generate/gqlormSchema";
9
10
  import { getConfig, getConfigPath } from "@cedarjs/project-config";
11
+ import { getPackageManager } from "@cedarjs/project-config/packageManager";
10
12
  import { errorTelemetry } from "@cedarjs/telemetry";
11
13
  import { exitWithError } from "../../lib/exit.js";
12
14
  import { generatePrismaClient } from "../../lib/generatePrismaClient.js";
@@ -15,13 +17,38 @@ import { getFreePort } from "../../lib/ports.js";
15
17
  import { serverFileExists } from "../../lib/project.js";
16
18
  import { getApiDebugFlag } from "./apiDebugFlag.js";
17
19
  import { getPackageWatchCommands } from "./packageWatchCommands.js";
20
+ const createdRequire = createRequire(import.meta.url);
21
+ function formatViteDevBinCommand(binName, extraNodeArgs = "") {
22
+ let vitePackageJsonPath;
23
+ let vitePackageJson;
24
+ try {
25
+ vitePackageJsonPath = createdRequire.resolve("@cedarjs/vite/package.json");
26
+ vitePackageJson = createdRequire("@cedarjs/vite/package.json");
27
+ } catch (e) {
28
+ const message = e instanceof Error ? e.message : String(e);
29
+ throw new Error(
30
+ `Could not resolve @cedarjs/vite, which the dev server needs to run. Is it installed? (${message})`
31
+ );
32
+ }
33
+ const binRelativePath = vitePackageJson.bin?.[binName];
34
+ if (!binRelativePath) {
35
+ throw new Error(
36
+ `@cedarjs/vite does not declare a "${binName}" bin. This is a bug in CedarJS.`
37
+ );
38
+ }
39
+ const binPath = path.join(path.dirname(vitePackageJsonPath), binRelativePath);
40
+ const nodeLauncher = getPackageManager() === "yarn" ? "yarn node" : "node";
41
+ const flags = extraNodeArgs ? `${extraNodeArgs} ` : "";
42
+ return `${nodeLauncher} ${flags}"${binPath}"`;
43
+ }
18
44
  const handler = async ({
19
45
  workspace = ["api", "web", "packages/*"],
20
46
  forward = "",
21
47
  generate = true,
22
48
  apiDebugPort,
23
49
  debugBrk,
24
- ud = false
50
+ ud = false,
51
+ nodeArgs = ""
25
52
  }) => {
26
53
  recordTelemetryAttributes({
27
54
  command: "dev",
@@ -174,7 +201,7 @@ const handler = async ({
174
201
  return null;
175
202
  }
176
203
  return [
177
- `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-unified-dev"])}`,
204
+ formatViteDevBinCommand("cedar-unified-dev", nodeArgs),
178
205
  ` --port ${webAvailablePort}`,
179
206
  ` --apiPort ${apiAvailablePort}`,
180
207
  getApiDebugFlag(apiDebugPort, apiAvailablePort),
@@ -230,13 +257,16 @@ const handler = async ({
230
257
  });
231
258
  }
232
259
  if (workspace.includes("web")) {
233
- let webCommand = `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-vite-dev"])} ${forward}`;
260
+ let webCommand = `${formatViteDevBinCommand("cedar-vite-dev", nodeArgs)} ${forward}`;
234
261
  if (streamingSsrEnabled) {
235
- webCommand = `${formatRunBinCommand("cross-env", ["NODE_ENV=development", "cedar-dev-fe"])} ${forward}`;
262
+ webCommand = `${formatViteDevBinCommand("cedar-dev-fe", nodeArgs)} ${forward}`;
236
263
  }
237
264
  jobs.push({
238
265
  name: "web",
239
266
  command: webCommand,
267
+ env: {
268
+ NODE_ENV: "development"
269
+ },
240
270
  prefixColor: "blue",
241
271
  cwd: cedarPaths.web.base,
242
272
  runWhen: () => fs.existsSync(cedarPaths.web.src)
@@ -31,6 +31,9 @@ const builder = (yargs) => {
31
31
  type: "boolean",
32
32
  default: false,
33
33
  description: "Use the unified Vite dev server that handles both web and API in a single process (experimental)."
34
+ }).option("nodeArgs", {
35
+ type: "string",
36
+ description: 'CLI args to pass to the node process running the web dev server, for example: `--node-args="--inspect --max-old-space-size=8192"`.'
34
37
  }).middleware(() => {
35
38
  const check = checkNodeVersion();
36
39
  if (check.ok) {
@@ -97,13 +97,11 @@ const handler = async ({
97
97
  {
98
98
  title: "Cleaning up...",
99
99
  task: () => {
100
- runBinSync("eslint", [
101
- "--fix",
102
- "--config",
103
- `${getPaths().base}/node_modules/@cedarjs/eslint-config/shared.js`,
104
- `${getPaths().api.jobsConfig}`,
105
- ...Object.keys(jobFiles)
106
- ]);
100
+ runBinSync(
101
+ "eslint",
102
+ ["--fix", `${getPaths().api.jobsConfig}`, ...Object.keys(jobFiles)],
103
+ { cwd: getPaths().base }
104
+ );
107
105
  }
108
106
  }
109
107
  ],
@@ -407,12 +407,9 @@ const handler = async ({
407
407
  {
408
408
  title: "Cleaning up...",
409
409
  task: () => {
410
- runBinSync("eslint", [
411
- "--fix",
412
- "--config",
413
- `${getPaths().base}/node_modules/@cedarjs/eslint-config/index.js`,
414
- ...Object.keys(packageFiles)
415
- ]);
410
+ runBinSync("eslint", ["--fix", ...Object.keys(packageFiles)], {
411
+ cwd: getPaths().base
412
+ });
416
413
  }
417
414
  }
418
415
  ],
@@ -46,15 +46,8 @@ const addFieldGraphQLComment = (field, str) => {
46
46
  const modelFieldToSDL = ({
47
47
  field,
48
48
  required = true,
49
- types = {},
50
49
  docs = false
51
50
  }) => {
52
- if (Object.entries(types).length && field.kind === "object") {
53
- const resolvedType = idType(types[field.type]);
54
- if (typeof resolvedType === "string") {
55
- field.type = resolvedType;
56
- }
57
- }
58
51
  const prismaTypeToGraphqlType = {
59
52
  Json: "JSON",
60
53
  Decimal: "Float",
@@ -73,7 +66,7 @@ const modelFieldToSDL = ({
73
66
  const querySDL = (model, docs = false) => {
74
67
  return model.fields.map((field) => modelFieldToSDL({ field, docs }));
75
68
  };
76
- const inputSDL = (model, required, types = {}, docs = false) => {
69
+ const inputSDL = (model, required, docs = false) => {
77
70
  const ignoredFields = DEFAULT_IGNORE_FIELDS_FOR_INPUT;
78
71
  return model.fields.filter((field) => {
79
72
  const idField = model.fields.find((field2) => field2.isId);
@@ -81,21 +74,19 @@ const inputSDL = (model, required, types = {}, docs = false) => {
81
74
  ignoredFields.push(idField.name);
82
75
  }
83
76
  return !ignoredFields.includes(field.name) && field.kind !== "object";
84
- }).map((field) => modelFieldToSDL({ field, required, types, docs }));
77
+ }).map((field) => modelFieldToSDL({ field, required, docs }));
85
78
  };
86
79
  function idInputSDL(idType2, docs) {
87
80
  if (!Array.isArray(idType2)) {
88
81
  return [];
89
82
  }
90
- return idType2.map(
91
- (field) => modelFieldToSDL({ field, required: true, types: {}, docs })
92
- );
83
+ return idType2.map((field) => modelFieldToSDL({ field, required: true, docs }));
93
84
  }
94
- const createInputSDL = (model, types = {}, docs = false) => {
95
- return inputSDL(model, true, types, docs);
85
+ const createInputSDL = (model, docs = false) => {
86
+ return inputSDL(model, true, docs);
96
87
  };
97
- const updateInputSDL = (model, types = {}, docs = false) => {
98
- return inputSDL(model, false, types, docs);
88
+ const updateInputSDL = (model, docs = false) => {
89
+ return inputSDL(model, false, docs);
99
90
  };
100
91
  function idType(model, crud) {
101
92
  if (!crud || !model) {
@@ -131,21 +122,6 @@ const sdlFromSchemaModel = async (name, crud, docs = false) => {
131
122
  );
132
123
  }
133
124
  const model = schemaResult;
134
- const resolvedTypes = await Promise.all(
135
- model.fields.filter((field) => field.kind === "object").map(async (field) => {
136
- const fieldModel = await getSchema(field.type);
137
- return fieldModel && "fields" in fieldModel ? fieldModel : void 0;
138
- })
139
- );
140
- const types = resolvedTypes.reduce(
141
- (acc, cur) => {
142
- if (!cur) {
143
- return acc;
144
- }
145
- return { ...acc, [cur.name]: cur };
146
- },
147
- {}
148
- );
149
125
  const enums = (await Promise.all(
150
126
  model.fields.filter((field) => field.kind === "enum").map(async (field) => {
151
127
  const enumDef = await getEnum(field.type);
@@ -159,8 +135,8 @@ const sdlFromSchemaModel = async (name, crud, docs = false) => {
159
135
  modelName,
160
136
  modelDescription,
161
137
  query: querySDL(model, docs).join("\n "),
162
- createInput: createInputSDL(model, types, docs).join("\n "),
163
- updateInput: updateInputSDL(model, types, docs).join("\n "),
138
+ createInput: createInputSDL(model, docs).join("\n "),
139
+ updateInput: updateInputSDL(model, docs).join("\n "),
164
140
  idInput: idInputSDL(idTypeRes, docs).join("\n "),
165
141
  idType: idType(model, crud),
166
142
  idName: idName(model, crud),
@@ -30,14 +30,8 @@ const customOrDefaultTemplatePath = ({
30
30
  generator,
31
31
  templatePath
32
32
  );
33
- const deprecatedCustomPath = getPaths()[side].generators ? path.join(getPaths()[side].generators, generator, templatePath) : void 0;
34
33
  if (fs.existsSync(customPath)) {
35
34
  return customPath;
36
- } else if (deprecatedCustomPath && fs.existsSync(deprecatedCustomPath)) {
37
- console.log(
38
- `Having generator templates in ${getPaths()[side].generators} has been deprecated. Please move them to ${getPaths().generatorTemplates}.`
39
- );
40
- return deprecatedCustomPath;
41
35
  } else {
42
36
  return defaultPath;
43
37
  }
@@ -1,63 +1,8 @@
1
1
  import fs from "node:fs";
2
- import path from "node:path";
3
2
  import { terminalLink } from "termi-link";
4
3
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
5
4
  import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
6
- import { getPaths, getConfig } from "@cedarjs/project-config";
7
- function detectLegacyEslintConfig() {
8
- const projectRoot = getPaths().base;
9
- const legacyConfigFiles = [
10
- ".eslintrc.js",
11
- ".eslintrc.cjs",
12
- ".eslintrc.json",
13
- ".eslintrc.yaml",
14
- ".eslintrc.yml"
15
- ];
16
- const foundLegacyFiles = [];
17
- for (const configFile of legacyConfigFiles) {
18
- if (fs.existsSync(path.join(projectRoot, configFile))) {
19
- foundLegacyFiles.push(configFile);
20
- }
21
- }
22
- const packageJsonPath = path.join(projectRoot, "package.json");
23
- if (fs.existsSync(packageJsonPath)) {
24
- try {
25
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
26
- if (packageJson.eslintConfig) {
27
- foundLegacyFiles.push("package.json (eslintConfig field)");
28
- }
29
- if (packageJson.eslint) {
30
- foundLegacyFiles.push("package.json (eslint field)");
31
- }
32
- } catch {
33
- }
34
- }
35
- return foundLegacyFiles;
36
- }
37
- function showLegacyEslintDeprecationWarning(legacyFiles) {
38
- console.warn("");
39
- console.warn("\u26A0\uFE0F DEPRECATION WARNING: Legacy ESLint Configuration Detected");
40
- console.warn("");
41
- console.warn(" The following legacy ESLint configuration files were found:");
42
- legacyFiles.forEach((file) => {
43
- console.warn(` - ${file}`);
44
- });
45
- console.warn("");
46
- console.warn(
47
- " Cedar has migrated to ESLint flat config format. Legacy configurations"
48
- );
49
- console.warn(
50
- " still work but are deprecated and will be removed in a future version."
51
- );
52
- console.warn("");
53
- console.warn(" To migrate to the new format:");
54
- console.warn(" 1. Remove the legacy config file(s) listed above");
55
- console.warn(" 2. Create an eslint.config.mjs");
56
- console.warn(" 3. Use the flat config format with @cedarjs/eslint-config");
57
- console.warn("");
58
- console.warn(" See more here: https://github.com/cedarjs/cedar/pull/629");
59
- console.warn("");
60
- }
5
+ import { getPaths } from "@cedarjs/project-config";
61
6
  const command = "lint [paths..]";
62
7
  const description = "Lint your files";
63
8
  const builder = (yargs) => {
@@ -86,11 +31,6 @@ const handler = async ({
86
31
  format = "stylish"
87
32
  }) => {
88
33
  recordTelemetryAttributes({ command: "lint", fix, format });
89
- const config = getConfig();
90
- const legacyConfigFiles = detectLegacyEslintConfig();
91
- if (legacyConfigFiles.length > 0 && config instanceof Object && "eslintLegacyConfigWarning" in config && config.eslintLegacyConfigWarning) {
92
- showLegacyEslintDeprecationWarning(legacyConfigFiles);
93
- }
94
34
  try {
95
35
  const sbPath = getPaths().web.storybook;
96
36
  const eslintArgs = [
@@ -49,18 +49,15 @@ const handler = async ({
49
49
  for (const [name, value] of Object.entries(options)) {
50
50
  args.push(name.length > 1 ? `--${name}` : `-${name}`);
51
51
  if (typeof value === "string") {
52
- if (value.split(" ").length > 1) {
53
- args.push(`"${value}"`);
54
- } else {
55
- args.push(value);
56
- }
52
+ args.push(value);
57
53
  } else if (typeof value === "number") {
58
54
  args.push(String(value));
59
55
  }
60
56
  }
57
+ const displayCommand = args.map((arg) => arg.includes(" ") ? `"${arg}"` : arg).join(" ");
61
58
  console.log();
62
59
  console.log(c.note("Running Prisma CLI..."));
63
- console.log(c.underline(`$ <pm exec> prisma ${args.join(" ")}`));
60
+ console.log(c.underline(`$ <pm exec> prisma ${displayCommand}`));
64
61
  console.log();
65
62
  try {
66
63
  runTransitiveBinSync("prisma", args, {
@@ -6,7 +6,6 @@ import { terminalLink } from "termi-link";
6
6
  import * as apiServerCLIConfig from "@cedarjs/api-server/apiCliConfig";
7
7
  import * as bothServerCLIConfig from "@cedarjs/api-server/bothCliConfig";
8
8
  import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
9
- import { projectIsEsm } from "@cedarjs/project-config";
10
9
  import * as webServerCLIConfig from "@cedarjs/web-server";
11
10
  import { getPaths, getConfig } from "../lib/index.js";
12
11
  import { serverFileExists } from "../lib/project.js";
@@ -162,12 +161,7 @@ const builder = async (yargs) => {
162
161
  const serveBothHandlers = await import("./serveBothHandler.js");
163
162
  await serveBothHandlers.bothSsrRscServerHandler(argv, rscEnabled);
164
163
  } else {
165
- if (!projectIsEsm()) {
166
- const { handler } = await import("@cedarjs/api-server/cjs/bothCliConfigHandler");
167
- await handler(argv);
168
- } else {
169
- await bothServerCLIConfig.handler(argv);
170
- }
164
+ await bothServerCLIConfig.handler(argv);
171
165
  }
172
166
  }
173
167
  }).command({
@@ -219,12 +213,7 @@ const builder = async (yargs) => {
219
213
  const { apiServerFileHandler } = await import("./serveApiHandler.js");
220
214
  await apiServerFileHandler(argv);
221
215
  } else {
222
- if (!projectIsEsm()) {
223
- const { handler } = await import("@cedarjs/api-server/cjs/apiCliConfigHandler");
224
- await handler(argv);
225
- } else {
226
- await apiServerCLIConfig.handler(argv);
227
- }
216
+ await apiServerCLIConfig.handler(argv);
228
217
  }
229
218
  }
230
219
  }).command({
@@ -1,13 +1,13 @@
1
1
  import path from "path";
2
2
  import concurrently from "concurrently";
3
- import { handler as apiServerHandler } from "@cedarjs/api-server/cjs/apiCliConfigHandler";
3
+ import { handler as apiServerHandler } from "@cedarjs/api-server/apiCliConfigHandler";
4
4
  import {
5
5
  getAPIHost,
6
6
  getAPIPort,
7
7
  getAPIRootPath,
8
8
  getWebHost,
9
9
  getWebPort
10
- } from "@cedarjs/api-server/cjs/cliHelpers";
10
+ } from "@cedarjs/api-server/cliHelpers";
11
11
  import { formatRunBinCommand } from "@cedarjs/cli-helpers/packageManager/display";
12
12
  import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
13
13
  import { getConfig, getPaths } from "@cedarjs/project-config";
@@ -237,7 +237,7 @@ async function getAuthSetupHandler(module) {
237
237
  });
238
238
  }
239
239
  const setupModule = await import(module);
240
- return setupModule.default.handler;
240
+ return setupModule.handler;
241
241
  }
242
242
  function isInstalled(module) {
243
243
  const { dependencies, devDependencies } = JSON.parse(
@@ -4,7 +4,6 @@ import * as parser from "@babel/parser";
4
4
  import * as t from "@babel/types";
5
5
  import execa from "execa";
6
6
  import { Listr } from "listr2";
7
- import * as recast from "recast";
8
7
  import { getConfigPath, getConfig } from "@cedarjs/project-config";
9
8
  import { getPaths, writeFilesTask } from "../../../../lib/index.js";
10
9
  const updateApiURLTask = (apiUrl) => {
@@ -88,14 +87,6 @@ const verifyUDSetupTask = () => {
88
87
  }
89
88
  };
90
89
  };
91
- function posToIndex(str, line, column) {
92
- const lines = str.split("\n");
93
- let index = 0;
94
- for (let i = 0; i < line - 1; i++) {
95
- index += lines[i].length + 1;
96
- }
97
- return index + column;
98
- }
99
90
  function resolveConfigObject(arg) {
100
91
  if (t.isObjectExpression(arg)) {
101
92
  return arg;
@@ -127,15 +118,9 @@ function insertPluginsBeforeCedar({
127
118
  content,
128
119
  pluginCodes
129
120
  }) {
130
- const ast = recast.parse(content, {
131
- parser: {
132
- parse(source) {
133
- return parser.parse(source, {
134
- sourceType: "module",
135
- plugins: ["typescript", "jsx"]
136
- });
137
- }
138
- }
121
+ const ast = parser.parse(content, {
122
+ sourceType: "module",
123
+ plugins: ["typescript", "jsx"]
139
124
  });
140
125
  const defaultExport = ast.program.body.find(t.isExportDefaultDeclaration);
141
126
  if (!defaultExport) {
@@ -163,33 +148,18 @@ function insertPluginsBeforeCedar({
163
148
  return null;
164
149
  }
165
150
  const cedarNode = cedarElement;
166
- if (!cedarNode.loc || !arrayExpr.loc || !pluginsProp.loc) {
151
+ if (!cedarNode.loc || !arrayExpr.loc || !pluginsProp.loc || cedarNode.start == null || arrayExpr.start == null || arrayExpr.end == null) {
167
152
  return null;
168
153
  }
169
154
  const isInline = cedarNode.loc.start.line === arrayExpr.loc.start.line;
170
155
  if (isInline) {
171
- const startPos = posToIndex(
172
- content,
173
- arrayExpr.loc.start.line,
174
- arrayExpr.loc.start.column
175
- );
176
- const endPos = posToIndex(
177
- content,
178
- arrayExpr.loc.end.line,
179
- arrayExpr.loc.end.column
180
- );
181
- const precedingText = content.slice(0, startPos);
182
- const followingText = content.slice(endPos);
156
+ const precedingText = content.slice(0, arrayExpr.start);
157
+ const followingText = content.slice(arrayExpr.end);
183
158
  const existingCodes = elements.flatMap((el) => {
184
- if (!el?.loc) {
159
+ if (el?.start == null || el.end == null) {
185
160
  return [];
186
161
  }
187
- return [
188
- content.slice(
189
- posToIndex(content, el.loc.start.line, el.loc.start.column),
190
- posToIndex(content, el.loc.end.line, el.loc.end.column)
191
- )
192
- ];
162
+ return [content.slice(el.start, el.end)];
193
163
  });
194
164
  const lines2 = content.split("\n");
195
165
  const pluginsLine = pluginsProp.loc.start.line;
@@ -205,7 +175,7 @@ function insertPluginsBeforeCedar({
205
175
  return precedingText + multiline + followingText;
206
176
  }
207
177
  const cedarLine = cedarNode.loc.start.line;
208
- const insertPos = posToIndex(content, cedarLine, 0);
178
+ const insertPos = cedarNode.start - cedarNode.loc.start.column;
209
179
  const lines = content.split("\n");
210
180
  const indent = (lines[cedarLine - 1].match(/^\s*/) ?? [""])[0];
211
181
  const insertion = pluginCodes.map((code) => `${indent}${code},
@@ -16,6 +16,10 @@ import {
16
16
  mysqlDatabaseService
17
17
  } from "../templates/flightcontrol.js";
18
18
  const { getConfig } = prismaInternals;
19
+ const APOLLO_PROVIDER_COMPONENT_NAMES = [
20
+ "CedarApolloProvider",
21
+ "RedwoodApolloProvider"
22
+ ];
19
23
  const getFlightcontrolJson = async (database) => {
20
24
  const flightcontrolConfig = getFlightcontrolConfig();
21
25
  if (database === "none") {
@@ -205,18 +209,26 @@ const updateApp = () => {
205
209
  appContent[authLineIndex] = ` <AuthProvider type="dbAuth" config={{ fetchConfig: { credentials: 'include' } }}>
206
210
  `;
207
211
  }
208
- const gqlLineIndex = appContent.findIndex(
209
- (line) => line.includes("<RedwoodApolloProvider")
210
- );
212
+ let gqlLineIndex = -1;
213
+ let apolloProviderComponentName = "";
214
+ for (const componentName of APOLLO_PROVIDER_COMPONENT_NAMES) {
215
+ gqlLineIndex = appContent.findIndex(
216
+ (line) => line.includes(`<${componentName}`)
217
+ );
218
+ if (gqlLineIndex !== -1) {
219
+ apolloProviderComponentName = componentName;
220
+ break;
221
+ }
222
+ }
211
223
  if (gqlLineIndex === -1) {
212
224
  console.log(`
213
- Couldn't find <RedwoodApolloProvider in web/src/App.js
225
+ Couldn't find <CedarApolloProvider in web/src/App.js
214
226
  If (and when) you use *dbAuth*, you'll have to add the following fetch config manually:
215
227
 
216
228
  graphQLClientConfig={{ httpLinkConfig: { credentials: 'include' }}}
217
229
  `);
218
230
  } else if (appContent.toString().match(/dbAuth/)) {
219
- appContent[gqlLineIndex] = ` <RedwoodApolloProvider graphQLClientConfig={{ httpLinkConfig: { credentials: 'include' }}} >
231
+ appContent[gqlLineIndex] = ` <${apolloProviderComponentName} graphQLClientConfig={{ httpLinkConfig: { credentials: 'include' }}} >
220
232
  `;
221
233
  }
222
234
  fs.writeFileSync(appPath, appContent.join(EOL));
@@ -16,8 +16,11 @@ function isPropertyWithName(node, name) {
16
16
  function transform(file, api) {
17
17
  const j = api.jscodeshift;
18
18
  const root = j(file.source);
19
- const redwoodApolloProvider = root.findJSXElements("RedwoodApolloProvider");
20
- const graphQLClientConfigCollection = redwoodApolloProvider.find(
19
+ let apolloProviderElements = root.findJSXElements("CedarApolloProvider");
20
+ if (apolloProviderElements.length === 0) {
21
+ apolloProviderElements = root.findJSXElements("RedwoodApolloProvider");
22
+ }
23
+ const graphQLClientConfigCollection = apolloProviderElements.find(
21
24
  j.JSXAttribute,
22
25
  {
23
26
  name: { name: "graphQLClientConfig" }
@@ -104,7 +107,7 @@ function transform(file, api) {
104
107
  cacheConfigValue.properties.push(property);
105
108
  }
106
109
  graphQLClientConfigCollection.remove();
107
- redwoodApolloProvider.get(0).node.openingElement.attributes.push(
110
+ apolloProviderElements.get(0).node.openingElement.attributes.push(
108
111
  j.jsxAttribute(
109
112
  j.jsxIdentifier("graphQLClientConfig"),
110
113
  j.jsxExpressionContainer(j.identifier(graphQLClientConfigVariableName))
@@ -87,7 +87,6 @@ const handler = async ({
87
87
  const projectPackages = ["prettier-plugin-tailwindcss@^0.8.0"];
88
88
  const webWorkspacePackages = [
89
89
  "postcss",
90
- "postcss-loader",
91
90
  "tailwindcss@^3.4.17",
92
91
  "autoprefixer"
93
92
  ];
package/dist/lib/exec.js CHANGED
@@ -54,19 +54,16 @@ async function runScriptFunction({
54
54
  nodeRunnerEnv: {}
55
55
  },
56
56
  resolve: {
57
+ // `$api/` and `api/` imports are handled by
58
+ // cedarjsResolveCedarStyleImportsPlugin below, which also resolves
59
+ // Cedar's directory named modules (`$api/src/services/posts` ->
60
+ // posts/posts.ts) and leaves an actual `api` npm package alone. The web
61
+ // side equivalents have no plugin support, so they stay aliases
57
62
  alias: [
58
- {
59
- find: /^\$api\//,
60
- replacement: getPaths().api.base + "/"
61
- },
62
63
  {
63
64
  find: /^\$web\//,
64
65
  replacement: getPaths().web.base + "/"
65
66
  },
66
- {
67
- find: /^api\//,
68
- replacement: getPaths().api.base + "/"
69
- },
70
67
  {
71
68
  find: /^web\//,
72
69
  replacement: getPaths().web.base + "/"
@@ -24,15 +24,35 @@ function getPersistenceDirectory() {
24
24
  persistenceDirectory = path.join(getPaths().generated.base, "updateCheck");
25
25
  return persistenceDirectory;
26
26
  }
27
- async function check() {
27
+ function getLocalVersion() {
28
+ let version;
28
29
  try {
29
- console.time("Update Check");
30
30
  const packageJson = JSON.parse(
31
31
  fs.readFileSync(path.join(getPaths().base, "package.json"), "utf-8")
32
32
  );
33
- let localVersion = packageJson.devDependencies["@cedarjs/core"];
34
- while (!/\d/.test(localVersion.charAt(0))) {
35
- localVersion = localVersion.substring(1);
33
+ version = packageJson.devDependencies?.["@cedarjs/core"];
34
+ } catch {
35
+ return void 0;
36
+ }
37
+ if (typeof version === "string" && semver.valid(version)) {
38
+ return version;
39
+ }
40
+ return void 0;
41
+ }
42
+ async function check() {
43
+ try {
44
+ console.time("Update Check");
45
+ const localVersion = getLocalVersion();
46
+ if (!localVersion) {
47
+ console.log(
48
+ "Skipping update check: no pinned @cedarjs/core version found"
49
+ );
50
+ updateUpdateDataFile({
51
+ localVersion: "0.0.0",
52
+ remoteVersions: /* @__PURE__ */ new Map(),
53
+ checkedAt: (/* @__PURE__ */ new Date()).getTime()
54
+ });
55
+ return;
36
56
  }
37
57
  console.log(`Detected the current version of Cedar: '${localVersion}'`);
38
58
  const remoteVersions = /* @__PURE__ */ new Map();
@@ -69,16 +89,24 @@ function shouldCheck() {
69
89
  return false;
70
90
  }
71
91
  const data = readUpdateDataFile();
92
+ const localVersion = getLocalVersion();
93
+ if (localVersion && localVersion !== data.localVersion) {
94
+ return true;
95
+ }
72
96
  return data.checkedAt < (/* @__PURE__ */ new Date()).getTime() - CHECK_PERIOD;
73
97
  }
74
98
  function shouldShow() {
75
99
  if (isLockSet(SHOW_LOCK_IDENTIFIER)) {
76
100
  return false;
77
101
  }
102
+ const localVersion = getLocalVersion();
103
+ if (!localVersion) {
104
+ return false;
105
+ }
78
106
  const data = readUpdateDataFile();
79
107
  let newerVersion = false;
80
108
  data.remoteVersions.forEach((version) => {
81
- newerVersion ||= semver.gt(version, data.localVersion);
109
+ newerVersion ||= semver.gt(version, localVersion);
82
110
  });
83
111
  return data.shownAt < (/* @__PURE__ */ new Date()).getTime() - SHOW_PERIOD && newerVersion;
84
112
  }
@@ -89,8 +89,6 @@ async function getResources() {
89
89
  complexity,
90
90
  sides,
91
91
  experiments: JSON.stringify(experiments),
92
- webBundler: "vite",
93
- // Hardcoded because this is now the only supported bundler
94
92
  uid: UID
95
93
  };
96
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli",
3
- "version": "5.0.6-rc.4",
3
+ "version": "5.0.7-next.186",
4
4
  "description": "The CedarJS Command Line",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,18 +33,18 @@
33
33
  "dependencies": {
34
34
  "@babel/parser": "7.29.7",
35
35
  "@babel/preset-typescript": "7.29.7",
36
- "@cedarjs/api-server": "5.0.6-rc.4",
37
- "@cedarjs/cli-helpers": "5.0.6-rc.4",
38
- "@cedarjs/fastify-web": "5.0.6-rc.4",
39
- "@cedarjs/internal": "5.0.6-rc.4",
40
- "@cedarjs/prerender": "5.0.6-rc.4",
41
- "@cedarjs/project-config": "5.0.6-rc.4",
42
- "@cedarjs/structure": "5.0.6-rc.4",
43
- "@cedarjs/telemetry": "5.0.6-rc.4",
44
- "@cedarjs/utils": "5.0.6-rc.4",
45
- "@cedarjs/vite": "5.0.6-rc.4",
46
- "@cedarjs/web-server": "5.0.6-rc.4",
47
- "@listr2/prompt-adapter-enquirer": "4.2.1",
36
+ "@cedarjs/api-server": "5.0.7-next.186",
37
+ "@cedarjs/cli-helpers": "5.0.7-next.186",
38
+ "@cedarjs/fastify-web": "5.0.7-next.186",
39
+ "@cedarjs/internal": "5.0.7-next.186",
40
+ "@cedarjs/prerender": "5.0.7-next.186",
41
+ "@cedarjs/project-config": "5.0.7-next.186",
42
+ "@cedarjs/structure": "5.0.7-next.186",
43
+ "@cedarjs/telemetry": "5.0.7-next.186",
44
+ "@cedarjs/utils": "5.0.7-next.186",
45
+ "@cedarjs/vite": "5.0.7-next.186",
46
+ "@cedarjs/web-server": "5.0.7-next.186",
47
+ "@listr2/prompt-adapter-enquirer": "4.3.0",
48
48
  "@opentelemetry/api": "1.9.1",
49
49
  "@opentelemetry/core": "1.30.1",
50
50
  "@opentelemetry/exporter-trace-otlp-http": "0.57.2",
@@ -52,7 +52,7 @@
52
52
  "@opentelemetry/sdk-trace-node": "1.30.1",
53
53
  "@opentelemetry/semantic-conventions": "1.41.1",
54
54
  "@prisma/internals": "7.8.0",
55
- "ansis": "4.2.0",
55
+ "ansis": "4.3.1",
56
56
  "archiver": "7.0.1",
57
57
  "boxen": "5.1.2",
58
58
  "camel-case": "4.1.2",
@@ -69,7 +69,7 @@
69
69
  "execa": "5.1.1",
70
70
  "fast-glob": "3.3.3",
71
71
  "humanize-string": "2.1.0",
72
- "jscodeshift": "17.3.0",
72
+ "jscodeshift": "17.4.0",
73
73
  "jsonc-parser": "3.3.1",
74
74
  "latest-version": "9.0.0",
75
75
  "listr2": "10.2.2",
@@ -80,7 +80,6 @@
80
80
  "prettier": "3.8.4",
81
81
  "prisma": "7.8.0",
82
82
  "prompts": "2.4.2",
83
- "recast": "0.23.11",
84
83
  "rimraf": "6.1.3",
85
84
  "semver": "7.7.4",
86
85
  "smol-toml": "1.6.1",
@@ -102,7 +101,7 @@
102
101
  "node-ssh": "13.2.1",
103
102
  "ts-dedent": "2.3.0",
104
103
  "typescript": "5.9.3",
105
- "vitest": "3.2.6"
104
+ "vitest": "4.1.10"
106
105
  },
107
106
  "engines": {
108
107
  "node": ">=24"
@@ -1,75 +0,0 @@
1
- import fs from "node:fs";
2
- import { createRequire } from "node:module";
3
- import path from "node:path";
4
- import repl from "node:repl";
5
- import { registerApiSideBabelHook } from "@cedarjs/babel-config";
6
- import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
7
- import { getPaths } from "../lib/index.js";
8
- const paths = getPaths();
9
- function isREPLServerWithHistory(replServer) {
10
- return "history" in replServer && "lines" in replServer;
11
- }
12
- const loadPrismaClient = (replContext) => {
13
- const createdRequire = createRequire(import.meta.url);
14
- const { db } = createdRequire(path.join(paths.api.lib, "db"));
15
- db[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")] = "PrismaClient";
16
- replContext.db = db;
17
- };
18
- const consoleHistoryFile = path.join(paths.generated.base, "console_history");
19
- const persistConsoleHistory = (r) => {
20
- const lines = isREPLServerWithHistory(r) ? r.lines : [];
21
- fs.appendFileSync(
22
- consoleHistoryFile,
23
- lines.filter((line) => line.trim()).join("\n") + "\n",
24
- "utf8"
25
- );
26
- };
27
- const loadConsoleHistory = async (r) => {
28
- try {
29
- const history = await fs.promises.readFile(consoleHistoryFile, "utf8");
30
- if (isREPLServerWithHistory(r)) {
31
- history.split("\n").reverse().map((line) => r.history.push(line));
32
- }
33
- } catch {
34
- }
35
- };
36
- const handler = (_options) => {
37
- recordTelemetryAttributes({
38
- command: "console"
39
- });
40
- registerApiSideBabelHook({
41
- plugins: [
42
- [
43
- "babel-plugin-module-resolver",
44
- {
45
- alias: {
46
- src: paths.api.src
47
- }
48
- },
49
- "rwjs-console-module-resolver"
50
- ]
51
- ]
52
- });
53
- const r = repl.start();
54
- const defaultEval = r.eval;
55
- const asyncEval = (cmd, context, filename, callback) => {
56
- defaultEval.call(r, cmd, context, filename, async (err, result) => {
57
- if (err) {
58
- callback(err, null);
59
- } else {
60
- try {
61
- callback(null, await Promise.resolve(result));
62
- } catch (err2) {
63
- callback(err2 instanceof Error ? err2 : new Error(String(err2)), null);
64
- }
65
- }
66
- });
67
- };
68
- r.eval = asyncEval;
69
- loadConsoleHistory(r);
70
- r.addListener("close", () => persistConsoleHistory(r));
71
- loadPrismaClient(r.context);
72
- };
73
- export {
74
- handler
75
- };