diff --git a/packages/@core/base/shared/build.config.ts b/packages/@core/base/shared/build.config.ts index 98e2209fe8d..0d8917f4173 100644 --- a/packages/@core/base/shared/build.config.ts +++ b/packages/@core/base/shared/build.config.ts @@ -10,5 +10,6 @@ export default defineBuildConfig({ 'src/color/index', 'src/cache/index', 'src/global-state', + 'src/crypto/index', ], }); diff --git a/packages/@core/base/shared/package.json b/packages/@core/base/shared/package.json index 6541b7772f4..073b748bf71 100644 --- a/packages/@core/base/shared/package.json +++ b/packages/@core/base/shared/package.json @@ -48,6 +48,11 @@ "types": "./dist/global-state.d.ts", "development": "./src/global-state.ts", "default": "./dist/global-state.mjs" + }, + "./crypto": { + "types": "./dist/crypto/index.d.ts", + "development": "./src/crypto/index.ts", + "default": "./dist/crypto/index.mjs" } }, "publishConfig": { @@ -75,6 +80,10 @@ "./global-state": { "types": "./dist/global-state.d.ts", "default": "./dist/global-state.mjs" + }, + "./crypto": { + "types": "./dist/crypto/index.d.ts", + "default": "./dist/crypto/index.mjs" } } }, @@ -84,14 +93,17 @@ "@types/lodash.get": "catalog:", "@vue/shared": "catalog:", "clsx": "catalog:", + "crypto-js": "catalog:", "defu": "catalog:", "lodash.clonedeep": "catalog:", "lodash.get": "catalog:", + "nanoid": "catalog:", "nprogress": "catalog:", "tailwind-merge": "catalog:", "theme-colors": "catalog:" }, "devDependencies": { + "@types/crypto-js": "catalog:", "@types/lodash.clonedeep": "catalog:", "@types/nprogress": "catalog:" } diff --git a/packages/@core/base/shared/src/crypto/index.ts b/packages/@core/base/shared/src/crypto/index.ts new file mode 100644 index 00000000000..17b4cc45a2f --- /dev/null +++ b/packages/@core/base/shared/src/crypto/index.ts @@ -0,0 +1,33 @@ +import CryptoJS from 'crypto-js'; + +export { CryptoJS }; +const MIN_SECRET_LENGTH = 32; +export class Crypto { + /** Secret */ + private readonly secret: string; + constructor(secret: string) { + if (typeof secret === 'string' && secret.length < MIN_SECRET_LENGTH) { + throw new Error( + `Secret must be at least ${MIN_SECRET_LENGTH} characters long`, + ); + } + this.secret = secret; + } + + decrypt(encrypted: string) { + const decrypted = CryptoJS.AES.decrypt(encrypted, this.secret); + const dataString = decrypted.toString(CryptoJS.enc.Utf8); + try { + return JSON.parse(dataString) as T; + } catch { + // avoid parse error + return null; + } + } + + encrypt(data: T): string { + const dataString = JSON.stringify(data); + const encrypted = CryptoJS.AES.encrypt(dataString, this.secret); + return encrypted.toString(); + } +} diff --git a/packages/@core/base/shared/src/utils/__tests__/nanoid.test.ts b/packages/@core/base/shared/src/utils/__tests__/nanoid.test.ts new file mode 100644 index 00000000000..122dc07c7b7 --- /dev/null +++ b/packages/@core/base/shared/src/utils/__tests__/nanoid.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest'; + +import { nanoid } from '../nanoid'; + +describe('nanoid', () => { + it('create uuid', () => { + const _nanoid = nanoid(); + // console.log('uuid:', _nanoid); + // expect(!!_nanoid).toBe(true); + expect(typeof _nanoid).toBe('string'); + expect(_nanoid.length).toBeGreaterThan(0); + }); + it('should generate unique ids', () => { + const ids = new Set(); + for (let i = 0; i < 1000; i++) { + const id = nanoid(); + expect(ids.has(id)).toBe(false); + ids.add(id); + } + }); +}); diff --git a/packages/@core/base/shared/src/utils/index.ts b/packages/@core/base/shared/src/utils/index.ts index e5526edf00a..dd584993a67 100644 --- a/packages/@core/base/shared/src/utils/index.ts +++ b/packages/@core/base/shared/src/utils/index.ts @@ -4,6 +4,7 @@ export * from './dom'; export * from './inference'; export * from './letter'; export * from './merge'; +export * from './nanoid'; export * from './nprogress'; export * from './state-handler'; export * from './to'; diff --git a/packages/@core/base/shared/src/utils/nanoid.ts b/packages/@core/base/shared/src/utils/nanoid.ts new file mode 100644 index 00000000000..924cef4fc9d --- /dev/null +++ b/packages/@core/base/shared/src/utils/nanoid.ts @@ -0,0 +1 @@ +export { nanoid } from 'nanoid'; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 80263b6ab65..bb7b4eb555b 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,4 +1,5 @@ export * from './helpers'; export * from '@vben-core/shared/cache'; export * from '@vben-core/shared/color'; +export * from '@vben-core/shared/crypto'; export * from '@vben-core/shared/utils'; diff --git a/playground/src/router/routes/modules/demos.ts b/playground/src/router/routes/modules/demos.ts index f587e0beafe..7a91fb1507e 100644 --- a/playground/src/router/routes/modules/demos.ts +++ b/playground/src/router/routes/modules/demos.ts @@ -221,6 +221,15 @@ const routes: RouteRecordRaw[] = [ title: 'Tanstack Query', }, }, + { + name: 'CryptoDemo', + path: '/demos/features/crypto', + component: () => import('#/views/demos/features/crypto/index.vue'), + meta: { + icon: 'lucide:message-square-lock', + title: 'Crypto Demo', + }, + }, ], }, // 面包屑导航 diff --git a/playground/src/views/demos/features/crypto/index.vue b/playground/src/views/demos/features/crypto/index.vue new file mode 100644 index 00000000000..f390c6f90a9 --- /dev/null +++ b/playground/src/views/demos/features/crypto/index.vue @@ -0,0 +1,215 @@ + + +