prisma-mock 1.0.0-alpha.8 → 1.0.0
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 +39 -51
- package/lib/client.js +3 -2
- package/lib/delegate.js +16 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,34 +76,16 @@ beforeEach(() => {
|
|
|
76
76
|
})
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
## API
|
|
80
|
+
|
|
79
81
|
### Exports
|
|
80
82
|
|
|
81
83
|
The library provides three different exports:
|
|
82
84
|
|
|
83
85
|
- **`prisma-mock`** (default): The recommended way to use the library. Automatically uses the Prisma client from `@prisma/client/default`, so you don't need to pass Prisma as an argument.
|
|
84
|
-
- **`prisma-mock/client`**: Use this when you need to explicitly pass the Prisma namespace
|
|
86
|
+
- **`prisma-mock/client`**: Use this when you need to explicitly pass the Prisma namespace.
|
|
85
87
|
- **`prisma-mock/legacy`**: The old API for backward compatibility. This export is deprecated but maintained for existing codebases.
|
|
86
88
|
|
|
87
|
-
### Legacy Export
|
|
88
|
-
|
|
89
|
-
The legacy export maintains the old API signature for backward compatibility:
|
|
90
|
-
|
|
91
|
-
```js
|
|
92
|
-
import createPrismaMock from "prisma-mock/legacy"
|
|
93
|
-
import { mockDeep } from "jest-mock-extended"
|
|
94
|
-
|
|
95
|
-
const client = createPrismaMock(
|
|
96
|
-
{ user: [{ id: 1, name: "John" }] }, // data
|
|
97
|
-
Prisma.dmmf.datamodel, // datamodel (optional)
|
|
98
|
-
mockDeep(), // mockClient (optional)
|
|
99
|
-
{ enableIndexes: true } // options (optional)
|
|
100
|
-
)
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Note**: If you're starting a new project, use the default export instead. The legacy export is only for maintaining existing codebases that haven't migrated yet.
|
|
104
|
-
|
|
105
|
-
## API
|
|
106
|
-
|
|
107
89
|
### Default Export (`prisma-mock`)
|
|
108
90
|
|
|
109
91
|
```ts
|
|
@@ -118,6 +100,24 @@ createPrismaMock<P extends PrismaClient = PrismaClient>(
|
|
|
118
100
|
): P & { $getInternalState: () => Required<PrismaMockData<P>> }
|
|
119
101
|
```
|
|
120
102
|
|
|
103
|
+
### Parameters
|
|
104
|
+
|
|
105
|
+
- **`options`** (optional): Configuration options (see below)
|
|
106
|
+
|
|
107
|
+
#### Options
|
|
108
|
+
|
|
109
|
+
- **`data`** (optional): Initial mock data for the Prisma models. An object containing keys for tables and values as arrays of objects.
|
|
110
|
+
- **`datamodel`** (optional): The Prisma datamodel, typically `Prisma.dmmf.datamodel` (default).
|
|
111
|
+
- **`mockClient`** (optional): A `jest-mock-extended` or `vitest-mock-extended` instance. If not provided, a plain object is used instead.
|
|
112
|
+
- **`caseInsensitive`** (boolean, default: `false`): If true, all string comparisons are case insensitive
|
|
113
|
+
- **`enableIndexes`** (boolean, default: `true`) If true, enables indexing for better query performance on primary keys, unique fields, and foreign keys
|
|
114
|
+
|
|
115
|
+
### Return Value
|
|
116
|
+
|
|
117
|
+
Returns a mock Prisma client with all standard model methods plus:
|
|
118
|
+
|
|
119
|
+
- `$getInternalState()`: Method to access the internal data state for testing/debugging
|
|
120
|
+
|
|
121
121
|
### Client Export (`prisma-mock/client`)
|
|
122
122
|
|
|
123
123
|
```ts
|
|
@@ -133,30 +133,28 @@ createPrismaMock<PClient extends PrismaClient, P extends typeof Prisma = typeof
|
|
|
133
133
|
): PClient & { $getInternalState: () => Required<PrismaMockData<PClient>> }
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
#### Default Export
|
|
139
|
-
|
|
140
|
-
- **`options`** (optional): Configuration options (see below)
|
|
141
|
-
|
|
142
|
-
#### Client Export
|
|
136
|
+
#### Parameters
|
|
143
137
|
|
|
144
138
|
- **`prisma`** (required): The Prisma namespace (e.g., `Prisma` from `@prisma/client`). This is used to access the datamodel and type information.
|
|
145
|
-
- **`options`** (optional): Configuration options
|
|
139
|
+
- **`options`** (optional): Configuration options. Same as the default export, with the exception of the `datamodel` not being optional.
|
|
146
140
|
|
|
147
|
-
|
|
141
|
+
### Legacy Export (`prisma-mock/legacy`)
|
|
148
142
|
|
|
149
|
-
|
|
150
|
-
- **`datamodel`** (optional): The Prisma datamodel, typically `Prisma.dmmf.datamodel`. Defaults to the Prisma client's datamodel.
|
|
151
|
-
- **`mockClient`** (optional): A `jest-mock-extended` or `vitest-mock-extended` instance. If not provided, a plain object is used instead.
|
|
152
|
-
- **`caseInsensitive`** (boolean, default: `false`): If true, all string comparisons are case insensitive
|
|
153
|
-
- **`enableIndexes`** (boolean, default: `false`) Experimental: If true, enables indexing for better query performance on primary keys, unique fields, and foreign keys
|
|
143
|
+
The legacy export maintains the old API signature for backward compatibility:
|
|
154
144
|
|
|
155
|
-
|
|
145
|
+
```js
|
|
146
|
+
import createPrismaMock from "prisma-mock/legacy"
|
|
147
|
+
import { mockDeep } from "jest-mock-extended"
|
|
156
148
|
|
|
157
|
-
|
|
149
|
+
const client = createPrismaMock(
|
|
150
|
+
{ user: [{ id: 1, name: "John" }] }, // data
|
|
151
|
+
Prisma.dmmf.datamodel, // datamodel (optional)
|
|
152
|
+
mockDeep(), // mockClient (optional)
|
|
153
|
+
{ enableIndexes: true } // options (optional)
|
|
154
|
+
)
|
|
155
|
+
```
|
|
158
156
|
|
|
159
|
-
|
|
157
|
+
**Note**: If you're starting a new project, use the default export instead. The legacy export is only for maintaining existing codebases that haven't migrated yet.
|
|
160
158
|
|
|
161
159
|
## DMMF Generator
|
|
162
160
|
|
|
@@ -180,7 +178,7 @@ generator client {
|
|
|
180
178
|
provider = "prisma-client-js"
|
|
181
179
|
}
|
|
182
180
|
|
|
183
|
-
generator
|
|
181
|
+
generator dmmf {
|
|
184
182
|
provider = "prisma-mock"
|
|
185
183
|
output = "./generated/dmmf"
|
|
186
184
|
}
|
|
@@ -353,19 +351,9 @@ The following features are planned but not yet implemented:
|
|
|
353
351
|
|
|
354
352
|
## Performance Features
|
|
355
353
|
|
|
356
|
-
### Indexing
|
|
357
|
-
|
|
358
|
-
Enable indexing for better query performance:
|
|
359
|
-
|
|
360
|
-
```js
|
|
361
|
-
import createPrismaMock from "prisma-mock"
|
|
362
|
-
|
|
363
|
-
const client = createPrismaMock({
|
|
364
|
-
enableIndexes: true,
|
|
365
|
-
})
|
|
366
|
-
```
|
|
354
|
+
### Indexing
|
|
367
355
|
|
|
368
|
-
|
|
356
|
+
Indexing is enabled by default for better query performance. Indexes are automatically created for:
|
|
369
357
|
|
|
370
358
|
- Primary key fields
|
|
371
359
|
- Unique fields
|
package/lib/client.js
CHANGED
|
@@ -11,14 +11,15 @@ const fieldHelpers_1 = require("./utils/fieldHelpers");
|
|
|
11
11
|
// @param prisma - The Prisma namespace or client constructor.
|
|
12
12
|
// @param options - Options for configuring the mock client:
|
|
13
13
|
// - data: Initial mock data for your models (default: {}).
|
|
14
|
+
// - datamodel: The Prisma datamodel, typically `Prisma.dmmf.datamodel`. Defaults to the Prisma client's datamodel.
|
|
14
15
|
// - caseInsensitive: If true, string matching is case-insensitive (default: false).
|
|
15
|
-
// - enableIndexes: If true, enables index lookups for performance (default:
|
|
16
|
+
// - enableIndexes: If true, enables index lookups for performance (default: true).
|
|
16
17
|
// - mockClient: Optionally provide your own mock client (jest-mock-extended or vitest-mock-extended) instance to use.
|
|
17
18
|
// @returns A mock Prisma client with all model methods and access to internal state.
|
|
18
19
|
function createPrismaMock(prisma, options = {
|
|
19
20
|
datamodel: prisma.dmmf?.datamodel,
|
|
20
21
|
caseInsensitive: false,
|
|
21
|
-
enableIndexes:
|
|
22
|
+
enableIndexes: true,
|
|
22
23
|
data: {}
|
|
23
24
|
}) {
|
|
24
25
|
// Reference object to hold the mock data state
|
package/lib/delegate.js
CHANGED
|
@@ -7,9 +7,8 @@ exports.createDelegate = void 0;
|
|
|
7
7
|
const defaults_1 = __importDefault(require("./defaults"));
|
|
8
8
|
const errors_1 = require("./errors");
|
|
9
9
|
const fieldHelpers_1 = require("./utils/fieldHelpers");
|
|
10
|
-
const queryMatching_1 = __importDefault(require("./utils/queryMatching"));
|
|
11
|
-
const shallowCompare_1 = require("./utils/shallowCompare");
|
|
12
10
|
const getWhereOnIds_1 = __importDefault(require("./utils/getWhereOnIds"));
|
|
11
|
+
const queryMatching_1 = __importDefault(require("./utils/queryMatching"));
|
|
13
12
|
/**
|
|
14
13
|
* Creates a delegate function that handles Prisma-like operations for a specific model
|
|
15
14
|
* This is the main factory function that generates model-specific CRUD operations
|
|
@@ -41,10 +40,10 @@ const createDelegate = ({ ref, prisma, datamodel = prisma.dmmf.datamodel, caseIn
|
|
|
41
40
|
*/
|
|
42
41
|
const Delegate = (prop, model) => {
|
|
43
42
|
const getDelegateForFieldName = (field) => {
|
|
43
|
+
const name = (0, fieldHelpers_1.getCamelCase)(field);
|
|
44
44
|
const otherModel = datamodel.models.find((model) => {
|
|
45
|
-
return
|
|
45
|
+
return name === (0, fieldHelpers_1.getCamelCase)(model.name);
|
|
46
46
|
});
|
|
47
|
-
const name = (0, fieldHelpers_1.getCamelCase)(field);
|
|
48
47
|
return Delegate(name, otherModel);
|
|
49
48
|
};
|
|
50
49
|
// Create matching function for WHERE clauses
|
|
@@ -174,30 +173,16 @@ const createDelegate = ({ ref, prisma, datamodel = prisma.dmmf.datamodel, caseIn
|
|
|
174
173
|
const keyToMatch = Object.keys(connect)[0];
|
|
175
174
|
const keyToGet = field.relationToFields[0];
|
|
176
175
|
const targetKey = field.relationFromFields[0];
|
|
176
|
+
const delegate = getDelegateForFieldName(field.type);
|
|
177
177
|
if (keyToGet && targetKey) {
|
|
178
178
|
let connectionValue = connect[keyToGet];
|
|
179
179
|
if (keyToMatch !== keyToGet) {
|
|
180
|
-
|
|
181
|
-
let matchingRow =
|
|
182
|
-
|
|
180
|
+
// Try to find by unique index if direct match fails
|
|
181
|
+
let matchingRow = delegate.findOne({
|
|
182
|
+
where: connect
|
|
183
183
|
});
|
|
184
184
|
if (!matchingRow) {
|
|
185
|
-
|
|
186
|
-
const refModel = datamodel.models.find((model) => (0, fieldHelpers_1.getCamelCase)(field.type) === (0, fieldHelpers_1.getCamelCase)(model.name));
|
|
187
|
-
const uniqueIndexes = refModel.uniqueIndexes.map((index) => {
|
|
188
|
-
return {
|
|
189
|
-
...index,
|
|
190
|
-
key: index.name ?? index.fields.join("_"),
|
|
191
|
-
};
|
|
192
|
-
});
|
|
193
|
-
const indexKey = uniqueIndexes.find((index) => index.key === keyToMatch);
|
|
194
|
-
matchingRow = ref.data[(0, fieldHelpers_1.getCamelCase)(field.type)].find((row) => {
|
|
195
|
-
const target = Object.fromEntries(Object.entries(row).filter((row) => indexKey?.fields.includes(row[0]) ?? false));
|
|
196
|
-
return (0, shallowCompare_1.shallowCompare)(target, valueToMatch);
|
|
197
|
-
});
|
|
198
|
-
if (!matchingRow) {
|
|
199
|
-
(0, errors_1.throwKnownError)(prisma, "An operation failed because it depends on one or more records that were required but not found. {cause}");
|
|
200
|
-
}
|
|
185
|
+
(0, errors_1.throwKnownError)(prisma, "An operation failed because it depends on one or more records that were required but not found. {cause}");
|
|
201
186
|
}
|
|
202
187
|
connectionValue = matchingRow[keyToGet];
|
|
203
188
|
}
|
|
@@ -210,11 +195,14 @@ const createDelegate = ({ ref, prisma, datamodel = prisma.dmmf.datamodel, caseIn
|
|
|
210
195
|
}
|
|
211
196
|
else {
|
|
212
197
|
inputData = rest;
|
|
198
|
+
const newData = {
|
|
199
|
+
...item,
|
|
200
|
+
...inputData,
|
|
201
|
+
};
|
|
213
202
|
const otherModel = datamodel.models.find((model) => {
|
|
214
203
|
return model.name === field.type;
|
|
215
204
|
});
|
|
216
205
|
const otherField = otherModel.fields.find((otherField) => field.relationName === otherField.relationName);
|
|
217
|
-
const delegate = getDelegateForFieldName(field.type);
|
|
218
206
|
const otherTargetKey = otherField.relationToFields[0];
|
|
219
207
|
if ((!targetKey && !keyToGet) && otherTargetKey) {
|
|
220
208
|
delegate.update({
|
|
@@ -222,9 +210,9 @@ const createDelegate = ({ ref, prisma, datamodel = prisma.dmmf.datamodel, caseIn
|
|
|
222
210
|
data: {
|
|
223
211
|
[(0, fieldHelpers_1.getCamelCase)(otherField.name)]: {
|
|
224
212
|
connect: {
|
|
225
|
-
[otherTargetKey]:
|
|
226
|
-
}
|
|
227
|
-
}
|
|
213
|
+
[otherTargetKey]: newData[otherTargetKey],
|
|
214
|
+
}
|
|
215
|
+
}
|
|
228
216
|
}
|
|
229
217
|
});
|
|
230
218
|
}
|
|
@@ -234,7 +222,7 @@ const createDelegate = ({ ref, prisma, datamodel = prisma.dmmf.datamodel, caseIn
|
|
|
234
222
|
[field.type]: delegate.findOne({
|
|
235
223
|
where: connect
|
|
236
224
|
}),
|
|
237
|
-
[otherField.type]: item ||
|
|
225
|
+
[otherField.type]: item || newData
|
|
238
226
|
});
|
|
239
227
|
}
|
|
240
228
|
}
|