Skip to content

Commit

Permalink
chore(boxes): adding an init command for an empty project (#7398)
Browse files Browse the repository at this point in the history
Quick PR to add a `npx aztec-app init` command that provides a `nargo
new`-like feature. This will be used in tutorials and specially in the
EthCC workshop.

---------

Co-authored-by: josh crites <[email protected]>
  • Loading branch information
signorecello and critesjosh authored Jul 10, 2024
1 parent 59b92ca commit a6a605d
Show file tree
Hide file tree
Showing 16 changed files with 269 additions and 229 deletions.
18 changes: 18 additions & 0 deletions .devcontainer/sandbox_only/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Sandbox Only",
"image": "node:lts-bookworm",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"onCreateCommand": "cp -R /root/workspace /root/scripts && rm -rf /root/workspace/* && sh /root/scripts/onCreateCommand.sh sandbox_only",
"postAttachCommand": "sh /root/scripts/postAttachCommand.sh",
"customizations": {
"vscode": {
"settings": {},
"extensions": ["noir-lang.vscode-noir"]
}
},
"workspaceMount": "source=${localWorkspaceFolder}/.devcontainer/scripts,target=/root/workspace,type=bind",
"workspaceFolder": "/root/workspace",
"forwardPorts": [8080]
}
21 changes: 12 additions & 9 deletions .devcontainer/scripts/onCreateCommand.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ fi
if ! grep -q "alias sandbox" ~/.bashrc; then
echo "alias sandbox=\"npx aztec-app sandbox\"" >> ~/.bashrc
fi
corepack enable

