Add docs.installTemplate RPC method #102
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_books#102
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent: #101
What to add
Method:
docs.installTemplateParams:
{ path: string, reset?: bool }Returns:
{ job_id: string }Wraps:
DocSite::install_template(reset)atlib.rs:85Implementation steps
hero_docs install-templatesubcommand exists inhero_docsbinaryhandle_docs_install_template(id, params, config) -> RpcResponseincrates/hero_books_server/src/web/rpc.rs"docs.installTemplate"in match block atrpc.rs:155crates/hero_books_server/openrpc.jsonwith params, result, and examples block matching existingdocs.*styleinfo.versioninopenrpc.jsonrpc.rs:9-28Acceptance Criteria
hero_docs install-templatesubcommand exists{ job_id }immediately; client pollsdocs.jobStatusImplementation Spec for Issue #102
Objective
Expose
DocSite::install_templateover the OpenRPC interface asdocs.installTemplate. The method submits ahero_procjob that shells out to thehero_docsbinary, follows the existing async/dedup pattern ofdocs.newanddocs.generate, and returns{ "job_id": "<n>" }for clients to poll viadocs.jobStatus. Thehero_docsbinary itself grows a matchinginstall-templatesubcommand so the handler has something to invoke.Requirements
docs.installTemplateis dispatchable fromcrates/hero_books_server/src/web/rpc.rsand reaches a new handlerhandle_docs_install_template.crates/hero_books_server/openrpc.jsonmirroring the existingdocs.new/docs.generatestyle (noexamplesblock — none exist today).info.versioninopenrpc.jsonis bumped (0.1.5->0.1.6).# Available Methodsdoc-comment header inrpc.rs(lines 9-28) gains a## Docssection listing all currently exposeddocs.*methods (docs.new,docs.generate,docs.installTemplate,docs.jobStatus).hero_docs(src/bin/hero_docs.rs) gains a newinstall-templatesubcommand:hero_docs install-template --path <path> [--reset]. It callshero_books_docusaurus::template::install_template(&path, reset)directly — no heroscript loading required, since the underlying function only needs a build-directory path.config.hero_docs_bin, never callingDocSitein-process.submit_or_dedup_docs_job(...)with action namedocs_install_template_<input_hash>.handle_docs_job_status's prefix-strip block (rpc.rs:1508-1519) is updated so it recognisesdocs_install_template_as a known prefix that produces nooutput_path(the user-supplied path is not recoverable from the input hash, and there is no deterministic build artifact to surface).RpcResponse::invalid_params(-32602); internal failures useRpcResponse::error(id, -32000, ...).Files to Modify/Create
src/bin/hero_docs.rs— addInstallTemplate(InstallTemplateArgs)variant, args struct,run_install_templaterunner.crates/hero_books_server/src/web/rpc.rs— addhandle_docs_install_template, dispatch arm, doc-header## Docssection, prefix recognition inhandle_docs_job_status.crates/hero_books_server/openrpc.json— adddocs.installTemplatemethod entry, bumpinfo.versionto"0.1.6".No new files.
Implementation Plan
Step 1 — Add
install-templatesubcommand tohero_docsFiles:
src/bin/hero_docs.rsCommandsenum with a newInstallTemplate(InstallTemplateArgs)variant. Keep the existing kebab-case CLI surface clap derives by default (install-template).main()alongsideCommands::New/Commands::Generate.Dependencies: none.
Step 2 — Add
handle_docs_install_templatehandler inrpc.rsFiles:
crates/hero_books_server/src/web/rpc.rshandle_docs_generate(around the existinghandle_docs_job_statusneighbourhood) with the standard signaturefn handle_docs_install_template(id: Option<Value>, params: Option<Value>, config: &ServerConfig) -> RpcResponse.path(required, non-empty string) andreset(optional bool, defaultfalse) from the params object. Reject empty / missingpathwithRpcResponse::invalid_params(id, "missing or empty 'path' parameter").let input_hash = calculate_docs_input_hash(&[&path, &reset.to_string()]);— both raw inputs included so dedup is stable across calls with differentreset.submit_or_dedup_docs_job(id, config, &format!("docs_install_template_{}", input_hash), &script).Dependencies: Step 1 (the
install-templatesubcommand must exist for runtime invocations to succeed; not required for compilation).Step 3 — Wire dispatch arm
Files:
crates/hero_books_server/src/web/rpc.rsmatch request.method.as_str()block (lines 155-205), inside the// Docs APIgroup, add after the existingdocs.generatearm and beforedocs.jobStatus:Dependencies: Step 2.
Step 4 — Recognise the new prefix in
handle_docs_job_statusFiles:
crates/hero_books_server/src/web/rpc.rsrpc.rs:1508-1519stripsdocs_new_/docs_generate_to recover the hash foroutput_path. Update it sodocs_install_template_is a recognised butoutput_path-less prefix: The recognition is implicit (we simply don't try to strip these prefixes), but the comment makes future maintenance obvious.Dependencies: Step 2.
Step 5 — Update doc-comment header in
rpc.rsFiles:
crates/hero_books_server/src/web/rpc.rs## Docssection. Add one: Insert between the## Collectionsblock and the## Legacy (deprecated)/ other trailing items so the header reads naturally.Dependencies: none (purely documentation).
Step 6 — Add
docs.installTemplateentry inopenrpc.jsonFiles:
crates/hero_books_server/openrpc.jsoninfo.versionfrom"0.1.5"to"0.1.6".methodsarray betweendocs.generateanddocs.jobStatus:Dependencies: Step 3 (so the verification diff in Step 7 passes).
Step 7 — Verify spec/impl parity and build
Files: none (read-only check + cargo).
cargo check -p hero_books_serverandcargo check --bin hero_docs.cargo test -p hero_books_serverto confirm no regressions.cargo run --bin hero_docs -- install-template --help.Dependencies: Steps 1-6.
Acceptance Criteria
hero_docs install-template --helpprints usage with--path(required) and--reset(flag) options.hero_docs install-template --path /tmp/test_docs(from a clean state) succeeds and creates a Docusaurus template at the path.crates/hero_books_server/src/web/rpc.rsdefineshandle_docs_install_templatematching the existinghandle_docs_*signature.docs.installTemplatearm is wired into the dispatchermatchblock, ordered betweendocs.generateanddocs.jobStatus.handle_docs_job_statusdoes not synthesise anoutput_pathfor jobs whose action name starts withdocs_install_template_.rpc.rs:9-28listsdocs.*methods includingdocs.installTemplateunder a## Docssection.crates/hero_books_server/openrpc.jsoncontains thedocs.installTemplatemethod entry with the params/result shape above.info.versioninopenrpc.jsonis"0.1.6".cargo check -p hero_books_serversucceeds.cargo check --bin hero_docssucceeds.cargo test -p hero_books_serverpasses (no regressions).Notes
docs.installTemplate. Sibling methods (docs.updateTemplate,docs.build,docs.dev,docs.publish,docs.publishDev) are tracked in #103-#107 and ship in their own PRs. Resist the urge to bundle them.pathis the Docusaurus build directory — the same kind of path the underlyingtemplate::install_template(&Path, bool)expects. It is not a heroscript path. We bypassDocSite::from_heroscriptbecauseinstall_templateonly needspath_build, and forcing a heroscript at the target would add round-trips with no benefit. (Compare:docs.newalso takes a target directory rather than a heroscript.)output_path. We extend the prefix recognition inhandle_docs_job_statusrather than emitting one. If a future change wantsoutput_pathfordocs.installTemplate, it requires augmenting the action-name encoding (e.g. embedding base64 ofpath) — out of scope for #102.input_hashis computed from the rawpathandresetflag string. Callingdocs.installTemplate({path:"/x"})twice in quick succession returns the same job id; calling it withreset:trueproduces a distinct job, which is what we want — the operations are not equivalent.info.versionbump: required by INSTRUCTIONS_OPENRPC.md whenever the spec changes.0.1.5->0.1.6on this PR; subsequent child issues will continue bumping (0.1.7, ...).-32602for invalid params,-32000for hero_proc / internal failures — matchhandle_docs_new.install-template(it's bounded by the bun install). The 10-minute default timeout insubmit_or_dedup_docs_jobis fine.Test Results
Suite:
cargo test -p hero_books_server --libTotal: 17 — Passed: 17 — Failed: 0
New test added with this change:
web::rpc::tests::test_docs_install_template_missing_params— covers missingpath, emptypath, and missingparamsobject. All assertions pass.Existing
docs.*validation tests still green (test_docs_new_missing_params,test_docs_generate_missing_params,test_docs_generate_invalid_book_id,test_docs_job_status_rejects_non_numeric_id).Spec/impl parity
INSTRUCTIONS_OPENRPC.md §Verification diff command produces empty output —
openrpc.jsonand the dispatcher inrpc.rsagree, withdocs.installTemplatelisted in both.Build
cargo check -p hero_books_server— OKcargo check --bin hero_docs— OKCLI smoke test
Live end-to-end RPC test (against running hero_books_server + hero_proc)
rpc.discoverlistsdocs.installTemplatewith correct params/result schemapathreturns-32602 "missing or empty 'path' parameter"{"job_id":"76"}job_id: "76"hero_procand ranhero_docs install-template ...docs.jobStatusoutput_pathfield on the response (per design — input path not recoverable from hash)The single live failure was an environment issue (
bun is not installed) insidetemplate::install_template, whichdocs.new/docs.generatealready exercise — not a defect introduced by this change. The full RPC chain (dispatch → handler → hero_proc →hero_docs install-template→ status reporting) executed end-to-end.Implementation Summary
docs.installTemplateis now exposed over JSON-RPC. The handler shells out viahero_procto a newhero_docs install-templatesubcommand, mirroring the async/dedup pattern ofdocs.newanddocs.generate.Files changed
src/bin/hero_docs.rs— newInstallTemplate(InstallTemplateArgs)subcommand, wired intomain().crates/hero_books_server/src/web/rpc.rshandle_docs_install_templatehandler (-32602for invalid params, dedup keydocs_install_template_<input_hash>)."docs.installTemplate"betweendocs.generateanddocs.jobStatus.handle_docs_job_statusupdated with a comment block documenting why nooutput_pathis synthesised fordocs_install_template_*jobs (user-suppliedpathis not recoverable from the input hash).## Docssection in the file-level doc-comment header listingdocs.new,docs.generate,docs.installTemplate,docs.jobStatus.test_docs_install_template_missing_paramscovering missingpath, emptypath, and missingparamsobject.crates/hero_books_server/src/web/rpc_spec.rs— inline schema (used byrpc.discover) updated with the samedocs.installTemplateentry.crates/hero_books_server/openrpc.json— new method entry;info.versionbumped0.1.5 -> 0.1.6.crates/hero_books_server/openrpc.client.generated.rs— auto-regenerated by theopenrpc_client!macro to reflect the new method.Test results
hero_books_server/hero_procconfirmed: discovery, validation, submission, idempotent dedup, hero_proc dispatch, error-tail surfacing throughdocs.jobStatus. Thebunruntime not being installed produced afailedstate fromtemplate::install_template, which is shared infrastructure exercised by the existingdocs.*methods and out of scope for #102.Notes
pathis the Docusaurus build directory — passed straight totemplate::install_template(&Path, bool). No heroscript loading. Same convention asdocs.new's--path.info.versionwill continue bumping in the sibling PRs for #103-#107.Pull request opened: #108
This PR implements the changes discussed in this issue. It is the rolling PR covering all six child issues of #101 — the next iteration will add #103 (
docs.updateTemplate).rawdaGastan referenced this issue2026-04-26 14:48:57 +00:00
rawdaGastan referenced this issue2026-04-26 15:06:11 +00:00
rawdaGastan referenced this issue2026-04-26 15:48:26 +00:00
rawdaGastan referenced this issue2026-04-26 16:20:59 +00:00
rawdaGastan referenced this issue2026-04-27 09:23:12 +00:00