Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b46ece276e | ||
|
|
f5ba3146d7 |
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import { Entity } from "data/entities";
|
import { Entity } from "data/entities";
|
||||||
import { NumberField, TextField, PrimaryField } from "data/fields";
|
import { NumberField, TextField } from "data/fields";
|
||||||
|
|
||||||
describe("[data] Entity", async () => {
|
describe("[data] Entity", async () => {
|
||||||
const entity = new Entity("test", [
|
const entity = new Entity("test", [
|
||||||
@@ -47,16 +47,4 @@ describe("[data] Entity", async () => {
|
|||||||
entity.addField(field);
|
entity.addField(field);
|
||||||
expect(entity.getField("new_field")).toBe(field);
|
expect(entity.getField("new_field")).toBe(field);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("custom primary", async () => {
|
|
||||||
const customPrimaryEntity = new Entity("custom", [
|
|
||||||
new PrimaryField("custom", { format: "uuid" }),
|
|
||||||
new TextField("name"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(customPrimaryEntity.getPrimaryField().name).toEqual("custom");
|
|
||||||
expect(customPrimaryEntity.getPrimaryField().format).toEqual("uuid");
|
|
||||||
expect(customPrimaryEntity.getSelect()).toEqual(["custom", "name"]);
|
|
||||||
expect(customPrimaryEntity.getField("id")).toBeUndefined(); // no auto id
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Entity, EntityManager } from "data/entities";
|
|||||||
import {
|
import {
|
||||||
ManyToOneRelation,
|
ManyToOneRelation,
|
||||||
OneToOneRelation,
|
OneToOneRelation,
|
||||||
RelationField,
|
type RelationField,
|
||||||
RelationMutator,
|
RelationMutator,
|
||||||
} from "data/relations";
|
} from "data/relations";
|
||||||
import { NumberField, TextField } from "data/fields";
|
import { NumberField, TextField } from "data/fields";
|
||||||
@@ -41,6 +41,24 @@ describe("[data] Mutator (base)", async () => {
|
|||||||
|
|
||||||
// but expect additional fields to be present
|
// but expect additional fields to be present
|
||||||
expect((res.data as any).not_fillable).toBeDefined();
|
expect((res.data as any).not_fillable).toBeDefined();
|
||||||
|
expect((res.data as any).id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("insertMany", async () => {
|
||||||
|
expect(em.mutator(entity).getValidatedData(payload, "create")).resolves.toEqual(payload);
|
||||||
|
const res = await em.mutator(entity).insertMany([
|
||||||
|
{ label: "item 1", count: 1 },
|
||||||
|
{ label: "item 2", count: 2 },
|
||||||
|
{ label: "item 3", count: 3 },
|
||||||
|
{ label: "item 4", count: 4 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(res.data.length).toBe(4);
|
||||||
|
res.data.forEach((entry) => {
|
||||||
|
expect((entry as any).id).toBeDefined();
|
||||||
|
expect((entry as any).label).toStartWith("item ");
|
||||||
|
expect(entry.count).toBeNumber();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("updateOne", async () => {
|
test("updateOne", async () => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
|
|||||||
import { PrimaryField } from "data/fields";
|
import { PrimaryField } from "data/fields";
|
||||||
|
|
||||||
describe("[data] PrimaryField", async () => {
|
describe("[data] PrimaryField", async () => {
|
||||||
const field = new PrimaryField("primary", { fillable: false });
|
const field = new PrimaryField("primary");
|
||||||
|
|
||||||
test("name", async () => {
|
test("name", async () => {
|
||||||
expect(field.name).toBe("primary");
|
expect(field.name).toBe("primary");
|
||||||
@@ -64,23 +64,3 @@ describe("[data] PrimaryField", async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe("[data] PrimaryField (fillable)", async () => {
|
|
||||||
const field = new PrimaryField("primary", { fillable: true });
|
|
||||||
|
|
||||||
test("isFillable", async () => {
|
|
||||||
expect(field.isFillable()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("transformPersist/Retrieve", async () => {
|
|
||||||
expect(field.transformPersist(null)).resolves.toBeUndefined();
|
|
||||||
expect(field.transformRetrieve(1)).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("format", () => {
|
|
||||||
const uuid = new PrimaryField("integer", { format: "uuid" });
|
|
||||||
expect(uuid.transformPersist(null)).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const entityConfigSchema = s
|
|||||||
name: s.string(),
|
name: s.string(),
|
||||||
name_singular: s.string(),
|
name_singular: s.string(),
|
||||||
description: s.string(),
|
description: s.string(),
|
||||||
sort_field: s.string(),
|
sort_field: s.string({ default: config.data.default_primary_field }),
|
||||||
sort_dir: s.string({ enum: ["asc", "desc"], default: "asc" }),
|
sort_dir: s.string({ enum: ["asc", "desc"], default: "asc" }),
|
||||||
primary_format: s.string({ enum: primaryFieldTypes }),
|
primary_format: s.string({ enum: primaryFieldTypes }),
|
||||||
},
|
},
|
||||||
@@ -82,10 +82,6 @@ export class Entity<
|
|||||||
fields.forEach((field) => this.addField(field));
|
fields.forEach((field) => this.addField(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.config.sort_field) {
|
|
||||||
this.config.sort_field = this.getPrimaryField().name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type) this.type = type;
|
if (type) this.type = type;
|
||||||
this[ENTITY_SYMBOL] = true;
|
this[ENTITY_SYMBOL] = true;
|
||||||
}
|
}
|
||||||
@@ -119,7 +115,7 @@ export class Entity<
|
|||||||
|
|
||||||
getDefaultSort() {
|
getDefaultSort() {
|
||||||
return {
|
return {
|
||||||
by: this.config.sort_field ?? this.getPrimaryField().name,
|
by: this.config.sort_field ?? "id",
|
||||||
dir: this.config.sort_dir ?? "asc",
|
dir: this.config.sort_dir ?? "asc",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -171,7 +167,7 @@ export class Entity<
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPrimaryField(): PrimaryField {
|
getPrimaryField(): PrimaryField {
|
||||||
return this.fields.find((field) => field.type === "primary") as PrimaryField;
|
return this.fields[0] as PrimaryField;
|
||||||
}
|
}
|
||||||
|
|
||||||
id(): PrimaryField {
|
id(): PrimaryField {
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ export class Mutator<
|
|||||||
|
|
||||||
const validated: any[] = [];
|
const validated: any[] = [];
|
||||||
for (const row of data) {
|
for (const row of data) {
|
||||||
const validatedData = {
|
let validatedData = {
|
||||||
...entity.getDefaultObject(),
|
...entity.getDefaultObject(),
|
||||||
...(await this.getValidatedData(row, "create")),
|
...(await this.getValidatedData(row, "create")),
|
||||||
};
|
};
|
||||||
@@ -328,6 +328,16 @@ export class Mutator<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// primary
|
||||||
|
const primary = entity.getPrimaryField();
|
||||||
|
const primary_value = primary.getNewValue();
|
||||||
|
if (primary_value) {
|
||||||
|
validatedData = {
|
||||||
|
[primary.name]: primary_value,
|
||||||
|
...validatedData,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
validated.push(validatedData);
|
validated.push(validatedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,7 @@ export class PrimaryField<Required extends true | false = false> extends Field<
|
|||||||
override readonly type = "primary";
|
override readonly type = "primary";
|
||||||
|
|
||||||
constructor(name: string = config.data.default_primary_field, cfg?: PrimaryFieldConfig) {
|
constructor(name: string = config.data.default_primary_field, cfg?: PrimaryFieldConfig) {
|
||||||
super(name, {
|
super(name, { ...cfg, fillable: false, required: false });
|
||||||
...cfg,
|
|
||||||
fillable: cfg?.fillable ?? name !== config.data.default_primary_field,
|
|
||||||
required: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override isRequired(): boolean {
|
override isRequired(): boolean {
|
||||||
@@ -64,13 +60,7 @@ export class PrimaryField<Required extends true | false = false> extends Field<
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
override async transformPersist(value: any): Promise<any> {
|
override async transformPersist(value: any): Promise<number> {
|
||||||
if (this.isFillable()) {
|
|
||||||
if (value == null) {
|
|
||||||
return this.getNewValue();
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
throw new Error("PrimaryField: This function should not be called");
|
throw new Error("PrimaryField: This function should not be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import {
|
|||||||
type NumberFieldConfig,
|
type NumberFieldConfig,
|
||||||
TextField,
|
TextField,
|
||||||
type TextFieldConfig,
|
type TextFieldConfig,
|
||||||
PrimaryField,
|
|
||||||
type PrimaryFieldConfig,
|
|
||||||
} from "data/fields";
|
} from "data/fields";
|
||||||
|
|
||||||
import { Entity, type EntityConfig, type TEntityType } from "data/entities";
|
import { Entity, type EntityConfig, type TEntityType } from "data/entities";
|
||||||
@@ -53,8 +51,6 @@ type Options<Config = any> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FieldMap = {
|
const FieldMap = {
|
||||||
primary: (o: Omit<Options, "required">) =>
|
|
||||||
new PrimaryField(o.field_name, { ...o.config, required: true }),
|
|
||||||
text: (o: Options) => new TextField(o.field_name, { ...o.config, required: o.is_required }),
|
text: (o: Options) => new TextField(o.field_name, { ...o.config, required: o.is_required }),
|
||||||
number: (o: Options) => new NumberField(o.field_name, { ...o.config, required: o.is_required }),
|
number: (o: Options) => new NumberField(o.field_name, { ...o.config, required: o.is_required }),
|
||||||
date: (o: Options) => new DateField(o.field_name, { ...o.config, required: o.is_required }),
|
date: (o: Options) => new DateField(o.field_name, { ...o.config, required: o.is_required }),
|
||||||
@@ -112,11 +108,6 @@ export class FieldPrototype {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function primary(
|
|
||||||
config?: Omit<PrimaryFieldConfig, "required">,
|
|
||||||
): PrimaryField<false> & { required: () => PrimaryField<true> } {
|
|
||||||
return new FieldPrototype("primary", config, false) as any;
|
|
||||||
}
|
|
||||||
export function text(
|
export function text(
|
||||||
config?: Omit<TextFieldConfig, "required">,
|
config?: Omit<TextFieldConfig, "required">,
|
||||||
): TextField<false> & { required: () => TextField<true> } {
|
): TextField<false> & { required: () => TextField<true> } {
|
||||||
@@ -419,5 +410,5 @@ export type Schemas<T extends Record<string, Entity>> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type InsertSchema<T> = Simplify<OptionalUndefined<InferEntityFields<T>>>;
|
export type InsertSchema<T> = Simplify<OptionalUndefined<InferEntityFields<T>>>;
|
||||||
export type Schema<T> = Simplify<{ id: Generated<number> | string } & InsertSchema<T>>;
|
export type Schema<T> = Simplify<{ id: Generated<number> } & InsertSchema<T>>;
|
||||||
export type FieldSchema<T> = Simplify<OptionalUndefined<InferFields<T>>>;
|
export type FieldSchema<T> = Simplify<OptionalUndefined<InferFields<T>>>;
|
||||||
|
|||||||
@@ -173,7 +173,6 @@ export {
|
|||||||
|
|
||||||
// data prototype
|
// data prototype
|
||||||
export {
|
export {
|
||||||
primary,
|
|
||||||
text,
|
text,
|
||||||
number,
|
number,
|
||||||
date,
|
date,
|
||||||
|
|||||||
Reference in New Issue
Block a user