Files
publisher-dashboard/CLAUDE.md
igm 848d9e9af1 Add db-dump and db-migrate scripts to strip \restrict lines
PostgreSQL 17.6+ adds random \restrict/\unrestrict tokens to pg_dump
output (CVE-2025-8714 security fix), causing schema.sql to appear
changed on every dump even when the schema hasn't changed.

These wrapper scripts run dbmate and strip the \restrict lines from
the output to keep schema.sql stable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 12:33:20 +08:00

2.8 KiB

Claude Code Notes

Database Scripts

Use the wrapper scripts instead of running dbmate directly:

  • ./scripts/db-dump - Dump schema without random \restrict tokens
  • ./scripts/db-migrate - Run migrations and dump clean schema

PostgreSQL 17.6+ adds random \restrict/\unrestrict lines to pg_dump output (CVE-2025-8714 fix), causing schema.sql to show as changed on every dump. These scripts strip those lines.

Development Server

Before starting the dev server, check if it's already running:

  • Use lsof -i :6827 or check for existing background tasks
  • The dev server runs on port 6827 (may fall back to 6828 if port is in use)
  • Start with bun run --cwd apps/publisher-dashboard dev or devenv up

Pull Requests

This repo uses Gitea (git.rev.iq) with the tea CLI for pull requests:

  • Use the /gitea skill when creating PRs
  • tea 0.10.1 is pinned in nix/tea.nix (0.11.x has TTY bugs)
  • Always specify -r igm/publisher-dashboard flag (SSH remote auto-detection doesn't work)

macOS sed Syntax

macOS uses BSD sed which differs from GNU sed:

  • In-place edit requires empty string for backup: sed -i '' 's/old/new/g' file
  • GNU sed (Linux): sed -i 's/old/new/g' file
  • Use | as delimiter when patterns contain /: sed -i '' 's|old/path|new/path|g' file
  • For multiple files: for f in *.txt; do sed -i '' 's/old/new/g' "$f"; done

SvelteKit resolve() Usage

Use resolve() from $app/paths for type-safe navigation. The patterns are:

Static routes - use resolve() directly

href={resolve("/auth/login")}
href={resolve("/dashboard")}

Dynamic routes - use two-argument form

href={resolve("/dashboard/[slug]", { slug: orgSlug })}
href={resolve("/account/org-invites/[inviteId]", { inviteId: String(invite.id) })}

Login redirects - use gotoLogin helper

For redirecting to login with a return URL, use the helper from $lib/utils/navigation:

import { gotoLogin } from "$lib/utils/navigation";

gotoLogin(page.url.pathname);

This helper uses resolve() internally and handles the query string correctly.

Navigation arrays - use as const with route patterns

For type-safe navigation arrays, define routes as literal strings with as const:

const navItems = [
  { route: "/dashboard/[slug]/settings", icon: Settings, label: "General" },
  { route: "/dashboard/[slug]/settings/members", icon: Users, label: "Members" },
] as const;

Then use resolve with params:

{#each navItems as item (item.route)}
  <a href={resolve(item.route, { slug })}>
{/each}

Runtime strings - skip resolve, use eslint-disable

When paths are fully dynamic (e.g., server-provided redirects), skip resolve:

// eslint-disable-next-line svelte/no-navigation-without-resolve
goto(redirectUrl);