prisma-mock 0.10.0 → 0.11.0-alpha.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/README.md +1 -1
- package/lib/index.js +53 -16
- package/lib/indexes.d.ts +7 -0
- package/lib/indexes.js +116 -0
- package/lib/indexes.test.d.ts +1 -0
- package/lib/indexes.test.js +52 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ TODO (has, hasEvery, hasSome, isEmpty, equals)
|
|
|
188
188
|
|
|
189
189
|
- @@id
|
|
190
190
|
- @default
|
|
191
|
-
- @unique
|
|
191
|
+
- @unique
|
|
192
192
|
- @@unique (TODO: no error if duplicate)
|
|
193
193
|
- @relation
|
|
194
194
|
- @updatedAt: Partially supported, value is set at creation (TODO: update value on update)
|
package/lib/index.js
CHANGED
|
@@ -33,6 +33,7 @@ const shallowCompare_1 = require("./utils/shallowCompare");
|
|
|
33
33
|
const deepEqual_1 = require("./utils/deepEqual");
|
|
34
34
|
const deepCopy_1 = require("./utils/deepCopy");
|
|
35
35
|
const getNestedValue_1 = __importDefault(require("./utils/getNestedValue"));
|
|
36
|
+
const indexes_1 = __importDefault(require("./indexes"));
|
|
36
37
|
function IsFieldDefault(f) {
|
|
37
38
|
return f.name !== undefined;
|
|
38
39
|
}
|
|
@@ -62,6 +63,7 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
62
63
|
caseInsensitive: false,
|
|
63
64
|
}) => {
|
|
64
65
|
const manyToManyData = {};
|
|
66
|
+
const indexes = (0, indexes_1.default)();
|
|
65
67
|
// let data = options.data || {}
|
|
66
68
|
// const datamodel = options.datamodel || Prisma.dmmf.datamodel
|
|
67
69
|
const caseInsensitive = options.caseInsensitive || false;
|
|
@@ -71,6 +73,7 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
71
73
|
return name.substr(0, 1).toLowerCase() + name.substr(1);
|
|
72
74
|
};
|
|
73
75
|
const removeMultiFieldIds = (model, data) => {
|
|
76
|
+
/// [tableName][field][value] = Array
|
|
74
77
|
const c = getCamelCase(model.name);
|
|
75
78
|
const idFields = model.idFields || model.primaryKey?.fields;
|
|
76
79
|
const removeId = (ids) => {
|
|
@@ -335,11 +338,14 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
335
338
|
});
|
|
336
339
|
}
|
|
337
340
|
if (c.create || c.createMany) {
|
|
341
|
+
const otherModel = datamodel.models.find((model) => {
|
|
342
|
+
return model.name === field.type;
|
|
343
|
+
});
|
|
338
344
|
const { [field.name]: create, ...rest } = d;
|
|
339
345
|
d = rest;
|
|
340
346
|
// @ts-ignore
|
|
341
347
|
const name = getCamelCase(field.type);
|
|
342
|
-
const delegate = Delegate(name,
|
|
348
|
+
const delegate = Delegate(name, otherModel);
|
|
343
349
|
const joinfield = getJoinField(field);
|
|
344
350
|
if (field.relationFromFields.length > 0) {
|
|
345
351
|
const item = delegate.create({
|
|
@@ -594,6 +600,7 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
594
600
|
if (!joinWhere) {
|
|
595
601
|
return false;
|
|
596
602
|
}
|
|
603
|
+
// return true
|
|
597
604
|
const res = delegate.findMany({
|
|
598
605
|
where: {
|
|
599
606
|
AND: [
|
|
@@ -823,9 +830,19 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
823
830
|
return found;
|
|
824
831
|
};
|
|
825
832
|
const findMany = (args) => {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
833
|
+
const match = matchFnc(args?.where);
|
|
834
|
+
const inc = includes(args);
|
|
835
|
+
// let res = data[prop]
|
|
836
|
+
// .filter(matchFnc(args?.where))
|
|
837
|
+
// .map(includes(args))
|
|
838
|
+
let items = indexes.getIndexedItems(prop, args?.where) || data[prop];
|
|
839
|
+
let res = [];
|
|
840
|
+
for (const item of items) {
|
|
841
|
+
if (match(item)) {
|
|
842
|
+
const i = inc(item);
|
|
843
|
+
res.push(i);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
829
846
|
if (args?.distinct) {
|
|
830
847
|
let values = {};
|
|
831
848
|
res = res.filter((item) => {
|
|
@@ -886,10 +903,12 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
886
903
|
if (matchFnc(args.where)(e)) {
|
|
887
904
|
let data = nestedUpdate(args, false, e);
|
|
888
905
|
nbUpdated++;
|
|
889
|
-
|
|
906
|
+
const newItem = {
|
|
890
907
|
...e,
|
|
891
908
|
...data,
|
|
892
909
|
};
|
|
910
|
+
indexes.updateItem(prop, newItem);
|
|
911
|
+
return newItem;
|
|
893
912
|
}
|
|
894
913
|
return e;
|
|
895
914
|
});
|
|
@@ -913,7 +932,9 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
913
932
|
where[field.name] = d[field.name];
|
|
914
933
|
}
|
|
915
934
|
}
|
|
916
|
-
|
|
935
|
+
const item = findOne({ where, ...args });
|
|
936
|
+
indexes.updateItem(prop, item);
|
|
937
|
+
return item;
|
|
917
938
|
};
|
|
918
939
|
const createMany = (args) => {
|
|
919
940
|
const createdItems = [];
|
|
@@ -951,19 +972,23 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
951
972
|
// Referential Actions
|
|
952
973
|
deleted.forEach((item) => {
|
|
953
974
|
model.fields.forEach((field) => {
|
|
975
|
+
indexes.deleteItemByField(prop, field, item);
|
|
954
976
|
const joinfield = getJoinField(field);
|
|
955
977
|
if (!joinfield)
|
|
956
978
|
return;
|
|
957
979
|
const delegate = Delegate(getCamelCase(field.type), model);
|
|
958
980
|
if (joinfield.relationOnDelete === "SetNull") {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
981
|
+
try {
|
|
982
|
+
delegate.update({
|
|
983
|
+
where: {
|
|
984
|
+
[joinfield.relationFromFields[0]]: item[joinfield.relationToFields[0]],
|
|
985
|
+
},
|
|
986
|
+
data: {
|
|
987
|
+
[joinfield.relationFromFields[0]]: null,
|
|
988
|
+
},
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
catch (e) { }
|
|
967
992
|
}
|
|
968
993
|
else if (joinfield.relationOnDelete === "Cascade") {
|
|
969
994
|
try {
|
|
@@ -1065,18 +1090,24 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
1065
1090
|
};
|
|
1066
1091
|
const update = (args) => {
|
|
1067
1092
|
let updatedItem;
|
|
1093
|
+
let hasMatch = false;
|
|
1094
|
+
const match = matchFnc(args.where);
|
|
1068
1095
|
const newItems = data[prop].map((e) => {
|
|
1069
|
-
if (
|
|
1096
|
+
if (match(e)) {
|
|
1097
|
+
hasMatch = true;
|
|
1070
1098
|
let data = nestedUpdate(args, false, e);
|
|
1071
|
-
data; //?
|
|
1072
1099
|
updatedItem = {
|
|
1073
1100
|
...e,
|
|
1074
1101
|
...data,
|
|
1075
1102
|
};
|
|
1103
|
+
indexes.updateItem(prop, updatedItem);
|
|
1076
1104
|
return updatedItem;
|
|
1077
1105
|
}
|
|
1078
1106
|
return e;
|
|
1079
1107
|
});
|
|
1108
|
+
if (!hasMatch) {
|
|
1109
|
+
throwKnownError("An operation failed because it depends on one or more records that were required but not found. Record to update not found.", { meta: { cause: "Record to update not found." } });
|
|
1110
|
+
}
|
|
1080
1111
|
data = {
|
|
1081
1112
|
...data,
|
|
1082
1113
|
[prop]: newItems,
|
|
@@ -1160,6 +1191,12 @@ const createPrismaMock = (data = {}, datamodel = client_1.Prisma.dmmf.datamodel,
|
|
|
1160
1191
|
};
|
|
1161
1192
|
}
|
|
1162
1193
|
data = removeMultiFieldIds(model, data);
|
|
1194
|
+
model.fields.forEach((field) => {
|
|
1195
|
+
indexes.addIndexFieldIfNeeded(c, field);
|
|
1196
|
+
});
|
|
1197
|
+
data[c].forEach((item) => {
|
|
1198
|
+
indexes.updateItem(c, item);
|
|
1199
|
+
});
|
|
1163
1200
|
const objs = Delegate(c, model);
|
|
1164
1201
|
Object.keys(objs).forEach((fncName) => {
|
|
1165
1202
|
if (fncName.indexOf("_") === 0)
|
package/lib/indexes.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Prisma } from "@prisma/client";
|
|
2
|
+
export default function createIndexes(): {
|
|
3
|
+
addIndexFieldIfNeeded: (tableName: string, field: Prisma.DMMF.Field) => void;
|
|
4
|
+
getIndexedItems: (tableName: string, where: any) => any;
|
|
5
|
+
updateItem: (tableName: string, item: any) => void;
|
|
6
|
+
deleteItemByField: (tableName: string, field: Prisma.DMMF.Field, item: any) => void;
|
|
7
|
+
};
|
package/lib/indexes.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function createIndexes() {
|
|
4
|
+
let items = new Map();
|
|
5
|
+
let indexedFieldNames = new Map();
|
|
6
|
+
let fields = new Map();
|
|
7
|
+
let idFieldNames = new Map();
|
|
8
|
+
const addIndexFieldIfNeeded = (tableName, field) => {
|
|
9
|
+
if (!indexedFieldNames.has(tableName)) {
|
|
10
|
+
indexedFieldNames.set(tableName, []);
|
|
11
|
+
}
|
|
12
|
+
if (!fields.has(tableName)) {
|
|
13
|
+
fields.set(tableName, new Map());
|
|
14
|
+
}
|
|
15
|
+
if (!idFieldNames.has(tableName)) {
|
|
16
|
+
idFieldNames.set(tableName, []);
|
|
17
|
+
}
|
|
18
|
+
let thisFields = fields.get(tableName);
|
|
19
|
+
let thisFieldNames = indexedFieldNames.get(tableName);
|
|
20
|
+
let thisIdFieldNames = idFieldNames.get(tableName);
|
|
21
|
+
if (thisFieldNames.includes(field.name))
|
|
22
|
+
return;
|
|
23
|
+
if (field.isId || field.isUnique) {
|
|
24
|
+
thisFieldNames.push(field.name);
|
|
25
|
+
}
|
|
26
|
+
if (field.isId) {
|
|
27
|
+
thisIdFieldNames.push(field.name);
|
|
28
|
+
}
|
|
29
|
+
if (!!field.relationFromFields?.length) {
|
|
30
|
+
const fieldName = field.relationFromFields[0];
|
|
31
|
+
thisFieldNames.push(fieldName);
|
|
32
|
+
}
|
|
33
|
+
thisFields.set(field.name, field);
|
|
34
|
+
};
|
|
35
|
+
const getIndexedItems = (tableName, where) => {
|
|
36
|
+
for (const field in where) {
|
|
37
|
+
if (field === "AND") {
|
|
38
|
+
const subWhere = where.AND;
|
|
39
|
+
if (Array.isArray(subWhere)) {
|
|
40
|
+
for (const subWhereItem of subWhere) {
|
|
41
|
+
const items = getIndexedItems(tableName, subWhereItem);
|
|
42
|
+
if (items) {
|
|
43
|
+
return items;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (indexedFieldNames.has(tableName)) {
|
|
49
|
+
if (indexedFieldNames.get(tableName).includes(field)) {
|
|
50
|
+
return items.get(tableName)?.get(field)?.get(where[field]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const updateItem = (tableName, item) => {
|
|
56
|
+
if (!items.has(tableName)) {
|
|
57
|
+
items.set(tableName, new Map());
|
|
58
|
+
}
|
|
59
|
+
if (!indexedFieldNames.has(tableName)) {
|
|
60
|
+
throw new Error(`No indexed fields for table ${tableName}`);
|
|
61
|
+
}
|
|
62
|
+
const tableItems = items.get(tableName);
|
|
63
|
+
for (const fieldName of indexedFieldNames.get(tableName)) {
|
|
64
|
+
if (!tableItems.has(fieldName)) {
|
|
65
|
+
tableItems.set(fieldName, new Map());
|
|
66
|
+
}
|
|
67
|
+
const thisItems = tableItems.get(fieldName);
|
|
68
|
+
if (!thisItems.has(item[fieldName])) {
|
|
69
|
+
thisItems.set(item[fieldName], [item]);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const field = fields.get(tableName).get(fieldName);
|
|
73
|
+
if (field && (field.isId || field.isUnique)) {
|
|
74
|
+
thisItems.set(item[fieldName], [item]);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const array = thisItems.get(item[fieldName]);
|
|
78
|
+
if (array.length === 0) {
|
|
79
|
+
array.push(item);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const thisIdFieldNames = idFieldNames.get(tableName) || [];
|
|
83
|
+
let hasFound = false;
|
|
84
|
+
for (let i = 0; i < array.length; i++) {
|
|
85
|
+
const oldItem = array[i];
|
|
86
|
+
for (const thisIdFieldName of thisIdFieldNames) {
|
|
87
|
+
if (item[thisIdFieldName] === oldItem[thisIdFieldName]) {
|
|
88
|
+
hasFound = true;
|
|
89
|
+
array[i] = item;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!hasFound) {
|
|
95
|
+
array.push(item);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const deleteItemByField = (tableName, field, item) => {
|
|
103
|
+
if (indexedFieldNames.has(tableName)) {
|
|
104
|
+
if (indexedFieldNames.get(tableName).includes(field.name)) {
|
|
105
|
+
items.get(tableName)?.get(field.name)?.delete(item[field.name]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
addIndexFieldIfNeeded,
|
|
111
|
+
getIndexedItems,
|
|
112
|
+
updateItem,
|
|
113
|
+
deleteItemByField
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
exports.default = createIndexes;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const indexes_1 = __importDefault(require("./indexes"));
|
|
8
|
+
test("createIndexes", () => {
|
|
9
|
+
const indexes = (0, indexes_1.default)();
|
|
10
|
+
indexes.addIndexFieldIfNeeded("User", {
|
|
11
|
+
name: "id",
|
|
12
|
+
isId: true
|
|
13
|
+
});
|
|
14
|
+
indexes.addIndexFieldIfNeeded("User", {
|
|
15
|
+
name: "account",
|
|
16
|
+
relationFromFields: ["accountId"]
|
|
17
|
+
});
|
|
18
|
+
indexes.updateItem("User", {
|
|
19
|
+
id: 1,
|
|
20
|
+
name: "Alice",
|
|
21
|
+
accountId: 1
|
|
22
|
+
});
|
|
23
|
+
const items1 = indexes.getIndexedItems("User", {
|
|
24
|
+
accountId: 1
|
|
25
|
+
});
|
|
26
|
+
expect(items1).toMatchInlineSnapshot(`
|
|
27
|
+
Array [
|
|
28
|
+
Object {
|
|
29
|
+
"accountId": 1,
|
|
30
|
+
"id": 1,
|
|
31
|
+
"name": "Alice",
|
|
32
|
+
},
|
|
33
|
+
]
|
|
34
|
+
`);
|
|
35
|
+
indexes.updateItem("User", {
|
|
36
|
+
id: 1,
|
|
37
|
+
name: "Alice 2",
|
|
38
|
+
accountId: 1
|
|
39
|
+
});
|
|
40
|
+
const items2 = indexes.getIndexedItems("User", {
|
|
41
|
+
accountId: 1
|
|
42
|
+
});
|
|
43
|
+
expect(items2).toMatchInlineSnapshot(`
|
|
44
|
+
Array [
|
|
45
|
+
Object {
|
|
46
|
+
"accountId": 1,
|
|
47
|
+
"id": 1,
|
|
48
|
+
"name": "Alice 2",
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
`);
|
|
52
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-mock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0-alpha.2",
|
|
4
4
|
"description": "Mock prisma for unit testing database",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"repository": "https://github.com/demonsters/prisma-mock",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"uuid": "^9.0.0"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"preversion": "tsc",
|
|
24
|
+
"preversion": "jest && tsc",
|
|
25
25
|
"build": "tsc",
|
|
26
26
|
"test": "jest",
|
|
27
27
|
"watch": "tsc --watch",
|