feat: code cleanup

This commit is contained in:
chenos 2022-02-11 18:13:14 +08:00
parent ad648431e9
commit a507267b72
18 changed files with 116 additions and 75 deletions

View File

@ -55,10 +55,20 @@ const api = new Application({
}, },
}); });
api.plugin(require('@nocobase/plugin-collection-manager').default); const plugins = [
api.plugin(require('@nocobase/plugin-ui-schema-storage').default); '@nocobase/plugin-collection-manager',
api.plugin(require('@nocobase/plugin-ui-routes-storage').default); '@nocobase/plugin-ui-schema-storage',
// api.plugin(require('@nocobase/plugin-acl')); '@nocobase/plugin-ui-routes-storage',
'@nocobase/plugin-client',
'@nocobase/plugin-file-manager',
'@nocobase/plugin-system-settings',
'@nocobase/plugin-users',
'@nocobase/plugin-acl',
];
for (const plugin of plugins) {
api.plugin(require(plugin).default);
}
if (process.argv.length < 3) { if (process.argv.length < 3) {
// @ts-ignore // @ts-ignore

View File

@ -1 +1,2 @@
export { default as default } from './server'; export { default } from './server';

View File

@ -1,9 +1,9 @@
import { Plugin } from '@nocobase/server';
import { ACL } from '@nocobase/acl'; import { ACL } from '@nocobase/acl';
import { Plugin } from '@nocobase/server';
import path from 'path'; import path from 'path';
import { createACL } from './acl';
import { availableActionResource } from './actions/available-actions'; import { availableActionResource } from './actions/available-actions';
import { roleCollectionsResource } from './actions/role-collections'; import { roleCollectionsResource } from './actions/role-collections';
import { createACL } from './acl';
import { RoleResourceActionModel } from './model/RoleResourceActionModel'; import { RoleResourceActionModel } from './model/RoleResourceActionModel';
import { RoleResourceModel } from './model/RoleResourceModel'; import { RoleResourceModel } from './model/RoleResourceModel';
@ -27,7 +27,7 @@ export class GrantHelper {
constructor() {} constructor() {}
} }
export default class PluginACL extends Plugin { export class PluginACL extends Plugin {
acl: ACL; acl: ACL;
associationFieldsActions: AssociationFieldsActions = {}; associationFieldsActions: AssociationFieldsActions = {};
@ -190,3 +190,5 @@ export default class PluginACL extends Plugin {
this.app.resourcer.use(this.acl.middleware()); this.app.resourcer.use(this.acl.middleware());
} }
} }
export default PluginACL;

View File

@ -1,25 +1 @@
import { Plugin } from '@nocobase/server'; export { default } from './plugin';
export default class PluginClient extends Plugin {
async beforeLoad() {
const cmd = this.app.findCommand('install');
if (cmd) {
cmd.option('--import-demo');
cmd.option('--lang [lang]');
}
this.app.on('afterInstall', async (app, options) => {
const [opts] = options?.cliArgs || [{}];
if (opts?.importDemo) {
}
if (opts?.lang) {
}
});
}
async load() {
}
}

View File

@ -0,0 +1,35 @@
import { Plugin } from '@nocobase/server';
export class ClientPlugin extends Plugin {
async beforeLoad() {
const cmd = this.app.findCommand('install');
if (cmd) {
cmd.option('--import-demo');
cmd.option('--lang [lang]');
}
this.app.on('afterInstall', async (app, options) => {
const [opts] = options?.cliArgs || [{}];
if (opts?.importDemo) {
}
if (opts?.lang) {
}
});
}
async load() {
this.app.resource({
name: 'app',
actions: {
async getLang(ctx, next) {
ctx.body = {
lang: 'zh-CN',
};
await next();
},
},
});
}
}
export default ClientPlugin;

View File

@ -1,2 +1,3 @@
export * from './constants'; export * from './constants';
export { default } from './server'; export { default } from './server';

View File

