chore: add tsdoc (#3788)

* chore: tsdoc

* chore: tsdoc

* fix: error

* chore: code format

* chore: code format
This commit is contained in:
chenos 2024-03-26 17:08:45 +08:00 committed by GitHub
parent b6ae528d80
commit c4aa8b78c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 540 additions and 173 deletions

View File

@ -45,14 +45,40 @@ interface CanArgs {
} }
export class ACL extends EventEmitter { export class ACL extends EventEmitter {
/**
* @internal
*/
public availableStrategy = new Map<string, ACLAvailableStrategy>(); public availableStrategy = new Map<string, ACLAvailableStrategy>();
/**
* @internal
*/
public allowManager = new AllowManager(this); public allowManager = new AllowManager(this);
/**
* @internal
*/
public snippetManager = new SnippetManager(); public snippetManager = new SnippetManager();
/**
* @internal
*/
roles = new Map<string, ACLRole>(); roles = new Map<string, ACLRole>();
/**
* @internal
*/
actionAlias = new Map<string, string>(); actionAlias = new Map<string, string>();
/**
* @internal
*/
configResources: string[] = []; configResources: string[] = [];
protected availableActions = new Map<string, ACLAvailableAction>(); protected availableActions = new Map<string, ACLAvailableAction>();
protected fixedParamsManager = new FixedParamsManager(); protected fixedParamsManager = new FixedParamsManager();
protected middlewares: Toposort<any>; protected middlewares: Toposort<any>;
constructor() { constructor() {
@ -114,14 +140,23 @@ export class ACL extends EventEmitter {
return this.roles.delete(name); return this.roles.delete(name);
} }
/**
* @internal
*/
registerConfigResources(names: string[]) { registerConfigResources(names: string[]) {
names.forEach((name) => this.registerConfigResource(name)); names.forEach((name) => this.registerConfigResource(name));
} }
/**
* @internal
*/
registerConfigResource(name: string) { registerConfigResource(name: string) {
this.configResources.push(name); this.configResources.push(name);
} }
/**
* @internal
*/
isConfigResource(name: string) { isConfigResource(name: string) {
return this.configResources.includes(name); return this.configResources.includes(name);
} }
@ -227,6 +262,9 @@ export class ACL extends EventEmitter {
return null; return null;
} }
/**
* @internal
*/
public resolveActionAlias(action: string) { public resolveActionAlias(action: string) {
return this.actionAlias.get(action) ? this.actionAlias.get(action) : action; 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); return this.skip(resourceName, actionNames, condition);
} }
/**
* @deprecated
*/
skip(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc) { skip(resourceName: string, actionNames: string[] | string, condition?: string | ConditionFunc) {
if (!Array.isArray(actionNames)) { if (!Array.isArray(actionNames)) {
actionNames = [actionNames]; actionNames = [actionNames];
@ -252,6 +293,9 @@ export class ACL extends EventEmitter {
} }
} }
/**
* @internal
*/
async parseJsonTemplate(json: any, ctx: any) { async parseJsonTemplate(json: any, ctx: any) {
if (json.filter) { if (json.filter) {
ctx.logger?.info?.('parseJsonTemplate.raw', JSON.parse(JSON.stringify(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) { async getActionParams(ctx) {
const roleName = ctx.state.currentRole || 'anonymous'; const roleName = ctx.state.currentRole || 'anonymous';
const { resourceName, actionName } = ctx.action; const { resourceName, actionName } = ctx.action;
@ -322,6 +369,9 @@ export class ACL extends EventEmitter {
this.snippetManager.register(snippet); this.snippetManager.register(snippet);
} }
/**
* @internal
*/
filterParams(ctx, resourceName, params) { filterParams(ctx, resourceName, params) {
if (params?.filter?.createdById) { if (params?.filter?.createdById) {
const collection = ctx.db.getCollection(resourceName); const collection = ctx.db.getCollection(resourceName);

View File

@ -11,7 +11,7 @@ export const ADMIN_SETTINGS_PATH = '/admin/settings/';
export const SNIPPET_PREFIX = 'pm.'; export const SNIPPET_PREFIX = 'pm.';
export interface PluginSettingOptions { export interface PluginSettingOptions {
title: string | React.ReactElement; title: any;
/** /**
* @default Outlet * @default Outlet
*/ */

View File

@ -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 compose from 'koa-compose';
import _ from 'lodash'; import _ from 'lodash';
import Middleware, { MiddlewareType } from './middleware'; import Middleware, { MiddlewareType } from './middleware';
import Resource from './resource'; import Resource from './resource';
import { HandlerType } from './resourcer'; import { HandlerType } from './resourcer';
import { RecordableHistogram, performance } from 'perf_hooks';
export type ActionType = string | HandlerType | ActionOptions; export type ActionType = string | HandlerType | ActionOptions;
@ -161,27 +160,38 @@ export interface ActionParams {
*/ */
values?: any; values?: any;
/** /**
* Model * This method is deprecated and should not be used.
* Use {@link action.resourceName.split(',')[0]} instead.
* @deprecated
*/ */
resourceName?: string; resourceName?: string;
/** /**
* * This method is deprecated and should not be used.
* Use {@link filterByTk} instead.
* @deprecated
*/ */
resourceIndex?: string; resourceIndex?: string;
/** /**
* * This method is deprecated and should not be used.
* Use {@link action.resourceName.split(',')[1]} instead.
* @deprecated
*/ */
associatedName?: string; associatedName?: string;
/** /**
* * This method is deprecated and should not be used.
* Use {@link action.sourceId} instead.
* @deprecated
*/ */
associatedIndex?: string; associatedIndex?: string;
/** /**
* * This method is deprecated and should not be used.
* @deprecated
*/ */
associated?: any; associated?: any;
/** /**
* * This method is deprecated and should not be used.
* Use {@link action.actionName} instead.
* @deprecated
*/ */
actionName?: string; actionName?: string;
/** /**
@ -204,11 +214,23 @@ export class Action {
public params: ActionParams = {}; public params: ActionParams = {};
public actionName: string; public actionName: string;
public resourceName: string; public resourceName: string;
/**
* This method is deprecated and should not be used.
* Use {@link this.sourceId} instead.
* @deprecated
*/
public resourceOf: any; public resourceOf: any;
public sourceId: any;
public readonly middlewares: Array<Middleware> = []; public readonly middlewares: Array<Middleware> = [];
/**
* @internal
*/
constructor(options: ActionOptions) { constructor(options: ActionOptions) {
options = requireModule(options); options = requireModule(options);
if (typeof options === 'function') { if (typeof options === 'function') {
@ -221,15 +243,22 @@ export class Action {
this.mergeParams(params); this.mergeParams(params);
} }
/**
* @internal
*/
toJSON() { toJSON() {
return { return {
actionName: this.actionName, actionName: this.actionName,
resourceName: this.resourceName, resourceName: this.resourceName,
resourceOf: this.resourceOf, resourceOf: this.sourceId,
sourceId: this.sourceId,
params: this.params, params: this.params,
}; };
} }
/**
* @internal
*/
clone() { clone() {
const options = _.cloneDeep(this.options); const options = _.cloneDeep(this.options);
delete options.middleware; delete options.middleware;
@ -241,6 +270,9 @@ export class Action {
return action; return action;
} }
/**
* @internal
*/
setContext(context: any) { setContext(context: any) {
this.context = context; this.context = context;
} }
@ -266,34 +298,55 @@ export class Action {
}); });
} }
/**
* @internal
*/
setResource(resource: Resource) { setResource(resource: Resource) {
this.resource = resource; this.resource = resource;
return this; return this;
} }
/**
* @internal
*/
getResource() { getResource() {
return this.resource; return this.resource;
} }
/**
* @internal
*/
getOptions(): ActionOptions { getOptions(): ActionOptions {
return this.options; return this.options;
} }
/**
* @internal
*/
setName(name: ActionName) { setName(name: ActionName) {
this.name = name; this.name = name;
return this; return this;
} }
/**
* @internal
*/
getName() { getName() {
return this.name; return this.name;
} }
/**
* @internal
*/
getMiddlewareHandlers() { getMiddlewareHandlers() {
return this.middlewares return this.middlewares
.filter((middleware) => middleware.canAccess(this.name)) .filter((middleware) => middleware.canAccess(this.name))
.map((middleware) => middleware.getHandler()); .map((middleware) => middleware.getHandler());
} }
/**
* @internal
*/
getHandler() { getHandler() {
const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name)); const handler = requireModule(this.handler || this.resource.resourcer.getRegisteredHandler(this.name));
if (typeof handler !== 'function') { if (typeof handler !== 'function') {
@ -303,6 +356,9 @@ export class Action {
return handler; return handler;
} }
/**
* @internal
*/
getHandlers() { getHandlers() {
const handlers = [ const handlers = [
...this.resource.resourcer.getMiddlewares(), ...this.resource.resourcer.getMiddlewares(),
@ -315,10 +371,16 @@ export class Action {
return handlers; return handlers;
} }
/**
* @internal
*/
async execute(context: any, next?: any) { async execute(context: any, next?: any) {
return await compose(this.getHandlers())(context, next); return await compose(this.getHandlers())(context, next);
} }
/**
* @internal
*/
static toInstanceMap(actions: object, resource?: Resource) { static toInstanceMap(actions: object, resource?: Resource) {
return new Map( return new Map(
Object.entries(actions).map(([key, options]) => { Object.entries(actions).map(([key, options]) => {

View File

@ -150,6 +150,9 @@ export interface ImportOptions {
} }
export class Resourcer { export class Resourcer {
/**
* @internal
*/
public readonly options: ResourcerOptions; public readonly options: ResourcerOptions;
protected resources = new Map<string, Resource>(); protected resources = new Map<string, Resource>();
/** /**
@ -173,6 +176,7 @@ export class Resourcer {
* @param {object} [options] * @param {object} [options]
* @param {string} [options.directory] * @param {string} [options.directory]
* @param {array} [options.extensions = ['js', 'ts', 'json']] * @param {array} [options.extensions = ['js', 'ts', 'json']]
*
*/ */
public async import(options: ImportOptions): Promise<Map<string, Resource>> { public async import(options: ImportOptions): Promise<Map<string, Resource>> {
const { extensions = ['js', 'ts', 'json'], directory } = options; const { extensions = ['js', 'ts', 'json'], directory } = options;
@ -206,14 +210,27 @@ export class Resourcer {
return this.resources.has(name); return this.resources.has(name);
} }
/**
* @internal
*/
removeResource(name) { removeResource(name) {
return this.resources.delete(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) { registerAction(name: ActionName, handler: HandlerType) {
this.registerActionHandler(name, handler); this.registerActionHandler(name, handler);
} }
/**
* This method is deprecated and should not be used.
* Use {@link this.registerActionHandlers()} instead.
* @deprecated
*/
registerActions(handlers: Handlers) { registerActions(handlers: Handlers) {
this.registerActionHandlers(handlers); this.registerActionHandlers(handlers);
} }
@ -233,14 +250,23 @@ export class Resourcer {
this.actionHandlers.set(name, handler); this.actionHandlers.set(name, handler);
} }
/**
* @internal
*/
getRegisteredHandler(name: ActionName) { getRegisteredHandler(name: ActionName) {
return this.actionHandlers.get(name); return this.actionHandlers.get(name);
} }
/**
* @internal
*/
getRegisteredHandlers() { getRegisteredHandlers() {
return this.actionHandlers; return this.actionHandlers;
} }
/**
* @internal
*/
getResource(name: string): Resource { getResource(name: string): Resource {
if (!this.resources.has(name)) { if (!this.resources.has(name)) {
throw new Error(`${name} resource does not exist`); throw new Error(`${name} resource does not exist`);
@ -248,6 +274,9 @@ export class Resourcer {
return this.resources.get(name); return this.resources.get(name);
} }
/**
* @internal
*/
getAction(name: string, action: ActionName): Action { getAction(name: string, action: ActionName): Action {
// 支持注册局部 action // 支持注册局部 action
if (this.actionHandlers.has(`${name}:${action}`)) { if (this.actionHandlers.has(`${name}:${action}`)) {
@ -256,6 +285,9 @@ export class Resourcer {
return this.getResource(name).getAction(action); return this.getResource(name).getAction(action);
} }
/**
* @internal
*/
getMiddlewares() { getMiddlewares() {
return this.middlewares.nodes; return this.middlewares.nodes;
} }
@ -264,6 +296,11 @@ export class Resourcer {
this.middlewares.add(middlewares, options); 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 = {}) { restApiMiddleware({ prefix, accessors, skipIfDataSourceExists = false }: KoaMiddlewareOptions = {}) {
return async (ctx: ResourcerContext, next: () => Promise<any>) => { return async (ctx: ResourcerContext, next: () => Promise<any>) => {
if (skipIfDataSourceExists) { if (skipIfDataSourceExists) {
@ -317,6 +354,7 @@ export class Resourcer {
ctx.action.setContext(ctx); ctx.action.setContext(ctx);
ctx.action.actionName = params.actionName; ctx.action.actionName = params.actionName;
ctx.action.sourceId = params.associatedIndex;
ctx.action.resourceOf = params.associatedIndex; ctx.action.resourceOf = params.associatedIndex;
ctx.action.resourceName = params.associatedName ctx.action.resourceName = params.associatedName
? `${params.associatedName}.${params.resourceName}` ? `${params.associatedName}.${params.resourceName}`
@ -349,11 +387,7 @@ export class Resourcer {
} }
/** /**
* API * @internal
*
* @param options
* @param context
* @param next
*/ */
async execute(options: ExecuteOptions, context: ResourcerContext = {}, next?: any) { async execute(options: ExecuteOptions, context: ResourcerContext = {}, next?: any) {
const { resource, action } = options; const { resource, action } = options;

View File

@ -139,19 +139,41 @@ export type MaintainingCommandStatus = {
}; };
export class Application<StateT = DefaultState, ContextT = DefaultContext> extends Koa implements AsyncEmitter { export class Application<StateT = DefaultState, ContextT = DefaultContext> extends Koa implements AsyncEmitter {
/**
* @internal
*/
declare middleware: any; declare middleware: any;
/**
* @internal
*/
stopped = false; stopped = false;
/**
* @internal
*/
ready = false; ready = false;
declare emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>; declare emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
/**
* @internal
*/
public rawOptions: ApplicationOptions; public rawOptions: ApplicationOptions;
/**
* @internal
*/
public activatedCommand: { public activatedCommand: {
name: string; name: string;
} = null; } = null;
/**
* @internal
*/
public running = false; public running = false;
/**
* @internal
*/
public perfHistograms = new Map<string, RecordableHistogram>(); public perfHistograms = new Map<string, RecordableHistogram>();
protected plugins = new Map<string, Plugin>(); protected plugins = new Map<string, Plugin>();
protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance(); protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance();
protected _started: boolean; protected _started: boolean;
protected _logger: SystemLogger;
private _authenticated = false; private _authenticated = false;
private _maintaining = false; private _maintaining = false;
private _maintainingCommandStatus: MaintainingCommandStatus; private _maintainingCommandStatus: MaintainingCommandStatus;
@ -169,12 +191,18 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
protected _loaded: boolean; protected _loaded: boolean;
/**
* @internal
*/
get loaded() { get loaded() {
return this._loaded; return this._loaded;
} }
private _maintainingMessage: string; private _maintainingMessage: string;
/**
* @internal
*/
get maintainingMessage() { get maintainingMessage() {
return this._maintainingMessage; return this._maintainingMessage;
} }
@ -198,8 +226,6 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this.mainDataSource.collectionManager.db; return this.mainDataSource.collectionManager.db;
} }
protected _logger: SystemLogger;
get logger() { get logger() {
return this._logger; return this._logger;
} }
@ -220,6 +246,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this._cache; return this._cache;
} }
/**
* @internal
*/
set cache(cache: Cache) { set cache(cache: Cache) {
this._cache = cache; this._cache = cache;
} }
@ -254,6 +283,11 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
protected _locales: Locale; protected _locales: Locale;
/**
* This method is deprecated and should not be used.
* Use {@link #localeManager} instead.
* @deprecated
*/
get locales() { get locales() {
return this._locales; return this._locales;
} }
@ -288,10 +322,16 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this._dataSourceManager; return this._dataSourceManager;
} }
/**
* @internal
*/
getMaintaining() { getMaintaining() {
return this._maintainingCommandStatus; return this._maintainingCommandStatus;
} }
/**
* @internal
*/
setMaintaining(_maintainingCommandStatus: MaintainingCommandStatus) { setMaintaining(_maintainingCommandStatus: MaintainingCommandStatus) {
this._maintainingCommandStatus = _maintainingCommandStatus; this._maintainingCommandStatus = _maintainingCommandStatus;
@ -305,6 +345,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
this._maintaining = true; this._maintaining = true;
} }
/**
* @internal
*/
setMaintainingMessage(message: string) { setMaintainingMessage(message: string) {
this._maintainingMessage = message; this._maintainingMessage = message;
@ -314,11 +357,18 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}); });
} }
/**
* This method is deprecated and should not be used.
* Use {@link #this.version.get()} instead.
* @deprecated
*/
getVersion() { getVersion() {
return packageJson.version; return packageJson.version;
} }
/** /**
* This method is deprecated and should not be used.
* Use {@link #this.pm.addPreset()} instead.
* @deprecated * @deprecated
*/ */
plugin<O = any>(pluginClass: any, options?: O) { plugin<O = any>(pluginClass: any, options?: O) {
@ -335,6 +385,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this; return this;
} }
/**
* @internal
*/
callback() { callback() {
const fn = compose(this.middleware.nodes); const fn = compose(this.middleware.nodes);
@ -348,14 +401,29 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}; };
} }
/**
* This method is deprecated and should not be used.
* Use {@link #this.db.collection()} instead.
* @deprecated
*/
collection(options: CollectionOptions) { collection(options: CollectionOptions) {
return this.db.collection(options); return this.db.collection(options);
} }
/**
* This method is deprecated and should not be used.
* Use {@link #this.resourcer.define()} instead.
* @deprecated
*/
resource(options: ResourceOptions) { resource(options: ResourceOptions) {
return this.resourcer.define(options); 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) { actions(handlers: any, options?: ActionsOptions) {
return this.resourcer.registerActions(handlers); return this.resourcer.registerActions(handlers);
} }
@ -368,11 +436,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return (this.cli as any)._findCommand(name); return (this.cli as any)._findCommand(name);
} }
async preload() { /**
// load core collections * @internal
// load plugin commands */
}
async reInit() { async reInit() {
if (!this._loaded) { if (!this._loaded) {
return; return;
@ -476,12 +542,19 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
} }
/** /**
* This method is deprecated and should not be used.
* Use {@link this.pm.get()} instead.
* @deprecated * @deprecated
*/ */
getPlugin<P extends Plugin>(name: string | typeof Plugin) { getPlugin<P extends Plugin>(name: string | typeof Plugin) {
return this.pm.get(name) as P; 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) { async parse(argv = process.argv) {
return this.runAsCLI(argv); return this.runAsCLI(argv);
} }
@ -504,7 +577,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return await this.runAsCLI([command, ...args], { from: 'user', throwError: true }); return await this.runAsCLI([command, ...args], { from: 'user', throwError: true });
} }
createCli() { protected createCLI() {
const command = new AppCommand('nocobase') const command = new AppCommand('nocobase')
.usage('[command] [options]') .usage('[command] [options]')
.hook('preAction', async (_, actionCommand) => { .hook('preAction', async (_, actionCommand) => {
@ -544,6 +617,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return command; return command;
} }
/**
* @internal
*/
async loadMigrations(options) { async loadMigrations(options) {
const { directory, context, namespace } = options; const { directory, context, namespace } = options;
const migrations = { const migrations = {
@ -570,6 +646,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return migrations; return migrations;
} }
/**
* @internal
*/
async loadCoreMigrations() { async loadCoreMigrations() {
const migrations = await this.loadMigrations({ const migrations = await this.loadMigrations({
directory: resolve(__dirname, 'migrations'), directory: resolve(__dirname, 'migrations'),
@ -600,11 +679,17 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}; };
} }
/**
* @internal
*/
async loadPluginCommands() { async loadPluginCommands() {
this.log.debug('load plugin commands'); this.log.debug('load plugin commands');
await this.pm.loadCommands(); await this.pm.loadCommands();
} }
/**
* @internal
*/
async runAsCLI(argv = process.argv, options?: ParseOptions & { throwError?: boolean; reqId?: string }) { async runAsCLI(argv = process.argv, options?: ParseOptions & { throwError?: boolean; reqId?: string }) {
if (this.activatedCommand) { if (this.activatedCommand) {
return; return;
@ -689,6 +774,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
this.stopped = false; this.stopped = false;
} }
/**
* @internal
*/
async emitStartedEvent(options: StartOptions = {}) { async emitStartedEvent(options: StartOptions = {}) {
await this.emitAsync('__started', this, { await this.emitAsync('__started', this, {
maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus), maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus),
@ -700,6 +788,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this._started; return this._started;
} }
/**
* @internal
*/
async tryReloadOrRestart(options: StartOptions = {}) { async tryReloadOrRestart(options: StartOptions = {}) {
if (this._started) { if (this._started) {
await this.restart(options); await this.restart(options);
@ -898,6 +989,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}; };
} }
/**
* @internal
*/
reInitEvents() { reInitEvents() {
for (const eventName of this.eventNames()) { for (const eventName of this.eventNames()) {
for (const listener of this.listeners(eventName)) { for (const listener of this.listeners(eventName)) {
@ -943,7 +1037,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
this._cronJobManager = new CronJobManager(this); this._cronJobManager = new CronJobManager(this);
this._cli = this.createCli(); this._cli = this.createCLI();
this._i18n = createI18n(options); this._i18n = createI18n(options);
this.context.db = this.db; this.context.db = this.db;

View File

@ -3,12 +3,21 @@ import lodash from 'lodash';
import { PluginManager } from './plugin-manager'; import { PluginManager } from './plugin-manager';
export class PluginManagerRepository extends Repository { export class PluginManagerRepository extends Repository {
/**
* @internal
*/
pm: PluginManager; pm: PluginManager;
/**
* @internal
*/
setPluginManager(pm: PluginManager) { setPluginManager(pm: PluginManager) {
this.pm = pm; this.pm = pm;
} }
/**
* @deprecated
*/
async remove(name: string | string[]) { async remove(name: string | string[]) {
await this.destroy({ await this.destroy({
filter: { filter: {
@ -17,6 +26,9 @@ export class PluginManagerRepository extends Repository {
}); });
} }
/**
* @deprecated
*/
async enable(name: string | string[]) { async enable(name: string | string[]) {
const pluginNames = lodash.castArray(name); const pluginNames = lodash.castArray(name);
const plugins = pluginNames.map((name) => this.pm.get(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[]) { async disable(name: string | string[]) {
name = lodash.cloneDeep(name); name = lodash.cloneDeep(name);

View File

@ -45,12 +45,39 @@ export interface InstallOptions {
export class AddPresetError extends Error {} export class AddPresetError extends Error {}
export class PluginManager { export class PluginManager {
/**
* @internal
*/
app: Application; app: Application;
/**
* @internal
*/
collection: Collection; collection: Collection;
/**
* @internal
*/
pluginInstances = new Map<typeof Plugin, Plugin>(); pluginInstances = new Map<typeof Plugin, Plugin>();
/**
* @internal
*/
pluginAliases = new Map<string, Plugin>(); pluginAliases = new Map<string, Plugin>();
/**
* @internal
*/
server: net.Server; server: net.Server;
/**
* @internal
*/
_repository: PluginManagerRepository;
/**
* @internal
*/
constructor(public options: PluginManagerOptions) { constructor(public options: PluginManagerOptions) {
this.app = options.app; this.app = options.app;
this.app.db.registerRepositories({ this.app.db.registerRepositories({
@ -76,18 +103,22 @@ export class PluginManager {
this.app.resourcer.use(uploadMiddleware); this.app.resourcer.use(uploadMiddleware);
} }
_repository: PluginManagerRepository;
get repository() { get repository() {
return this.app.db.getRepository('applicationPlugins') as PluginManagerRepository; return this.app.db.getRepository('applicationPlugins') as PluginManagerRepository;
} }
/**
* @internal
*/
static async getPackageJson(packageName: string) { static async getPackageJson(packageName: string) {
const file = await fs.promises.realpath(resolve(process.env.NODE_MODULES_PATH, packageName, 'package.json')); 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' }); const data = await fs.promises.readFile(file, { encoding: 'utf-8' });
return JSON.parse(data); return JSON.parse(data);
} }
/**
* @internal
*/
static async getPackageName(name: string) { static async getPackageName(name: string) {
const prefixes = this.getPluginPkgPrefix(); const prefixes = this.getPluginPkgPrefix();
for (const prefix of prefixes) { for (const prefix of prefixes) {
@ -100,12 +131,18 @@ export class PluginManager {
throw new Error(`${name} plugin does not exist`); throw new Error(`${name} plugin does not exist`);
} }
/**
* @internal
*/
static getPluginPkgPrefix() { static getPluginPkgPrefix() {
return (process.env.PLUGIN_PACKAGE_PREFIX || '@nocobase/plugin-,@nocobase/preset-,@nocobase/plugin-pro-').split( return (process.env.PLUGIN_PACKAGE_PREFIX || '@nocobase/plugin-,@nocobase/preset-,@nocobase/plugin-pro-').split(
',', ',',
); );
} }
/**
* @internal
*/
static async findPackage(name: string) { static async findPackage(name: string) {
try { try {
const packageName = this.getPackageName(name); const packageName = this.getPackageName(name);
@ -130,6 +167,9 @@ export class PluginManager {
throw new Error(`No available packages found, ${name} plugin does not exist`); throw new Error(`No available packages found, ${name} plugin does not exist`);
} }
/**
* @internal
*/
static clearCache(packageName: string) { static clearCache(packageName: string) {
return; return;
const packageNamePath = packageName.replace('/', sep); const packageNamePath = packageName.replace('/', sep);
@ -140,6 +180,9 @@ export class PluginManager {
}); });
} }
/**
* @internal
*/
static async resolvePlugin(pluginName: string | typeof Plugin, isUpgrade = false, isPkg = false) { static async resolvePlugin(pluginName: string | typeof Plugin, isUpgrade = false, isPkg = false) {
if (typeof pluginName === 'string') { if (typeof pluginName === 'string') {
const packageName = isPkg ? pluginName : await this.getPackageName(pluginName); const packageName = isPkg ? pluginName : await this.getPackageName(pluginName);
@ -296,11 +339,17 @@ export class PluginManager {
await instance.afterAdd(); await instance.afterAdd();
} }
/**
* @internal
*/
async initPlugins() { async initPlugins() {
await this.initPresetPlugins(); await this.initPresetPlugins();
await this.initOtherPlugins(); await this.initOtherPlugins();
} }
/**
* @internal
*/
async loadCommands() { async loadCommands() {
this.app.log.debug('load commands'); this.app.log.debug('load commands');
const items = await this.repository.find({ const items = await this.repository.find({
@ -619,6 +668,9 @@ export class PluginManager {
await execa('yarn', ['nocobase', 'refresh']); await execa('yarn', ['nocobase', 'refresh']);
} }
/**
* @deprecated
*/
async loadOne(plugin: Plugin) { async loadOne(plugin: Plugin) {
this.app.setMaintainingMessage(`loading plugin ${plugin.name}...`); this.app.setMaintainingMessage(`loading plugin ${plugin.name}...`);
if (plugin.state.loaded || !plugin.enabled) { if (plugin.state.loaded || !plugin.enabled) {
@ -637,6 +689,9 @@ export class PluginManager {
this.app.setMaintainingMessage(`loaded plugin ${plugin.name}`); this.app.setMaintainingMessage(`loaded plugin ${plugin.name}`);
} }
/**
* @internal
*/
async addViaCLI(urlOrName: string, options?: PluginData) { async addViaCLI(urlOrName: string, options?: PluginData) {
if (isURL(urlOrName)) { if (isURL(urlOrName)) {
await this.addByCompressedFileUrl({ await this.addByCompressedFileUrl({
@ -679,6 +734,9 @@ export class PluginManager {
await execa('yarn', ['nocobase', 'postinstall']); await execa('yarn', ['nocobase', 'postinstall']);
} }
/**
* @internal
*/
async addByNpm(options: { packageName: string; name?: string; registry: string; authToken?: string }) { async addByNpm(options: { packageName: string; name?: string; registry: string; authToken?: string }) {
let { name = '', registry, packageName, authToken } = options; let { name = '', registry, packageName, authToken } = options;
name = name.trim(); name = name.trim();
@ -693,6 +751,9 @@ export class PluginManager {
return this.addByCompressedFileUrl({ name, compressedFileUrl, registry, authToken, type: 'npm' }); return this.addByCompressedFileUrl({ name, compressedFileUrl, registry, authToken, type: 'npm' });
} }
/**
* @internal
*/
async addByFile(options: { file: string; registry?: string; authToken?: string; type?: string; name?: string }) { async addByFile(options: { file: string; registry?: string; authToken?: string; type?: string; name?: string }) {
const { file, authToken } = options; const { file, authToken } = options;
@ -708,6 +769,9 @@ export class PluginManager {
return this.add(name, { packageName }, true); return this.add(name, { packageName }, true);
} }
/**
* @internal
*/
async addByCompressedFileUrl(options: { async addByCompressedFileUrl(options: {
compressedFileUrl: string; compressedFileUrl: string;
registry?: string; registry?: string;
@ -748,6 +812,9 @@ export class PluginManager {
await this.app.upgrade(); await this.app.upgrade();
} }
/**
* @internal
*/
async upgradeByNpm(values: PluginData) { async upgradeByNpm(values: PluginData) {
const name = values.name; const name = values.name;
const plugin = this.get(name); const plugin = this.get(name);
@ -769,6 +836,9 @@ export class PluginManager {
return this.upgradeByCompressedFileUrl({ compressedFileUrl, name, version, registry, authToken }); return this.upgradeByCompressedFileUrl({ compressedFileUrl, name, version, registry, authToken });
} }
/**
* @internal
*/
async upgradeByCompressedFileUrl(options: PluginData) { async upgradeByCompressedFileUrl(options: PluginData) {
const { name, compressedFileUrl, authToken } = options; const { name, compressedFileUrl, authToken } = options;
const data = await this.repository.findOne({ filter: { name } }); 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); await this.add(name, { version, packageName: data.packageName }, true, true);
} }
/**
* @internal
*/
getNameByPackageName(packageName: string) { getNameByPackageName(packageName: string) {
const prefixes = PluginManager.getPluginPkgPrefix(); const prefixes = PluginManager.getPluginPkgPrefix();
const prefix = prefixes.find((prefix) => packageName.startsWith(prefix)); const prefix = prefixes.find((prefix) => packageName.startsWith(prefix));
@ -808,12 +881,18 @@ export class PluginManager {
); );
} }
/**
* @internal
*/
async getNpmVersionList(name: string) { async getNpmVersionList(name: string) {
const plugin = this.get(name); const plugin = this.get(name);
const npmInfo = await getNpmInfo(plugin.options.packageName, plugin.options.registry, plugin.options.authToken); const npmInfo = await getNpmInfo(plugin.options.packageName, plugin.options.registry, plugin.options.authToken);
return Object.keys(npmInfo.versions); return Object.keys(npmInfo.versions);
} }
/**
* @internal
*/
async loadPresetMigrations() { async loadPresetMigrations() {
const migrations = { const migrations = {
beforeLoad: [], beforeLoad: [],
@ -854,6 +933,9 @@ export class PluginManager {
}; };
} }
/**
* @internal
*/
async loadOtherMigrations() { async loadOtherMigrations() {
const migrations = { const migrations = {
beforeLoad: [], beforeLoad: [],
@ -897,6 +979,9 @@ export class PluginManager {
}; };
} }
/**
* @internal
*/
async loadPresetPlugins() { async loadPresetPlugins() {
await this.initPresetPlugins(); await this.initPresetPlugins();
await this.load(); await this.load();
@ -931,6 +1016,9 @@ export class PluginManager {
}); });
} }
/**
* @internal
*/
async initOtherPlugins() { async initOtherPlugins() {
if (this['_initOtherPlugins']) { if (this['_initOtherPlugins']) {
return; return;
@ -939,6 +1027,9 @@ export class PluginManager {
this['_initOtherPlugins'] = true; this['_initOtherPlugins'] = true;
} }
/**
* @internal
*/
async initPresetPlugins() { async initPresetPlugins() {
if (this['_initPresetPlugins']) { if (this['_initPresetPlugins']) {
return; return;

View File

@ -33,9 +33,22 @@ export interface PluginOptions {
export abstract class Plugin<O = any> implements PluginInterface { export abstract class Plugin<O = any> implements PluginInterface {
options: any; options: any;
app: Application; app: Application;
/**
* @deprecated
*/
model: Model; model: Model;
/**
* @internal
*/
state: any = {}; state: any = {};
/**
* @internal
*/
private _sourceDir: string;
constructor(app: Application, options?: any) { constructor(app: Application, options?: any) {
this.app = app; this.app = app;
this.setOptions(options); this.setOptions(options);
@ -80,10 +93,6 @@ export abstract class Plugin<O = any> implements PluginInterface {
return this.options.isPreset; return this.options.isPreset;
} }
setOptions(options: any) {
this.options = options || {};
}
getName() { getName() {
return (this.options as any).name; return (this.options as any).name;
} }
@ -92,64 +101,6 @@ export abstract class Plugin<O = any> implements PluginInterface {
return this.app.createLogger(options); 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() {} afterAdd() {}
beforeLoad() {} beforeLoad() {}
@ -172,13 +123,86 @@ export abstract class Plugin<O = any> implements PluginInterface {
async afterRemove() {} async afterRemove() {}
async importCollections(collectionsPath: string) { /**
// await this.db.import({ * @deprecated
// directory: collectionsPath, */
// from: `plugin:${this.getName()}`, 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() { async loadCollections() {
if (!this.options.packageName) { if (!this.options.packageName) {
return; return;
@ -197,6 +221,9 @@ export abstract class Plugin<O = any> implements PluginInterface {
} }
} }
/**
* @deprecated
*/
requiredPlugins() { requiredPlugins() {
return []; return [];
} }
@ -205,6 +232,9 @@ export abstract class Plugin<O = any> implements PluginInterface {
return this.app.i18n.t(text, { ns: this.options['packageName'], ...(options as any) }); return this.app.i18n.t(text, { ns: this.options['packageName'], ...(options as any) });
} }
/**
* @internal
*/
protected async isDev() { protected async isDev() {
if (!this.options.packageName) { if (!this.options.packageName) {
return false; return false;
@ -218,6 +248,9 @@ export abstract class Plugin<O = any> implements PluginInterface {
return false; return false;
} }
/**
* @experimental
*/
async toJSON(options: any = {}) { async toJSON(options: any = {}) {
const { locale = 'en-US' } = options; const { locale = 'en-US' } = options;
const { name, packageName, packageJson } = this.options; const { name, packageName, packageJson } = this.options;

View File

@ -2,12 +2,12 @@ import { Plugin } from '@nocobase/client';
import { RolesManagement } from './RolesManagement'; import { RolesManagement } from './RolesManagement';
import { RolesManager } from './roles-manager'; import { RolesManager } from './roles-manager';
class ACLPlugin extends Plugin { export class PluginACLClient extends Plugin {
rolesManager = new RolesManager(); rolesManager = new RolesManager();
async load() { async load() {
this.app.pluginSettingsManager.add('users-permissions.roles', { this.pluginSettingsManager.add('users-permissions.roles', {
title: '{{t("Roles & Permissions")}}', title: this.t('Roles & Permissions'),
icon: 'LockOutlined', icon: 'LockOutlined',
Component: RolesManagement, Component: RolesManagement,
aclSnippet: 'pm.acl.roles', aclSnippet: 'pm.acl.roles',
@ -16,5 +16,5 @@ class ACLPlugin extends Plugin {
} }
} }
export default ACLPlugin;
export { RolesManagerContext } from './RolesManagerProvider'; export { RolesManagerContext } from './RolesManagerProvider';
export default PluginACLClient;

View File

@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
export function useACLTranslation() { export function useACLTranslation() {
return useTranslation(['acl', 'client'], { nsMode: 'fallback' }); return useTranslation(['@nocobase/plugin-acl', 'client'], { nsMode: 'fallback' });
} }

View File

@ -1,6 +1,6 @@
import { ISchema, useForm } from '@formily/react';
import { import {
CollectionContext, CollectionContext,
CollectionProvider,
CollectionProvider_deprecated, CollectionProvider_deprecated,
ResourceActionContext, ResourceActionContext,
SchemaComponent, SchemaComponent,
@ -8,17 +8,14 @@ import {
useActionContext, useActionContext,
useFilterFieldOptions, useFilterFieldOptions,
useFilterFieldProps, useFilterFieldProps,
useCollectionRecord,
useRecord, useRecord,
useRequest, useRequest,
useResourceActionContext, useResourceActionContext,
} from '@nocobase/client'; } from '@nocobase/client';
import React, { useContext, useEffect } from 'react'; import React, { useContext, useEffect } from 'react';
import { roleCollectionsSchema } from '../schemas/roles';
import { RolesManagerContext } from '../RolesManagerProvider'; import { RolesManagerContext } from '../RolesManagerProvider';
import { ISchema } from '@formily/react'; import { roleCollectionsSchema } from '../schemas/roles';
import { RolesResourcesActions } from './RolesResourcesActions'; import { RolesResourcesActions } from './RolesResourcesActions';
import { useForm } from '@formily/react';
const collection = { const collection = {
name: 'collections', name: 'collections',

View File

@ -2,5 +2,10 @@
"The current user has no roles. Please try another account.": "当前用户没有角色,请使用其他账号。", "The current user has no roles. Please try another account.": "当前用户没有角色,请使用其他账号。",
"The user role does not exist. Please try signing in again": "用户角色不存在,请尝试重新登录。", "The user role does not exist. Please try signing in again": "用户角色不存在,请尝试重新登录。",
"New role": "新建角色", "New role": "新建角色",
"Permissions": "权限" "Permissions": "权限",
"Roles & Permissions": "角色和权限",
"General": "通用",
"Menu": "菜单",
"Plugin settings": "插件设置",
"Data sources": "数据源"
} }

View File

@ -1,5 +1,6 @@
export { default } from './server'; export * from './middlewares/setCurrentRole';
export * from './middlewares/with-acl-meta';
export { RoleResourceActionModel } from './model/RoleResourceActionModel'; export { RoleResourceActionModel } from './model/RoleResourceActionModel';
export { RoleResourceModel } from './model/RoleResourceModel'; export { RoleResourceModel } from './model/RoleResourceModel';
export * from './middlewares/with-acl-meta';
export * from './middlewares/setCurrentRole'; export { default } from './server';

View File

@ -1,20 +1,20 @@
import { Plugin, useCollection_deprecated } from '@nocobase/client'; import { Plugin, useCollection_deprecated } from '@nocobase/client';
import { bulkEditActionSettings, deprecatedBulkEditActionSettings } from './BulkEditAction.Settings'; import { bulkEditActionSettings, deprecatedBulkEditActionSettings } from './BulkEditAction.Settings';
import { BulkEditFormItemInitializers_deprecated, bulkEditFormItemInitializers } from './BulkEditFormItemInitializers'; import { BulkEditActionInitializer } from './BulkEditActionInitializer';
import { import {
CreateFormBulkEditBlockInitializers,
BulkEditBlockInitializers_deprecated, BulkEditBlockInitializers_deprecated,
CreateFormBulkEditBlockInitializers,
bulkEditBlockInitializers, bulkEditBlockInitializers,
} from './BulkEditBlockInitializers'; } from './BulkEditBlockInitializers';
import { import {
BulkEditFormActionInitializers_deprecated, BulkEditFormActionInitializers_deprecated,
bulkEditFormActionInitializers, bulkEditFormActionInitializers,
} from './BulkEditFormActionInitializers'; } from './BulkEditFormActionInitializers';
import { BulkEditActionInitializer } from './BulkEditActionInitializer'; import { BulkEditFormItemInitializers_deprecated, bulkEditFormItemInitializers } from './BulkEditFormItemInitializers';
import { bulkEditFormItemSettings } from './bulkEditFormItemSettings'; import { bulkEditFormItemSettings } from './bulkEditFormItemSettings';
import { BulkEditField } from './component/BulkEditField'; import { BulkEditField } from './component/BulkEditField';
import { useCustomizeBulkEditActionProps } from './utils'; import { useCustomizeBulkEditActionProps } from './utils';
export class BulkEditPlugin extends Plugin { export class PluginActionBulkEditClient extends Plugin {
async load() { async load() {
this.app.addComponents({ BulkEditField }); this.app.addComponents({ BulkEditField });
this.app.addScopes({ useCustomizeBulkEditActionProps }); this.app.addScopes({ useCustomizeBulkEditActionProps });
@ -61,4 +61,4 @@ export class BulkEditPlugin extends Plugin {
} }
} }
export default BulkEditPlugin; export default PluginActionBulkEditClient;

View File

@ -1,10 +1,7 @@
import { i18n } from '@nocobase/client'; import { i18n } from '@nocobase/client';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
export const NAMESPACE = 'bulk-edit'; export const NAMESPACE = '@nocobase/plugin-bulk-edit';
// i18n.addResources('zh-CN', NAMESPACE, zhCN);
// i18n.addResources('en-US', NAMESPACE, enUS);
export function lang(key: string) { export function lang(key: string) {
return i18n.t(key, { ns: NAMESPACE }); return i18n.t(key, { ns: NAMESPACE });

View File

@ -1,9 +1,9 @@
import { Plugin, useCollection_deprecated } from '@nocobase/client'; import { Plugin, useCollection_deprecated } from '@nocobase/client';
import { bulkUpdateActionSettings, deprecatedBulkUpdateActionSettings } from './BulkUpdateAction.Settings'; import { bulkUpdateActionSettings, deprecatedBulkUpdateActionSettings } from './BulkUpdateAction.Settings';
import { BulkUpdateActionInitializer } from './BulkUpdateActionInitializer';
import { CustomizeActionInitializer } from './CustomizeActionInitializer'; import { CustomizeActionInitializer } from './CustomizeActionInitializer';
import { useCustomizeBulkUpdateActionProps } from './utils'; import { useCustomizeBulkUpdateActionProps } from './utils';
import { BulkUpdateActionInitializer } from './BulkUpdateActionInitializer'; export class PluginActionBulkUpdateClient extends Plugin {
export class PluginBulkUpdateClient extends Plugin {
async load() { async load() {
this.app.addComponents({ CustomizeActionInitializer }); this.app.addComponents({ CustomizeActionInitializer });
this.app.addScopes({ useCustomizeBulkUpdateActionProps }); this.app.addScopes({ useCustomizeBulkUpdateActionProps });
@ -31,4 +31,4 @@ export class PluginBulkUpdateClient extends Plugin {
} }
} }
export default PluginBulkUpdateClient; export default PluginActionBulkUpdateClient;

View File

@ -3,9 +3,6 @@ import { useTranslation } from 'react-i18next';
export const NAMESPACE = 'bulk-update'; export const NAMESPACE = 'bulk-update';
// i18n.addResources('zh-CN', NAMESPACE, zhCN);
// i18n.addResources('en-US', NAMESPACE, enUS);
export function lang(key: string) { export function lang(key: string) {
return i18n.t(key, { ns: NAMESPACE }); return i18n.t(key, { ns: NAMESPACE });
} }

View File

@ -4,7 +4,7 @@ import { deprecatedDuplicateActionSettings, duplicateActionSettings } from './Du
import { DuplicateActionInitializer } from './DuplicateActionInitializer'; import { DuplicateActionInitializer } from './DuplicateActionInitializer';
import { DuplicatePluginProvider } from './DuplicatePluginProvider'; import { DuplicatePluginProvider } from './DuplicatePluginProvider';
export class PluginDuplicateClient extends Plugin { export class PluginActionDuplicateClient extends Plugin {
async load() { async load() {
this.app.use(DuplicatePluginProvider); this.app.use(DuplicatePluginProvider);
this.app.addComponents({ this.app.addComponents({
@ -64,5 +64,5 @@ export class PluginDuplicateClient extends Plugin {
} }
} }
export default PluginDuplicateClient; export default PluginActionDuplicateClient;
export * from './DuplicateAction'; export * from './DuplicateAction';

View File

@ -1,7 +1,7 @@
import { Plugin } from '@nocobase/client'; import { Plugin } from '@nocobase/client';
import { deprecatedPrintActionSettings, printActionSettings } from './PrintAction.Settings'; import { deprecatedPrintActionSettings, printActionSettings } from './PrintAction.Settings';
import { PrintActionPluginProvider } from './PrintActionPluginProvider'; import { PrintActionPluginProvider } from './PrintActionPluginProvider';
export class PrintPlugin extends Plugin { export class PluginActionPrintClient extends Plugin {
async load() { async load() {
this.app.use(PrintActionPluginProvider); this.app.use(PrintActionPluginProvider);
this.app.schemaSettingsManager.add(deprecatedPrintActionSettings); this.app.schemaSettingsManager.add(deprecatedPrintActionSettings);
@ -23,4 +23,4 @@ export class PrintPlugin extends Plugin {
} }
} }
export default PrintPlugin; export default PluginActionPrintClient;

View File

@ -37,7 +37,7 @@ const SCDocumentation = () => {
); );
}; };
export class APIDocumentationPlugin extends Plugin { export class PluginAPIDocClient extends Plugin {
async load() { async load() {
this.app.pluginSettingsManager.add(NAMESPACE, { this.app.pluginSettingsManager.add(NAMESPACE, {
title: `{{t("API documentation", { ns: "${NAMESPACE}" })}}`, title: `{{t("API documentation", { ns: "${NAMESPACE}" })}}`,
@ -53,4 +53,4 @@ export class APIDocumentationPlugin extends Plugin {
} }
} }
export default APIDocumentationPlugin; export default PluginAPIDocClient;

View File

@ -2,7 +2,7 @@ import { Context } from '@nocobase/actions';
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import { SwaggerManager } from './swagger'; import { SwaggerManager } from './swagger';
export default class APIDoc extends Plugin { export class PluginAPIDocServer extends Plugin {
swagger: SwaggerManager; swagger: SwaggerManager;
constructor(app, options) { constructor(app, options) {
super(app, options); super(app, options);
@ -10,7 +10,7 @@ export default class APIDoc extends Plugin {
} }
async beforeLoad() {} async beforeLoad() {}
async load() { async load() {
this.app.resource({ this.app.resourcer.define({
name: 'swagger', name: 'swagger',
type: 'single', type: 'single',
actions: { actions: {
@ -46,3 +46,5 @@ export default class APIDoc extends Plugin {
}); });
} }
} }
export default PluginAPIDocServer;

View File

@ -2,15 +2,15 @@ import { Plugin } from '@nocobase/client';
import { NAMESPACE } from '../constants'; import { NAMESPACE } from '../constants';
import { Configuration } from './Configuration'; import { Configuration } from './Configuration';
class APIKeysPlugin extends Plugin { export class PluginAPIKeysClient extends Plugin {
async load() { async load() {
this.app.pluginSettingsManager.add(NAMESPACE, { this.pluginSettingsManager.add(NAMESPACE, {
icon: 'KeyOutlined', icon: 'KeyOutlined',
title: '{{t("API keys", {"ns": "api-keys"})}}', title: this.t('API keys'),
Component: Configuration, Component: Configuration,
aclSnippet: 'pm.api-keys.configuration', aclSnippet: 'pm.api-keys.configuration',
}); });
} }
} }
export default APIKeysPlugin; export default PluginAPIKeysClient;

View File

@ -1 +1 @@
export const NAMESPACE = 'api-keys'; export const NAMESPACE = '@nocobase/plugin-api-keys';

View File

@ -1,24 +1,11 @@
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import { resolve } from 'path';
import { NAMESPACE } from '../constants';
import { create, destroy } from './actions/api-keys'; import { create, destroy } from './actions/api-keys';
import { enUS, zhCN } from './locale';
export interface ApiKeysPluginConfig { export class PluginAPIKeysServer extends Plugin {
name?: string;
}
export default class ApiKeysPlugin extends Plugin<ApiKeysPluginConfig> {
resourceName = 'apiKeys'; resourceName = 'apiKeys';
constructor(app, options) {
super(app, options);
}
async beforeLoad() { async beforeLoad() {
this.app.i18n.addResources('zh-CN', NAMESPACE, zhCN); this.app.resourcer.define({
this.app.i18n.addResources('en-US', NAMESPACE, enUS);
await this.app.resourcer.define({
name: this.resourceName, name: this.resourceName,
actions: { actions: {
create, create,
@ -34,11 +21,9 @@ export default class ApiKeysPlugin extends Plugin<ApiKeysPluginConfig> {
} }
async load() { async load() {
await this.importCollections(resolve(__dirname, '../collections'));
this.app.resourcer.use(async (ctx, next) => { this.app.resourcer.use(async (ctx, next) => {
const { resourceName, actionName } = ctx.action.params; const { resourceName, actionName } = ctx.action;
if (resourceName == this.resourceName && ['list', 'destroy'].includes(actionName)) { if (resourceName === this.resourceName && ['list', 'destroy'].includes(actionName)) {
ctx.action.mergeParams({ ctx.action.mergeParams({
filter: { filter: {
createdById: ctx.auth.user.id, createdById: ctx.auth.user.id,
@ -49,3 +34,5 @@ export default class ApiKeysPlugin extends Plugin<ApiKeysPluginConfig> {
}); });
} }
} }
export default PluginAPIKeysServer;

View File

@ -1,13 +1,13 @@
import { Plugin } from '@nocobase/client'; 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 { Registry } from '@nocobase/utils/client';
import { ComponentType } from 'react';
import { presetAuthType } from '../preset'; import { presetAuthType } from '../preset';
import { SignInForm, SignUpForm, Options } from './basic'; import { AuthProvider } from './AuthProvider';
import { Authenticator as AuthenticatorType } from './authenticator'; 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 = { export type AuthOptions = {
components: Partial<{ components: Partial<{
@ -18,7 +18,7 @@ export type AuthOptions = {
}>; }>;
}; };
export class AuthPlugin extends Plugin { export class PluginAuthClient extends Plugin {
authTypes = new Registry<AuthOptions>(); authTypes = new Registry<AuthOptions>();
registerType(authType: string, options: AuthOptions) { registerType(authType: string, options: AuthOptions) {
@ -63,7 +63,8 @@ export class AuthPlugin extends Plugin {
} }
} }
export default AuthPlugin; export { AuthenticatorsContext, useAuthenticator } from './authenticator';
export { useSignIn } from './basic';
export { useAuthenticator, AuthenticatorsContext } from './authenticator';
export type { Authenticator } from './authenticator'; export type { Authenticator } from './authenticator';
export { useSignIn } from './basic';
export default PluginAuthClient;

View File

@ -1,17 +1,17 @@
import { Cache } from '@nocobase/cache';
import { Model } from '@nocobase/database'; import { Model } from '@nocobase/database';
import { InstallOptions, Plugin } from '@nocobase/server'; import { InstallOptions, Plugin } from '@nocobase/server';
import { resolve } from 'path'; import { resolve } from 'path';
import { namespace, presetAuthenticator, presetAuthType } from '../preset'; import { namespace, presetAuthType, presetAuthenticator } from '../preset';
import authActions from './actions/auth'; import authActions from './actions/auth';
import authenticatorsActions from './actions/authenticators'; import authenticatorsActions from './actions/authenticators';
import { BasicAuth } from './basic-auth'; import { BasicAuth } from './basic-auth';
import { enUS, zhCN } from './locale'; import { enUS, zhCN } from './locale';
import { AuthModel } from './model/authenticator'; import { AuthModel } from './model/authenticator';
import { TokenBlacklistService } from './token-blacklist';
import { Cache } from '@nocobase/cache';
import { Storer } from './storer'; import { Storer } from './storer';
import { TokenBlacklistService } from './token-blacklist';
export class AuthPlugin extends Plugin { export class PluginAuthServer extends Plugin {
cache: Cache; cache: Cache;
afterAdd() {} afterAdd() {}
@ -105,4 +105,4 @@ export class AuthPlugin extends Plugin {
async remove() {} async remove() {}
} }
export default AuthPlugin; export default PluginAuthServer;

View File

@ -2,11 +2,12 @@ import { Plugin } from '@nocobase/client';
import { BackupAndRestoreList } from './Configuration'; import { BackupAndRestoreList } from './Configuration';
import { DuplicatorProvider } from './DuplicatorProvider'; import { DuplicatorProvider } from './DuplicatorProvider';
import { NAMESPACE } from './locale'; import { NAMESPACE } from './locale';
export class DuplicatorPlugin extends Plugin {
export class PluginBackupRestoreClient extends Plugin {
async load() { async load() {
this.app.use(DuplicatorProvider); this.app.use(DuplicatorProvider);
this.app.pluginSettingsManager.add(NAMESPACE, { this.app.pluginSettingsManager.add(NAMESPACE, {
title: `{{t("Backup & Restore", { ns: "${NAMESPACE}" })}}`, title: this.t('Backup & Restore'),
icon: 'CloudServerOutlined', icon: 'CloudServerOutlined',
Component: BackupAndRestoreList, Component: BackupAndRestoreList,
aclSnippet: 'pm.backup.restore', aclSnippet: 'pm.backup.restore',
@ -14,4 +15,4 @@ export class DuplicatorPlugin extends Plugin {
} }
} }
export default DuplicatorPlugin; export default PluginBackupRestoreClient;

View File

@ -1,7 +1,7 @@
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import backupFilesResourcer from './resourcers/backup-files'; import backupFilesResourcer from './resourcers/backup-files';
export default class Duplicator extends Plugin { export default class PluginBackupRestoreServer extends Plugin {
beforeLoad() { beforeLoad() {
this.app.acl.registerSnippet({ this.app.acl.registerSnippet({
name: `pm.${this.name}`, name: `pm.${this.name}`,