wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<!--
  What this repository commits about itself: `.wsb/repo.json` — its name, the
  alias other repositories' templates know it by, where its templates look,
  and how its version is made. Saved whole, as the file is; the change is in
  the next commit like any other.
-->
<script lang="ts">
  import type { RepoSettings } from "../../api/client.js";
  import { settings } from "../../stores/settings.svelte.js";
  import SettingsSection from "./SettingsSection.svelte";

  /** One per line, blank lines dropped. */
  function lines(text: string): string[] {
    return text
      .split("\n")
      .map((line) => line.trim())
      .filter((line) => line.length > 0);
  }

  function draftOf(held: RepoSettings | undefined) {
    return {
      name: held?.name ?? "",
      alias: held?.alias ?? "",
      templatesRoot: held?.templates_root ?? ".",
      major: held?.version.major ?? 0,
      file: held?.version.file ?? "version.txt",
      suffix: held?.version.suffix ?? "",
      detect: held?.version.detect_manifests ?? true,
      manifests: (held?.version.manifests ?? []).join("\n"),
    };
  }

  const held = $derived(settings.repo?.settings);
  let draft = $state(draftOf(undefined));
  $effect(() => {
    draft = draftOf(held);
  });

  const written = $derived<RepoSettings>({
    name: draft.name.trim(),
    alias: draft.alias.trim(),
    templates_root: draft.templatesRoot.trim(),
    version: {
      major: draft.major,
      file: draft.file.trim(),
      suffix: draft.suffix.trim() || null,
      detect_manifests: draft.detect,
      manifests: lines(draft.manifests),
    },
  });
  const dirty = $derived(JSON.stringify(draftOf(held)) !== JSON.stringify(draft));

  async function save() {
    await settings.save({ repo: written });
  }
</script>

<SettingsSection
  title="Repository"
  description="What this repository commits about itself, in {settings.repo?.path ?? '.wsb/repo.json'}."
>
  <div class="settings-form">
    <label class="field">
      <span class="field-label">Name</span>
      <input class="field-input" bind:value={draft.name} />
    </label>
    <label class="field">
      <span class="field-label">Alias — what other repositories' templates call it</span>
      <input class="field-input" bind:value={draft.alias} />
    </label>
    <label class="field">
      <span class="field-label">Templates root — where its templates look for the repositories they name</span>
      <input class="field-input" bind:value={draft.templatesRoot} />
    </label>
    <div class="settings-row">
      <label class="field">
        <span class="field-label">Major version</span>
        <input class="field-input" type="number" min="0" bind:value={draft.major} />
      </label>
      <label class="field">
        <span class="field-label">Version file</span>
        <input class="field-input" bind:value={draft.file} />
      </label>
      <label class="field">
        <span class="field-label">Suffix</span>
        <input class="field-input" placeholder="none" bind:value={draft.suffix} />
      </label>
    </div>
    <label class="check">
      <input type="checkbox" bind:checked={draft.detect} />
      The manifests at the repository's root (Cargo.toml, package.json, …) carry the version
    </label>
    <label class="field">
      <span class="field-label">Further manifests that carry it, one per line</span>
      <textarea class="field-input" rows="3" bind:value={draft.manifests}></textarea>
    </label>
    {#if dirty}
      <div class="button-row">
        <button class="primary" disabled={settings.saving} onclick={() => void save()}>
          {settings.saving ? "Saving…" : "Save"}
        </button>
        <button class="secondary" onclick={() => (draft = draftOf(held))}>Discard</button>
      </div>
    {/if}
  </div>
</SettingsSection>

<style>
  .settings-form {
    display: flex;
    flex-direction: column;
    gap: var(--wb-spacing-10);
  }

  .settings-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--wb-spacing-10);
  }
</style>