Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@compas/server

Package Overview
Dependencies
Maintainers
1
Versions
196
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@compas/server - npm Package Compare versions

Comparing version 0.0.157 to 0.0.158

index.d.ts.map

1326

index.d.ts

@@ -1,1317 +0,9 @@

// Original types from @types/koa & @types/koa-compose
//
// This project is licensed under the MIT license.
// Copyrights are respective of each contributor listed at the beginning of each definition
// file.
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Type definitions for koa-compose 3.2
// Project: https://github.com/koajs/compose
// Definitions by: jKey Lu <https://github.com/jkeylu>
// Anton Astashov <https://github.com/astashov>
// TypeScript Version: 2.3
//
// Type definitions for Koa 2.11.0
// Project: http://koajs.com
// Definitions by: DavidCai1993 <https://github.com/DavidCai1993>
// jKey Lu <https://github.com/jkeylu>
// Brice Bernard <https://github.com/brikou>
// harryparkdotio <https://github.com/harryparkdotio>
// Wooram Jun <https://github.com/chatoo2412>
//
// Type definitions for koa-session 5.10
// Project: https://github.com/koajs/session
// Definitions by: Yu Hsin Lu <https://github.com/kerol2r20>
// Tomek Łaziuk <https://github.com/tlaziuk>
// Hiroshi Ioka <https://github.com/hirochachacha>
import { InsightEvent, Logger } from "@compas/stdlib";
import { StoreFile } from "@compas/store";
import { AxiosInstance } from "axios";
import { EventEmitter } from "events";
import { Files } from "formidable";
import { IncomingMessage, Server, ServerResponse } from "http";
import { ListenOptions, Socket } from "net";
import * as url from "url";
import ReadableStream = NodeJS.ReadableStream;
/**
* @private
*/
interface ContextDelegatedRequest {
/**
* Return request header.
*/
header: any;
/**
* Return request header, alias as request.header
*/
headers: any;
/**
* Get/Set request URL.
*/
url: string;
/**
* Get origin of URL.
*/
origin: string;
/**
* Get full request URL.
*/
href: string;
/**
* Get/Set request method.
*/
method: string;
/**
* Get request pathname.
* Set pathname, retaining the query-string when present.
*/
path: string;
/**
* Get parsed query-string.
* Set query-string as an object.
*/
query: any;
/**
* Get/Set query string.
*/
querystring: string;
/**
* Get the search string. Same as the querystring
* except it includes the leading ?.
*
* Set the search string. Same as
* response.querystring= but included for ubiquity.
*/
search: string;
/**
* Parse the "Host" header field host
* and support X-Forwarded-Host when a
* proxy is enabled.
*/
host: string;
/**
* Parse the "Host" header field hostname
* and support X-Forwarded-Host when a
* proxy is enabled.
*/
hostname: string;
/**
* Get WHATWG parsed URL object.
*/
URL: url.URL;
/**
* Check if the request is fresh, aka
* Last-Modified and/or the ETag
* still match.
*/
fresh: boolean;
/**
* Check if the request is stale, aka
* "Last-Modified" and / or the "ETag" for the
* resource has changed.
*/
stale: boolean;
/**
* Check if the request is idempotent.
*/
idempotent: boolean;
/**
* Return the request socket.
*/
socket: Socket;
/**
* Return the protocol string "http" or "https"
* when requested with TLS. When the proxy setting
* is enabled the "X-Forwarded-Proto" header
* field will be trusted. If you're running behind
* a reverse proxy that supplies https for you this
* may be enabled.
*/
protocol: string;
/**
* Short-hand for:
*
* this.protocol == 'https'
*/
secure: boolean;
/**
* Request remote address. Supports X-Forwarded-For when app.proxy is true.
*/
ip: string;
/**
* When `app.proxy` is `true`, parse
* the "X-Forwarded-For" ip address list.
*
* For example if the value were "client, proxy1, proxy2"
* you would receive the array `["client", "proxy1", "proxy2"]`
* where "proxy2" is the furthest down-stream.
*/
ips: string[];
/**
* Return subdomains as an array.
*
* Subdomains are the dot-separated parts of the host before the main domain
* of the app. By default, the domain of the app is assumed to be the last two
* parts of the host. This can be changed by setting `app.subdomainOffset`.
*
* For example, if the domain is "tobi.ferrets.example.com":
* If `app.subdomainOffset` is not set, this.subdomains is
* `["ferrets", "tobi"]`.
* If `app.subdomainOffset` is 3, this.subdomains is `["tobi"]`.
*/
subdomains: string[];
/**
* Check if the given `type(s)` is acceptable, returning
* the best match when true, otherwise `undefined`, in which
* case you should respond with 406 "Not Acceptable".
*
* The `type` value may be a single mime type string
* such as "application/json", the extension name
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
* or array is given the _best_ match, if any is returned.
*
* Examples:
*
* // Accept: text/html
* this.accepts('html');
* // => "html"
*
* // Accept: text/*, application/json
* this.accepts('html');
* // => "html"
* this.accepts('text/html');
* // => "text/html"
* this.accepts('json', 'text');
* // => "json"
* this.accepts('application/json');
* // => "application/json"
*
* // Accept: text/*, application/json
* this.accepts('image/png');
* this.accepts('png');
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* this.accepts(['html', 'json']);
* this.accepts('html', 'json');
* // => "json"
*/
accepts(): string[] | boolean;
accepts(...types: string[]): string | boolean;
accepts(types: string[]): string | boolean;
/**
* Return accepted encodings or best fit based on `encodings`.
*
* Given `Accept-Encoding: gzip, deflate`
* an array sorted by quality is returned:
*
* ['gzip', 'deflate']
*/
acceptsEncodings(): string[] | boolean;
acceptsEncodings(...encodings: string[]): string | boolean;
acceptsEncodings(encodings: string[]): string | boolean;
/**
* Return accepted charsets or best fit based on `charsets`.
*
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
* an array sorted by quality is returned:
*
* ['utf-8', 'utf-7', 'iso-8859-1']
*/
acceptsCharsets(): string[] | boolean;
acceptsCharsets(...charsets: string[]): string | boolean;
acceptsCharsets(charsets: string[]): string | boolean;
/**
* Return accepted languages or best fit based on `langs`.
*
* Given `Accept-Language: en;q=0.8, es, pt`
* an array sorted by quality is returned:
*
* ['es', 'pt', 'en']
*/
acceptsLanguages(): string[] | boolean;
acceptsLanguages(...langs: string[]): string | boolean;
acceptsLanguages(langs: string[]): string | boolean;
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains any of the give mime `type`s.
* If there is no request body, `null` is returned.
* If there is no content type, `false` is returned.
* Otherwise, it returns the first `type` that matches.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* this.is('html'); // => 'html'
* this.is('text/html'); // => 'text/html'
* this.is('text/*', 'application/json'); // => 'text/html'
*
* // When Content-Type is application/json
* this.is('json', 'urlencoded'); // => 'json'
* this.is('application/json'); // => 'application/json'
* this.is('html', 'application/*'); // => 'application/json'
*
* this.is('html'); // => false
*/
// is(): string | boolean;
is(...types: string[]): string | boolean;
is(types: string[]): string | boolean;
/**
* Return request header. If the header is not set, will return an empty
* string.
*
* The `Referrer` header field is special-cased, both `Referrer` and
* `Referer` are interchangeable.
*
* Examples:
*
* this.get('Content-Type');
* // => "text/plain"
*
* this.get('content-type');
* // => "text/plain"
*
* this.get('Something');
* // => ''
*/
get(field: string): string;
}
/**
* @private
*/
interface ContextDelegatedResponse {
/**
* Get/Set response status code.
*/
status: number;
/**
* Get response status message
*/
message: string;
/**
* Get/Set response body.
*/
body: unknown;
/**
* Return parsed response Content-Length when present.
* Set Content-Length field to `n`.
*/
length: number;
/**
* Check if a header has been written to the socket.
*/
headerSent: boolean;
/**
* Vary on `field`.
*/
vary(field: string): void;
/**
* Perform a 302 redirect to `url`.
*
* The string "back" is special-cased
* to provide Referrer support, when Referrer
* is not present `alt` or "/" is used.
*
* Examples:
*
* this.redirect('back');
* this.redirect('back', '/index.html');
* this.redirect('/login');
* this.redirect('http://google.com');
*/
redirect(url: string, alt?: string): void;
/**
* Return the response mime type void of
* parameters such as "charset".
*
* Set Content-Type response header with `type` through `mime.lookup()`
* when it does not contain a charset.
*
* Examples:
*
* this.type = '.html';
* this.type = 'html';
* this.type = 'json';
* this.type = 'application/json';
* this.type = 'png';
*/
type: string;
/**
* Get the Last-Modified date in Date form, if it exists.
* Set the Last-Modified date using a string or a Date.
*
* this.response.lastModified = new Date();
* this.response.lastModified = '2013-09-13';
*/
lastModified: Date;
/**
* Get/Set the ETag of a response.
* This will normalize the quotes if necessary.
*
* this.response.etag = 'md5hashsum';
* this.response.etag = '"md5hashsum"';
* this.response.etag = 'W/"123456789"';
*
* @param {string} etag
* @api public
*/
etag: string;
/**
* Set header `field` to `val`, or pass
* an object of header fields.
*
* Examples:
*
* this.set('Foo', ['bar', 'baz']);
* this.set('Accept', 'application/json');
* this.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*/
set(field: { [key: string]: string }): void;
set(field: string, val: string | string[]): void;
/**
* Append additional header `field` with value `val`.
*
* Examples:
*
* ```
* this.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
* this.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
* this.append('Warning', '199 Miscellaneous warning');
* ```
*/
append(field: string, val: string | string[]): void;
/**
* Remove header `field`.
*/
remove(field: string): void;
/**
* Checks if the request is writable.
* Tests for the existence of the socket
* as node sometimes does not set it.
*/
writable: boolean;
/**
* Flush any set headers, and begin the body
*/
flushHeaders(): void;
}
export class Application<
StateT = DefaultState,
CustomT = DefaultContext,
> extends EventEmitter {
proxy: boolean;
proxyIpHeader: string;
maxIpsCount: number;
middleware: Middleware<StateT, CustomT>[];
subdomainOffset: number;
env: string;
context: BaseContext & CustomT;
request: BaseRequest;
response: BaseResponse;
silent: boolean;
keys: string[];
constructor();
/**
* Shorthand for:
*
* http.createServer(app.callback()).listen(...)
*/
listen(
port?: number,
hostname?: string,
backlog?: number,
listeningListener?: () => void,
): Server;
listen(
port: number,
hostname?: string,
listeningListener?: () => void,
): Server;
listen(
port: number,
backlog?: number,
listeningListener?: () => void,
): Server;
listen(port: number, listeningListener?: () => void): Server;
listen(
path: string,
backlog?: number,
listeningListener?: () => void,
): Server;
listen(path: string, listeningListener?: () => void): Server;
listen(options: ListenOptions, listeningListener?: () => void): Server;
listen(handle: any, backlog?: number, listeningListener?: () => void): Server;
listen(handle: any, listeningListener?: () => void): Server;
/**
* Return JSON representation.
* We only bother showing settings.
*/
inspect(): any;
/**
* Return JSON representation.
* We only bother showing settings.
*/
toJSON(): any;
/**
* Use the given middleware `fn`.
*
* Old-style middleware will be converted.
*/
use<NewStateT = {}, NewCustomT = {}>(
middleware: Middleware<StateT & NewStateT, CustomT & NewCustomT>,
): Application<StateT & NewStateT, CustomT & NewCustomT>;
/**
* Return a request handler callback
* for node's native http/http2 server.
*/
callback(): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
/**
* Initialize a new context.
*
* @api private
*/
createContext<StateT = DefaultState>(
req: IncomingMessage,
res: ServerResponse,
): Context<StateT>;
/**
* Default error handler.
*
* @api private
*/
onerror(err: Error): void;
}
/**
* @private
*/
type DefaultStateExtends = any;
/**
* This interface can be augmented by users to add types to Koa's default state
*
* @private
*/
interface DefaultState extends DefaultStateExtends {}
/**
* @private
*/
type DefaultContextExtends = {};
/**
* This interface can be augmented by users to add types to Koa's default context
* @private
*/
interface DefaultContext extends DefaultContextExtends {
/**
* Custom properties.
*/
[key: string]: any;
}
type Middleware<StateT = DefaultState, CustomT = DefaultContext> = (
context: Context<StateT, CustomT>,
next: Next,
) => any;
/**
* @private
*/
interface BaseRequest extends ContextDelegatedRequest {
/**
* Get the charset when present or undefined.
*/
charset: string;
/**
* Return parsed Content-Length when present.
*/
length: number;
/**
* Return the request mime type void of
* parameters such as "charset".
*/
type: string;
body?: any;
files?: Files;
/**
* Inspect implementation.
*/
inspect(): any;
/**
* Return JSON representation.
*/
toJSON(): any;
}
/**
* @private
*/
interface BaseResponse extends ContextDelegatedResponse {
/**
* Return the request socket.
*/
socket: Socket;
/**
* Return response header.
*/
header: any;
/**
* Return response header, alias as response.header
*/
headers: any;
/**
* Check whether the response is one of the listed types.
* Pretty much the same as `this.request.is()`.
*/
is(...types: string[]): string;
is(types: string[]): string;
/**
* Return response header. If the header is not set, will return an empty
* string.
*
* The `Referrer` header field is special-cased, both `Referrer` and
* `Referer` are interchangeable.
*
* Examples:
*
* this.get('Content-Type');
* // => "text/plain"
*
* this.get('content-type');
* // => "text/plain"
*
* this.get('Something');
* // => ''
*/
get(field: string): string;
/**
* Inspect implementation.
*/
inspect(): any;
/**
* Return JSON representation.
*/
toJSON(): any;
}
/**
* @private
*/
interface BaseContext
extends ContextDelegatedRequest,
ContextDelegatedResponse {
inspect(): any;
toJSON(): any;
throw(message: string, code?: number, properties?: {}): never;
/**
* Default error handling.
*/
onerror(err: Error): void;
log: Logger;
event: InsightEvent;
session: Session | null;
}
/**
* @private
*/
interface Request extends BaseRequest {
app: Application;
req: IncomingMessage;
res: ServerResponse;
ctx: Context;
response: Response;
originalUrl: string;
ip: string;
accept: any;
}
/**
* @private
*/
interface Response extends BaseResponse {
app: Application;
req: IncomingMessage;
res: ServerResponse;
ctx: Context;
request: Request;
}
/**
* @private
*/
interface ExtendableContext extends BaseContext {
app: Application;
request: Request;
response: Response;
req: IncomingMessage;
res: ServerResponse;
originalUrl: string;
cookies: any;
accept: any;
/**
* To bypass Koa's built-in response handling, you may explicitly set `ctx.respond = false;`
*/
respond?: boolean;
}
export type Context<
StateT = DefaultState,
CustomT = DefaultContext,
> = ExtendableContext & {
state: StateT;
} & CustomT;
export type Next = () => void | Promise<void>;
/**
* @private
*/
export function compose<T1, U1, T2, U2>(
middleware: [Middleware<T1, U1>, Middleware<T2, U2>],
): Middleware<T1 & T2, U1 & U2>;
/**
* @private
*/
export function compose<T1, U1, T2, U2, T3, U3>(
middleware: [Middleware<T1, U1>, Middleware<T2, U2>, Middleware<T3, U3>],
): Middleware<T1 & T2 & T3, U1 & U2 & U3>;
/**
* @private
*/
export function compose<T1, U1, T2, U2, T3, U3, T4, U4>(
middleware: [
Middleware<T1, U1>,
Middleware<T2, U2>,
Middleware<T3, U3>,
Middleware<T4, U4>,
],
): Middleware<T1 & T2 & T3 & T4, U1 & U2 & U3 & U4>;
/**
* @private
*/
export function compose<T1, U1, T2, U2, T3, U3, T4, U4, T5, U5>(
middleware: [
Middleware<T1, U1>,
Middleware<T2, U2>,
Middleware<T3, U3>,
Middleware<T4, U4>,
Middleware<T5, U5>,
],
): Middleware<T1 & T2 & T3 & T4 & T5, U1 & U2 & U3 & U4 & U5>;
/**
* @private
*/
export function compose<T1, U1, T2, U2, T3, U3, T4, U4, T5, U5, T6, U6>(
middleware: [
Middleware<T1, U1>,
Middleware<T2, U2>,
Middleware<T3, U3>,
Middleware<T4, U4>,
Middleware<T5, U5>,
Middleware<T6, U6>,
],
): Middleware<T1 & T2 & T3 & T4 & T5 & T6, U1 & U2 & U3 & U4 & U5 & U6>;
/**
* @private
*/
export function compose<T1, U1, T2, U2, T3, U3, T4, U4, T5, U5, T6, U6, T7, U7>(
middleware: [
Middleware<T1, U1>,
Middleware<T2, U2>,
Middleware<T3, U3>,
Middleware<T4, U4>,
Middleware<T5, U5>,
Middleware<T6, U6>,
Middleware<T7, U7>,
],
): Middleware<
T1 & T2 & T3 & T4 & T5 & T6 & T7,
U1 & U2 & U3 & U4 & U5 & U6 & U7
>;
/**
* @private
*/
export function compose<
T1,
U1,
T2,
U2,
T3,
U3,
T4,
U4,
T5,
U5,
T6,
U6,
T7,
U7,
T8,
U8,
>(
middleware: [
Middleware<T1, U1>,
Middleware<T2, U2>,
Middleware<T3, U3>,
Middleware<T4, U4>,
Middleware<T5, U5>,
Middleware<T6, U6>,
Middleware<T7, U7>,
Middleware<T8, U8>,
],
): Middleware<
T1 & T2 & T3 & T4 & T5 & T6 & T7 & T8,
U1 & U2 & U3 & U4 & U5 & U6 & U7 & U8
>;
/**
* Compose middleware
*/
export function compose<T>(
middleware: Array<Middleware<T>>,
): (context: T, next?: Next) => Promise<void>;
/**
* @private
*/
interface Session {
/**
* JSON representation of the session.
*/
toJSON(): object;
/**
* alias to `toJSON`
*/
inspect(): object;
/**
* Return how many values there are in the session object.
* Used to see if it"s "populated".
*/
readonly length: number;
/**
* populated flag, which is just a boolean alias of .length.
*/
readonly populated: boolean;
/**
* get/set session maxAge
*/
maxAge: SessionOptions["maxAge"];
/**
* save this session no matter whether it is populated
*/
save(): void;
/**
* allow to put any value on session object
*/
[_: string]: any;
}
/**
* @private
*/
interface SessionStore {
/**
* get session object by key
*/
get(
key: string,
maxAge: SessionOptions["maxAge"],
data: { rolling: SessionOptions["rolling"] },
): any;
get(id: string): Promise<object | boolean>;
/**
* set session object for key, with a maxAge (in ms)
*/
set(
key: string,
sess: Partial<Session> & { _expire?: number; _maxAge?: number },
maxAge: SessionOptions["maxAge"],
data: { changed: boolean; rolling: SessionOptions["rolling"] },
): any;
set(id: string, session: object, age: number): Promise<void>;
/**
* destroy session for key
*/
destroy(key: string): any;
destroy(id: string): Promise<void>;
}
export interface SessionOptions {
/**
* cookie key (default is process.env.APP_NAME.sess)
*/
key?: string;
/**
* Domain to set the cookie for
* When development (default undefined)
* When production (default process.env.COOKIE_URL)
*/
domain?: string;
/**
* maxAge in ms (default is 6 days)
* "session" will result in a cookie that expires when session/browser is closed or when
* eighteen hours are passed without a request.
* Works best with the options 'rolling' set to true
*/
maxAge?: number | "session";
/**
* Automatically commit headers (default true)
*/
autoCommit?: boolean;
/**
* Can overwrite or not (default true)
*/
overwrite?: boolean;
/**
* httpOnly or not (default true)
*/
httpOnly?: boolean;
/**
* Set and check signature cookie (default true)
*/
signed?: boolean;
/**
* Set Secure cookie, only available in https context (default process.env.NODE_ENV ===
* "production")
*/
secure?: boolean;
/**
* Session cookie sameSite options (default "lax")
*/
sameSite?: "strict" | "lax" | boolean;
/**
* Force a session identifier cookie to be set on every response. The expiration is reset to
* the original maxAge, resetting the expiration countdown. default is false
*/
rolling?: boolean;
/**
* Renew session when session is nearly expired, so we can always keep user logged in.
* (default is true)
*/
renew?: boolean;
/**
* You can store the session content in external stores(redis, mongodb or other DBs)
* Use `newSessionStore` provided by `@compas/store`
*/
store?: SessionStore;
/**
* Keeps a plain browser JS readable cookie in sync with the session cookie.
* This allows the browser to do some basic conditional rendering and api calls, that are
* right most of the time. Note that this cookie is not signed, and the real verification
* and session happens in the httpOnly cookie.
*/
keepPublicCookie?: boolean;
/**
* If your session store requires data or utilities from context, opts.ContextStore is alse
* supported. ContextStore must be a class which claims three instance methods demonstrated
* above. new ContextStore(ctx) will be executed on every request.
*/
ContextStore?: { new (ctx: Context): SessionStore };
/**
* If you want to add prefix for all external session id, you can use options.prefix, it
* will not work if options.genid present.
*/
prefix?: string;
}
// ===========
// END OF @types
// ============
interface KoaBodyOptions {
/**
* Defaults to 'true'
*/
urlencoded?: boolean | undefined;
/**
* Defaults to 'true'
*/
json?: boolean | undefined;
/**
* Defaults to 'true'
*/
text?: boolean | undefined;
/**
* Defaults to 'utf-8'
*/
encoding?: string | undefined;
/**
* See 'https://github.com/ljharb/qs' for available options
*/
queryString?: any | undefined;
/**
* Defaults to '1mb'
*/
jsonLimit?: string | undefined;
/**
* Defaults to '1mb'
*/
formLimit?: string | undefined;
/**
* Defaults to '56kb'
*/
textLimit?: string | undefined;
/**
* Defaults to '["POST", "PUT", "PATCH"]'
*/
parsedMethods?: string[] | undefined;
}
/**
* @private
*/
interface IFormidableBodyOptions {
/**
* {string} - default 'utf-8'; sets encoding for incoming form fields
*/
encoding?: string;
/**
* default `os.tmpdir()` the directory for placing file uploads in. You can move them later
* by using `fs.rename()`
*/
uploadDir?: string;
/**
* {boolean} - default false; to include the extensions of the original files or not
*/
keepExtensions?: boolean;
/**
* {number} - default 200 * 1024 * 1024 (200mb); limit the size of uploaded file
*/
maxFileSize?: number;
/**
* {number} - default 1000; limit the number of fields that the Querystring parser will
* decode, set 0 for unlimited
*/
maxFields?: number;
/**
* {number} - default 20 * 1024 * 1024 (20mb); limit the amount of memory all fields
* together (except files) can allocate in bytes
*/
maxFieldsSize?: number;
/**
* {boolean} - default false; include checksums calculated for incoming files, set this to
* some hash algorithm, see crypto.createHash for available algorithms
*/
hash?: boolean;
}
/**
* Extract data for the response from the AppError data
*/
export interface AppErrorHandler {
(ctx: Context, key: string, info: any): Record<string, any>;
}
/**
* Return truthy when handled or falsey when skipped
*/
export interface CustomErrorHandler {
(ctx: Context, err: Error): boolean;
}
export interface ErrorHandlerOptions {
/**
* Called to set the initial body when the error is an AppError
*/
onAppError?: AppErrorHandler;
/**
* Called before all others to let the user handle their own errors
*/
onError?: CustomErrorHandler;
/**
* Useful on development and staging environments to just dump the error to the consumer
*/
leakError?: boolean;
}
export interface HeaderOptions {
cors?: CorsOptions;
}
export interface CorsOptions {
/**
* `Access-Control-Allow-Origin`, default is request Origin header
*/
origin?: string | ((ctx: Context) => string | undefined);
/**
* `Access-Control-Expose-Headers`
*/
exposeHeaders?: string[] | string;
/**
* `Access-Control-Max-Age` in seconds
*/
maxAge?: string | number;
/**
* `Access-Control-Allow-Credentials`
*/
credentials?: boolean;
/**
* `Access-Control-Allow-Methods`, default is ['GET', 'PUT', 'POST', 'PATCH', 'DELETE',
* 'HEAD', 'OPTIONS']
*/
allowMethods?: string[] | string;
/**
* `Access-Control-Allow-Headers`
*/
allowHeaders?: string[] | string;
}
export interface GetAppOptions {
/**
* Trust proxy headers
*/
proxy?: boolean;
/**
* Don't handle cors headers
*/
disableHeaders?: boolean;
/**
* Disable GET /_health
*/
disableHealthRoute?: boolean;
/**
* Flexible error handling options
*/
errorOptions?: ErrorHandlerOptions;
/**
* Argument for defaultHeader middleware
*/
headers?: HeaderOptions;
/**
* Options passed to the log middleware
*/
logOptions?: {
/**
* Disable event creation on ctx.event
*/
disableRootEvent?: boolean;
};
}
/**
* Create a new Koa instance with some default middleware
*/
export function getApp(opts?: GetAppOptions): Application;
export interface BodyParserPair {
bodyParser: (context: Context, next?: Next | undefined) => Promise<void>;
multipartBodyParser: (
context: Context,
next?: Next | undefined,
) => Promise<void>;
}
/**
* Creates a body parser and a body parser with multipart enabled
* Note that koa-body parses url-encoded, form data, json and text by default
*/
export function createBodyParsers(
bodyOptions?: KoaBodyOptions,
multipartBodyOptions?: IFormidableBodyOptions,
): BodyParserPair;
/**
* Compatible with @compas/store files. Needs either updated_at or last_modified
* @private
*/
type SendFileItem =
| StoreFile
| (Pick<StoreFile, "id" | "contentLength" | "contentType"> & {
lastModified: Date;
});
/**
* @private
*/
interface GetStreamFn {
(fileInfo: SendFileItem, start?: number, end?: number): Promise<{
stream: ReadableStream;
cacheControl?: string;
}>;
}
/**
* Send any file to the ctx.body
* User is free to set Cache-Control
*/
export function sendFile(
ctx: Context,
file: unknown,
getStreamFn: GetStreamFn,
): Promise<void>;
/**
* Session middleware
* Requires process.env.APP_KEYS
* To generate a key use something like
* node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
* For more information read koa-session docs.
* See also the custom `supportOptionOverwrites` property on `SessionOptions`.
*/
export function session(app: Application, options: SessionOptions): Middleware;
/**
* Calls app.listen on a random port and sets the correct baseURL on the provided axios
* instance
*/
export function createTestAppAndClient(
app: Application,
axios: AxiosInstance,
): Promise<void>;
/**
* Stops the server created with `createTestAppAndClient`
*/
export function closeTestApp(app: Application): Promise<void>;
export { getApp } from "./src/app.js";
export type Application = import("./src/app").KoaApplication;
export type Context<S, C, R> = import("koa").ParameterizedContext<S, C, R>;
export type Middleware = import("koa").Middleware;
export type Next = import("koa").Next;
export type BodyParserPair = import("./src/middleware/body").BodyParserPair;
export { createBodyParsers, sendFile, session, compose } from "./src/middleware/index.js";
export { closeTestApp, createTestAppAndClient } from "./src/testing.js";
//# sourceMappingURL=index.d.ts.map

