diff --git a/.changeset/dry-cooks-unite.md b/.changeset/dry-cooks-unite.md new file mode 100644 index 0000000..380b24f --- /dev/null +++ b/.changeset/dry-cooks-unite.md @@ -0,0 +1,9 @@ +--- +"@nailyjs/typeorm": patch +"@nailyjs/config": patch +"@nailyjs/eslint": patch +"@nailyjs/cache": patch +"@nailyjs/ioc": patch +--- + +feat: add global intelliSense helper interface, update all packages and add cache module diff --git a/naily.config.ts b/naily.config.ts index 242398e..4f3972f 100644 --- a/naily.config.ts +++ b/naily.config.ts @@ -4,8 +4,6 @@ import { defineConfig } from './packages/config/src/helper' export default defineConfig({ naily: { - cli: {}, - eslint: { type: 'lib', rules: { @@ -18,6 +16,8 @@ export default defineConfig({ }, }, + cacheManager: {}, + typeorm: { type: 'sqlite', database: path.join(cwd(), './node_modules/.cache/naily/typeorm.db'), diff --git a/package.json b/package.json index 2878f44..a6fbb93 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "build:rpc": "pnpm -F @nailyjs/rpc build", "build:eslint": "pnpm -F @nailyjs/eslint build", "build:unplugin-rpc": "pnpm -F unplugin-rpc build", + "build:cache": "pnpm -F @nailyjs/cache build", "play:rpc": "pnpm -F rpc dev", "lint": "eslint .", diff --git a/packages/cache/package.json b/packages/cache/package.json new file mode 100644 index 0000000..7d9b167 --- /dev/null +++ b/packages/cache/package.json @@ -0,0 +1,33 @@ +{ + "name": "@nailyjs/cache", + "type": "module", + "version": "2.0.1", + "description": "Cache manager package for naily.js", + "author": "Naily Zero (https://naily.cc)", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "publishConfig": { + "access": "public" + }, + "scripts": { + "build": "tsup", + "watch": "tsup -w", + "prepublishOnly": "tsup" + }, + "dependencies": { + "@nailyjs/config": "workspace:*", + "@nailyjs/ioc": "workspace:*", + "cache-manager": "^6.1.2" + }, + "devDependencies": { + "tsup": "^8.3.0" + } +} diff --git a/packages/cache/src/cache.service.ts b/packages/cache/src/cache.service.ts new file mode 100644 index 0000000..88cdd3f --- /dev/null +++ b/packages/cache/src/cache.service.ts @@ -0,0 +1,40 @@ +import { Value } from '@nailyjs/config' +import { Autowired, ClassWrapper, Container, Optional, Service } from '@nailyjs/ioc' +import { createCache } from 'cache-manager' +import { CustomCacheManager } from './configure-cache-protocol' + +export const CACHE_MANAGER = '__naily_cache_manager__' + +@Service() +export class CacheFactoryService { + constructor( + @Value('naily.cacheManager') + private cacheOptions: Naily.Configuration.NailyUserConfig['cacheManager'], + @Optional() + @Autowired(CustomCacheManager) + private readonly configureService: CustomCacheManager, + ) {} + + async setup(container: Container): Promise { + let cacheOptions = this.cacheOptions + if (this.configureService && typeof this.configureService.configure === 'function') + cacheOptions = await this.configureService.configure(cacheOptions) + + if (Array.isArray(cacheOptions)) { + for (const cacheOption of cacheOptions) { + const cacheInstance = createCache(cacheOption) + container.createConstantWrapper(cacheOption.injectionToken, cacheInstance).save() + } + } + else { + const cacheInstance = createCache() + container.createConstantWrapper(CACHE_MANAGER, cacheInstance).save() + } + } + + static getInstance(container: Container): CacheFactoryService { + const wrapper = container.getContainer().get(CacheFactoryService) as ClassWrapper + if (wrapper && wrapper.wrapperType === 'class') return wrapper.getClassFactory().getOrCreateInstance() + return container.createClassWrapper(CacheFactoryService).getClassFactory().getOrCreateInstance() + } +} diff --git a/packages/cache/src/configure-cache-protocol.ts b/packages/cache/src/configure-cache-protocol.ts new file mode 100644 index 0000000..c2ae3ba --- /dev/null +++ b/packages/cache/src/configure-cache-protocol.ts @@ -0,0 +1,4 @@ +export const CustomCacheManager = '__naily_custom_cache_manager__' +export interface CustomCacheManager { + configure(cacheManagerOptions: Naily.Configuration.NailyUserConfig['cache']): Naily.Configuration.NailyUserConfig['cache'] | Promise +} diff --git a/packages/cache/src/index.ts b/packages/cache/src/index.ts new file mode 100644 index 0000000..381a70d --- /dev/null +++ b/packages/cache/src/index.ts @@ -0,0 +1,4 @@ +export * from './cache.service' +export * from './configure-cache-protocol' +export * from './plugin' +export * from './types' diff --git a/packages/cache/src/plugin.ts b/packages/cache/src/plugin.ts new file mode 100644 index 0000000..dc55012 --- /dev/null +++ b/packages/cache/src/plugin.ts @@ -0,0 +1,14 @@ +import { Container, IocPlugin } from '@nailyjs/ioc' +import { CacheFactoryService } from './cache.service' + +class CachePluginImpl implements IocPlugin { + name: string = 'naily:cache-manager-plugin' + + beforeRun(container: Container): void { + CacheFactoryService.getInstance(container).setup(container) + } +} + +export function CachePlugin(): IocPlugin { + return new CachePluginImpl() +} diff --git a/packages/cache/src/types.ts b/packages/cache/src/types.ts new file mode 100644 index 0000000..5ed2e86 --- /dev/null +++ b/packages/cache/src/types.ts @@ -0,0 +1,24 @@ +import { InjectionTokenable } from '@nailyjs/ioc' +import { CreateCacheOptions } from 'cache-manager' + +declare global { + namespace Naily { + namespace Configuration { + interface NailyUserConfig { + /** + * Cache manager options. + * + * @see https://github.com/jaredwray/cacheable + * @see https://www.npmjs.com/package/cache-manager + */ + cacheManager?: CacheManagerOptions | InjectionTokenable[] + } + interface NailyUserIntelliSense { + cacheManager?: CacheManagerOptions + } + } + } +} + +export interface CacheManagerOptions extends CreateCacheOptions { +} diff --git a/packages/cache/tsconfig.json b/packages/cache/tsconfig.json new file mode 100644 index 0000000..ddc0a63 --- /dev/null +++ b/packages/cache/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2022", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "ES2022", + "moduleResolution": "Bundler" + }, + "include": ["src"] +} diff --git a/packages/cache/tsup.config.ts b/packages/cache/tsup.config.ts new file mode 100644 index 0000000..31fd75b --- /dev/null +++ b/packages/cache/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: { + index: './src/index.ts', + }, + dts: true, + sourcemap: true, + clean: true, + format: ['cjs', 'esm'], +}) diff --git a/packages/config/src/decorators/value.decorator.ts b/packages/config/src/decorators/value.decorator.ts index 072faa6..a31314e 100644 --- a/packages/config/src/decorators/value.decorator.ts +++ b/packages/config/src/decorators/value.decorator.ts @@ -11,7 +11,7 @@ export interface ValueMetadata { parameterIndex?: number } -export function Value = Naily.Configuration.UserConfig>(jexl: Path> | (string & {})): PropertyDecorator & ParameterDecorator +export function Value = Naily.Configuration.UserIntelliSense>(jexl: Path> | (string & {})): PropertyDecorator & ParameterDecorator export function Value(jexl: Key): PropertyDecorator & ParameterDecorator export function Value(jexl: string = ''): PropertyDecorator & ParameterDecorator { return ((target: Object, propertyKey: string | symbol, parameterIndex?: number) => { diff --git a/packages/config/src/helper.ts b/packages/config/src/helper.ts index adad77e..911137a 100644 --- a/packages/config/src/helper.ts +++ b/packages/config/src/helper.ts @@ -8,6 +8,14 @@ declare global { naily?: NailyUserConfig [key: string]: any } + + export interface NailyUserIntelliSense { + [key: string]: any + } + export interface UserIntelliSense { + naily?: NailyUserIntelliSense + [key: string]: any + } } } } diff --git a/packages/eslint/src/index.ts b/packages/eslint/src/index.ts index de8eb47..ce06fd2 100644 --- a/packages/eslint/src/index.ts +++ b/packages/eslint/src/index.ts @@ -49,3 +49,6 @@ export async function nailyProxy(): Promise> { } export default naily + +export * from './eslint-bootstrap' +export * from './types' diff --git a/packages/eslint/src/types.ts b/packages/eslint/src/types.ts index 99cb0e7..c1747ce 100644 --- a/packages/eslint/src/types.ts +++ b/packages/eslint/src/types.ts @@ -16,6 +16,12 @@ declare global { * ``` * It will proxy the config from `naily.config.ts` to this `naily.eslint` object. */ + eslint?: Parameters[0] & { + extraOptions?: Array[1]> + } + } + + interface NailyUserIntelliSense { eslint?: Omit[0], 'overrides'> & { extraOptions?: Array[1]> } diff --git a/packages/ioc/src/types.ts b/packages/ioc/src/types.ts index a1e484a..9ebcd3c 100644 --- a/packages/ioc/src/types.ts +++ b/packages/ioc/src/types.ts @@ -62,3 +62,6 @@ export interface IPostConstructCatchContext extends ErrorHandlerContext { export interface PostConstructErrorHandler extends ErrorHandler { catch(error: any, context: IPostConstructCatchContext): any } +export type InjectionTokenable> = T & { + injectionToken: string +} diff --git a/packages/typeorm/src/datasource.ts b/packages/typeorm/src/datasource.ts index 81fc9f1..780620c 100644 --- a/packages/typeorm/src/datasource.ts +++ b/packages/typeorm/src/datasource.ts @@ -4,11 +4,14 @@ import { DataSource, type DataSourceOptions } from 'typeorm' declare global { namespace Naily { - export namespace Configuration { - export interface NailyUserConfig { + namespace Configuration { + interface NailyUserConfig { /** TypeORM configuration */ typeorm?: DataSourceOptions } + interface NailyUserIntelliSense { + typeorm?: DataSourceOptions + } } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4206eea..a65972a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -146,6 +146,22 @@ importers: specifier: ^8.3.0 version: 8.3.5(@swc/core@1.7.42)(jiti@2.4.0)(postcss@8.4.47)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.6.0) + packages/cache: + dependencies: + '@nailyjs/config': + specifier: workspace:* + version: link:../config + '@nailyjs/ioc': + specifier: workspace:* + version: link:../ioc + cache-manager: + specifier: ^6.1.2 + version: 6.1.2 + devDependencies: + tsup: + specifier: ^8.3.0 + version: 8.3.5(@swc/core@1.7.42)(jiti@2.4.0)(postcss@8.4.47)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.6.0) + packages/cli: dependencies: '@nailyjs/config': @@ -1037,6 +1053,9 @@ packages: resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==} engines: {node: '>=10'} + '@keyv/serialize@1.0.1': + resolution: {integrity: sha512-kKXeynfORDGPUEEl2PvTExM2zs+IldC6ZD8jPcfvI351MDNtfMlw9V9s4XZXuJNDK2qR5gbEKxRyoYx3quHUVQ==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1652,6 +1671,9 @@ packages: resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} engines: {node: '>= 10'} + cache-manager@6.1.2: + resolution: {integrity: sha512-hBFCGc7g1sVMto7+Dwr1BWrOXOMuLvC77SbTYaI44tZPFK9myaySBmgvmBYgc7iqbG/qNyUc6oyuDOcHn6oTvw==} + call-me-maybe@1.0.2: resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} @@ -2683,6 +2705,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@5.1.3: + resolution: {integrity: sha512-qWefZgq3GByWFTQgn+C9U7iaHe+mwAVb1utqbna15ggTO5RiLSL91NY+5liTgzchAhGhI6MOn5NVVn/eR1FkPA==} + kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -4858,6 +4883,10 @@ snapshots: string-argv: 0.3.2 type-detect: 4.1.0 + '@keyv/serialize@1.0.1': + dependencies: + buffer: 6.0.3 + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.26.0 @@ -5576,6 +5605,10 @@ snapshots: - bluebird optional: true + cache-manager@6.1.2: + dependencies: + keyv: 5.1.3 + call-me-maybe@1.0.2: {} callsites@3.1.0: {} @@ -6688,6 +6721,10 @@ snapshots: dependencies: json-buffer: 3.0.1 + keyv@5.1.3: + dependencies: + '@keyv/serialize': 1.0.1 + kleur@3.0.3: {} klona@2.0.6: {}