qoq
v0.0.55
Published
A TS-Only node framework
Downloads
1,655
Readme
QOQ
A restful node framework for real type checking, a new way for avoiding syntax mistake and saving life. It's based on popular koa2, almostly the total middlewares can be integrated into here.
🔥 no typescript, no coding.
Features
- web router
- console commander
- validator
- caching
- slot
- strong type-checking
Installation
yarn add qoq
Official Related
| Project | Version | Platform | Description | | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------ | --------------------------------- | | qoq-sequelize | | Web, Console | database ORM (mysql, sqlite, ...) | | qoq-redis | | Web, Console | redis command, cache extension | | qoq-compress | | Web | gzip, brotli | | qoq-morgan | | Web | logger | | qoq-cors | | Web | CORS | | qoq-ratelimit | | Web | request rate limiter | | qoq-jwt | | Web | validating json token | | qoq-etag | | Web | header: etag | | qoq-response-time | | Web | header: X-Response-Time | | qoq-helmet | | Web | security headers | | qoq-pretty-json | | Web | format JSON | | qoq-static | | Web | static file serve | | qoq-views | | Web | template rendering | | qoq-json-error | | Web | JSON error handler |
And more from koa community...
Demos
Usage
Create web app
// src/index.ts
import { WebApplication } from 'qoq';
const app = new WebApplication();
app.listen(3000, () => {
console.log('Server started!');
});
Create web slots (middleware)
// src/bootstrap/web.ts
import { WebSlotManager, Tree } from 'qoq';
import { Cors } from 'qoq-cors';
import { Redis } from 'qoq-redis';
export const webSlots = WebslotManager
.use(new Cors())
.use(new Redis())
.use((ctx, next) => {
console.log(ctx.request.ip);
return next();
});
export const advancedSlots = webSlots.use(...).use(...);
// the trunk will always run through
// until slot or router interrput it ( by skip execute next() ).
Tree.trunk(advancedSlots);
Create web router
// src/routers/index.ts
import { WebRouter, validator } from 'qoq';
import { webSlots } from '../bootstrap/web';
export const router = new WebRouter({
prefix: '/',
// slots behind webSlots will be convert to router group slots
slots: webSlots.use(new CustomSlot()).use(...),
});
router
.get('/user/:id')
.params({
id: validator.number,
})
.action(async (ctx, payload) => {
const userId = payload.params.id; // TS type annotation: number
const user = await ctx.redis.get(`user-${userId}`);
!user && ctx.throw(400, 'user not found');
ctx.body = user;
});
router
.get('/users')
.query({
// page is required, otherwise a 400 bad-request error will be thrown.
page: validator.number,
// pageSize is optional and will set to 10 when data is undefined/null.
pageSize: validator.number.default(10),
})
.action(async (ctx, payload) => {
// TS type annotation: { page: number; pageSize: number }
const { page, pageSize } = payload.query;
const users = await User.findAll({
offset: (page - 1) * pageSize,
limit: pageSize,
});
ctx.body = users;
});
router
.post('/user')
.body({
name: validator.string,
vip: validator.boolean.default(false),
homepage: validator.url.optional(),
})
.action(async (ctx, payload) => {
// TS type annotation of body: { name: string; vip: boolean; homepage?: string }
const user = await User.create(payload.body);
ctx.status = 201;
ctx.body = user;
});
Create console app
// src/index.ts
import { ConsoleApplication } from 'qoq';
const app = new ConsoleApplication();
app.execute().then(() => {
// Optional invoke here.
process.exit(0);
});
Create console router
// src/commands/index.ts
import { ConsoleRouter, validator } from 'qoq';
import { webSlots } from '../bootstrap/web';
export const router = new ConsoleRouter({
prefix: '/',
slots: consoleSlots
// as router group slots
.use(new CustomSlot()),
});
router
.command('my:schedule')
.options({
dateFrom: validator.string.optional(),
dateTo: validator.string.optional(),
})
.alias({
f: 'dateFrom',
t: 'dateTo',
})
.action(async (ctx, payload) => {
// TS type annotation: { dateFrom?: string; dateTo?: string }
const { dateFrom, dateTo } = payload.options;
// ...your business
console.log('Done!');
});
You can execute this command like this:
npx qoq my:schedule
# or
npx qoq my:schedule --dateFrom '..' --dateTo '..'
# or
npx qoq my:schedule -f '..' -t '..'
For testing, feel free to execute command as follows:
test ('can do something', async () => {
const app = new ConsoleApplication();
const ctx = await app.execute('my:schedule', '-f', '..', '-t', '..');
expect(...);
});
Cli
npx qoq -h
# or
yarn qoq -h
# or
node ./src/console.js -h
# or
ts-node ./src/console.ts -h