Compare commits

...

8 Commits

Author SHA1 Message Date
ca8728c90c модалочки оп-оп 2026-06-01 05:07:42 +06:00
0dd9efb9fb обновОЧКИ 2026-05-29 04:28:09 +06:00
3c885edc46 brutalism design 2026-05-24 16:26:52 +06:00
12ae0ae839 brutalism design 2026-05-23 22:49:52 +06:00
d06892e990 brutalism design 2026-05-22 06:01:27 +06:00
5d45c9674f brutalism design 2026-05-22 05:27:41 +06:00
1ca73e786c brutalism design 2026-05-22 05:08:41 +06:00
e4ed785911 brutalism design 2026-05-22 05:08:02 +06:00
85 changed files with 3202 additions and 1308 deletions

View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(python -c \"import sys,json; p=json.load\\(sys.stdin\\); deps={**p.get\\('dependencies',{}\\), **p.get\\('devDependencies',{}\\)}; [print\\(k,v\\) for k in sorted\\(deps\\) if any\\(x in k for x in ['mediasoup','socket','vueuse','vue']\\)]\")"
]
}
}

1
new-client/AGENTS.md Normal file
View File

@@ -0,0 +1 @@
use context7

View File

@@ -6,10 +6,10 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vue-tsc -b && vite build", "build": "vue-tsc -b && vite build",
"preview": "vite preview" "preview": "vite preview",
"typegen": "npx swagger-typescript-api generate --path http://localhost:4000/reference/openapi.yaml --output ./src/shared/api --name generated-chad-api.ts"
}, },
"dependencies": { "dependencies": {
"@ark-ui/vue": "^5.36.2",
"@lucide/vue": "^1.14.0", "@lucide/vue": "^1.14.0",
"@tanstack/query-persist-client-core": "^5.100.10", "@tanstack/query-persist-client-core": "^5.100.10",
"@tanstack/vue-query": "^5.100.10", "@tanstack/vue-query": "^5.100.10",
@@ -20,9 +20,14 @@
"@vueuse/core": "^14.3.0", "@vueuse/core": "^14.3.0",
"@zag-js/avatar": "^1.40.0", "@zag-js/avatar": "^1.40.0",
"@zag-js/collapsible": "^1.40.0", "@zag-js/collapsible": "^1.40.0",
"@zag-js/dialog": "^1.41.1",
"@zag-js/file-upload": "^1.41.0",
"@zag-js/file-utils": "^1.40.0",
"@zag-js/password-input": "^1.40.0", "@zag-js/password-input": "^1.40.0",
"@zag-js/toggle": "^1.40.0",
"@zag-js/vue": "^1.40.0", "@zag-js/vue": "^1.40.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"mediasoup-client": "^3.20.0",
"mitt": "^3.0.1", "mitt": "^3.0.1",
"primevue": "^4.5.5", "primevue": "^4.5.5",
"socket.io-client": "^4.8.3", "socket.io-client": "^4.8.3",

View File

@@ -2,9 +2,12 @@
<Component :is="layoutComponent"> <Component :is="layoutComponent">
<RouterView /> <RouterView />
</Component> </Component>
<ChadDialogContainer />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import ChadDialogContainer from '@shared/components/ui/DialogContainer.vue'
import DefaultLayout from '@shared/layouts/Default.vue' import DefaultLayout from '@shared/layouts/Default.vue'
import { computed } from 'vue' import { computed } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'

View File

@@ -0,0 +1,138 @@
import { useMediasoup } from '@shared/composables/use-mediasoup'
import { useSignaling } from '@shared/composables/use-signaling'
import { Device } from 'mediasoup-client'
import { markRaw, watch } from 'vue'
const ICE_SERVERS: RTCIceServer[] = [
{ urls: 'stun:stunserver2025.stunprotocol.org:3478' },
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun.l.google.com:5349' },
{ urls: 'stun:stun1.l.google.com:3478' },
{ urls: 'stun:stun1.l.google.com:5349' },
{ urls: 'stun:stun2.l.google.com:19302' },
{ urls: 'stun:stun2.l.google.com:5349' },
{ urls: 'stun:stun3.l.google.com:3478' },
{ urls: 'stun:stun3.l.google.com:5349' },
{ urls: 'stun:stun4.l.google.com:19302' },
{ urls: 'stun:stun4.l.google.com:5349' },
]
export default function () {
const { socket } = useSignaling()
const ms = useMediasoup()
watch(socket, (socket) => {
if (!socket)
return
socket.on('initialized', async (initData) => {
ms.device.value = new Device()
await ms.device.value.load({ routerRtpCapabilities: initData.rtpCapabilities })
const sendInfo = await socket.emitWithAck('create-transport', { producing: true, consuming: false })
const sendTransport = ms.device.value.createSendTransport({
...sendInfo,
iceServers: [...ICE_SERVERS, ...(sendInfo.iceServers ?? [])],
})
ms.sendTransport.value = sendTransport
await ms.transports.add({
id: sendTransport.id,
ref: markRaw(sendTransport),
})
sendTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.emitWithAck('connect-transport', { transportId: sendTransport.id, dtlsParameters })
callback()
}
catch (error) {
if (error instanceof Error)
errback(error)
}
})
sendTransport.on('produce', async ({ kind, rtpParameters, appData }, callback, errback) => {
try {
const { id } = await socket.emitWithAck('produce', {
transportId: sendTransport.id,
kind,
rtpParameters,
appData,
})
callback({ id })
}
catch (error) {
if (error instanceof Error)
errback(error)
}
})
const recvInfo = await socket.emitWithAck('create-transport', { producing: false, consuming: true })
const recvTransport = ms.device.value.createRecvTransport({
...recvInfo,
iceServers: [...ICE_SERVERS, ...(recvInfo.iceServers ?? [])],
})
ms.recvTransport.value = recvTransport
await ms.transports.add({
id: recvTransport.id,
ref: markRaw(recvTransport),
})
recvTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.emitWithAck('connect-transport', { transportId: recvTransport.id, dtlsParameters })
callback()
}
catch (error) {
if (error instanceof Error)
errback(error)
}
})
})
socket.on('new-consumer', async ({ id, producerId, kind, rtpParameters, socketId, appData, producerPaused }, cb) => {
const rt = ms.recvTransport.value
if (!rt)
return
const consumer = await rt.consume({
id,
producerId,
kind,
rtpParameters,
streamId: `${socketId}-${appData.source ?? 'stream'}`,
appData: { ...appData, socketId },
})
if (producerPaused)
consumer.pause()
await ms.consumers.add({
id: consumer.id,
paused: consumer.paused,
kind: consumer.kind,
appData: consumer.appData as Record<string, unknown>,
track: consumer.track,
ref: markRaw(consumer),
})
cb()
})
socket.on('consumer-closed', ({ consumerId }) => {
ms.consumers.get(consumerId)?.ref.close()
})
socket.on('consumer-paused', ({ consumerId }) => {
ms.consumers.get(consumerId)?.ref.pause()
})
socket.on('consumer-resumed', ({ consumerId }) => {
ms.consumers.get(consumerId)?.ref.resume()
})
socket.on('disconnect', () => {
ms.clearAll()
})
}, { immediate: true })
}

View File

@@ -0,0 +1,52 @@
import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
import { useAuth } from '@shared/composables/use-auth.ts'
import { useClients } from '@shared/composables/use-clients'
import { useEventBus } from '@shared/composables/use-event-bus.ts'
import { useSignaling } from '@shared/composables/use-signaling'
import { watch, watchEffect } from 'vue'
import { queryClient } from '../plugins/tanstack-query'
export default function () {
const { authorized } = useAuth()
const signaling = useSignaling()
const { addClient, updateClient, removeClient, clear: clearClients } = useClients()
const eventBus = useEventBus()
watch(signaling.connected, (connected) => {
if (!connected)
return
const socket = signaling.socket.value!
socket.on('initialized', async ({ clients }) => {
addClient(...clients)
})
socket.on('new-client', (client) => {
addClient(client)
})
socket.on('client-switched-channel', (client) => {
updateClient(client.socketId, client)
})
socket.on('client-disconnected', (socketId) => {
removeClient(socketId)
})
socket.on('disconnect', async () => {
clearClients()
await queryClient.resetQueries()
})
socket.on('chat:new-message', (message: ChatMessage) => {
eventBus.emit('chat:new-message', message)
})
})
watchEffect(() => {
if (authorized.value) {
signaling.connect()
}
})
}

View File