@ -1,14 +1,14 @@
import path from 'path';
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import { resolve } from 'path';
import { action as uploadAction, middleware as uploadMiddleware } from './actions/upload'; import { action as uploadAction, middleware as uploadMiddleware } from './actions/upload';
import { getStorageConfig } from './storages';
import { STORAGE_TYPE_LOCAL } from './constants'; import { STORAGE_TYPE_LOCAL } from './constants';
import { getStorageConfig } from './storages';
export default class PluginFileManager extends Plugin { export default class PluginFileManager extends Plugin {
storageType() { storageType() {
return process.env.DEFAULT_STORAGE_TYPE; return process.env.DEFAULT_STORAGE_TYPE;
} }
async beforeLoad() { async beforeLoad() {
this.app.on('installing', async () => { this.app.on('installing', async () => {
const defaultStorageConfig = getStorageConfig(this.storageType()); const defaultStorageConfig = getStorageConfig(this.storageType());
@ -27,7 +27,7 @@ export default class PluginFileManager extends Plugin {
async load() { async load() {
await this.db.import({ await this.db.import({
directory: path.resolve(__dirname, 'collections'), directory: resolve(__dirname, 'collections'),
}); });
// 暂时中间件只能通过 use 加进来 // 暂时中间件只能通过 use 加进来

View File

@ -1,7 +1,7 @@
import { CollectionOptions } from '@nocobase/database'; import { defineCollection } from '@nocobase/database';
export default { export default defineCollection({
name: 'system_settings', name: 'systemSettings',
fields: [ fields: [
{ {
type: 'string', type: 'string',
@ -26,4 +26,5 @@ export default {
name: 'appLang', name: 'appLang',
}, },
], ],
} as CollectionOptions; });

View File

@ -1 +1 @@
export { default } from './server'; export { default } from './plugin';

View File

@ -1,10 +1,10 @@
import path from 'path'; import { Plugin } from '@nocobase/server';
import { Plugin, PluginOptions } from '@nocobase/server'; import { resolve } from 'path';
export default class PluginSystemSettings extends Plugin { export class SystemSettingsPlugin extends Plugin {
async beforeLoad() { async beforeLoad() {
this.app.on('installing', async () => { this.app.on('installing', async () => {
await this.db.getRepository('system_settings').create({ await this.db.getRepository('systemSettings').create({
values: { values: {
title: 'NocoBase', title: 'NocoBase',
logo: { logo: {
@ -21,7 +21,9 @@ export default class PluginSystemSettings extends Plugin {
async load() { async load() {
await this.app.db.import({ await this.app.db.import({
directory: path.resolve(__dirname, 'collections'), directory: resolve(__dirname, 'collections'),
}); });
} }
} }
export default SystemSettingsPlugin;

View File

@ -1,4 +1,4 @@
import PluginUiSchema from './server'; export * from './repository';
import UiSchemaRepository from './repository'; export * from './server';
export default PluginUiSchema; export { default } from './server';
export { UiSchemaRepository };

View File

@ -1,8 +1,8 @@
import { Repository, TransactionAble } from '@nocobase/database'; import { Repository, TransactionAble } from '@nocobase/database';
import lodash from 'lodash';
import { ChildOptions, SchemaNode, TargetPosition, UiSchemaNodeDAO } from './dao/ui_schema_node_dao';
import { uid } from '@nocobase/utils'; import { uid } from '@nocobase/utils';
import lodash from 'lodash';
import { Transaction } from 'sequelize'; import { Transaction } from 'sequelize';
import { ChildOptions, SchemaNode, TargetPosition } from './dao/ui_schema_node_dao';
interface GetJsonSchemaOptions { interface GetJsonSchemaOptions {
includeAsyncNode?: boolean; includeAsyncNode?: boolean;
@ -11,7 +11,7 @@ interface GetJsonSchemaOptions {
const nodeKeys = ['properties', 'definitions', 'patternProperties', 'additionalProperties', 'items']; const nodeKeys = ['properties', 'definitions', 'patternProperties', 'additionalProperties', 'items'];
export default class UiSchemaRepository extends Repository { export class UiSchemaRepository extends Repository {
static schemaToSingleNodes(schema: any, carry: SchemaNode[] = [], childOptions: ChildOptions = null): SchemaNode[] { static schemaToSingleNodes(schema: any, carry: SchemaNode[] = [], childOptions: ChildOptions = null): SchemaNode[] {
const node = lodash.cloneDeep( const node = lodash.cloneDeep(
lodash.isString(schema) lodash.isString(schema)
@ -706,3 +706,5 @@ export default class UiSchemaRepository extends Repository {
return savedNode; return savedNode;
} }
} }
export default UiSchemaRepository;

View File

@ -1,4 +1,4 @@
import { UiSchemaRepository } from '../../'; import { UiSchemaRepository } from '../../repository';
export async function removeSchema({ schemaInstance, options, db, params }) { export async function removeSchema({ schemaInstance, options, db, params }) {
const { transaction } = options; const { transaction } = options;

View File

@ -2,12 +2,12 @@ import { MagicAttributeModel } from '@nocobase/database';
import { Plugin } from '@nocobase/server'; import { Plugin } from '@nocobase/server';
import path from 'path'; import path from 'path';
import { uiSchemaActions } from './actions/ui-schema-action'; import { uiSchemaActions } from './actions/ui-schema-action';
import { UiSchemaModel } from './model';
import UiSchemaRepository from './repository'; import UiSchemaRepository from './repository';
import { ServerHooks } from './server-hooks'; import { ServerHooks } from './server-hooks';
import { UiSchemaModel } from './model';
import { ServerHookModel } from './server-hooks/model'; import { ServerHookModel } from './server-hooks/model';
export default class PluginUiSchema extends Plugin { export class UiSchemaStoragePlugin extends Plugin {
serverHooks: ServerHooks; serverHooks: ServerHooks;
registerRepository() { registerRepository() {
@ -65,3 +65,5 @@ export default class PluginUiSchema extends Plugin {
}); });
} }
} }
export default UiSchemaStoragePlugin;

View File

@ -25,9 +25,10 @@ describe('createdBy/updatedBy', () => {
updatedBy: true, updatedBy: true,
}); });
expect(Post.hasField('createdBy')).toBeTruthy(); expect(Post.hasField('createdBy')).toBeTruthy();
expect(Post.hasField('updatedBy')).toBeTruthy();
}); });
it.skip('case 2', async () => { it('case 2', async () => {
const Post = db.collection({ const Post = db.collection({
name: 'posts', name: 'posts',
createdBy: true, createdBy: true,
@ -35,7 +36,7 @@ describe('createdBy/updatedBy', () => {
}); });
await db.sync(); await db.sync();
const currentUser = await db.getCollection('users').model.create(); const currentUser = await db.getCollection('users').model.create();
const p1 = await Post.repository.create({ await Post.repository.create({
context: { context: {
state: { state: {
currentUser, currentUser,
@ -45,11 +46,12 @@ describe('createdBy/updatedBy', () => {
const p2 = await Post.repository.findOne({ const p2 = await Post.repository.findOne({
appends: ['createdBy', 'updatedBy'], appends: ['createdBy', 'updatedBy'],
}); });
expect(p2.get('createdBy')).toMatchObject(currentUser.toJSON()); const data = p2.toJSON();
expect(p2.get('updatedBy')).toMatchObject(currentUser.toJSON()); expect(data.createdBy.id).toBe(currentUser.get('id'));
expect(data.updatedBy.id).toBe(currentUser.get('id'));
}); });
it.skip('case 3', async () => { it('case 3', async () => {
const Post = db.collection({ const Post = db.collection({
name: 'posts', name: 'posts',
createdBy: true, createdBy: true,
@ -77,8 +79,9 @@ describe('createdBy/updatedBy', () => {
const p2 = await Post.repository.findOne({ const p2 = await Post.repository.findOne({
appends: ['createdBy', 'updatedBy'], appends: ['createdBy', 'updatedBy'],
}); });
expect(p2.get('createdBy')).toMatchObject(user1.toJSON()); const data = p2.toJSON();
expect(p2.get('updatedBy')).toMatchObject(user2.toJSON()); expect(data.createdBy.id).toBe(user1.get('id'));
expect(data.updatedBy.id).toBe(user2.get('id'));
}); });
}); });
}); });

View File

@ -1,6 +1,6 @@
import { MockServer, mockServer } from '@nocobase/test';
import Database from '@nocobase/database'; import Database from '@nocobase/database';
import PluginACL from '@nocobase/plugin-acl'; import PluginACL from '@nocobase/plugin-acl';
import { MockServer, mockServer } from '@nocobase/test';
describe('role', () => { describe('role', () => {
let api: MockServer; let api: MockServer;

View File

@ -4,7 +4,7 @@ import { Context, Next } from '@nocobase/actions';
// 中间件默认只解决解析 token 和附加对应 user 的工作,不解决是否提前报 401 退出。 // 中间件默认只解决解析 token 和附加对应 user 的工作,不解决是否提前报 401 退出。
// 因为是否提供匿名访问资源是应用决定的,不是使用插件就一定不能匿名访问。 // 因为是否提供匿名访问资源是应用决定的,不是使用插件就一定不能匿名访问。
export function parseToken(options) { export function parseToken(options?: any) {
return async function parseToken(ctx: Context, next: Next) { return async function parseToken(ctx: Context, next: Next) {
const token = ctx.get('Authorization').replace(/^Bearer\s+/gi, ''); const token = ctx.get('Authorization').replace(/^Bearer\s+/gi, '');
const User = ctx.db.getCollection('users'); const User = ctx.db.getCollection('users');

View File

@ -1,17 +1,23 @@
import path from 'path'; import { Collection } from '@nocobase/database';
import { Plugin } from '@nocobase/server';
import { resolve } from 'path';
import * as actions from './actions/users'; import * as actions from './actions/users';
import * as middlewares from './middlewares'; import * as middlewares from './middlewares';
import { Collection } from '@nocobase/database';
import { Plugin, PluginOptions } from '@nocobase/server';
export default class PluginUsers extends Plugin { export default class UsersPlugin extends Plugin {
async beforeLoad() { async beforeLoad() {
const {
adminNickname = 'Super Admin',
adminEmail = 'admin@nocobase.com',
adminPassword = 'admin123',
} = this.options;
this.app.on('installing', async () => { this.app.on('installing', async () => {
const User = this.db.getCollection('users'); const User = this.db.getCollection('users');
await User.model.create({ await User.model.create({
nickname: 'Super Admin', nickname: adminNickname,
email: process.env.ADMIN_EMAIL || 'admin@nocobase.com', email: adminEmail,
password: process.env.ADMIN_PASSWORD || 'admin123', password: adminPassword,
}); });
}); });
@ -65,12 +71,12 @@ export default class PluginUsers extends Plugin {
this.app.resourcer.registerActionHandler(`users:${key}`, action); this.app.resourcer.registerActionHandler(`users:${key}`, action);
} }
this.app.resourcer.use(middlewares.parseToken({})); this.app.resourcer.use(middlewares.parseToken());
} }
async load() { async load() {
await this.db.import({ await this.db.import({
directory: path.resolve(__dirname, 'collections'), directory: resolve(__dirname, 'collections'),
}); });
} }
} }