@@ -0,1 +1,22 @@

/**
* @typedef {import("./src/app").KoaApplication} Application
*/
/**
* @template S,C,R
* @typedef {import("koa").ParameterizedContext<S,C,R>} Context
*/
/**
* @typedef {import("koa").Middleware} Middleware
*/
/**
* @typedef {import("koa").Next} Next
*/
/**
* @typedef {import("./src/middleware/body").BodyParserPair} BodyParserPair
*/
export { getApp } from "./src/app.js";

@@ -2,0 +23,0 @@ export {

{
"name": "@compas/server",
"version": "0.0.157",
"version": "0.0.158",
"description": "Koa server and common middleware",

@@ -18,3 +18,6 @@ "main": "./index.js",

"dependencies": {
"@compas/stdlib": "0.0.157",
"@compas/stdlib": "0.0.158",
"@types/formidable": "1.2.3",
"@types/koa": "2.13.4",
"@types/koa-session": "5.10.4",
"co-body": "6.1.0",

@@ -21,0 +24,0 @@ "formidable": "2.0.0-canary.20200504.1",

@@ -12,2 +12,49 @@ import { isProduction } from "@compas/stdlib";

/**
* @typedef {ReturnType<getApp>} KoaApplication
*/
/**
* @typedef {object} GetAppOptions
* @property {boolean|undefined} [proxy] Trust proxy headers
* @property {boolean|undefined} [disableHeaders] Don't handle cors headers
* @property {boolean|undefined} [disableHealthRoute] Disable GET /_health
* @property {ErrorHandlerOptions|undefined} [errorOptions] Flexible error handling
* options
* @property {HeaderOptions|undefined} [headers] Argument for defaultHeader middleware
* @property {{ disableRootEvent?: boolean|undefined }|undefined} [logOptions]
*/
/**
* @typedef {object} ErrorHandlerOptions
* @property {((
* ctx: Koa.Context,
* key: string,
* info: any
* ) => Record<string, any> )| undefined} [onAppError] Called to set the initial body
* when the error is an AppError
* @property {((ctx: Koa.Context, err: Error) => boolean)|undefined} [onError] Called
* before any logic, to let the user handle errors. If 'true' is returned, no other
* logic is applied.
* @property {boolean|undefined} [leakError] Adds the stacktrace and originalError to the
* response. Useful on development and staging environments.
*/
/**
* @typedef {object} HeaderOptions
* @property {CorsOptions|undefined} [cors]
*/
/**
* @typedef {object} CorsOptions
* @property {string|((ctx: Koa.Context) => (string|undefined))} [origin]
* 'Access-Control-Allow-Origin', defaults to the 'Origin' header.
* @property {string|string[]|undefined} [exposeHeaders] 'Access-Control-Expose-Headers'
* @property {string|number|undefined} [maxAge] 'Access-Control-Max-Age' in seconds
* @property {boolean|undefined} [credentials] 'Access-Control-Allow-Credentials'
* @property {string|string[]|undefined} [allowMethods] 'Access-Control-Allow-Methods',
* defaults to ["DELETE", "GET", "PUT", "POST", "PATCH", "HEAD", "OPTIONS"]
* @property {string|string[]|undefined} [allowHeaders] 'Access-Control-Allow-Headers'
*/
/**
* Create a new Koa instance with default middleware applied.

@@ -30,3 +77,2 @@ * Adds the following:

* @param {GetAppOptions} [opts={}]
* @returns {Application}
*/

@@ -42,3 +88,3 @@ export function getApp(opts = {}) {

app.use(logMiddleware(opts.logOptions ?? {}));
app.use(errorHandler(opts.errorOptions || {}));
app.use(errorHandler(opts.errorOptions ?? {}));
app.use(notFoundHandler());

@@ -45,0 +91,0 @@

@@ -6,2 +6,6 @@ import { AppError } from "@compas/stdlib";

/**
* @typedef {import("koa").Middleware} Middleware
*/
/**
* @typedef {object} KoaBodyOptions

@@ -17,5 +21,10 @@ * @property {boolean|undefined} [urlencoded]

* @property {string[]|undefined} [parsedMethods]
*
*/
/**
* @typedef {object} BodyParserPair
* @property {Middleware} bodyParser
* @property {Middleware} multipartBodyParser
*/
const jsonTypes = [

@@ -35,3 +44,3 @@ "application/json",

* @param {KoaBodyOptions} [bodyOpts={}] Options that will be passed to koa-body
* @param {IFormidableBodyOptions} [multipartBodyOpts={}] Options that will be passed to
* @param {formidable.Options} [multipartBodyOpts={}] Options that will be passed to
* formidable

@@ -53,3 +62,3 @@ * @returns {BodyParserPair}

*
* @param {KoaBodyOptions} [opts={}] Options that will be passed to koa-body
* @param {KoaBodyOptions} opts Options that will be passed to koa-body
*/

@@ -73,2 +82,3 @@ function koaBody(opts = {}) {

// only parse the body on specifically chosen methods
// @ts-ignore
if (opts.parsedMethods.includes(ctx.method.toUpperCase())) {

@@ -97,3 +107,3 @@ try {

}
} catch (parsingError) {
} catch (/** @type {any} */ parsingError) {
if (parsingError instanceof SyntaxError) {

@@ -104,5 +114,3 @@ delete parsingError.stack;

message: parsingError.message,
fileName: parsingError.fileName,
lineNumber: parsingError.lineNumber,
columnNumber: parsingError.columnNumber,
// @ts-ignore
rawBody: parsingError.body,

@@ -136,3 +144,3 @@ });

*
* @param {IFormidableBodyOptions} opts
* @param {formidable.Options} opts
* @returns {Middleware}

@@ -168,5 +176,8 @@ */

form.on("end", () => {
// @ts-ignore
ctx.request.files = files;
// @ts-ignore
resolve();
});
// @ts-ignore
form.parse(ctx.req);

@@ -173,0 +184,0 @@ }).then(() => {

@@ -9,2 +9,6 @@ /*

/**
* @typedef {import("koa").Middleware} Middleware
*/
/**
* Compose `middleware` returning of all those which are passed.

@@ -14,3 +18,3 @@ *

*
* @param {Array} middleware
* @param {Middleware[]} middleware
* @returns {Middleware}

@@ -17,0 +21,0 @@ */

@@ -40,3 +40,3 @@ import { environment, isStaging } from "@compas/stdlib";

*
* @param {CorsOptions} [options]
* @param {import("../app").CorsOptions} [options]
* @returns {Function}

@@ -48,2 +48,3 @@ */

if (Array.isArray(opts.exposeHeaders)) {
// @ts-ignore
opts.exposeHeaders = opts.exposeHeaders.join(",");

@@ -57,2 +58,3 @@ }

if (Array.isArray(opts.allowMethods)) {
// @ts-ignore
opts.allowMethods = opts.allowMethods.join(",");

@@ -59,0 +61,0 @@ }

import { AppError, isNil, isStaging } from "@compas/stdlib";
/**
* @type CustomErrorHandler
* @typedef {import("../app").ErrorHandlerOptions} ErrorHandlerOptions
*/
/**
* @type {NonNullable<ErrorHandlerOptions["onError"]>}
* Default onError handler that doesn't handle anything

@@ -10,3 +14,3 @@ */

/**
* @type AppErrorHandler
* @type {NonNullable<ErrorHandlerOptions["onAppError"]>}
* Default onAppError handler that builds a simple object with key, message and info.

@@ -20,8 +24,9 @@ */

* @param {ErrorHandlerOptions} opts
* @returns {function(...[*]=)}
* @returns {Middleware}
*/
export function errorHandler({ onAppError, onError, leakError }) {
onAppError = onAppError || defaultOnAppError;
onError = onError || defaultOnError;
leakError = leakError === true || (leakError === undefined && isStaging());
export function errorHandler(opts) {
const onAppError = opts.onAppError ?? defaultOnAppError;
const onError = opts.onError ?? defaultOnError;
const leakError =
opts.leakError === true || (opts.leakError === undefined && isStaging());

@@ -31,3 +36,3 @@ return async (ctx, next) => {

await next();
} catch (error) {
} catch (/** @type {any} */ error) {
if (onError(ctx, error)) {

@@ -34,0 +39,0 @@ return;

import { cors } from "./cors.js";
/**
* @param {object} [opts]
* @param {CorsOptions} opts.cors Cors configuration see koa2-cors
* @param {import("../app").HeaderOptions} [opts]
*/

@@ -7,0 +6,0 @@ export function defaultHeaders(opts = {}) {

import { isNil } from "@compas/stdlib";
/**
* @typedef {(
* file: StoreFile,
* start?: number | undefined,
* end?: number | undefined
* ) => Promise<{
* stream: NodeJS.ReadableStream,
* cacheControl: string,
* }>} GetStreamFn
*/
/**
* Send a `StoreFile` instance from @compas/store as a `ctx` response.

@@ -10,14 +21,18 @@ * Handles byte range requests as well. May need some improvements to set some better

*
* @param {Context} ctx
* @param {SendFileItem} file
* @param {import("koa").Context} ctx
* @param {StoreFile} file
* @param {GetStreamFn} getStreamFn
* @returns {Promise<undefined>}
* @returns {Promise<void>}
*/
export async function sendFile(ctx, file, getStreamFn) {
ctx.set("Accept-Ranges", "bytes");
// @ts-ignore
ctx.set("Last-Modified", file.updatedAt || file.lastModified);
ctx.type = file.contentType;
// @ts-ignore
if (ctx.headers["if-modified-since"]?.length > 0) {
// @ts-ignore
const dateValue = new Date(ctx.headers["if-modified-since"]);
// @ts-ignore
const currentDate = new Date(file.updatedAt ?? file.lastModified);

@@ -40,3 +55,5 @@

// @ts-ignore
let start = range[1] ? parseInt(range[1]) : undefined;
// @ts-ignore
let end = range[2] ? parseInt(range[2]) : file.contentLength;

@@ -43,0 +60,0 @@

@@ -6,2 +6,6 @@ import { environment, isNil, isProduction, merge, uuid } from "@compas/stdlib";

/**
* @typedef {import("koa").Middleware} Middleware
*/
/**
* Session middleware. Requires process.env.APP_KEYS to be set. To generate a key use

@@ -14,4 +18,4 @@ * something like:

*
* @param {Application} app
* @param {SessionOptions} opts KoaSession options
* @param {import("../app").KoaApplication} app
* @param {Partial<koaSession.opts>} opts KoaSession options
* @returns {Middleware}

@@ -68,3 +72,6 @@ */

*
* @param {{ store: SessionStore, key: string, } & SessionOptions} opts
* @param {{
* store: SessionStore,
* key: string,
* } & Partial<koaSession.opts>} opts
*/

@@ -84,2 +91,3 @@ function wrapStoreCalls({ store, key, ...cookieOpts }) {

if (!args[3]?.ctx) {
// @ts-ignore
return originalSet(...args);

@@ -91,2 +99,3 @@ }

// @ts-ignore
return originalSet(...args);

@@ -97,2 +106,3 @@ };

if (!args[1]?.ctx) {
// @ts-ignore
return originalDestroy(...args);

@@ -104,4 +114,5 @@ }

// @ts-ignore
return originalDestroy(...args);
};
}

@@ -7,5 +7,5 @@ /**

*
* @param {Application} app
* @param {AxiosInstance} axios
* @returns {Promise<undefined>}
* @param {import("./app").KoaApplication} app
* @param {import("axios").AxiosInstance} axios
* @returns {Promise<void>}
*/

@@ -15,9 +15,13 @@ export async function createTestAppAndClient(app, axios) {

let isListening = false;
// @ts-ignore
app._server = app.listen();
// @ts-ignore
app._server.on("listening", () => {
isListening = true;
// @ts-ignore
resolve();
});
// @ts-ignore
app._server.on("error", (err) => {

@@ -30,2 +34,3 @@ if (!isListening) {

// @ts-ignore
const { port } = app._server.address();

@@ -40,8 +45,10 @@ axios.defaults.baseURL = `http://127.0.0.1:${port}/`;

*
* @param {Application} app
* @returns {Promise<undefined>}
* @param {import("./app").KoaApplication} app
* @returns {Promise<void>}
*/
export function closeTestApp(app) {
return new Promise((resolve, reject) => {
// @ts-ignore
if (app._server && app._server.listening) {
// @ts-ignore
app._server.close((err) => {

@@ -48,0 +55,0 @@ if (err) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc