@getstrata/core 0.5.98 → 0.5.100
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 +30 -0
- package/dist/core/database/baseRepository.d.ts +3 -1
- package/dist/core/database/factory.d.ts +19 -4
- package/dist/core/database/index.d.ts +1 -1
- package/dist/core/database/model.d.ts +56 -19
- package/dist/core/database/relationQuery.d.ts +24 -1
- package/dist/core/database/relationships.d.ts +4 -2
- package/dist/core/database/repositoryQuery.d.ts +4 -1
- package/dist/core/http/resources.d.ts +2 -1
- package/dist/entries/database/factory.js +44 -2
- package/dist/entries/database/model.js +497 -145
- package/dist/entries/database/query.js +1 -1
- package/dist/entries/database/relationships.js +85 -21
- package/dist/entries/database/repositoryQuery.js +242 -8
- package/dist/entries/database/schema.js +1 -1
- package/dist/entries/http/resources.js +9 -3
- package/dist/framework/public-api.d.ts +1 -1
- package/dist/index.js +606 -178
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.100
|
|
4
|
+
|
|
5
|
+
HiroApp dogfood of 0.5.99: eager `with()` / nested `load("a.b")` missed related rows when a Postgres int4 PK arrived as a JS `number` and an int8 FK as a `bigint`. Map matching used `===`.
|
|
6
|
+
|
|
7
|
+
- Relation indexers and eager attach compare keys with `relationMatchKey` (`1`, `1n`, `"1"` match).
|
|
8
|
+
- Sequential `load("position")` / `application.position()` already used SQL `get()` and were unaffected.
|
|
9
|
+
- `registerModelRepository(User, users)` already names `User` and `$morphClass`. Do not also call `registerModelClass("User", User)`. `registerModelClass` is only for an alias that is neither `constructor.name` nor `$morphClass`.
|
|
10
|
+
|
|
11
|
+
Still non-conforming (honest): Bun cannot infer `morphTo()` method names. `hashed` cast is a no-op. `Factory.has()` without a bound model still needs an explicit FK.
|
|
12
|
+
|
|
13
|
+
## 0.5.99
|
|
14
|
+
|
|
15
|
+
HiroApp dogfood of 0.5.98 found lookalike APIs. This release matches Laravel call shape and SQL, not just export names.
|
|
16
|
+
|
|
17
|
+
- Relation queries are thenable: `await user.applications()` delegates to `get()`.
|
|
18
|
+
- `Model.with()` / `where()` / `whereHas()` return a `ModelQuery` that hydrates models and chains into `where` / `find` / `findOrFail` / `first` / `get`. `first()` / `find()` use `LIMIT` / PK lookup.
|
|
19
|
+
- `belongsTo.where()` threads constraints into `whereHas` EXISTS (HiroApp application search).
|
|
20
|
+
- `{ ilike }` uses the value as-is (Laravel). Pass `%term%` yourself; the operator no longer wraps extra `%`.
|
|
21
|
+
- Morph type defaults to `$morphClass` / class name, not `table.name`. Override with `$morphClass = "App\\Models\\User"` or the last `morphMany` argument. `morphTo()` no longer silently defaults to `imageable_*`.
|
|
22
|
+
- `primaryKey()` defaults to the table PK (`id`).
|
|
23
|
+
- Nested `load("a.b")` / `with("a.b")` skip already-loaded heads and batch the next level.
|
|
24
|
+
- `count()` is `COUNT(*)` (relations and `RepositoryQuery`).
|
|
25
|
+
- `belongsToMany` eager-loads in two queries; `toggle()` and `withPivotValues()` exist. `hasMany.save($model)` sets the FK and saves.
|
|
26
|
+
- Factory `for(parent)` infers `user_id` from a Model parent. Bound `model` uses `Model.create()` so observers fire.
|
|
27
|
+
- `JsonResource.collection().toResponse()` wraps once: `{ data: [...] }`.
|
|
28
|
+
- Observers: `saving` / `saved` / `retrieved`. Integer casts: `integer` / `int`.
|
|
29
|
+
- `hasMany("Application")` / `() => Application` / `registerModelClass()` for ESM cycles.
|
|
30
|
+
|
|
31
|
+
Still non-conforming (honest): Bun cannot infer `morphTo()` method names (`debug_backtrace` equivalent is empty). `hashed` cast is a no-op (bcrypt is async). `Factory.has()` without a model class still needs an explicit FK.
|
|
32
|
+
|
|
3
33
|
## 0.5.98
|
|
4
34
|
|
|
5
35
|
- Eloquent-shaped relations: `this.hasMany(Related)` returns a relation query (`get`/`where`/`create`/`attach`). `load()` / `loaded()` and `Model.with()` replace PHP `__get`. `whereHas`/`has`/`doesntHave`, morph* methods, and nested `with("a.b")` are supported.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CursorPaginatedResult, type PaginatedResult } from "../pagination/index.ts";
|
|
2
|
-
import { type BelongsToRelation, type HasManyRelation, type MorphManyRelation, type MorphOneRelation, type MorphToRelation } from "./relationships.ts";
|
|
2
|
+
import { type BelongsToManyRelation, type BelongsToRelation, type HasManyRelation, type MorphManyRelation, type MorphOneRelation, type MorphToRelation } from "./relationships.ts";
|
|
3
3
|
import { RepositoryQuery } from "./repositoryQuery.ts";
|
|
4
4
|
import type { TableDefinition } from "./table.ts";
|
|
5
5
|
import type { MutationValues, QueryOptions, QueryWhere, UpdateValues } from "./types.ts";
|
|
@@ -20,6 +20,7 @@ declare class BaseRepository<TEntity extends object, PrimaryKey extends keyof TE
|
|
|
20
20
|
protected readonly table: TableDefinition<TEntity, PrimaryKey>;
|
|
21
21
|
protected readonly connection: DatabaseConnection;
|
|
22
22
|
constructor(table: TableDefinition<TEntity, PrimaryKey>, connection?: DatabaseConnection);
|
|
23
|
+
count(options?: ExtendedQueryOptions<TEntity>): Promise<number>;
|
|
23
24
|
findAll(options?: ExtendedQueryOptions<TEntity>): Promise<TEntity[]>;
|
|
24
25
|
paginate(options: {
|
|
25
26
|
page: number;
|
|
@@ -62,6 +63,7 @@ declare class BaseRepository<TEntity extends object, PrimaryKey extends keyof TE
|
|
|
62
63
|
loadMorphManyForParents<TParent extends object, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TEntity & string, MorphIdKey extends keyof TEntity & string>(parents: readonly TParent[], relation: MorphManyRelation<TParent, TEntity, LocalKey, MorphTypeKey, MorphIdKey>, options?: Omit<QueryOptions<TEntity>, "where">): Promise<Map<TParent[LocalKey], TEntity[]>>;
|
|
63
64
|
loadMorphOneForParents<TParent extends object, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TEntity & string, MorphIdKey extends keyof TEntity & string>(parents: readonly TParent[], relation: MorphOneRelation<TParent, TEntity, LocalKey, MorphTypeKey, MorphIdKey>, options?: Omit<QueryOptions<TEntity>, "where">): Promise<Map<TParent[LocalKey], TEntity | undefined>>;
|
|
64
65
|
loadMorphToForChildren<TChild extends object, TParent extends object, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string, OwnerKey extends keyof TParent & string>(children: readonly TChild[], relation: MorphToRelation<TChild, MorphTypeKey, MorphIdKey>, repositoriesByType: ReadonlyMap<string, BaseRepository<TParent, OwnerKey>>, options?: Omit<QueryOptions<TParent>, "where">): Promise<Map<TChild[MorphIdKey], TParent>>;
|
|
66
|
+
loadBelongsToManyForParents<TParent extends object, TRelated extends object, Pivot extends object, ParentKey extends keyof TParent & string, RelatedKey extends keyof TRelated & string, ForeignPivotKey extends keyof Pivot & string, RelatedPivotKey extends keyof Pivot & string>(parents: readonly TParent[], relation: BelongsToManyRelation<TParent, TRelated, Pivot, ParentKey, RelatedKey, ForeignPivotKey, RelatedPivotKey>, relatedRepository: BaseRepository<TRelated, RelatedKey>, options?: Omit<QueryOptions<TRelated>, "where">): Promise<Map<TParent[ParentKey], TRelated[]>>;
|
|
65
67
|
}
|
|
66
68
|
export { BaseRepository };
|
|
67
69
|
export default BaseRepository;
|
|
@@ -11,6 +11,11 @@ declare class Factory<TRecord extends object, Counted extends boolean = false> {
|
|
|
11
11
|
private children;
|
|
12
12
|
private afterMakingCallbacks;
|
|
13
13
|
private afterCreatingCallbacks;
|
|
14
|
+
protected model?: {
|
|
15
|
+
create(attributes: Record<string, unknown>): Promise<{
|
|
16
|
+
toObject(): object;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
14
19
|
protected definition(): TRecord;
|
|
15
20
|
protected clone(): this;
|
|
16
21
|
count(quantity: number): Factory<TRecord, true>;
|
|
@@ -18,19 +23,29 @@ declare class Factory<TRecord extends object, Counted extends boolean = false> {
|
|
|
18
23
|
sequence(...items: Array<FactorySequence<TRecord>>): Factory<TRecord, Counted>;
|
|
19
24
|
for(parent: {
|
|
20
25
|
id?: unknown;
|
|
21
|
-
|
|
26
|
+
getRepository?: () => {
|
|
27
|
+
getTable(): {
|
|
28
|
+
name: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}, foreignKey?: keyof TRecord & string): Factory<TRecord, Counted>;
|
|
22
32
|
recycle(parent: {
|
|
23
33
|
id?: unknown;
|
|
24
|
-
|
|
34
|
+
getRepository?: () => {
|
|
35
|
+
getTable(): {
|
|
36
|
+
name: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}, foreignKey?: keyof TRecord & string): Factory<TRecord, Counted>;
|
|
25
40
|
afterMaking(callback: (record: TRecord) => void): Factory<TRecord, Counted>;
|
|
26
41
|
afterCreating(callback: (record: TRecord) => void | Promise<void>): Factory<TRecord, Counted>;
|
|
27
|
-
has<TRelated extends object, RelatedCounted extends boolean>(factory: Factory<TRelated, RelatedCounted>, foreignKey
|
|
42
|
+
has<TRelated extends object, RelatedCounted extends boolean>(factory: Factory<TRelated, RelatedCounted>, foreignKey?: keyof TRelated & string): Factory<TRecord, Counted>;
|
|
28
43
|
make(overrides?: Partial<TRecord>): FactoryMakeResult<TRecord, Counted>;
|
|
29
44
|
create(overrides?: Partial<TRecord>): Promise<FactoryMakeResult<TRecord, Counted>>;
|
|
30
45
|
protected makeOne(overrides?: Partial<TRecord>): TRecord;
|
|
31
46
|
protected createOne(overrides?: Partial<TRecord>): Promise<TRecord>;
|
|
32
47
|
protected insertable(record: TRecord): Partial<TRecord>;
|
|
33
|
-
protected persist(
|
|
48
|
+
protected persist(values: Partial<TRecord>): Promise<TRecord>;
|
|
34
49
|
}
|
|
35
50
|
export type { FactoryMakeResult };
|
|
36
51
|
export { Factory };
|
|
@@ -5,7 +5,7 @@ export { mapDatabaseError, withDatabaseErrorHandling } from "./errors.ts";
|
|
|
5
5
|
export { Factory } from "./factory.ts";
|
|
6
6
|
export { foreignKeyFromTable, pivotTableName, singularize } from "./inflection.ts";
|
|
7
7
|
export type { CastType, GlobalScopeFn, ModelConstructor } from "./model.ts";
|
|
8
|
-
export { applyCasts, BelongsToManyRelationQuery, BelongsToRelationQuery, dehydrateValue, filterMassAssignable, HasManyRelationQuery, HasOneRelationQuery, hydrateValue, Model, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, registerModelRepository, } from "./model.ts";
|
|
8
|
+
export { applyCasts, BelongsToManyRelationQuery, BelongsToRelationQuery, dehydrateValue, filterMassAssignable, HasManyRelationQuery, HasOneRelationQuery, hydrateValue, Model, ModelQuery, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, registerModelClass, registerModelRepository, } from "./model.ts";
|
|
9
9
|
export { buildAdvancedWhereClause, buildCountQuery, buildDeleteByIdQuery, buildGroupedCountQuery, buildInsertQuery, buildJoinClause, buildOrderByClause, buildProjectionQuery, buildQueryWhereClause, buildRestoreByIdQuery, buildSelectQuery, buildSoftDeleteByIdQuery, buildUpdateQuery, buildWhereClause, parseQualifiedColumn, qualifyColumn, quoteIdentifier, resolveQualifiedColumn, resolveSoftDeleteColumn, } from "./query.ts";
|
|
10
10
|
export type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasOneRelation, MorphManyRelation, MorphOneRelation, MorphToRelation, } from "./relationships.ts";
|
|
11
11
|
export { belongsTo, belongsToMany, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, } from "./relationships.ts";
|
|
@@ -4,7 +4,7 @@ import { BelongsToManyRelationQuery, BelongsToRelationQuery, HasManyRelationQuer
|
|
|
4
4
|
import type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasOneRelation } from "./relationships.ts";
|
|
5
5
|
import type { RepositoryQuery } from "./repositoryQuery.ts";
|
|
6
6
|
import type { QueryOptions, QueryWhere } from "./types.ts";
|
|
7
|
-
type CastType = "date" | "datetime" | "json" | "bool" | "boolean";
|
|
7
|
+
type CastType = "date" | "datetime" | "json" | "bool" | "boolean" | "integer" | "int" | "hashed";
|
|
8
8
|
type LoadedAttributes = Record<string, unknown>;
|
|
9
9
|
type ModelCasts = Partial<Record<string, CastType>>;
|
|
10
10
|
type GlobalScopeFn<TEntity extends object, PrimaryKey extends keyof TEntity & string> = (query: RepositoryQuery<TEntity, PrimaryKey>) => RepositoryQuery<TEntity, PrimaryKey>;
|
|
@@ -13,18 +13,56 @@ interface ModelConstructor<TEntity extends object, PrimaryKey extends keyof TEnt
|
|
|
13
13
|
new (attributes: TEntity, repository: BaseRepository<TEntity, PrimaryKey>, exists?: boolean): TModel;
|
|
14
14
|
}
|
|
15
15
|
type AnyModel = Model<Record<string, unknown>, "id">;
|
|
16
|
+
type RelatedRef<TRelated extends object, RelatedKey extends keyof TRelated & string> = RelatedModelClass<TRelated, RelatedKey> | string | (() => RelatedModelClass<TRelated, RelatedKey>);
|
|
16
17
|
type ModelObserver = {
|
|
18
|
+
retrieved?: (model: AnyModel) => unknown;
|
|
17
19
|
creating?: (model: AnyModel) => unknown;
|
|
18
20
|
created?: (model: AnyModel) => unknown;
|
|
19
21
|
updating?: (model: AnyModel) => unknown;
|
|
20
22
|
updated?: (model: AnyModel) => unknown;
|
|
23
|
+
saving?: (model: AnyModel) => unknown;
|
|
24
|
+
saved?: (model: AnyModel) => unknown;
|
|
21
25
|
deleting?: (model: AnyModel) => unknown;
|
|
22
26
|
deleted?: (model: AnyModel) => unknown;
|
|
23
27
|
};
|
|
28
|
+
/** Alias for `hasMany("Name")` when `Name` is not `constructor.name` or `$morphClass`. */
|
|
29
|
+
declare function registerModelClass(name: string, model: object): void;
|
|
24
30
|
declare function hydrateValue(value: unknown, cast: CastType): unknown;
|
|
25
31
|
declare function dehydrateValue(value: unknown, cast: CastType): unknown;
|
|
26
32
|
declare function filterMassAssignable(fillable: readonly string[] | undefined, guarded: readonly string[] | true | undefined, input: LoadedAttributes): LoadedAttributes;
|
|
27
33
|
declare function applyCasts(values: LoadedAttributes, casts: ModelCasts, direction: "hydrate" | "dehydrate"): LoadedAttributes;
|
|
34
|
+
declare class ModelQuery {
|
|
35
|
+
private readonly modelClass;
|
|
36
|
+
readonly query: RepositoryQuery<Record<string, unknown>, "id">;
|
|
37
|
+
private readonly eager;
|
|
38
|
+
constructor(modelClass: object, query: RepositoryQuery<Record<string, unknown>, "id">);
|
|
39
|
+
with(...relations: string[]): this;
|
|
40
|
+
where(input: QueryWhere<object> | ((builder: import("./whereBuilder.ts").WhereBuilder<object>) => void)): this;
|
|
41
|
+
orWhere(input: QueryWhere<object> | ((builder: import("./whereBuilder.ts").WhereBuilder<object>) => void)): this;
|
|
42
|
+
orderBy(orderBy: QueryOptions<object>["orderBy"]): this;
|
|
43
|
+
limit(limit: number): this;
|
|
44
|
+
offset(offset: number): this;
|
|
45
|
+
whereNull(column: string): this;
|
|
46
|
+
whereIn(column: string, values: readonly unknown[]): this;
|
|
47
|
+
whereExists(sql: string, params?: readonly unknown[]): this;
|
|
48
|
+
whereNotExists(sql: string, params?: readonly unknown[]): this;
|
|
49
|
+
whereHas(name: string, constrain?: (query: AnyRelationQuery) => void): this;
|
|
50
|
+
has(name: string): this;
|
|
51
|
+
doesntHave(name: string): this;
|
|
52
|
+
whereDoesntHave(name: string, constrain?: (query: AnyRelationQuery) => void): this;
|
|
53
|
+
withHasMany(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withHasMany"]>): this;
|
|
54
|
+
withBelongsTo(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withBelongsTo"]>): this;
|
|
55
|
+
withBelongsToMany(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withBelongsToMany"]>): this;
|
|
56
|
+
withMorphMany(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withMorphMany"]>): this;
|
|
57
|
+
withMorphOne(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withMorphOne"]>): this;
|
|
58
|
+
withMorphTo(...args: Parameters<RepositoryQuery<Record<string, unknown>, "id">["withMorphTo"]>): this;
|
|
59
|
+
get(): Promise<Array<Model<Record<string, unknown>, "id">>>;
|
|
60
|
+
first(): Promise<Model<Record<string, unknown>, "id"> | null>;
|
|
61
|
+
find(id: unknown): Promise<Model<Record<string, unknown>, "id"> | null>;
|
|
62
|
+
findOrFail(id: unknown, errorFactory?: (id: unknown) => Error): Promise<Model<Record<string, unknown>, "id">>;
|
|
63
|
+
then(onfulfilled?: ((value: Array<Model<Record<string, unknown>, "id">>) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
64
|
+
private constrainExists;
|
|
65
|
+
}
|
|
28
66
|
declare class Model<TEntity extends object, PrimaryKey extends keyof TEntity & string> {
|
|
29
67
|
protected attributes: TEntity;
|
|
30
68
|
protected readonly repository: BaseRepository<TEntity, PrimaryKey>;
|
|
@@ -35,6 +73,7 @@ declare class Model<TEntity extends object, PrimaryKey extends keyof TEntity & s
|
|
|
35
73
|
static $hidden?: readonly string[];
|
|
36
74
|
static $visible?: readonly string[];
|
|
37
75
|
static $appends?: readonly string[];
|
|
76
|
+
static $morphClass?: string;
|
|
38
77
|
private _exists;
|
|
39
78
|
private readonly loadedRelations;
|
|
40
79
|
private hiddenOverrides;
|
|
@@ -60,21 +99,18 @@ declare class Model<TEntity extends object, PrimaryKey extends keyof TEntity & s
|
|
|
60
99
|
static observe(this: object, observer: ModelObserver): void;
|
|
61
100
|
static addGlobalScope<TEntity extends object, PrimaryKey extends keyof TEntity & string>(this: object, _name: string, scope: GlobalScopeFn<TEntity, PrimaryKey>): void;
|
|
62
101
|
static repository<TEntity extends object, PrimaryKey extends keyof TEntity & string>(this: object): BaseRepository<TEntity, PrimaryKey>;
|
|
63
|
-
static query
|
|
102
|
+
static query(this: object): ModelQuery;
|
|
64
103
|
static newFromRecord(this: object, record: object, exists?: boolean): Model<Record<string, unknown>, "id">;
|
|
65
104
|
static create(this: object, attributes: Record<string, unknown>, forced?: Record<string, unknown>): Promise<Model<Record<string, unknown>, "id">>;
|
|
66
|
-
static with(this: object, ...relations: string[]):
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
static
|
|
71
|
-
static has(this: object, name: string): RepositoryQuery<Record<string, unknown>, "id">;
|
|
72
|
-
static doesntHave(this: object, name: string): RepositoryQuery<Record<string, unknown>, "id">;
|
|
73
|
-
static whereDoesntHave(this: object, name: string, constrain?: (query: AnyRelationQuery) => void): RepositoryQuery<Record<string, unknown>, "id">;
|
|
105
|
+
static with(this: object, ...relations: string[]): ModelQuery;
|
|
106
|
+
static whereHas(this: object, name: string, constrain?: (query: AnyRelationQuery) => void): ModelQuery;
|
|
107
|
+
static has(this: object, name: string): ModelQuery;
|
|
108
|
+
static doesntHave(this: object, name: string): ModelQuery;
|
|
109
|
+
static whereDoesntHave(this: object, name: string, constrain?: (query: AnyRelationQuery) => void): ModelQuery;
|
|
74
110
|
static find(this: object, id: unknown): Promise<Model<Record<string, unknown>, "id"> | null>;
|
|
75
111
|
static findOrFail(this: object, id: unknown, errorFactory?: (id: unknown) => Error): Promise<Model<Record<string, unknown>, "id">>;
|
|
76
112
|
static all(this: object, options?: Omit<QueryOptions<object>, "where">): Promise<Array<Model<Record<string, unknown>, "id">>>;
|
|
77
|
-
static where(this: object, where: QueryWhere<object>):
|
|
113
|
+
static where(this: object, where: QueryWhere<object>): ModelQuery;
|
|
78
114
|
static firstWhere(this: object, where: QueryWhere<object>, options?: Omit<QueryOptions<object>, "where">): Promise<Model<Record<string, unknown>, "id"> | null>;
|
|
79
115
|
static firstOrNew(this: object, where: QueryWhere<object>, values?: Record<string, unknown>): Promise<Model<Record<string, unknown>, "id">>;
|
|
80
116
|
static firstOrCreate(this: object, where: QueryWhere<object>, values?: Record<string, unknown>): Promise<Model<Record<string, unknown>, "id">>;
|
|
@@ -88,19 +124,20 @@ declare class Model<TEntity extends object, PrimaryKey extends keyof TEntity & s
|
|
|
88
124
|
loadHasOne<TChild extends object, LocalKey extends keyof TEntity & string, ForeignKey extends keyof TChild & string, Alias extends string>(as: Alias, relation: HasOneRelation<TEntity, TChild, LocalKey, ForeignKey>, childRepository: BaseRepository<TChild, keyof TChild & string>, options?: Omit<QueryOptions<TChild>, "where">): Promise<this & Record<Alias, TChild | undefined>>;
|
|
89
125
|
loadBelongsTo<TParent extends object, ForeignKey extends keyof TEntity & string, OwnerKey extends keyof TParent & string, Alias extends string>(as: Alias, relation: BelongsToRelation<TEntity, TParent, ForeignKey, OwnerKey>, parentRepository: BaseRepository<TParent, OwnerKey>, options?: Omit<QueryOptions<TParent>, "where">): Promise<this & Record<Alias, TParent | undefined>>;
|
|
90
126
|
loadBelongsToMany<TRelated extends object, Pivot extends object, ParentKey extends keyof TEntity & string, RelatedKey extends keyof TRelated & string, ForeignPivotKey extends keyof Pivot & string, RelatedPivotKey extends keyof Pivot & string, Alias extends string>(as: Alias, relation: BelongsToManyRelation<TEntity, TRelated, Pivot, ParentKey, RelatedKey, ForeignPivotKey, RelatedPivotKey>, relatedRepository: BaseRepository<TRelated, RelatedKey>, options?: Omit<QueryOptions<TRelated>, "where">): Promise<this & Record<Alias, TRelated[]>>;
|
|
91
|
-
hasMany<TRelated extends object, RelatedKey extends keyof TRelated & string>(related:
|
|
92
|
-
hasOne<TRelated extends object, RelatedKey extends keyof TRelated & string>(related:
|
|
93
|
-
belongsTo<TRelated extends object, RelatedKey extends keyof TRelated & string>(related:
|
|
94
|
-
belongsToMany<TRelated extends object, RelatedKey extends keyof TRelated & string, Pivot extends object = Record<string, unknown>>(related:
|
|
95
|
-
morphMany<TRelated extends object, RelatedKey extends keyof TRelated & string>(related:
|
|
96
|
-
morphOne<TRelated extends object, RelatedKey extends keyof TRelated & string>(related:
|
|
97
|
-
morphTo(relatedByType: Record<string,
|
|
127
|
+
hasMany<TRelated extends object, RelatedKey extends keyof TRelated & string>(related: RelatedRef<TRelated, RelatedKey>, foreignKey?: keyof TRelated & string, localKey?: PrimaryKey): HasManyRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey>;
|
|
128
|
+
hasOne<TRelated extends object, RelatedKey extends keyof TRelated & string>(related: RelatedRef<TRelated, RelatedKey>, foreignKey?: keyof TRelated & string, localKey?: PrimaryKey): HasOneRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey>;
|
|
129
|
+
belongsTo<TRelated extends object, RelatedKey extends keyof TRelated & string>(related: RelatedRef<TRelated, RelatedKey>, foreignKey?: keyof TEntity & string, ownerKey?: RelatedKey): BelongsToRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey>;
|
|
130
|
+
belongsToMany<TRelated extends object, RelatedKey extends keyof TRelated & string, Pivot extends object = Record<string, unknown>>(related: RelatedRef<TRelated, RelatedKey>, pivotTable?: string, foreignPivotKey?: keyof Pivot & string, relatedPivotKey?: keyof Pivot & string): BelongsToManyRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey, Pivot>;
|
|
131
|
+
morphMany<TRelated extends object, RelatedKey extends keyof TRelated & string>(related: RelatedRef<TRelated, RelatedKey>, morphName: string, typeKey?: keyof TRelated & string, idKey?: keyof TRelated & string, morphType?: string): MorphManyRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey>;
|
|
132
|
+
morphOne<TRelated extends object, RelatedKey extends keyof TRelated & string>(related: RelatedRef<TRelated, RelatedKey>, morphName: string, typeKey?: keyof TRelated & string, idKey?: keyof TRelated & string, morphType?: string): MorphOneRelationQuery<TEntity, PrimaryKey, TRelated, RelatedKey>;
|
|
133
|
+
morphTo(relatedByType: Record<string, RelatedRef<Record<string, unknown>, "id">>, morphName?: string, typeKey?: keyof TEntity & string, idKey?: keyof TEntity & string): MorphToRelationQuery<TEntity, PrimaryKey>;
|
|
98
134
|
load(...names: string[]): Promise<this>;
|
|
99
135
|
loaded<T = unknown>(name: string): T | undefined;
|
|
100
136
|
setLoaded(name: string, value: unknown): this;
|
|
101
137
|
mergeAttributes(patch: Partial<TEntity>): this;
|
|
102
138
|
}
|
|
139
|
+
/** Binds a Model class to its table/connection and names it for `hasMany("User")`. */
|
|
103
140
|
declare function registerModelRepository<TModelClass>(model: TModelClass, repository: object): TModelClass;
|
|
104
141
|
export { BelongsToManyRelationQuery, BelongsToRelationQuery, HasManyRelationQuery, HasOneRelationQuery, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, } from "./relationQuery.ts";
|
|
105
142
|
export type { CastType, GlobalScopeFn, ModelClassType, ModelConstructor };
|
|
106
|
-
export { applyCasts, dehydrateValue, filterMassAssignable, hydrateValue, Model, registerModelRepository, };
|
|
143
|
+
export { applyCasts, dehydrateValue, filterMassAssignable, hydrateValue, Model, ModelQuery, registerModelClass, registerModelRepository, };
|
|
@@ -40,7 +40,12 @@ declare class HasManyRelationQuery<TParent extends object, ParentKey extends key
|
|
|
40
40
|
get(): Promise<RelatedRecord[]>;
|
|
41
41
|
first(): Promise<RelatedRecord | null>;
|
|
42
42
|
count(): Promise<number>;
|
|
43
|
+
then(onfulfilled?: ((value: RelatedRecord[]) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
43
44
|
create(attributes?: Record<string, unknown>): Promise<RelatedRecord>;
|
|
45
|
+
save(related: RelatedRecord | (Record<string, unknown> & {
|
|
46
|
+
save?: () => Promise<unknown>;
|
|
47
|
+
mergeAttributes?: (patch: Record<string, unknown>) => unknown;
|
|
48
|
+
})): Promise<RelatedRecord>;
|
|
44
49
|
createMany(records: ReadonlyArray<Record<string, unknown>>): Promise<RelatedRecord[]>;
|
|
45
50
|
}
|
|
46
51
|
declare class HasOneRelationQuery<TParent extends object, ParentKey extends keyof TParent & string, TChild extends object, ChildKey extends keyof TChild & string> {
|
|
@@ -56,21 +61,26 @@ declare class HasOneRelationQuery<TParent extends object, ParentKey extends keyo
|
|
|
56
61
|
get(): Promise<RelatedRecord | null>;
|
|
57
62
|
first(): Promise<RelatedRecord | null>;
|
|
58
63
|
count(): Promise<number>;
|
|
64
|
+
then(onfulfilled?: ((value: RelatedRecord | null) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
59
65
|
create(attributes?: Record<string, unknown>): Promise<RelatedRecord>;
|
|
66
|
+
save(related: RelatedRecord | Record<string, unknown>): Promise<RelatedRecord>;
|
|
60
67
|
}
|
|
61
68
|
declare class BelongsToRelationQuery<TChild extends object, ChildKey extends keyof TChild & string, TParent extends object, ParentKey extends keyof TParent & string> {
|
|
62
69
|
private readonly parent;
|
|
63
70
|
private readonly related;
|
|
64
71
|
readonly relation: BelongsToRelation<TChild, TParent, keyof TChild & string, ParentKey>;
|
|
65
72
|
readonly kind: RelationKind;
|
|
73
|
+
private extraWhere;
|
|
66
74
|
private extraOptions;
|
|
67
75
|
constructor(parent: RelationHost<TChild, ChildKey>, related: RelatedModelClass<TParent, ParentKey>, relation: BelongsToRelation<TChild, TParent, keyof TChild & string, ParentKey>);
|
|
76
|
+
where(where: QueryWhere<TParent>): this;
|
|
68
77
|
orderBy(orderBy: QueryOptions<TParent>["orderBy"]): this;
|
|
69
78
|
applyEagerLoad(query: RepositoryQuery<TChild, ChildKey>, alias: string): void;
|
|
70
79
|
hydrateEager(row: Record<string, unknown>, alias: string): unknown;
|
|
71
80
|
toExistsClause(parentTable: string): ExistsClause;
|
|
72
81
|
get(): Promise<RelatedRecord | null>;
|
|
73
82
|
first(): Promise<RelatedRecord | null>;
|
|
83
|
+
then(onfulfilled?: ((value: RelatedRecord | null) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
74
84
|
associate(owner: {
|
|
75
85
|
id?: unknown;
|
|
76
86
|
} | RelatedRecord): Promise<void>;
|
|
@@ -83,17 +93,21 @@ declare class BelongsToManyRelationQuery<TParent extends object, ParentKey exten
|
|
|
83
93
|
readonly kind: RelationKind;
|
|
84
94
|
private extraWhere;
|
|
85
95
|
private extraOptions;
|
|
96
|
+
private pivotValues;
|
|
86
97
|
constructor(parent: RelationHost<TParent, ParentKey>, related: RelatedModelClass<TRelated, RelatedKey>, relation: BelongsToManyRelation<TParent, TRelated, Pivot, ParentKey, RelatedKey, keyof Pivot & string, keyof Pivot & string>);
|
|
87
98
|
where(where: QueryWhere<TRelated>): this;
|
|
88
99
|
orderBy(orderBy: QueryOptions<TRelated>["orderBy"]): this;
|
|
89
|
-
applyEagerLoad(
|
|
100
|
+
applyEagerLoad(query: RepositoryQuery<TParent, ParentKey>, alias: string): void;
|
|
101
|
+
withPivotValues(values: Record<string, unknown>): this;
|
|
90
102
|
hydrateEager(row: Record<string, unknown>, alias: string): unknown;
|
|
91
103
|
toExistsClause(parentTable: string): ExistsClause;
|
|
92
104
|
private connection;
|
|
93
105
|
get(): Promise<RelatedRecord[]>;
|
|
94
106
|
first(): Promise<RelatedRecord | null>;
|
|
95
107
|
count(): Promise<number>;
|
|
108
|
+
then(onfulfilled?: ((value: RelatedRecord[]) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
96
109
|
attach(ids: unknown | readonly unknown[]): Promise<void>;
|
|
110
|
+
toggle(ids: unknown | readonly unknown[]): Promise<void>;
|
|
97
111
|
detach(ids?: unknown | readonly unknown[]): Promise<void>;
|
|
98
112
|
sync(ids: readonly unknown[]): Promise<void>;
|
|
99
113
|
create(attributes?: Record<string, unknown>): Promise<RelatedRecord>;
|
|
@@ -112,6 +126,8 @@ declare class MorphManyRelationQuery<TParent extends object, ParentKey extends k
|
|
|
112
126
|
toExistsClause(parentTable: string): ExistsClause;
|
|
113
127
|
get(): Promise<RelatedRecord[]>;
|
|
114
128
|
first(): Promise<RelatedRecord | null>;
|
|
129
|
+
count(): Promise<number>;
|
|
130
|
+
then(onfulfilled?: ((value: RelatedRecord[]) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
115
131
|
create(attributes?: Record<string, unknown>): Promise<RelatedRecord>;
|
|
116
132
|
}
|
|
117
133
|
declare class MorphOneRelationQuery<TParent extends object, ParentKey extends keyof TParent & string, TChild extends object, ChildKey extends keyof TChild & string> {
|
|
@@ -124,6 +140,9 @@ declare class MorphOneRelationQuery<TParent extends object, ParentKey extends ke
|
|
|
124
140
|
hydrateEager(row: Record<string, unknown>, alias: string): unknown;
|
|
125
141
|
toExistsClause(parentTable: string): ExistsClause;
|
|
126
142
|
get(): Promise<RelatedRecord | null>;
|
|
143
|
+
first(): Promise<RelatedRecord | null>;
|
|
144
|
+
count(): Promise<number>;
|
|
145
|
+
then(onfulfilled?: ((value: RelatedRecord | null) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
127
146
|
create(attributes?: Record<string, unknown>): Promise<RelatedRecord>;
|
|
128
147
|
}
|
|
129
148
|
declare class MorphToRelationQuery<TChild extends object, ChildKey extends keyof TChild & string> {
|
|
@@ -131,11 +150,14 @@ declare class MorphToRelationQuery<TChild extends object, ChildKey extends keyof
|
|
|
131
150
|
private readonly relatedByType;
|
|
132
151
|
readonly relation: MorphToRelation<TChild, keyof TChild & string, keyof TChild & string>;
|
|
133
152
|
readonly kind: RelationKind;
|
|
153
|
+
private extraWhere;
|
|
134
154
|
constructor(parent: RelationHost<TChild, ChildKey>, relatedByType: Record<string, RelatedModelClass<Record<string, unknown>, "id">>, relation: MorphToRelation<TChild, keyof TChild & string, keyof TChild & string>);
|
|
155
|
+
where(where: QueryWhere<Record<string, unknown>>): this;
|
|
135
156
|
applyEagerLoad(query: RepositoryQuery<TChild, ChildKey>, alias: string): void;
|
|
136
157
|
hydrateEager(row: Record<string, unknown>, alias: string): unknown;
|
|
137
158
|
toExistsClause(parentTable: string): ExistsClause;
|
|
138
159
|
get(): Promise<RelatedRecord | null>;
|
|
160
|
+
then(onfulfilled?: ((value: RelatedRecord | null) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null): Promise<unknown>;
|
|
139
161
|
}
|
|
140
162
|
type AnyRelationQuery = {
|
|
141
163
|
kind: RelationKind;
|
|
@@ -144,6 +166,7 @@ type AnyRelationQuery = {
|
|
|
144
166
|
get(): Promise<unknown>;
|
|
145
167
|
toExistsClause(parentTable: string): ExistsClause;
|
|
146
168
|
where?(where: Record<string, unknown>): unknown;
|
|
169
|
+
then?: (onfulfilled?: ((value: unknown) => unknown) | null, onrejected?: ((reason: unknown) => unknown) | null) => Promise<unknown>;
|
|
147
170
|
};
|
|
148
171
|
export type { AnyRelationQuery, RelatedModelClass, RelatedRecord, RelationHost };
|
|
149
172
|
export { BelongsToManyRelationQuery, BelongsToRelationQuery, HasManyRelationQuery, HasOneRelationQuery, MorphManyRelationQuery, MorphOneRelationQuery, MorphToRelationQuery, };
|
|
@@ -48,6 +48,8 @@ declare function belongsToMany<TParent, TRelated, Pivot extends object, ParentKe
|
|
|
48
48
|
foreignPivotKey: ForeignPivotKey;
|
|
49
49
|
relatedPivotKey: RelatedPivotKey;
|
|
50
50
|
}): BelongsToManyRelation<TParent, TRelated, Pivot, ParentKey, RelatedKey, ForeignPivotKey, RelatedPivotKey>;
|
|
51
|
+
declare function relationMatchKey(value: unknown): string;
|
|
52
|
+
declare function getByRelationKey<K, V>(map: ReadonlyMap<K, V>, key: unknown): V | undefined;
|
|
51
53
|
declare function indexHasManyRelation<TParent, TChild, LocalKey extends keyof TParent & string, ForeignKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: HasManyRelation<TParent, TChild, LocalKey, ForeignKey>): Map<TParent[LocalKey], TChild[]>;
|
|
52
54
|
declare function indexHasOneRelation<TParent, TChild, LocalKey extends keyof TParent & string, ForeignKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: HasOneRelation<TParent, TChild, LocalKey, ForeignKey>): Map<TParent[LocalKey], TChild | undefined>;
|
|
53
55
|
declare function indexBelongsToRelation<TChild, TParent, ForeignKey extends keyof TChild & string, OwnerKey extends keyof TParent & string>(children: readonly TChild[], parents: readonly TParent[], relation: BelongsToRelation<TChild, TParent, ForeignKey, OwnerKey>): Map<TChild[ForeignKey], TParent>;
|
|
@@ -95,6 +97,6 @@ declare function morphTo<TChild, MorphTypeKey extends keyof TChild & string = ke
|
|
|
95
97
|
}): MorphToRelation<TChild, MorphTypeKey, MorphIdKey>;
|
|
96
98
|
declare function indexMorphManyRelation<TParent, TChild, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: MorphManyRelation<TParent, TChild, LocalKey, MorphTypeKey, MorphIdKey>): Map<TParent[LocalKey], TChild[]>;
|
|
97
99
|
declare function indexMorphOneRelation<TParent, TChild, LocalKey extends keyof TParent & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: MorphOneRelation<TParent, TChild, LocalKey, MorphTypeKey, MorphIdKey>): Map<TParent[LocalKey], TChild | undefined>;
|
|
98
|
-
declare function indexMorphToRelation<TChild, TParent extends object, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string,
|
|
100
|
+
declare function indexMorphToRelation<TChild, TParent extends object, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string, _OwnerKey extends keyof TParent & string = keyof TParent & string>(children: readonly TChild[], parentsByType: ReadonlyMap<string, ReadonlyMap<unknown, TParent>>, relation: MorphToRelation<TChild, MorphTypeKey, MorphIdKey>): Map<TChild[MorphIdKey], TParent>;
|
|
99
101
|
export type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasOneRelation, MorphManyRelation, MorphOneRelation, MorphToRelation, };
|
|
100
|
-
export { belongsTo, belongsToMany, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, };
|
|
102
|
+
export { belongsTo, belongsToMany, getByRelationKey, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, indexMorphManyRelation, indexMorphOneRelation, indexMorphToRelation, morphMany, morphOne, morphTo, relationMatchKey, };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PaginatedResult } from "../pagination/index.ts";
|
|
2
2
|
import type BaseRepository from "./baseRepository.ts";
|
|
3
|
-
import type { BelongsToRelation, HasManyRelation, MorphManyRelation, MorphOneRelation, MorphToRelation } from "./relationships.ts";
|
|
3
|
+
import type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, MorphManyRelation, MorphOneRelation, MorphToRelation } from "./relationships.ts";
|
|
4
4
|
import type { QueryOptions, QueryWhere } from "./types.ts";
|
|
5
5
|
import { WhereBuilder } from "./whereBuilder.ts";
|
|
6
6
|
type LoadedRow = Record<string, unknown>;
|
|
@@ -30,8 +30,11 @@ declare class RepositoryQuery<TEntity extends object, PrimaryKey extends keyof T
|
|
|
30
30
|
withMorphMany<TChild extends object, LocalKey extends keyof TEntity & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string, Alias extends string>(as: Alias, relation: MorphManyRelation<TEntity, TChild, LocalKey, MorphTypeKey, MorphIdKey>, childRepository: BaseRepository<TChild, keyof TChild & string>, options?: Omit<QueryOptions<TChild>, "where">): this;
|
|
31
31
|
withMorphOne<TChild extends object, LocalKey extends keyof TEntity & string, MorphTypeKey extends keyof TChild & string, MorphIdKey extends keyof TChild & string, Alias extends string>(as: Alias, relation: MorphOneRelation<TEntity, TChild, LocalKey, MorphTypeKey, MorphIdKey>, childRepository: BaseRepository<TChild, keyof TChild & string>, options?: Omit<QueryOptions<TChild>, "where">): this;
|
|
32
32
|
withMorphTo<TParent extends object, MorphTypeKey extends keyof TEntity & string, MorphIdKey extends keyof TEntity & string, Alias extends string>(as: Alias, relation: MorphToRelation<TEntity, MorphTypeKey, MorphIdKey>, repositoriesByType: ReadonlyMap<string, BaseRepository<TParent, keyof TParent & string>>, options?: Omit<QueryOptions<TParent>, "where">): this;
|
|
33
|
+
withBelongsToMany<TRelated extends object, Pivot extends object, ParentKey extends keyof TEntity & string, RelatedKey extends keyof TRelated & string, ForeignPivotKey extends keyof Pivot & string, RelatedPivotKey extends keyof Pivot & string, Alias extends string>(as: Alias, relation: BelongsToManyRelation<TEntity, TRelated, Pivot, ParentKey, RelatedKey, ForeignPivotKey, RelatedPivotKey>, relatedRepository: BaseRepository<TRelated, RelatedKey>, options?: Omit<QueryOptions<TRelated>, "where">): this;
|
|
33
34
|
get(): Promise<Array<TEntity & LoadedRow>>;
|
|
34
35
|
first(): Promise<(TEntity & LoadedRow) | null>;
|
|
36
|
+
count(): Promise<number>;
|
|
37
|
+
attachToRows(rows: readonly TEntity[]): Promise<Array<TEntity & LoadedRow>>;
|
|
35
38
|
paginate(options: {
|
|
36
39
|
page: number;
|
|
37
40
|
perPage: number;
|
|
@@ -5,7 +5,7 @@ declare function whenLoaded<T>(model: {
|
|
|
5
5
|
declare class JsonResource<T = unknown> {
|
|
6
6
|
protected readonly resource: T;
|
|
7
7
|
static wrap: string | null;
|
|
8
|
-
|
|
8
|
+
protected extra: Record<string, unknown>;
|
|
9
9
|
constructor(resource: T);
|
|
10
10
|
static make<TResource>(resource: TResource): JsonResource<TResource>;
|
|
11
11
|
static collection<TResource>(items: readonly TResource[]): ResourceCollection<TResource>;
|
|
@@ -17,6 +17,7 @@ declare class JsonResource<T = unknown> {
|
|
|
17
17
|
}
|
|
18
18
|
declare class ResourceCollection<T> extends JsonResource<readonly T[]> {
|
|
19
19
|
toArray(): Record<string, unknown>;
|
|
20
|
+
toResponse(): Record<string, unknown>;
|
|
20
21
|
}
|
|
21
22
|
declare function toResourceCollection<TInput, TOutput>(items: readonly TInput[], transformer: (item: TInput) => TOutput): TOutput[];
|
|
22
23
|
declare function toPaginatedResourceCollection<TInput, TOutput, TMeta extends object>(items: readonly TInput[], meta: TMeta, transformer: (item: TInput) => TOutput): {
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// ../../src/core/database/inflection.ts
|
|
3
|
+
function singularize(word) {
|
|
4
|
+
if (word.endsWith("ies") && word.length > 3) {
|
|
5
|
+
return `${word.slice(0, -3)}y`;
|
|
6
|
+
}
|
|
7
|
+
if (/(ses|xes|zes|ches|shes)$/i.test(word)) {
|
|
8
|
+
return word.slice(0, -2);
|
|
9
|
+
}
|
|
10
|
+
if (word.endsWith("s") && !word.endsWith("ss")) {
|
|
11
|
+
return word.slice(0, -1);
|
|
12
|
+
}
|
|
13
|
+
return word;
|
|
14
|
+
}
|
|
15
|
+
function foreignKeyFromTable(tableName) {
|
|
16
|
+
return `${singularize(tableName)}_id`;
|
|
17
|
+
}
|
|
18
|
+
function pivotTableName(leftTable, rightTable) {
|
|
19
|
+
return [singularize(leftTable), singularize(rightTable)].sort().join("_");
|
|
20
|
+
}
|
|
21
|
+
|
|
2
22
|
// ../../src/core/database/factory.ts
|
|
23
|
+
function inferFactoryForeignKey(parent, explicit) {
|
|
24
|
+
if (explicit) {
|
|
25
|
+
if (explicit.endsWith("_id")) {
|
|
26
|
+
return explicit;
|
|
27
|
+
}
|
|
28
|
+
return `${explicit}_id`;
|
|
29
|
+
}
|
|
30
|
+
if (typeof parent.getRepository === "function") {
|
|
31
|
+
return foreignKeyFromTable(parent.getRepository().getTable().name);
|
|
32
|
+
}
|
|
33
|
+
throw new Error("Factory.for() requires a foreign key or a parent Model.");
|
|
34
|
+
}
|
|
35
|
+
|
|
3
36
|
class Factory {
|
|
4
37
|
quantity = 1;
|
|
5
38
|
counted = false;
|
|
@@ -10,6 +43,7 @@ class Factory {
|
|
|
10
43
|
children = [];
|
|
11
44
|
afterMakingCallbacks = [];
|
|
12
45
|
afterCreatingCallbacks = [];
|
|
46
|
+
model;
|
|
13
47
|
definition() {
|
|
14
48
|
throw new Error("Factory definition must be implemented by subclass.");
|
|
15
49
|
}
|
|
@@ -50,8 +84,9 @@ class Factory {
|
|
|
50
84
|
if (parent.id === undefined || parent.id === null) {
|
|
51
85
|
throw new Error("Factory.for() requires a parent with an id.");
|
|
52
86
|
}
|
|
87
|
+
const key = inferFactoryForeignKey(parent, foreignKey);
|
|
53
88
|
const next = this.clone();
|
|
54
|
-
next.parentAssociations = [...this.parentAssociations, { foreignKey, value: parent.id }];
|
|
89
|
+
next.parentAssociations = [...this.parentAssociations, { foreignKey: key, value: parent.id }];
|
|
55
90
|
return next;
|
|
56
91
|
}
|
|
57
92
|
recycle(parent, foreignKey) {
|
|
@@ -132,7 +167,14 @@ class Factory {
|
|
|
132
167
|
}
|
|
133
168
|
return values;
|
|
134
169
|
}
|
|
135
|
-
persist(
|
|
170
|
+
async persist(values) {
|
|
171
|
+
if (this.model) {
|
|
172
|
+
const created = await this.model.create(values);
|
|
173
|
+
if (created && typeof created.toObject === "function") {
|
|
174
|
+
return created.toObject();
|
|
175
|
+
}
|
|
176
|
+
return created;
|
|
177
|
+
}
|
|
136
178
|
throw new Error("Factory.persist() must be implemented to use create().");
|
|
137
179
|
}
|
|
138
180
|
}
|