feat: enhance point registration with improved timestamp synchronization and direct photo processing, and add Convex Svelte best practices documentation.
This commit is contained in:
127
.agent/rules/convex-svelte-best-practices.md
Normal file
127
.agent/rules/convex-svelte-best-practices.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
trigger: glob
|
||||||
|
globs: **/*.svelte.ts,**/*.svelte
|
||||||
|
---
|
||||||
|
|
||||||
|
# Convex + Svelte Best Practices
|
||||||
|
|
||||||
|
This document outlines the mandatory rules and best practices for integrating Convex with Svelte in this project.
|
||||||
|
|
||||||
|
## 1. Imports
|
||||||
|
|
||||||
|
Always use the following import paths. Do NOT use `$lib/convex` or relative paths for generated files unless specifically required by a local override.
|
||||||
|
|
||||||
|
### Correct Imports:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||||
|
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||||
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Incorrect Imports (Avoid):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { convex } from '$lib/convex'; // Avoid direct client usage for queries
|
||||||
|
import { api } from '$lib/convex/_generated/api'; // Incorrect path
|
||||||
|
import { api } from '../convex/_generated/api'; // Relative path
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Data Fetching
|
||||||
|
|
||||||
|
### Use `useQuery` for Reactivity
|
||||||
|
|
||||||
|
Instead of manually fetching data inside `onMount`, use the `useQuery` hook. This ensures your data is reactive and automatically updates when the backend data changes.
|
||||||
|
|
||||||
|
**Preferred Pattern:**
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script lang="ts">
|
||||||
|
import { useQuery } from 'convex-svelte';
|
||||||
|
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||||
|
|
||||||
|
const tasksQuery = useQuery(api.tasks.list, { status: 'pending' });
|
||||||
|
const tasks = $derived(tasksQuery.data || []);
|
||||||
|
const isLoading = $derived(tasksQuery.isLoading);
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Avoid Pattern:**
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { convex } from '$lib/convex';
|
||||||
|
|
||||||
|
let tasks = [];
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// This is not reactive!
|
||||||
|
tasks = await convex.query(api.tasks.list, { status: 'pending' });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mutations
|
||||||
|
|
||||||
|
Use `useConvexClient` to access the client for mutations.
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script lang="ts">
|
||||||
|
import { useConvexClient } from 'convex-svelte';
|
||||||
|
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||||
|
|
||||||
|
const client = useConvexClient();
|
||||||
|
|
||||||
|
async function completeTask(id) {
|
||||||
|
await client.mutation(api.tasks.complete, { id });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Type Safety
|
||||||
|
|
||||||
|
### No `any`
|
||||||
|
|
||||||
|
Strictly avoid using `any`. The Convex generated data model provides precise types for all your tables.
|
||||||
|
|
||||||
|
### Use Generated Types
|
||||||
|
|
||||||
|
Use `Doc<"tableName">` for full document objects and `Id<"tableName">` for IDs.
|
||||||
|
|
||||||
|
**Correct:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import type { Doc, Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
|
||||||
|
let selectedTask: Doc<'tasks'> | null = $state(null);
|
||||||
|
let taskId: Id<'tasks'>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Incorrect:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let selectedTask: any = $state(null);
|
||||||
|
let taskId: string;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Union Types for Enums
|
||||||
|
|
||||||
|
When dealing with status fields or other enums, define the specific union type instead of casting to `any`.
|
||||||
|
|
||||||
|
**Correct:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async function updateStatus(newStatus: 'pending' | 'completed' | 'archived') {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Incorrect:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async function updateStatus(newStatus: string) {
|
||||||
|
// ...
|
||||||
|
status: newStatus as any; // Avoid this
|
||||||
|
}
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user