Add ModeTemplate with Svelte 5 frontend and components
- Create reusable components: auth, api-client, shared-types - ModeTemplate with Hono backend and SvelteKit frontend - Auth store refactored to class-based Svelte 5 pattern - SSR-safe hydrate() pattern for localStorage access - Frontend builds successfully with Svelte 5 runes
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# Shared Types
|
||||
|
||||
Common types used by both frontend and backend. Keeps API contracts in sync.
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import type { User, ApiResult, PaginatedResponse } from './components/shared-types';
|
||||
|
||||
// Backend endpoint
|
||||
app.get('/api/users', async (c): Promise<ApiResult<PaginatedResponse<User>>> => {
|
||||
const users = await getUsers();
|
||||
return c.json({ success: true, data: users });
|
||||
});
|
||||
|
||||
// Frontend call
|
||||
const result = await api.get<ApiResult<PaginatedResponse<User>>>('/users');
|
||||
if (result.ok && result.data?.success) {
|
||||
const users = result.data.data.items;
|
||||
}
|
||||
```
|
||||
|
||||
## Types Included
|
||||
|
||||
**User/Auth:**
|
||||
- `User` - User record
|
||||
- `AuthState` - Frontend auth state
|
||||
|
||||
**API Responses:**
|
||||
- `SuccessResponse<T>` - `{ success: true, data: T }`
|
||||
- `ErrorResponse` - `{ success: false, error: string }`
|
||||
- `ApiResult<T>` - Either success or error
|
||||
- `PaginatedResponse<T>` - List with pagination metadata
|
||||
|
||||
**Request Params:**
|
||||
- `PaginationParams` - `{ page?, perPage? }`
|
||||
- `SortParams` - `{ sort?, order? }`
|
||||
- `ListParams` - Combined pagination + sort
|
||||
|
||||
**Utility Types:**
|
||||
- `CreateInput<T>` - Omits id and timestamps for creating
|
||||
- `UpdateInput<T>` - Partial without id/timestamps for updating
|
||||
|
||||
## Copying to a Mode
|
||||
|
||||
1. Copy `components/shared-types/` to your mode root as `types/`
|
||||
2. Import from `./types` in both frontend and backend
|
||||
|
||||
## Dependencies
|
||||
|
||||
None - pure TypeScript types.
|
||||
@@ -0,0 +1,15 @@
|
||||
export type {
|
||||
User,
|
||||
AuthState,
|
||||
SuccessResponse,
|
||||
ErrorResponse,
|
||||
ApiResult,
|
||||
PaginatedResponse,
|
||||
PaginationParams,
|
||||
SortParams,
|
||||
ListParams,
|
||||
PartialBy,
|
||||
RequiredBy,
|
||||
CreateInput,
|
||||
UpdateInput,
|
||||
} from './types';
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Shared Types
|
||||
*
|
||||
* Common types used by both frontend and backend.
|
||||
* Copy this to any Mode to ensure type consistency.
|
||||
*/
|
||||
|
||||
// ============================================
|
||||
// USER / AUTH
|
||||
// ============================================
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
displayName: string;
|
||||
role?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface AuthState {
|
||||
isAuthenticated: boolean;
|
||||
user: User | null;
|
||||
token: string | null;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// API RESPONSES
|
||||
// ============================================
|
||||
|
||||
/** Standard success response */
|
||||
export interface SuccessResponse<T = unknown> {
|
||||
success: true;
|
||||
data: T;
|
||||
}
|
||||
|
||||
/** Standard error response */
|
||||
export interface ErrorResponse {
|
||||
success: false;
|
||||
error: string;
|
||||
code?: string;
|
||||
}
|
||||
|
||||
/** Combined response type */
|
||||
export type ApiResult<T = unknown> = SuccessResponse<T> | ErrorResponse;
|
||||
|
||||
/** Paginated list response */
|
||||
export interface PaginatedResponse<T> {
|
||||
items: T[];
|
||||
page: number;
|
||||
perPage: number;
|
||||
totalItems: number;
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// REQUEST TYPES
|
||||
// ============================================
|
||||
|
||||
/** Standard pagination params */
|
||||
export interface PaginationParams {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
}
|
||||
|
||||
/** Standard sort params */
|
||||
export interface SortParams {
|
||||
sort?: string;
|
||||
order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
/** Combined list params */
|
||||
export type ListParams = PaginationParams & SortParams;
|
||||
|
||||
// ============================================
|
||||
// UTILITY TYPES
|
||||
// ============================================
|
||||
|
||||
/** Make specific properties optional */
|
||||
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||
|
||||
/** Make specific properties required */
|
||||
export type RequiredBy<T, K extends keyof T> = T & Required<Pick<T, K>>;
|
||||
|
||||
/** Create/Update types - id is optional for create */
|
||||
export type CreateInput<T extends { id: string }> = Omit<T, 'id' | 'createdAt' | 'updatedAt'>;
|
||||
export type UpdateInput<T extends { id: string }> = Partial<Omit<T, 'id' | 'createdAt' | 'updatedAt'>>;
|
||||
Reference in New Issue
Block a user