refactor: merge playground into webui

This commit is contained in:
2025-03-07 01:50:53 +08:00
parent 383e6340ea
commit 27cdcdef58
100 changed files with 4119 additions and 3757 deletions

View File

@@ -1,24 +0,0 @@
{
"name": "recorder",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "rsbuild dev",
"build": "rsbuild build",
"preview": "rsbuild preview"
},
"dependencies": {
"@graphiql/react": "^0.28.2",
"@graphiql/toolkit": "^0.11.1",
"graphiql": "^3.8.3",
"graphql-ws": "^6.0.4",
"observable-hooks": "^4.2.4",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@rsbuild/plugin-react": "^1.1.1",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3"
}
}

View File

@@ -1,5 +0,0 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};

View File

@@ -1 +0,0 @@
../../../../assets/favicon.ico

View File

@@ -1,75 +0,0 @@
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';
export default defineConfig({
plugins: [pluginReact()],
html: {
favicon: './public/assets/favicon.ico',
// tags: [
// {
// tag: 'script',
// attrs: { src: 'https://cdn.tailwindcss.com' },
// },
// ],
},
tools: {
rspack: {
plugins: [TanStackRouterRspack()],
},
},
source: {
entry: {
index: './src/main.tsx',
},
define: {
'process.env.AUTH_TYPE': JSON.stringify(process.env.AUTH_TYPE),
'process.env.OIDC_CLIENT_ID': JSON.stringify(process.env.OIDC_CLIENT_ID),
'process.env.OIDC_CLIENT_SECRET': JSON.stringify(
process.env.OIDC_CLIENT_SECRET
),
'process.env.OIDC_ISSUER': JSON.stringify(process.env.OIDC_ISSUER),
'process.env.OIDC_AUDIENCE': JSON.stringify(process.env.OIDC_AUDIENCE),
'process.env.OIDC_EXTRA_SCOPES': JSON.stringify(
process.env.OIDC_EXTRA_SCOPES
),
},
},
dev: {
client: {
path: '/api/playground/rsbuild-hmr',
},
setupMiddlewares: [
(middlewares) => {
middlewares.unshift((req, res, next) => {
if (process.env.AUTH_TYPE === 'basic') {
res.setHeader('WWW-Authenticate', 'Basic realm="konobangu"');
const authorization =
(req.headers.authorization || '').split(' ')[1] || '';
const [user, password] = Buffer.from(authorization, 'base64')
.toString()
.split(':');
if (
user !== process.env.BASIC_USER ||
password !== process.env.BASIC_PASSWORD
) {
res.statusCode = 401;
res.write('Unauthorized');
res.end();
return;
}
}
next();
});
return middlewares;
},
],
},
server: {
base: '/api/playground/',
host: '0.0.0.0',
port: 5002,
},
});

View File

@@ -1 +0,0 @@
/// <reference types="@rsbuild/core/types" />

View File

@@ -1 +0,0 @@
@import "tailwindcss";

View File

@@ -1,96 +0,0 @@
import '@abraham/reflection';
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
import { RouterProvider, createRouter } from '@tanstack/react-router';
import {
OidcSecurityService,
provideAuth,
withCheckAuthResultEvent,
withDefaultFeatures,
} from 'oidc-client-rx';
import { withTanstackRouter } from 'oidc-client-rx/adapters/@tanstack/react-router';
import {
InjectorContextVoidInjector,
InjectorProvider,
} from 'oidc-client-rx/adapters/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { buildOidcConfig, isBasicAuth } from './auth/config';
import { useAuth } from './auth/hooks';
import { routeTree } from './routeTree.gen';
import './main.css';
const router = createRouter({
routeTree,
basepath: '/api/playground',
defaultPreload: 'intent',
context: {
isAuthenticated: isBasicAuth,
injector: InjectorContextVoidInjector,
oidcSecurityService: {} as OidcSecurityService,
},
});
// Register things for typesafety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router;
}
}
const injector: Injector = isBasicAuth
? ReflectiveInjector.resolveAndCreate([])
: ReflectiveInjector.resolveAndCreate(
provideAuth(
{
config: buildOidcConfig(),
},
withDefaultFeatures({
router: { enabled: false },
securityStorage: { type: 'local-storage' },
}),
withTanstackRouter(router),
withCheckAuthResultEvent()
)
);
// if needed, check when init
let oidcSecurityService: OidcSecurityService | undefined;
if (!isBasicAuth) {
oidcSecurityService = injector.get(OidcSecurityService);
oidcSecurityService.checkAuth().subscribe();
}
const AppWithBasicAuth = () => {
return <RouterProvider router={router} />;
};
const AppWithOidcAuth = () => {
const { isAuthenticated, oidcSecurityService, injector } = useAuth();
return (
<RouterProvider
router={router}
context={{
isAuthenticated,
oidcSecurityService,
injector,
}}
/>
);
};
const App = isBasicAuth ? AppWithBasicAuth : AppWithOidcAuth;
const rootEl = document.getElementById('root');
if (rootEl) {
rootEl.classList.add('min-h-svh');
const root = ReactDOM.createRoot(rootEl);
root.render(
<React.StrictMode>
<InjectorProvider injector={injector}>
<App />
</InjectorProvider>
</React.StrictMode>
);
}

View File

