diff --git a/.clinerules b/.clinerules new file mode 120000 index 0000000..ac534a3 --- /dev/null +++ b/.clinerules @@ -0,0 +1 @@ +AGENT.md \ No newline at end of file diff --git a/.cursor/rules/AGENT.md b/.cursor/rules/AGENT.md new file mode 120000 index 0000000..ec2887d --- /dev/null +++ b/.cursor/rules/AGENT.md @@ -0,0 +1 @@ +../../AGENT.md \ No newline at end of file diff --git a/.cursor/rules/api-patterns.mdc b/.cursor/rules/api-patterns.mdc deleted file mode 100644 index 9cefd24..0000000 --- a/.cursor/rules/api-patterns.mdc +++ /dev/null @@ -1,88 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# API Design Patterns - -## API Route Structure - -### Link Management API -Located in the `server/api/link/` directory, containing the following endpoints: - -- [create.post.ts](mdc:server/api/link/create.post.ts): Create new short links -- [edit.put.ts](mdc:server/api/link/edit.put.ts): Edit existing links -- [delete.post.ts](mdc:server/api/link/delete.post.ts): Delete links -- [list.get.ts](mdc:server/api/link/list.get.ts): Get link lists -- [query.get.ts](mdc:server/api/link/query.get.ts): Query specific links -- [search.get.ts](mdc:server/api/link/search.get.ts): Search links -- [upsert.post.ts](mdc:server/api/link/upsert.post.ts): Create or update links -- [ai.get.ts](mdc:server/api/link/ai.get.ts): AI-generated slugs - -### Other APIs -- [location.ts](mdc:server/api/location.ts): Geographic location information -- [verify.ts](mdc:server/api/verify.ts): Authentication -- `stats/`: Analytics-related APIs -- `logs/`: Logging-related APIs -- `ws/`: WebSocket-related APIs - -## API Design Conventions - -### HTTP Methods -- `GET`: Retrieve data (queries, lists) -- `POST`: Create resources or perform operations -- `PUT`: Update resources -- `DELETE`: Remove resources - -### Response Format -```typescript -// Success response -{ - success: true, - data: any -} - -// Error response -{ - success: false, - error: string, - code?: number -} -``` - -### Authentication -- Use Site Token for authentication -- Pass token in request header: `Authorization: Bearer ` - -### Data Validation -- Use Zod for input validation -- Define validation schemas in `schemas/` directory -- Unified error handling and response format - -### Cloudflare Integration -- Use Cloudflare Workers KV for data storage -- Leverage Cloudflare Analytics Engine for statistics -- Use Cloudflare AI for slug generation - -## Error Handling - -### Common Error Codes -- `400`: Bad request parameters -- `401`: Unauthorized access -- `403`: Insufficient permissions -- `404`: Resource not found -- `429`: Rate limit exceeded -- `500`: Internal server error - -### Error Handling Pattern -```typescript -try { - // API logic - return { success: true, data: result } -} catch (error) { - return createError({ - statusCode: 400, - statusMessage: error.message - }) -} -``` diff --git a/.cursor/rules/coding-standards.mdc b/.cursor/rules/coding-standards.mdc deleted file mode 100644 index 41dda80..0000000 --- a/.cursor/rules/coding-standards.mdc +++ /dev/null @@ -1,393 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# Coding Standards - -## Code Quality - -### TypeScript Requirements -- All new code must use TypeScript -- Enable strict type checking -- Avoid using `any` type, prefer specific types -- Define interfaces or type aliases for complex objects - -```typescript -// ✅ Good practice -interface LinkData { - slug: string - url: string - createdAt: Date - expiresAt?: Date -} - -// ❌ Avoid -const linkData: any = { ... } -``` - -### Function and Variable Naming -- Use descriptive names -- Function names should start with verbs -- Boolean variables use `is`, `has`, `should` prefixes -- Constants use UPPER_SNAKE_CASE - -```typescript -// ✅ Good practice -const isValidUrl = (url: string): boolean => { ... } -const hasExpired = computed(() => { ... }) -const MAX_SLUG_LENGTH = 50 - -// ❌ Avoid -const check = (u: string) => { ... } -const expired = computed(() => { ... }) -const maxLen = 50 -``` - -## Security Requirements - -### Input Validation -- All user input must be validated using Zod -- API endpoints must validate request parameters -- Frontend forms use vee-validate + Zod - -```typescript -// API input validation -import { z } from 'zod' - -const createLinkSchema = z.object({ - url: z.string().url(), - slug: z.string().min(1).max(50).optional(), - expiresAt: z.string().datetime().optional() -}) - -export default defineEventHandler(async (event) => { - const body = await readBody(event) - const validatedData = createLinkSchema.parse(body) - // ... -}) -``` - -### Authentication -- Use Site Token for authentication -- Sensitive operations require permission verification -- Don't store sensitive information on the client - -### Data Sanitization -- Sanitize user-input HTML content -- Validate URL format and security -- Prevent XSS and injection attacks - -## Performance Best Practices - -### Reactive Data -- Use `ref` and `reactive` appropriately -- Avoid unnecessary reactive wrapping -- Use `readonly` to protect data - -```typescript -// ✅ Good practice -const { data: links, pending } = await $fetch('/api/links') -const filteredLinks = computed(() => - links.value.filter(link => link.isActive) -) - -// ❌ Avoid -const links = ref([]) -const filteredLinks = ref([]) -watch(links, () => { - filteredLinks.value = links.value.filter(link => link.isActive) -}) -``` - -### Async Operations -- Use `async/await` instead of Promise chains -- Handle errors and loading states properly -- Avoid blocking UI operations - -```typescript -// ✅ Good practice -const { data, error, pending } = await useFetch('/api/links') - -// Error handling -try { - const result = await $fetch('/api/link/create', { ... }) -} catch (error) { - // Handle error -} -``` - -## Code Organization - -### File Structure -- Each file should export only one main functionality -- Group related functionality in the same directory -- Use `index.ts` as directory entry point - -### Import/Export -- Use ES6 module syntax -- Organize imports alphabetically -- Separate third-party and local imports - -```typescript -// Third-party libraries -import { ref, computed } from 'vue' -import { z } from 'zod' - -// Local imports -import type { LinkData } from '~/types' -import { validateUrl } from '~/utils/validation' -``` - -### Comments and Documentation -- Add comments for complex logic -- Use JSDoc comments for public APIs -- Keep comments in sync with code - -```typescript -/** - * Create a new short link - * @param url - Original URL - * @param slug - Custom slug (optional) - * @returns Created link data - */ -export async function createLink(url: string, slug?: string): Promise { - // Implementation logic -} -``` - -## Testing Standards - -### Unit Testing Requirements -- **Mandatory for all `server/api` endpoints** - Every API route must have comprehensive unit tests -- Use Vitest as the primary testing framework with Nuxt Test Utils -- Follow the Test-Driven Development (TDD) approach when possible -- Maintain test coverage above 80% for API endpoints - -### Testing Scope and Strategy -- **API Layer**: Test all endpoints in [server/api/](mdc:server/api/) directory -- **Validation Logic**: Test Zod schemas and input validation -- **Error Handling**: Verify error responses and status codes -- **Authentication**: Test token validation and authorization flows -- **Business Logic**: Cover edge cases and critical functionality - -### Test File Organization -```typescript -// File naming convention -tests/api/link/create.test.ts // Unit tests for API endpoints -tests/api/helpers/fixtures.ts // Shared test data -tests/sink.spec.ts // Integration/E2E tests -``` - -### Testing Best Practices -- **Write descriptive test names** that explain the behavior being tested -- **Test both happy path and error scenarios** -- **Use meaningful assertions** that validate expected behavior -- **Keep tests independent** - no test should depend on another test's state -- **Mock external dependencies** to ensure test reliability - -```typescript -// ✅ Good test structure -describe('POST /api/link/create', () => { - it('should create a new link with valid URL and custom slug', async () => { - const response = await $fetch('/api/link/create', { - method: 'POST', - body: { url: 'https://example.com', slug: 'my-link' } - }) - - expect(response.success).toBe(true) - expect(response.data.slug).toBe('my-link') - expect(response.data.url).toBe('https://example.com') - }) - - it('should reject requests with invalid URL format', async () => { - await expect($fetch('/api/link/create', { - method: 'POST', - body: { url: 'not-a-valid-url' } - })).rejects.toThrow() - }) -}) -``` - -### Test Data Management -- Use factory functions for creating test data -- Store common test fixtures in `tests/api/helpers/fixtures.ts` -- Avoid hardcoded values in tests; use constants and variables - -```typescript -// ✅ Good test data management -const validLinkPayload = { - url: 'https://example.com', - slug: 'test-slug', - expiresAt: new Date(Date.now() + 86400000).toISOString() -} - -const invalidUrlPayload = { - url: 'invalid-url-format', - slug: 'test-slug' -} -``` - -### Running and Maintaining Tests -- Run tests locally before pushing changes: `npm run test` -- Use watch mode during development: `npm run test:watch` -- Generate coverage reports: `npm run test:coverage` -- Tests must pass in CI/CD pipeline before merging - -## Git Commit Conventions - -### Commit Message Format -Follow the conventional commit specification: -``` -type(scope): brief description - -Optional body explaining what and why vs how - -Optional footer with issue references -``` - -### Commit Types -- **feat**: New feature implementation -- **fix**: Bug fix or issue resolution -- **docs**: Documentation updates only -- **style**: Code formatting changes (no functional impact) -- **refactor**: Code restructuring without changing functionality -- **perf**: Performance optimization -- **test**: Adding or modifying tests -- **chore**: Build process, dependency updates, or auxiliary tool changes -- **ci**: Continuous integration configuration changes - -### Scope Examples -- **api**: Changes to server/api endpoints -- **ui**: Frontend components or styling -- **auth**: Authentication related changes -- **db**: Database or data storage changes -- **config**: Configuration file updates - -### Writing Good Commit Messages - -#### Good Examples -```bash -feat(api): add AI-powered slug generation endpoint - -Integrate Cloudflare AI Workers to automatically generate -meaningful slugs based on URL content and page titles. - -- Add new /api/link/ai endpoint -- Implement content analysis logic -- Update link creation flow to support AI suggestions -- Add comprehensive test coverage - -Closes #123 -``` - -```bash -fix(auth): resolve token validation edge case - -Handle expired tokens more gracefully by returning proper -401 status code instead of throwing unhandled exceptions. - -Fixes #456 -``` - -```bash -test(api): add comprehensive coverage for link endpoints - -- Add unit tests for create, edit, delete operations -- Include validation error scenarios -- Test authentication requirements -- Achieve 85% coverage for link management APIs -``` - -#### Avoid These Patterns -```bash -# ❌ Too vague -fix: stuff - -# ❌ Not descriptive -update code - -# ❌ Multiple concerns in one commit -feat: add new API endpoint and fix UI bug and update docs - -# ❌ All caps or inconsistent formatting -FIX: BROKEN AUTH SYSTEM -``` - -### Commit Best Practices - -#### Single Responsibility -Each commit should represent one logical change: -- One feature addition -- One bug fix -- One refactoring operation -- One documentation update - -#### Atomic Commits -Commits should be complete and functional: -- Code compiles without errors -- Tests pass -- No broken functionality introduced - -#### Meaningful Descriptions -- Use imperative mood ("add feature" not "added feature") -- Capitalize the first letter -- No period at the end of the subject line -- Keep subject line under 50 characters -- Use body for detailed explanations when needed - -### Branch Naming Conventions -```bash -# Feature branches -feature/ai-slug-generation -feature/link-expiration - -# Bug fix branches -fix/auth-token-validation -fix/mobile-responsive-layout - -# Documentation branches -docs/api-endpoint-guide -docs/deployment-instructions - -# Hotfix branches -hotfix/security-vulnerability -hotfix/production-crash -``` - -### Pull Request Guidelines - -#### PR Title Format -Use the same format as commit messages: -``` -feat(api): add AI-powered slug generation -fix(auth): resolve token validation edge case -docs(readme): update installation instructions -``` - -#### PR Description Template -```markdown -## Summary -Brief description of changes made - -## Type of Change -- [ ] Bug fix -- [ ] New feature -- [ ] Documentation update -- [ ] Refactoring -- [ ] Performance improvement - -## Testing -- [ ] Unit tests added/updated -- [ ] Integration tests pass -- [ ] Manual testing completed - -## Checklist -- [ ] Code follows project style guidelines -- [ ] Self-review completed -- [ ] Documentation updated if needed -- [ ] Tests cover new functionality -- [ ] No breaking changes introduced -``` - -This standardized approach ensures clean, readable commit history and makes it easier to track changes, generate changelogs, and collaborate effectively with team members. diff --git a/.cursor/rules/component-patterns.mdc b/.cursor/rules/component-patterns.mdc deleted file mode 100644 index 8f4245c..0000000 --- a/.cursor/rules/component-patterns.mdc +++ /dev/null @@ -1,156 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# Vue Component Design Patterns - -## Component Directory Structure - -### UI Components (`app/components/ui/`) -Reusable UI components based on shadcn-vue: -- Buttons, inputs, dialogs, and other fundamental components -- Follow shadcn-vue design system -- Styled with Tailwind CSS -- Support theme switching (light/dark mode) - -### Business Components -- `dashboard/`: Dashboard-related components -- `home/`: Homepage-related components -- `login/`: Login-related components -- `layouts/`: Layout components -- `spark-ui/`: Special UI components - -### Global Components -- [SwitchLanguage.vue](mdc:app/components/SwitchLanguage.vue): Language switching component -- [SwitchTheme.vue](mdc:app/components/SwitchTheme.vue): Theme switching component - -## Component Development Standards - -### Component Structure -```vue - - - - - -``` - -### Naming Conventions -- Component files use PascalCase: `MyComponent.vue` -- Internal variables use camelCase -- CSS class names use Tailwind CSS utility classes -- Event names use kebab-case - -### Props and Events -```typescript -// Props type definition -interface Props { - title: string - isVisible?: boolean - items: Array -} - -// Events type definition -const emit = defineEmits<{ - update: [value: string] - close: [] - select: [item: Item] -}>() -``` - -## State Management - -### Composables (`app/composables/`) -- Use VueUse utility functions -- Create custom composables for shared state management -- Follow `use` prefix naming convention - -### Reactive State -```typescript -// composables/useAuth.ts -export function useAuth() { - const isAuthenticated = ref(false) - const user = ref(null) - - const login = async (token: string) => { - // login logic - } - - const logout = () => { - // logout logic - } - - return { - isAuthenticated: readonly(isAuthenticated), - user: readonly(user), - login, - logout - } -} -``` - -## Styling and Theming - -### Tailwind CSS -- Use Tailwind utility classes for styling -- Configuration file: [tailwind.config.js](mdc:tailwind.config.js) -- Support responsive design and dark mode - -### Theme System -- Use `@nuxtjs/color-mode` module -- Support automatic system theme detection -- Theme switching component: [SwitchTheme.vue](mdc:app/components/SwitchTheme.vue) - -### Animation Effects -- Use `@vueuse/motion` for animations -- Use animation classes provided by `tailwindcss-animate` -- Keep animations simple and performance-friendly - -## Internationalization - -### Multi-language Support -- Use `@nuxtjs/i18n` module -- Language switching component: [SwitchLanguage.vue](mdc:app/components/SwitchLanguage.vue) -- Store translation files in `i18n/` directory - -### Usage -```vue - -``` diff --git a/.cursor/rules/deployment-and-infrastructure.mdc b/.cursor/rules/deployment-and-infrastructure.mdc deleted file mode 100644 index 5d230a8..0000000 --- a/.cursor/rules/deployment-and-infrastructure.mdc +++ /dev/null @@ -1,139 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# Deployment and Infrastructure - -## Cloudflare Platform - -Sink runs entirely on the Cloudflare platform, leveraging the following services: - -### Cloudflare Workers -- Serverless computing platform -- Global edge network deployment -- Configuration file: [wrangler.jsonc](mdc:wrangler.jsonc) - -### Cloudflare Pages -- Static website hosting -- Automatic build and deployment -- Preview deployment support - -### Cloudflare Workers KV -- Key-value storage database -- Globally distributed storage -- Used for storing link data and configuration - -### Cloudflare Analytics Engine -- Real-time analytics data collection -- High-performance time-series database -- Used for link click statistics - -### Cloudflare AI -- AI model inference service -- Used for automatic slug generation -- Model: `@cf/meta/llama-3.1-8b-instruct` - -## Deployment Configuration - -### Environment Variables -Defined in `runtimeConfig` in [nuxt.config.ts](mdc:nuxt.config.ts): - -```typescript -runtimeConfig: { - siteToken: 'SinkCool', // Site access token - redirectStatusCode: '301', // Redirect status code - linkCacheTtl: 60, // Link cache time - redirectWithQuery: false, // Whether to preserve query parameters - homeURL: '', // Home URL - cfAccountId: '', // Cloudflare Account ID - cfApiToken: '', // Cloudflare API token - dataset: 'sink', // Analytics dataset name - aiModel: '@cf/meta/llama-3.1-8b-instruct', // AI model - caseSensitive: false, // Case sensitivity - listQueryLimit: 500, // List query limit - disableBotAccessLog: false, // Disable bot access logging -} -``` - -### Build Scripts -- `pnpm build`: Build for production -- `pnpm build:map`: Build map data -- `pnpm build:colo`: Build Cloudflare data center information - -### Deployment Commands -```bash -# Preview deployment -pnpm preview - -# Production deployment -pnpm deploy - -# Using Wrangler CLI -wrangler pages deploy dist -``` - -## Performance Optimization - -### Caching Strategy -- Static assets cached using Cloudflare CDN -- Configurable link data cache TTL -- Leverage edge computing to reduce latency - -### Route Rules -Configured in [nuxt.config.ts](mdc:nuxt.config.ts): - -```typescript -routeRules: { - '/': { - prerender: true, // Prerender homepage - }, - '/dashboard/**': { - prerender: true, // Prerender dashboard - ssr: false, // Disable server-side rendering - }, - '/dashboard': { - redirect: '/dashboard/links', // Redirect to links page - }, -} -``` - -### Build Optimization -- Use `NODE_OPTIONS=--max-old-space-size=8192` to increase memory limit -- Enable Nuxt's built-in optimization features -- Code splitting and lazy loading - -## Monitoring and Logging - -### Analytics Engine -- Real-time click data collection -- Geographic location statistics -- User agent analysis -- Referrer statistics - -### Error Handling -- Unified error response format -- Error logging -- Performance monitoring - -### Security -- Site Token authentication -- CORS configuration -- Input validation and sanitization -- Malicious link prevention - -## Development Environment - -### Local Development -```bash -# Start development server -pnpm dev - -# Code style checking -pnpm lint -``` - -### Environment Configuration -- Use `.env` file for local environment variables -- Use Cloudflare Workers local simulator during development -- Support hot reload and live preview diff --git a/.cursor/rules/development-guidelines.mdc b/.cursor/rules/development-guidelines.mdc deleted file mode 100644 index 8b8c096..0000000 --- a/.cursor/rules/development-guidelines.mdc +++ /dev/null @@ -1,64 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# Development Guidelines - -## Code Style and Standards - -### TypeScript/JavaScript -- Use TypeScript for type-safe development -- Follow ESLint rules defined in [eslint.config.mjs](mdc:eslint.config.mjs) -- Use `@antfu/eslint-config` as the base configuration -- Run `pnpm lint` to check code style, `pnpm lint:fix` to auto-fix issues - -### Vue Components -- Use Composition API with `