chore: extract fj-core shared types + issue-template parsing (FJ-7) #8

Merged
David merged 1 commit from chore/extract-fj-core-fj-7 into main 2026-05-25 15:53:28 +02:00
Owner

Summary

FJ-7 / FJ-3 Phase 3 of 5: stand up crates/fj-core with the shared repo-name types and the issue-template parser. Pure types and parsing only; per-command operations and network calls stay in the binary (Phase 4). Closes FJ-7.

Moved into fj-core

  • RepoName, RepoArg, RepoArgError from crates/fj/src/repo.rs -> crates/fj-core/src/repo.rs.
  • TemplateMetadata, MarkdownTemplate (+ MarkdownTemplate::new) from crates/fj/src/issues/template.rs -> crates/fj-core/src/template.rs.
  • The comrak-based YAML form parser crates/fj/src/issues/template/yaml.rs -> crates/fj-core/src/template/yaml.rs via git rename (byte-for-byte, including its MD_OPTIONS static and the YamlTemplate / TemplateItem / FieldValue types).

De-fluented at the crate boundary

RepoArgError's Display previously called ftl_write!("msg-repo-arg_no_owner"). In fj-core it writes the plain non-localized string repo name should be in the format [HOST/]OWNER/NAME, so fj-core stays fluent-free. The localization key is left in place so the binary can map RepoArgError to the localized message at the user boundary later if wanted.

API surface change

RepoName and RepoArg fields are private to fj-core, so RepoArg gains host() / owner() / name() accessors (RepoName already had owner() / name() / new()). The binary's RepoInfo::get_current and url_strip_repo_name now build RepoName via RepoName::new(..) and read RepoArg through the accessors instead of touching private fields.

Kept in crates/fj

RepoInfo / RepoInfo::get_current (git2 + auth-git2 + fluent), the entire clap command surface (RepoCommand, RepoCreateArgs, UnitsSubcommand, ...), the network op get_template_file, and the interactive generate_from_template ($EDITOR loop). The binary re-exports the moved types under the historical crate::repo::* and crate::issues::template::* paths so the rest of the source compiles unchanged.

Dependencies

fj-core depends on fj-client, comrak (default-features = false), eyre, regex, serde (derive), serde-saphyr. No clap / crossterm / fluent-*; no direct git2 / auth-git2. forgejo-api, serde_json, and url from the issue's suggested dep list are omitted as direct deps because the moved code references none of them directly; forgejo-api remains available transitively via fj-client should Phase 4 need it.

Verification

  • cargo build --locked (workspace) and cargo build -p fj-core (standalone) both succeed.
  • cargo tree -p fj-core -e normal | grep -E 'clap|crossterm|fluent' prints nothing.
  • cargo fmt --check clean; cargo clippy --all-targets -- -D warnings clean; cargo test passes.
  • Template-driven flows (markdown + YAML, interactive + --body) were not exercised against a live Forgejo in this run, but the parser moved as a byte-identical git rename and generate_from_template is unchanged, so behavior is preserved.

🤖 Generated with Claude Code

