Skip to content

Commit

Permalink
edgedb-js/create refactor (#1186)
Browse files Browse the repository at this point in the history
Use PackageManager class.
Use user's package runner to run the Gel CLI instead of installing it.
  • Loading branch information
diksipav authored Jan 27, 2025
1 parent 8de5387 commit 138ce6a
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 60 deletions.
4 changes: 2 additions & 2 deletions packages/create/src/recipes/_base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import debug from "debug";
import * as p from "@clack/prompts";
import { updatePackage } from "write-package";

import { getPackageManager, copyTemplateFiles } from "../../utils.js";
import { copyTemplateFiles, PackageManager } from "../../utils.js";
import type { Framework, BaseRecipe, BaseOptions } from "../types.js";

const logger = debug("@gel/create:recipe:base");

const recipe: BaseRecipe = {
async getOptions() {
const packageManager = getPackageManager();
const packageManager = new PackageManager();
logger({ packageManager });

const opts = await p.group(
Expand Down
76 changes: 20 additions & 56 deletions packages/create/src/recipes/_gel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from "node:path";
import debug from "debug";

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

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

Expand All @@ -24,82 +24,45 @@ const recipe: Recipe<GelOptions> = {
},

async apply(
{ projectDir, useGelAuth }: BaseOptions,
{ projectDir, useGelAuth, packageManager }: BaseOptions,
{ initializeProject }: GelOptions,
) {
logger("Running gel recipe");
logger("Checking for existing Gel CLI");

const spinner = p.spinner();

if (initializeProject) {
let gelCliVersion: string | null = null;
let shouldInstallCli: boolean | symbol = true;
try {
const { stdout } = await execInLoginShell("gel --version");
gelCliVersion = stdout.trim();
logger(gelCliVersion);
} catch (_error) {
logger("No Gel CLI detected");
shouldInstallCli = await p.confirm({
message:
"The Gel CLI is required to initialize a project. Install now?",
initialValue: true,
});
}

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

logger("Installing Gel CLI");

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

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

spinner.start("Initializing Gel project");
try {
await execInLoginShell("gel project init --non-interactive", {
cwd: projectDir,
});
const { stdout, stderr } = await execInLoginShell(
"gel query 'select sys::get_version_as_str()'",
await packageManager.runPackageBin(
"gel",
["project", "init", "--non-interactive"],
{
cwd: projectDir,
},
);
const { stdout, stderr } = await packageManager.runPackageBin(
"gel",
["query", "select sys::get_version_as_str()"],
{ cwd: projectDir },
);
const serverVersion = JSON.parse(stdout.trim());
logger(`Gel server version: ${serverVersion}`);

if (serverVersion === "") {
const err = new Error(
"There was a problem initializing the Gel project",
);
spinner.stop(err.message);
logger({ stdout, stderr });

throw err;
}

spinner.stop(`Gel v${serverVersion} project initialized`);
} catch (error) {
logger(error);
spinner.stop("Failed to initialize Gel project");
throw error;
} finally {
spinner.stop();
}
} else {
logger("Skipping gel project init");
Expand All @@ -122,16 +85,17 @@ const recipe: Recipe<GelOptions> = {
logger("Creating and applying initial migration");
spinner.start("Creating and applying initial migration");
try {
await execInLoginShell("gel migration create", {
await packageManager.runPackageBin("gel", ["migration", "create"], {
cwd: projectDir,
});
await packageManager.runPackageBin("gel", ["migrate"], {
cwd: projectDir,
});
await execInLoginShell("gel migrate", { cwd: projectDir });
spinner.stop("Initial migration created and applied");
} catch (error) {
logger(error);
spinner.stop("Failed to create and apply migration");
throw error;
} finally {
spinner.stop();
}
}
}
Expand Down
32 changes: 30 additions & 2 deletions packages/create/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ 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";
type PkgManager = "npm" | "yarn" | "pnpm" | "bun";

export function getPackageManager(): PackageManager {
export function getPackageManager(): PkgManager {
const userAgent = process.env.npm_config_user_agent;
switch (true) {
case userAgent?.startsWith("yarn"):
Expand All @@ -20,6 +20,13 @@ export function getPackageManager(): PackageManager {
}
}

const PM_TO_RUNNER_MAP = {
npm: "npx",
yarn: "yarn dlx",
pnpm: "pnpm dlx",
bun: "bunx",
} as const;

interface CopyTemplateFilesOpts {
tags?: Set<string>;
rewritePath?: (path: string) => string;
Expand Down Expand Up @@ -153,3 +160,24 @@ stdout: ${stdout}`,
});
});
}

export class PackageManager {
readonly runner: string;

constructor(readonly packageManager = getPackageManager()) {
this.runner = PM_TO_RUNNER_MAP[packageManager];
}

toString() {
return this.packageManager;
}

async runPackageBin(
binName: string,
args: string[] = [],
options?: SpawnOptionsWithoutStdio,
): Promise<{ stdout: string; stderr: string }> {
const command = `${this.runner} ${binName} ${args.join(" ")}`;
return execInLoginShell(command, options);
}
}

0 comments on commit 138ce6a

Please sign in to comment.