test: refactor test in database and add more (#17)
This commit is contained in:
parent
eb93f0734f
commit
85e42f95a5
@ -36,7 +36,7 @@ const connection = {
|
||||
},
|
||||
},
|
||||
},
|
||||
logging: false,
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
|
||||
},
|
||||
database: null,
|
||||
create() {
|
||||
|
@ -18,7 +18,8 @@ describe('list', () => {
|
||||
for (let index = 0; index < 2; index++) {
|
||||
items.push({
|
||||
title: `title${index}`,
|
||||
status: index % 2 ? 'published' : 'draft'
|
||||
status: index % 2 ? 'published' : 'draft',
|
||||
published_at: index % 2 ? new Date() : null
|
||||
});
|
||||
}
|
||||
await Post.bulkCreate(items);
|
||||
@ -58,6 +59,48 @@ describe('list', () => {
|
||||
expect(response.body.rows[0].title).toBe(drafts[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('null', () => {
|
||||
it('filter[published_at.is]', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const expected = await Post.findAll({
|
||||
where: {
|
||||
published_at: {
|
||||
[Op.is]: null
|
||||
}
|
||||
}
|
||||
});
|
||||
const response = await agent.get('/posts?filter[published_at.is]');
|
||||
expect(response.body.count).toBe(expected.length);
|
||||
});
|
||||
|
||||
it('filter[published_at.not]', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const expected = await Post.findAll({
|
||||
where: {
|
||||
published_at: {
|
||||
[Op.not]: null
|
||||
}
|
||||
}
|
||||
});
|
||||
const response = await agent.get('/posts?filter[published_at.not]');
|
||||
expect(response.body.count).toBe(expected.length);
|
||||
});
|
||||
|
||||
// TODO(bug): should use `user.is`
|
||||
it('filter[user_id.is]', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const expected = await Post.findAll({
|
||||
where: {
|
||||
user_id: {
|
||||
[Op.is]: null
|
||||
}
|
||||
}
|
||||
});
|
||||
const response = await agent.get('/posts?filter[user_id.is]');
|
||||
expect(response.body.count).toBe(expected.length);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('page', () => {
|
||||
|
@ -13,6 +13,10 @@ export default {
|
||||
name: 'status',
|
||||
defaultValue: 'publish',
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'published_at'
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
|
@ -37,10 +37,6 @@ export async function list(ctx: Context, next: Next) {
|
||||
context: ctx,
|
||||
});
|
||||
let data = {};
|
||||
if (page || perPage) {
|
||||
options.limit = 1*(perPage||20);
|
||||
options.offset = options.limit * (page > 0 ? page - 1 : 0);
|
||||
}
|
||||
if (associated && resourceField) {
|
||||
const AssociatedModel = ctx.db.getModel(associatedName);
|
||||
if (!(associated instanceof AssociatedModel)) {
|
||||
|
@ -1,7 +1,14 @@
|
||||
import Database from '../database';
|
||||
import { Dialect } from 'sequelize';
|
||||
|
||||
|
||||
function getTestKey() {
|
||||
const { id } = require.main;
|
||||
const key = id
|
||||
.replace(process.env.PWD, '')
|
||||
.replace('.test.ts', '')
|
||||
.replace(/[^\w]/g, '_');
|
||||
return key
|
||||
}
|
||||
|
||||
const config = {
|
||||
username: process.env.DB_USER,
|
||||
@ -21,5 +28,12 @@ const config = {
|
||||
};
|
||||
|
||||
export function getDatabase() {
|
||||
return new Database(config);
|
||||
return new Database({
|
||||
...config,
|
||||
hooks: {
|
||||
beforeDefine(columns, model) {
|
||||
model.tableName = `${getTestKey()}_${model.tableName || model.name.plural}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,15 +1,13 @@
|
||||
import Database from '..';
|
||||
import { getDatabase } from '.';
|
||||
import { Op, Sequelize } from 'sequelize';
|
||||
import Model, { ModelCtor } from '../model';
|
||||
import { BelongsToMany } from '../fields';
|
||||
import { Mode } from 'fs';
|
||||
import Database from '../..';
|
||||
import { getDatabase } from '..';
|
||||
import Model, { ModelCtor } from '../../model';
|
||||
|
||||
|
||||
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
db = getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@ -269,137 +267,7 @@ describe('actions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseApiJson', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeEach(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
tableName: 'bazs_model'
|
||||
});
|
||||
db.table({
|
||||
name: 'bays',
|
||||
tableName: 'bays_model'
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
tableName: 'bars_model',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'bay',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
tableName: 'foos_model',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fozs',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'coos',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'fozs',
|
||||
tableName: 'fozs_model',
|
||||
});
|
||||
db.table({
|
||||
name: 'coos',
|
||||
tableName: 'coos_model',
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
afterEach(() => db.close());
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
}
|
||||
});
|
||||
expect(data).toEqual({ where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'] });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'], where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1', 'bars.col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByApiJson', () => {
|
||||
describe('query', () => {
|
||||
it('q', async () => {
|
||||
db.getModel('tags').addScope('scopeName', (name, ctx) => {
|
||||
expect(ctx.scopeName).toBe(name);
|
||||
@ -477,17 +345,15 @@ describe('actions', () => {
|
||||
expect(row.get('title')).toBe('title112233');
|
||||
expect(row.user.get('name')).toBe('name112233');
|
||||
});
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
// console.log(count);
|
||||
|
||||
// expect(count).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('query', () => {
|
||||
it('to be explained', async () => {
|
||||
const [User, Post] = db.getModels(['users', 'posts']);
|
||||
const postData = [];
|
206
packages/database/src/__tests__/model/parseApiJson.test.ts
Normal file
206
packages/database/src/__tests__/model/parseApiJson.test.ts
Normal file
@ -0,0 +1,206 @@
|
||||
import { literal } from 'sequelize';
|
||||
import { getDatabase } from '..';
|
||||
import Database from '../../database';
|
||||
import Model, { ModelCtor } from '../../model';
|
||||
|
||||
|
||||
let db: Database;
|
||||
let Bar: ModelCtor<Model>;
|
||||
let Foo: ModelCtor<Model>;
|
||||
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
});
|
||||
db.table({
|
||||
name: 'bays',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'bay',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fozs',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'coos',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'fozs',
|
||||
});
|
||||
db.table({
|
||||
name: 'coos',
|
||||
});
|
||||
Bar = db.getModel('bars');
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
afterAll(() => db.close());
|
||||
|
||||
|
||||
|
||||
describe('parseApiJson', () => {
|
||||
describe('self table', () => {
|
||||
it('filter', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
}
|
||||
});
|
||||
expect(data).toEqual({ where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('fields', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'] });
|
||||
});
|
||||
|
||||
it('filter and fields', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'], where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('pagination: page and perPage', () => {
|
||||
expect(Foo.parseApiJson({
|
||||
page: 1,
|
||||
perPage: 10
|
||||
})).toEqual({
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
});
|
||||
});
|
||||
|
||||
it('pagination: only page', () => {
|
||||
expect(Foo.parseApiJson({
|
||||
page: 1
|
||||
})).toEqual({
|
||||
offset: 0,
|
||||
limit: 20,
|
||||
});
|
||||
});
|
||||
|
||||
it('sort: single self field', () => {
|
||||
expect(Foo.parseApiJson({
|
||||
sort: 'a'
|
||||
})).toEqual({
|
||||
order: [
|
||||
['a', 'ASC']
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
// TODO(bug): should not contain additional attributes
|
||||
it('sort: multiple self fields', () => {
|
||||
expect(Foo.parseApiJson({
|
||||
sort: 'a,-b'
|
||||
})).toEqual({
|
||||
order: [
|
||||
['a', 'ASC'],
|
||||
['b', 'DESC'],
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
// TODO(feature): order by association should be ok
|
||||
it.skip('sort: association field', () => {
|
||||
expect(Bar.parseApiJson({
|
||||
sort: '-foo.a'
|
||||
})).toEqual({
|
||||
order: [
|
||||
[{ model: Foo, as: 'foo' }, 'a', 'DESC'],
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('page + sort + fields', () => {
|
||||
expect(Foo.parseApiJson({
|
||||
fields: ['a', 'b'],
|
||||
page: 2,
|
||||
perPage: 10,
|
||||
sort: 'a'
|
||||
})).toEqual({
|
||||
attributes: ['a', 'b'],
|
||||
offset: 10,
|
||||
limit: 10,
|
||||
order: [
|
||||
['a', 'ASC']
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('associations', () => {
|
||||
it('filter on hasMany field', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('filter and fields to fetch hasMany field', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1', 'bars.col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -6,7 +6,7 @@ import { getDatabase } from './';
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
db = getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
@ -6,7 +6,7 @@ import Model from '../model';
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
db = getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@ -47,7 +47,8 @@ describe('tables', () => {
|
||||
name: 'foos',
|
||||
});
|
||||
expect(db.getModel('foos').name).toBe('foos');
|
||||
expect(db.getModel('foos').getTableName()).toBe('foos');
|
||||
// hooked by beforeDefine in index.ts
|
||||
expect(db.getModel('foos').getTableName()).toBe('_packages_database_src___tests___tables_foos');
|
||||
});
|
||||
|
||||
it('should be custom when tableName is defined', async () => {
|
||||
@ -56,7 +57,8 @@ describe('tables', () => {
|
||||
tableName: 'bar_v2'
|
||||
});
|
||||
expect(db.getModel('bar').name).toBe('bar');
|
||||
expect(db.getModel('bar').getTableName()).toBe('bar_v2');
|
||||
// hooked by beforeDefine in index.ts
|
||||
expect(db.getModel('bar').getTableName()).toBe('_packages_database_src___tests___tables_bar_v2');
|
||||
});
|
||||
|
||||
it('should be custom when timestamps is defined', async () => {
|
||||
|
@ -86,6 +86,14 @@ describe('utils.toWhere', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.lt', () => {
|
||||
expect(toWhere({
|
||||
'id.lt': 1
|
||||
})).toEqual({
|
||||
id: { [Op.lt]: 1 }
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.between', () => {
|
||||
expect(toWhere({
|
||||
@ -94,6 +102,14 @@ describe('utils.toWhere', () => {
|
||||
id: { [Op.between]: [1, 2] }
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.between date', () => {
|
||||
expect(toWhere({
|
||||
'id.between': ['2020-11-01T00:00:00.000Z', '2020-12-01T00:00:00.000Z']
|
||||
})).toEqual({
|
||||
id: { [Op.between]: ['2020-11-01T00:00:00.000Z', '2020-12-01T00:00:00.000Z'] }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('group by logical operator', () => {
|
||||
@ -149,6 +165,30 @@ describe('utils.toWhere', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('or in or (not fully parsed)', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { 'b.or': [3, 4] }],
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { b: { [Op.or]: [3, 4] } }],
|
||||
});
|
||||
});
|
||||
|
||||
it('or in or (parsed)', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { b: { or: [3, 4] } }],
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { b: { [Op.or]: [3, 4] } }],
|
||||
});
|
||||
});
|
||||
|
||||
it('or in or in or', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { or: { b: 3, c: { or: [5, 6] } } }],
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { [Op.or]: { b: 3, c: { [Op.or]: [5, 6] } } }],
|
||||
});
|
||||
});
|
||||
|
||||
it('or in and', () => {
|
||||
expect(toWhere({
|
||||
and: [{ a: 1 }, { 'b.or': [3, 4] }],
|
||||
@ -165,8 +205,16 @@ describe('utils.toWhere', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('logical and other comparation', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { b: { gt: 2 } }],
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { b: { [Op.gt]: 2 } }],
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: bug
|
||||
it.skip('field as or', () => {
|
||||
it.skip('field as "or"', () => {
|
||||
expect(toWhere({
|
||||
or: 1,
|
||||
})).toEqual({
|
||||
@ -175,7 +223,7 @@ describe('utils.toWhere', () => {
|
||||
});
|
||||
|
||||
// TODO: bug
|
||||
it.skip('or for field as or', () => {
|
||||
it.skip('or for field as "or"', () => {
|
||||
expect(toWhere({
|
||||
'or.or': [1, 2],
|
||||
})).toEqual({
|
||||
@ -186,60 +234,59 @@ describe('utils.toWhere', () => {
|
||||
|
||||
describe('association', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
name: 'users',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
name: 'user',
|
||||
}
|
||||
]
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
name: 'categories',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
name: 'posts',
|
||||
}
|
||||
],
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
afterAll(() => db.close());
|
||||
|
||||
const toWhereExpect = (options, logging = false) => {
|
||||
const toWhereExpect = (options: any) => {
|
||||
const Category = db.getModel('categories');
|
||||
const where = toWhere(options, {
|
||||
associations: Foo.associations,
|
||||
associations: Category.associations,
|
||||
});
|
||||
return expect(where);
|
||||
}
|
||||
|
||||
it('association', () => {
|
||||
it('with included association where', () => {
|
||||
toWhereExpect({
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
posts: {
|
||||
name: {
|
||||
ilike: 'aa',
|
||||
},
|
||||
col2: {
|
||||
lt: 2,
|
||||
},
|
||||
baz: {
|
||||
user: {
|
||||
col1: 12,
|
||||
},
|
||||
},
|
||||
'bars.col3.ilike': 'aa',
|
||||
'posts.col3.ilike': 'aa',
|
||||
}).toEqual({
|
||||
col1: 'val1',
|
||||
$__include: {
|
||||
bars: {
|
||||
posts: {
|
||||
name: {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
@ -250,7 +297,7 @@ describe('utils.toWhere', () => {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
$__include: {
|
||||
baz: {
|
||||
user: {
|
||||
col1: 12
|
||||
},
|
||||
},
|
||||
@ -258,5 +305,19 @@ describe('utils.toWhere', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: 是否要考虑跨关联表的逻辑分组这种情况
|
||||
it.skip('logical across association', () => {
|
||||
toWhereExpect({
|
||||
or: {
|
||||
status: 1,
|
||||
posts: {
|
||||
status: 1
|
||||
}
|
||||
}
|
||||
}).toEqual({
|
||||
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -82,6 +82,12 @@ export interface ApiJsonOptions {
|
||||
*/
|
||||
sort?: any;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
|
||||
context?: any;
|
||||
|
||||
[key: string]: any;
|
||||
@ -226,13 +232,17 @@ export abstract class Model extends SequelizeModel {
|
||||
}
|
||||
|
||||
static parseApiJson(options: ApiJsonOptions) {
|
||||
const { fields, filter, sort, context, ...restOptions } = options;
|
||||
const { fields, filter, sort, context, page, perPage } = options;
|
||||
const data = toInclude({fields, filter, sort}, {
|
||||
Model: this,
|
||||
associations: this.associations,
|
||||
dialect: this.sequelize.getDialect(),
|
||||
ctx: context,
|
||||
});
|
||||
if (page || perPage) {
|
||||
data.limit = perPage || 20;
|
||||
data.offset = data.limit * (page > 0 ? page - 1 : 0);
|
||||
}
|
||||
if (data.attributes && data.attributes.length === 0) {
|
||||
delete data.attributes;
|
||||
}
|
||||
|
@ -111,11 +111,12 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
||||
if (Array.isArray(key)) {
|
||||
order.push(key);
|
||||
} else {
|
||||
const direction = key.indexOf('-') === 0 ? 'DESC' : 'ASC';
|
||||
const direction = key[0] === '-' ? 'DESC' : 'ASC';
|
||||
const field = key.replace(/^-/, '');
|
||||
items.appends.push(field);
|
||||
// TODO:暂时只支持 postgresql
|
||||
order.push([Sequelize.literal(dialect === 'mysql' ? `\`${field}\`` : `"${field}"`), direction]);
|
||||
// TODO(verify): 理论上只是排序并不一定要输出相关字段
|
||||
// items.appends.push(field);
|
||||
// TODO: 暂时只支持主表排序,后续需要按`.`分隔符拆分 field 为关联排序
|
||||
order.push([field, direction]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -257,7 +257,10 @@ export class Resourcer {
|
||||
ctx.action = this.getAction(nameRule(params), params.actionName).clone();
|
||||
ctx.action.setContext(ctx);
|
||||
// 自带 query 处理的不太给力,需要用 qs 转一下
|
||||
const query = qs.parse(qs.stringify(ctx.query));
|
||||
const query = qs.parse(ctx.request.querystring, {
|
||||
// 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型
|
||||
strictNullHandling: true
|
||||
});
|
||||
// filter 支持 json string
|
||||
if (typeof query.filter === 'string') {
|
||||
query.filter = JSON.parse(query.filter);
|
||||
|
@ -87,7 +87,10 @@ export function middleware(options: MiddlewareOptions = {}) {
|
||||
ctx.action = resourcer.getAction(resourceName, params.actionName).clone();
|
||||
ctx.action.setContext(ctx);
|
||||
// 自带 query 处理的不太给力,需要用 qs 转一下
|
||||
const query = qs.parse(qs.stringify(ctx.query));
|
||||
const query = qs.parse(ctx.request.querystring, {
|
||||
// 原始 query string 中如果一个键连等号“=”都没有可以被认为是 null 类型
|
||||
strictNullHandling: true
|
||||
});
|
||||
// filter 支持 json string
|
||||
if (typeof query.filter === 'string') {
|
||||
query.filter = JSON.parse(query.filter);
|
||||
|
Loading…
Reference in New Issue
Block a user