Skip to content

Commit

Permalink
feat: create-graz-app & templates
Browse files Browse the repository at this point in the history
  • Loading branch information
codingki committed Oct 20, 2022
1 parent 4fe9e60 commit 4850149
Show file tree
Hide file tree
Showing 47 changed files with 2,173 additions and 35 deletions.
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"eslint.workingDirectories": [
{ "!cwd": false, "directory": "docs" },
{ "!cwd": false, "directory": "example" },
{ "!cwd": false, "pattern": "packages/*" }
{ "!cwd": false, "pattern": "packages/*" },
{ "!cwd": false, "pattern": "templates/*" }
],
"npm.packageManager": "pnpm"
"npm.packageManager": "pnpm",
"editor.formatOnSave": true
}
8 changes: 2 additions & 6 deletions example/ui/chain-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,9 @@ export const ChainSwitcher: FC = () => {
},
});

const { connect } = useConnect({
onSuccess: () => console.log("switched chain"),
});
const { connect } = useConnect();

const { suggestAndConnect } = useSuggestChainAndConnect({
onSuccess: () => console.log("switched chain"),
});
const { suggestAndConnect } = useSuggestChainAndConnect();

return (
<FormControl>
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"workspaces": [
"docs",
"example",
"packages/*"
"packages/*",
"templates/*"
],
"scripts": {
"build": "turbo run build --filter=!@project/docs --filter=!graz-adapter-*",
Expand All @@ -13,9 +14,11 @@
"docs": "pnpm --dir docs",
"example": "pnpm --dir example",
"graz": "pnpm --dir packages/graz",
"create-graz-app": "pnpm --dir packages/create-graz-app",
"lint": "turbo run lint",
"prepare": "husky install",
"release": "turbo run build --filter=graz && pnpm publish --filter graz",
"templates": "pnpm --dir templates/default",
"test": "turbo run test"
},
"devDependencies": {
Expand Down
18 changes: 18 additions & 0 deletions packages/create-graz-app/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @ts-check

const { getTsconfigPath } = require("@strangelovelabs/style-guide/eslint/helpers");

/** @type {import("eslint").Linter.Config} */
const eslintConfig = {
extends: [
require.resolve("@strangelovelabs/style-guide/eslint/browser-node"),
require.resolve("@strangelovelabs/style-guide/eslint/typescript"),
],
ignorePatterns: [".next", "node_modules", "out"],
parserOptions: {
project: getTsconfigPath(),
},
root: true,
};

module.exports = eslintConfig;
1 change: 1 addition & 0 deletions packages/create-graz-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist/
103 changes: 103 additions & 0 deletions packages/create-graz-app/create-apps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import retry from "async-retry";
import chalk from "chalk";
import path from "path";

import type { PackageManager } from "./helpers/get-pkg-manager";
import { tryGitInit } from "./helpers/git";
import { install } from "./helpers/install";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { getOnline } from "./helpers/is-online";
import { isWriteable } from "./helpers/is-writeable";
import { makeDir } from "./helpers/make-dir";
import type { RepoInfo } from "./helpers/repo";
import { downloadAndExtractRepo } from "./helpers/repo";

export class DownloadError extends Error {}

export async function createApp({
appPath,
packageManager,
}: {
appPath: string;
packageManager: PackageManager;
}): Promise<void> {
const repo: RepoInfo = {
username: "strangelove-ventures",
branch: "dev",
name: "graz",
filePath: "templates/default",
};

const root = path.resolve(appPath);

if (!(await isWriteable(path.dirname(root)))) {
console.error("The application path is not writable, please check folder permissions and try again.");
console.error("It is likely you do not have write permissions for this folder.");
process.exit(1);
}

const appName = path.basename(root);

await makeDir(root);
if (!isFolderEmpty(root, appName)) {
process.exit(1);
}

const useYarn = packageManager === "yarn";
const isOnline = !useYarn || (await getOnline());
const originalDirectory = process.cwd();

console.log(`Creating a cosmos frontend in ${chalk.green(root)}.`);
console.log();

process.chdir(root);

try {
console.log(`Downloading files from repo. This might take a moment.`);
console.log();
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await retry(() => downloadAndExtractRepo(root, repo), {
retries: 3,
});
} catch (reason) {
// eslint-disable-next-line no-inner-declarations
function isErrorLike(err: unknown): err is { message: string } {
return typeof err === "object" && err !== null && typeof (err as { message?: unknown }).message === "string";
}

throw new DownloadError(isErrorLike(reason) ? reason.message : `${reason}`);
}
console.log("Installing packages. This might take a couple of minutes.");
console.log();
await install(root, null, { packageManager, isOnline });

if (tryGitInit(root)) {
console.log("Initialized a git repository.");
console.log();
}

let cdpath: string;
if (path.join(originalDirectory, appName) === appPath) {
cdpath = appName;
} else {
cdpath = appPath;
}

console.log(`${chalk.green("Success!")} Created ${appName} at ${appPath}`);

console.log("Inside that directory, you can run several commands:");
console.log();
console.log(chalk.cyan(` ${packageManager} ${useYarn ? "" : "run "}dev`));
console.log(" Starts the development server.");
console.log();
console.log(chalk.cyan(` ${packageManager} ${useYarn ? "" : "run "}build`));
console.log(" Builds the app for production.");
console.log();
console.log(chalk.cyan(` ${packageManager} start`));
console.log(" Runs the built app in production mode.");
console.log();
console.log("We suggest that you begin by typing:");
console.log();
console.log(chalk.cyan(" cd"), cdpath);
console.log(` ${chalk.cyan(`${packageManager} ${useYarn ? "" : "run "}dev`)}`);
}
25 changes: 25 additions & 0 deletions packages/create-graz-app/helpers/get-pkg-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { execSync } from "child_process";

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

export function getPkgManager(): PackageManager {
try {
const userAgent = process.env.npm_config_user_agent;
if (userAgent) {
if (userAgent.startsWith("yarn")) {
return "yarn";
} else if (userAgent.startsWith("pnpm")) {
return "pnpm";
}
}
try {
execSync("yarn --version", { stdio: "ignore" });
return "yarn";
} catch {
execSync("pnpm --version", { stdio: "ignore" });
return "pnpm";
}
} catch {
return "npm";
}
}
51 changes: 51 additions & 0 deletions packages/create-graz-app/helpers/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { execSync } from "child_process";
import path from "path";
import rimraf from "rimraf";

function isInGitRepository(): boolean {
try {
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
return true;
} catch (_) {
return false;
}
}
function isInMercurialRepository(): boolean {
try {
execSync("hg --cwd . root", { stdio: "ignore" });
return true;
} catch (_) {
return false;
}
}

export function tryGitInit(root: string): boolean {
let didInit = false;
try {
execSync("git --version", { stdio: "ignore" });
if (isInGitRepository() || isInMercurialRepository()) {
return false;
}

execSync("git init", { stdio: "ignore" });
didInit = true;

execSync("git checkout -b main", { stdio: "ignore" });

execSync("git add -A", { stdio: "ignore" });

// execSync('git commit -m "Initial commit from create-graz-app"', {
// stdio: "ignore",
// });
return true;
} catch (e) {
if (didInit) {
try {
rimraf.sync(path.join(root, ".git"));
} catch (_) {
return false;
}
}
return false;
}
}
115 changes: 115 additions & 0 deletions packages/create-graz-app/helpers/install.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import chalk from "chalk";
import spawn from "cross-spawn";

import type { PackageManager } from "./get-pkg-manager";

interface InstallArgs {
/**
* Indicate whether to install packages using npm, pnpm or Yarn.
*/
packageManager: PackageManager;
/**
* Indicate whether there is an active Internet connection.
*/
isOnline: boolean;
/**
* Indicate whether the given dependencies are devDependencies.
*/
devDependencies?: boolean;
}

/**
* Spawn a package manager installation with either Yarn or NPM.
*
* @returns A Promise that resolves once the installation is finished.
*/
export function install(
root: string,
dependencies: string[] | null,
{ packageManager, isOnline, devDependencies }: InstallArgs,
): Promise<void> {
/**
* (p)npm-specific command-line flags.
*/
const npmFlags: string[] = [];
/**
* Yarn-specific command-line flags.
*/
const yarnFlags: string[] = [];
/**
* Return a Promise that resolves once the installation is finished.
*/
return new Promise((resolve, reject) => {
let args: string[];
const command = packageManager;
const useYarn = packageManager === "yarn";

if (dependencies?.length) {
/**
* If there are dependencies, run a variation of `{packageManager} add`.
*/
if (useYarn) {
/**
* Call `yarn add --exact (--offline)? (-D)? ...`.
*/
args = ["add", "--exact"];
if (!isOnline) args.push("--offline");
args.push("--cwd", root);
if (devDependencies) args.push("--dev");
args.push(...dependencies);
} else {
/**
* Call `(p)npm install [--save|--save-dev] ...`.
*/
args = ["install", "--save-exact"];
args.push(devDependencies ? "--save-dev" : "--save");
args.push(...dependencies);
}
} else {
/**
* If there are no dependencies, run a variation of `{packageManager} install`.
*/
args = ["install"];
if (!isOnline) {
console.log(chalk.yellow("You appear to be offline."));
if (useYarn) {
console.log(chalk.yellow("Falling back to the local Yarn cache."));
console.log();
args.push("--offline");
} else {
console.log();
}
}
}
/**
* Add any package manager-specific flags.
*/
if (useYarn) {
args.push(...yarnFlags);
} else {
args.push(...npmFlags);
}
/**
* Spawn the installation process.
*/
const child = spawn(command, args, {
stdio: "inherit",
env: {
...process.env,
ADBLOCK: "1",
// we set NODE_ENV to development as pnpm skips dev
// dependencies when production
NODE_ENV: "development",
DISABLE_OPENCOLLECTIVE: "1",
},
});
child.on("close", (code) => {
if (code !== 0) {
// eslint-disable-next-line prefer-promise-reject-errors
reject({ command: `${command} ${args.join(" ")}` });
return;
}
resolve();
});
});
}
Loading

0 comments on commit 4850149

Please sign in to comment.