@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/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