## Summary FJ-7 / FJ-3 Phase 3 of 5: stand up `crates/fj-core` with the shared repo-name types and the issue-template parser. Pure types and parsing only; per-command operations and network calls stay in the binary (Phase 4). Closes FJ-7. ## Moved into `fj-core` - `RepoName`, `RepoArg`, `RepoArgError` from `crates/fj/src/repo.rs` -> `crates/fj-core/src/repo.rs`. - `TemplateMetadata`, `MarkdownTemplate` (+ `MarkdownTemplate::new`) from `crates/fj/src/issues/template.rs` -> `crates/fj-core/src/template.rs`. - The comrak-based YAML form parser `crates/fj/src/issues/template/yaml.rs` -> `crates/fj-core/src/template/yaml.rs` via git rename (byte-for-byte, including its `MD_OPTIONS` static and the `YamlTemplate` / `TemplateItem` / `FieldValue` types). ## De-fluented at the crate boundary `RepoArgError`'s `Display` previously called `ftl_write!("msg-repo-arg_no_owner")`. In fj-core it writes the plain non-localized string `repo name should be in the format [HOST/]OWNER/NAME`, so fj-core stays fluent-free. The localization key is left in place so the binary can map `RepoArgError` to the localized message at the user boundary later if wanted. ## API surface change `RepoName` and `RepoArg` fields are private to fj-core, so `RepoArg` gains `host()` / `owner()` / `name()` accessors (`RepoName` already had `owner()` / `name()` / `new()`). The binary's `RepoInfo::get_current` and `url_strip_repo_name` now build `RepoName` via `RepoName::new(..)` and read `RepoArg` through the accessors instead of touching private fields. ## Kept in `crates/fj` `RepoInfo` / `RepoInfo::get_current` (git2 + auth-git2 + fluent), the entire clap command surface (`RepoCommand`, `RepoCreateArgs`, `UnitsSubcommand`, ...), the network op `get_template_file`, and the interactive `generate_from_template` (`$EDITOR` loop). The binary re-exports the moved types under the historical `crate::repo::*` and `crate::issues::template::*` paths so the rest of the source compiles unchanged. ## Dependencies fj-core depends on `fj-client`, `comrak` (default-features = false), `eyre`, `regex`, `serde` (derive), `serde-saphyr`. No `clap` / `crossterm` / `fluent-*`; no direct `git2` / `auth-git2`. `forgejo-api`, `serde_json`, and `url` from the issue's suggested dep list are omitted as direct deps because the moved code references none of them directly; `forgejo-api` remains available transitively via fj-client should Phase 4 need it. ## Verification - `cargo build --locked` (workspace) and `cargo build -p fj-core` (standalone) both succeed. - `cargo tree -p fj-core -e normal | grep -E 'clap|crossterm|fluent'` prints nothing. - `cargo fmt --check` clean; `cargo clippy --all-targets -- -D warnings` clean; `cargo test` passes. - Template-driven flows (markdown + YAML, interactive + `--body`) were not exercised against a live Forgejo in this run, but the parser moved as a byte-identical git rename and `generate_from_template` is unchanged, so behavior is preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chore: extract fj-core shared types + issue-template parsing (FJ-7)
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 35s
Create release / Create release from merged PR (pull_request) Has been skipped
8d1e5a22b1
FJ-3 Phase 3 of 5: stand up crates/fj-core with the shared repo-name types and the issue-template parser. Pure types and parsing only; per-command operations and network calls stay in the binary (Phase 4).

Moved into fj-core: RepoName, RepoArg, and RepoArgError from crates/fj/src/repo.rs (now crates/fj-core/src/repo.rs); TemplateMetadata and MarkdownTemplate (with MarkdownTemplate::new) from crates/fj/src/issues/template.rs (now crates/fj-core/src/template.rs); and the comrak-based YAML form parser crates/fj/src/issues/template/yaml.rs (now crates/fj-core/src/template/yaml.rs via git rename, byte-for-byte including its MD_OPTIONS static and YamlTemplate / TemplateItem / FieldValue types).

De-fluented at the crate boundary: RepoArgError's Display previously called ftl_write!("msg-repo-arg_no_owner"); in fj-core it writes the plain non-localized string "repo name should be in the format [HOST/]OWNER/NAME". fj-core stays fluent-free. The localization key is left in place so the binary can map RepoArgError to the localized message at the user boundary later if wanted.

API surface: RepoName and RepoArg fields are private to fj-core, so RepoArg gains host()/owner()/name() accessors (RepoName already had owner()/name()/new()). The binary's RepoInfo::get_current and url_strip_repo_name now build RepoName via RepoName::new(..) and read RepoArg via the accessors instead of touching private fields.

Kept in crates/fj: RepoInfo / RepoInfo::get_current (git2 + auth-git2 + fluent), the whole clap command surface (RepoCommand, RepoCreateArgs, UnitsSubcommand, ...), the network op get_template_file, and the interactive generate_from_template ($EDITOR loop). The binary re-exports the moved types under the historical crate::repo::* and crate::issues::template::* paths (pub use fj_core::{RepoArg, RepoArgError, RepoName} and pub use fj_core::template::{yaml, MarkdownTemplate, TemplateMetadata}) so the rest of the source compiles unchanged.

fj-core dependencies: fj-client, comrak (default-features = false), eyre, regex, serde (derive), serde-saphyr. No clap / crossterm / fluent-*; no direct git2 / auth-git2. forgejo-api, serde_json, and url from the issue's suggested dep list are omitted as direct deps because the moved code references none of them directly; forgejo-api remains available transitively via fj-client should Phase 4 need it.

Verified: cargo build --locked (workspace) and cargo build -p fj-core (standalone) both succeed; cargo tree -p fj-core -e normal | grep -E 'clap|crossterm|fluent' prints nothing; cargo fmt --check is clean; clippy --all-targets -- -D warnings is clean; cargo test passes. The template-driven flows (markdown + YAML, interactive + --body) were not exercised against a live Forgejo in this run, but the parser moved as a byte-identical git rename and generate_from_template is unchanged, so behavior is preserved.

#FJ-7 State Done

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
David merged commit 237aadc0eb into main 2026-05-25 15:53:28 +02:00
David deleted branch chore/extract-fj-core-fj-7 2026-05-25 15:53:28 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/forgejo-cli!8
No description provided.