feat: improve code
This commit is contained in:
parent
99d33a0241
commit
336e0b17b8
@ -1,9 +1,10 @@
|
||||
import Server from '@nocobase/server';
|
||||
import { registerActions } from '@nocobase/actions';
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
|
||||
const start = Date.now();
|
||||
console.log('startAt', new Date().toUTCString());
|
||||
console.log('starting... ', new Date().toUTCString());
|
||||
|
||||
dotenv.config({
|
||||
path: path.resolve(__dirname, '../../../../.env'),
|
||||
@ -39,11 +40,17 @@ const api = new Server({
|
||||
resourcer: {
|
||||
prefix: '/api',
|
||||
},
|
||||
dataWrapping: true,
|
||||
});
|
||||
|
||||
console.log(`@nocobase/preset-nocobase/${__filename.endsWith('.ts') ? 'src' : 'lib'}/index`);
|
||||
registerActions(api);
|
||||
|
||||
api.registerPlugin('@nocobase/preset-nocobase', require(`@nocobase/preset-nocobase/${__filename.endsWith('.ts') ? 'src' : 'lib'}/index`).default);
|
||||
const file = `${__filename.endsWith('.ts') ? 'src' : 'lib'}/index`;
|
||||
|
||||
api.registerPlugin(
|
||||
'@nocobase/preset-nocobase',
|
||||
require(`@nocobase/preset-nocobase/${file}`).default,
|
||||
);
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
process.argv.push('start', '--port', '2000');
|
||||
|
@ -461,36 +461,10 @@ type HookType =
|
||||
* 关闭数据库连接
|
||||
*/
|
||||
public async close() {
|
||||
this.removeAllListeners();
|
||||
return this.sequelize.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 hook
|
||||
*
|
||||
* @param hookType
|
||||
* @param fn
|
||||
*/
|
||||
public addHook(hookType: HookType | string, fn: Function) {
|
||||
const hooks = this.hooks[hookType] || [];
|
||||
hooks.push(fn);
|
||||
this.hooks[hookType] = hooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行 hook
|
||||
*
|
||||
* @param hookType
|
||||
* @param args
|
||||
*/
|
||||
public async runHooks(hookType: HookType | string, ...args) {
|
||||
const hooks = this.hooks[hookType] || [];
|
||||
for (const hook of hooks) {
|
||||
if (typeof hook === 'function') {
|
||||
await hook(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getFieldByPath(fieldPath: string) {
|
||||
const [tableName, fieldName] = fieldPath.split('.');
|
||||
return this.getTable(tableName).getField(fieldName);
|
||||
|
@ -221,7 +221,8 @@ export type ColumnOptions = AbstractFieldOptions
|
||||
| JsonOptions
|
||||
| VirtualOptions
|
||||
| FormulaOptions
|
||||
| ReferenceOptions;
|
||||
| ReferenceOptions
|
||||
| SortOptions;
|
||||
|
||||
export type ElementOptions = BooleanOptions
|
||||
| IntegerOptions
|
||||
@ -236,7 +237,8 @@ export type ElementOptions = BooleanOptions
|
||||
| DateOnlyOptions
|
||||
| ArrayOptions
|
||||
| JsonOptions
|
||||
| VirtualOptions;
|
||||
| VirtualOptions
|
||||
| SortOptions;
|
||||
|
||||
export type RelationOptions = HasOneOptions | HasManyOptions | BelongsToOptions | BelongsToManyOptions;
|
||||
|
||||
|
@ -530,7 +530,7 @@ export abstract class Model extends SequelizeModel {
|
||||
});
|
||||
}
|
||||
|
||||
await this.database.runHooks('afterUpdateAssociations', this, {
|
||||
await this.database.emitAsync('afterUpdateAssociations', this, {
|
||||
...options,
|
||||
transaction,
|
||||
});
|
||||
|
@ -139,7 +139,7 @@ export class Table {
|
||||
|
||||
constructor(options: TableOptions, context: TabelContext) {
|
||||
const { database } = context;
|
||||
database.runHooks('beforeTableInit', options);
|
||||
database.emit('beforeTableInit', options);
|
||||
const {
|
||||
model,
|
||||
fields = [],
|
||||
@ -157,7 +157,7 @@ export class Table {
|
||||
// this.modelInit('modelOnly');
|
||||
this.setFields(fields);
|
||||
this.initSortable();
|
||||
database.runHooks('afterTableInit', this);
|
||||
database.emit('afterTableInit', this);
|
||||
}
|
||||
|
||||
public initSortable() {
|
||||
@ -312,7 +312,7 @@ export class Table {
|
||||
* @param reinitialize
|
||||
*/
|
||||
public addField(options: FieldOptions, reinitialize: Reinitialize = true) {
|
||||
this.database.runHooks('beforeAddField', options, this);
|
||||
this.database.emit('beforeAddField', options, this);
|
||||
const { name, index } = options;
|
||||
const field = buildField(options, {
|
||||
sourceTable: this,
|
||||
@ -348,7 +348,7 @@ export class Table {
|
||||
this.modelAttributes[name] = field.getAttributeOptions();
|
||||
}
|
||||
this.modelInit(reinitialize);
|
||||
this.database.runHooks('afterAddField', field, this);
|
||||
this.database.emit('afterAddField', field, this);
|
||||
return field;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/actions": "^0.4.0-alpha.7",
|
||||
"@nocobase/server": "^0.4.0-alpha.7"
|
||||
"@nocobase/test": "^0.4.0-alpha.7"
|
||||
},
|
||||
"gitHead": "f0b335ac30f29f25c95d7d137655fa64d8d67f1e"
|
||||
}
|
||||
|
@ -1,15 +1,22 @@
|
||||
import Database from '@nocobase/database';
|
||||
import Application from '@nocobase/server';
|
||||
import { getApp, getAPI, getAgent } from '.';
|
||||
import { registerActions } from '@nocobase/actions';
|
||||
import { mockServer, MockServer } from '@nocobase/test';
|
||||
import logPlugin from '../server';
|
||||
|
||||
describe('hook', () => {
|
||||
let app: Application;
|
||||
let api: MockServer;
|
||||
let db: Database;
|
||||
let api;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await getApp();
|
||||
db = app.database;
|
||||
api = mockServer();
|
||||
api.registerPlugin({
|
||||
collections: require('@nocobase/plugin-collections/src/server').default,
|
||||
users: require('@nocobase/plugin-users/src/server').default,
|
||||
logs: logPlugin,
|
||||
});
|
||||
registerActions(api);
|
||||
await api.loadPlugins();
|
||||
db = api.database;
|
||||
db.table({
|
||||
name: 'posts',
|
||||
logging: true,
|
||||
@ -28,14 +35,11 @@ describe('hook', () => {
|
||||
await db.sync();
|
||||
const User = db.getModel('users');
|
||||
const user = await User.create({ nickname: 'a', token: 'token1' });
|
||||
console.log('beforeEach', user);
|
||||
const userAgent = getAgent(app);
|
||||
userAgent.set('Authorization', `Bearer ${user.token}`);
|
||||
api = getAPI(userAgent);
|
||||
api.agent().set('Authorization', `Bearer ${user.token}`);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
await api.destroy();
|
||||
});
|
||||
|
||||
it('database', async () => {
|
||||
|
@ -1,122 +0,0 @@
|
||||
import path from 'path';
|
||||
import qs from 'qs';
|
||||
import supertest from 'supertest';
|
||||
import bodyParser from 'koa-bodyparser';
|
||||
import { Dialect } from 'sequelize';
|
||||
import Database from '@nocobase/database';
|
||||
import { actions, middlewares } from '@nocobase/actions';
|
||||
import { Application } from '@nocobase/server';
|
||||
import middleware from '@nocobase/server/src/middleware';
|
||||
import plugin from '../server';
|
||||
|
||||
function getTestKey() {
|
||||
const { id } = require.main;
|
||||
const key = id
|
||||
.replace(`${process.env.PWD}/packages`, '')
|
||||
.replace(/src\/__tests__/g, '')
|
||||
.replace('.test.ts', '')
|
||||
.replace(/[^\w]/g, '_')
|
||||
.replace(/_+/g, '_');
|
||||
return key
|
||||
}
|
||||
|
||||
const config = {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: Number.parseInt(process.env.DB_PORT, 10),
|
||||
dialect: process.env.DB_DIALECT as Dialect,
|
||||
logging: process.env.DB_LOG_SQL === 'on',
|
||||
sync: {
|
||||
force: true,
|
||||
alter: {
|
||||
drop: true,
|
||||
},
|
||||
},
|
||||
hooks: {
|
||||
beforeDefine(columns, model) {
|
||||
model.tableName = `${getTestKey()}_${model.tableName || model.name.plural}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export function getDatabase() {
|
||||
return new Database(config);
|
||||
};
|
||||
|
||||
export async function getApp(): Promise<Application> {
|
||||
const app = new Application({
|
||||
database: config,
|
||||
resourcer: {
|
||||
prefix: '/api',
|
||||
},
|
||||
});
|
||||
app.registerPlugin({
|
||||
collections: path.resolve(__dirname, '../../../plugin-collections'),
|
||||
users: path.resolve(__dirname, '../../../plugin-users'),
|
||||
logs: plugin
|
||||
});
|
||||
await app.loadPlugins();
|
||||
await app.database.sync();
|
||||
return app;
|
||||
}
|
||||
|
||||
interface ActionParams {
|
||||
resourceKey?: string | number;
|
||||
// resourceName?: string;
|
||||
// associatedName?: string;
|
||||
associatedKey?: string | number;
|
||||
fields?: any;
|
||||
filter?: any;
|
||||
values?: any;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface Handler {
|
||||
get: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
list: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
create: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
update: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
destroy: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
[name: string]: (params?: ActionParams) => Promise<supertest.Response>;
|
||||
}
|
||||
|
||||
export interface Agent {
|
||||
resource: (name: string) => Handler;
|
||||
}
|
||||
|
||||
export function getAgent(app: Application) {
|
||||
return supertest.agent(app.callback());
|
||||
}
|
||||
|
||||
export function getAPI(agent) {
|
||||
return {
|
||||
resource(name: string): any {
|
||||
return new Proxy({}, {
|
||||
get(target, method: string, receiver) {
|
||||
return (params: ActionParams = {}) => {
|
||||
const { associatedKey, resourceKey, values = {}, filePath, ...restParams } = params;
|
||||
let url = `/api/${name}`;
|
||||
if (associatedKey) {
|
||||
url = `/api/${name.split('.').join(`/${associatedKey}/`)}`;
|
||||
}
|
||||
url += `:${method as string}`;
|
||||
if (resourceKey) {
|
||||
url += `/${resourceKey}`;
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case 'list':
|
||||
case 'get':
|
||||
return agent.get(`${url}?${qs.stringify(restParams)}`);
|
||||
|
||||
default:
|
||||
return agent.post(`${url}?${qs.stringify(restParams)}`).send(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import { TableOptions } from "@nocobase/database";
|
||||
|
||||
export default {
|
||||
name: 'comments',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'content',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'post',
|
||||
},
|
||||
]
|
||||
} as TableOptions;
|
@ -1,22 +0,0 @@
|
||||
import { TableOptions } from "@nocobase/database";
|
||||
|
||||
export default {
|
||||
name: 'posts',
|
||||
// 目前默认就带了
|
||||
// createdBy: true,
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'status',
|
||||
defaultValue: 'draft',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'comments',
|
||||
}
|
||||
]
|
||||
} as TableOptions;
|
@ -12,18 +12,18 @@ export default {
|
||||
type: 'belongsTo',
|
||||
name: 'log',
|
||||
target: 'action_logs',
|
||||
foreignKey: 'log_id',
|
||||
foreignKey: 'action_log_id',
|
||||
},
|
||||
{
|
||||
type: 'jsonb',
|
||||
type: 'json',
|
||||
name: 'field',
|
||||
},
|
||||
{
|
||||
type: 'jsonb',
|
||||
type: 'json',
|
||||
name: 'before',
|
||||
},
|
||||
{
|
||||
type: 'jsonb',
|
||||
type: 'json',
|
||||
name: 'after',
|
||||
}
|
||||
],
|
||||
|
@ -18,12 +18,16 @@ export default {
|
||||
target: 'users',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'collection',
|
||||
target: 'collections',
|
||||
targetKey: 'name',
|
||||
constraints: false,
|
||||
type: 'string',
|
||||
name: 'collection_name',
|
||||
},
|
||||
// {
|
||||
// type: 'belongsTo',
|
||||
// name: 'collection',
|
||||
// target: 'collections',
|
||||
// targetKey: 'name',
|
||||
// constraints: false,
|
||||
// },
|
||||
{
|
||||
type: 'string',
|
||||
name: 'type',
|
||||
@ -36,7 +40,7 @@ export default {
|
||||
type: 'hasMany',
|
||||
name: 'changes',
|
||||
target: 'action_changes',
|
||||
foreignKey: 'log_id',
|
||||
foreignKey: 'action_log_id',
|
||||
}
|
||||
],
|
||||
} as TableOptions;
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { extend } from '@nocobase/database';
|
||||
|
||||
// TODO(bug): collections 表创建关联字段有问题
|
||||
export default extend({
|
||||
name: 'collections',
|
||||
logging: false
|
||||
});
|
@ -1,10 +1,7 @@
|
||||
import { Model, ModelCtor } from '@nocobase/database';
|
||||
import { actions, middlewares } from '@nocobase/actions';
|
||||
import { sort } from '@nocobase/actions/src/actions/common';
|
||||
import { cloneDeep, omit } from 'lodash';
|
||||
import { actions, Context, Next } from '@nocobase/actions';
|
||||
|
||||
export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||
await actions.common.create(ctx, async () => {});
|
||||
export const create = async (ctx: Context, next: Next) => {
|
||||
await actions.create(ctx, async () => {});
|
||||
const { associated } = ctx.action.params;
|
||||
await ctx.body.generateReverseField();
|
||||
await associated.migrate();
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { Model, ModelCtor } from '@nocobase/database';
|
||||
import { actions, middlewares } from '@nocobase/actions';
|
||||
import { sort } from '@nocobase/actions/src/actions/common';
|
||||
import { cloneDeep, omit } from 'lodash';
|
||||
import { actions, Context, Next } from '@nocobase/actions';
|
||||
|
||||
export const findAll = async (ctx: actions.Context, next: actions.Next) => {
|
||||
export const findAll = async (ctx: Context, next: Next) => {
|
||||
const Collection = ctx.db.getModel('collections');
|
||||
const collections = await Collection.findAll(Collection.parseApiJson({
|
||||
sort: 'sort',
|
||||
@ -16,7 +13,7 @@ export const findAll = async (ctx: actions.Context, next: actions.Next) => {
|
||||
await next();
|
||||
}
|
||||
|
||||
export const createOrUpdate = async (ctx: actions.Context, next: actions.Next) => {
|
||||
export const createOrUpdate = async (ctx: Context, next: Next) => {
|
||||
const { values } = ctx.action.params;
|
||||
const Collection = ctx.db.getModel('collections');
|
||||
let collection;
|
||||
@ -55,4 +52,5 @@ export const createOrUpdate = async (ctx: actions.Context, next: actions.Next) =
|
||||
throw error;
|
||||
}
|
||||
ctx.body = collection;
|
||||
await next();
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ export default async function (this: Application, options = {}) {
|
||||
database.import({
|
||||
directory: path.resolve(__dirname, 'collections'),
|
||||
});
|
||||
this.on('server.beforeStart', async () => {
|
||||
console.log('server.beforeStart');
|
||||
this.on('plugins.afterLoad', async () => {
|
||||
console.log('plugins.afterLoad');
|
||||
await database.getModel('collections').load();
|
||||
});
|
||||
const [Collection, Field] = database.getModels(['collections', 'fields']);
|
||||
|
@ -10,7 +10,6 @@ import _ from 'lodash';
|
||||
export interface ResourcerContext {
|
||||
resourcer?: Resourcer;
|
||||
action?: Action;
|
||||
params?: ParsedParams;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user