diff --git a/AGENTS.md b/AGENTS.md index 726ddb0b5..69919acdf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,138 +1,243 @@ -# Appwrite Console - Copilot Instructions +# Appwrite Console -## Repository Overview +SvelteKit web dashboard for Appwrite. Manages projects, databases, functions, auth, storage, messaging, and sites. Static SPA (no SSR) served behind Nginx at `/console`. -Appwrite Console is the web-based GUI for the Appwrite backend-as-a-service platform. Single-page application built with -**Svelte 5 + SvelteKit 2**, **TypeScript** (not strict mode), **Vite 7**, tested with **Vitest + Playwright**. Package -manager/runtime: **Bun** (Node 20+ optional for tooling). ~1500 files with extensive component-based architecture. +## Commands -## Critical Build & Test Commands +All commands use **bun** (not pnpm/npm). Use `bun run +``` -**Unit (Bun test)**: Tests in `src/lib/helpers/*.test.ts`, run with `TZ=EST` (timezone matters). Setup mocks SvelteKit ( -`$app/*`) in `bun-test-setup.ts` via `bunfig.toml`. -**E2E (Playwright)**: Tests in `e2e/journeys/*.spec.ts`, needs build+preview on port 4173, retries 3x, timeout 120s, -Chromium only. +Runes (Svelte 5 -- preferred for new and modified code): -## Common Pitfalls +```svelte + +``` -## Code Conventions +### SDK usage (`src/lib/stores/sdk.ts`) -- Imports: Use `$lib`, `$routes`, `$themes` aliases -- Components: PascalCase, in `src/lib/components/[feature]/` -- Helpers: Pure functions in `src/lib/helpers/` -- Types: Inline or `.d.ts`, not `.types.ts` files -- Comments: Minimal, use for TODOs or complex logic -- TypeScript: Not strict mode, `any` tolerated +Four client instances: `clientConsole` (console API), `scopedConsoleClient` (region-scoped console API, used by `forConsoleIn()`), `clientProject` (project API, admin mode), `clientRealtime` (realtime subscriptions). Region-aware endpoints with subdomain routing (fra., nyc., syd., sfo., sgp., tor.). -## Workflow +```typescript +import { sdk } from '$lib/stores/sdk'; -1. Run Appwrite backend locally (see [docs](https://appwrite.io/docs/advanced/self-hosting)) -2. Configure `.env` with backend endpoint -3. `bun install --frozen-lockfile` -4. `bun run dev` (hot reload on port 3000) -5. Before commit: `bun run check && bun run format && bun run lint && bun run test && bun run build` -6. **Take screenshots**: For any UI changes, capture screenshots and include them in the PR description or comments - before finalizing +// Console-level operations +await sdk.forConsole.account.get(); -## Required Pre-Completion Checklist +// Region-scoped console operations +await sdk.forConsoleIn(region).projects.get({ projectId }); -**CRITICAL**: Before finishing any work or marking a task complete, agents MUST run the following commands in order and -ensure all pass: +// Project-level operations (admin mode) +await sdk.forProject(region, projectId).tablesDB.listTables(); +``` -1. **`bun run format`** - Auto-fix all formatting issues -2. **`bun run check`** - Verify TypeScript/Svelte types (must show 0 errors, 0 warnings) -3. **`bun run lint`** - Check code style (ignore pre-existing issues in files you didn't modify) -4. **`bun run test`** - Run all unit tests (all tests must pass) -5. **`bun run build`** - Ensure production build succeeds +### Database types (feat-dedicated-db) -If any command fails: +The databases feature unifies multiple database backends behind a polymorph API (`$database/(entity)/helpers/sdk.ts`): -- **Format/Lint**: Run `bun run format` to auto-fix, then re-check -- **Type errors**: Fix all TypeScript errors in files you modified -- **Test failures**: Fix failing tests or ensure failures are unrelated to your changes -- **Build failures**: Debug and resolve build issues before proceeding +| Type | Entity | Field | Record | Status | +| ------------- | ---------- | --------- | -------- | ------------------------ | +| `tablesdb` | table | column | row | Implemented | +| `documentsdb` | collection | attribute | document | Implemented | +| `vectorsdb` | -- | -- | -- | Not yet implemented | +| `dedicateddb` | table | column | row | Cross-repo (cloud/edge) | -**Never skip these checks** - they are mandatory quality gates before any work is considered complete. +- `useDatabaseSdk()` returns a unified interface regardless of backing type +- `useTerminology()` returns singular/plural names for the current database type -**Trust these instructions** - only search if incomplete/incorrect. See CONTRIBUTING.md for PR conventions. Use -`--frozen-lockfile` always. Docker builds: multi-stage, final image is nginx serving static files from `/console` path. +### Data loading + +Load functions declare dependencies for cache invalidation via `depends()`: + +```typescript +export const load: LayoutLoad = async ({ depends, parent, params }) => { + depends(Dependencies.DATABASE); + return { database: await sdk.forProject(...).tablesDB.get(...) }; +}; +``` + +Invalidate with `await invalidate(Dependencies.DATABASE)` after mutations. The `Dependencies` enum in `src/lib/constants.ts` defines 66+ keys for fine-grained cache invalidation (e.g. `DATABASES`, `TABLES`, `FUNCTIONS`, `USERS`, `DEPLOYMENTS`). + +### State management + +Stores in `src/lib/stores/` -- writable, derived, and "conservative" (selective update via `createConservative()` from `$lib/helpers/stores`) patterns. Key stores: `app`, `user`, `organization`, `projects`, `billing`, `wizard`, `notifications`, `sdk`. + +### Wizard pattern (`$lib/stores/wizard`) + +Modal wizard flow: `wizard.start(Component, media?, step?, props?)` to open, `wizard.hide()` to close. Methods: `setInterceptor(callback)` for async pre-step validation, `setNextDisabled(bool)` for flow control, `setStep(n)` / `updateStep(cb)` for navigation, `showCover(Component)` for overlays. + +### Notifications (`$lib/stores/notifications`) + +```typescript +import { addNotification } from '$lib/stores/notifications'; +addNotification({ type: 'error', message: error.message }); +``` + +Types: `'success' | 'error' | 'info' | 'warning'`. Auto-dismisses after 6s. Max 5 visible. + +### Analytics (`$lib/actions/analytics`) + +Plausible + custom Growth endpoint. Track events via `trackEvent(Click.* | Submit.*, data)` and errors via `trackError(exception, Submit.*)`. Respects `navigator.doNotTrack`. + +### Theming and modes + +Four theme variants in `src/themes/`: `light`, `dark`, `light-cloud`, `dark-cloud`. Resolved based on `isCloud` flag and user preference. Two modes (`src/lib/system.ts`): `cloud` and `self-hosted`, set via `PUBLIC_CONSOLE_MODE` env var. Gate features using `isCloud` (for cloud-only) or `isSelfHosted` (for self-hosted-only). + +## Code style + +- **Formatter:** Prettier -- 4 spaces, single quotes, no trailing commas, 100 char width, bracket same line +- **Prefer Svelte 5 runes** in new and modified code (`$props()`, `$state()`, `$derived()`, `$effect()`) +- Types from `@appwrite.io/console` SDK (`Models`, `Query`, enums) -- don't redefine what the SDK provides +- Error handling: try/catch with `addNotification()` for user-facing errors, `trackError()` for analytics +- Queries use the SDK's `Query` builder: `Query.equal()`, `Query.limit()`, `Query.offset()`, etc. +- Mark tech debt with `@todo` annotations, never `@fixme` +- Don't add new dependencies without consulting the team + +## Environment variables + +Set via `.env` (copy `.env.example`). All prefixed with `PUBLIC_` for SvelteKit: + +| Variable | Default | Purpose | +| ------------------------------------ | --------------------- | ------------------------------ | +| `PUBLIC_CONSOLE_MODE` | `self-hosted` | `cloud` or `self-hosted` | +| `PUBLIC_APPWRITE_ENDPOINT` | `http://localhost/v1` | API endpoint | +| `PUBLIC_APPWRITE_MULTI_REGION` | `false` | Multi-region support | +| `PUBLIC_STRIPE_KEY` | -- | Stripe public key (cloud only) | +| `PUBLIC_GROWTH_ENDPOINT` | -- | Analytics endpoint | +| `PUBLIC_CONSOLE_FEATURE_FLAGS` | -- | Feature flags | +| `PUBLIC_CONSOLE_EMAIL_VERIFICATION` | `false` | Require email verification | +| `PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS` | `true` | Mock AI in dev | + +## Common pitfalls + +- **Blank page in dev:** Disable ad blockers if seeing "Failed to fetch dynamically imported module" +- **OOM on build:** Set `NODE_OPTIONS=--max_old_space_size=8192` +- **Test failures:** Always use `bun run tests` (runs test:unit with TZ=EST, plus test:e2e), not `bun test` directly +- **TS errors not showing:** Run `bun run check` explicitly (dev server doesn't always surface them) +- **Format vs lint conflicts:** Run `bun run format` before `bun run lint` +- **Stale build:** Clear `.svelte-kit` if changes not reflected: `rm -rf .svelte-kit && bun run build` + +## Branch naming + +`TYPE-ISSUE_ID-DESCRIPTION` (e.g. `feat-548-add-backup-ui`). Types: feat, fix, doc, cicd, refactor. + +## Cross-repo context + +The `feat-dedicated-db` feature spans cloud, edge, and console. When modifying API contracts or response models, check the other repos for breaking changes. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..6fd2fb21c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,2 @@ + +@AGENTS.md