diff --git a/package.json b/package.json
index f5d58cac..eff99c19 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"dependencies": {
"@halo-dev/admin-api": "^1.1.0",
"@halo-dev/components": "workspace:*",
+ "@halo-dev/admin-shared": "workspace:*",
"@vueuse/core": "^8.6.0",
"filepond": "^4.30.4",
"filepond-plugin-image-preview": "^4.6.11",
diff --git a/packages/shared/.eslintrc.cjs b/packages/shared/.eslintrc.cjs
new file mode 100644
index 00000000..feeabc42
--- /dev/null
+++ b/packages/shared/.eslintrc.cjs
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: ["../../.eslintrc.cjs"],
+};
diff --git a/packages/shared/env.d.ts b/packages/shared/env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/packages/shared/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/shared/package.json b/packages/shared/package.json
new file mode 100644
index 00000000..dace5743
--- /dev/null
+++ b/packages/shared/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "@halo-dev/admin-shared",
+ "version": "0.0.0",
+ "description": "",
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "dev": "vite build --watch",
+ "build": "vite build"
+ },
+ "keywords": [],
+ "author": {
+ "name": "@halo-dev",
+ "url": "https://github.com/halo-dev"
+ },
+ "main": "./dist/halo-admin-shared.cjs.js",
+ "module": "./dist/halo-admin-shared.es.js",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "require": "./dist/halo-admin-shared.cjs.js",
+ "import": "./dist/halo-admin-shared.es.js"
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/halo-dev/halo-admin.git",
+ "directory": "packages/shared"
+ },
+ "bugs": {
+ "url": "https://github.com/halo-dev/halo/issues"
+ },
+ "homepage": "https://github.com/halo-dev/halo-admin/tree/next/shared/components#readme",
+ "license": "MIT",
+ "devDependencies": {
+ "vite-plugin-dts": "^1.2.0"
+ },
+ "peerDependencies": {
+ "vue": "^3.2.37",
+ "vue-router": "^4.0.16"
+ }
+}
diff --git a/packages/shared/prettier.config.js b/packages/shared/prettier.config.js
new file mode 100644
index 00000000..38409a26
--- /dev/null
+++ b/packages/shared/prettier.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ plugins: ["../../prettier.config.js"],
+};
diff --git a/packages/shared/src/components/.gitkeep b/packages/shared/src/components/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts
new file mode 100644
index 00000000..94c9cf4f
--- /dev/null
+++ b/packages/shared/src/index.ts
@@ -0,0 +1,2 @@
+export * from "./types/plugin";
+export * from "./types/menus";
diff --git a/packages/shared/src/types/menus.ts b/packages/shared/src/types/menus.ts
new file mode 100644
index 00000000..b09929c2
--- /dev/null
+++ b/packages/shared/src/types/menus.ts
@@ -0,0 +1,14 @@
+import type { Component } from "vue";
+
+export interface MenuGroupType {
+ name?: string;
+ items: MenuItemType[];
+}
+
+export interface MenuItemType {
+ name: string;
+ path: string;
+ icon?: Component;
+ meta?: Record;
+ children?: MenuItemType[];
+}
diff --git a/packages/shared/src/types/plugin.ts b/packages/shared/src/types/plugin.ts
new file mode 100644
index 00000000..795806c6
--- /dev/null
+++ b/packages/shared/src/types/plugin.ts
@@ -0,0 +1,40 @@
+import type { Component } from "vue";
+import type { RouteRecordRaw } from "vue-router";
+import type { MenuGroupType } from "./menus";
+
+export type ExtensionPointName =
+ | "POSTS"
+ | "POST_EDITOR"
+ | "DASHBOARD"
+ | "USER_SETTINGS";
+
+// TODO define extension point state
+export type ExtensionPointState = Record;
+
+export interface Plugin {
+ name: string;
+
+ /**
+ * This components will be registered when plugin is activated.
+ */
+ components?: Component[];
+
+ /**
+ * Activate hook will be called when plugin is activated.
+ */
+ activated?: () => void;
+
+ /**
+ * Deactivate hook will be called when plugin is deactivated.
+ */
+ deactivated?: () => void;
+
+ routes?: RouteRecordRaw[];
+
+ menus?: MenuGroupType[];
+
+ extensionPoints?: Record<
+ ExtensionPointName,
+ (state: ExtensionPointState) => void
+ >;
+}
diff --git a/packages/shared/tsconfig.app.json b/packages/shared/tsconfig.app.json
new file mode 100644
index 00000000..cdbea1d7
--- /dev/null
+++ b/packages/shared/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+ "extends": "@vue/tsconfig/tsconfig.web.json",
+ "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+ "exclude": ["src/**/__tests__/*"],
+ "compilerOptions": {
+ "composite": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json
new file mode 100644
index 00000000..24f21b06
--- /dev/null
+++ b/packages/shared/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.vite-config.json"
+ },
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.vitest.json"
+ }
+ ]
+}
diff --git a/packages/shared/tsconfig.vite-config.json b/packages/shared/tsconfig.vite-config.json
new file mode 100644
index 00000000..d20d8726
--- /dev/null
+++ b/packages/shared/tsconfig.vite-config.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@vue/tsconfig/tsconfig.node.json",
+ "include": ["vite.config.*"],
+ "compilerOptions": {
+ "composite": true,
+ "types": ["node", "vitest"]
+ }
+}
diff --git a/packages/shared/tsconfig.vitest.json b/packages/shared/tsconfig.vitest.json
new file mode 100644
index 00000000..d080d611
--- /dev/null
+++ b/packages/shared/tsconfig.vitest.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.app.json",
+ "exclude": [],
+ "compilerOptions": {
+ "composite": true,
+ "lib": [],
+ "types": ["node", "jsdom"]
+ }
+}
diff --git a/packages/shared/vite.config.ts b/packages/shared/vite.config.ts
new file mode 100644
index 00000000..b1922bfa
--- /dev/null
+++ b/packages/shared/vite.config.ts
@@ -0,0 +1,44 @@
+import { fileURLToPath, URL } from "url";
+
+import { defineConfig } from "vite";
+import Vue from "@vitejs/plugin-vue";
+import VueJsx from "@vitejs/plugin-vue-jsx";
+import path from "path";
+import Dts from "vite-plugin-dts";
+
+export default defineConfig({
+ plugins: [
+ Vue(),
+ VueJsx(),
+ Dts({
+ entryRoot: "./src",
+ outputDir: "./dist",
+ insertTypesEntry: true,
+ }),
+ ],
+ resolve: {
+ alias: {
+ "@": fileURLToPath(new URL("./src", import.meta.url)),
+ },
+ },
+ build: {
+ outDir: path.resolve(__dirname, "dist"),
+ lib: {
+ entry: path.resolve(__dirname, "src/index.ts"),
+ name: "HaloAdminShared",
+ formats: ["es", "cjs", "umd", "iife"],
+ fileName: (format) => `halo-admin-shared.${format}.js`,
+ },
+ rollupOptions: {
+ external: ["vue", "vue-router"],
+ output: {
+ globals: {
+ vue: "Vue",
+ "vue-router": "VueRouter",
+ },
+ exports: "named",
+ },
+ },
+ sourcemap: true,
+ },
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 62ed09fa..54484163 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,6 +5,7 @@ importers:
.:
specifiers:
'@halo-dev/admin-api': ^1.1.0
+ '@halo-dev/admin-shared': workspace:*
'@halo-dev/components': workspace:*
'@rushstack/eslint-patch': ^1.1.3
'@tailwindcss/aspect-ratio': ^0.4.0
@@ -52,6 +53,7 @@ importers:
vue-tsc: ^0.34.17
dependencies:
'@halo-dev/admin-api': 1.1.0
+ '@halo-dev/admin-shared': link:packages/shared
'@halo-dev/components': link:packages/components
'@vueuse/core': 8.6.0_vue@3.2.37
filepond: 4.30.4
@@ -116,6 +118,12 @@ importers:
unplugin-icons: 0.14.4
vite-plugin-dts: 1.2.0
+ packages/shared:
+ specifiers:
+ vite-plugin-dts: ^1.2.0
+ devDependencies:
+ vite-plugin-dts: 1.2.0
+
packages:
/@ampproject/remapping/2.1.2:
@@ -1803,7 +1811,7 @@ packages:
colors: 1.2.5
lodash: 4.17.21
resolve: 1.17.0
- semver: 7.3.5
+ semver: 7.3.7
source-map: 0.6.1
typescript: 4.6.4
dev: true
@@ -1951,7 +1959,7 @@ packages:
import-lazy: 4.0.0
jju: 1.4.0
resolve: 1.17.0
- semver: 7.3.5
+ semver: 7.3.7
timsort: 0.3.0
z-schema: 5.0.3
dev: true
@@ -4698,7 +4706,7 @@ packages:
dev: true
/is-extglob/2.1.1:
- resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
dev: true