@cedarjs/cli 5.0.6 → 5.0.7-next.219

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +7 -10
  2. package/dist/cfw.js +3 -1
  3. package/dist/commands/build/buildHandler.js +14 -6
  4. package/dist/commands/console.js +5 -3
  5. package/dist/commands/dev/devHandler.js +34 -4
  6. package/dist/commands/dev.js +3 -0
  7. package/dist/commands/experimental/setupOpentelemetryHandler.js +1 -1
  8. package/dist/commands/generate/job/jobHandler.js +5 -7
  9. package/dist/commands/generate/package/packageHandler.js +3 -6
  10. package/dist/commands/generate/scaffold/scaffoldHandler.js +73 -4
  11. package/dist/commands/generate/sdl/sdlHandler.js +9 -33
  12. package/dist/commands/generate/yargsHandlerHelpers.js +0 -6
  13. package/dist/commands/lint.js +1 -61
  14. package/dist/commands/prismaHandler.js +3 -6
  15. package/dist/commands/serve.js +21 -22
  16. package/dist/commands/serveBothHandler.js +4 -4
  17. package/dist/commands/setup/auth/auth.js +1 -1
  18. package/dist/commands/setup/database/database.js +15 -0
  19. package/dist/commands/setup/database/postgres.js +19 -0
  20. package/dist/commands/setup/database/postgresHandler.js +194 -0
  21. package/dist/commands/setup/deploy/helpers/index.js +9 -39
  22. package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +17 -5
  23. package/dist/commands/setup/deploy/providers/renderHandler.js +4 -20
  24. package/dist/commands/setup/deploy/templates/render.js +24 -14
  25. package/dist/commands/setup/docker/templates/Dockerfile.yarn +2 -5
  26. package/dist/commands/setup/docker/templates/docker-compose.dev.yml +1 -1
  27. package/dist/commands/setup/docker/templates/docker-compose.prod.yml +2 -5
  28. package/dist/commands/setup/graphql/features/fragments/appGqlConfigTransform.js +6 -3
  29. package/dist/commands/setup/neon/neonHandler.js +96 -254
  30. package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +0 -1
  31. package/dist/commands/setup.js +2 -1
  32. package/dist/lib/exec.js +5 -8
  33. package/dist/lib/index.js +22 -6
  34. package/dist/lib/updateCheck.js +34 -6
  35. package/dist/telemetry/resource.js +3 -8
  36. package/package.json +20 -21
  37. package/dist/commands/consoleHandler.js +0 -75
  38. /package/dist/commands/setup/{neon → database}/templates/db.ts.template +0 -0
