diff --git a/packages/core/acl/src/acl.ts b/packages/core/acl/src/acl.ts index e750f663fe..db52b9a72f 100644 --- a/packages/core/acl/src/acl.ts +++ b/packages/core/acl/src/acl.ts @@ -45,14 +45,40 @@ interface CanArgs { } export class ACL extends EventEmitter { + /** + * @internal + */ public availableStrategy = new Map(); + + /** + * @internal + */ public allowManager = new AllowManager(this); + + /** + * @internal + */ public snippetManager = new SnippetManager(); + + /** + * @internal + */ roles = new Map(); + + /** + * @internal + */ actionAlias = new Map(); + + /** + * @internal + */ configResources: string[] = []; + protected availableActions = new Map(); + protected fixedParamsManager = new FixedParamsManager(); + protected middlewares: Toposort; constructor() { @@ -114,14 +140,23 @@ export class ACL extends EventEmitter { return this.roles.delete(name); } + /** + * @internal + */ registerConfigResources(names: string[]) { names.forEach((name) => this.registerConfigResource(name)); } + /** + * @internal + */ registerConfigResource(name: string) { this.configResources.push(name); } + /** + * @internal + */ isConfigResource(name: string) { return this.configResources.includes(name); } @@ -227,6 +262,9 @@ export class ACL extends EventEmitter { return null; } + /** + * @internal + */ public resolveActionAlias(action: string) { return this.actionAlias.get(action) ? this.actionAlias.get(action) : action; } @@ -242,6 +280,9 @@ export class ACL extends EventEmitter { return this.skip(resourceName, actionNames, condition); } + /** + * @deprecated + */ skip(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc) { if (!Array.isArray(actionNames)) { actionNames = [actionNames]; @@ -252,6 +293,9 @@ export class ACL extends EventEmitter { } } + /** + * @internal + */ async parseJsonTemplate(json: any, ctx: any) { if (json.filter) { ctx.logger?.info?.('parseJsonTemplate.raw', JSON.parse(JSON.stringify(json.filter))); @@ -295,6 +339,9 @@ export class ACL extends EventEmitter { }; } + /** + * @internal + */ async getActionParams(ctx) { const roleName = ctx.state.currentRole || 'anonymous'; const { resourceName, actionName } = ctx.action; @@ -322,6 +369,9 @@ export class ACL extends EventEmitter { this.snippetManager.register(snippet); } + /** + * @internal + */ filterParams(ctx, resourceName, params) { if (params?.filter?.createdById) { const collection = ctx.db.getCollection(resourceName); diff --git a/packages/core/client/src/application/PluginSettingsManager.ts b/packages/core/client/src/application/PluginSettingsManager.ts index 3a5a12a8a9..1b08efe793 100644 --- a/packages/core/client/src/application/PluginSettingsManager.ts +++ b/packages/core/client/src/application/PluginSettingsManager.ts @@ -11,7 +11,7 @@ export const ADMIN_SETTINGS_PATH = '/admin/settings/'; export const SNIPPET_PREFIX = 'pm.'; export interface PluginSettingOptions { - title: string | React.ReactElement; + title: any; /** * @default Outlet */ diff --git a/packages/core/resourcer/src/action.ts b/packages/core/resourcer/src/action.ts index 6db30eebc8..98594d1ce0 100644 --- a/packages/core/resourcer/src/action.ts +++ b/packages/core/resourcer/src/action.ts @@ -1,10 +1,9 @@ -import { assign, MergeStrategies, prePerfHooksWrap, requireModule } from '@nocobase/utils'; +import { assign, MergeStrategies, requireModule } from '@nocobase/utils'; import compose from 'koa-compose'; import _ from 'lodash'; import Middleware, { MiddlewareType } from './middleware'; import Resource from './resource'; import { HandlerType } from './resourcer'; -import { RecordableHistogram, performance } from 'perf_hooks'; export type ActionType = string | HandlerType | ActionOptions; @@ -161,27 +160,38 @@ export interface ActionParams { */ values?: any; /** - * 当前资源的主体,对应的表名或 Model 名称 + * This method is deprecated and should not be used. + * Use {@link action.resourceName.split(',')[0]} instead. + * @deprecated */ resourceName?: string; /** - * 资源标识符 + * This method is deprecated and should not be used. + * Use {@link filterByTk} instead. + * @deprecated */ resourceIndex?: string; /** - * 资源的从属关系 + * This method is deprecated and should not be used. + * Use {@link action.resourceName.split(',')[1]} instead. + * @deprecated */ associatedName?: string; /** - * 从属关系的标识符 + * This method is deprecated and should not be used. + * Use {@link action.sourceId} instead. + * @deprecated */ associatedIndex?: string; /** - * 从属关系的当前实例 + * This method is deprecated and should not be used. + * @deprecated */ associated?: any; /** - * 资源提供哪些行为或方法 + * This method is deprecated and should not be used. + * Use {@link action.actionName} instead. + * @deprecated */ actionName?: string; /** @@ -204,11 +214,23 @@ export class Action { public params: ActionParams = {}; public actionName: string; + public resourceName: string; + + /** + * This method is deprecated and should not be used. + * Use {@link this.sourceId} instead. + * @deprecated + */ public resourceOf: any; + public sourceId: any; + public readonly middlewares: Array = []; + /** + * @internal + */ constructor(options: ActionOptions) { options = requireModule(options); if (typeof options === 'function') { @@ -221,15 +243,22 @@ export class Action { this.mergeParams(params); } + /** + * @internal + */ toJSON() { return { actionName: this.actionName, resourceName: this.resourceName, - resourceOf: this.resourceOf, + resourceOf: this.sourceId, + sourceId: this.sourceId, params: this.params, }; } + /** + * @internal + */ clone() { const options = _.cloneDeep(this.options); delete options.middleware; @@ -241,6 +270,9 @@ export class Action { return action; } + /** + * @internal + */ setContext(context: any) { this.context = context; } @@ -266,34 +298,55 @@ export class Action { }); } + /** + * @internal + */ setResource(resource: Resource) { this.resource = resource; return this; } + /** + * @internal + */ getResource() { return this.resource; } + /** + * @internal + */ getOptions(): ActionOptions { return this.options; } + /** + * @internal + */ setName(name: ActionName) { this.name = name; return this; } + /** + * @internal + */ getName() { return this.name; } + /** + * @internal + */ getMiddlewareHandlers() { return this.middlewares .filter((middleware) => middleware.canAccess(this.name)) .map((middleware) => middleware.getHandler()); } + /** + * @internal + */ getHandler() { const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name)); if (typeof handler !== 'function') { @@ -303,6 +356,9 @@ export class Action { return handler; } + /** + * @internal + */ getHandlers() { const handlers = [ ...this.resource.resourcer.getMiddlewares(), @@ -315,10 +371,16 @@ export class Action { return handlers; } + /** + * @internal + */ async execute(context: any, next?: any) { return await compose(this.getHandlers())(context, next); } + /** + * @internal + */ static toInstanceMap(actions: object, resource?: Resource) { return new Map( Object.entries(actions).map(([key, options]) => { diff --git a/packages/core/resourcer/src/resourcer.ts b/packages/core/resourcer/src/resourcer.ts index c223ffd87b..25eb37c049 100644 --- a/packages/core/resourcer/src/resourcer.ts +++ b/packages/core/resourcer/src/resourcer.ts @@ -150,6 +150,9 @@ export interface ImportOptions { } export class Resourcer { + /** + * @internal + */ public readonly options: ResourcerOptions; protected resources = new Map(); /** @@ -173,6 +176,7 @@ export class Resourcer { * @param {object} [options] * @param {string} [options.directory] 指定配置所在路径 * @param {array} [options.extensions = ['js', 'ts', 'json']] 文件后缀 + * */ public async import(options: ImportOptions): Promise> { const { extensions = ['js', 'ts', 'json'], directory } = options; @@ -206,14 +210,27 @@ export class Resourcer { return this.resources.has(name); } + /** + * @internal + */ removeResource(name) { return this.resources.delete(name); } + /** + * This method is deprecated and should not be used. + * Use {@link this.registerActionHandler()} instead. + * @deprecated + */ registerAction(name: ActionName, handler: HandlerType) { this.registerActionHandler(name, handler); } + /** + * This method is deprecated and should not be used. + * Use {@link this.registerActionHandlers()} instead. + * @deprecated + */ registerActions(handlers: Handlers) { this.registerActionHandlers(handlers); } @@ -233,14 +250,23 @@ export class Resourcer { this.actionHandlers.set(name, handler); } + /** + * @internal + */ getRegisteredHandler(name: ActionName) { return this.actionHandlers.get(name); } + /** + * @internal + */ getRegisteredHandlers() { return this.actionHandlers; } + /** + * @internal + */ getResource(name: string): Resource { if (!this.resources.has(name)) { throw new Error(`${name} resource does not exist`); @@ -248,6 +274,9 @@ export class Resourcer { return this.resources.get(name); } + /** + * @internal + */ getAction(name: string, action: ActionName): Action { // 支持注册局部 action if (this.actionHandlers.has(`${name}:${action}`)) { @@ -256,6 +285,9 @@ export class Resourcer { return this.getResource(name).getAction(action); } + /** + * @internal + */ getMiddlewares() { return this.middlewares.nodes; } @@ -264,6 +296,11 @@ export class Resourcer { this.middlewares.add(middlewares, options); } + /** + * This method is deprecated and should not be used. + * Use {@link this.middleware()} instead. + * @deprecated + */ restApiMiddleware({ prefix, accessors, skipIfDataSourceExists = false }: KoaMiddlewareOptions = {}) { return async (ctx: ResourcerContext, next: () => Promise) => { if (skipIfDataSourceExists) { @@ -317,6 +354,7 @@ export class Resourcer { ctx.action.setContext(ctx); ctx.action.actionName = params.actionName; + ctx.action.sourceId = params.associatedIndex; ctx.action.resourceOf = params.associatedIndex; ctx.action.resourceName = params.associatedName ? `${params.associatedName}.${params.resourceName}` @@ -349,11 +387,7 @@ export class Resourcer { } /** - * 实验性 API - * - * @param options - * @param context - * @param next + * @internal */ async execute(options: ExecuteOptions, context: ResourcerContext = {}, next?: any) { const { resource, action } = options; diff --git a/packages/core/server/src/application.ts b/packages/core/server/src/application.ts index 975427fa86..9ec4ba12c5 100644 --- a/packages/core/server/src/application.ts +++ b/packages/core/server/src/application.ts @@ -139,19 +139,41 @@ export type MaintainingCommandStatus = { }; export class Application extends Koa implements AsyncEmitter { + /** + * @internal + */ declare middleware: any; + /** + * @internal + */ stopped = false; + /** + * @internal + */ ready = false; declare emitAsync: (event: string | symbol, ...args: any[]) => Promise; + /** + * @internal + */ public rawOptions: ApplicationOptions; + /** + * @internal + */ public activatedCommand: { name: string; } = null; + /** + * @internal + */ public running = false; + /** + * @internal + */ public perfHistograms = new Map(); protected plugins = new Map(); protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance(); protected _started: boolean; + protected _logger: SystemLogger; private _authenticated = false; private _maintaining = false; private _maintainingCommandStatus: MaintainingCommandStatus; @@ -169,12 +191,18 @@ export class Application exten protected _loaded: boolean; + /** + * @internal + */ get loaded() { return this._loaded; } private _maintainingMessage: string; + /** + * @internal + */ get maintainingMessage() { return this._maintainingMessage; } @@ -198,8 +226,6 @@ export class Application exten return this.mainDataSource.collectionManager.db; } - protected _logger: SystemLogger; - get logger() { return this._logger; } @@ -220,6 +246,9 @@ export class Application exten return this._cache; } + /** + * @internal + */ set cache(cache: Cache) { this._cache = cache; } @@ -254,6 +283,11 @@ export class Application exten protected _locales: Locale; + /** + * This method is deprecated and should not be used. + * Use {@link #localeManager} instead. + * @deprecated + */ get locales() { return this._locales; } @@ -288,10 +322,16 @@ export class Application exten return this._dataSourceManager; } + /** + * @internal + */ getMaintaining() { return this._maintainingCommandStatus; } + /** + * @internal + */ setMaintaining(_maintainingCommandStatus: MaintainingCommandStatus) { this._maintainingCommandStatus = _maintainingCommandStatus; @@ -305,6 +345,9 @@ export class Application exten this._maintaining = true; } + /** + * @internal + */ setMaintainingMessage(message: string) { this._maintainingMessage = message; @@ -314,11 +357,18 @@ export class Application exten }); } + /** + * This method is deprecated and should not be used. + * Use {@link #this.version.get()} instead. + * @deprecated + */ getVersion() { return packageJson.version; } /** + * This method is deprecated and should not be used. + * Use {@link #this.pm.addPreset()} instead. * @deprecated */ plugin(pluginClass: any, options?: O) { @@ -335,6 +385,9 @@ export class Application exten return this; } + /** + * @internal + */ callback() { const fn = compose(this.middleware.nodes); @@ -348,14 +401,29 @@ export class Application exten }; } + /** + * This method is deprecated and should not be used. + * Use {@link #this.db.collection()} instead. + * @deprecated + */ collection(options: CollectionOptions) { return this.db.collection(options); } + /** + * This method is deprecated and should not be used. + * Use {@link #this.resourcer.define()} instead. + * @deprecated + */ resource(options: ResourceOptions) { return this.resourcer.define(options); } + /** + * This method is deprecated and should not be used. + * Use {@link #this.resourcer.registerActions()} instead. + * @deprecated + */ actions(handlers: any, options?: ActionsOptions) { return this.resourcer.registerActions(handlers); } @@ -368,11 +436,9 @@ export class Application exten return (this.cli as any)._findCommand(name); } - async preload() { - // load core collections - // load plugin commands - } - + /** + * @internal + */ async reInit() { if (!this._loaded) { return; @@ -476,12 +542,19 @@ export class Application exten } /** + * This method is deprecated and should not be used. + * Use {@link this.pm.get()} instead. * @deprecated */ getPlugin

(name: string | typeof Plugin) { return this.pm.get(name) as P; } + /** + * This method is deprecated and should not be used. + * Use {@link this.runAsCLI()} instead. + * @deprecated + */ async parse(argv = process.argv) { return this.runAsCLI(argv); } @@ -504,7 +577,7 @@ export class Application exten return await this.runAsCLI([command, ...args], { from: 'user', throwError: true }); } - createCli() { + protected createCLI() { const command = new AppCommand('nocobase') .usage('[command] [options]') .hook('preAction', async (_, actionCommand) => { @@ -544,6 +617,9 @@ export class Application exten return command; } + /** + * @internal + */ async loadMigrations(options) { const { directory, context, namespace } = options; const migrations = { @@ -570,6 +646,9 @@ export class Application exten return migrations; } + /** + * @internal + */ async loadCoreMigrations() { const migrations = await this.loadMigrations({ directory: resolve(__dirname, 'migrations'), @@ -600,11 +679,17 @@ export class Application exten }; } + /** + * @internal + */ async loadPluginCommands() { this.log.debug('load plugin commands'); await this.pm.loadCommands(); } + /** + * @internal + */ async runAsCLI(argv = process.argv, options?: ParseOptions & { throwError?: boolean; reqId?: string }) { if (this.activatedCommand) { return; @@ -689,6 +774,9 @@ export class Application exten this.stopped = false; } + /** + * @internal + */ async emitStartedEvent(options: StartOptions = {}) { await this.emitAsync('__started', this, { maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus), @@ -700,6 +788,9 @@ export class Application exten return this._started; } + /** + * @internal + */ async tryReloadOrRestart(options: StartOptions = {}) { if (this._started) { await this.restart(options); @@ -898,6 +989,9 @@ export class Application exten }; } + /** + * @internal + */ reInitEvents() { for (const eventName of this.eventNames()) { for (const listener of this.listeners(eventName)) { @@ -943,7 +1037,7 @@ export class Application exten this._cronJobManager = new CronJobManager(this); - this._cli = this.createCli(); + this._cli = this.createCLI(); this._i18n = createI18n(options); this.context.db = this.db; diff --git a/packages/core/server/src/plugin-manager/plugin-manager-repository.ts b/packages/core/server/src/plugin-manager/plugin-manager-repository.ts index 4fba1d7ffe..8cb74b198d 100644 --- a/packages/core/server/src/plugin-manager/plugin-manager-repository.ts +++ b/packages/core/server/src/plugin-manager/plugin-manager-repository.ts @@ -3,12 +3,21 @@ import lodash from 'lodash'; import { PluginManager } from './plugin-manager'; export class PluginManagerRepository extends Repository { + /** + * @internal + */ pm: PluginManager; + /** + * @internal + */ setPluginManager(pm: PluginManager) { this.pm = pm; } + /** + * @deprecated + */ async remove(name: string | string[]) { await this.destroy({ filter: { @@ -17,6 +26,9 @@ export class PluginManagerRepository extends Repository { }); } + /** + * @deprecated + */ async enable(name: string | string[]) { const pluginNames = lodash.castArray(name); const plugins = pluginNames.map((name) => this.pm.get(name)); @@ -56,6 +68,9 @@ export class PluginManagerRepository extends Repository { } } + /** + * @deprecated + */ async disable(name: string | string[]) { name = lodash.cloneDeep(name); diff --git a/packages/core/server/src/plugin-manager/plugin-manager.ts b/packages/core/server/src/plugin-manager/plugin-manager.ts index 3a1b72a11d..960be122b7 100644 --- a/packages/core/server/src/plugin-manager/plugin-manager.ts +++ b/packages/core/server/src/plugin-manager/plugin-manager.ts @@ -45,12 +45,39 @@ export interface InstallOptions { export class AddPresetError extends Error {} export class PluginManager { + /** + * @internal + */ app: Application; + + /** + * @internal + */ collection: Collection; + + /** + * @internal + */ pluginInstances = new Map(); + + /** + * @internal + */ pluginAliases = new Map(); + + /** + * @internal + */ server: net.Server; + /** + * @internal + */ + _repository: PluginManagerRepository; + + /** + * @internal + */ constructor(public options: PluginManagerOptions) { this.app = options.app; this.app.db.registerRepositories({ @@ -76,18 +103,22 @@ export class PluginManager { this.app.resourcer.use(uploadMiddleware); } - _repository: PluginManagerRepository; - get repository() { return this.app.db.getRepository('applicationPlugins') as PluginManagerRepository; } + /** + * @internal + */ static async getPackageJson(packageName: string) { const file = await fs.promises.realpath(resolve(process.env.NODE_MODULES_PATH, packageName, 'package.json')); const data = await fs.promises.readFile(file, { encoding: 'utf-8' }); return JSON.parse(data); } + /** + * @internal + */ static async getPackageName(name: string) { const prefixes = this.getPluginPkgPrefix(); for (const prefix of prefixes) { @@ -100,12 +131,18 @@ export class PluginManager { throw new Error(`${name} plugin does not exist`); } + /** + * @internal + */ static getPluginPkgPrefix() { return (process.env.PLUGIN_PACKAGE_PREFIX || '@nocobase/plugin-,@nocobase/preset-,@nocobase/plugin-pro-').split( ',', ); } + /** + * @internal + */ static async findPackage(name: string) { try { const packageName = this.getPackageName(name); @@ -130,6 +167,9 @@ export class PluginManager { throw new Error(`No available packages found, ${name} plugin does not exist`); } + /** + * @internal + */ static clearCache(packageName: string) { return; const packageNamePath = packageName.replace('/', sep); @@ -140,6 +180,9 @@ export class PluginManager { }); } + /** + * @internal + */ static async resolvePlugin(pluginName: string | typeof Plugin, isUpgrade = false, isPkg = false) { if (typeof pluginName === 'string') { const packageName = isPkg ? pluginName : await this.getPackageName(pluginName); @@ -296,11 +339,17 @@ export class PluginManager { await instance.afterAdd(); } + /** + * @internal + */ async initPlugins() { await this.initPresetPlugins(); await this.initOtherPlugins(); } + /** + * @internal + */ async loadCommands() { this.app.log.debug('load commands'); const items = await this.repository.find({ @@ -619,6 +668,9 @@ export class PluginManager { await execa('yarn', ['nocobase', 'refresh']); } + /** + * @deprecated + */ async loadOne(plugin: Plugin) { this.app.setMaintainingMessage(`loading plugin ${plugin.name}...`); if (plugin.state.loaded || !plugin.enabled) { @@ -637,6 +689,9 @@ export class PluginManager { this.app.setMaintainingMessage(`loaded plugin ${plugin.name}`); } + /** + * @internal + */ async addViaCLI(urlOrName: string, options?: PluginData) { if (isURL(urlOrName)) { await this.addByCompressedFileUrl({ @@ -679,6 +734,9 @@ export class PluginManager { await execa('yarn', ['nocobase', 'postinstall']); } + /** + * @internal + */ async addByNpm(options: { packageName: string; name?: string; registry: string; authToken?: string }) { let { name = '', registry, packageName, authToken } = options; name = name.trim(); @@ -693,6 +751,9 @@ export class PluginManager { return this.addByCompressedFileUrl({ name, compressedFileUrl, registry, authToken, type: 'npm' }); } + /** + * @internal + */ async addByFile(options: { file: string; registry?: string; authToken?: string; type?: string; name?: string }) { const { file, authToken } = options; @@ -708,6 +769,9 @@ export class PluginManager { return this.add(name, { packageName }, true); } + /** + * @internal + */ async addByCompressedFileUrl(options: { compressedFileUrl: string; registry?: string; @@ -748,6 +812,9 @@ export class PluginManager { await this.app.upgrade(); } + /** + * @internal + */ async upgradeByNpm(values: PluginData) { const name = values.name; const plugin = this.get(name); @@ -769,6 +836,9 @@ export class PluginManager { return this.upgradeByCompressedFileUrl({ compressedFileUrl, name, version, registry, authToken }); } + /** + * @internal + */ async upgradeByCompressedFileUrl(options: PluginData) { const { name, compressedFileUrl, authToken } = options; const data = await this.repository.findOne({ filter: { name } }); @@ -780,6 +850,9 @@ export class PluginManager { await this.add(name, { version, packageName: data.packageName }, true, true); } + /** + * @internal + */ getNameByPackageName(packageName: string) { const prefixes = PluginManager.getPluginPkgPrefix(); const prefix = prefixes.find((prefix) => packageName.startsWith(prefix)); @@ -808,12 +881,18 @@ export class PluginManager { ); } + /** + * @internal + */ async getNpmVersionList(name: string) { const plugin = this.get(name); const npmInfo = await getNpmInfo(plugin.options.packageName, plugin.options.registry, plugin.options.authToken); return Object.keys(npmInfo.versions); } + /** + * @internal + */ async loadPresetMigrations() { const migrations = { beforeLoad: [], @@ -854,6 +933,9 @@ export class PluginManager { }; } + /** + * @internal + */ async loadOtherMigrations() { const migrations = { beforeLoad: [], @@ -897,6 +979,9 @@ export class PluginManager { }; } + /** + * @internal + */ async loadPresetPlugins() { await this.initPresetPlugins(); await this.load(); @@ -931,6 +1016,9 @@ export class PluginManager { }); } + /** + * @internal + */ async initOtherPlugins() { if (this['_initOtherPlugins']) { return; @@ -939,6 +1027,9 @@ export class PluginManager { this['_initOtherPlugins'] = true; } + /** + * @internal + */ async initPresetPlugins() { if (this['_initPresetPlugins']) { return; diff --git a/packages/core/server/src/plugin.ts b/packages/core/server/src/plugin.ts index a97f1caec9..5f99eb840a 100644 --- a/packages/core/server/src/plugin.ts +++ b/packages/core/server/src/plugin.ts @@ -33,9 +33,22 @@ export interface PluginOptions { export abstract class Plugin implements PluginInterface { options: any; app: Application; + + /** + * @deprecated + */ model: Model; + + /** + * @internal + */ state: any = {}; + /** + * @internal + */ + private _sourceDir: string; + constructor(app: Application, options?: any) { this.app = app; this.setOptions(options); @@ -80,10 +93,6 @@ export abstract class Plugin implements PluginInterface { return this.options.isPreset; } - setOptions(options: any) { - this.options = options || {}; - } - getName() { return (this.options as any).name; } @@ -92,64 +101,6 @@ export abstract class Plugin implements PluginInterface { return this.app.createLogger(options); } - protected _sourceDir: string; - - protected async getSourceDir() { - if (this._sourceDir) { - return this._sourceDir; - } - if (await this.isDev()) { - return (this._sourceDir = 'src'); - } - if (basename(__dirname) === 'src') { - return (this._sourceDir = 'src'); - } - return (this._sourceDir = this.isPreset ? 'lib' : 'dist'); - } - - async loadCommands() { - const extensions = ['js', 'ts']; - const directory = resolve( - process.env.NODE_MODULES_PATH, - this.options.packageName, - await this.getSourceDir(), - 'server/commands', - ); - const patten = `${directory}/*.{${extensions.join(',')}}`; - const files = glob.sync(patten, { - ignore: ['**/*.d.ts'], - }); - for (const file of files) { - let filename = basename(file); - filename = filename.substring(0, filename.lastIndexOf('.')) || filename; - const callback = await importModule(file); - callback(this.app); - } - if (files.length) { - this.app.log.debug(`load commands [${this.name}]`); - } - } - - async loadMigrations() { - this.app.log.debug(`load plugin migrations [${this.name}]`); - if (!this.options.packageName) { - return { beforeLoad: [], afterSync: [], afterLoad: [] }; - } - const directory = resolve( - process.env.NODE_MODULES_PATH, - this.options.packageName, - await this.getSourceDir(), - 'server/migrations', - ); - return await this.app.loadMigrations({ - directory, - namespace: this.options.packageName, - context: { - plugin: this, - }, - }); - } - afterAdd() {} beforeLoad() {} @@ -172,13 +123,86 @@ export abstract class Plugin implements PluginInterface { async afterRemove() {} - async importCollections(collectionsPath: string) { - // await this.db.import({ - // directory: collectionsPath, - // from: `plugin:${this.getName()}`, - // }); + /** + * @deprecated + */ + async importCollections(collectionsPath: string) {} + + /** + * @internal + */ + setOptions(options: any) { + this.options = options || {}; } + /** + * @internal + */ + protected async getSourceDir() { + if (this._sourceDir) { + return this._sourceDir; + } + if (await this.isDev()) { + return (this._sourceDir = 'src'); + } + if (basename(__dirname) === 'src') { + return (this._sourceDir = 'src'); + } + return (this._sourceDir = this.isPreset ? 'lib' : 'dist'); + } + + /** + * @internal + */ + async loadCommands() { + const extensions = ['js', 'ts']; + const directory = resolve( + process.env.NODE_MODULES_PATH, + this.options.packageName, + await this.getSourceDir(), + 'server/commands', + ); + const patten = `${directory}/*.{${extensions.join(',')}}`; + const files = glob.sync(patten, { + ignore: ['**/*.d.ts'], + }); + for (const file of files) { + let filename = basename(file); + filename = filename.substring(0, filename.lastIndexOf('.')) || filename; + const callback = await importModule(file); + callback(this.app); + } + if (files.length) { + this.app.log.debug(`load commands [${this.name}]`); + } + } + + /** + * @internal + */ + async loadMigrations() { + this.app.log.debug(`load plugin migrations [${this.name}]`); + if (!this.options.packageName) { + return { beforeLoad: [], afterSync: [], afterLoad: [] }; + } + const directory = resolve( + process.env.NODE_MODULES_PATH, + this.options.packageName, + await this.getSourceDir(), + 'server/migrations', + ); + return await this.app.loadMigrations({ + directory, + namespace: this.options.packageName, + context: { + plugin: this, + }, + }); + } + + /** + * @internal + */ async loadCollections() { if (!this.options.packageName) { return; @@ -197,6 +221,9 @@ export abstract class Plugin implements PluginInterface { } } + /** + * @deprecated + */ requiredPlugins() { return []; } @@ -205,6 +232,9 @@ export abstract class Plugin implements PluginInterface { return this.app.i18n.t(text, { ns: this.options['packageName'], ...(options as any) }); } + /** + * @internal + */ protected async isDev() { if (!this.options.packageName) { return false; @@ -218,6 +248,9 @@ export abstract class Plugin implements PluginInterface { return false; } + /** + * @experimental + */ async toJSON(options: any = {}) { const { locale = 'en-US' } = options; const { name, packageName, packageJson } = this.options; diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/index.ts b/packages/plugins/@nocobase/plugin-acl/src/client/index.ts index 172585bc1d..cec44c813d 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/client/index.ts @@ -2,12 +2,12 @@ import { Plugin } from '@nocobase/client'; import { RolesManagement } from './RolesManagement'; import { RolesManager } from './roles-manager'; -class ACLPlugin extends Plugin { +export class PluginACLClient extends Plugin { rolesManager = new RolesManager(); async load() { - this.app.pluginSettingsManager.add('users-permissions.roles', { - title: '{{t("Roles & Permissions")}}', + this.pluginSettingsManager.add('users-permissions.roles', { + title: this.t('Roles & Permissions'), icon: 'LockOutlined', Component: RolesManagement, aclSnippet: 'pm.acl.roles', @@ -16,5 +16,5 @@ class ACLPlugin extends Plugin { } } -export default ACLPlugin; export { RolesManagerContext } from './RolesManagerProvider'; +export default PluginACLClient; diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/locale.ts b/packages/plugins/@nocobase/plugin-acl/src/client/locale.ts index e2996e2847..d80c57e434 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/locale.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/client/locale.ts @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; export function useACLTranslation() { - return useTranslation(['acl', 'client'], { nsMode: 'fallback' }); + return useTranslation(['@nocobase/plugin-acl', 'client'], { nsMode: 'fallback' }); } diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/permissions/ActionPermissions.tsx b/packages/plugins/@nocobase/plugin-acl/src/client/permissions/ActionPermissions.tsx index d174bdf583..e7038f66ef 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/permissions/ActionPermissions.tsx +++ b/packages/plugins/@nocobase/plugin-acl/src/client/permissions/ActionPermissions.tsx @@ -1,6 +1,6 @@ +import { ISchema, useForm } from '@formily/react'; import { CollectionContext, - CollectionProvider, CollectionProvider_deprecated, ResourceActionContext, SchemaComponent, @@ -8,17 +8,14 @@ import { useActionContext, useFilterFieldOptions, useFilterFieldProps, - useCollectionRecord, useRecord, useRequest, useResourceActionContext, } from '@nocobase/client'; import React, { useContext, useEffect } from 'react'; -import { roleCollectionsSchema } from '../schemas/roles'; import { RolesManagerContext } from '../RolesManagerProvider'; -import { ISchema } from '@formily/react'; +import { roleCollectionsSchema } from '../schemas/roles'; import { RolesResourcesActions } from './RolesResourcesActions'; -import { useForm } from '@formily/react'; const collection = { name: 'collections', diff --git a/packages/plugins/@nocobase/plugin-acl/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-acl/src/locale/zh-CN.json index 17d953a878..0a13115b3d 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-acl/src/locale/zh-CN.json @@ -2,5 +2,10 @@ "The current user has no roles. Please try another account.": "当前用户没有角色,请使用其他账号。", "The user role does not exist. Please try signing in again": "用户角色不存在,请尝试重新登录。", "New role": "新建角色", - "Permissions": "权限" + "Permissions": "权限", + "Roles & Permissions": "角色和权限", + "General": "通用", + "Menu": "菜单", + "Plugin settings": "插件设置", + "Data sources": "数据源" } diff --git a/packages/plugins/@nocobase/plugin-acl/src/server/index.ts b/packages/plugins/@nocobase/plugin-acl/src/server/index.ts index 933c0462e9..b35e3bfb9d 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/server/index.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/server/index.ts @@ -1,5 +1,6 @@ -export { default } from './server'; +export * from './middlewares/setCurrentRole'; +export * from './middlewares/with-acl-meta'; export { RoleResourceActionModel } from './model/RoleResourceActionModel'; export { RoleResourceModel } from './model/RoleResourceModel'; -export * from './middlewares/with-acl-meta'; -export * from './middlewares/setCurrentRole'; + +export { default } from './server'; diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/index.tsx b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/index.tsx index fe337eafc3..b64ac562db 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/index.tsx @@ -1,20 +1,20 @@ import { Plugin, useCollection_deprecated } from '@nocobase/client'; import { bulkEditActionSettings, deprecatedBulkEditActionSettings } from './BulkEditAction.Settings'; -import { BulkEditFormItemInitializers_deprecated, bulkEditFormItemInitializers } from './BulkEditFormItemInitializers'; +import { BulkEditActionInitializer } from './BulkEditActionInitializer'; import { - CreateFormBulkEditBlockInitializers, BulkEditBlockInitializers_deprecated, + CreateFormBulkEditBlockInitializers, bulkEditBlockInitializers, } from './BulkEditBlockInitializers'; import { BulkEditFormActionInitializers_deprecated, bulkEditFormActionInitializers, } from './BulkEditFormActionInitializers'; -import { BulkEditActionInitializer } from './BulkEditActionInitializer'; +import { BulkEditFormItemInitializers_deprecated, bulkEditFormItemInitializers } from './BulkEditFormItemInitializers'; import { bulkEditFormItemSettings } from './bulkEditFormItemSettings'; import { BulkEditField } from './component/BulkEditField'; import { useCustomizeBulkEditActionProps } from './utils'; -export class BulkEditPlugin extends Plugin { +export class PluginActionBulkEditClient extends Plugin { async load() { this.app.addComponents({ BulkEditField }); this.app.addScopes({ useCustomizeBulkEditActionProps }); @@ -61,4 +61,4 @@ export class BulkEditPlugin extends Plugin { } } -export default BulkEditPlugin; +export default PluginActionBulkEditClient; diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/locale/index.ts b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/locale/index.ts index 30b82f7d8d..da9aa4d926 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/locale/index.ts +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/locale/index.ts @@ -1,10 +1,7 @@ import { i18n } from '@nocobase/client'; import { useTranslation } from 'react-i18next'; -export const NAMESPACE = 'bulk-edit'; - -// i18n.addResources('zh-CN', NAMESPACE, zhCN); -// i18n.addResources('en-US', NAMESPACE, enUS); +export const NAMESPACE = '@nocobase/plugin-bulk-edit'; export function lang(key: string) { return i18n.t(key, { ns: NAMESPACE }); diff --git a/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/index.tsx b/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/index.tsx index 360b126492..e8ee9a03ed 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/index.tsx @@ -1,9 +1,9 @@ import { Plugin, useCollection_deprecated } from '@nocobase/client'; import { bulkUpdateActionSettings, deprecatedBulkUpdateActionSettings } from './BulkUpdateAction.Settings'; +import { BulkUpdateActionInitializer } from './BulkUpdateActionInitializer'; import { CustomizeActionInitializer } from './CustomizeActionInitializer'; import { useCustomizeBulkUpdateActionProps } from './utils'; -import { BulkUpdateActionInitializer } from './BulkUpdateActionInitializer'; -export class PluginBulkUpdateClient extends Plugin { +export class PluginActionBulkUpdateClient extends Plugin { async load() { this.app.addComponents({ CustomizeActionInitializer }); this.app.addScopes({ useCustomizeBulkUpdateActionProps }); @@ -31,4 +31,4 @@ export class PluginBulkUpdateClient extends Plugin { } } -export default PluginBulkUpdateClient; +export default PluginActionBulkUpdateClient; diff --git a/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/locale/index.ts b/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/locale/index.ts index d65c0dd93d..2028aa4a47 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/locale/index.ts +++ b/packages/plugins/@nocobase/plugin-action-bulk-update/src/client/locale/index.ts @@ -3,9 +3,6 @@ import { useTranslation } from 'react-i18next'; export const NAMESPACE = 'bulk-update'; -// i18n.addResources('zh-CN', NAMESPACE, zhCN); -// i18n.addResources('en-US', NAMESPACE, enUS); - export function lang(key: string) { return i18n.t(key, { ns: NAMESPACE }); } diff --git a/packages/plugins/@nocobase/plugin-action-duplicate/src/client/index.ts b/packages/plugins/@nocobase/plugin-action-duplicate/src/client/index.ts index 072d681d8a..264e405ada 100644 --- a/packages/plugins/@nocobase/plugin-action-duplicate/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-action-duplicate/src/client/index.ts @@ -4,7 +4,7 @@ import { deprecatedDuplicateActionSettings, duplicateActionSettings } from './Du import { DuplicateActionInitializer } from './DuplicateActionInitializer'; import { DuplicatePluginProvider } from './DuplicatePluginProvider'; -export class PluginDuplicateClient extends Plugin { +export class PluginActionDuplicateClient extends Plugin { async load() { this.app.use(DuplicatePluginProvider); this.app.addComponents({ @@ -64,5 +64,5 @@ export class PluginDuplicateClient extends Plugin { } } -export default PluginDuplicateClient; +export default PluginActionDuplicateClient; export * from './DuplicateAction'; diff --git a/packages/plugins/@nocobase/plugin-action-print/src/client/index.tsx b/packages/plugins/@nocobase/plugin-action-print/src/client/index.tsx index 3730092f62..645845abdf 100644 --- a/packages/plugins/@nocobase/plugin-action-print/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-action-print/src/client/index.tsx @@ -1,7 +1,7 @@ import { Plugin } from '@nocobase/client'; import { deprecatedPrintActionSettings, printActionSettings } from './PrintAction.Settings'; import { PrintActionPluginProvider } from './PrintActionPluginProvider'; -export class PrintPlugin extends Plugin { +export class PluginActionPrintClient extends Plugin { async load() { this.app.use(PrintActionPluginProvider); this.app.schemaSettingsManager.add(deprecatedPrintActionSettings); @@ -23,4 +23,4 @@ export class PrintPlugin extends Plugin { } } -export default PrintPlugin; +export default PluginActionPrintClient; diff --git a/packages/plugins/@nocobase/plugin-api-doc/src/client/index.tsx b/packages/plugins/@nocobase/plugin-api-doc/src/client/index.tsx index 92659aa6f0..bc8779b507 100644 --- a/packages/plugins/@nocobase/plugin-api-doc/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-api-doc/src/client/index.tsx @@ -37,7 +37,7 @@ const SCDocumentation = () => { ); }; -export class APIDocumentationPlugin extends Plugin { +export class PluginAPIDocClient extends Plugin { async load() { this.app.pluginSettingsManager.add(NAMESPACE, { title: `{{t("API documentation", { ns: "${NAMESPACE}" })}}`, @@ -53,4 +53,4 @@ export class APIDocumentationPlugin extends Plugin { } } -export default APIDocumentationPlugin; +export default PluginAPIDocClient; diff --git a/packages/plugins/@nocobase/plugin-api-doc/src/server/server.ts b/packages/plugins/@nocobase/plugin-api-doc/src/server/server.ts index 8ffad423cf..a052885f5b 100644 --- a/packages/plugins/@nocobase/plugin-api-doc/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-api-doc/src/server/server.ts @@ -2,7 +2,7 @@ import { Context } from '@nocobase/actions'; import { Plugin } from '@nocobase/server'; import { SwaggerManager } from './swagger'; -export default class APIDoc extends Plugin { +export class PluginAPIDocServer extends Plugin { swagger: SwaggerManager; constructor(app, options) { super(app, options); @@ -10,7 +10,7 @@ export default class APIDoc extends Plugin { } async beforeLoad() {} async load() { - this.app.resource({ + this.app.resourcer.define({ name: 'swagger', type: 'single', actions: { @@ -46,3 +46,5 @@ export default class APIDoc extends Plugin { }); } } + +export default PluginAPIDocServer; diff --git a/packages/plugins/@nocobase/plugin-api-keys/src/client/index.tsx b/packages/plugins/@nocobase/plugin-api-keys/src/client/index.tsx index 910dc0db0e..c16d4168e1 100644 --- a/packages/plugins/@nocobase/plugin-api-keys/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-api-keys/src/client/index.tsx @@ -2,15 +2,15 @@ import { Plugin } from '@nocobase/client'; import { NAMESPACE } from '../constants'; import { Configuration } from './Configuration'; -class APIKeysPlugin extends Plugin { +export class PluginAPIKeysClient extends Plugin { async load() { - this.app.pluginSettingsManager.add(NAMESPACE, { + this.pluginSettingsManager.add(NAMESPACE, { icon: 'KeyOutlined', - title: '{{t("API keys", {"ns": "api-keys"})}}', + title: this.t('API keys'), Component: Configuration, aclSnippet: 'pm.api-keys.configuration', }); } } -export default APIKeysPlugin; +export default PluginAPIKeysClient; diff --git a/packages/plugins/@nocobase/plugin-api-keys/src/constants.ts b/packages/plugins/@nocobase/plugin-api-keys/src/constants.ts index ab5fd31e1d..c99c64ea4f 100644 --- a/packages/plugins/@nocobase/plugin-api-keys/src/constants.ts +++ b/packages/plugins/@nocobase/plugin-api-keys/src/constants.ts @@ -1 +1 @@ -export const NAMESPACE = 'api-keys'; +export const NAMESPACE = '@nocobase/plugin-api-keys'; diff --git a/packages/plugins/@nocobase/plugin-api-keys/src/server/plugin.ts b/packages/plugins/@nocobase/plugin-api-keys/src/server/plugin.ts index 77f67586b9..6314e85796 100644 --- a/packages/plugins/@nocobase/plugin-api-keys/src/server/plugin.ts +++ b/packages/plugins/@nocobase/plugin-api-keys/src/server/plugin.ts @@ -1,24 +1,11 @@ import { Plugin } from '@nocobase/server'; -import { resolve } from 'path'; -import { NAMESPACE } from '../constants'; import { create, destroy } from './actions/api-keys'; -import { enUS, zhCN } from './locale'; -export interface ApiKeysPluginConfig { - name?: string; -} - -export default class ApiKeysPlugin extends Plugin { +export class PluginAPIKeysServer extends Plugin { resourceName = 'apiKeys'; - constructor(app, options) { - super(app, options); - } async beforeLoad() { - this.app.i18n.addResources('zh-CN', NAMESPACE, zhCN); - this.app.i18n.addResources('en-US', NAMESPACE, enUS); - - await this.app.resourcer.define({ + this.app.resourcer.define({ name: this.resourceName, actions: { create, @@ -34,11 +21,9 @@ export default class ApiKeysPlugin extends Plugin { } async load() { - await this.importCollections(resolve(__dirname, '../collections')); - this.app.resourcer.use(async (ctx, next) => { - const { resourceName, actionName } = ctx.action.params; - if (resourceName == this.resourceName && ['list', 'destroy'].includes(actionName)) { + const { resourceName, actionName } = ctx.action; + if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) { ctx.action.mergeParams({ filter: { createdById: ctx.auth.user.id, @@ -49,3 +34,5 @@ export default class ApiKeysPlugin extends Plugin { }); } } + +export default PluginAPIKeysServer; diff --git a/packages/plugins/@nocobase/plugin-auth/src/client/index.tsx b/packages/plugins/@nocobase/plugin-auth/src/client/index.tsx index 50f5e12039..bf5ec09713 100644 --- a/packages/plugins/@nocobase/plugin-auth/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-auth/src/client/index.tsx @@ -1,13 +1,13 @@ import { Plugin } from '@nocobase/client'; -import { AuthProvider } from './AuthProvider'; -import { NAMESPACE } from './locale'; -import { Authenticator } from './settings/Authenticator'; -import { AuthLayout, SignInPage, SignUpPage } from './pages'; -import { ComponentType } from 'react'; import { Registry } from '@nocobase/utils/client'; +import { ComponentType } from 'react'; import { presetAuthType } from '../preset'; -import { SignInForm, SignUpForm, Options } from './basic'; +import { AuthProvider } from './AuthProvider'; import { Authenticator as AuthenticatorType } from './authenticator'; +import { Options, SignInForm, SignUpForm } from './basic'; +import { NAMESPACE } from './locale'; +import { AuthLayout, SignInPage, SignUpPage } from './pages'; +import { Authenticator } from './settings/Authenticator'; export type AuthOptions = { components: Partial<{ @@ -18,7 +18,7 @@ export type AuthOptions = { }>; }; -export class AuthPlugin extends Plugin { +export class PluginAuthClient extends Plugin { authTypes = new Registry(); registerType(authType: string, options: AuthOptions) { @@ -63,7 +63,8 @@ export class AuthPlugin extends Plugin { } } -export default AuthPlugin; -export { useSignIn } from './basic'; -export { useAuthenticator, AuthenticatorsContext } from './authenticator'; +export { AuthenticatorsContext, useAuthenticator } from './authenticator'; export type { Authenticator } from './authenticator'; +export { useSignIn } from './basic'; + +export default PluginAuthClient; diff --git a/packages/plugins/@nocobase/plugin-auth/src/server/plugin.ts b/packages/plugins/@nocobase/plugin-auth/src/server/plugin.ts index 9856744ff5..5c42e737e0 100644 --- a/packages/plugins/@nocobase/plugin-auth/src/server/plugin.ts +++ b/packages/plugins/@nocobase/plugin-auth/src/server/plugin.ts @@ -1,17 +1,17 @@ +import { Cache } from '@nocobase/cache'; import { Model } from '@nocobase/database'; import { InstallOptions, Plugin } from '@nocobase/server'; import { resolve } from 'path'; -import { namespace, presetAuthenticator, presetAuthType } from '../preset'; +import { namespace, presetAuthType, presetAuthenticator } from '../preset'; import authActions from './actions/auth'; import authenticatorsActions from './actions/authenticators'; import { BasicAuth } from './basic-auth'; import { enUS, zhCN } from './locale'; import { AuthModel } from './model/authenticator'; -import { TokenBlacklistService } from './token-blacklist'; -import { Cache } from '@nocobase/cache'; import { Storer } from './storer'; +import { TokenBlacklistService } from './token-blacklist'; -export class AuthPlugin extends Plugin { +export class PluginAuthServer extends Plugin { cache: Cache; afterAdd() {} @@ -105,4 +105,4 @@ export class AuthPlugin extends Plugin { async remove() {} } -export default AuthPlugin; +export default PluginAuthServer; diff --git a/packages/plugins/@nocobase/plugin-backup-restore/src/client/index.tsx b/packages/plugins/@nocobase/plugin-backup-restore/src/client/index.tsx index 87b73f9147..8ea08dbb24 100644 --- a/packages/plugins/@nocobase/plugin-backup-restore/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-backup-restore/src/client/index.tsx @@ -2,11 +2,12 @@ import { Plugin } from '@nocobase/client'; import { BackupAndRestoreList } from './Configuration'; import { DuplicatorProvider } from './DuplicatorProvider'; import { NAMESPACE } from './locale'; -export class DuplicatorPlugin extends Plugin { + +export class PluginBackupRestoreClient extends Plugin { async load() { this.app.use(DuplicatorProvider); this.app.pluginSettingsManager.add(NAMESPACE, { - title: `{{t("Backup & Restore", { ns: "${NAMESPACE}" })}}`, + title: this.t('Backup & Restore'), icon: 'CloudServerOutlined', Component: BackupAndRestoreList, aclSnippet: 'pm.backup.restore', @@ -14,4 +15,4 @@ export class DuplicatorPlugin extends Plugin { } } -export default DuplicatorPlugin; +export default PluginBackupRestoreClient; diff --git a/packages/plugins/@nocobase/plugin-backup-restore/src/server/server.ts b/packages/plugins/@nocobase/plugin-backup-restore/src/server/server.ts index d04fbdf6ee..4b75c4908b 100644 --- a/packages/plugins/@nocobase/plugin-backup-restore/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-backup-restore/src/server/server.ts @@ -1,7 +1,7 @@ import { Plugin } from '@nocobase/server'; import backupFilesResourcer from './resourcers/backup-files'; -export default class Duplicator extends Plugin { +export default class PluginBackupRestoreServer extends Plugin { beforeLoad() { this.app.acl.registerSnippet({ name: `pm.${this.name}`,