From b9929d8c87118d4caabba7c4aeb820312e576584 Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Fri, 29 May 2026 16:08:15 +0100 Subject: [PATCH] feat: rename CLI command from dot to playground (with pg alias) Rename the CLI command from `dot` to `playground`, with `pg` as a short alias. Both names invoke the same binary, so `playground init` and `pg init` (and every other subcommand) are interchangeable. - install.sh saves the (still `dot-*`) release asset locally as `playground`, symlinks `pg` into both PATH bin dirs, removes any legacy `dot` install, and prints a yellow rounded-border box telling the user to run `playground init` or `pg init`. - update.ts self-update and e2e-post-release.yml agree on the `playground` installed filename; detectAsset() still resolves the `dot-*` download asset. - Sweep all user-facing runtime strings (errors, --help descriptions, TUI header breadcrumbs, terminal window titles, version-update banner) from `dot` to `playground`, with unit/e2e assertions and the telemetry expected-error regex updated in lockstep. - The old `dot` command is no longer installed. --- .changeset/rename-cli-to-playground.md | 5 ++ .github/workflows/e2e-post-release.yml | 8 ++-- README.md | 42 ++++++++-------- docs/e2e-running-tests.md | 2 +- e2e/cli/install.test.ts | 6 +-- install.sh | 48 ++++++++++++++----- package.json | 7 +-- src/commands/contract.ts | 2 +- src/commands/contractDeployUi.tsx | 2 +- src/commands/contractInstallUi.tsx | 2 +- .../decentralize/DecentralizeScreen.tsx | 10 ++-- src/commands/decentralize/index.ts | 6 +-- src/commands/deploy/DeployScreen.tsx | 16 +++---- src/commands/deploy/index.ts | 6 +-- src/commands/init/AccountSetup.tsx | 4 +- src/commands/init/InitScreen.tsx | 2 +- src/commands/init/UsernamePrompt.tsx | 2 +- src/commands/logout/LogoutScreen.tsx | 2 +- src/commands/logout/index.ts | 2 +- src/commands/mod/SetupScreen.tsx | 4 +- src/commands/mod/index.ts | 2 +- src/commands/update.ts | 6 +-- src/index.ts | 2 +- src/telemetry.test.ts | 6 +-- src/telemetry.ts | 9 +++- src/utils/allowances/bulletin.test.ts | 2 +- src/utils/allowances/bulletin.ts | 8 ++-- src/utils/allowances/smartContracts.ts | 4 +- src/utils/deploy/signerMode.test.ts | 2 +- src/utils/deploy/signerMode.ts | 2 +- src/utils/sessionSigner.test.ts | 4 +- src/utils/sessionSigner.ts | 2 +- src/utils/signer.test.ts | 2 +- src/utils/signer.ts | 4 +- src/utils/version-check.test.ts | 6 +-- src/utils/version-check.ts | 2 +- 36 files changed, 139 insertions(+), 102 deletions(-) create mode 100644 .changeset/rename-cli-to-playground.md diff --git a/.changeset/rename-cli-to-playground.md b/.changeset/rename-cli-to-playground.md new file mode 100644 index 0000000..5bdc05d --- /dev/null +++ b/.changeset/rename-cli-to-playground.md @@ -0,0 +1,5 @@ +--- +"playground-cli": minor +--- + +Rename the CLI command from `dot` to `playground`, with `pg` as a short alias. Both `playground` and `pg` invoke the same binary, so `playground init` and `pg init` (and every other subcommand) are interchangeable. The curl installer now symlinks both names onto your PATH and prints a yellow "next step" box showing that either command works. Release artifacts are still published as `dot--`; only the installed command names changed. The old `dot` command is no longer installed. diff --git a/.github/workflows/e2e-post-release.yml b/.github/workflows/e2e-post-release.yml index 303a4db..63524d2 100644 --- a/.github/workflows/e2e-post-release.yml +++ b/.github/workflows/e2e-post-release.yml @@ -66,19 +66,19 @@ jobs: TAG="${{ steps.tag.outputs.tag }}" # Pin to the just-released version; install.sh resolves "latest" # by default which can lag behind a just-published release. - # install.sh runs `dot init` at the end; init requires an - # interactive QR scan and will exit non-zero in headless CI — + # install.sh runs `playground init` at the end; init requires + # an interactive QR scan and will exit non-zero in headless CI — # that is expected. The binary is installed before init runs, # so we tolerate the init failure and verify the binary below. curl -fsSL "https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/install.sh" \ | VERSION="$TAG" bash || true # Hard-fail here if the binary was not installed — that IS a # real regression in the install script's download/chmod path. - ls -la "$HOME/.polkadot/bin/dot" + ls -la "$HOME/.polkadot/bin/playground" - name: Compute installed-binary path shell: bash - run: echo "DOT_E2E_BINARY=$HOME/.polkadot/bin/dot" >> "$GITHUB_ENV" + run: echo "DOT_E2E_BINARY=$HOME/.polkadot/bin/playground" >> "$GITHUB_ENV" - name: Smoke test the installed binary uses: nick-fields/retry@v3 diff --git a/README.md b/README.md index 6c0330d..2e19e3d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # playground-cli -CLI tooling for Polkadot Playground. Installed as the `dot` command. +CLI tooling for Polkadot Playground. Installed as the `playground` command, with `pg` as a short alias — both invoke the same binary, so `playground init` and `pg init` are interchangeable. ## Quick Start @@ -14,11 +14,11 @@ To install a specific version: curl -fsSL https://raw.githubusercontent.com/paritytech/playground-cli/main/install.sh | VERSION=v0.2.0 bash ``` -The installer drops the binary into `~/.polkadot/bin/`, symlinks it at `~/.local/bin/dot`, appends the path to your shell rc, and then runs `dot init` so you can finish setup without a second command. +The installer drops the binary into `~/.polkadot/bin/playground`, symlinks both `playground` and the short `pg` alias into `~/.local/bin/`, appends the path to your shell rc, and then runs `playground init` so you can finish setup without a second command. ## Commands -### `dot init` +### `playground init` End-to-end first-run setup. Login and toolchain install run **concurrently**; account setup runs **once both have completed successfully**. @@ -33,11 +33,11 @@ Flags: - `-y, --yes` — skip the QR login entirely. Dependencies still install, account setup is skipped (no session). -### `dot update` +### `playground update` Self-update from the latest GitHub release. Detects your OS/arch, downloads the corresponding `dot--` asset, verifies HOME is set, and atomically replaces the running binary (write-to-staging-then-rename so the running process is never served a half-written file). -### `dot build` +### `playground build` Auto-detects the project's package manager (pnpm / yarn / bun / npm from the lockfile) and runs the `build` npm script. If no `build` script is defined, falls back to a framework invocation (`vite build`, `next build`, `tsc`) based on what's installed. @@ -45,7 +45,7 @@ Flags: - `--dir ` — project directory (defaults to the current working directory). -### `dot deploy` +### `playground deploy` Builds the project, uploads the output to Bulletin, registers a `.dot` domain via DotNS, and optionally publishes the app to the Playground registry (so it shows up in the user's "my apps" list). @@ -57,13 +57,13 @@ Flags: - `--no-build` — skip the frontend build step and deploy whatever is already in `--buildDir`. - `--playground` — publish to the playground registry so the app appears under "my apps". Interactive prompt (default: no) if omitted. - `--private` — publish to the playground with private (owner-only) visibility. Requires `--playground`. Not interactively prompted; pass the flag to opt in. -- `--moddable` / `--no-moddable` — publish the source repo URL alongside the deploy so others can `dot mod` it. Requires `--playground`. Interactive prompt (default: no) if omitted. The CLI reads your existing `origin` and records its URL in the Bulletin metadata; it never creates a repo or pushes for you. The deploy fails with an actionable message if `origin` is unset, points to a private repo, or points to anything other than GitHub (since `dot mod` only fetches from `codeload.github.com`). Set up the repo yourself before re-running: create a public repo on GitHub, then `git remote add origin https://github.com//` followed by `git push -u origin main`. (If you happen to have `gh` installed, `gh repo create my-app --public --source=. --push` does both in one shot — `dot` does not require `gh`.) +- `--moddable` / `--no-moddable` — publish the source repo URL alongside the deploy so others can `playground mod` it. Requires `--playground`. Interactive prompt (default: no) if omitted. The CLI reads your existing `origin` and records its URL in the Bulletin metadata; it never creates a repo or pushes for you. The deploy fails with an actionable message if `origin` is unset, points to a private repo, or points to anything other than GitHub (since `playground mod` only fetches from `codeload.github.com`). Set up the repo yourself before re-running: create a public repo on GitHub, then `git remote add origin https://github.com//` followed by `git push -u origin main`. (If you happen to have `gh` installed, `gh repo create my-app --public --source=. --push` does both in one shot — `playground` does not require `gh`.) - `--suri ` — override signer with a dev secret URI (e.g. `//Alice`). Useful for CI. - `--env ` — target environment. Defaults to `paseo-next-v2` (the only one fully wired today). Accepts the bulletin-deploy env IDs (`preview`, `paseo-next`, `paseo-review`, `paseo-next-v2`, `polkadot`, `kusama`) plus the legacy `testnet`/`mainnet` aliases — `testnet` maps to `paseo-next-v2`, `mainnet` to `polkadot`. Any env other than `paseo-next-v2` throws "not supported" until its entry is wired up in `src/config.ts::CONFIGS`. Passing all four of `--signer`, `--domain`, `--buildDir`, and `--playground` runs in fully non-interactive mode. Any absent flag is filled in by the TUI prompt. `--moddable` and `--private` are independently optional in both modes — their absence means a non-moddable, public deploy. -**Requirement**: the `ipfs` CLI (Kubo) must be on `PATH`. `dot init` installs it; if you skipped init you can install it manually (`brew install ipfs` or follow [docs.ipfs.tech/install](https://docs.ipfs.tech/install/)). This is a temporary requirement while `bulletin-deploy`'s pure-JS merkleizer has a bug that makes the browser fallback unusable. +**Requirement**: the `ipfs` CLI (Kubo) must be on `PATH`. `playground init` installs it; if you skipped init you can install it manually (`brew install ipfs` or follow [docs.ipfs.tech/install](https://docs.ipfs.tech/install/)). This is a temporary requirement while `bulletin-deploy`'s pure-JS merkleizer has a bug that makes the browser fallback unusable. The publish step is always signed by the user so the registry contract records their address as the app owner — this is what drives the Playground "my apps" view. @@ -76,16 +76,16 @@ For fully non-interactive (CI) runs, combine `--signer`, `--domain`, `--buildDir - `--no-moddable` — explicitly skip source publishing even if `--moddable` would otherwise apply. - `--private` — publish to the playground with owner-only visibility. -### `dot contract` +### `playground contract` CDM-backed workflows for contracts: -- `dot contract deploy` builds, deploys, and registers CDM contracts with dot's logged-in signer by default. Pass `--suri //Alice` for local/dev signing. -- `dot contract deploy --features ` forwards Cargo feature flags into CDM's build pipeline. -- `dot contract deploy --registry-address
` targets a specific CDM registry. -- `dot contract install [libraries...]` uses the CDM install backend with dot's native TUI, then writes `cdm.json` and CDM post-install outputs. +- `playground contract deploy` builds, deploys, and registers CDM contracts with playground's logged-in signer by default. Pass `--suri //Alice` for local/dev signing. +- `playground contract deploy --features ` forwards Cargo feature flags into CDM's build pipeline. +- `playground contract deploy --registry-address
` targets a specific CDM registry. +- `playground contract install [libraries...]` uses the CDM install backend with playground's native TUI, then writes `cdm.json` and CDM post-install outputs. -### `dot mod` +### `playground mod` Pull a moddable playground app's source into a fresh local project so you can customise and re-deploy it. The interactive picker only shows apps that opted into moddable at deploy time; non-moddable apps surface a clear "this app is not moddable" error if you target them by domain. @@ -98,9 +98,9 @@ Flags: The local directory name is auto-generated as `-<6 hex chars>` so repeated mods of the same starter never collide (unlike GitHub forks, which were limited to one per account per repo). -### `dot logout` +### `playground logout` -Sign out of the account paired via `dot init`. Sends a `Disconnected` statement so the paired Polkadot mobile app drops its side of the connection, then clears the local session files under `~/.polkadot-apps/`. If the remote notification fails (statement store unreachable, …), the local files are still cleared and the command surfaces a `partial` status — the mobile app will show a stale pairing until it reconnects. No-op when no session is signed in. +Sign out of the account paired via `playground init`. Sends a `Disconnected` statement so the paired Polkadot mobile app drops its side of the connection, then clears the local session files under `~/.polkadot-apps/`. If the remote notification fails (statement store unreachable, …), the local files are still cleared and the command surfaces a `partial` status — the mobile app will show a stale pairing until it reconnects. No-op when no session is signed in. ## Troubleshooting @@ -117,10 +117,10 @@ Telemetry scrubs local home-directory paths and avoids sending raw command argum ### Reporting a memory issue -If `dot deploy` gets killed with `✖ Memory use exceeded 4 GB` (the watchdog's abort) or you see RSS climb unexpectedly, re-run with both of: +If `playground deploy` gets killed with `✖ Memory use exceeded 4 GB` (the watchdog's abort) or you see RSS climb unexpectedly, re-run with both of: ```bash -DOT_MEMORY_TRACE=1 DOT_DEPLOY_VERBOSE=1 dot deploy ... +DOT_MEMORY_TRACE=1 DOT_DEPLOY_VERBOSE=1 playground deploy ... ``` - `DOT_MEMORY_TRACE=1` streams a per-second `rss / heap / external / peak` sample to stderr from the watchdog worker. The worker has its own event loop, so samples keep firing even while the main thread is busy — perfect for capturing the timeline of a leak. @@ -139,7 +139,7 @@ pnpm build ### Local Install -Compile and install the `dot` binary to `~/.polkadot/bin/`: +Compile and install the `playground` binary (plus the `pg` alias) to `~/.polkadot/bin/`: ```bash pnpm cli:install @@ -152,7 +152,7 @@ pnpm test # unit tests, one-shot pnpm test:watch # rerun on change npx tsc --noEmit # type check -pnpm test:e2e # E2E tests (slow; run `dot init` first) +pnpm test:e2e # E2E tests (slow; run `playground init` first) ``` #### Unit tests @@ -163,7 +163,7 @@ Live alongside the code as `*.test.ts`. They avoid mocking so deeply that they j Live under `e2e/cli/*.test.ts`, with a separate `e2e/vitest.config.ts`. Each test spawns the CLI via `bun run src/index.ts` (execa wrapper in `e2e/cli/helpers/dot.ts`) and asserts on stdout/stderr/exit code. Files run serially — they share a single deployer account on Paseo and would race otherwise. -Prerequisite: run `dot init` once to install the required local deps (mainly Kubo IPFS for the deploy pipeline). Tests also reach Paseo Asset Hub and `codeload.github.com` over the internet, so they need network. +Prerequisite: run `playground init` once to install the required local deps (mainly Kubo IPFS for the deploy pipeline). Tests also reach Paseo Asset Hub and `codeload.github.com` over the internet, so they need network. CI runs the suite on every PR, on push to `main`, and daily at 06:00 UTC (`.github/workflows/e2e.yml`). diff --git a/docs/e2e-running-tests.md b/docs/e2e-running-tests.md index a3bf5f0..6c45c03 100644 --- a/docs/e2e-running-tests.md +++ b/docs/e2e-running-tests.md @@ -178,7 +178,7 @@ a stable release is cut. Tag: `e2e-ci-release`. **e2e-post-release.yml** (`release: published`, stable only — `prerelease != true`, or `workflow_dispatch`): Runs `install.sh` using the pinned tag (`VERSION= curl … | bash`), verifies -the binary lands at `~/.polkadot/bin/dot`, then runs `published.test.ts` against +the binary lands at `~/.polkadot/bin/playground`, then runs `published.test.ts` against the installed binary. Catches `install.sh` regressions that the SEA-download path doesn't exercise. Tag: `e2e-ci-post-release`. diff --git a/e2e/cli/install.test.ts b/e2e/cli/install.test.ts index 205398e..8e718bc 100644 --- a/e2e/cli/install.test.ts +++ b/e2e/cli/install.test.ts @@ -38,13 +38,13 @@ describe("dot install", () => { test("dot update reports a meaningful outcome", async () => { const result = await dot(["update"]); expect(result.exitCode).toBe(0); - // Without this, a regression where `dot update` silently no-ops is + // Without this, a regression where `playground update` silently no-ops is // invisible. Match either exact wording from src/commands/update.ts: // "already on latest (vX.Y.Z)" — when current === latest tag - // "Updated dot to vX.Y.Z" — when an update happened + // "Updated playground to vX.Y.Z" — when an update happened // Both branches print "Checking for updates..." first, so anchor on // the outcome line. - expect(result.stdout).toMatch(/already on latest \(v|Updated dot to v/); + expect(result.stdout).toMatch(/already on latest \(v|Updated playground to v/); // Verify the binary still works after the update reported success. const version = await dot(["--version"]); expect(version.exitCode).toBe(0); diff --git a/install.sh b/install.sh index c29862b..e553208 100755 --- a/install.sh +++ b/install.sh @@ -3,12 +3,18 @@ set -e INSTALL_DIR="$HOME/.polkadot" REPO="paritytech/playground-cli" -BIN="dot" +# The command users invoke, plus a short alias. Both resolve to the same binary. +CMD="playground" +ALIAS="pg" +# Release artifacts are still published as `dot--` — keep the asset +# prefix in sync with .github/workflows/release.yml. The downloaded file is +# saved locally under $CMD, so the old `dot` command name is gone. +ASSET_PREFIX="dot" # 1) Detect platform OS=$(uname -s); case "$OS" in Linux) OS=linux;; Darwin) OS=darwin;; *) echo "Unsupported OS: $OS"; exit 1;; esac ARCH=$(uname -m); case "$ARCH" in x86_64|amd64) ARCH=x64;; arm64|aarch64) ARCH=arm64;; *) echo "Unsupported arch: $ARCH"; exit 1;; esac -ASSET="$BIN-$OS-$ARCH" +ASSET="$ASSET_PREFIX-$OS-$ARCH" # 2) Resolve release tag # @@ -33,21 +39,27 @@ fi # 3) Install binary spin() { while true; do for c in '|' '/' '-' '\'; do printf "\r%s %s" "$1" "$c"; sleep 0.1; done; done; } -spin "Installing dot ($OS/$ARCH) $TAG" & +spin "Installing $CMD ($OS/$ARCH) $TAG" & SPIN_PID=$! trap "kill $SPIN_PID 2>/dev/null" EXIT mkdir -p "$INSTALL_DIR/bin" "$HOME/.local/bin" -curl -fsSL "https://github.com/$REPO/releases/download/$TAG/$ASSET" -o "$INSTALL_DIR/bin/$BIN" -chmod +x "$INSTALL_DIR/bin/$BIN" +curl -fsSL "https://github.com/$REPO/releases/download/$TAG/$ASSET" -o "$INSTALL_DIR/bin/$CMD" +chmod +x "$INSTALL_DIR/bin/$CMD" if [ "$OS" = "darwin" ]; then - codesign --sign - --force "$INSTALL_DIR/bin/$BIN" 2>/dev/null || true - xattr -c "$INSTALL_DIR/bin/$BIN" 2>/dev/null || true + codesign --sign - --force "$INSTALL_DIR/bin/$CMD" 2>/dev/null || true + xattr -c "$INSTALL_DIR/bin/$CMD" 2>/dev/null || true fi -ln -sf "$INSTALL_DIR/bin/$BIN" "$HOME/.local/bin/$BIN" +# Expose both the full command and its short alias from both bin dirs on PATH. +ln -sf "$INSTALL_DIR/bin/$CMD" "$INSTALL_DIR/bin/$ALIAS" +ln -sf "$INSTALL_DIR/bin/$CMD" "$HOME/.local/bin/$CMD" +ln -sf "$INSTALL_DIR/bin/$CMD" "$HOME/.local/bin/$ALIAS" +# Remove the legacy `dot` binary/symlink from earlier installs so it stops +# resolving on PATH — the command is now `playground` (or `pg`). +rm -f "$INSTALL_DIR/bin/dot" "$HOME/.local/bin/dot" kill $SPIN_PID 2>/dev/null; wait $SPIN_PID 2>/dev/null || true; trap - EXIT -printf "\rInstalled dot (%s/%s) %s \n" "$OS" "$ARCH" "$TAG" +printf "\rInstalled %s (%s/%s) %s \n" "$CMD" "$OS" "$ARCH" "$TAG" # 4) Add to PATH append_once() { @@ -69,12 +81,22 @@ fi export PATH="$INSTALL_DIR/bin:$HOME/.local/bin:$PATH" echo "" -echo -e "dot is ready! Setting up dependencies…" +echo -e "$CMD is ready! Setting up dependencies…" echo "" -if ! "$INSTALL_DIR/bin/$BIN" init --yes; then +if ! "$INSTALL_DIR/bin/$CMD" init --yes; then INIT_EXIT=$? - echo -e "\n\033[33mDependency setup failed. Run \033[1mdot init\033[0;33m when ready.\033[0m" >&2 + echo -e "\n\033[33mDependency setup failed. Run \033[1m$CMD init\033[0;33m (or \033[1m$ALIAS init\033[0;33m) when ready.\033[0m" >&2 exit "$INIT_EXIT" fi + +# Final "what to run next" prompt, styled to match the yellow rounded-border +# Callout the TUI uses for phone-signing notifications (see +# src/utils/ui/theme/Callout.tsx). Mirrored in bash so it shows the moment the +# curl install finishes. +Y='\033[33m'; B='\033[1m'; R='\033[0m' echo "" -echo -e "Run \033[1mdot init\033[0m to log in with the Polkadot mobile app." +echo -e "${Y}╭─ ${B}next step${R}${Y} ──────────────────────────────╮${R}" +echo -e "${Y}│${R} Run ${B}$CMD init${R} or ${B}$ALIAS init${R} to log in ${Y}│${R}" +echo -e "${Y}│${R} with the Polkadot mobile app. ${Y}│${R}" +echo -e "${Y}│${R} Both commands work the same. ${Y}│${R}" +echo -e "${Y}╰──────────────────────────────────────────╯${R}" diff --git a/package.json b/package.json index e9e72dc..989a773 100644 --- a/package.json +++ b/package.json @@ -7,15 +7,16 @@ "type": "module", "packageManager": "pnpm@10.32.1", "bin": { - "dot": "./src/index.ts" + "playground": "./src/index.ts", + "pg": "./src/index.ts" }, "scripts": { "postinstall": "bash node_modules/@parity/product-sdk-terminal/scripts/patch-wasm.sh", "format": "biome format --write .", "format:check": "biome format .", "lint:license": "./scripts/check-license-headers.sh", - "build": "bun build --compile src/index.ts --outfile ./dist/dot", - "cli:install": "bun build --compile src/index.ts --outfile ~/.polkadot/bin/dot", + "build": "bun build --compile src/index.ts --outfile ./dist/playground", + "cli:install": "bun build --compile src/index.ts --outfile ~/.polkadot/bin/playground && ln -sf ~/.polkadot/bin/playground ~/.polkadot/bin/pg", "test": "vitest run", "test:watch": "vitest", "test:e2e": "vitest run --config e2e/vitest.config.ts", diff --git a/src/commands/contract.ts b/src/commands/contract.ts index eafa95d..c628092 100644 --- a/src/commands/contract.ts +++ b/src/commands/contract.ts @@ -483,7 +483,7 @@ async function runContractInstall(libraries: string[], opts: ContractInstallOpts function makeDeployCommand(): Command { return new Command("deploy") - .description("Build, deploy, and register CDM contracts with the dot signer") + .description("Build, deploy, and register CDM contracts with the logged-in signer") .addOption(new Option("--signer ", "Signer mode").choices(["dev", "phone"])) .option("--assethub-url ", "Override the Asset Hub WebSocket URL") .option("--bulletin-url ", "Override the Bulletin WebSocket URL") diff --git a/src/commands/contractDeployUi.tsx b/src/commands/contractDeployUi.tsx index c8917c6..ef8a2a4 100644 --- a/src/commands/contractDeployUi.tsx +++ b/src/commands/contractDeployUi.tsx @@ -153,7 +153,7 @@ function ContractDeployScreen({ return (
- To deploy to a domain owned by you, run `dot init` and re-run `dot - decentralize` with the mobile signer. + To deploy to a domain owned by you, run `playground init` and re-run + `playground decentralize` with the mobile signer. )} diff --git a/src/commands/decentralize/index.ts b/src/commands/decentralize/index.ts index 7d81fce..3b58f5a 100644 --- a/src/commands/decentralize/index.ts +++ b/src/commands/decentralize/index.ts @@ -75,7 +75,7 @@ export const decentralizeCommand = new Command("decentralize") .option( "--suri ", "Sign with this SURI (dev name like //Bob, or a BIP-39 mnemonic). " + - "Default: the session signer paired by `dot init`.", + "Default: the session signer paired by `playground init`.", ) .option( "--playground", @@ -306,8 +306,8 @@ export function printHeadlessSuccess(outcome: DecentralizeOutcome): void { process.stdout.write(`${lines.join("\n")}\n`); if (outcome.signerSource === "dev") { process.stdout.write( - "\n To deploy to a domain owned by you, run `dot init` and re-run\n" + - " `dot decentralize` with the mobile signer.\n", + "\n To deploy to a domain owned by you, run `playground init` and re-run\n" + + " `playground decentralize` with the mobile signer.\n", ); } process.stdout.write("\n"); diff --git a/src/commands/deploy/DeployScreen.tsx b/src/commands/deploy/DeployScreen.tsx index 442cebe..307bc52 100644 --- a/src/commands/deploy/DeployScreen.tsx +++ b/src/commands/deploy/DeployScreen.tsx @@ -184,7 +184,7 @@ export function DeployScreen({ return (
- label="make this app moddable? (anyone in the playground can dot mod it)" + label="make this app moddable? (anyone in the playground can playground mod it)" options={[ { value: false, @@ -360,14 +360,14 @@ export function DeployScreen({ onFinish={(outcome, chunkTimings) => { setStage({ kind: "done", outcome }); // Surface completion on the terminal tab so users can glance over. - setWindowTitle(`dot deploy · ${resolved.domain} · ✓`); + setWindowTitle(`playground deploy · ${resolved.domain} · ✓`); onDone(outcome); // chunkTimings is threaded via ref below — consumed by FinalResult. finalChunkTimingsRef.current = chunkTimings; }} onError={(message) => { setStage({ kind: "error", message }); - setWindowTitle(`dot deploy · ${resolved.domain} · ✕`); + setWindowTitle(`playground deploy · ${resolved.domain} · ✕`); onDone(null); }} /> @@ -753,7 +753,7 @@ function RunningStage({ useEffect(() => { // Announce the command + target in the terminal tab on mount. - setWindowTitle(`dot deploy · ${inputs.domain} · building`); + setWindowTitle(`playground deploy · ${inputs.domain} · building`); let cancelled = false; @@ -787,11 +787,11 @@ function RunningStage({ setRunningState((s) => runningReducer(s, event)); if (event.kind === "phase-start") { if (event.phase === "build") { - setWindowTitle(`dot deploy · ${inputs.domain} · building`); + setWindowTitle(`playground deploy · ${inputs.domain} · building`); } else if (event.phase === "storage-and-dotns") { - setWindowTitle(`dot deploy · ${inputs.domain} · uploading`); + setWindowTitle(`playground deploy · ${inputs.domain} · uploading`); } else if (event.phase === "playground") { - setWindowTitle(`dot deploy · ${inputs.domain} · publishing`); + setWindowTitle(`playground deploy · ${inputs.domain} · publishing`); } } else if (event.kind === "build-log") { queueFrontendLog(event.line); diff --git a/src/commands/deploy/index.ts b/src/commands/deploy/index.ts index 1b02df8..fff8548 100644 --- a/src/commands/deploy/index.ts +++ b/src/commands/deploy/index.ts @@ -79,7 +79,7 @@ export const deployCommand = new Command("deploy") ) .option( "--moddable", - "Publish the source repo so others can `dot mod` it. Requires --playground and a public GitHub `origin`.", + "Publish the source repo so others can `playground mod` it. Requires --playground and a public GitHub `origin`.", ) .option("--no-moddable", "Explicitly skip publishing source (the default).") .option("--suri ", "Secret URI for the user signer (e.g. //Alice for dev)") @@ -217,7 +217,7 @@ async function preflight(opts: { // (e.g. quick smoke tests, CI without a session). process.stderr.write( "warning: --signer dev --playground with no session and no --suri — " + - "publishing under the dev (Alice) account. Run `dot init` first " + + "publishing under the dev (Alice) account. Run `playground init` first " + "if you want the app to appear in your MyApps view.\n", ); captureWarning("dev mode playground publish with no user identity", { @@ -245,7 +245,7 @@ async function preflight(opts: { if (!mapped) { signer.destroy(); throw new Error( - 'Account is not mapped in Revive. Run "dot init" first to finish account setup.', + 'Account is not mapped in Revive. Run "playground init" first to finish account setup.', ); } diff --git a/src/commands/init/AccountSetup.tsx b/src/commands/init/AccountSetup.tsx index 2a22b33..b2aeee9 100644 --- a/src/commands/init/AccountSetup.tsx +++ b/src/commands/init/AccountSetup.tsx @@ -131,7 +131,7 @@ export function AccountSetup({ prev.map((s) => ({ ...s, status: "failed", - error: "no session — run dot init to log in", + error: "no session — run playground init to log in", })), ); finish(false); @@ -219,7 +219,7 @@ export function AccountSetup({ accountSetupOk = false; update(0, { status: "failed", - error: `denied: ${denied}. Re-run \`dot init\` and approve on your phone.`, + error: `denied: ${denied}. Re-run \`playground init\` and approve on your phone.`, valueTone: "danger", }); } else { diff --git a/src/commands/init/InitScreen.tsx b/src/commands/init/InitScreen.tsx index 50ed0c7..53790f9 100644 --- a/src/commands/init/InitScreen.tsx +++ b/src/commands/init/InitScreen.tsx @@ -86,7 +86,7 @@ export function InitScreen({ return (
{ } export const logoutCommand = new Command("logout") - .description("Sign out of the account paired via `dot init`") + .description("Sign out of the account paired via `playground init`") .action(async () => runCliCommand("logout", { hardExit: true }, async () => { console.log(); diff --git a/src/commands/mod/SetupScreen.tsx b/src/commands/mod/SetupScreen.tsx index 6a11e64..055681b 100644 --- a/src/commands/mod/SetupScreen.tsx +++ b/src/commands/mod/SetupScreen.tsx @@ -91,7 +91,7 @@ export function SetupScreen({ domain, metadata: initial, registry, targetDir, on const ref = parseGitHubRepoUrl(repoUrl); if (!ref) { throw new Error( - `Only GitHub-hosted source is supported for dot mod today (got ${repoUrl}).`, + `Only GitHub-hosted source is supported for playground mod today (got ${repoUrl}).`, ); } // `meta.branch` is written by `dot deploy --moddable` from @@ -134,7 +134,7 @@ export function SetupScreen({ domain, metadata: initial, registry, targetDir, on return (
{ console.log(" Next steps:"); console.log(` 1. cd ${targetDir}`); console.log(" 2. edit with claude"); - console.log(" 3. dot deploy --playground"); + console.log(" 3. playground deploy --playground"); } if (!ok) process.exitCode = 1; } finally { diff --git a/src/commands/update.ts b/src/commands/update.ts index 0ad0b26..a5750bd 100644 --- a/src/commands/update.ts +++ b/src/commands/update.ts @@ -123,7 +123,7 @@ export function atomicInstall(dest: string, bytes: Buffer, mode = 0o755): void { } export const updateCommand = new Command("update") - .description("Update dot to the latest version") + .description("Update playground to the latest version") .action(async () => runCliCommand("update", { hardExit: true }, async () => { const installDir = await withSpan( @@ -171,7 +171,7 @@ export const updateCommand = new Command("update") throw err; } - const dest = resolve(installDir, "dot"); + const dest = resolve(installDir, "playground"); try { await withSpan( "cli.update.install", @@ -203,6 +203,6 @@ export const updateCommand = new Command("update") } console.log("done"); - console.log(`Updated dot to ${tag}`); + console.log(`Updated playground to ${tag}`); }), ); diff --git a/src/index.ts b/src/index.ts index d908e2b..74a88ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -121,7 +121,7 @@ onProcessShutdown(() => closeTelemetry(2000)); onProcessShutdown(clearWindowTitle); const program = new Command() - .name("dot") + .name("playground") .description("CLI for Polkadot Playground") .version(pkg.version); diff --git a/src/telemetry.test.ts b/src/telemetry.test.ts index bca89c6..702b3ab 100644 --- a/src/telemetry.test.ts +++ b/src/telemetry.test.ts @@ -45,9 +45,9 @@ describe("telemetry disabled mode", () => { describe("expected CLI errors", () => { it("classifies known user-facing failures as expected", async () => { const { isExpectedCliError } = await import("./telemetry.js"); - expect(isExpectedCliError('Account is not mapped in Revive. Run "dot init" first.')).toBe( - true, - ); + expect( + isExpectedCliError('Account is not mapped in Revive. Run "playground init" first.'), + ).toBe(true); expect(isExpectedCliError("Bulletin storage allowance is exhausted")).toBe(true); expect( isExpectedCliError( diff --git a/src/telemetry.ts b/src/telemetry.ts index cc48369..b1bc0af 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -107,7 +107,7 @@ export function sanitizeSentryTransaction>(eve } export function isExpectedCliError(message: string): boolean { - return /badregistrylookup|signer.*not available|run "dot init"|account is not mapped|storage allowance is exhausted|invalid domain|already owned|reserved|insufficient balance|no github origin configured|must use a public github repository|private or does not exist|github api returned|download failed/i.test( + return /badregistrylookup|signer.*not available|run "playground init"|account is not mapped|storage allowance is exhausted|invalid domain|already owned|reserved|insufficient balance|no github origin configured|must use a public github repository|private or does not exist|github api returned|download failed/i.test( message, ); } @@ -260,7 +260,12 @@ export async function withCommandTelemetry( command: CliCommandName, fn: () => Promise | T, ): Promise { - return withRootSpan(`cli.${command}`, `dot ${command}`, getCliRootAttributes(command), fn); + return withRootSpan( + `cli.${command}`, + `playground ${command}`, + getCliRootAttributes(command), + fn, + ); } export async function withSpan(op: string, name: string, fn: () => Promise | T): Promise; diff --git a/src/utils/allowances/bulletin.test.ts b/src/utils/allowances/bulletin.test.ts index 4cfdc51..aba693e 100644 --- a/src/utils/allowances/bulletin.test.ts +++ b/src/utils/allowances/bulletin.test.ts @@ -293,7 +293,7 @@ describe("Bulletin allowance authorization", () => { bulletinApi: {} as any, requiredBytes: 50, }), - ).rejects.toThrow(/Re-run `dot init` and approve on your phone/); + ).rejects.toThrow(/Re-run `playground init` and approve on your phone/); expect(requestResourceAllocation).toHaveBeenCalledWith({ callingProductId: "playground.dot", resources: [{ tag: "BulletInAllowance", value: undefined }], diff --git a/src/utils/allowances/bulletin.ts b/src/utils/allowances/bulletin.ts index 13a05de..cd3c857 100644 --- a/src/utils/allowances/bulletin.ts +++ b/src/utils/allowances/bulletin.ts @@ -99,7 +99,7 @@ async function requestBulletinAllowanceKey( ): Promise { if (!publishSigner.userSession) { throw new Error( - 'No Bulletin allowance account cached. Run "dot init" to grant allowances.', + 'No Bulletin allowance account cached. Run "playground init" to grant allowances.', ); } @@ -118,7 +118,7 @@ async function requestBulletinAllowanceKey( if (key) return key; const outcome = outcomes[0]; throw new Error( - `Bulletin allowance allocation ${outcome?.tag ?? "returned no outcome"}. Re-run \`dot init\` and approve on your phone.`, + `Bulletin allowance allocation ${outcome?.tag ?? "returned no outcome"}. Re-run \`playground init\` and approve on your phone.`, ); } @@ -164,8 +164,8 @@ export async function getBulletinAllowanceSigner({ const address = authorization.address; throw new Error( authorization.status.authorized - ? `Bulletin allowance for ${address} is live but does not have enough quota. Re-run \`dot init\` and approve on your phone.` - : `Bulletin allowance account ${address} is not authorized. Re-run \`dot init\` and approve on your phone.`, + ? `Bulletin allowance for ${address} is live but does not have enough quota. Re-run \`playground init\` and approve on your phone.` + : `Bulletin allowance account ${address} is not authorized. Re-run \`playground init\` and approve on your phone.`, ); } diff --git a/src/utils/allowances/smartContracts.ts b/src/utils/allowances/smartContracts.ts index 25c6e7c..d7daf4f 100644 --- a/src/utils/allowances/smartContracts.ts +++ b/src/utils/allowances/smartContracts.ts @@ -40,7 +40,7 @@ export async function ensureSmartContractAllowance({ if (!deploySigner.userSession) { throw new Error( - 'No smart-contract gas allowance cached. Run "dot init" to grant allowances.', + 'No smart-contract gas allowance cached. Run "playground init" to grant allowances.', ); } @@ -58,6 +58,6 @@ export async function ensureSmartContractAllowance({ const outcome = outcomes[0]?.tag ?? "returned no outcome"; throw new Error( - `Smart-contract gas allowance allocation ${outcome}. Re-run \`dot init\` and approve on your phone.`, + `Smart-contract gas allowance allocation ${outcome}. Re-run \`playground init\` and approve on your phone.`, ); } diff --git a/src/utils/deploy/signerMode.test.ts b/src/utils/deploy/signerMode.test.ts index 2f843ee..2bf42d8 100644 --- a/src/utils/deploy/signerMode.test.ts +++ b/src/utils/deploy/signerMode.test.ts @@ -109,7 +109,7 @@ describe("resolveSignerSetup — phone mode", () => { userSigner: null, publishToPlayground: false, }), - ).toThrow(/dot init|--signer dev/); + ).toThrow(/playground init|--signer dev/); }); it("no plan + no publish → 3 DotNS approvals in exact order, auth options wired to user signer", () => { diff --git a/src/utils/deploy/signerMode.ts b/src/utils/deploy/signerMode.ts index abcf9d7..972dd43 100644 --- a/src/utils/deploy/signerMode.ts +++ b/src/utils/deploy/signerMode.ts @@ -190,7 +190,7 @@ export function resolveSignerSetup(opts: ResolveOptions): DeploySignerSetup { if (opts.mode === "phone") { if (!opts.userSigner) { throw new Error( - 'Phone signer requested but no session found. Run "dot init" to log in, or pass --signer dev.', + 'Phone signer requested but no session found. Run "playground init" to log in, or pass --signer dev.', ); } bulletinDeployAuthOptions = { diff --git a/src/utils/sessionSigner.test.ts b/src/utils/sessionSigner.test.ts index b8d15ba..244027d 100644 --- a/src/utils/sessionSigner.test.ts +++ b/src/utils/sessionSigner.test.ts @@ -114,7 +114,9 @@ describe("init / deploy / playground-app account equivalence", () => { productId: PLAYGROUND_PRODUCT_ID, derivationIndex: 0, }), - ).toThrow('Stored login session is missing the root account public key. Run "dot logout"'); + ).toThrow( + 'Stored login session is missing the root account public key. Run "playground logout"', + ); }); test("PLAYGROUND_PRODUCT_ID matches the playground-app's default dotNsId", () => { diff --git a/src/utils/sessionSigner.ts b/src/utils/sessionSigner.ts index b24afc8..77ea83c 100644 --- a/src/utils/sessionSigner.ts +++ b/src/utils/sessionSigner.ts @@ -65,7 +65,7 @@ export interface ProductAccountRef { } export const INCOMPLETE_SESSION_MESSAGE = - 'Stored login session is missing the root account public key. Run "dot logout" and then "dot init" to pair again.'; + 'Stored login session is missing the root account public key. Run "playground logout" and then "playground init" to pair again.'; export function sessionRootPublicKey(session: UserSession): Uint8Array { const rootAccountId = (session as { rootAccountId?: Uint8Array }).rootAccountId; diff --git a/src/utils/signer.test.ts b/src/utils/signer.test.ts index 48c3e1f..a6e5ca0 100644 --- a/src/utils/signer.test.ts +++ b/src/utils/signer.test.ts @@ -153,7 +153,7 @@ describe("resolveSigner", () => { mockGetSessionSigner.mockResolvedValue(null); await expect(resolveSigner()).rejects.toThrow(SignerNotAvailableError); - await expect(resolveSigner()).rejects.toThrow(/dot init/); + await expect(resolveSigner()).rejects.toThrow(/playground init/); }); it("prefers SURI over session even when session exists", async () => { diff --git a/src/utils/signer.ts b/src/utils/signer.ts index c460700..7ce59b1 100644 --- a/src/utils/signer.ts +++ b/src/utils/signer.ts @@ -55,7 +55,9 @@ export interface SignerOptions { export class SignerNotAvailableError extends Error { constructor() { - super('No signer available. Run "dot init" to log in, or pass --suri //Alice for dev.'); + super( + 'No signer available. Run "playground init" to log in, or pass --suri //Alice for dev.', + ); this.name = "SignerNotAvailableError"; } } diff --git a/src/utils/version-check.test.ts b/src/utils/version-check.test.ts index 2cd7a34..49b4be6 100644 --- a/src/utils/version-check.test.ts +++ b/src/utils/version-check.test.ts @@ -114,11 +114,11 @@ describe("shouldSkip", () => { }); describe("formatBanner", () => { - it("includes both versions with v-prefixes and the dot update hint", () => { + it("includes both versions with v-prefixes and the playground update hint", () => { const out = formatBanner("0.16.14", "0.16.15"); expect(out).toContain("v0.16.14"); expect(out).toContain("v0.16.15"); - expect(out).toContain("dot update"); + expect(out).toContain("playground update"); }); }); @@ -164,7 +164,7 @@ describe("startVersionCheck", () => { expect(banner).not.toBeNull(); expect(banner).toContain("v0.16.14"); expect(banner).toContain("v0.17.0"); - expect(banner).toContain("dot update"); + expect(banner).toContain("playground update"); }); it("returns null when the network call fails", async () => { diff --git a/src/utils/version-check.ts b/src/utils/version-check.ts index cbaa02f..0c5eefb 100644 --- a/src/utils/version-check.ts +++ b/src/utils/version-check.ts @@ -116,7 +116,7 @@ export function formatBanner(currentVersion: string, latestVersion: string): str // visual treatment would quickly become noise. return ( `\n ${ANSI_YELLOW}${GLYPH.warn}${ANSI_RESET} Update available: ${current} → ${latest}\n` + - ` Run ${ANSI_BOLD}dot update${ANSI_RESET} to upgrade.\n` + ` Run ${ANSI_BOLD}playground update${ANSI_RESET} to upgrade.\n` ); }