Skip to content

Commit

Permalink
Add EdgeDB create-app recipe (#818)
Browse files Browse the repository at this point in the history
  • Loading branch information
scotttrinh authored Jan 3, 2024
1 parent 5eabf23 commit 9ebb33d
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 25 deletions.
122 changes: 100 additions & 22 deletions packages/create/src/recipes/_edgedb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,116 @@ import * as p from "@clack/prompts";
import fs from "node:fs/promises";
import path from "node:path";
import debug from "debug";
import util from "node:util";
import childProcess from "node:child_process";

import { BaseOptions, Recipe } from "../types.js";
import type { BaseOptions, Recipe } from "../types.js";
import { copyTemplateFiles, execInLoginShell } from "../../utils.js";

const logger = debug("@edgedb/create:recipe:edgedb");
const exec = util.promisify(childProcess.exec);

const recipe: Recipe = {
async apply({ projectDir, useEdgeDBAuth }: BaseOptions) {
interface EdgeDBOptions {
initializeProject: boolean;
}

const recipe: Recipe<EdgeDBOptions> = {
getOptions() {
return p.group({
initializeProject: () =>
p.confirm({
message: "Initialize a new EdgeDB project with edgedb project init?",
initialValue: true,
}),
});
},

async apply(
{ projectDir, useEdgeDBAuth }: BaseOptions,
{ initializeProject }: EdgeDBOptions
) {
logger("Running edgedb recipe");
logger("Checking for existing EdgeDB CLI");

const spinner = p.spinner();

spinner.start("Initializing EdgeDB project");
await exec("edgedb project init --non-interactive", { cwd: projectDir });
const { stdout, stderr } = await exec(
"edgedb query 'select sys::get_version_as_str()'",
{ cwd: projectDir }
);
const serverVersion = JSON.parse(stdout.trim());
logger(`EdgeDB version: ${serverVersion}`);
if (serverVersion === "") {
const err = new Error(
"There was a problem initializing the EdgeDB project"
);
spinner.stop(err.message);
logger({ stdout, stderr });
if (initializeProject) {
let edgedbCliVersion: string | null = null;
let shouldInstallCli: boolean | symbol = true;
try {
const { stdout } = await execInLoginShell("edgedb --version");
edgedbCliVersion = stdout.trim();
logger(edgedbCliVersion);
} catch (error) {
logger("No EdgeDB CLI detected");
shouldInstallCli = await p.confirm({
message:
"The EdgeDB CLI is required to initialize a project. Install now?",
initialValue: true,
});
}

if (edgedbCliVersion === null) {
if (shouldInstallCli === false) {
logger("User declined to install EdgeDB CLI");
throw new Error("EdgeDB CLI is required");
}

logger("Installing EdgeDB CLI");

throw err;
spinner.start("Installing EdgeDB CLI");
const { stdout, stderr } = await execInLoginShell(
"curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh -s -- -y"
);
logger({ stdout, stderr });
spinner.stop("EdgeDB CLI installed");
}

try {
const { stdout } = await execInLoginShell("edgedb --version");
edgedbCliVersion = stdout.trim();
logger(edgedbCliVersion);
} catch (error) {
logger("EdgeDB CLI could not be installed.");
logger(error);
throw new Error("EdgeDB CLI could not be installed.");
}

spinner.start("Initializing EdgeDB project");
try {
await execInLoginShell("edgedb project init --non-interactive", {
cwd: projectDir,
});
const { stdout, stderr } = await execInLoginShell(
"edgedb query 'select sys::get_version_as_str()'",
{ cwd: projectDir }
);
const serverVersion = JSON.parse(stdout.trim());
logger(`EdgeDB server version: ${serverVersion}`);
if (serverVersion === "") {
const err = new Error(
"There was a problem initializing the EdgeDB project"
);
spinner.stop(err.message);
logger({ stdout, stderr });

throw err;
}
spinner.stop(`EdgeDB v${serverVersion} project initialized`);
} catch (error) {
logger(error);
throw error;
} finally {
spinner.stop();
}
} else {
logger("Skipping edgedb project init");
logger("Copying basic EdgeDB project files");

const dirname = path.dirname(new URL(import.meta.url).pathname);
await copyTemplateFiles(
path.resolve(dirname, "./template"),
projectDir,
new Set()
);
}
spinner.stop(`EdgeDB v${serverVersion} project initialized`);

if (useEdgeDBAuth) {
logger("Adding auth extension to project");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module default {

}
3 changes: 1 addition & 2 deletions packages/create/src/recipes/_install/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import debug from "debug";
import * as p from "@clack/prompts";

import * as utils from "../../utils.js";
import { BaseOptions, Recipe } from "../types.js";
import type { BaseOptions, Recipe } from "../types.js";

const logger = debug("@edgedb/create:recipe:install");

Expand Down
2 changes: 1 addition & 1 deletion packages/create/src/recipes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import _install from "./_install/index.js";
import express from "./express/index.js";
import nextjs from "./nextjs/index.js";

import { Recipe } from "./types.js";
import { type Recipe } from "./types.js";

export { baseRecipe };

Expand Down
32 changes: 32 additions & 0 deletions packages/create/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import process from "node:process";
import fs from "node:fs/promises";
import { type Dirent } from "node:fs";
import path from "node:path";
import { spawn, type SpawnOptionsWithoutStdio } from "node:child_process";

export type PackageManager = "npm" | "yarn" | "pnpm" | "bun";

Expand Down Expand Up @@ -117,3 +118,34 @@ async function _walkDir(
}
}
}

export async function execInLoginShell(
command: string,
options?: SpawnOptionsWithoutStdio
): Promise<{ stdout: string; stderr: string }> {
return new Promise((resolve, reject) => {
let stdout = "";
let stderr = "";
const child = spawn("/bin/bash", ["-l", "-c", command], options);
child.stdout.on("data", (data) => {
stdout += data;
});
child.stderr.on("data", (data) => {
stderr += data;
});
child.on("close", (code) => {
if (code !== 0) {
reject(
new Error(
`\
Command "${command}" exited with code ${code}
stderr: ${stderr}
stdout: ${stdout}`
)
);
} else {
resolve({ stdout, stderr });
}
});
});
}

0 comments on commit 9ebb33d

Please sign in to comment.