Company listing, authentication, and page error handling are all working
This commit is contained in:
+140
-39
@@ -1,56 +1,157 @@
|
||||
# Copilot Instructions — electron-svelte (SveltronKit)
|
||||
# Copilot Instructions for ttscm-ui
|
||||
|
||||
This repo is an Electron + SvelteKit app (SveltronKit). The goal of this document is to give an AI coding agent immediate, actionable knowledge about architecture, conventions, and common tasks so suggestions and changes are correct and context-aware.
|
||||
## Project Overview
|
||||
|
||||
Big picture
|
||||
**ttscm-ui** is an Electron desktop application built with **SvelteKit**, TypeScript, and Vite. It connects to the Optima API for credential and company management. The app uses standard SvelteKit routing for single-page navigation and pnpm for package management with patches applied to SvelteKit.
|
||||
|
||||
- App = Electron main + SvelteKit renderer. See [electron/main.ts](electron/main.ts) and renderer sources under `src/`.
|
||||
- Renderer is a normal SvelteKit app but configured to use the hash router — all routed links expected in the app should begin with `#/` when constructing absolute links for the packaged Electron app (see README).
|
||||
- Electron main process loads the Vite dev server when `MAIN_WINDOW_VITE_DEV_SERVER_URL` is set; otherwise loads the built renderer. See [electron/main.ts](electron/main.ts).
|
||||
## Architecture Layers
|
||||
|
||||
How to run & build (developer workflows)
|
||||
### Electron Architecture
|
||||
|
||||
- Uses pnpm. Always use `pnpm install` first.
|
||||
- Dev (runs Electron + Vite via Electron Forge): `pnpm run start` (invokes `electron-forge start`).
|
||||
- Build & package: `pnpm run package` (builds renderer with `vite build` then runs `electron-forge package`).
|
||||
- Create distributable: `pnpm run make`.
|
||||
- Tests: unit tests via `vitest` and e2e via Playwright. `pnpm run test` runs both (`test:unit` and `test:e2e`). See `package.json` scripts.
|
||||
- **`electron/main.ts`**: Main process—creates/manages windows, handles file system access. Loads preload script and serves the renderer.
|
||||
- **`electron/preload.ts`**: Currently empty bridge between main and renderer processes. Extend here to expose secure IPC handlers if needed.
|
||||
- **`forge.config.ts`**: Electron Forge configuration with Vite plugin for building main, preload, and renderer targets.
|
||||
|
||||
Key files & patterns to reference
|
||||
### Frontend (SvelteKit)
|
||||
|
||||
- Electron bootstrap: [electron/main.ts](electron/main.ts) — env vars used: `MAIN_WINDOW_VITE_DEV_SERVER_URL`, `MAIN_WINDOW_VITE_NAME`.
|
||||
- Preload bridge: [electron/preload.ts](electron/preload.ts) (currently empty) — add safe, whitelisted APIs here when exposing functionality to the renderer.
|
||||
- SvelteKit entry routes: `src/routes/` (examples: [src/routes/+page.svelte](src/routes/+page.svelte), [src/routes/companies/+page.svelte](src/routes/companies/+page.svelte)).
|
||||
- API client: [src/lib/axios.ts](src/lib/axios.ts) — `api` is created from `PUBLIC_API_URL` ($env/static/public).
|
||||
- Auth helper: [src/lib/authUri.ts](src/lib/authUri.ts) — example of calling backend `/v1/auth/uri`.
|
||||
- Data access: [src/lib/companies.ts](src/lib/companies.ts) — `fetchMany(accessToken)` demonstrates header usage `Authorization: Bearer <token>`.
|
||||
- Global styles: `src/app.css` (Tailwind is present in the project).
|
||||
- Patches: `patches/` contains `@sveltejs__kit.patch` and is referenced in `package.json` via `patchedDependencies` — don't remove or ignore without verifying its purpose.
|
||||
- **`src/routes/`**: SvelteKit file-based routing with standard pathname router.
|
||||
- `(auth)` group: Authentication pages (login)
|
||||
- `(secure)` group: Protected pages requiring auth
|
||||
- **`src/lib/`**: Reusable modules
|
||||
- `optima-api/`: API client abstraction with modular endpoints (auth, companies, credentials, etc.)
|
||||
- `axios.ts`: Base axios instance with `PUBLIC_API_URL` env variable
|
||||
- **`src/components/`**: Reusable Svelte components (modals, spinners, error boundaries)
|
||||
|
||||
Project-specific conventions and examples
|
||||
### API Communication
|
||||
|
||||
- Router: Because of the hash-router configuration, when constructing absolute links in a packaged app prefer `#/path` (README highlights this). For client navigation within components prefer `goto()` from `$app/navigation` (see [src/routes/+page.svelte](src/routes/+page.svelte)).
|
||||
- Env & API: Use `PUBLIC_API_URL` (imported from `$env/static/public`) as the renderer-side base URL. For backend calls that require auth, pass `Authorization: Bearer <token>` headers (see `src/lib/companies.ts`).
|
||||
- IPC surface: The preload file is where to expose limited, safe APIs to the renderer. The main process defines windows and startup behavior — avoid adding unsafe globals to the renderer.
|
||||
- TypeScript & Svelte: The project uses TypeScript + Svelte 5 — keep code consistent with existing component patterns (script blocks, `$:` reactivity, `svelte:head`, named +page routes).
|
||||
The `$lib/index.ts` exports `optima` object aggregating all API modules. Example:
|
||||
|
||||
Tests & tooling
|
||||
```typescript
|
||||
export const optima = {
|
||||
auth: (await import("./optima-api/modules/auth")).auth,
|
||||
company: (await import("./optima-api/modules/companies")).company,
|
||||
// etc.
|
||||
};
|
||||
```
|
||||
|
||||
- Unit tests: `vitest` (run `pnpm run test:unit`). Look at `demo.spec.ts` and `src/routes/page.svelte.test.ts` for existing examples.
|
||||
- E2E: Playwright tests live under `e2e/` and are run with `pnpm run test:e2e`.
|
||||
- Sync: `prepare` script runs `svelte-kit sync`. Running `pnpm run check` runs `svelte-check` too; use it when editing routes/type-heavy code.
|
||||
Each module (e.g., `auth.ts`) exports functions that call the API using a custom axios instance.
|
||||
|
||||
When making changes, be conservative
|
||||
## Key Conventions
|
||||
|
||||
- Changing build or packaging behavior affects developers' ability to run the app locally. Prefer edits to renderer code (under `src/`) unless the user asked to adjust packaging.
|
||||
- If adding new native electron APIs, update `electron/preload.ts` to expose a minimal API surface and document it.
|
||||
### Routing
|
||||
|
||||
Useful snippets / concrete examples
|
||||
- **Use standard SvelteKit routing with `/` prefix** (e.g., `href="/credentials"`)
|
||||
- Routes in `src/routes/` map to `/path` at runtime
|
||||
- Do NOT use hash-based routing (`#/` routes)
|
||||
|
||||
- Navigate programmatically: `import { goto } from "$app/navigation"; goto('/logout');` (see [src/routes/+page.svelte](src/routes/+page.svelte)).
|
||||
- API client usage: `import { api } from 'src/lib/axios'; const res = await api.get('/v1/...');`
|
||||
- Auth redirect fetch: `const { uri, callbackKey } = await fetchAuthRedirectUri(apiUrl);` (see [src/lib/authUri.ts](src/lib/authUri.ts)).
|
||||
### API Module Pattern
|
||||
|
||||
If anything is ambiguous or you need additional examples (tests, CI, or a missing preload implementation), ask the maintainer which behavior they want (safe IPC surface, packaging targets, or CI test matrix) before making large changes.
|
||||
Create API modules in `src/lib/optima-api/modules/` following this pattern:
|
||||
|
||||
-- End
|
||||
```typescript
|
||||
// Example: credentials.ts
|
||||
export const credential = {
|
||||
async fetchCredentials(api: AxiosInstance) {
|
||||
// Implementation
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Export as a named object, then import/aggregate in `src/lib/index.ts`.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `PUBLIC_API_URL`: API base URL, used in `src/lib/optima-api/axios.ts`
|
||||
- Prefixed with `PUBLIC_` to be accessible in client code
|
||||
|
||||
### File Organization
|
||||
|
||||
- Components go in `src/components/` (e.g., modals, spinners)
|
||||
- Page-specific logic in `src/routes/[route]/+page.svelte` and `+page.server.ts`
|
||||
- Styles in `src/styles/` with Tailwind CSS + TailwindCSS vite plugin
|
||||
- Tests colocated: `*.spec.ts` or `*.test.ts` next to source files
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Installation & Setup
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Uses pnpm with SvelteKit patches (see `patches/` directory).
|
||||
|
||||
### Running in Development
|
||||
|
||||
```bash
|
||||
pnpm run start
|
||||
```
|
||||
|
||||
Electron Forge + Vite handles dev server and hot module replacement (HMR). Dev tools open automatically. Main window loads `/login` first.
|
||||
|
||||
### Building & Packaging
|
||||
|
||||
- **Build for production**: `pnpm run package` → outputs to `out/` directory
|
||||
- **Create distributable**: `pnpm run make` → creates installers (configure in `forge.config.ts`)
|
||||
- **Check types & lint**: `pnpm run check` (runs svelte-kit sync + svelte-check)
|
||||
|
||||
### Testing
|
||||
|
||||
#### Unit Tests (Vitest)
|
||||
|
||||
```bash
|
||||
pnpm run test:unit
|
||||
```
|
||||
|
||||
- Client tests: `src/**/*.svelte.{test,spec}.{js,ts}` (jsdom environment)
|
||||
- Server tests: `src/**/*.{test,spec}.{js,ts}` excluding svelte tests (node environment)
|
||||
- Setup: `vitest-setup-client.ts` mocks `window.matchMedia` for Svelte 5 + jsdom compatibility
|
||||
|
||||
#### E2E Tests (Playwright)
|
||||
|
||||
```bash
|
||||
pnpm run test:e2e
|
||||
```
|
||||
|
||||
- Tests in `e2e/` directory
|
||||
- Config: `playwright.config.ts` (builds and previews before testing)
|
||||
|
||||
#### Run All Tests
|
||||
|
||||
```bash
|
||||
pnpm run test
|
||||
```
|
||||
|
||||
Runs unit tests first, then e2e.
|
||||
|
||||
## Critical Integration Points
|
||||
|
||||
### IPC (Electron Main ↔ Renderer)
|
||||
|
||||
**Status**: Preload script is currently empty. If file system access is needed, define IPC handlers in `electron/main.ts` and expose them via `electron/preload.ts` to renderer process.
|
||||
|
||||
### API Authentication
|
||||
|
||||
- Auth flow starts in `src/lib/optima-api/modules/auth.ts` with `fetchAuthRedirectUri()`
|
||||
- TODO: Enforce auth checks on every page change (see `src/lib/index.ts` comment)
|
||||
|
||||
### Build Artifacts
|
||||
|
||||
- **Dev server URL**: `MAIN_WINDOW_VITE_DEV_SERVER_URL` (injected by Electron Forge)
|
||||
- **Output**: Rendered app built to `.vite/renderer/main_window/` (configured in `svelte.config.js`)
|
||||
|
||||
## Common Patterns & Gotchas
|
||||
|
||||
1. **Standard Routing**: Use standard SvelteKit routing with `/` prefix (e.g., `href="/credentials"`) — do NOT use hash-based routing
|
||||
2. **SvelteKit Patches**: Project patches SvelteKit in `patches/` to work around issues. When updating SvelteKit, verify patches still apply.
|
||||
3. **Async Components**: Svelte 5 has `experimental.async: true` enabled; be aware of async component patterns.
|
||||
4. **Tailwind**: Uses `@tailwindcss/vite` plugin; configure utilities in tailwind config if needed.
|
||||
5. **API Error Handling**: API modules throw errors with descriptive messages. Use `$lib/errorHandler.ts` for consistent error formatting.
|
||||
|
||||
## Useful Entry Points for Navigation
|
||||
|
||||
- **Frontend Layout**: [src/routes/+layout.svelte](src/routes/+layout.svelte) (main shell, sidebar, header)
|
||||
- **API Abstraction**: [src/lib/optima-api/axios.ts](src/lib/optima-api/axios.ts) (base client)
|
||||
- **API Modules**: [src/lib/optima-api/modules/](src/lib/optima-api/modules/) (auth, companies, credentials, etc.)
|
||||
- **App Entry**: [src/app.html](src/app.html)
|
||||
- **Electron Main**: [electron/main.ts](electron/main.ts)
|
||||
|
||||
Reference in New Issue
Block a user