proclamation-categories: sub-category management inline in parent form

- Registry: Remove 'parent.name' from listFields (all shown records
  are top-level with no parent), remove 'parent: true' from include
  since unused
- +page.server.ts: Custom load filters to parentId=null (top-level
  only); custom upsert syncs children (create/update/delete) and
  handles P2002 duplicate-name errors; custom delete cascades to
  children first to avoid FK constraint violations
- CategoryForm.svelte: Replace parentId select dropdown with dynamic
  list of sub-category inputs. Each row has a name field and Remove
  button. Pre-populates from record.children when editing existing
  categories. Add Sub-category button appends new rows
- +page.svelte: Remove unused relationOptionsData prop from
  CategoryForm; rename submit button label from 'Update' to 'Save'
- prisma: Add ProclamationCategorySubscriptionLevel join table
  migration and regenerate client
- General: Update TipTap mock, Toast, license-keys page, proclamations
  server/route tests, README, AGENTS.md, and other admin forms
This commit is contained in:
NeilClack
2026-07-08 10:31:28 -05:00
parent 37bed4f64c
commit 93d941569e
35 changed files with 23467 additions and 19108 deletions
+11 -11
View File
@@ -6,16 +6,16 @@ SvelteKit 2 + Svelte 5 + Tailwind CSS v4 + Prisma 7 + PostgreSQL + Better-Auth.
Admin CRUD pages at `/admin`. 9 models have per-page routes with modals for create/edit: Admin CRUD pages at `/admin`. 9 models have per-page routes with modals for create/edit:
| Included | Excluded | | Included | Excluded |
| -------- | --------------------- | | ------------------------ | --------------------------------- |
| users | Session (Better Auth) | | users | Session (Better Auth) |
| profiles | Account (Better Auth) | | profiles | Account (Better Auth) |
| addresses| Verification (Better Auth) | | addresses | Verification (Better Auth) |
| user-roles | UserProclamations (composite key) | | user-roles | UserProclamations (composite key) |
| proclamations | | | proclamations | |
| solfeggio-frequencies | | | solfeggio-frequencies | |
| proclamation-categories | | | proclamation-categories | |
| license-keys (list-only) | | | license-keys (list-only) | |
| subscription-levels | | | subscription-levels | |
See `src/lib/svelte-admin/README.md` for architecture and configuration docs. See `src/lib/svelte-admin/README.md` for architecture and configuration docs.
@@ -0,0 +1,19 @@
-- DropIndex
DROP INDEX "Proclamation_subscriptionLevelId_idx";
-- AlterTable
ALTER TABLE "Proclamation" ALTER COLUMN "subscriptionLevelId" DROP DEFAULT;
-- CreateTable
CREATE TABLE "ProclamationCategorySubscriptionLevel" (
"categoryId" INTEGER NOT NULL,
"subscriptionLevelId" INTEGER NOT NULL,
CONSTRAINT "ProclamationCategorySubscriptionLevel_pkey" PRIMARY KEY ("categoryId","subscriptionLevelId")
);
-- AddForeignKey
ALTER TABLE "ProclamationCategorySubscriptionLevel" ADD CONSTRAINT "ProclamationCategorySubscriptionLevel_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "ProclamationCategory"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ProclamationCategorySubscriptionLevel" ADD CONSTRAINT "ProclamationCategorySubscriptionLevel_subscriptionLevelId_fkey" FOREIGN KEY ("subscriptionLevelId") REFERENCES "SubscriptionLevel"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+22 -12
View File
@@ -124,10 +124,8 @@ model Proclamation {
categoryId Int categoryId Int
category ProclamationCategory @relation(fields: [categoryId], references: [id]) category ProclamationCategory @relation(fields: [categoryId], references: [id])
userProclamations UserProclamations[] userProclamations UserProclamations[]
subscriptionLevelId Int @default(1) subscriptionLevelId Int // Keeping old FK for migration stability
subscriptionLevel SubscriptionLevel @relation(fields: [subscriptionLevelId], references: [id]) subscriptionLevel SubscriptionLevel @relation(fields: [subscriptionLevelId], references: [id])
@@index(subscriptionLevelId)
} }
model UserProclamations { model UserProclamations {
@@ -149,16 +147,27 @@ model SolfeggioFrequency {
} }
model ProclamationCategory { model ProclamationCategory {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
parentId Int? parentId Int?
parent ProclamationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id]) parent ProclamationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id])
children ProclamationCategory[] @relation("CategoryHierarchy") children ProclamationCategory[] @relation("CategoryHierarchy")
proclamations Proclamation[] proclamations Proclamation[]
subscriptionLevels ProclamationCategorySubscriptionLevel[]
@@unique([parentId, name]) @@unique([parentId, name])
} }
// Join table for ProclamationCategory -> SubscriptionLevel defaults
model ProclamationCategorySubscriptionLevel {
categoryId Int
category ProclamationCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade)
subscriptionLevelId Int
subscriptionLevel SubscriptionLevel @relation(fields: [subscriptionLevelId], references: [id], onDelete: Cascade)
@@id([categoryId, subscriptionLevelId])
}
model LicenseKey { model LicenseKey {
id String @id @default(uuid()) id String @id @default(uuid())
key String @unique key String @unique
@@ -169,8 +178,9 @@ model LicenseKey {
} }
model SubscriptionLevel { model SubscriptionLevel {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
description String? description String?
proclamations Proclamation[] proclamations Proclamation[]
categoryLevels ProclamationCategorySubscriptionLevel[]
} }
+5 -6
View File
@@ -32,16 +32,15 @@
{#if visible} {#if visible}
<div <div
role="alert" role="alert"
class="fixed bottom-4 left-4 z-50 flex min-w-64 items-center gap-3 border px-4 py-3 text-sm shadow-lg {type === 'success' class="fixed bottom-4 left-4 z-50 flex min-w-64 items-center gap-3 border px-4 py-3 text-sm shadow-lg {type ===
'success'
? 'border-green-600 bg-green-50 text-green-800' ? 'border-green-600 bg-green-50 text-green-800'
: 'border-red-600 bg-red-50 text-red-800'}" : 'border-red-600 bg-red-50 text-red-800'}"
> >
<span class="flex-1">{message}</span> <span class="flex-1">{message}</span>
<span class="tabular-nums text-xs opacity-70">{remaining}s</span> <span class="text-xs tabular-nums opacity-70">{remaining}s</span>
<button <button type="button" onclick={dismiss} class="ml-1 leading-none font-bold hover:opacity-70"
type="button" >&times;</button
onclick={dismiss}
class="ml-1 font-bold leading-none hover:opacity-70">&times;</button
> >
</div> </div>
{/if} {/if}
+19 -8
View File
@@ -30,7 +30,8 @@
content: initialContent, content: initialContent,
editorProps: { editorProps: {
attributes: { attributes: {
class: 'prose prose-sm max-w-none outline-none h-full min-h-40 p-3 dark:prose-invert dark:text-gray-100' class:
'prose prose-sm max-w-none outline-none h-full min-h-40 p-3 dark:prose-invert dark:text-gray-100'
} }
}, },
onUpdate: ({ editor }) => { onUpdate: ({ editor }) => {
@@ -43,9 +44,15 @@
return () => editor.destroy(); return () => editor.destroy();
}); });
function toggleBold() { editor?.chain().focus().toggleBold().run(); } function toggleBold() {
function toggleItalic() { editor?.chain().focus().toggleItalic().run(); } editor?.chain().focus().toggleBold().run();
function toggleHighlight() { editor?.chain().focus().toggleHighlight().run(); } }
function toggleItalic() {
editor?.chain().focus().toggleItalic().run();
}
function toggleHighlight() {
editor?.chain().focus().toggleHighlight().run();
}
function setColor() { function setColor() {
const current = editor?.getAttributes('textStyle').color ?? '#000000'; const current = editor?.getAttributes('textStyle').color ?? '#000000';
@@ -64,22 +71,26 @@
type="button" type="button"
onclick={toggleBold} onclick={toggleBold}
class="min-w-8 px-2 py-1 font-bold hover:bg-gray-200 dark:hover:bg-gray-700" class="min-w-8 px-2 py-1 font-bold hover:bg-gray-200 dark:hover:bg-gray-700"
title="Bold">B</button> title="Bold">B</button
>
<button <button
type="button" type="button"
onclick={toggleItalic} onclick={toggleItalic}
class="min-w-8 px-2 py-1 italic hover:bg-gray-200 dark:hover:bg-gray-700" class="min-w-8 px-2 py-1 italic hover:bg-gray-200 dark:hover:bg-gray-700"
title="Italic">I</button> title="Italic">I</button
>
<button <button
type="button" type="button"
onclick={toggleHighlight} onclick={toggleHighlight}
class="min-w-8 px-2 py-1 hover:bg-gray-200 dark:hover:bg-gray-700" class="min-w-8 px-2 py-1 hover:bg-gray-200 dark:hover:bg-gray-700"
title="Highlight"><span class="bg-yellow-200 px-1 dark:bg-yellow-600">H</span></button> title="Highlight"><span class="bg-yellow-200 px-1 dark:bg-yellow-600">H</span></button
>
<button <button
type="button" type="button"
onclick={setColor} onclick={setColor}
class="min-w-8 px-2 py-1 hover:bg-gray-200 dark:hover:bg-gray-700" class="min-w-8 px-2 py-1 hover:bg-gray-200 dark:hover:bg-gray-700"
title="Cycle text color">A</button> title="Cycle text color">A</button
>
</div> </div>
<div <div
bind:this={element} bind:this={element}
+32 -33
View File
@@ -1,84 +1,83 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file should be your main import to use Prisma-related types and utilities in a browser. * This file should be your main import to use Prisma-related types and utilities in a browser.
* Use it to get access to models, enums, and input types. * Use it to get access to models, enums, and input types.
* *
* This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only. * This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
* See `client.ts` for the standard, server-side entry point. * See `client.ts` for the standard, server-side entry point.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import * as Prisma from './internal/prismaNamespaceBrowser.ts' import * as Prisma from './internal/prismaNamespaceBrowser.ts';
export { Prisma } export { Prisma };
export * as $Enums from './enums.ts' export * as $Enums from './enums.ts';
export * from './enums.ts'; export * from './enums.ts';
/** /**
* Model User * Model User
* *
*/ */
export type User = Prisma.UserModel export type User = Prisma.UserModel;
/** /**
* Model Profile * Model Profile
* *
*/ */
export type Profile = Prisma.ProfileModel export type Profile = Prisma.ProfileModel;
/** /**
* Model Address * Model Address
* *
*/ */
export type Address = Prisma.AddressModel export type Address = Prisma.AddressModel;
/** /**
* Model Session * Model Session
* *
*/ */
export type Session = Prisma.SessionModel export type Session = Prisma.SessionModel;
/** /**
* Model Account * Model Account
* *
*/ */
export type Account = Prisma.AccountModel export type Account = Prisma.AccountModel;
/** /**
* Model UserRole * Model UserRole
* *
*/ */
export type UserRole = Prisma.UserRoleModel export type UserRole = Prisma.UserRoleModel;
/** /**
* Model Verification * Model Verification
* *
*/ */
export type Verification = Prisma.VerificationModel export type Verification = Prisma.VerificationModel;
/** /**
* Model Proclamation * Model Proclamation
* *
*/ */
export type Proclamation = Prisma.ProclamationModel export type Proclamation = Prisma.ProclamationModel;
/** /**
* Model UserProclamations * Model UserProclamations
* *
*/ */
export type UserProclamations = Prisma.UserProclamationsModel export type UserProclamations = Prisma.UserProclamationsModel;
/** /**
* Model SolfeggioFrequency * Model SolfeggioFrequency
* *
*/ */
export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel;
/** /**
* Model ProclamationCategory * Model ProclamationCategory
* *
*/ */
export type ProclamationCategory = Prisma.ProclamationCategoryModel export type ProclamationCategory = Prisma.ProclamationCategoryModel;
/** /**
* Model LicenseKey * Model LicenseKey
* *
*/ */
export type LicenseKey = Prisma.LicenseKeyModel export type LicenseKey = Prisma.LicenseKeyModel;
/** /**
* Model SubscriptionLevel * Model SubscriptionLevel
* *
*/ */
export type SubscriptionLevel = Prisma.SubscriptionLevelModel export type SubscriptionLevel = Prisma.SubscriptionLevelModel;
+46 -43
View File
@@ -1,8 +1,7 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types. * This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
* If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead. * If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
@@ -10,21 +9,21 @@
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import * as process from 'node:process' import * as process from 'node:process';
import * as path from 'node:path' import * as path from 'node:path';
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url';
globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url)) globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url));
import * as runtime from "@prisma/client/runtime/client" import * as runtime from '@prisma/client/runtime/client';
import * as $Enums from "./enums.ts" import * as $Enums from './enums.ts';
import * as $Class from "./internal/class.ts" import * as $Class from './internal/class.ts';
import * as Prisma from "./internal/prismaNamespace.ts" import * as Prisma from './internal/prismaNamespace.ts';
export * as $Enums from './enums.ts' export * as $Enums from './enums.ts';
export * from "./enums.ts" export * from './enums.ts';
/** /**
* ## Prisma Client * ## Prisma Client
* *
* Type-safe database client for TypeScript * Type-safe database client for TypeScript
* @example * @example
* ``` * ```
@@ -34,75 +33,79 @@ export * from "./enums.ts"
* // Fetch zero or more Users * // Fetch zero or more Users
* const users = await prisma.user.findMany() * const users = await prisma.user.findMany()
* ``` * ```
* *
* Read more in our [docs](https://pris.ly/d/client). * Read more in our [docs](https://pris.ly/d/client).
*/ */
export const PrismaClient = $Class.getPrismaClientClass() export const PrismaClient = $Class.getPrismaClientClass();
export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs> export type PrismaClient<
export { Prisma } LogOpts extends Prisma.LogLevel = never,
OmitOpts extends Prisma.PrismaClientOptions['omit'] = Prisma.PrismaClientOptions['omit'],
ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs
> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>;
export { Prisma };
/** /**
* Model User * Model User
* *
*/ */
export type User = Prisma.UserModel export type User = Prisma.UserModel;
/** /**
* Model Profile * Model Profile
* *
*/ */
export type Profile = Prisma.ProfileModel export type Profile = Prisma.ProfileModel;
/** /**
* Model Address * Model Address
* *
*/ */
export type Address = Prisma.AddressModel export type Address = Prisma.AddressModel;
/** /**
* Model Session * Model Session
* *
*/ */
export type Session = Prisma.SessionModel export type Session = Prisma.SessionModel;
/** /**
* Model Account * Model Account
* *
*/ */
export type Account = Prisma.AccountModel export type Account = Prisma.AccountModel;
/** /**
* Model UserRole * Model UserRole
* *
*/ */
export type UserRole = Prisma.UserRoleModel export type UserRole = Prisma.UserRoleModel;
/** /**
* Model Verification * Model Verification
* *
*/ */
export type Verification = Prisma.VerificationModel export type Verification = Prisma.VerificationModel;
/** /**
* Model Proclamation * Model Proclamation
* *
*/ */
export type Proclamation = Prisma.ProclamationModel export type Proclamation = Prisma.ProclamationModel;
/** /**
* Model UserProclamations * Model UserProclamations
* *
*/ */
export type UserProclamations = Prisma.UserProclamationsModel export type UserProclamations = Prisma.UserProclamationsModel;
/** /**
* Model SolfeggioFrequency * Model SolfeggioFrequency
* *
*/ */
export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel;
/** /**
* Model ProclamationCategory * Model ProclamationCategory
* *
*/ */
export type ProclamationCategory = Prisma.ProclamationCategoryModel export type ProclamationCategory = Prisma.ProclamationCategoryModel;
/** /**
* Model LicenseKey * Model LicenseKey
* *
*/ */
export type LicenseKey = Prisma.LicenseKeyModel export type LicenseKey = Prisma.LicenseKeyModel;
/** /**
* Model SubscriptionLevel * Model SubscriptionLevel
* *
*/ */
export type SubscriptionLevel = Prisma.SubscriptionLevelModel export type SubscriptionLevel = Prisma.SubscriptionLevelModel;
+331 -335
View File
@@ -1,406 +1,402 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file exports various common sort, input & filter types that are not directly linked to a particular model. * This file exports various common sort, input & filter types that are not directly linked to a particular model.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import type * as runtime from "@prisma/client/runtime/client" import type * as runtime from '@prisma/client/runtime/client';
import * as $Enums from "./enums.ts" import * as $Enums from './enums.ts';
import type * as Prisma from "./internal/prismaNamespace.ts" import type * as Prisma from './internal/prismaNamespace.ts';
export type StringFilter<$PrismaModel = never> = { export type StringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> equals?: string | Prisma.StringFieldRefInput<$PrismaModel>;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
mode?: Prisma.QueryMode mode?: Prisma.QueryMode;
not?: Prisma.NestedStringFilter<$PrismaModel> | string not?: Prisma.NestedStringFilter<$PrismaModel> | string;
} };
export type BoolFilter<$PrismaModel = never> = { export type BoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel> equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>;
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean;
} };
export type StringNullableFilter<$PrismaModel = never> = { export type StringNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
mode?: Prisma.QueryMode mode?: Prisma.QueryMode;
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null;
} };
export type DateTimeFilter<$PrismaModel = never> = { export type DateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string;
} };
export type IntNullableFilter<$PrismaModel = never> = { export type IntNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null;
} };
export type SortOrderInput = { export type SortOrderInput = {
sort: Prisma.SortOrder sort: Prisma.SortOrder;
nulls?: Prisma.NullsOrder nulls?: Prisma.NullsOrder;
} };
export type StringWithAggregatesFilter<$PrismaModel = never> = { export type StringWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> equals?: string | Prisma.StringFieldRefInput<$PrismaModel>;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
mode?: Prisma.QueryMode mode?: Prisma.QueryMode;
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedStringFilter<$PrismaModel> _min?: Prisma.NestedStringFilter<$PrismaModel>;
_max?: Prisma.NestedStringFilter<$PrismaModel> _max?: Prisma.NestedStringFilter<$PrismaModel>;
} };
export type BoolWithAggregatesFilter<$PrismaModel = never> = { export type BoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel> equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>;
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedBoolFilter<$PrismaModel> _min?: Prisma.NestedBoolFilter<$PrismaModel>;
_max?: Prisma.NestedBoolFilter<$PrismaModel> _max?: Prisma.NestedBoolFilter<$PrismaModel>;
} };
export type StringNullableWithAggregatesFilter<$PrismaModel = never> = { export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
mode?: Prisma.QueryMode mode?: Prisma.QueryMode;
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedStringNullableFilter<$PrismaModel> _min?: Prisma.NestedStringNullableFilter<$PrismaModel>;
_max?: Prisma.NestedStringNullableFilter<$PrismaModel> _max?: Prisma.NestedStringNullableFilter<$PrismaModel>;
} };
export type DateTimeWithAggregatesFilter<$PrismaModel = never> = { export type DateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedDateTimeFilter<$PrismaModel> _min?: Prisma.NestedDateTimeFilter<$PrismaModel>;
_max?: Prisma.NestedDateTimeFilter<$PrismaModel> _max?: Prisma.NestedDateTimeFilter<$PrismaModel>;
} };
export type IntNullableWithAggregatesFilter<$PrismaModel = never> = { export type IntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel> _avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>;
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel> _sum?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedIntNullableFilter<$PrismaModel> _min?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_max?: Prisma.NestedIntNullableFilter<$PrismaModel> _max?: Prisma.NestedIntNullableFilter<$PrismaModel>;
} };
export type DateTimeNullableFilter<$PrismaModel = never> = { export type DateTimeNullableFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null;
} };
export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> _min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>;
_max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>;
} };
export type IntFilter<$PrismaModel = never> = { export type IntFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> equals?: number | Prisma.IntFieldRefInput<$PrismaModel>;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntFilter<$PrismaModel> | number not?: Prisma.NestedIntFilter<$PrismaModel> | number;
} };
export type IntWithAggregatesFilter<$PrismaModel = never> = { export type IntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> equals?: number | Prisma.IntFieldRefInput<$PrismaModel>;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_avg?: Prisma.NestedFloatFilter<$PrismaModel> _avg?: Prisma.NestedFloatFilter<$PrismaModel>;
_sum?: Prisma.NestedIntFilter<$PrismaModel> _sum?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedIntFilter<$PrismaModel> _min?: Prisma.NestedIntFilter<$PrismaModel>;
_max?: Prisma.NestedIntFilter<$PrismaModel> _max?: Prisma.NestedIntFilter<$PrismaModel>;
} };
export type NestedStringFilter<$PrismaModel = never> = { export type NestedStringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> equals?: string | Prisma.StringFieldRefInput<$PrismaModel>;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
not?: Prisma.NestedStringFilter<$PrismaModel> | string not?: Prisma.NestedStringFilter<$PrismaModel> | string;
} };
export type NestedBoolFilter<$PrismaModel = never> = { export type NestedBoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel> equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>;
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean;
} };
export type NestedStringNullableFilter<$PrismaModel = never> = { export type NestedStringNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null;
} };
export type NestedDateTimeFilter<$PrismaModel = never> = { export type NestedDateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string;
} };
export type NestedIntNullableFilter<$PrismaModel = never> = { export type NestedIntNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null;
} };
export type NestedStringWithAggregatesFilter<$PrismaModel = never> = { export type NestedStringWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> equals?: string | Prisma.StringFieldRefInput<$PrismaModel>;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedStringFilter<$PrismaModel> _min?: Prisma.NestedStringFilter<$PrismaModel>;
_max?: Prisma.NestedStringFilter<$PrismaModel> _max?: Prisma.NestedStringFilter<$PrismaModel>;
} };
export type NestedIntFilter<$PrismaModel = never> = { export type NestedIntFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> equals?: number | Prisma.IntFieldRefInput<$PrismaModel>;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntFilter<$PrismaModel> | number not?: Prisma.NestedIntFilter<$PrismaModel> | number;
} };
export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = { export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel> equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>;
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedBoolFilter<$PrismaModel> _min?: Prisma.NestedBoolFilter<$PrismaModel>;
_max?: Prisma.NestedBoolFilter<$PrismaModel> _max?: Prisma.NestedBoolFilter<$PrismaModel>;
} };
export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null;
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null;
lt?: string | Prisma.StringFieldRefInput<$PrismaModel> lt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
lte?: string | Prisma.StringFieldRefInput<$PrismaModel> lte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gt?: string | Prisma.StringFieldRefInput<$PrismaModel> gt?: string | Prisma.StringFieldRefInput<$PrismaModel>;
gte?: string | Prisma.StringFieldRefInput<$PrismaModel> gte?: string | Prisma.StringFieldRefInput<$PrismaModel>;
contains?: string | Prisma.StringFieldRefInput<$PrismaModel> contains?: string | Prisma.StringFieldRefInput<$PrismaModel>;
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel> endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>;
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedStringNullableFilter<$PrismaModel> _min?: Prisma.NestedStringNullableFilter<$PrismaModel>;
_max?: Prisma.NestedStringNullableFilter<$PrismaModel> _max?: Prisma.NestedStringNullableFilter<$PrismaModel>;
} };
export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = { export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedDateTimeFilter<$PrismaModel> _min?: Prisma.NestedDateTimeFilter<$PrismaModel>;
_max?: Prisma.NestedDateTimeFilter<$PrismaModel> _max?: Prisma.NestedDateTimeFilter<$PrismaModel>;
} };
export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel> _avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>;
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel> _sum?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedIntNullableFilter<$PrismaModel> _min?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_max?: Prisma.NestedIntNullableFilter<$PrismaModel> _max?: Prisma.NestedIntNullableFilter<$PrismaModel>;
} };
export type NestedFloatNullableFilter<$PrismaModel = never> = { export type NestedFloatNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> | null equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> | null;
in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null;
notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null;
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel> lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel> lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel> gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel> gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null;
} };
export type NestedDateTimeNullableFilter<$PrismaModel = never> = { export type NestedDateTimeNullableFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null;
} };
export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null;
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null;
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>;
not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null;
_count?: Prisma.NestedIntNullableFilter<$PrismaModel> _count?: Prisma.NestedIntNullableFilter<$PrismaModel>;
_min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> _min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>;
_max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>;
} };
export type NestedIntWithAggregatesFilter<$PrismaModel = never> = { export type NestedIntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> equals?: number | Prisma.IntFieldRefInput<$PrismaModel>;
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>;
lt?: number | Prisma.IntFieldRefInput<$PrismaModel> lt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
lte?: number | Prisma.IntFieldRefInput<$PrismaModel> lte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gt?: number | Prisma.IntFieldRefInput<$PrismaModel> gt?: number | Prisma.IntFieldRefInput<$PrismaModel>;
gte?: number | Prisma.IntFieldRefInput<$PrismaModel> gte?: number | Prisma.IntFieldRefInput<$PrismaModel>;
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number;
_count?: Prisma.NestedIntFilter<$PrismaModel> _count?: Prisma.NestedIntFilter<$PrismaModel>;
_avg?: Prisma.NestedFloatFilter<$PrismaModel> _avg?: Prisma.NestedFloatFilter<$PrismaModel>;
_sum?: Prisma.NestedIntFilter<$PrismaModel> _sum?: Prisma.NestedIntFilter<$PrismaModel>;
_min?: Prisma.NestedIntFilter<$PrismaModel> _min?: Prisma.NestedIntFilter<$PrismaModel>;
_max?: Prisma.NestedIntFilter<$PrismaModel> _max?: Prisma.NestedIntFilter<$PrismaModel>;
} };
export type NestedFloatFilter<$PrismaModel = never> = { export type NestedFloatFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> equals?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>;
notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>;
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel> lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel> lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel> gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel> gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>;
not?: Prisma.NestedFloatFilter<$PrismaModel> | number not?: Prisma.NestedFloatFilter<$PrismaModel> | number;
} };
+6 -9
View File
@@ -1,15 +1,12 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file exports all enum related types from the schema. * This file exports all enum related types from the schema.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
// This file is empty because there are no enums in the schema. // This file is empty because there are no enums in the schema.
export {} export {};
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1,8 +1,7 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* WARNING: This is an internal file that is subject to change! * WARNING: This is an internal file that is subject to change!
* *
@@ -15,249 +14,243 @@
* model files in the `model` directory! * model files in the `model` directory!
*/ */
import * as runtime from "@prisma/client/runtime/index-browser" import * as runtime from '@prisma/client/runtime/index-browser';
export type * from '../models.ts' export type * from '../models.ts';
export type * from './prismaNamespace.ts' export type * from './prismaNamespace.ts';
export const Decimal = runtime.Decimal
export const Decimal = runtime.Decimal;
export const NullTypes = { export const NullTypes = {
DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull), DbNull: runtime.NullTypes.DbNull as new (secret: never) => typeof runtime.DbNull,
JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull), JsonNull: runtime.NullTypes.JsonNull as new (secret: never) => typeof runtime.JsonNull,
AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull), AnyNull: runtime.NullTypes.AnyNull as new (secret: never) => typeof runtime.AnyNull
} };
/** /**
* Helper for filtering JSON entries that have `null` on the database (empty on the db) * Helper for filtering JSON entries that have `null` on the database (empty on the db)
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const DbNull = runtime.DbNull export const DbNull = runtime.DbNull;
/** /**
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db) * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const JsonNull = runtime.JsonNull export const JsonNull = runtime.JsonNull;
/** /**
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull` * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const AnyNull = runtime.AnyNull export const AnyNull = runtime.AnyNull;
export const ModelName = { export const ModelName = {
User: 'User', User: 'User',
Profile: 'Profile', Profile: 'Profile',
Address: 'Address', Address: 'Address',
Session: 'Session', Session: 'Session',
Account: 'Account', Account: 'Account',
UserRole: 'UserRole', UserRole: 'UserRole',
Verification: 'Verification', Verification: 'Verification',
Proclamation: 'Proclamation', Proclamation: 'Proclamation',
UserProclamations: 'UserProclamations', UserProclamations: 'UserProclamations',
SolfeggioFrequency: 'SolfeggioFrequency', SolfeggioFrequency: 'SolfeggioFrequency',
ProclamationCategory: 'ProclamationCategory', ProclamationCategory: 'ProclamationCategory',
LicenseKey: 'LicenseKey', LicenseKey: 'LicenseKey',
SubscriptionLevel: 'SubscriptionLevel' SubscriptionLevel: 'SubscriptionLevel'
} as const } as const;
export type ModelName = (typeof ModelName)[keyof typeof ModelName] export type ModelName = (typeof ModelName)[keyof typeof ModelName];
/* /*
* Enums * Enums
*/ */
export const TransactionIsolationLevel = runtime.makeStrictEnum({ export const TransactionIsolationLevel = runtime.makeStrictEnum({
ReadUncommitted: 'ReadUncommitted', ReadUncommitted: 'ReadUncommitted',
ReadCommitted: 'ReadCommitted', ReadCommitted: 'ReadCommitted',
RepeatableRead: 'RepeatableRead', RepeatableRead: 'RepeatableRead',
Serializable: 'Serializable' Serializable: 'Serializable'
} as const) } as const);
export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel]
export type TransactionIsolationLevel =
(typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel];
export const UserScalarFieldEnum = { export const UserScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
email: 'email', email: 'email',
emailVerified: 'emailVerified', emailVerified: 'emailVerified',
image: 'image', image: 'image',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt', updatedAt: 'updatedAt',
roleId: 'roleId' roleId: 'roleId'
} as const } as const;
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum]
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum];
export const ProfileScalarFieldEnum = { export const ProfileScalarFieldEnum = {
id: 'id', id: 'id',
userId: 'userId', userId: 'userId',
firstName: 'firstName', firstName: 'firstName',
lastName: 'lastName', lastName: 'lastName',
phoneNumber: 'phoneNumber', phoneNumber: 'phoneNumber',
ghlContactId: 'ghlContactId' ghlContactId: 'ghlContactId'
} as const } as const;
export type ProfileScalarFieldEnum = (typeof ProfileScalarFieldEnum)[keyof typeof ProfileScalarFieldEnum]
export type ProfileScalarFieldEnum =
(typeof ProfileScalarFieldEnum)[keyof typeof ProfileScalarFieldEnum];
export const AddressScalarFieldEnum = { export const AddressScalarFieldEnum = {
id: 'id', id: 'id',
profileId: 'profileId', profileId: 'profileId',
street: 'street', street: 'street',
city: 'city', city: 'city',
state: 'state', state: 'state',
postalCode: 'postalCode', postalCode: 'postalCode',
country: 'country', country: 'country',
type: 'type', type: 'type',
isDefaultMailing: 'isDefaultMailing', isDefaultMailing: 'isDefaultMailing',
isDefaultBilling: 'isDefaultBilling', isDefaultBilling: 'isDefaultBilling',
isDefaultShipping: 'isDefaultShipping' isDefaultShipping: 'isDefaultShipping'
} as const } as const;
export type AddressScalarFieldEnum = (typeof AddressScalarFieldEnum)[keyof typeof AddressScalarFieldEnum]
export type AddressScalarFieldEnum =
(typeof AddressScalarFieldEnum)[keyof typeof AddressScalarFieldEnum];
export const SessionScalarFieldEnum = { export const SessionScalarFieldEnum = {
id: 'id', id: 'id',
expiresAt: 'expiresAt', expiresAt: 'expiresAt',
token: 'token', token: 'token',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt', updatedAt: 'updatedAt',
ipAddress: 'ipAddress', ipAddress: 'ipAddress',
userAgent: 'userAgent', userAgent: 'userAgent',
userId: 'userId' userId: 'userId'
} as const } as const;
export type SessionScalarFieldEnum = (typeof SessionScalarFieldEnum)[keyof typeof SessionScalarFieldEnum]
export type SessionScalarFieldEnum =
(typeof SessionScalarFieldEnum)[keyof typeof SessionScalarFieldEnum];
export const AccountScalarFieldEnum = { export const AccountScalarFieldEnum = {
id: 'id', id: 'id',
accountId: 'accountId', accountId: 'accountId',
providerId: 'providerId', providerId: 'providerId',
userId: 'userId', userId: 'userId',
accessToken: 'accessToken', accessToken: 'accessToken',
refreshToken: 'refreshToken', refreshToken: 'refreshToken',
idToken: 'idToken', idToken: 'idToken',
accessTokenExpiresAt: 'accessTokenExpiresAt', accessTokenExpiresAt: 'accessTokenExpiresAt',
refreshTokenExpiresAt: 'refreshTokenExpiresAt', refreshTokenExpiresAt: 'refreshTokenExpiresAt',
scope: 'scope', scope: 'scope',
password: 'password', password: 'password',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const;
export type AccountScalarFieldEnum = (typeof AccountScalarFieldEnum)[keyof typeof AccountScalarFieldEnum]
export type AccountScalarFieldEnum =
(typeof AccountScalarFieldEnum)[keyof typeof AccountScalarFieldEnum];
export const UserRoleScalarFieldEnum = { export const UserRoleScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name' name: 'name'
} as const } as const;
export type UserRoleScalarFieldEnum = (typeof UserRoleScalarFieldEnum)[keyof typeof UserRoleScalarFieldEnum]
export type UserRoleScalarFieldEnum =
(typeof UserRoleScalarFieldEnum)[keyof typeof UserRoleScalarFieldEnum];
export const VerificationScalarFieldEnum = { export const VerificationScalarFieldEnum = {
id: 'id', id: 'id',
identifier: 'identifier', identifier: 'identifier',
value: 'value', value: 'value',
expiresAt: 'expiresAt', expiresAt: 'expiresAt',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const;
export type VerificationScalarFieldEnum = (typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum]
export type VerificationScalarFieldEnum =
(typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum];
export const ProclamationScalarFieldEnum = { export const ProclamationScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
content: 'content', content: 'content',
solfeggioFrequencyId: 'solfeggioFrequencyId', solfeggioFrequencyId: 'solfeggioFrequencyId',
categoryId: 'categoryId', categoryId: 'categoryId',
subscriptionLevelId: 'subscriptionLevelId' subscriptionLevelId: 'subscriptionLevelId'
} as const } as const;
export type ProclamationScalarFieldEnum = (typeof ProclamationScalarFieldEnum)[keyof typeof ProclamationScalarFieldEnum]
export type ProclamationScalarFieldEnum =
(typeof ProclamationScalarFieldEnum)[keyof typeof ProclamationScalarFieldEnum];
export const UserProclamationsScalarFieldEnum = { export const UserProclamationsScalarFieldEnum = {
userId: 'userId', userId: 'userId',
proclamationId: 'proclamationId', proclamationId: 'proclamationId',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const;
export type UserProclamationsScalarFieldEnum = (typeof UserProclamationsScalarFieldEnum)[keyof typeof UserProclamationsScalarFieldEnum]
export type UserProclamationsScalarFieldEnum =
(typeof UserProclamationsScalarFieldEnum)[keyof typeof UserProclamationsScalarFieldEnum];
export const SolfeggioFrequencyScalarFieldEnum = { export const SolfeggioFrequencyScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
value: 'value' value: 'value'
} as const } as const;
export type SolfeggioFrequencyScalarFieldEnum = (typeof SolfeggioFrequencyScalarFieldEnum)[keyof typeof SolfeggioFrequencyScalarFieldEnum]
export type SolfeggioFrequencyScalarFieldEnum =
(typeof SolfeggioFrequencyScalarFieldEnum)[keyof typeof SolfeggioFrequencyScalarFieldEnum];
export const ProclamationCategoryScalarFieldEnum = { export const ProclamationCategoryScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
parentId: 'parentId' parentId: 'parentId'
} as const } as const;
export type ProclamationCategoryScalarFieldEnum = (typeof ProclamationCategoryScalarFieldEnum)[keyof typeof ProclamationCategoryScalarFieldEnum]
export type ProclamationCategoryScalarFieldEnum =
(typeof ProclamationCategoryScalarFieldEnum)[keyof typeof ProclamationCategoryScalarFieldEnum];
export const LicenseKeyScalarFieldEnum = { export const LicenseKeyScalarFieldEnum = {
id: 'id', id: 'id',
key: 'key', key: 'key',
active: 'active', active: 'active',
level: 'level', level: 'level',
userId: 'userId' userId: 'userId'
} as const } as const;
export type LicenseKeyScalarFieldEnum = (typeof LicenseKeyScalarFieldEnum)[keyof typeof LicenseKeyScalarFieldEnum]
export type LicenseKeyScalarFieldEnum =
(typeof LicenseKeyScalarFieldEnum)[keyof typeof LicenseKeyScalarFieldEnum];
export const SubscriptionLevelScalarFieldEnum = { export const SubscriptionLevelScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
description: 'description' description: 'description'
} as const } as const;
export type SubscriptionLevelScalarFieldEnum = (typeof SubscriptionLevelScalarFieldEnum)[keyof typeof SubscriptionLevelScalarFieldEnum]
export type SubscriptionLevelScalarFieldEnum =
(typeof SubscriptionLevelScalarFieldEnum)[keyof typeof SubscriptionLevelScalarFieldEnum];
export const SortOrder = { export const SortOrder = {
asc: 'asc', asc: 'asc',
desc: 'desc' desc: 'desc'
} as const } as const;
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder];
export const QueryMode = { export const QueryMode = {
default: 'default', default: 'default',
insensitive: 'insensitive' insensitive: 'insensitive'
} as const } as const;
export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode]
export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode];
export const NullsOrder = { export const NullsOrder = {
first: 'first', first: 'first',
last: 'last' last: 'last'
} as const } as const;
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder];
+15 -16
View File
@@ -1,24 +1,23 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This is a barrel export file for all models and their related types. * This is a barrel export file for all models and their related types.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
export type * from './models/User.ts' export type * from './models/User.ts';
export type * from './models/Profile.ts' export type * from './models/Profile.ts';
export type * from './models/Address.ts' export type * from './models/Address.ts';
export type * from './models/Session.ts' export type * from './models/Session.ts';
export type * from './models/Account.ts' export type * from './models/Account.ts';
export type * from './models/UserRole.ts' export type * from './models/UserRole.ts';
export type * from './models/Verification.ts' export type * from './models/Verification.ts';
export type * from './models/Proclamation.ts' export type * from './models/Proclamation.ts';
export type * from './models/UserProclamations.ts' export type * from './models/UserProclamations.ts';
export type * from './models/SolfeggioFrequency.ts' export type * from './models/SolfeggioFrequency.ts';
export type * from './models/ProclamationCategory.ts' export type * from './models/ProclamationCategory.ts';
export type * from './models/LicenseKey.ts' export type * from './models/LicenseKey.ts';
export type * from './models/SubscriptionLevel.ts' export type * from './models/SubscriptionLevel.ts';
export type * from './commonInputTypes.ts' export type * from './commonInputTypes.ts';
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+71 -71
View File
@@ -111,14 +111,14 @@ src/lib/components/admin/ # Reusable admin UI components
Controls both form input rendering and FormData parsing: Controls both form input rendering and FormData parsing:
| Type | HTML Input | Parse Logic | | Type | HTML Input | Parse Logic |
| ---------- | ------------------------------------- | ------------------------------ | | ---------- | -------------------------------------- | ------------------------------- |
| `String` | `<input type="text">` | `raw.toString()` | | `String` | `<input type="text">` | `raw.toString()` |
| `Int` | `<input type="number" step="1">` | `parseInt()`, empty -> `null` | | `Int` | `<input type="number" step="1">` | `parseInt()`, empty -> `null` |
| `Float` | `<input type="number" step="0.01">` | `parseFloat()`, empty -> `null` | | `Float` | `<input type="number" step="0.01">` | `parseFloat()`, empty -> `null` |
| `Boolean` | `<input type="checkbox">` | `'on'` or `'true'` -> `true` | | `Boolean` | `<input type="checkbox">` | `'on'` or `'true'` -> `true` |
| `DateTime` | `<input type="datetime-local">` | `new Date()`, empty -> `null` | | `DateTime` | `<input type="datetime-local">` | `new Date()`, empty -> `null` |
| `Tiptap` | TipTap rich-text editor (hidden input)| `raw.toString()` | | `Tiptap` | TipTap rich-text editor (hidden input) | `raw.toString()` |
### RelationOptionConfig ### RelationOptionConfig
@@ -194,19 +194,19 @@ Display has-one or has-many related records as panels on the edit page using `re
```ts ```ts
relatedRecords: [ relatedRecords: [
{ {
relationKey: 'profile', relationKey: 'profile',
label: 'Profile', label: 'Profile',
type: 'has-one', type: 'has-one',
displayFields: ['firstName', 'lastName'], displayFields: ['firstName', 'lastName'],
editSlug: 'profiles' // links to /admin/profiles/{id} editSlug: 'profiles' // links to /admin/profiles/{id}
}, },
{ {
relationKey: 'licenseKeys', relationKey: 'licenseKeys',
label: 'License Keys', label: 'License Keys',
type: 'has-many', type: 'has-many',
displayFields: ['key', 'active', 'level'] displayFields: ['key', 'active', 'level']
} }
]; ];
``` ```
@@ -236,11 +236,11 @@ Use `accessFilter` to restrict which records a viewer can see:
```ts ```ts
accessFilter: (viewerRoleId: number) => { accessFilter: (viewerRoleId: number) => {
if (viewerRoleId <= ROLES.SUPER) return undefined; if (viewerRoleId <= ROLES.SUPER) return undefined;
if (viewerRoleId <= ROLES.ADMIN) { if (viewerRoleId <= ROLES.ADMIN) {
return { roleId: { gte: ROLES.STAFF } }; return { roleId: { gte: ROLES.STAFF } };
} }
return { roleId: { gt: ROLES.STAFF } }; return { roleId: { gt: ROLES.STAFF } };
}; };
``` ```
@@ -258,15 +258,15 @@ accessFilter: (viewerRoleId: number) => {
### AdminTable ### AdminTable
| Prop | Type | Description | | Prop | Type | Description |
| -------------- | --------------------------- | ------------------------------------ | | -------------- | ---------------------------------- | ------------------------------------ |
| `records` | `Record<string, unknown>[]` | Data rows | | `records` | `Record<string, unknown>[]` | Data rows |
| `listFields` | `string[]` | Column keys (dot-notation supported) | | `listFields` | `string[]` | Column keys (dot-notation supported) |
| `searchFields` | `string[]` | Fields for client-side search | | `searchFields` | `string[]` | Fields for client-side search |
| `fieldTypes` | `Record<string, PrismaScalarType>` | Type mapping for cell formatting | | `fieldTypes` | `Record<string, PrismaScalarType>` | Type mapping for cell formatting |
| `singular` | `string` | Singular label for UI text | | `singular` | `string` | Singular label for UI text |
| `onRowClick` | `(record) => void?` | Click handler for edit modal | | `onRowClick` | `(record) => void?` | Click handler for edit modal |
| `onNew` | `() => void?` | Click handler for create modal | | `onNew` | `() => void?` | Click handler for create modal |
Features: client-side search, click-to-sort columns, auto-formatted cells (dates, booleans, Features: client-side search, click-to-sort columns, auto-formatted cells (dates, booleans,
decimals), empty state. decimals), empty state.
@@ -286,12 +286,12 @@ decimals), empty state.
### AdminModal ### AdminModal
| Prop | Type | Description | | Prop | Type | Description |
| --------- | ----------------- | ------------------------ | | ---------- | ------------ | ------------------ |
| `open` | `boolean` | Show/hide modal | | `open` | `boolean` | Show/hide modal |
| `title` | `string` | Modal heading | | `title` | `string` | Modal heading |
| `onClose` | `() => void` | Close handler | | `onClose` | `() => void` | Close handler |
| `children`| `Snippet` | Modal body content | | `children` | `Snippet` | Modal body content |
### TipTap ### TipTap
@@ -302,43 +302,43 @@ decimals), empty state.
## Utility Functions ## Utility Functions
| Function | Module | Description | | Function | Module | Description |
| ------------------------------------------ | -------------------- | ----------------------------------------------------------------------------- | | ------------------------------------------ | -------------------- | ------------------------------------------------------------------------------ |
| `fieldNameToLabel(name)` | `introspect.ts` | `'solfeggioFrequencyId'` -> `'Solfeggio Frequency'` (strips `Id`, adds spaces) | | `fieldNameToLabel(name)` | `introspect.ts` | `'solfeggioFrequencyId'` -> `'Solfeggio Frequency'` (strips `Id`, adds spaces) |
| `resolveFieldValue(record, path)` | `introspect.ts` | Resolves dot-notation paths like `'category.name'` on nested objects | | `resolveFieldValue(record, path)` | `introspect.ts` | Resolves dot-notation paths like `'category.name'` on nested objects |
| `extractFormData(formData, fields, types)` | `form-data.ts` | Parses `FormData` with type-aware conversion per `PrismaScalarType` | | `extractFormData(formData, fields, types)` | `form-data.ts` | Parses `FormData` with type-aware conversion per `PrismaScalarType` |
| `getDelegate(config)` | `prisma-delegate.ts` | Returns `prisma[lcfirst(modelName)]` delegate | | `getDelegate(config)` | `prisma-delegate.ts` | Returns `prisma[lcfirst(modelName)]` delegate |
| `parseId(config, raw)` | `prisma-delegate.ts` | Parses string to `number` when `idType` is `'Int'` | | `parseId(config, raw)` | `prisma-delegate.ts` | Parses string to `number` when `idType` is `'Int'` |
| `getModelConfig(slug)` | `registry.ts` | Looks up config by URL slug | | `getModelConfig(slug)` | `registry.ts` | Looks up config by URL slug |
| `getAllModelConfigs()` | `registry.ts` | Returns all registered model configs | | `getAllModelConfigs()` | `registry.ts` | Returns all registered model configs |
| `hasRole(roleId, required)` | `roles.ts` | `true` if `roleId <= required` | | `hasRole(roleId, required)` | `roles.ts` | `true` if `roleId <= required` |
| `canAccessAdmin(roleId)` | `roles.ts` | `true` if `roleId <= ROLES.STAFF` | | `canAccessAdmin(roleId)` | `roles.ts` | `true` if `roleId <= ROLES.STAFF` |
| `loadRecords(locals, config)` | `crud.ts` | Fetches records + FK dropdown options for a model | | `loadRecords(locals, config)` | `crud.ts` | Fetches records + FK dropdown options for a model |
| `upsertRecord(formData, config, locals)` | `crud.ts` | Creates or updates a record based on presence of `id` in form data | | `upsertRecord(formData, config, locals)` | `crud.ts` | Creates or updates a record based on presence of `id` in form data |
| `deleteRecord(formData, config, locals)` | `crud.ts` | Deletes a record by ID | | `deleteRecord(formData, config, locals)` | `crud.ts` | Deletes a record by ID |
## Models in Admin ## Models in Admin
| Registry Slug | Prisma Model | Notes | | Registry Slug | Prisma Model | Notes |
| -------------------------- | ---------------------- | ---------------------------------- | | ------------------------- | -------------------- | ----------------------------------- |
| `users` | User | Role assignment, view-only fields | | `users` | User | Role assignment, view-only fields |
| `profiles` | Profile | Linked to user FK | | `profiles` | Profile | Linked to user FK |
| `addresses` | Address | Linked to profile FK | | `addresses` | Address | Linked to profile FK |
| `user-roles` | UserRole | | | `user-roles` | UserRole | |
| `proclamations` | Proclamation | TipTap rich-text editor for content| | `proclamations` | Proclamation | TipTap rich-text editor for content |
| `solfeggio-frequencies` | SolfeggioFrequency | | | `solfeggio-frequencies` | SolfeggioFrequency | |
| `proclamation-categories` | ProclamationCategory | Parent category hierarchy | | `proclamation-categories` | ProclamationCategory | Parent category hierarchy |
| `license-keys` | LicenseKey | listOnly — read-only table, no CRUD| | `license-keys` | LicenseKey | listOnly — read-only table, no CRUD |
| `subscription-levels` | SubscriptionLevel | | | `subscription-levels` | SubscriptionLevel | |
### Excluded from Admin ### Excluded from Admin
| Model | Reason | | Model | Reason |
| ------------------ | -------------------------------------------- | | ----------------- | --------------------------------------------- |
| Session | Better Auth internal — not for manual editing| | Session | Better Auth internal — not for manual editing |
| Account | Better Auth internal | | Account | Better Auth internal |
| Verification | Better Auth internal | | Verification | Better Auth internal |
| UserProclamations | Composite key — managed via other models | | UserProclamations | Composite key — managed via other models |
## Complete Example ## Complete Example
+2 -2
View File
@@ -202,8 +202,8 @@ const models: AdminModelConfig[] = [
displayName: 'Proclamation Categories', displayName: 'Proclamation Categories',
displayNameSingular: 'Proclamation Category', displayNameSingular: 'Proclamation Category',
idType: 'Int', idType: 'Int',
include: { proclamations: true, children: true, parent: true }, include: { proclamations: true, children: true },
listFields: ['name', 'parent.name'], listFields: ['name'],
searchFields: ['name'], searchFields: ['name'],
formFields: ['name', 'parentId'], formFields: ['name', 'parentId'],
readonlyFields: ['id'], readonlyFields: ['id'],
+1 -1
View File
@@ -56,7 +56,7 @@ export const Proclamation = z.object({
name: z.string().min(1, 'Required'), name: z.string().min(1, 'Required'),
solfeggioFrequencyId: z.coerce.number().int(), solfeggioFrequencyId: z.coerce.number().int(),
parentCategoryId: z.coerce.number().int(), parentCategoryId: z.coerce.number().int(),
categoryId: z.coerce.number().int(), categoryId: z.coerce.number().int().optional(),
subscriptionLevelId: z.coerce.number().int(), subscriptionLevelId: z.coerce.number().int(),
content: z.string().optional().default('') content: z.string().optional().default('')
}); });
@@ -23,7 +23,11 @@ export const load: PageServerLoad = async ({ url }) => {
const [proclamations, categories] = await Promise.all([ const [proclamations, categories] = await Promise.all([
prisma.proclamation.findMany({ prisma.proclamation.findMany({
where, where,
include: { solfeggioFrequency: true, category: { include: { parent: true } }, subscriptionLevel: true }, include: {
solfeggioFrequency: true,
category: { include: { parent: true } },
subscriptionLevel: true
},
orderBy: { name: 'asc' } orderBy: { name: 'asc' }
}), }),
prisma.proclamationCategory.findMany({ include: { parent: true }, orderBy: { name: 'asc' } }) prisma.proclamationCategory.findMany({ include: { parent: true }, orderBy: { name: 'asc' } })
@@ -111,7 +111,11 @@ describe('(protected)/admin/proclamations page server load', () => {
expect(proclamationFindMany).toHaveBeenCalledWith( expect(proclamationFindMany).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
include: { solfeggioFrequency: true, category: { include: { parent: true } }, subscriptionLevel: true } include: {
solfeggioFrequency: true,
category: { include: { parent: true } },
subscriptionLevel: true
}
}) })
); );
}); });
@@ -47,7 +47,12 @@
</div> </div>
{#if showCreateForm} {#if showCreateForm}
<form method="POST" action="?/createKey" use:enhance class="mb-6 border border-gray-200 p-4 dark:border-gray-700"> <form
method="POST"
action="?/createKey"
use:enhance
class="mb-6 border border-gray-200 p-4 dark:border-gray-700"
>
<h2 class="mb-3 text-sm font-semibold text-gray-700 dark:text-gray-300"> <h2 class="mb-3 text-sm font-semibold text-gray-700 dark:text-gray-300">
Create New License Key Create New License Key
</h2> </h2>
@@ -58,7 +63,10 @@
{/if} {/if}
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<div> <div>
<label for="email" class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"> <label
for="email"
class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
User Email User Email
</label> </label>
<input <input
@@ -1,18 +1,142 @@
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { getModelConfig } from '$lib/svelte-admin/registry'; import { getModelConfig } from '$lib/svelte-admin/registry';
import { loadRecords, upsertRecord, deleteRecord } from '$lib/svelte-admin/crud'; import { getDelegate } from '$lib/svelte-admin/prisma-delegate';
const config = getModelConfig('proclamation-categories')!; const config = getModelConfig('proclamation-categories')!;
export const load: PageServerLoad = async ({ locals }) => { export const load: PageServerLoad = async ({ locals }) => {
return loadRecords(locals, config); const delegate = getDelegate(config);
const records = await delegate.findMany({
where: { parentId: null },
include: config.include,
orderBy: { id: 'asc' }
});
const relationOptionsData: Record<string, { label: string; value: string | number }[]> = {};
for (const [field, relConfig] of Object.entries(config.relationOptions ?? {})) {
const relDelegate = getDelegate({ ...config, modelName: relConfig.model });
const selectFields: Record<string, boolean> = {
[relConfig.valueField]: true,
[relConfig.labelField]: true
};
const options = await relDelegate.findMany({
select: selectFields,
orderBy: { [relConfig.labelField]: 'asc' }
});
const mapped = (options as Record<string, unknown>[]).map((opt: Record<string, unknown>) => ({
label: String(opt[relConfig.labelField]),
value: opt[relConfig.valueField] as string | number
}));
relationOptionsData[field] = mapped;
}
return {
records: records as Record<string, unknown>[],
relationOptionsData
};
}; };
export const actions = { export const actions = {
upsert: async ({ request, locals }) => { upsert: async ({ request, locals }) => {
return upsertRecord(request, config, locals); const formData = await request.formData();
const name = (formData.get('name')?.toString() ?? '').trim();
const rawId = formData.get('id')?.toString();
const childIds = formData.getAll('childId').map(v => v.toString());
const childNames = formData.getAll('childName').map(v => v.toString().trim()).filter(Boolean);
if (!name) {
return { success: false, error: 'Name is required', fieldErrors: { name: 'Required' } };
}
const delegate = getDelegate(config);
try {
let categoryId: number;
if (rawId) {
const id = parseInt(rawId, 10);
await delegate.update({
where: { id },
data: { name }
});
categoryId = id;
} else {
const created = await delegate.create({
data: { name }
});
categoryId = created.id;
}
const existingChildren = await delegate.findMany({
where: { parentId: categoryId },
select: { id: true }
});
const existingChildIdSet = new Set(existingChildren.map((c: { id: number }) => c.id));
const submittedIdSet = new Set<number>();
for (let i = 0; i < childNames.length; i++) {
const childName = childNames[i];
if (!childName) continue;
const childIdRaw = childIds[i] ? parseInt(childIds[i], 10) : null;
if (childIdRaw && existingChildIdSet.has(childIdRaw)) {
submittedIdSet.add(childIdRaw);
await delegate.update({
where: { id: childIdRaw },
data: { name: childName }
});
} else {
await delegate.create({
data: { name: childName, parentId: categoryId }
});
}
}
for (const child of existingChildren) {
if (!submittedIdSet.has(child.id)) {
await delegate.delete({ where: { id: child.id } });
}
}
return { success: true };
} catch (e: unknown) {
if (
e &&
typeof e === 'object' &&
'code' in e &&
(e as { code: string }).code === 'P2002'
) {
return {
success: false,
error:
'A sub-category with this name already exists under this parent.'
};
}
throw e;
}
}, },
delete: async ({ request, locals }) => { delete: async ({ request, locals }) => {
return deleteRecord(request, config, locals); const formData = await request.formData();
const rawId = formData.get('id')?.toString();
if (!rawId) return { success: false, error: 'Missing id' };
const id = parseInt(rawId, 10);
const delegate = getDelegate(config);
const viewerRoleId = (locals.user as { roleId?: number } | null)?.roleId ?? 4;
const where = config.accessFilter?.(viewerRoleId);
if (where) {
const match = await delegate.findFirst({ where: { id, ...where } });
if (!match) return { success: false, error: 'Access denied' };
}
await delegate.deleteMany({ where: { parentId: id } });
await delegate.delete({ where: { id } });
return { success: true };
} }
}; };
@@ -79,10 +79,9 @@
> >
<CategoryForm <CategoryForm
record={editingRecord ?? {}} record={editingRecord ?? {}}
relationOptionsData={data.relationOptionsData}
{fieldErrors} {fieldErrors}
{formError} {formError}
submitLabel={editingRecord ? 'Update' : 'Create'} submitLabel={editingRecord ? 'Save' : 'Create'}
/> />
</AdminModal> </AdminModal>
@@ -5,29 +5,43 @@
record = {} as Record<string, unknown>, record = {} as Record<string, unknown>,
fieldErrors = {} as Record<string, string>, fieldErrors = {} as Record<string, string>,
formError = '', formError = '',
relationOptionsData = {} as Record<string, { label: string; value: string | number }[]>,
action = '?/upsert', action = '?/upsert',
submitLabel = 'Save' submitLabel = 'Save'
}: { }: {
record?: Record<string, unknown>; record?: Record<string, unknown>;
fieldErrors?: Record<string, string>; fieldErrors?: Record<string, string>;
formError?: string; formError?: string;
relationOptionsData?: Record<string, { label: string; value: string | number }[]>;
action?: string; action?: string;
submitLabel?: string; submitLabel?: string;
} = $props(); } = $props();
let name = $state(String(record.name ?? '')); let name = $state('');
let parentId = $state(String(record.parentId ?? '')); let children = $state<{ id: number | null; name: string }[]>([]);
let dirty = $state(false); let dirty = $state(false);
$effect(() => { $effect(() => {
dirty = false; dirty = false;
}); });
$effect(() => {
name = String(record.name ?? '');
const existingChildren = (record.children as Array<{ id: number; name: string }>) ?? [];
children = existingChildren.map(c => ({ id: c.id, name: c.name }));
});
function markDirty() { function markDirty() {
if (record.id) dirty = true; if (record.id) dirty = true;
} }
function addChild() {
children = [...children, { id: null, name: '' }];
if (record.id) dirty = true;
}
function removeChild(index: number) {
children = children.filter((_, i) => i !== index);
if (record.id) dirty = true;
}
</script> </script>
<form {action} method="POST" use:enhance oninput={markDirty}> <form {action} method="POST" use:enhance oninput={markDirty}>
@@ -64,28 +78,37 @@
</div> </div>
<div> <div>
<label <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
for="field-parentId" Sub-categories
class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Parent Category
</label> </label>
<select {#each children as child, i}
id="field-parentId" <div class="mb-2 flex items-center gap-2">
name="parentId" <input type="hidden" name="childId" value={child.id ?? ''} />
bind:value={parentId} <input
class="w-full border px-3 py-1.5 text-sm {fieldErrors.parentId type="text"
? 'border-red-400' name="childName"
: 'border-gray-300 dark:border-gray-600'} dark:bg-gray-800 dark:text-gray-100" bind:value={child.name}
placeholder="Sub-category name"
class="flex-1 border px-3 py-1.5 text-sm {fieldErrors[`childName.${i}`]
? 'border-red-400'
: 'border-gray-300 dark:border-gray-600'} dark:bg-gray-800 dark:text-gray-100"
/>
<button
type="button"
onclick={() => removeChild(i)}
class="shrink-0 px-2 py-1 text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
>
Remove
</button>
</div>
{/each}
<button
type="button"
onclick={addChild}
class="mt-1 text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
> >
<option value="">-- No Parent --</option> + Add Sub-category
{#each relationOptionsData.parentId ?? [] as opt (String(opt.value))} </button>
<option value={opt.value}>{opt.label}</option>
{/each}
</select>
{#if fieldErrors.parentId}
<p class="mt-1 text-xs text-red-600">{fieldErrors.parentId}</p>
{/if}
</div> </div>
<div class="flex justify-end gap-2 pt-2"> <div class="flex justify-end gap-2 pt-2">