diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/package.json b/package.json new file mode 100644 index 0000000..1a2f09c --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "tiny-pattern-ts", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "~5.7.2", + "vite": "^6.3.1" + } +} diff --git a/project-specs.md b/project-specs.md new file mode 100644 index 0000000..e2fac7c --- /dev/null +++ b/project-specs.md @@ -0,0 +1,295 @@ +# Project Specifications for TypeScript NPM Module + +- name of package: tiny-pattern-ts + +## 0. References + +typescript-lib-starter-tiny => https://github.com/tmueller/typescript-lib-starter-tiny/ + +## 1. Development Environment + +- **TypeScript**: Use strictest rules (via npm package "@tsconfig/strictest", additional strictures) +- **EditorConfig**: Use `.editorconfig` from typescript-lib-starter-tiny +- **Prettier**: For code formatting, integrated with ESLint +- **ESLint**: Strictest type-checked rules, integrated with Prettier +- **Import Sorting**: Via Prettier or ESLint +- **cspell**: Basic spelling configuration +- **Lefthook**: Pre-commit checks for: + + - Type checking + - Spelling + - Package sorting + - Linting + - Formatting + - Outdated Packages + +- **Additional Dev Dependencies**: + + - lefthook + - sort-package-json + - check-outdated + +## 2. Build & Test + +- **Build Tool**: Vite (ESM only, no CJS) +- **Testing**: Vitest +- **TypeScript Build Output**: `dist` directory +- **Additional Runtime Dependencies**: + - tslib + - type-fest + +## 3. Project Structure & Files + +- __.gitignore__: Ignore `dist`, `node_modules`, and other common files +- **.npmignore**: Ignore `src` and other non-dist files +- **LICENSE**: MIT +- **README.md**: Scaffolded +- **commit-message-template**: From typescript-lib-starter-tiny +- **Target Environments**: Browser and latest LTS Node.js +- **No React, No CJS, ESM only** + +## 4. Automation & Quality + +- **Version Automation**: Use standard `npm version` for versioning +- **Unused Dependency Check**: Use `check-outdated` with config +- **No commitlint, no conventional commits** + +## 5. Scripts (Clustered as in typescript-lib-starter-tiny, named similarly) + +### SETUP + +- `use:git-commit-message`: Set up commit message template (if needed) + +### TEST + +- `test`: Run typecheck and all tests +- `test:unit`: Run unit tests with Vitest +- `test:ci`: Run tests in CI mode (with coverage, fail-fast) + +### BUILD + +- `build`: Build the project using Vite + +### CLEAN + +- `clean`: Clean build output +- `clean:build`: Remove dist directory + +### CHECK + +- `check`: Run all checks (lint, spell, typecheck, import/package sort, outdated) +- `check:eslint`: Run ESLint +- `check:prettier`: Check formatting with Prettier +- `check:cspell`: Run cspell +- `check:tsc`: TypeScript typecheck (no emit) +- `check:package`: Check package.json sort +- `check:outdated`: Check for unused/outdated dependencies + +### FIX + +- `fix`: Run all fixers (eslint, prettier, package sort) +- `fix:eslint`: Auto-fix ESLint issues +- `fix:prettier`: Auto-fix formatting with Prettier +- `fix:package`: Auto-fix package.json sort + +### HOOKS + +- Lefthook will run relevant scripts on staged files for pre-commit (typecheck, lint, spell, sort, format, check:outdated) + +--- + +## 6. Repository & CI/CD + +- **Repository**: Hosted on GitHub +- **Build Pipeline**: Use GitHub Actions for CI/CD + - On push and pull request: run build, lint, typecheck, test:ci, spell, check:outdated + - On release (tagged commit): publish to npm + +## 7. Versioning & Publishing + +- **Version Update**: Use `npm version` to bump version after merging to main and before publishing +- **Publishing to npm**: Only publish from CI on tagged commits (e.g., after version bump and release notes) +- **Recommended Workflow**: + 1. Develop and merge PRs to main + 2. Run all checks via CI + 3. Bump version with `npm version ` + 4. Push tag to GitHub + 5. CI builds and publishes to npm on tag + +## 8. NPM Keywords + +- pattern-matching +- pattern +- match +- algebraic-data-types +- adt +- typescript + +> The library is for pattern matching (not regex), similar to F#'s pattern matching, for TypeScript/ESM environments. + +## 9. Code Coverage + +- **Configuration**: + +```ts +import { defineConfig } from 'vitest/config'; +export default defineConfig({ + test: { + coverage: { + reporter: ['text', 'html', 'lcov'], + include: ['src/**/*.ts'], + exclude: ['src/**/*.test.ts', 'test/**'], + }, + }, +}); +``` + +- Coverage reports: text summary, HTML, and lcov formats + +- Add coverage thresholds if desired + +- **CI**: Ensure coverage is generated and optionally uploaded as an artifact or checked for minimum thresholds + +## 10. Source Structure & Tree Shaking + +- **Source Directory**: All source code resides in `src/` and is exported via `src/index.ts`. +- **Configuration**: + - Ensure `sideEffects: false` in `package.json` + - Use ESM-only exports + - Avoid top-level side effects in modules + - Prefer explicit exports in `index.ts` for best results +- the human will implement the source code + +## 11. Included Templates from typescript-lib-starter-tiny + +### .editorconfig + +```plaintext +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +max_line_length = 80 +trim_trailing_whitespace = true +quote_type = double + +[*.md] +max_line_length = 0 +trim_trailing_whitespace = false + +[COMMIT_EDITMSG] +max_line_length = 0 +``` + +### commit-message-template + +```plaintext +# If applied, this commit will... (Max 50 char) + + +# Explain why this change is being made (Max 72 Char) [WHAT and WHY vs HOW] + + +# Provide links or keys to any relevant tickets, articles or other resources +Resolves #... + +# --- COMMIT END --- +# Remember to +# Use the imperative mood in the subject line +# Capitalize the subject line +# Do not end the subject line with a period +# Separate subject from body with a blank line +# Use the body to explain what and why vs. how +# Can use multiple lines with "-" for bullet points in body +``` + +### README.md Structure (to scaffold) + +- Project title and description +- Development + - Build: `npm run build` + - Test: `npm run test`, `npm run test:ci` + - Checks: `npm run check`, `npm run fix` +- VSCode integration + - Debugging + - Running tests +- Document workflows like + - Version updates + - Changelog automation + - Publishing +- Contribution guidelines + - Commit signing (GPG) + - How to set up commit message template + - Reference to commit-message-template + +## 12. Project Initialization & Commit Strategy + +- Start by initilizing git with a main branch +- Initial commit: add an empty README.md +- create a feature branch: `feature/setup` +- For each technology or tool added (and its configuration), create a separate commit: + - Prepend each commit message with a matching gitmoji (e.g., :sparkles: for new features, :wrench: for config, etc.) + - Example commit messages: + - :tada: Initial commit with empty README + - :sparkles: Configured Vite (Vite-specific setup) + - :sparkles: Configured TypeScript (may be merged with Vite if dependent) + - :wrench: Configured ESLint + - :wrench: Configured Prettier + - ...and so on for each technology/tool +- Each commit should include only the relevant files and configuration for that technology/tool +- This approach ensures a clean, understandable project history and makes it easy to review or revert specific setup steps + + +## 13. Changelog Automation + +- Use a tool like standard-version or changesets to automate changelog generation from commit messages or PRs. +- Ensure changelog is updated as part of the release process. + +## 14. Publishing Public + +- Configure npm publishing to be public by default. +- Add `"publishConfig": { "access": "public" }` to package.json. +- Ensure CI/CD pipeline publishes with public access. + +## 15. VSCode Integration + +- Add a `.vscode/settings.json` with the following content: + +```json +{ + "typescript.tsdk": "node_modules/typescript/lib", + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[mdx]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + } +} +``` + +- Add `.vscode/extensions.json` with recommended extensions: + - `esbenp.prettier-vscode` (Prettier) + - `dbaeumer.vscode-eslint` (ESLint) + - `streetsidesoftware.code-spell-checker` (cspell) + - `vitest.explorer` (for test integration) + - `ms-vscode.vscode-typescript-next` (for latest TS features, optional) + +- Add `.vscode/tasks.json` for common tasks (optional): + - Build, test, lint, typecheck, format, spell, check:outdated +- Ensure VSCode uses workspace TypeScript version and Prettier for formatting diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..3bcdbd0 --- /dev/null +++ b/src/style.css @@ -0,0 +1,96 @@ +:root { + font-family: 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; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #3178c6aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/src/typescript.svg b/src/typescript.svg new file mode 100644 index 0000000..d91c910 --- /dev/null +++ b/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a4883f2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +}