Skip to content

Commit

Permalink
Change alter to defer
Browse files Browse the repository at this point in the history
  • Loading branch information
aquapi committed May 22, 2024
1 parent 7bd63dc commit 4aa9bad
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 39 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bit-js/byte",
"version": "1.3.5",
"version": "1.3.6",
"module": "index.js",
"devDependencies": {
"@types/bun": "latest",
Expand Down
22 changes: 12 additions & 10 deletions src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { ProtoSchema, RequestMethod } from '../utils/methods';

import { Route, type BaseRoute, type RoutesRecord } from './route';
import type { InferValidatorRecord, ValidatorRecord } from './types/validator';
import { Context, type AlterFn, type BaseHandler, type Fn } from './types/handler';
import { Context, type BaseHandler, type DeferFn, type Fn } from './types/handler';

import { bit } from '../client';
import { emptyList } from '../../utils/defaultOptions';
Expand Down Expand Up @@ -46,7 +46,7 @@ export abstract class Plugin {
*/
export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
readonly actions: Fn[] = [];
readonly alters: AlterFn[] = [];
readonly defers: DeferFn[] = [];

/**
* Run before validation
Expand All @@ -59,8 +59,8 @@ export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
/**
* Run after response handler
*/
alter(...fns: AlterFn[]) {
this.alters.push(...fns);
defer(...fns: DeferFn[]) {
this.defers.push(...fns);
return this;
}

Expand All @@ -82,10 +82,10 @@ export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
/**
* Register sub-routes
*/
route(base: string, { routes, actions, alters }: BaseByte) {
route(base: string, { routes, actions, defers }: BaseByte) {
const currentRoutes = this.routes;
for (let i = 0, { length } = routes; i < length; ++i)
currentRoutes.push(routes[i].clone(base, actions, alters));
currentRoutes.push(routes[i].clone(base, actions, defers));

return this;
}
Expand Down Expand Up @@ -123,7 +123,7 @@ export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
*/
handle(method: string, path: string, ...args: any[]) {
// Load necessary actions
const { actions, alters } = this;
const { actions, defers } = this;

// Push new route
this.routes.push(
Expand All @@ -133,14 +133,16 @@ export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
// Check for validator
null, args[0],
// Load the actions and alters
actions.length === 0 ? emptyList : [actions], alters
actions.length === 0 ? emptyList : [actions],
defers.length === 0 ? emptyList : [defers]
)
: new Route(
method, path,
// Check for validator
args[0], args[1],
// Load the actions and alters
actions.length === 0 ? emptyList : [actions], alters
actions.length === 0 ? emptyList : [actions],
defers.length === 0 ? emptyList : [defers]
)
);

Expand All @@ -164,7 +166,7 @@ export class Byte<Rec extends RoutesRecord = []> implements ProtoSchema {
/**
* Create an alter handler
*/
static alter<const T extends AlterFn>(fn: T) {
static defer<const T extends DeferFn>(fn: T) {
return fn;
}

Expand Down
47 changes: 26 additions & 21 deletions src/core/server/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { BaseRouter } from '@bit-js/blitz';

import type { AlterFn, Fn } from './types/handler';
import type { DeferFn, Fn } from './types/handler';
import type { ValidatorRecord } from './types/validator';

import { isAsync, passChecks } from './utils/macro';
Expand All @@ -23,13 +23,13 @@ export class Route<
readonly validator: Validator,
readonly handler: Handler,
readonly actions: Fn[][],
readonly alters: AlterFn[]
readonly defers: DeferFn[][]
) { }

/**
* Clone the route with a new base path
*/
clone(base: string, otherAppActions: Fn[], otherAppAlters: AlterFn[]) {
clone(base: string, otherAppActions: Fn[], otherAppDefers: DeferFn[]) {
const { path } = this;

return new Route(
Expand All @@ -39,8 +39,8 @@ export class Route<
// Copy other props
this.validator, this.handler,
// Push other stuff
[otherAppActions, ...this.actions],
[...this.alters, ...otherAppAlters]
otherAppActions.length === 0 ? this.actions : [otherAppActions, ...this.actions],
otherAppDefers.length === 0 ? this.defers : [...this.defers, otherAppDefers]
);
}

Expand All @@ -59,14 +59,14 @@ export class Route<
*
*/
compile() {
const { handler, validator, actions, alters } = this;
const { handler, validator, actions, defers } = this;

// Conditions
const noActions = actions.length === 0;
const noValidator = validator === null;
const noAlters = alters.length === 0;
const noDefers = defers.length === 0;

if (noValidator && noActions && noAlters) return handler;
if (noValidator && noActions && noDefers) return handler;

const keys = [];
const statements = [];
Expand Down Expand Up @@ -146,30 +146,35 @@ export class Route<
noContext = noContext && handlerNoContext;

// Check for alters
if (noAlters)
if (noDefers)
// Save some milliseconds if the function is async
statements.push(`return ${isAsync(handler) && hasAsync ? 'await ' : ''}$(${handlerNoContext ? '' : 'c'});`);
else {
const fnAsync = isAsync(handler);
hasAsync = hasAsync || fnAsync;

statements.push(`const r=${fnAsync ? 'await ' : ''}$(${handlerNoContext ? '' : 'c'})`);
// Hold a ref to the context
statements.push(`const r=c.res=${fnAsync ? 'await ' : ''}$(${handlerNoContext ? '' : 'c'})`);

for (let i = 0, { length } = alters; i < length; ++i) {
const fn = alters[i];
const fnKey = `f${idx}`;
for (let i = 0, { length } = defers; i < length; ++i) {
const list = defers[i];

keys.push(fnKey);
values.push(fn);
for (let i = list.length - 1; i > -1; --i) {
const fn = list[i];
const fnKey = `f${idx}`;

const fnAsync = isAsync(fn);
hasAsync = hasAsync || fnAsync;
keys.push(fnKey);
values.push(fn);

const fnNoContext = fn.length < 2;
noContext = noContext && fnNoContext;
const fnAsync = isAsync(fn);
hasAsync = hasAsync || fnAsync;

statements.push(`${fnAsync ? 'await ' : ''}${fnKey}(${fn.length === 0 ? '' : noContext ? 'r' : 'r,c'})`);
++idx;
const fnNoContext = fn.length === 0;
noContext = noContext && fnNoContext;

statements.push(`${fnAsync ? 'await ' : ''}${fnKey}(${noContext ? '' : 'c'})`);
++idx;
}
}

statements.push('return r;');
Expand Down
2 changes: 1 addition & 1 deletion src/core/server/types/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ export type BaseContext = Context<any, any>;
export type BaseHandler<Path extends string, State = undefined> = (c: Context<Params<Path>, State>) => any;

export type Fn<R = any> = (c: BaseContext) => R;
export type AlterFn = (res: Response, c: BaseContext) => any;
export type DeferFn = (c: BaseContext & { res: Response }) => any;
6 changes: 3 additions & 3 deletions tests/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ export const apiWithCsrf = new Byte()
.get('/', send.body('Hi'));

// Alters
export const apiWithAlters = new Byte()
export const apiWithDefers = new Byte()
.use((ctx) => console.time(ctx.path))
.alter((res, ctx) => {
.defer((ctx) => {
// You should change the response here
console.log(res.ok);
console.log(ctx.res.ok);
console.timeEnd(ctx.path);
})
.get('/', send.body('Hi'));
6 changes: 3 additions & 3 deletions tests/bun/alters.spec.ts → tests/bun/defers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { test, expect, spyOn } from 'bun:test';
import { apiWithAlters } from '@app';
import { apiWithDefers } from '@app';

const client = apiWithAlters.client();
const client = apiWithDefers.client();

test('Alters', async () => {
const timeSpy = spyOn(console, 'timeEnd')
const timeSpy = spyOn(console, 'timeEnd');

const res = await client.get('/');
expect(await res.text()).toBe('Hi');
Expand Down

0 comments on commit 4aa9bad

Please sign in to comment.