From ff9c65bf30ab768a7dab6f0dd0645f0104820f82 Mon Sep 17 00:00:00 2001 From: Cassiano Montanari Date: Tue, 3 Mar 2026 21:03:37 +0100 Subject: [PATCH] Change blinking frames --- .../skills/github-actions-templates/SKILL.md | 334 -------- .../skills/typescript-advanced-types/SKILL.md | 724 ------------------ src/cli.ts | 2 +- 3 files changed, 1 insertion(+), 1059 deletions(-) delete mode 100644 .agents/skills/github-actions-templates/SKILL.md delete mode 100644 .agents/skills/typescript-advanced-types/SKILL.md diff --git a/.agents/skills/github-actions-templates/SKILL.md b/.agents/skills/github-actions-templates/SKILL.md deleted file mode 100644 index 691f4bc..0000000 --- a/.agents/skills/github-actions-templates/SKILL.md +++ /dev/null @@ -1,334 +0,0 @@ ---- -name: github-actions-templates -description: Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates. ---- - -# GitHub Actions Templates - -Production-ready GitHub Actions workflow patterns for testing, building, and deploying applications. - -## Purpose - -Create efficient, secure GitHub Actions workflows for continuous integration and deployment across various tech stacks. - -## When to Use - -- Automate testing and deployment -- Build Docker images and push to registries -- Deploy to Kubernetes clusters -- Run security scans -- Implement matrix builds for multiple environments - -## Common Workflow Patterns - -### Pattern 1: Test Workflow - -```yaml -name: Test - -on: - push: - branches: [main, develop] - pull_request: - branches: [main] - -jobs: - test: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x, 20.x] - - steps: - - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: "npm" - - - name: Install dependencies - run: npm ci - - - name: Run linter - run: npm run lint - - - name: Run tests - run: npm test - - - name: Upload coverage - uses: codecov/codecov-action@v3 - with: - files: ./coverage/lcov.info -``` - -**Reference:** See `assets/test-workflow.yml` - -### Pattern 2: Build and Push Docker Image - -```yaml -name: Build and Push - -on: - push: - branches: [main] - tags: ["v*"] - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - uses: actions/checkout@v4 - - - name: Log in to Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max -``` - -**Reference:** See `assets/deploy-workflow.yml` - -### Pattern 3: Deploy to Kubernetes - -```yaml -name: Deploy to Kubernetes - -on: - push: - branches: [main] - -jobs: - deploy: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-west-2 - - - name: Update kubeconfig - run: | - aws eks update-kubeconfig --name production-cluster --region us-west-2 - - - name: Deploy to Kubernetes - run: | - kubectl apply -f k8s/ - kubectl rollout status deployment/my-app -n production - kubectl get services -n production - - - name: Verify deployment - run: | - kubectl get pods -n production - kubectl describe deployment my-app -n production -``` - -### Pattern 4: Matrix Build - -```yaml -name: Matrix Build - -on: [push, pull_request] - -jobs: - build: - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11", "3.12"] - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run tests - run: pytest -``` - -**Reference:** See `assets/matrix-build.yml` - -## Workflow Best Practices - -1. **Use specific action versions** (@v4, not @latest) -2. **Cache dependencies** to speed up builds -3. **Use secrets** for sensitive data -4. **Implement status checks** on PRs -5. **Use matrix builds** for multi-version testing -6. **Set appropriate permissions** -7. **Use reusable workflows** for common patterns -8. **Implement approval gates** for production -9. **Add notification steps** for failures -10. **Use self-hosted runners** for sensitive workloads - -## Reusable Workflows - -```yaml -# .github/workflows/reusable-test.yml -name: Reusable Test Workflow - -on: - workflow_call: - inputs: - node-version: - required: true - type: string - secrets: - NPM_TOKEN: - required: true - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ inputs.node-version }} - - run: npm ci - - run: npm test -``` - -**Use reusable workflow:** - -```yaml -jobs: - call-test: - uses: ./.github/workflows/reusable-test.yml - with: - node-version: "20.x" - secrets: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} -``` - -## Security Scanning - -```yaml -name: Security Scan - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - security: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - scan-type: "fs" - scan-ref: "." - format: "sarif" - output: "trivy-results.sarif" - - - name: Upload Trivy results to GitHub Security - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: "trivy-results.sarif" - - - name: Run Snyk Security Scan - uses: snyk/actions/node@master - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} -``` - -## Deployment with Approvals - -```yaml -name: Deploy to Production - -on: - push: - tags: ["v*"] - -jobs: - deploy: - runs-on: ubuntu-latest - environment: - name: production - url: https://app.example.com - - steps: - - uses: actions/checkout@v4 - - - name: Deploy application - run: | - echo "Deploying to production..." - # Deployment commands here - - - name: Notify Slack - if: success() - uses: slackapi/slack-github-action@v1 - with: - webhook-url: ${{ secrets.SLACK_WEBHOOK }} - payload: | - { - "text": "Deployment to production completed successfully!" - } -``` - -## Reference Files - -- `assets/test-workflow.yml` - Testing workflow template -- `assets/deploy-workflow.yml` - Deployment workflow template -- `assets/matrix-build.yml` - Matrix build template -- `references/common-workflows.md` - Common workflow patterns - -## Related Skills - -- `gitlab-ci-patterns` - For GitLab CI workflows -- `deployment-pipeline-design` - For pipeline architecture -- `secrets-management` - For secrets handling diff --git a/.agents/skills/typescript-advanced-types/SKILL.md b/.agents/skills/typescript-advanced-types/SKILL.md deleted file mode 100644 index 8d64396..0000000 --- a/.agents/skills/typescript-advanced-types/SKILL.md +++ /dev/null @@ -1,724 +0,0 @@ ---- -name: typescript-advanced-types -description: Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects. ---- - -# TypeScript Advanced Types - -Comprehensive guidance for mastering TypeScript's advanced type system including generics, conditional types, mapped types, template literal types, and utility types for building robust, type-safe applications. - -## When to Use This Skill - -- Building type-safe libraries or frameworks -- Creating reusable generic components -- Implementing complex type inference logic -- Designing type-safe API clients -- Building form validation systems -- Creating strongly-typed configuration objects -- Implementing type-safe state management -- Migrating JavaScript codebases to TypeScript - -## Core Concepts - -### 1. Generics - -**Purpose:** Create reusable, type-flexible components while maintaining type safety. - -**Basic Generic Function:** - -```typescript -function identity(value: T): T { - return value; -} - -const num = identity(42); // Type: number -const str = identity("hello"); // Type: string -const auto = identity(true); // Type inferred: boolean -``` - -**Generic Constraints:** - -```typescript -interface HasLength { - length: number; -} - -function logLength(item: T): T { - console.log(item.length); - return item; -} - -logLength("hello"); // OK: string has length -logLength([1, 2, 3]); // OK: array has length -logLength({ length: 10 }); // OK: object has length -// logLength(42); // Error: number has no length -``` - -**Multiple Type Parameters:** - -```typescript -function merge(obj1: T, obj2: U): T & U { - return { ...obj1, ...obj2 }; -} - -const merged = merge({ name: "John" }, { age: 30 }); -// Type: { name: string } & { age: number } -``` - -### 2. Conditional Types - -**Purpose:** Create types that depend on conditions, enabling sophisticated type logic. - -**Basic Conditional Type:** - -```typescript -type IsString = T extends string ? true : false; - -type A = IsString; // true -type B = IsString; // false -``` - -**Extracting Return Types:** - -```typescript -type ReturnType = T extends (...args: any[]) => infer R ? R : never; - -function getUser() { - return { id: 1, name: "John" }; -} - -type User = ReturnType; -// Type: { id: number; name: string; } -``` - -**Distributive Conditional Types:** - -```typescript -type ToArray = T extends any ? T[] : never; - -type StrOrNumArray = ToArray; -// Type: string[] | number[] -``` - -**Nested Conditions:** - -```typescript -type TypeName = T extends string - ? "string" - : T extends number - ? "number" - : T extends boolean - ? "boolean" - : T extends undefined - ? "undefined" - : T extends Function - ? "function" - : "object"; - -type T1 = TypeName; // "string" -type T2 = TypeName<() => void>; // "function" -``` - -### 3. Mapped Types - -**Purpose:** Transform existing types by iterating over their properties. - -**Basic Mapped Type:** - -```typescript -type Readonly = { - readonly [P in keyof T]: T[P]; -}; - -interface User { - id: number; - name: string; -} - -type ReadonlyUser = Readonly; -// Type: { readonly id: number; readonly name: string; } -``` - -**Optional Properties:** - -```typescript -type Partial = { - [P in keyof T]?: T[P]; -}; - -type PartialUser = Partial; -// Type: { id?: number; name?: string; } -``` - -**Key Remapping:** - -```typescript -type Getters = { - [K in keyof T as `get${Capitalize}`]: () => T[K]; -}; - -interface Person { - name: string; - age: number; -} - -type PersonGetters = Getters; -// Type: { getName: () => string; getAge: () => number; } -``` - -**Filtering Properties:** - -```typescript -type PickByType = { - [K in keyof T as T[K] extends U ? K : never]: T[K]; -}; - -interface Mixed { - id: number; - name: string; - age: number; - active: boolean; -} - -type OnlyNumbers = PickByType; -// Type: { id: number; age: number; } -``` - -### 4. Template Literal Types - -**Purpose:** Create string-based types with pattern matching and transformation. - -**Basic Template Literal:** - -```typescript -type EventName = "click" | "focus" | "blur"; -type EventHandler = `on${Capitalize}`; -// Type: "onClick" | "onFocus" | "onBlur" -``` - -**String Manipulation:** - -```typescript -type UppercaseGreeting = Uppercase<"hello">; // "HELLO" -type LowercaseGreeting = Lowercase<"HELLO">; // "hello" -type CapitalizedName = Capitalize<"john">; // "John" -type UncapitalizedName = Uncapitalize<"John">; // "john" -``` - -**Path Building:** - -```typescript -type Path = T extends object - ? { - [K in keyof T]: K extends string ? `${K}` | `${K}.${Path}` : never; - }[keyof T] - : never; - -interface Config { - server: { - host: string; - port: number; - }; - database: { - url: string; - }; -} - -type ConfigPath = Path; -// Type: "server" | "database" | "server.host" | "server.port" | "database.url" -``` - -### 5. Utility Types - -**Built-in Utility Types:** - -```typescript -// Partial - Make all properties optional -type PartialUser = Partial; - -// Required - Make all properties required -type RequiredUser = Required; - -// Readonly - Make all properties readonly -type ReadonlyUser = Readonly; - -// Pick - Select specific properties -type UserName = Pick; - -// Omit - Remove specific properties -type UserWithoutPassword = Omit; - -// Exclude - Exclude types from union -type T1 = Exclude<"a" | "b" | "c", "a">; // "b" | "c" - -// Extract - Extract types from union -type T2 = Extract<"a" | "b" | "c", "a" | "b">; // "a" | "b" - -// NonNullable - Exclude null and undefined -type T3 = NonNullable; // string - -// Record - Create object type with keys K and values T -type PageInfo = Record<"home" | "about", { title: string }>; -``` - -## Advanced Patterns - -### Pattern 1: Type-Safe Event Emitter - -```typescript -type EventMap = { - "user:created": { id: string; name: string }; - "user:updated": { id: string }; - "user:deleted": { id: string }; -}; - -class TypedEventEmitter> { - private listeners: { - [K in keyof T]?: Array<(data: T[K]) => void>; - } = {}; - - on(event: K, callback: (data: T[K]) => void): void { - if (!this.listeners[event]) { - this.listeners[event] = []; - } - this.listeners[event]!.push(callback); - } - - emit(event: K, data: T[K]): void { - const callbacks = this.listeners[event]; - if (callbacks) { - callbacks.forEach((callback) => callback(data)); - } - } -} - -const emitter = new TypedEventEmitter(); - -emitter.on("user:created", (data) => { - console.log(data.id, data.name); // Type-safe! -}); - -emitter.emit("user:created", { id: "1", name: "John" }); -// emitter.emit("user:created", { id: "1" }); // Error: missing 'name' -``` - -### Pattern 2: Type-Safe API Client - -```typescript -type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE"; - -type EndpointConfig = { - "/users": { - GET: { response: User[] }; - POST: { body: { name: string; email: string }; response: User }; - }; - "/users/:id": { - GET: { params: { id: string }; response: User }; - PUT: { params: { id: string }; body: Partial; response: User }; - DELETE: { params: { id: string }; response: void }; - }; -}; - -type ExtractParams = T extends { params: infer P } ? P : never; -type ExtractBody = T extends { body: infer B } ? B : never; -type ExtractResponse = T extends { response: infer R } ? R : never; - -class APIClient>> { - async request( - path: Path, - method: Method, - ...[options]: ExtractParams extends never - ? ExtractBody extends never - ? [] - : [{ body: ExtractBody }] - : [ - { - params: ExtractParams; - body?: ExtractBody; - }, - ] - ): Promise> { - // Implementation here - return {} as any; - } -} - -const api = new APIClient(); - -// Type-safe API calls -const users = await api.request("/users", "GET"); -// Type: User[] - -const newUser = await api.request("/users", "POST", { - body: { name: "John", email: "john@example.com" }, -}); -// Type: User - -const user = await api.request("/users/:id", "GET", { - params: { id: "123" }, -}); -// Type: User -``` - -### Pattern 3: Builder Pattern with Type Safety - -```typescript -type BuilderState = { - [K in keyof T]: T[K] | undefined; -}; - -type RequiredKeys = { - [K in keyof T]-?: {} extends Pick ? never : K; -}[keyof T]; - -type OptionalKeys = { - [K in keyof T]-?: {} extends Pick ? K : never; -}[keyof T]; - -type IsComplete = - RequiredKeys extends keyof S - ? S[RequiredKeys] extends undefined - ? false - : true - : false; - -class Builder = {}> { - private state: S = {} as S; - - set(key: K, value: T[K]): Builder> { - this.state[key] = value; - return this as any; - } - - build(this: IsComplete extends true ? this : never): T { - return this.state as T; - } -} - -interface User { - id: string; - name: string; - email: string; - age?: number; -} - -const builder = new Builder(); - -const user = builder - .set("id", "1") - .set("name", "John") - .set("email", "john@example.com") - .build(); // OK: all required fields set - -// const incomplete = builder -// .set("id", "1") -// .build(); // Error: missing required fields -``` - -### Pattern 4: Deep Readonly/Partial - -```typescript -type DeepReadonly = { - readonly [P in keyof T]: T[P] extends object - ? T[P] extends Function - ? T[P] - : DeepReadonly - : T[P]; -}; - -type DeepPartial = { - [P in keyof T]?: T[P] extends object - ? T[P] extends Array - ? Array> - : DeepPartial - : T[P]; -}; - -interface Config { - server: { - host: string; - port: number; - ssl: { - enabled: boolean; - cert: string; - }; - }; - database: { - url: string; - pool: { - min: number; - max: number; - }; - }; -} - -type ReadonlyConfig = DeepReadonly; -// All nested properties are readonly - -type PartialConfig = DeepPartial; -// All nested properties are optional -``` - -### Pattern 5: Type-Safe Form Validation - -```typescript -type ValidationRule = { - validate: (value: T) => boolean; - message: string; -}; - -type FieldValidation = { - [K in keyof T]?: ValidationRule[]; -}; - -type ValidationErrors = { - [K in keyof T]?: string[]; -}; - -class FormValidator> { - constructor(private rules: FieldValidation) {} - - validate(data: T): ValidationErrors | null { - const errors: ValidationErrors = {}; - let hasErrors = false; - - for (const key in this.rules) { - const fieldRules = this.rules[key]; - const value = data[key]; - - if (fieldRules) { - const fieldErrors: string[] = []; - - for (const rule of fieldRules) { - if (!rule.validate(value)) { - fieldErrors.push(rule.message); - } - } - - if (fieldErrors.length > 0) { - errors[key] = fieldErrors; - hasErrors = true; - } - } - } - - return hasErrors ? errors : null; - } -} - -interface LoginForm { - email: string; - password: string; -} - -const validator = new FormValidator({ - email: [ - { - validate: (v) => v.includes("@"), - message: "Email must contain @", - }, - { - validate: (v) => v.length > 0, - message: "Email is required", - }, - ], - password: [ - { - validate: (v) => v.length >= 8, - message: "Password must be at least 8 characters", - }, - ], -}); - -const errors = validator.validate({ - email: "invalid", - password: "short", -}); -// Type: { email?: string[]; password?: string[]; } | null -``` - -### Pattern 6: Discriminated Unions - -```typescript -type Success = { - status: "success"; - data: T; -}; - -type Error = { - status: "error"; - error: string; -}; - -type Loading = { - status: "loading"; -}; - -type AsyncState = Success | Error | Loading; - -function handleState(state: AsyncState): void { - switch (state.status) { - case "success": - console.log(state.data); // Type: T - break; - case "error": - console.log(state.error); // Type: string - break; - case "loading": - console.log("Loading..."); - break; - } -} - -// Type-safe state machine -type State = - | { type: "idle" } - | { type: "fetching"; requestId: string } - | { type: "success"; data: any } - | { type: "error"; error: Error }; - -type Event = - | { type: "FETCH"; requestId: string } - | { type: "SUCCESS"; data: any } - | { type: "ERROR"; error: Error } - | { type: "RESET" }; - -function reducer(state: State, event: Event): State { - switch (state.type) { - case "idle": - return event.type === "FETCH" - ? { type: "fetching", requestId: event.requestId } - : state; - case "fetching": - if (event.type === "SUCCESS") { - return { type: "success", data: event.data }; - } - if (event.type === "ERROR") { - return { type: "error", error: event.error }; - } - return state; - case "success": - case "error": - return event.type === "RESET" ? { type: "idle" } : state; - } -} -``` - -## Type Inference Techniques - -### 1. Infer Keyword - -```typescript -// Extract array element type -type ElementType = T extends (infer U)[] ? U : never; - -type NumArray = number[]; -type Num = ElementType; // number - -// Extract promise type -type PromiseType = T extends Promise ? U : never; - -type AsyncNum = PromiseType>; // number - -// Extract function parameters -type Parameters = T extends (...args: infer P) => any ? P : never; - -function foo(a: string, b: number) {} -type FooParams = Parameters; // [string, number] -``` - -### 2. Type Guards - -```typescript -function isString(value: unknown): value is string { - return typeof value === "string"; -} - -function isArrayOf( - value: unknown, - guard: (item: unknown) => item is T, -): value is T[] { - return Array.isArray(value) && value.every(guard); -} - -const data: unknown = ["a", "b", "c"]; - -if (isArrayOf(data, isString)) { - data.forEach((s) => s.toUpperCase()); // Type: string[] -} -``` - -### 3. Assertion Functions - -```typescript -function assertIsString(value: unknown): asserts value is string { - if (typeof value !== "string") { - throw new Error("Not a string"); - } -} - -function processValue(value: unknown) { - assertIsString(value); - // value is now typed as string - console.log(value.toUpperCase()); -} -``` - -## Best Practices - -1. **Use `unknown` over `any`**: Enforce type checking -2. **Prefer `interface` for object shapes**: Better error messages -3. **Use `type` for unions and complex types**: More flexible -4. **Leverage type inference**: Let TypeScript infer when possible -5. **Create helper types**: Build reusable type utilities -6. **Use const assertions**: Preserve literal types -7. **Avoid type assertions**: Use type guards instead -8. **Document complex types**: Add JSDoc comments -9. **Use strict mode**: Enable all strict compiler options -10. **Test your types**: Use type tests to verify type behavior - -## Type Testing - -```typescript -// Type assertion tests -type AssertEqual = [T] extends [U] - ? [U] extends [T] - ? true - : false - : false; - -type Test1 = AssertEqual; // true -type Test2 = AssertEqual; // false -type Test3 = AssertEqual; // false - -// Expect error helper -type ExpectError = T; - -// Example usage -type ShouldError = ExpectError>; -``` - -## Common Pitfalls - -1. **Over-using `any`**: Defeats the purpose of TypeScript -2. **Ignoring strict null checks**: Can lead to runtime errors -3. **Too complex types**: Can slow down compilation -4. **Not using discriminated unions**: Misses type narrowing opportunities -5. **Forgetting readonly modifiers**: Allows unintended mutations -6. **Circular type references**: Can cause compiler errors -7. **Not handling edge cases**: Like empty arrays or null values - -## Performance Considerations - -- Avoid deeply nested conditional types -- Use simple types when possible -- Cache complex type computations -- Limit recursion depth in recursive types -- Use build tools to skip type checking in production - -## Resources - -- **TypeScript Handbook**: https://www.typescriptlang.org/docs/handbook/ -- **Type Challenges**: https://github.com/type-challenges/type-challenges -- **TypeScript Deep Dive**: https://basarat.gitbook.io/typescript/ -- **Effective TypeScript**: Book by Dan Vanderkam diff --git a/src/cli.ts b/src/cli.ts index 784e94f..96a2d23 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -653,7 +653,7 @@ export function runClaudeAnalysis(projectDir: string, projectInfo: ProjectInfo): text: "Claude is analyzing your project...", spinner: { interval: 200, - frames: ["·", "✢", "✳", "✶", "✻", "✽", "✻", "✶", "✳", "✢"], + frames: ["·", "✢", "✳", "✶", "✳", "✢"], }, color: "cyan", }).start();