@@ -1,134 +0,0 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
// Import Routes
import { Route as rootRoute } from './web/controller/__root'
import { Route as IndexImport } from './web/controller/index'
import { Route as GraphqlIndexImport } from './web/controller/graphql/index'
import { Route as OidcCallbackImport } from './web/controller/oidc/callback'
// Create/Update Routes
const IndexRoute = IndexImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRoute,
} as any)
const GraphqlIndexRoute = GraphqlIndexImport.update({
id: '/graphql/',
path: '/graphql/',
getParentRoute: () => rootRoute,
} as any)
const OidcCallbackRoute = OidcCallbackImport.update({
id: '/oidc/callback',
path: '/oidc/callback',
getParentRoute: () => rootRoute,
} as any)
// Populate the FileRoutesByPath interface
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute
}
'/oidc/callback': {
id: '/oidc/callback'
path: '/oidc/callback'
fullPath: '/oidc/callback'
preLoaderRoute: typeof OidcCallbackImport
parentRoute: typeof rootRoute
}
'/graphql/': {
id: '/graphql/'
path: '/graphql'
fullPath: '/graphql'
preLoaderRoute: typeof GraphqlIndexImport
parentRoute: typeof rootRoute
}
}
}
// Create and export the route tree
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/oidc/callback': typeof OidcCallbackRoute
'/graphql': typeof GraphqlIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/oidc/callback': typeof OidcCallbackRoute
'/graphql': typeof GraphqlIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRoute
'/': typeof IndexRoute
'/oidc/callback': typeof OidcCallbackRoute
'/graphql/': typeof GraphqlIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/oidc/callback' | '/graphql'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/oidc/callback' | '/graphql'
id: '__root__' | '/' | '/oidc/callback' | '/graphql/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
OidcCallbackRoute: typeof OidcCallbackRoute
GraphqlIndexRoute: typeof GraphqlIndexRoute
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
OidcCallbackRoute: OidcCallbackRoute,
GraphqlIndexRoute: GraphqlIndexRoute,
}
export const routeTree = rootRoute
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()
/* ROUTE_MANIFEST_START
{
"routes": {
"__root__": {
"filePath": "__root.tsx",
"children": [
"/",
"/oidc/callback",
"/graphql/"
]
},
"/": {
"filePath": "index.tsx"
},
"/oidc/callback": {
"filePath": "oidc/callback.tsx"
},
"/graphql/": {
"filePath": "graphql/index.tsx"
}
}
}
ROUTE_MANIFEST_END */

View File

@@ -1,32 +0,0 @@
import type { Injector } from '@outposts/injection-js';
import {
Outlet,
createRootRouteWithContext,
} from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
import type { OidcSecurityService } from 'oidc-client-rx';
export type RouterContext =
| {
isAuthenticated: false;
injector: Injector;
oidcSecurityService: OidcSecurityService;
}
| {
isAuthenticated: true;
injector?: Injector;
oidcSecurityService?: OidcSecurityService;
};
export const Route = createRootRouteWithContext<RouterContext>()({
component: RootComponent,
});
function RootComponent() {
return (
<>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
</>
);
}

View File

@@ -1,36 +0,0 @@
import { type Fetcher, createGraphiQLFetcher } from '@graphiql/toolkit';
import { createFileRoute } from '@tanstack/react-router';
import GraphiQL from 'graphiql';
import { useMemo } from 'react';
import { firstValueFrom } from 'rxjs';
import { beforeLoadGuard } from '../../../auth/guard';
import { useAuth } from '../../../auth/hooks';
import 'graphiql/graphiql.css';
export const Route = createFileRoute('/graphql/')({
component: RouteComponent,
beforeLoad: beforeLoadGuard,
});
function RouteComponent() {
const { oidcSecurityService } = useAuth();
const fetcher = useMemo(
(): Fetcher => async (props) => {
const accessToken = oidcSecurityService
? await firstValueFrom(oidcSecurityService.getAccessToken())
: undefined;
return createGraphiQLFetcher({
url: '/api/graphql',
headers: accessToken
? {
Authorization: `Bearer ${accessToken}`,
}
: undefined,
})(props);
},
[oidcSecurityService]
);
return <GraphiQL fetcher={fetcher} className="!h-svh" />;
}

View File

@@ -1,9 +0,0 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello to playground!</div>
}

View File

@@ -1,32 +0,0 @@
import { createFileRoute, redirect } from '@tanstack/react-router';
import { EventTypes } from 'oidc-client-rx';
import { useAuth } from '../../../auth/hooks';
export const Route = createFileRoute('/oidc/callback')({
component: RouteComponent,
beforeLoad: ({ context }) => {
if (!context.oidcSecurityService) {
throw redirect({
to: '/',
});
}
},
});
function RouteComponent() {
const auth = useAuth();
if (!auth.checkAuthResultEvent) {
return <div>Loading...</div>;
}
return (
<div>
OpenID Connect Auth Callback:{' '}
{auth.checkAuthResultEvent?.type ===
EventTypes.CheckingAuthFinishedWithError
? auth.checkAuthResultEvent.value
: 'success'}
</div>
);
}

View File

@@ -1,16 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"composite": true,
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "Bundler",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"include": ["src"]
}

View File

@@ -1,4 +0,0 @@
{
"routesDirectory": "./src/web/controller",
"generatedRouteTree": "./src/routeTree.gen.ts"
}