Skip to content
Open
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
2 changes: 2 additions & 0 deletions packages/cli/src/commands/explorer/explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export const explorerCommand: CommandModule = {
describe: "Explorer commands",
builder: async (yargs) => {
const { explorerStartCommand } = await import("./explorerStart");
const { explorerStopCommand } = await import("./explorerStop");

return yargs
.command(explorerStartCommand)
.command(explorerStopCommand)
.demandCommand(
1,
"You must specify a subcommand. Use --help to see available options."
Expand Down
17 changes: 17 additions & 0 deletions packages/cli/src/commands/explorer/explorerStop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CommandModule } from "yargs";

export const explorerStopCommand: CommandModule = {
command: "stop",
describe: "Stop the explorer UI",
handler: async () => {
try {
const { default: explorerStop } =
await import("../../scripts/explorer/stop");
await explorerStop();
process.exit(0);
} catch (error) {
console.error("Failed to stop explorer:", error);
process.exit(1);
}
},
};
24 changes: 24 additions & 0 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { CommandModule } from "yargs";

import type { InitArgs } from "../scripts/init";

export const initCommand: CommandModule<{}, InitArgs> = {
command: "init [name]",
describe: "Create a new Protokit project from the starter-kit template",
builder: (yarg) =>
yarg.positional("name", {
type: "string",
default: "starter-kit",
describe: "Directory name for the new project",
}),
handler: async (args) => {
try {
const { default: init } = await import("../scripts/init");
await init({ name: args.name });
process.exit(0);
} catch (error) {
console.error("Failed to initialize project:", error);
process.exit(1);
}
},
};
2 changes: 2 additions & 0 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { wizardCommand } from "./commands/wizard";
import { settlementCommand } from "./commands/settlement/settlement";
import { lightnetCommand } from "./commands/lightnet/lightnet";
import { bridgeCommand } from "./commands/bridge/bridge";
import { initCommand } from "./commands/init";

process.removeAllListeners("warning");
process.env.NODE_NO_WARNINGS = "1";
Expand All @@ -25,6 +26,7 @@ await yargs(hideBin(process.argv))
.command(settlementCommand)
.command(lightnetCommand)
.command(bridgeCommand)
.command(initCommand)
.demandCommand(
1,
"You must specify a command. Use --help to see available commands."
Expand Down
10 changes: 9 additions & 1 deletion packages/cli/src/scripts/explorer/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ async function runDockerContainer(args: {
const { port = 5003, explorerImage } = args;
console.log(`\nExplorer is running at http://localhost:${port}\n`);

const dockerArgs = ["run", "--rm", "-p", `${port}:3000`];
const dockerArgs = [
"run",
"-d",
"--rm",
"--name",
"protokit-explorer",
"-p",
`${port}:3000`,
];

if (args.indexerUrl !== undefined) {
dockerArgs.push("-e", `NEXT_PUBLIC_INDEXER_URL=${args.indexerUrl}`);
Expand Down
37 changes: 37 additions & 0 deletions packages/cli/src/scripts/explorer/stop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { spawn } from "child_process";

const CONTAINER_NAME = "protokit-explorer";

async function stopDockerContainer(): Promise<void> {
return await new Promise<void>((resolve, reject) => {
console.log("Stopping explorer container...");
const child = spawn("docker", ["stop", CONTAINER_NAME], {
stdio: "inherit",
});

child.on("error", (error) => {
console.error("Failed to stop explorer container:", error);
reject(error);
});

child.on("exit", (code) => {
if (code !== null && code !== 0) {
reject(
new Error(`Failed to stop explorer container (exit code ${code})`)
);
} else {
console.log("Explorer container stopped successfully");
resolve();
}
});
});
}

export default async function (): Promise<void> {
try {
await stopDockerContainer();
} catch (error) {
console.error("Failed to stop explorer:", error);
throw error;
}
}
42 changes: 42 additions & 0 deletions packages/cli/src/scripts/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { spawn } from "child_process";

const STARTER_KIT_REPO = "https://github.com/proto-kit/starter-kit.git";

export interface InitArgs {
name?: string;
}

export default async function (args: InitArgs): Promise<void> {
const targetDir = args.name ?? "starter-kit";

console.log(`\nCloning starter-kit into ./${targetDir}...\n`);

return await new Promise<void>((resolve, reject) => {
const child = spawn("git", ["clone", STARTER_KIT_REPO, targetDir], {
stdio: "inherit",
});

child.on("error", (error) => {
console.error("Failed to clone starter-kit:", error);
reject(error);
});

child.on("exit", (code) => {
if (code !== null && code !== 0) {
reject(new Error(`git clone failed with exit code ${code}`));
} else {
console.log(`\nProject created at ./${targetDir}`);
console.log("\nNext steps:");
console.log(` cd ${targetDir}`);
console.log(" pnpm install");
console.log(" pnpm env:development prisma:generate");
console.log(" pnpm env:inmemory dev");
console.log(" ✨ You're all set. Enjoy coding! ✨");
console.log(
"\nFor more details, see the README.md in the project directory.\n"
);
resolve();
}
});
});
}
Loading