67 lines
3.2 KiB
Markdown
67 lines
3.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
## Build & Test Commands
|
|
|
|
```bash
|
|
# Build (dual ESM/CJS via tsup)
|
|
pnpm build
|
|
|
|
# Test (Vitest runtime tests)
|
|
pnpm test
|
|
|
|
# Run a single test file
|
|
pnpm test -- src/option/spec/map.spec.ts
|
|
|
|
# Type-level tests (vitest typecheck, runs *.type-spec.ts files)
|
|
pnpm test:types
|
|
|
|
# Watch mode
|
|
pnpm test:watch
|
|
|
|
# Type-check without emitting
|
|
pnpm typecheck
|
|
|
|
# Lint
|
|
pnpm lint
|
|
|
|
# Format
|
|
pnpm format
|
|
pnpm format:check
|
|
```
|
|
|
|
## Architecture
|
|
|
|
`native-monad` is a monad library for TypeScript that uses native JS/TS idioms (Array.prototype.map, Array.isArray, Promise.all patterns). **Do not use Rust/FP naming conventions** (no unwrap, orElse, inspect, getOrElse, etc.). It provides three monadic types with class-based implementations:
|
|
|
|
- **Result** (`Ok<T> | Err<E>`) - success/failure. Factory functions: `ok(value)`, `err(error)`.
|
|
- **Option** (`Some<T> | None`) - presence/absence. Factory functions: `some(value)`, `none()`. `none()` returns a frozen singleton.
|
|
- **Query** (`OkSome<T> | OkNone | ErrNone<E>`) - three-state monad combining Result and Option (success-with-value, success-without-value, error). Factory functions: `okSome(value)`, `okNone()`, `errNone(error)`. `okNone()` returns a frozen singleton.
|
|
|
|
Each module (`src/result/`, `src/option/`, `src/query/`) follows the same pattern:
|
|
1. An **interface** defining the API contract (e.g. `ResultInterface<T, E>`)
|
|
2. **Class implementations** for each variant (e.g. `Ok<T>`, `Err<E>`)
|
|
3. A **union type** alias (e.g. `type Result<T, E> = Ok<T> | Err<E>`)
|
|
4. **Factory functions** as lowercase creators (e.g. `ok()`, `err()`)
|
|
5. A **namespace object** with static collection operations (`Result.all()`, `Result.from()`, `Result.partition()`, `Result.compact()`, etc.)
|
|
6. A **Promise namespace** wrapping collection operations for async usage (`ResultPromise`, `OptionPromise`, `QueryPromise`)
|
|
|
|
The three types are independent modules with no cross-type conversions. Users convert via `match()` if needed.
|
|
|
|
**IMPORTANT: Banned method names.** Never suggest, generate, or reference these Rust/Haskell/FP idioms — they do not exist in this library and must not be proposed as additions:
|
|
`unwrap`, `unwrapOr`, `unwrapOrElse`, `expect`, `or`, `orElse`, `and`, `andThen`, `inspect`, `getOrElse`, `fold`, `contains`, `zip`, `unzip`, `transpose`.
|
|
Use `match()` for value extraction and `map()`/`flatMap()` for chaining. Only use methods defined in the interfaces.
|
|
|
|
## Test Conventions
|
|
|
|
There are two parallel test systems:
|
|
- **`*.spec.ts`** - Runtime behavior tests using Vitest with Arrange/Act/Assert pattern
|
|
- **`*.type-spec.ts`** - Compile-time type tests using vitest typecheck with expect-type (`expectTypeOf(x).toEqualTypeOf<T>()`)
|
|
|
|
Tests are colocated in `spec/` directories next to the module they test, organized by operation (e.g. `map.spec.ts`, `filter.spec.ts`, `is.spec.ts`).
|
|
|
|
## Key Design Details
|
|
|
|
- **Falsy** is defined as only `null | undefined` in `src/util/index.ts`. Values like `0`, `false`, and `""` are **not** considered falsy. `Option.from()` and `Query.from()` use this definition.
|
|
- Type narrowing is central: `isOk()`/`isErr()` are type guards (`this is Ok<T>`) enabling direct `.value`/`.err` access after checking.
|
|
- The package ships dual ESM/CJS via tsup. Entry point: `src/index.ts`.
|