diff --git a/apps/recorder/.devcontainer/Dockerfile b/.devcontainer.bk/Dockerfile similarity index 100% rename from apps/recorder/.devcontainer/Dockerfile rename to .devcontainer.bk/Dockerfile diff --git a/apps/recorder/.devcontainer/devcontainer.json b/.devcontainer.bk/devcontainer.json similarity index 100% rename from apps/recorder/.devcontainer/devcontainer.json rename to .devcontainer.bk/devcontainer.json diff --git a/apps/recorder/.devcontainer/docker-compose.yml b/.devcontainer.bk/docker-compose.yml similarity index 100% rename from apps/recorder/.devcontainer/docker-compose.yml rename to .devcontainer.bk/docker-compose.yml diff --git a/apps/app/.env.development b/apps/app/.env.development deleted file mode 100644 index d0abda2..0000000 --- a/apps/app/.env.development +++ /dev/null @@ -1,29 +0,0 @@ -# Server -AUTH_TYPE="basic" # - -BASIC_USER="konobangu" -BASIC_PASSWORD="konobangu" - -OIDC_PROVIDER_ENDPOINT="https://some-oidc-auth.com/oidc/.well-known/openid-configuration" -OIDC_CLIENT_ID="" -OIDC_CLIENT_SECRET="" -OIDC_ISSUER="https://some-oidc-auth.com/oidc" -OIDC_AUDIENCE="https://konobangu.com/api" -OIDC_ICON_URL="" -OIDC_EXTRA_SCOPE_REGEX="" -OIDC_EXTRA_CLAIM_KEY="" -OIDC_EXTRA_CLAIM_VALUE="" - -DATABASE_URL="postgres://konobangu:konobangu@127.0.0.1:5432/konobangu" -BETTERSTACK_API_KEY="" -BETTERSTACK_URL="" -FLAGS_SECRET="" -ARCJET_KEY="" -SVIX_TOKEN="" -LIVEBLOCKS_SECRET="" - -# Client -NEXT_PUBLIC_APP_URL="http://localhost:5000" -NEXT_PUBLIC_WEB_URL="http://localhost:5001" -NEXT_PUBLIC_DOCS_URL="http://localhost:5004" -NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL="https://konobangu.com" \ No newline at end of file diff --git a/apps/app/.env.example b/apps/app/.env.example deleted file mode 100644 index 059e679..0000000 --- a/apps/app/.env.example +++ /dev/null @@ -1,29 +0,0 @@ -# AUTH -AUTH_TYPE="basic" - -NEXT_PUBLIC_OIDC_PROVIDER_ENDPOINT="https://some-oidc-auth.com/oidc/.well-known/openid-configuration" -NEXT_PUBLIC_OIDC_CLIENT_ID="" -NEXT_PUBLIC_OIDC_CLIENT_SECRET="" -NEXT_PUBLIC_OIDC_ICON_URL="" -OIDC_ISSUER="https://some-oidc-auth.com/oidc" -OIDC_AUDIENCE="https://konobangu.com/api" -OIDC_EXTRA_SCOPES="" # 如 "read:konobangu,write:konobangu" -OIDC_EXTRA_CLAIM_KEY="" -OIDC_EXTRA_CLAIM_VALUE="" - -# DATABASE -DATABASE_URL="postgres://konobangu:konobangu@127.0.0.1:5432/konobangu" - -# SERVER MISC -BETTERSTACK_API_KEY="" -BETTERSTACK_URL="" -FLAGS_SECRET="" -ARCJET_KEY="" -SVIX_TOKEN="" -LIVEBLOCKS_SECRET="" - -# WEBUI -NEXT_PUBLIC_APP_URL="http://localhost:5000" -NEXT_PUBLIC_WEB_URL="http://localhost:5001" -NEXT_PUBLIC_DOCS_URL="http://localhost:5004" -NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL="https://konobangu.com" \ No newline at end of file diff --git a/apps/app/.gitignore b/apps/app/.gitignore deleted file mode 100644 index 9045095..0000000 --- a/apps/app/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts - -# prisma -.env - -# react.email -.react-email - -# Sentry -.sentryclirc diff --git a/apps/app/__tests__/sign-in.test.tsx b/apps/app/__tests__/sign-in.test.tsx deleted file mode 100644 index 5bd4c28..0000000 --- a/apps/app/__tests__/sign-in.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { expect, test } from 'vitest'; -import Page from '../app/(unauthenticated)/sign-in/[[...sign-in]]/page'; - -test('Sign In Page', () => { - render(); - expect( - screen.getByRole('heading', { - level: 1, - name: 'Welcome back', - }) - ).toBeDefined(); -}); diff --git a/apps/app/__tests__/sign-up.test.tsx b/apps/app/__tests__/sign-up.test.tsx deleted file mode 100644 index 9a4dcbe..0000000 --- a/apps/app/__tests__/sign-up.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { expect, test } from 'vitest'; -import Page from '../app/(unauthenticated)/sign-up/[[...sign-up]]/page'; - -test('Sign Up Page', () => { - render(); - expect( - screen.getByRole('heading', { - level: 1, - name: 'Create an account', - }) - ).toBeDefined(); -}); diff --git a/apps/app/app/(authenticated)/components/avatar-stack.tsx b/apps/app/app/(authenticated)/components/avatar-stack.tsx deleted file mode 100644 index 1e926d5..0000000 --- a/apps/app/app/(authenticated)/components/avatar-stack.tsx +++ /dev/null @@ -1,59 +0,0 @@ -'use client'; - -import { useOthers, useSelf } from '@konobangu/collaboration/hooks'; -import { - Avatar, - AvatarFallback, - AvatarImage, -} from '@konobangu/design-system/components/ui/avatar'; -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from '@konobangu/design-system/components/ui/tooltip'; -import { tailwind } from '@konobangu/tailwind-config'; - -type PresenceAvatarProps = { - info?: Liveblocks['UserMeta']['info']; -}; - -const PresenceAvatar = ({ info }: PresenceAvatarProps) => ( - - - - - - {info?.name?.slice(0, 2)} - - - - -