@@ -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";
@@ -27,8 +27,8 @@ const bothServerFileHandler = async (argv) => {
27
27
  } else {
28
28
  argv.apiPort ??= getAPIPort();
29
29
  argv.apiHost ??= getAPIHost();
30
- argv.webPort ??= getWebPort();
31
- argv.webHost ??= getWebHost();
30
+ argv.webPort ??= getWebPort({ isPublicSide: true });
31
+ argv.webHost ??= getWebHost({ isPublicSide: true });
32
32
  const apiRootPath = argv.apiRootPath ?? getAPIRootPath();
33
33
  const apiProxyTarget = [
34
34
  "http://",
@@ -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(
@@ -0,0 +1,15 @@
1
+ import { terminalLink } from "termi-link";
2
+ import * as setupDatabasePostgres from "./postgres.js";
3
+ const command = "database <command>";
4
+ const description = "Switch your project's database";
5
+ const builder = (yargs) => yargs.command(setupDatabasePostgres).demandCommand().epilogue(
6
+ `Also see the ${terminalLink(
7
+ "CedarJS CLI Reference",
8
+ "https://cedarjs.com/docs/cli-commands#setup"
9
+ )}`
10
+ );
11
+ export {
12
+ builder,
13
+ command,
14
+ description
15
+ };
@@ -0,0 +1,19 @@
1
+ import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
2
+ const command = "postgres";
3
+ const description = "Switch your project from SQLite to PostgreSQL (schema, dependencies, and database adapter)";
4
+ function builder(yargs) {
5
+ return yargs;
6
+ }
7
+ async function handler() {
8
+ recordTelemetryAttributes({
9
+ command: "setup database postgres"
10
+ });
11
+ const { handler: handler2 } = await import("./postgresHandler.js");
12
+ return handler2();
13
+ }
14
+ export {
15
+ builder,
16
+ command,
17
+ description,
18
+ handler
19
+ };
@@ -0,0 +1,194 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import execa from "execa";
4
+ import { Listr } from "listr2";
5
+ import { colors, getPaths, installPackages } from "@cedarjs/cli-helpers";
6
+ import { prettyPrintCedarCommand } from "@cedarjs/cli-helpers/packageManager";
7
+ import { addWorkspacePackages } from "@cedarjs/cli-helpers/packageManager/packages";
8
+ import { resolveFile } from "@cedarjs/project-config";
9
+ import { errorTelemetry } from "@cedarjs/telemetry";
10
+ function checkProjectShape(cedarPaths) {
11
+ const schemaPath = path.join(cedarPaths.api.base, "db", "schema.prisma");
12
+ const dbPath = resolveFile(path.join(cedarPaths.api.lib, "db"));
13
+ if (!fs.existsSync(schemaPath)) {
14
+ return blocked(`Could not find ${schemaPath}.`);
15
+ }
16
+ if (!dbPath) {
17
+ return blocked(`No ${path.join(cedarPaths.api.lib, "db")} file found`);
18
+ }
19
+ const schemaContent = fs.readFileSync(schemaPath, "utf-8");
20
+ const hasPgAdapter = fs.readFileSync(dbPath, "utf-8").includes("PrismaPg");
21
+ if (schemaContent.includes('provider = "postgresql"') && hasPgAdapter) {
22
+ return {
23
+ ok: false,
24
+ alreadyConverted: true,
25
+ message: "This project is already configured for PostgreSQL."
26
+ };
27
+ }
28
+ if (!schemaContent.includes('provider = "sqlite"') || hasPgAdapter) {
29
+ return blocked(
30
+ "This command only converts a project that is still on SQLite, with the default adapter in api/src/lib/db.ts (or db.js) untouched. This project doesn't match that shape (a different provider, or a partial previous conversion). Please switch it over to PostgreSQL manually."
31
+ );
32
+ }
33
+ return { ok: true, dbPath };
34
+ }
35
+ function blocked(message) {
36
+ return { ok: false, alreadyConverted: false, message };
37
+ }
38
+ function getSqliteToPostgresTasks({
39
+ dbPath
40
+ }) {
41
+ const cedarPaths = getPaths();
42
+ const schemaPath = path.join(cedarPaths.api.base, "db", "schema.prisma");
43
+ const rootPkgPath = path.join(cedarPaths.base, "package.json");
44
+ const apiPkgPath = path.join(cedarPaths.api.base, "package.json");
45
+ const dbTsTemplatePath = path.join(
46
+ import.meta.dirname,
47
+ "templates",
48
+ "db.ts.template"
49
+ );
50
+ return [
51
+ {
52
+ title: "Removing SQLite dependencies from api/package.json",
53
+ task: () => {
54
+ const pkg = JSON.parse(fs.readFileSync(apiPkgPath, "utf-8"));
55
+ if (pkg.dependencies) {
56
+ delete pkg.dependencies["better-sqlite3"];
57
+ delete pkg.dependencies["@prisma/adapter-better-sqlite3"];
58
+ }
59
+ fs.writeFileSync(apiPkgPath, JSON.stringify(pkg, null, 2) + "\n");
60
+ }
61
+ },
62
+ {
63
+ title: "Removing better-sqlite3 dependenciesMeta",
64
+ task: () => {
65
+ if (!fs.existsSync(rootPkgPath)) {
66
+ return;
67
+ }
68
+ const pkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf-8"));
69
+ if (pkg.dependenciesMeta?.["better-sqlite3"]) {
70
+ delete pkg.dependenciesMeta["better-sqlite3"];
71
+ if (Object.keys(pkg.dependenciesMeta).length === 0) {
72
+ delete pkg.dependenciesMeta;
73
+ }
74
+ fs.writeFileSync(rootPkgPath, JSON.stringify(pkg, null, 2) + "\n");
75
+ }
76
+ }
77
+ },
78
+ {
79
+ title: "Switching Prisma schema to PostgreSQL",
80
+ task: () => {
81
+ const schemaContent = fs.readFileSync(schemaPath, "utf-8");
82
+ fs.writeFileSync(
83
+ schemaPath,
84
+ schemaContent.replace(
85
+ 'provider = "sqlite"',
86
+ 'provider = "postgresql"'
87
+ )
88
+ );
89
+ }
90
+ },
91
+ {
92
+ title: "Updating database adapter",
93
+ task: () => {
94
+ const pgDbTs = fs.readFileSync(dbTsTemplatePath, "utf-8");
95
+ fs.writeFileSync(dbPath, pgDbTs);
96
+ }
97
+ },
98
+ {
99
+ title: "Adding required api packages...",
100
+ task: async () => {
101
+ await addWorkspacePackages("api", ["@prisma/adapter-pg@7.8.0"], {
102
+ cwd: cedarPaths.api.base
103
+ });
104
+ }
105
+ }
106
+ ];
107
+ }
108
+ function readEnvVar(envContent, name) {
109
+ return envContent.match(new RegExp(`^${name}=(.*)$`, "m"))?.[1] || void 0;
110
+ }
111
+ async function handler() {
112
+ const cedarPaths = getPaths();
113
+ const shape = checkProjectShape(cedarPaths);
114
+ if (!shape.ok) {
115
+ if (shape.alreadyConverted) {
116
+ console.log(colors.note(shape.message));
117
+ return;
118
+ }
119
+ console.error(colors.error(shape.message));
120
+ process.exit(1);
121
+ }
122
+ const envPath = path.join(cedarPaths.base, ".env");
123
+ const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
124
+ const databaseUrl = readEnvVar(envContent, "DATABASE_URL");
125
+ const tasks = new Listr(
126
+ [
127
+ ...getSqliteToPostgresTasks({ dbPath: shape.dbPath }),
128
+ installPackages,
129
+ {
130
+ title: "Running Prisma migrations",
131
+ skip: () => {
132
+ if (!databaseUrl) {
133
+ return `No DATABASE_URL found in \`.env\`. Set it to your PostgreSQL connection string, then run \`${prettyPrintCedarCommand(["prisma", "migrate", "dev"])}\``;
134
+ }
135
+ return false;
136
+ },
137
+ task: () => {
138
+ const result = execa.commandSync(
139
+ "yarn cedar prisma migrate dev --name init-postgres",
140
+ {
141
+ cwd: cedarPaths.base,
142
+ stdio: ["inherit", "inherit", "pipe"],
143
+ reject: false
144
+ }
145
+ );
146
+ if (result.exitCode !== 0) {
147
+ throw new Error(
148
+ "Prisma migration failed:\n\n" + result.stderr + `
149
+
150
+ You can try running it manually:
151
+ ${prettyPrintCedarCommand(["prisma", "migrate", "dev", "--name", "init-postgres"])}`
152
+ );
153
+ }
154
+ }
155
+ }
156
+ ],
157
+ {
158
+ exitOnError: false,
159
+ collectErrors: "minimal"
160
+ }
161
+ );
162
+ try {
163
+ await tasks.run();
164
+ if (tasks.errors.length > 0) {
165
+ for (const error of tasks.errors) {
166
+ if (isErrorWithMessage(error)) {
167
+ errorTelemetry(process.argv, error.message);
168
+ console.error(colors.error(error.message));
169
+ }
170
+ }
171
+ process.exit(1);
172
+ }
173
+ } catch (e) {
174
+ if (isErrorWithMessage(e)) {
175
+ errorTelemetry(process.argv, e.message);
176
+ console.error(colors.error(e.message));
177
+ }
178
+ if (isErrorWithExitCode(e)) {
179
+ process.exit(e.exitCode);
180
+ }
181
+ process.exit(1);
182
+ }
183
+ }
184
+ function isErrorWithMessage(e) {
185
+ return !!e && typeof e === "object" && "message" in e;
186
+ }
187
+ function isErrorWithExitCode(e) {
188
+ return !!e && typeof e === "object" && "exitCode" in e && typeof e.exitCode === "number";
189
+ }
190
+ export {
191
+ checkProjectShape,
192
+ getSqliteToPostgresTasks,
193
+ handler
194
+ };
@@ -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));
@@ -5,13 +5,7 @@ import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
5
5
  import { getPaths, getPrismaSchemas } from "@cedarjs/project-config";
6
6
  import { errorTelemetry } from "@cedarjs/telemetry";
7
7
  import { writeFilesTask, printSetupNotes } from "../../../../lib/index.js";
8
- import { addFilesTask } from "../helpers/index.js";
9
- import {
10
- POSTGRES_YAML,
11
- RENDER_HEALTH_CHECK,
12
- RENDER_YAML,
13
- SQLITE_YAML
14
- } from "../templates/render.js";
8
+ import { POSTGRES_YAML, RENDER_YAML, SQLITE_YAML } from "../templates/render.js";
15
9
  const { getConfig } = prismaInternals;
16
10
  const getRenderYamlContent = async (database) => {
17
11
  if (database === "none") {
@@ -54,14 +48,9 @@ const getRenderYamlContent = async (database) => {
54
48
  const notes = [
55
49
  "You are ready to deploy to Render!\n",
56
50
  "Go to https://dashboard.render.com/iacs to create your account and deploy to Render",
57
- "Check out the deployment docs at https://render.com/docs/deploy-redwood for detailed instructions",
58
- "Note: After first deployment to Render update the rewrite rule destination in `./render.yaml`"
59
- ];
60
- const additionalFiles = [
61
- {
62
- path: path.join(getPaths().base, "api/src/functions/healthz.js"),
63
- content: RENDER_HEALTH_CHECK
64
- }
51
+ "Check out the deployment docs at https://cedarjs.com/docs/deploy/render for detailed instructions",
52
+ "Note: After first deployment to Render update the rewrite rule destination in `./render.yaml`",
53
+ "Note: The api service now health checks `/graphql/health`. If a previous setup left an unused `api/src/functions/healthz.js` behind, you can delete it"
65
54
  ];
66
55
  const handler = async ({
67
56
  force,
@@ -83,11 +72,6 @@ const handler = async ({
83
72
  return writeFilesTask(files, { overwriteExisting: force });
84
73
  }
85
74
  },
86
- // Add health check api function
87
- addFilesTask({
88
- files: additionalFiles,
89
- force
90
- }),
91
75
  printSetupNotes(notes)
92
76
  ],
93
77
  { rendererOptions: { collapseSubtasks: false } }
@@ -5,13 +5,15 @@ const PROJECT_NAME = path.basename(getPaths().base);
5
5
  const RENDER_YAML = (database) => {
6
6
  const apiUrl = getUserApiUrl().replace(/\/$/, "");
7
7
  return `# Quick links to the docs:
8
- # - Redwood on Render: https://render.com/docs/deploy-redwood
9
- # - Render's Blueprint spec: https://render.com/docs/yaml-spec
8
+ # - Deploying Cedar: https://cedarjs.com/docs/deploy/render
9
+ # - Render's own walkthrough (uses \`yarn rw\`, but just swap in \`yarn cedar\`):
10
+ # https://render.com/docs/deploy-redwood
11
+ # - Render's Blueprint spec: https://render.com/docs/blueprint-spec
10
12
 
11
13
  services:
12
14
  - name: ${PROJECT_NAME}-web
13
15
  type: web
14
- env: static
16
+ runtime: static
15
17
  buildCommand: npm install --global corepack && yarn install && yarn cedar deploy render web
16
18
  staticPublishPath: ./web/dist
17
19
 
@@ -22,11 +24,16 @@ services:
22
24
  routes:
23
25
  - type: rewrite
24
26
  source: ${apiUrl}/*
25
- # Replace \`destination\` here after your first deploy:
27
+ # Replace \`destination\` after your first deploy, with the api service's
28
+ # URL from the Render dashboard:
26
29
  #
27
30
  # \`\`\`
28
- # destination: https://my-redwood-project-api.onrender.com/*
31
+ # destination: https://${PROJECT_NAME}-api.onrender.com/*
29
32
  # \`\`\`
33
+ #
34
+ # This can't be filled in automatically \u2014 Render's \`fromService\` only
35
+ # resolves service hosts into \`envVars\`, not into a static site's route
36
+ # destination.
30
37
  destination: replace_with_api_url/*
31
38
  - type: rewrite
32
39
  source: /*
@@ -35,11 +42,22 @@ services:
35
42
  - name: ${PROJECT_NAME}-api
36
43
  type: web
37
44
  plan: free
38
- env: node
45
+ runtime: node
39
46
  region: oregon
40
47
  buildCommand: npm install --global corepack && yarn install && yarn cedar build api
41
48
  startCommand: yarn cedar deploy render api
42
49
 
50
+ # Proves the GraphQL server is actually serving, not just that the process
51
+ # is alive. Returns 200 with an \`x-yoga-id\` response header.
52
+ #
53
+ # The route is \`<apiRootPath><graphiQLEndpoint>/health\`, and the value below
54
+ # assumes both defaults (\`/\` and \`/graphql\`). Update it to match if you
55
+ # customize either \u2014 by setting \`CEDAR_API_ROOT_PATH\` in the envVars below,
56
+ # by passing \`apiRootPath\` to \`createServer\` in \`api/src/server.ts\`, or by
57
+ # setting \`graphiQLEndpoint\` in \`api/src/functions/graphql.ts\`. A mismatch
58
+ # here 404s, and Render will not promote the deploy.
59
+ healthCheckPath: /graphql/health
60
+
43
61
  envVars:
44
62
  ${database}
45
63
  `;
@@ -58,17 +76,9 @@ const SQLITE_YAML = ` - key: DATABASE_URL
58
76
  name: sqlite-data
59
77
  mountPath: /opt/render/project/src/api/db/data
60
78
  sizeGB: 1`;
61
- const RENDER_HEALTH_CHECK = `// render-health-check
62
- export const handler = async () => {
63
- return {
64
- statusCode: 200,
65
- }
66
- }
67
- `;
68
79
  export {
69
80
  POSTGRES_YAML,
70
81
  PROJECT_NAME,
71
- RENDER_HEALTH_CHECK,
72
82
  RENDER_YAML,
73
83
  SQLITE_YAML
74
84
  };
@@ -94,11 +94,8 @@ ENV NODE_ENV=production
94
94
 
95
95
  # default api serve command
96
96
  # ---------
97
- # If you are using a custom server file, you must use the following
98
- # command to launch your server instead of the default api-server below.
99
- # This is important if you intend to configure GraphQL to use Realtime.
100
- #
101
- # CMD [ "./api/dist/server.js" ]
97
+ # See https://cedarjs.com/docs/server-file for customizing the api server
98
+ # (Realtime, custom Fastify plugins, etc).
102
99
  CMD ["node_modules/.bin/cedarjs-server", "api"]
103
100
 
104
101
  # web serve
@@ -18,7 +18,7 @@ services:
18
18
  - SESSION_SECRET=super_secret_session_key_change_me_in_production_please
19
19
  - CI=
20
20
  - NODE_ENV=development
21
- - REDWOOD_API_HOST=0.0.0.0
21
+ - CEDAR_API_HOST=0.0.0.0
22
22
 
23
23
  db:
24
24
  image: postgres:18-bookworm
@@ -4,11 +4,8 @@ services:
4
4
  context: .
5
5
  dockerfile: ./Dockerfile
6
6
  target: api_serve
7
- # Without a command specified, the Dockerfile's api_serve CMD will be used.
8
- # If you are using a custom server file, you should either use the following
9
- # command to launch your server or update the Dockerfile to do so.
10
- # This is important if you intend to configure GraphQL to use Realtime.
11
- # command: "./api/dist/server.js"
7
+ # See https://cedarjs.com/docs/server-file for customizing the api
8
+ # server (Realtime, custom Fastify plugins, etc).
12
9
  ports:
13
10
  - '8911:8911'
14
11
  depends_on:
@@ -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))