source ~/.bashrc
yes | npx aztec-app -t $TYPE -n $NAME -s
mv $NAME/* $NAME/.* .
rm -rf $NAME
if [ "$TYPE" != "sandbox_only" ]; then
source ~/.bashrc
yes | npx create-aztec-app -t $TYPE -n $NAME -s
mv $NAME/* $NAME/.* .
rm -rf $NAME

yarn

yarn

npx -y playwright install --with-deps
yarn add @aztec/builder
yarn prep
npx -y playwright install --with-deps
yarn add @aztec/builder
yarn prep
fi
3 changes: 1 addition & 2 deletions .devcontainer/scripts/postAttachCommand.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env bash
TYPE=$1
NAME=$2

apt update
apt install gh
gh codespace ports visibility 8080:public -c $CODESPACE_NAME

Expand Down
22 changes: 21 additions & 1 deletion boxes/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
# Aztec Boxes
# Aztec-App

Aztec-App is a set of tools to ease development on Aztec. It consists of two main components:
1. `npx` script
2. boxes (starter kits)
## npx script

NPX is a tool bundled with `npm` and other package managers. It allows you to run a binary from a cache without installing it globally.

To ease the development process, Aztec has developed this binary. To run it, install Node and run:

```bash
npx aztec-app
```

This will prompt you with some options to clone `Aztec Boxes` and install the sandbox. As the `npx` script evolves, other commands will be added or removed. You can run it with the `-h` flag to know what other commands and flags you can pass to it.

> [!NOTE]
> As a tool that doesn't (yet) have automated testing, it versioning and release process is decoupled from `aztec`, and its deployment is entirely manual by running `yarn npm publish --access public`.
## Aztec Boxes

Aztec Boxes are the one-stop-shop for developing on Aztec. They often include a combination of:

Expand Down
169 changes: 81 additions & 88 deletions boxes/bin.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
#!/usr/bin/env node
import { Command, Option } from "commander";
import { Command } from "commander";
const program = new Command();
import { chooseProject } from "./scripts/steps/chooseBox.js";
import {
install,
update,
sandboxInstallOrUpdate,
} from "./scripts/steps/sandbox/install.js";
import { sandboxInstallOrUpdate } from "./scripts/steps/sandbox/install.js";
import axios from "axios";
import pino from "pino";
import pretty from "pino-pretty";
import ora from "ora";
import { AZTEC_REPO } from "./scripts/config.js";
import {
start,
stop,
log,
sandboxRunStep,
} from "./scripts/steps/sandbox/run.js";
import { sandboxRunStep } from "./scripts/steps/sandbox/run.js";
import { init } from "./scripts/init.js";

const getLatestStable = async () => {
const { data } = await axios.get(
Expand All @@ -26,86 +18,88 @@ const getLatestStable = async () => {
return data[0].tag_name.split("-v")[1];
};

const init = async ({ debug, github_token, version }) => {
const axiosOpts = {
timeout: 5000,
headers: github_token ? { Authorization: `token ${github_token}` } : {},
};

const prettyOpts = {
sync: true,
colorize: true,
include: debug ? "time" : "",
customLevels: "success:80",
customColors: "success:bgGreen",
};

const prettyStream = pretty(prettyOpts);
const logger = pino(
{
customLevels: {
success: 80,
program
.option("-v, --version <version>", "a version number or master tag")
.option("-d, --debug", "output extra debugging")
.option("-gh, --github_token <github_token>", "a github token")
.hook("preSubcommand", async (thisCommand) => {
const { debug, github_token, version } = thisCommand.opts();
const axiosOpts = {
timeout: 5000,
headers: github_token ? { Authorization: `token ${github_token}` } : {},
};

const prettyOpts = {
sync: true,
colorize: true,
include: debug ? "time" : "",
customLevels: "success:80",
customColors: "success:bgGreen",
};

const prettyStream = pretty(prettyOpts);
const logger = pino(
{
customLevels: {
success: 80,
},
level: debug ? "debug" : "info",
},
level: debug ? "debug" : "info",
},
prettyStream,
);

global.debug = (msg) => logger.debug(msg);
global.info = (msg) => logger.info(msg);
global.success = (msg) => logger.success(msg);

global.warn = (msg) => logger.warn(msg);
global.error = (msg) => logger.error(msg);

global.github = async ({ path, raw = false }) => {
try {
const url = raw
? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}`
: `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`;
const { data } = await axios.get(url, axiosOpts);
global.debug(data);
return data;
} catch (e) {
global.error(e);
}
};

// versioning is confusing here because "latest" and "master" point to the same thing at times
// so let's clarify a bit:
//
// if the user has set a version (ex. "master" or "0.23.0"), use that
// otherwise use the stable release (ex. 0.24.0)
global.latestStable = await getLatestStable();
global.version = version || global.latestStable;

// if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0)
// otherwise use the version as the tag
global.tag = global.version.match(/^\d+\.\d+\.\d+$/)
? `aztec-packages-v${global.version}`
: global.version;

global.debug(`Version: ${global.version}`);
global.debug(`Tag: ${global.tag}`);
global.debug(`LatestStable: ${global.latestStable}`);

global.spinner = ora({ color: "blue" });
};
prettyStream,
);

global.debug = (msg) => logger.debug(msg);
global.info = (msg) => logger.info(msg);
global.success = (msg) => logger.success(msg);

global.warn = (msg) => logger.warn(msg);
global.error = (msg) => logger.error(msg);

global.github = async ({ path, raw = false }) => {
try {
const url = raw
? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}`
: `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`;
const { data } = await axios.get(url, axiosOpts);
global.debug(data);
return data;
} catch (e) {
global.error(e);
}
};

// versioning is confusing here because "latest" and "master" point to the same thing at times
// so let's clarify a bit:
//
// if the user has set a version (ex. "master" or "0.23.0"), use that
// otherwise use the stable release (ex. 0.24.0)
global.latestStable = await getLatestStable();
global.version = version || global.latestStable;

// if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0)
// otherwise use the version as the tag
global.tag = global.version.match(/^\d+\.\d+\.\d+$/)
? `aztec-packages-v${global.version}`
: global.version;

global.debug(`Version: ${global.version}`);
global.debug(`Tag: ${global.tag}`);
global.debug(`LatestStable: ${global.latestStable}`);

global.spinner = ora({ color: "blue" });
});

const sandbox = program.command("sandbox");
sandbox.description("Manage the Aztec Sandbox");
sandbox.command("start").action(start);
sandbox.command("logs").action(log);
sandbox.command("stop").action(stop);
sandbox.command("install").action(install);
sandbox.command("update").action(update);
program
.command("init")
.description("Bootstrap an empty Aztec contract")
.argument("[folder]", "optional folder to init your project into", ".")
.action(async (folder) => {
await init(folder);
});

program
.command("new", { isDefault: true })
.description("An Aztec project with a built-in development network")
.option("-d, --debug", "output extra debugging")
.option("-gh, --github_token <github_token>", "a github token")
.option("-v, --version <version>", "a version number or master tag")
.option(
"-s, --skip-sandbox",
"skip sandbox installation and run after cloning",
Expand All @@ -128,8 +122,7 @@ program
}

const { projectType, projectName, skipSandbox } = options;
// SETUP: Initialize global variables
await init(options);

// // STEP 1: Choose the boilerplate
await chooseProject({ projectType, projectName });

Expand Down
1 change: 1 addition & 0 deletions boxes/init/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
6 changes: 6 additions & 0 deletions boxes/init/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "init"
type = "contract"

[dependencies]
aztec = { path = "../../noir-projects/aztec-nr/aztec" }
9 changes: 9 additions & 0 deletions boxes/init/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"packageManager": "[email protected]",
"type": "module",
"dependencies": {
"@aztec/accounts": "latest",
"@aztec/aztec.js": "latest",
"@aztec/builder": "latest"
}
}
6 changes: 6 additions & 0 deletions boxes/init/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

contract Main {
#[aztec(private)]
#[aztec(initializer)]
fn constructor() { }
}
4 changes: 2 additions & 2 deletions boxes/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "create-aztec-app",
"name": "aztec-app",
"packageManager": "[email protected]",
"version": "0.4.4",
"version": "0.4.9",
"type": "module",
"scripts": {
"compile": "yarn workspaces foreach -A -v run compile",
Expand Down
19 changes: 19 additions & 0 deletions boxes/scripts/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { replacePaths } from "./utils.js";
import { AZTEC_REPO } from "./config.js";
import tiged from "tiged";

export async function init(folder) {
const emitter = tiged(`${AZTEC_REPO}/boxes/init${tag && `#${tag}`}`, {
verbose: true,
});
emitter.on("info", ({ message }) => debug(message));
emitter.on("warn", ({ message }) => error(message));
await emitter.clone(`${folder}`);

await replacePaths({
rootDir: `${folder}`,
tag,
version,
prefix: "",
});
}
13 changes: 1 addition & 12 deletions boxes/scripts/steps/sandbox/run.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
import confirm from "@inquirer/confirm";
import { execSync } from "child_process";
import axios from "axios";

const sandbox = (command) =>
execSync(
`docker compose -f $HOME/.aztec/docker-compose.yml -p sandbox ${command}`,
{ stdio: "inherit" }
);

export const start = () => sandbox("up -d");
export const stop = () => sandbox("down");
export const log = () => sandbox("logs -f");

export async function sandboxRunStep() {
spinner.text = "Trying to reach the sandbox...";

Expand All @@ -29,7 +18,7 @@ export async function sandboxRunStep() {
Accept: "*/*",
"Content-Type": "application/json",
},
}
},
);
spinner.succeed();
success("The Sandbox is already running!");
Expand Down
3 changes: 2 additions & 1 deletion boxes/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export async function replacePaths({ rootDir, prefix = "" }) {
replaces.push(
new Promise(async (resolve, reject) => {
let content = parse(await fs.readFile(filePath, "utf8"));

if (!content.dependencies) return;
Object.keys(content.dependencies).forEach((dep) => {
const directory = content.dependencies[dep].path.replace(
/^(..\/)+/,
Expand All @@ -224,6 +224,7 @@ export async function replacePaths({ rootDir, prefix = "" }) {
replaces.push(
new Promise(async (resolve, reject) => {
let content = JSON.parse(await fs.readFile(filePath, "utf8"));
if (!content.dependencies) return;
Object.keys(content.dependencies)
.filter((deps) => deps.match("@aztec"))
// "master" actually means "latest" for the npm release
Expand Down
Loading

0 comments on commit a6a605d

Please sign in to comment.