shelving 1.143.0 → 1.144.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/Endpoint.d.ts +11 -1
- package/api/Endpoint.js +25 -2
- package/api/util.d.ts +14 -0
- package/api/util.js +40 -19
- package/error/BaseError.d.ts +3 -6
- package/error/BaseError.js +6 -13
- package/error/NetworkError.js +0 -1
- package/error/RequestError.d.ts +7 -12
- package/error/RequestError.js +10 -18
- package/error/RequiredError.js +0 -1
- package/error/ResponseError.js +0 -1
- package/error/UnexpectedError.js +0 -1
- package/error/UnimplementedError.js +0 -1
- package/error/ValueError.js +0 -1
- package/package.json +1 -1
- package/util/ansi.d.ts +24 -0
- package/util/ansi.js +28 -0
- package/util/array.d.ts +1 -1
- package/util/async.d.ts +3 -4
- package/util/boolean.d.ts +1 -1
- package/util/bytes.d.ts +1 -1
- package/util/callback.d.ts +2 -0
- package/util/color.d.ts +1 -1
- package/util/data.d.ts +1 -1
- package/util/date.d.ts +1 -1
- package/util/dictionary.d.ts +1 -1
- package/util/entity.d.ts +1 -1
- package/util/equal.d.ts +1 -1
- package/util/error.d.ts +0 -2
- package/util/error.js +1 -1
- package/util/file.d.ts +1 -1
- package/util/function.d.ts +3 -0
- package/util/http.d.ts +21 -3
- package/util/http.js +25 -5
- package/util/index.d.ts +1 -0
- package/util/index.js +1 -0
- package/util/jwt.d.ts +1 -1
- package/util/link.d.ts +1 -1
- package/util/map.d.ts +1 -1
- package/util/null.d.ts +1 -1
- package/util/number.d.ts +1 -1
- package/util/optional.d.ts +1 -1
- package/util/path.d.ts +1 -1
- package/util/sequence.d.ts +2 -2
- package/util/set.d.ts +1 -1
- package/util/source.d.ts +1 -1
- package/util/string.d.ts +1 -1
- package/util/template.d.ts +1 -1
- package/util/time.d.ts +1 -1
- package/util/undefined.d.ts +1 -1
- package/util/url.d.ts +1 -1
- package/util/validate.d.ts +2 -1
package/api/Endpoint.d.ts
CHANGED
|
@@ -36,9 +36,19 @@ export declare class Endpoint<P, R> implements Validator<R> {
|
|
|
36
36
|
*/
|
|
37
37
|
validate(unsafeResult: unknown): R;
|
|
38
38
|
/**
|
|
39
|
-
* Return an `EndpointHandler` for this endpoint
|
|
39
|
+
* Return an `EndpointHandler` for this endpoint.
|
|
40
|
+
*
|
|
41
|
+
* @param callback The callback function that implements the logic for this endpoint by receiving the payload and returning the response.
|
|
40
42
|
*/
|
|
41
43
|
handler(callback: EndpointCallback<P, R>): EndpointHandler<P, R>;
|
|
44
|
+
/**
|
|
45
|
+
* Handle a request to this endpoint with a callback implementation, with a given payload and request.
|
|
46
|
+
*
|
|
47
|
+
* @param callback The endpoint callback function that implements the logic for this endpoint by receiving the payload and returning the response.
|
|
48
|
+
* @param unsafePayload The payload to pass into the callback (will be validated against this endpoint's payload schema).
|
|
49
|
+
* @param request The entire HTTP request that is being handled (payload was possibly extracted from this somehow).
|
|
50
|
+
*/
|
|
51
|
+
handle(callback: EndpointCallback<P, R>, unsafePayload: unknown, request: Request): Promise<Response>;
|
|
42
52
|
}
|
|
43
53
|
/** Extract the payload type from a `Endpoint`. */
|
|
44
54
|
export type PayloadType<X extends Endpoint<unknown, unknown>> = X extends Endpoint<infer Y, unknown> ? Y : never;
|
package/api/Endpoint.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValueError } from "../error/ValueError.js";
|
|
2
|
+
import { UNDEFINED, getValid } from "../util/validate.js";
|
|
2
3
|
/**
|
|
3
4
|
* An abstract API resource definition, used to specify types for e.g. serverless functions.
|
|
4
5
|
*
|
|
@@ -41,11 +42,33 @@ export class Endpoint {
|
|
|
41
42
|
return this.result.validate(unsafeResult);
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
44
|
-
* Return an `EndpointHandler` for this endpoint
|
|
45
|
+
* Return an `EndpointHandler` for this endpoint.
|
|
46
|
+
*
|
|
47
|
+
* @param callback The callback function that implements the logic for this endpoint by receiving the payload and returning the response.
|
|
45
48
|
*/
|
|
46
49
|
handler(callback) {
|
|
47
50
|
return { endpoint: this, callback };
|
|
48
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Handle a request to this endpoint with a callback implementation, with a given payload and request.
|
|
54
|
+
*
|
|
55
|
+
* @param callback The endpoint callback function that implements the logic for this endpoint by receiving the payload and returning the response.
|
|
56
|
+
* @param unsafePayload The payload to pass into the callback (will be validated against this endpoint's payload schema).
|
|
57
|
+
* @param request The entire HTTP request that is being handled (payload was possibly extracted from this somehow).
|
|
58
|
+
*/
|
|
59
|
+
async handle(callback, unsafePayload, request) {
|
|
60
|
+
const payload = this.prepare(unsafePayload);
|
|
61
|
+
// Call the callback with the validated payload to get the result.
|
|
62
|
+
const returned = await callback(payload, request);
|
|
63
|
+
// If the callback returned a `Response`, return it directly.
|
|
64
|
+
if (returned instanceof Response)
|
|
65
|
+
return returned;
|
|
66
|
+
// Otherwise validate the result against the endpoint's result type.
|
|
67
|
+
// Throw a `ValueError` if the result is not valid, which indicates an internal error in the callback implementation.
|
|
68
|
+
const result = getValid(returned, this, ValueError, this.handle);
|
|
69
|
+
// Return a new `Response` with a 200 status and the validated result data.
|
|
70
|
+
return Response.json(result);
|
|
71
|
+
}
|
|
49
72
|
}
|
|
50
73
|
export function GET(path, payload, result) {
|
|
51
74
|
return new Endpoint("GET", path, payload || UNDEFINED, result || UNDEFINED);
|
package/api/util.d.ts
CHANGED
|
@@ -38,3 +38,17 @@ export type EndpointHandlers = ReadonlyArray<AnyEndpointHandler>;
|
|
|
38
38
|
* @throws `NotFoundError` if no handler matches the `Request`.
|
|
39
39
|
*/
|
|
40
40
|
export declare function handleEndpoints(request: Request, endpoints: EndpointHandlers): Promise<Response>;
|
|
41
|
+
/**
|
|
42
|
+
* Correctly interpret an error thrown from an endpoint and return the correct `Response`.
|
|
43
|
+
*
|
|
44
|
+
* Returns the correct `Response` based on the type of error thrown:
|
|
45
|
+
* - If `reason` is a `Response` instance, return it directly.
|
|
46
|
+
* - If `reason` is a `Feedback` instance, return a 400 response with the feedback's message as JSON, e.g. `{ message: "Invalid input" }`
|
|
47
|
+
* - If `reason` is an `RequestError` instance, return a response with the error's message and code (but only if `debug` is true so we don't leak error details to the client).
|
|
48
|
+
* - If `reason` is an `Error` instance, return a 500 response with the error's message (but only if `debug` is true so we don't leak error details to the client).
|
|
49
|
+
* - Anything else returns a 500 response.
|
|
50
|
+
*
|
|
51
|
+
* @param reason The error thrown from the endpoint.
|
|
52
|
+
* @param debug If `true` include the error message in the response (for debugging), or `false` to return generic error codes (for security).
|
|
53
|
+
*/
|
|
54
|
+
export declare function handleEndpointError(reason: unknown, debug?: boolean): Response;
|
package/api/util.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { NotFoundError, RequestError } from "../error/RequestError.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Feedback } from "../feedback/Feedback.js";
|
|
3
3
|
import { isData } from "../util/data.js";
|
|
4
4
|
import { getDictionary } from "../util/dictionary.js";
|
|
5
|
+
import { isError } from "../util/error.js";
|
|
5
6
|
import { getRequestContent } from "../util/http.js";
|
|
6
7
|
import { matchTemplate } from "../util/template.js";
|
|
7
8
|
import { getURL } from "../util/url.js";
|
|
8
|
-
import { getValid } from "../util/validate.js";
|
|
9
9
|
/**
|
|
10
10
|
* Handler a `Request` with the first matching `EndpointHandlers`.
|
|
11
11
|
*
|
|
@@ -18,9 +18,10 @@ import { getValid } from "../util/validate.js";
|
|
|
18
18
|
*/
|
|
19
19
|
export function handleEndpoints(request, endpoints) {
|
|
20
20
|
// Parse the URL of the request.
|
|
21
|
-
const
|
|
21
|
+
const requestUrl = request.url;
|
|
22
|
+
const url = getURL(requestUrl);
|
|
22
23
|
if (!url)
|
|
23
|
-
throw new RequestError("Invalid request URL", { received:
|
|
24
|
+
throw new RequestError("Invalid request URL", { received: requestUrl, caller: handleEndpoints });
|
|
24
25
|
const { pathname, searchParams } = url;
|
|
25
26
|
// Iterate over the handlers and return the first one that matches the request.
|
|
26
27
|
for (const { endpoint, callback } of endpoints) {
|
|
@@ -35,27 +36,47 @@ export function handleEndpoints(request, endpoints) {
|
|
|
35
36
|
// Make a simple dictionary object from the `{placeholder}` path params and the `?a=123` query params from the URL.
|
|
36
37
|
const params = searchParams.size ? { ...getDictionary(searchParams), ...pathParams } : pathParams;
|
|
37
38
|
// Get the response by calling the callback.
|
|
38
|
-
return
|
|
39
|
+
return handleEndpoint(endpoint, callback, params, request);
|
|
39
40
|
}
|
|
40
41
|
// No handler matched the request.
|
|
41
|
-
throw new NotFoundError("
|
|
42
|
+
throw new NotFoundError("No matching endpoint", { received: requestUrl, caller: handleEndpoints });
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
/** Handle an individual call to an endpoint callback. */
|
|
45
|
+
async function handleEndpoint(endpoint, callback, params, request) {
|
|
44
46
|
// Extract a data object from the request body and validate it against the endpoint's payload type.
|
|
45
47
|
const content = await getRequestContent(request, handleEndpoints);
|
|
46
48
|
// If content is undefined, it means the request has no body, so params are the only payload.
|
|
47
49
|
// If the content is a data object merge if with the params.
|
|
48
50
|
// If the content is not a data object (e.g. string, number, array), set a single `content` property and merge it with the params.
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
const payload = content === undefined ? params : isData(content) ? { ...content, ...params } : { content, ...params };
|
|
52
|
+
// Call `endpoint.handle()` with the payload and request.
|
|
53
|
+
return endpoint.handle(callback, payload, request);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Correctly interpret an error thrown from an endpoint and return the correct `Response`.
|
|
57
|
+
*
|
|
58
|
+
* Returns the correct `Response` based on the type of error thrown:
|
|
59
|
+
* - If `reason` is a `Response` instance, return it directly.
|
|
60
|
+
* - If `reason` is a `Feedback` instance, return a 400 response with the feedback's message as JSON, e.g. `{ message: "Invalid input" }`
|
|
61
|
+
* - If `reason` is an `RequestError` instance, return a response with the error's message and code (but only if `debug` is true so we don't leak error details to the client).
|
|
62
|
+
* - If `reason` is an `Error` instance, return a 500 response with the error's message (but only if `debug` is true so we don't leak error details to the client).
|
|
63
|
+
* - Anything else returns a 500 response.
|
|
64
|
+
*
|
|
65
|
+
* @param reason The error thrown from the endpoint.
|
|
66
|
+
* @param debug If `true` include the error message in the response (for debugging), or `false` to return generic error codes (for security).
|
|
67
|
+
*/
|
|
68
|
+
export function handleEndpointError(reason, debug = false) {
|
|
69
|
+
// Throw `Response` to do a custom response that is not logged.
|
|
70
|
+
if (reason instanceof Response)
|
|
71
|
+
return reason;
|
|
72
|
+
// Throw 'Feedback' to return `{ message: "etc" }` to the client, e.g. for input validation.
|
|
73
|
+
if (reason instanceof Feedback)
|
|
74
|
+
return Response.json(reason, { status: 422 }); // HTTP 422 Unprocessable Entity
|
|
75
|
+
// Throw `RequestError` to set a custom status code (e.g. `UnauthorizedError`).
|
|
76
|
+
const status = reason instanceof RequestError ? reason.code : 500;
|
|
77
|
+
// Throw `Error` to return `{ message: "etc" }` to the client (but only if `debug` is true so we don't leak error details to the client).
|
|
78
|
+
if (debug && isError(reason))
|
|
79
|
+
return Response.json(reason, { status });
|
|
80
|
+
// Otherwise return a generic error message.
|
|
81
|
+
return new Response(undefined, { status });
|
|
61
82
|
}
|
package/error/BaseError.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { AnyFunction } from "../util/function.js";
|
|
3
|
-
/** Any calling function or constructor that can appear in a stack tracer. */
|
|
4
|
-
export type AnyCaller = AnyFunction | AnyConstructor;
|
|
1
|
+
import type { AnyCaller } from "../util/function.js";
|
|
5
2
|
/** Options for `BaseError` that provide additional helpful error functionality. */
|
|
6
3
|
export interface BaseErrorOptions extends ErrorOptions {
|
|
7
4
|
/**
|
|
@@ -15,7 +12,7 @@ export interface BaseErrorOptions extends ErrorOptions {
|
|
|
15
12
|
}
|
|
16
13
|
/** An error that provides additional helpful functionality. */
|
|
17
14
|
export declare abstract class BaseError extends Error {
|
|
18
|
-
/** Provide additional named contextual data that
|
|
19
|
-
[key: string]: unknown;
|
|
15
|
+
/** Provide additional named contextual data that is relevant to the `Error` instance. */
|
|
16
|
+
readonly [key: string]: unknown;
|
|
20
17
|
constructor(message?: string, options?: BaseErrorOptions);
|
|
21
18
|
}
|
package/error/BaseError.js
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
/** An error that provides additional helpful functionality. */
|
|
2
2
|
export class BaseError extends Error {
|
|
3
|
-
constructor(message, options) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Error.captureStackTrace(this, caller);
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
super(message);
|
|
13
|
-
Error.captureStackTrace(this, BaseError);
|
|
14
|
-
}
|
|
3
|
+
constructor(message, options = {}) {
|
|
4
|
+
super(message, options);
|
|
5
|
+
const { cause, caller = BaseError, ...rest } = options;
|
|
6
|
+
for (const [key, value] of Object.entries(rest))
|
|
7
|
+
this[key] = value;
|
|
8
|
+
Error.captureStackTrace(this, caller);
|
|
15
9
|
}
|
|
16
10
|
}
|
|
17
11
|
BaseError.prototype.name = "BaseError";
|
|
18
|
-
BaseError.prototype.message = "Unknown error";
|
package/error/NetworkError.js
CHANGED
package/error/RequestError.d.ts
CHANGED
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
import { BaseError, type BaseErrorOptions } from "./BaseError.js";
|
|
2
|
-
/** Options for a `RequestError` */
|
|
3
|
-
interface RequestErrorOptions extends BaseErrorOptions {
|
|
4
|
-
code?: number;
|
|
5
|
-
}
|
|
6
2
|
/** Error thrown when a request isn't well-formed. */
|
|
7
3
|
export declare class RequestError extends BaseError {
|
|
8
4
|
/** The corresponding HTTP status code for this error, in the range `400-499` */
|
|
9
|
-
code: number;
|
|
10
|
-
constructor(message?: string, options?:
|
|
5
|
+
readonly code: number;
|
|
6
|
+
constructor(message?: string, options?: BaseErrorOptions);
|
|
11
7
|
}
|
|
12
8
|
/** Thrown if an operation failed because the user is not logged in, or the login information is not well-formed. */
|
|
13
9
|
export declare class UnauthorizedError extends RequestError {
|
|
14
10
|
readonly code: number;
|
|
15
|
-
constructor(message?: string, options?:
|
|
11
|
+
constructor(message?: string, options?: BaseErrorOptions);
|
|
16
12
|
}
|
|
17
13
|
/** Thrown if the requested content is not found. */
|
|
18
14
|
export declare class NotFoundError extends RequestError {
|
|
19
|
-
readonly code
|
|
20
|
-
constructor(message?: string, options?:
|
|
15
|
+
readonly code: number;
|
|
16
|
+
constructor(message?: string, options?: BaseErrorOptions);
|
|
21
17
|
}
|
|
22
18
|
/** Error thrown when a request is is valid and well-formed, but its actual data is not. */
|
|
23
19
|
export declare class UnprocessableError extends RequestError {
|
|
24
20
|
readonly code: number;
|
|
25
|
-
constructor(message?: string, options?:
|
|
21
|
+
constructor(message?: string, options?: BaseErrorOptions);
|
|
26
22
|
}
|
|
27
23
|
/** Thrown if an operation failed because the user is logged in, but does not have sufficient privileges to access this content. */
|
|
28
24
|
export declare class ForbiddenError extends RequestError {
|
|
29
25
|
readonly code: number;
|
|
30
|
-
constructor(message?: string, options?:
|
|
26
|
+
constructor(message?: string, options?: BaseErrorOptions);
|
|
31
27
|
}
|
|
32
|
-
export {};
|
package/error/RequestError.js
CHANGED
|
@@ -2,49 +2,41 @@ import { BaseError } from "./BaseError.js";
|
|
|
2
2
|
/** Error thrown when a request isn't well-formed. */
|
|
3
3
|
export class RequestError extends BaseError {
|
|
4
4
|
/** The corresponding HTTP status code for this error, in the range `400-499` */
|
|
5
|
-
code;
|
|
6
|
-
constructor(message
|
|
5
|
+
code = 400;
|
|
6
|
+
constructor(message, options) {
|
|
7
7
|
super(message, { caller: RequestError, ...options });
|
|
8
|
-
this.code = options?.code || 400;
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
10
|
RequestError.prototype.name = "RequestError";
|
|
12
|
-
RequestError.prototype.message = "Invalid request";
|
|
13
11
|
/** Thrown if an operation failed because the user is not logged in, or the login information is not well-formed. */
|
|
14
12
|
export class UnauthorizedError extends RequestError {
|
|
15
13
|
code = 401;
|
|
16
|
-
constructor(message
|
|
17
|
-
super(message, { caller: UnauthorizedError,
|
|
14
|
+
constructor(message, options) {
|
|
15
|
+
super(message, { caller: UnauthorizedError, ...options });
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
18
|
UnauthorizedError.prototype.name = "UnauthorizedError";
|
|
21
|
-
UnauthorizedError.prototype.message = "Authorization is required";
|
|
22
19
|
/** Thrown if the requested content is not found. */
|
|
23
20
|
export class NotFoundError extends RequestError {
|
|
24
21
|
code = 404;
|
|
25
|
-
constructor(message
|
|
26
|
-
super(message, { caller: NotFoundError,
|
|
27
|
-
Error.captureStackTrace(this, NotFoundError);
|
|
22
|
+
constructor(message, options) {
|
|
23
|
+
super(message, { caller: NotFoundError, ...options });
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
NotFoundError.prototype.name = "NotFoundError";
|
|
31
|
-
NotFoundError.prototype.message = "Cannot find requested content";
|
|
32
27
|
/** Error thrown when a request is is valid and well-formed, but its actual data is not. */
|
|
33
28
|
export class UnprocessableError extends RequestError {
|
|
34
29
|
code = 422;
|
|
35
|
-
constructor(message
|
|
36
|
-
super(message, { caller: UnprocessableError,
|
|
37
|
-
Error.captureStackTrace(this, UnprocessableError);
|
|
30
|
+
constructor(message, options) {
|
|
31
|
+
super(message, { caller: UnprocessableError, ...options });
|
|
38
32
|
}
|
|
39
33
|
}
|
|
40
34
|
UnprocessableError.prototype.name = "UnprocessableError";
|
|
41
|
-
UnprocessableError.prototype.message = "Input data is invalid";
|
|
42
35
|
/** Thrown if an operation failed because the user is logged in, but does not have sufficient privileges to access this content. */
|
|
43
36
|
export class ForbiddenError extends RequestError {
|
|
44
37
|
code = 403;
|
|
45
|
-
constructor(message
|
|
46
|
-
super(message, { caller: ForbiddenError,
|
|
38
|
+
constructor(message, options) {
|
|
39
|
+
super(message, { caller: ForbiddenError, ...options });
|
|
47
40
|
}
|
|
48
41
|
}
|
|
49
42
|
ForbiddenError.prototype.name = "ForbiddenError";
|
|
50
|
-
ForbiddenError.prototype.message = "Insufficient privileges to access this content";
|
package/error/RequiredError.js
CHANGED
package/error/ResponseError.js
CHANGED
package/error/UnexpectedError.js
CHANGED
package/error/ValueError.js
CHANGED
package/package.json
CHANGED
package/util/ansi.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const ANSI_TEXT_DEFAULT = "\u001B[39m";
|
|
2
|
+
export declare const ANSI_TEXT_BLACK = "\u001B[30m";
|
|
3
|
+
export declare const ANSI_TEXT_RED = "\u001B[31m";
|
|
4
|
+
export declare const ANSI_TEXT_GREEN = "\u001B[32m";
|
|
5
|
+
export declare const ANSI_TEXT_YELLOW = "\u001B[33m";
|
|
6
|
+
export declare const ANSI_TEXT_BLUE = "\u001B[34m";
|
|
7
|
+
export declare const ANSI_TEXT_MAGENTA = "\u001B[35m";
|
|
8
|
+
export declare const ANSI_TEXT_CYAN = "\u001B[36m";
|
|
9
|
+
export declare const ANSI_TEXT_WHITE = "\u001B[37m";
|
|
10
|
+
export declare const ANSI_FILL_DEFAULT = "\u001B[49m";
|
|
11
|
+
export declare const ANSI_FILL_BLACK = "\u001B[40m";
|
|
12
|
+
export declare const ANSI_FILL_RED = "\u001B[41m";
|
|
13
|
+
export declare const ANSI_FILL_GREEN = "\u001B[42m";
|
|
14
|
+
export declare const ANSI_FILL_YELLOW = "\u001B[43m";
|
|
15
|
+
export declare const ANSI_FILL_BLUE = "\u001B[44m";
|
|
16
|
+
export declare const ANSI_FILL_MAGENTA = "\u001B[45m";
|
|
17
|
+
export declare const ANSI_FILL_CYAN = "\u001B[46m";
|
|
18
|
+
export declare const ANSI_FILL_WHITE = "\u001B[47m";
|
|
19
|
+
export declare const ANSI_BOLD = "\u001B[1m";
|
|
20
|
+
export declare const ANSI_ITALIC = "\u001B[3m";
|
|
21
|
+
export declare const ANSI_UNDERLINE = "\u001B[4m";
|
|
22
|
+
export declare const ANSI_STRIKE = "\u001B[9m";
|
|
23
|
+
export declare const ANSI_INVERSE = "\u001B[7m";
|
|
24
|
+
export declare const ANSI_RESET = "\u001B[0m";
|
package/util/ansi.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Foreground colors.
|
|
2
|
+
export const ANSI_TEXT_DEFAULT = "\x1b[39m";
|
|
3
|
+
export const ANSI_TEXT_BLACK = "\x1b[30m";
|
|
4
|
+
export const ANSI_TEXT_RED = "\x1b[31m";
|
|
5
|
+
export const ANSI_TEXT_GREEN = "\x1b[32m";
|
|
6
|
+
export const ANSI_TEXT_YELLOW = "\x1b[33m";
|
|
7
|
+
export const ANSI_TEXT_BLUE = "\x1b[34m";
|
|
8
|
+
export const ANSI_TEXT_MAGENTA = "\x1b[35m";
|
|
9
|
+
export const ANSI_TEXT_CYAN = "\x1b[36m";
|
|
10
|
+
export const ANSI_TEXT_WHITE = "\x1b[37m";
|
|
11
|
+
// Background colors.
|
|
12
|
+
export const ANSI_FILL_DEFAULT = "\x1b[49m";
|
|
13
|
+
export const ANSI_FILL_BLACK = "\x1b[40m";
|
|
14
|
+
export const ANSI_FILL_RED = "\x1b[41m";
|
|
15
|
+
export const ANSI_FILL_GREEN = "\x1b[42m";
|
|
16
|
+
export const ANSI_FILL_YELLOW = "\x1b[43m";
|
|
17
|
+
export const ANSI_FILL_BLUE = "\x1b[44m";
|
|
18
|
+
export const ANSI_FILL_MAGENTA = "\x1b[45m";
|
|
19
|
+
export const ANSI_FILL_CYAN = "\x1b[46m";
|
|
20
|
+
export const ANSI_FILL_WHITE = "\x1b[47m";
|
|
21
|
+
// Styles.
|
|
22
|
+
export const ANSI_BOLD = "\x1b[1m";
|
|
23
|
+
export const ANSI_ITALIC = "\x1b[3m";
|
|
24
|
+
export const ANSI_UNDERLINE = "\x1b[4m";
|
|
25
|
+
export const ANSI_STRIKE = "\x1b[9m";
|
|
26
|
+
export const ANSI_INVERSE = "\x1b[7m";
|
|
27
|
+
// Reset.
|
|
28
|
+
export const ANSI_RESET = "\x1b[0m";
|
package/util/array.d.ts
CHANGED
package/util/async.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ImmutableArray } from "./array.js";
|
|
2
|
-
import type { ValueCallback } from "./callback.js";
|
|
3
|
-
import type { Report } from "./error.js";
|
|
2
|
+
import type { ErrorCallback, ValueCallback } from "./callback.js";
|
|
4
3
|
/** Is a value an asynchronous value implementing a `then()` function. */
|
|
5
4
|
export declare function isAsync<T>(value: PromiseLike<T> | T): value is PromiseLike<T>;
|
|
6
5
|
/** Is a value a synchronous value. */
|
|
@@ -39,14 +38,14 @@ export declare abstract class AbstractPromise<T> extends Promise<T> {
|
|
|
39
38
|
/** Resolve this promise with a value. */
|
|
40
39
|
protected readonly _resolve: ValueCallback<T>;
|
|
41
40
|
/** Reject this promise with a reason. */
|
|
42
|
-
protected readonly _reject:
|
|
41
|
+
protected readonly _reject: ErrorCallback;
|
|
43
42
|
constructor();
|
|
44
43
|
}
|
|
45
44
|
/** Deferred allows you to access the internal resolve/reject callbacks of a `Promise` */
|
|
46
45
|
export type Deferred<T> = {
|
|
47
46
|
promise: Promise<T>;
|
|
48
47
|
resolve: ValueCallback<T>;
|
|
49
|
-
reject:
|
|
48
|
+
reject: ErrorCallback;
|
|
50
49
|
};
|
|
51
50
|
/**
|
|
52
51
|
* Get a deferred to access the `resolve()` and `reject()` functions of a promise.
|
package/util/boolean.d.ts
CHANGED
package/util/bytes.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyCaller } from "
|
|
1
|
+
import type { AnyCaller } from "./function.js";
|
|
2
2
|
/** Types that can be converted to a `Uint8Array` byte sequence. */
|
|
3
3
|
export type PossibleBytes = Uint8Array | ArrayBuffer | string;
|
|
4
4
|
/** Assert that an unknown value is a `Uint8Array` byte sequence. */
|
package/util/callback.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export type AsyncValueCallback<T = void> = (value: T) => void | PromiseLike<void
|
|
|
11
11
|
export type ValuesCallback<T extends Arguments = []> = (...values: T) => void;
|
|
12
12
|
/** Callback function that receives multiple values and possibly returns a promise that must be handled. */
|
|
13
13
|
export type AsyncValuesCallback<T extends Arguments = []> = (...values: T) => void | PromiseLike<void>;
|
|
14
|
+
/** Callback function that receives an error. */
|
|
15
|
+
export type ErrorCallback = (reason: unknown) => void;
|
|
14
16
|
/** Safely call a callback function (possibly with a value). */
|
|
15
17
|
export declare function call<A extends Arguments = []>(callback: (...v: A) => unknown, ...values: A): void;
|
|
16
18
|
/** Return a callback function that safely calls a callback function (possibly with a value). */
|
package/util/color.d.ts
CHANGED
package/util/data.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { ImmutableArray } from "./array.js";
|
|
3
2
|
import type { EntryObject } from "./entry.js";
|
|
3
|
+
import type { AnyCaller } from "./function.js";
|
|
4
4
|
import type { DeepPartial } from "./object.js";
|
|
5
5
|
/** Data object. */
|
|
6
6
|
export type Data = {
|
package/util/date.d.ts
CHANGED
package/util/dictionary.d.ts
CHANGED
package/util/entity.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyCaller } from "
|
|
1
|
+
import type { AnyCaller } from "./function.js";
|
|
2
2
|
import type { Optional } from "./optional.js";
|
|
3
3
|
/** Entity strings combine a type and ID, e.g. `challenge:a1b2c3` */
|
|
4
4
|
export type Entity<T extends string = string> = `${T}:${string}`;
|
package/util/equal.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { ImmutableArray } from "./array.js";
|
|
3
2
|
import type { Match } from "./filter.js";
|
|
3
|
+
import type { AnyCaller } from "./function.js";
|
|
4
4
|
import type { ImmutableMap } from "./map.js";
|
|
5
5
|
import type { ImmutableObject } from "./object.js";
|
|
6
6
|
/** Assert two values are equal. */
|
package/util/error.d.ts
CHANGED
package/util/error.js
CHANGED
package/util/file.d.ts
CHANGED
package/util/function.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import type { AnyConstructor } from "./class.js";
|
|
1
2
|
/** Unknown function. */
|
|
2
3
|
export type UnknownFunction = (...args: unknown[]) => unknown;
|
|
3
4
|
/** Any function (purposefully as wide as possible for use with `extends X` or `is X` statements). */
|
|
4
5
|
export type AnyFunction = (...args: any) => any;
|
|
6
|
+
/** Any calling function or constructor, usually referring to something that can call in the current scope that can appear in a stack trace. */
|
|
7
|
+
export type AnyCaller = AnyFunction | AnyConstructor;
|
|
5
8
|
/** Is a value a function? */
|
|
6
9
|
export declare function isFunction(value: unknown): value is AnyFunction;
|
|
7
10
|
/** Assert that a value is a function. */
|
package/util/http.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import { RequestError } from "../error/RequestError.js";
|
|
3
2
|
import { ResponseError } from "../error/ResponseError.js";
|
|
3
|
+
import type { AnyCaller } from "./function.js";
|
|
4
4
|
/** A handler function takes a `Request` and returns a `Response` (possibly asynchronously). */
|
|
5
5
|
export type RequestHandler = (request: Request) => Response | Promise<Response>;
|
|
6
6
|
export declare function _getMessageJSON(message: Request | Response, MessageError: typeof RequestError | typeof ResponseError, caller: AnyCaller): Promise<unknown>;
|
|
@@ -9,9 +9,9 @@ export declare function _getMessageContent(message: Request | Response, MessageE
|
|
|
9
9
|
/**
|
|
10
10
|
* Get the body content of an HTTP `Request` based on its content type, or throw `RequestError` if the content could not be parsed.
|
|
11
11
|
*
|
|
12
|
-
* @returns string If content type is `text/plain` (including empty string if it's empty).
|
|
13
12
|
* @returns unknown If content type is `application/json` and has valid JSON (including `undefined` if the content is empty).
|
|
14
13
|
* @returns unknown If content type is `multipart/form-data` then convert it to a simple `Data` object.
|
|
14
|
+
* @returns string If content type is `text/plain` or anything else (including `""` empty string if it's empty).
|
|
15
15
|
*
|
|
16
16
|
* @throws RequestError if the content is not `text/plain`, or `application/json` with valid JSON.
|
|
17
17
|
*/
|
|
@@ -19,10 +19,28 @@ export declare function getRequestContent(message: Request, caller?: AnyCaller):
|
|
|
19
19
|
/**
|
|
20
20
|
* Get the body content of an HTTP `Response` based on its content type, or throw `ResponseError` if the content could not be parsed.
|
|
21
21
|
*
|
|
22
|
-
* @returns string If content type is `text/plain` (including empty string if it's empty).
|
|
23
22
|
* @returns unknown If content type is `application/json` and has valid JSON (including `undefined` if the content is empty).
|
|
24
23
|
* @returns unknown If content type is `multipart/form-data` then convert it to a simple `Data` object.
|
|
24
|
+
* @returns string If content type is `text/plain` or anything else (including `""` empty string if it's empty).
|
|
25
25
|
*
|
|
26
26
|
* @throws RequestError if the content is not `text/plain` or `application/json` with valid JSON.
|
|
27
27
|
*/
|
|
28
28
|
export declare function getResponseContent(message: Response, caller?: AnyCaller): Promise<unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Get the body content of an HTTP `Request` as JSON, or throw `RequestError` if the content could not be parsed.
|
|
31
|
+
* - Doesn't check the `Content-Type` header, so it can be used for any request.
|
|
32
|
+
*
|
|
33
|
+
* @returns unknown The parsed JSON content of the request body, or `undefined` if the body is empty.
|
|
34
|
+
*
|
|
35
|
+
* @throws RequestError if the content is not valid JSON.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getRequestJSON(message: Request, caller?: AnyCaller): Promise<unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* Get the body content of an HTTP `Response` as JSON, or throw `ResponseError` if the content could not be parsed.
|
|
40
|
+
* - Doesn't check the `Content-Type` header, so it can be used for any response.
|
|
41
|
+
*
|
|
42
|
+
* @returns unknown The parsed JSON content of the response body, or `undefined` if the body is empty.
|
|
43
|
+
*
|
|
44
|
+
* @throws RequestError if the content is not valid JSON.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getResponseJSON(message: Response, caller?: AnyCaller): Promise<unknown>;
|
package/util/http.js
CHANGED
|
@@ -22,20 +22,18 @@ export async function _getMessageFormData(message, MessageError, caller) {
|
|
|
22
22
|
}
|
|
23
23
|
export function _getMessageContent(message, MessageError, caller) {
|
|
24
24
|
const type = message.headers.get("Content-Type");
|
|
25
|
-
if (type?.startsWith("text/plain"))
|
|
26
|
-
return message.text();
|
|
27
25
|
if (type?.startsWith("application/json"))
|
|
28
26
|
return _getMessageJSON(message, MessageError, caller);
|
|
29
27
|
if (type?.startsWith("multipart/form-data"))
|
|
30
28
|
return _getMessageFormData(message, MessageError, caller);
|
|
31
|
-
|
|
29
|
+
return message.text();
|
|
32
30
|
}
|
|
33
31
|
/**
|
|
34
32
|
* Get the body content of an HTTP `Request` based on its content type, or throw `RequestError` if the content could not be parsed.
|
|
35
33
|
*
|
|
36
|
-
* @returns string If content type is `text/plain` (including empty string if it's empty).
|
|
37
34
|
* @returns unknown If content type is `application/json` and has valid JSON (including `undefined` if the content is empty).
|
|
38
35
|
* @returns unknown If content type is `multipart/form-data` then convert it to a simple `Data` object.
|
|
36
|
+
* @returns string If content type is `text/plain` or anything else (including `""` empty string if it's empty).
|
|
39
37
|
*
|
|
40
38
|
* @throws RequestError if the content is not `text/plain`, or `application/json` with valid JSON.
|
|
41
39
|
*/
|
|
@@ -47,12 +45,34 @@ export function getRequestContent(message, caller = getRequestContent) {
|
|
|
47
45
|
/**
|
|
48
46
|
* Get the body content of an HTTP `Response` based on its content type, or throw `ResponseError` if the content could not be parsed.
|
|
49
47
|
*
|
|
50
|
-
* @returns string If content type is `text/plain` (including empty string if it's empty).
|
|
51
48
|
* @returns unknown If content type is `application/json` and has valid JSON (including `undefined` if the content is empty).
|
|
52
49
|
* @returns unknown If content type is `multipart/form-data` then convert it to a simple `Data` object.
|
|
50
|
+
* @returns string If content type is `text/plain` or anything else (including `""` empty string if it's empty).
|
|
53
51
|
*
|
|
54
52
|
* @throws RequestError if the content is not `text/plain` or `application/json` with valid JSON.
|
|
55
53
|
*/
|
|
56
54
|
export function getResponseContent(message, caller = getResponseContent) {
|
|
57
55
|
return _getMessageContent(message, ResponseError, caller);
|
|
58
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the body content of an HTTP `Request` as JSON, or throw `RequestError` if the content could not be parsed.
|
|
59
|
+
* - Doesn't check the `Content-Type` header, so it can be used for any request.
|
|
60
|
+
*
|
|
61
|
+
* @returns unknown The parsed JSON content of the request body, or `undefined` if the body is empty.
|
|
62
|
+
*
|
|
63
|
+
* @throws RequestError if the content is not valid JSON.
|
|
64
|
+
*/
|
|
65
|
+
export function getRequestJSON(message, caller = getRequestJSON) {
|
|
66
|
+
return _getMessageJSON(message, RequestError, caller);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the body content of an HTTP `Response` as JSON, or throw `ResponseError` if the content could not be parsed.
|
|
70
|
+
* - Doesn't check the `Content-Type` header, so it can be used for any response.
|
|
71
|
+
*
|
|
72
|
+
* @returns unknown The parsed JSON content of the response body, or `undefined` if the body is empty.
|
|
73
|
+
*
|
|
74
|
+
* @throws RequestError if the content is not valid JSON.
|
|
75
|
+
*/
|
|
76
|
+
export function getResponseJSON(message, caller = getResponseJSON) {
|
|
77
|
+
return _getMessageJSON(message, ResponseError, caller);
|
|
78
|
+
}
|
package/util/index.d.ts
CHANGED
package/util/index.js
CHANGED
package/util/jwt.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import { type PossibleBytes } from "./bytes.js";
|
|
3
2
|
import type { Data } from "./data.js";
|
|
3
|
+
import type { AnyCaller } from "./function.js";
|
|
4
4
|
/**
|
|
5
5
|
* Encode a JWT and return the string token.
|
|
6
6
|
* - Currently only supports HMAC SHA-512 signing.
|
package/util/link.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { ImmutableArray } from "./array.js";
|
|
2
|
+
import type { AnyCaller } from "./function.js";
|
|
3
3
|
import type { Optional } from "./optional.js";
|
|
4
4
|
import type { Path } from "./path.js";
|
|
5
5
|
import { type PossibleURL } from "./url.js";
|
package/util/map.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { Entry } from "./entry.js";
|
|
2
|
+
import type { AnyCaller } from "./function.js";
|
|
3
3
|
/** `Map` that cannot be changed. */
|
|
4
4
|
export type ImmutableMap<K = unknown, T = unknown> = ReadonlyMap<K, T>;
|
|
5
5
|
/** Class for a `Map` that cannot be changed (so you can extend `Map` while implementing `ImmutableMap`). */
|
package/util/null.d.ts
CHANGED
package/util/number.d.ts
CHANGED
package/util/optional.d.ts
CHANGED
package/util/path.d.ts
CHANGED
package/util/sequence.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AsyncValueCallback, ValueCallback } from "./callback.js";
|
|
2
|
+
import type { ErrorCallback } from "./callback.js";
|
|
2
3
|
import { STOP } from "./constants.js";
|
|
3
|
-
import type { Report } from "./error.js";
|
|
4
4
|
import type { Stop } from "./start.js";
|
|
5
5
|
/**
|
|
6
6
|
* Is a value an async iterable object?
|
|
@@ -15,4 +15,4 @@ export declare function repeatDelay(ms: number): AsyncIterable<number>;
|
|
|
15
15
|
/** Dispatch items in a sequence to a (possibly async) callback. */
|
|
16
16
|
export declare function callSequence<T>(sequence: AsyncIterable<T>, callback: AsyncValueCallback<T>): AsyncIterable<T>;
|
|
17
17
|
/** Pull values from a sequence until the returned function is called. */
|
|
18
|
-
export declare function runSequence<T>(sequence: AsyncIterable<T>, onNext?: ValueCallback<T>, onError?:
|
|
18
|
+
export declare function runSequence<T>(sequence: AsyncIterable<T>, onNext?: ValueCallback<T>, onError?: ErrorCallback): Stop;
|
package/util/set.d.ts
CHANGED
package/util/source.d.ts
CHANGED
package/util/string.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { ImmutableArray } from "./array.js";
|
|
2
|
+
import type { AnyCaller } from "./function.js";
|
|
3
3
|
/**
|
|
4
4
|
* Type that never matches the `string` type.
|
|
5
5
|
* - `string` itself is iterable (iterating over its individual characters) and implements `Iterable<string>`
|
package/util/template.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
1
|
import type { ImmutableArray } from "./array.js";
|
|
3
2
|
import { type ImmutableDictionary } from "./dictionary.js";
|
|
3
|
+
import type { AnyCaller } from "./function.js";
|
|
4
4
|
import type { NotString } from "./string.js";
|
|
5
5
|
/** Dictionary of named template values in `{ myPlaceholder: "value" }` format. */
|
|
6
6
|
export type TemplateDictionary = ImmutableDictionary<string>;
|
package/util/time.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyCaller } from "
|
|
1
|
+
import type { AnyCaller } from "./function.js";
|
|
2
2
|
/** Class representing a time in the day in 24 hour format in the user's current locale. */
|
|
3
3
|
export declare class Time {
|
|
4
4
|
/** Make a new `Time` instance from a time string. */
|
package/util/undefined.d.ts
CHANGED
package/util/url.d.ts
CHANGED
package/util/validate.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BaseError, BaseErrorOptions } from "../error/BaseError.js";
|
|
2
2
|
import type { ImmutableArray, PossibleArray } from "./array.js";
|
|
3
3
|
import type { Constructor } from "./class.js";
|
|
4
4
|
import type { Data } from "./data.js";
|
|
5
5
|
import type { ImmutableDictionary } from "./dictionary.js";
|
|
6
|
+
import type { AnyCaller } from "./function.js";
|
|
6
7
|
import type { DeepPartial } from "./object.js";
|
|
7
8
|
/** Object that can validate an unknown value with its `validate()` method. */
|
|
8
9
|
export interface Validator<T> {
|