Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add accessors to enum details. #372

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions packages/codegen/src/generateEntityCodegenFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,17 @@ export function generateEntityCodegenFile(config: Config, meta: EntityDbMetadata
.forEach((e) => {
const { fieldName, enumType, enumDetailType, enumDetailsType, notNull, enumRows } = e;
const maybeOptional = notNull ? "" : " | undefined";
const getByCode = code`${enumDetailType}.getByCode(this.${fieldName})`;
// We avoid using `|| fail()` because during em.create, setOpts calls all getters, and
// expects them to return `undefined` if the field is not set.
const maybeBang = notNull ? code`!` : "";
const getter = code`
get ${fieldName}(): ${enumType}${maybeOptional} {
return this.__orm.data["${fieldName}"];
}

get ${fieldName}Details(): ${enumDetailsType}${maybeOptional} {
return ${notNull ? getByCode : code`this.${fieldName} ? ${getByCode} : undefined`};
get ${fieldName}(): ${enumDetailsType}${maybeOptional} {
return ${enumDetailType}.findByCode(this.__orm.data["${fieldName}"])${maybeBang};
}
`;
const setter = code`
set ${fieldName}(${fieldName}: ${enumType}${maybeOptional}) {
${setField}(this, "${fieldName}", ${fieldName});
set ${fieldName}(${fieldName}: ${enumDetailsType}${maybeOptional}) {
${setField}(this, "${fieldName}", ${fieldName}?.code);
}
`;

Expand Down
27 changes: 25 additions & 2 deletions packages/codegen/src/generateEnumFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EnumTableData } from "./index";

export function generateEnumFile(config: Config, enumData: EnumTableData, enumName: string): Code {
const { rows, extraPrimitives } = enumData;

const detailsName = `${enumName}Details`;
const detailsDefinition = [
"id: number;",
Expand All @@ -22,13 +23,17 @@ export function generateEnumFile(config: Config, enumData: EnumTableData, enumNa
}
return `${primitive.fieldName}: ${primitive.fieldType};`;
}),
// Add `isApproved` / etc. accessors
...rows.map((row) => `is${pascalCase(row.code)}: boolean;`),
].join(" ");
return code`
export enum ${enumName} {
${rows.map((row) => `${pascalCase(row.code)} = '${row.code}'`).join(",\n")}
}

export type ${detailsName} = {${detailsDefinition}};
export type ${detailsName} = {
${detailsDefinition}
};

const details: Record<${enumName}, ${detailsName}> = {
${rows
Expand All @@ -38,12 +43,30 @@ export function generateEnumFile(config: Config, enumData: EnumTableData, enumNa
const extras = extraPrimitives
.map((p) => `${p.fieldName}: ${JSON.stringify((row as any)[p.columnName])}`)
.join(", ");
return `[${enumName}.${code}]: { id: ${row.id}, code: ${enumName}.${code}, name: '${safeName}', ${extras} }`;
const accessors = rows
.map((otherRow) => {
return `is${pascalCase(otherRow.code)}: ${row === otherRow}`;
})
.join(", ");
return `[${enumName}.${code}]: {
id: ${row.id},
code: ${enumName}.${code},
name: '${safeName}',
${accessors},
${extras}
}`;
})
.join(",")}
};

export const ${pluralize(enumName)} = {
${rows
.map((row) => {
const code = pascalCase(row.code);
return `${code}: details[${enumName}.${code}],`;
})
.join("\n")}

getByCode(code: ${enumName}): ${detailsName} {
return details[code];
},
Expand Down
40 changes: 36 additions & 4 deletions packages/integration-tests/src/entities/AdvanceStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,47 @@ export enum AdvanceStatus {
Paid = "PAID",
}

export type AdvanceStatusDetails = { id: number; code: AdvanceStatus; name: string };
export type AdvanceStatusDetails = {
id: number;
code: AdvanceStatus;
name: string;
isPending: boolean;
isSigned: boolean;
isPaid: boolean;
};

const details: Record<AdvanceStatus, AdvanceStatusDetails> = {
[AdvanceStatus.Pending]: { id: 1, code: AdvanceStatus.Pending, name: "Pending" },
[AdvanceStatus.Signed]: { id: 2, code: AdvanceStatus.Signed, name: "Signed" },
[AdvanceStatus.Paid]: { id: 3, code: AdvanceStatus.Paid, name: "Paid" },
[AdvanceStatus.Pending]: {
id: 1,
code: AdvanceStatus.Pending,
name: "Pending",
isPending: true,
isSigned: false,
isPaid: false,
},
[AdvanceStatus.Signed]: {
id: 2,
code: AdvanceStatus.Signed,
name: "Signed",
isPending: false,
isSigned: true,
isPaid: false,
},
[AdvanceStatus.Paid]: {
id: 3,
code: AdvanceStatus.Paid,
name: "Paid",
isPending: false,
isSigned: false,
isPaid: true,
},
};

export const AdvanceStatuses = {
Pending: details[AdvanceStatus.Pending],
Signed: details[AdvanceStatus.Signed],
Paid: details[AdvanceStatus.Paid],

getByCode(code: AdvanceStatus): AdvanceStatusDetails {
return details[code];
},
Expand Down
12 changes: 4 additions & 8 deletions packages/integration-tests/src/entities/BookAdvanceCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,12 @@ export abstract class BookAdvanceCodegen extends BaseEntity<EntityManager> {
return this.__orm.data["updatedAt"];
}

get status(): AdvanceStatus {
return this.__orm.data["status"];
get status(): AdvanceStatusDetails {
return AdvanceStatuses.findByCode(this.__orm.data["status"])!;
}

get statusDetails(): AdvanceStatusDetails {
return AdvanceStatuses.getByCode(this.status);
}

set status(status: AdvanceStatus) {
setField(this, "status", status);
set status(status: AdvanceStatusDetails) {
setField(this, "status", status?.code);
}

get isPending(): boolean {
Expand Down
40 changes: 36 additions & 4 deletions packages/integration-tests/src/entities/Color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,47 @@ export enum Color {
Blue = "BLUE",
}

export type ColorDetails = { id: number; code: Color; name: string };
export type ColorDetails = {
id: number;
code: Color;
name: string;
isRed: boolean;
isGreen: boolean;
isBlue: boolean;
};

const details: Record<Color, ColorDetails> = {
[Color.Red]: { id: 1, code: Color.Red, name: "Red" },
[Color.Green]: { id: 2, code: Color.Green, name: "Green" },
[Color.Blue]: { id: 3, code: Color.Blue, name: "Blue" },
[Color.Red]: {
id: 1,
code: Color.Red,
name: "Red",
isRed: true,
isGreen: false,
isBlue: false,
},
[Color.Green]: {
id: 2,
code: Color.Green,
name: "Green",
isRed: false,
isGreen: true,
isBlue: false,
},
[Color.Blue]: {
id: 3,
code: Color.Blue,
name: "Blue",
isRed: false,
isGreen: false,
isBlue: true,
},
};

export const Colors = {
Red: details[Color.Red],
Green: details[Color.Green],
Blue: details[Color.Blue],

getByCode(code: Color): ColorDetails {
return details[code];
},
Expand Down
2 changes: 1 addition & 1 deletion packages/integration-tests/src/entities/Image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class Image extends ImageCodegen {
[ImageType.AuthorImage]: this.author,
[ImageType.BookImage]: this.book,
[ImageType.PublisherImage]: this.publisher,
}[this.type];
}[this.type.code];
}
}

Expand Down
12 changes: 4 additions & 8 deletions packages/integration-tests/src/entities/ImageCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,12 @@ export abstract class ImageCodegen extends BaseEntity<EntityManager> {
return this.__orm.data["updatedAt"];
}

get type(): ImageType {
return this.__orm.data["type"];
get type(): ImageTypeDetails {
return ImageTypes.findByCode(this.__orm.data["type"])!;
}

get typeDetails(): ImageTypeDetails {
return ImageTypes.getByCode(this.type);
}

set type(type: ImageType) {
setField(this, "type", type);
set type(type: ImageTypeDetails) {
setField(this, "type", type?.code);
}

get isBookImage(): boolean {
Expand Down
16 changes: 16 additions & 0 deletions packages/integration-tests/src/entities/ImageType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ export type ImageTypeDetails = {
sortOrder: 100 | 200 | 300;
visible: boolean;
nickname: "book_image" | "author_image" | "publisher_image";
isBookImage: boolean;
isAuthorImage: boolean;
isPublisherImage: boolean;
};

const details: Record<ImageType, ImageTypeDetails> = {
[ImageType.BookImage]: {
id: 1,
code: ImageType.BookImage,
name: "Book Image",
isBookImage: true,
isAuthorImage: false,
isPublisherImage: false,
sortOrder: 100,
visible: true,
nickname: "book_image",
Expand All @@ -26,6 +32,9 @@ const details: Record<ImageType, ImageTypeDetails> = {
id: 2,
code: ImageType.AuthorImage,
name: "Author Image",
isBookImage: false,
isAuthorImage: true,
isPublisherImage: false,
sortOrder: 200,
visible: true,
nickname: "author_image",
Expand All @@ -34,13 +43,20 @@ const details: Record<ImageType, ImageTypeDetails> = {
id: 3,
code: ImageType.PublisherImage,
name: "Publisher Image",
isBookImage: false,
isAuthorImage: false,
isPublisherImage: true,
sortOrder: 300,
visible: true,
nickname: "publisher_image",
},
};

export const ImageTypes = {
BookImage: details[ImageType.BookImage],
AuthorImage: details[ImageType.AuthorImage],
PublisherImage: details[ImageType.PublisherImage],

getByCode(code: ImageType): ImageTypeDetails {
return details[code];
},
Expand Down
6 changes: 3 additions & 3 deletions packages/integration-tests/src/entities/Publisher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Collection, CustomCollection, getEm, Loaded } from "joist-orm";
import { Image, ImageType, ImageTypes, PublisherCodegen, publisherConfig as config } from "./entities";
import { Image, ImageTypes, PublisherCodegen, publisherConfig as config } from "./entities";

const allImagesHint = { images: [], authors: { image: [], books: "image" } } as const;

Expand All @@ -19,12 +19,12 @@ export class Publisher extends PublisherCodegen {
[...loaded.images.get],
)
.filter((imageOrUndefined) => imageOrUndefined !== undefined)
.sort((a, b) => ImageTypes.findByCode(a.type)!.sortOrder - ImageTypes.findByCode(b.type)!.sortOrder);
.sort((a, b) => a.type.sortOrder - b.type.sortOrder);
},
add: (entity, value) => {
const allImages = (entity as Loaded<Publisher, "allImages">).allImages;
if (!allImages.get.includes(value)) {
value.type = ImageType.PublisherImage;
value.type = ImageTypes.PublisherImage;
value.author.set(undefined);
value.book.set(undefined);
value.publisher.set(entity);
Expand Down
24 changes: 8 additions & 16 deletions packages/integration-tests/src/entities/PublisherCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,12 @@ export abstract class PublisherCodegen extends BaseEntity<EntityManager> {
return this.__orm.data["updatedAt"];
}

get size(): PublisherSize | undefined {
return this.__orm.data["size"];
get size(): PublisherSizeDetails | undefined {
return PublisherSizes.findByCode(this.__orm.data["size"]);
}

get sizeDetails(): PublisherSizeDetails | undefined {
return this.size ? PublisherSizes.getByCode(this.size) : undefined;
}

set size(size: PublisherSize | undefined) {
setField(this, "size", size);
set size(size: PublisherSizeDetails | undefined) {
setField(this, "size", size?.code);
}

get isSizeSmall(): boolean {
Expand All @@ -250,16 +246,12 @@ export abstract class PublisherCodegen extends BaseEntity<EntityManager> {
return this.__orm.data["size"] === PublisherSize.Large;
}

get type(): PublisherType {
return this.__orm.data["type"];
}

get typeDetails(): PublisherTypeDetails {
return PublisherTypes.getByCode(this.type);
get type(): PublisherTypeDetails {
return PublisherTypes.findByCode(this.__orm.data["type"])!;
}

set type(type: PublisherType) {
setField(this, "type", type);
set type(type: PublisherTypeDetails) {
setField(this, "type", type?.code);
}

get isTypeSmall(): boolean {
Expand Down
27 changes: 24 additions & 3 deletions packages/integration-tests/src/entities/PublisherSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,35 @@ export enum PublisherSize {
Large = "LARGE",
}

export type PublisherSizeDetails = { id: number; code: PublisherSize; name: string };
export type PublisherSizeDetails = {
id: number;
code: PublisherSize;
name: string;
isSmall: boolean;
isLarge: boolean;
};

const details: Record<PublisherSize, PublisherSizeDetails> = {
[PublisherSize.Small]: { id: 1, code: PublisherSize.Small, name: "Small" },
[PublisherSize.Large]: { id: 2, code: PublisherSize.Large, name: "Large" },
[PublisherSize.Small]: {
id: 1,
code: PublisherSize.Small,
name: "Small",
isSmall: true,
isLarge: false,
},
[PublisherSize.Large]: {
id: 2,
code: PublisherSize.Large,
name: "Large",
isSmall: false,
isLarge: true,
},
};

export const PublisherSizes = {
Small: details[PublisherSize.Small],
Large: details[PublisherSize.Large],

getByCode(code: PublisherSize): PublisherSizeDetails {
return details[code];
},
Expand Down
Loading