diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8bb6dc1 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +TS_RS_EXPORT_DIR = { value = "src/types/generated", relative = true } +TS_RS_LARGE_INT = "number" diff --git a/Cargo.lock b/Cargo.lock index 9ac785a..aaf9084 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,7 @@ version = "0.0.0" dependencies = [ "serde", "serde_json", + "ts-rs", "uuid", ] @@ -4438,6 +4439,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -4801,6 +4811,28 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "ts-rs" +version = "12.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756050066659291d47a554a9f558125db17428b073c5ffce1daf5dcb0f7231d8" +dependencies = [ + "thiserror 2.0.18", + "ts-rs-macros", +] + +[[package]] +name = "ts-rs-macros" +version = "12.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d90eea51bc7988ef9e674bf80a85ba6804739e535e9cab48e4bb34a8b652aa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "termcolor", +] + [[package]] name = "typeid" version = "1.0.3" diff --git a/Taskfile.yaml b/Taskfile.yaml index ee0d9ea..d394962 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -27,6 +27,24 @@ tasks: cmds: - cargo test -p adhd-ranch-domain -p adhd-ranch-storage -p adhd-ranch-commands -p adhd-ranch-http-api --all-targets + gen-types: + desc: Regenerate src/types/generated/*.ts from Rust domain via ts-rs + cmds: + - cargo test -p adhd-ranch-domain --features export-ts --quiet + + gen-types:check: + desc: Fail if generated TS types are out of sync with Rust domain + cmds: + - task: gen-types + - git diff --exit-code -- src/types/generated + - | + untracked=$(git ls-files --others --exclude-standard -- src/types/generated) + if [ -n "$untracked" ]; then + echo "Untracked generated files (commit them):" >&2 + echo "$untracked" >&2 + exit 1 + fi + test:web: desc: Run frontend tests deps: [install] @@ -72,11 +90,12 @@ tasks: - npm run fmt check: - desc: PR gate — lint + typecheck + tests + desc: PR gate — lint + typecheck + tests + ts-rs drift check cmds: - task: lint - task: typecheck - task: test + - task: gen-types:check build:web: desc: Build frontend bundle diff --git a/biome.json b/biome.json index 3e91b18..d9ebb48 100644 --- a/biome.json +++ b/biome.json @@ -1,7 +1,7 @@ { "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "files": { - "ignore": ["dist", "src-tauri", "node_modules"] + "ignore": ["dist", "src-tauri", "node_modules", "src/types/generated"] }, "organizeImports": { "enabled": true diff --git a/crates/domain/Cargo.toml b/crates/domain/Cargo.toml index ceae575..65c7f55 100644 --- a/crates/domain/Cargo.toml +++ b/crates/domain/Cargo.toml @@ -10,6 +10,10 @@ path = "src/lib.rs" [dependencies] serde = { workspace = true } serde_json = { workspace = true } +ts-rs = { version = "12", optional = true } uuid = { version = "1", features = ["v7", "serde"] } +[features] +export-ts = ["dep:ts-rs"] + [dev-dependencies] diff --git a/crates/domain/src/focus.rs b/crates/domain/src/focus.rs index 365001c..98eede9 100644 --- a/crates/domain/src/focus.rs +++ b/crates/domain/src/focus.rs @@ -21,9 +21,13 @@ impl TaskText { } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct FocusId(pub String); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Task { pub id: String, pub text: String, @@ -32,6 +36,8 @@ pub struct Task { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Focus { pub id: FocusId, pub title: String, diff --git a/crates/domain/src/lib.rs b/crates/domain/src/lib.rs index 4037714..d2f095e 100644 --- a/crates/domain/src/lib.rs +++ b/crates/domain/src/lib.rs @@ -3,6 +3,7 @@ pub mod caps; pub mod decision; pub mod error; pub mod focus; +pub mod monitor; pub mod parse; pub mod pig_rect; pub mod proposal; @@ -15,6 +16,7 @@ pub use caps::{cap_state, CapState}; pub use decision::{Decision, DecisionKind}; pub use error::DomainError; pub use focus::{Focus, FocusId, Task, TaskText}; +pub use monitor::MonitorInfo; pub use parse::{parse_focus_md, ParseError}; pub use pig_rect::{PigRect, RectUpdater}; pub use proposal::{NewFocus, Proposal, ProposalId, ProposalKind, ProposalValidationError}; diff --git a/crates/domain/src/monitor.rs b/crates/domain/src/monitor.rs new file mode 100644 index 0000000..1842f90 --- /dev/null +++ b/crates/domain/src/monitor.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] +pub struct MonitorInfo { + pub idx: usize, + pub label: String, +} diff --git a/crates/domain/src/proposal.rs b/crates/domain/src/proposal.rs index 7ebd75c..e58a5cd 100644 --- a/crates/domain/src/proposal.rs +++ b/crates/domain/src/proposal.rs @@ -4,9 +4,13 @@ use crate::error::DomainError; use crate::timer::TimerPreset; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct ProposalId(pub String); #[derive(Debug, Clone, PartialEq, Eq, Serialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct NewFocus { title: String, description: String, @@ -67,6 +71,8 @@ impl<'de> Deserialize<'de> for NewFocus { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "snake_case")] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub enum ProposalKind { AddTask { target_focus_id: String, @@ -79,6 +85,8 @@ pub enum ProposalKind { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Proposal { pub id: ProposalId, #[serde(flatten)] diff --git a/crates/domain/src/settings.rs b/crates/domain/src/settings.rs index a6390bc..1fff5bc 100644 --- a/crates/domain/src/settings.rs +++ b/crates/domain/src/settings.rs @@ -4,6 +4,8 @@ pub const DEFAULT_MAX_FOCUSES: usize = 5; pub const DEFAULT_MAX_TASKS_PER_FOCUS: usize = 7; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Widget { pub always_on_top: bool, pub confirm_delete: bool, @@ -19,6 +21,8 @@ impl Default for Widget { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Caps { pub max_focuses: usize, pub max_tasks_per_focus: usize, @@ -34,6 +38,8 @@ impl Default for Caps { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Alerts { pub system_notifications: bool, } @@ -48,6 +54,8 @@ impl Default for Alerts { /// Which monitor indices have an active overlay window. Default: primary only (index 0). #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct DisplayConfig { pub enabled_indices: Vec, } @@ -61,6 +69,8 @@ impl Default for DisplayConfig { } #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct Settings { pub caps: Caps, pub alerts: Alerts, diff --git a/crates/domain/src/timer.rs b/crates/domain/src/timer.rs index 5a1722d..ee3185e 100644 --- a/crates/domain/src/timer.rs +++ b/crates/domain/src/timer.rs @@ -1,12 +1,16 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub enum TimerStatus { Running, Expired, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub enum TimerPreset { Two, Four, @@ -30,6 +34,8 @@ impl TimerPreset { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "export-ts", derive(ts_rs::TS))] +#[cfg_attr(feature = "export-ts", ts(export))] pub struct FocusTimer { pub duration_secs: u64, pub started_at: i64, diff --git a/issues/README.md b/issues/README.md index fb9c9a1..442554b 100644 --- a/issues/README.md +++ b/issues/README.md @@ -6,7 +6,7 @@ Each issue is a self-contained vertical slice an AFK coding agent ("ralph") can Complete these before picking up any other open issue. All are unblocked and independent — grab any order. -- [ ] [036 — Generate TypeScript types from Rust via ts-rs](036-ts-types-from-rust.md) +_Queue empty — pick from open GitHub issues._ ## How to pick up an issue diff --git a/issues/036-ts-types-from-rust.md b/issues/done/036-ts-types-from-rust.md similarity index 100% rename from issues/036-ts-types-from-rust.md rename to issues/done/036-ts-types-from-rust.md diff --git a/src-tauri/src/ui_bridge/mod.rs b/src-tauri/src/ui_bridge/mod.rs index 9092214..66f34bc 100644 --- a/src-tauri/src/ui_bridge/mod.rs +++ b/src-tauri/src/ui_bridge/mod.rs @@ -250,11 +250,7 @@ pub fn update_settings( Ok(()) } -#[derive(serde::Serialize)] -pub struct MonitorInfo { - pub idx: usize, - pub label: String, -} +use adhd_ranch_domain::MonitorInfo; #[tauri::command] pub fn get_monitors(app: AppHandle) -> Vec { diff --git a/src/api/fixtureFocusReader.test.ts b/src/api/fixtureFocusReader.test.ts index 477acfc..f4e05c2 100644 --- a/src/api/fixtureFocusReader.test.ts +++ b/src/api/fixtureFocusReader.test.ts @@ -5,8 +5,14 @@ import { createFixtureFocusReader } from "./fixtureFocusReader"; describe("fixtureFocusReader", () => { it("returns the supplied focuses", async () => { const focuses: Focus[] = [ - { id: "a", title: "A", description: "", tasks: [] }, - { id: "b", title: "B", description: "", tasks: [{ id: "t1", text: "do", done: false }] }, + { id: "a", title: "A", description: "", created_at: "", tasks: [] }, + { + id: "b", + title: "B", + description: "", + created_at: "", + tasks: [{ id: "t1", text: "do", done: false }], + }, ]; const reader = createFixtureFocusReader(focuses); expect(await reader.list()).toEqual(focuses); diff --git a/src/api/tauriFocusReader.ts b/src/api/tauriFocusReader.ts index fc2896b..4bfcc22 100644 --- a/src/api/tauriFocusReader.ts +++ b/src/api/tauriFocusReader.ts @@ -18,6 +18,7 @@ function fromRust(raw: RustFocus): Focus { id: raw.id, title: raw.title, description: raw.description, + created_at: raw.created_at, tasks: raw.tasks.map((t) => ({ id: t.id, text: t.text, done: t.done ?? false })), }; } diff --git a/src/components/App.test.tsx b/src/components/App.test.tsx index 752a419..c665f26 100644 --- a/src/components/App.test.tsx +++ b/src/components/App.test.tsx @@ -40,8 +40,8 @@ vi.mock(import("../hooks/usePigMovement"), async (importOriginal) => { }); const sample: Focus[] = [ - { id: "a", title: "Customer X bug", description: "", tasks: [] }, - { id: "b", title: "API refactor", description: "", tasks: [] }, + { id: "a", title: "Customer X bug", description: "", created_at: "", tasks: [] }, + { id: "b", title: "API refactor", description: "", created_at: "", tasks: [] }, ]; function noopFocusWriter(): FocusWriter { diff --git a/src/components/EditProposalModal.test.tsx b/src/components/EditProposalModal.test.tsx index b7d42a9..b26ebf6 100644 --- a/src/components/EditProposalModal.test.tsx +++ b/src/components/EditProposalModal.test.tsx @@ -5,8 +5,8 @@ import type { Proposal } from "../types/proposal"; import { EditProposalModal } from "./EditProposalModal"; const focuses: Focus[] = [ - { id: "f1", title: "Customer X bug", description: "", tasks: [] }, - { id: "f2", title: "API refactor", description: "", tasks: [] }, + { id: "f1", title: "Customer X bug", description: "", created_at: "", tasks: [] }, + { id: "f2", title: "API refactor", description: "", created_at: "", tasks: [] }, ]; const addTaskProposal: Proposal = { diff --git a/src/components/FocusCard.test.tsx b/src/components/FocusCard.test.tsx index 185ec6c..b98bcf4 100644 --- a/src/components/FocusCard.test.tsx +++ b/src/components/FocusCard.test.tsx @@ -7,6 +7,7 @@ const focus: Focus = { id: "f1", title: "Customer X bug", description: "", + created_at: "", tasks: [{ id: "t1", text: "ship", done: false }], }; diff --git a/src/components/FocusList.test.tsx b/src/components/FocusList.test.tsx index 3c38bde..be53ccd 100644 --- a/src/components/FocusList.test.tsx +++ b/src/components/FocusList.test.tsx @@ -8,6 +8,7 @@ const sample: Focus[] = [ id: "a", title: "Customer X bug", description: "", + created_at: "", tasks: [ { id: "t1", text: "ship the fix", done: false }, { id: "t2", text: "verify on staging", done: false }, @@ -17,6 +18,7 @@ const sample: Focus[] = [ id: "b", title: "API refactor", description: "", + created_at: "", tasks: [{ id: "t3", text: "extract pipeline", done: false }], }, ]; diff --git a/src/components/PendingTray.test.tsx b/src/components/PendingTray.test.tsx index 0b2bca6..43fcb5c 100644 --- a/src/components/PendingTray.test.tsx +++ b/src/components/PendingTray.test.tsx @@ -5,7 +5,9 @@ import type { Focus } from "../types/focus"; import type { Proposal } from "../types/proposal"; import { PendingTray } from "./PendingTray"; -const focuses: Focus[] = [{ id: "f1", title: "Customer X bug", description: "", tasks: [] }]; +const focuses: Focus[] = [ + { id: "f1", title: "Customer X bug", description: "", created_at: "", tasks: [] }, +]; const addTaskProposal: Proposal = { id: "p1", diff --git a/src/components/PigDetail.test.tsx b/src/components/PigDetail.test.tsx index dca60ad..b02dbda 100644 --- a/src/components/PigDetail.test.tsx +++ b/src/components/PigDetail.test.tsx @@ -8,6 +8,7 @@ const baseFocus: Focus = { id: "pig-a", title: "Ship it", description: "", + created_at: "", tasks: [], }; @@ -96,6 +97,7 @@ describe("PigDetail task editing", () => { id: "pig-a", title: "Ship it", description: "", + created_at: "", tasks: [ { id: "t1", text: "alpha", done: false }, { id: "t2", text: "beta", done: true }, diff --git a/src/hooks/useAppState.test.tsx b/src/hooks/useAppState.test.tsx index 23786b6..d6cde86 100644 --- a/src/hooks/useAppState.test.tsx +++ b/src/hooks/useAppState.test.tsx @@ -39,7 +39,7 @@ describe("useAppState", () => { }); it("becomes ready when both focuses and proposals resolve", async () => { - const focuses: Focus[] = [{ id: "a", title: "A", description: "", tasks: [] }]; + const focuses: Focus[] = [{ id: "a", title: "A", description: "", created_at: "", tasks: [] }]; const proposals: Proposal[] = []; const { result } = renderHook(() => useAppState({ diff --git a/src/hooks/useFocuses.test.tsx b/src/hooks/useFocuses.test.tsx index 53ca05c..698012d 100644 --- a/src/hooks/useFocuses.test.tsx +++ b/src/hooks/useFocuses.test.tsx @@ -7,7 +7,9 @@ import { useFocuses } from "./useFocuses"; describe("useFocuses", () => { it("transitions loading → ready with focuses", async () => { - const reader = createFixtureFocusReader([{ id: "a", title: "A", description: "", tasks: [] }]); + const reader = createFixtureFocusReader([ + { id: "a", title: "A", description: "", created_at: "", tasks: [] }, + ]); const { result } = renderHook(() => useFocuses(reader)); expect(result.current.status).toBe("loading"); await waitFor(() => { @@ -22,10 +24,10 @@ describe("useFocuses", () => { it("re-fetches when subscribe callback fires", async () => { let callCount = 0; let trigger: (() => void) | null = null; - const focusesA: Focus[] = [{ id: "a", title: "A", description: "", tasks: [] }]; + const focusesA: Focus[] = [{ id: "a", title: "A", description: "", created_at: "", tasks: [] }]; const focusesB: Focus[] = [ - { id: "a", title: "A", description: "", tasks: [] }, - { id: "b", title: "B", description: "", tasks: [] }, + { id: "a", title: "A", description: "", created_at: "", tasks: [] }, + { id: "b", title: "B", description: "", created_at: "", tasks: [] }, ]; const reader: FocusReader = { list: () => { diff --git a/src/lib/capState.test.ts b/src/lib/capState.test.ts index a62a26c..8bb8b92 100644 --- a/src/lib/capState.test.ts +++ b/src/lib/capState.test.ts @@ -9,6 +9,7 @@ function makeFocus(id: string, taskCount: number): Focus { id, title: id, description: "", + created_at: "", tasks: Array.from({ length: taskCount }, (_, i) => ({ id: `${id}:${i}`, text: `t${i}`, diff --git a/src/types/focus.ts b/src/types/focus.ts index a7ba09c..c94c64b 100644 --- a/src/types/focus.ts +++ b/src/types/focus.ts @@ -1,12 +1,3 @@ -export interface Task { - readonly id: string; - readonly text: string; - readonly done: boolean; -} - -export interface Focus { - readonly id: string; - readonly title: string; - readonly description: string; - readonly tasks: readonly Task[]; -} +export type { Focus } from "./generated/Focus"; +export type { FocusId } from "./generated/FocusId"; +export type { Task } from "./generated/Task"; diff --git a/src/types/generated/Alerts.ts b/src/types/generated/Alerts.ts new file mode 100644 index 0000000..1379624 --- /dev/null +++ b/src/types/generated/Alerts.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Alerts = { system_notifications: boolean, }; diff --git a/src/types/generated/Caps.ts b/src/types/generated/Caps.ts new file mode 100644 index 0000000..9326a18 --- /dev/null +++ b/src/types/generated/Caps.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Caps = { max_focuses: number, max_tasks_per_focus: number, }; diff --git a/src/types/generated/DisplayConfig.ts b/src/types/generated/DisplayConfig.ts new file mode 100644 index 0000000..ff6a470 --- /dev/null +++ b/src/types/generated/DisplayConfig.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Which monitor indices have an active overlay window. Default: primary only (index 0). + */ +export type DisplayConfig = { enabled_indices: Array, }; diff --git a/src/types/generated/Focus.ts b/src/types/generated/Focus.ts new file mode 100644 index 0000000..75dcd60 --- /dev/null +++ b/src/types/generated/Focus.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FocusId } from "./FocusId"; +import type { FocusTimer } from "./FocusTimer"; +import type { Task } from "./Task"; + +export type Focus = { id: FocusId, title: string, description: string, created_at: string, tasks: Array, timer?: FocusTimer | null, }; diff --git a/src/types/generated/FocusId.ts b/src/types/generated/FocusId.ts new file mode 100644 index 0000000..1a42408 --- /dev/null +++ b/src/types/generated/FocusId.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FocusId = string; diff --git a/src/types/generated/FocusTimer.ts b/src/types/generated/FocusTimer.ts new file mode 100644 index 0000000..e380df6 --- /dev/null +++ b/src/types/generated/FocusTimer.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TimerStatus } from "./TimerStatus"; + +export type FocusTimer = { duration_secs: number, started_at: number, status: TimerStatus, }; diff --git a/src/types/generated/MonitorInfo.ts b/src/types/generated/MonitorInfo.ts new file mode 100644 index 0000000..61d364d --- /dev/null +++ b/src/types/generated/MonitorInfo.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MonitorInfo = { idx: number, label: string, }; diff --git a/src/types/generated/NewFocus.ts b/src/types/generated/NewFocus.ts new file mode 100644 index 0000000..46e0d12 --- /dev/null +++ b/src/types/generated/NewFocus.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TimerPreset } from "./TimerPreset"; + +export type NewFocus = { title: string, description: string, timer_preset?: TimerPreset | null, }; diff --git a/src/types/generated/Proposal.ts b/src/types/generated/Proposal.ts new file mode 100644 index 0000000..c5e1234 --- /dev/null +++ b/src/types/generated/Proposal.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NewFocus } from "./NewFocus"; +import type { ProposalId } from "./ProposalId"; + +export type Proposal = { id: ProposalId, summary: string, reasoning: string, created_at: string, } & ({ "kind": "add_task", target_focus_id: string, task_text: string, } | { "kind": "new_focus", new_focus: NewFocus, } | { "kind": "discard" }); diff --git a/src/types/generated/ProposalId.ts b/src/types/generated/ProposalId.ts new file mode 100644 index 0000000..bad6190 --- /dev/null +++ b/src/types/generated/ProposalId.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ProposalId = string; diff --git a/src/types/generated/ProposalKind.ts b/src/types/generated/ProposalKind.ts new file mode 100644 index 0000000..0dd666b --- /dev/null +++ b/src/types/generated/ProposalKind.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NewFocus } from "./NewFocus"; + +export type ProposalKind = { "kind": "add_task", target_focus_id: string, task_text: string, } | { "kind": "new_focus", new_focus: NewFocus, } | { "kind": "discard" }; diff --git a/src/types/generated/Settings.ts b/src/types/generated/Settings.ts new file mode 100644 index 0000000..70fae89 --- /dev/null +++ b/src/types/generated/Settings.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Alerts } from "./Alerts"; +import type { Caps } from "./Caps"; +import type { DisplayConfig } from "./DisplayConfig"; +import type { Widget } from "./Widget"; + +export type Settings = { caps: Caps, alerts: Alerts, widget: Widget, displays: DisplayConfig, }; diff --git a/src/types/generated/Task.ts b/src/types/generated/Task.ts new file mode 100644 index 0000000..431935c --- /dev/null +++ b/src/types/generated/Task.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Task = { id: string, text: string, done: boolean, }; diff --git a/src/types/generated/TimerPreset.ts b/src/types/generated/TimerPreset.ts new file mode 100644 index 0000000..255f8cd --- /dev/null +++ b/src/types/generated/TimerPreset.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type TimerPreset = "Two" | "Four" | "Eight" | "Sixteen" | "ThirtyTwo" | { "Custom": number }; diff --git a/src/types/generated/TimerStatus.ts b/src/types/generated/TimerStatus.ts new file mode 100644 index 0000000..83ee37c --- /dev/null +++ b/src/types/generated/TimerStatus.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type TimerStatus = "Running" | "Expired"; diff --git a/src/types/generated/Widget.ts b/src/types/generated/Widget.ts new file mode 100644 index 0000000..2cacb47 --- /dev/null +++ b/src/types/generated/Widget.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Widget = { always_on_top: boolean, confirm_delete: boolean, }; diff --git a/src/types/monitor.ts b/src/types/monitor.ts index 8968410..cc2bfdb 100644 --- a/src/types/monitor.ts +++ b/src/types/monitor.ts @@ -1,4 +1 @@ -export interface MonitorInfo { - readonly idx: number; - readonly label: string; -} +export type { MonitorInfo } from "./generated/MonitorInfo"; diff --git a/src/types/proposal.ts b/src/types/proposal.ts index c688db1..c8a7710 100644 --- a/src/types/proposal.ts +++ b/src/types/proposal.ts @@ -1,16 +1,4 @@ -export interface NewFocus { - readonly title: string; - readonly description: string; -} - -export type ProposalKind = - | { readonly kind: "add_task"; readonly target_focus_id: string; readonly task_text: string } - | { readonly kind: "new_focus"; readonly new_focus: NewFocus } - | { readonly kind: "discard" }; - -export type Proposal = ProposalKind & { - readonly id: string; - readonly summary: string; - readonly reasoning: string; - readonly created_at: string; -}; +export type { NewFocus } from "./generated/NewFocus"; +export type { Proposal } from "./generated/Proposal"; +export type { ProposalId } from "./generated/ProposalId"; +export type { ProposalKind } from "./generated/ProposalKind"; diff --git a/src/types/settings.ts b/src/types/settings.ts index dd27f36..3762bac 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -1,24 +1,5 @@ -export interface Caps { - readonly max_focuses: number; - readonly max_tasks_per_focus: number; -} - -export interface Alerts { - readonly system_notifications: boolean; -} - -export interface Widget { - readonly always_on_top: boolean; - readonly confirm_delete: boolean; -} - -export interface DisplayConfig { - readonly enabled_indices: readonly number[]; -} - -export interface Settings { - readonly caps: Caps; - readonly alerts: Alerts; - readonly widget: Widget; - readonly displays: DisplayConfig; -} +export type { Alerts } from "./generated/Alerts"; +export type { Caps } from "./generated/Caps"; +export type { DisplayConfig } from "./generated/DisplayConfig"; +export type { Settings } from "./generated/Settings"; +export type { Widget } from "./generated/Widget"; diff --git a/src/types/timer.ts b/src/types/timer.ts index adf011a..0625e2c 100644 --- a/src/types/timer.ts +++ b/src/types/timer.ts @@ -1,14 +1,10 @@ -export type TimerPresetVariant = "Two" | "Four" | "Eight" | "Sixteen" | "ThirtyTwo"; +import type { TimerPreset } from "./generated/TimerPreset"; -export type TimerPreset = TimerPresetVariant | { Custom: number }; // minutes +export type { FocusTimer } from "./generated/FocusTimer"; +export type { TimerPreset } from "./generated/TimerPreset"; +export type { TimerStatus } from "./generated/TimerStatus"; -export type TimerStatus = "Running" | "Expired"; - -export interface FocusTimer { - readonly duration_secs: number; - readonly started_at: number; - readonly status: TimerStatus; -} +export type TimerPresetVariant = Exclude; export const PRESET_OPTIONS: Array<{ label: string; value: TimerPreset | null }> = [ { label: "No timer", value: null }, @@ -17,5 +13,5 @@ export const PRESET_OPTIONS: Array<{ label: string; value: TimerPreset | null }> { label: "8m", value: "Eight" }, { label: "16m", value: "Sixteen" }, { label: "32m", value: "ThirtyTwo" }, - { label: "Custom", value: null }, // placeholder — custom uses number input + { label: "Custom", value: null }, ];