diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81d60b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: CC0-1.0 + +# Dependencies +node_modules/ + +# Build artifacts +dist/ +build/ +.vite/ +.turbo/ + +# Environment & Secrets +.env +.env.* +!.env.example +secrets/ +credentials/ +*.key +*.pem +*.p12 +*.pfx +*.keystore +*.jks +.npmrc +.yarnrc + +# Testing +coverage/ +.nyc_output/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db +Desktop.ini + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Temporary files +*.tmp +*.temp +.cache/ + +# Storybook +storybook-static/ diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..1dd8622 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "default": true, + "MD013": false, + "MD033": false, + "MD041": false +} diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..4890ada --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,3 @@ +node_modules/ +LICENSES/ +CHANGELOG.md diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d35af50 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 SecPal +# SPDX-License-Identifier: CC0-1.0 + +node_modules/ +dist/ +build/ +coverage/ +package-lock.json +pnpm-lock.yaml +yarn.lock +.vite/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..115ffb9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "semi": true, + "trailingComma": "es5", + "singleQuote": false, + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56a5e34 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Initial repository setup +- React + TypeScript + Vite configuration +- Testing setup with Vitest and React Testing Library +- REUSE 3.3 compliance +- Pre-commit and pre-push quality gates + +[unreleased]: https://github.com/SecPal/frontend/commits/main diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..132c2b6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,5 @@ +This project is licensed under the GNU Affero General Public License v3.0 or later. + +See LICENSES/AGPL-3.0-or-later.txt for the full license text. + +For third-party licenses, see the LICENSES/ directory. diff --git a/README.md b/README.md index 0c9bf2b..0cc5a18 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,208 @@ -# frontend -React/TypeScript frontend for SecPal platform + + +# SecPal Frontend + +[![REUSE Compliance](https://github.com/SecPal/frontend/actions/workflows/reuse.yml/badge.svg)](https://github.com/SecPal/frontend/actions/workflows/reuse.yml) +[![License Check](https://github.com/SecPal/frontend/actions/workflows/license-compatibility.yml/badge.svg)](https://github.com/SecPal/frontend/actions/workflows/license-compatibility.yml) +[![Quality Gates](https://github.com/SecPal/frontend/actions/workflows/quality.yml/badge.svg)](https://github.com/SecPal/frontend/actions/workflows/quality.yml) + +React/TypeScript frontend for the SecPal platform. + +## ๐Ÿ“‹ Prerequisites + +- Node.js >= 20.0.0 +- npm >= 10.0.0 +- Git with GPG signing configured + +## ๐Ÿš€ Getting Started + +### Clone Repository + +```bash +cd ~/code/SecPal +git clone https://github.com/SecPal/frontend.git +cd frontend +``` + +### โš ๏ธ IMPORTANT: Create Symlinks (DRY Principle) + +**Before installing dependencies**, you MUST create symlinks to avoid file duplication: + +```bash +# Navigate to frontend repository +cd ~/code/SecPal/frontend + +# Create symlinks to .github repository (governance files) +ln -sf ../.github/CONTRIBUTING.md . +ln -sf ../.github/SECURITY.md . +ln -sf ../.github/CODE_OF_CONDUCT.md . +ln -sf ../.github/CODEOWNERS . +ln -sf ../.github/.editorconfig .editorconfig +ln -sf ../.github/.gitattributes .gitattributes + +# Verify symlinks were created correctly +file CONTRIBUTING.md # Should show: symbolic link to ../.github/CONTRIBUTING.md +``` + +**Why symlinks?** To maintain DRY (Don't Repeat Yourself) principle across repositories. All governance files are centralized in the `.github` repository. + +### Install Dependencies + +```bash +npm install +``` + +### Setup Pre-Commit Hooks + +```bash +./scripts/setup-pre-commit.sh +``` + +## ๐Ÿ› ๏ธ Development + +### Start Development Server + +```bash +npm run dev +``` + +### Build for Production + +```bash +npm run build +``` + +### Run Tests + +```bash +# Run all tests +npm test + +# Run tests in watch mode +npm run test:ui + +# Generate coverage report +npm run test:coverage +``` + +### Code Quality + +```bash +# Lint code +npm run lint + +# Type checking +npm run typecheck + +# Format code +npm run format + +# Check formatting +npm run format:check +``` + +### Pre-Push Validation + +**Before every push**, run the preflight script: + +```bash +./scripts/preflight.sh +``` + +This runs: + +- โœ… Prettier formatting check +- โœ… Markdownlint +- โœ… REUSE compliance +- โœ… ESLint +- โœ… TypeScript type checking +- โœ… Vitest test suite +- โœ… PR size validation (โ‰ค600 lines) + +## ๐Ÿ“ Project Structure + +``` +frontend/ +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ components/ # React components +โ”‚ โ”œโ”€โ”€ hooks/ # Custom hooks +โ”‚ โ”œโ”€โ”€ pages/ # Page components +โ”‚ โ”œโ”€โ”€ services/ # API services +โ”‚ โ”œโ”€โ”€ types/ # TypeScript types +โ”‚ โ”œโ”€โ”€ utils/ # Utility functions +โ”‚ โ”œโ”€โ”€ App.tsx # Root component +โ”‚ โ””โ”€โ”€ main.tsx # Entry point +โ”œโ”€โ”€ public/ # Static assets +โ”œโ”€โ”€ tests/ # Test files +โ”œโ”€โ”€ .github/ # GitHub workflows and templates +โ”œโ”€โ”€ scripts/ # Build and utility scripts +โ””โ”€โ”€ package.json # Dependencies and scripts +``` + +## ๐Ÿงช Testing Guidelines + +- **Coverage target:** 80%+ for new code, 100% for critical paths +- **TDD mandatory:** Write failing test first, implement, refactor +- Use `@testing-library/react` for component testing +- Mock API calls with MSW (Mock Service Worker) +- Test user-visible behavior, not implementation + +## ๐Ÿ”’ Security + +- **Secret scanning:** Enabled with push protection +- **Dependabot:** Daily security updates (04:00 CET) +- **SAST:** CodeQL analysis on pull requests +- **Never commit:** API keys, passwords, tokens, `.env` files + +See [SECURITY.md](SECURITY.md) for reporting vulnerabilities. + +## ๐Ÿ“ Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. + +### Branch Naming Convention + +- `feature/` - New features +- `fix/` - Bug fixes +- `docs/` - Documentation +- `refactor/` - Code refactoring +- `test/` - Test additions/fixes +- `chore/` - Maintenance +- `spike/` - Exploration (no TDD required, cannot merge to main) + +### Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: add user authentication +fix: resolve memory leak in dashboard +docs: update API integration guide +test: add tests for login form +``` + +## ๐Ÿ“œ License + +**AGPL-3.0-or-later** - See [LICENSE](LICENSE) for details. + +This project is REUSE 3.3 compliant. All files contain SPDX license headers. + +## ๐Ÿ”— Related Repositories + +- [API](https://github.com/SecPal/api) - Laravel backend +- [Contracts](https://github.com/SecPal/contracts) - OpenAPI specifications +- [.github](https://github.com/SecPal/.github) - Organization defaults + +## ๐Ÿ“ž Support + +- **Issues:** [GitHub Issues](https://github.com/SecPal/frontend/issues) +- **Security:** See [SECURITY.md](SECURITY.md) +- **Code of Conduct:** [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) + +--- + +**Maintained by:** SecPal Team +**Last Updated:** October 2025 diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000..abcaac8 --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2025 SecPal +# SPDX-License-Identifier: CC0-1.0 + +version = 1 +SPDX-FileCopyrightText = "SecPal Contributors" + +[[annotations]] +path = "src/**" +SPDX-License-Identifier = "AGPL-3.0-or-later" + +[[annotations]] +path = "public/**" +SPDX-License-Identifier = "AGPL-3.0-or-later" + +[[annotations]] +path = "package.json" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "package-lock.json" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "tsconfig*.json" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "vite.config.ts" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".prettierrc.json" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".prettierignore" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".gitignore" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "README.md" +SPDX-FileCopyrightText = "2025 SecPal" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".github/**" +SPDX-FileCopyrightText = "2025 SecPal" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "CHANGELOG.md" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".markdownlint*.json" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".markdownlintignore" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "scripts/**" +SPDX-FileCopyrightText = "2025 SecPal Contributors" +SPDX-License-Identifier = "MIT" diff --git a/index.html b/index.html new file mode 100644 index 0000000..764de3b --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + SecPal + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..e3bfd77 --- /dev/null +++ b/package.json @@ -0,0 +1,62 @@ +{ + "name": "@secpal/frontend", + "version": "0.0.1", + "description": "React/TypeScript frontend for SecPal platform", + "private": true, + "type": "module", + "author": "SecPal", + "license": "AGPL-3.0-or-later", + "repository": { + "type": "git", + "url": "https://github.com/SecPal/frontend.git" + }, + "homepage": "https://github.com/SecPal/frontend#readme", + "bugs": { + "url": "https://github.com/SecPal/frontend/issues" + }, + "keywords": [ + "secpal", + "frontend", + "react", + "typescript", + "vite" + ], + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "typecheck": "tsc --noEmit", + "test": "vitest", + "test:ui": "vitest --ui", + "test:coverage": "vitest --coverage", + "format": "prettier --write '**/*.{md,yml,yaml,json,ts,tsx,js,jsx}'", + "format:check": "prettier --check '**/*.{md,yml,yaml,json,ts,tsx,js,jsx}'" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@testing-library/react": "^16.1.0", + "@testing-library/user-event": "^14.5.2", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@typescript-eslint/eslint-plugin": "^8.26.0", + "@typescript-eslint/parser": "^8.26.0", + "@vitejs/plugin-react": "^4.3.4", + "@vitest/ui": "^3.0.5", + "eslint": "^9.18.0", + "eslint-plugin-react-hooks": "^5.1.0", + "eslint-plugin-react-refresh": "^0.4.18", + "jsdom": "^25.0.1", + "prettier": "^3.4.2", + "typescript": "^5.7.3", + "vite": "^6.0.6", + "vitest": "^3.0.5" + }, + "engines": { + "node": ">=20.0.0", + "npm": ">=10.0.0" + } +} diff --git a/scripts/preflight.sh b/scripts/preflight.sh new file mode 100644 index 0000000..446aae9 --- /dev/null +++ b/scripts/preflight.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: MIT + +set -euo pipefail + +ROOT_DIR="$(git rev-parse --show-toplevel)" +cd "$ROOT_DIR" + +# Auto-detect default branch (fallback to main) +BASE="$(git remote show origin 2>/dev/null | sed -n '/HEAD branch/s/.*: //p')" +[ -z "${BASE:-}" ] && BASE="main" + +echo "Using base branch: $BASE" + +# Fetch base branch for PR size check (failure is handled later) +git fetch origin "$BASE" 2>/dev/null || true + +# 0) Formatting & Compliance +FORMAT_EXIT=0 +if command -v npx >/dev/null 2>&1; then + npx --yes prettier --check '**/*.{md,yml,yaml,json,ts,tsx,js,jsx}' || FORMAT_EXIT=1 + npx --yes markdownlint-cli2 '**/*.md' || FORMAT_EXIT=1 +fi +# Workflow linting (part of documented gates) +if [ -d .github/workflows ]; then + if command -v actionlint >/dev/null 2>&1; then + actionlint || FORMAT_EXIT=1 + else + echo "Warning: .github/workflows found but actionlint not installed - skipping workflow lint" >&2 + fi +fi +if command -v reuse >/dev/null 2>&1; then + reuse lint || FORMAT_EXIT=1 +fi +if [ "$FORMAT_EXIT" -ne 0 ]; then + echo "Formatting/compliance checks failed. Fix issues above." >&2 + exit 1 +fi + +# 1) Node.js / React / TypeScript +if [ -f pnpm-lock.yaml ] && command -v pnpm >/dev/null 2>&1; then + pnpm install --frozen-lockfile + pnpm run --if-present lint + pnpm run --if-present typecheck + pnpm run --if-present test +elif [ -f package-lock.json ] && command -v npm >/dev/null 2>&1; then + npm ci + npm audit --audit-level=high || { + echo "High or critical severity vulnerabilities detected by npm audit. Please address the issues above before continuing." >&2 + exit 1 + } + npm run --if-present lint + npm run --if-present typecheck + npm run --if-present test +elif [ -f yarn.lock ] && command -v yarn >/dev/null 2>&1; then + yarn install --frozen-lockfile + if command -v jq >/dev/null 2>&1; then + jq -e '.scripts.lint' package.json >/dev/null 2>&1 && yarn lint + jq -e '.scripts.typecheck' package.json >/dev/null 2>&1 && yarn typecheck + jq -e '.scripts.test' package.json >/dev/null 2>&1 && yarn test + elif command -v node >/dev/null 2>&1; then + node -e "process.exit(require('./package.json').scripts?.lint ? 0 : 1)" && yarn lint + node -e "process.exit(require('./package.json').scripts?.typecheck ? 0 : 1)" && yarn typecheck + node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)" && yarn test + else + echo "Warning: jq and node not found - attempting to run yarn scripts (failures will be ignored)" >&2 + yarn lint 2>/dev/null || true + yarn typecheck 2>/dev/null || true + yarn test 2>/dev/null || true + fi +fi + +# 2) Check PR size locally (against BASE) +if ! git rev-parse -q --verify "origin/$BASE" >/dev/null 2>&1; then + echo "Warning: Cannot verify base branch origin/$BASE - skipping PR size check." >&2 + echo "Tip: Run 'git fetch origin $BASE' to enable PR size checking." >&2 +else + MERGE_BASE=$(git merge-base "origin/$BASE" HEAD 2>/dev/null) + if [ -z "$MERGE_BASE" ]; then + echo "Warning: Cannot determine merge base with origin/$BASE. Skipping PR size check." >&2 + else + # Use --numstat for locale-independent parsing (sum insertions + deletions) + CHANGED=$(git diff --numstat "$MERGE_BASE"..HEAD 2>/dev/null | awk '{ins+=$1; del+=$2} END {print ins+del+0}') + [ -z "$CHANGED" ] && CHANGED=0 + if [ "$CHANGED" -gt 600 ]; then + echo "PR too large ($CHANGED > 600 lines). Please split into smaller slices." >&2 + exit 2 + fi + echo "Preflight OK ยท Changed lines: $CHANGED" + fi +fi + +# All checks passed +exit 0 diff --git a/scripts/setup-pre-commit.sh b/scripts/setup-pre-commit.sh new file mode 100644 index 0000000..038c425 --- /dev/null +++ b/scripts/setup-pre-commit.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: MIT + +set -euo pipefail + +ROOT_DIR="$(git rev-parse --show-toplevel)" +GIT_HOOKS_DIR="$ROOT_DIR/.git/hooks" +PROJECT_HOOKS_DIR="$ROOT_DIR/.githooks" + +echo "Setting up pre-commit hooks..." + +# Create .githooks directory if it doesn't exist +mkdir -p "$PROJECT_HOOKS_DIR" + +# Create pre-push hook +cat > "$PROJECT_HOOKS_DIR/pre-push" << 'EOF' +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: MIT + +set -euo pipefail + +ROOT_DIR="$(git rev-parse --show-toplevel)" +cd "$ROOT_DIR" + +# Check if current branch is spike/* +BRANCH=$(git rev-parse --abbrev-ref HEAD) +if [[ "$BRANCH" == spike/* ]]; then + echo "Spike branch detected ($BRANCH) - running minimal checks (formatting + REUSE)" + + # Run only formatting and REUSE compliance + FORMAT_EXIT=0 + if command -v npx >/dev/null 2>&1; then + npx --yes prettier --check '**/*.{md,yml,yaml,json,ts,tsx,js,jsx}' || FORMAT_EXIT=1 + npx --yes markdownlint-cli2 '**/*.md' || FORMAT_EXIT=1 + fi + if command -v reuse >/dev/null 2>&1; then + reuse lint || FORMAT_EXIT=1 + fi + + if [ "$FORMAT_EXIT" -ne 0 ]; then + echo "Formatting/compliance checks failed. Fix issues above." >&2 + exit 1 + fi + + echo "Spike branch checks passed." + exit 0 +fi + +# For non-spike branches, run full preflight script +if [ -f "$ROOT_DIR/scripts/preflight.sh" ]; then + "$ROOT_DIR/scripts/preflight.sh" +else + echo "Warning: preflight.sh not found - skipping pre-push checks" >&2 +fi +EOF + +chmod +x "$PROJECT_HOOKS_DIR/pre-push" + +# Create symlink in .git/hooks +ln -sf "$PROJECT_HOOKS_DIR/pre-push" "$GIT_HOOKS_DIR/pre-push" + +echo "โœ… Pre-commit hooks configured successfully" +echo " - Pre-push hook: Runs preflight.sh before every push" +echo " - Spike branches: Only formatting + REUSE (tests skipped)" +echo "" +echo "To bypass (NOT RECOMMENDED):" +echo " git push --no-verify" diff --git a/src/App.test.tsx b/src/App.test.tsx new file mode 100644 index 0000000..fec8f7d --- /dev/null +++ b/src/App.test.tsx @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2025 SecPal +// SPDX-License-Identifier: AGPL-3.0-or-later + +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; + +describe("App", () => { + it("renders welcome message", () => { + render(); + expect(screen.getByText(/SecPal Frontend/i)).toBeInTheDocument(); + }); + + it("renders main content", () => { + render(); + expect( + screen.getByText(/Welcome to SecPal - Your secure platform/i) + ).toBeInTheDocument(); + }); +}); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..cf3fdc7 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2025 SecPal +// SPDX-License-Identifier: AGPL-3.0-or-later + +function App() { + return ( +
+
+

