Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(create-mud): rip out create-create-app #3479

Merged
merged 10 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hip-spoons-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-mud": patch
---

Replaced internal usage of `create-create-app` with a simpler recursive copy operation.
3 changes: 2 additions & 1 deletion .github/workflows/test-published-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ jobs:

- name: Test
run: |
pnpm create mud@${{ inputs.tag-or-version }} project --template ${{ matrix.template }}
pnpm create mud@${{ inputs.tag-or-version }} --name project --template ${{ matrix.template }}
pnpm --dir project install
pnpm --dir project run test
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ You can see MUD's features, both those available and those still in development,
## Quickstart

```
pnpm create mud my-project
pnpm create mud@latest
```

Then follow the directions onscreen.
Expand Down
4 changes: 3 additions & 1 deletion docs/pages/guides/hello-world/add-chain-client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Note that this is not required if you are going to use Lattice chains, [redstone
Use the vanilla template.

```sh copy
pnpm create mud@latest tutorial --template vanilla
pnpm create mud@latest --name tutorial --template vanilla
cd tutorial
pnpm install
pnpm dev
```

You can also use the `react-ecs` or `threejs` templates without any changes to the tutorial.
Expand Down
4 changes: 3 additions & 1 deletion docs/pages/guides/hello-world/add-system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ In this tutorial you add a system to decrement the counter and update the applic
Use the vanilla template.

```sh copy
pnpm create mud@latest tutorial --template vanilla
pnpm create mud@latest --name tutorial --template vanilla
cd tutorial
pnpm install
pnpm dev
```

## Add a contract for the new system
Expand Down
4 changes: 3 additions & 1 deletion docs/pages/guides/hello-world/add-table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ For the sake of simplicity, we will implement this in the `increment` function r
Use the `vanilla` template.

```sh copy
pnpm create mud@latest tutorial --template vanilla
pnpm create mud@latest --name tutorial --template vanilla
cd tutorial
pnpm install
pnpm dev
```

## Modify the MUD configuration file
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/guides/hello-world/deploy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ In this tutorial you deploy a MUD application to our test blockchain, [Garnet](h
Use the `vanilla` template.

```sh copy
pnpm create mud@latest tutorial --template vanilla
pnpm create mud@latest --name tutorial --template vanilla
cd tutorial
pnpm install
pnpm dev
```

Expand Down
6 changes: 3 additions & 3 deletions docs/pages/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,10 @@ To install the TypeScript templates you need:

To run any of the TypeScript templates:

1. Create the template with pnpm.
If you need, replace `tutorial` with your application name.
1. Create a new project from a template with pnpm.

```sh copy
pnpm create mud@latest tutorial
pnpm create mud@latest
```

<details>
Expand Down Expand Up @@ -155,6 +154,7 @@ To run any of the TypeScript templates:

```sh copy
cd tutorial
pnpm install
pnpm dev
```

Expand Down
1 change: 1 addition & 0 deletions packages/create-mud/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public/

# End of https://www.gitignore.io/api/node

templates

# Created by `pnpm test`
test-project
6 changes: 2 additions & 4 deletions packages/create-mud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

Create a new MUD project

> created by [create-create-app](https://github.com/uetchy/create-create-app).

## Usage

```bash
npm create mud <name>
```
pnpm create mud@latest
```
4 changes: 4 additions & 0 deletions packages/create-mud/bin/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node

// workaround for https://github.com/pnpm/pnpm/issues/1801
import "../dist/cli.js";
26 changes: 16 additions & 10 deletions packages/create-mud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,35 @@
"description": "Create a new MUD project",
"license": "MIT",
"author": "Lattice <[email protected]>",
"bin": "dist/cli.js",
"type": "module",
"bin": "bin/cli.js",
"files": [
"dist"
"bin",
"dist",
"templates"
],
"scripts": {
"build": "pnpm run build:js",
"build:js": "tsup && tsx ./scripts/copy-templates.ts",
"build:js": "tsup && pnpm run copy-templates",
"clean": "pnpm run clean:js",
"clean:js": "shx rm -rf dist",
"copy-templates": "tsx ./scripts/copy-templates.ts",
"dev": "tsup --watch",
"prepublishOnly": "npm run clean && npm run build",
"test": "pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs",
"test": "pnpm run copy-templates && pnpm vitest --run && pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs",
"test:ci": "pnpm run test",
"test:phaser": "dist/cli.js test-project --template phaser && shx rm -rf test-project",
"test:react": "dist/cli.js test-project --template react && shx rm -rf test-project",
"test:react-ecs": "dist/cli.js test-project --template react-ecs && shx rm -rf test-project",
"test:threejs": "dist/cli.js test-project --template threejs && shx rm -rf test-project",
"test:vanilla": "dist/cli.js test-project --template vanilla && shx rm -rf test-project"
"test:phaser": "bin/cli.js --name test-project --template phaser && pnpm --dir test-project install && shx rm -rf test-project",
"test:react": "bin/cli.js --name test-project --template react && pnpm --dir test-project install && shx rm -rf test-project",
"test:react-ecs": "bin/cli.js --name test-project --template react-ecs && pnpm --dir test-project install && shx rm -rf test-project",
"test:threejs": "bin/cli.js --name test-project --template threejs && pnpm --dir test-project install && shx rm -rf test-project",
"test:vanilla": "bin/cli.js --name test-project --template vanilla && pnpm --dir test-project install && shx rm -rf test-project"
},
"dependencies": {
"create-create-app": "git+https://github.com/holic/create-create-app#74376c59b48a04aabbe94d9cacfe9cb1cecccd63"
"fast-glob": "^3.3.3",
"yargs-interactive": "^3.0.1"
},
"devDependencies": {
"@types/yargs-interactive": "^2.1.6",
"execa": "^7.0.0"
},
"publishConfig": {
Expand Down
30 changes: 19 additions & 11 deletions packages/create-mud/scripts/copy-templates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import fs from "node:fs/promises";
import path from "node:path";
import { execa } from "execa";
import { glob } from "glob";
import glob from "fast-glob";
import { fileURLToPath } from "node:url";
import { exists } from "../src/exists";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

(async () => {
const packageDir = path.resolve(__dirname, "..");
Expand All @@ -15,22 +20,25 @@ import { glob } from "glob";
return packages.filter((p) => !p.private).map((p) => p.name);
})();

const files = (await execa("git", ["ls-files", "templates"], { cwd: rootDir })).stdout.trim().split("\n");
const sourceDir = path.join(rootDir, "templates");
const destDir = path.join(packageDir, "templates");

// clean
if (await exists(destDir)) {
await fs.rm(destDir, { recursive: true });
}

const files = (await execa("git", ["ls-files"], { cwd: sourceDir })).stdout.trim().split("\n");

for (const file of files) {
const sourcePath = path.resolve(rootDir, file);
const destPath = path.resolve(
packageDir,
"dist",
// Rename `.gitignore` to `gitignore`, so that create-create-app can copy it properly.
file.replace(/\.gitignore$/, "gitignore"),
);
const sourcePath = path.resolve(sourceDir, file);
const destPath = path.resolve(destDir, file);

await fs.mkdir(path.dirname(destPath), { recursive: true });

// Replace all MUD package links with mustache placeholder used by create-create-app
// that will be replaced with the latest MUD version number when the template is used.
if (/package.json$/.test(destPath)) {
if (/package\.json$/.test(destPath)) {
const source = await fs.readFile(sourcePath, "utf-8");
await fs.writeFile(
destPath,
Expand All @@ -41,7 +49,7 @@ import { glob } from "glob";
}
// Replace template workspace root `tsconfig.json` files (which have paths relative to monorepo)
// with one that inherits our base tsconfig.
else if (/templates\/[^/]+\/tsconfig.json/.test(destPath)) {
else if (/templates\/[^/]+\/tsconfig\.json/.test(destPath)) {
await fs.copyFile(path.join(__dirname, "tsconfig.base.json"), destPath);
} else {
await fs.copyFile(sourcePath, destPath);
Expand Down
70 changes: 70 additions & 0 deletions packages/create-mud/src/bin/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import yargsInteractive from "yargs-interactive";
import glob from "fast-glob";
import packageJson from "../../package.json";
import { templates } from "../common";
import { exists } from "../exists";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function run() {
yargsInteractive()
.usage("$0 [args]")
.interactive({
interactive: { default: true },
name: {
describe: "Name your project",
type: "input",
},
template: {
describe: "Pick a template",
type: "list",
choices: templates,
},
"mud-version": {
type: "input",
describe: "The version of MUD packages to use, defaults to latest",
default: packageJson.version,
},
})
.then(async (args) => {
if (!args.name) throw new Error("No project name provided.");

const destDir = path.join(process.cwd(), args.name);
if (await exists(destDir)) {
throw new Error(`Target directory "${destDir}" already exists.`);
}

const sourceDir = path.join(__dirname, "..", "templates", args.template);
const files = await glob("**/*", { cwd: sourceDir, dot: true });

for (const filename of files) {
const sourceFile = path.join(sourceDir, filename);
const destFile = path.join(destDir, filename);

await fs.mkdir(path.dirname(destFile), { recursive: true });

if (/package\.json$/.test(sourceFile)) {
const source = await fs.readFile(sourceFile, "utf-8");
await fs.writeFile(destFile, source.replaceAll(/{{mud-version}}/g, args.mudVersion), "utf-8");
} else {
await fs.copyFile(sourceFile, destFile);
}
}

console.log(`
New project created! Run it with:

cd ${args.name}
pnpm install
pnpm dev

Have fun! For more info, check the docs at https://mud.dev/
`);
});
}

run();
29 changes: 0 additions & 29 deletions packages/create-mud/src/cli.ts

This file was deleted.

14 changes: 14 additions & 0 deletions packages/create-mud/src/common.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { describe, expect, it } from "vitest";
import { glob } from "glob";
import { templates } from "./common";

describe("templates", () => {
it("matches what is in the file system", async () => {
const availableTemplates = await glob("*", {
maxDepth: 1,
cwd: `${__dirname}/../templates`,
});
expect(templates).toEqual(expect.arrayContaining(availableTemplates));
expect(availableTemplates).toEqual(expect.arrayContaining(templates));
});
});
3 changes: 3 additions & 0 deletions packages/create-mud/src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// We define these here to keep them in the order we want to present in the CLI.
// Tests will ensure this list stays up to date.
export const templates = ["react", "react-ecs", "phaser", "threejs", "vanilla"];
10 changes: 10 additions & 0 deletions packages/create-mud/src/exists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import fs from "node:fs/promises";

export async function exists(path: string) {
try {
await fs.access(path);
return true;
} catch {
return false;
}
}
4 changes: 3 additions & 1 deletion packages/create-mud/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { defineConfig } from "tsup";

export default defineConfig((opts) => ({
entry: ["src/cli.ts"],
entry: ["src/bin/cli.ts"],
target: "esnext",
format: ["esm"],
minify: true,
sourcemap: true,
// don't generate DTS during watch mode because it's slow
Expand Down
Loading
Loading