Merge branch 'fork' of 124-template-94/d8d-admin-mobile-starter-public into main
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
待实现
|
||||
迁移管理页面,在正式环境中,需要验证env中配置的密码参数才能打开
|
||||
|
||||
2025.05.14 0.1.1
|
||||
创建 server/middlewares.ts - 集中管理所有中间件配置
|
||||
创建 server/router.ts - 统一处理路由注册逻辑
|
||||
重构 server/app.tsx - 仅保留应用初始化和服务启动逻辑
|
||||
保持原有功能不变,同时提高代码可维护性和扩展性
|
||||
|
||||
2025.05.13 0.1.0
|
||||
将admin api.ts 拆开
|
||||
打开迁移管理页面时,将迁移历史读取出来
|
||||
|
||||
255
server/app.tsx
255
server/app.tsx
@@ -1,39 +1,15 @@
|
||||
/** @jsxImportSource https://esm.d8d.fun/hono@4.7.4/jsx */
|
||||
import { Hono } from 'hono'
|
||||
import { Auth } from '@d8d-appcontainer/auth'
|
||||
import type { User as AuthUser } from '@d8d-appcontainer/auth'
|
||||
import React from 'hono/jsx'
|
||||
import type { FC } from 'hono/jsx'
|
||||
import { cors } from 'hono/cors'
|
||||
import type { Context as HonoContext } from 'hono'
|
||||
import { serveStatic } from 'hono/deno'
|
||||
import { APIClient } from '@d8d-appcontainer/api'
|
||||
import debug from "debug"
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import type { SystemSettingRecord, GlobalConfig } from '../client/share/types.ts';
|
||||
import { SystemSettingKey, OssType, MapMode } from '../client/share/types.ts';
|
||||
|
||||
import { createKnowInfoRoutes } from "./routes_know_info.ts";
|
||||
import { createFileCategoryRoutes } from "./routes_file_category.ts";
|
||||
import { createFileUploadRoutes } from "./routes_file_upload.ts";
|
||||
import { createThemeRoutes } from "./routes_theme.ts";
|
||||
import { createSystemSettingsRoutes } from "./routes_system_settings.ts";
|
||||
|
||||
import {
|
||||
createMapRoutes,
|
||||
} from "./routes_maps.ts";
|
||||
|
||||
import {
|
||||
createChartRoutes,
|
||||
} from "./routes_charts.ts";
|
||||
|
||||
// 导入基础路由
|
||||
import { createAuthRoutes } from "./routes_auth.ts";
|
||||
import { createUserRoutes } from "./routes_users.ts";
|
||||
import { createMessagesRoutes } from "./routes_messages.ts";
|
||||
import { createMigrationsRoutes } from "./routes_migrations.ts";
|
||||
import { createHomeRoutes } from "./routes_home.ts";
|
||||
import type { GlobalConfig } from '../client/share/types.ts';
|
||||
import { OssType, MapMode } from '../client/share/types.ts';
|
||||
import { createRouter } from './router.ts'
|
||||
dayjs.extend(utc)
|
||||
// 初始化debug实例
|
||||
const log = {
|
||||
@@ -66,35 +42,6 @@ log.auth.enabled = true
|
||||
log.api.enabled = true
|
||||
log.debug.enabled = true
|
||||
|
||||
// 定义自定义上下文类型
|
||||
export interface Variables {
|
||||
auth: Auth
|
||||
user?: AuthUser
|
||||
apiClient: APIClient
|
||||
moduleDir: string
|
||||
systemSettings?: SystemSettingRecord
|
||||
}
|
||||
|
||||
// 定义登录历史类型
|
||||
interface LoginHistory {
|
||||
id: number
|
||||
user_id: number
|
||||
login_time: string
|
||||
ip_address?: string
|
||||
user_agent?: string
|
||||
}
|
||||
|
||||
// 定义仪表盘数据类型
|
||||
interface DashboardData {
|
||||
lastLogin: string
|
||||
loginCount: number
|
||||
fileCount: number
|
||||
userCount: number
|
||||
systemInfo: {
|
||||
version: string
|
||||
lastUpdate: string
|
||||
}
|
||||
}
|
||||
|
||||
interface EsmScriptConfig {
|
||||
src: string
|
||||
@@ -105,122 +52,6 @@ interface EsmScriptConfig {
|
||||
prodSrc?: string
|
||||
}
|
||||
|
||||
// Auth实例
|
||||
let authInstance: Auth | null = null
|
||||
|
||||
// 初始化Auth实例
|
||||
const initAuth = async (apiClient: APIClient) => {
|
||||
try {
|
||||
if (authInstance) {
|
||||
return authInstance
|
||||
}
|
||||
|
||||
log.auth('正在初始化Auth实例')
|
||||
|
||||
authInstance = new Auth(apiClient as any, {
|
||||
jwtSecret: Deno.env.get("JWT_SECRET") || 'your-jwt-secret-key',
|
||||
initialUsers: [],
|
||||
storagePrefix: '',
|
||||
userTable: 'users',
|
||||
fieldNames: {
|
||||
id: 'id',
|
||||
username: 'username',
|
||||
password: 'password',
|
||||
phone: 'phone',
|
||||
email: 'email',
|
||||
is_disabled: 'is_disabled',
|
||||
is_deleted: 'is_deleted'
|
||||
},
|
||||
tokenExpiry: 24 * 60 * 60,
|
||||
refreshTokenExpiry: 7 * 24 * 60 * 60
|
||||
})
|
||||
|
||||
log.auth('Auth实例初始化完成')
|
||||
|
||||
return authInstance
|
||||
} catch (error) {
|
||||
log.auth('Auth初始化失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化系统设置
|
||||
const initSystemSettings = async (apiClient: APIClient) => {
|
||||
try {
|
||||
const systemSettings = await apiClient.database.table('system_settings')
|
||||
.select()
|
||||
|
||||
// 将系统设置转换为键值对形式
|
||||
const settings = systemSettings.reduce((acc: Record<string, any>, setting: any) => {
|
||||
acc[setting.key] = setting.value
|
||||
return acc
|
||||
}, {}) as SystemSettingRecord
|
||||
|
||||
// 更新全局配置
|
||||
if (settings[SystemSettingKey.SITE_NAME]) {
|
||||
GLOBAL_CONFIG.APP_NAME = String(settings[SystemSettingKey.SITE_NAME])
|
||||
}
|
||||
|
||||
// 设置其他全局配置项
|
||||
if (settings[SystemSettingKey.SITE_FAVICON]) {
|
||||
GLOBAL_CONFIG.DEFAULT_THEME = String(settings[SystemSettingKey.SITE_FAVICON])
|
||||
}
|
||||
|
||||
if (settings[SystemSettingKey.SITE_LOGO]) {
|
||||
GLOBAL_CONFIG.MAP_CONFIG.KEY = String(settings[SystemSettingKey.SITE_LOGO])
|
||||
}
|
||||
|
||||
if (settings[SystemSettingKey.SITE_DESCRIPTION]) {
|
||||
GLOBAL_CONFIG.CHART_THEME = String(settings[SystemSettingKey.SITE_DESCRIPTION])
|
||||
}
|
||||
|
||||
// 设置主题配置开关
|
||||
if (settings[SystemSettingKey.ENABLE_THEME_CONFIG]) {
|
||||
GLOBAL_CONFIG.ENABLE_THEME_CONFIG = settings[SystemSettingKey.ENABLE_THEME_CONFIG] === 'true'
|
||||
}
|
||||
|
||||
// 查询ID1管理员的主题配置
|
||||
const adminTheme = await apiClient.database.table('theme_settings')
|
||||
.where('user_id', 1)
|
||||
.first()
|
||||
|
||||
if (adminTheme) {
|
||||
GLOBAL_CONFIG.THEME = adminTheme.settings
|
||||
}
|
||||
|
||||
return settings
|
||||
|
||||
} catch (error) {
|
||||
log.app('获取系统设置失败:', error)
|
||||
return {} as SystemSettingRecord
|
||||
}
|
||||
}
|
||||
|
||||
// 中间件:验证认证
|
||||
const withAuth = async (c: HonoContext<{ Variables: Variables }>, next: () => Promise<void>) => {
|
||||
try {
|
||||
const auth = c.get('auth')
|
||||
|
||||
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
||||
if (token) {
|
||||
const userData = await auth.verifyToken(token)
|
||||
if (userData) {
|
||||
c.set('user', userData)
|
||||
await next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({ error: '未授权' }, 401)
|
||||
} catch (error) {
|
||||
log.auth('认证失败:', error)
|
||||
return c.json({ error: '无效凭证' }, 401)
|
||||
}
|
||||
}
|
||||
|
||||
// 导出withAuth类型定义
|
||||
export type WithAuth = typeof withAuth;
|
||||
|
||||
// 定义模块参数接口
|
||||
interface ModuleParams {
|
||||
apiClient: APIClient
|
||||
@@ -230,84 +61,10 @@ interface ModuleParams {
|
||||
|
||||
export default function({ apiClient, app, moduleDir }: ModuleParams) {
|
||||
const honoApp = app
|
||||
// 添加CORS中间件
|
||||
honoApp.use('/*', cors())
|
||||
|
||||
// 创建API路由
|
||||
const api = new Hono<{ Variables: Variables }>()
|
||||
|
||||
|
||||
// // 使用数据库中间件
|
||||
// api.use('/*', withDatabase)
|
||||
|
||||
// 设置环境变量
|
||||
api.use('*', async (c, next) => {
|
||||
c.set('apiClient', apiClient)
|
||||
c.set('moduleDir', moduleDir)
|
||||
c.set('auth', await initAuth(apiClient))
|
||||
c.set('systemSettings', await initSystemSettings(apiClient))
|
||||
await next()
|
||||
})
|
||||
|
||||
// 查询仪表盘数据
|
||||
api.get('/dashboard', withAuth, async (c) => {
|
||||
try {
|
||||
const user = c.get('user')!
|
||||
const apiClient = c.get('apiClient')
|
||||
const lastLogin = await apiClient.database.table('login_history')
|
||||
.where('user_id', user.id)
|
||||
.orderBy('login_time', 'desc')
|
||||
.limit(1)
|
||||
.first()
|
||||
|
||||
// 获取登录总次数
|
||||
const loginCount = await apiClient.database.table('login_history')
|
||||
.where('user_id', user.id)
|
||||
.count()
|
||||
|
||||
// 获取系统数据统计
|
||||
const fileCount = await apiClient.database.table('file_library')
|
||||
.where('is_deleted', 0)
|
||||
.count()
|
||||
|
||||
const userCount = await apiClient.database.table('users')
|
||||
.where('is_deleted', 0)
|
||||
.count()
|
||||
|
||||
// 返回仪表盘数据
|
||||
const dashboardData: DashboardData = {
|
||||
lastLogin: lastLogin ? lastLogin.login_time : new Date().toISOString(),
|
||||
loginCount: loginCount,
|
||||
fileCount: Number(fileCount),
|
||||
userCount: Number(userCount),
|
||||
systemInfo: {
|
||||
version: '1.0.0',
|
||||
lastUpdate: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
|
||||
return c.json(dashboardData)
|
||||
} catch (error) {
|
||||
log.api('获取仪表盘数据失败:', error)
|
||||
return c.json({ error: '获取仪表盘数据失败' }, 500)
|
||||
}
|
||||
})
|
||||
// 注册基础路由
|
||||
api.route('/auth', createAuthRoutes(withAuth))
|
||||
api.route('/users', createUserRoutes(withAuth))
|
||||
api.route('/know-infos', createKnowInfoRoutes(withAuth))
|
||||
api.route('/upload', createFileUploadRoutes(withAuth)) // 添加文件上传路由
|
||||
api.route('/file-categories', createFileCategoryRoutes(withAuth)) // 添加文件分类管理路由
|
||||
api.route('/theme', createThemeRoutes(withAuth)) // 添加主题设置路由
|
||||
api.route('/charts', createChartRoutes(withAuth)) // 添加图表数据路由
|
||||
api.route('/map', createMapRoutes(withAuth)) // 添加地图数据路由
|
||||
api.route('/settings', createSystemSettingsRoutes(withAuth)) // 添加系统设置路由
|
||||
api.route('/messages', createMessagesRoutes(withAuth)) // 添加消息路由
|
||||
api.route('/migrations', createMigrationsRoutes(withAuth)) // 添加数据库迁移路由
|
||||
api.route('/home', createHomeRoutes(withAuth)) // 添加首页路由
|
||||
|
||||
// 注册API路由
|
||||
honoApp.route('/api', api)
|
||||
// 创建路由
|
||||
const router = createRouter(apiClient, moduleDir)
|
||||
honoApp.route('/', router)
|
||||
|
||||
// 首页路由 - SSR
|
||||
honoApp.get('/', async (c: HonoContext) => {
|
||||
|
||||
111
server/middlewares.ts
Normal file
111
server/middlewares.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { Hono } from 'hono'
|
||||
import { cors } from 'hono/cors'
|
||||
import type { Context as HonoContext } from 'hono'
|
||||
import { Auth } from '@d8d-appcontainer/auth'
|
||||
import type { User as AuthUser } from '@d8d-appcontainer/auth'
|
||||
import { APIClient } from '@d8d-appcontainer/api'
|
||||
import type { SystemSettingRecord } from '../client/share/types.ts'
|
||||
import debug from "debug"
|
||||
|
||||
const log = {
|
||||
auth: debug('auth:server')
|
||||
}
|
||||
|
||||
// 定义自定义上下文类型
|
||||
export interface Variables {
|
||||
auth: Auth
|
||||
user?: AuthUser
|
||||
apiClient: APIClient
|
||||
moduleDir: string
|
||||
systemSettings?: SystemSettingRecord
|
||||
}
|
||||
// 认证中间件
|
||||
export const withAuth = async (c: HonoContext<{ Variables: Variables }>, next: () => Promise<void>) => {
|
||||
try {
|
||||
const auth = c.get('auth')
|
||||
|
||||
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
||||
if (token) {
|
||||
const userData = await auth.verifyToken(token)
|
||||
if (userData) {
|
||||
c.set('user', userData)
|
||||
await next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({ error: '未授权' }, 401)
|
||||
} catch (error) {
|
||||
log.auth('认证失败:', error)
|
||||
return c.json({ error: '无效凭证' }, 401)
|
||||
}
|
||||
}
|
||||
|
||||
// 导出withAuth类型定义
|
||||
export type WithAuth = typeof withAuth;
|
||||
|
||||
// 环境变量设置中间件
|
||||
export const setEnvVariables = (apiClient: APIClient, moduleDir: string) => {
|
||||
return async (c: HonoContext<{ Variables: Variables }>, next: () => Promise<void>) => {
|
||||
c.set('apiClient', apiClient)
|
||||
c.set('moduleDir', moduleDir)
|
||||
c.set('auth', await initAuth(apiClient))
|
||||
c.set('systemSettings', await initSystemSettings(apiClient))
|
||||
await next()
|
||||
}
|
||||
}
|
||||
|
||||
// CORS中间件
|
||||
export const corsMiddleware = cors()
|
||||
|
||||
// 初始化Auth实例
|
||||
const initAuth = async (apiClient: APIClient) => {
|
||||
try {
|
||||
log.auth('正在初始化Auth实例')
|
||||
|
||||
const auth = new Auth(apiClient as any, {
|
||||
jwtSecret: Deno.env.get("JWT_SECRET") || 'your-jwt-secret-key',
|
||||
initialUsers: [],
|
||||
storagePrefix: '',
|
||||
userTable: 'users',
|
||||
fieldNames: {
|
||||
id: 'id',
|
||||
username: 'username',
|
||||
password: 'password',
|
||||
phone: 'phone',
|
||||
email: 'email',
|
||||
is_disabled: 'is_disabled',
|
||||
is_deleted: 'is_deleted'
|
||||
},
|
||||
tokenExpiry: 24 * 60 * 60,
|
||||
refreshTokenExpiry: 7 * 24 * 60 * 60
|
||||
})
|
||||
|
||||
log.auth('Auth实例初始化完成')
|
||||
return auth
|
||||
|
||||
} catch (error) {
|
||||
log.auth('Auth初始化失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化系统设置
|
||||
const initSystemSettings = async (apiClient: APIClient) => {
|
||||
try {
|
||||
const systemSettings = await apiClient.database.table('system_settings')
|
||||
.select()
|
||||
|
||||
// 将系统设置转换为键值对形式
|
||||
const settings = systemSettings.reduce((acc: Record<string, any>, setting: any) => {
|
||||
acc[setting.key] = setting.value
|
||||
return acc
|
||||
}, {}) as SystemSettingRecord
|
||||
|
||||
return settings
|
||||
|
||||
} catch (error) {
|
||||
log.auth('获取系统设置失败:', error)
|
||||
return {} as SystemSettingRecord
|
||||
}
|
||||
}
|
||||
50
server/router.ts
Normal file
50
server/router.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/** @jsxImportSource https://esm.d8d.fun/hono@4.7.4/jsx */
|
||||
import { Hono } from 'hono'
|
||||
import { corsMiddleware, withAuth, setEnvVariables } from './middlewares.ts'
|
||||
import type { APIClient } from '@d8d-appcontainer/api'
|
||||
|
||||
// 导入路由模块
|
||||
import { createAuthRoutes } from "./routes_auth.ts"
|
||||
import { createUserRoutes } from "./routes_users.ts"
|
||||
import { createKnowInfoRoutes } from "./routes_know_info.ts"
|
||||
import { createFileUploadRoutes } from "./routes_file_upload.ts"
|
||||
import { createFileCategoryRoutes } from "./routes_file_category.ts"
|
||||
import { createThemeRoutes } from "./routes_theme.ts"
|
||||
import { createChartRoutes } from "./routes_charts.ts"
|
||||
import { createMapRoutes } from "./routes_maps.ts"
|
||||
import { createSystemSettingsRoutes } from "./routes_system_settings.ts"
|
||||
import { createMessagesRoutes } from "./routes_messages.ts"
|
||||
import { createMigrationsRoutes } from "./routes_migrations.ts"
|
||||
import { createHomeRoutes } from "./routes_home.ts"
|
||||
|
||||
export function createRouter(apiClient: APIClient, moduleDir: string) {
|
||||
const router = new Hono()
|
||||
|
||||
// 添加CORS中间件
|
||||
router.use('/*', corsMiddleware)
|
||||
|
||||
// 创建API路由
|
||||
const api = new Hono()
|
||||
|
||||
// 设置环境变量
|
||||
api.use('*', setEnvVariables(apiClient, moduleDir))
|
||||
|
||||
// 注册所有路由
|
||||
api.route('/auth', createAuthRoutes(withAuth))
|
||||
api.route('/users', createUserRoutes(withAuth))
|
||||
api.route('/know-infos', createKnowInfoRoutes(withAuth))
|
||||
api.route('/upload', createFileUploadRoutes(withAuth))
|
||||
api.route('/file-categories', createFileCategoryRoutes(withAuth))
|
||||
api.route('/theme', createThemeRoutes(withAuth))
|
||||
api.route('/charts', createChartRoutes(withAuth))
|
||||
api.route('/map', createMapRoutes(withAuth))
|
||||
api.route('/settings', createSystemSettingsRoutes(withAuth))
|
||||
api.route('/messages', createMessagesRoutes(withAuth))
|
||||
api.route('/migrations', createMigrationsRoutes(withAuth))
|
||||
api.route('/home', createHomeRoutes(withAuth))
|
||||
|
||||
// 注册API路由到主路由器
|
||||
router.route('/api', api)
|
||||
|
||||
return router
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Hono } from 'hono'
|
||||
import type { Variables } from './app.tsx'
|
||||
import type { WithAuth } from './app.tsx'
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
export function createAuthRoutes(withAuth: WithAuth) {
|
||||
const authRoutes = new Hono<{ Variables: Variables }>()
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
DeleteStatus,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
DeleteStatus,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
EnableStatus,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Hono } from 'hono'
|
||||
import type { Variables } from './app.tsx'
|
||||
import type { WithAuth } from './app.tsx'
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
import { AuditStatus } from '../client/share/types.ts'
|
||||
|
||||
export function createHomeRoutes(withAuth: WithAuth) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DeleteStatus,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Hono } from "hono";
|
||||
import debug from "debug";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Hono } from 'hono'
|
||||
import type { Variables } from './app.tsx'
|
||||
import type { WithAuth } from './app.tsx'
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
import { MessageType, MessageStatus } from '../client/share/types.ts'
|
||||
|
||||
export function createMessagesRoutes(withAuth: WithAuth) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Hono } from 'hono'
|
||||
import { APIClient } from '@d8d-appcontainer/api'
|
||||
import type { Variables } from './app.tsx'
|
||||
import type { WithAuth } from './app.tsx'
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
import { migrations } from './migrations.ts'
|
||||
import debug from "debug";
|
||||
const log = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
SystemSettingGroupData,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
CompactMode,
|
||||
} from "../client/share/types.ts";
|
||||
|
||||
import type { Variables, WithAuth } from "./app.tsx";
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
const log = {
|
||||
api: debug("api:sys"),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Hono } from 'hono'
|
||||
import type { Variables } from './app.tsx'
|
||||
import type { WithAuth } from './app.tsx'
|
||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||
|
||||
export function createUserRoutes(withAuth: WithAuth) {
|
||||
const usersRoutes = new Hono<{ Variables: Variables }>()
|
||||
|
||||
Reference in New Issue
Block a user