SecPal Frontend

+
+
+

Welcome to SecPal - Your secure platform

+
+
+ ); +} + +export default App; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..2b1182d --- /dev/null +++ b/src/index.css @@ -0,0 +1,44 @@ +/* SPDX-FileCopyrightText: 2025 SecPal */ +/* SPDX-License-Identifier: AGPL-3.0-or-later */ + +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +.app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +header h1 { + font-size: 3.2em; + line-height: 1.1; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } +} diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..f80f1af --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 SecPal +// SPDX-License-Identifier: AGPL-3.0-or-later + +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App"; +import "./index.css"; + +const rootElement = document.getElementById("root"); +if (!rootElement) { + throw new Error("Root element not found"); +} + +createRoot(rootElement).render( + + + +); diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 0000000..eb9431c --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,4 @@ +// SPDX-FileCopyrightText: 2025 SecPal +// SPDX-License-Identifier: AGPL-3.0-or-later + +import "@testing-library/jest-dom"; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..76baccb --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Path aliases */ + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..97ede7e --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..c06bc61 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2025 SecPal +// SPDX-License-Identifier: CC0-1.0 + +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import path from "path"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": path.resolve(__dirname, "src"), + }, + }, + test: { + globals: true, + environment: "jsdom", + setupFiles: "./tests/setup.ts", + coverage: { + provider: "v8", + reporter: ["text", "json", "html"], + exclude: [ + "node_modules/", + "tests/", + "**/*.config.ts", + "**/*.d.ts", + "**/index.ts", + ], + }, + }, +});