Skip to content
Draft
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
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,15 @@ jobs:
- name: Run codegen
run: ./scripts/codegen.sh

- name: Check generated Rust output is committed
- name: Check generated output is committed
run: |
git diff --exit-code -- \
rust/crates/truapi-server/src/generated \
rust/crates/truapi-server/src/wasm/generated_bridge.rs
rust/crates/truapi-server/src/wasm/generated_bridge.rs \
rust/crates/truapi-host-cli/js/script-types.d.ts

- name: Type-check headless host scripts
run: node_modules/.bin/tsc -p rust/crates/truapi-host-cli/js/tsconfig.json

- name: Check Rust/TS wire table parity
run: TRUAPI_REQUIRE_GENERATED_TS=1 cargo test -p truapi-server --test wire_table_ts_parity
Expand All @@ -146,6 +150,7 @@ jobs:
js/packages/truapi/src/explorer/versions.ts
js/packages/truapi-host/src/generated
playground/test/generated
rust/crates/truapi-host-cli/js/script-types.d.ts

ios-bindings:
name: iOS bindings (uniffi)
Expand Down
16 changes: 10 additions & 6 deletions .github/workflows/release-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ jobs:
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: runner-bundle
path: target/dist/runner.js
path: |
target/dist/runner.js
target/dist/script-types.d.ts
if-no-files-found: error

build:
Expand Down Expand Up @@ -117,8 +119,8 @@ jobs:
if: endsWith(matrix.target, '-musl')
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y musl-tools

