towards multi-user
This commit is contained in:
+80
-10
@@ -70,20 +70,81 @@ def _ensure_npm(site: Path) -> None:
|
||||
subprocess.run(["npm", "install"], cwd=site, check=True)
|
||||
|
||||
|
||||
def _merge_edits(data: Path) -> None:
|
||||
"""Run the sidecar merge step, producing data/_merged/."""
|
||||
def _is_multiuser(data: Path) -> bool:
|
||||
return (data / "instance.db").exists()
|
||||
|
||||
|
||||
def _user_dirs(data: Path) -> list[Path]:
|
||||
"""Return all per-user subdirectories (contain an activities/ dir)."""
|
||||
return sorted(
|
||||
p for p in data.iterdir()
|
||||
if p.is_dir() and (p / "activities").exists()
|
||||
)
|
||||
|
||||
|
||||
def _merge_edits(data: Path, handle: str | None = None) -> None:
|
||||
"""Run the sidecar merge step for one user or all users."""
|
||||
from bincio.render.merge import merge_all
|
||||
n = merge_all(data)
|
||||
if n:
|
||||
console.print(f"Merged [cyan]{n}[/cyan] sidecar edit(s) into _merged/")
|
||||
|
||||
if _is_multiuser(data):
|
||||
targets = [data / handle] if handle else _user_dirs(data)
|
||||
total = 0
|
||||
for user_dir in targets:
|
||||
n = merge_all(user_dir)
|
||||
total += n
|
||||
console.print(f" [cyan]{user_dir.name}[/cyan]: {n} sidecar(s) merged")
|
||||
if not total:
|
||||
console.print("No sidecars found — _merged/ dirs mirror extracted data.")
|
||||
else:
|
||||
console.print("No sidecars found — _merged/ mirrors extracted data.")
|
||||
n = merge_all(data)
|
||||
if n:
|
||||
console.print(f"Merged [cyan]{n}[/cyan] sidecar edit(s) into _merged/")
|
||||
else:
|
||||
console.print("No sidecars found — _merged/ mirrors extracted data.")
|
||||
|
||||
|
||||
def _write_root_manifest(data: Path) -> None:
|
||||
"""Rewrite the root index.json shard manifest from current user dirs."""
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
users = _user_dirs(data)
|
||||
# Read existing manifest to preserve instance metadata
|
||||
root = data / "index.json"
|
||||
existing: dict = {}
|
||||
if root.exists():
|
||||
try:
|
||||
existing = json.loads(root.read_text())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
manifest = {
|
||||
"bas_version": "1.0",
|
||||
"instance": existing.get("instance", {"name": "BincioActivity", "private": True}),
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"shards": [
|
||||
{
|
||||
"handle": u.name,
|
||||
"url": f"{u.name}/_merged/index.json"
|
||||
if (u / "_merged" / "index.json").exists()
|
||||
else f"{u.name}/index.json",
|
||||
}
|
||||
for u in users
|
||||
],
|
||||
"activities": [],
|
||||
}
|
||||
root.write_text(json.dumps(manifest, indent=2))
|
||||
console.print(f"Root manifest updated: [cyan]{len(users)}[/cyan] user shard(s)")
|
||||
|
||||
|
||||
def _link_data(site: Path, data: Path) -> None:
|
||||
"""Symlink site/public/data → data/_merged/ (the post-merge output)."""
|
||||
merged = data / "_merged"
|
||||
target = merged if merged.exists() else data
|
||||
"""Symlink site/public/data → data (multi-user) or data/_merged/ (single-user)."""
|
||||
if _is_multiuser(data):
|
||||
# Multi-user: link to data root directly (each user has their own _merged/)
|
||||
target = data
|
||||
else:
|
||||
merged = data / "_merged"
|
||||
target = merged if merged.exists() else data
|
||||
public_data = site / "public" / "data"
|
||||
public_data.parent.mkdir(parents=True, exist_ok=True)
|
||||
if public_data.is_symlink():
|
||||
@@ -113,6 +174,8 @@ def _link_data(site: Path, data: Path) -> None:
|
||||
help="Start dev server with hot reload instead of building.")
|
||||
@click.option("--deploy", default=None, metavar="TARGET",
|
||||
help="Deploy after build. Currently supports: github.")
|
||||
@click.option("--handle", default=None,
|
||||
help="(Multi-user) Incrementally re-merge one user's shard only.")
|
||||
def render(
|
||||
config_path: Optional[str],
|
||||
data_dir: Optional[str],
|
||||
@@ -120,6 +183,7 @@ def render(
|
||||
out_dir: Optional[str],
|
||||
serve: bool,
|
||||
deploy: Optional[str],
|
||||
handle: Optional[str],
|
||||
) -> None:
|
||||
"""Build (or serve) the BincioActivity static site from a BAS data store."""
|
||||
|
||||
@@ -129,8 +193,14 @@ def render(
|
||||
console.print(f"Site: [cyan]{site}[/cyan]")
|
||||
console.print(f"Data: [cyan]{data}[/cyan]")
|
||||
|
||||
multiuser = _is_multiuser(data)
|
||||
if multiuser:
|
||||
console.print("[cyan]Multi-user mode[/cyan]")
|
||||
|
||||
_ensure_npm(site)
|
||||
_merge_edits(data)
|
||||
_merge_edits(data, handle=handle)
|
||||
if multiuser:
|
||||
_write_root_manifest(data)
|
||||
_link_data(site, data)
|
||||
|
||||
env = {**os.environ, "BINCIO_DATA_DIR": str(data)}
|
||||
|
||||
Reference in New Issue
Block a user