# v2.0.0 — 2026-06-01

## Overview

v2.0.0 is a full **TypeScript rewrite** of monSQLize. The public API is preserved — existing v1 code requires only minor configuration adjustments to run on v2.

---

## Architecture

| Layer | Change |
|---|---|
| Source language | JavaScript → TypeScript (strict mode) |
| Cache engine | Internal implementation → [`cache-hub`](https://github.com/vextjs/cache-hub) |
| Internal structure | Flat modules → capability layers + adapter bridge |
| Type declarations | Hand-maintained `.d.ts` → generated from source (single source of truth) |

---

## Compatibility Notes and Breaking Changes

### B1 — `SagaResult` shape documents v1/v2 aliases

`SagaResult` now exposes the runtime fields and the restored v1/v2 alias fields:

```ts
{
  executionId: string;          // primary v1 field
  sagaId?: string;              // v2 alias, optional for v1 fixtures
  sagaName?: string;
  success: boolean;
  result?: unknown;
  error?: Error;
  errorMessage?: string;
  completedSteps: string[];
  completedStepCount?: number;
  completedStepNames?: string[];
  compensatedSteps: string[];
  duration: number;
  compensation?: { success: boolean; results: [...] };
}
```

### B2 — `TransactionInfo.status` keeps the v1 `'started'` value

The internal transaction state still uses `'active'`, but `Transaction#getInfo().status` maps it back to `'started'` for v1 callers. Public values are `'pending' | 'started' | 'committed' | 'aborted'`.

### B3 — `getPoolStats()` / `getPoolHealth()` return `Record<string, T>`

```ts
// v1 — array
getPoolStats(): PoolStats[]
getPoolHealth(): PoolHealthStatus[]

// v2 — keyed by pool name
getPoolStats(): Record<string, PoolStats>
getPoolHealth(): Record<string, PoolHealthStatus>
```

### B4 — `PoolStats` shape extended

`PoolStats` now includes `connections`, `available`, `waiting`, and `status` fields that were absent in v1 type declarations (but present in the runtime).

### B5 — `getCache()` returns `CacheLike`

```ts
// v1
getCache(): MemoryCache

// v2
getCache(): CacheLike  // MemoryCache | MultiLevelCache | custom adapter
```

This is a widening: `MemoryCache` is still the default; the return type is broader to accommodate the two new cache modes.

---

## New Features

### MultiLevel cache via `cache` option

```ts
const msq = new MonSQLize({
  type: 'mongodb',
  cache: {
    multiLevel: true,
    local: { maxEntries: 5000 },
    remote: MonSQLize.createRedisCacheAdapter('redis://localhost:6379'),
    policy: { writePolicy: 'local-first-async-remote', backfillLocalOnRemoteHit: true },
  },
});
```

### SSH tunnel support

Connect to MongoDB through a bastion host with no code changes required:

```ts
const msq = new MonSQLize({
  type: 'mongodb',
  config: {
    uri: 'mongodb://mongo.internal:27017/mydb',
    ssh: {
      host: 'bastion.example.com',
      username: 'deploy',
      privateKeyPath: '~/.ssh/id_rsa',
    },
  },
});
```

Historical v2.0.0 note: SSH tunneling originally expected `ssh2` to be present separately. In current `v2.0.2+` packages, `ssh2` is installed with `monsqlize`.

### Custom `CacheLike` pass-through (v1 compat)

Passing a custom `CacheLike` instance (e.g. a Redis adapter) directly as `cache` is now supported:

```ts
const msq = new MonSQLize({
  type: 'mongodb',
  cache: MonSQLize.createRedisCacheAdapter('redis://localhost:6379'),
});
```

In v1 this silently fell back to a default `MemoryCache`. In v2 it is used directly.

### `HealthView.driver` field

`health()` now returns `driver: { connected: boolean }` alongside the existing fields.

### `ModelInstance` soft-delete and batch methods

`findOneOnlyDeleted`, `countWithDeleted`, `countOnlyDeleted`, `insertBatch`, `updateBatch` are now declared in the public type surface (they existed at runtime in v1 but were not typed).

---

## v1 Compatibility Map

| v1 option | v2 equivalent | Status |
|---|---|---|
| `cache.maxSize` | `cache.maxEntries` | ✅ auto-mapped |
| `cache.ttl` | `cache.defaultTtl` | ✅ auto-mapped |
| `cache.autoInvalidate` | `cacheAutoInvalidate` (top-level) | ✅ both accepted |
| `cache: CacheLike` | `cache: CacheLike` | ✅ pass-through |
| `cache: MultiLevelCacheOptions` | `cache: { multiLevel: true, ... }` | ✅ fully supported |
| `options.database` | `options.databaseName` | ✅ alias preserved |
| `SagaResult.sagaId` | `SagaResult.sagaId` + `executionId` alias | ✅ |
| `ctx.sagaId` in Saga steps | `ctx.executionId` + `ctx.sagaId` alias | ✅ alias preserved |

---

## JSDoc Coverage

All public API surface now carries complete English JSDoc:

- `types/collection.d.ts` — 49 Collection / DbAccessor / AdminAccessor methods
- `types/model.d.ts` — 44 ModelInstance methods
- `types/monsqlize.d.ts` — 43 MonSQLize interface methods
- `types/lock.d.ts` — Lock / LockManager
- `types/saga.d.ts` — SagaOrchestrator / SagaContext / SagaStep
- `types/transaction.d.ts` — Transaction / TransactionManager / CacheLockManager
- `types/runtime.d.ts` — MemoryCache / MultiLevelCache / FunctionCache

---

## v1 Compatibility Fixes (included in this release)

### API / Runtime
- **`findAndCount`**: return value includes `documents` as a backward-compat alias for `data` (`{ data, total, documents }`)
- **`findOneById` / `findByIds`**: `options.cache` now restores v1-style read-through TTL caching.
- **Runtime query defaults**: built-in defaults now match v1 (`maxTimeMS=2000`, `findLimit=10`, `slowQueryMs=500`, `findPageMaxLimit=500`).
- **`LockManager` TTL**: explicit lock TTL values are no longer silently capped by `maxDuration`.
- **`withCache(fn)`**: default behavior now matches v1 (`ttl=60000`, `namespace='fn'`, `enableStats=true`).
- **`adaptLegacyCacheLike`**: exported as both a named import and `MonSQLize.adaptLegacyCacheLike`
- **`MultiLevelCache`**: exported as both a named import and `MonSQLize.MultiLevelCache`
- **Error messages**: `createValidationError` default message `参数校验失败`; `createCursorError` default `游标无效`
- **`FunctionCache.defaultTTL`**: v1 option `defaultTTL` now accepted as an alias for `ttl`; v1 code using `new FunctionCache(db, { defaultTTL: 60000 })` works without changes
- **Read query meta wrapper**: `find` / `findOne` / `count` / `aggregate` / `distinct` now restore the v1 `{ data, meta }` result shape when `options.meta` is enabled.
- **`FunctionCache` defaults and stats**: `new FunctionCache()` is supported, the default namespace is restored to `action`, and stats include `totalTime` / `avgTime`.
- **Batch writes**: `insertBatch` / `deleteBatch` retry defaults are restored to `3` attempts and `1000ms`; `updateBatch` now supports `onError='retry'`, `retryAttempts`, `retryDelay`, and `onRetry`.
- **Model hooks**: flat hooks support `beforeInsert` / `afterInsert` aliases and now cover bulk/upsert/findOneAnd* write paths.

### Type Declarations
- **`FindAndCountResult`**: includes `documents?: TSchema[]` optional backward-compat alias
- **`SagaResult`**: includes `completedStepNames?: string[]` (ordered step names, v1 compat) and `errorCause?: unknown`
- **`CachedFunction`**: exposes `getCacheStats()` as a v1 shim over `stats()`
- **Query meta overloads**: public collection types now expose `ResultWithMeta<T>` overloads for meta-enabled read APIs.
- **Collection management methods**: public collection types now declare `stats`, `renameCollection`, `collMod`, `convertToCapped`, validator setters, and `getValidator`.
- **`ModelInstance` helpers**: public model types now declare `getRelations()` and `getEnums()`.
- **`Model hooks`**: `beforeInsert` / `afterInsert` are declared as flat hook aliases.
- **Batch options**: public batch option types now expose retry and progress options consistently.
- **Workspace smooth-upgrade bridge**: legacy-wide `Model` / `Collection` public contracts accept v1 consumer fixture shapes without source changes, including object schema definitions, `validate:true` operation overrides, `validate()` response data, array-form `populate()`, document-level `populate()`, Transaction stats, Saga metadata/return contracts, FunctionCache registration, Mongo connection aliases, package metadata exports, sync transform overloads, top-level `FindPageOptions.comment`, and optional v2-only counter aliases.
- **Root and static export parity**: ESM named exports and default `MonSQLize` statics are aligned with the CJS surface, including advanced capabilities and package metadata.
- **Remaining v1 operation contracts**: `MonSQLize#scopedCollection()` pool scoping, `ConnectionPoolManager#selectPool()` string operations, chainable `ModelDocument#populate()`, synchronous `listSagas()`, and required `SagaResult.compensatedSteps` are restored for v1-compatible consumers.
- **Collection `find()` overload**: the v1 three-argument `find(query, projection, options)` form is restored at runtime and in public types.
- **Redis adapter errors**: legacy invalid-argument and missing-`ioredis` messages are preserved while keeping structured monSQLize error codes.

### Workspace Upgrade Validation
- Verified zero-business-code upgrade paths for workspace consumers `chat`, `payment`, `user`, `admin`, `search`, `vext`, and `permission-core` by overlaying only the local monSQLize package candidate and running each service's TypeScript/test gate.
- Additional workspace declarations were classified in `requirements/平滑升级支持/06-工作区依赖覆盖矩阵.md`; historical/spec assets and credential-bearing scripts are static-only exclusions from the default release gate until they are sanitized.

### Internal
- `src/entry/runtime-core.ts` reduced from 852 to 769 lines; cache normalizer extracted to `runtime-cache-normalizer.ts`
- `node --test --test-concurrency=1` applied to all integration test scripts to prevent parallel mongod startup hangs on Windows
- `withCache()` performance validation ledgers now align with the current benchmark source and document that v1 transaction benchmarks are not directly comparable to the v2 function-cache hot-path baseline.
- The transaction/cache-lock unit test was stabilized, and release preflight now runs the default `npm test` gate before pack dry-run.
- Runtime dependency `schema-dsl` now follows npm `latest` TypeScript line `^2.0.3`; deprecated mistake releases in the `2.3.x` range are explicitly excluded from the upgrade target.
- Project licensing is now Apache-2.0, and the package README is published in English for npm and GitHub users.
- npm package artifacts are limited to runtime CJS / ESM bundles, public `.d.ts` declarations, and release documentation. Source maps are disabled by default and excluded from the package boundary even when generated locally.
- GitHub Actions publish flow now runs `release:preflight` once before `npm publish --ignore-scripts`, avoiding duplicate `prepublishOnly` lifecycle execution inside the final publish step while preserving raw `npm publish` safeguards.

---

## Migration Notes

Most v1 applications will **run without modification**. The steps below apply only if you hit one of the breaking changes.

1. **`getPoolStats()` / `getPoolHealth()`** — if you iterate the result as an array, switch to `Object.values(msq.getPoolStats())`.
2. **`Saga context`** — replace `ctx.sagaId` with `ctx.executionId` inside step handlers.
3. **`getCache()` narrowing** — if you assigned the result to a `MemoryCache` typed variable, widen the type to `CacheLike`.
4. **`cache.maxSize`** — still works transparently; rename to `maxEntries` at your convenience.
5. **`slow-query-log queryHash`** — v2 now normalizes the hash from stable identity fields (`database|db`、`collection|coll`、`operation|op`、`queryShape|query`) and stores a 16-character digest. Historical slow-query-log records remain readable, but new and old aggregation keys are not guaranteed to stay continuous. This release does **not** include an automatic migration script; if your downstream analytics depend on historical key continuity, migrate those records explicitly before or during rollout.