{info?.name ?? 'Unknown'}

-
-
-); - -export const AvatarStack = () => { - const others = useOthers(); - const self = useSelf(); - const hasMoreUsers = others.length > 3; - - return ( -
- {others.slice(0, 3).map(({ connectionId, info }) => ( - - ))} - - {hasMoreUsers && ( - - )} - - {self && } -
- ); -}; diff --git a/apps/app/app/(authenticated)/components/collaboration-provider.tsx b/apps/app/app/(authenticated)/components/collaboration-provider.tsx deleted file mode 100644 index 94bb373..0000000 --- a/apps/app/app/(authenticated)/components/collaboration-provider.tsx +++ /dev/null @@ -1,48 +0,0 @@ -'use client'; - -import { getUsers } from '@/app/actions/users/get'; -import { searchUsers } from '@/app/actions/users/search'; -import { Room } from '@konobangu/collaboration/room'; -import type { ReactNode } from 'react'; - -export const CollaborationProvider = ({ - orgId, - children, -}: { - orgId: string; - children: ReactNode; -}) => { - const resolveUsers = async ({ userIds }: { userIds: string[] }) => { - const response = await getUsers(userIds); - - if ('error' in response) { - throw new Error('Problem resolving users'); - } - - return response.data; - }; - - const resolveMentionSuggestions = async ({ text }: { text: string }) => { - const response = await searchUsers(text); - - if ('error' in response) { - throw new Error('Problem resolving mention suggestions'); - } - - return response.data; - }; - - return ( - Loading... - } - resolveUsers={resolveUsers} - resolveMentionSuggestions={resolveMentionSuggestions} - > - {children} - - ); -}; diff --git a/apps/app/app/(authenticated)/components/cursors.tsx b/apps/app/app/(authenticated)/components/cursors.tsx deleted file mode 100644 index d630598..0000000 --- a/apps/app/app/(authenticated)/components/cursors.tsx +++ /dev/null @@ -1,106 +0,0 @@ -'use client'; - -import { useMyPresence, useOthers } from '@konobangu/collaboration/hooks'; -import { useEffect } from 'react'; - -const Cursor = ({ - name, - color, - x, - y, -}: { - name: string | undefined; - color: string; - x: number; - y: number; -}) => ( -
- - Cursor - - -
- {name} -
-
-); - -export const Cursors = () => { - /** - * useMyPresence returns the presence of the current user and a function to update it. - * updateMyPresence is different than the setState function returned by the useState hook from React. - * You don't need to pass the full presence object to update it. - * See https://liveblocks.io/docs/api-reference/liveblocks-react#useMyPresence for more information - */ - const [_cursor, updateMyPresence] = useMyPresence(); - - /** - * Return all the other users in the room and their presence (a cursor position in this case) - */ - const others = useOthers(); - - useEffect(() => { - const onPointerMove = (event: PointerEvent) => { - // Update the user cursor position on every pointer move - updateMyPresence({ - cursor: { - x: Math.round(event.clientX), - y: Math.round(event.clientY), - }, - }); - }; - - const onPointerLeave = () => { - // When the pointer goes out, set cursor to null - updateMyPresence({ - cursor: null, - }); - }; - - document.body.addEventListener('pointermove', onPointerMove); - document.body.addEventListener('pointerleave', onPointerLeave); - - return () => { - document.body.removeEventListener('pointermove', onPointerMove); - document.body.removeEventListener('pointerleave', onPointerLeave); - }; - }, [updateMyPresence]); - - return others.map(({ connectionId, presence, info }) => { - if (!presence.cursor) { - return null; - } - - return ( - - ); - }); -}; diff --git a/apps/app/app/(authenticated)/components/header.tsx b/apps/app/app/(authenticated)/components/header.tsx deleted file mode 100644 index 138eb88..0000000 --- a/apps/app/app/(authenticated)/components/header.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator, -} from '@konobangu/design-system/components/ui/breadcrumb'; -import { Separator } from '@konobangu/design-system/components/ui/separator'; -import { SidebarTrigger } from '@konobangu/design-system/components/ui/sidebar'; -import { Fragment, type ReactNode } from 'react'; - -type HeaderProps = { - pages: string[]; - page: string; - children?: ReactNode; -}; - -export const Header = ({ pages, page, children }: HeaderProps) => ( -
-
- - - - - {pages.map((page, index) => ( - - {index > 0 && } - - {page} - - - ))} - - - {page} - - - -
- {children} -
-); diff --git a/apps/app/app/(authenticated)/components/posthog-identifier.tsx b/apps/app/app/(authenticated)/components/posthog-identifier.tsx deleted file mode 100644 index bda1472..0000000 --- a/apps/app/app/(authenticated)/components/posthog-identifier.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client'; - -import { analytics } from '@konobangu/analytics/client'; -import { useSession } from '@konobangu/auth/client'; -import { usePathname, useSearchParams } from 'next/navigation'; -import { useEffect, useRef } from 'react'; - -export const PostHogIdentifier = () => { - const session = useSession(); - const user = session?.data?.user; - const identified = useRef(false); - const pathname = usePathname(); - const searchParams = useSearchParams(); - - useEffect(() => { - // Track pageviews - if (pathname && analytics) { - let url = window.origin + pathname; - if (searchParams.toString()) { - url = `${url}?${searchParams.toString()}`; - } - analytics.capture('$pageview', { - $current_url: url, - }); - } - }, [pathname, searchParams]); - - useEffect(() => { - if (!user || identified.current) { - return; - } - - analytics.identify(user.id, { - email: user.email, - name: user.name, - createdAt: user.createdAt, - avatar: user.image, - }); - - identified.current = true; - }, [user]); - - return null; -}; diff --git a/apps/app/app/(authenticated)/components/sidebar.tsx b/apps/app/app/(authenticated)/components/sidebar.tsx deleted file mode 100644 index 5a5c103..0000000 --- a/apps/app/app/(authenticated)/components/sidebar.tsx +++ /dev/null @@ -1,342 +0,0 @@ -'use client'; - -// import { OrganizationSwitcher, UserButton } from '@konobangu/auth/client'; -import { ModeToggle } from '@konobangu/design-system/components/mode-toggle'; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from '@konobangu/design-system/components/ui/collapsible'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from '@konobangu/design-system/components/ui/dropdown-menu'; -import { - Sidebar, - SidebarContent, - SidebarFooter, - SidebarGroup, - SidebarGroupContent, - SidebarGroupLabel, - SidebarHeader, - SidebarInset, - SidebarMenu, - SidebarMenuAction, - SidebarMenuButton, - SidebarMenuItem, - SidebarMenuSub, - SidebarMenuSubButton, - SidebarMenuSubItem, - useSidebar, -} from '@konobangu/design-system/components/ui/sidebar'; -import { cn } from '@konobangu/design-system/lib/utils'; -import { - AnchorIcon, - BookOpenIcon, - BotIcon, - ChevronRightIcon, - FolderIcon, - FrameIcon, - LifeBuoyIcon, - MapIcon, - MoreHorizontalIcon, - PieChartIcon, - SendIcon, - Settings2Icon, - ShareIcon, - SquareTerminalIcon, - Trash2Icon, -} from 'lucide-react'; -import type { ReactNode } from 'react'; - -type GlobalSidebarProperties = { - readonly children: ReactNode; -}; - -const data = { - user: { - name: 'shadcn', - email: 'm@example.com', - avatar: '/avatars/shadcn.jpg', - }, - navMain: [ - { - title: 'Playground', - url: '#', - icon: SquareTerminalIcon, - isActive: true, - items: [ - { - title: 'History', - url: '#', - }, - { - title: 'Starred', - url: '#', - }, - { - title: 'Settings', - url: '#', - }, - ], - }, - { - title: 'Models', - url: '#', - icon: BotIcon, - items: [ - { - title: 'Genesis', - url: '#', - }, - { - title: 'Explorer', - url: '#', - }, - { - title: 'Quantum', - url: '#', - }, - ], - }, - { - title: 'Documentation', - url: '#', - icon: BookOpenIcon, - items: [ - { - title: 'Introduction', - url: '#', - }, - { - title: 'Get Started', - url: '#', - }, - { - title: 'Tutorials', - url: '#', - }, - { - title: 'Changelog', - url: '#', - }, - ], - }, - { - title: 'Settings', - url: '#', - icon: Settings2Icon, - items: [ - { - title: 'General', - url: '#', - }, - { - title: 'Team', - url: '#', - }, - { - title: 'Billing', - url: '#', - }, - { - title: 'Limits', - url: '#', - }, - ], - }, - ], - navSecondary: [ - { - title: 'Webhooks', - url: '/webhooks', - icon: AnchorIcon, - }, - { - title: 'Support', - url: '#', - icon: LifeBuoyIcon, - }, - { - title: 'Feedback', - url: '#', - icon: SendIcon, - }, - ], - projects: [ - { - name: 'Design Engineering', - url: '#', - icon: FrameIcon, - }, - { - name: 'Sales & Marketing', - url: '#', - icon: PieChartIcon, - }, - { - name: 'Travel', - url: '#', - icon: MapIcon, - }, - ], -}; - -export const GlobalSidebar = ({ children }: GlobalSidebarProperties) => { - const sidebar = useSidebar(); - - return ( - <> - - - - -
div]:w-full', - sidebar.open ? '' : '-mx-1' - )} - > - {/* */} -
-
-
-
- - - Platform - - {data.navMain.map((item) => ( - - - - - - {item.title} - - - {item.items?.length ? ( - <> - - - - Toggle - - - - - {item.items?.map((subItem) => ( - - - - {subItem.title} - - - - ))} - - - - ) : null} - - - ))} - - - - Projects - - {data.projects.map((item) => ( - - - - - {item.name} - - - - - - - More - - - - - - View Project - - - - Share Project - - - - - Delete Project - - - - - ))} - - - - More - - - - - - - - {data.navSecondary.map((item) => ( - - - - - {item.title} - - - - ))} - - - - - - - - {/* */} - - - - -
- {children} - - ); -}; diff --git a/apps/app/app/(authenticated)/layout.tsx b/apps/app/app/(authenticated)/layout.tsx deleted file mode 100644 index ccf64bd..0000000 --- a/apps/app/app/(authenticated)/layout.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { getSessionFromHeaders } from '@konobangu/auth/server'; -import { SidebarProvider } from '@konobangu/design-system/components/ui/sidebar'; -import { env } from '@konobangu/env'; -import { showBetaFeature } from '@konobangu/feature-flags'; -import { secure } from '@konobangu/security'; -import { redirect } from 'next/navigation'; -import type { ReactNode } from 'react'; -import { PostHogIdentifier } from './components/posthog-identifier'; -import { GlobalSidebar } from './components/sidebar'; - -type AppLayoutProperties = { - readonly children: ReactNode; -}; - -const AppLayout = async ({ children }: AppLayoutProperties) => { - if (env.ARCJET_KEY) { - await secure(['CATEGORY:PREVIEW']); - } - - const { user } = await getSessionFromHeaders(); - - if (!user) { - return redirect('/sign-in'); // from next/navigation - } - const betaFeature = await showBetaFeature(); - - return ( - - - {betaFeature && ( -
- Beta feature now available -
- )} - {children} -
- -
- ); -}; - -export default AppLayout; diff --git a/apps/app/app/(authenticated)/page.tsx b/apps/app/app/(authenticated)/page.tsx deleted file mode 100644 index ddaafd1..0000000 --- a/apps/app/app/(authenticated)/page.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { getSessionFromHeaders } from '@konobangu/auth/server'; -import { database } from '@konobangu/database'; -import { env } from '@konobangu/env'; -import type { Metadata } from 'next'; -import dynamic from 'next/dynamic'; -import { notFound } from 'next/navigation'; -import { AvatarStack } from './components/avatar-stack'; -import { Cursors } from './components/cursors'; -import { Header } from './components/header'; - -const title = 'Acme Inc'; -const description = 'My application.'; - -const CollaborationProvider = dynamic(() => - import('./components/collaboration-provider').then( - (mod) => mod.CollaborationProvider - ) -); - -export const metadata: Metadata = { - title, - description, -}; - -const App = async () => { - const pages = await database.selectFrom('page').selectAll().execute(); - const { orgId } = await getSessionFromHeaders(); - - if (!orgId) { - notFound(); - } - - return ( - <> -
- {env.LIVEBLOCKS_SECRET && ( - - - - - )} -
-
-
- {pages.map((page) => ( -
- {page.name} -
- ))} -
-
-
- - ); -}; - -export default App; diff --git a/apps/app/app/(authenticated)/webhooks/page.tsx b/apps/app/app/(authenticated)/webhooks/page.tsx deleted file mode 100644 index b0bae17..0000000 --- a/apps/app/app/(authenticated)/webhooks/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { webhooks } from '@konobangu/webhooks'; -import { notFound } from 'next/navigation'; - -export const metadata = { - title: 'Webhooks', - description: 'Send webhooks to your users.', -}; - -const WebhooksPage = async () => { - const response = await webhooks.getAppPortal(); - - if (!response?.url) { - notFound(); - } - - return ( -
-