@exogee/graphweaver-mikroorm 0.2.24 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.js.map +1 -1
- package/lib/database.d.ts +3 -3
- package/lib/database.js +7 -11
- package/lib/database.js.map +2 -2
- package/lib/decorators/external-id-field.js.map +2 -2
- package/lib/decorators/index.js +4 -0
- package/lib/entities/audit-change.d.ts +1 -2
- package/lib/entities/audit-change.js +3 -6
- package/lib/entities/audit-change.js.map +2 -2
- package/lib/entities/audit-related-entity-change.d.ts +1 -2
- package/lib/entities/audit-related-entity-change.js +2 -4
- package/lib/entities/audit-related-entity-change.js.map +2 -2
- package/lib/entities/index.d.ts +0 -1
- package/lib/entities/index.js +5 -1
- package/lib/entities/index.js.map +2 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js +14 -2
- package/lib/index.js.map +2 -2
- package/lib/introspection/files/base-file.js.map +1 -1
- package/lib/introspection/files/data-entity-file.js +10 -12
- package/lib/introspection/files/data-entity-file.js.map +2 -2
- package/lib/introspection/files/data-entity-index-file.js +3 -3
- package/lib/introspection/files/data-entity-index-file.js.map +2 -2
- package/lib/introspection/files/data-source-index-file.js.map +1 -1
- package/lib/introspection/files/database-file.js +2 -2
- package/lib/introspection/files/database-file.js.map +2 -2
- package/lib/introspection/files/index.d.ts +0 -2
- package/lib/introspection/files/index.js +9 -2
- package/lib/introspection/files/index.js.map +2 -2
- package/lib/introspection/files/schema-entity-file.d.ts +2 -1
- package/lib/introspection/files/schema-entity-file.js +41 -25
- package/lib/introspection/files/schema-entity-file.js.map +3 -3
- package/lib/introspection/files/schema-index-file.js +3 -19
- package/lib/introspection/files/schema-index-file.js.map +2 -2
- package/lib/introspection/generate.js +22 -20
- package/lib/introspection/generate.js.map +2 -2
- package/lib/plugins/clear-database-context.js +1 -0
- package/lib/plugins/clear-database-context.js.map +1 -1
- package/lib/{base-resolver → provider}/assign.d.ts +1 -1
- package/lib/{base-resolver → provider}/assign.js +41 -13
- package/lib/provider/assign.js.map +7 -0
- package/lib/{base-resolver → provider}/index.js +7 -3
- package/lib/provider/index.js.map +7 -0
- package/lib/{base-resolver → provider}/provider.d.ts +13 -15
- package/lib/{base-resolver → provider}/provider.js +45 -43
- package/lib/provider/provider.js.map +7 -0
- package/lib/types/date-type.d.ts +5 -5
- package/lib/types/date-type.js +8 -11
- package/lib/types/date-type.js.map +2 -2
- package/lib/types/decimal-type.d.ts +5 -5
- package/lib/types/decimal-type.js +12 -20
- package/lib/types/decimal-type.js.map +2 -2
- package/lib/types/index.js +5 -0
- package/lib/types/time-type.d.ts +5 -5
- package/lib/types/time-type.js +12 -20
- package/lib/types/time-type.js.map +2 -2
- package/lib/utils/authentication-context.js.map +1 -1
- package/lib/utils/change-tracker.js +10 -9
- package/lib/utils/change-tracker.js.map +2 -2
- package/lib/utils/index.js +7 -0
- package/lib/utils/tracked-entity.d.ts +1 -2
- package/lib/utils/tracked-entity.js +2 -4
- package/lib/utils/tracked-entity.js.map +2 -2
- package/lib/utils/untracked-property.d.ts +0 -1
- package/lib/utils/untracked-property.js +0 -1
- package/lib/utils/untracked-property.js.map +2 -2
- package/package.json +20 -20
- package/lib/base-resolver/assign.js.map +0 -7
- package/lib/base-resolver/index.js.map +0 -7
- package/lib/base-resolver/provider.js.map +0 -7
- package/lib/entities/base-entity.d.ts +0 -5
- package/lib/entities/base-entity.js +0 -37
- package/lib/entities/base-entity.js.map +0 -7
- package/lib/introspection/files/schema-entity-index-file.d.ts +0 -6
- package/lib/introspection/files/schema-entity-index-file.js +0 -44
- package/lib/introspection/files/schema-entity-index-file.js.map +0 -7
- package/lib/introspection/files/schema-resolver-file.d.ts +0 -6
- package/lib/introspection/files/schema-resolver-file.js +0 -62
- package/lib/introspection/files/schema-resolver-file.js.map +0 -7
- /package/lib/{base-resolver → provider}/index.d.ts +0 -0
|
@@ -25,8 +25,7 @@ var import_core = require("@mikro-orm/core");
|
|
|
25
25
|
var import_logger = require("@exogee/logger");
|
|
26
26
|
var import_database = require("../database");
|
|
27
27
|
const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set(), em = import_database.ConnectionManager.default.em) => {
|
|
28
|
-
if (visited.has(entity))
|
|
29
|
-
return entity;
|
|
28
|
+
if (visited.has(entity)) return entity;
|
|
30
29
|
visited.add(entity);
|
|
31
30
|
const metadata = (0, import_core.wrap)(entity, true).__meta;
|
|
32
31
|
for (const [property, value] of Object.entries(data)) {
|
|
@@ -42,20 +41,31 @@ const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set()
|
|
|
42
41
|
`Tried to merge array into non-collection property ${property} on entity ${metadata.name}`
|
|
43
42
|
);
|
|
44
43
|
}
|
|
44
|
+
const relatedEntity = em.getMetadata().find(propertyMetadata.entity());
|
|
45
|
+
if (relatedEntity?.primaryKeys.length !== 1) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Entity ${propertyMetadata.entity()} has multiple primary keys, which is not yet supported.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const [relatedPrimaryKeyField] = relatedEntity.primaryKeys;
|
|
45
51
|
const visitedEntities = /* @__PURE__ */ new Set();
|
|
46
52
|
for (const subvalue of value) {
|
|
47
53
|
let entity2;
|
|
48
|
-
if (subvalue
|
|
49
|
-
entity2 = em.getUnitOfWork().getById(propertyMetadata.type, subvalue
|
|
54
|
+
if (subvalue[relatedPrimaryKeyField]) {
|
|
55
|
+
entity2 = em.getUnitOfWork().getById(propertyMetadata.type, subvalue[relatedPrimaryKeyField]);
|
|
50
56
|
if (!entity2) {
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
const subvalueKeys = Object.keys(subvalue);
|
|
58
|
+
if (subvalueKeys.length === 1 && subvalueKeys[0] === relatedPrimaryKeyField) {
|
|
59
|
+
entity2 = em.getReference(
|
|
60
|
+
propertyMetadata.type,
|
|
61
|
+
subvalue[relatedPrimaryKeyField]
|
|
62
|
+
);
|
|
53
63
|
} else {
|
|
54
64
|
import_logger.logger.warn(
|
|
55
|
-
`Doing a full database fetch for ${propertyMetadata.type} with id ${subvalue
|
|
65
|
+
`Doing a full database fetch for ${propertyMetadata.type} with id ${subvalue[relatedPrimaryKeyField]}, this should ideally be prefetched into the Unit of Work before calling assign() for performance`
|
|
56
66
|
);
|
|
57
67
|
entity2 = await em.findOne(propertyMetadata.type, {
|
|
58
|
-
|
|
68
|
+
[relatedPrimaryKeyField]: subvalue[relatedPrimaryKeyField]
|
|
59
69
|
}) ?? void 0;
|
|
60
70
|
}
|
|
61
71
|
}
|
|
@@ -68,6 +78,7 @@ const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set()
|
|
|
68
78
|
const newEntity = await createOrAssignEntity({
|
|
69
79
|
entity: entity2,
|
|
70
80
|
entityType: propertyMetadata.type,
|
|
81
|
+
primaryKeyField: relatedPrimaryKeyField,
|
|
71
82
|
data: subvalue,
|
|
72
83
|
options,
|
|
73
84
|
visited,
|
|
@@ -84,15 +95,30 @@ const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set()
|
|
|
84
95
|
entity[property] = null;
|
|
85
96
|
} else {
|
|
86
97
|
const valueKeys = Object.keys(value);
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
const relatedEntity = em.getMetadata().find(propertyMetadata.entity());
|
|
99
|
+
if (!relatedEntity) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Could not find entity ${propertyMetadata.entity()} in MikroORM metadata.`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
if (relatedEntity.primaryKeys.length !== 1) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Entity ${propertyMetadata.entity()} has ${relatedEntity.primaryKeys.length} primary keys, but we only support 1.`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
const relatedPrimaryKeyField = relatedEntity.primaryKeys[0];
|
|
110
|
+
if (valueKeys.length === 1 && valueKeys[0] === relatedPrimaryKeyField) {
|
|
111
|
+
entity[property] = em.getReference(
|
|
112
|
+
propertyMetadata.type,
|
|
113
|
+
value[relatedPrimaryKeyField]
|
|
114
|
+
);
|
|
89
115
|
} else {
|
|
90
116
|
if (entityPropertyValue && !import_core.Reference.isReference(entityPropertyValue)) {
|
|
91
117
|
throw new Error(
|
|
92
118
|
`Trying to merge to related property ${property} on entity ${metadata.name} which is not a reference.`
|
|
93
119
|
);
|
|
94
120
|
}
|
|
95
|
-
if (entityPropertyValue && !entityPropertyValue.isInitialized()) {
|
|
121
|
+
if (import_core.Reference.isReference(entityPropertyValue) && !entityPropertyValue.isInitialized()) {
|
|
96
122
|
throw new Error(
|
|
97
123
|
`Trying to merge to related property ${property} on entity ${metadata.name} which is not initialised.`
|
|
98
124
|
);
|
|
@@ -100,12 +126,13 @@ const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set()
|
|
|
100
126
|
const newEntity = await createOrAssignEntity({
|
|
101
127
|
entity: entityPropertyValue?.unwrap(),
|
|
102
128
|
entityType: propertyMetadata.type,
|
|
129
|
+
primaryKeyField: relatedPrimaryKeyField,
|
|
103
130
|
data: value,
|
|
104
131
|
options,
|
|
105
132
|
visited,
|
|
106
133
|
em
|
|
107
134
|
});
|
|
108
|
-
|
|
135
|
+
relatedEntity[property] = import_core.Reference.create(newEntity);
|
|
109
136
|
}
|
|
110
137
|
}
|
|
111
138
|
} else {
|
|
@@ -117,6 +144,7 @@ const assign = async (entity, data, options, visited = /* @__PURE__ */ new Set()
|
|
|
117
144
|
const createOrAssignEntity = ({
|
|
118
145
|
entity,
|
|
119
146
|
entityType,
|
|
147
|
+
primaryKeyField,
|
|
120
148
|
data,
|
|
121
149
|
options,
|
|
122
150
|
visited,
|
|
@@ -124,7 +152,7 @@ const createOrAssignEntity = ({
|
|
|
124
152
|
}) => {
|
|
125
153
|
const create = options?.create ?? true;
|
|
126
154
|
const update = options?.update ?? true;
|
|
127
|
-
if (data
|
|
155
|
+
if (data[primaryKeyField]) {
|
|
128
156
|
if (!update) {
|
|
129
157
|
throw new Error(
|
|
130
158
|
`Updates are disabled, but update value ${JSON.stringify(
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/provider/assign.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n\tAnyEntity,\n\tEntityData,\n\tEntityManager,\n\tEntityProperty,\n\tReference,\n\tReferenceKind,\n\tUtils,\n\twrap,\n} from '@mikro-orm/core';\nimport { logger } from '@exogee/logger';\n\nimport { ConnectionManager } from '../database';\n\n// This is how Mikro ORM does it within their own code, so in this file we're ok with non-null assertions.\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\ninterface AssignOptions {\n\t// Whether this assign should be allowed to create new entities.\n\t// If false and a create is attempted, assign will throw.\n\t// Defaults to true if not specified.\n\tcreate?: boolean;\n\n\t// Whether this assign should be allowed update existing entities.\n\t// If false and an update is attempted, assign will throw.\n\t// Defaults to true if not specified.\n\tupdate?: boolean;\n}\n\nexport const assign = async <T extends AnyEntity<T>>(\n\tentity: T,\n\tdata: EntityData<T>,\n\toptions?: AssignOptions,\n\tvisited = new Set<AnyEntity<any>>(),\n\tem = ConnectionManager.default.em\n) => {\n\tif (visited.has(entity)) return entity;\n\tvisited.add(entity);\n\n\t// We'll need the metadata for this entity to be able to traverse the properties later.\n\tconst metadata = wrap(entity, true).__meta!;\n\n\tfor (const [property, value] of Object.entries(data)) {\n\t\tconst entityPropertyValue = entity[property as keyof T];\n\n\t\t// We're going to need the metadata for this property so we can ensure it exists and so that we can\n\t\t// navigate to related entities.\n\t\tconst propertyMetadata = (metadata.properties as any)[property] as\n\t\t\t| EntityProperty<T>\n\t\t\t| undefined;\n\n\t\tif (\n\t\t\tpropertyMetadata?.kind === ReferenceKind.MANY_TO_MANY ||\n\t\t\tpropertyMetadata?.kind === ReferenceKind.ONE_TO_MANY\n\t\t) {\n\t\t\tif (!Array.isArray(value))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value is not an array while trying to assign to collection property ${property} on entity ${metadata.name}`\n\t\t\t\t);\n\n\t\t\t// Ensure the entity has a loaded collection at the same place.\n\t\t\tif (!Utils.isCollection<T, any>(entityPropertyValue)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tried to merge array into non-collection property ${property} on entity ${metadata.name}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst relatedEntity = em.getMetadata().find(propertyMetadata.entity());\n\t\t\tif (relatedEntity?.primaryKeys.length !== 1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Entity ${propertyMetadata.entity()} has multiple primary keys, which is not yet supported.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst [relatedPrimaryKeyField] = relatedEntity.primaryKeys;\n\n\t\t\tconst visitedEntities = new Set<T>();\n\n\t\t\tfor (const subvalue of value) {\n\t\t\t\tlet entity: T | undefined;\n\n\t\t\t\tif (subvalue[relatedPrimaryKeyField]) {\n\t\t\t\t\t// Get the current entity from the ORM if there's an ID.\n\t\t\t\t\tentity = em\n\t\t\t\t\t\t.getUnitOfWork()\n\t\t\t\t\t\t.getById(propertyMetadata.type, subvalue[relatedPrimaryKeyField]);\n\n\t\t\t\t\tif (!entity) {\n\t\t\t\t\t\t// There are two cases here: either the user is trying to assign properties to the entity as well as changing members of a collection,\n\t\t\t\t\t\t// or they're just changing members of a collection.\n\t\t\t\t\t\t// For the former we actually need the entity from the DB, while for the latter we can let it slide and just pass an ID entity on down.\n\t\t\t\t\t\tconst subvalueKeys = Object.keys(subvalue);\n\t\t\t\t\t\tif (subvalueKeys.length === 1 && subvalueKeys[0] === relatedPrimaryKeyField) {\n\t\t\t\t\t\t\t// It's just the ID.\n\t\t\t\t\t\t\tentity = em.getReference(\n\t\t\t\t\t\t\t\tpropertyMetadata.type,\n\t\t\t\t\t\t\t\tsubvalue[relatedPrimaryKeyField]\n\t\t\t\t\t\t\t) as T;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\t`Doing a full database fetch for ${propertyMetadata.type} with id ${subvalue[relatedPrimaryKeyField]}, this should ideally be prefetched into the Unit of Work before calling assign() for performance`\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// We should be prefetching for performance in most cases here but if we don't have it we can load it now.\n\t\t\t\t\t\t\t// From base resolver a reason this would be needed is when you're switching collection values from one entity to another, e.g.\n\t\t\t\t\t\t\t// Business unit 1 -> Business unit 2. In this scenario we prefetch the one that's currently on the entity, but the one we're changing\n\t\t\t\t\t\t\t// to is not in the unit of work.\n\t\t\t\t\t\t\tentity =\n\t\t\t\t\t\t\t\t((await em.findOne<any>(propertyMetadata.type, {\n\t\t\t\t\t\t\t\t\t[relatedPrimaryKeyField]: subvalue[relatedPrimaryKeyField],\n\t\t\t\t\t\t\t\t})) as T | null) ?? undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!entity) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Attempted to assign as an update to '${propertyMetadata.name}' property of ${metadata.name} Entity, but even after a full fetch to the database ${propertyMetadata.type} with ID of ${subvalue.id} could not be found.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst newEntity = await createOrAssignEntity<T>({\n\t\t\t\t\tentity,\n\t\t\t\t\tentityType: propertyMetadata.type,\n\t\t\t\t\tprimaryKeyField: relatedPrimaryKeyField,\n\t\t\t\t\tdata: subvalue,\n\t\t\t\t\toptions,\n\t\t\t\t\tvisited,\n\t\t\t\t\tem,\n\t\t\t\t});\n\n\t\t\t\t// Ok, now we've got the created or updated entity, ensure it's in the collection\n\t\t\t\t// so its foreign keys are set correctly. If it's already in the collection this is a noop.\n\t\t\t\tentityPropertyValue.add(newEntity);\n\n\t\t\t\t// We need to keep track of the fact that this entity belongs here so it doesn't get removed in the cleanup step down below.\n\t\t\t\tvisitedEntities.add(newEntity);\n\t\t\t}\n\n\t\t\t// Ok, at this point we know what IDs we visited. If anything is left in the collection that has an ID and has not been visited\n\t\t\t// it needs to be removed from the collection, because this is the canonical list of everything that's in the collection now.\n\t\t\t// ------------\n\t\t\t// \u2757\uD83D\uDC3B WARNING BEAR TRAP \uD83D\uDC3B\u2757: If you're looking at this going, \"But I just want to pass in the items I want to update and for it not to\n\t\t\t// mess with the rest of the collection\", this is here because without this behaviour, there's no way to remove items from\n\t\t\t// Many to Many properties. Consider the case of tags on an entity, when we pass ['a', 'b', 'c'] as the list of tags, that\n\t\t\t// means we need to remove anything that isn't 'a', 'b', or 'c' because it's not in the array.\n\t\t\tentityPropertyValue.remove(\n\t\t\t\tentityPropertyValue.getItems().filter((entity) => !visitedEntities.has(entity))\n\t\t\t);\n\t\t} else if (\n\t\t\tpropertyMetadata?.kind == ReferenceKind.MANY_TO_ONE ||\n\t\t\tpropertyMetadata?.kind === ReferenceKind.ONE_TO_ONE\n\t\t) {\n\t\t\tif (value === null) {\n\t\t\t\t// If the value is null, unset the reference\n\t\t\t\t(entity as any)[property] = null;\n\t\t\t} else {\n\t\t\t\tconst valueKeys = Object.keys(value as any);\n\t\t\t\tconst relatedEntity = em.getMetadata().find(propertyMetadata.entity());\n\t\t\t\tif (!relatedEntity) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Could not find entity ${propertyMetadata.entity()} in MikroORM metadata.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (relatedEntity.primaryKeys.length !== 1) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Entity ${propertyMetadata.entity()} has ${relatedEntity.primaryKeys.length} primary keys, but we only support 1.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst relatedPrimaryKeyField = relatedEntity.primaryKeys[0];\n\n\t\t\t\tif (valueKeys.length === 1 && valueKeys[0] === relatedPrimaryKeyField) {\n\t\t\t\t\t// Ok, this is just the ID, set the reference and move on.\n\t\t\t\t\tentity[property as keyof T] = em.getReference(\n\t\t\t\t\t\tpropertyMetadata.type,\n\t\t\t\t\t\t(value as any)[relatedPrimaryKeyField]\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tif (entityPropertyValue && !Reference.isReference(entityPropertyValue)) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Trying to merge to related property ${property} on entity ${metadata.name} which is not a reference.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Reference.isReference(entityPropertyValue) && !entityPropertyValue.isInitialized()) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Trying to merge to related property ${property} on entity ${metadata.name} which is not initialised.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newEntity = await createOrAssignEntity<T>({\n\t\t\t\t\t\tentity: (entityPropertyValue as Reference<T>)?.unwrap(),\n\t\t\t\t\t\tentityType: propertyMetadata.type,\n\t\t\t\t\t\tprimaryKeyField: relatedPrimaryKeyField,\n\t\t\t\t\t\tdata: value as EntityData<T>,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\tvisited,\n\t\t\t\t\t\tem,\n\t\t\t\t\t});\n\n\t\t\t\t\t(relatedEntity as any)[property] = Reference.create(newEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Ok, we're a simple scalar.\n\t\t\t(entity as any)[property] = value;\n\t\t}\n\t}\n\n\treturn entity;\n};\n\nconst createOrAssignEntity = <T extends AnyEntity<T>>({\n\tentity,\n\tentityType,\n\tprimaryKeyField,\n\tdata,\n\toptions,\n\tvisited,\n\tem,\n}: {\n\tentity?: T;\n\tentityType: string;\n\tprimaryKeyField: string;\n\tdata: EntityData<T>;\n\toptions?: AssignOptions;\n\tvisited: Set<AnyEntity<any>>;\n\tem: EntityManager;\n}) => {\n\tconst create = options?.create ?? true;\n\tconst update = options?.update ?? true;\n\n\tif ((data as any)[primaryKeyField]) {\n\t\tif (!update) {\n\t\t\tthrow new Error(\n\t\t\t\t`Updates are disabled, but update value ${JSON.stringify(\n\t\t\t\t\tdata\n\t\t\t\t)} was passed which has an ID property.`\n\t\t\t);\n\t\t}\n\n\t\tif (!entity) {\n\t\t\tthrow new Error(\n\t\t\t\t`Tried to update with data ${JSON.stringify(\n\t\t\t\t\tdata\n\t\t\t\t)} but entity could not be located to update.`\n\t\t\t);\n\t\t}\n\n\t\t// Ok, we need to recurse here.\n\t\treturn assign(entity, data, options, visited);\n\t} else {\n\t\tif (!create) {\n\t\t\tthrow new Error(\n\t\t\t\t`Creates are disabled, but update value ${JSON.stringify(\n\t\t\t\t\tdata\n\t\t\t\t)} was passed which does not have an ID property.`\n\t\t\t);\n\t\t}\n\n\t\t// We don't want Mikro to manage the data merging here, we'll do it in the next line.\n\t\tconst entity = em.create<T>(entityType, {} as any);\n\t\treturn assign(entity, data, options, visited);\n\t}\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["entity"]
|
|
7
|
+
}
|
|
@@ -13,7 +13,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
13
13
|
};
|
|
14
14
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
15
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
-
var
|
|
17
|
-
module.exports = __toCommonJS(
|
|
18
|
-
__reExport(
|
|
16
|
+
var provider_exports = {};
|
|
17
|
+
module.exports = __toCommonJS(provider_exports);
|
|
18
|
+
__reExport(provider_exports, require("./provider"), module.exports);
|
|
19
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
20
|
+
0 && (module.exports = {
|
|
21
|
+
...require("./provider")
|
|
22
|
+
});
|
|
19
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BackendProvider, PaginationOptions, Filter,
|
|
1
|
+
import { BackendProvider, PaginationOptions, Filter, BackendProviderConfig, FieldMetadata } from '@exogee/graphweaver';
|
|
2
2
|
import { IsolationLevel, ConnectionOptions } from '..';
|
|
3
3
|
import { ApolloServerPlugin, BaseContext } from '@apollo/server';
|
|
4
4
|
export declare const gqlToMikro: (filter: any) => any;
|
|
5
|
-
export declare class MikroBackendProvider<D
|
|
5
|
+
export declare class MikroBackendProvider<D> implements BackendProvider<D> {
|
|
6
6
|
private _backendId;
|
|
7
7
|
private connection;
|
|
8
8
|
entityType: new () => D;
|
|
@@ -14,27 +14,25 @@ export declare class MikroBackendProvider<D extends BaseDataEntity, G extends Gr
|
|
|
14
14
|
private get database();
|
|
15
15
|
get transactional(): <T>(callback: () => Promise<T>, isolationLevel?: IsolationLevel) => Promise<T>;
|
|
16
16
|
withTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
|
17
|
-
get em(): import("@mikro-orm/postgresql").EntityManager<import("@mikro-orm/postgresql").PostgreSqlDriver> | import("@mikro-orm/postgresql").EntityManager<import("@mikro-orm/mysql").MySqlDriver>;
|
|
18
|
-
private getRepository;
|
|
17
|
+
get em(): import("@mikro-orm/postgresql").EntityManager<import("@mikro-orm/postgresql").PostgreSqlDriver> | import("@mikro-orm/postgresql").EntityManager<import("@mikro-orm/mysql").MySqlDriver> | import("@mikro-orm/postgresql").EntityManager<import("@mikro-orm/sqlite").SqliteDriver>;
|
|
19
18
|
constructor(mikroType: new () => D, connection: ConnectionOptions, transactionIsolationLevel?: IsolationLevel);
|
|
20
19
|
private mapAndAssignKeys;
|
|
21
20
|
private applyExternalIdFields;
|
|
22
21
|
visitPathForPopulate: (entityName: string, updateArgBranch: any, populateBranch?: string) => Set<string>;
|
|
23
|
-
find(filter: Filter<
|
|
24
|
-
findOne(filter: Filter<
|
|
22
|
+
find(filter: Filter<D>, pagination?: PaginationOptions, additionalOptionsForBackend?: any): Promise<D[]>;
|
|
23
|
+
findOne(filter: Filter<D>): Promise<D | null>;
|
|
25
24
|
findByRelatedId(entity: any, relatedField: string, relatedFieldIds: string[], filter?: any): Promise<D[]>;
|
|
26
|
-
updateOne(id: string, updateArgs: Partial<
|
|
25
|
+
updateOne(id: string | number, updateArgs: Partial<D & {
|
|
27
26
|
version?: number;
|
|
28
27
|
}>): Promise<D>;
|
|
29
|
-
updateMany(updateItems: (Partial<
|
|
28
|
+
updateMany(updateItems: (Partial<D> & {
|
|
30
29
|
id: string;
|
|
31
30
|
})[]): Promise<D[]>;
|
|
32
|
-
createOrUpdateMany(items: Partial<
|
|
33
|
-
createOne(createArgs: Partial<
|
|
34
|
-
createMany(createItems: Partial<
|
|
35
|
-
deleteOne(filter: Filter<
|
|
36
|
-
deleteMany(filter: Filter<
|
|
37
|
-
|
|
38
|
-
isCollection(entity: unknown): entity is Iterable<unknown & WithId>;
|
|
31
|
+
createOrUpdateMany(items: Partial<D>[]): Promise<D[]>;
|
|
32
|
+
createOne(createArgs: Partial<D>): Promise<D>;
|
|
33
|
+
createMany(createItems: Partial<D>[]): Promise<D[]>;
|
|
34
|
+
deleteOne(filter: Filter<D>): Promise<boolean>;
|
|
35
|
+
deleteMany(filter: Filter<D>): Promise<boolean>;
|
|
36
|
+
foreignKeyForRelationshipField?(field: FieldMetadata, dataEntity: D): any;
|
|
39
37
|
get plugins(): ApolloServerPlugin<BaseContext>[];
|
|
40
38
|
}
|
|
@@ -27,33 +27,16 @@ var import_logger = require("@exogee/logger");
|
|
|
27
27
|
var import__ = require("..");
|
|
28
28
|
var import_errors = require("../utils/errors");
|
|
29
29
|
var import_assign = require("./assign");
|
|
30
|
+
var import_core = require("@mikro-orm/core");
|
|
30
31
|
const objectOperations = /* @__PURE__ */ new Set(["_and", "_or", "_not"]);
|
|
31
32
|
const mikroObjectOperations = /* @__PURE__ */ new Set(["$and", "$or", "$not"]);
|
|
32
|
-
const nonJoinKeys = /* @__PURE__ */ new Set([
|
|
33
|
-
"$and",
|
|
34
|
-
"$gt",
|
|
35
|
-
"$gte",
|
|
36
|
-
"$in",
|
|
37
|
-
"$lt",
|
|
38
|
-
"$lte",
|
|
39
|
-
"$ne",
|
|
40
|
-
"$nin",
|
|
41
|
-
"$not",
|
|
42
|
-
"$or",
|
|
43
|
-
"$like",
|
|
44
|
-
"$ilike",
|
|
45
|
-
"$null",
|
|
46
|
-
"$notnull",
|
|
47
|
-
"id"
|
|
48
|
-
]);
|
|
49
33
|
const appendPath = (path, newPath) => path.length ? `${path}.${newPath}` : newPath;
|
|
50
34
|
const gqlToMikro = (filter) => {
|
|
51
35
|
if (Array.isArray(filter)) {
|
|
52
36
|
return filter.map((element) => gqlToMikro(element));
|
|
53
37
|
} else if (typeof filter === "object") {
|
|
54
38
|
for (const key of Object.keys(filter)) {
|
|
55
|
-
if (filter[key] === null)
|
|
56
|
-
continue;
|
|
39
|
+
if (filter[key] === null) continue;
|
|
57
40
|
if (objectOperations.has(key)) {
|
|
58
41
|
filter[key.replace("_", "$")] = gqlToMikro(filter[key]);
|
|
59
42
|
delete filter[key];
|
|
@@ -76,6 +59,7 @@ const gqlToMikro = (filter) => {
|
|
|
76
59
|
class MikroBackendProvider {
|
|
77
60
|
constructor(mikroType, connection, transactionIsolationLevel = import__.IsolationLevel.REPEATABLE_READ) {
|
|
78
61
|
this.supportsInFilter = true;
|
|
62
|
+
// Default backend provider config
|
|
79
63
|
this.backendProviderConfig = {
|
|
80
64
|
filter: {
|
|
81
65
|
root: true,
|
|
@@ -94,12 +78,6 @@ class MikroBackendProvider {
|
|
|
94
78
|
root: false
|
|
95
79
|
}
|
|
96
80
|
};
|
|
97
|
-
this.getRepository = () => {
|
|
98
|
-
const repository = this.database.em.getRepository(this.entityType);
|
|
99
|
-
if (!repository)
|
|
100
|
-
throw new Error("Could not find repository for " + this.entityType.name);
|
|
101
|
-
return repository;
|
|
102
|
-
};
|
|
103
81
|
this.mapAndAssignKeys = (result, entityType, inputArgs) => {
|
|
104
82
|
const assignmentObj = this.applyExternalIdFields(entityType, inputArgs);
|
|
105
83
|
return (0, import_assign.assign)(result, assignmentObj, void 0, void 0, this.database.em);
|
|
@@ -144,11 +122,15 @@ class MikroBackendProvider {
|
|
|
144
122
|
});
|
|
145
123
|
return values;
|
|
146
124
|
};
|
|
125
|
+
// Check if we have any keys that are a collection of entities
|
|
147
126
|
this.visitPathForPopulate = (entityName, updateArgBranch, populateBranch = "") => {
|
|
148
127
|
const { properties } = this.database.em.getMetadata().get(entityName);
|
|
149
128
|
const collectedPaths = populateBranch ? /* @__PURE__ */ new Set([populateBranch]) : /* @__PURE__ */ new Set([]);
|
|
150
129
|
for (const [key, value] of Object.entries(updateArgBranch ?? {})) {
|
|
151
|
-
if (
|
|
130
|
+
if (
|
|
131
|
+
// If it's a relationship, go ahead and and '.' it in, recurse.
|
|
132
|
+
properties[key]?.kind === import__.ReferenceKind.ONE_TO_ONE || properties[key]?.kind === import__.ReferenceKind.ONE_TO_MANY || properties[key]?.kind === import__.ReferenceKind.MANY_TO_ONE || properties[key]?.kind === import__.ReferenceKind.MANY_TO_MANY
|
|
133
|
+
) {
|
|
152
134
|
if (Array.isArray(value)) {
|
|
153
135
|
collectedPaths.add(appendPath(populateBranch, key));
|
|
154
136
|
for (const entry of value) {
|
|
@@ -181,16 +163,17 @@ class MikroBackendProvider {
|
|
|
181
163
|
return this._backendId;
|
|
182
164
|
}
|
|
183
165
|
get database() {
|
|
184
|
-
if (!this.connectionManagerId)
|
|
185
|
-
return import__.ConnectionManager.default;
|
|
166
|
+
if (!this.connectionManagerId) return import__.ConnectionManager.default;
|
|
186
167
|
return import__.ConnectionManager.database(this.connectionManagerId) || import__.ConnectionManager.default;
|
|
187
168
|
}
|
|
169
|
+
// This is exposed for use in the RLS package
|
|
188
170
|
get transactional() {
|
|
189
171
|
return this.database.transactional;
|
|
190
172
|
}
|
|
191
173
|
async withTransaction(callback) {
|
|
192
174
|
return this.database.transactional(callback, this.transactionIsolationLevel);
|
|
193
175
|
}
|
|
176
|
+
// This is exposed for use in the RLS package
|
|
194
177
|
get em() {
|
|
195
178
|
return this.database.em;
|
|
196
179
|
}
|
|
@@ -200,7 +183,7 @@ class MikroBackendProvider {
|
|
|
200
183
|
});
|
|
201
184
|
const where = filter ? gqlToMikro(JSON.parse(JSON.stringify(filter))) : void 0;
|
|
202
185
|
const whereWithAppliedExternalIdFields = where ? this.applyExternalIdFields(this.entityType, where) : {};
|
|
203
|
-
const query = this.
|
|
186
|
+
const query = this.em.createQueryBuilder(this.entityType);
|
|
204
187
|
if (Object.keys(whereWithAppliedExternalIdFields).length > 0) {
|
|
205
188
|
query.andWhere(whereWithAppliedExternalIdFields);
|
|
206
189
|
}
|
|
@@ -235,13 +218,23 @@ class MikroBackendProvider {
|
|
|
235
218
|
}
|
|
236
219
|
async findOne(filter) {
|
|
237
220
|
import_logger.logger.trace(`Running findOne ${this.entityType.name} with filter ${filter}`);
|
|
238
|
-
const
|
|
221
|
+
const metadata = this.em.getMetadata().get(this.entityType.name);
|
|
222
|
+
if (metadata.primaryKeys.length !== 1) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
`Entity ${this.entityType.name} has ${metadata.primaryKeys.length} primary keys. We only support entities with a single primary key at this stage.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const [result] = await this.find(filter, {
|
|
228
|
+
orderBy: { [metadata.primaryKeys[0]]: import_graphweaver.Sort.DESC },
|
|
229
|
+
offset: 0,
|
|
230
|
+
limit: 1
|
|
231
|
+
});
|
|
239
232
|
import_logger.logger.trace(`findOne ${this.entityType.name} result`, { result });
|
|
240
233
|
return result;
|
|
241
234
|
}
|
|
242
235
|
async findByRelatedId(entity, relatedField, relatedFieldIds, filter) {
|
|
243
236
|
const queryFilter = {
|
|
244
|
-
$and: [{ [relatedField]: { $in: relatedFieldIds } }, ...[filter ?? []]]
|
|
237
|
+
$and: [{ [relatedField]: { $in: relatedFieldIds } }, ...[gqlToMikro(filter) ?? []]]
|
|
245
238
|
};
|
|
246
239
|
const populate = [relatedField];
|
|
247
240
|
const result = await this.database.em.find(entity, queryFilter, {
|
|
@@ -255,6 +248,7 @@ class MikroBackendProvider {
|
|
|
255
248
|
updateArgs: JSON.stringify(updateArgs)
|
|
256
249
|
});
|
|
257
250
|
const entity = await this.database.em.findOne(this.entityType, id, {
|
|
251
|
+
// This is an optimisation so that assign() doesn't have to go fetch everything one at a time.
|
|
258
252
|
populate: [...this.visitPathForPopulate(this.entityType.name, updateArgs)]
|
|
259
253
|
});
|
|
260
254
|
if (entity === null) {
|
|
@@ -280,8 +274,7 @@ class MikroBackendProvider {
|
|
|
280
274
|
const entities = await this.database.transactional(async () => {
|
|
281
275
|
return Promise.all(
|
|
282
276
|
updateItems.map(async (item) => {
|
|
283
|
-
if (!item?.id)
|
|
284
|
-
throw new Error("You must pass an ID for this entity to update it.");
|
|
277
|
+
if (!item?.id) throw new Error("You must pass an ID for this entity to update it.");
|
|
285
278
|
const entity = await this.database.em.findOneOrFail(this.entityType, item.id, {
|
|
286
279
|
populate: [...this.visitPathForPopulate(this.entityType.name, item)]
|
|
287
280
|
});
|
|
@@ -390,17 +383,26 @@ class MikroBackendProvider {
|
|
|
390
383
|
import_logger.logger.trace(`delete ${this.entityType.name} result: deleted ${deletedRows} row(s)`);
|
|
391
384
|
return true;
|
|
392
385
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
386
|
+
foreignKeyForRelationshipField(field, dataEntity) {
|
|
387
|
+
const value = dataEntity[field.name];
|
|
388
|
+
if (import_core.Reference.isReference(value)) {
|
|
389
|
+
const { properties } = this.database.em.getMetadata().get(this.entityType);
|
|
390
|
+
const property = properties[field.name];
|
|
391
|
+
const [primaryKey] = property.targetMeta?.primaryKeys ?? [];
|
|
392
|
+
if (!primaryKey) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`Could not determine primary key for ${field.name} on ${this.entityType.name}`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
const foreignKey = value.unwrap()[primaryKey];
|
|
398
|
+
if (foreignKey === void 0 || foreignKey === null) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
`Could not read foreign key from reference: ${value.unwrap()} with primary key name ${primaryKey}`
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
return foreignKey;
|
|
399
404
|
}
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
isCollection(entity) {
|
|
403
|
-
return import__.Utils.isCollection(entity);
|
|
405
|
+
return null;
|
|
404
406
|
}
|
|
405
407
|
get plugins() {
|
|
406
408
|
return [import__.ClearDatabaseContext, (0, import__.connectToDatabase)(this.connection)];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/provider/provider.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n\tBackendProvider,\n\tPaginationOptions,\n\tSort,\n\tFilter,\n\tBackendProviderConfig,\n\tFieldMetadata,\n} from '@exogee/graphweaver';\nimport { logger } from '@exogee/logger';\n\nimport {\n\tLockMode,\n\tQueryFlag,\n\tReferenceKind,\n\tConnectionManager,\n\texternalIdFieldMap,\n\tAnyEntity,\n\tIsolationLevel,\n\tConnectionOptions,\n\tClearDatabaseContext,\n\tconnectToDatabase,\n} from '..';\n\nimport { OptimisticLockError } from '../utils/errors';\nimport { assign } from './assign';\n\nimport { Reference } from '@mikro-orm/core';\nimport { AutoPath, PopulateHint } from '@mikro-orm/postgresql';\nimport { ApolloServerPlugin, BaseContext } from '@apollo/server';\n\ntype PostgresError = {\n\tcode: string;\n\troutine: string;\n};\n\nconst objectOperations = new Set(['_and', '_or', '_not']);\nconst mikroObjectOperations = new Set(['$and', '$or', '$not']);\n\nconst appendPath = (path: string, newPath: string) =>\n\tpath.length ? `${path}.${newPath}` : newPath;\n\nexport const gqlToMikro: (filter: any) => any = (filter: any) => {\n\tif (Array.isArray(filter)) {\n\t\treturn filter.map((element) => gqlToMikro(element));\n\t} else if (typeof filter === 'object') {\n\t\tfor (const key of Object.keys(filter)) {\n\t\t\t// A null here is a user-specified value and is valid to filter on\n\t\t\tif (filter[key] === null) continue;\n\n\t\t\tif (objectOperations.has(key)) {\n\t\t\t\t// { _not: '1' } => { $not: '1' }\n\t\t\t\tfilter[key.replace('_', '$')] = gqlToMikro(filter[key]);\n\t\t\t\tdelete filter[key];\n\t\t\t} else if (typeof filter[key] === 'object' && !Array.isArray(filter[key])) {\n\t\t\t\t// Recurse over nested filters only (arrays are an argument to a filter, not a nested filter)\n\t\t\t\tfilter[key] = gqlToMikro(filter[key]);\n\t\t\t} else if (key.indexOf('_') >= 0) {\n\t\t\t\t// { firstName_in: ['k', 'b'] } => { firstName: { $in: ['k', 'b'] } }\n\t\t\t\tconst [newKey, operator] = key.split('_');\n\t\t\t\tconst newValue = { [`$${operator}`]: gqlToMikro(filter[key]) };\n\n\t\t\t\t// They can construct multiple filters for the same key. In that case we need\n\t\t\t\t// to append them all into an object.\n\t\t\t\tif (typeof filter[newKey] !== 'undefined') {\n\t\t\t\t\tfilter[newKey] = { ...filter[newKey], ...newValue };\n\t\t\t\t} else {\n\t\t\t\t\tfilter[newKey] = newValue;\n\t\t\t\t}\n\n\t\t\t\tdelete filter[key];\n\t\t\t}\n\t\t}\n\t}\n\treturn filter;\n};\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport class MikroBackendProvider<D> implements BackendProvider<D> {\n\tprivate _backendId: string;\n\n\tprivate connection: ConnectionOptions;\n\n\tpublic entityType: new () => D;\n\tpublic connectionManagerId?: string;\n\tprivate transactionIsolationLevel!: IsolationLevel;\n\n\tpublic readonly supportsInFilter = true;\n\n\t// Default backend provider config\n\tpublic readonly backendProviderConfig: BackendProviderConfig = {\n\t\tfilter: {\n\t\t\troot: true,\n\t\t\tparentByChild: true,\n\t\t\tchildByChild: true,\n\t\t},\n\t\tpagination: {\n\t\t\troot: false,\n\t\t\toffset: false,\n\t\t\tlimit: false,\n\t\t},\n\t\torderBy: {\n\t\t\troot: false,\n\t\t},\n\t\tsort: {\n\t\t\troot: false,\n\t\t},\n\t};\n\n\tget backendId() {\n\t\treturn this._backendId;\n\t}\n\n\tprivate get database() {\n\t\t// If we have a connection manager ID then use that else fallback to the Database\n\t\tif (!this.connectionManagerId) return ConnectionManager.default;\n\t\treturn ConnectionManager.database(this.connectionManagerId) || ConnectionManager.default;\n\t}\n\n\t// This is exposed for use in the RLS package\n\tpublic get transactional() {\n\t\treturn this.database.transactional;\n\t}\n\n\tpublic async withTransaction<T>(callback: () => Promise<T>) {\n\t\treturn this.database.transactional<T>(callback, this.transactionIsolationLevel);\n\t}\n\n\t// This is exposed for use in the RLS package\n\tpublic get em() {\n\t\treturn this.database.em;\n\t}\n\n\tpublic constructor(\n\t\tmikroType: new () => D,\n\t\tconnection: ConnectionOptions,\n\t\ttransactionIsolationLevel: IsolationLevel = IsolationLevel.REPEATABLE_READ\n\t) {\n\t\tthis.entityType = mikroType;\n\t\tthis.connectionManagerId = connection.connectionManagerId;\n\t\tthis._backendId = `mikro-orm-${connection.connectionManagerId || ''}`;\n\t\tthis.transactionIsolationLevel = transactionIsolationLevel;\n\t\tthis.connection = connection;\n\t}\n\n\tprivate mapAndAssignKeys = (result: D, entityType: new () => D, inputArgs: Partial<D>) => {\n\t\t// Clean the input and remove any GraphQL classes from the object\n\t\tconst assignmentObj = this.applyExternalIdFields(entityType, inputArgs);\n\t\treturn assign(result, assignmentObj, undefined, undefined, this.database.em);\n\t};\n\n\tprivate applyExternalIdFields = (target: AnyEntity | string, values: any) => {\n\t\tconst targetName = typeof target === 'string' ? target : target.name;\n\t\tconst map = externalIdFieldMap.get(targetName);\n\n\t\tconst mapFieldNames = (partialFilterObj: any) => {\n\t\t\tfor (const [from, to] of Object.entries(map || {})) {\n\t\t\t\tif (partialFilterObj[from] && typeof partialFilterObj[from].id !== 'undefined') {\n\t\t\t\t\tif (Object.keys(partialFilterObj[from]).length > 1) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Expected precisely 1 key called 'id' in queryObj.${from} on ${target}, got ${JSON.stringify(\n\t\t\t\t\t\t\t\tpartialFilterObj[from],\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t4\n\t\t\t\t\t\t\t)}`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tpartialFilterObj[to] = partialFilterObj[from].id;\n\t\t\t\t\tdelete partialFilterObj[from];\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Check for and/or/etc at the root level and handle correctly\n\t\tfor (const rootLevelKey of Object.keys(values)) {\n\t\t\tif (mikroObjectOperations.has(rootLevelKey)) {\n\t\t\t\tfor (const field of values[rootLevelKey]) {\n\t\t\t\t\tmapFieldNames(field);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Map the rest of the field names as well\n\t\tmapFieldNames(values);\n\n\t\t// Traverse the nested entities\n\t\tconst { properties } = this.database.em.getMetadata().get(targetName);\n\t\tObject.values(properties)\n\t\t\t.filter((property) => typeof property.entity !== 'undefined' && values[property.name])\n\t\t\t.forEach((property) => {\n\t\t\t\tif (Array.isArray(values[property.name])) {\n\t\t\t\t\tvalues[property.name].forEach((value: any) =>\n\t\t\t\t\t\tthis.applyExternalIdFields(property.type, value)\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tvalues[property.name] = this.applyExternalIdFields(property.type, values[property.name]);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn values;\n\t};\n\n\t// Check if we have any keys that are a collection of entities\n\tpublic visitPathForPopulate = (entityName: string, updateArgBranch: any, populateBranch = '') => {\n\t\tconst { properties } = this.database.em.getMetadata().get(entityName);\n\t\tconst collectedPaths = populateBranch ? new Set<string>([populateBranch]) : new Set<string>([]);\n\n\t\tfor (const [key, value] of Object.entries(updateArgBranch ?? {})) {\n\t\t\tif (\n\t\t\t\t// If it's a relationship, go ahead and and '.' it in, recurse.\n\t\t\t\tproperties[key]?.kind === ReferenceKind.ONE_TO_ONE ||\n\t\t\t\tproperties[key]?.kind === ReferenceKind.ONE_TO_MANY ||\n\t\t\t\tproperties[key]?.kind === ReferenceKind.MANY_TO_ONE ||\n\t\t\t\tproperties[key]?.kind === ReferenceKind.MANY_TO_MANY\n\t\t\t) {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t// In the case where the array is empty we also need to make sure we load the collection.\n\t\t\t\t\tcollectedPaths.add(appendPath(populateBranch, key));\n\n\t\t\t\t\tfor (const entry of value) {\n\t\t\t\t\t\t// Recurse\n\t\t\t\t\t\tconst newPaths = this.visitPathForPopulate(\n\t\t\t\t\t\t\tproperties[key].type,\n\t\t\t\t\t\t\tentry,\n\t\t\t\t\t\t\tappendPath(populateBranch, key)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tnewPaths.forEach((path) => collectedPaths.add(path));\n\t\t\t\t\t}\n\t\t\t\t} else if (typeof value === 'object') {\n\t\t\t\t\t// Recurse\n\t\t\t\t\tconst newPaths = this.visitPathForPopulate(\n\t\t\t\t\t\tproperties[key].type,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tappendPath(populateBranch, key)\n\t\t\t\t\t);\n\t\t\t\t\tnewPaths.forEach((path) => collectedPaths.add(path));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn collectedPaths;\n\t};\n\n\tpublic async find(\n\t\tfilter: Filter<D>,\n\t\tpagination?: PaginationOptions,\n\t\tadditionalOptionsForBackend?: any // @todo: Create a type for this\n\t): Promise<D[]> {\n\t\tlogger.trace(`Running find ${this.entityType.name} with filter`, {\n\t\t\tfilter: JSON.stringify(filter),\n\t\t});\n\n\t\t// Strip custom types out of the equation.\n\t\t// This query only works if we JSON.parse(JSON.stringify(filter)):\n\t\t//\n\t\t// query {\n\t\t// drivers (filter: { region: { name: \"North Shore\" }}) {\n\t\t// id\n\t\t// }\n\t\t// }\n\t\tconst where = filter ? gqlToMikro(JSON.parse(JSON.stringify(filter))) : undefined;\n\n\t\t// Convert from: { account: {id: '6' }}\n\t\t// to { accountId: '6' }\n\t\t// This conversion only works on root level objects\n\t\tconst whereWithAppliedExternalIdFields = where\n\t\t\t? this.applyExternalIdFields(this.entityType, where)\n\t\t\t: {};\n\n\t\t// Regions need some fancy handling with Query Builder. Process the where further\n\t\t// and return a Query Builder instance.\n\t\tconst query = this.em.createQueryBuilder(this.entityType);\n\t\tif (Object.keys(whereWithAppliedExternalIdFields).length > 0) {\n\t\t\tquery.andWhere(whereWithAppliedExternalIdFields);\n\t\t}\n\n\t\t// If we have specified a limit, offset or order then update the query\n\t\tpagination?.limit && query.limit(pagination.limit);\n\t\tpagination?.offset && query.offset(pagination.offset);\n\t\tpagination?.orderBy && query.orderBy({ ...pagination.orderBy });\n\n\t\t// Certain query filters can result in duplicate records once all joins are resolved\n\t\t// These duplicates can be discarded as related entities are returned to the\n\t\t// API consumer via field resolvers\n\t\tquery.setFlag(QueryFlag.DISTINCT);\n\n\t\t// 1:1 relations that aren't on the owning side need to get populated so the references get set.\n\t\t// This method is protected, but we need to use it from here, hence the `as any`.\n\t\tconst driver = this.database.em.getDriver();\n\t\tconst meta = this.database.em.getMetadata().get(this.entityType.name);\n\t\tquery.populate((driver as any).autoJoinOneToOneOwner(meta, []));\n\n\t\tif (additionalOptionsForBackend?.populate) {\n\t\t\tquery.populate(additionalOptionsForBackend.populate);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await query.getResult();\n\t\t\tlogger.trace(`find ${this.entityType.name} result: ${result.length} rows`);\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tlogger.error(`find ${this.entityType.name} error: ${JSON.stringify(err)}`);\n\n\t\t\tif ((err as PostgresError)?.routine === 'InitializeSessionUserId') {\n\t\t\t\t// Throw if the user credentials are incorrect\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Database connection failed, please check you are using the correct user credentials for the database.'\n\t\t\t\t);\n\t\t\t} else if ((err as PostgresError)?.code === 'ECONNREFUSED') {\n\t\t\t\t// Throw if the database address or port is incorrect\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Database connection failed, please check you are using the correct address and port for the database.'\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async findOne(filter: Filter<D>): Promise<D | null> {\n\t\tlogger.trace(`Running findOne ${this.entityType.name} with filter ${filter}`);\n\n\t\tconst metadata = this.em.getMetadata().get(this.entityType.name);\n\t\tif (metadata.primaryKeys.length !== 1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Entity ${this.entityType.name} has ${metadata.primaryKeys.length} primary keys. We only support entities with a single primary key at this stage.`\n\t\t\t);\n\t\t}\n\n\t\tconst [result] = await this.find(filter, {\n\t\t\torderBy: { [metadata.primaryKeys[0]]: Sort.DESC },\n\t\t\toffset: 0,\n\t\t\tlimit: 1,\n\t\t});\n\n\t\tlogger.trace(`findOne ${this.entityType.name} result`, { result });\n\n\t\treturn result;\n\t}\n\n\tpublic async findByRelatedId(\n\t\tentity: any,\n\t\trelatedField: string,\n\t\trelatedFieldIds: string[],\n\t\tfilter?: any\n\t): Promise<D[]> {\n\t\tconst queryFilter = {\n\t\t\t$and: [{ [relatedField]: { $in: relatedFieldIds } }, ...[gqlToMikro(filter) ?? []]],\n\t\t};\n\n\t\tconst populate = [relatedField as AutoPath<typeof entity, PopulateHint>];\n\t\tconst result = await this.database.em.find(entity, queryFilter, {\n\t\t\tpopulate,\n\t\t});\n\n\t\treturn result as D[];\n\t}\n\n\tpublic async updateOne(\n\t\tid: string | number,\n\t\tupdateArgs: Partial<D & { version?: number }>\n\t): Promise<D> {\n\t\tlogger.trace(`Running update ${this.entityType.name} with args`, {\n\t\t\tid,\n\t\t\tupdateArgs: JSON.stringify(updateArgs),\n\t\t});\n\n\t\tconst entity = await this.database.em.findOne(this.entityType, id, {\n\t\t\t// This is an optimisation so that assign() doesn't have to go fetch everything one at a time.\n\t\t\tpopulate: [...this.visitPathForPopulate(this.entityType.name, updateArgs)] as `${string}.`[],\n\t\t});\n\n\t\tif (entity === null) {\n\t\t\tthrow new Error(`Unable to locate ${this.entityType.name} with ID: '${id}' for updating.`);\n\t\t}\n\n\t\t// If a version has been sent, let's check it\n\t\tif (updateArgs?.version) {\n\t\t\ttry {\n\t\t\t\tawait this.database.em.lock(entity, LockMode.OPTIMISTIC, updateArgs.version);\n\t\t\t\tdelete updateArgs.version;\n\t\t\t} catch (err) {\n\t\t\t\tthrow new OptimisticLockError((err as Error)?.message, { entity });\n\t\t\t}\n\t\t}\n\n\t\tawait this.mapAndAssignKeys(entity, this.entityType, updateArgs);\n\t\tawait this.database.em.persistAndFlush(entity);\n\n\t\tlogger.trace(`update ${this.entityType.name} entity`, entity);\n\n\t\treturn entity;\n\t}\n\n\tpublic async updateMany(updateItems: (Partial<D> & { id: string })[]): Promise<D[]> {\n\t\tlogger.trace(`Running update many ${this.entityType.name} with args`, {\n\t\t\tupdateItems: JSON.stringify(updateItems),\n\t\t});\n\n\t\tconst entities = await this.database.transactional<D[]>(async () => {\n\t\t\treturn Promise.all<D>(\n\t\t\t\tupdateItems.map(async (item) => {\n\t\t\t\t\tif (!item?.id) throw new Error('You must pass an ID for this entity to update it.');\n\n\t\t\t\t\t// Find the entity in the database\n\t\t\t\t\tconst entity = await this.database.em.findOneOrFail(this.entityType, item.id, {\n\t\t\t\t\t\tpopulate: [...this.visitPathForPopulate(this.entityType.name, item)] as `${string}.`[],\n\t\t\t\t\t});\n\t\t\t\t\tawait this.mapAndAssignKeys(entity, this.entityType, item);\n\t\t\t\t\tthis.database.em.persist(entity);\n\t\t\t\t\treturn entity;\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\n\t\tlogger.trace(`updated ${this.entityType.name} items `, entities);\n\n\t\treturn entities;\n\t}\n\n\tpublic async createOrUpdateMany(items: Partial<D>[]): Promise<D[]> {\n\t\tlogger.trace(`Running create or update many for ${this.entityType.name} with args`, {\n\t\t\titems: JSON.stringify(items),\n\t\t});\n\n\t\tconst entities = await this.database.transactional<D[]>(async () => {\n\t\t\treturn Promise.all<D>(\n\t\t\t\titems.map(async (item) => {\n\t\t\t\t\tlet entity;\n\t\t\t\t\tconst { id } = item as any;\n\t\t\t\t\tif (id) {\n\t\t\t\t\t\tentity = await this.database.em.findOneOrFail(this.entityType, id, {\n\t\t\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t\t\t...this.visitPathForPopulate(this.entityType.name, item),\n\t\t\t\t\t\t\t] as `${string}.`[],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlogger.trace(`Running update on ${this.entityType.name} with item`, {\n\t\t\t\t\t\t\titem: JSON.stringify(item),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait this.mapAndAssignKeys(entity, this.entityType, item);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tentity = new this.entityType();\n\t\t\t\t\t\tawait this.mapAndAssignKeys(entity, this.entityType, item);\n\t\t\t\t\t\tlogger.trace(`Running create on ${this.entityType.name} with item`, {\n\t\t\t\t\t\t\titem: JSON.stringify(item),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tthis.database.em.persist(entity);\n\t\t\t\t\treturn entity;\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\n\t\tlogger.trace(`created or updated ${this.entityType.name} items `, entities);\n\n\t\treturn entities;\n\t}\n\n\tpublic async createOne(createArgs: Partial<D>): Promise<D> {\n\t\tlogger.trace(`Running create ${this.entityType.name} with args`, {\n\t\t\tcreateArgs: JSON.stringify(createArgs),\n\t\t});\n\n\t\tconst entity = new this.entityType();\n\t\tawait this.mapAndAssignKeys(entity, this.entityType, createArgs);\n\t\tawait this.database.em.persistAndFlush(entity as Partial<D>);\n\n\t\tlogger.trace(`create ${this.entityType.name} result`, entity);\n\n\t\treturn entity;\n\t}\n\n\tpublic async createMany(createItems: Partial<D>[]): Promise<D[]> {\n\t\tlogger.trace(`Running create ${this.entityType.name} with args`, {\n\t\t\tcreateArgs: JSON.stringify(createItems),\n\t\t});\n\n\t\tconst entities = await this.database.transactional<D[]>(async () => {\n\t\t\treturn Promise.all<D>(\n\t\t\t\tcreateItems.map(async (item) => {\n\t\t\t\t\tconst entity = new this.entityType();\n\t\t\t\t\tawait this.mapAndAssignKeys(entity, this.entityType, item);\n\t\t\t\t\tthis.database.em.persist(entity as Partial<D>);\n\t\t\t\t\treturn entity;\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\n\t\tlogger.trace(`created ${this.entityType.name} items `, entities);\n\n\t\treturn entities;\n\t}\n\n\tpublic async deleteOne(filter: Filter<D>): Promise<boolean> {\n\t\tlogger.trace(`Running delete ${this.entityType.name} with filter ${filter}`);\n\t\tconst where = filter ? gqlToMikro(JSON.parse(JSON.stringify(filter))) : undefined;\n\t\tconst whereWithAppliedExternalIdFields =\n\t\t\twhere && this.applyExternalIdFields(this.entityType, where);\n\n\t\tconst deletedRows = await this.database.em.nativeDelete(\n\t\t\tthis.entityType,\n\t\t\twhereWithAppliedExternalIdFields\n\t\t);\n\n\t\tif (deletedRows > 1) {\n\t\t\tthrow new Error('Multiple deleted rows');\n\t\t}\n\n\t\tlogger.trace(`delete ${this.entityType.name} result: deleted ${deletedRows} row(s)`);\n\n\t\treturn deletedRows === 1;\n\t}\n\n\tpublic async deleteMany(filter: Filter<D>): Promise<boolean> {\n\t\tlogger.trace(`Running delete ${this.entityType.name}`);\n\n\t\tconst deletedRows = await this.database.transactional<number>(async () => {\n\t\t\tconst where = filter ? gqlToMikro(JSON.parse(JSON.stringify(filter))) : undefined;\n\t\t\tconst whereWithAppliedExternalIdFields =\n\t\t\t\twhere && this.applyExternalIdFields(this.entityType, where);\n\n\t\t\tconst toDelete = await this.database.em.count(\n\t\t\t\tthis.entityType,\n\t\t\t\twhereWithAppliedExternalIdFields\n\t\t\t);\n\t\t\tconst deletedCount = await this.database.em.nativeDelete(\n\t\t\t\tthis.entityType,\n\t\t\t\twhereWithAppliedExternalIdFields\n\t\t\t);\n\n\t\t\tif (deletedCount !== toDelete) {\n\t\t\t\tthrow new Error('We did not delete any rows, rolling back.');\n\t\t\t}\n\n\t\t\treturn deletedCount;\n\t\t});\n\n\t\tlogger.trace(`delete ${this.entityType.name} result: deleted ${deletedRows} row(s)`);\n\n\t\treturn true;\n\t}\n\n\tpublic foreignKeyForRelationshipField?(field: FieldMetadata, dataEntity: D) {\n\t\tconst value = dataEntity[field.name as keyof D];\n\n\t\tif (Reference.isReference(value)) {\n\t\t\tconst { properties } = this.database.em.getMetadata().get(this.entityType);\n\t\t\tconst property = properties[field.name];\n\t\t\tconst [primaryKey] = property.targetMeta?.primaryKeys ?? [];\n\t\t\tif (!primaryKey) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not determine primary key for ${field.name} on ${this.entityType.name}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst foreignKey = (value.unwrap() as any)[primaryKey];\n\t\t\tif (foreignKey === undefined || foreignKey === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not read foreign key from reference: ${value.unwrap()} with primary key name ${primaryKey}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn foreignKey;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic get plugins(): ApolloServerPlugin<BaseContext>[] {\n\t\treturn [ClearDatabaseContext, connectToDatabase(this.connection)];\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/lib/types/date-type.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Type } from '@mikro-orm/core';
|
|
2
2
|
export declare class DateType extends Type {
|
|
3
|
-
convertToDatabaseValue(value: any
|
|
4
|
-
convertToJSValue(value: any
|
|
5
|
-
getColumnType(
|
|
6
|
-
toJSON(value: any
|
|
3
|
+
convertToDatabaseValue(value: any): any;
|
|
4
|
+
convertToJSValue(value: any): any;
|
|
5
|
+
getColumnType(): string;
|
|
6
|
+
toJSON(value: any): any;
|
|
7
7
|
}
|
package/lib/types/date-type.js
CHANGED
|
@@ -24,30 +24,27 @@ module.exports = __toCommonJS(date_type_exports);
|
|
|
24
24
|
var import_core = require("@mikro-orm/core");
|
|
25
25
|
const DatePattern = /^\d{4}-\d{1,2}-\d{1,2}$/;
|
|
26
26
|
class DateType extends import_core.Type {
|
|
27
|
-
convertToDatabaseValue(value
|
|
28
|
-
if (!value)
|
|
29
|
-
return value;
|
|
27
|
+
convertToDatabaseValue(value) {
|
|
28
|
+
if (!value) return value;
|
|
30
29
|
if (typeof value === "string") {
|
|
31
30
|
const [date] = value.split("T");
|
|
32
31
|
const [year, month, day] = date.split("-");
|
|
33
|
-
return new Date(`${year}-${month}-${day}T00:00:00Z`);
|
|
32
|
+
return /* @__PURE__ */ new Date(`${year}-${month}-${day}T00:00:00Z`);
|
|
34
33
|
}
|
|
35
34
|
throw import_core.ValidationError.invalidType(DateType, value, "JS");
|
|
36
35
|
}
|
|
37
|
-
convertToJSValue(value
|
|
38
|
-
if (!value)
|
|
39
|
-
return value;
|
|
36
|
+
convertToJSValue(value) {
|
|
37
|
+
if (!value) return value;
|
|
40
38
|
if (typeof value === "string" && DatePattern.test(value)) {
|
|
41
39
|
return value;
|
|
42
40
|
}
|
|
43
41
|
throw import_core.ValidationError.invalidType(DateType, value, "database");
|
|
44
42
|
}
|
|
45
|
-
getColumnType(
|
|
43
|
+
getColumnType() {
|
|
46
44
|
return "date";
|
|
47
45
|
}
|
|
48
|
-
toJSON(value
|
|
49
|
-
if (!value)
|
|
50
|
-
return value;
|
|
46
|
+
toJSON(value) {
|
|
47
|
+
if (!value) return value;
|
|
51
48
|
if (value instanceof Date) {
|
|
52
49
|
return `${value.getFullYear()}-${value.getMonth() + 1}-${value.getDate()}`;
|
|
53
50
|
} else if (typeof value === "string") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/types/date-type.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { Type, ValidationError } from '@mikro-orm/core';\n\nconst DatePattern = /^\\d{4}-\\d{1,2}-\\d{1,2}$/;\n\nexport class DateType extends Type {\n\tconvertToDatabaseValue(value: any) {\n\t\tif (!value) return value;\n\n\t\tif (typeof value === 'string') {\n\t\t\tconst [date] = value.split('T');\n\t\t\tconst [year, month, day] = date.split('-');\n\t\t\treturn new Date(`${year}-${month}-${day}T00:00:00Z`);\n\t\t}\n\n\t\tthrow ValidationError.invalidType(DateType, value, 'JS');\n\t}\n\n\tconvertToJSValue(value: any) {\n\t\tif (!value) return value;\n\n\t\tif (typeof value === 'string' && DatePattern.test(value)) {\n\t\t\treturn value;\n\t\t}\n\n\t\tthrow ValidationError.invalidType(DateType, value, 'database');\n\t}\n\n\tgetColumnType() {\n\t\treturn 'date';\n\t}\n\n\ttoJSON(value: any) {\n\t\tif (!value) return value;\n\t\tif (value instanceof Date) {\n\t\t\treturn `${value.getFullYear()}-${value.getMonth() + 1}-${value.getDate()}`;\n\t\t} else if (typeof value === 'string') {\n\t\t\treturn value;\n\t\t}\n\t\tthrow ValidationError.invalidType(DateType, value, 'JS');\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsC;AAEtC,MAAM,cAAc;AAEb,MAAM,iBAAiB,iBAAK;AAAA,EAClC,uBAAuB,OAAY;AAClC,QAAI,CAAC,MAAO,QAAO;AAEnB,QAAI,OAAO,UAAU,UAAU;AAC9B,YAAM,CAAC,IAAI,IAAI,MAAM,MAAM,GAAG;AAC9B,YAAM,CAAC,MAAM,OAAO,GAAG,IAAI,KAAK,MAAM,GAAG;AACzC,aAAO,oBAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,YAAY;AAAA,IACpD;AAEA,UAAM,4BAAgB,YAAY,UAAU,OAAO,IAAI;AAAA,EACxD;AAAA,EAEA,iBAAiB,OAAY;AAC5B,QAAI,CAAC,MAAO,QAAO;AAEnB,QAAI,OAAO,UAAU,YAAY,YAAY,KAAK,KAAK,GAAG;AACzD,aAAO;AAAA,IACR;AAEA,UAAM,4BAAgB,YAAY,UAAU,OAAO,UAAU;AAAA,EAC9D;AAAA,EAEA,gBAAgB;AACf,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,OAAY;AAClB,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,iBAAiB,MAAM;AAC1B,aAAO,GAAG,MAAM,YAAY,CAAC,IAAI,MAAM,SAAS,IAAI,CAAC,IAAI,MAAM,QAAQ,CAAC;AAAA,IACzE,WAAW,OAAO,UAAU,UAAU;AACrC,aAAO;AAAA,IACR;AACA,UAAM,4BAAgB,YAAY,UAAU,OAAO,IAAI;AAAA,EACxD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Type } from '@mikro-orm/core';
|
|
2
2
|
export declare class DecimalType extends Type {
|
|
3
3
|
private readonly precision;
|
|
4
4
|
private readonly scale;
|
|
5
5
|
constructor(precision?: number, scale?: number);
|
|
6
|
-
convertToDatabaseValue(value: any
|
|
7
|
-
convertToJSValue(value: any
|
|
8
|
-
getColumnType(
|
|
9
|
-
toJSON(value: any
|
|
6
|
+
convertToDatabaseValue(value: any): any;
|
|
7
|
+
convertToJSValue(value: any): any;
|
|
8
|
+
getColumnType(): string;
|
|
9
|
+
toJSON(value: any): any;
|
|
10
10
|
}
|
|
@@ -29,37 +29,29 @@ class DecimalType extends import_core.Type {
|
|
|
29
29
|
this.precision = precision;
|
|
30
30
|
this.scale = scale;
|
|
31
31
|
}
|
|
32
|
-
convertToDatabaseValue(value
|
|
33
|
-
if (value == null)
|
|
34
|
-
return value;
|
|
32
|
+
convertToDatabaseValue(value) {
|
|
33
|
+
if (value == null) return value;
|
|
35
34
|
if (value instanceof import_decimal.Decimal) {
|
|
36
|
-
if (value.isNaN())
|
|
37
|
-
|
|
38
|
-
if (!value.isFinite())
|
|
39
|
-
throw new Error("Decimal should be finite");
|
|
35
|
+
if (value.isNaN()) throw new Error("Decimal should not be NaN");
|
|
36
|
+
if (!value.isFinite()) throw new Error("Decimal should be finite");
|
|
40
37
|
return value.toFixed(this.scale);
|
|
41
38
|
}
|
|
42
39
|
throw import_core.ValidationError.invalidType(DecimalType, value, "JS");
|
|
43
40
|
}
|
|
44
|
-
convertToJSValue(value
|
|
45
|
-
if (value == null)
|
|
46
|
-
return value;
|
|
41
|
+
convertToJSValue(value) {
|
|
42
|
+
if (value == null) return value;
|
|
47
43
|
const decimal = new import_decimal.Decimal(value);
|
|
48
|
-
if (!decimal.isFinite())
|
|
49
|
-
throw new Error("Decimal should be finite");
|
|
44
|
+
if (!decimal.isFinite()) throw new Error("Decimal should be finite");
|
|
50
45
|
return decimal;
|
|
51
46
|
}
|
|
52
|
-
getColumnType(
|
|
47
|
+
getColumnType() {
|
|
53
48
|
return `numeric(${this.precision}, ${this.scale})`;
|
|
54
49
|
}
|
|
55
|
-
toJSON(value
|
|
56
|
-
if (value === null || typeof value === "undefined")
|
|
57
|
-
return value;
|
|
50
|
+
toJSON(value) {
|
|
51
|
+
if (value === null || typeof value === "undefined") return value;
|
|
58
52
|
if (value instanceof import_decimal.Decimal) {
|
|
59
|
-
if (value.isNaN())
|
|
60
|
-
|
|
61
|
-
if (!value.isFinite())
|
|
62
|
-
throw new Error("Decimal should be finite");
|
|
53
|
+
if (value.isNaN()) throw new Error("Decimal should not be NaN");
|
|
54
|
+
if (!value.isFinite()) throw new Error("Decimal should be finite");
|
|
63
55
|
return value.toNumber();
|
|
64
56
|
}
|
|
65
57
|
throw import_core.ValidationError.invalidType(DecimalType, value, "JS");
|