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 CHANGED
@@ -188,7 +188,7 @@ TODO (has, hasEvery, hasSome, isEmpty, equals)
188
188
 
189
189
  - @@id
190
190
  - @default
191
- - @unique (TODO: no error if duplicate)
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, model);
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
- let res = data[prop]
827
- .filter(matchFnc(args?.where))
828
- .map(includes(args));
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
- return {
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
- return findOne({ where, ...args });
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
- delegate.update({
960
- where: {
961
- [joinfield.relationFromFields[0]]: item[joinfield.relationToFields[0]],
962
- },
963
- data: {
964
- [joinfield.relationFromFields[0]]: null,
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 (matchFnc(args.where)(e)) {
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)
@@ -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.10.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",