@nest-admin/nestjs 0.11.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/LICENSE +21 -0
- package/README.md +252 -0
- package/dist/admin-ui/assets/index-AyWOamlt.js +50 -0
- package/dist/admin-ui/assets/index-AyWOamlt.js.map +1 -0
- package/dist/admin-ui/assets/index-D4Eh84eD.css +2 -0
- package/dist/admin-ui/index.html +14 -0
- package/dist/chunk-7IXLRGGQ.js +356 -0
- package/dist/chunk-7IXLRGGQ.js.map +1 -0
- package/dist/drizzle.cjs +895 -0
- package/dist/drizzle.cjs.map +1 -0
- package/dist/drizzle.d.cts +335 -0
- package/dist/drizzle.d.ts +335 -0
- package/dist/drizzle.js +756 -0
- package/dist/drizzle.js.map +1 -0
- package/dist/index.cjs +3247 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1652 -0
- package/dist/index.d.ts +1652 -0
- package/dist/index.js +2901 -0
- package/dist/index.js.map +1 -0
- package/dist/prisma.cjs +1159 -0
- package/dist/prisma.cjs.map +1 -0
- package/dist/prisma.d.cts +585 -0
- package/dist/prisma.d.ts +585 -0
- package/dist/prisma.js +995 -0
- package/dist/prisma.js.map +1 -0
- package/package.json +130 -0
package/dist/prisma.js
ADDED
|
@@ -0,0 +1,995 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AdapterError,
|
|
3
|
+
ConstraintError,
|
|
4
|
+
FieldNotFoundError,
|
|
5
|
+
InvalidQueryError,
|
|
6
|
+
ModelNotFoundError,
|
|
7
|
+
NestAdminError,
|
|
8
|
+
RecordNotFoundError,
|
|
9
|
+
__name,
|
|
10
|
+
displayFieldFor,
|
|
11
|
+
inverseRelationField,
|
|
12
|
+
isNestAdminError
|
|
13
|
+
} from "./chunk-7IXLRGGQ.js";
|
|
14
|
+
|
|
15
|
+
// ../prisma/dist/index.js
|
|
16
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
17
|
+
import { join, resolve } from "path";
|
|
18
|
+
import { getDMMF } from "@prisma/get-dmmf";
|
|
19
|
+
var REQUIRED_METHODS = [
|
|
20
|
+
"findMany",
|
|
21
|
+
"findUnique",
|
|
22
|
+
"count",
|
|
23
|
+
"create",
|
|
24
|
+
"update",
|
|
25
|
+
"delete"
|
|
26
|
+
];
|
|
27
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
28
|
+
"__proto__",
|
|
29
|
+
"constructor",
|
|
30
|
+
"prototype"
|
|
31
|
+
]);
|
|
32
|
+
function toDelegateKey(modelName) {
|
|
33
|
+
if (modelName.length === 0) return modelName;
|
|
34
|
+
return modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
35
|
+
}
|
|
36
|
+
__name(toDelegateKey, "toDelegateKey");
|
|
37
|
+
function resolveDelegate(client, modelName, knownModels) {
|
|
38
|
+
if (!knownModels.includes(modelName)) {
|
|
39
|
+
throw new ModelNotFoundError(modelName, knownModels);
|
|
40
|
+
}
|
|
41
|
+
const key = toDelegateKey(modelName);
|
|
42
|
+
if (FORBIDDEN_KEYS.has(key)) {
|
|
43
|
+
throw new ModelNotFoundError(modelName, knownModels);
|
|
44
|
+
}
|
|
45
|
+
if (typeof client !== "object" || client === null) {
|
|
46
|
+
throw new AdapterError(`PrismaAdapter requires a constructed Prisma Client instance. Received ${client === null ? "null" : typeof client}.`);
|
|
47
|
+
}
|
|
48
|
+
const candidate = client[key];
|
|
49
|
+
if (typeof candidate !== "object" || candidate === null) {
|
|
50
|
+
throw new AdapterError(`The Prisma Client has no delegate "${key}" for model "${modelName}". This usually means the client was generated from a different schema than the one Nest Admin read - re-run \`prisma generate\`.`);
|
|
51
|
+
}
|
|
52
|
+
const delegate = candidate;
|
|
53
|
+
const missing = REQUIRED_METHODS.filter((method) => typeof delegate[method] !== "function");
|
|
54
|
+
if (missing.length > 0) {
|
|
55
|
+
throw new AdapterError(`Prisma Client delegate "${key}" is missing expected methods: ${missing.join(", ")}.`);
|
|
56
|
+
}
|
|
57
|
+
return candidate;
|
|
58
|
+
}
|
|
59
|
+
__name(resolveDelegate, "resolveDelegate");
|
|
60
|
+
var SUPPORTED_PRISMA_MAJORS = [
|
|
61
|
+
7
|
|
62
|
+
];
|
|
63
|
+
var PrismaVersionUnsupportedError = class extends NestAdminError {
|
|
64
|
+
static {
|
|
65
|
+
__name(this, "PrismaVersionUnsupportedError");
|
|
66
|
+
}
|
|
67
|
+
constructor(clientVersion, supportedMajors) {
|
|
68
|
+
super(`Nest Admin ships a Prisma ${supportedMajors.join("/")} schema parser, but this application uses Prisma Client ${clientVersion}. Schema parsing would likely fail with a misleading error, so it was stopped here instead. Align the versions, or open an issue if Prisma ${clientVersion.split(".")[0]} should be supported.`);
|
|
69
|
+
this.clientVersion = clientVersion;
|
|
70
|
+
this.supportedMajors = supportedMajors;
|
|
71
|
+
}
|
|
72
|
+
clientVersion;
|
|
73
|
+
supportedMajors;
|
|
74
|
+
};
|
|
75
|
+
function readClientVersion(client) {
|
|
76
|
+
if (typeof client !== "object" || client === null) return void 0;
|
|
77
|
+
const version = client["_clientVersion"];
|
|
78
|
+
return typeof version === "string" && version !== "" ? version : void 0;
|
|
79
|
+
}
|
|
80
|
+
__name(readClientVersion, "readClientVersion");
|
|
81
|
+
function majorOf(version) {
|
|
82
|
+
const major = Number(version.split(".")[0]);
|
|
83
|
+
return Number.isInteger(major) ? major : void 0;
|
|
84
|
+
}
|
|
85
|
+
__name(majorOf, "majorOf");
|
|
86
|
+
function assertSupportedPrismaVersion(client, supportedMajors = SUPPORTED_PRISMA_MAJORS) {
|
|
87
|
+
const version = readClientVersion(client);
|
|
88
|
+
if (version === void 0) return;
|
|
89
|
+
const major = majorOf(version);
|
|
90
|
+
if (major === void 0) return;
|
|
91
|
+
if (!supportedMajors.includes(major)) {
|
|
92
|
+
throw new PrismaVersionUnsupportedError(version, supportedMajors);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
__name(assertSupportedPrismaVersion, "assertSupportedPrismaVersion");
|
|
96
|
+
var DEFAULT_SCHEMA_CANDIDATES = [
|
|
97
|
+
"prisma/schema.prisma",
|
|
98
|
+
"prisma/schema",
|
|
99
|
+
"schema.prisma"
|
|
100
|
+
];
|
|
101
|
+
var PrismaSchemaNotFoundError = class extends NestAdminError {
|
|
102
|
+
static {
|
|
103
|
+
__name(this, "PrismaSchemaNotFoundError");
|
|
104
|
+
}
|
|
105
|
+
constructor(triedPaths, explicit) {
|
|
106
|
+
super(explicit ? `Prisma schema not found at "${triedPaths[0]}".` : `Could not locate a Prisma schema. Tried: ${triedPaths.join(", ")}. Pass \`schemaPath\` to PrismaAdapter if your schema lives elsewhere.`);
|
|
107
|
+
this.triedPaths = triedPaths;
|
|
108
|
+
}
|
|
109
|
+
triedPaths;
|
|
110
|
+
};
|
|
111
|
+
var PrismaSchemaInvalidError = class extends NestAdminError {
|
|
112
|
+
static {
|
|
113
|
+
__name(this, "PrismaSchemaInvalidError");
|
|
114
|
+
}
|
|
115
|
+
constructor(prismaMessage, options) {
|
|
116
|
+
super(`Prisma rejected the schema:
|
|
117
|
+
${prismaMessage}`, options);
|
|
118
|
+
this.prismaMessage = prismaMessage;
|
|
119
|
+
}
|
|
120
|
+
prismaMessage;
|
|
121
|
+
};
|
|
122
|
+
function locateSchema(schemaPath, cwd) {
|
|
123
|
+
if (schemaPath !== void 0) {
|
|
124
|
+
const absolute = resolve(cwd, schemaPath);
|
|
125
|
+
if (!existsSync(absolute)) throw new PrismaSchemaNotFoundError([
|
|
126
|
+
absolute
|
|
127
|
+
], true);
|
|
128
|
+
return absolute;
|
|
129
|
+
}
|
|
130
|
+
const tried = [];
|
|
131
|
+
for (const candidate of DEFAULT_SCHEMA_CANDIDATES) {
|
|
132
|
+
const absolute = resolve(cwd, candidate);
|
|
133
|
+
tried.push(absolute);
|
|
134
|
+
if (existsSync(absolute)) return absolute;
|
|
135
|
+
}
|
|
136
|
+
throw new PrismaSchemaNotFoundError(tried, false);
|
|
137
|
+
}
|
|
138
|
+
__name(locateSchema, "locateSchema");
|
|
139
|
+
function readSchemaFiles(absolutePath) {
|
|
140
|
+
if (statSync(absolutePath).isDirectory()) {
|
|
141
|
+
const files = readdirSync(absolutePath).filter((name) => name.endsWith(".prisma")).sort();
|
|
142
|
+
if (files.length === 0) {
|
|
143
|
+
throw new PrismaSchemaNotFoundError([
|
|
144
|
+
join(absolutePath, "*.prisma")
|
|
145
|
+
], true);
|
|
146
|
+
}
|
|
147
|
+
return files.map((name) => {
|
|
148
|
+
const file = join(absolutePath, name);
|
|
149
|
+
return [
|
|
150
|
+
file,
|
|
151
|
+
readFileSync(file, "utf8")
|
|
152
|
+
];
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return [
|
|
156
|
+
[
|
|
157
|
+
absolutePath,
|
|
158
|
+
readFileSync(absolutePath, "utf8")
|
|
159
|
+
]
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
__name(readSchemaFiles, "readSchemaFiles");
|
|
163
|
+
function readPrismaDmmf(options = {}) {
|
|
164
|
+
const cwd = options.cwd ?? process.cwd();
|
|
165
|
+
const absolutePath = locateSchema(options.schemaPath, cwd);
|
|
166
|
+
let files;
|
|
167
|
+
try {
|
|
168
|
+
files = readSchemaFiles(absolutePath);
|
|
169
|
+
} catch (cause) {
|
|
170
|
+
if (isNestAdminError(cause)) throw cause;
|
|
171
|
+
throw new AdapterError(`Failed to read the Prisma schema at "${absolutePath}".`, {
|
|
172
|
+
cause
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const result = getDMMF({
|
|
176
|
+
datamodel: files
|
|
177
|
+
});
|
|
178
|
+
if (!isDmmfDocument(result)) {
|
|
179
|
+
throw new PrismaSchemaInvalidError(extractPrismaMessage(result), {
|
|
180
|
+
cause: result.error
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
__name(readPrismaDmmf, "readPrismaDmmf");
|
|
186
|
+
function readDatasourceProvider(options = {}) {
|
|
187
|
+
try {
|
|
188
|
+
const files = readSchemaFiles(locateSchema(options.schemaPath, options.cwd ?? process.cwd()));
|
|
189
|
+
for (const [, content] of files) {
|
|
190
|
+
const declared = /datasources+w+s*{[^}]*?providers*=s*"([a-z]+)"/i.exec(content);
|
|
191
|
+
if (declared?.[1] !== void 0) return declared[1].toLowerCase();
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
}
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
__name(readDatasourceProvider, "readDatasourceProvider");
|
|
198
|
+
function isDmmfDocument(value) {
|
|
199
|
+
return "datamodel" in value;
|
|
200
|
+
}
|
|
201
|
+
__name(isDmmfDocument, "isDmmfDocument");
|
|
202
|
+
function extractPrismaMessage(result) {
|
|
203
|
+
const raw = result.error?.message ?? result.reason;
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(raw);
|
|
206
|
+
if (typeof parsed === "object" && parsed !== null && "message" in parsed) {
|
|
207
|
+
const message = parsed.message;
|
|
208
|
+
if (typeof message === "string") return stripAnsi(message);
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
return stripAnsi(raw);
|
|
213
|
+
}
|
|
214
|
+
__name(extractPrismaMessage, "extractPrismaMessage");
|
|
215
|
+
var ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
|
|
216
|
+
function stripAnsi(value) {
|
|
217
|
+
return value.replace(ANSI_PATTERN, "");
|
|
218
|
+
}
|
|
219
|
+
__name(stripAnsi, "stripAnsi");
|
|
220
|
+
var SCALAR_KINDS = {
|
|
221
|
+
String: "string",
|
|
222
|
+
Int: "number",
|
|
223
|
+
Float: "number",
|
|
224
|
+
Boolean: "boolean",
|
|
225
|
+
DateTime: "datetime",
|
|
226
|
+
Json: "json"
|
|
227
|
+
};
|
|
228
|
+
function toFieldKind(field) {
|
|
229
|
+
if (field.kind === "object") return "relation";
|
|
230
|
+
if (field.kind === "enum") return "enum";
|
|
231
|
+
if (field.kind === "scalar") return SCALAR_KINDS[field.type] ?? "unknown";
|
|
232
|
+
return "unknown";
|
|
233
|
+
}
|
|
234
|
+
__name(toFieldKind, "toFieldKind");
|
|
235
|
+
function isFunctionDefault(value) {
|
|
236
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && "name" in value;
|
|
237
|
+
}
|
|
238
|
+
__name(isFunctionDefault, "isFunctionDefault");
|
|
239
|
+
function toFieldMetadata(field, enums) {
|
|
240
|
+
const kind = toFieldKind(field);
|
|
241
|
+
const isGenerated = field.isUpdatedAt === true || isFunctionDefault(field.default);
|
|
242
|
+
const hasLiteralDefault = field.hasDefaultValue === true && !isFunctionDefault(field.default);
|
|
243
|
+
const base = {
|
|
244
|
+
name: field.name,
|
|
245
|
+
kind,
|
|
246
|
+
isId: field.isId === true,
|
|
247
|
+
isRequired: field.isRequired === true,
|
|
248
|
+
isUnique: field.isUnique === true,
|
|
249
|
+
isList: field.isList === true,
|
|
250
|
+
isGenerated
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
...base,
|
|
254
|
+
...hasLiteralDefault ? {
|
|
255
|
+
defaultValue: field.default
|
|
256
|
+
} : {},
|
|
257
|
+
...kind === "enum" ? {
|
|
258
|
+
enumValues: enums.get(field.type) ?? []
|
|
259
|
+
} : {},
|
|
260
|
+
...kind === "relation" ? {
|
|
261
|
+
relation: {
|
|
262
|
+
targetModel: field.type,
|
|
263
|
+
// Cardinality follows directly from isList - the single attribute
|
|
264
|
+
// the generated Prisma Client does not expose at runtime, which is
|
|
265
|
+
// why metadata comes from the schema rather than the client.
|
|
266
|
+
cardinality: field.isList === true ? "many" : "one",
|
|
267
|
+
// Present only on the owning side of a to-one relation. Prisma
|
|
268
|
+
// gives both sides a relation field but only one of them a column,
|
|
269
|
+
// and these arrays are empty on the side that has none - so an
|
|
270
|
+
// empty array means "no foreign key here", not "unknown".
|
|
271
|
+
...field.relationFromFields?.[0] !== void 0 ? {
|
|
272
|
+
from: field.relationFromFields[0]
|
|
273
|
+
} : {},
|
|
274
|
+
...field.relationToFields?.[0] !== void 0 ? {
|
|
275
|
+
to: field.relationToFields[0]
|
|
276
|
+
} : {},
|
|
277
|
+
// Shared by both halves, so the other side can be found. Prisma
|
|
278
|
+
// generates one when the schema does not name it.
|
|
279
|
+
...field.relationName !== void 0 ? {
|
|
280
|
+
name: field.relationName
|
|
281
|
+
} : {}
|
|
282
|
+
}
|
|
283
|
+
} : {}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
__name(toFieldMetadata, "toFieldMetadata");
|
|
287
|
+
function toPrimaryKey(model) {
|
|
288
|
+
const compositeFields = model.primaryKey?.fields;
|
|
289
|
+
if (compositeFields && compositeFields.length > 0) return [
|
|
290
|
+
...compositeFields
|
|
291
|
+
];
|
|
292
|
+
return model.fields.filter((field) => field.isId === true).map((field) => field.name);
|
|
293
|
+
}
|
|
294
|
+
__name(toPrimaryKey, "toPrimaryKey");
|
|
295
|
+
function toModelMetadata(dmmf) {
|
|
296
|
+
const enums = new Map(dmmf.datamodel.enums.map((enumType) => [
|
|
297
|
+
enumType.name,
|
|
298
|
+
enumType.values.map((value) => value.name)
|
|
299
|
+
]));
|
|
300
|
+
return dmmf.datamodel.models.map((model) => ({
|
|
301
|
+
name: model.name,
|
|
302
|
+
primaryKey: toPrimaryKey(model),
|
|
303
|
+
fields: model.fields.map((field) => toFieldMetadata(field, enums))
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
__name(toModelMetadata, "toModelMetadata");
|
|
307
|
+
function toIncludeClause(model, models) {
|
|
308
|
+
const include = {};
|
|
309
|
+
for (const field of model.fields) {
|
|
310
|
+
const relation = field.relation;
|
|
311
|
+
if (!relation || relation.cardinality !== "one" || relation.from === void 0) continue;
|
|
312
|
+
const target = models.find((candidate) => candidate.name === relation.targetModel);
|
|
313
|
+
if (!target) continue;
|
|
314
|
+
const select = {};
|
|
315
|
+
for (const key of target.primaryKey) select[key] = true;
|
|
316
|
+
select[displayFieldFor(target)] = true;
|
|
317
|
+
include[field.name] = {
|
|
318
|
+
select
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return Object.keys(include).length > 0 ? include : void 0;
|
|
322
|
+
}
|
|
323
|
+
__name(toIncludeClause, "toIncludeClause");
|
|
324
|
+
var CONSTRAINT_CODES = {
|
|
325
|
+
P2002: "unique",
|
|
326
|
+
P2003: "foreign-key",
|
|
327
|
+
P2014: "foreign-key",
|
|
328
|
+
P2011: "required",
|
|
329
|
+
P2012: "required",
|
|
330
|
+
P2013: "required"
|
|
331
|
+
};
|
|
332
|
+
function isPrismaKnownError(value) {
|
|
333
|
+
return typeof value === "object" && value !== null && "code" in value && typeof value.code === "string";
|
|
334
|
+
}
|
|
335
|
+
__name(isPrismaKnownError, "isPrismaKnownError");
|
|
336
|
+
function fieldsFrom(meta) {
|
|
337
|
+
if (!meta) return [];
|
|
338
|
+
const nested = meta["driverAdapterError"]?.cause?.constraint;
|
|
339
|
+
const candidate = nested?.fields ?? meta["target"] ?? meta["field_name"] ?? meta["constraint"];
|
|
340
|
+
if (Array.isArray(candidate)) {
|
|
341
|
+
return candidate.filter((entry) => typeof entry === "string");
|
|
342
|
+
}
|
|
343
|
+
if (typeof candidate !== "string") return [];
|
|
344
|
+
const index = /^(.+?)_(.+)_key$/.exec(candidate);
|
|
345
|
+
if (index?.[2] !== void 0) return index[2].split("_");
|
|
346
|
+
return [
|
|
347
|
+
candidate
|
|
348
|
+
];
|
|
349
|
+
}
|
|
350
|
+
__name(fieldsFrom, "fieldsFrom");
|
|
351
|
+
function missingArguments(cause) {
|
|
352
|
+
if (!(cause instanceof Error) || cause.constructor.name !== "PrismaClientValidationError") {
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
const names = [];
|
|
356
|
+
for (const match of cause.message.matchAll(/Argument `([A-Za-z0-9_]+)` is missing/g)) {
|
|
357
|
+
if (match[1] !== void 0) names.push(match[1]);
|
|
358
|
+
}
|
|
359
|
+
return names;
|
|
360
|
+
}
|
|
361
|
+
__name(missingArguments, "missingArguments");
|
|
362
|
+
function toConstraintError(cause, model) {
|
|
363
|
+
const missing = missingArguments(cause);
|
|
364
|
+
if (missing.length > 0) return new ConstraintError("required", model, missing);
|
|
365
|
+
if (!isPrismaKnownError(cause)) return void 0;
|
|
366
|
+
const constraint = CONSTRAINT_CODES[cause.code];
|
|
367
|
+
if (!constraint) return void 0;
|
|
368
|
+
return new ConstraintError(constraint, model, fieldsFrom(cause.meta));
|
|
369
|
+
}
|
|
370
|
+
__name(toConstraintError, "toConstraintError");
|
|
371
|
+
function toRelatedWhere(parent, relationFieldName, parentId, models) {
|
|
372
|
+
const field = parent.fields.find((candidate) => candidate.name === relationFieldName);
|
|
373
|
+
if (!field?.relation) {
|
|
374
|
+
throw new FieldNotFoundError(parent.name, relationFieldName, "Only a relation field can be listed this way.");
|
|
375
|
+
}
|
|
376
|
+
if (field.relation.cardinality !== "many") {
|
|
377
|
+
throw new FieldNotFoundError(parent.name, relationFieldName, "This is a to-one relation. It arrives with the record itself.");
|
|
378
|
+
}
|
|
379
|
+
const target = models.find((candidate) => candidate.name === field.relation?.targetModel);
|
|
380
|
+
if (!target) {
|
|
381
|
+
throw new FieldNotFoundError(parent.name, relationFieldName, `${field.relation.targetModel} is not available.`);
|
|
382
|
+
}
|
|
383
|
+
const inverse = inverseRelationField(field, models);
|
|
384
|
+
if (!inverse) {
|
|
385
|
+
throw new FieldNotFoundError(parent.name, relationFieldName, "The other half of this relation could not be resolved.");
|
|
386
|
+
}
|
|
387
|
+
const [parentKey] = parent.primaryKey;
|
|
388
|
+
if (parentKey === void 0) {
|
|
389
|
+
throw new FieldNotFoundError(parent.name, relationFieldName, `${parent.name} has no primary key.`);
|
|
390
|
+
}
|
|
391
|
+
const match = {
|
|
392
|
+
[parentKey]: parentId
|
|
393
|
+
};
|
|
394
|
+
return {
|
|
395
|
+
target,
|
|
396
|
+
where: {
|
|
397
|
+
[inverse.name]: inverse.relation?.cardinality === "many" ? {
|
|
398
|
+
some: match
|
|
399
|
+
} : {
|
|
400
|
+
is: match
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
__name(toRelatedWhere, "toRelatedWhere");
|
|
406
|
+
var DEFAULT_PER_PAGE = 25;
|
|
407
|
+
var MAX_PER_PAGE = 100;
|
|
408
|
+
var STRING_ONLY_OPERATORS = /* @__PURE__ */ new Set([
|
|
409
|
+
"contains",
|
|
410
|
+
"startsWith",
|
|
411
|
+
"endsWith"
|
|
412
|
+
]);
|
|
413
|
+
var COMPARISON_OPERATORS = /* @__PURE__ */ new Set([
|
|
414
|
+
"gt",
|
|
415
|
+
"gte",
|
|
416
|
+
"lt",
|
|
417
|
+
"lte"
|
|
418
|
+
]);
|
|
419
|
+
function findQueryableField(model, fieldName, purpose) {
|
|
420
|
+
const field = model.fields.find((candidate) => candidate.name === fieldName);
|
|
421
|
+
if (!field) {
|
|
422
|
+
throw new FieldNotFoundError(model.name, fieldName);
|
|
423
|
+
}
|
|
424
|
+
if (field.kind === "relation") {
|
|
425
|
+
const owned = field.relation?.from;
|
|
426
|
+
if (owned !== void 0 && field.relation?.cardinality === "one") {
|
|
427
|
+
if (purpose === "filter") return findQueryableField(model, owned, purpose);
|
|
428
|
+
throw new FieldNotFoundError(model.name, fieldName, `Sorting by a relation is not supported in this version. Sorting by "${owned}" would order by an opaque key rather than by anything readable.`);
|
|
429
|
+
}
|
|
430
|
+
throw new FieldNotFoundError(model.name, fieldName, "Relation fields cannot be filtered or sorted in this version.");
|
|
431
|
+
}
|
|
432
|
+
if (field.isList) {
|
|
433
|
+
throw new FieldNotFoundError(model.name, fieldName, "List fields cannot be filtered or sorted in this version.");
|
|
434
|
+
}
|
|
435
|
+
return field;
|
|
436
|
+
}
|
|
437
|
+
__name(findQueryableField, "findQueryableField");
|
|
438
|
+
function toPrismaCondition(model, rule) {
|
|
439
|
+
const field = findQueryableField(model, rule.field, "filter");
|
|
440
|
+
if (STRING_ONLY_OPERATORS.has(rule.operator) && field.kind !== "string") {
|
|
441
|
+
throw new InvalidQueryError(`Operator "${rule.operator}" requires a string field, but "${model.name}.${field.name}" is of kind "${field.kind}".`);
|
|
442
|
+
}
|
|
443
|
+
if (COMPARISON_OPERATORS.has(rule.operator) && field.kind === "boolean") {
|
|
444
|
+
throw new InvalidQueryError(`Operator "${rule.operator}" cannot be applied to boolean field "${model.name}.${field.name}".`);
|
|
445
|
+
}
|
|
446
|
+
if (rule.operator === "in") {
|
|
447
|
+
if (!Array.isArray(rule.value)) {
|
|
448
|
+
throw new InvalidQueryError(`Operator "in" requires an array value for "${model.name}.${field.name}".`);
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
[field.name]: {
|
|
452
|
+
in: rule.value
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
if (rule.operator === "eq") return {
|
|
457
|
+
[field.name]: {
|
|
458
|
+
equals: rule.value
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
if (rule.operator === "ne") return {
|
|
462
|
+
[field.name]: {
|
|
463
|
+
not: rule.value
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
return {
|
|
467
|
+
[field.name]: {
|
|
468
|
+
[rule.operator]: rule.value
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
__name(toPrismaCondition, "toPrismaCondition");
|
|
473
|
+
var INSENSITIVE_MODE_PROVIDERS = /* @__PURE__ */ new Set([
|
|
474
|
+
"postgresql",
|
|
475
|
+
"postgres",
|
|
476
|
+
"mongodb"
|
|
477
|
+
]);
|
|
478
|
+
function insensitively(provider) {
|
|
479
|
+
return provider !== void 0 && INSENSITIVE_MODE_PROVIDERS.has(provider) ? {
|
|
480
|
+
mode: "insensitive"
|
|
481
|
+
} : {};
|
|
482
|
+
}
|
|
483
|
+
__name(insensitively, "insensitively");
|
|
484
|
+
var TEXTUAL_OPERATORS = /* @__PURE__ */ new Set([
|
|
485
|
+
"contains",
|
|
486
|
+
"startsWith",
|
|
487
|
+
"endsWith"
|
|
488
|
+
]);
|
|
489
|
+
function toSearchCondition(model, term, provider) {
|
|
490
|
+
const foreignKeys = new Set(model.fields.map((field) => field.relation?.from).filter((name) => name !== void 0));
|
|
491
|
+
const stringFields = model.fields.filter((field) => field.kind === "string" && !field.isList && !field.isGenerated && !foreignKeys.has(field.name));
|
|
492
|
+
if (stringFields.length === 0) return void 0;
|
|
493
|
+
return {
|
|
494
|
+
OR: stringFields.map((field) => ({
|
|
495
|
+
[field.name]: {
|
|
496
|
+
contains: term,
|
|
497
|
+
...insensitively(provider)
|
|
498
|
+
}
|
|
499
|
+
}))
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
__name(toSearchCondition, "toSearchCondition");
|
|
503
|
+
function buildWhere(model, query, provider) {
|
|
504
|
+
const conditions = [];
|
|
505
|
+
for (const rule of query.filters ?? []) {
|
|
506
|
+
const condition = toPrismaCondition(model, rule);
|
|
507
|
+
conditions.push(TEXTUAL_OPERATORS.has(rule.operator) ? insensitive(condition, provider) : condition);
|
|
508
|
+
}
|
|
509
|
+
const search = query.search?.trim();
|
|
510
|
+
if (search) {
|
|
511
|
+
const searchCondition = toSearchCondition(model, search, provider);
|
|
512
|
+
if (searchCondition) conditions.push(searchCondition);
|
|
513
|
+
}
|
|
514
|
+
if (conditions.length === 0) return void 0;
|
|
515
|
+
if (conditions.length === 1) return conditions[0];
|
|
516
|
+
return {
|
|
517
|
+
AND: conditions
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
__name(buildWhere, "buildWhere");
|
|
521
|
+
function buildOrderBy(model, query) {
|
|
522
|
+
const rules = query.sort ?? [];
|
|
523
|
+
if (rules.length === 0) return void 0;
|
|
524
|
+
return rules.map((rule) => {
|
|
525
|
+
const field = findQueryableField(model, rule.field, "sort");
|
|
526
|
+
return {
|
|
527
|
+
[field.name]: rule.direction
|
|
528
|
+
};
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
__name(buildOrderBy, "buildOrderBy");
|
|
532
|
+
function resolvePagination(query) {
|
|
533
|
+
const rawPage = query.page ?? 1;
|
|
534
|
+
if (!Number.isInteger(rawPage) || rawPage < 1) {
|
|
535
|
+
throw new InvalidQueryError(`"page" must be an integer >= 1, received ${JSON.stringify(query.page)}.`);
|
|
536
|
+
}
|
|
537
|
+
const rawPerPage = query.perPage ?? DEFAULT_PER_PAGE;
|
|
538
|
+
if (!Number.isInteger(rawPerPage) || rawPerPage < 1) {
|
|
539
|
+
throw new InvalidQueryError(`"perPage" must be an integer >= 1, received ${JSON.stringify(query.perPage)}.`);
|
|
540
|
+
}
|
|
541
|
+
const perPage = Math.min(rawPerPage, MAX_PER_PAGE);
|
|
542
|
+
return {
|
|
543
|
+
page: rawPage,
|
|
544
|
+
perPage,
|
|
545
|
+
skip: (rawPage - 1) * perPage,
|
|
546
|
+
take: perPage
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
__name(resolvePagination, "resolvePagination");
|
|
550
|
+
function insensitive(condition, provider) {
|
|
551
|
+
const mode = insensitively(provider);
|
|
552
|
+
if (mode.mode === void 0) return condition;
|
|
553
|
+
const entries = Object.entries(condition).map(([field, comparison]) => [
|
|
554
|
+
field,
|
|
555
|
+
typeof comparison === "object" && comparison !== null ? {
|
|
556
|
+
...comparison,
|
|
557
|
+
...mode
|
|
558
|
+
} : comparison
|
|
559
|
+
]);
|
|
560
|
+
return Object.fromEntries(entries);
|
|
561
|
+
}
|
|
562
|
+
__name(insensitive, "insensitive");
|
|
563
|
+
function toFindManyArgs(model, query, provider) {
|
|
564
|
+
const { skip, take } = resolvePagination(query);
|
|
565
|
+
const where = buildWhere(model, query, provider);
|
|
566
|
+
const orderBy = buildOrderBy(model, query);
|
|
567
|
+
return {
|
|
568
|
+
...where ? {
|
|
569
|
+
where
|
|
570
|
+
} : {},
|
|
571
|
+
...orderBy ? {
|
|
572
|
+
orderBy
|
|
573
|
+
} : {},
|
|
574
|
+
skip,
|
|
575
|
+
take
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
__name(toFindManyArgs, "toFindManyArgs");
|
|
579
|
+
var PRISMA_RECORD_NOT_FOUND = "P2025";
|
|
580
|
+
var PrismaAdapter = class {
|
|
581
|
+
static {
|
|
582
|
+
__name(this, "PrismaAdapter");
|
|
583
|
+
}
|
|
584
|
+
name = "prisma";
|
|
585
|
+
#client;
|
|
586
|
+
#schemaPath;
|
|
587
|
+
#cwd;
|
|
588
|
+
/**
|
|
589
|
+
* Metadata is derived from a static schema, so it is read once and reused.
|
|
590
|
+
* Every operation validates against it, which would otherwise re-parse the
|
|
591
|
+
* schema on each call.
|
|
592
|
+
*/
|
|
593
|
+
#models;
|
|
594
|
+
/**
|
|
595
|
+
* Which database this is, so a search can ignore capitalisation the way that
|
|
596
|
+
* database allows. Read alongside the metadata, and `undefined` when the
|
|
597
|
+
* schema does not say - see `insensitively` in `to-prisma-args.ts`.
|
|
598
|
+
*/
|
|
599
|
+
#provider;
|
|
600
|
+
constructor(options) {
|
|
601
|
+
if (options.client === null || options.client === void 0) {
|
|
602
|
+
throw new AdapterError("PrismaAdapter requires a constructed Prisma Client. Pass one via `new PrismaAdapter({ client })`.");
|
|
603
|
+
}
|
|
604
|
+
this.#client = options.client;
|
|
605
|
+
this.#schemaPath = options.schemaPath;
|
|
606
|
+
this.#cwd = options.cwd;
|
|
607
|
+
}
|
|
608
|
+
async getModels() {
|
|
609
|
+
if (this.#models) return this.#models;
|
|
610
|
+
assertSupportedPrismaVersion(this.#client);
|
|
611
|
+
const dmmf = readPrismaDmmf({
|
|
612
|
+
...this.#schemaPath !== void 0 ? {
|
|
613
|
+
schemaPath: this.#schemaPath
|
|
614
|
+
} : {},
|
|
615
|
+
...this.#cwd !== void 0 ? {
|
|
616
|
+
cwd: this.#cwd
|
|
617
|
+
} : {}
|
|
618
|
+
});
|
|
619
|
+
this.#models = toModelMetadata(dmmf);
|
|
620
|
+
this.#provider = readDatasourceProvider({
|
|
621
|
+
...this.#schemaPath !== void 0 ? {
|
|
622
|
+
schemaPath: this.#schemaPath
|
|
623
|
+
} : {},
|
|
624
|
+
...this.#cwd !== void 0 ? {
|
|
625
|
+
cwd: this.#cwd
|
|
626
|
+
} : {}
|
|
627
|
+
});
|
|
628
|
+
return this.#models;
|
|
629
|
+
}
|
|
630
|
+
async list(model, query) {
|
|
631
|
+
const declared = await this.#requireModel(model);
|
|
632
|
+
const delegate = await this.#delegate(model);
|
|
633
|
+
const metadata = narrowFields(declared, query.fields);
|
|
634
|
+
const args = toFindManyArgs(metadata, query, this.#provider);
|
|
635
|
+
const include = toIncludeClause(metadata, await this.getModels());
|
|
636
|
+
const omit = omitClause(declared, query.fields);
|
|
637
|
+
const withRelations = {
|
|
638
|
+
...args,
|
|
639
|
+
...include ? {
|
|
640
|
+
include
|
|
641
|
+
} : {},
|
|
642
|
+
...omit ? {
|
|
643
|
+
omit
|
|
644
|
+
} : {}
|
|
645
|
+
};
|
|
646
|
+
const { page, perPage } = resolvePagination(query);
|
|
647
|
+
const [rows, total] = await this.#run(model, () => Promise.all([
|
|
648
|
+
delegate.findMany(withRelations),
|
|
649
|
+
delegate.count(args.where ? {
|
|
650
|
+
where: args.where
|
|
651
|
+
} : {})
|
|
652
|
+
]));
|
|
653
|
+
return {
|
|
654
|
+
data: rows,
|
|
655
|
+
total,
|
|
656
|
+
page,
|
|
657
|
+
perPage
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
async findOne(model, id) {
|
|
661
|
+
const metadata = await this.#requireModel(model);
|
|
662
|
+
const delegate = await this.#delegate(model);
|
|
663
|
+
const where = this.#whereById(metadata, id);
|
|
664
|
+
const include = toIncludeClause(metadata, await this.getModels());
|
|
665
|
+
const record = await this.#run(model, () => delegate.findUnique(include ? {
|
|
666
|
+
where,
|
|
667
|
+
include
|
|
668
|
+
} : {
|
|
669
|
+
where
|
|
670
|
+
}));
|
|
671
|
+
return record ?? null;
|
|
672
|
+
}
|
|
673
|
+
async create(model, data) {
|
|
674
|
+
const metadata = await this.#requireModel(model);
|
|
675
|
+
const delegate = await this.#delegate(model);
|
|
676
|
+
const writable = this.#validateWritableData(metadata, data);
|
|
677
|
+
const created = await this.#run(model, () => delegate.create({
|
|
678
|
+
data: writable
|
|
679
|
+
}));
|
|
680
|
+
return created;
|
|
681
|
+
}
|
|
682
|
+
async update(model, id, data) {
|
|
683
|
+
const metadata = await this.#requireModel(model);
|
|
684
|
+
const delegate = await this.#delegate(model);
|
|
685
|
+
const where = this.#whereById(metadata, id);
|
|
686
|
+
const writable = this.#validateWritableData(metadata, data);
|
|
687
|
+
const updated = await this.#run(model, () => delegate.update({
|
|
688
|
+
where,
|
|
689
|
+
data: writable
|
|
690
|
+
}), id);
|
|
691
|
+
return updated;
|
|
692
|
+
}
|
|
693
|
+
async delete(model, id) {
|
|
694
|
+
const metadata = await this.#requireModel(model);
|
|
695
|
+
const delegate = await this.#delegate(model);
|
|
696
|
+
const where = this.#whereById(metadata, id);
|
|
697
|
+
await this.#run(model, () => delegate.delete({
|
|
698
|
+
where
|
|
699
|
+
}), id);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* A page of the records on the far side of a to-many relation.
|
|
703
|
+
*
|
|
704
|
+
* Implemented as an ordinary list of the *target* model with one extra
|
|
705
|
+
* condition, so pagination, sorting, filtering and relation loading all
|
|
706
|
+
* behave exactly as they do on a top-level list. See `to-related-where.ts`.
|
|
707
|
+
*/
|
|
708
|
+
async listRelated(model, id, relationField, query) {
|
|
709
|
+
const metadata = await this.#requireModel(model);
|
|
710
|
+
const models = await this.getModels();
|
|
711
|
+
const { target, where } = toRelatedWhere(metadata, relationField, id, models);
|
|
712
|
+
await this.#requireRecord(model, metadata, id);
|
|
713
|
+
const delegate = await this.#delegate(target.name);
|
|
714
|
+
const narrowed = narrowFields(target, query.fields);
|
|
715
|
+
const args = toFindManyArgs(narrowed, query, this.#provider);
|
|
716
|
+
const combined = args.where ? {
|
|
717
|
+
AND: [
|
|
718
|
+
args.where,
|
|
719
|
+
where
|
|
720
|
+
]
|
|
721
|
+
} : where;
|
|
722
|
+
const include = toIncludeClause(narrowed, models);
|
|
723
|
+
const omit = omitClause(target, query.fields);
|
|
724
|
+
const { page, perPage } = resolvePagination(query);
|
|
725
|
+
const [rows, total] = await this.#run(target.name, () => Promise.all([
|
|
726
|
+
delegate.findMany({
|
|
727
|
+
...args,
|
|
728
|
+
where: combined,
|
|
729
|
+
...include ? {
|
|
730
|
+
include
|
|
731
|
+
} : {},
|
|
732
|
+
...omit ? {
|
|
733
|
+
omit
|
|
734
|
+
} : {}
|
|
735
|
+
}),
|
|
736
|
+
delegate.count({
|
|
737
|
+
where: combined
|
|
738
|
+
})
|
|
739
|
+
]));
|
|
740
|
+
return {
|
|
741
|
+
data: rows,
|
|
742
|
+
total,
|
|
743
|
+
page,
|
|
744
|
+
perPage
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
async attachRelated(model, id, relationField, targetId) {
|
|
748
|
+
await this.#link(model, id, relationField, targetId, "connect");
|
|
749
|
+
}
|
|
750
|
+
async detachRelated(model, id, relationField, targetId) {
|
|
751
|
+
await this.#link(model, id, relationField, targetId, "disconnect");
|
|
752
|
+
}
|
|
753
|
+
// ---------------------------------------------------------------- internals
|
|
754
|
+
/**
|
|
755
|
+
* Add or remove one link, from the parent's side.
|
|
756
|
+
*
|
|
757
|
+
* Prisma expresses both the same way and works out where the link is stored -
|
|
758
|
+
* a join-table row for a many-to-many, the child's foreign key for a
|
|
759
|
+
* one-to-many. Whether the operation is allowed is the caller's decision;
|
|
760
|
+
* this performs it.
|
|
761
|
+
*/
|
|
762
|
+
async #link(model, id, relationField, targetId, operation) {
|
|
763
|
+
const metadata = await this.#requireModel(model);
|
|
764
|
+
const models = await this.getModels();
|
|
765
|
+
const { target } = toRelatedWhere(metadata, relationField, id, models);
|
|
766
|
+
const [targetKey] = target.primaryKey;
|
|
767
|
+
if (targetKey === void 0) {
|
|
768
|
+
throw new FieldNotFoundError(target.name, relationField, "The target has no primary key.");
|
|
769
|
+
}
|
|
770
|
+
const delegate = await this.#delegate(model);
|
|
771
|
+
await this.#run(model, () => delegate.update({
|
|
772
|
+
where: this.#whereById(metadata, id),
|
|
773
|
+
data: {
|
|
774
|
+
[relationField]: {
|
|
775
|
+
[operation]: {
|
|
776
|
+
[targetKey]: targetId
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}), id);
|
|
781
|
+
}
|
|
782
|
+
/** Throw `RecordNotFoundError` unless the record exists. */
|
|
783
|
+
async #requireRecord(model, metadata, id) {
|
|
784
|
+
const delegate = await this.#delegate(model);
|
|
785
|
+
const found = await this.#run(model, () => delegate.findUnique({
|
|
786
|
+
where: this.#whereById(metadata, id)
|
|
787
|
+
}), id);
|
|
788
|
+
if (found === null || found === void 0) throw new RecordNotFoundError(model, id);
|
|
789
|
+
}
|
|
790
|
+
async #requireModel(model) {
|
|
791
|
+
const models = await this.getModels();
|
|
792
|
+
const found = models.find((candidate) => candidate.name === model);
|
|
793
|
+
if (!found) {
|
|
794
|
+
throw new ModelNotFoundError(model, models.map((candidate) => candidate.name));
|
|
795
|
+
}
|
|
796
|
+
return found;
|
|
797
|
+
}
|
|
798
|
+
async #delegate(model) {
|
|
799
|
+
const models = await this.getModels();
|
|
800
|
+
return resolveDelegate(this.#client, model, models.map((candidate) => candidate.name));
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Build a `where` clause addressing a single record by primary key.
|
|
804
|
+
*
|
|
805
|
+
* Composite keys are represented in metadata but not supported here: a
|
|
806
|
+
* `RecordId` is a single scalar, so there is nothing to map the second
|
|
807
|
+
* column from. Rejected explicitly rather than silently mis-querying.
|
|
808
|
+
*/
|
|
809
|
+
#whereById(model, id) {
|
|
810
|
+
const [primaryKeyField, ...rest] = model.primaryKey;
|
|
811
|
+
if (primaryKeyField === void 0) {
|
|
812
|
+
throw new InvalidQueryError(`Model "${model.name}" has no primary key, so records cannot be addressed by id.`);
|
|
813
|
+
}
|
|
814
|
+
if (rest.length > 0) {
|
|
815
|
+
throw new InvalidQueryError(`Model "${model.name}" has a composite primary key (${model.primaryKey.join(", ")}), which is not supported in this version.`);
|
|
816
|
+
}
|
|
817
|
+
return {
|
|
818
|
+
[primaryKeyField]: this.#coerceId(model, primaryKeyField, id)
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Coerce an id to the type the schema declares.
|
|
823
|
+
*
|
|
824
|
+
* Ids arriving from a URL are always strings, but a Prisma `Int @id` column
|
|
825
|
+
* must be queried with a number or Prisma rejects the argument.
|
|
826
|
+
*/
|
|
827
|
+
#coerceId(model, fieldName, id) {
|
|
828
|
+
const field = model.fields.find((candidate) => candidate.name === fieldName);
|
|
829
|
+
if (field?.kind !== "number" || typeof id === "number") return id;
|
|
830
|
+
const numeric = Number(id);
|
|
831
|
+
if (!Number.isFinite(numeric)) {
|
|
832
|
+
throw new InvalidQueryError(`Invalid id ${JSON.stringify(id)} for numeric primary key "${model.name}.${fieldName}".`);
|
|
833
|
+
}
|
|
834
|
+
return numeric;
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Reject anything the caller has no business writing.
|
|
838
|
+
*
|
|
839
|
+
* Unknown keys are an error rather than silently dropped: quietly discarding
|
|
840
|
+
* a field the user filled in is worse than telling them it does not exist.
|
|
841
|
+
* Relation and list fields are rejected because nested writes are not
|
|
842
|
+
* implemented - see the Phase 2 report.
|
|
843
|
+
*/
|
|
844
|
+
#validateWritableData(model, data) {
|
|
845
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
846
|
+
throw new InvalidQueryError(`Write payload for "${model.name}" must be an object.`);
|
|
847
|
+
}
|
|
848
|
+
const writable = {};
|
|
849
|
+
for (const [key, value] of Object.entries(data)) {
|
|
850
|
+
const field = model.fields.find((candidate) => candidate.name === key);
|
|
851
|
+
if (!field) {
|
|
852
|
+
throw new FieldNotFoundError(model.name, key);
|
|
853
|
+
}
|
|
854
|
+
if (field.kind === "relation") {
|
|
855
|
+
throw new FieldNotFoundError(model.name, key, "Writing relation fields is not supported in this version.");
|
|
856
|
+
}
|
|
857
|
+
if (field.isList) {
|
|
858
|
+
throw new FieldNotFoundError(model.name, key, "Writing list fields is not supported in this version.");
|
|
859
|
+
}
|
|
860
|
+
writable[key] = value;
|
|
861
|
+
}
|
|
862
|
+
return writable;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Run a client call, translating Prisma failures into Core errors.
|
|
866
|
+
*
|
|
867
|
+
* Prisma error types are identified by their `code` property rather than
|
|
868
|
+
* `instanceof`. Importing `@prisma/client` to get the error classes would
|
|
869
|
+
* mean loading a second copy of a package the consumer owns, and would tie
|
|
870
|
+
* us to their Prisma version.
|
|
871
|
+
*/
|
|
872
|
+
async #run(model, operation, id) {
|
|
873
|
+
try {
|
|
874
|
+
return await operation();
|
|
875
|
+
} catch (cause) {
|
|
876
|
+
if (isNestAdminError(cause)) throw cause;
|
|
877
|
+
if (isPrismaError(cause) && cause.code === PRISMA_RECORD_NOT_FOUND && id !== void 0) {
|
|
878
|
+
throw new RecordNotFoundError(model, id);
|
|
879
|
+
}
|
|
880
|
+
const constraint = toConstraintError(cause, model);
|
|
881
|
+
if (constraint) throw constraint;
|
|
882
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
883
|
+
throw new AdapterError(`Prisma operation failed for model "${model}": ${detail}`, {
|
|
884
|
+
cause
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
function isPrismaError(value) {
|
|
890
|
+
return typeof value === "object" && value !== null && "code" in value && typeof value.code === "string";
|
|
891
|
+
}
|
|
892
|
+
__name(isPrismaError, "isPrismaError");
|
|
893
|
+
function narrowFields(model, fields) {
|
|
894
|
+
if (!fields) return model;
|
|
895
|
+
const allowed = new Set(fields);
|
|
896
|
+
return {
|
|
897
|
+
...model,
|
|
898
|
+
fields: model.fields.filter((field) => allowed.has(field.name))
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
__name(narrowFields, "narrowFields");
|
|
902
|
+
function omitClause(model, fields) {
|
|
903
|
+
if (!fields) return void 0;
|
|
904
|
+
const allowed = new Set(fields);
|
|
905
|
+
const omitted = {};
|
|
906
|
+
for (const field of model.fields) {
|
|
907
|
+
if (!allowed.has(field.name) && field.kind !== "relation") omitted[field.name] = true;
|
|
908
|
+
}
|
|
909
|
+
return Object.keys(omitted).length > 0 ? omitted : void 0;
|
|
910
|
+
}
|
|
911
|
+
__name(omitClause, "omitClause");
|
|
912
|
+
var DEFAULTS = {
|
|
913
|
+
id: "id",
|
|
914
|
+
email: "email",
|
|
915
|
+
name: "name",
|
|
916
|
+
passwordHash: "passwordHash",
|
|
917
|
+
disabled: "disabled",
|
|
918
|
+
lastLoginAt: "lastLoginAt"
|
|
919
|
+
};
|
|
920
|
+
function prismaAccountStore(options) {
|
|
921
|
+
const model = options.model ?? "AdminAccount";
|
|
922
|
+
const column = {
|
|
923
|
+
...DEFAULTS,
|
|
924
|
+
...options.fields
|
|
925
|
+
};
|
|
926
|
+
const delegate = /* @__PURE__ */ __name(() => resolveDelegate(options.client, model, [
|
|
927
|
+
model
|
|
928
|
+
]), "delegate");
|
|
929
|
+
const toAccount = /* @__PURE__ */ __name((row) => {
|
|
930
|
+
if (typeof row !== "object" || row === null) return null;
|
|
931
|
+
const record = row;
|
|
932
|
+
const id = record[column.id];
|
|
933
|
+
const email = record[column.email];
|
|
934
|
+
const hash = record[column.passwordHash];
|
|
935
|
+
if (typeof id !== "string" && typeof id !== "number") return null;
|
|
936
|
+
if (typeof email !== "string") return null;
|
|
937
|
+
if (typeof hash !== "string" || hash === "") return null;
|
|
938
|
+
const name = record[column.name];
|
|
939
|
+
const disabled = record[column.disabled];
|
|
940
|
+
return {
|
|
941
|
+
id: String(id),
|
|
942
|
+
email,
|
|
943
|
+
passwordHash: hash,
|
|
944
|
+
...typeof name === "string" && name !== "" ? {
|
|
945
|
+
name
|
|
946
|
+
} : {},
|
|
947
|
+
...typeof disabled === "boolean" ? {
|
|
948
|
+
disabled
|
|
949
|
+
} : {}
|
|
950
|
+
};
|
|
951
|
+
}, "toAccount");
|
|
952
|
+
return {
|
|
953
|
+
describes: model,
|
|
954
|
+
async findByEmail(email) {
|
|
955
|
+
const rows = await delegate().findMany({
|
|
956
|
+
where: {
|
|
957
|
+
[column.email]: email
|
|
958
|
+
},
|
|
959
|
+
take: 1
|
|
960
|
+
});
|
|
961
|
+
return toAccount(rows[0]);
|
|
962
|
+
},
|
|
963
|
+
async findById(id) {
|
|
964
|
+
const rows = await delegate().findMany({
|
|
965
|
+
where: {
|
|
966
|
+
[column.id]: id
|
|
967
|
+
},
|
|
968
|
+
take: 1
|
|
969
|
+
});
|
|
970
|
+
return toAccount(rows[0]);
|
|
971
|
+
},
|
|
972
|
+
async count() {
|
|
973
|
+
return delegate().count();
|
|
974
|
+
},
|
|
975
|
+
async recordLogin(id) {
|
|
976
|
+
await delegate().update({
|
|
977
|
+
where: {
|
|
978
|
+
[column.id]: id
|
|
979
|
+
},
|
|
980
|
+
data: {
|
|
981
|
+
[column.lastLoginAt]: /* @__PURE__ */ new Date()
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
__name(prismaAccountStore, "prismaAccountStore");
|
|
988
|
+
export {
|
|
989
|
+
PrismaAdapter,
|
|
990
|
+
PrismaSchemaInvalidError,
|
|
991
|
+
PrismaSchemaNotFoundError,
|
|
992
|
+
PrismaVersionUnsupportedError,
|
|
993
|
+
prismaAccountStore
|
|
994
|
+
};
|
|
995
|
+
//# sourceMappingURL=prisma.js.map
|