UNPKG

@furystack/core

Version:
279 lines (160 loc) 10.6 kB
# Changelog ## [17.1.0] - 2026-05-21 ### ✨ Features ### New `NotFoundError` and `NotSupportedError` exports Two new error classes are exported from the package's `errors` barrel so adapters can signal narrow precondition failures by type instead of by message: - `NotFoundError` — thrown by a `PhysicalStore` when an operation targets a missing entity (e.g. `update` called with an id that does not exist). Callers can branch on `instanceof NotFoundError` instead of parsing strings. - `NotSupportedError` — thrown when an adapter cannot serve a given operation against its backing storage (e.g. `find` against a key/value store). Adapters throw at call time rather than at construction so the rest of the surface remains usable. `InMemoryStore.update` now throws `NotFoundError` for the missing-entity case (was a plain `Error`); the message was tightened from `... cannot update!` to `... cannot update`. Sibling adapters (`@furystack/mongodb-store`, `@furystack/sequelize-store`, `@furystack/redis-store`) were updated in lockstep. **Impact:** code that matched on the previous error message will keep working — `Error.message` still contains the entity id and the `cannot update` substring, only the trailing `!` was dropped. Callers can now switch to `instanceof NotFoundError`. ### 📚 Documentation - Rewrote JSDoc across the public API (`defineStore`, `InMemoryStore`, `PhysicalStore`, the `errors/` family, `IdentityContext`, `globalDisposables`, `filterItems`, `User`) to follow the new value-test guidance: dropped restate-the-type narration, kept intent / trade-offs / constraints, and added type-only imports for cross-file `{@link}` targets. ### ⬆️ Dependencies - Bump dev `vitest` to `^4.1.5`. - Bumped `@types/node` to `^25.9.1` and `vitest` to `^4.1.7`. No source changes — dev-tooling bump only. ## [17.0.0] - 2026-04-25 ### 💥 Breaking Changes Stores are now first-class DI tokens. See the [v7 migration guide](../../docs/migrations/v7-functional-di.md) for rationale, recipes, and pitfalls. - Removed `StoreManager`, `addStore(injector, store)`. Declare stores with `defineStore({ name, model, primaryKey, factory })` at module scope — the returned `StoreToken<T, PK>` is self-disposing on injector teardown and carries `model` + `primaryKey` metadata. - Added `IdentityContext` as an interface + singleton token (previously a class). Bind a concrete implementation at app bootstrap; `useSystemIdentityContext` still returns a child injector with an elevated identity and is the recommended server-side elevation path. - `Constructable` now lives in this package (moved from `@furystack/inject`). Any downstream package that used `Constructable` must switch its import. ### Quick reference Before: ```ts const sm = injector.getInstance(StoreManager) sm.addStore(new InMemoryStore({ model: User, primaryKey: 'id' })) const store = sm.getStoreFor(User, 'id') ``` After: ```ts export const UserStore = defineStore({ name: 'app/UserStore', model: User, primaryKey: 'id', factory: () => new InMemoryStore({ model: User, primaryKey: 'id' }), }) const store = injector.get(UserStore) ``` ## [16.0.4] - 2026-04-17 ### ⬆️ Dependencies - Raised `@types/node` to ^25.6.0, `typescript` to ^6.0.3, and `vitest` to ^4.1.4 so package development matches the workspace toolchain. ## [16.0.3] - 2026-03-27 ### ⬆️ Dependencies - Updated `vitest` to ^4.1.2 ## [16.0.2] - 2026-03-25 ### 📦 Build - Removed deprecated `baseUrl` from tsconfig.json for TypeScript 6 compatibility ### ⬆️ Dependencies - Upgraded `typescript` from ^5.9.3 to ^6.0.2 - Upgraded `vitest` from ^4.1.0 to ^4.1.1 ## [16.0.1] - 2026-03-19 ### ✨ Features - Core package bump to 16.0.0 with the breaking change above and other internal refinements. ### 📚 Documentation - Updated `IdentityContext` JSDoc to reflect the new explicit lifetime and parent‑chain inheritance. ### ⬆️ Dependencies - Upgraded `vite` from ^7.3.1 to ^8.0.0 for improved build performance and new features - Upgraded `vitest` from ^4.0.18 to ^4.1.0 - Upgraded `@vitest/coverage-istanbul` from ^4.0.18 to ^4.1.0 ### 💥 Breaking Changes ### IdentityContext lifetime changed from `scoped` to `explicit` `IdentityContext` now uses `@Injectable({ lifetime: 'explicit' })` so child injectors inherit the instance from their parent. Code that previously relied on the default scoped instance may now need to call `injector.setExplicitInstance` before accessing it. See migration notes in the package changelog. ## [16.0.0] - 2026-03-10 ### 💥 Breaking Changes ### IdentityContext lifetime changed from `scoped` to `explicit` `IdentityContext` now uses `@Injectable({ lifetime: 'explicit' })` instead of `@Injectable({ lifetime: 'scoped' })`. **Why:** With `scoped` lifetime, child injectors created via `createChild()` could not inherit the `IdentityContext` from their parent. Each child silently created a new default instance whose methods returned `false` or threw `"No IdentityContext"`. This was a common source of confusion, especially in Shades frontend applications where nested component injectors should share the same identity. With `explicit` lifetime, `getInstance(IdentityContext)` walks up the parent injector chain, so you only need to set it once on the root (or request-scoped) injector and all descendants will find it. **Who is affected:** Code that called `injector.getInstance(IdentityContext)` without a prior `setExplicitInstance` call. Previously this returned a useless default instance; now it throws `CannotInstantiateExplicitLifetimeError`. **Who is NOT affected:** All standard FuryStack server-side setups (`useHttpAuthentication`, `useJwtAuthentication`, `useSystemIdentityContext`, REST/WebSocket API managers) already call `setExplicitInstance` before accessing `IdentityContext` and will continue to work without changes. **Migration:** ```typescript // ❌ Before (scoped) — silently returned a broken default const ctx = injector.getInstance(IdentityContext) // ✅ After (explicit) — set it before accessing injector.setExplicitInstance(myIdentityContext, IdentityContext) const ctx = injector.getInstance(IdentityContext) // works // ✅ Child injectors now inherit automatically const child = injector.createChild() const ctx = child.getInstance(IdentityContext) // same instance from parent ``` ### 📚 Documentation - Updated `IdentityContext` JSDoc to reflect the `explicit` lifetime, including setup instructions and parent inheritance behavior ## [15.2.5] - 2026-03-07 ### ⬆️ Dependencies - Updated `@types/node` from `^25.3.1` to `^25.3.5` ## [15.2.4] - 2026-03-06 ### ⬆️ Dependencies - Updated internal FuryStack dependencies ## [15.2.3] - 2026-03-03 ### ⬆️ Dependencies - Updated `@furystack/utils` with EventHub listener error handling and ObservableValue `onError` support ## [15.2.2] - 2026-02-26 ### 🔧 Chores - Normalized line endings in `store-manager.ts` ### ⬆️ Dependencies - Bumped `@types/node` from ^25.3.0 to ^25.3.1 ## [15.2.1] - 2026-02-26 ### 📝 Documentation - Added JSDoc recommendations to `PhysicalStore` and `StoreManager.getStoreFor()` pointing to `DataSet` as the preferred write gateway for application-level code ## [15.2.0] - 2026-02-22 ### ✨ Features ### Public `filterItems()` function Extracted the filter logic from `InMemoryStore` into a standalone `filterItems()` function, now exported from `@furystack/core`. This allows consumers to filter arrays using `FilterType` expressions without needing a store instance. **Usage:** ```typescript import { filterItems } from '@furystack/core' const results = filterItems(myArray, { name: { $startsWith: 'foo' }, age: { $gte: 18 }, }) ``` ### ♻️ Refactoring - `InMemoryStore` now delegates to the public `filterItems()` function internally instead of using a private method ## [15.1.0] - 2026-02-19 ### ✨ Features ### `SystemIdentityContext` -- elevated identity for trusted server-side operations Added `SystemIdentityContext`, an `IdentityContext` subclass that is always authenticated and authorized. It is intended for background jobs, migrations, and seed scripts that need to write through the `DataSet` layer without an HTTP user session. Also added the `useSystemIdentityContext()` helper that creates a scoped child injector with the elevated context. The returned injector is `AsyncDisposable` and works with `usingAsync()` for automatic cleanup. **Usage:** ```typescript import { useSystemIdentityContext } from '@furystack/core' import { getDataSetFor } from '@furystack/repository' import { usingAsync } from '@furystack/utils' await usingAsync(useSystemIdentityContext({ injector, username: 'migration-job' }), async (systemInjector) => { const dataSet = getDataSetFor(systemInjector, MyModel, 'id') await dataSet.add(systemInjector, newEntity) }) ``` ### 📚 Documentation - Expanded JSDoc on `PhysicalStore` to warn that writing directly to the store bypasses DataSet authorization, hooks, and events ### 🧪 Tests - Added tests for `SystemIdentityContext` (authentication, authorization, custom username) - Added tests for `useSystemIdentityContext` (child injector scoping, disposal, identity resolution) ### ⬆️ Dependencies - Updated `@furystack/inject` and `@furystack/utils` ## [15.0.36] - 2026-02-11 ### ⬆️ Dependencies - Bump `vitest` from `^4.0.17` to `^4.0.18` - Bump `@types/node` from `^25.0.10` to `^25.2.3` - Updated internal dependencies ## [15.0.35] - 2026-02-09 ### 🐛 Bug Fixes - Fixed `getPort()` to assign deterministic port ranges per Vitest worker using `VITEST_POOL_ID` instead of a random base port, preventing port collisions in parallel test runs ### 🧪 Tests - Refactored `globalDisposable` tests to use `usingAsync` for proper `Injector` disposal ## [15.0.34] - 2026-01-26 ### 🔧 Chores - Standardized author format, improved keywords, removed obsolete `gitHead`, added `engines` (Node 22+) and `sideEffects: false` ## [15.0.33] - 2026-01-26 ### ⬆️ Dependencies - Updated `@furystack/inject` with fix for singleton injector reference being overwritten by child injectors ## [15.0.32] - 2026-01-22 ### ⬆️ Dependencies - Dependency updates ### 📚 Documentation - Improved README with clearer examples and better structure ### 🐛 Bug Fixes - Fixed `getPort()` returning duplicate ports by reusing a shared generator instance instead of creating a new one on each call ### 🔧 Chores - Migrated to centralized changelog management system