@zerotal/orm 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/README.md +3 -3
- package/package.json +3 -3
- package/src/index.ts +13 -11
- package/src/model/BaseModel.ts +36 -1
- package/src/model/SoftDeletes.ts +3 -3
- package/src/model/State.ts +3 -3
- package/src/model/decorators/table.ts +2 -2
- package/src/model/mixins.ts +126 -501
package/CHANGELOG.md
CHANGED
|
@@ -8,11 +8,58 @@ follows the Zerotal monorepo's unified versioning.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.3.0] — 2026-08-09
|
|
12
|
+
|
|
13
|
+
### Changed — BREAKING
|
|
14
|
+
|
|
15
|
+
- **`BaseModelWith(...)` is replaced by the `Model.using(...)` static.** Mixin composition is now
|
|
16
|
+
a property of the base class rather than a helper shipped alongside it, so there is one idiom to
|
|
17
|
+
learn and nothing extra to import.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
// before
|
|
21
|
+
import { BaseModelWith } from "@zerotal/orm";
|
|
22
|
+
class User extends BaseModelWith(Authenticatable, Permissions, Roles) {}
|
|
23
|
+
|
|
24
|
+
// after
|
|
25
|
+
import { Model } from "@zerotal/orm";
|
|
26
|
+
class User extends Model.using(Authenticatable, Permissions, Roles) {}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Run `bun run scripts/codemod-mixin-composition.ts` to rewrite call sites and imports.
|
|
30
|
+
|
|
31
|
+
How mixins are **authored** is unchanged — `<T extends Constructor>(Base: T) => class extends Base`
|
|
32
|
+
still works exactly as before, and every shipped mixin (`SoftDeletes`, `State`, `Authenticatable`,
|
|
33
|
+
`Roles`, `Permissions`, `Notifiable`, `Tenantable`, `Auditable`, …) keeps its signature. The
|
|
34
|
+
`Constructor` and `Mixin` types are still exported; `Compose` (the type of `Model.using`) joins
|
|
35
|
+
them. Mixin authors declaring columns still call `registerColumn` imperatively.
|
|
36
|
+
|
|
37
|
+
`with` was deliberately **not** used for this. It is reserved for the eager-load static
|
|
38
|
+
(`User.with("posts")`), the one conspicuous gap in the model's existing query-forwarder family
|
|
39
|
+
(`where`, `whereIn`, `orderBy`, `latest`, `first`, `paginate`, `find`, `all`, `count`, …).
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- **`Model` is now the canonical name for the base class; `BaseModel` is the alias.** They are the
|
|
44
|
+
same class object and both remain exported, so no code breaks — but `class User extends Model {}`
|
|
45
|
+
is the documented form from here, mirroring Flow's `class PostsPage extends Component {}`.
|
|
46
|
+
`BaseModel` was previously the canonical name and `Model` an unused compat alias added in 1.0.2.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- **`using` composes onto any class in the chain, not just the root.** An app-level base model can
|
|
51
|
+
now carry mixins without being flattened out of the prototype chain — `AppModel.using(SoftDeletes)`
|
|
52
|
+
keeps `AppModel` and its statics in the lineage. `BaseModelWith` hardcoded `BaseModel`, so this
|
|
53
|
+
previously required hand-nesting.
|
|
54
|
+
- **Composition chains.** The composed class carries `using` itself, so
|
|
55
|
+
`Model.using(a, b).using(c, d)` works past the 8-mixin overload set — which is why the overload
|
|
56
|
+
set shrank from 20 hand-written arities to 8 without losing any capability.
|
|
57
|
+
|
|
11
58
|
## [1.1.0] — 2026-08-08
|
|
12
59
|
|
|
13
60
|
### Fixed
|
|
14
61
|
|
|
15
|
-
- **A `json` column returns the type it was given.** Writing skipped `JSON.stringify` for values that were already strings, so a string went into the column as bare characters — `62812345678`, not `"62812345678"` — and the read side's `JSON.parse` turned it back into a number. A `json`-cast setting holding an account number came back as a number, and only for
|
|
62
|
+
- **A `json` column returns the type it was given.** Writing skipped `JSON.stringify` for values that were already strings, so a string went into the column as bare characters — `62812345678`, not `"62812345678"` — and the read side's `JSON.parse` turned it back into a number. A `json`-cast setting holding an account number came back as a number, and only for _some_ values, since a string that fails to parse fell through unchanged. Encoding is now symmetric in both directions, and `where()` against a `json` column encodes the same way, so a query finds what a write stores. **Upgrade note:** rows written by an older version hold bare scalars, so a string column may still read back as a number, and a `where()` on a string will not match those older rows — they are stored unquoted. Only affects bare scalars in `json`/`array` columns; objects and arrays were always encoded and are untouched.
|
|
16
63
|
- **`bun zt make:model` generates a file that parses.** The stub emitted `@table('posts').withTimestamps()`, which is not valid decorator syntax — the grammar allows a call at the end of the chain, not in the middle — so every generated model failed with `Expected "class" but found "."`. The stub now emits plain `@table('posts')`; timestamps are on by default and the chained form needs outer parentheses, `@(table("x").withoutTimestamps())`. The same broken form is corrected in the `BaseModel` docblocks, and every generated stub is now parsed by a test rather than checked for substrings.
|
|
17
64
|
- **A column `default` is applied on insert.** A declared field that was never assigned was written as an explicit `NULL`, so the INSERT named the column, the database never applied its own default, and a `NOT NULL` column failed outright — on a model and migration that both declared `default: 0`. `undefined` now means "I didn't say": the declared default is used, or the column is omitted so the database decides. An explicit `null` still stores `NULL`.
|
|
18
65
|
- **A `Date` compared against a timestamp column matches again.** Bound values are serialised through the column's cast metadata, but the framework-managed `created_at` / `updated_at` / `deleted_at` carry no `@column` registration — so a `Date` was bound raw and matched nothing. `where("created_at", ">=", monthStart)` is the commonest reporting query there is, and it silently returned zero rows: a dashboard reading "0 this month" looks like a quiet month, not a broken query.
|
package/README.md
CHANGED
|
@@ -43,11 +43,11 @@ export default DatabaseConfig({
|
|
|
43
43
|
### Define a model
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
|
-
import {
|
|
46
|
+
import { Model, column, table, belongsTo, hasMany } from "@zerotal/orm";
|
|
47
47
|
import type { Columns } from "@zerotal/orm";
|
|
48
48
|
|
|
49
49
|
@(table("posts").withTimestamps().withSoftDeletes())
|
|
50
|
-
export class Post extends
|
|
50
|
+
export class Post extends Model {
|
|
51
51
|
static fillable: Columns<Post>[] = ["title", "body", "status", "userId"];
|
|
52
52
|
|
|
53
53
|
@column("string") title!: string;
|
|
@@ -144,7 +144,7 @@ This package exposes two subpath entry points:
|
|
|
144
144
|
|
|
145
145
|
Main exports from the default entry point:
|
|
146
146
|
|
|
147
|
-
- **Models** — `
|
|
147
|
+
- **Models** — `Model` (aka `BaseModel`), `ModelQueryBuilder`, `DB`, `QueryBuilder`
|
|
148
148
|
- **Decorators** — `column`, `table`, `belongsTo`, `hasMany`, `hasOne`, `manyToMany`, `morphTo`, `morphMany`, `morphOne`, `hasManyThrough`, `hasOneThrough`, `morphToMany`, `morphedByMany`
|
|
149
149
|
- **Schema / migrations** — `Schema`, `Blueprint`, `Migration`, `MigrationRunner`, `SchemaInspector`, `ModelInspector`, `SchemaDiffer`, `synchronizeSchema`
|
|
150
150
|
- **Seeding** — `Seeder`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zerotal/orm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"maturity": "stable",
|
|
6
6
|
"private": false,
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"typecheck": "tsc --noEmit"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@zerotal/core": "1.
|
|
34
|
-
"@zerotal/validator": "1.
|
|
33
|
+
"@zerotal/core": "1.3.0",
|
|
34
|
+
"@zerotal/validator": "1.3.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"typescript": "^5.8.0"
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A Bun-native Active Record ORM built on `Bun.sql`.
|
|
3
3
|
*
|
|
4
|
-
* Models extend {@link
|
|
4
|
+
* Models extend {@link Model}: you declare columns with {@link column | `@column`},
|
|
5
5
|
* relationships with decorators like {@link hasMany | `@hasMany`} and
|
|
6
6
|
* {@link belongsTo | `@belongsTo`}, and then query and persist through the model's
|
|
7
7
|
* static and instance methods. Under the hood a {@link QueryBuilder} routes every
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
* using the {@link Schema} facade and the {@link Blueprint} table builder.
|
|
12
12
|
*
|
|
13
13
|
* Mass assignment is **guarded by default** — a model with neither `fillable` nor
|
|
14
|
-
* `guarded` declared rejects all attributes in {@link
|
|
14
|
+
* `guarded` declared rejects all attributes in {@link Model.fill | `fill()`}.
|
|
15
15
|
* Soft deletes and state machines are opt-in mixins composed via
|
|
16
|
-
*
|
|
16
|
+
* `Model.using(...)`. The ORM's CLI commands (`migrate`, `make:model`, …) live
|
|
17
17
|
* under the `@zerotal/orm/commands` subpath.
|
|
18
18
|
*
|
|
19
19
|
* @example Define a model
|
|
20
20
|
* ```ts
|
|
21
|
-
* import {
|
|
21
|
+
* import { Model, column, hasMany, type HasMany } from "@zerotal/orm";
|
|
22
22
|
* import { Post } from "./Post.ts";
|
|
23
23
|
*
|
|
24
|
-
* export class User extends
|
|
24
|
+
* export class User extends Model {
|
|
25
25
|
* @column({ primary: true }) id!: number;
|
|
26
26
|
* @column() email!: string;
|
|
27
27
|
* @column() name!: string;
|
|
@@ -70,12 +70,14 @@
|
|
|
70
70
|
|
|
71
71
|
// @zerotal/orm — public API barrel
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
export {
|
|
75
|
-
|
|
76
|
-
//
|
|
73
|
+
// `Model` is the canonical base class; `BaseModel` is the same class under its original name.
|
|
74
|
+
export { Model, BaseModel } from "./model/BaseModel.ts";
|
|
75
|
+
// Mixin authoring types. Compose them onto a model with the `Model.using(...)` static —
|
|
76
|
+
// `class User extends Model.using(Authenticatable, Roles)`.
|
|
77
|
+
export type { Constructor, Mixin, Compose } from "./model/mixins.ts";
|
|
78
|
+
// State-machine behaviour is an opt-in mixin — compose with `Model.using(State)`.
|
|
77
79
|
export { State } from "./model/State.ts";
|
|
78
|
-
// Soft deletes are opt-in — compose with `
|
|
80
|
+
// Soft deletes are opt-in — compose with `Model.using(SoftDeletes)`.
|
|
79
81
|
export { SoftDeletes } from "./model/SoftDeletes.ts";
|
|
80
82
|
export type {
|
|
81
83
|
StateDefinition,
|
|
@@ -143,7 +145,7 @@ export { column, columnRegistry } from "./model/decorators/column.ts";
|
|
|
143
145
|
export type { ColumnOptions, ColumnShorthand } from "./model/decorators/column.ts";
|
|
144
146
|
export { registerModel, modelByName, modelsByName } from "./model/decorators/_metadata.ts";
|
|
145
147
|
// Imperative column registration — for mixin authors composing model behaviour with
|
|
146
|
-
//
|
|
148
|
+
// Model.using (the @column decorator can't run inside a returned class expression).
|
|
147
149
|
export { registerColumn, columnsFor } from "./model/decorators/_metadata.ts";
|
|
148
150
|
export { table } from "./model/decorators/table.ts";
|
|
149
151
|
export type { TableDecoratorBuilder, TableOptions } from "./model/decorators/table.ts";
|
package/src/model/BaseModel.ts
CHANGED
|
@@ -33,6 +33,8 @@ import {
|
|
|
33
33
|
} from "../errors/index.ts";
|
|
34
34
|
import { type ManyToMany } from "./relations/RelationRegistry.ts";
|
|
35
35
|
import { installReactiveAccessors, type ColumnOptions } from "./decorators/column.ts";
|
|
36
|
+
import { _compose } from "./mixins.ts";
|
|
37
|
+
import type { Compose } from "./mixins.ts";
|
|
36
38
|
import { columnsFor, relationsFor } from "./decorators/_metadata.ts";
|
|
37
39
|
import { TransactionContext } from "../db/TransactionContext.ts";
|
|
38
40
|
import type { InsertPayload, UpdatePayload, FillablePayload } from "./payload.ts";
|
|
@@ -567,6 +569,37 @@ export class BaseModel {
|
|
|
567
569
|
*/
|
|
568
570
|
declare readonly __isZerotalModel: true;
|
|
569
571
|
|
|
572
|
+
/**
|
|
573
|
+
* Compose one or more model mixins onto this class, folding them left-to-right, so reusable
|
|
574
|
+
* model behaviour (auth contract, roles, permissions, soft deletes, tenancy, …) stacks flat
|
|
575
|
+
* instead of nesting.
|
|
576
|
+
*
|
|
577
|
+
* @remarks
|
|
578
|
+
* Each mixin receives the accumulated base and returns an extended class, so this class's full
|
|
579
|
+
* static surface (`query()`, `find()`, `create()`, scopes, …) and every mixin's instance and
|
|
580
|
+
* static members flow through to the composed class — fully type-checked. Prefer this over
|
|
581
|
+
* hand-nesting mixins (`Roles(Permissions(AuthUser))`), which reads inside-out and repeats the
|
|
582
|
+
* base.
|
|
583
|
+
*
|
|
584
|
+
* `using` composes onto whatever class it is called on, so it also works on an intermediate
|
|
585
|
+
* model base, and the composed class carries `using` itself, so `Model.using(a, b).using(c)`
|
|
586
|
+
* chains past the 8-mixin overload set.
|
|
587
|
+
*
|
|
588
|
+
* Mixin authors declaring columns must call {@link registerColumn} imperatively — the `@column`
|
|
589
|
+
* decorator cannot run inside a returned class expression.
|
|
590
|
+
*
|
|
591
|
+
* @param mixins - Mixin factories applied in order; each receives the class the previous one produced.
|
|
592
|
+
* @returns A model class extending this one with every mixin applied.
|
|
593
|
+
*
|
|
594
|
+
* @example
|
|
595
|
+
* ```ts
|
|
596
|
+
* class User extends Model.using(Authenticatable, Permissions, Roles) {}
|
|
597
|
+
* ```
|
|
598
|
+
*
|
|
599
|
+
* @category Composition
|
|
600
|
+
*/
|
|
601
|
+
static using: Compose = _compose;
|
|
602
|
+
|
|
570
603
|
/**
|
|
571
604
|
* Database table this model maps to. Usually set for you by the `@table("…")`
|
|
572
605
|
* decorator; assign directly to override.
|
|
@@ -2530,5 +2563,7 @@ function _applyRow(inst: BaseModel, row: Record<string, unknown>): void {
|
|
|
2530
2563
|
(inst as unknown as { _original: Record<string, unknown> })._original = orig;
|
|
2531
2564
|
}
|
|
2532
2565
|
|
|
2533
|
-
//
|
|
2566
|
+
// `Model` is the canonical name at the declaration site — `class User extends Model.using(…)`
|
|
2567
|
+
// mirrors Flow's `class PostsPage extends Component.using(…)`. `BaseModel` remains exported as
|
|
2568
|
+
// an alias (same class object) for code that references the base class by that name.
|
|
2534
2569
|
export { BaseModel as Model };
|
package/src/model/SoftDeletes.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
// `deletedAt`, `forceDelete()`, `restore()`, `trashed()`, and the `withTrashed()` /
|
|
5
5
|
// `onlyTrashed()` query scopes. A hard-delete model has none of these.
|
|
6
6
|
//
|
|
7
|
-
// import {
|
|
7
|
+
// import { Model, SoftDeletes } from "@zerotal/orm";
|
|
8
8
|
//
|
|
9
9
|
// @table("posts")
|
|
10
|
-
// class Post extends
|
|
10
|
+
// class Post extends Model.using(SoftDeletes) {
|
|
11
11
|
// @column() title!: string;
|
|
12
12
|
// }
|
|
13
13
|
//
|
|
@@ -47,7 +47,7 @@ interface SoftDeleteModelClass<T extends BaseModel> {
|
|
|
47
47
|
* @example
|
|
48
48
|
* ```ts
|
|
49
49
|
* @table("posts")
|
|
50
|
-
* class Post extends
|
|
50
|
+
* class Post extends Model.using(SoftDeletes) {
|
|
51
51
|
* @column() title!: string;
|
|
52
52
|
* }
|
|
53
53
|
*
|
package/src/model/State.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// workflow carry the API — `transitionTo` / `forceState` / `onTransition` / the
|
|
5
5
|
// `states` + `stateField` statics never appear on models that don't use them.
|
|
6
6
|
//
|
|
7
|
-
// import {
|
|
7
|
+
// import { Model, State } from "@zerotal/orm";
|
|
8
8
|
//
|
|
9
9
|
// const States = {
|
|
10
10
|
// pending: { canTransitionTo: ["active", "cancelled"] as const },
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// cancelled: { canTransitionTo: [] as const },
|
|
15
15
|
// } as const;
|
|
16
16
|
//
|
|
17
|
-
// class Subscription extends
|
|
17
|
+
// class Subscription extends Model.using(State) {
|
|
18
18
|
// static states = States;
|
|
19
19
|
// @column() status!: keyof typeof States;
|
|
20
20
|
// }
|
|
@@ -132,7 +132,7 @@ interface StateModelClass {
|
|
|
132
132
|
* cancelled: { canTransitionTo: [] as const },
|
|
133
133
|
* } as const;
|
|
134
134
|
*
|
|
135
|
-
* class Subscription extends
|
|
135
|
+
* class Subscription extends Model.using(State) {
|
|
136
136
|
* static states = States;
|
|
137
137
|
* @column() status!: keyof typeof States;
|
|
138
138
|
* }
|
|
@@ -46,7 +46,7 @@ interface TableConfig {
|
|
|
46
46
|
* export class Post extends BaseModel { ... }
|
|
47
47
|
*
|
|
48
48
|
* Soft deletes are opt-in via the `SoftDeletes` mixin, not `@table`:
|
|
49
|
-
* `class Post extends
|
|
49
|
+
* `class Post extends Model.using(SoftDeletes) {}` — see /docs/orm/lifecycle.
|
|
50
50
|
*/
|
|
51
51
|
export interface TableDecoratorBuilder {
|
|
52
52
|
/** Apply the decorator to a class constructor (called automatically by TS). */
|
|
@@ -77,7 +77,7 @@ export interface TableDecoratorBuilder {
|
|
|
77
77
|
* ```
|
|
78
78
|
*
|
|
79
79
|
* Timestamps are **on by default** — use `.withoutTimestamps()` to opt out. Soft
|
|
80
|
-
* deletes are **opt-in via the `SoftDeletes` mixin**: `extends
|
|
80
|
+
* deletes are **opt-in via the `SoftDeletes` mixin**: `extends Model.using(SoftDeletes)`.
|
|
81
81
|
*
|
|
82
82
|
* `@table` is the single, required way to configure a model: besides setting the
|
|
83
83
|
* table name and options, it anchors the class's `@column`/relation registrations at
|
package/src/model/mixins.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
// ── Model mixins ──────────────────────────────────────────────────────────────
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// Mixin composition machinery for the ORM. The entry point is `Model.using(...)`
|
|
4
|
+
// (see BaseModel.ts) — this module owns the types it is built from, and the fold
|
|
5
|
+
// itself. Nothing here imports `BaseModel`: the fold seeds from its receiver, so
|
|
6
|
+
// this is a leaf module.
|
|
7
|
+
//
|
|
8
|
+
// `Model.using(...)` composes any number of model mixins, so packages can ship
|
|
9
|
+
// reusable model behaviour (auth contract, roles, permissions, soft deletes, …)
|
|
10
|
+
// that apps stack without "wrapper hell":
|
|
6
11
|
//
|
|
7
12
|
// // before — nested, base repeated, order reads inside-out
|
|
8
13
|
// class User extends Roles(Permissions(AuthUser)) {}
|
|
9
14
|
//
|
|
10
15
|
// // after — flat, left-to-right, base baked in
|
|
11
|
-
// class User extends
|
|
16
|
+
// class User extends Model.using(Authenticatable, Permissions, Roles) {}
|
|
12
17
|
//
|
|
13
18
|
// A mixin is the canonical generic form `(<T>(Base: T) => class extends Base { … })`.
|
|
14
|
-
// Because each one returns `class extends Base`,
|
|
19
|
+
// Because each one returns `class extends Base`, the base's full static surface
|
|
15
20
|
// (`User.query()`, `find()`, `create()`, scopes, …) and every mixin's instance
|
|
16
21
|
// members flow through to the final class — fully type-checked.
|
|
17
22
|
|
|
18
|
-
import { BaseModel } from "./BaseModel.ts";
|
|
19
|
-
|
|
20
23
|
/** A concrete class constructor. */
|
|
21
24
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic mixin base bound
|
|
22
25
|
export type Constructor<T = object> = new (...args: any[]) => T;
|
|
@@ -32,505 +35,127 @@ export type Mixin<TIn extends Constructor = Constructor, TOut extends Constructo
|
|
|
32
35
|
Base: TIn,
|
|
33
36
|
) => TOut;
|
|
34
37
|
|
|
35
|
-
type Base = typeof BaseModel;
|
|
36
|
-
|
|
37
|
-
// Typed overloads (1–8 mixins) thread the accumulated type through each step so the
|
|
38
|
-
// result is `BaseModel`'s statics + every mixin's members. Need more? Nest a
|
|
39
|
-
// `BaseModelWith(...)` call or add another overload.
|
|
40
|
-
|
|
41
38
|
/**
|
|
42
|
-
*
|
|
43
|
-
* folding them left-to-right so the resulting class carries `BaseModel`'s full
|
|
44
|
-
* static surface (`query()`, `find()`, `create()`, scopes, …) plus every mixin's
|
|
45
|
-
* instance and static members — all fully type-checked.
|
|
46
|
-
*
|
|
47
|
-
* Prefer this over hand-nesting mixins (`Roles(Permissions(AuthUser))`), which
|
|
48
|
-
* reads inside-out and repeats the base. Each overload (1–20 mixins) threads the
|
|
49
|
-
* accumulated type through every step; for more, nest a second `BaseModelWith(...)`.
|
|
39
|
+
* The call signatures behind `Model.using(...)`.
|
|
50
40
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
41
|
+
* Each overload threads the accumulated type through every step, so the composed class carries
|
|
42
|
+
* the base's full static surface plus every mixin's instance and static members — fully
|
|
43
|
+
* type-checked. The `this: TBase` parameter is what makes the base polymorphic: `using` composes
|
|
44
|
+
* onto whatever class it is called on, not onto a hardcoded `BaseModel`.
|
|
54
45
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* class User extends BaseModelWith(Authenticatable, Permissions, Roles) {}
|
|
58
|
-
* ```
|
|
46
|
+
* Overloads cover 1–8 mixins. There is no ceiling: the composed class carries `using` too, so
|
|
47
|
+
* `Model.using(a, b).using(c, d)` chains.
|
|
59
48
|
*/
|
|
60
|
-
export
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
i: (base: H) => I,
|
|
160
|
-
): I;
|
|
161
|
-
export function BaseModelWith<
|
|
162
|
-
A extends Constructor,
|
|
163
|
-
B extends Constructor,
|
|
164
|
-
C extends Constructor,
|
|
165
|
-
D extends Constructor,
|
|
166
|
-
E extends Constructor,
|
|
167
|
-
F extends Constructor,
|
|
168
|
-
G extends Constructor,
|
|
169
|
-
H extends Constructor,
|
|
170
|
-
I extends Constructor,
|
|
171
|
-
J extends Constructor,
|
|
172
|
-
>(
|
|
173
|
-
a: (base: Base) => A,
|
|
174
|
-
b: (base: A) => B,
|
|
175
|
-
c: (base: B) => C,
|
|
176
|
-
d: (base: C) => D,
|
|
177
|
-
e: (base: D) => E,
|
|
178
|
-
f: (base: E) => F,
|
|
179
|
-
g: (base: F) => G,
|
|
180
|
-
h: (base: G) => H,
|
|
181
|
-
i: (base: H) => I,
|
|
182
|
-
j: (base: I) => J,
|
|
183
|
-
): J;
|
|
184
|
-
export function BaseModelWith<
|
|
185
|
-
A extends Constructor,
|
|
186
|
-
B extends Constructor,
|
|
187
|
-
C extends Constructor,
|
|
188
|
-
D extends Constructor,
|
|
189
|
-
E extends Constructor,
|
|
190
|
-
F extends Constructor,
|
|
191
|
-
G extends Constructor,
|
|
192
|
-
H extends Constructor,
|
|
193
|
-
I extends Constructor,
|
|
194
|
-
J extends Constructor,
|
|
195
|
-
K extends Constructor,
|
|
196
|
-
>(
|
|
197
|
-
a: (base: Base) => A,
|
|
198
|
-
b: (base: A) => B,
|
|
199
|
-
c: (base: B) => C,
|
|
200
|
-
d: (base: C) => D,
|
|
201
|
-
e: (base: D) => E,
|
|
202
|
-
f: (base: E) => F,
|
|
203
|
-
g: (base: F) => G,
|
|
204
|
-
h: (base: G) => H,
|
|
205
|
-
i: (base: H) => I,
|
|
206
|
-
j: (base: I) => J,
|
|
207
|
-
k: (base: J) => K,
|
|
208
|
-
): K;
|
|
209
|
-
export function BaseModelWith<
|
|
210
|
-
A extends Constructor,
|
|
211
|
-
B extends Constructor,
|
|
212
|
-
C extends Constructor,
|
|
213
|
-
D extends Constructor,
|
|
214
|
-
E extends Constructor,
|
|
215
|
-
F extends Constructor,
|
|
216
|
-
G extends Constructor,
|
|
217
|
-
H extends Constructor,
|
|
218
|
-
I extends Constructor,
|
|
219
|
-
J extends Constructor,
|
|
220
|
-
K extends Constructor,
|
|
221
|
-
L extends Constructor,
|
|
222
|
-
>(
|
|
223
|
-
a: (base: Base) => A,
|
|
224
|
-
b: (base: A) => B,
|
|
225
|
-
c: (base: B) => C,
|
|
226
|
-
d: (base: C) => D,
|
|
227
|
-
e: (base: D) => E,
|
|
228
|
-
f: (base: E) => F,
|
|
229
|
-
g: (base: F) => G,
|
|
230
|
-
h: (base: G) => H,
|
|
231
|
-
i: (base: H) => I,
|
|
232
|
-
j: (base: I) => J,
|
|
233
|
-
k: (base: J) => K,
|
|
234
|
-
l: (base: K) => L,
|
|
235
|
-
): L;
|
|
236
|
-
export function BaseModelWith<
|
|
237
|
-
A extends Constructor,
|
|
238
|
-
B extends Constructor,
|
|
239
|
-
C extends Constructor,
|
|
240
|
-
D extends Constructor,
|
|
241
|
-
E extends Constructor,
|
|
242
|
-
F extends Constructor,
|
|
243
|
-
G extends Constructor,
|
|
244
|
-
H extends Constructor,
|
|
245
|
-
I extends Constructor,
|
|
246
|
-
J extends Constructor,
|
|
247
|
-
K extends Constructor,
|
|
248
|
-
L extends Constructor,
|
|
249
|
-
M extends Constructor,
|
|
250
|
-
>(
|
|
251
|
-
a: (base: Base) => A,
|
|
252
|
-
b: (base: A) => B,
|
|
253
|
-
c: (base: B) => C,
|
|
254
|
-
d: (base: C) => D,
|
|
255
|
-
e: (base: D) => E,
|
|
256
|
-
f: (base: E) => F,
|
|
257
|
-
g: (base: F) => G,
|
|
258
|
-
h: (base: G) => H,
|
|
259
|
-
i: (base: H) => I,
|
|
260
|
-
j: (base: I) => J,
|
|
261
|
-
k: (base: J) => K,
|
|
262
|
-
l: (base: K) => L,
|
|
263
|
-
m: (base: L) => M,
|
|
264
|
-
): M;
|
|
265
|
-
export function BaseModelWith<
|
|
266
|
-
A extends Constructor,
|
|
267
|
-
B extends Constructor,
|
|
268
|
-
C extends Constructor,
|
|
269
|
-
D extends Constructor,
|
|
270
|
-
E extends Constructor,
|
|
271
|
-
F extends Constructor,
|
|
272
|
-
G extends Constructor,
|
|
273
|
-
H extends Constructor,
|
|
274
|
-
I extends Constructor,
|
|
275
|
-
J extends Constructor,
|
|
276
|
-
K extends Constructor,
|
|
277
|
-
L extends Constructor,
|
|
278
|
-
M extends Constructor,
|
|
279
|
-
N extends Constructor,
|
|
280
|
-
>(
|
|
281
|
-
a: (base: Base) => A,
|
|
282
|
-
b: (base: A) => B,
|
|
283
|
-
c: (base: B) => C,
|
|
284
|
-
d: (base: C) => D,
|
|
285
|
-
e: (base: D) => E,
|
|
286
|
-
f: (base: E) => F,
|
|
287
|
-
g: (base: F) => G,
|
|
288
|
-
h: (base: G) => H,
|
|
289
|
-
i: (base: H) => I,
|
|
290
|
-
j: (base: I) => J,
|
|
291
|
-
k: (base: J) => K,
|
|
292
|
-
l: (base: K) => L,
|
|
293
|
-
m: (base: L) => M,
|
|
294
|
-
n: (base: M) => N,
|
|
295
|
-
): N;
|
|
296
|
-
export function BaseModelWith<
|
|
297
|
-
A extends Constructor,
|
|
298
|
-
B extends Constructor,
|
|
299
|
-
C extends Constructor,
|
|
300
|
-
D extends Constructor,
|
|
301
|
-
E extends Constructor,
|
|
302
|
-
F extends Constructor,
|
|
303
|
-
G extends Constructor,
|
|
304
|
-
H extends Constructor,
|
|
305
|
-
I extends Constructor,
|
|
306
|
-
J extends Constructor,
|
|
307
|
-
K extends Constructor,
|
|
308
|
-
L extends Constructor,
|
|
309
|
-
M extends Constructor,
|
|
310
|
-
N extends Constructor,
|
|
311
|
-
O extends Constructor,
|
|
312
|
-
>(
|
|
313
|
-
a: (base: Base) => A,
|
|
314
|
-
b: (base: A) => B,
|
|
315
|
-
c: (base: B) => C,
|
|
316
|
-
d: (base: C) => D,
|
|
317
|
-
e: (base: D) => E,
|
|
318
|
-
f: (base: E) => F,
|
|
319
|
-
g: (base: F) => G,
|
|
320
|
-
h: (base: G) => H,
|
|
321
|
-
i: (base: H) => I,
|
|
322
|
-
j: (base: I) => J,
|
|
323
|
-
k: (base: J) => K,
|
|
324
|
-
l: (base: K) => L,
|
|
325
|
-
m: (base: L) => M,
|
|
326
|
-
n: (base: M) => N,
|
|
327
|
-
o: (base: N) => O,
|
|
328
|
-
): O;
|
|
329
|
-
export function BaseModelWith<
|
|
330
|
-
A extends Constructor,
|
|
331
|
-
B extends Constructor,
|
|
332
|
-
C extends Constructor,
|
|
333
|
-
D extends Constructor,
|
|
334
|
-
E extends Constructor,
|
|
335
|
-
F extends Constructor,
|
|
336
|
-
G extends Constructor,
|
|
337
|
-
H extends Constructor,
|
|
338
|
-
I extends Constructor,
|
|
339
|
-
J extends Constructor,
|
|
340
|
-
K extends Constructor,
|
|
341
|
-
L extends Constructor,
|
|
342
|
-
M extends Constructor,
|
|
343
|
-
N extends Constructor,
|
|
344
|
-
O extends Constructor,
|
|
345
|
-
P extends Constructor,
|
|
346
|
-
>(
|
|
347
|
-
a: (base: Base) => A,
|
|
348
|
-
b: (base: A) => B,
|
|
349
|
-
c: (base: B) => C,
|
|
350
|
-
d: (base: C) => D,
|
|
351
|
-
e: (base: D) => E,
|
|
352
|
-
f: (base: E) => F,
|
|
353
|
-
g: (base: F) => G,
|
|
354
|
-
h: (base: G) => H,
|
|
355
|
-
i: (base: H) => I,
|
|
356
|
-
j: (base: I) => J,
|
|
357
|
-
k: (base: J) => K,
|
|
358
|
-
l: (base: K) => L,
|
|
359
|
-
m: (base: L) => M,
|
|
360
|
-
n: (base: M) => N,
|
|
361
|
-
o: (base: N) => O,
|
|
362
|
-
p: (base: O) => P,
|
|
363
|
-
): P;
|
|
364
|
-
export function BaseModelWith<
|
|
365
|
-
A extends Constructor,
|
|
366
|
-
B extends Constructor,
|
|
367
|
-
C extends Constructor,
|
|
368
|
-
D extends Constructor,
|
|
369
|
-
E extends Constructor,
|
|
370
|
-
F extends Constructor,
|
|
371
|
-
G extends Constructor,
|
|
372
|
-
H extends Constructor,
|
|
373
|
-
I extends Constructor,
|
|
374
|
-
J extends Constructor,
|
|
375
|
-
K extends Constructor,
|
|
376
|
-
L extends Constructor,
|
|
377
|
-
M extends Constructor,
|
|
378
|
-
N extends Constructor,
|
|
379
|
-
O extends Constructor,
|
|
380
|
-
P extends Constructor,
|
|
381
|
-
Q extends Constructor,
|
|
382
|
-
>(
|
|
383
|
-
a: (base: Base) => A,
|
|
384
|
-
b: (base: A) => B,
|
|
385
|
-
c: (base: B) => C,
|
|
386
|
-
d: (base: C) => D,
|
|
387
|
-
e: (base: D) => E,
|
|
388
|
-
f: (base: E) => F,
|
|
389
|
-
g: (base: F) => G,
|
|
390
|
-
h: (base: G) => H,
|
|
391
|
-
i: (base: H) => I,
|
|
392
|
-
j: (base: I) => J,
|
|
393
|
-
k: (base: J) => K,
|
|
394
|
-
l: (base: K) => L,
|
|
395
|
-
m: (base: L) => M,
|
|
396
|
-
n: (base: M) => N,
|
|
397
|
-
o: (base: N) => O,
|
|
398
|
-
p: (base: O) => P,
|
|
399
|
-
q: (base: P) => Q,
|
|
400
|
-
): Q;
|
|
401
|
-
export function BaseModelWith<
|
|
402
|
-
A extends Constructor,
|
|
403
|
-
B extends Constructor,
|
|
404
|
-
C extends Constructor,
|
|
405
|
-
D extends Constructor,
|
|
406
|
-
E extends Constructor,
|
|
407
|
-
F extends Constructor,
|
|
408
|
-
G extends Constructor,
|
|
409
|
-
H extends Constructor,
|
|
410
|
-
I extends Constructor,
|
|
411
|
-
J extends Constructor,
|
|
412
|
-
K extends Constructor,
|
|
413
|
-
L extends Constructor,
|
|
414
|
-
M extends Constructor,
|
|
415
|
-
N extends Constructor,
|
|
416
|
-
O extends Constructor,
|
|
417
|
-
P extends Constructor,
|
|
418
|
-
Q extends Constructor,
|
|
419
|
-
R extends Constructor,
|
|
420
|
-
>(
|
|
421
|
-
a: (base: Base) => A,
|
|
422
|
-
b: (base: A) => B,
|
|
423
|
-
c: (base: B) => C,
|
|
424
|
-
d: (base: C) => D,
|
|
425
|
-
e: (base: D) => E,
|
|
426
|
-
f: (base: E) => F,
|
|
427
|
-
g: (base: F) => G,
|
|
428
|
-
h: (base: G) => H,
|
|
429
|
-
i: (base: H) => I,
|
|
430
|
-
j: (base: I) => J,
|
|
431
|
-
k: (base: J) => K,
|
|
432
|
-
l: (base: K) => L,
|
|
433
|
-
m: (base: L) => M,
|
|
434
|
-
n: (base: M) => N,
|
|
435
|
-
o: (base: N) => O,
|
|
436
|
-
p: (base: O) => P,
|
|
437
|
-
q: (base: P) => Q,
|
|
438
|
-
r: (base: Q) => R,
|
|
439
|
-
): R;
|
|
440
|
-
export function BaseModelWith<
|
|
441
|
-
A extends Constructor,
|
|
442
|
-
B extends Constructor,
|
|
443
|
-
C extends Constructor,
|
|
444
|
-
D extends Constructor,
|
|
445
|
-
E extends Constructor,
|
|
446
|
-
F extends Constructor,
|
|
447
|
-
G extends Constructor,
|
|
448
|
-
H extends Constructor,
|
|
449
|
-
I extends Constructor,
|
|
450
|
-
J extends Constructor,
|
|
451
|
-
K extends Constructor,
|
|
452
|
-
L extends Constructor,
|
|
453
|
-
M extends Constructor,
|
|
454
|
-
N extends Constructor,
|
|
455
|
-
O extends Constructor,
|
|
456
|
-
P extends Constructor,
|
|
457
|
-
Q extends Constructor,
|
|
458
|
-
R extends Constructor,
|
|
459
|
-
S extends Constructor,
|
|
460
|
-
>(
|
|
461
|
-
a: (base: Base) => A,
|
|
462
|
-
b: (base: A) => B,
|
|
463
|
-
c: (base: B) => C,
|
|
464
|
-
d: (base: C) => D,
|
|
465
|
-
e: (base: D) => E,
|
|
466
|
-
f: (base: E) => F,
|
|
467
|
-
g: (base: F) => G,
|
|
468
|
-
h: (base: G) => H,
|
|
469
|
-
i: (base: H) => I,
|
|
470
|
-
j: (base: I) => J,
|
|
471
|
-
k: (base: J) => K,
|
|
472
|
-
l: (base: K) => L,
|
|
473
|
-
m: (base: L) => M,
|
|
474
|
-
n: (base: M) => N,
|
|
475
|
-
o: (base: N) => O,
|
|
476
|
-
p: (base: O) => P,
|
|
477
|
-
q: (base: P) => Q,
|
|
478
|
-
r: (base: Q) => R,
|
|
479
|
-
s: (base: R) => S,
|
|
480
|
-
): S;
|
|
481
|
-
export function BaseModelWith<
|
|
482
|
-
A extends Constructor,
|
|
483
|
-
B extends Constructor,
|
|
484
|
-
C extends Constructor,
|
|
485
|
-
D extends Constructor,
|
|
486
|
-
E extends Constructor,
|
|
487
|
-
F extends Constructor,
|
|
488
|
-
G extends Constructor,
|
|
489
|
-
H extends Constructor,
|
|
490
|
-
I extends Constructor,
|
|
491
|
-
J extends Constructor,
|
|
492
|
-
K extends Constructor,
|
|
493
|
-
L extends Constructor,
|
|
494
|
-
M extends Constructor,
|
|
495
|
-
N extends Constructor,
|
|
496
|
-
O extends Constructor,
|
|
497
|
-
P extends Constructor,
|
|
498
|
-
Q extends Constructor,
|
|
499
|
-
R extends Constructor,
|
|
500
|
-
S extends Constructor,
|
|
501
|
-
T extends Constructor,
|
|
502
|
-
>(
|
|
503
|
-
a: (base: Base) => A,
|
|
504
|
-
b: (base: A) => B,
|
|
505
|
-
c: (base: B) => C,
|
|
506
|
-
d: (base: C) => D,
|
|
507
|
-
e: (base: D) => E,
|
|
508
|
-
f: (base: E) => F,
|
|
509
|
-
g: (base: F) => G,
|
|
510
|
-
h: (base: G) => H,
|
|
511
|
-
i: (base: H) => I,
|
|
512
|
-
j: (base: I) => J,
|
|
513
|
-
k: (base: J) => K,
|
|
514
|
-
l: (base: K) => L,
|
|
515
|
-
m: (base: L) => M,
|
|
516
|
-
n: (base: M) => N,
|
|
517
|
-
o: (base: N) => O,
|
|
518
|
-
p: (base: O) => P,
|
|
519
|
-
q: (base: P) => Q,
|
|
520
|
-
r: (base: Q) => R,
|
|
521
|
-
s: (base: R) => S,
|
|
522
|
-
t: (base: S) => T,
|
|
523
|
-
): T;
|
|
49
|
+
export interface Compose {
|
|
50
|
+
<TBase extends Constructor, A extends Constructor>(this: TBase, a: (base: TBase) => A): A;
|
|
51
|
+
<TBase extends Constructor, A extends Constructor, B extends Constructor>(
|
|
52
|
+
this: TBase,
|
|
53
|
+
a: (base: TBase) => A,
|
|
54
|
+
b: (base: A) => B,
|
|
55
|
+
): B;
|
|
56
|
+
<TBase extends Constructor, A extends Constructor, B extends Constructor, C extends Constructor>(
|
|
57
|
+
this: TBase,
|
|
58
|
+
a: (base: TBase) => A,
|
|
59
|
+
b: (base: A) => B,
|
|
60
|
+
c: (base: B) => C,
|
|
61
|
+
): C;
|
|
62
|
+
<
|
|
63
|
+
TBase extends Constructor,
|
|
64
|
+
A extends Constructor,
|
|
65
|
+
B extends Constructor,
|
|
66
|
+
C extends Constructor,
|
|
67
|
+
D extends Constructor,
|
|
68
|
+
>(
|
|
69
|
+
this: TBase,
|
|
70
|
+
a: (base: TBase) => A,
|
|
71
|
+
b: (base: A) => B,
|
|
72
|
+
c: (base: B) => C,
|
|
73
|
+
d: (base: C) => D,
|
|
74
|
+
): D;
|
|
75
|
+
<
|
|
76
|
+
TBase extends Constructor,
|
|
77
|
+
A extends Constructor,
|
|
78
|
+
B extends Constructor,
|
|
79
|
+
C extends Constructor,
|
|
80
|
+
D extends Constructor,
|
|
81
|
+
E extends Constructor,
|
|
82
|
+
>(
|
|
83
|
+
this: TBase,
|
|
84
|
+
a: (base: TBase) => A,
|
|
85
|
+
b: (base: A) => B,
|
|
86
|
+
c: (base: B) => C,
|
|
87
|
+
d: (base: C) => D,
|
|
88
|
+
e: (base: D) => E,
|
|
89
|
+
): E;
|
|
90
|
+
<
|
|
91
|
+
TBase extends Constructor,
|
|
92
|
+
A extends Constructor,
|
|
93
|
+
B extends Constructor,
|
|
94
|
+
C extends Constructor,
|
|
95
|
+
D extends Constructor,
|
|
96
|
+
E extends Constructor,
|
|
97
|
+
F extends Constructor,
|
|
98
|
+
>(
|
|
99
|
+
this: TBase,
|
|
100
|
+
a: (base: TBase) => A,
|
|
101
|
+
b: (base: A) => B,
|
|
102
|
+
c: (base: B) => C,
|
|
103
|
+
d: (base: C) => D,
|
|
104
|
+
e: (base: D) => E,
|
|
105
|
+
f: (base: E) => F,
|
|
106
|
+
): F;
|
|
107
|
+
<
|
|
108
|
+
TBase extends Constructor,
|
|
109
|
+
A extends Constructor,
|
|
110
|
+
B extends Constructor,
|
|
111
|
+
C extends Constructor,
|
|
112
|
+
D extends Constructor,
|
|
113
|
+
E extends Constructor,
|
|
114
|
+
F extends Constructor,
|
|
115
|
+
G extends Constructor,
|
|
116
|
+
>(
|
|
117
|
+
this: TBase,
|
|
118
|
+
a: (base: TBase) => A,
|
|
119
|
+
b: (base: A) => B,
|
|
120
|
+
c: (base: B) => C,
|
|
121
|
+
d: (base: C) => D,
|
|
122
|
+
e: (base: D) => E,
|
|
123
|
+
f: (base: E) => F,
|
|
124
|
+
g: (base: F) => G,
|
|
125
|
+
): G;
|
|
126
|
+
<
|
|
127
|
+
TBase extends Constructor,
|
|
128
|
+
A extends Constructor,
|
|
129
|
+
B extends Constructor,
|
|
130
|
+
C extends Constructor,
|
|
131
|
+
D extends Constructor,
|
|
132
|
+
E extends Constructor,
|
|
133
|
+
F extends Constructor,
|
|
134
|
+
G extends Constructor,
|
|
135
|
+
H extends Constructor,
|
|
136
|
+
>(
|
|
137
|
+
this: TBase,
|
|
138
|
+
a: (base: TBase) => A,
|
|
139
|
+
b: (base: A) => B,
|
|
140
|
+
c: (base: B) => C,
|
|
141
|
+
d: (base: C) => D,
|
|
142
|
+
e: (base: D) => E,
|
|
143
|
+
f: (base: E) => F,
|
|
144
|
+
g: (base: F) => G,
|
|
145
|
+
h: (base: G) => H,
|
|
146
|
+
): H;
|
|
147
|
+
}
|
|
524
148
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
149
|
+
/**
|
|
150
|
+
* The fold behind {@link Compose}: apply each mixin left-to-right, seeding from `this` (the
|
|
151
|
+
* class `using` was called on). Assigned to `BaseModel.using` — not exported publicly.
|
|
152
|
+
*
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
|
+
export const _compose = function (
|
|
156
|
+
this: Constructor,
|
|
529
157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- variadic mixin folder
|
|
530
158
|
...mixins: Array<(base: any) => Constructor>
|
|
531
159
|
): Constructor {
|
|
532
|
-
return mixins.reduce<Constructor>(
|
|
533
|
-
|
|
534
|
-
BaseModel as unknown as Constructor,
|
|
535
|
-
);
|
|
536
|
-
}
|
|
160
|
+
return mixins.reduce<Constructor>((acc, mixin) => mixin(acc), this);
|
|
161
|
+
} as Compose;
|