diff --git a/CHANGELOG.md b/CHANGELOG.md index bb189cc..d22fdb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,57 @@ [compare changes](https://github.com/AntelopeJS/interface-database/compare/v0.3.3...v0.4.0) +### Upgrade notes + +- **A query is no longer a promise.** `Query` has no `then()`, and `QueryExecution` no longer extends `PromiseLike`. `await query` gives back the query object and sends nothing to the provider. Run a query with `run()`, or read it with `cursor()` or `for await`. A query in `Promise.all([...])`, or returned from an `async` function, is no longer run either. TypeScript rejects a query passed where a `PromiseLike` is expected, and the `typescript/await-thenable` lint rule reports `await` on a query and a query passed to `Promise.all`, `Promise.race` or another promise aggregator. The conformance suite in `dist/tests` runs every query with `run()`. A database module implements nothing new. + + ```ts + // Before + const adults = await users.filter((u) => u.key("age").ge(18)); + // After + const adults = await users.filter((u) => u.key("age").ge(18)).run(); + ``` + +- **`cast()` returns a new object.** `Datum#cast`, `Stream#cast` and `ValueProxy#cast` return a new object with the same stages, built by the new `StagedObject` constructor form `new X(undefined, previous)`, which records no stage. `cast()` on a `Table`, a `Selection` or a `SingleSelection` returns a plain `Stream` or `Datum`, the class its type already declared. Code that compared the result with its receiver, or relied on it keeping the subclass methods at runtime, such as a table's `insert` or `getAll`, keeps the receiver instead. + + ```ts + // Before: the same object, still a Table at runtime + table.cast() === table; // true + // After: a new Stream with the same stages + table.cast() === table; // false + table.cast().build(); // equal to table.build() + ``` + +- **`Schema.get()` takes no type arguments.** The registry keeps none, so `Schema.get(id)` returns `Schema | undefined`: tables hold `any` documents, and the definition is typed `unknown`. A typed lookup such as `Schema.get<{ users: User }>(id)` fails to compile (TS2558). Query typed tables through the schema object the constructor returned. On the runtime entry, `Schema.list().get(id)` returns the schema with its definition typed `SchemaDefinition`. + + ```ts + // Before + const schema = Schema.get<{ users: User }>("myapp")!; + // After: export the schema you define, and import it + export const schema = new Schema<{ users: User }>("myapp", definition); + ``` + +- **The build-only `Query` keeps its result type.** Loaded from `@antelopejs/interface-database/staged-query` alone, `Query` now uses `T`, so `ExtractType` reads the result type of a `Datum` or a `Stream` a mapper returns, and a `Query` is no longer assignable to a `Query`. Code that relied on that assignment fails to compile. + + ```ts + // Before, build-only entry: compiled, typed unknown + const q: Query = schema.createInstance(); // Query + // After: TS2322 + ``` + +- **`StagedObject#callfunc` checks its argument classes.** The protected method takes one or two `StagedConstructor`s, and each must build the parameter type `func` declares. A subclass that passed `ValueProxy` for a parameter typed `ValueProxy` passes `ValueProxy`. + + ```ts + // Before + this.callfunc(mapper, Stream, ValueProxy); + // After + this.callfunc( + mapper, + Stream, + ValueProxy, + ); + ``` + ### 🚀 Enhancements - **staged-query:** ⚠️ Drop casts, thenable queries and caller-typed schema lookups ([#91](https://github.com/AntelopeJS/interface-database/pull/91))