/** @jsxImportSource https://esm.d8d.fun/hono@4.7.4/jsx */
import { Hono } from 'hono'
import React from 'hono/jsx'
import type { Context as HonoContext } from 'hono'
import { serveStatic } from 'hono/deno'
import { APIClient } from '@d8d-appcontainer/api'
import { Auth } from '@d8d-appcontainer/auth';
import debug from "debug"
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
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 = {
app: debug('app:server'),
auth: debug('auth:server'),
api: debug('api:server'),
debug: debug('debug:server')
}
const GLOBAL_CONFIG: GlobalConfig = {
OSS_BASE_URL: Deno.env.get('OSS_BASE_URL') || 'https://d8d-appcontainer-user.oss-cn-beijing.aliyuncs.com',
OSS_TYPE: Deno.env.get('OSS_TYPE') === OssType.MINIO ? OssType.MINIO : OssType.ALIYUN,
API_BASE_URL: '/api',
APP_NAME: Deno.env.get('APP_NAME') || '应用Starter',
ENV: Deno.env.get('ENV') || 'development',
DEFAULT_THEME: 'light', // 默认主题
MAP_CONFIG: {
KEY: Deno.env.get('AMAP_KEY') || '您的地图API密钥',
VERSION: '2.0',
PLUGINS: ['AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation'],
MAP_MODE: Deno.env.get('MAP_MODE') === MapMode.OFFLINE ? MapMode.OFFLINE : MapMode.ONLINE,
},
CHART_THEME: 'default', // 图表主题
ENABLE_THEME_CONFIG: false, // 主题配置开关
THEME: null
};
log.app.enabled = true
log.auth.enabled = true
log.api.enabled = true
log.debug.enabled = true
interface EsmScriptConfig {
src: string
href: string
denoJson: string
refresh: boolean
prodPath?: string
prodSrc?: string
}
// 定义模块参数接口
interface ModuleParams {
apiClient: APIClient,
auth: Auth,
app: Hono
moduleDir: string
}
export default function({ apiClient, app, moduleDir , auth}: ModuleParams) {
const honoApp = app
// 创建路由
const router = createRouter(apiClient, moduleDir, auth)
honoApp.route('/', router)
// 首页路由 - SSR
honoApp.get('/', async (c: HonoContext) => {
const systemName = GLOBAL_CONFIG.APP_NAME
return c.html(
{systemName}
{/* 系统介绍区域 */}
{systemName}
全功能应用Starter
这是一个基于Hono和React的应用Starter,提供了用户认证、文件管理、图表分析、地图集成和主题切换等常用功能。
{/* 管理入口按钮 */}
)
})
// 创建一个函数,用于生成包含全局配置的HTML页面
const createHtmlWithConfig = (scriptConfig: EsmScriptConfig, title = '应用Starter') => {
return (c: HonoContext) => {
const isProd = GLOBAL_CONFIG.ENV === 'production';
const isLocalDeploy = Deno.env.get('IS_LOCAL_DEPLOY') === 'true';
return c.html(
{isProd && }
{title}
{isLocalDeploy ? (
) : (
)}
{isLocalDeploy ? () : ()}
{isProd && (
<>
>
)}
{!isProd && (
<>
>
)}
)
}
}
// 后台管理路由
honoApp.get('/admin', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/admin/web_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "admin/web_app.js"
}, GLOBAL_CONFIG.APP_NAME))
honoApp.get('/admin/*', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/admin/web_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "admin/web_app.js"
}, GLOBAL_CONFIG.APP_NAME))
// 移动端路由
honoApp.get('/mobile', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/mobile/mobile_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "mobile/mobile_app.js"
}, GLOBAL_CONFIG.APP_NAME))
honoApp.get('/mobile/*', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/mobile/mobile_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "mobile/mobile_app.js"
}, GLOBAL_CONFIG.APP_NAME))
// 迁移管理路由
honoApp.get('/migrations', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/migrations/migrations_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "migrations/migrations_app.js"
}, GLOBAL_CONFIG.APP_NAME))
honoApp.get('/migrations/*', createHtmlWithConfig({
src: "https://esm.d8d.fun/xb",
href: "/client/migrations/migrations_app.tsx",
denoJson: "/deno.json",
refresh: true,
prodPath: "migrations/migrations_app.js"
}, GLOBAL_CONFIG.APP_NAME))
const staticRoutes = serveStatic({
root: moduleDir,
onFound: async (path: string, c: HonoContext) => {
const fileExt = path.split('.').pop()?.toLowerCase()
if (fileExt === 'tsx' || fileExt === 'ts') {
c.header('Content-Type', 'text/typescript; charset=utf-8')
} else if (fileExt === 'js' || fileExt === 'mjs') {
c.header('Content-Type', 'application/javascript; charset=utf-8')
} else if (fileExt === 'json') {
c.header('Content-Type', 'application/json; charset=utf-8')
} else if (fileExt === 'html') {
c.header('Content-Type', 'text/html; charset=utf-8')
} else if (fileExt === 'css') {
c.header('Content-Type', 'text/css; charset=utf-8')
} else if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt || '')) {
c.header('Content-Type', `image/${fileExt}`)
}
const fileInfo = await Deno.stat(path)
c.header('Last-Modified', fileInfo.mtime?.toUTCString() ?? new Date().toUTCString())
},
})
// 静态资源路由
honoApp.get('/deno.json', staticRoutes)
honoApp.get('/client/*', staticRoutes)
honoApp.get('/amap/*', staticRoutes)
honoApp.get('/tailwindcss@3.4.16/*', staticRoutes)
honoApp.get('/client_dist/*', staticRoutes)
return honoApp
}