@@ -30,7 +30,7 @@ pnpm run lint
3030pnpm 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
4444pnpm 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/
5867pnpm 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
1291403 . ** 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
1351464 . ** 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
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
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
291319The ` 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
3123381 . ** 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
3143402 . ** 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