cac13a88da
### Scope
Models R to U
### What
Refactor OAS for models to accurately represent their shape in API responses.
### Why
About 33% of model fields are not accurately represented in the OAS. Most of the issues are:
- fields that can not be omitted in the response are not declared as `required`
- fields that could return `null` as their value are not declared as `nullable: true`
When using a code generator, these OAS issues would lead to inaccurate response shapes in the generated client.
### How
#### nullable
Fields meeting at least one of the following condition will be represented as `nullable: true` in OAS:
* The field is decorated with `@Column({ nullable: true })`
* The field is decorated with `@OneToOne`, `@ManyToOne`
* The field is decorated with `@DeleteDateColumn`
#### optional
Fields meeting at least one of the following conditions will never be listed as `required` in OAS and will be considered optional and could be omitted in the response:
* The field is decorated with `@OneToOne`, `@ManyToOne`, `@OneToMany`, `@ManyToMany`
* The field is decorated with `@FeatureFlagColumn`
* The field is decorated with `@Column({select: false})`
* The field is representing dynamic values not persisted in the database
Fields not meeting any of the conditions above will be declared as `required` and are expected to be present in the response.
### Test
* Ran OAS validator.
* Ran docs build script.
Expect OAS changes to be reflected in the API documentation.
115 lines
2.7 KiB
TypeScript
115 lines
2.7 KiB
TypeScript
import { BeforeInsert, Column, Entity, Index } from "typeorm"
|
|
|
|
import { DbAwareColumn } from "../utils/db-aware-column"
|
|
import { SoftDeletableEntity } from "../interfaces/models/soft-deletable-entity"
|
|
import { generateEntityId } from "../utils/generate-entity-id"
|
|
|
|
export enum UserRoles {
|
|
ADMIN = "admin",
|
|
MEMBER = "member",
|
|
DEVELOPER = "developer",
|
|
}
|
|
|
|
@Entity()
|
|
export class User extends SoftDeletableEntity {
|
|
@DbAwareColumn({
|
|
type: "enum",
|
|
enum: UserRoles,
|
|
nullable: true,
|
|
default: UserRoles.MEMBER,
|
|
})
|
|
role: UserRoles
|
|
|
|
@Index({ unique: true, where: "deleted_at IS NULL" })
|
|
@Column()
|
|
email: string
|
|
|
|
@Column({ nullable: true })
|
|
first_name: string
|
|
|
|
@Column({ nullable: true })
|
|
last_name: string
|
|
|
|
@Column({ nullable: true, select: false })
|
|
password_hash: string
|
|
|
|
@Column({ nullable: true })
|
|
api_token: string
|
|
|
|
@DbAwareColumn({ type: "jsonb", nullable: true })
|
|
metadata: Record<string, unknown>
|
|
|
|
@BeforeInsert()
|
|
private beforeInsert(): void {
|
|
this.id = generateEntityId(this.id, "usr")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @schema User
|
|
* title: "User"
|
|
* description: "Represents a User who can manage store settings."
|
|
* type: object
|
|
* required:
|
|
* - api_token
|
|
* - created_at
|
|
* - deleted_at
|
|
* - email
|
|
* - first_name
|
|
* - id
|
|
* - last_name
|
|
* - metadata
|
|
* - role
|
|
* - updated_at
|
|
* properties:
|
|
* id:
|
|
* description: The user's ID
|
|
* type: string
|
|
* example: usr_01G1G5V26F5TB3GPAPNJ8X1S3V
|
|
* role:
|
|
* description: The user's role
|
|
* type: string
|
|
* enum:
|
|
* - admin
|
|
* - member
|
|
* - developer
|
|
* default: member
|
|
* email:
|
|
* description: The email of the User
|
|
* type: string
|
|
* format: email
|
|
* first_name:
|
|
* description: The first name of the User
|
|
* nullable: true
|
|
* type: string
|
|
* example: Levi
|
|
* last_name:
|
|
* description: The last name of the User
|
|
* nullable: true
|
|
* type: string
|
|
* example: Bogan
|
|
* api_token:
|
|
* description: An API token associated with the user.
|
|
* nullable: true
|
|
* type: string
|
|
* example: null
|
|
* created_at:
|
|
* description: The date with timezone at which the resource was created.
|
|
* type: string
|
|
* format: date-time
|
|
* updated_at:
|
|
* description: The date with timezone at which the resource was updated.
|
|
* type: string
|
|
* format: date-time
|
|
* deleted_at:
|
|
* description: The date with timezone at which the resource was deleted.
|
|
* nullable: true
|
|
* type: string
|
|
* format: date-time
|
|
* metadata:
|
|
* description: An optional key-value map with additional details
|
|
* nullable: true
|
|
* type: object
|
|
* example: {car: "white"}
|
|
*/
|