diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..a4d9caf --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN} +@abearxiong:registry=https://npm.pkg.github.com +//registry.npmjs.org/:_authToken=${NPM_TOKEN} \ No newline at end of file diff --git a/package.json b/package.json index 24d2bf0..0b4e61b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/store", - "version": "0.0.1-alpha.2", + "version": "0.0.1-alpha.3", "main": "dist/store.js", "module": "dist/store.js", "types": "dist/store.d.ts", @@ -29,13 +29,13 @@ "fast-deep-equal": "^3.1.3", "immer": "^10.1.1", "lodash-es": "^4.17.21", - "nanoid": "^5.0.7", - "rollup": "^4.24.0", + "nanoid": "^5.0.9", + "rollup": "^4.27.4", "rollup-plugin-dts": "^6.1.1", "ts-node": "^10.9.2", - "tslib": "^2.8.0", - "typescript": "^5.6.3", - "zustand": "^5.0.0" + "tslib": "^2.8.1", + "typescript": "^5.7.2", + "zustand": "^5.0.1" }, "publishConfig": { "access": "public" @@ -48,6 +48,21 @@ ".": { "import": "./dist/store.js", "require": "./dist/store.js" + }, + "./config": { + "import": "./dist/web-config.js", + "require": "./dist/web-config.js" + }, + "./context": { + "import": "./dist/web-context.js", + "require": "./dist/web-context.js" + }, + "./page": { + "import": "./dist/web-page.js", + "require": "./dist/web-page.js" } + }, + "dependencies": { + "path-to-regexp": "^8.2.0" } } \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index 2fc438f..a324c73 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,7 +10,7 @@ import { dts } from 'rollup-plugin-dts'; */ export default [ { - input: 'src/index.ts', // TypeScript 入口文件 + input: 'src/store.ts', // TypeScript 入口文件 output: { file: 'dist/store.js', // 输出文件 format: 'es', // 输出格式设置为 ES 模块 @@ -22,11 +22,59 @@ export default [ ], }, { - input: 'src/index.ts', + input: 'src/store.ts', output: { file: 'dist/store.d.ts', format: 'es', }, plugins: [dts()], }, + { + input: 'src/web-config.ts', + output: { + file: 'dist/web-config.js', + format: 'cjs', + }, + plugins: [resolve(), commonjs(), typescript()], + }, + { + input: 'src/web-config.ts', + output: { + file: 'dist/web-config.d.ts', + format: 'es', + }, + plugins: [dts()], + }, + { + input: 'src/web-context.ts', + output: { + file: 'dist/web-context.js', + format: 'es', + }, + plugins: [resolve(), commonjs(), typescript()], + }, + { + input: 'src/web-context.ts', + output: { + file: 'dist/web-context.d.ts', + format: 'es', + }, + plugins: [dts()], + }, + { + input: 'src/page.ts', + output: { + file: 'dist/web-page.js', + format: 'es', + }, + plugins: [resolve(), commonjs(), typescript()], + }, + { + input: 'src/page.ts', + output: { + file: 'dist/web-page.d.ts', + format: 'es', + }, + plugins: [dts()], + }, ]; diff --git a/src/page.ts b/src/page.ts new file mode 100644 index 0000000..bcb299f --- /dev/null +++ b/src/page.ts @@ -0,0 +1,68 @@ +import { getPathKey } from '@/utils/path-key.ts'; +import { match } from 'path-to-regexp'; + +type PageOptions = { + path?: string; + key?: string; + basename?: string; +}; +type PageModule = { + // 模块的key,如 user,定义模块的唯一标识 + key: string; + // 模块的path路径,如 /user/:id,match的时候会用到 + path: string; +}; +export class Page { + pageModule = new Map(); + path: string; + key: string; + basename: string; + constructor(opts?: PageOptions) { + const pathKey = getPathKey(); + this.path = opts?.path ?? pathKey.path; + this.key = opts?.key ?? pathKey.key; + this.basename = opts?.basename ?? `/${this.path}/${this.key}`; + } + addPage(path: string, key?: string) { + this.pageModule.set(key, { path, key }); + } + check(key: string, pathname?: string): boolean | Record { + if (!key) { + console.error('key is required'); + return; + } + const has = this.pageModule.has(key); + if (!has) { + console.error(`PageModule ${key} not found`); + return; + } + const pageModule = this.pageModule.get(key); + const location = window.location; + const _pathname = pathname || location.pathname; + const cur = _pathname.replace(this.basename, ''); + const routeMatch = match(pageModule.path, { decode: decodeURIComponent }); + const result = routeMatch(cur); + let params = {}; + if (result) { + result.path; + params = result.params; + return params; + } + return false; + } + /** + * + * @returns 返回当前路径 + */ + getPath() { + const location = window.location; + const pathname = location.pathname; + return pathname.replace(this.basename, ''); + } + decodePath(path: string) { + return decodeURIComponent(path); + } + encodePath(path: string) { + return encodeURIComponent(path); + } +} diff --git a/src/index.ts b/src/store.ts similarity index 100% rename from src/index.ts rename to src/store.ts diff --git a/src/utils/path-key.ts b/src/utils/path-key.ts new file mode 100644 index 0000000..76b87bc --- /dev/null +++ b/src/utils/path-key.ts @@ -0,0 +1,7 @@ +export const getPathKey = () => { + // 从localtion.href的路径中,/a/b 中 a为path,b为key + const pathname = location.pathname; + const paths = pathname.split('/'); + const [path, key] = paths.slice(1); + return { path, key, id: path + '---' + key, prefix: `/${path}/${key}` }; +}; diff --git a/src/web-config.ts b/src/web-config.ts new file mode 100644 index 0000000..0e41401 --- /dev/null +++ b/src/web-config.ts @@ -0,0 +1,41 @@ +import { getPathKey } from './utils/path-key.ts'; + +type GlobalConfig = { + name?: string; + [key: string]: any; +}; +export const useConfig = (initConfig?: GlobalConfig) => { + const config: GlobalConfig = (window as any).config; + const _config = config || initConfig; + !config && ((window as any)['config'] = _config); + return _config; +}; + +export const useConfigKey = (key: string, init: () => T): T => { + const _config = useConfig({}); + if (key && init) { + _config[key] = init(); + return _config[key] as any; + } + if (key) { + return _config[key]; + } + return _config as any; +}; + +export const useConfigKeySync = async (key: string, init: () => Promise): Promise => { + const _config = useConfig({}); + if (key && init) { + _config[key] = await init(); + return _config[key] as any; + } + if (key) { + return _config[key]; + } + return _config as any; +}; + +export const usePageConfig = (init?: () => {}) => { + const { id } = getPathKey(); + return useConfigKey(id, init); +}; diff --git a/src/web-context.ts b/src/web-context.ts new file mode 100644 index 0000000..79005ad --- /dev/null +++ b/src/web-context.ts @@ -0,0 +1,41 @@ +import { getPathKey } from './utils/path-key.ts'; + +type GlobalContext = { + name?: string; + [key: string]: any; +}; +export const useContext = (initContext?: GlobalContext) => { + const context: GlobalContext = (window as any).context; + const _context = context || initContext; + !context && ((window as any)['context'] = _context); + return _context; +}; + +export const useContextKey = (key: string, init: () => T): T => { + const _context = useContext({}); + if (key && init) { + _context[key] = init(); + return _context[key] as any; + } + if (key) { + return _context[key]; + } + return _context as any; +}; + +export const useContextKeySync = async (key: string, init: () => Promise): Promise => { + const _context = useContext({}); + if (key && init) { + _context[key] = await init(); + return _context[key] as any; + } + if (key) { + return _context[key]; + } + return _context as any; +}; + +export const usePageContext = (init?: () => {}) => { + const { id } = getPathKey(); + return useContextKey(id, init); +};