@@ -1,7 +1,9 @@
import initializeApp from './bootstrap/app' import initializeApp from './bootstrap/app'
import authorize from './bootstrap/authorize' import authorize from './bootstrap/authorize'
import showError from './bootstrap/error' import showError from './bootstrap/error'
import setupMediasoup from './bootstrap/mediasoup'
import preloader from './bootstrap/preloader' import preloader from './bootstrap/preloader'
import connectSignaling from './bootstrap/signaling'
import checkUpdates from './bootstrap/updater' import checkUpdates from './bootstrap/updater'
(async () => { (async () => {
@@ -13,6 +15,9 @@ import checkUpdates from './bootstrap/updater'
await authorize() await authorize()
connectSignaling()
setupMediasoup()
await initializeApp() await initializeApp()
} }
catch (error) { catch (error) {

View File

@@ -1,8 +1,18 @@
import type { FunctionPlugin } from 'vue' import type { FunctionPlugin } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query' import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query'
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
export default { export default {
install(app) { install(app) {
app.use(VueQueryPlugin, {}) app.use(VueQueryPlugin, {
queryClient,
})
}, },
} as FunctionPlugin } as FunctionPlugin

View File

@@ -0,0 +1,19 @@
import type { Channel, CreateChannelPayload, ResponseError } from '@shared/api/generated-chad-api'
import api from '@shared/api/client'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
export function mCreateChannel() {
const queryClient = useQueryClient()
return useMutation<Channel, ResponseError, CreateChannelPayload, Channel>({
mutationFn: async (payload) => {
const response = await api.chad.channelCreate(payload)
return response.data
},
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ['channel-list'] })
},
})
}

View File

@@ -0,0 +1,44 @@
<template>
<ChadDialog :id="DIALOG_ID" title="Create channel">
<ChadInput v-model="name" label="Name" />
<template #actions>
<ChadButton style="grid-column: 2" :disabled="!valid" :loading="submitting" @click="submit()">
Create
</ChadButton>
</template>
</ChadDialog>
</template>
<script setup lang="ts">
import ChadButton from '@shared/components/ui/Button.vue'
import ChadDialog from '@shared/components/ui/Dialog.vue'
import ChadInput from '@shared/components/ui/Input.vue'
import { useDialogManager } from '@shared/composables/use-dialog.ts'
import { computed, ref } from 'vue'
import { mCreateChannel } from '@/entities/channel/api/mCreateChannel.ts'
const DIALOG_ID = 'create-channel'
const dialogManager = useDialogManager()
const { mutateAsync: createChannel, isPending: submitting } = mCreateChannel()
const name = ref('')
const valid = computed(() => {
return name.value.trim().length > 0
})
async function submit() {
if (!valid.value)
return
await createChannel({
name: name.value,
persistent: false,
})
dialogManager.close(DIALOG_ID)
}
</script>

View File

@@ -6,7 +6,7 @@
</div> </div>
<template #actions> <template #actions>
<ChadButton full type="submit" :disabled="!valid" :loading="submitting"> <ChadButton full native-type="submit" :disabled="!valid" :loading="submitting">
Let's go Let's go
</ChadButton> </ChadButton>
</template> </template>

View File

@@ -7,7 +7,7 @@
</div> </div>
<template #actions> <template #actions>
<ChadButton full type="submit" :disabled="!valid" :loading="submitting"> <ChadButton full native-type="submit" :disabled="!valid" :loading="submitting">
Create an account Create an account
</ChadButton> </ChadButton>
</template> </template>

View File

@@ -2,6 +2,7 @@ import { Api } from './generated-chad-api'
const api = new Api({ const api = new Api({
baseUrl: 'http://localhost:4000', baseUrl: 'http://localhost:4000',
baseApiParams: { credentials: 'include' },
}) })
function isChadResponseError(error) { function isChadResponseError(error) {

View File

@@ -30,7 +30,7 @@ export interface Attachment {
*/ */
export interface Channel { export interface Channel {
id: string; id: string;
ownerId: string | null; ownerUsername: string | null;
name: string; name: string;
persistent: boolean; persistent: boolean;
} }
@@ -42,15 +42,22 @@ export interface Channel {
export interface ChatMessage { export interface ChatMessage {
/** @format uuid */ /** @format uuid */
id: string; id: string;
/** @format uuid */ senderUsername: string;
senderId: string;
/** @minLength 1 */ /** @minLength 1 */
text: string; text: string;
/** @format date-time */ /** @format date-time */
createdAt: string; createdAt: string;
/** @format date-time */ /** @format date-time */
updatedAt: string; updatedAt: string;
attachments: string[]; attachments: {
id: string;
name: string;
mimetype: string;
/** @min 0 */
size: number;
/** @format date-time */
createdAt: string;
}[];
} }
/** /**
@@ -118,8 +125,7 @@ export interface NewChatMessagePayload {
export interface Reply { export interface Reply {
/** @format uuid */ /** @format uuid */
messageId: string; messageId: string;
/** @format uuid */ senderUsername: string;
senderId: string;
text: string; text: string;
} }
@@ -164,7 +170,6 @@ export interface UserPreferences {
* User * User
*/ */
export interface User { export interface User {
id: string;
username: string; username: string;
displayName: string; displayName: string;
/** @format date-time */ /** @format date-time */
@@ -232,7 +237,7 @@ export class HttpClient<SecurityDataType = unknown> {
fetch(...fetchParams); fetch(...fetchParams);
private baseApiParams: RequestParams = { private baseApiParams: RequestParams = {
credentials: "include", credentials: "same-origin",
headers: {}, headers: {},
redirect: "follow", redirect: "follow",
referrerPolicy: "no-referrer", referrerPolicy: "no-referrer",
@@ -590,30 +595,8 @@ export class Api<
* @summary Send message * @summary Send message
* @request POST:/chad/chat/send * @request POST:/chad/chat/send
*/ */
chatSend: ( chatSend: (data: NewChatMessagePayload, params: RequestParams = {}) =>
data: { this.request<ChatMessage, ResponseError>({
/** @minLength 1 */
text: string;
attachments?: string[];
},
params: RequestParams = {},
) =>
this.request<
{
/** @format uuid */
id: string;
/** @format uuid */
senderId: string;
/** @minLength 1 */
text: string;
/** @format date-time */
createdAt: string;
/** @format date-time */
updatedAt: string;
attachments: string[];
},
ResponseError
>({
path: `/chad/chat/send`, path: `/chad/chat/send`,
method: "POST", method: "POST",
body: data, body: data,
@@ -648,19 +631,7 @@ export class Api<
) => ) =>
this.request< this.request<
{ {
messages: { messages: ChatMessage[];
/** @format uuid */
id: string;
/** @format uuid */
senderId: string;
/** @minLength 1 */
text: string;
/** @format date-time */
createdAt: string;
/** @format date-time */
updatedAt: string;
attachments: string[];
}[];
/** /**
* Cursor to last message * Cursor to last message
* @format uuid * @format uuid

View File

@@ -8,7 +8,7 @@ export function qUser(username: MaybeRefOrGetter<string>) {
return useQuery<User, ResponseError>({ return useQuery<User, ResponseError>({
queryKey: ['user', username], queryKey: ['user', username],
queryFn: async () => { queryFn: async () => {
const response = await api.chad.userGet({ id: toValue(username) }) const response = await api.chad.userGet({ username: toValue(username) })
return response.data return response.data
}, },

View File

@@ -46,6 +46,10 @@ const api = computed(() => avatar.connect(service, normalizeProps))
#{$self}.highlighted & { #{$self}.highlighted & {
background-color: var(--yellow); background-color: var(--yellow);
} }
&[data-state='hidden'] {
display: none;
}
} }
&__image { &__image {
@@ -53,6 +57,10 @@ const api = computed(() => avatar.connect(service, normalizeProps))
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
object-position: center; object-position: center;
&[data-state='hidden'] {
display: none;
}
} }
} }
</style> </style>

View File

@@ -1,46 +1,70 @@
<template> <template>
<button <button
class="chad-button" :class="[
:data-loading="loading || undefined" bem.b(),
:data-disabled="disabled || undefined" bem.exp(!!type, bem.m(type!)),
bem.is('icon-only', iconOnly),
bem.is('loading', loading),
bem.is('disabled', disabled),
bem.is('full', full),
]"
:disabled="disabled" :disabled="disabled"
:type="type" :type="nativeType"
:data-full="full || undefined"
> >
<ChadSpinner v-if="loading" class="chad-button__spinner" /> <ChadSpinner v-if="loading" class="chad-button__spinner" />
<slot v-else />
<template v-else>
<Component :is="icon" v-if="icon" class="chad-button__icon" />
<span v-if="$slots.default">
<slot />
</span>
</template>
</button> </button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Component } from 'vue'
import ChadSpinner from '@shared/components/ui/Spinner.vue' import ChadSpinner from '@shared/components/ui/Spinner.vue'
import useBem from '@shared/composables/use-bem.ts'
import { computed, useSlots } from 'vue'
defineOptions({ defineOptions({
name: 'ChadButton', name: 'ChadButton',
}) })
withDefaults( const props = withDefaults(
defineProps<Props>(), defineProps<ChadButtonProps>(),
{ {
type: 'button', nativeType: 'button',
}, },
) )
interface Props { export interface ChadButtonProps {
loading?: boolean loading?: boolean
disabled?: boolean disabled?: boolean
type?: 'button' | 'submit' type?: 'secondary'
nativeType?: 'button' | 'submit'
icon?: Component
full?: boolean full?: boolean
} }
const slots = useSlots()
const bem = useBem('chad-button')
const iconOnly = computed(() => {
return !slots.default && props.icon
})
</script> </script>
<style lang="scss"> <style lang="scss">
.chad-button { .chad-button {
@include font-display-14; @include font-display-14;
flex-shrink: 0;
border: none; border: none;
color: var(--ink); color: var(--ink);
padding-inline: var(--space-3); padding: 0 var(--space-3);
height: 44px; height: 44px;
background-color: var(--yellow); background-color: var(--yellow);
font-weight: 700; font-weight: 700;
@@ -49,10 +73,15 @@ interface Props {
outline: var(--border-w) solid var(--ink); outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1); outline-offset: calc(var(--border-w) * -1);
&[data-full] { &.is-full:not(.is-icon-only) {
width: 100%; width: 100%;
} }
&.is-icon-only {
padding: 0;
aspect-ratio: 1;
}
&:hover, &:hover,
&:focus { &:focus {
background-color: var(--yellow-deep); background-color: var(--yellow-deep);
@@ -63,16 +92,35 @@ interface Props {
color: var(--yellow); color: var(--yellow);
} }
&[data-disabled], &--secondary {
background-color: var(--grey-1);
&:hover,
&:focus {
background-color: var(--grey-2);
}
&:active {
background-color: var(--grey-3);
color: var(--ink);
}
}
&:disabled { &:disabled {
cursor: not-allowed; cursor: not-allowed;
background-color: var(--grey-1); background-color: var(--grey-1);
color: var(--grey-3); color: var(--grey-3);
} }
&[data-loading] { &.is-loading {
background-color: var(--grey-1); background-color: var(--grey-1);
cursor: wait; cursor: wait;
} }
&__icon {
&:not(:last-child) {
margin-right: var(--space-1);
}
}
} }
</style> </style>

View File

@@ -1,9 +1,15 @@
<template> <template>
<Component :is="as" class="chad-card"> <Component :is="as" class="chad-card">
<div v-if="title || description" class="chad-card__header">
<p v-if="title" class="chad-card__title"> <p v-if="title" class="chad-card__title">
{{ title }} {{ title }}
</p> </p>
<p v-if="description" class="chad-card__description">
{{ description }}
</p>
</div>
<div class="chad-card__content"> <div class="chad-card__content">
<slot /> <slot />
</div> </div>
@@ -39,6 +45,7 @@ const slots = defineSlots<{
interface Props { interface Props {
as?: string as?: string
title?: string title?: string
description?: string
} }
</script> </script>
@@ -51,13 +58,23 @@ interface Props {
outline-offset: calc(var(--border-w) * -1); outline-offset: calc(var(--border-w) * -1);
box-shadow: var(--shadow); box-shadow: var(--shadow);
&__title { &__header {
@include font-display-22;
margin-bottom: var(--space-6); margin-bottom: var(--space-6);
} }
&__title {
@include font-display-22;
}
&__description {
margin-top: var(--space-2);
color: var(--grey-3);
}
&__actions { &__actions {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-3);
margin-top: var(--space-6); margin-top: var(--space-6);
} }

View File

@@ -0,0 +1,169 @@
<template>
<Teleport to="body">
<div :class="[bem.b()]">
<Transition name="chad-dialog-overlay" appear>
<div v-if="api.open" :class="bem.e('overlay')" v-bind="api.getBackdropProps()" />
</Transition>
<Transition
name="chad-dialog-content"
appear
@after-enter="emit('opened')"
@before-leave="emit('beforeClose')"
@after-leave="emit('closed')"
>
<div v-if="api.open" :class="bem.e('positioner')" v-bind="api.getPositionerProps()">
<ChadCard
:class="bem.e('content')"
v-bind="api.getContentProps()"
:title="title"
:description="description"
>
<slot v-bind="{ close }" />
<template v-if="$slots.actions" #actions>
<slot name="actions" v-bind="{ close }" />
</template>
<template v-if="$slots.bottom" #bottom>
<slot name="bottom" v-bind="{ close }" />
</template>
<ChadButton v-bind="api.getCloseTriggerProps()" :icon="XIcon" :class="bem.e('close')" type="secondary" />
</ChadCard>
</div>
</Transition>
</div>
</Teleport>
</template>
<script setup lang="ts">
import type { Props as DialogProps } from '@zag-js/dialog'
import { XIcon } from '@lucide/vue'
import ChadButton from '@shared/components/ui/Button.vue'
import ChadCard from '@shared/components/ui/Card.vue'
import useBem from '@shared/composables/use-bem.ts'
import { useDialogManager } from '@shared/composables/use-dialog.ts'
import { connect, machine } from '@zag-js/dialog'
import { normalizeProps, useMachine } from '@zag-js/vue'
import { computed, getCurrentInstance, onBeforeUnmount, onMounted } from 'vue'
export interface ChadDialogProps {
id: string
title: string
description?: string
closeOnEscape?: boolean
closeOnInteractOutside?: boolean
}
defineOptions({
name: 'ChadDialog',
})
const props = withDefaults(
defineProps<ChadDialogProps>(),
{
closeOnEscape: true,
closeOnInteractOutside: true,
},
)
const emit = defineEmits<{
opened: []
beforeClose: []
closed: []
}>()
const bem = useBem('chad-dialog')
const service = useMachine(machine, computed(() => {
return {
id: props.id,
defaultOpen: true,
closeOnEscape: props.closeOnEscape,
closeOnInteractOutside: props.closeOnInteractOutside,
} as DialogProps
}))
const api = computed(() => connect(service, normalizeProps))
const instance = getCurrentInstance()
const manager = useDialogManager()
function close() {
api.value.setOpen(false)
}
onMounted(() => {
if (!instance)
return
manager.instances.push(instance)
})
onBeforeUnmount(() => {
const index = manager.instances.findIndex(_instance => _instance === instance)
if (index === -1)
return
manager.instances.splice(index, 1)
})
defineExpose({
close,
})
</script>
<style lang="scss">
.chad-dialog {
&__overlay {
position: fixed;
inset: 0;
background-color: color-mix(in srgb, var(--ink) 60%, transparent);
backdrop-filter: blur(4px);
}
&__positioner {
position: fixed;
inset: 0;
display: flex;
padding: var(--space-4);
}
&__content {
position: relative;
margin: auto;
width: 560px;
}
&__close {
position: absolute;
bottom: calc(100% + var(--space-2));
right: 0;
//right: var(--space-6);
//top: var(--space-6);
}
&-overlay-enter-active,
&-overlay-leave-active {
transition: opacity 0.15s ease-out;
}
&-overlay-enter-from,
&-overlay-leave-to {
opacity: 0;
}
&-content-enter-active,
&-content-leave-active {
transition: 0.15s ease-out;
transition-property: opacity, translate, scale;
}
&-content-enter-from,
&-content-leave-to {
opacity: 0;
scale: 0.99;
}
}
</style>

View File

@@ -0,0 +1,17 @@
<template>
<Component :is="dialog.component" v-for="dialog in dialogs" v-bind="dialog.attrs" :id="dialog.id" :key="dialog.id">
<template v-for="(slot, key) in dialog.slots" #[key] :key="key">
<Component :is="slot" />
</template>
</Component>
</template>
<script setup lang="ts">
import { useDialogManager } from '@shared/composables/use-dialog.ts'
defineOptions({
name: 'ChadDialogContainer',
})
const { dialogs } = useDialogManager()
</script>

View File

@@ -9,7 +9,7 @@
{{ label }} {{ label }}
</label> </label>
<input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text"> <input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text" autocomplete="off">
<p v-if="helper" class="chad-input__helper"> <p v-if="helper" class="chad-input__helper">
{{ helper }} {{ helper }}

View File

@@ -0,0 +1,25 @@
<template>
<div class="chad-notification-badge">
<slot />
</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss">
.chad-notification-badge {
position: relative;
&::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 12px;
aspect-ratio: 1;
background-color: var(--yellow);
}
}
</style>

View File

@@ -0,0 +1,47 @@
<template>
<div class="chad-tag" :data-type="type">
<slot />
</div>
</template>
<script setup lang="ts">
interface Props {
type: 'success' | 'error'
}
defineOptions({
name: 'ChadTag',
})
defineProps<Props>()
</script>
<style lang="scss">
.chad-tag {
@include font-micro;
display: flex;
align-items: center;
gap: var(--space-1);
color: var(--grey-3);
&::before {
content: '';
display: block;
width: 10px;
height: 10px;
}
&[data-type='success'] {
&::before {
background-color: var(--green);
}
}
&[data-type='error'] {
&::before {
background-color: var(--red);
}
}
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<button class="chad-to-bottom">
<ArrowDown />
</button>
</template>
<script setup lang="ts">
import { ArrowDown } from '@lucide/vue'
defineOptions({
name: 'ChadToBottom',
})
</script>
<style lang="scss">
.chad-to-bottom {
cursor: pointer;
width: 40px;
aspect-ratio: 1;
text-align: center;
line-height: 40px;
outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1);
border: none;
background-color: var(--grey-1);
padding: 0;
box-shadow: var(--shadow-sm);
&:hover,
&:focus {
background-color: var(--grey-2);
}
&:active {
background-color: var(--grey-3);
}
}
</style>

View File

@@ -0,0 +1,67 @@
<template>
<button class="chad-toggle" v-bind="api.getRootProps()">
<span class="chad-toggle__indicator" v-bind="api.getIndicatorProps()" />
<slot />
</button>
</template>
<script setup lang="ts">
import type { Component } from 'vue'
import * as toggle from '@zag-js/toggle'
import { normalizeProps, useMachine } from '@zag-js/vue'
import { computed } from 'vue'
defineOptions({
name: 'ChadToggle',
})
const props = defineProps<{
disabled?: boolean
icon?: Component
}>()
const modelValue = defineModel<boolean>('modelValue')
const service = useMachine(toggle.machine, computed(() => {
return {
disabled: props.disabled,
pressed: modelValue.value,
onPressedChange: (pressed) => {
modelValue.value = pressed
},
} as toggle.Props
}))
const api = computed(() => toggle.connect(service, normalizeProps))
</script>
<style lang="scss">
.chad-toggle {
@include font-micro;
border: var(--border-w) solid var(--ink);
height: 44px;
cursor: pointer;
&:hover,
&:active {
background-color: var(--grey-2);
}
&[data-state='on'] {
background-color: var(--yellow);
}
&[data-state='off'] {
background-color: var(--paper);
color: var(--grey-3);
}
&:disabled {
cursor: not-allowed;
background-color: var(--grey-1);
color: var(--grey-3);
}
}
</style>

View File

@@ -0,0 +1,68 @@
interface Options {
block: string
blockSuffix?: string
element?: string
modifier?: string
}
function _bem(options: Options) {
const { block, blockSuffix, element, modifier } = options
let cls = block
if (blockSuffix)
cls += `-${blockSuffix}`
if (element)
cls += `__${element}`
if (modifier)
cls += `--${modifier}`
return cls
}
function isTruthy(value: unknown): boolean {
if (Array.isArray(value)) {
return value.length > 0
}
else if (typeof value === 'object' && value !== null) {
return Object.keys(value).length > 0
}
return !!value
}
export default (block: string) => {
const b = (blockSuffix?: string) => _bem({ block, blockSuffix })
const e = (element: string) => _bem({ block, element })
const m = (modifier: string) => _bem({ block, modifier })
const be = (blockSuffix: string, element: string) => _bem({ block, blockSuffix, element })
const em = (element: string, modifier: string) => _bem({ block, element, modifier })
const bm = (blockSuffix: string, modifier: string) => _bem({ block, blockSuffix, modifier })
const bem = (blockSuffix: string, element: string, modifier: string) => _bem({ block, blockSuffix, element, modifier })
const is = (name: string, state: unknown) => isTruthy(state) ? `is-${name}` : ''
const has = (name: string, state: unknown) => isTruthy(state) ? `has-${name}` : ''
const exp = (condition: boolean, trueState: string, falseState: string = '') => condition ? trueState : falseState
return {
b,
e,
m,
be,
em,
bm,
bem,
is,
has,
exp,
}
}

View File

@@ -0,0 +1,72 @@
import type { ChadClient } from '@shared/types.ts'
import { useSignaling } from '@shared/composables/use-signaling.ts'
import { createGlobalState } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
import { useAuth } from './use-auth'
export const useClients = createGlobalState(() => {
const { me } = useAuth()
const signaling = useSignaling()
const clients = shallowRef<ChadClient[]>([])
function addClient(...incoming: ChadClient[]) {
const ids = new Set(incoming.map(c => c.socketId))
clients.value = [
...clients.value.filter(c => !ids.has(c.socketId)),
...incoming,
]
}
function removeClient(...socketIds: string[]) {
const ids = new Set(socketIds)
clients.value = clients.value.filter(c => !ids.has(c.socketId))
}
function updateClient(socketId: string, patch: Partial<Omit<ChadClient, 'socketId'>>) {
clients.value = clients.value.map(c =>
c.socketId === socketId ? { ...c, ...patch } : c,
)
}
function findById(socketId: string) {
return clients.value.find(c => c.socketId === socketId)
}
function findByChannel(channelId: string) {
return clients.value.filter(c => c.channelId === channelId)
}
function findByUsername(username: string) {
return clients.value.find(c => c.username === username)
}
const self = computed(() => {
return clients.value.find((client) => {
if (signaling.socket.value) {
return client.socketId === signaling.socket.value.id
}
else if (me.value) {
return client.username === me.value.username
}
return undefined
})
})
function clear() {
clients.value = []
}
return {
clients,
self,
addClient,
removeClient,
updateClient,
findById,
findByChannel,
findByUsername,
clear,
}
})

View File

@@ -0,0 +1,69 @@
import type { Component, ComponentInternalInstance } from 'vue'
import { createGlobalState } from '@vueuse/core'
import { mergeProps, shallowReactive } from 'vue'
type ComponentAttrs = Record<string, any>
export interface UseDialogOptions {
id: string
component: Component
attrs?: ComponentAttrs
slots?: Record<string, Component>
}
export const useDialogManager = createGlobalState(() => {
const dialogs = shallowReactive<UseDialogOptions[]>([])
const instances = shallowReactive<ComponentInternalInstance[]>([])
function close(id: UseDialogOptions['id']) {
const instance = instances.find(instance => instance.props.id === id)
if (!instance?.exposed?.close || typeof instance.exposed.close !== 'function')
return
instance.exposed.close()
}
function closeAll() {
for (const dialog of dialogs) {
close(dialog.id)
}
}
return {
dialogs,
instances,
close,
closeAll,
}
})
export function useDialog(options: UseDialogOptions) {
const manager = useDialogManager()
const initialAttrs = mergeProps(options.attrs ?? {}, {
onClosed: () => {
const index = manager.dialogs.findIndex(dialog => options.id === dialog.id)
if (index === -1)
return
manager.dialogs.splice(index, 1)
},
})
function open(openAttrs?: ComponentAttrs) {
const attrs = mergeProps(initialAttrs, openAttrs ?? {})
manager.dialogs.push({ ...options, attrs })
}
function close() {
manager.close(options.id)
}
return {
open,
close,
}
}

View File

@@ -1,3 +1,4 @@
import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
import type { EventType } from 'mitt' import type { EventType } from 'mitt'
import mitt from 'mitt' import mitt from 'mitt'
@@ -29,7 +30,7 @@ export interface AppEvents extends Record<EventType, unknown> {
'share:enabled': void 'share:enabled': void
'share:disabled': void 'share:disabled': void
'chat:new-message': void 'chat:new-message': ChatMessage
} }
const emitter = mitt<AppEvents>() const emitter = mitt<AppEvents>()

View File

@@ -0,0 +1,74 @@
import { createGlobalState } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { useMediasoup } from './use-mediasoup'
import { useProducers } from './use-producers'
export const useMediaControls = createGlobalState(() => {
const { producers } = useMediasoup()
const { enableMic, enableVideo, disableVideo, enableShare, disableShare, pauseProducer, resumeProducer } = useProducers()
const micProducer = computed(() => producers.values.value.find(p => p.appData.source === 'mic'))
const cameraProducer = computed(() => producers.values.value.find(p => p.appData.source === 'camera'))
const shareProducer = computed(() => producers.values.value.find(p => p.appData.source === 'share'))
const isSoundEnabled = ref(true)
const isMicEnabled = computed(() => isSoundEnabled.value && !!micProducer.value && !micProducer.value.paused)
const isCameraEnabled = computed(() => !!cameraProducer.value && !cameraProducer.value.paused)
const isShareEnabled = computed(() => !!shareProducer.value)
watch(isSoundEnabled, async (enabled) => {
if (!enabled) {
if (micProducer.value && !micProducer.value.paused)
await pauseProducer(micProducer.value.id)
}
else {
if (micProducer.value?.paused)
await resumeProducer(micProducer.value.id)
}
})
async function toggleMic() {
if (!isSoundEnabled.value)
return
if (isMicEnabled.value) {
await pauseProducer(micProducer.value!.id)
}
else if (micProducer.value?.paused) {
await resumeProducer(micProducer.value.id)
}
else {
await enableMic()
}
}
function toggleSound() {
isSoundEnabled.value = !isSoundEnabled.value
}
async function toggleCamera() {
if (isCameraEnabled.value)
await disableVideo()
else
await enableVideo()
}
async function toggleShare() {
if (isShareEnabled.value)
await disableShare()
else
await enableShare()
}
return {
isMicEnabled,
isSoundEnabled,
isCameraEnabled,
isShareEnabled,
toggleMic,
toggleSound,
toggleCamera,
toggleShare,
}
})

View File

@@ -0,0 +1,119 @@
import type { Consumer, Device, Producer, Transport } from 'mediasoup-client/types'
import type { Ref } from 'vue'
import { createEventHook, createGlobalState } from '@vueuse/core'
import { computed, ref, shallowRef } from 'vue'
interface Snapshot<T> {
id: string
ref: T
[key: string]: any
}
export interface ProducerSnapshot extends Snapshot<Producer> {
paused: boolean
kind: string
appData: Record<string, unknown>
}
export interface ConsumerSnapshot extends Snapshot<Consumer> {
paused: boolean
kind: string
appData: Record<string, unknown>
track: MediaStreamTrack
}
export interface TransportSnapshot extends Snapshot<Transport> {
}
function createEntityStore<T extends { id: string }>() {
const store = ref(new Map<string, T>()) as unknown as Ref<Map<string, T>>
const onAddEvent = createEventHook<T>()
const onRemoveEvent = createEventHook<string>()
const values = computed(() => Array.from(store.value.values()))
async function add(entity: T) {
store.value.set(entity.id, entity)
// eslint-disable-next-line ts/ban-ts-comment
// @ts-expect-error
await onAddEvent.trigger(entity)
}
async function remove(id: string) {
store.value.delete(id)
await onRemoveEvent.trigger(id)
}
function get(id: string) {
return store.value.get(id)
}
function clear() {
store.value.clear()
}
return {
store,
values,
onAdd: onAddEvent.on,
onRemove: onRemoveEvent.on,
add,
remove,
get,
clear,
}
}
export const useMediasoup = createGlobalState(() => {
const device = shallowRef<Device>()
const sendTransport = shallowRef<Transport>()
const recvTransport = shallowRef<Transport>()
const producers = createEntityStore<ProducerSnapshot>()
producers.onAdd((producer) => {
producer.ref.observer.on('pause', () => {
producers.store.value.set(producer.id, { ...producer, paused: true })
})
producer.ref.observer.on('resume', () => {
producers.store.value.set(producer.id, { ...producer, paused: false })
})
producer.ref.observer.on('close', () => producers.remove(producer.id))
})
const consumers = createEntityStore<ConsumerSnapshot>()
consumers.onAdd((consumer) => {
consumer.ref.on('trackended', () => consumer.ref.close())
consumer.ref.observer.on('pause', () => {
consumers.store.value.set(consumer.id, { ...consumer, paused: true })
})
consumer.ref.observer.on('resume', () => {
consumers.store.value.set(consumer.id, { ...consumer, paused: false })
})
consumer.ref.observer.on('close', () => consumers.remove(consumer.id))
})
const transports = createEntityStore<TransportSnapshot>()
transports.onAdd((transport) => {
transport.ref.observer.on('close', () => transports.remove(transport.id))
})
function clearAll() {
device.value = undefined
sendTransport.value = undefined
recvTransport.value = undefined
producers.clear()
consumers.clear()
transports.clear()
}
return {
device,
sendTransport,
recvTransport,
producers,
consumers,
transports,
clearAll,
}
})

View File

@@ -0,0 +1,164 @@
import type { MediaKind, ProducerOptions } from 'mediasoup-client/types'
import { createGlobalState } from '@vueuse/core'
import { markRaw } from 'vue'
import { useMediasoup } from './use-mediasoup'
import { useSignaling } from './use-signaling'
export const useProducers = createGlobalState(() => {
const { socket } = useSignaling()
const { device, sendTransport, producers } = useMediasoup()
async function createProducer(options: ProducerOptions) {
if (!sendTransport.value || !device.value || !options.track)
return
if (!device.value.canProduce(options.track.kind as MediaKind))
return
const producer = await sendTransport.value.produce({ disableTrackOnPause: true, ...options })
producer.observer.on('trackended', () => disableProducer(producer.id))
await producers.add({
id: producer.id,
paused: producer.paused,
kind: producer.kind,
appData: producer.appData as Record<string, unknown>,
ref: markRaw(producer),
})
}
async function disableProducer(producerId: string) {
const snap = producers.get(producerId)
if (!snap)
return
try {
snap.ref.close()
await socket.value?.emitWithAck('close-producer', { producerId })
}
catch {}
}
async function pauseProducer(producerId: string) {
const snap = producers.get(producerId)
if (!snap || snap.paused)
return
try {
snap.ref.pause()
await socket.value?.emitWithAck('pause-producer', { producerId })
}
catch {
snap.ref.resume()
}
}
async function resumeProducer(producerId: string) {
const snap = producers.get(producerId)
if (!snap || !snap.paused)
return
try {
snap.ref.resume()
await socket.value?.emitWithAck('resume-producer', { producerId })
}
catch {
snap.ref.pause()
}
}
async function enableMic() {
for (const snap of producers.store.value.values()) {
if (snap.kind === 'audio')
return
}
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
const track = stream.getAudioTracks()[0]
if (!track)
return
await createProducer({
track,
streamId: 'mic-video',
codecOptions: { opusStereo: true, opusDtx: true },
appData: { source: 'mic' },
})
}
async function disableMic() {
for (const snap of producers.store.value.values()) {
if (snap.kind === 'audio')
await disableProducer(snap.id)
}
}
async function enableVideo() {
for (const snap of producers.store.value.values()) {
if (snap.kind === 'video' && snap.appData.source !== 'share')
return
}
const stream = await navigator.mediaDevices.getUserMedia({
video: { width: { ideal: 1920 }, height: { ideal: 1080 }, frameRate: { ideal: 60 } },
})
const track = stream.getVideoTracks()[0]
if (!track)
return
await createProducer({
track,
streamId: 'mic-video',
appData: { source: 'camera' },
})
}
async function disableVideo() {
for (const snap of producers.store.value.values()) {
if (snap.kind === 'video' && snap.appData.source !== 'share')
await disableProducer(snap.id)
}
}
async function enableShare() {
for (const snap of producers.store.value.values()) {
if (snap.appData.source === 'share')
return
}
const stream = await navigator.mediaDevices.getDisplayMedia({
audio: false,
video: { displaySurface: 'monitor' },
})
const track = stream.getVideoTracks()[0]
if (!track)
return
await createProducer({
track,
streamId: 'share',
zeroRtpOnPause: true,
appData: { source: 'share' },
})
}
async function disableShare() {
for (const snap of producers.store.value.values()) {
if (snap.appData.source === 'share')
await disableProducer(snap.id)
}
}
return {
enableMic,
disableMic,
enableVideo,
disableVideo,
enableShare,
disableShare,
pauseProducer,
resumeProducer,
disableProducer,
}
})

View File

@@ -0,0 +1,3 @@
export function useSession() {
return {}
}

View File

@@ -7,7 +7,7 @@ import { useAuth } from './use-auth'
import { useEventBus } from './use-event-bus' import { useEventBus } from './use-event-bus'
export const useSignaling = createSharedComposable(() => { export const useSignaling = createSharedComposable(() => {
const { emit } = useEventBus() const eventBus = useEventBus()
const { me } = useAuth() const { me } = useAuth()
const socket = shallowRef<Socket>() const socket = shallowRef<Socket>()
@@ -44,9 +44,9 @@ export const useSignaling = createSharedComposable(() => {
watch(connected, (connected) => { watch(connected, (connected) => {
if (connected) if (connected)
emit('socket:connected') eventBus.emit('socket:connected')
else else
emit('socket:disconnected') eventBus.emit('socket:disconnected')
}, { immediate: true }) }, { immediate: true })
watch(me, (me) => { watch(me, (me) => {
@@ -56,10 +56,7 @@ export const useSignaling = createSharedComposable(() => {
} }
}) })
onScopeDispose(() => { onScopeDispose(disconnect)
socket.value?.close()
socket.value = undefined
})
function connect() { function connect() {
if (socket.value || !me.value) if (socket.value || !me.value)
@@ -73,15 +70,18 @@ export const useSignaling = createSharedComposable(() => {
path: `${pathname}/ws`, path: `${pathname}/ws`,
transports: ['websocket'], transports: ['websocket'],
withCredentials: true, withCredentials: true,
auth: {
userId: me.value.id,
},
}) })
} }
function disconnect() {
socket.value?.disconnect()
socket.value = undefined
}
return { return {
socket, socket,
connected, connected,
connect, connect,
disconnect,
} }
}) })

View File

@@ -21,9 +21,26 @@
<aside class="sidebar"> <aside class="sidebar">
<ChannelList class="sidebar__channel-list" /> <ChannelList class="sidebar__channel-list" />
<ChadButton style="margin: var(--space-2);" @click="logout"> <!-- <dl> -->
Logout <!-- <template v-for="consumer in consumers.store.value.values()" :key="consumer.id"> -->
<!-- <dt>{{ consumer.id }}</dt> -->
<!-- <dd><strong>paused</strong> <i>{{ consumer.paused }}</i></dd> -->
<!-- <dd><strong>appData</strong> <i>{{ consumer.appData }}</i></dd> -->
<!-- </template> -->
<!-- </dl> -->
<!-- <ChadButton style="margin: var(&#45;&#45;space-2);" @click="toggleMic"> -->
<!-- Toggle mic -->
<!-- </ChadButton> -->
<!-- <ChadButton style="margin: var(&#45;&#45;space-2);" @click="logout"> -->
<!-- Logout -->
<!-- </ChadButton> -->
<ChadButton style="margin: var(--space-2)" type="secondary" @click="createChannelDialog.open()">
Create channel
</ChadButton> </ChadButton>
<ControlPanel />
</aside> </aside>
<div class="content"> <div class="content">
@@ -35,15 +52,34 @@
<script setup lang="ts"> <script setup lang="ts">
import ChadButton from '@shared/components/ui/Button.vue' import ChadButton from '@shared/components/ui/Button.vue'
import { useApp } from '@shared/composables/use-app.js' import { useApp } from '@shared/composables/use-app.js'
import { useAuth } from '@shared/composables/use-auth.ts' import { useDialog } from '@shared/composables/use-dialog.ts'
import { useMediasoup } from '@shared/composables/use-mediasoup.ts'
import { useProducers } from '@shared/composables/use-producers.ts'
import ChannelList from '@widgets/channel-list/ui/ChannelList.vue' import ChannelList from '@widgets/channel-list/ui/ChannelList.vue'
import ControlPanel from '@widgets/control-panel/ui/ControlPanel.vue'
import { watchEffect } from 'vue'
import CreateChannelDialog from '@/entities/channel/ui/CreateChannelDialog.vue'
defineOptions({ defineOptions({
name: 'DefaultLayout', name: 'DefaultLayout',
}) })
const { version } = useApp() const { version } = useApp()
const { logout } = useAuth()
const { sendTransport } = useMediasoup()
const { enableMic } = useProducers()
const createChannelDialog = useDialog({
id: 'create-channel',
component: CreateChannelDialog,
})
watchEffect(() => {
if (!sendTransport.value)
return
enableMic()
})
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -35,9 +35,18 @@ a {
color: var(--yellow); color: var(--yellow);
} }
} }
//
//*, ::-webkit-scrollbar {
//*::before, color: var(--grey-2);
//*::after { height: 8px;
// @include font-body; width: 8px;
//} }
::-webkit-scrollbar-thumb {
background-color: var(--grey-2);
//border-right: 4px solid var(--paper);
&:hover {
background-color: var(--grey-3);
}
}

View File

@@ -10,6 +10,7 @@
--grey-2: #c9c6bd; --grey-2: #c9c6bd;
--grey-3: #8a8a82; --grey-3: #8a8a82;
--shadow-sm: 3px 3px 0 0 var(--ink);
--shadow: 6px 6px 0 0 var(--ink); --shadow: 6px 6px 0 0 var(--ink);
--border-w: 2px; --border-w: 2px;

View File

@@ -1,7 +1,8 @@
export interface ChadClient { export interface ChadClient {
socketId: string socketId: string
userId: string username: string
channelId: string channelId: string
inputMuted?: boolean micMuted?: boolean
outputMuted?: boolean soundMuted?: boolean
streaming?: boolean
} }

View File

@@ -5,26 +5,38 @@
</div> </div>
<div v-bind="api.getContentProps()" class="channel__content"> <div v-bind="api.getContentProps()" class="channel__content">
Clients... <p v-for="client in clients" :key="client.socketId">
{{ client.username }}
</p>
</div> </div>
</li> </li>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Channel } from '@shared/api/generated-chad-api.ts' import type { Channel } from '@shared/api/generated-chad-api.ts'
import type { ChadClient } from '@shared/types.ts' import { useClients } from '@shared/composables/use-clients.ts'
import * as collapsible from '@zag-js/collapsible' import * as collapsible from '@zag-js/collapsible'
import { normalizeProps, useMachine } from '@zag-js/vue' import { normalizeProps, useMachine } from '@zag-js/vue'
import { computed } from 'vue' import { computed } from 'vue'
const props = defineProps<{ const props = defineProps<{
channel: Channel channel: Channel
clients: ChadClient[]
}>() }>()
const service = useMachine(collapsible.machine, { id: '1' }) const { findByChannel } = useClients()
const service = useMachine(collapsible.machine, computed(() => {
return {
id: props.channel.id,
defaultOpen: true,
}
}))
const api = computed(() => collapsible.connect(service, normalizeProps)) const api = computed(() => collapsible.connect(service, normalizeProps))
const clients = computed(() => {
return findByChannel(props.channel.id)
})
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -1,14 +1,14 @@
<template> <template>
<div class="channel-list"> <div class="channel-list">
<ul class="channel-list__list"> <ul class="channel-list__list">
<ChannelItem v-for="channel in channels" :key="channel.id" :channel="channel" /> <Channel v-for="channel in channels" :key="channel.id" :channel="channel" />
</ul> </ul>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { qChannelList } from '../api/qChannelList.ts' import { qChannelList } from '../api/qChannelList.ts'
import ChannelItem from './ChannelItem.vue' import Channel from './Channel.vue'
const { data: channels } = qChannelList() const { data: channels } = qChannelList()
</script> </script>

View File

@@ -1,5 +1,5 @@
import type { ChatMessage, ResponseError } from '@shared/api/generated-chad-api.ts' import type { ChatMessage, ResponseError } from '@shared/api/generated-chad-api.ts'
import type { InfiniteData, QueryKey } from '@tanstack/vue-query' import type { QueryKey } from '@tanstack/vue-query'
import api from '@shared/api/client.ts' import api from '@shared/api/client.ts'
import { useInfiniteQuery } from '@tanstack/vue-query' import { useInfiniteQuery } from '@tanstack/vue-query'
@@ -10,21 +10,16 @@ interface Response {
type PageParam = string | undefined type PageParam = string | undefined
export function qChatMessages() { export function qChatMessages() {
return useInfiniteQuery<Response, ResponseError, InfiniteData<Response, PageParam>, QueryKey, PageParam>({ return useInfiniteQuery<Response, ResponseError, ChatMessage[], QueryKey, PageParam>({
queryKey: ['chat-messages'], queryKey: ['chat-messages'],
queryFn: async ({ pageParam }) => { queryFn: async ({ pageParam }) => {
const response = await api.chad.chatMessages({ cursor: pageParam, limit: 30 }) const response = await api.chad.chatMessages({ cursor: pageParam, limit: 25 })
return response.data return response.data
// return {
// messages: response.data.messages.reverse(),
// nextCursor: response.data.nextCursor,
// }
}, },
// select: data => ({ select: (data) => {
// pages: [...data.pages].reverse(), return data.pages.flatMap(page => page.messages).toReversed()
// pageParams: [...data.pageParams].reverse(), },
// }),
initialPageParam: undefined, initialPageParam: undefined,
getNextPageParam: (lastPage) => { getNextPageParam: (lastPage) => {
return lastPage.nextCursor return lastPage.nextCursor

View File

@@ -0,0 +1,42 @@
import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
import { useEventBus } from '@shared/composables/use-event-bus.ts'
import { createGlobalState } from '@vueuse/core'
import { computed, shallowRef, triggerRef } from 'vue'
import { qChatMessages } from '../api/qChatMessages.ts'
export interface MessageGroup {
senderUsername: string
messages: ChatMessage[]
}
export const useChatHistory = createGlobalState(() => {
const eventBus = useEventBus()
const { data: messages, hasNextPage: hasMoreMessages, fetchNextPage: loadMoreMessages, isFetching } = qChatMessages()
const feedItems = shallowRef<ChatMessage[]>([])
eventBus.on('chat:new-message', (message: ChatMessage) => {
feedItems.value.push(message)
triggerRef(feedItems)
})
const messageGroups = computed<MessageGroup[]>(() => {
const all = [...(messages.value ?? []), ...feedItems.value]
return all.reduce((groups, msg) => {
const last = groups.at(-1)
if (last?.senderUsername === msg.senderUsername)
last.messages.push(msg)
else
groups.push({ senderUsername: msg.senderUsername, messages: [msg] })
return groups
}, [] as MessageGroup[])
})
return {
messageGroups,
hasMoreMessages,
loadMoreMessages,
isFetching,
}
})

View File

@@ -0,0 +1,110 @@
import type { MaybeRefOrGetter, TemplateRef } from 'vue'
import { useEventListener, useMutationObserver } from '@vueuse/core'
import { computed, reactive, toValue, watch } from 'vue'
interface ChatScrollOptions {
startOffset?: number
endOffset?: number
}
export function useChatScroll(target: TemplateRef<HTMLElement>, options?: MaybeRefOrGetter<ChatScrollOptions>) {
const el = computed(() => toValue(target))
const arrivedState = reactive({
start: true,
end: false,
})
let lastScrollHeight = 0
let lastScrollTop = 0
watch(el, (el) => {
if (!el)
return
scrollToStart(true)
getArrivedState()
}, { flush: 'post' })
useMutationObserver(el, (mutations) => {
if (arrivedState.start) {
scrollToStart(true)
}
else {
// const prepended = mutations.some(mutation => Array.from(mutation.addedNodes.values()).some(node => !!node.nextEle))
// console.log('prepended', prepended)
// for (const mutation of mutations) {
// for (const node of mutation.addedNodes) {
// console.log('added node', node, !!node.nextSibling)
// if (node.nextSibling) {
// // добавлено сверху/в середину
// // el.value!.scrollTop += (node as HTMLElement).offsetHeight
// }
// }
//
// // for (const node of mutation.removedNodes) {
// // // previousSibling/nextSibling здесь — это соседи на момент удаления
// // if (mutation.previousSibling || mutation.nextSibling) {
// // // удалено сверху/в середину — уменьшаем scrollTop
// // el.value!.scrollTop -= (node as HTMLElement).offsetHeight
// // }
// // }
// }
const heightDiff = el.value!.scrollHeight - lastScrollHeight
// const scrollDiff = el.value!.scrollTop - lastScrollTop
//
// console.log('height', 'old', lastScrollHeight, 'new', el.value!.scrollHeight, 'diff', heightDiff)
// console.log('scroll', 'old', lastScrollTop, 'new', el.value!.scrollTop, 'diff', scrollDiff)
//
el.value!.scrollTop += heightDiff
}
getArrivedState()
}, {
childList: true,
subtree: true,
})
useEventListener(el, 'scroll', () => {
getArrivedState()
lastScrollTop = el.value!.scrollTop
}, { passive: true })
useEventListener(el, 'scrollend', () => {
getArrivedState()
}, { passive: true })
function getArrivedState() {
if (!el.value) {
arrivedState.start = true
arrivedState.end = false
return
}
const { startOffset = 0, endOffset = 0 } = toValue(options) ?? {}
const offsetHeight = el.value.offsetHeight
const scrollHeight = el.value.scrollHeight
const scrollTop = Math.abs(el.value.scrollTop)
arrivedState.start = scrollTop + offsetHeight >= scrollHeight - startOffset
arrivedState.end = scrollTop <= endOffset
lastScrollHeight = el.value!.scrollHeight
}
function scrollToStart(instant = false) {
if (!el.value)
return
const offset = Math.ceil(el.value.scrollHeight - el.value.offsetHeight)
el.value.scrollTo({ top: offset, behavior: instant ? 'instant' : 'smooth' })
}
return {
arrivedState,
scrollToStart,
}
}

View File

@@ -1,13 +1,18 @@
import { createGlobalState } from '@vueuse/core' import type { NewChatMessagePayload } from '@shared/api/generated-chad-api.ts'
import { qChatMessages } from '../api/qChatMessages.ts' import api from '@shared/api/client.ts'
export const useChat = createGlobalState(() => { export function useChat() {
const { data: messages, hasNextPage: hasMoreMessages, fetchNextPage, isFetching } = qChatMessages() async function sendMessage(newMessage: NewChatMessagePayload) {
newMessage.text = newMessage.text.trim()
if (newMessage.attachments?.length === 0 && newMessage.text.length === 0) {
return
}
await api.chad.chatSend(newMessage)
}
return { return {
messages, sendMessage,
hasMoreMessages, }
fetchNextPage,
isFetching,
} }
})

View File

@@ -1,13 +1,19 @@
<template> <template>
<div class="chat"> <div class="chat">
<ChatMessages class="chat__messages" /> <ChatMessages class="chat__messages" />
<!-- <ChadButton @click="loadMoreMessages()"> -->
<!-- PENIS -->
<!-- </ChadButton> -->
<ChatInput class="chat__input" /> <ChatInput class="chat__input" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useChatHistory } from '@widgets/chat/composables/use-chat-history.ts'
import ChatInput from '@widgets/chat/ui/ChatInput.vue' import ChatInput from '@widgets/chat/ui/ChatInput.vue'
import ChatMessages from '@widgets/chat/ui/ChatMessages.vue' import ChatMessages from '@widgets/chat/ui/ChatMessages.vue'
const { loadMoreMessages } = useChatHistory()
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -0,0 +1,62 @@
<template>
<div
:class="[
bem.b(),
bem.is('loading', loading),
bem.is('error', error),
]"
>
{{ name }}
</div>
</template>
<script setup lang="ts">
import useBem from '@shared/composables/use-bem.ts'
const props = defineProps<{
name: string
loading?: boolean
error?: boolean
}>()
const bem = useBem('chat-attachment')
</script>
<style lang="scss">
.chat-attachment {
--stripe-width: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: var(--space-1) var(--space-2);
background-color: var(--grey-1);
outline: 1px solid var(--ink);
outline-offset: -1px;
cursor: pointer;
background-repeat: repeat;
color: var(--grey-3);
&.is-loading {
background-image: repeating-linear-gradient(
-45deg,
transparent 25%,
transparent 50%,
var(--grey-2) 50%,
var(--grey-2) 75%
);
background-size: var(--stripe-width) var(--stripe-width);
animation: loading 500ms infinite linear;
}
}
@keyframes loading {
from {
background-position-x: 0;
}
to {
background-position-x: var(--stripe-width);
}
}
</style>

View File

@@ -1,16 +1,181 @@
<template> <template>
<div class="chat-input"> <div class="chat-input" v-bind="fileUploadApi.getRootProps()">
<ChadInput placeholder="Write a message..." /> <div class="chat-input__input-row">
<ChadButton
class="chat-input__add-attachment"
type="secondary"
:icon="Plus"
@click="fileUploadApi.openFilePicker()"
/>
<ChadInput
v-model="message.text"
class="chat-input__input"
placeholder="Write a message..."
@keydown.enter="sendMessage()"
/>
<ChadButton
class="chat-input__send"
:loading="isUploading"
@click="sendMessage()"
>
Send
</ChadButton>
</div>
<div v-if="fileUploadApi.acceptedFiles.length > 0" class="chat-input__attachments" v-bind="fileUploadApi.getItemGroupProps()">
<ChatAttachment
v-for="file in fileUploadApi.acceptedFiles"
:key="file.name"
:loading="uploadStates.get(file)?.status === 'loading'"
:error="uploadStates.get(file)?.status === 'error'"
class="chat-input__attachment"
v-bind="fileUploadApi.getItemProps({ file })"
:name="file.name"
@click="removeFile(file)"
/>
</div>
<input v-bind="fileUploadApi.getHiddenInputProps()">
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { FullRequestParams, NewChatMessagePayload } from '@shared/api/generated-chad-api.ts'
import { Plus } from '@lucide/vue'
import api from '@shared/api/client.ts'
import { ContentType } from '@shared/api/generated-chad-api.ts'
import ChadButton from '@shared/components/ui/Button.vue'
import ChadInput from '@shared/components/ui/Input.vue' import ChadInput from '@shared/components/ui/Input.vue'
import { useEventListener } from '@vueuse/core'
import { useChat } from '@widgets/chat/composables/use-chat.ts'
import ChatAttachment from '@widgets/chat/ui/ChatAttachment.vue'
import * as fileUpload from '@zag-js/file-upload'
import { normalizeProps, useMachine } from '@zag-js/vue'
import { computed, reactive, useId } from 'vue'
interface UploadStatus {
status: 'loading' | 'done' | 'error'
uuid?: string
abortController: AbortController
}
const id = useId()
const chat = useChat()
const message: NewChatMessagePayload = reactive({
text: '',
attachments: [],
})
const uploadStates = reactive(new Map<File, UploadStatus>())
const isUploading = computed(() => {
return Array.from(uploadStates.values()).some(s => s.status === 'loading')
})
const service = useMachine(fileUpload.machine, {
id,
maxFiles: 10,
maxFileSize: 1000 * 1024 * 1024,
name: 'chat-input',
capture: 'environment',
allowDrop: false,
onFileAccept: (details) => {
for (const file of details.files) {
if (uploadStates.has(file))
continue
const state: UploadStatus = { status: 'loading', abortController: new AbortController() }
uploadStates.set(file, state)
const formData = new FormData()
formData.append('file', file)
try {
api.chad.attachmentUpload({
body: formData,
format: 'text',
type: ContentType.FormData,
signal: state.abortController.signal,
} as FullRequestParams).then((response) => {
uploadStates.set(file, { ...state, status: 'done', uuid: response.data })
message.attachments!.push(response.data)
})
}
catch {
uploadStates.set(file, { ...state, status: 'error' })
}
}
},
})
const fileUploadApi = computed(() => fileUpload.connect(service, normalizeProps))
useEventListener(document, 'paste', (event) => {
fileUploadApi.value.setClipboardFiles(event.clipboardData)
})
function removeFile(file: File) {
uploadStates.get(file)?.abortController.abort('Attachment removed')
uploadStates.delete(file)
fileUploadApi.value.deleteFile(file)
}
function sendMessage() {
if (isUploading.value)
return
chat.sendMessage(message)
reset()
}
function reset() {
message.text = ''
message.attachments = []
uploadStates.clear()
fileUploadApi.value.clearFiles()
}
</script> </script>
<style lang="scss"> <style lang="scss">
.chat-input { .chat-input {
padding: var(--space-3) var(--space-6); padding: var(--space-3) var(--space-6);
border-top: var(--border-w) solid var(--ink); border-top: var(--border-w) solid var(--ink);
&__input-row {
display: flex;
}
&__add-attachment {
flex-shrink: 0;
margin-right: calc(var(--border-w) * -1);
}
&__input {
flex: 1;
}
&__send {
flex-shrink: 0;
margin-left: calc(var(--border-w) * -1);
}
&__attachments {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
padding: var(--space-2);
margin-top: var(--space-2);
outline: var(--border-w) dashed var(--ink);
outline-offset: calc(var(--border-w) * -1);
overflow: hidden;
> * {
max-width: 300px;
}
}
} }
</style> </style>

View File

@@ -1,10 +1,8 @@
<template> <template>
<div class="chat-message"> <div class="chat-message">
<ChadAvatar class="chat-message__avatar" src="" :fallback="initials" :highlighted="isMyMessage" />
<div>
<div class="chat-message__top"> <div class="chat-message__top">
<p class="chat-message__sender"> <p class="chat-message__sender">
{{ !sender ? message.senderId : sender.displayName }} {{ !sender ? message.senderUsername : sender.displayName }}
</p> </p>
<p class="chat-message__datetime"> <p class="chat-message__datetime">
@@ -16,19 +14,14 @@
{{ message.text }} {{ message.text }}
</p> </p>
<div v-if="message.attachments.length > 0" class="chat-message__attachments"> <ChatMessageAttachments v-if="message.attachments.length > 0" :attachments="message.attachments" class="chat-message__attachments" />
<ChatMessageAttachment v-for="attachmentId in message.attachments" :key="attachmentId" :attachment-id="attachmentId" />
</div>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ChatMessage } from '@shared/api/generated-chad-api.ts' import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
import ChadAvatar from '@shared/components/ui/Avatar.vue'
import { useAuth } from '@shared/composables/use-auth.ts'
import { useUserDetails } from '@shared/composables/use-user-details.ts' import { useUserDetails } from '@shared/composables/use-user-details.ts'
import ChatMessageAttachment from '@widgets/chat/ui/ChatMessageAttachment.vue' import ChatMessageAttachments from '@widgets/chat/ui/ChatMessageAttachments.vue'
import { format, isThisYear, isToday } from 'date-fns' import { format, isThisYear, isToday } from 'date-fns'
import { computed, toRef } from 'vue' import { computed, toRef } from 'vue'
@@ -36,15 +29,7 @@ const props = defineProps<{
message: ChatMessage message: ChatMessage
}>() }>()
const { me } = useAuth() const { user: sender } = useUserDetails(toRef(() => props.message.senderUsername))
const isMyMessage = computed(() => {
return props.message.senderId === me.value?.id
})
const { user: sender, isFetching: fetchingSender } = useUserDetails(toRef(() => props.message.senderId))
const initials = computed(() => props.message.senderId.slice(props.message.senderId.length - 2))
const datetime = computed(() => { const datetime = computed(() => {
let formatStr = 'd MMMM yyyy, HH:mm' let formatStr = 'd MMMM yyyy, HH:mm'
@@ -64,26 +49,23 @@ const datetime = computed(() => {
.chat-message { .chat-message {
$self: &; $self: &;
display: grid; &:not(:last-child) {
grid-template-columns: auto 1fr; margin-bottom: var(--space-3);
grid-template-areas: 'avatar top' 'avatar body';
column-gap: var(--space-3);
padding: var(--space-3) var(--space-6);
&__avatar {
grid-area: avatar;
} }
&__top { &__top {
display: flex; display: flex;
gap: var(--space-2); gap: var(--space-2);
align-items: center; align-items: center;
grid-area: top;
//margin-top: var(--space-1); //margin-top: var(--space-1);
} }
&__sender { &__sender {
@include font-body-bold; @include font-body-bold;
#{$self}:not(:first-child) & {
display: none;
}
} }
&__datetime { &__datetime {
@@ -94,16 +76,12 @@ const datetime = computed(() => {
} }
&__body { &__body {
grid-area: body;
margin-top: var(--space-1); margin-top: var(--space-1);
} }
&__attachments { &__attachments {
//overflow-x: auto;
margin-top: var(--space-2); margin-top: var(--space-2);
> *:not(:last-child) {
margin-bottom: var(--space-1);
}
} }
} }
</style> </style>

View File

@@ -1,46 +1,108 @@
<template> <template>
<div class="chat-message-attachment"> <div class="chat-message-attachment" :title="attachment.name" @click="download">
<p v-if="isFetching"> <div class="chat-message-attachment__extension">
Loading... {{ extension }}
</div>
<div class="chat-message-attachment__body">
<p class="chat-message-attachment__name">
{{ attachment.name }}
</p> </p>
<template v-else-if="attachment"> <p class="chat-message-attachment__size">
<img v-if="isImage" :src="src" :alt="attachmentId" draggable="false"> {{ size }}
</template> </p>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { qMessageAttachment } from '@widgets/chat/api/qMessageAttachment.ts' import type { Attachment } from '@shared/api/generated-chad-api.ts'
import { computed, toRef } from 'vue' import api from '@shared/api/client.ts'
import { downloadFile } from '@zag-js/file-utils'
import { formatBytes } from '@zag-js/i18n-utils'
import { computed } from 'vue'
const props = defineProps<{ const props = defineProps<{
attachmentId: string attachment: Attachment
}>() }>()
const { isFetching, data: attachment } = qMessageAttachment(toRef(() => props.attachmentId)) const extension = computed(() => props.attachment.name.split('.').at(-1))
const isImage = computed(() => { const url = computed(() => {
return attachment.value?.type.startsWith('image/') return `${__API_BASE_URL__}/attachment/${props.attachment.id}`
}) })
const src = computed(() => { const size = computed(() => {
if (!attachment.value || !isImage.value) return formatBytes(props.attachment.size, 'en-US', { unitSystem: 'binary' })
return undefined
return URL.createObjectURL(attachment.value)
}) })
async function download() {
const response = await api.chad.attachmentGet(props.attachment.id, { format: 'blob' })
downloadFile({ name: props.attachment.name, type: props.attachment.mimetype, file: response.data })
}
</script> </script>
<style lang="scss"> <style lang="scss">
.chat-message-attachment { .chat-message-attachment {
$self: &;
display: grid;
grid-template-columns: 52px 1fr;
outline: var(--border-w) solid var(--ink); outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1); outline-offset: calc(var(--border-w) * -1);
background-color: var(--grey-1); background-color: var(--grey-1);
width: fit-content; width: 300px;
height: 52px;
> img { cursor: pointer;
max-width: 260px;
max-height: 160px; &:focus,
&:hover {
background-color: var(--grey-2);
}
&:active {
background-color: var(--grey-3);
}
&__extension {
@include font-label;
overflow: hidden;
white-space: nowrap;
line-height: 52px;
text-align: center;
background-color: var(--ink);
color: var(--white);
}
&__body {
flex: 1;
padding: var(--space-3);
align-self: center;
overflow: hidden;
}
&__name {
@include font-body-bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__size {
@include font-micro;
margin-top: var(--space-1);
color: var(--grey-3);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
#{$self}:active & {
color: var(--grey-1);
}
} }
} }
</style> </style>

View File

@@ -0,0 +1,47 @@
<template>
<div class="chat-message-attachments">
<div v-if="images.length > 0" class="chat-message-attachments__images">
<ChatMessageImageAttachment v-for="attachment in images" :key="attachment.id" :attachment="attachment" />
</div>
<div v-if="notImages.length > 0" class="chat-message-attachments__list">
<ChatMessageAttachment v-for="attachment in notImages" :key="attachment.id" :attachment="attachment" />
</div>
</div>
</template>
<script setup lang="ts">
import type { Attachment } from '@shared/api/generated-chad-api.ts'
import ChatMessageAttachment from '@widgets/chat/ui/ChatMessageAttachment.vue'
import ChatMessageImageAttachment from '@widgets/chat/ui/ChatMessageImageAttachment.vue'
import { computed } from 'vue'
const props = defineProps<{
attachments: Attachment[]
}>()
const images = computed(() => {
return props.attachments.filter(attachment => attachment.mimetype.startsWith('image/'))
})
const notImages = computed(() => {
return props.attachments.filter(attachment => !attachment.mimetype.startsWith('image/'))
})
</script>
<style lang="scss">
.chat-message-attachments {
overflow-x: auto;
&__images,
&__list {
display: flex;
gap: var(--space-2);
flex-wrap: nowrap;
}
&__list {
margin-top: var(--space-3);
}
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div class="chat-message-group">
<ChadAvatar class="chat-message-group__avatar" src="" :fallback="initials" :highlighted="isMyMessage" />
<div class="chat-message-group__messages">
<ChatMessage
v-for="message in group.messages"
:key="message.id"
:message="message"
/>
</div>
</div>
</template>
<script setup lang="ts">
import type { MessageGroup } from '@widgets/chat/composables/use-chat-history.js'
import ChadAvatar from '@shared/components/ui/Avatar.vue'
import { useAuth } from '@shared/composables/use-auth.ts'
import ChatMessage from '@widgets/chat/ui/ChatMessage.vue'
import { computed } from 'vue'
const props = defineProps<{
group: MessageGroup
}>()
const { me } = useAuth()
const initials = computed(() => props.group.senderUsername.slice(props.group.senderUsername.length - 2))
const isMyMessage = computed(() => {
return props.group.senderUsername === me.value?.username
})
</script>
<style lang="scss">
.chat-message-group {
display: grid;
grid-template-columns: auto 1fr;
column-gap: var(--space-3);
padding-block: var(--space-3);
padding-inline: var(--space-6);
&__avatar {
position: sticky;
top: var(--space-3);
}
}
</style>

View File

@@ -0,0 +1,35 @@
<template>
<div class="chat-message-image-attachment">
<img :src="src" :alt="attachment.name" draggable="false">
</div>
</template>
<script setup lang="ts">
import type { Attachment } from '@shared/api/generated-chad-api.ts'
import { computed } from 'vue'
const props = defineProps<{
attachment: Attachment
}>()
const src = computed(() => {
return `${__API_BASE_URL__}/attachment/${props.attachment.id}`
})
</script>
<style lang="scss">
.chat-message-image-attachment {
outline: var(--border-w) solid var(--ink);
outline-offset: calc(var(--border-w) * -1);
background-color: var(--grey-1);
width: fit-content;
height: 160px;
> img {
object-fit: contain;
object-position: center;
max-width: 260px;
height: 100%;
}
}
</style>

View File

@@ -1,38 +1,74 @@
<template> <template>
<div class="chat-messages"> <div class="chat-messages">
<div v-if="messages" ref="scroll" class="chat-messages__list"> <div v-if="messageGroups.length" ref="scroll" class="chat-messages__list">
<template v-for="(page, pageIdx) in messages.pages" :key="pageIdx"> <ChatMessageGroup
<ChatMessage v-for="message in page.messages" :key="message.id" :message="message" /> v-for="group in messageGroups"
</template> :key="`group-${group.messages[0].id}`"
:group="group"
/>
</div> </div>
<ChadSpinner v-if="isFetching" class="chat-messages__spinner" /> <ChadSpinner v-if="isFetching" class="chat-messages__spinner" />
<div v-if="!arrivedState.start" class="chat-messages__floating-actions">
<div v-if="hasUnreadMessages" class="chat-messages__has-unread-messages">
New messages
</div>
<ChadToBottom
class="chat-messages__scroll-to-bottom"
@click="scrollToStart()"
/>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import ChadSpinner from '@shared/components/ui/Spinner.vue' import ChadSpinner from '@shared/components/ui/Spinner.vue'
import { useInfiniteScroll } from '@vueuse/core' import ChadToBottom from '@shared/components/ui/ToBottom.vue'
import ChatMessage from '@widgets/chat/ui/ChatMessage.vue' import { useEventBus } from '@shared/composables/use-event-bus.ts'
import { useTemplateRef } from 'vue' import { useChatScroll } from '@widgets/chat/composables/use-chat-scroll.ts'
import { useChat } from '../composables/use-chat' import ChatMessageGroup from '@widgets/chat/ui/ChatMessageGroup.vue'
import { onUnmounted, ref, useTemplateRef, watch } from 'vue'
import { useChatHistory } from '../composables/use-chat-history'
const eventBus = useEventBus()
const scrollRef = useTemplateRef('scroll') const scrollRef = useTemplateRef('scroll')
const { messages, hasMoreMessages, fetchNextPage, isFetching } = useChat() const { messageGroups, hasMoreMessages, loadMoreMessages, isFetching } = useChatHistory()
useInfiniteScroll( const hasUnreadMessages = ref(false)
scrollRef,
() => { const { arrivedState, scrollToStart } = useChatScroll(scrollRef, {
fetchNextPage() startOffset: 100,
}, endOffset: 100,
{ })
distance: 500,
direction: 'top', watch(() => arrivedState.end, (arrived) => {
interval: 300, if (!arrived)
canLoadMore: () => hasMoreMessages.value && !isFetching.value, return
},
) if (hasMoreMessages.value) {
loadMoreMessages()
}
})
watch(() => arrivedState.start, () => {
hasUnreadMessages.value = false
})
eventBus.on('chat:new-message', onNewChatMessage)
onUnmounted(() => {
eventBus.off('chat:new-message', onNewChatMessage)
})
function onNewChatMessage() {
if (!arrivedState.start) {
hasUnreadMessages.value = true
}
}
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -49,11 +85,35 @@ useInfiniteScroll(
} }
&__list { &__list {
overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
overflow-y: overlay;
overflow-anchor: none;
display: flex; position: relative;
flex-direction: column-reverse; max-height: 100%;
height: 100%; }
&__floating-actions {
position: absolute;
display: inline-flex;
align-items: flex-end;
gap: var(--space-2);
bottom: var(--space-4);
right: var(--space-4);
pointer-events: none;
}
&__has-unread-messages {
@include font-micro;
background-color: var(--yellow);
padding: var(--space-1) var(--space-2);
box-shadow: var(--shadow-sm);
}
&__scroll-to-bottom {
pointer-events: auto;
} }
} }
</style> </style>

View File

@@ -0,0 +1,63 @@
<template>
<div class="control-panel">
<ChadTag class="control-panel__status" :type="connected ? 'success' : 'error'">
{{ connected ? 'Connected' : 'Disconnected' }}
</ChadTag>
<div class="control-panel__toggles">
<ChadToggle :model-value="isMicEnabled" @update:model-value="toggleMic">
MIC
</ChadToggle>
<ChadToggle :model-value="isSoundEnabled" @update:model-value="toggleSound">
SND
</ChadToggle>
<ChadToggle :model-value="isCameraEnabled" @update:model-value="toggleCamera">
CAM
</ChadToggle>
<ChadToggle :model-value="isShareEnabled" @update:model-value="toggleShare">
SHR
</ChadToggle>
</div>
</div>
</template>
<script setup lang="ts">
import ChadTag from '@shared/components/ui/Tag.vue'
import ChadToggle from '@shared/components/ui/Toggle.vue'
import { useMediaControls } from '@shared/composables/use-media-controls.ts'
import { useSignaling } from '@shared/composables/use-signaling.ts'
const { connected } = useSignaling()
const {
isMicEnabled,
isSoundEnabled,
isCameraEnabled,
isShareEnabled,
toggleMic,
toggleSound,
toggleCamera,
toggleShare,
} = useMediaControls()
</script>
<style lang="scss">
.control-panel {
border-top: var(--border-w) solid var(--ink);
padding: var(--space-3);
background-color: var(--grey-1);
&__status {
margin-bottom: var(--space-3);
}
&__toggles {
display: grid;
grid-template-columns: repeat(4, 1fr);
align-items: center;
> *:not(:last-child) {
border-right: none;
}
}
}
</style>

View File

@@ -2,7 +2,7 @@
"extends": "@vue/tsconfig/tsconfig.dom.json", "extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": { "compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"lib": ["ES2023", "DOM"],
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"paths": { "paths": {
"@app/*": ["./src/app/*"], "@app/*": ["./src/app/*"],

File diff suppressed because it is too large Load Diff

2
server/.gitignore vendored
View File

@@ -18,3 +18,5 @@ node_modules
.env* .env*
*.db *.db
uploads

View File

@@ -4,7 +4,6 @@ import fp from 'fastify-plugin'
import { Lucia } from 'lucia' import { Lucia } from 'lucia'
interface DatabaseUserAttributes { interface DatabaseUserAttributes {
id: string
displayName: string displayName: string
username: string username: string
createdAt: Date createdAt: Date

View File

@@ -1,7 +1,6 @@
import { Type } from 'typebox' import { Type } from 'typebox'
export const UserSchema = Type.Object({ export const UserSchema = Type.Object({
id: Type.String(),
username: Type.String(), username: Type.String(),
displayName: Type.String(), displayName: Type.String(),
createdAt: Type.String({ format: 'date-time' }), createdAt: Type.String({ format: 'date-time' }),

View File

@@ -2,7 +2,7 @@ import { Type } from 'typebox'
export const ChannelSchema = Type.Object({ export const ChannelSchema = Type.Object({
id: Type.String(), id: Type.String(),
ownerId: Type.Union([Type.String(), Type.Null()]), ownerUsername: Type.Union([Type.String(), Type.Null()]),
name: Type.String(), name: Type.String(),
persistent: Type.Boolean(), persistent: Type.Boolean(),
}, { $id: 'Channel' }) }, { $id: 'Channel' })

View File

@@ -1,23 +1,24 @@
import { Type } from 'typebox' import { Type } from 'typebox'
import { AttachmentSchema } from './attachment.ts'
export const ReplySchema = Type.Object({ export const ReplySchema = Type.Object({
messageId: Type.String({ format: 'uuid' }), messageId: Type.String({ format: 'uuid' }),
senderId: Type.String({ format: 'uuid' }), senderUsername: Type.String(),
text: Type.String(), text: Type.String(),
}, { $id: 'Reply' }) }, { $id: 'Reply' })
export const ChatMessageSchema = Type.Object({ export const ChatMessageSchema = Type.Object({
id: Type.String({ format: 'uuid' }), id: Type.String({ format: 'uuid' }),
senderId: Type.String({ format: 'uuid' }), senderUsername: Type.String(),
text: Type.String({ minLength: 1 }), text: Type.String({ minLength: 1 }),
createdAt: Type.String({ format: 'date-time' }), createdAt: Type.String({ format: 'date-time' }),
updatedAt: Type.String({ format: 'date-time' }), updatedAt: Type.String({ format: 'date-time' }),
attachments: Type.Array(Type.String({ format: 'uuid' })), attachments: Type.Array(AttachmentSchema),
}, { $id: 'ChatMessage' }) }, { $id: 'ChatMessage' })
export const NewChatMessagePayloadSchema = Type.Object({ export const NewChatMessagePayloadSchema = Type.Object({
text: Type.String({ minLength: 1 }), text: Type.String(),
attachments: Type.Optional(Type.Array(Type.String({ format: 'uuid' }))), attachments: Type.Optional(Type.Array(Type.String({ format: 'uuid' }))),
// replyTo: Type.Object({ // replyTo: Type.Object({
// messageId: Type.String({ format: 'uuid' }), // messageId: Type.String({ format: 'uuid' }),

View File

@@ -2,7 +2,6 @@ import { Type } from 'typebox'
export const GetUserQuerySchema = Type.Partial(Type.Object({ export const GetUserQuerySchema = Type.Partial(Type.Object({
username: Type.String(), username: Type.String(),
id: Type.String(),
}), { $id: 'GetUserQuery' }) }), { $id: 'GetUserQuery' })
export const UserPreferencesSchema = Type.Object({ export const UserPreferencesSchema = Type.Object({

View File

@@ -4,7 +4,7 @@ import type { Channel, User } from '../../prisma/generated-client/client.ts'
export interface SerializedClient { export interface SerializedClient {
socketId: string socketId: string
userId: User['id'] username: User['username']
channelId: Channel['id'] channelId: Channel['id']
inputMuted: boolean inputMuted: boolean
outputMuted: boolean outputMuted: boolean

View File

@@ -26,7 +26,7 @@ interface ClientEvents {
export class Client extends EventEmitter<ClientEvents> { export class Client extends EventEmitter<ClientEvents> {
readonly socketId: string readonly socketId: string
readonly userId: string readonly username: string
channelId: string = '' channelId: string = ''
#inputMuted = false #inputMuted = false
@@ -38,11 +38,11 @@ export class Client extends EventEmitter<ClientEvents> {
readonly #producers = new Map<string, types.Producer>() readonly #producers = new Map<string, types.Producer>()
readonly #consumers = new Map<string, types.Consumer>() readonly #consumers = new Map<string, types.Consumer>()
constructor(socketId: string, userId: string, router: types.Router) { constructor(socketId: string, username: string, router: types.Router) {
super() super()
this.socketId = socketId this.socketId = socketId
this.userId = userId this.username = username
this.#router = router this.#router = router
} }
@@ -278,7 +278,7 @@ export class Client extends EventEmitter<ClientEvents> {
serialize(): SerializedClient { serialize(): SerializedClient {
return { return {
socketId: this.socketId, socketId: this.socketId,
userId: this.userId, username: this.username,
channelId: this.channelId, channelId: this.channelId,
inputMuted: this.#inputMuted, inputMuted: this.#inputMuted,
outputMuted: this.#outputMuted, outputMuted: this.#outputMuted,

View File

@@ -23,7 +23,7 @@ export default async function (fastify: FastifyInstance) {
io.on('connection', async (socket) => { io.on('connection', async (socket) => {
consola.info('[WebRtc]', 'Client connected', socket.id) consola.info('[WebRtc]', 'Client connected', socket.id)
const client = new Client(socket.id, socket.data.user.id, mediasoupRouter) const client = new Client(socket.id, socket.data.user.username, mediasoupRouter)
defaultChannel.addClient(client) defaultChannel.addClient(client)
socket.join(defaultChannel.id) socket.join(defaultChannel.id)

View File

@@ -1,3 +1,4 @@
/* !!! 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
@@ -7,7 +8,7 @@
* 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.
*/ */

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,4 @@
/* !!! 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
@@ -7,7 +8,7 @@
* *
* 🛑 Under no circumstances should you import this file directly! 🛑 * 🛑 Under no circumstances should you import this file directly! 🛑
* *
* All exports from this file are wrapped under a `Prisma` namespace object in the Client.ts file. * All exports from this file are wrapped under a `Prisma` namespace object in the client.ts file.
* While this enables partial backward compatibility, it is not part of the stable public API. * While this enables partial backward compatibility, it is not part of the stable public API.
* *
* If you are looking for your Models, Enums, and Input Types, please import them from the respective * If you are looking for your Models, Enums, and Input Types, please import them from the respective
@@ -964,7 +965,6 @@ export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof
export const UserScalarFieldEnum = { export const UserScalarFieldEnum = {
id: 'id',
username: 'username', username: 'username',
password: 'password', password: 'password',
displayName: 'displayName', displayName: 'displayName',
@@ -985,7 +985,7 @@ export type SessionScalarFieldEnum = (typeof SessionScalarFieldEnum)[keyof typeo
export const UserPreferencesScalarFieldEnum = { export const UserPreferencesScalarFieldEnum = {
userId: 'userId', username: 'username',
toggleInputHotkey: 'toggleInputHotkey', toggleInputHotkey: 'toggleInputHotkey',
toggleOutputHotkey: 'toggleOutputHotkey' toggleOutputHotkey: 'toggleOutputHotkey'
} as const } as const
@@ -995,6 +995,7 @@ export type UserPreferencesScalarFieldEnum = (typeof UserPreferencesScalarFieldE
export const AttachmentScalarFieldEnum = { export const AttachmentScalarFieldEnum = {
id: 'id', id: 'id',
username: 'username',
name: 'name', name: 'name',
mimetype: 'mimetype', mimetype: 'mimetype',
size: 'size', size: 'size',
@@ -1007,7 +1008,7 @@ export type AttachmentScalarFieldEnum = (typeof AttachmentScalarFieldEnum)[keyof
export const MessageScalarFieldEnum = { export const MessageScalarFieldEnum = {
id: 'id', id: 'id',
text: 'text', text: 'text',
senderId: 'senderId', senderUsername: 'senderUsername',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const
@@ -1025,7 +1026,7 @@ export type MessageAttachmentScalarFieldEnum = (typeof MessageAttachmentScalarFi
export const ChannelScalarFieldEnum = { export const ChannelScalarFieldEnum = {
id: 'id', id: 'id',
ownerId: 'ownerId', ownerUsername: 'ownerUsername',
name: 'name', name: 'name',
persistent: 'persistent' persistent: 'persistent'
} as const } as const

View File

@@ -74,7 +74,6 @@ export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof
export const UserScalarFieldEnum = { export const UserScalarFieldEnum = {
id: 'id',
username: 'username', username: 'username',
password: 'password', password: 'password',
displayName: 'displayName', displayName: 'displayName',
@@ -95,7 +94,7 @@ export type SessionScalarFieldEnum = (typeof SessionScalarFieldEnum)[keyof typeo
export const UserPreferencesScalarFieldEnum = { export const UserPreferencesScalarFieldEnum = {
userId: 'userId', username: 'username',
toggleInputHotkey: 'toggleInputHotkey', toggleInputHotkey: 'toggleInputHotkey',
toggleOutputHotkey: 'toggleOutputHotkey' toggleOutputHotkey: 'toggleOutputHotkey'
} as const } as const
@@ -105,6 +104,7 @@ export type UserPreferencesScalarFieldEnum = (typeof UserPreferencesScalarFieldE
export const AttachmentScalarFieldEnum = { export const AttachmentScalarFieldEnum = {
id: 'id', id: 'id',
username: 'username',
name: 'name', name: 'name',
mimetype: 'mimetype', mimetype: 'mimetype',
size: 'size', size: 'size',
@@ -117,7 +117,7 @@ export type AttachmentScalarFieldEnum = (typeof AttachmentScalarFieldEnum)[keyof
export const MessageScalarFieldEnum = { export const MessageScalarFieldEnum = {
id: 'id', id: 'id',
text: 'text', text: 'text',
senderId: 'senderId', senderUsername: 'senderUsername',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const } as const
@@ -135,7 +135,7 @@ export type MessageAttachmentScalarFieldEnum = (typeof MessageAttachmentScalarFi
export const ChannelScalarFieldEnum = { export const ChannelScalarFieldEnum = {
id: 'id', id: 'id',
ownerId: 'ownerId', ownerUsername: 'ownerUsername',
name: 'name', name: 'name',
persistent: 'persistent' persistent: 'persistent'
} as const } as const

View File

@@ -36,6 +36,7 @@ export type AttachmentSumAggregateOutputType = {
export type AttachmentMinAggregateOutputType = { export type AttachmentMinAggregateOutputType = {
id: string | null id: string | null
username: string | null
name: string | null name: string | null
mimetype: string | null mimetype: string | null
size: number | null size: number | null
@@ -44,6 +45,7 @@ export type AttachmentMinAggregateOutputType = {
export type AttachmentMaxAggregateOutputType = { export type AttachmentMaxAggregateOutputType = {
id: string | null id: string | null
username: string | null
name: string | null name: string | null
mimetype: string | null mimetype: string | null
size: number | null size: number | null
@@ -52,6 +54,7 @@ export type AttachmentMaxAggregateOutputType = {
export type AttachmentCountAggregateOutputType = { export type AttachmentCountAggregateOutputType = {
id: number id: number
username: number
name: number name: number
mimetype: number mimetype: number
size: number size: number
@@ -70,6 +73,7 @@ export type AttachmentSumAggregateInputType = {
export type AttachmentMinAggregateInputType = { export type AttachmentMinAggregateInputType = {
id?: true id?: true
username?: true
name?: true name?: true
mimetype?: true mimetype?: true
size?: true size?: true
@@ -78,6 +82,7 @@ export type AttachmentMinAggregateInputType = {
export type AttachmentMaxAggregateInputType = { export type AttachmentMaxAggregateInputType = {
id?: true id?: true
username?: true
name?: true name?: true
mimetype?: true mimetype?: true
size?: true size?: true
@@ -86,6 +91,7 @@ export type AttachmentMaxAggregateInputType = {
export type AttachmentCountAggregateInputType = { export type AttachmentCountAggregateInputType = {
id?: true id?: true
username?: true
name?: true name?: true
mimetype?: true mimetype?: true
size?: true size?: true
@@ -181,6 +187,7 @@ export type AttachmentGroupByArgs<ExtArgs extends runtime.Types.Extensions.Inter
export type AttachmentGroupByOutputType = { export type AttachmentGroupByOutputType = {
id: string id: string
username: string | null
name: string name: string
mimetype: string mimetype: string
size: number size: number
@@ -212,19 +219,23 @@ export type AttachmentWhereInput = {
OR?: Prisma.AttachmentWhereInput[] OR?: Prisma.AttachmentWhereInput[]
NOT?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[] NOT?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[]
id?: Prisma.StringFilter<"Attachment"> | string id?: Prisma.StringFilter<"Attachment"> | string
username?: Prisma.StringNullableFilter<"Attachment"> | string | null
name?: Prisma.StringFilter<"Attachment"> | string name?: Prisma.StringFilter<"Attachment"> | string
mimetype?: Prisma.StringFilter<"Attachment"> | string mimetype?: Prisma.StringFilter<"Attachment"> | string
size?: Prisma.IntFilter<"Attachment"> | number size?: Prisma.IntFilter<"Attachment"> | number
createdAt?: Prisma.DateTimeFilter<"Attachment"> | Date | string createdAt?: Prisma.DateTimeFilter<"Attachment"> | Date | string
user?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
message?: Prisma.MessageAttachmentListRelationFilter message?: Prisma.MessageAttachmentListRelationFilter
} }
export type AttachmentOrderByWithRelationInput = { export type AttachmentOrderByWithRelationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
username?: Prisma.SortOrderInput | Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
mimetype?: Prisma.SortOrder mimetype?: Prisma.SortOrder
size?: Prisma.SortOrder size?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
user?: Prisma.UserOrderByWithRelationInput
message?: Prisma.MessageAttachmentOrderByRelationAggregateInput message?: Prisma.MessageAttachmentOrderByRelationAggregateInput
} }
@@ -233,15 +244,18 @@ export type AttachmentWhereUniqueInput = Prisma.AtLeast<{
AND?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[] AND?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[]
OR?: Prisma.AttachmentWhereInput[] OR?: Prisma.AttachmentWhereInput[]
NOT?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[] NOT?: Prisma.AttachmentWhereInput | Prisma.AttachmentWhereInput[]
username?: Prisma.StringNullableFilter<"Attachment"> | string | null
name?: Prisma.StringFilter<"Attachment"> | string name?: Prisma.StringFilter<"Attachment"> | string
mimetype?: Prisma.StringFilter<"Attachment"> | string mimetype?: Prisma.StringFilter<"Attachment"> | string
size?: Prisma.IntFilter<"Attachment"> | number size?: Prisma.IntFilter<"Attachment"> | number
createdAt?: Prisma.DateTimeFilter<"Attachment"> | Date | string createdAt?: Prisma.DateTimeFilter<"Attachment"> | Date | string
user?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
message?: Prisma.MessageAttachmentListRelationFilter message?: Prisma.MessageAttachmentListRelationFilter
}, "id"> }, "id">
export type AttachmentOrderByWithAggregationInput = { export type AttachmentOrderByWithAggregationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
username?: Prisma.SortOrderInput | Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
mimetype?: Prisma.SortOrder mimetype?: Prisma.SortOrder
size?: Prisma.SortOrder size?: Prisma.SortOrder
@@ -258,6 +272,7 @@ export type AttachmentScalarWhereWithAggregatesInput = {
OR?: Prisma.AttachmentScalarWhereWithAggregatesInput[] OR?: Prisma.AttachmentScalarWhereWithAggregatesInput[]
NOT?: Prisma.AttachmentScalarWhereWithAggregatesInput | Prisma.AttachmentScalarWhereWithAggregatesInput[] NOT?: Prisma.AttachmentScalarWhereWithAggregatesInput | Prisma.AttachmentScalarWhereWithAggregatesInput[]
id?: Prisma.StringWithAggregatesFilter<"Attachment"> | string id?: Prisma.StringWithAggregatesFilter<"Attachment"> | string
username?: Prisma.StringNullableWithAggregatesFilter<"Attachment"> | string | null
name?: Prisma.StringWithAggregatesFilter<"Attachment"> | string name?: Prisma.StringWithAggregatesFilter<"Attachment"> | string
mimetype?: Prisma.StringWithAggregatesFilter<"Attachment"> | string mimetype?: Prisma.StringWithAggregatesFilter<"Attachment"> | string
size?: Prisma.IntWithAggregatesFilter<"Attachment"> | number size?: Prisma.IntWithAggregatesFilter<"Attachment"> | number
@@ -270,11 +285,13 @@ export type AttachmentCreateInput = {
mimetype: string mimetype: string
size: number size: number
createdAt?: Date | string createdAt?: Date | string
user?: Prisma.UserCreateNestedOneWithoutAttachmentsInput
message?: Prisma.MessageAttachmentCreateNestedManyWithoutAttachmentInput message?: Prisma.MessageAttachmentCreateNestedManyWithoutAttachmentInput
} }
export type AttachmentUncheckedCreateInput = { export type AttachmentUncheckedCreateInput = {
id?: string id?: string
username?: string | null
name: string name: string
mimetype: string mimetype: string
size: number size: number
@@ -288,11 +305,13 @@ export type AttachmentUpdateInput = {
mimetype?: Prisma.StringFieldUpdateOperationsInput | string mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
user?: Prisma.UserUpdateOneWithoutAttachmentsNestedInput
message?: Prisma.MessageAttachmentUpdateManyWithoutAttachmentNestedInput message?: Prisma.MessageAttachmentUpdateManyWithoutAttachmentNestedInput
} }
export type AttachmentUncheckedUpdateInput = { export type AttachmentUncheckedUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number size?: Prisma.IntFieldUpdateOperationsInput | number
@@ -302,6 +321,7 @@ export type AttachmentUncheckedUpdateInput = {
export type AttachmentCreateManyInput = { export type AttachmentCreateManyInput = {
id?: string id?: string
username?: string | null
name: string name: string
mimetype: string mimetype: string
size: number size: number
@@ -318,14 +338,26 @@ export type AttachmentUpdateManyMutationInput = {
export type AttachmentUncheckedUpdateManyInput = { export type AttachmentUncheckedUpdateManyInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
export type AttachmentListRelationFilter = {
every?: Prisma.AttachmentWhereInput
some?: Prisma.AttachmentWhereInput
none?: Prisma.AttachmentWhereInput
}
export type AttachmentOrderByRelationAggregateInput = {
_count?: Prisma.SortOrder
}
export type AttachmentCountOrderByAggregateInput = { export type AttachmentCountOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
username?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
mimetype?: Prisma.SortOrder mimetype?: Prisma.SortOrder
size?: Prisma.SortOrder size?: Prisma.SortOrder
@@ -338,6 +370,7 @@ export type AttachmentAvgOrderByAggregateInput = {
export type AttachmentMaxOrderByAggregateInput = { export type AttachmentMaxOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
username?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
mimetype?: Prisma.SortOrder mimetype?: Prisma.SortOrder
size?: Prisma.SortOrder size?: Prisma.SortOrder
@@ -346,6 +379,7 @@ export type AttachmentMaxOrderByAggregateInput = {
export type AttachmentMinOrderByAggregateInput = { export type AttachmentMinOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
username?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
mimetype?: Prisma.SortOrder mimetype?: Prisma.SortOrder
size?: Prisma.SortOrder size?: Prisma.SortOrder
@@ -361,6 +395,48 @@ export type AttachmentScalarRelationFilter = {
isNot?: Prisma.AttachmentWhereInput isNot?: Prisma.AttachmentWhereInput
} }
export type AttachmentCreateNestedManyWithoutUserInput = {
create?: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput> | Prisma.AttachmentCreateWithoutUserInput[] | Prisma.AttachmentUncheckedCreateWithoutUserInput[]
connectOrCreate?: Prisma.AttachmentCreateOrConnectWithoutUserInput | Prisma.AttachmentCreateOrConnectWithoutUserInput[]
createMany?: Prisma.AttachmentCreateManyUserInputEnvelope
connect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
}
export type AttachmentUncheckedCreateNestedManyWithoutUserInput = {
create?: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput> | Prisma.AttachmentCreateWithoutUserInput[] | Prisma.AttachmentUncheckedCreateWithoutUserInput[]
connectOrCreate?: Prisma.AttachmentCreateOrConnectWithoutUserInput | Prisma.AttachmentCreateOrConnectWithoutUserInput[]
createMany?: Prisma.AttachmentCreateManyUserInputEnvelope
connect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
}
export type AttachmentUpdateManyWithoutUserNestedInput = {
create?: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput> | Prisma.AttachmentCreateWithoutUserInput[] | Prisma.AttachmentUncheckedCreateWithoutUserInput[]
connectOrCreate?: Prisma.AttachmentCreateOrConnectWithoutUserInput | Prisma.AttachmentCreateOrConnectWithoutUserInput[]
upsert?: Prisma.AttachmentUpsertWithWhereUniqueWithoutUserInput | Prisma.AttachmentUpsertWithWhereUniqueWithoutUserInput[]
createMany?: Prisma.AttachmentCreateManyUserInputEnvelope
set?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
disconnect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
delete?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
connect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
update?: Prisma.AttachmentUpdateWithWhereUniqueWithoutUserInput | Prisma.AttachmentUpdateWithWhereUniqueWithoutUserInput[]
updateMany?: Prisma.AttachmentUpdateManyWithWhereWithoutUserInput | Prisma.AttachmentUpdateManyWithWhereWithoutUserInput[]
deleteMany?: Prisma.AttachmentScalarWhereInput | Prisma.AttachmentScalarWhereInput[]
}
export type AttachmentUncheckedUpdateManyWithoutUserNestedInput = {
create?: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput> | Prisma.AttachmentCreateWithoutUserInput[] | Prisma.AttachmentUncheckedCreateWithoutUserInput[]
connectOrCreate?: Prisma.AttachmentCreateOrConnectWithoutUserInput | Prisma.AttachmentCreateOrConnectWithoutUserInput[]
upsert?: Prisma.AttachmentUpsertWithWhereUniqueWithoutUserInput | Prisma.AttachmentUpsertWithWhereUniqueWithoutUserInput[]
createMany?: Prisma.AttachmentCreateManyUserInputEnvelope
set?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
disconnect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
delete?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
connect?: Prisma.AttachmentWhereUniqueInput | Prisma.AttachmentWhereUniqueInput[]
update?: Prisma.AttachmentUpdateWithWhereUniqueWithoutUserInput | Prisma.AttachmentUpdateWithWhereUniqueWithoutUserInput[]
updateMany?: Prisma.AttachmentUpdateManyWithWhereWithoutUserInput | Prisma.AttachmentUpdateManyWithWhereWithoutUserInput[]
deleteMany?: Prisma.AttachmentScalarWhereInput | Prisma.AttachmentScalarWhereInput[]
}
export type IntFieldUpdateOperationsInput = { export type IntFieldUpdateOperationsInput = {
set?: number set?: number
increment?: number increment?: number
@@ -383,16 +459,73 @@ export type AttachmentUpdateOneRequiredWithoutMessageNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.AttachmentUpdateToOneWithWhereWithoutMessageInput, Prisma.AttachmentUpdateWithoutMessageInput>, Prisma.AttachmentUncheckedUpdateWithoutMessageInput> update?: Prisma.XOR<Prisma.XOR<Prisma.AttachmentUpdateToOneWithWhereWithoutMessageInput, Prisma.AttachmentUpdateWithoutMessageInput>, Prisma.AttachmentUncheckedUpdateWithoutMessageInput>
} }
export type AttachmentCreateWithoutUserInput = {
id?: string
name: string
mimetype: string
size: number
createdAt?: Date | string
message?: Prisma.MessageAttachmentCreateNestedManyWithoutAttachmentInput
}
export type AttachmentUncheckedCreateWithoutUserInput = {
id?: string
name: string
mimetype: string
size: number
createdAt?: Date | string
message?: Prisma.MessageAttachmentUncheckedCreateNestedManyWithoutAttachmentInput
}
export type AttachmentCreateOrConnectWithoutUserInput = {
where: Prisma.AttachmentWhereUniqueInput
create: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput>
}
export type AttachmentCreateManyUserInputEnvelope = {
data: Prisma.AttachmentCreateManyUserInput | Prisma.AttachmentCreateManyUserInput[]
}
export type AttachmentUpsertWithWhereUniqueWithoutUserInput = {
where: Prisma.AttachmentWhereUniqueInput
update: Prisma.XOR<Prisma.AttachmentUpdateWithoutUserInput, Prisma.AttachmentUncheckedUpdateWithoutUserInput>
create: Prisma.XOR<Prisma.AttachmentCreateWithoutUserInput, Prisma.AttachmentUncheckedCreateWithoutUserInput>
}
export type AttachmentUpdateWithWhereUniqueWithoutUserInput = {
where: Prisma.AttachmentWhereUniqueInput
data: Prisma.XOR<Prisma.AttachmentUpdateWithoutUserInput, Prisma.AttachmentUncheckedUpdateWithoutUserInput>
}
export type AttachmentUpdateManyWithWhereWithoutUserInput = {
where: Prisma.AttachmentScalarWhereInput
data: Prisma.XOR<Prisma.AttachmentUpdateManyMutationInput, Prisma.AttachmentUncheckedUpdateManyWithoutUserInput>
}
export type AttachmentScalarWhereInput = {
AND?: Prisma.AttachmentScalarWhereInput | Prisma.AttachmentScalarWhereInput[]
OR?: Prisma.AttachmentScalarWhereInput[]
NOT?: Prisma.AttachmentScalarWhereInput | Prisma.AttachmentScalarWhereInput[]
id?: Prisma.StringFilter<"Attachment"> | string
username?: Prisma.StringNullableFilter<"Attachment"> | string | null
name?: Prisma.StringFilter<"Attachment"> | string
mimetype?: Prisma.StringFilter<"Attachment"> | string
size?: Prisma.IntFilter<"Attachment"> | number
createdAt?: Prisma.DateTimeFilter<"Attachment"> | Date | string
}
export type AttachmentCreateWithoutMessageInput = { export type AttachmentCreateWithoutMessageInput = {
id?: string id?: string
name: string name: string
mimetype: string mimetype: string
size: number size: number
createdAt?: Date | string createdAt?: Date | string
user?: Prisma.UserCreateNestedOneWithoutAttachmentsInput
} }
export type AttachmentUncheckedCreateWithoutMessageInput = { export type AttachmentUncheckedCreateWithoutMessageInput = {
id?: string id?: string
username?: string | null
name: string name: string
mimetype: string mimetype: string
size: number size: number
@@ -421,9 +554,45 @@ export type AttachmentUpdateWithoutMessageInput = {
mimetype?: Prisma.StringFieldUpdateOperationsInput | string mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
user?: Prisma.UserUpdateOneWithoutAttachmentsNestedInput
} }
export type AttachmentUncheckedUpdateWithoutMessageInput = { export type AttachmentUncheckedUpdateWithoutMessageInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
}
export type AttachmentCreateManyUserInput = {
id?: string
name: string
mimetype: string
size: number
createdAt?: Date | string
}
export type AttachmentUpdateWithoutUserInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
message?: Prisma.MessageAttachmentUpdateManyWithoutAttachmentNestedInput
}
export type AttachmentUncheckedUpdateWithoutUserInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string
size?: Prisma.IntFieldUpdateOperationsInput | number
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
message?: Prisma.MessageAttachmentUncheckedUpdateManyWithoutAttachmentNestedInput
}
export type AttachmentUncheckedUpdateManyWithoutUserInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.StringFieldUpdateOperationsInput | string
mimetype?: Prisma.StringFieldUpdateOperationsInput | string mimetype?: Prisma.StringFieldUpdateOperationsInput | string
@@ -464,53 +633,67 @@ export type AttachmentCountOutputTypeCountMessageArgs<ExtArgs extends runtime.Ty
export type AttachmentSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type AttachmentSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
username?: boolean
name?: boolean name?: boolean
mimetype?: boolean mimetype?: boolean
size?: boolean size?: boolean
createdAt?: boolean createdAt?: boolean
user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
message?: boolean | Prisma.Attachment$messageArgs<ExtArgs> message?: boolean | Prisma.Attachment$messageArgs<ExtArgs>
_count?: boolean | Prisma.AttachmentCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.AttachmentCountOutputTypeDefaultArgs<ExtArgs>
}, ExtArgs["result"]["attachment"]> }, ExtArgs["result"]["attachment"]>
export type AttachmentSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type AttachmentSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
username?: boolean
name?: boolean name?: boolean
mimetype?: boolean mimetype?: boolean
size?: boolean size?: boolean
createdAt?: boolean createdAt?: boolean
user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
}, ExtArgs["result"]["attachment"]> }, ExtArgs["result"]["attachment"]>
export type AttachmentSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type AttachmentSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
username?: boolean
name?: boolean name?: boolean
mimetype?: boolean mimetype?: boolean
size?: boolean size?: boolean
createdAt?: boolean createdAt?: boolean
user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
}, ExtArgs["result"]["attachment"]> }, ExtArgs["result"]["attachment"]>
export type AttachmentSelectScalar = { export type AttachmentSelectScalar = {
id?: boolean id?: boolean
username?: boolean
name?: boolean name?: boolean
mimetype?: boolean mimetype?: boolean
size?: boolean size?: boolean
createdAt?: boolean createdAt?: boolean
} }
export type AttachmentOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "name" | "mimetype" | "size" | "createdAt", ExtArgs["result"]["attachment"]> export type AttachmentOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "username" | "name" | "mimetype" | "size" | "createdAt", ExtArgs["result"]["attachment"]>
export type AttachmentInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type AttachmentInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
message?: boolean | Prisma.Attachment$messageArgs<ExtArgs> message?: boolean | Prisma.Attachment$messageArgs<ExtArgs>
_count?: boolean | Prisma.AttachmentCountOutputTypeDefaultArgs<ExtArgs> _count?: boolean | Prisma.AttachmentCountOutputTypeDefaultArgs<ExtArgs>
} }
export type AttachmentIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {} export type AttachmentIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
export type AttachmentIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {} user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
}
export type AttachmentIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
user?: boolean | Prisma.Attachment$userArgs<ExtArgs>
}
export type $AttachmentPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type $AttachmentPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
name: "Attachment" name: "Attachment"
objects: { objects: {
user: Prisma.$UserPayload<ExtArgs> | null
message: Prisma.$MessageAttachmentPayload<ExtArgs>[] message: Prisma.$MessageAttachmentPayload<ExtArgs>[]
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
username: string | null
name: string name: string
mimetype: string mimetype: string
size: number size: number
@@ -909,6 +1092,7 @@ readonly fields: AttachmentFieldRefs;
*/ */
export interface Prisma__AttachmentClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> { export interface Prisma__AttachmentClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
readonly [Symbol.toStringTag]: "PrismaPromise" readonly [Symbol.toStringTag]: "PrismaPromise"
user<T extends Prisma.Attachment$userArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Attachment$userArgs<ExtArgs>>): Prisma.Prisma__UserClient<runtime.Types.Result.GetResult<Prisma.$UserPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
message<T extends Prisma.Attachment$messageArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Attachment$messageArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MessageAttachmentPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> message<T extends Prisma.Attachment$messageArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Attachment$messageArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MessageAttachmentPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/** /**
* Attaches callbacks for the resolution and/or rejection of the Promise. * Attaches callbacks for the resolution and/or rejection of the Promise.
@@ -940,6 +1124,7 @@ export interface Prisma__AttachmentClient<T, Null = never, ExtArgs extends runti
*/ */
export interface AttachmentFieldRefs { export interface AttachmentFieldRefs {
readonly id: Prisma.FieldRef<"Attachment", 'String'> readonly id: Prisma.FieldRef<"Attachment", 'String'>
readonly username: Prisma.FieldRef<"Attachment", 'String'>
readonly name: Prisma.FieldRef<"Attachment", 'String'> readonly name: Prisma.FieldRef<"Attachment", 'String'>
readonly mimetype: Prisma.FieldRef<"Attachment", 'String'> readonly mimetype: Prisma.FieldRef<"Attachment", 'String'>
readonly size: Prisma.FieldRef<"Attachment", 'Int'> readonly size: Prisma.FieldRef<"Attachment", 'Int'>
@@ -1196,6 +1381,10 @@ export type AttachmentCreateManyAndReturnArgs<ExtArgs extends runtime.Types.Exte
* The data used to create many Attachments. * The data used to create many Attachments.
*/ */
data: Prisma.AttachmentCreateManyInput | Prisma.AttachmentCreateManyInput[] data: Prisma.AttachmentCreateManyInput | Prisma.AttachmentCreateManyInput[]
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AttachmentIncludeCreateManyAndReturn<ExtArgs> | null
} }
/** /**
@@ -1266,6 +1455,10 @@ export type AttachmentUpdateManyAndReturnArgs<ExtArgs extends runtime.Types.Exte
* Limit how many Attachments to update. * Limit how many Attachments to update.
*/ */
limit?: number limit?: number
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AttachmentIncludeUpdateManyAndReturn<ExtArgs> | null
} }
/** /**
@@ -1334,6 +1527,25 @@ export type AttachmentDeleteManyArgs<ExtArgs extends runtime.Types.Extensions.In
limit?: number limit?: number
} }
/**
* Attachment.user
*/
export type Attachment$userArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the User
*/
select?: Prisma.UserSelect<ExtArgs> | null
/**
* Omit specific fields from the User
*/
omit?: Prisma.UserOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.UserInclude<ExtArgs> | null
where?: Prisma.UserWhereInput
}
/** /**
* Attachment.message * Attachment.message
*/ */

View File

@@ -26,21 +26,21 @@ export type AggregateChannel = {
export type ChannelMinAggregateOutputType = { export type ChannelMinAggregateOutputType = {
id: string | null id: string | null
ownerId: string | null ownerUsername: string | null
name: string | null name: string | null
persistent: boolean | null persistent: boolean | null
} }
export type ChannelMaxAggregateOutputType = { export type ChannelMaxAggregateOutputType = {
id: string | null id: string | null
ownerId: string | null ownerUsername: string | null
name: string | null name: string | null
persistent: boolean | null persistent: boolean | null
} }
export type ChannelCountAggregateOutputType = { export type ChannelCountAggregateOutputType = {
id: number id: number
ownerId: number ownerUsername: number
name: number name: number
persistent: number persistent: number
_all: number _all: number
@@ -49,21 +49,21 @@ export type ChannelCountAggregateOutputType = {
export type ChannelMinAggregateInputType = { export type ChannelMinAggregateInputType = {
id?: true id?: true
ownerId?: true ownerUsername?: true
name?: true name?: true
persistent?: true persistent?: true
} }
export type ChannelMaxAggregateInputType = { export type ChannelMaxAggregateInputType = {
id?: true id?: true
ownerId?: true ownerUsername?: true
name?: true name?: true
persistent?: true persistent?: true
} }
export type ChannelCountAggregateInputType = { export type ChannelCountAggregateInputType = {
id?: true id?: true
ownerId?: true ownerUsername?: true
name?: true name?: true
persistent?: true persistent?: true
_all?: true _all?: true
@@ -143,7 +143,7 @@ export type ChannelGroupByArgs<ExtArgs extends runtime.Types.Extensions.Internal
export type ChannelGroupByOutputType = { export type ChannelGroupByOutputType = {
id: string id: string
ownerId: string | null ownerUsername: string | null
name: string name: string
persistent: boolean persistent: boolean
_count: ChannelCountAggregateOutputType | null _count: ChannelCountAggregateOutputType | null
@@ -171,7 +171,7 @@ export type ChannelWhereInput = {
OR?: Prisma.ChannelWhereInput[] OR?: Prisma.ChannelWhereInput[]
NOT?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[] NOT?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[]
id?: Prisma.StringFilter<"Channel"> | string id?: Prisma.StringFilter<"Channel"> | string
ownerId?: Prisma.StringNullableFilter<"Channel"> | string | null ownerUsername?: Prisma.StringNullableFilter<"Channel"> | string | null
name?: Prisma.StringFilter<"Channel"> | string name?: Prisma.StringFilter<"Channel"> | string
persistent?: Prisma.BoolFilter<"Channel"> | boolean persistent?: Prisma.BoolFilter<"Channel"> | boolean
owner?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null owner?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
@@ -179,7 +179,7 @@ export type ChannelWhereInput = {
export type ChannelOrderByWithRelationInput = { export type ChannelOrderByWithRelationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
ownerId?: Prisma.SortOrderInput | Prisma.SortOrder ownerUsername?: Prisma.SortOrderInput | Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
persistent?: Prisma.SortOrder persistent?: Prisma.SortOrder
owner?: Prisma.UserOrderByWithRelationInput owner?: Prisma.UserOrderByWithRelationInput
@@ -190,7 +190,7 @@ export type ChannelWhereUniqueInput = Prisma.AtLeast<{
AND?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[] AND?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[]
OR?: Prisma.ChannelWhereInput[] OR?: Prisma.ChannelWhereInput[]
NOT?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[] NOT?: Prisma.ChannelWhereInput | Prisma.ChannelWhereInput[]
ownerId?: Prisma.StringNullableFilter<"Channel"> | string | null ownerUsername?: Prisma.StringNullableFilter<"Channel"> | string | null
name?: Prisma.StringFilter<"Channel"> | string name?: Prisma.StringFilter<"Channel"> | string
persistent?: Prisma.BoolFilter<"Channel"> | boolean persistent?: Prisma.BoolFilter<"Channel"> | boolean
owner?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null owner?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
@@ -198,7 +198,7 @@ export type ChannelWhereUniqueInput = Prisma.AtLeast<{
export type ChannelOrderByWithAggregationInput = { export type ChannelOrderByWithAggregationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
ownerId?: Prisma.SortOrderInput | Prisma.SortOrder ownerUsername?: Prisma.SortOrderInput | Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
persistent?: Prisma.SortOrder persistent?: Prisma.SortOrder
_count?: Prisma.ChannelCountOrderByAggregateInput _count?: Prisma.ChannelCountOrderByAggregateInput
@@ -211,7 +211,7 @@ export type ChannelScalarWhereWithAggregatesInput = {
OR?: Prisma.ChannelScalarWhereWithAggregatesInput[] OR?: Prisma.ChannelScalarWhereWithAggregatesInput[]
NOT?: Prisma.ChannelScalarWhereWithAggregatesInput | Prisma.ChannelScalarWhereWithAggregatesInput[] NOT?: Prisma.ChannelScalarWhereWithAggregatesInput | Prisma.ChannelScalarWhereWithAggregatesInput[]
id?: Prisma.StringWithAggregatesFilter<"Channel"> | string id?: Prisma.StringWithAggregatesFilter<"Channel"> | string
ownerId?: Prisma.StringNullableWithAggregatesFilter<"Channel"> | string | null ownerUsername?: Prisma.StringNullableWithAggregatesFilter<"Channel"> | string | null
name?: Prisma.StringWithAggregatesFilter<"Channel"> | string name?: Prisma.StringWithAggregatesFilter<"Channel"> | string
persistent?: Prisma.BoolWithAggregatesFilter<"Channel"> | boolean persistent?: Prisma.BoolWithAggregatesFilter<"Channel"> | boolean
} }
@@ -225,7 +225,7 @@ export type ChannelCreateInput = {
export type ChannelUncheckedCreateInput = { export type ChannelUncheckedCreateInput = {
id?: string id?: string
ownerId?: string | null ownerUsername?: string | null
name: string name: string
persistent: boolean persistent: boolean
} }
@@ -239,14 +239,14 @@ export type ChannelUpdateInput = {
export type ChannelUncheckedUpdateInput = { export type ChannelUncheckedUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
ownerId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null ownerUsername?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.StringFieldUpdateOperationsInput | string
persistent?: Prisma.BoolFieldUpdateOperationsInput | boolean persistent?: Prisma.BoolFieldUpdateOperationsInput | boolean
} }
export type ChannelCreateManyInput = { export type ChannelCreateManyInput = {
id?: string id?: string
ownerId?: string | null ownerUsername?: string | null
name: string name: string
persistent: boolean persistent: boolean
} }
@@ -259,7 +259,7 @@ export type ChannelUpdateManyMutationInput = {
export type ChannelUncheckedUpdateManyInput = { export type ChannelUncheckedUpdateManyInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
ownerId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null ownerUsername?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.StringFieldUpdateOperationsInput | string
persistent?: Prisma.BoolFieldUpdateOperationsInput | boolean persistent?: Prisma.BoolFieldUpdateOperationsInput | boolean
} }
@@ -276,21 +276,21 @@ export type ChannelOrderByRelationAggregateInput = {
export type ChannelCountOrderByAggregateInput = { export type ChannelCountOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
ownerId?: Prisma.SortOrder ownerUsername?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
persistent?: Prisma.SortOrder persistent?: Prisma.SortOrder
} }
export type ChannelMaxOrderByAggregateInput = { export type ChannelMaxOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
ownerId?: Prisma.SortOrder ownerUsername?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
persistent?: Prisma.SortOrder persistent?: Prisma.SortOrder
} }
export type ChannelMinOrderByAggregateInput = { export type ChannelMinOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
ownerId?: Prisma.SortOrder ownerUsername?: Prisma.SortOrder
name?: Prisma.SortOrder name?: Prisma.SortOrder
persistent?: Prisma.SortOrder persistent?: Prisma.SortOrder
} }
@@ -383,7 +383,7 @@ export type ChannelScalarWhereInput = {
OR?: Prisma.ChannelScalarWhereInput[] OR?: Prisma.ChannelScalarWhereInput[]
NOT?: Prisma.ChannelScalarWhereInput | Prisma.ChannelScalarWhereInput[] NOT?: Prisma.ChannelScalarWhereInput | Prisma.ChannelScalarWhereInput[]
id?: Prisma.StringFilter<"Channel"> | string id?: Prisma.StringFilter<"Channel"> | string
ownerId?: Prisma.StringNullableFilter<"Channel"> | string | null ownerUsername?: Prisma.StringNullableFilter<"Channel"> | string | null
name?: Prisma.StringFilter<"Channel"> | string name?: Prisma.StringFilter<"Channel"> | string
persistent?: Prisma.BoolFilter<"Channel"> | boolean persistent?: Prisma.BoolFilter<"Channel"> | boolean
} }
@@ -416,7 +416,7 @@ export type ChannelUncheckedUpdateManyWithoutOwnerInput = {
export type ChannelSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type ChannelSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
ownerId?: boolean ownerUsername?: boolean
name?: boolean name?: boolean
persistent?: boolean persistent?: boolean
owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs> owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs>
@@ -424,7 +424,7 @@ export type ChannelSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs
export type ChannelSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type ChannelSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
ownerId?: boolean ownerUsername?: boolean
name?: boolean name?: boolean
persistent?: boolean persistent?: boolean
owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs> owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs>
@@ -432,7 +432,7 @@ export type ChannelSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Exten
export type ChannelSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type ChannelSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
ownerId?: boolean ownerUsername?: boolean
name?: boolean name?: boolean
persistent?: boolean persistent?: boolean
owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs> owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs>
@@ -440,12 +440,12 @@ export type ChannelSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Exten
export type ChannelSelectScalar = { export type ChannelSelectScalar = {
id?: boolean id?: boolean
ownerId?: boolean ownerUsername?: boolean
name?: boolean name?: boolean
persistent?: boolean persistent?: boolean
} }
export type ChannelOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "ownerId" | "name" | "persistent", ExtArgs["result"]["channel"]> export type ChannelOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "ownerUsername" | "name" | "persistent", ExtArgs["result"]["channel"]>
export type ChannelInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type ChannelInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs> owner?: boolean | Prisma.Channel$ownerArgs<ExtArgs>
} }
@@ -463,7 +463,7 @@ export type $ChannelPayload<ExtArgs extends runtime.Types.Extensions.InternalArg
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
ownerId: string | null ownerUsername: string | null
name: string name: string
persistent: boolean persistent: boolean
}, ExtArgs["result"]["channel"]> }, ExtArgs["result"]["channel"]>
@@ -891,7 +891,7 @@ export interface Prisma__ChannelClient<T, Null = never, ExtArgs extends runtime.
*/ */
export interface ChannelFieldRefs { export interface ChannelFieldRefs {
readonly id: Prisma.FieldRef<"Channel", 'String'> readonly id: Prisma.FieldRef<"Channel", 'String'>
readonly ownerId: Prisma.FieldRef<"Channel", 'String'> readonly ownerUsername: Prisma.FieldRef<"Channel", 'String'>
readonly name: Prisma.FieldRef<"Channel", 'String'> readonly name: Prisma.FieldRef<"Channel", 'String'>
readonly persistent: Prisma.FieldRef<"Channel", 'Boolean'> readonly persistent: Prisma.FieldRef<"Channel", 'Boolean'>
} }

View File

@@ -27,7 +27,7 @@ export type AggregateMessage = {
export type MessageMinAggregateOutputType = { export type MessageMinAggregateOutputType = {
id: string | null id: string | null
text: string | null text: string | null
senderId: string | null senderUsername: string | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -35,7 +35,7 @@ export type MessageMinAggregateOutputType = {
export type MessageMaxAggregateOutputType = { export type MessageMaxAggregateOutputType = {
id: string | null id: string | null
text: string | null text: string | null
senderId: string | null senderUsername: string | null
createdAt: Date | null createdAt: Date | null
updatedAt: Date | null updatedAt: Date | null
} }
@@ -43,7 +43,7 @@ export type MessageMaxAggregateOutputType = {
export type MessageCountAggregateOutputType = { export type MessageCountAggregateOutputType = {
id: number id: number
text: number text: number
senderId: number senderUsername: number
createdAt: number createdAt: number
updatedAt: number updatedAt: number
_all: number _all: number
@@ -53,7 +53,7 @@ export type MessageCountAggregateOutputType = {
export type MessageMinAggregateInputType = { export type MessageMinAggregateInputType = {
id?: true id?: true
text?: true text?: true
senderId?: true senderUsername?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -61,7 +61,7 @@ export type MessageMinAggregateInputType = {
export type MessageMaxAggregateInputType = { export type MessageMaxAggregateInputType = {
id?: true id?: true
text?: true text?: true
senderId?: true senderUsername?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
} }
@@ -69,7 +69,7 @@ export type MessageMaxAggregateInputType = {
export type MessageCountAggregateInputType = { export type MessageCountAggregateInputType = {
id?: true id?: true
text?: true text?: true
senderId?: true senderUsername?: true
createdAt?: true createdAt?: true
updatedAt?: true updatedAt?: true
_all?: true _all?: true
@@ -150,7 +150,7 @@ export type MessageGroupByArgs<ExtArgs extends runtime.Types.Extensions.Internal
export type MessageGroupByOutputType = { export type MessageGroupByOutputType = {
id: string id: string
text: string text: string
senderId: string | null senderUsername: string | null
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
_count: MessageCountAggregateOutputType | null _count: MessageCountAggregateOutputType | null
@@ -179,7 +179,7 @@ export type MessageWhereInput = {
NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[]
id?: Prisma.StringFilter<"Message"> | string id?: Prisma.StringFilter<"Message"> | string
text?: Prisma.StringFilter<"Message"> | string text?: Prisma.StringFilter<"Message"> | string
senderId?: Prisma.StringNullableFilter<"Message"> | string | null senderUsername?: Prisma.StringNullableFilter<"Message"> | string | null
createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string
sender?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null sender?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
@@ -189,7 +189,7 @@ export type MessageWhereInput = {
export type MessageOrderByWithRelationInput = { export type MessageOrderByWithRelationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
text?: Prisma.SortOrder text?: Prisma.SortOrder
senderId?: Prisma.SortOrderInput | Prisma.SortOrder senderUsername?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
sender?: Prisma.UserOrderByWithRelationInput sender?: Prisma.UserOrderByWithRelationInput
@@ -202,7 +202,7 @@ export type MessageWhereUniqueInput = Prisma.AtLeast<{
OR?: Prisma.MessageWhereInput[] OR?: Prisma.MessageWhereInput[]
NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[]
text?: Prisma.StringFilter<"Message"> | string text?: Prisma.StringFilter<"Message"> | string
senderId?: Prisma.StringNullableFilter<"Message"> | string | null senderUsername?: Prisma.StringNullableFilter<"Message"> | string | null
createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string
sender?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null sender?: Prisma.XOR<Prisma.UserNullableScalarRelationFilter, Prisma.UserWhereInput> | null
@@ -212,7 +212,7 @@ export type MessageWhereUniqueInput = Prisma.AtLeast<{
export type MessageOrderByWithAggregationInput = { export type MessageOrderByWithAggregationInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
text?: Prisma.SortOrder text?: Prisma.SortOrder
senderId?: Prisma.SortOrderInput | Prisma.SortOrder senderUsername?: Prisma.SortOrderInput | Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
_count?: Prisma.MessageCountOrderByAggregateInput _count?: Prisma.MessageCountOrderByAggregateInput
@@ -226,7 +226,7 @@ export type MessageScalarWhereWithAggregatesInput = {
NOT?: Prisma.MessageScalarWhereWithAggregatesInput | Prisma.MessageScalarWhereWithAggregatesInput[] NOT?: Prisma.MessageScalarWhereWithAggregatesInput | Prisma.MessageScalarWhereWithAggregatesInput[]
id?: Prisma.StringWithAggregatesFilter<"Message"> | string id?: Prisma.StringWithAggregatesFilter<"Message"> | string
text?: Prisma.StringWithAggregatesFilter<"Message"> | string text?: Prisma.StringWithAggregatesFilter<"Message"> | string
senderId?: Prisma.StringNullableWithAggregatesFilter<"Message"> | string | null senderUsername?: Prisma.StringNullableWithAggregatesFilter<"Message"> | string | null
createdAt?: Prisma.DateTimeWithAggregatesFilter<"Message"> | Date | string createdAt?: Prisma.DateTimeWithAggregatesFilter<"Message"> | Date | string
updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Message"> | Date | string updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Message"> | Date | string
} }
@@ -243,7 +243,7 @@ export type MessageCreateInput = {
export type MessageUncheckedCreateInput = { export type MessageUncheckedCreateInput = {
id?: string id?: string
text: string text: string
senderId?: string | null senderUsername?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
attachments?: Prisma.MessageAttachmentUncheckedCreateNestedManyWithoutMessageInput attachments?: Prisma.MessageAttachmentUncheckedCreateNestedManyWithoutMessageInput
@@ -261,7 +261,7 @@ export type MessageUpdateInput = {
export type MessageUncheckedUpdateInput = { export type MessageUncheckedUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
text?: Prisma.StringFieldUpdateOperationsInput | string text?: Prisma.StringFieldUpdateOperationsInput | string
senderId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null senderUsername?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
attachments?: Prisma.MessageAttachmentUncheckedUpdateManyWithoutMessageNestedInput attachments?: Prisma.MessageAttachmentUncheckedUpdateManyWithoutMessageNestedInput
@@ -270,7 +270,7 @@ export type MessageUncheckedUpdateInput = {
export type MessageCreateManyInput = { export type MessageCreateManyInput = {
id?: string id?: string
text: string text: string
senderId?: string | null senderUsername?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -285,7 +285,7 @@ export type MessageUpdateManyMutationInput = {
export type MessageUncheckedUpdateManyInput = { export type MessageUncheckedUpdateManyInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
text?: Prisma.StringFieldUpdateOperationsInput | string text?: Prisma.StringFieldUpdateOperationsInput | string
senderId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null senderUsername?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -303,7 +303,7 @@ export type MessageOrderByRelationAggregateInput = {
export type MessageCountOrderByAggregateInput = { export type MessageCountOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
text?: Prisma.SortOrder text?: Prisma.SortOrder
senderId?: Prisma.SortOrder senderUsername?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -311,7 +311,7 @@ export type MessageCountOrderByAggregateInput = {
export type MessageMaxOrderByAggregateInput = { export type MessageMaxOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
text?: Prisma.SortOrder text?: Prisma.SortOrder
senderId?: Prisma.SortOrder senderUsername?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -319,7 +319,7 @@ export type MessageMaxOrderByAggregateInput = {
export type MessageMinOrderByAggregateInput = { export type MessageMinOrderByAggregateInput = {
id?: Prisma.SortOrder id?: Prisma.SortOrder
text?: Prisma.SortOrder text?: Prisma.SortOrder
senderId?: Prisma.SortOrder senderUsername?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
} }
@@ -432,7 +432,7 @@ export type MessageScalarWhereInput = {
NOT?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[] NOT?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[]
id?: Prisma.StringFilter<"Message"> | string id?: Prisma.StringFilter<"Message"> | string
text?: Prisma.StringFilter<"Message"> | string text?: Prisma.StringFilter<"Message"> | string
senderId?: Prisma.StringNullableFilter<"Message"> | string | null senderUsername?: Prisma.StringNullableFilter<"Message"> | string | null
createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Message"> | Date | string
} }
@@ -448,7 +448,7 @@ export type MessageCreateWithoutAttachmentsInput = {
export type MessageUncheckedCreateWithoutAttachmentsInput = { export type MessageUncheckedCreateWithoutAttachmentsInput = {
id?: string id?: string
text: string text: string
senderId?: string | null senderUsername?: string | null
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
} }
@@ -480,7 +480,7 @@ export type MessageUpdateWithoutAttachmentsInput = {
export type MessageUncheckedUpdateWithoutAttachmentsInput = { export type MessageUncheckedUpdateWithoutAttachmentsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string id?: Prisma.StringFieldUpdateOperationsInput | string
text?: Prisma.StringFieldUpdateOperationsInput | string text?: Prisma.StringFieldUpdateOperationsInput | string
senderId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null senderUsername?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
} }
@@ -549,7 +549,7 @@ export type MessageCountOutputTypeCountAttachmentsArgs<ExtArgs extends runtime.T
export type MessageSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type MessageSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
text?: boolean text?: boolean
senderId?: boolean senderUsername?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
sender?: boolean | Prisma.Message$senderArgs<ExtArgs> sender?: boolean | Prisma.Message$senderArgs<ExtArgs>
@@ -560,7 +560,7 @@ export type MessageSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs
export type MessageSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type MessageSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
text?: boolean text?: boolean
senderId?: boolean senderUsername?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
sender?: boolean | Prisma.Message$senderArgs<ExtArgs> sender?: boolean | Prisma.Message$senderArgs<ExtArgs>
@@ -569,7 +569,7 @@ export type MessageSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Exten
export type MessageSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type MessageSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean id?: boolean
text?: boolean text?: boolean
senderId?: boolean senderUsername?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
sender?: boolean | Prisma.Message$senderArgs<ExtArgs> sender?: boolean | Prisma.Message$senderArgs<ExtArgs>
@@ -578,12 +578,12 @@ export type MessageSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Exten
export type MessageSelectScalar = { export type MessageSelectScalar = {
id?: boolean id?: boolean
text?: boolean text?: boolean
senderId?: boolean senderUsername?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
} }
export type MessageOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "text" | "senderId" | "createdAt" | "updatedAt", ExtArgs["result"]["message"]> export type MessageOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "text" | "senderUsername" | "createdAt" | "updatedAt", ExtArgs["result"]["message"]>
export type MessageInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type MessageInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
sender?: boolean | Prisma.Message$senderArgs<ExtArgs> sender?: boolean | Prisma.Message$senderArgs<ExtArgs>
attachments?: boolean | Prisma.Message$attachmentsArgs<ExtArgs> attachments?: boolean | Prisma.Message$attachmentsArgs<ExtArgs>
@@ -605,7 +605,7 @@ export type $MessagePayload<ExtArgs extends runtime.Types.Extensions.InternalArg
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string id: string
text: string text: string
senderId: string | null senderUsername: string | null
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
}, ExtArgs["result"]["message"]> }, ExtArgs["result"]["message"]>
@@ -1035,7 +1035,7 @@ export interface Prisma__MessageClient<T, Null = never, ExtArgs extends runtime.
export interface MessageFieldRefs { export interface MessageFieldRefs {
readonly id: Prisma.FieldRef<"Message", 'String'> readonly id: Prisma.FieldRef<"Message", 'String'>
readonly text: Prisma.FieldRef<"Message", 'String'> readonly text: Prisma.FieldRef<"Message", 'String'>
readonly senderId: Prisma.FieldRef<"Message", 'String'> readonly senderUsername: Prisma.FieldRef<"Message", 'String'>
readonly createdAt: Prisma.FieldRef<"Message", 'DateTime'> readonly createdAt: Prisma.FieldRef<"Message", 'DateTime'>
readonly updatedAt: Prisma.FieldRef<"Message", 'DateTime'> readonly updatedAt: Prisma.FieldRef<"Message", 'DateTime'>
} }

View File

@@ -25,7 +25,6 @@ export type AggregateUser = {
} }
export type UserMinAggregateOutputType = { export type UserMinAggregateOutputType = {
id: string | null
username: string | null username: string | null
password: string | null password: string | null
displayName: string | null displayName: string | null
@@ -34,7 +33,6 @@ export type UserMinAggregateOutputType = {
} }
export type UserMaxAggregateOutputType = { export type UserMaxAggregateOutputType = {
id: string | null
username: string | null username: string | null
password: string | null password: string | null
displayName: string | null displayName: string | null
@@ -43,7 +41,6 @@ export type UserMaxAggregateOutputType = {
} }
export type UserCountAggregateOutputType = { export type UserCountAggregateOutputType = {
id: number
username: number username: number
password: number password: number
displayName: number displayName: number
@@ -54,7 +51,6 @@ export type UserCountAggregateOutputType = {
export type UserMinAggregateInputType = { export type UserMinAggregateInputType = {
id?: true
username?: true username?: true
password?: true password?: true
displayName?: true displayName?: true
@@ -63,7 +59,6 @@ export type UserMinAggregateInputType = {
} }
export type UserMaxAggregateInputType = { export type UserMaxAggregateInputType = {
id?: true
username?: true username?: true
password?: true password?: true
displayName?: true displayName?: true
@@ -72,7 +67,6 @@ export type UserMaxAggregateInputType = {
} }
export type UserCountAggregateInputType = { export type UserCountAggregateInputType = {
id?: true
username?: true username?: true
password?: true password?: true
displayName?: true displayName?: true
@@ -154,7 +148,6 @@ export type UserGroupByArgs<ExtArgs extends runtime.Types.Extensions.InternalArg
} }
export type UserGroupByOutputType = { export type UserGroupByOutputType = {
id: string
username: string username: string
password: string password: string
displayName: string displayName: string
@@ -184,12 +177,12 @@ export type UserWhereInput = {
AND?: Prisma.UserWhereInput | Prisma.UserWhereInput[] AND?: Prisma.UserWhereInput | Prisma.UserWhereInput[]
OR?: Prisma.UserWhereInput[] OR?: Prisma.UserWhereInput[]
NOT?: Prisma.UserWhereInput | Prisma.UserWhereInput[] NOT?: Prisma.UserWhereInput | Prisma.UserWhereInput[]
id?: Prisma.StringFilter<"User"> | string
username?: Prisma.StringFilter<"User"> | string username?: Prisma.StringFilter<"User"> | string
password?: Prisma.StringFilter<"User"> | string password?: Prisma.StringFilter<"User"> | string
displayName?: Prisma.StringFilter<"User"> | string displayName?: Prisma.StringFilter<"User"> | string
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
Attachments?: Prisma.AttachmentListRelationFilter
Session?: Prisma.SessionListRelationFilter Session?: Prisma.SessionListRelationFilter
UserPreferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null UserPreferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null
Messages?: Prisma.MessageListRelationFilter Messages?: Prisma.MessageListRelationFilter
@@ -197,12 +190,12 @@ export type UserWhereInput = {
} }
export type UserOrderByWithRelationInput = { export type UserOrderByWithRelationInput = {
id?: Prisma.SortOrder
username?: Prisma.SortOrder username?: Prisma.SortOrder
password?: Prisma.SortOrder password?: Prisma.SortOrder
displayName?: Prisma.SortOrder displayName?: Prisma.SortOrder
createdAt?: Prisma.SortOrder createdAt?: Prisma.SortOrder
updatedAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder
Attachments?: Prisma.AttachmentOrderByRelationAggregateInput
Session?: Prisma.SessionOrderByRelationAggregateInput Session?: Prisma.SessionOrderByRelationAggregateInput
UserPreferences?: Prisma.UserPreferencesOrderByWithRelationInput UserPreferences?: Prisma.UserPreferencesOrderByWithRelationInput
Messages?: Prisma.MessageOrderByRelationAggregateInput Messages?: Prisma.MessageOrderByRelationAggregateInput
@@ -210,7 +203,6 @@ export type UserOrderByWithRelationInput = {
} }
export type UserWhereUniqueInput = Prisma.AtLeast<{ export type UserWhereUniqueInput = Prisma.AtLeast<{
id?: string
username?: string username?: string
AND?: Prisma.UserWhereInput | Prisma.UserWhereInput[] AND?: Prisma.UserWhereInput | Prisma.UserWhereInput[]
OR?: Prisma.UserWhereInput[] OR?: Prisma.UserWhereInput[]
@@ -219,14 +211,14 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{
displayName?: Prisma.StringFilter<"User"> | string displayName?: Prisma.StringFilter<"User"> | string
createdAt?: Prisma.DateTimeFilter<"User"> | Date | string createdAt?: Prisma.DateTimeFilter<"User"> | Date | string
updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string updatedAt?: Prisma.DateTimeFilter<"User"> | Date | string
Attachments?: Prisma.AttachmentListRelationFilter
Session?: Prisma.SessionListRelationFilter Session?: Prisma.SessionListRelationFilter
UserPreferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null UserPreferences?: Prisma.XOR<Prisma.UserPreferencesNullableScalarRelationFilter, Prisma.UserPreferencesWhereInput> | null
Messages?: Prisma.MessageListRelationFilter Messages?: Prisma.MessageListRelationFilter
Channels?: Prisma.ChannelListRelationFilter Channels?: Prisma.ChannelListRelationFilter
}, "id" | "username"> }, "username" | "username">
export type UserOrderByWithAggregationInput = { export type UserOrderByWithAggregationInput = {
id?: Prisma.SortOrder
username?: Prisma.SortOrder username?: Prisma.SortOrder
password?: Prisma.SortOrder password?: Prisma.SortOrder
displayName?: Prisma.SortOrder displayName?: Prisma.SortOrder
@@ -241,7 +233,6 @@ export type UserScalarWhereWithAggregatesInput = {
AND?: Prisma.UserScalarWhereWithAggregatesInput | Prisma.UserScalarWhereWithAggregatesInput[] AND?: Prisma.UserScalarWhereWithAggregatesInput | Prisma.UserScalarWhereWithAggregatesInput[]
OR?: Prisma.UserScalarWhereWithAggregatesInput[] OR?: Prisma.UserScalarWhereWithAggregatesInput[]
NOT?: Prisma.UserScalarWhereWithAggregatesInput | Prisma.UserScalarWhereWithAggregatesInput[] NOT?: Prisma.UserScalarWhereWithAggregatesInput | Prisma.UserScalarWhereWithAggregatesInput[]
id?: Prisma.StringWithAggregatesFilter<"User"> | string
username?: Prisma.StringWithAggregatesFilter<"User"> | string username?: Prisma.StringWithAggregatesFilter<"User"> | string
password?: Prisma.StringWithAggregatesFilter<"User"> | string password?: Prisma.StringWithAggregatesFilter<"User"> | string
displayName?: Prisma.StringWithAggregatesFilter<"User"> | string displayName?: Prisma.StringWithAggregatesFilter<"User"> | string
@@ -250,12 +241,12 @@ export type UserScalarWhereWithAggregatesInput = {
} }
export type UserCreateInput = { export type UserCreateInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentCreateNestedManyWithoutUserInput
Session?: Prisma.SessionCreateNestedManyWithoutUserInput Session?: Prisma.SessionCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput
@@ -263,12 +254,12 @@ export type UserCreateInput = {
} }
export type UserUncheckedCreateInput = { export type UserUncheckedCreateInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentUncheckedCreateNestedManyWithoutUserInput
Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput
@@ -276,12 +267,12 @@ export type UserUncheckedCreateInput = {
} }
export type UserUpdateInput = { export type UserUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput
@@ -289,12 +280,12 @@ export type UserUpdateInput = {
} }
export type UserUncheckedUpdateInput = { export type UserUncheckedUpdateInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUncheckedUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput
@@ -302,7 +293,6 @@ export type UserUncheckedUpdateInput = {
} }
export type UserCreateManyInput = { export type UserCreateManyInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
@@ -311,7 +301,6 @@ export type UserCreateManyInput = {
} }
export type UserUpdateManyMutationInput = { export type UserUpdateManyMutationInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
@@ -320,7 +309,6 @@ export type UserUpdateManyMutationInput = {
} }
export type UserUncheckedUpdateManyInput = { export type UserUncheckedUpdateManyInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
@@ -329,7 +317,6 @@ export type UserUncheckedUpdateManyInput = {
} }
export type UserCountOrderByAggregateInput = { export type UserCountOrderByAggregateInput = {
id?: Prisma.SortOrder
username?: Prisma.SortOrder username?: Prisma.SortOrder
password?: Prisma.SortOrder password?: Prisma.SortOrder
displayName?: Prisma.SortOrder displayName?: Prisma.SortOrder
@@ -338,7 +325,6 @@ export type UserCountOrderByAggregateInput = {
} }
export type UserMaxOrderByAggregateInput = { export type UserMaxOrderByAggregateInput = {
id?: Prisma.SortOrder
username?: Prisma.SortOrder username?: Prisma.SortOrder
password?: Prisma.SortOrder password?: Prisma.SortOrder
displayName?: Prisma.SortOrder displayName?: Prisma.SortOrder
@@ -347,7 +333,6 @@ export type UserMaxOrderByAggregateInput = {
} }
export type UserMinOrderByAggregateInput = { export type UserMinOrderByAggregateInput = {
id?: Prisma.SortOrder
username?: Prisma.SortOrder username?: Prisma.SortOrder
password?: Prisma.SortOrder password?: Prisma.SortOrder
displayName?: Prisma.SortOrder displayName?: Prisma.SortOrder
@@ -401,6 +386,22 @@ export type UserUpdateOneRequiredWithoutUserPreferencesNestedInput = {
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutUserPreferencesInput, Prisma.UserUpdateWithoutUserPreferencesInput>, Prisma.UserUncheckedUpdateWithoutUserPreferencesInput> update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutUserPreferencesInput, Prisma.UserUpdateWithoutUserPreferencesInput>, Prisma.UserUncheckedUpdateWithoutUserPreferencesInput>
} }
export type UserCreateNestedOneWithoutAttachmentsInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutAttachmentsInput, Prisma.UserUncheckedCreateWithoutAttachmentsInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutAttachmentsInput
connect?: Prisma.UserWhereUniqueInput
}
export type UserUpdateOneWithoutAttachmentsNestedInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutAttachmentsInput, Prisma.UserUncheckedCreateWithoutAttachmentsInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutAttachmentsInput
upsert?: Prisma.UserUpsertWithoutAttachmentsInput
disconnect?: Prisma.UserWhereInput | boolean
delete?: Prisma.UserWhereInput | boolean
connect?: Prisma.UserWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.UserUpdateToOneWithWhereWithoutAttachmentsInput, Prisma.UserUpdateWithoutAttachmentsInput>, Prisma.UserUncheckedUpdateWithoutAttachmentsInput>
}
export type UserCreateNestedOneWithoutMessagesInput = { export type UserCreateNestedOneWithoutMessagesInput = {
create?: Prisma.XOR<Prisma.UserCreateWithoutMessagesInput, Prisma.UserUncheckedCreateWithoutMessagesInput> create?: Prisma.XOR<Prisma.UserCreateWithoutMessagesInput, Prisma.UserUncheckedCreateWithoutMessagesInput>
connectOrCreate?: Prisma.UserCreateOrConnectWithoutMessagesInput connectOrCreate?: Prisma.UserCreateOrConnectWithoutMessagesInput
@@ -434,24 +435,24 @@ export type UserUpdateOneWithoutChannelsNestedInput = {
} }
export type UserCreateWithoutSessionInput = { export type UserCreateWithoutSessionInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput
} }
export type UserUncheckedCreateWithoutSessionInput = { export type UserUncheckedCreateWithoutSessionInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentUncheckedCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput
@@ -474,48 +475,48 @@ export type UserUpdateToOneWithWhereWithoutSessionInput = {
} }
export type UserUpdateWithoutSessionInput = { export type UserUpdateWithoutSessionInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput
} }
export type UserUncheckedUpdateWithoutSessionInput = { export type UserUncheckedUpdateWithoutSessionInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUncheckedUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput
} }
export type UserCreateWithoutUserPreferencesInput = { export type UserCreateWithoutUserPreferencesInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentCreateNestedManyWithoutUserInput
Session?: Prisma.SessionCreateNestedManyWithoutUserInput Session?: Prisma.SessionCreateNestedManyWithoutUserInput
Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput
} }
export type UserUncheckedCreateWithoutUserPreferencesInput = { export type UserUncheckedCreateWithoutUserPreferencesInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentUncheckedCreateNestedManyWithoutUserInput
Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput
@@ -538,31 +539,30 @@ export type UserUpdateToOneWithWhereWithoutUserPreferencesInput = {
} }
export type UserUpdateWithoutUserPreferencesInput = { export type UserUpdateWithoutUserPreferencesInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUpdateManyWithoutUserNestedInput
Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput
} }
export type UserUncheckedUpdateWithoutUserPreferencesInput = { export type UserUncheckedUpdateWithoutUserPreferencesInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUncheckedUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput
} }
export type UserCreateWithoutMessagesInput = { export type UserCreateWithoutAttachmentsInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
@@ -570,11 +570,11 @@ export type UserCreateWithoutMessagesInput = {
updatedAt?: Date | string updatedAt?: Date | string
Session?: Prisma.SessionCreateNestedManyWithoutUserInput Session?: Prisma.SessionCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput
} }
export type UserUncheckedCreateWithoutMessagesInput = { export type UserUncheckedCreateWithoutAttachmentsInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
@@ -582,6 +582,71 @@ export type UserUncheckedCreateWithoutMessagesInput = {
updatedAt?: Date | string updatedAt?: Date | string
Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput
Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput
}
export type UserCreateOrConnectWithoutAttachmentsInput = {
where: Prisma.UserWhereUniqueInput
create: Prisma.XOR<Prisma.UserCreateWithoutAttachmentsInput, Prisma.UserUncheckedCreateWithoutAttachmentsInput>
}
export type UserUpsertWithoutAttachmentsInput = {
update: Prisma.XOR<Prisma.UserUpdateWithoutAttachmentsInput, Prisma.UserUncheckedUpdateWithoutAttachmentsInput>
create: Prisma.XOR<Prisma.UserCreateWithoutAttachmentsInput, Prisma.UserUncheckedCreateWithoutAttachmentsInput>
where?: Prisma.UserWhereInput
}
export type UserUpdateToOneWithWhereWithoutAttachmentsInput = {
where?: Prisma.UserWhereInput
data: Prisma.XOR<Prisma.UserUpdateWithoutAttachmentsInput, Prisma.UserUncheckedUpdateWithoutAttachmentsInput>
}
export type UserUpdateWithoutAttachmentsInput = {
username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Session?: Prisma.SessionUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput
}
export type UserUncheckedUpdateWithoutAttachmentsInput = {
username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput
Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput
}
export type UserCreateWithoutMessagesInput = {
username: string
password: string
displayName: string
createdAt?: Date | string
updatedAt?: Date | string
Attachments?: Prisma.AttachmentCreateNestedManyWithoutUserInput
Session?: Prisma.SessionCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
Channels?: Prisma.ChannelCreateNestedManyWithoutOwnerInput
}
export type UserUncheckedCreateWithoutMessagesInput = {
username: string
password: string
displayName: string
createdAt?: Date | string
updatedAt?: Date | string
Attachments?: Prisma.AttachmentUncheckedCreateNestedManyWithoutUserInput
Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput Channels?: Prisma.ChannelUncheckedCreateNestedManyWithoutOwnerInput
} }
@@ -602,48 +667,48 @@ export type UserUpdateToOneWithWhereWithoutMessagesInput = {
} }
export type UserUpdateWithoutMessagesInput = { export type UserUpdateWithoutMessagesInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUpdateManyWithoutOwnerNestedInput
} }
export type UserUncheckedUpdateWithoutMessagesInput = { export type UserUncheckedUpdateWithoutMessagesInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUncheckedUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput Channels?: Prisma.ChannelUncheckedUpdateManyWithoutOwnerNestedInput
} }
export type UserCreateWithoutChannelsInput = { export type UserCreateWithoutChannelsInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentCreateNestedManyWithoutUserInput
Session?: Prisma.SessionCreateNestedManyWithoutUserInput Session?: Prisma.SessionCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageCreateNestedManyWithoutSenderInput
} }
export type UserUncheckedCreateWithoutChannelsInput = { export type UserUncheckedCreateWithoutChannelsInput = {
id?: string
username: string username: string
password: string password: string
displayName: string displayName: string
createdAt?: Date | string createdAt?: Date | string
updatedAt?: Date | string updatedAt?: Date | string
Attachments?: Prisma.AttachmentUncheckedCreateNestedManyWithoutUserInput
Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput Session?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput
UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput UserPreferences?: Prisma.UserPreferencesUncheckedCreateNestedOneWithoutUserInput
Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput Messages?: Prisma.MessageUncheckedCreateNestedManyWithoutSenderInput
@@ -666,24 +731,24 @@ export type UserUpdateToOneWithWhereWithoutChannelsInput = {
} }
export type UserUpdateWithoutChannelsInput = { export type UserUpdateWithoutChannelsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUpdateManyWithoutSenderNestedInput
} }
export type UserUncheckedUpdateWithoutChannelsInput = { export type UserUncheckedUpdateWithoutChannelsInput = {
id?: Prisma.StringFieldUpdateOperationsInput | string
username?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
password?: Prisma.StringFieldUpdateOperationsInput | string password?: Prisma.StringFieldUpdateOperationsInput | string
displayName?: Prisma.StringFieldUpdateOperationsInput | string displayName?: Prisma.StringFieldUpdateOperationsInput | string
createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
Attachments?: Prisma.AttachmentUncheckedUpdateManyWithoutUserNestedInput
Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput Session?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput
UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput UserPreferences?: Prisma.UserPreferencesUncheckedUpdateOneWithoutUserNestedInput
Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput Messages?: Prisma.MessageUncheckedUpdateManyWithoutSenderNestedInput
@@ -695,12 +760,14 @@ export type UserUncheckedUpdateWithoutChannelsInput = {
*/ */
export type UserCountOutputType = { export type UserCountOutputType = {
Attachments: number
Session: number Session: number
Messages: number Messages: number
Channels: number Channels: number
} }
export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type UserCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
Attachments?: boolean | UserCountOutputTypeCountAttachmentsArgs
Session?: boolean | UserCountOutputTypeCountSessionArgs Session?: boolean | UserCountOutputTypeCountSessionArgs
Messages?: boolean | UserCountOutputTypeCountMessagesArgs Messages?: boolean | UserCountOutputTypeCountMessagesArgs
Channels?: boolean | UserCountOutputTypeCountChannelsArgs Channels?: boolean | UserCountOutputTypeCountChannelsArgs
@@ -716,6 +783,13 @@ export type UserCountOutputTypeDefaultArgs<ExtArgs extends runtime.Types.Extensi
select?: Prisma.UserCountOutputTypeSelect<ExtArgs> | null select?: Prisma.UserCountOutputTypeSelect<ExtArgs> | null
} }
/**
* UserCountOutputType without action
*/
export type UserCountOutputTypeCountAttachmentsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.AttachmentWhereInput
}
/** /**
* UserCountOutputType without action * UserCountOutputType without action
*/ */
@@ -739,12 +813,12 @@ export type UserCountOutputTypeCountChannelsArgs<ExtArgs extends runtime.Types.E
export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
username?: boolean username?: boolean
password?: boolean password?: boolean
displayName?: boolean displayName?: boolean
createdAt?: boolean createdAt?: boolean
updatedAt?: boolean updatedAt?: boolean
Attachments?: boolean | Prisma.User$AttachmentsArgs<ExtArgs>
Session?: boolean | Prisma.User$SessionArgs<ExtArgs> Session?: boolean | Prisma.User$SessionArgs<ExtArgs>
UserPreferences?: boolean | Prisma.User$UserPreferencesArgs<ExtArgs> UserPreferences?: boolean | Prisma.User$UserPreferencesArgs<ExtArgs>
Messages?: boolean | Prisma.User$MessagesArgs<ExtArgs> Messages?: boolean | Prisma.User$MessagesArgs<ExtArgs>
@@ -753,7 +827,6 @@ export type UserSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = r
}, ExtArgs["result"]["user"]> }, ExtArgs["result"]["user"]>
export type UserSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
username?: boolean username?: boolean
password?: boolean password?: boolean
displayName?: boolean displayName?: boolean
@@ -762,7 +835,6 @@ export type UserSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensio
}, ExtArgs["result"]["user"]> }, ExtArgs["result"]["user"]>
export type UserSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
username?: boolean username?: boolean
password?: boolean password?: boolean
displayName?: boolean displayName?: boolean
@@ -771,7 +843,6 @@ export type UserSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensio
}, ExtArgs["result"]["user"]> }, ExtArgs["result"]["user"]>
export type UserSelectScalar = { export type UserSelectScalar = {
id?: boolean
username?: boolean username?: boolean
password?: boolean password?: boolean
displayName?: boolean displayName?: boolean
@@ -779,8 +850,9 @@ export type UserSelectScalar = {
updatedAt?: boolean updatedAt?: boolean
} }
export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "username" | "password" | "displayName" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]> export type UserOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"username" | "password" | "displayName" | "createdAt" | "updatedAt", ExtArgs["result"]["user"]>
export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type UserInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
Attachments?: boolean | Prisma.User$AttachmentsArgs<ExtArgs>
Session?: boolean | Prisma.User$SessionArgs<ExtArgs> Session?: boolean | Prisma.User$SessionArgs<ExtArgs>
UserPreferences?: boolean | Prisma.User$UserPreferencesArgs<ExtArgs> UserPreferences?: boolean | Prisma.User$UserPreferencesArgs<ExtArgs>
Messages?: boolean | Prisma.User$MessagesArgs<ExtArgs> Messages?: boolean | Prisma.User$MessagesArgs<ExtArgs>
@@ -793,13 +865,13 @@ export type UserIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensi
export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type $UserPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
name: "User" name: "User"
objects: { objects: {
Attachments: Prisma.$AttachmentPayload<ExtArgs>[]
Session: Prisma.$SessionPayload<ExtArgs>[] Session: Prisma.$SessionPayload<ExtArgs>[]
UserPreferences: Prisma.$UserPreferencesPayload<ExtArgs> | null UserPreferences: Prisma.$UserPreferencesPayload<ExtArgs> | null
Messages: Prisma.$MessagePayload<ExtArgs>[] Messages: Prisma.$MessagePayload<ExtArgs>[]
Channels: Prisma.$ChannelPayload<ExtArgs>[] Channels: Prisma.$ChannelPayload<ExtArgs>[]
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
id: string
username: string username: string
password: string password: string
displayName: string displayName: string
@@ -888,8 +960,8 @@ export interface UserDelegate<ExtArgs extends runtime.Types.Extensions.InternalA
* // Get first 10 Users * // Get first 10 Users
* const users = await prisma.user.findMany({ take: 10 }) * const users = await prisma.user.findMany({ take: 10 })
* *
* // Only select the `id` * // Only select the `username`
* const userWithIdOnly = await prisma.user.findMany({ select: { id: true } }) * const userWithUsernameOnly = await prisma.user.findMany({ select: { username: true } })
* *
*/ */
findMany<T extends UserFindManyArgs>(args?: Prisma.SelectSubset<T, UserFindManyArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$UserPayload<ExtArgs>, T, "findMany", GlobalOmitOptions>> findMany<T extends UserFindManyArgs>(args?: Prisma.SelectSubset<T, UserFindManyArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$UserPayload<ExtArgs>, T, "findMany", GlobalOmitOptions>>
@@ -933,9 +1005,9 @@ export interface UserDelegate<ExtArgs extends runtime.Types.Extensions.InternalA
* ] * ]
* }) * })
* *
* // Create many Users and only return the `id` * // Create many Users and only return the `username`
* const userWithIdOnly = await prisma.user.createManyAndReturn({ * const userWithUsernameOnly = await prisma.user.createManyAndReturn({
* select: { id: true }, * select: { username: true },
* data: [ * data: [
* // ... provide data here * // ... provide data here
* ] * ]
@@ -1024,9 +1096,9 @@ export interface UserDelegate<ExtArgs extends runtime.Types.Extensions.InternalA
* ] * ]
* }) * })
* *
* // Update zero or more Users and only return the `id` * // Update zero or more Users and only return the `username`
* const userWithIdOnly = await prisma.user.updateManyAndReturn({ * const userWithUsernameOnly = await prisma.user.updateManyAndReturn({
* select: { id: true }, * select: { username: true },
* where: { * where: {
* // ... provide filter here * // ... provide filter here
* }, * },
@@ -1199,6 +1271,7 @@ readonly fields: UserFieldRefs;
*/ */
export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> { export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
readonly [Symbol.toStringTag]: "PrismaPromise" readonly [Symbol.toStringTag]: "PrismaPromise"
Attachments<T extends Prisma.User$AttachmentsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$AttachmentsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AttachmentPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
Session<T extends Prisma.User$SessionArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$SessionArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$SessionPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> Session<T extends Prisma.User$SessionArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$SessionArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$SessionPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
UserPreferences<T extends Prisma.User$UserPreferencesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$UserPreferencesArgs<ExtArgs>>): Prisma.Prisma__UserPreferencesClient<runtime.Types.Result.GetResult<Prisma.$UserPreferencesPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> UserPreferences<T extends Prisma.User$UserPreferencesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$UserPreferencesArgs<ExtArgs>>): Prisma.Prisma__UserPreferencesClient<runtime.Types.Result.GetResult<Prisma.$UserPreferencesPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
Messages<T extends Prisma.User$MessagesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$MessagesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MessagePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null> Messages<T extends Prisma.User$MessagesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.User$MessagesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$MessagePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
@@ -1232,7 +1305,6 @@ export interface Prisma__UserClient<T, Null = never, ExtArgs extends runtime.Typ
* Fields of the User model * Fields of the User model
*/ */
export interface UserFieldRefs { export interface UserFieldRefs {
readonly id: Prisma.FieldRef<"User", 'String'>
readonly username: Prisma.FieldRef<"User", 'String'> readonly username: Prisma.FieldRef<"User", 'String'>
readonly password: Prisma.FieldRef<"User", 'String'> readonly password: Prisma.FieldRef<"User", 'String'>
readonly displayName: Prisma.FieldRef<"User", 'String'> readonly displayName: Prisma.FieldRef<"User", 'String'>
@@ -1628,6 +1700,30 @@ export type UserDeleteManyArgs<ExtArgs extends runtime.Types.Extensions.Internal
limit?: number limit?: number
} }
/**
* User.Attachments
*/
export type User$AttachmentsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the Attachment
*/
select?: Prisma.AttachmentSelect<ExtArgs> | null
/**
* Omit specific fields from the Attachment
*/
omit?: Prisma.AttachmentOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AttachmentInclude<ExtArgs> | null
where?: Prisma.AttachmentWhereInput
orderBy?: Prisma.AttachmentOrderByWithRelationInput | Prisma.AttachmentOrderByWithRelationInput[]
cursor?: Prisma.AttachmentWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.AttachmentScalarFieldEnum | Prisma.AttachmentScalarFieldEnum[]
}
/** /**
* User.Session * User.Session
*/ */

View File

@@ -25,19 +25,19 @@ export type AggregateUserPreferences = {
} }
export type UserPreferencesMinAggregateOutputType = { export type UserPreferencesMinAggregateOutputType = {
userId: string | null username: string | null
toggleInputHotkey: string | null toggleInputHotkey: string | null
toggleOutputHotkey: string | null toggleOutputHotkey: string | null
} }
export type UserPreferencesMaxAggregateOutputType = { export type UserPreferencesMaxAggregateOutputType = {
userId: string | null username: string | null
toggleInputHotkey: string | null toggleInputHotkey: string | null
toggleOutputHotkey: string | null toggleOutputHotkey: string | null
} }
export type UserPreferencesCountAggregateOutputType = { export type UserPreferencesCountAggregateOutputType = {
userId: number username: number
toggleInputHotkey: number toggleInputHotkey: number
toggleOutputHotkey: number toggleOutputHotkey: number
_all: number _all: number
@@ -45,19 +45,19 @@ export type UserPreferencesCountAggregateOutputType = {
export type UserPreferencesMinAggregateInputType = { export type UserPreferencesMinAggregateInputType = {
userId?: true username?: true
toggleInputHotkey?: true toggleInputHotkey?: true
toggleOutputHotkey?: true toggleOutputHotkey?: true
} }
export type UserPreferencesMaxAggregateInputType = { export type UserPreferencesMaxAggregateInputType = {
userId?: true username?: true
toggleInputHotkey?: true toggleInputHotkey?: true
toggleOutputHotkey?: true toggleOutputHotkey?: true
} }
export type UserPreferencesCountAggregateInputType = { export type UserPreferencesCountAggregateInputType = {
userId?: true username?: true
toggleInputHotkey?: true toggleInputHotkey?: true
toggleOutputHotkey?: true toggleOutputHotkey?: true
_all?: true _all?: true
@@ -136,7 +136,7 @@ export type UserPreferencesGroupByArgs<ExtArgs extends runtime.Types.Extensions.
} }
export type UserPreferencesGroupByOutputType = { export type UserPreferencesGroupByOutputType = {
userId: string username: string
toggleInputHotkey: string | null toggleInputHotkey: string | null
toggleOutputHotkey: string | null toggleOutputHotkey: string | null
_count: UserPreferencesCountAggregateOutputType | null _count: UserPreferencesCountAggregateOutputType | null
@@ -163,31 +163,31 @@ export type UserPreferencesWhereInput = {
AND?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[] AND?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[]
OR?: Prisma.UserPreferencesWhereInput[] OR?: Prisma.UserPreferencesWhereInput[]
NOT?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[] NOT?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[]
userId?: Prisma.StringFilter<"UserPreferences"> | string username?: Prisma.StringFilter<"UserPreferences"> | string
toggleInputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null toggleInputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null
toggleOutputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null toggleOutputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null
user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput> user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput>
} }
export type UserPreferencesOrderByWithRelationInput = { export type UserPreferencesOrderByWithRelationInput = {
userId?: Prisma.SortOrder username?: Prisma.SortOrder
toggleInputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder toggleInputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder
toggleOutputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder toggleOutputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder
user?: Prisma.UserOrderByWithRelationInput user?: Prisma.UserOrderByWithRelationInput
} }
export type UserPreferencesWhereUniqueInput = Prisma.AtLeast<{ export type UserPreferencesWhereUniqueInput = Prisma.AtLeast<{
userId?: string username?: string
AND?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[] AND?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[]
OR?: Prisma.UserPreferencesWhereInput[] OR?: Prisma.UserPreferencesWhereInput[]
NOT?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[] NOT?: Prisma.UserPreferencesWhereInput | Prisma.UserPreferencesWhereInput[]
toggleInputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null toggleInputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null
toggleOutputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null toggleOutputHotkey?: Prisma.StringNullableFilter<"UserPreferences"> | string | null
user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput> user?: Prisma.XOR<Prisma.UserScalarRelationFilter, Prisma.UserWhereInput>
}, "userId" | "userId"> }, "username" | "username">
export type UserPreferencesOrderByWithAggregationInput = { export type UserPreferencesOrderByWithAggregationInput = {
userId?: Prisma.SortOrder username?: Prisma.SortOrder
toggleInputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder toggleInputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder
toggleOutputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder toggleOutputHotkey?: Prisma.SortOrderInput | Prisma.SortOrder
_count?: Prisma.UserPreferencesCountOrderByAggregateInput _count?: Prisma.UserPreferencesCountOrderByAggregateInput
@@ -199,7 +199,7 @@ export type UserPreferencesScalarWhereWithAggregatesInput = {
AND?: Prisma.UserPreferencesScalarWhereWithAggregatesInput | Prisma.UserPreferencesScalarWhereWithAggregatesInput[] AND?: Prisma.UserPreferencesScalarWhereWithAggregatesInput | Prisma.UserPreferencesScalarWhereWithAggregatesInput[]
OR?: Prisma.UserPreferencesScalarWhereWithAggregatesInput[] OR?: Prisma.UserPreferencesScalarWhereWithAggregatesInput[]
NOT?: Prisma.UserPreferencesScalarWhereWithAggregatesInput | Prisma.UserPreferencesScalarWhereWithAggregatesInput[] NOT?: Prisma.UserPreferencesScalarWhereWithAggregatesInput | Prisma.UserPreferencesScalarWhereWithAggregatesInput[]
userId?: Prisma.StringWithAggregatesFilter<"UserPreferences"> | string username?: Prisma.StringWithAggregatesFilter<"UserPreferences"> | string
toggleInputHotkey?: Prisma.StringNullableWithAggregatesFilter<"UserPreferences"> | string | null toggleInputHotkey?: Prisma.StringNullableWithAggregatesFilter<"UserPreferences"> | string | null
toggleOutputHotkey?: Prisma.StringNullableWithAggregatesFilter<"UserPreferences"> | string | null toggleOutputHotkey?: Prisma.StringNullableWithAggregatesFilter<"UserPreferences"> | string | null
} }
@@ -211,7 +211,7 @@ export type UserPreferencesCreateInput = {
} }
export type UserPreferencesUncheckedCreateInput = { export type UserPreferencesUncheckedCreateInput = {
userId: string username: string
toggleInputHotkey?: string | null toggleInputHotkey?: string | null
toggleOutputHotkey?: string | null toggleOutputHotkey?: string | null
} }
@@ -223,13 +223,13 @@ export type UserPreferencesUpdateInput = {
} }
export type UserPreferencesUncheckedUpdateInput = { export type UserPreferencesUncheckedUpdateInput = {
userId?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
toggleInputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null toggleInputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
toggleOutputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null toggleOutputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
} }
export type UserPreferencesCreateManyInput = { export type UserPreferencesCreateManyInput = {
userId: string username: string
toggleInputHotkey?: string | null toggleInputHotkey?: string | null
toggleOutputHotkey?: string | null toggleOutputHotkey?: string | null
} }
@@ -240,7 +240,7 @@ export type UserPreferencesUpdateManyMutationInput = {
} }
export type UserPreferencesUncheckedUpdateManyInput = { export type UserPreferencesUncheckedUpdateManyInput = {
userId?: Prisma.StringFieldUpdateOperationsInput | string username?: Prisma.StringFieldUpdateOperationsInput | string
toggleInputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null toggleInputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
toggleOutputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null toggleOutputHotkey?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
} }
@@ -251,19 +251,19 @@ export type UserPreferencesNullableScalarRelationFilter = {
} }
export type UserPreferencesCountOrderByAggregateInput = { export type UserPreferencesCountOrderByAggregateInput = {
userId?: Prisma.SortOrder username?: Prisma.SortOrder
toggleInputHotkey?: Prisma.SortOrder toggleInputHotkey?: Prisma.SortOrder
toggleOutputHotkey?: Prisma.SortOrder toggleOutputHotkey?: Prisma.SortOrder
} }
export type UserPreferencesMaxOrderByAggregateInput = { export type UserPreferencesMaxOrderByAggregateInput = {
userId?: Prisma.SortOrder username?: Prisma.SortOrder
toggleInputHotkey?: Prisma.SortOrder toggleInputHotkey?: Prisma.SortOrder
toggleOutputHotkey?: Prisma.SortOrder toggleOutputHotkey?: Prisma.SortOrder
} }
export type UserPreferencesMinOrderByAggregateInput = { export type UserPreferencesMinOrderByAggregateInput = {
userId?: Prisma.SortOrder username?: Prisma.SortOrder
toggleInputHotkey?: Prisma.SortOrder toggleInputHotkey?: Prisma.SortOrder
toggleOutputHotkey?: Prisma.SortOrder toggleOutputHotkey?: Prisma.SortOrder
} }
@@ -343,33 +343,33 @@ export type UserPreferencesUncheckedUpdateWithoutUserInput = {
export type UserPreferencesSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserPreferencesSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
userId?: boolean username?: boolean
toggleInputHotkey?: boolean toggleInputHotkey?: boolean
toggleOutputHotkey?: boolean toggleOutputHotkey?: boolean
user?: boolean | Prisma.UserDefaultArgs<ExtArgs> user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
}, ExtArgs["result"]["userPreferences"]> }, ExtArgs["result"]["userPreferences"]>
export type UserPreferencesSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserPreferencesSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
userId?: boolean username?: boolean
toggleInputHotkey?: boolean toggleInputHotkey?: boolean
toggleOutputHotkey?: boolean toggleOutputHotkey?: boolean
user?: boolean | Prisma.UserDefaultArgs<ExtArgs> user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
}, ExtArgs["result"]["userPreferences"]> }, ExtArgs["result"]["userPreferences"]>
export type UserPreferencesSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{ export type UserPreferencesSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
userId?: boolean username?: boolean
toggleInputHotkey?: boolean toggleInputHotkey?: boolean
toggleOutputHotkey?: boolean toggleOutputHotkey?: boolean
user?: boolean | Prisma.UserDefaultArgs<ExtArgs> user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
}, ExtArgs["result"]["userPreferences"]> }, ExtArgs["result"]["userPreferences"]>
export type UserPreferencesSelectScalar = { export type UserPreferencesSelectScalar = {
userId?: boolean username?: boolean
toggleInputHotkey?: boolean toggleInputHotkey?: boolean
toggleOutputHotkey?: boolean toggleOutputHotkey?: boolean
} }
export type UserPreferencesOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"userId" | "toggleInputHotkey" | "toggleOutputHotkey", ExtArgs["result"]["userPreferences"]> export type UserPreferencesOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"username" | "toggleInputHotkey" | "toggleOutputHotkey", ExtArgs["result"]["userPreferences"]>
export type UserPreferencesInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type UserPreferencesInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
user?: boolean | Prisma.UserDefaultArgs<ExtArgs> user?: boolean | Prisma.UserDefaultArgs<ExtArgs>
} }
@@ -386,7 +386,7 @@ export type $UserPreferencesPayload<ExtArgs extends runtime.Types.Extensions.Int
user: Prisma.$UserPayload<ExtArgs> user: Prisma.$UserPayload<ExtArgs>
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
userId: string username: string
toggleInputHotkey: string | null toggleInputHotkey: string | null
toggleOutputHotkey: string | null toggleOutputHotkey: string | null
}, ExtArgs["result"]["userPreferences"]> }, ExtArgs["result"]["userPreferences"]>
@@ -472,8 +472,8 @@ export interface UserPreferencesDelegate<ExtArgs extends runtime.Types.Extension
* // Get first 10 UserPreferences * // Get first 10 UserPreferences
* const userPreferences = await prisma.userPreferences.findMany({ take: 10 }) * const userPreferences = await prisma.userPreferences.findMany({ take: 10 })
* *
* // Only select the `userId` * // Only select the `username`
* const userPreferencesWithUserIdOnly = await prisma.userPreferences.findMany({ select: { userId: true } }) * const userPreferencesWithUsernameOnly = await prisma.userPreferences.findMany({ select: { username: true } })
* *
*/ */
findMany<T extends UserPreferencesFindManyArgs>(args?: Prisma.SelectSubset<T, UserPreferencesFindManyArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$UserPreferencesPayload<ExtArgs>, T, "findMany", GlobalOmitOptions>> findMany<T extends UserPreferencesFindManyArgs>(args?: Prisma.SelectSubset<T, UserPreferencesFindManyArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$UserPreferencesPayload<ExtArgs>, T, "findMany", GlobalOmitOptions>>
@@ -517,9 +517,9 @@ export interface UserPreferencesDelegate<ExtArgs extends runtime.Types.Extension
* ] * ]
* }) * })
* *
* // Create many UserPreferences and only return the `userId` * // Create many UserPreferences and only return the `username`
* const userPreferencesWithUserIdOnly = await prisma.userPreferences.createManyAndReturn({ * const userPreferencesWithUsernameOnly = await prisma.userPreferences.createManyAndReturn({
* select: { userId: true }, * select: { username: true },
* data: [ * data: [
* // ... provide data here * // ... provide data here
* ] * ]
@@ -608,9 +608,9 @@ export interface UserPreferencesDelegate<ExtArgs extends runtime.Types.Extension
* ] * ]
* }) * })
* *
* // Update zero or more UserPreferences and only return the `userId` * // Update zero or more UserPreferences and only return the `username`
* const userPreferencesWithUserIdOnly = await prisma.userPreferences.updateManyAndReturn({ * const userPreferencesWithUsernameOnly = await prisma.userPreferences.updateManyAndReturn({
* select: { userId: true }, * select: { username: true },
* where: { * where: {
* // ... provide filter here * // ... provide filter here
* }, * },
@@ -813,7 +813,7 @@ export interface Prisma__UserPreferencesClient<T, Null = never, ExtArgs extends
* Fields of the UserPreferences model * Fields of the UserPreferences model
*/ */
export interface UserPreferencesFieldRefs { export interface UserPreferencesFieldRefs {
readonly userId: Prisma.FieldRef<"UserPreferences", 'String'> readonly username: Prisma.FieldRef<"UserPreferences", 'String'>
readonly toggleInputHotkey: Prisma.FieldRef<"UserPreferences", 'String'> readonly toggleInputHotkey: Prisma.FieldRef<"UserPreferences", 'String'>
readonly toggleOutputHotkey: Prisma.FieldRef<"UserPreferences", 'String'> readonly toggleOutputHotkey: Prisma.FieldRef<"UserPreferences", 'String'>
} }

View File

@@ -0,0 +1,101 @@
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
-- =====================
-- Channel
-- =====================
CREATE TABLE "new_Channel" (
"id" TEXT NOT NULL PRIMARY KEY,
"ownerId" TEXT,
"ownerUsername" TEXT,
"name" TEXT NOT NULL,
"persistent" BOOLEAN NOT NULL,
CONSTRAINT "Channel_ownerUsername_fkey" FOREIGN KEY ("ownerUsername") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Channel" ("id", "name", "ownerId", "ownerUsername", "persistent")
SELECT c."id", c."name", c."ownerId",
(SELECT u."username" FROM "User" u WHERE u."id" = c."ownerId"),
c."persistent"
FROM "Channel" c;
DROP TABLE "Channel";
ALTER TABLE "new_Channel" RENAME TO "Channel";
-- =====================
-- Message
-- =====================
CREATE TABLE "new_Message" (
"id" TEXT NOT NULL PRIMARY KEY,
"text" TEXT NOT NULL,
"senderId" TEXT,
"senderUsername" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Message_senderUsername_fkey" FOREIGN KEY ("senderUsername") REFERENCES "User" ("username") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_Message" ("id", "text", "senderId", "senderUsername", "createdAt", "updatedAt")
SELECT m."id", m."text", m."senderId",
(SELECT u."username" FROM "User" u WHERE u."id" = m."senderId"),
m."createdAt", m."updatedAt"
FROM "Message" m;
DROP TABLE "Message";
ALTER TABLE "new_Message" RENAME TO "Message";
-- =====================
-- Session
-- =====================
CREATE TABLE "new_Session" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"username" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
CONSTRAINT "Session_username_fkey" FOREIGN KEY ("username") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Session" ("id", "userId", "username", "expiresAt")
SELECT s."id", s."userId",
(SELECT u."username" FROM "User" u WHERE u."id" = s."userId"),
s."expiresAt"
FROM "Session" s;
DROP TABLE "Session";
ALTER TABLE "new_Session" RENAME TO "Session";
CREATE INDEX "Session_userId_idx" ON "Session"("userId");
-- =====================
-- User
-- =====================
CREATE TABLE "new_User" (
"id" TEXT NOT NULL,
"username" TEXT NOT NULL PRIMARY KEY,
"password" TEXT NOT NULL,
"displayName" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "displayName", "id", "password", "updatedAt", "username")
SELECT "createdAt", "displayName", "id", "password", "updatedAt", "username"
FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
-- =====================
-- UserPreferences
-- =====================
CREATE TABLE "new_UserPreferences" (
"userId" TEXT NOT NULL,
"username" TEXT NOT NULL PRIMARY KEY,
"toggleInputHotkey" TEXT DEFAULT '',
"toggleOutputHotkey" TEXT DEFAULT '',
CONSTRAINT "UserPreferences_username_fkey" FOREIGN KEY ("username") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_UserPreferences" ("userId", "username", "toggleInputHotkey", "toggleOutputHotkey")
SELECT up."userId",
(SELECT u."username" FROM "User" u WHERE u."id" = up."userId"),
up."toggleInputHotkey", up."toggleOutputHotkey"
FROM "UserPreferences" up;
DROP TABLE "UserPreferences";
ALTER TABLE "new_UserPreferences" RENAME TO "UserPreferences";
CREATE UNIQUE INDEX "UserPreferences_userId_key" ON "UserPreferences"("userId");
CREATE UNIQUE INDEX "UserPreferences_username_key" ON "UserPreferences"("username");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,67 @@
/*
Warnings:
- You are about to drop the column `ownerId` on the `Channel` table. All the data in the column will be lost.
- You are about to drop the column `senderId` on the `Message` table. All the data in the column will be lost.
- You are about to drop the column `userId` on the `Session` table. All the data in the column will be lost.
- You are about to drop the column `id` on the `User` table. All the data in the column will be lost.
- You are about to drop the column `userId` on the `UserPreferences` table. All the data in the column will be lost.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Channel" (
"id" TEXT NOT NULL PRIMARY KEY,
"ownerUsername" TEXT,
"name" TEXT NOT NULL,
"persistent" BOOLEAN NOT NULL,
CONSTRAINT "Channel_ownerUsername_fkey" FOREIGN KEY ("ownerUsername") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Channel" ("id", "name", "ownerUsername", "persistent") SELECT "id", "name", "ownerUsername", "persistent" FROM "Channel";
DROP TABLE "Channel";
ALTER TABLE "new_Channel" RENAME TO "Channel";
CREATE TABLE "new_Message" (
"id" TEXT NOT NULL PRIMARY KEY,
"text" TEXT NOT NULL,
"senderUsername" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Message_senderUsername_fkey" FOREIGN KEY ("senderUsername") REFERENCES "User" ("username") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_Message" ("createdAt", "id", "senderUsername", "text", "updatedAt") SELECT "createdAt", "id", "senderUsername", "text", "updatedAt" FROM "Message";
DROP TABLE "Message";
ALTER TABLE "new_Message" RENAME TO "Message";
CREATE TABLE "new_Session" (
"id" TEXT NOT NULL PRIMARY KEY,
"username" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
CONSTRAINT "Session_username_fkey" FOREIGN KEY ("username") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Session" ("expiresAt", "id", "username") SELECT "expiresAt", "id", "username" FROM "Session";
DROP TABLE "Session";
ALTER TABLE "new_Session" RENAME TO "Session";
CREATE INDEX "Session_username_idx" ON "Session"("username");
CREATE TABLE "new_User" (
"username" TEXT NOT NULL PRIMARY KEY,
"password" TEXT NOT NULL,
"displayName" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "displayName", "password", "updatedAt", "username") SELECT "createdAt", "displayName", "password", "updatedAt", "username" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
CREATE TABLE "new_UserPreferences" (
"username" TEXT NOT NULL PRIMARY KEY,
"toggleInputHotkey" TEXT DEFAULT '',
"toggleOutputHotkey" TEXT DEFAULT '',
CONSTRAINT "UserPreferences_username_fkey" FOREIGN KEY ("username") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_UserPreferences" ("toggleInputHotkey", "toggleOutputHotkey", "username") SELECT "toggleInputHotkey", "toggleOutputHotkey", "username" FROM "UserPreferences";
DROP TABLE "UserPreferences";
ALTER TABLE "new_UserPreferences" RENAME TO "UserPreferences";
CREATE UNIQUE INDEX "UserPreferences_username_key" ON "UserPreferences"("username");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,21 @@
/*
Warnings:
- You are about to drop the column `username` on the `Session` table. All the data in the column will be lost.
- Added the required column `userId` to the `Session` table without a default value. This is not possible if the table is not empty.
*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Session" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Session" ("expiresAt", "id") SELECT "expiresAt", "id" FROM "Session";
DROP TABLE "Session";
ALTER TABLE "new_Session" RENAME TO "Session";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -0,0 +1,17 @@
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Attachment" (
"id" TEXT NOT NULL PRIMARY KEY,
"username" TEXT,
"name" TEXT NOT NULL,
"mimetype" TEXT NOT NULL,
"size" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Attachment_username_fkey" FOREIGN KEY ("username") REFERENCES "User" ("username") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_Attachment" ("createdAt", "id", "mimetype", "name", "size") SELECT "createdAt", "id", "mimetype", "name", "size" FROM "Attachment";
DROP TABLE "Attachment";
ALTER TABLE "new_Attachment" RENAME TO "Attachment";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;

View File

@@ -8,13 +8,13 @@ generator client {
} }
model User { model User {
id String @id @default(cuid()) username String @id @unique
username String @unique
password String password String
displayName String displayName String
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
Attachments Attachment[]
Session Session[] Session Session[]
UserPreferences UserPreferences? UserPreferences UserPreferences?
Messages Message[] Messages Message[]
@@ -26,37 +26,37 @@ model Session {
userId String userId String
expiresAt DateTime expiresAt DateTime
user User @relation(references: [id], fields: [userId], onDelete: Cascade) user User @relation(references: [username], fields: [userId], onDelete: Cascade)
@@index([userId])
} }
model UserPreferences { model UserPreferences {
userId String @id @unique username String @id @unique
toggleInputHotkey String? @default("") toggleInputHotkey String? @default("")
toggleOutputHotkey String? @default("") toggleOutputHotkey String? @default("")
user User @relation(references: [id], fields: [userId], onDelete: Cascade) user User @relation(references: [username], fields: [username], onDelete: Cascade)
} }
model Attachment { model Attachment {
id String @id @default(uuid()) id String @id @default(uuid())
username String?
name String name String
mimetype String mimetype String
size Int size Int
createdAt DateTime @default(now()) createdAt DateTime @default(now())
user User? @relation(references: [username], fields: [username], onDelete: Cascade)
message MessageAttachment[] message MessageAttachment[]
} }
model Message { model Message {
id String @id @default(uuid()) id String @id @default(uuid())
text String text String
senderId String? senderUsername String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
sender User? @relation(references: [id], fields: [senderId], onDelete: SetNull) sender User? @relation(references: [username], fields: [senderUsername], onDelete: SetNull)
attachments MessageAttachment[] attachments MessageAttachment[]
} }
@@ -72,9 +72,9 @@ model MessageAttachment {
model Channel { model Channel {
id String @id @default(uuid()) id String @id @default(uuid())
ownerId String? ownerUsername String?
name String name String
persistent Boolean persistent Boolean
owner User? @relation(references: [id], fields: [ownerId], onDelete: Cascade) owner User? @relation(references: [username], fields: [ownerUsername], onDelete: Cascade)
} }

View File

@@ -27,6 +27,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
}, },
}, },
async (req, reply) => { async (req, reply) => {
const user = req.user!
const data = await req.file() const data = await req.file()
if (!data) { if (!data) {
@@ -36,6 +37,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const meta = await fastify.prisma.attachment.create({ const meta = await fastify.prisma.attachment.create({
data: { data: {
name: data.filename, name: data.filename,
username: user.username,
mimetype: data.mimetype, mimetype: data.mimetype,
size: 0, size: 0,
}, },
@@ -47,13 +49,25 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const filePath = path.join(process.cwd(), 'uploads', meta.id) const filePath = path.join(process.cwd(), 'uploads', meta.id)
let fileSize = 0
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
const writeStream = fs.createWriteStream(filePath) const writeStream = fs.createWriteStream(filePath)
data.file.pipe(writeStream) data.file.pipe(writeStream)
data.file.on('data', (chunk) => {
fileSize += chunk.length
})
data.file.on('end', resolve) data.file.on('end', resolve)
data.file.on('error', reject) data.file.on('error', reject)
}) })
await fastify.prisma.attachment.update({
where: { id: meta.id },
data: { size: fileSize },
})
// await new Promise(resolve => setTimeout(resolve, Math.random() * 10000))
return meta.id return meta.id
}, },
) )

View File

@@ -33,13 +33,12 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
}, },
}) })
const session = await fastify.lucia.createSession(user.id, {}) const session = await fastify.lucia.createSession(user.username, {})
const cookie = fastify.lucia.createSessionCookie(session.id) const cookie = fastify.lucia.createSessionCookie(session.id)
reply.setCookie(cookie.name, cookie.value, cookie.attributes) reply.setCookie(cookie.name, cookie.value, cookie.attributes)
return { return {
id: user.id,
username: user.username, username: user.username,
displayName: user.username, displayName: user.username,
createdAt: user.createdAt.toISOString(), createdAt: user.createdAt.toISOString(),
@@ -67,7 +66,6 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const user = await fastify.prisma.user.findFirst({ const user = await fastify.prisma.user.findFirst({
where: { username: req.body.username }, where: { username: req.body.username },
select: { select: {
id: true,
username: true, username: true,
displayName: true, displayName: true,
createdAt: true, createdAt: true,
@@ -84,7 +82,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
return reply.notFound('Incorrect username or password') return reply.notFound('Incorrect username or password')
} }
const session = await fastify.lucia.createSession(user.id, {}) const session = await fastify.lucia.createSession(user.username, {})
const cookie = fastify.lucia.createSessionCookie(session.id) const cookie = fastify.lucia.createSessionCookie(session.id)
reply.setCookie(cookie.name, cookie.value, cookie.attributes) reply.setCookie(cookie.name, cookie.value, cookie.attributes)
@@ -112,7 +110,6 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const user = req.user! const user = req.user!
return { return {
id: user.id,
username: user.username, username: user.username,
displayName: user.displayName, displayName: user.displayName,
createdAt: user.createdAt.toISOString(), createdAt: user.createdAt.toISOString(),

View File

@@ -41,7 +41,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const channel = await fastify.prisma.channel.create({ const channel = await fastify.prisma.channel.create({
data: { data: {
name: req.body.name, name: req.body.name,
ownerId: user.id, ownerUsername: user.username,
persistent: req.body.persistent, persistent: req.body.persistent,
}, },
}) })
@@ -73,7 +73,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
try { try {
const channel = await fastify.prisma.channel.delete({ const channel = await fastify.prisma.channel.delete({
where: { id: req.params.id, ownerId: user.id }, where: { id: req.params.id, ownerUsername: user.username },
}) })
fastify.bus.emit('channel:removed', channel) fastify.bus.emit('channel:removed', channel)

View File

@@ -1,6 +1,7 @@
import type { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' import type { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox'
import { Type } from 'typebox' import { Type } from 'typebox'
import { ChatMessageSchema, NewChatMessagePayloadSchema } from '../plugins/schemas/chat.ts' import { ChatMessageSchema, NewChatMessagePayloadSchema } from '../plugins/schemas/chat.ts'
import { TypeboxRef } from '../utils/typebox-ref.ts'
const plugin: FastifyPluginAsyncTypebox = async (fastify) => { const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
fastify.post( fastify.post(
@@ -10,9 +11,9 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
summary: 'Send message', summary: 'Send message',
tags: ['Chat'], tags: ['Chat'],
operationId: 'chat.send', operationId: 'chat.send',
body: NewChatMessagePayloadSchema, body: TypeboxRef(NewChatMessagePayloadSchema),
response: { response: {
200: ChatMessageSchema, 200: TypeboxRef(ChatMessageSchema),
}, },
}, },
}, },
@@ -22,7 +23,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const message = await fastify.prisma.message.create({ const message = await fastify.prisma.message.create({
data: { data: {
text: req.body.text, text: req.body.text,
senderId: user.id, senderUsername: user.username,
attachments: { attachments: {
create: (req.body.attachments ?? []).map((attachmentId) => { create: (req.body.attachments ?? []).map((attachmentId) => {
return { return {
@@ -35,6 +36,13 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
}), }),
}, },
}, },
include: {
attachments: {
include: {
attachment: true,
},
},
},
}) })
if (!message) { if (!message) {
@@ -43,11 +51,11 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const response = { const response = {
id: message.id, id: message.id,
senderId: user.id, senderUsername: user.username,
text: message.text, text: message.text,
createdAt: message.createdAt.toISOString(), createdAt: message.createdAt.toISOString(),
updatedAt: message.updatedAt.toISOString(), updatedAt: message.updatedAt.toISOString(),
attachments: req.body.attachments ?? [], attachments: message.attachments.map(({ attachment }) => attachment),
} }
fastify.bus.emit('chat:new-message', response) fastify.bus.emit('chat:new-message', response)
@@ -69,7 +77,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
}), }),
response: { response: {
200: Type.Object({ 200: Type.Object({
messages: Type.Array(ChatMessageSchema), messages: Type.Array(TypeboxRef(ChatMessageSchema)),
nextCursor: Type.Optional(Type.String({ format: 'uuid', description: 'Cursor to last message' })), nextCursor: Type.Optional(Type.String({ format: 'uuid', description: 'Cursor to last message' })),
}), }),
}, },
@@ -81,7 +89,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const messages = await fastify.prisma.message.findMany({ const messages = await fastify.prisma.message.findMany({
orderBy: { createdAt: 'desc' }, orderBy: { createdAt: 'desc' },
take: req.query.limit + 1, take: req.query.limit + 1,
include: { attachments: true }, include: { attachments: { include: { attachment: true } } },
...(req.query.cursor && { ...(req.query.cursor && {
cursor: { cursor: {
id: req.query.cursor, id: req.query.cursor,
@@ -99,7 +107,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
...message, ...message,
createdAt: message.createdAt.toISOString(), createdAt: message.createdAt.toISOString(),
updatedAt: message.updatedAt.toISOString(), updatedAt: message.updatedAt.toISOString(),
attachments: message.attachments.map(({ attachmentId }) => attachmentId), attachments: message.attachments.map(({ attachment }) => attachment),
} }
}), }),
nextCursor: cursorMessage?.id, nextCursor: cursorMessage?.id,

View File

@@ -19,9 +19,8 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
}, },
async (req, reply) => { async (req, reply) => {
const user = await fastify.prisma.user.findFirst({ const user = await fastify.prisma.user.findFirst({
where: { username: req.query.username, id: req.query.id }, where: { username: req.query.username },
select: { select: {
id: true,
username: true, username: true,
displayName: true, displayName: true,
createdAt: true, createdAt: true,
@@ -55,8 +54,8 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const user = req.user! const user = req.user!
const preferences = await fastify.prisma.userPreferences.upsert({ const preferences = await fastify.prisma.userPreferences.upsert({
where: { userId: user.id }, where: { username: user.username },
create: { userId: user.id }, create: { username: user.username },
update: {}, update: {},
}) })
@@ -81,9 +80,9 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const user = req.user! const user = req.user!
return fastify.prisma.userPreferences.upsert({ return fastify.prisma.userPreferences.upsert({
where: { userId: user.id }, where: { username: user.username },
create: { create: {
userId: user.id, username: user.username,
...req.body, ...req.body,
}, },
update: req.body, update: req.body,
@@ -108,12 +107,11 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
const user = req.user! const user = req.user!
const updatedUser = await fastify.prisma.user.update({ const updatedUser = await fastify.prisma.user.update({
where: { id: user.id }, where: { username: user.username },
data: { data: {
displayName: req.body.displayName, displayName: req.body.displayName,
}, },
select: { select: {
id: true,
username: true, username: true,
displayName: true, displayName: true,
createdAt: true, createdAt: true,

View File

@@ -105,7 +105,12 @@ fastify.register(FastifyCors, {
}) })
fastify.register(FastifyCookie) fastify.register(FastifyCookie)
fastify.register(FastifyMultipart) fastify.register(FastifyMultipart, {
limits: {
files: 10,
fileSize: 500 * 1024 * 1024,
},
})
fastify.register(FastifyAutoLoad, { fastify.register(FastifyAutoLoad, {
dir: join(__dirname, 'plugins'), dir: join(__dirname, 'plugins'),