mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-02 04:07:50 +08:00
feat: improve code
This commit is contained in:
parent
09c42abdcc
commit
b7eb720eb4
@ -7,6 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"bootstrap": "lerna bootstrap",
|
"bootstrap": "lerna bootstrap",
|
||||||
"clean": "lerna clean",
|
"clean": "lerna clean",
|
||||||
|
"examples": "ts-node-dev -r dotenv/config ./examples",
|
||||||
"start": "cd packages/app && npm start",
|
"start": "cd packages/app && npm start",
|
||||||
"start-client": "cd packages/app && npm run start-client",
|
"start-client": "cd packages/app && npm run start-client",
|
||||||
"start-server": "nodemon",
|
"start-server": "nodemon",
|
||||||
|
@ -6,6 +6,7 @@ import Database, { DatabaseOptions, TableOptions } from '@nocobase/database';
|
|||||||
import Resourcer, { ResourceOptions } from '@nocobase/resourcer';
|
import Resourcer, { ResourceOptions } from '@nocobase/resourcer';
|
||||||
import { dataWrapping, table2resource } from './middlewares';
|
import { dataWrapping, table2resource } from './middlewares';
|
||||||
import { PluginType, Plugin, PluginOptions } from './plugin';
|
import { PluginType, Plugin, PluginOptions } from './plugin';
|
||||||
|
import { registerActions } from '@nocobase/actions';
|
||||||
|
|
||||||
export interface ResourcerOptions {
|
export interface ResourcerOptions {
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
@ -20,6 +21,7 @@ export interface ApplicationOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Application extends Koa {
|
export class Application extends Koa {
|
||||||
|
|
||||||
public readonly db: Database;
|
public readonly db: Database;
|
||||||
|
|
||||||
public readonly resourcer: Resourcer;
|
public readonly resourcer: Resourcer;
|
||||||
@ -31,7 +33,12 @@ export class Application extends Koa {
|
|||||||
constructor(options: ApplicationOptions) {
|
constructor(options: ApplicationOptions) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
if (options.database instanceof Database) {
|
||||||
|
this.db = options.database;
|
||||||
|
} else {
|
||||||
this.db = new Database(options.database);
|
this.db = new Database(options.database);
|
||||||
|
}
|
||||||
|
|
||||||
this.resourcer = new Resourcer({ ...options.resourcer });
|
this.resourcer = new Resourcer({ ...options.resourcer });
|
||||||
this.cli = new Command();
|
this.cli = new Command();
|
||||||
|
|
||||||
@ -55,17 +62,19 @@ export class Application extends Koa {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (options.dataWrapping !== false) {
|
if (options.dataWrapping !== false) {
|
||||||
this.use(dataWrapping);
|
this.use(dataWrapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.use(table2resource);
|
this.use(table2resource());
|
||||||
this.use(this.resourcer.restApiMiddleware());
|
this.use(this.resourcer.restApiMiddleware());
|
||||||
|
|
||||||
|
registerActions(this);
|
||||||
|
|
||||||
this.cli
|
this.cli
|
||||||
.command('db sync')
|
.command('db sync')
|
||||||
.option('-f, --force')
|
.option('-f, --force')
|
||||||
.action(async (...args) => {
|
.action(async (...args) => {
|
||||||
console.log('db sync');
|
console.log('db sync...');
|
||||||
const cli = args.pop();
|
const cli = args.pop();
|
||||||
const force = cli.opts()?.force;
|
const force = cli.opts()?.force;
|
||||||
await this.load();
|
await this.load();
|
||||||
@ -120,6 +129,10 @@ export class Application extends Koa {
|
|||||||
return this.resourcer.define(options);
|
return this.resourcer.define(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actions(handlers: any) {
|
||||||
|
return this.resourcer.registerActions(handlers);
|
||||||
|
}
|
||||||
|
|
||||||
command(nameAndArgs: string, opts?: CommandOptions) {
|
command(nameAndArgs: string, opts?: CommandOptions) {
|
||||||
return this.cli.command(nameAndArgs, opts);
|
return this.cli.command(nameAndArgs, opts);
|
||||||
}
|
}
|
||||||
@ -216,58 +229,13 @@ export class Application extends Koa {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerPlugin(key: string | object, plugin?: any) {
|
async parse(argv = process.argv) {
|
||||||
// if (typeof key === 'object') {
|
|
||||||
// Object.keys(key).forEach((k) => {
|
|
||||||
// this.registerPlugin(k, key[k]);
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// const config = {};
|
|
||||||
// if (Array.isArray(plugin)) {
|
|
||||||
// const [entry, options = {}] = plugin;
|
|
||||||
// Object.assign(config, { entry, options });
|
|
||||||
// } else {
|
|
||||||
// Object.assign(config, { entry: plugin, options: {} });
|
|
||||||
// }
|
|
||||||
// this.plugins.set(key, config);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async loadPlugins() {
|
|
||||||
// await this.emitAsync('plugins.beforeLoad');
|
|
||||||
// const allPlugins = this.plugins.values();
|
|
||||||
// for (const plugin of allPlugins) {
|
|
||||||
// plugin.instance = await this.loadPlugin(plugin);
|
|
||||||
// }
|
|
||||||
// await this.emitAsync('plugins.afterLoad');
|
|
||||||
// }
|
|
||||||
|
|
||||||
async start(argv = process.argv) {
|
|
||||||
return this.cli.parseAsync(argv);
|
return this.cli.parseAsync(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
async destroy() {
|
async destroy() {
|
||||||
await this.db.close();
|
await this.db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// protected async loadPlugin({
|
|
||||||
// entry,
|
|
||||||
// options = {},
|
|
||||||
// }: {
|
|
||||||
// entry: string | Function;
|
|
||||||
// options: any;
|
|
||||||
// }) {
|
|
||||||
// let main: any;
|
|
||||||
// if (typeof entry === 'function') {
|
|
||||||
// main = entry;
|
|
||||||
// } else if (typeof entry === 'string') {
|
|
||||||
// const pathname = `${entry}/${
|
|
||||||
// __filename.endsWith('.ts') ? 'src' : 'lib'
|
|
||||||
// }/server`;
|
|
||||||
// main = require(pathname).default;
|
|
||||||
// }
|
|
||||||
// return main && (await main.call(this, options));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Application;
|
export default Application;
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import { Context, Next } from '@nocobase/actions';
|
|
||||||
|
|
||||||
export function actionParams(options: any = {}) {
|
|
||||||
return async (ctx: Context, next: Next) => {
|
|
||||||
const { actionName, resourceField, resourceName, fields = {} } = ctx.action.params;
|
|
||||||
const table = ctx.db.getTable(resourceField ? resourceField.options.target : resourceName);
|
|
||||||
// ctx.state.developerMode = {[Op.not]: null};
|
|
||||||
ctx.state.developerMode = false;
|
|
||||||
if (table && table.hasField('developerMode') && ctx.state.developerMode === false) {
|
|
||||||
ctx.action.mergeParams({ filter: { "developerMode.$isFalsy": true } }, { filter: 'and' });
|
|
||||||
}
|
|
||||||
if (table && ['get', 'list'].includes(actionName)) {
|
|
||||||
const except = [];
|
|
||||||
const appends = [];
|
|
||||||
for (const [name, field] of table.getFields()) {
|
|
||||||
if (field.options.hidden) {
|
|
||||||
except.push(field.options.name);
|
|
||||||
}
|
|
||||||
// if (field.options.appends) {
|
|
||||||
// appends.push(field.options.name);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
ctx.action.mergeParams({ fields: {
|
|
||||||
except,
|
|
||||||
appends
|
|
||||||
} }, { fields: 'append' });
|
|
||||||
// console.log('ctx.action.params.fields', ctx.action.params.fields, except, appends);
|
|
||||||
}
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import path from 'path';
|
|
||||||
import send from 'koa-send';
|
|
||||||
import serve from 'koa-static';
|
|
||||||
import { Context, Next } from '@nocobase/actions';
|
|
||||||
|
|
||||||
export interface AppDistServeOptions {
|
|
||||||
root?: string;
|
|
||||||
useStaticServer?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function appDistServe(options: AppDistServeOptions = {}) {
|
|
||||||
return async (ctx: Context, next: Next) => {
|
|
||||||
if (!options.root || !options.useStaticServer) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
let root = options.root;
|
|
||||||
if (!root.startsWith('/')) {
|
|
||||||
root = path.resolve(process.cwd(), root);
|
|
||||||
}
|
|
||||||
await serve(root)(ctx, next);
|
|
||||||
if (ctx.status == 404) {
|
|
||||||
return send(ctx, 'index.html', { root });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
import { Context, Next } from '@nocobase/actions';
|
import { Context, Next } from '@nocobase/actions';
|
||||||
|
|
||||||
export async function dataWrapping(ctx: Context, next: Next) {
|
export function dataWrapping() {
|
||||||
|
return async function dataWrapping(ctx: Context, next: Next) {
|
||||||
await next();
|
await next();
|
||||||
if (ctx.withoutDataWrapping) {
|
if (ctx.withoutDataWrapping) {
|
||||||
return;
|
return;
|
||||||
@ -25,6 +26,7 @@ export async function dataWrapping(ctx: Context, next: Next) {
|
|||||||
data: ctx.body,
|
data: ctx.body,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default dataWrapping;
|
export default dataWrapping;
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import { Context, Next } from '@nocobase/actions';
|
|
||||||
|
|
||||||
export interface DemoBlackListedActionsOptions {
|
|
||||||
emails?: string[];
|
|
||||||
blacklist?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultBlacklist = ['create', 'update', 'destroy', 'sort', 'upload'];
|
|
||||||
|
|
||||||
export function demoBlacklistedActions(options: DemoBlackListedActionsOptions = {}) {
|
|
||||||
const { emails, blacklist = defaultBlacklist } = options;
|
|
||||||
return async (ctx: Context, next: Next) => {
|
|
||||||
const currentUser = ctx.state.currentUser;
|
|
||||||
if (currentUser && emails.includes(currentUser.email)) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
const { actionName } = ctx.action.params;
|
|
||||||
if (blacklist.includes(actionName)) {
|
|
||||||
ctx.body = {
|
|
||||||
data: {},
|
|
||||||
meta: {},
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,2 @@
|
|||||||
export * from './action-params';
|
|
||||||
export * from './app-dist-serve';
|
|
||||||
export * from './demo-blacklisted-actions';
|
|
||||||
export * from './table2resource';
|
export * from './table2resource';
|
||||||
export * from './data-wrapping';
|
export * from './data-wrapping';
|
||||||
|
@ -6,12 +6,13 @@ import {
|
|||||||
} from '@nocobase/resourcer';
|
} from '@nocobase/resourcer';
|
||||||
import { BELONGSTO, BELONGSTOMANY, HASMANY, HASONE } from '@nocobase/database';
|
import { BELONGSTO, BELONGSTOMANY, HASMANY, HASONE } from '@nocobase/database';
|
||||||
|
|
||||||
export async function table2resource(
|
export function table2resource() {
|
||||||
|
return async function table2resource(
|
||||||
ctx: ResourcerContext,
|
ctx: ResourcerContext,
|
||||||
next: () => Promise<any>,
|
next: () => Promise<any>,
|
||||||
) {
|
) {
|
||||||
const resourcer = ctx.resourcer;
|
const resourcer = ctx.resourcer;
|
||||||
const database = ctx.database;
|
const database = ctx.db;
|
||||||
let params = parseRequest(
|
let params = parseRequest(
|
||||||
{
|
{
|
||||||
path: ctx.request.path,
|
path: ctx.request.path,
|
||||||
@ -67,6 +68,7 @@ export async function table2resource(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return next();
|
return next();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default table2resource;
|
export default table2resource;
|
||||||
|
@ -28,7 +28,7 @@ describe('mock server', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('resource', async () => {
|
it('resource', async () => {
|
||||||
const response = await api.resource('test').list();
|
const response = await api.agent().resource('test').list();
|
||||||
expect(response.body).toEqual([1, 2]);
|
expect(response.body).toEqual([1, 2]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import qs from 'qs';
|
import qs from 'qs';
|
||||||
import supertest from 'supertest';
|
import supertest, { SuperAgentTest } from 'supertest';
|
||||||
import Application, { ApplicationOptions } from '@nocobase/server';
|
import Application, { ApplicationOptions } from '@nocobase/server';
|
||||||
import { getConfig } from './mockDatabase';
|
import { getConfig } from './mockDatabase';
|
||||||
|
|
||||||
@ -46,20 +46,14 @@ interface Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MockServer extends Application {
|
export class MockServer extends Application {
|
||||||
|
agent(): SuperAgentTest & { resource: (name: string) => Resource } {
|
||||||
protected agentInstance: supertest.SuperAgentTest;
|
const agent = supertest.agent(this.callback());
|
||||||
|
|
||||||
agent() {
|
|
||||||
if (!this.agentInstance) {
|
|
||||||
this.agentInstance = supertest.agent(this.callback());
|
|
||||||
}
|
|
||||||
return this.agentInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
resource(name: string) {
|
|
||||||
const agent = this.agent();
|
|
||||||
const keys = name.split('.');
|
|
||||||
const prefix = this.resourcer.options.prefix;
|
const prefix = this.resourcer.options.prefix;
|
||||||
|
const proxy = new Proxy({}, {
|
||||||
|
get(target, method: string, receiver) {
|
||||||
|
if (method === 'resource') {
|
||||||
|
return (name: string) => {
|
||||||
|
const keys = name.split('.');
|
||||||
const proxy = new Proxy({}, {
|
const proxy = new Proxy({}, {
|
||||||
get(target, method: string, receiver) {
|
get(target, method: string, receiver) {
|
||||||
return (params: ActionParams = {}) => {
|
return (params: ActionParams = {}) => {
|
||||||
@ -98,7 +92,15 @@ export class MockServer extends Application {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return proxy as Resource;
|
return proxy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (...args: any[]) => {
|
||||||
|
return agent[method](...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return proxy as any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@nocobase/*": [
|
"@nocobase/*": [
|
||||||
"./packages/*"
|
"./packages/*/src"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user