diff --git a/README.md b/README.md index 7b50a24..536b3e2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ Pattern matching for TypeScript/ESM environments (F#-style, not regex). - Version updates via `npm version`. - Publishing via GitHub Actions on tagged commits (see `.github/workflows/ci.yml`). -- Changesets is available as a devDependency for changelog automation if desired. ## Contribution guidelines diff --git a/cspell.json b/cspell.json index 52fd7ee..86ab275 100644 --- a/cspell.json +++ b/cspell.json @@ -9,12 +9,14 @@ "oxfmt", "oxc", "nodenext", - "nocheck", "oxfmtrc", "oxlintrc", "sortpackagerc", "EDITMSG", - "typescriptteam" + "typescriptteam", + "gitmoji", + "dbaeumer", + "msvc" ], "ignorePaths": ["dist", "node_modules", "public", "coverage", "*.svg"] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7ddc7e3..7595ee5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,6 @@ "version": "0.0.0", "license": "MIT", "devDependencies": { - "@oxfmt/binding-linux-x64-musl": "^0.66.0", - "@oxlint/binding-linux-x64-musl": "^1.81.0", "@types/node": "^22.10.0", "c8": "^10.1.3", "check-outdated": "^2.13.0", @@ -26,6 +24,22 @@ }, "engines": { "node": ">=26" + }, + "optionalDependencies": { + "@oxfmt/binding-darwin-arm64": "^0.66.0", + "@oxfmt/binding-darwin-x64": "^0.66.0", + "@oxfmt/binding-linux-arm64-gnu": "^0.66.0", + "@oxfmt/binding-linux-arm64-musl": "^0.66.0", + "@oxfmt/binding-linux-x64-gnu": "^0.66.0", + "@oxfmt/binding-linux-x64-musl": "^0.66.0", + "@oxfmt/binding-win32-x64-msvc": "^0.66.0", + "@oxlint/binding-darwin-arm64": "^1.81.0", + "@oxlint/binding-darwin-x64": "^1.81.0", + "@oxlint/binding-linux-arm64-gnu": "^1.81.0", + "@oxlint/binding-linux-arm64-musl": "^1.81.0", + "@oxlint/binding-linux-x64-gnu": "^1.81.0", + "@oxlint/binding-linux-x64-musl": "^1.81.0", + "@oxlint/binding-win32-x64-msvc": "^1.81.0" } }, "node_modules/@bcoe/v8-coverage": { @@ -723,7 +737,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -740,7 +753,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -808,7 +820,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "glibc" ], @@ -828,7 +839,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "musl" ], @@ -928,7 +938,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "glibc" ], @@ -948,11 +957,11 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "musl" ], "license": "MIT", + "optional": true, "os": [ "linux" ], @@ -1018,7 +1027,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1069,7 +1077,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1086,7 +1093,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1154,7 +1160,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "glibc" ], @@ -1174,7 +1179,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "musl" ], @@ -1274,7 +1278,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "glibc" ], @@ -1294,11 +1297,11 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "musl" ], "license": "MIT", + "optional": true, "os": [ "linux" ], @@ -1364,7 +1367,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ diff --git a/package.json b/package.json index d5a54ae..e0f48be 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "build": "tsc -p tsconfig.build.json", "check": "npm run check:oxlint && npm run check:oxfmt && npm run check:tsc && npm run check:cspell && npm run check:package && npm run check:outdated", "check:cspell": "cspell .", - "check:outdated": "check-outdated", + "check:outdated": "check-outdated --ignore-pre-releases --ignore-packages @oxfmt/binding-darwin-arm64,@oxfmt/binding-darwin-x64,@oxfmt/binding-linux-arm64-gnu,@oxfmt/binding-linux-arm64-musl,@oxfmt/binding-linux-x64-gnu,@oxfmt/binding-linux-x64-musl,@oxfmt/binding-win32-x64-msvc,@oxlint/binding-darwin-arm64,@oxlint/binding-darwin-x64,@oxlint/binding-linux-arm64-gnu,@oxlint/binding-linux-arm64-musl,@oxlint/binding-linux-x64-gnu,@oxlint/binding-linux-x64-musl,@oxlint/binding-win32-x64-msvc", "check:oxfmt": "oxfmt --check src", "check:oxlint": "oxlint src", "check:package": "sort-package-json --check", @@ -49,8 +49,6 @@ "use:git-commit-message": "cp commit-message-template .git/COMMIT_EDITMSG || true" }, "devDependencies": { - "@oxfmt/binding-linux-x64-musl": "^0.66.0", - "@oxlint/binding-linux-x64-musl": "^1.81.0", "@types/node": "^22.10.0", "c8": "^10.1.3", "check-outdated": "^2.13.0", @@ -64,6 +62,22 @@ "type-fest": "^4.40.1", "typescript": "^7.0.2" }, + "optionalDependencies": { + "@oxfmt/binding-darwin-arm64": "^0.66.0", + "@oxfmt/binding-darwin-x64": "^0.66.0", + "@oxfmt/binding-linux-arm64-gnu": "^0.66.0", + "@oxfmt/binding-linux-arm64-musl": "^0.66.0", + "@oxfmt/binding-linux-x64-gnu": "^0.66.0", + "@oxfmt/binding-linux-x64-musl": "^0.66.0", + "@oxfmt/binding-win32-x64-msvc": "^0.66.0", + "@oxlint/binding-darwin-arm64": "^1.81.0", + "@oxlint/binding-darwin-x64": "^1.81.0", + "@oxlint/binding-linux-arm64-gnu": "^1.81.0", + "@oxlint/binding-linux-arm64-musl": "^1.81.0", + "@oxlint/binding-linux-x64-gnu": "^1.81.0", + "@oxlint/binding-linux-x64-musl": "^1.81.0", + "@oxlint/binding-win32-x64-msvc": "^1.81.0" + }, "engines": { "node": ">=26" }, diff --git a/project-specs.md b/project-specs.md index a872e09..86526ba 100644 --- a/project-specs.md +++ b/project-specs.md @@ -8,107 +8,200 @@ typescript-lib-starter-tiny => https://github.com/tmueller/typescript-lib-starte ## 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 +- **TypeScript**: Use strictest practical rules. Inline in `tsconfig.json` (not + via `@tsconfig/strictest`). The rule set is: `strict`, `noImplicitAny`, + `noImplicitThis`, `alwaysStrict`, `strictNullChecks`, `strictFunctionTypes`, + `strictBindCallApply`, `strictPropertyInitialization`, `noImplicitReturns`, + `noFallthroughCasesInSwitch`, `noUncheckedIndexedAccess`, `noImplicitOverride`, + `noUnusedLocals`, `noUnusedParameters`, `forceConsistentCasingInFileNames`, + `isolatedModules`, `verbatimModuleSyntax`. +- **EditorConfig**: Use `.editorconfig` from typescript-lib-starter-tiny. +- **oxfmt**: Rust-based formatter, Prettier-compatible. Replaces Prettier. + Config in `.oxfmtrc.json` (same shape as `.prettierrc`). +- **oxlint**: Rust-based linter. Replaces ESLint. Config in `.oxlintrc.json` + with `typescript`, `unicorn`, `oxc`, `import` plugins. Categories enabled + as errors: `correctness`, `suspicious`, `restriction`. As warnings: `perf`, + `style`. `nursery` is off. +- **oxlint rules disabled by design** (in `.oxlintrc.json`): + - `eslint/no-undefined` — we use `undefined` as the no-match sentinel. + - `eslint/sort-keys` — handler/case order is semantic, not alphabetical. + - `eslint/id-length` — `T`, `R`, `U`, `V` are standard TS generics. + - `import/no-named-export` — false positive on library entry re-exports. + For `*.test.ts` files additionally: `no-unused-expressions` (for + `expectTypeOf(...)` calls), `no-empty-file` (we have a single import + per test file in some cases), `import/no-nodejs-modules` (we use + `node:test`/`node:assert`/`node:fs` intentionally), `eslint/no-magic-numbers` + (literals in tests are fine). +- **Import sorting**: built into oxfmt (no separate plugin). +- **cspell**: Basic spelling configuration. Words dictionary in `cspell.json` + covers tooling names (`oxlint`, `oxfmt`, `oxc`, `nodenext`, + `oxfmtrc`, `oxlintrc`, `sortpackagerc`, `EDITMSG`, `typescriptteam`, + `gitmoji`, `dbaeumer`, `msvc`) and a few library names (`tslib`, + `typefest`, `lefthook`). +- **Lefthook**: Pre-commit checks for (run in parallel): + - oxlint on staged JS/TS files + - oxfmt --check on staged JS/TS files + - cspell on staged files + - sort-package-json --check + - tsc --noEmit + `outdated` is intentionally NOT a pre-commit check (it can flag + upstream patch releases that aren't actionable locally); it runs in + CI and via the explicit `lefthook run outdated` command. - **Additional Dev Dependencies**: - - - lefthook - - sort-package-json - - check-outdated + - lefthook + - sort-package-json + - check-outdated + - c8 (coverage for `node --test`) + - expect-type (type-level assertions in tests) + - oxfmt, oxlint (with their native bindings as `optionalDependencies` + so the correct binding is selected per platform automatically) + - typescript (TS 7) + - @types/node + - tslib (available for future runtime helper imports) + - type-fest (utility types) ## 2. Build & Test -- **Build Tool**: Vite (ESM only, no CJS) -- **Testing**: Vitest -- **TypeScript Build Output**: `dist` directory -- **Additional Runtime Dependencies**: - - tslib - - type-fest +- **Build Tool**: TypeScript 7 (`tsc`) — no bundler, no Vite. The build + is a plain `tsc -p tsconfig.build.json` invocation that emits ESM + JavaScript and `.d.ts` declarations to `dist/`. ESM only, no CJS. +- **Testing**: Node's built-in `node --test` with `--strip-types` (Node + 22.6+, unflagged on Node 24/26). Test files are co-located with + source as `*.test.ts`. No Vitest. +- **TypeScript Build Output**: `dist` directory (set in + `tsconfig.build.json#outDir`; `tsconfig.json` keeps `outDir` for + editor tooling but excludes tests from emission via + `tsconfig.build.json#exclude`). +- **Import extensions**: Source uses `.ts` extensions in imports + (e.g. `from "./match.ts"`) so `node --strip-types` resolves them + at test time. TypeScript's `rewriteRelativeImportExtensions` (in + `tsconfig.build.json`) rewrites these to `.js` in the emitted + `dist/*` output, so consumers see conventional ESM imports. +- **TypeScript Compiler Options Notes**: + - `allowImportingTsExtensions: true` is set in the root + `tsconfig.json` (works because the root config has `noEmit: true`). + - `rewriteRelativeImportExtensions: true` is set in + `tsconfig.build.json` to rewrite `.ts` to `.js` on emit. + - `module: nodenext`, `moduleResolution: nodenext` for ESM-first + Node packages. + - `verbatimModuleSyntax: true` enforces explicit `import type`. + - `target: es2024`, `lib: ["es2024"]` (Node 26 supports all ES2024 + features natively). +- **Additional Dev Dependencies** (for types and tests): + - `tslib` — available for runtime helper imports; not currently + used by source (kept for future use per the original spec). + - `type-fest` — utility types; not currently used by source + (kept for future use per the original spec). + - `@types/node` — types for `node:test`, `node:assert`, `node:fs`. +- **Node Version**: `>=26` (engines field). Pinned via `.node-version` + for fnm/nvm/volta/mise auto-switching and CI + (`actions/setup-node@v4` with `node-version-file: .node-version`). ## 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** +- **.gitignore**: Ignore `dist`, `node_modules`, `coverage`, and other + common files. +- **.node-version**: Single line containing the Node major version + (currently `26`). Used by version managers and CI. +- **.npmignore**: Ignore `node_modules/`, `coverage/`, `*.log`, + `*.tsbuildinfo`, `src/`, `.vscode/`, `.editorconfig`, + `.oxfmtrc.json`, `.oxlintrc.json`, `.node-version`, `cspell.json`, + `lefthook.yml`, `.sortpackagerc.json`, `commit-message-template`. + (Note: `dist/` is included via `package.json#files`, not by absence + from `.npmignore`.) +- **.oxfmtrc.json**: oxfmt configuration (Prettier-shaped). +- **.oxlintrc.json**: oxlint configuration. +- **.oxlintrc.json + .oxfmtrc.json** replace the old `.eslintrc.cjs` + and `.prettierrc`. +- **LICENSE**: MIT. +- **README.md**: Scaffolded. +- **commit-message-template**: From typescript-lib-starter-tiny. +- **Target Environments**: Node 26 LTS only (no browser target; this + is a pure Node library, no DOM, no DOM lib in tsconfig). +- **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** +- **Version Automation**: Use standard `npm version` for versioning. +- **Unused Dependency Check**: Use `check-outdated` (devDep, runs in CI + and via the explicit `lefthook run outdated` command). +- **No commitlint, no conventional commits**. Commits use gitmoji + prefixes (e.g. `:sparkles:`, `:wrench:`, `:bug:`, `:fire:`, + `:white_check_mark:`, `:tada:`) for at-a-glance categorization. -## 5. Scripts (Clustered as in typescript-lib-starter-tiny, named similarly) +## 5. Scripts ### SETUP -- `use:git-commit-message`: Set up commit message template (if needed) +- `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) +- `test`: Run `tsc --noEmit` then `node --test --strip-types src/`. +- `test:unit`: Run unit tests with `node --test --strip-types src/` + (no preceding typecheck). +- `test:ci`: Run tests in CI mode with c8 coverage (text + lcov + html + reporters), uploading `coverage/` as an artifact. ### BUILD -- `build`: Build the project using Vite +- `build`: Build the project using `tsc -p tsconfig.build.json` + (emits `dist/*.js` + `dist/*.d.ts` + sourcemaps, with `.ts` + imports rewritten to `.js`). ### CLEAN -- `clean`: Clean build output -- `clean:build`: Remove dist directory +- `clean`: Remove `dist/` via `node -e "fs.rmSync('dist', {recursive:true, force:true})"`. + (Replaces `clean:build` from the original spec — same effect, + no `rimraf` dep needed.) ### 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 +- `check`: Run all checks in order — `check:oxlint`, `check:oxfmt`, + `check:tsc`, `check:cspell`, `check:package`, `check:outdated`. +- `check:oxlint`: `oxlint src`. +- `check:oxfmt`: `oxfmt --check src`. +- `check:tsc`: `tsc --noEmit`. +- `check:cspell`: `cspell .`. +- `check:package`: `sort-package-json --check`. +- `check:outdated`: `check-outdated --ignore-pre-releases --ignore-packages @oxfmt/binding-*,@oxlint/binding-*`. The oxc native bindings are declared as `optionalDependencies` so the correct one is selected per platform automatically; the `*`-platform bindings show as "not installed" on the current platform and are explicitly ignored here. ### 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 +- `fix:oxlint`: `oxlint --fix src`. +- `fix:oxfmt`: `oxfmt src`. +- `fix:package`: `sort-package-json --write`. + (There is no `fix` aggregator in the scripts; run the `fix:*` scripts + individually or via the lefthook `commands:` block.) ### HOOKS -- Lefthook will run relevant scripts on staged files for pre-commit (typecheck, lint, spell, sort, format, check:outdated) +- Lefthook runs the relevant `check:*` scripts on staged files in + parallel for pre-commit. See `lefthook.yml`. --- ## 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 +- **Repository**: Hosted on GitHub. +- **Build Pipeline**: GitHub Actions (`.github/workflows/ci.yml`). + - `build` job on push and pull_request to `main` and on + `workflow_dispatch`. Steps: `actions/checkout@v4`, + `actions/setup-node@v4` (with `node-version-file: .node-version`, + `cache: npm`), `npm ci`, `npm run build`, `npm run check`, + `npm run test:ci`, then upload `coverage/` as an artifact. + - `publish` job: only on `refs/tags/*`, depends on `build`. Steps: + `actions/checkout@v4`, `actions/setup-node@v4` (with + `node-version-file: .node-version` and `registry-url`), + `npm ci`, `npm run build`, `npm publish --access public` + with `NODE_AUTH_TOKEN` from secrets. ## 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) +- **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. - **Recommended Workflow**: 1. Develop and merge PRs to main 2. Run all checks via CI @@ -125,40 +218,42 @@ typescript-lib-starter-tiny => https://github.com/tmueller/typescript-lib-starte - adt - typescript -> The library is for pattern matching (not regex), similar to F#'s pattern matching, for TypeScript/ESM environments. +> The library is for pattern matching (not regex), similar to F#'s +> pattern matching, for TypeScript/ESM environments. ## 9. Code Coverage -- **Configuration**: +- **Tool**: c8 (V8-native coverage, no instrumentation step). +- **Configuration**: c8 has no project config; the report shape is + pinned in the `test:ci` script: -```ts -import { defineConfig } from 'vitest/config'; -export default defineConfig({ - test: { - coverage: { - reporter: ['text', 'html', 'lcov'], - include: ['src/**/*.ts'], - exclude: ['src/**/*.test.ts', 'test/**'], - }, - }, -}); +```jsonc +"test:ci": "c8 --reporter=text --reporter=lcov --reporter=html node --test --strip-types src/" ``` -- 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 +- **Reporters**: text summary, HTML, and lcov (matching the original + spec). +- **CI**: `coverage/` is uploaded as a workflow artifact via + `actions/upload-artifact@v4` (see `.github/workflows/ci.yml`). +- **Optional**: Coverage thresholds can be added in c8 config when the + library surface stabilizes. ## 10. Source Structure & Tree Shaking -- **Source Directory**: All source code resides in `src/` and is exported via `src/index.ts`. +- **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 + - `sideEffects: false` in `package.json` (set). + - ESM-only exports; `package.json#exports` field maps `.` to + `{"types": "./dist/index.d.ts", "import": "./dist/index.js"}`. + - Avoid top-level side effects in modules. + - Explicit re-exports in `index.ts` for best results. +- Source structure (current): + - `src/index.ts` — public barrel. + - `src/match.ts` — `match(value).with(...).exhaustive() / .otherwise(...)` builder. + - `src/pattern.ts` — `P.literal`, `P.type`, `P.when`, `P.any`, `P.shape` constructors and the `Matcher` interface. + - `src/index.test.ts` — runtime + type-level tests using `node --test` + `expect-type`. +- The human will implement the source code. ## 11. Included Templates from typescript-lib-starter-tiny @@ -207,90 +302,137 @@ Resolves #... # Can use multiple lines with "-" for bullet points in body ``` -### README.md Structure (to scaffold) +### README.md Structure (scaffolded) - Project title and description - Development - Build: `npm run build` - Test: `npm run test`, `npm run test:ci` - - Checks: `npm run check`, `npm run fix` + - Checks: `npm run check`, `npm run fix:oxfmt`, `npm run fix:oxlint` +- Tooling section listing TypeScript 7, node --test, c8, oxlint, oxfmt, + cspell, sort-package-json, lefthook +- Requirements: Node.js >= 26 - VSCode integration - Debugging - Running tests -- Document workflows like - - Version updates - - Changelog automation - - Publishing + - oxc.oxc-vscode provides oxlint and oxfmt in-editor +- Workflows + - Version updates via `npm version` + - Publishing via GitHub Actions on tagged commits - Contribution guidelines - Commit signing (GPG) - - How to set up commit message template + - How to set up commit message template (`npm run use:git-commit-message`) - Reference to commit-message-template + - Type-level tests use `expect-type`'s `expectTypeOf(...)` inside + `node --test` cases ## 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 - +- Start by initializing git with a `main` branch. +- Initial commit: empty README + LICENSE. +- 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, + `:bug:` for fixes, `:fire:` for removals, + `:white_check_mark:` for tests, `:tada:` for initial commit). + - Example commit messages used in this project: + - `:tada: Initial commit with empty README` + - `:wrench: Track .vscode/settings.json for workspace settings` + - `:construction_worker: Added GitHub Actions workflow for CI/CD` + - `:test_tube: Added Vitest configuration with coverage` (later removed) + - `:sparkles: Scaffolded src/index.ts entry point for library code` + - `:wrench: Replace Vite/Vitest with TypeScript 7 and node --test` + - `:wrench: Replace ESLint and Prettier with oxlint and oxfmt` + - `:fire: Remove Vite scaffold leftovers` + - `:sparkles: Add initial pattern-matching API` + - `:white_check_mark: Add expect-type for type-level tests` + - `:wrench: Declare Node 26 as the supported runtime` + - `:bug: Use .ts extensions in imports for node --strip-types` + - `:wrench: Remove Prettier from editor formatter config` +- 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. +- Not currently configured. The intended workflow, when adopted, is a + changesets-driven release process: feature PRs include a changeset, + which gets consumed by a release workflow, producing a `CHANGELOG.md` + and a version bump on merge to main. +- The changelog should be 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. +- npm publishing is configured to be public by default. +- `publishConfig: { "access": "public" }` is set in `package.json`. +- The CI/CD pipeline publishes with `--access public` on tagged commits. ## 15. VSCode Integration -- Add a `.vscode/settings.json` with the following content: +- `.vscode/settings.json` uses `oxc.oxc-vscode` as the default + formatter for `[typescript]`, `[javascript]`, `[json]`, `[jsonc]`, + `[markdown]`, `[mdx]`, and `[yaml]` (oxfmt under the hood). ```json { "typescript.tsdk": "node_modules/typescript/lib", + "js/ts.tsdk.path": "node_modules/typescript/lib", "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true + }, + "[javascript]": { + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true }, "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true + }, + "[jsonc]": { + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true + }, + "[markdown]": { + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true }, "[mdx]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true }, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", + "[yaml]": { + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true - } + }, + "editor.defaultFormatter": "oxc.oxc-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) - - TODO: Native test extension with node test runner - - `ms-vscode.vscode-typescript-next` (for latest TS features, optional) +- `.vscode/extensions.json` recommends: + - `oxc.oxc-vscode` (oxlint + oxfmt, replaces eslint/prettier/vitest) + - `streetsidesoftware.code-spell-checker` (cspell) + - `typescriptteam.native-preview` (TypeScript 7 nightly support; + replaces the older `ms-vscode.vscode-typescript-next`) -- 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 +```json +{ + "recommendations": [ + "oxc.oxc-vscode", + "streetsidesoftware.code-spell-checker", + "typescriptteam.native-preview" + ] +} +``` + +- `.vscode/tasks.json` is not currently provided; common tasks + (build, test, lint, typecheck, format, spell, check:outdated) are + run via the npm scripts in `package.json` from the integrated + terminal. +- VSCode uses the workspace TypeScript version via + `typescript.tsdk` (and the explicit `js/ts.tsdk.path`), with + `oxc.oxc-vscode` for formatting and linting.