# `make cli-dist` treats target/dist/runner.js as a file target, so
# dropping it here means the archive reuses it instead of rebuilding.
# `make cli-dist` treats the runner artifacts as file targets, so dropping
# them here means the archive reuses them instead of rebuilding.
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: runner-bundle
Expand Down Expand Up @@ -152,9 +154,11 @@ jobs:
reported="$(./target/${{ matrix.target }}/release/truapi-host --version)"
[ "${reported}" = "truapi-host ${VERSION}" ] \
|| { echo "::error::binary reports '${reported}'"; exit 1; }
tar -tzf "target/dist/truapi-host-${VERSION}-${{ matrix.target }}.tar.gz" \
| grep -qx runner.js \
|| { echo "::error::archive is missing the product-script runner"; exit 1; }
contents="$(tar -tzf "target/dist/truapi-host-${VERSION}-${{ matrix.target }}.tar.gz")"
for required in runner.js script-types.d.ts; do
grep -qx "${required}" <<< "${contents}" \
|| { echo "::error::archive is missing ${required}"; exit 1; }
done

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ playground/next-env.d.ts
playground/tsconfig.tsbuildinfo
js/packages/truapi/dist/
js/packages/truapi/node_modules/
rust/crates/truapi-host-cli/js/script-types.d.ts
REVIEW_TODO*.md
15 changes: 11 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ CLI_TARGET ?= $(shell rustc -vV | sed -n 's/^host: //p' | sed 's/-linux-gnu$$/-l
CLI_VERSION ?= $(shell awk -F'"' '/^version = /{print $$2; exit}' rust/crates/truapi-host-cli/Cargo.toml)
CLI_ARCHIVE := truapi-host-$(CLI_VERSION)-$(CLI_TARGET).tar.gz
CLI_RUNNER := $(CLI_DIST_DIR)/runner.js
CLI_SCRIPT_TYPES_SOURCE := rust/crates/truapi-host-cli/js/script-types.d.ts
CLI_SCRIPT_TYPES := $(CLI_DIST_DIR)/script-types.d.ts
CLI_STAGE := $(CLI_DIST_DIR)/$(CLI_TARGET)
# macOS ships shasum, most Linux images ship only sha256sum.
SHA256 := $(shell command -v sha256sum >/dev/null 2>&1 && echo "sha256sum" || echo "shasum -a 256")
Expand All @@ -97,15 +99,20 @@ $(CLI_RUNNER):
mkdir -p $(CLI_DIST_DIR)
bun build rust/crates/truapi-host-cli/js/runner.ts --target=bun --outfile $@

cli-runner: $(CLI_RUNNER) ## Bundle the self-contained product-script runner into target/dist.
$(CLI_SCRIPT_TYPES): $(CLI_SCRIPT_TYPES_SOURCE)
mkdir -p $(CLI_DIST_DIR)
cp $< $@

cli-runner: $(CLI_RUNNER) $(CLI_SCRIPT_TYPES) ## Bundle the product-script runner and its self-contained types into target/dist.
node_modules/.bin/tsc -p rust/crates/truapi-host-cli/js/tsconfig.json

cli-dist: $(CLI_RUNNER) ## Package truapi-host for CLI_TARGET into target/dist in the release artifact layout.
cli-dist: $(CLI_RUNNER) $(CLI_SCRIPT_TYPES) ## Package truapi-host for CLI_TARGET into target/dist in the release artifact layout.
rustup target add $(CLI_TARGET)
$(CARGO) build -p truapi-host-cli --release --target $(CLI_TARGET)
rm -rf $(CLI_STAGE)
mkdir -p $(CLI_STAGE)
cp target/$(CLI_TARGET)/release/truapi-host $(CLI_RUNNER) $(CLI_STAGE)/
tar -czf $(CLI_DIST_DIR)/$(CLI_ARCHIVE) -C $(CLI_STAGE) truapi-host runner.js
cp target/$(CLI_TARGET)/release/truapi-host $(CLI_RUNNER) $(CLI_SCRIPT_TYPES) $(CLI_STAGE)/
tar -czf $(CLI_DIST_DIR)/$(CLI_ARCHIVE) -C $(CLI_STAGE) truapi-host runner.js script-types.d.ts
cd $(CLI_DIST_DIR) && $(SHA256) $(CLI_ARCHIVE) > $(CLI_ARCHIVE).sha256
@echo "packaged $(CLI_DIST_DIR)/$(CLI_ARCHIVE)"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The interactive playground lets you browse every method, edit request payloads,
curl -fsSL https://raw.githubusercontent.com/paritytech/host-rust-core/main/scripts/truapi-host-installer.sh | bash
```

Prebuilt for macOS on Apple silicon and Linux on x86_64 and arm64. No Rust toolchain or checkout needed, and it keeps itself up to date. See the [`truapi-host-cli` guide](rust/crates/truapi-host-cli/README.md) for the commands, the terminal UI, and product scripts.
Prebuilt for macOS on Apple silicon and Linux on x86_64 and arm64. No Rust toolchain or checkout needed, and it keeps itself up to date. Scratch scripts created by `/script` include generated editor types for the injected `truapi`, `host`, and `assert` globals without a local npm package. See the [`truapi-host-cli` guide](rust/crates/truapi-host-cli/README.md) for the commands, the terminal UI, and product scripts.

## Usage

Expand Down
11 changes: 7 additions & 4 deletions rust/crates/truapi-host-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ moves that one link.
| `TRUAPI_HOST_BIN_DIR` | Directory the `PATH` symlink goes in, default `~/.local/bin`. |

Product scripts (`--script`, `/script`) work from an installed binary: the
archive ships a `runner.js` with the `@parity/truapi` client bundled in. You
still need `bun` on `PATH`, since it executes the runner and your script.
archive ships a `runner.js` with the `@parity/truapi` client bundled in and a
self-contained `script-types.d.ts` for the globals it injects. You still need
`bun` on `PATH`, since it executes the runner and your script.

Product frames use a private, per-process WebSocket-over-Unix-domain-socket by
default, so starting either host does not reserve a TCP port. Pass
Expand Down Expand Up @@ -269,8 +270,10 @@ including a path previously selected with `/script <path>`. If that file is
missing or the session has no script yet, it creates a durable Bun TypeScript
file under the active host state's `scripts/` directory. The dependency-free
starter calls `truapi.account.getUserId()` and prints the returned user id.
Scripts opened from an npm project can import packages installed by that
project.
The generated file references an adjacent declaration bundle, so the editor
provides completion and type checking for `truapi`, `host`, and `assert`
without requiring `@parity/truapi` in a parent npm project. Scripts opened
from an npm project can still import packages installed by that project.
The TUI temporarily yields the terminal to `$VISUAL`, then `$EDITOR`, or
`vi` when neither is set. After the editor exits successfully, the TUI is
restored and the saved script runs through the public frame endpoint. Editor
Expand Down
29 changes: 22 additions & 7 deletions rust/crates/truapi-host-cli/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ release pointer, downloads the archive for the detected target

```
$XDG_DATA_HOME/truapi-host/versions/<version>/truapi-host
$XDG_DATA_HOME/truapi-host/versions/<version>/runner.js
$XDG_DATA_HOME/truapi-host/versions/<version>/script-types.d.ts
$XDG_DATA_HOME/truapi-host/current -> versions/<version>
~/.local/bin/truapi-host -> $XDG_DATA_HOME/truapi-host/current/truapi-host
```
Expand Down Expand Up @@ -200,10 +202,17 @@ The runner is resolved in this order: `TRUAPI_HOST_RUNNER`, then `runner.js`
next to the running binary, then `js/runner.ts` in the source checkout
(compiled from `CARGO_MANIFEST_DIR`).

A release archive ships `runner.js` beside the binary, with `@parity/truapi`
bundled in, so an installed copy runs product scripts with no source tree. A
source build has no bundle and falls back to the checkout copy, whose relative
`@parity/truapi` import means it only works from a built tree.
A release archive ships `runner.js` and `script-types.d.ts` beside the binary.
The runner has `@parity/truapi` bundled in, and the declaration file contains
the matching generated client and injected-global types, so an installed copy
runs and edits product scripts with no source tree or npm package. A source
build has no runner bundle and falls back to the checkout copies, whose
relative `@parity/truapi` import means the runner only works from a built
tree.

A `TRUAPI_HOST_RUNNER` override must provide a compatible
`script-types.d.ts` beside the selected runner when bare `/script` needs to
create an editor scratch file.

`bun` is required either way, since the runner and user scripts are executed by
it.
Expand Down Expand Up @@ -777,8 +786,8 @@ These variables are runner internals, not CLI configuration inputs.
- A thrown error or rejected promise is printed as `[script error] ...` and
exits `1`.
- Failure to open the product socket within 15 seconds exits `2`.
- Failure to locate the runner, canonicalize the script, or spawn Bun is a CLI
error.
- Failure to locate the runner or its declaration bundle, canonicalize the
script, or spawn Bun is a CLI error.

The CLI emits `Script running` before Bun starts and `Script finished` or
`Script failed` afterward.
Expand Down Expand Up @@ -824,7 +833,13 @@ by a new scratch file.

The default scratch file is a dependency-free Bun script that calls
`truapi.account.getUserId()` and prints `user id` followed by the returned
value. It does not emit terminal styling.
value. A same-named `.d.ts` file is copied beside it from the selected runner's
`script-types.d.ts`, and the script carries a relative triple-slash reference
to that copy. Editors therefore resolve the matching generated types for
`truapi`, `host`, and `assert` without a checkout or npm package. Keeping the
declaration beside the scratch file preserves its types across session
promotion and removal of older installed binary versions. The script does not
emit terminal styling.

Mnemonic-backed ephemeral signing sessions remember a path only for the
current process and create scratch files under the system temporary
Expand Down
24 changes: 24 additions & 0 deletions rust/crates/truapi-host-cli/js/runner-types.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// <reference path="./script-types.d.ts" />
export {};

const productContext = await truapi.system.getProductContext();
if (productContext.isOk()) {
const productId: string = productContext.value.productId;
assert(productId.length > 0);

// @ts-expect-error Product context does not contain the signed-in user.
productContext.value.userId;
}

const account = host.productAccount(0);
const accountProductId: string = account.dotNsIdentifier;
assert(accountProductId.length > 0);

// @ts-expect-error Product accounts have no user-facing username.
account.username;

// @ts-expect-error Derivation indices are numeric.
host.productAccount("0");

// @ts-expect-error The generated client rejects unknown services.
truapi.unknownService;
Loading