feat(types,utils): DML can create a bigNumber property (#7801)
what:
- adds bigNumber as a property to DML
- creates a bigNumber options field (`raw_{{ field }}`) as a part of the schema
RESOLVES CORE-2375
This commit is contained in:
1 parent
ae6dbc06be
commit
5c944ae5d0
11 files changed
+279
-54
No files matched your search
@@ -15,6 +15,7 @@ export type KnownDataTypes =
|
|||||||
| "boolean"
|
| "boolean"
|
||||||
| "enum"
|
| "enum"
|
||||||
| "number"
|
| "number"
|
||||||
|
| "bigNumber"
|
||||||
| "dateTime"
|
| "dateTime"
|
||||||
| "json"
|
| "json"
|
||||||
| "id"
|
| "id"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Property } from "@mikro-orm/core"
|
|
||||||
import { isPresent, trimZeros } from "../../common"
|
|
||||||
import { BigNumber } from "../../totals/big-number"
|
|
||||||
import { BigNumberInput } from "@medusajs/types"
|
import { BigNumberInput } from "@medusajs/types"
|
||||||
|
import { Property } from "@mikro-orm/core"
|
||||||
|
import { isDefined, isPresent, trimZeros } from "../../common"
|
||||||
|
import { BigNumber } from "../../totals/big-number"
|
||||||
|
|
||||||
export function MikroOrmBigNumberProperty(
|
export function MikroOrmBigNumberProperty(
|
||||||
options: Parameters<typeof Property>[0] & {
|
options: Parameters<typeof Property>[0] & {
|
||||||
@@ -45,12 +45,22 @@ export function MikroOrmBigNumberProperty(
|
|||||||
const raw = bigNumber.raw!
|
const raw = bigNumber.raw!
|
||||||
raw.value = trimZeros(raw.value as string)
|
raw.value = trimZeros(raw.value as string)
|
||||||
|
|
||||||
this.__helper.__data[columnName] = bigNumber.numeric
|
// Note: this.__helper isn't present when directly working with the entity
|
||||||
this.__helper.__data[rawColumnName] = raw
|
// Adding this in optionally for it not to break.
|
||||||
|
if (isDefined(this.__helper)) {
|
||||||
|
this.__helper.__data[columnName] = bigNumber.numeric
|
||||||
|
this.__helper.__data[rawColumnName] = raw
|
||||||
|
}
|
||||||
|
|
||||||
this[rawColumnName] = raw
|
this[rawColumnName] = raw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: this.__helper isn't present when directly working with the entity
|
||||||
|
// Adding this in optionally for it not to break.
|
||||||
|
if (!isDefined(this.__helper)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// This is custom code to keep track of which fields are bignumber, as well as their data
|
// This is custom code to keep track of which fields are bignumber, as well as their data
|
||||||
if (!this.__helper.__bignumberdata) {
|
if (!this.__helper.__bignumberdata) {
|
||||||
this.__helper.__bignumberdata = {}
|
this.__helper.__bignumberdata = {}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { expectTypeOf } from "expect-type"
|
||||||
|
import { BigNumberProperty } from "../properties/big-number"
|
||||||
|
|
||||||
|
describe("Big Number property", () => {
|
||||||
|
test("create bigNumber property type", () => {
|
||||||
|
const property = new BigNumberProperty()
|
||||||
|
|
||||||
|
expectTypeOf(property["$dataType"]).toEqualTypeOf<number>()
|
||||||
|
expect(property.parse("age")).toEqual({
|
||||||
|
fieldName: "age",
|
||||||
|
dataType: {
|
||||||
|
name: "bigNumber",
|
||||||
|
},
|
||||||
|
nullable: false,
|
||||||
|
indexes: [],
|
||||||
|
relationships: [],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import { expectTypeOf } from "expect-type"
|
|
||||||
import { MetadataStorage } from "@mikro-orm/core"
|
import { MetadataStorage } from "@mikro-orm/core"
|
||||||
import { EntityConstructor } from "../types"
|
import { expectTypeOf } from "expect-type"
|
||||||
import { EntityBuilder } from "../entity-builder"
|
|
||||||
import { createMikrORMEntity } from "../helpers/create-mikro-orm-entity"
|
|
||||||
import { DmlEntity } from "../entity"
|
import { DmlEntity } from "../entity"
|
||||||
|
import { EntityBuilder } from "../entity-builder"
|
||||||
|
import {
|
||||||
|
createMikrORMEntity,
|
||||||
|
toMikroORMEntity,
|
||||||
|
} from "../helpers/create-mikro-orm-entity"
|
||||||
|
import { EntityConstructor } from "../types"
|
||||||
|
|
||||||
describe("Entity builder", () => {
|
describe("Entity builder", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -32,14 +35,18 @@ describe("Entity builder", () => {
|
|||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
|
spend_limit: model.bigNumber(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const entityBuilder = createMikrORMEntity()
|
||||||
const User = entityBuilder(user)
|
const User = entityBuilder(user)
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
email: string
|
email: string
|
||||||
|
spend_limit: number
|
||||||
|
raw_spend_limit: Record<string, unknown>
|
||||||
created_at: Date
|
created_at: Date
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
deleted_at: Date | null
|
deleted_at: Date | null
|
||||||
@@ -97,6 +104,25 @@ describe("Entity builder", () => {
|
|||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
|
spend_limit: {
|
||||||
|
columnType: "numeric",
|
||||||
|
getter: true,
|
||||||
|
name: "spend_limit",
|
||||||
|
nullable: false,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: true,
|
||||||
|
trackChanges: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
|
raw_spend_limit: {
|
||||||
|
columnType: "jsonb",
|
||||||
|
getter: false,
|
||||||
|
name: "raw_spend_limit",
|
||||||
|
nullable: false,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
updated_at: {
|
updated_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
type: "date",
|
||||||
@@ -127,6 +153,7 @@ describe("Entity builder", () => {
|
|||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text().default("foo"),
|
username: model.text().default("foo"),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
|
spend_limit: model.bigNumber().default(500.4),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const entityBuilder = createMikrORMEntity()
|
||||||
@@ -180,6 +207,26 @@ describe("Entity builder", () => {
|
|||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
|
spend_limit: {
|
||||||
|
columnType: "numeric",
|
||||||
|
default: 500.4,
|
||||||
|
getter: true,
|
||||||
|
name: "spend_limit",
|
||||||
|
nullable: false,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: true,
|
||||||
|
trackChanges: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
|
raw_spend_limit: {
|
||||||
|
columnType: "jsonb",
|
||||||
|
getter: false,
|
||||||
|
name: "raw_spend_limit",
|
||||||
|
nullable: false,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
type: "date",
|
||||||
@@ -221,27 +268,44 @@ describe("Entity builder", () => {
|
|||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text().nullable(),
|
username: model.text().nullable(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
|
spend_limit: model.bigNumber().nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string | null
|
username: string | null
|
||||||
email: string
|
email: string
|
||||||
|
spend_limit: number | null
|
||||||
|
raw_spend_limit: Record<string, unknown> | null
|
||||||
|
created_at: Date
|
||||||
|
updated_at: Date
|
||||||
deleted_at: Date | null
|
deleted_at: Date | null
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const metaData = MetadataStorage.getMetadataFromDecorator(User)
|
const metaData = MetadataStorage.getMetadataFromDecorator(User)
|
||||||
|
|
||||||
expect(metaData.className).toEqual("User")
|
expect(metaData.className).toEqual("User")
|
||||||
expect(metaData.path).toEqual("User")
|
expect(metaData.path).toEqual("User")
|
||||||
|
|
||||||
const userInstance = new User()
|
const userInstance = new User()
|
||||||
|
|
||||||
expect(userInstance.username).toEqual(null)
|
expect(userInstance.username).toEqual(null)
|
||||||
|
|
||||||
|
expect(userInstance.spend_limit).toEqual(undefined)
|
||||||
|
expect(userInstance.raw_spend_limit).toEqual(null)
|
||||||
|
|
||||||
userInstance.username = "john"
|
userInstance.username = "john"
|
||||||
expect(userInstance.username).toEqual("john")
|
expect(userInstance.username).toEqual("john")
|
||||||
|
|
||||||
|
userInstance.spend_limit = 150.5
|
||||||
|
expect(userInstance.spend_limit).toEqual(150.5)
|
||||||
|
expect(userInstance.raw_spend_limit).toEqual({
|
||||||
|
precision: 20,
|
||||||
|
value: "150.5",
|
||||||
|
})
|
||||||
|
|
||||||
expect(metaData.filters).toEqual({
|
expect(metaData.filters).toEqual({
|
||||||
softDeletable: {
|
softDeletable: {
|
||||||
name: "softDeletable",
|
name: "softDeletable",
|
||||||
@@ -279,6 +343,25 @@ describe("Entity builder", () => {
|
|||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
|
raw_spend_limit: {
|
||||||
|
columnType: "jsonb",
|
||||||
|
getter: false,
|
||||||
|
name: "raw_spend_limit",
|
||||||
|
nullable: true,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
|
spend_limit: {
|
||||||
|
columnType: "numeric",
|
||||||
|
getter: true,
|
||||||
|
name: "spend_limit",
|
||||||
|
nullable: true,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: true,
|
||||||
|
trackChanges: false,
|
||||||
|
type: "any",
|
||||||
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
type: "date",
|
||||||
|
|||||||
@@ -1,27 +1,34 @@
|
|||||||
import { DmlEntity } from "./entity"
|
|
||||||
import { TextProperty } from "./properties/text"
|
|
||||||
import { EnumProperty } from "./properties/enum"
|
|
||||||
import { JSONProperty } from "./properties/json"
|
|
||||||
import { HasOne } from "./relations/has-one"
|
|
||||||
import { HasMany } from "./relations/has-many"
|
|
||||||
import { NumberProperty } from "./properties/number"
|
|
||||||
import { BooleanProperty } from "./properties/boolean"
|
|
||||||
import { BelongsTo } from "./relations/belongs-to"
|
|
||||||
import { DateTimeProperty } from "./properties/date-time"
|
|
||||||
import { ManyToMany } from "./relations/many-to-many"
|
|
||||||
import type {
|
import type {
|
||||||
PropertyType,
|
PropertyType,
|
||||||
RelationshipOptions,
|
RelationshipOptions,
|
||||||
RelationshipType,
|
RelationshipType,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { NullableModifier } from "./properties/nullable"
|
import { DmlEntity } from "./entity"
|
||||||
|
import { createBigNumberProperties } from "./helpers/entity-builder/create-big-number-properties"
|
||||||
|
import { createDefaultProperties } from "./helpers/entity-builder/create-default-properties"
|
||||||
|
import { BigNumberProperty } from "./properties/big-number"
|
||||||
|
import { BooleanProperty } from "./properties/boolean"
|
||||||
|
import { DateTimeProperty } from "./properties/date-time"
|
||||||
|
import { EnumProperty } from "./properties/enum"
|
||||||
import { IdProperty } from "./properties/id"
|
import { IdProperty } from "./properties/id"
|
||||||
|
import { JSONProperty } from "./properties/json"
|
||||||
|
import { NumberProperty } from "./properties/number"
|
||||||
|
import { TextProperty } from "./properties/text"
|
||||||
|
import { BelongsTo } from "./relations/belongs-to"
|
||||||
|
import { HasMany } from "./relations/has-many"
|
||||||
|
import { HasOne } from "./relations/has-one"
|
||||||
|
import { ManyToMany } from "./relations/many-to-many"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The implicit properties added by EntityBuilder in every schema
|
* The implicit properties added by EntityBuilder in every schema
|
||||||
*/
|
*/
|
||||||
const IMPLICIT_PROPERTIES = ["created_at", "updated_at", "deleted_at"]
|
const IMPLICIT_PROPERTIES = ["created_at", "updated_at", "deleted_at"]
|
||||||
|
|
||||||
|
export type DMLSchema = Record<
|
||||||
|
string,
|
||||||
|
PropertyType<any> | RelationshipType<any>
|
||||||
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity builder exposes the API to create an entity and define its
|
* Entity builder exposes the API to create an entity and define its
|
||||||
* schema using the shorthand methods.
|
* schema using the shorthand methods.
|
||||||
@@ -45,22 +52,13 @@ export class EntityBuilder {
|
|||||||
* Define an entity or a model. The name should be unique across
|
* Define an entity or a model. The name should be unique across
|
||||||
* all the entities.
|
* all the entities.
|
||||||
*/
|
*/
|
||||||
define<
|
define<Schema extends DMLSchema>(name: string, schema: Schema) {
|
||||||
Schema extends Record<string, PropertyType<any> | RelationshipType<any>>
|
|
||||||
>(name: string, schema: Schema) {
|
|
||||||
this.#disallowImplicitProperties(schema)
|
this.#disallowImplicitProperties(schema)
|
||||||
|
|
||||||
return new DmlEntity<
|
return new DmlEntity(name, {
|
||||||
Schema & {
|
|
||||||
created_at: DateTimeProperty
|
|
||||||
updated_at: DateTimeProperty
|
|
||||||
deleted_at: NullableModifier<Date, DateTimeProperty>
|
|
||||||
}
|
|
||||||
>(name, {
|
|
||||||
...schema,
|
...schema,
|
||||||
created_at: new DateTimeProperty(),
|
...createBigNumberProperties(schema),
|
||||||
updated_at: new DateTimeProperty(),
|
...createDefaultProperties(),
|
||||||
deleted_at: new DateTimeProperty().nullable(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,12 +85,21 @@ export class EntityBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a numeric/integer column
|
* Define an integer column
|
||||||
*/
|
*/
|
||||||
number() {
|
number() {
|
||||||
return new NumberProperty()
|
return new NumberProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a numeric column. This property produces an additional
|
||||||
|
* column - raw_{{ property_name }}, which stores the configuration
|
||||||
|
* of bignumber (https://github.com/MikeMcl/bignumber.js)
|
||||||
|
*/
|
||||||
|
bigNumber() {
|
||||||
|
return new BigNumberProperty()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a timestampz column
|
* Define a timestampz column
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { BelongsTo } from "./relations/belongs-to"
|
|
||||||
import {
|
import {
|
||||||
EntityCascades,
|
EntityCascades,
|
||||||
ExtractEntityRelations,
|
ExtractEntityRelations,
|
||||||
@@ -7,15 +6,14 @@ import {
|
|||||||
PropertyType,
|
PropertyType,
|
||||||
RelationshipType,
|
RelationshipType,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
|
import { DMLSchema } from "./entity-builder"
|
||||||
|
import { BelongsTo } from "./relations/belongs-to"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dml entity is a representation of a DML model with a unique
|
* Dml entity is a representation of a DML model with a unique
|
||||||
* name, its schema and relationships.
|
* name, its schema and relationships.
|
||||||
*/
|
*/
|
||||||
export class DmlEntity<
|
export class DmlEntity<Schema extends DMLSchema> implements IDmlEntity<Schema> {
|
||||||
Schema extends Record<string, PropertyType<any> | RelationshipType<any>>
|
|
||||||
> implements IDmlEntity<Schema>
|
|
||||||
{
|
|
||||||
[IsDmlEntity]: true = true
|
[IsDmlEntity]: true = true
|
||||||
|
|
||||||
#cascades: EntityCascades<string[]> = {}
|
#cascades: EntityCascades<string[]> = {}
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
import type {
|
||||||
|
EntityCascades,
|
||||||
|
EntityConstructor,
|
||||||
|
Infer,
|
||||||
|
KnownDataTypes,
|
||||||
|
PropertyMetadata,
|
||||||
|
PropertyType,
|
||||||
|
RelationshipMetadata,
|
||||||
|
RelationshipType,
|
||||||
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Entity,
|
Entity,
|
||||||
@@ -20,21 +30,14 @@ import {
|
|||||||
toCamelCase,
|
toCamelCase,
|
||||||
} from "../../common"
|
} from "../../common"
|
||||||
import { upperCaseFirst } from "../../common/upper-case-first"
|
import { upperCaseFirst } from "../../common/upper-case-first"
|
||||||
|
import {
|
||||||
|
MikroOrmBigNumberProperty,
|
||||||
|
mikroOrmSoftDeletableFilterOptions,
|
||||||
|
} from "../../dal"
|
||||||
import { DmlEntity } from "../entity"
|
import { DmlEntity } from "../entity"
|
||||||
import { HasMany } from "../relations/has-many"
|
import { HasMany } from "../relations/has-many"
|
||||||
import { HasOne } from "../relations/has-one"
|
import { HasOne } from "../relations/has-one"
|
||||||
import { ManyToMany as DmlManyToMany } from "../relations/many-to-many"
|
import { ManyToMany as DmlManyToMany } from "../relations/many-to-many"
|
||||||
import type {
|
|
||||||
EntityCascades,
|
|
||||||
EntityConstructor,
|
|
||||||
Infer,
|
|
||||||
KnownDataTypes,
|
|
||||||
PropertyMetadata,
|
|
||||||
PropertyType,
|
|
||||||
RelationshipMetadata,
|
|
||||||
RelationshipType,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
import { mikroOrmSoftDeletableFilterOptions } from "../../dal"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DML entity data types to PostgreSQL data types via
|
* DML entity data types to PostgreSQL data types via
|
||||||
@@ -49,6 +52,7 @@ const COLUMN_TYPES: {
|
|||||||
boolean: "boolean",
|
boolean: "boolean",
|
||||||
dateTime: "timestamptz",
|
dateTime: "timestamptz",
|
||||||
number: "integer",
|
number: "integer",
|
||||||
|
bigNumber: "numeric",
|
||||||
text: "text",
|
text: "text",
|
||||||
json: "jsonb",
|
json: "jsonb",
|
||||||
}
|
}
|
||||||
@@ -66,6 +70,7 @@ const PROPERTY_TYPES: {
|
|||||||
boolean: "boolean",
|
boolean: "boolean",
|
||||||
dateTime: "date",
|
dateTime: "date",
|
||||||
number: "number",
|
number: "number",
|
||||||
|
bigNumber: "number",
|
||||||
text: "string",
|
text: "string",
|
||||||
json: "any",
|
json: "any",
|
||||||
}
|
}
|
||||||
@@ -175,6 +180,27 @@ export function createMikrORMEntity() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defining an big number property
|
||||||
|
* A big number property always comes with a raw_{{ fieldName }} column
|
||||||
|
* where the config of the bigNumber is set.
|
||||||
|
* The `raw_` field is generated during DML schema generation as a json
|
||||||
|
* dataType.
|
||||||
|
*/
|
||||||
|
if (field.dataType.name === "bigNumber") {
|
||||||
|
MikroOrmBigNumberProperty({
|
||||||
|
nullable: field.nullable,
|
||||||
|
/**
|
||||||
|
* MikroORM does not ignore undefined values for default when generating
|
||||||
|
* the database schema SQL. Conditionally add it here to prevent undefined
|
||||||
|
* from being set as default value in SQL.
|
||||||
|
*/
|
||||||
|
...(isDefined(field.defaultValue) && { default: field.defaultValue }),
|
||||||
|
})(MikroORMEntity.prototype, field.fieldName)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defining an enum property
|
* Defining an enum property
|
||||||
*/
|
*/
|
||||||
@@ -615,6 +641,7 @@ export function createMikrORMEntity() {
|
|||||||
*/
|
*/
|
||||||
Object.entries(schema).forEach(([name, property]) => {
|
Object.entries(schema).forEach(([name, property]) => {
|
||||||
const field = property.parse(name)
|
const field = property.parse(name)
|
||||||
|
|
||||||
if ("fieldName" in field) {
|
if ("fieldName" in field) {
|
||||||
defineProperty(MikroORMEntity, field)
|
defineProperty(MikroORMEntity, field)
|
||||||
applyIndexes(MikroORMEntity, tableName, field)
|
applyIndexes(MikroORMEntity, tableName, field)
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { DMLSchema } from "../../entity-builder"
|
||||||
|
import { BigNumberProperty } from "../../properties/big-number"
|
||||||
|
import { JSONProperty } from "../../properties/json"
|
||||||
|
import { NullableModifier } from "../../properties/nullable"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The goal of this type is to look at the schema and see if there are any versions
|
||||||
|
* of a bigNumber property (nullable or otherwise) and if any are found, we append new
|
||||||
|
* fields of the same property to the type. These fields will be prepended by raw_
|
||||||
|
* These fields will be typed to a json property (nullable or otherwise)
|
||||||
|
*
|
||||||
|
* eg: const test = model.define('test', { amount: model.bigNumber() })
|
||||||
|
* test.amount // valid | type = number
|
||||||
|
* test.raw_amount // valid | type = Record<string, any>
|
||||||
|
*/
|
||||||
|
type DMLSchemaWithBigNumber<T extends DMLSchema> = {
|
||||||
|
[K in keyof T]: T[K]
|
||||||
|
} & {
|
||||||
|
[K in keyof T as T[K] extends
|
||||||
|
| BigNumberProperty
|
||||||
|
| NullableModifier<number, BigNumberProperty>
|
||||||
|
? `raw_${string & K}`
|
||||||
|
: never]: T[K] extends NullableModifier<number, BigNumberProperty>
|
||||||
|
? NullableModifier<Record<string, unknown>, JSONProperty>
|
||||||
|
: JSONProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createBigNumberProperties<Schema extends DMLSchema>(
|
||||||
|
schema: Schema
|
||||||
|
): DMLSchemaWithBigNumber<Schema> {
|
||||||
|
const schemaWithBigNumber: DMLSchema = {}
|
||||||
|
|
||||||
|
for (const [key, property] of Object.entries(schema)) {
|
||||||
|
if (
|
||||||
|
property instanceof BigNumberProperty ||
|
||||||
|
property instanceof NullableModifier
|
||||||
|
) {
|
||||||
|
const parsed = property.parse(key)
|
||||||
|
|
||||||
|
if (parsed.dataType?.name !== "bigNumber") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonProperty = parsed.nullable
|
||||||
|
? new JSONProperty().nullable()
|
||||||
|
: new JSONProperty()
|
||||||
|
|
||||||
|
schemaWithBigNumber[`raw_${key}`] = jsonProperty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return schemaWithBigNumber as DMLSchemaWithBigNumber<Schema>
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { DateTimeProperty } from "../../properties/date-time"
|
||||||
|
import { NullableModifier } from "../../properties/nullable"
|
||||||
|
|
||||||
|
export type DMLSchemaDefaults = {
|
||||||
|
created_at: DateTimeProperty
|
||||||
|
updated_at: DateTimeProperty
|
||||||
|
deleted_at: NullableModifier<Date, DateTimeProperty>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDefaultProperties(): DMLSchemaDefaults {
|
||||||
|
return {
|
||||||
|
created_at: new DateTimeProperty(),
|
||||||
|
updated_at: new DateTimeProperty(),
|
||||||
|
deleted_at: new DateTimeProperty().nullable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { BaseProperty } from "./base"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The NumberProperty is used to define a numeric/integer
|
||||||
|
* property
|
||||||
|
*/
|
||||||
|
export class BigNumberProperty extends BaseProperty<number> {
|
||||||
|
protected dataType = {
|
||||||
|
name: "bigNumber",
|
||||||
|
} as const
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { BaseProperty } from "./base"
|
|||||||
* The JSONProperty is used to define a property that stores
|
* The JSONProperty is used to define a property that stores
|
||||||
* data as a JSON string
|
* data as a JSON string
|
||||||
*/
|
*/
|
||||||
export class JSONProperty extends BaseProperty<string> {
|
export class JSONProperty extends BaseProperty<Record<string, unknown>> {
|
||||||
protected dataType = {
|
protected dataType = {
|
||||||
name: "json",
|
name: "json",
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
Reference in new issue
Block a user