added new em() shorthand for prototyping, added insertMany mutator function for seeding

This commit is contained in:
dswbx
2024-12-19 07:38:40 +01:00
parent 602235b372
commit 386c0d3ff0
6 changed files with 145 additions and 17 deletions

View File

@@ -0,0 +1,7 @@
import { Connection } from "./Connection";
export class DummyConnection extends Connection {
constructor() {
super(undefined as any);
}
}

View File

@@ -276,4 +276,39 @@ export class Mutator<DB = any, TB extends keyof DB = any, Data = Omit<DB[TB], "i
return (await this.many(query)) as any;
}
async insertMany(data: Data[]): Promise<MutatorResponse<DB[TB][]>> {
const entity = this.entity;
if (entity.type === "system" && this.__unstable_disable_system_entity_creation) {
throw new Error(`Creation of system entity "${entity.name}" is disabled`);
}
const validated: any[] = [];
for (const row of data) {
const validatedData = {
...entity.getDefaultObject(),
...(await this.getValidatedData(row, "create"))
};
// check if required fields are present
const required = entity.getRequiredFields();
for (const field of required) {
if (
typeof validatedData[field.name] === "undefined" ||
validatedData[field.name] === null
) {
throw new Error(`Field "${field.name}" is required`);
}
}
validated.push(validatedData);
}
const query = this.conn
.insertInto(entity.name)
.values(validated)
.returning(entity.getSelect());
return (await this.many(query)) as any;
}
}

View File

@@ -1,3 +1,5 @@
import { DummyConnection } from "data/connection/DummyConnection";
import { EntityManager } from "data/entities/EntityManager";
import type { Generated } from "kysely";
import { MediaField, type MediaFieldConfig, type MediaItem } from "media/MediaField";
import {
@@ -7,6 +9,7 @@ import {
type DateFieldConfig,
Entity,
type EntityConfig,
type EntityRelation,
EnumField,
type EnumFieldConfig,
type Field,
@@ -240,6 +243,57 @@ export function relation<Local extends Entity>(local: Local) {
};
}
class EntityManagerPrototype<Entities extends Record<string, Entity>> extends EntityManager<
Schema<Entities>
> {
constructor(
public __entities: Entities,
relations: EntityRelation[]
) {
super(Object.values(__entities), new DummyConnection(), relations);
}
}
export function em<Entities extends Record<string, Entity>>(
entities: Entities,
schema?: (rel: typeof relation, entities: Entities) => void
) {
const relations: EntityRelation[] = [];
const relationProxy = (local: Entity) => {
return new Proxy(relation(local), {
get(target, prop) {
if (typeof target[prop] === "function") {
return (...args: any[]) => {
const result = target[prop](...args);
relations.push(result);
return result;
};
}
return target[prop];
}
});
};
if (schema) {
schema(relationProxy, entities);
}
const e = new EntityManagerPrototype(entities, relations);
return {
DB: e.__entities as unknown as Schemas<Entities>,
entities: e.__entities,
relations,
indices: [],
toJSON: () => {
return e.toJSON() as unknown as {
entities: Schemas<Entities>;
relations: EntityRelation[];
indices: any[];
};
}
};
}
export type InferEntityFields<T> = T extends Entity<infer _N, infer Fields>
? {
[K in keyof Fields]: Fields[K] extends { _type: infer Type; _required: infer Required }
@@ -291,18 +345,9 @@ export type InferField<Field> = Field extends { _type: infer Type; _required: in
: Type | undefined
: never;
const n = number();
type T2 = InferField<typeof n>;
const users = entity("users", {
name: text(),
email: text(),
created_at: datetime(),
updated_at: datetime()
});
type TUsersFields = InferEntityFields<typeof users>;
type TUsers = Schema<typeof users>;
type TUsers2 = Simplify<OptionalUndefined<Schema<typeof users>>>;
export type Schemas<T extends Record<string, Entity>> = {
[K in keyof T]: Schema<T[K]>;
};
export type InsertSchema<T> = Simplify<OptionalUndefined<InferEntityFields<T>>>;
export type Schema<T> = Simplify<{ id: Generated<number> } & InsertSchema<T>>;