Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Row>() === table; // true
// After: a new Stream with the same stages
table.cast<Row>() === table; // false
table.cast<Row>().build(); // equal to table.build()
```

- **`Schema.get()` takes no type arguments.** The registry keeps none, so `Schema.get(id)` returns `Schema<any, unknown> | 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<T>` keeps its result type.** Loaded from `@antelopejs/interface-database/staged-query` alone, `Query<T>` now uses `T`, so `ExtractType` reads the result type of a `Datum` or a `Stream` a mapper returns, and a `Query<string>` is no longer assignable to a `Query<number>`. Code that relied on that assignment fails to compile.

```ts
// Before, build-only entry: compiled, typed unknown
const q: Query<number> = schema.createInstance(); // Query<string>
// 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<unknown>` for a parameter typed `ValueProxy<T>` passes `ValueProxy<T>`.

```ts
// Before
this.callfunc(mapper, Stream<T>, ValueProxy<unknown>);
// After
this.callfunc(
mapper,
Stream<T>,
ValueProxy<K extends keyof T ? T[K] : unknown>,
);
```

### 🚀 Enhancements

- **staged-query:** ⚠️ Drop casts, thenable queries and caller-typed schema lookups ([#91](https://github.com/AntelopeJS/interface-database/pull/91))
Expand Down
Loading