diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..31fb3b65 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,24 @@ +{ + "permissions": { + "allow": [ + "Bash(npm run test:*)", + "Bash(npm install)", + "Bash(npm audit:*)", + "Bash(npm outdated)", + "Bash(npm run typecheck:*)", + "Bash(npm run lint)", + "Bash(npm run coverage:*)", + "Bash(npm run build:production:*)", + "Bash(npm update:*)", + "Bash(npm view:*)", + "Bash(npm install:*)", + "Bash(npm run build:*)", + "Bash(npm run lint:*)", + "Bash(git checkout:*)", + "Bash(git add:*)", + "Bash(node:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..918b3b68 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,53 @@ +version: 2 +updates: + # Enable version updates for npm + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + open-pull-requests-limit: 10 + reviewers: + - "audit-brands/maintainers" + assignees: + - "audit-brands/maintainers" + commit-message: + prefix: "chore(deps):" + include: "scope" + labels: + - "dependencies" + - "javascript" + # Group minor and patch updates + groups: + development-dependencies: + patterns: + - "@types/*" + - "@vue/*" + - "@vitejs/*" + - "eslint*" + - "vitest*" + - "typescript" + - "vite" + update-types: + - "minor" + - "patch" + production-dependencies: + patterns: + - "@vueuse/*" + - "vue" + - "tailwindcss" + - "@tailwindcss/*" + update-types: + - "patch" + + # Enable version updates for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + commit-message: + prefix: "chore(ci):" + labels: + - "github-actions" + - "ci" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..812d0eae --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,114 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x, 22.x] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup 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 linting + run: npm run lint + + - name: Run type checking + run: npm run typecheck + + - name: Run tests + run: npm run test + + - name: Run test coverage + run: npm run coverage + + - name: Upload coverage to Codecov + if: matrix.node-version == '20.x' + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: false + verbose: true + + - name: Build package + run: npm run build:production + + - name: Build documentation + run: npm run build + + security: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run security audit + run: npm audit --audit-level=moderate + + - name: Check for outdated dependencies + run: npm outdated || true + + publish: + runs-on: ubuntu-latest + needs: [test, security] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + + - name: Build package + run: npm run build:production + + - name: Publish to NPM (if version changed) + run: | + # Only publish if package.json version is different from published version + CURRENT_VERSION=$(node -p "require('./package.json').version") + PUBLISHED_VERSION=$(npm view flowbite-vue version 2>/dev/null || echo "0.0.0") + + if [ "$CURRENT_VERSION" != "$PUBLISHED_VERSION" ]; then + echo "Publishing version $CURRENT_VERSION (was $PUBLISHED_VERSION)" + npm publish + else + echo "Version $CURRENT_VERSION already published, skipping" + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/dependency-updates.yml b/.github/workflows/dependency-updates.yml new file mode 100644 index 00000000..2620f880 --- /dev/null +++ b/.github/workflows/dependency-updates.yml @@ -0,0 +1,92 @@ +name: Dependency Updates + +on: + schedule: + # Run weekly on Mondays at 9 AM UTC + - cron: '0 9 * * 1' + workflow_dispatch: # Allow manual triggering + +jobs: + update-dependencies: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Check for updates + id: updates + run: | + npm outdated --json > outdated.json || true + if [ -s outdated.json ] && [ "$(cat outdated.json)" != "{}" ]; then + echo "has_updates=true" >> $GITHUB_OUTPUT + echo "Updates available:" + cat outdated.json + else + echo "has_updates=false" >> $GITHUB_OUTPUT + echo "No updates available" + fi + + - name: Create dependency update issue + if: steps.updates.outputs.has_updates == 'true' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const outdated = JSON.parse(fs.readFileSync('outdated.json', 'utf8')); + + let body = '# Dependency Updates Available\n\n'; + body += 'The following dependencies have updates available:\n\n'; + body += '| Package | Current | Wanted | Latest |\n'; + body += '|---------|---------|--------|--------|\n'; + + for (const [name, info] of Object.entries(outdated)) { + body += `| ${name} | ${info.current} | ${info.wanted} | ${info.latest} |\n`; + } + + body += '\n## Next Steps\n'; + body += '1. Review the changes for each package\n'; + body += '2. Test updates in a development environment\n'; + body += '3. Update dependencies with `npm update`\n'; + body += '4. Run tests to ensure compatibility\n'; + body += '\n*This issue was automatically created by the dependency update workflow.*'; + + // Check if an issue already exists + const issues = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: ['dependencies'] + }); + + const existingIssue = issues.data.find(issue => + issue.title.includes('Dependency Updates Available') + ); + + if (existingIssue) { + // Update existing issue + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: existingIssue.number, + body: body + }); + console.log(`Updated existing issue #${existingIssue.number}`); + } else { + // Create new issue + const issue = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Dependency Updates Available', + body: body, + labels: ['dependencies', 'maintenance'] + }); + console.log(`Created new issue #${issue.data.number}`); + } \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..9b57f26b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,83 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +### Development +```bash +# Start development server (VitePress documentation site) +npm run dev + +# Build documentation site +npm run build + +# Build the Vue component library for production +npm run build:production +``` + +### Testing & Quality +```bash +# Run tests with Vitest +npm run test + +# Run tests with coverage +npm run coverage + +# Run linting +npm run lint + +# Fix linting issues +npm run lint-fix + +# Type checking +npm run typecheck +``` + +### Library Build +```bash +# Build the package for distribution +npm run build:package + +# Build type declarations only +npm run build:types + +# Full production build (package + types) +npm run build:production +``` + +## Architecture + +### Component Structure +The project is a Vue 3 component library implementing Flowbite design system. Each component follows this structure: +- `src/components/FwbComponentName/` - Component directory + - `FwbComponentName.vue` - Main component implementation + - `types.ts` - TypeScript type definitions for props and types + - `composables/` - Vue composables for component logic (classes, state management) + - `tests/` - Vitest test files (when present) + +### Key Patterns +- **Class Generation**: Components use composables (e.g., `useComponentClasses.ts`) to generate Tailwind CSS classes based on props +- **Type Safety**: All components have TypeScript definitions in separate `types.ts` files +- **Composition API**: All components use Vue 3 Composition API with `