Skip to content

Commit c99f344

Browse files
author
jarvisjiang
committed
docs: update CODEBUDDY.md for Vitest/Vite migration
1 parent 671dda2 commit c99f344

File tree

1 file changed

+114
-89
lines changed

1 file changed

+114
-89
lines changed

CODEBUDDY.md

Lines changed: 114 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pnpm run lint
3030
pnpm run build
3131

3232
# Manual prebuild steps (runs automatically before build)
33-
pnpm run prebuild # Cleans dist/, runs check and lint
33+
pnpm run prebuild # Runs check and lint
3434
```
3535

3636
**Build outputs:**
@@ -40,63 +40,73 @@ pnpm run prebuild # Cleans dist/, runs check and lint
4040

4141
### Testing
4242
```bash
43-
# Run tests with coverage (using Deno)
43+
# Run tests with coverage
4444
pnpm run test
4545

46-
# Generate HTML coverage report
47-
pnpm run test:html
46+
# Run tests in watch mode
47+
pnpm run test:watch
48+
49+
# Run tests with UI
50+
pnpm run test:ui
4851

4952
# Run a specific test by name pattern
50-
deno test -A --filter "test name pattern"
53+
pnpm exec vitest run --filter "test name pattern"
5154
```
5255

53-
**Note:** Tests use Deno's native test runner. The test file is located at `tests/fetch.test.ts`.
56+
**Note:** Tests use Vitest with MSW (Mock Service Worker) for API mocking. The test file is located at `tests/fetch.test.ts`.
57+
58+
### Examples
59+
```bash
60+
# Run example files
61+
pnpm run eg
62+
```
5463

5564
### Documentation
5665
```bash
5766
# Generate TypeDoc documentation to docs/
5867
pnpm run docs
5968
```
6069

70+
Documentation is hosted on GitHub Pages at https://jiangjie.github.io/fetch-t/
71+
6172
## Repository Structure
6273

6374
```
6475
/data/workspace/fetch-t/
6576
├── .github/workflows/ # CI/CD pipelines
66-
│ ├── test.yml # Run tests with Deno + Codecov
77+
│ ├── test.yml # Run tests with Vitest + Codecov
6778
│ ├── npm-publish.yml # NPM registry publication
6879
│ ├── npm-publish-github-packages.yml
6980
│ └── jsr-publish.yml # JSR registry publication
7081
├── .vscode/
71-
│ └── settings.json # VSCode: format on save, Deno disabled for src/
72-
├── docs/ # Generated TypeDoc documentation
73-
├── classes/
74-
│ ├── functions/
75-
│ ├── interfaces/
76-
│ ├── type-aliases/
77-
│ ├── variables/
78-
│ └── README.md
82+
│ └── settings.json # VSCode settings
83+
├── docs/ # Generated TypeDoc documentation (GitHub Pages)
84+
├── examples/ # Runnable usage examples
85+
│ ├── main.ts # Entry point (runs all examples)
86+
│ ├── basic.ts # Basic fetch requests
87+
│ ├── with-progress.ts # Progress tracking examples
88+
│ ├── abortable.ts # Abortable request examples
89+
│ └── error-handling.ts # Error handling patterns
7990
├── src/ # Source code
8091
│ ├── fetch/
8192
│ │ ├── constants.ts # Error constants (ABORT_ERROR, TIMEOUT_ERROR)
8293
│ │ ├── defines.ts # All type definitions and interfaces
8394
│ │ └── fetch.ts # Core implementation with 10 function overloads
8495
│ └── mod.ts # Public API entry point (re-exports)
8596
├── tests/
86-
│ └── fetch.test.ts # Deno test suite
97+
│ └── fetch.test.ts # Vitest test suite with MSW mocking
8798
├── .gitignore # Excludes: node_modules, dist, coverage
8899
├── CODEBUDDY.md # This file
89-
├── deno.json # Deno configuration and imports
90100
├── eslint.config.mjs # ESLint configuration (strict + stylistic)
91101
├── jsr.json # JSR registry metadata
92-
├── LICENSE # GPL-3.0
102+
├── LICENSE # MIT
93103
├── package.json # NPM metadata and scripts
94104
├── pnpm-lock.yaml # Dependency lockfile
95105
├── README.md # English documentation
96106
├── README.cn.md # Chinese documentation
97-
├── rollup.config.mjs # Build configuration
98107
├── tsconfig.json # TypeScript compiler options
99-
└── typedoc.json # TypeDoc documentation config
108+
├── typedoc.json # TypeDoc documentation config
109+
└── vite.config.ts # Vite build + Vitest test configuration
100110
```
101111

102112
## Code Architecture
@@ -124,16 +134,17 @@ src/
124134
- Uses `happy-rusty` library's `Result` type for explicit error handling
125135
- All responses are wrapped in `AsyncResult<T, E>` (no throwing exceptions)
126136
- Call `.inspect()` for success cases, `.inspectErr()` for errors
137+
- Use `.isOk()`, `.isErr()`, `.unwrap()`, `.unwrapErr()` for conditional handling
127138
- Example: `result.inspect(data => console.log(data)).inspectErr(err => console.error(err))`
128139

129140
3. **Stream Multiplexing**
130-
- Uses `ReadableStream.tee()` to split response streams (line 175 in fetch.ts)
141+
- Uses `ReadableStream.tee()` to split response streams
131142
- One stream for progress/chunk tracking, another for response body parsing
132143
- Enables progress callbacks without consuming the response
133144
- Creates a new Response object with the teed stream to maintain compatibility
134145

135146
4. **Timeout Mechanism**
136-
- Uses `AbortController` + `setTimeout` for timeout implementation (lines 255-271)
147+
- Uses `AbortController` + `setTimeout` for timeout implementation
137148
- Timer is automatically cancelled when response completes or fails
138149
- Timeout errors are named `TIMEOUT_ERROR` for easy identification
139150
- `cancelTimer` function ensures cleanup to prevent memory leaks
@@ -142,7 +153,7 @@ src/
142153
- `FetchError` class extends Error with HTTP status codes
143154
- Constants for common error types: `ABORT_ERROR`, `TIMEOUT_ERROR`
144155
- Non-ok responses (e.g., 404, 500) return `Err(FetchError)` instead of throwing
145-
- Response body is cancelled on error to prevent resource leaks (line 164)
156+
- Response body is cancelled on error to prevent resource leaks
146157

147158
### Core Types & Interfaces
148159

@@ -165,29 +176,40 @@ src/
165176
### Dependencies
166177

167178
**Runtime:**
168-
- `happy-rusty` (^1.5.0) - Provides Result/AsyncResult types for functional error handling
179+
- `happy-rusty` (^1.6.1) - Provides Result/AsyncResult types for functional error handling
169180
- `tiny-invariant` (^1.3.3) - Runtime assertions and validation
170181

171182
**Dev:**
172183
- TypeScript (^5.9.3) - Type checking and compilation
173-
- Rollup (^4.53.3) - Module bundler with plugins:
174-
- `rollup-plugin-esbuild` (^6.2.1) - Transpiles to ESNext
175-
- `rollup-plugin-dts` (^6.2.3) - Bundles TypeScript definitions
176-
- ESLint (^9.39.1) + typescript-eslint (^8.48.0) - Linting
177-
- TypeDoc (^0.27.9) + typedoc-plugin-markdown (^4.4.2) - Documentation generation
184+
- Vite (^7.3.0) - Build tool and dev server
185+
- `vite-plugin-dts` (^4.5.4) - Bundles TypeScript definitions
186+
- Vitest (^4.0.16) - Test framework
187+
- `@vitest/coverage-v8` (^4.0.16) - Coverage provider
188+
- MSW (^2.12.4) - Mock Service Worker for API mocking in tests
189+
- ESLint (^9.39.2) + typescript-eslint (^8.50.0) - Linting
190+
- TypeDoc (^0.28.15) - Documentation generation
178191

179-
**External dependencies are marked as external in rollup.config.mjs** - they are not bundled.
192+
**External dependencies are marked as external in vite.config.ts** - they are not bundled.
180193

181194
## Build System
182195

183-
### Rollup Configuration
196+
### Vite Configuration
184197
- **Entry point:** `src/mod.ts`
185198
- **Plugins:**
186-
- `rollup-plugin-esbuild` - Transpiles to ESNext target
187-
- `rollup-plugin-dts` - Bundles TypeScript definitions
199+
- `vite-plugin-dts` - Bundles TypeScript definitions with `rollupTypes: true`
200+
- **Build options:**
201+
- `target: 'esnext'` - Modern JavaScript output
202+
- `minify: false` - No minification for library
203+
- `sourcemap: true` - Source maps enabled
188204
- **External dependencies:** happy-rusty, tiny-invariant (not bundled)
189205
- **Tree shaking:** Set to 'smallest' for optimal bundle size
190-
- **Output formats:** Both CommonJS (.cjs) and ES Module (.mjs) with source maps
206+
- **Output formats:** Both CommonJS (.cjs) and ES Module (.mjs)
207+
208+
### Vitest Configuration (in vite.config.ts)
209+
- **Test pattern:** `**/*.test.ts`
210+
- **Coverage provider:** v8
211+
- **Coverage reporters:** text, json, html, lcov
212+
- **Coverage include:** `src/**/*.ts`
191213

192214
### TypeScript Configuration
193215
- **Target:** ESNext
@@ -196,7 +218,7 @@ src/
196218
- `noUnusedLocals: true`
197219
- `noUnusedParameters: true`
198220
- `noPropertyAccessFromIndexSignature: true`
199-
- **No emit mode** - Build is handled by Rollup
221+
- **No emit mode** - Build is handled by Vite
200222
- **Module detection:** Forced to treat all files as modules
201223
- **Bundler mode features:**
202224
- `allowImportingTsExtensions: true` - Allows `.ts` extensions in imports
@@ -208,34 +230,40 @@ src/
208230
- `@eslint/js` recommended rules
209231
- TypeScript ESLint strict rules
210232
- TypeScript ESLint stylistic rules
233+
- `@stylistic/eslint-plugin` for code formatting
211234
- Ignores `dist/` directory
212235

213236
## Testing Guidelines
214237

215238
### Test Structure
216239
- Tests are in `tests/fetch.test.ts`
217-
- Uses Deno's native test runner (`Deno.test()`)
218-
- Uses public fake API (fakestoreapi.com) for integration testing
240+
- Uses Vitest as test framework
241+
- Uses MSW (Mock Service Worker) for HTTP mocking
242+
- 28 test cases with 100% coverage
219243
- Coverage includes:
220244
- All response types (text, arraybuffer, blob, JSON)
221245
- HTTP methods (GET, POST, PUT, PATCH, DELETE)
222246
- Progress and chunk callbacks
223247
- Abort and timeout functionality
224-
- Error scenarios (invalid JSON, 404 errors, invalid URLs)
248+
- Error scenarios (invalid JSON, 404 errors, network errors)
249+
250+
### MSW Setup
251+
- Mock server configured with handlers for various endpoints
252+
- Supports streaming responses for progress testing
253+
- Handles error scenarios (404, network errors)
225254

226255
### Coverage
227-
- Uses Deno's built-in coverage tool
256+
- Uses Vitest's v8 coverage provider
228257
- CI uploads to Codecov with token authentication
229-
- HTML reports available via `pnpm run test:html`
258+
- HTML reports available via coverage output
230259
- Coverage files stored in `coverage/` directory (git-ignored)
231260

232261
## CI/CD
233262

234263
### GitHub Actions Workflows
235264

236265
**test.yml** - Runs on every push to main:
237-
- Sets up Node.js (latest) and installs pnpm globally
238-
- Sets up Deno for running tests
266+
- Sets up Node.js (latest) and pnpm
239267
- Runs `pnpm test` (includes coverage generation)
240268
- Uploads coverage to Codecov
241269

@@ -258,24 +286,24 @@ src/
258286
## Implementation Details
259287

260288
### fetchT Function Flow
261-
1. **URL validation** (lines 132-134): Uses `tiny-invariant` to ensure URL is string or URL object
262-
2. **Options destructuring** (lines 136-144): Extracts custom options from FetchInit
263-
3. **Abort controller setup** (lines 146-158): Creates controller if abortable or timeout specified
264-
4. **Fetch execution** (line 160): Calls native fetch with processed options
265-
5. **Response handling** (lines 160-248):
289+
1. **URL validation**: Uses `tiny-invariant` to ensure URL is string or URL object
290+
2. **Options destructuring**: Extracts custom options from FetchInit
291+
3. **Abort controller setup**: Creates controller if abortable or timeout specified
292+
4. **Fetch execution**: Calls native fetch with processed options
293+
5. **Response handling**:
266294
- Check `res.ok` - return FetchError if false
267295
- Stream multiplexing for progress/chunk callbacks
268296
- Parse response based on `responseType`
269297
- Default to returning Response object
270-
6. **Error handling** (lines 249-253): Catch and wrap in Err()
271-
7. **Timeout setup** (lines 255-271): Schedule abort if timeout specified
272-
8. **Return value** (lines 273-291): FetchTask if abortable, otherwise FetchResponse
298+
6. **Error handling**: Catch and wrap in Err()
299+
7. **Timeout setup**: Schedule abort if timeout specified
300+
8. **Return value**: FetchTask if abortable, otherwise FetchResponse
273301

274302
### Progress Tracking Details
275-
- Requires `Content-Length` header to calculate progress (lines 183-192)
303+
- Requires `Content-Length` header to calculate progress
276304
- If header missing, calls `onProgress(Err(new Error('No content-length...')))` once
277305
- Compatible with both HTTP/1.1 and HTTP/2 (checks both header formats)
278-
- Uses recursive promise chain for reading chunks (lines 194-216)
306+
- Uses recursive promise chain for reading chunks
279307
- Progress calculation: `completedByteLength += value.byteLength`
280308

281309
### AbortController Behavior
@@ -289,67 +317,64 @@ src/
289317

290318
### Pre-publish Checklist
291319
The `prepublishOnly` script automatically runs `pnpm run build`, which includes:
292-
1. Clean dist/ directory (via `pnpm dlx rimraf dist`)
293-
2. Type checking (`pnpm run check`)
294-
3. Linting (`pnpm run lint`)
295-
4. Rollup build
320+
1. Type checking (`pnpm run check`)
321+
2. Linting (`pnpm run lint`)
322+
3. Vite build
296323

297324
### Distribution Targets
298325
- **NPM:** @happy-ts/fetch-t
299326
- **JSR:** @happy-ts/fetch-t
300327
- **GitHub Packages:** Via workflow
301328

302-
### Distribution Package Includes
303-
- Source code (`src/`)
304-
- Built files (`dist/`)
305-
- Documentation (`docs/`)
306-
- README files (both English and Chinese)
307-
- LICENSE (GPL-3.0)
308-
- package.json, jsr.json
329+
### Distribution Package Includes (defined in package.json files array)
330+
- LICENSE
331+
- README.md
332+
- README.cn.md
333+
- CHANGELOG.md
334+
- dist/
309335

310336
## Known Issues & Gotchas
311337

312338
1. **Progress tracking requires Content-Length header**: If the server doesn't send this header, progress tracking will fail (onProgress receives an Err). The code checks both `content-length` and `Content-Length` for HTTP/2 compatibility.
313339

314340
2. **Stream tee() limitation**: Progress/chunk callbacks add overhead due to stream splitting. Each chunk is read twice - once for tracking, once for parsing.
315341

316-
3. **Import extensions**: Source code uses `.ts` extensions in imports which is non-standard but enabled by TypeScript bundler mode. This is required for Deno compatibility.
342+
3. **Import extensions**: Source code uses `.ts` extensions in imports which is non-standard but enabled by TypeScript bundler mode.
317343

318-
4. **Deno vs Build environment**: The `.vscode/settings.json` disables Deno for `src/`, `eslint.config.mjs`, and `rollup.config.mjs` because these use Node.js-style module resolution during development/build, but tests use Deno.
344+
4. **Invalid JSON handling**: When `responseType: 'json'` is specified but the response is invalid JSON, the function returns `Err(new Error('Response is invalid json...'))` instead of letting the parse error propagate.
319345

320-
5. **Invalid JSON handling**: When `responseType: 'json'` is specified but the response is invalid JSON, the function returns `Err(new Error('Response is invalid json...'))` instead of letting the parse error propagate.
346+
5. **happy-rusty Result API**: Use `isOk()`, `isErr()`, `unwrap()`, `unwrapErr()` methods. Note that `match()` method does NOT exist in happy-rusty.
321347

322348
## Key Files Reference
323349

324350
### Source Code
325-
- `src/mod.ts:1-3` - Main entry point (re-exports from fetch/)
326-
- `src/fetch/fetch.ts:130` - Core fetchT implementation function
327-
- `src/fetch/fetch.ts:14-120` - 10 function overload signatures
328-
- `src/fetch/fetch.ts:175` - Stream tee() for progress tracking
329-
- `src/fetch/fetch.ts:183-192` - Content-Length header handling
330-
- `src/fetch/fetch.ts:255-271` - Timeout implementation
331-
- `src/fetch/defines.ts:16-33` - FetchTask interface
332-
- `src/fetch/defines.ts:58-85` - FetchInit interface
333-
- `src/fetch/defines.ts:90-104` - FetchError class
334-
- `src/fetch/constants.ts:1-2` - Error constants
351+
- `src/mod.ts` - Main entry point (re-exports from fetch/)
352+
- `src/fetch/fetch.ts` - Core fetchT implementation function with 10 overloads
353+
- `src/fetch/defines.ts` - All type definitions (FetchTask, FetchInit, FetchError, etc.)
354+
- `src/fetch/constants.ts` - Error constants (ABORT_ERROR, TIMEOUT_ERROR)
335355

336356
### Configuration
337-
- `package.json:22-34` - Available npm scripts
338-
- `package.json:56-59` - Runtime dependencies
339-
- `rollup.config.mjs:17-52` - Build configuration (dual output)
340-
- `tsconfig.json:1-29` - TypeScript compiler options
341-
- `eslint.config.mjs:4-13` - ESLint flat config
342-
- `typedoc.json:1-17` - Documentation generation settings
343-
- `deno.json:1-7` - Deno imports and configuration
344-
- `jsr.json:1-17` - JSR registry metadata
345-
346-
### Tests & CI
347-
- `tests/fetch.test.ts:1` - Test suite
348-
- `.github/workflows/test.yml:1` - CI test workflow
357+
- `package.json` - NPM metadata, scripts, and dependencies
358+
- `vite.config.ts` - Vite build configuration + Vitest test configuration
359+
- `tsconfig.json` - TypeScript compiler options
360+
- `eslint.config.mjs` - ESLint flat config
361+
- `typedoc.json` - Documentation generation settings
362+
- `jsr.json` - JSR registry metadata
363+
364+
### Tests & Examples
365+
- `tests/fetch.test.ts` - Vitest test suite with MSW mocking
366+
- `examples/main.ts` - Example entry point
367+
- `examples/basic.ts` - Basic usage examples
368+
- `examples/with-progress.ts` - Progress tracking examples
369+
- `examples/abortable.ts` - Abortable request examples
370+
- `examples/error-handling.ts` - Error handling examples
371+
372+
### CI/CD
373+
- `.github/workflows/test.yml` - CI test workflow
349374
- `.github/workflows/npm-publish.yml` - NPM publication
350375
- `.github/workflows/jsr-publish.yml` - JSR publication
351376

352377
### Documentation
353378
- `README.md` - English documentation
354379
- `README.cn.md` - Chinese documentation
355-
- `docs/README.md` - Generated API documentation index
380+
- `docs/` - Generated TypeDoc documentation (GitHub Pages)

0 commit comments

Comments
 (0)