feat: add info

This commit is contained in:
zhuzhengjian
2025-09-02 10:50:48 +08:00
commit 8053fdfc37
33 changed files with 5176 additions and 0 deletions

23
packages/vue/package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "@penna/vue",
"type": "module",
"version": "1.0.0-beta.1",
"description": "this is penna core",
"publishConfig": {
"access": "public"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsdown",
"prepublish": "pnpm build"
},
"dependencies": {
"pinia": "^3.0.3",
"vue": "^3.5.20",
"vue-router": "^4.5.1"
}
}

View File

@ -0,0 +1,96 @@
import type { RouteRecordRaw, RouterOptions } from 'vue-router'
import type { ModuleOptions } from './modules.ts'
import { createApp as createClientApp, defineComponent, h } from 'vue'
import { createRouter, createWebHistory, RouterView } from 'vue-router'
import { useModules } from './utils/module.ts'
export interface CreateAppOptions {
/**
* 根容器选择器
* @default "#app"
*/
rootContainer?: string
/**
* 模块配置
*/
modules?: ModuleOptions[]
/**
* 路由信息配置项
* @default {}
*/
routerOptions?: RouterOptions
/**
* 根路由重定向地址
* @default "/home"
*/
rootRedirect?: string
}
const RootComponent = defineComponent(
(_) => {
// 获取全局配置中的信息
const { modules } = useModules()
for (const module of modules) {
if (module.setup) {
module.setup?.()
}
}
return () => {
return h(RouterView)
}
},
)
export async function createApp(options: CreateAppOptions) {
const app = createClientApp(RootComponent)
const modules = options?.modules ?? []
// 挂载到全局的配置中
app.config.globalProperties.$modules = modules
let routes = (options?.routerOptions?.routes ?? []) as RouteRecordRaw[]
// 1. 先执行所有模块的setup方法
for (const module of modules) {
// 顺序执行以避免问题
if (module.app) {
// 支持异步
await module.app(app)
}
// 是否存在静态的路由配置信息
if (module.routes) {
if (typeof module.routes === 'function') {
routes = module.routes(routes) ?? routes
}
else {
routes.push(...(module.routes ?? []))
}
}
}
let rootRedirect = options?.rootRedirect ?? '/home'
if (rootRedirect === '/') {
console.error('[createApp]: rootRedirect cannot be \'/\', fall back to \'/home\'')
rootRedirect = '/home'
}
const rootRoute: RouteRecordRaw = {
path: '',
name: 'ROOT_ROUTE',
redirect: rootRedirect,
children: routes,
}
const router = createRouter({
history: createWebHistory(),
routes: [
rootRoute,
],
...options?.routerOptions,
})
// 2. 再执行所有模块的router方法
for (const module of modules) {
if (module.router) {
// 执行router相关的配置
await module.router(router)
}
}
app.use(router)
// 判断是否已经完成了router的加载
await router.isReady()
app.mount(options?.rootContainer ?? '#app')
}

View File

@ -0,0 +1,3 @@
export { createApp } from './create-app'
export type { ModuleOptions } from './modules'
export { defineModule } from './modules'

View File

@ -0,0 +1,36 @@
import type { App } from 'vue'
import type { Router, RouteRecordRaw } from 'vue-router'
export interface PageType {
component: any
meta?: RouteRecordRaw['meta']
name?: string
}
export interface ModuleOptions {
/**
* 初始化模块配置
* @param app
*/
app?: (app: App) => Promise<void> | void
/**
* 静态的路由配置信息
*/
routes?: RouteRecordRaw[] | ((routes: RouteRecordRaw[]) => RouteRecordRaw[])
/**
* 动态路由页面配置
*/
pages?: Record<string, PageType>
/**
* 给用户router的实例进行操作
*/
router?: (router: Router) => Promise<void> | void
/**
* 这里的setup就是rootComponent的setup
*/
setup?: () => void
}
export function defineModule(options: ModuleOptions) {
return options
}

View File

@ -0,0 +1,13 @@
import type { ModuleOptions } from '../modules.ts'
import { getCurrentInstance } from 'vue'
export function useModules() {
const instance = getCurrentInstance()
if (!instance) {
throw new Error('Failed to get current instance')
}
const modules = (instance.appContext.config.globalProperties?.$modules ?? []) as ModuleOptions[]
return {
modules,
}
}

View File

@ -0,0 +1,11 @@
{
"extends": [
"../../tsconfig.json"
],
"compilerOptions": {
},
"include": [
"src/**/*.ts"
]
}

View File

@ -0,0 +1,9 @@
import { defineConfig } from 'tsdown'
export default defineConfig({
platform: 'browser',
entry: [
'./src/index.ts',
],
dts: true,
})