Skip to content

Commit

Permalink
chore: initial work on clerk migration (not working)
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-bo-davis committed May 13, 2024
1 parent 7aef6d5 commit 09b87d7
Show file tree
Hide file tree
Showing 24 changed files with 426 additions and 194 deletions.
301 changes: 276 additions & 25 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion remix/app/.server/models/user/userModel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ChatInsert, User, UserInsert } from '@remix/.server/db';
import { isError, newError, promiseMayFail } from '@remix/.server/errors';
import { db, chatSchema, userSchema, messageSchema } from '@remix/.server/db';
import { db, userSchema } from '@remix/.server/db';
import * as chatModel from '@remix/.server/models/chat/chatModel';

export const ERRORS = {
Expand Down
22 changes: 11 additions & 11 deletions remix/app/.server/services/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Auth0Profile } from 'remix-auth-auth0';
import type { ServiceCommonParams } from './types';
import type { ServiceCommonArgs } from './types';

import { createCookieSessionStorage, redirect } from '@remix-run/node';
import { Authenticator } from 'remix-auth';
Expand Down Expand Up @@ -60,19 +60,19 @@ export const { commitSession, destroySession } = sessionStorage;

export const isAuthenticated = () => auth.isAuthenticated;

export const getSession = async ({ request }: ServiceCommonParams) => {
export const getSession = async ({ request }: ServiceCommonArgs) => {
if (!request?.headers.has('Cookie')) return null;
const session = await sessionStorage.getSession(
request.headers.get('Cookie'),
);
return session;
};

export type LogoutParams = ServiceCommonParams & {
export type LogoutArgs = ServiceCommonArgs & {
returnToPath?: string;
};

export const getLogoutURL = ({ request, returnToPath = '/' }: LogoutParams) => {
export const getLogoutURL = ({ request, returnToPath = '/' }: LogoutArgs) => {
// Parse the request URL to get the origin and replace the path
const url = new URL(request.url);
const returnToURL = new URL(returnToPath, url.origin);
Expand All @@ -84,8 +84,8 @@ export const getLogoutURL = ({ request, returnToPath = '/' }: LogoutParams) => {
return logoutURL.toString();
};

export const getLogoutOptions = async (params: ServiceCommonParams) => {
const session = await getSession(params);
export const getLogoutOptions = async (args: ServiceCommonArgs) => {
const session = await getSession(args);
if (!session) return newError({ code: 'auth:noSession' });

return {
Expand All @@ -95,17 +95,17 @@ export const getLogoutOptions = async (params: ServiceCommonParams) => {
};
};

export const logout = async (params: LogoutParams) => {
const logoutUrl = getLogoutURL(params);
const logoutOptions = await getLogoutOptions(params);
export const logout = async (args: LogoutArgs) => {
const logoutUrl = getLogoutURL(args);
const logoutOptions = await getLogoutOptions(args);
if (isError(logoutOptions)) throw redirect('/');

throw redirect(logoutUrl, logoutOptions);
};

export const getAuthProfile = async ({ request }: ServiceCommonParams) => {
export const getAuthProfile = async (args: ServiceCommonArgs) => {
if (getConfig('user.userAutoLogin')) return { id: 'mock-user' };
const session = await getSession({ request });
const session = await getSession(args);

if (!session) return null;
return session.data.user;
Expand Down
55 changes: 27 additions & 28 deletions remix/app/.server/services/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
AgentEmitterChannels,
AgentHistoryItem,
} from '@codellm/core';
import type { ServiceCommonParams } from './types.js';
import type { ServiceCommonArgs } from './types.js';

import { EventEmitter } from 'events';
import { remember } from '@epic-web/remember';
Expand Down Expand Up @@ -42,14 +42,13 @@ const eventStreamEmitter = remember(
export const getEventStreamEmitter = () => eventStreamEmitter;

// TODO: we're going to need channels for this eventually
const onAgentEmit =
(chatId: User['id']) => async (params: AgentHistoryItem) => {
const chat = await chatModel.getById(chatId);
if (isError(chat)) return chat;
await chat.addMessage(params);
log('onAgentEmit emitting', 'debug', params);
eventStreamEmitter.emit(`agent:${chatId}`, params);
};
const onAgentEmit = (chatId: User['id']) => async (args: AgentHistoryItem) => {
const chat = await chatModel.getById(chatId);
if (isError(chat)) return chat;
await chat.addMessage(args);
log('onAgentEmit emitting', 'debug', args);
eventStreamEmitter.emit(`agent:${chatId}`, args);
};

const onEmitListeners = (client: Agent, id: Chat['id']) =>
channelsToForward.map((channel) => client.onEmit(channel, onAgentEmit(id)));
Expand Down Expand Up @@ -90,12 +89,12 @@ export const _getOrCreateClient = async (id: Chat['id']) => {
return newLock;
};

export type ChatCommonParams = ServiceCommonParams & {
export type ChatCommonArgs = ServiceCommonArgs & {
id: Chat['id'];
};

export const createChat = async (params: ServiceCommonParams) => {
const user = await getValidatedUser(params);
export const createChat = async (args: ServiceCommonArgs) => {
const user = await getValidatedUser(args);
if (isError(user)) return user;

const chat = await user.addChat({ name: 'new chat' });
Expand All @@ -108,7 +107,7 @@ export const createChat = async (params: ServiceCommonParams) => {
return { client, ...chat };
};

export const getChat = async ({ id, request }: ChatCommonParams) => {
export const getChat = async ({ id }: ChatCommonArgs) => {
const chat = await chatModel.getById(id);
if (isError(chat)) return chat;

Expand All @@ -118,26 +117,26 @@ export const getChat = async ({ id, request }: ChatCommonParams) => {
return { client, ...chat };
};

export const deleteChat = async (params: ChatCommonParams) => {
const chat = await getChat(params);
export const deleteChat = async (args: ChatCommonArgs) => {
const chat = await getChat(args);
if (isError(chat)) return chat;

offEmitListeners(chat.client as Agent, params.id);
offEmitListeners(chat.client as Agent, args.id);
await chat.destroy();
};

export const getChats = async (params: ServiceCommonParams) => {
const user = await getValidatedUser(params);
export const getChats = async (args: ServiceCommonArgs) => {
const user = await getValidatedUser(args);
if (isError(user)) return user;

return user.getChats();
};

export type UpdateChatParams = ChatCommonParams & {
export type UpdateChatArgs = ChatCommonArgs & {
update: ChatUpdate;
};

export const updateChat = async ({ id, update }: UpdateChatParams) => {
export const updateChat = async ({ id, update }: UpdateChatArgs) => {
const chat = await chatModel.getById(id);
if (isError(chat)) return chat;

Expand All @@ -146,8 +145,8 @@ export const updateChat = async ({ id, update }: UpdateChatParams) => {
return updatedChat;
};

export const getMostRecentChat = async (params: ServiceCommonParams) => {
const user = await getValidatedUser(params);
export const getMostRecentChat = async (args: ServiceCommonArgs) => {
const user = await getValidatedUser(args);
if (isError(user)) return user;

const chats = await user.getChats();
Expand All @@ -156,15 +155,15 @@ export const getMostRecentChat = async (params: ServiceCommonParams) => {
return chats[0];
};

export type SendChatParams = ChatCommonParams & {
export type SendChatArgs = ChatCommonArgs & {
message: string;
};

export const sendChat = async (params: SendChatParams) => {
const chat = await getChat(params);
export const sendChat = async (args: SendChatArgs) => {
const chat = await getChat(args);
if (isError(chat)) return chat;

await updateChat({ ...params, update: { isLoading: true } });
await chat.client.chat(params.message);
await updateChat({ ...params, update: { isLoading: false } });
await updateChat({ ...args, update: { isLoading: true } });
await chat.client.chat(args.message);
await updateChat({ ...args, update: { isLoading: false } });
};
6 changes: 3 additions & 3 deletions remix/app/.server/services/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export type ServiceCommonParams = {
request: Request;
};
import type { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node';

export type ServiceCommonArgs = LoaderFunctionArgs | ActionFunctionArgs;
19 changes: 10 additions & 9 deletions remix/app/.server/services/user.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { ServiceCommonParams } from './types';
import type { ServiceCommonArgs } from './types';
import type { UserModel } from '@remix/.server/models';
import type { RemixError } from '@remix/.server/errors';

import { redirect } from '@remix-run/node';
import { getAuth } from '@clerk/remix/ssr.server';
import { userModel } from '@remix/.server/models';
import { getAuthProfile, logout } from '@remix/.server/services/auth';
import { isError, newError } from '@remix/.server/errors';

export const ERRORS = {
Expand All @@ -19,17 +18,19 @@ export const ERRORS = {
},
} as const;

export const getUser = async (params: ServiceCommonParams) => {
const authUser = await getAuthProfile(params);
if (!authUser) {
export const getUser = async (args: ServiceCommonArgs) => {
const authUser = await getAuth(args);
console.log('authUser', authUser);
if (!authUser.userId) {
return newError({
code: 'userService:noAuthUser',
message: 'No authenticated user found',
});
}

// @ts-expect-error - not fighting with types for now
const user = await userModel.getByAuth0Id(authUser.id);
if (isError(user, 'userModel:notFound')) return logout(params);
// if (isError(user, 'userModel:notFound')) return logout(args);
if (isError(user)) throw user;

return user;
Expand All @@ -43,8 +44,8 @@ export const validateUser = (user: UserModel | RemixError) => {
return user;
};

export const getValidatedUser = async (params: ServiceCommonParams) => {
const user = await getUser(params);
export const getValidatedUser = async (args: ServiceCommonArgs) => {
const user = await getUser(args);

return validateUser(user);
};
13 changes: 0 additions & 13 deletions remix/app/components/Layout.tsx

This file was deleted.

47 changes: 17 additions & 30 deletions remix/app/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import useUser from '@remix/components/hooks/useUser';
import { Form, Link } from '@remix-run/react';

Check failure on line 1 in remix/app/components/Navbar.tsx

View workflow job for this annotation

GitHub Actions / lint

'Form' is defined but never used

import { SignedIn, SignedOut, UserButton, useUser } from '@clerk/remix';

const Navbar = () => {
const { isAuthed, isVerified } = useUser();
const user = useUser();

console.log('user', user);

Check failure on line 8 in remix/app/components/Navbar.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
return (
<nav className="navbar bg-base-100">
<div className="navbar-start">
Expand All @@ -12,35 +14,20 @@ const Navbar = () => {
</Link>
</div>
<div className="navbar-end">
{isAuthed ? (
<>
{isVerified && (
<>
<Link
to="/chat"
prefetch="intent"
className="btn btn-ghost btn-sm"
>
Chat
</Link>
<Link
to="/import"
prefetch="intent"
className="btn btn-ghost btn-sm"
>
Import
</Link>
</>
)}
<Form method="post" action="/logout">
<button className="btn btn-ghost btn-sm">Logout</button>
</Form>
</>
) : (
<Form method="post" action="/#">
<SignedIn>
<Link to="/chat" prefetch="intent" className="btn btn-ghost btn-sm">
Chat
</Link>
<Link to="/import" prefetch="intent" className="btn btn-ghost btn-sm">
Import
</Link>
<UserButton />
</SignedIn>
<SignedOut>
<Link to="/#">
<button className="btn btn-ghost btn-sm">Login</button>
</Form>
)}
</Link>
</SignedOut>
</div>
</nav>
);
Expand Down
11 changes: 9 additions & 2 deletions remix/app/components/common/ContentWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
export const ContentWrapper = ({ children }: { children: React.ReactNode }) => {
export const ContentWrapper = ({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) => {
const myClassName = `p-5 border-2 border-primary rounded-lg ${className}`;
return (
<div className="bg-base-100 ">
<div className="p-5 border-2 border-primary rounded-lg">{children}</div>
<div className={myClassName}>{children}</div>
</div>
);
};
Expand Down
22 changes: 7 additions & 15 deletions remix/app/root.loader.server.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import type { LoaderFunctionArgs } from '@remix-run/node';
import { getAuth, rootAuthLoader } from '@clerk/remix/ssr.server';

Check failure on line 2 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

'getAuth' is defined but never used

import { getUser, validateUser } from '@remix/.server/services/user';

Check failure on line 4 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

'getUser' is defined but never used

Check failure on line 4 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

'validateUser' is defined but never used
import { initClient } from '@remix/.server/db/db';

Check failure on line 5 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

'initClient' is defined but never used
import { isError } from '@remix/.server/errors';

Check failure on line 6 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

'isError' is defined but never used
import { noAuthPayload } from '@remix/components/AuthProvider';

export const loader = async ({ request }: LoaderFunctionArgs) => {
await initClient();
const user = await getUser({ request });
if (isError(user)) return noAuthPayload;

const validatedUser = validateUser(user);
const isVerified = !isError(validatedUser);

return {
isAuthed: true,
isVerified,
user,
};
};
export const loader = async (args: LoaderFunctionArgs) =>
rootAuthLoader(args, (cbArgs) => {
console.log('cbArgs', cbArgs);

Check failure on line 10 in remix/app/root.loader.server.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
return {};
});

export type RootLoader = typeof loader;

Expand Down
Loading

0 comments on commit 09b87d7

Please # to comment.