@apisr/response 0.0.1 → 0.0.2
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/dist/error/default.d.mts +8 -0
- package/dist/error/default.mjs +103 -0
- package/dist/error/index.d.mts +30 -0
- package/dist/error/index.mjs +3 -0
- package/dist/handler.d.mts +127 -0
- package/dist/handler.mjs +272 -0
- package/dist/headers.d.mts +8 -0
- package/dist/headers.mjs +9 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.mjs +18 -0
- package/dist/options/base.d.mts +28 -0
- package/dist/options/binary.d.mts +13 -0
- package/dist/options/binary.mjs +7 -0
- package/dist/options/error.d.mts +31 -0
- package/dist/options/error.mjs +7 -0
- package/dist/options/index.d.mts +15 -0
- package/dist/options/index.mjs +15 -0
- package/dist/options/json.d.mts +19 -0
- package/dist/options/json.mjs +7 -0
- package/dist/options/meta.d.mts +20 -0
- package/dist/options/meta.mjs +7 -0
- package/dist/response/base.d.mts +19 -0
- package/dist/response/base.mjs +16 -0
- package/dist/response/binary/index.d.mts +10 -0
- package/dist/response/binary/index.mjs +9 -0
- package/dist/response/default.d.mts +11 -0
- package/dist/response/error/index.d.mts +28 -0
- package/dist/response/error/index.mjs +23 -0
- package/dist/response/index.mjs +7 -0
- package/dist/response/json/index.d.mts +22 -0
- package/dist/response/json/index.mjs +29 -0
- package/dist/response/meta/index.d.mts +7 -0
- package/dist/response/text/index.d.mts +9 -0
- package/dist/response/text/index.mjs +9 -0
- package/dist/schema/dist/index.mjs +124 -0
- package/dist/symbol.d.mts +4 -0
- package/dist/symbol.mjs +5 -0
- package/dist/types.d.mts +6 -0
- package/dist/zod/dist/index.mjs +17 -0
- package/package.json +3 -3
- package/src/headers.ts +11 -11
- package/src/index.ts +3 -3
- package/src/options/base.ts +24 -25
- package/src/options/binary.ts +5 -5
- package/src/options/index.ts +12 -12
- package/src/response/base.ts +16 -13
- package/src/response/binary/index.ts +2 -4
- package/src/response/default.ts +4 -4
- package/src/response/error/index.ts +42 -38
- package/src/response/index.ts +1 -1
- package/src/response/json/index.ts +44 -40
- package/src/response/meta/index.ts +3 -3
- package/src/response/text/index.ts +2 -4
- package/src/types.ts +3 -5
- package/tests/json-symbol.test.ts +7 -7
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ErrorOptions } from "../options/error.mjs";
|
|
2
|
+
import { Options } from "../options/base.mjs";
|
|
3
|
+
import { ErrorRegistry } from "./index.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/error/default.d.ts
|
|
6
|
+
declare function generateDefaultErrors<TOptions extends Options>(_mapDefaultError: ErrorOptions.Base["mapDefaultError"]): ErrorRegistry<TOptions>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { generateDefaultErrors };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { zod } from "../zod/dist/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/error/default.ts
|
|
4
|
+
function generateDefaultErrors(_mapDefaultError) {
|
|
5
|
+
const mapDefaultError = _mapDefaultError ?? ((err) => err);
|
|
6
|
+
const inputSchema = zod.object({ cause: zod.any().optional() }).optional();
|
|
7
|
+
return {
|
|
8
|
+
unauthorized: {
|
|
9
|
+
handler: ({ input }) => mapDefaultError({
|
|
10
|
+
message: "Unauthorized",
|
|
11
|
+
code: "UNAUTHORIZED",
|
|
12
|
+
name: "UnauthorizedError",
|
|
13
|
+
cause: input.cause
|
|
14
|
+
}),
|
|
15
|
+
options: {
|
|
16
|
+
input: inputSchema,
|
|
17
|
+
status: 401,
|
|
18
|
+
statusText: "Unauthorized"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
forbidden: {
|
|
22
|
+
handler: ({ input }) => mapDefaultError({
|
|
23
|
+
message: "Forbidden",
|
|
24
|
+
code: "FORBIDDEN",
|
|
25
|
+
name: "ForbiddenError",
|
|
26
|
+
cause: input.cause
|
|
27
|
+
}),
|
|
28
|
+
options: {
|
|
29
|
+
input: inputSchema,
|
|
30
|
+
status: 403,
|
|
31
|
+
statusText: "Forbidden"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
notFound: {
|
|
35
|
+
handler: ({ input }) => mapDefaultError({
|
|
36
|
+
message: "Not Found",
|
|
37
|
+
code: "NOT_FOUND",
|
|
38
|
+
name: "NotFoundError",
|
|
39
|
+
cause: input.cause
|
|
40
|
+
}),
|
|
41
|
+
options: {
|
|
42
|
+
input: inputSchema,
|
|
43
|
+
status: 404,
|
|
44
|
+
statusText: "Not Found"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
badRequest: {
|
|
48
|
+
handler: ({ input }) => mapDefaultError({
|
|
49
|
+
message: "Bad Request",
|
|
50
|
+
code: "BAD_REQUEST",
|
|
51
|
+
name: "BadRequestError",
|
|
52
|
+
cause: input.cause
|
|
53
|
+
}),
|
|
54
|
+
options: {
|
|
55
|
+
input: inputSchema,
|
|
56
|
+
status: 400,
|
|
57
|
+
statusText: "Bad Request"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
conflict: {
|
|
61
|
+
handler: ({ input }) => mapDefaultError({
|
|
62
|
+
message: "Conflict",
|
|
63
|
+
code: "CONFLICT",
|
|
64
|
+
name: "ConflictError",
|
|
65
|
+
cause: input.cause
|
|
66
|
+
}),
|
|
67
|
+
options: {
|
|
68
|
+
input: inputSchema,
|
|
69
|
+
status: 409,
|
|
70
|
+
statusText: "Conflict"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
tooMany: {
|
|
74
|
+
handler: ({ input }) => mapDefaultError({
|
|
75
|
+
message: "Too Many Requests",
|
|
76
|
+
code: "TOO_MANY_REQUESTS",
|
|
77
|
+
name: "TooManyRequestsError",
|
|
78
|
+
cause: input.cause
|
|
79
|
+
}),
|
|
80
|
+
options: {
|
|
81
|
+
input: inputSchema,
|
|
82
|
+
status: 429,
|
|
83
|
+
statusText: "Too Many Requests"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
internal: {
|
|
87
|
+
handler: ({ input }) => mapDefaultError({
|
|
88
|
+
message: "Internal Server Error",
|
|
89
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
90
|
+
name: "InternalServerError",
|
|
91
|
+
cause: input.cause
|
|
92
|
+
}),
|
|
93
|
+
options: {
|
|
94
|
+
input: inputSchema,
|
|
95
|
+
status: 500,
|
|
96
|
+
statusText: "Internal Server Error"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
export { generateDefaultErrors };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ErrorOptions } from "../options/error.mjs";
|
|
2
|
+
import { Options } from "../options/base.mjs";
|
|
3
|
+
import { generateDefaultErrors } from "./default.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/error/index.d.ts
|
|
6
|
+
type DefaultErrorTypes = "unauthorized" | "forbidden" | "notFound" | "badRequest" | "conflict" | "tooMany" | "internal";
|
|
7
|
+
type DefaultError = {
|
|
8
|
+
message: string;
|
|
9
|
+
code: string;
|
|
10
|
+
name: string;
|
|
11
|
+
cause?: unknown;
|
|
12
|
+
stack?: string[];
|
|
13
|
+
};
|
|
14
|
+
type ErrorHandler<TOptions extends Options, THandlerOptions extends ErrorHandlerOptions | undefined> = (data: {
|
|
15
|
+
meta: TOptions["meta"] extends undefined ? never : Infer<ExtractSchema<TOptions["meta"]>>;
|
|
16
|
+
input: THandlerOptions extends undefined ? never : Infer<Exclude<THandlerOptions, undefined>["input"]>;
|
|
17
|
+
}) => ErrorOptions.InferedSchema<TOptions>;
|
|
18
|
+
interface ErrorHandlerOptions<TSchema extends Schema = Schema> {
|
|
19
|
+
input?: TSchema;
|
|
20
|
+
status?: number;
|
|
21
|
+
statusText?: string;
|
|
22
|
+
validationType?: ValidationType;
|
|
23
|
+
}
|
|
24
|
+
type ErrorDefinition<TOptions extends Options, THandlerOptions extends ErrorHandlerOptions | undefined> = {
|
|
25
|
+
handler: ErrorHandler<TOptions, THandlerOptions> | ErrorOptions.InferedSchema<TOptions>;
|
|
26
|
+
options: THandlerOptions;
|
|
27
|
+
};
|
|
28
|
+
type ErrorRegistry<TOptions extends Options> = Record<string, ErrorDefinition<TOptions, any>>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { DefaultError, DefaultErrorTypes, ErrorDefinition, ErrorHandler, ErrorHandlerOptions, ErrorRegistry };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { PromiseOr } from "./types.mjs";
|
|
2
|
+
import { MetaOptions } from "./options/meta.mjs";
|
|
3
|
+
import { ErrorOptions } from "./options/error.mjs";
|
|
4
|
+
import { BaseResponse } from "./response/base.mjs";
|
|
5
|
+
import { JsonResponse } from "./response/json/index.mjs";
|
|
6
|
+
import { JsonOptions } from "./options/json.mjs";
|
|
7
|
+
import { Binary, BinaryResponse } from "./response/binary/index.mjs";
|
|
8
|
+
import { BinaryOptions } from "./options/binary.mjs";
|
|
9
|
+
import { ErrorResponse } from "./response/error/index.mjs";
|
|
10
|
+
import { DefaultResponse } from "./response/default.mjs";
|
|
11
|
+
import { Options } from "./options/base.mjs";
|
|
12
|
+
import { options as options$1 } from "./options/index.mjs";
|
|
13
|
+
import { DefaultErrorTypes, ErrorDefinition, ErrorHandler, ErrorHandlerOptions, ErrorRegistry } from "./error/index.mjs";
|
|
14
|
+
import { TextResponse } from "./response/text/index.mjs";
|
|
15
|
+
|
|
16
|
+
//#region src/handler.d.ts
|
|
17
|
+
declare function createResponseHandler<TMeta extends MetaOptions.Base, TError extends ErrorOptions.Base, TJson extends JsonOptions.Base, TBinary extends BinaryOptions.Base, TOptions extends Options<TMeta, TError, TJson, TBinary> = Options<TMeta, TError, TJson, TBinary>>(opts: TOptions | ((options: typeof options$1) => TOptions)): ResponseHandler<TMeta, TError, TJson, TBinary, TOptions, {}>;
|
|
18
|
+
type ResolveOptionsMeta<TOptions extends Options> = TOptions["meta"] extends undefined ? never : Exclude<TOptions["meta"], undefined>;
|
|
19
|
+
type AnyResponseHandler = ResponseHandler<any, any, any, any, any>;
|
|
20
|
+
declare class ResponseHandler<TMeta extends MetaOptions.Base, TError extends ErrorOptions.Base, TJson extends JsonOptions.Base, TBinary extends BinaryOptions.Base, TOptions extends Options<TMeta, TError, TJson, TBinary>, TErrors extends ErrorRegistry<TOptions> = {}> {
|
|
21
|
+
options: TOptions;
|
|
22
|
+
private errors;
|
|
23
|
+
private preasignedMeta;
|
|
24
|
+
/**
|
|
25
|
+
* Create a `ResponseHandler` instance.
|
|
26
|
+
*
|
|
27
|
+
* Prefer using {@link createResponseHandler} instead of calling this directly.
|
|
28
|
+
*
|
|
29
|
+
* @param params - Constructor params.
|
|
30
|
+
* @param params.options - Handler options.
|
|
31
|
+
* @param params.errors - Optional pre-defined error registry.
|
|
32
|
+
* @param params.preasignedMeta - Optional meta merged into each response.
|
|
33
|
+
*/
|
|
34
|
+
constructor({
|
|
35
|
+
options,
|
|
36
|
+
errors,
|
|
37
|
+
preasignedMeta
|
|
38
|
+
}: {
|
|
39
|
+
options: TOptions;
|
|
40
|
+
errors?: TErrors;
|
|
41
|
+
preasignedMeta?: Partial<MetaOptions.InferedSchema<TOptions>>;
|
|
42
|
+
});
|
|
43
|
+
fail<TKey extends keyof TErrors & string, TInput extends Infer<TErrors[TKey]["options"]["input"]>>(name: TKey, input?: TInput): ErrorResponse.Base<TKey, MetaOptions.InferedSchema<TOptions>, TInput>;
|
|
44
|
+
fail(name: DefaultErrorTypes, input?: Record<string, any>): ErrorResponse.Base<DefaultErrorTypes, MetaOptions.InferedSchema<TOptions>, Record<string, any>>;
|
|
45
|
+
/**
|
|
46
|
+
* Create a JSON `Response`.
|
|
47
|
+
*
|
|
48
|
+
* Validates input/output using configured schemas (if present), applies `onData` transformation,
|
|
49
|
+
* and resolves/merges headers.
|
|
50
|
+
*
|
|
51
|
+
* @typeParam IInput - Inferred input type for configured JSON input schema.
|
|
52
|
+
* @param _input - JSON input value.
|
|
53
|
+
* @param options - Optional response init options.
|
|
54
|
+
* @returns JSON response instance.
|
|
55
|
+
*/
|
|
56
|
+
json<IInput extends JsonOptions.InferedSchema<TOptions>>(_input: IInput, options?: JsonResponse.Options): JsonResponse.Base<IInput>;
|
|
57
|
+
/**
|
|
58
|
+
* Create a plain text `Response`.
|
|
59
|
+
*
|
|
60
|
+
* @param text - Raw text response body.
|
|
61
|
+
* @param options - Optional response init options.
|
|
62
|
+
* @returns Text response instance.
|
|
63
|
+
*/
|
|
64
|
+
text(text: string, options?: TextResponse.Options): TextResponse.Base;
|
|
65
|
+
/**
|
|
66
|
+
* Create a binary `Response`.
|
|
67
|
+
*
|
|
68
|
+
* Applies optional `binary.onData` transformation and resolves/merges headers.
|
|
69
|
+
*
|
|
70
|
+
* @param binary - Binary payload (Blob/ArrayBuffer/Uint8Array/ReadableStream).
|
|
71
|
+
* @param options - Optional response init options.
|
|
72
|
+
* @returns Binary response instance.
|
|
73
|
+
*/
|
|
74
|
+
binary(binary: Binary, options?: BinaryResponse.Options): BinaryResponse.Base;
|
|
75
|
+
/**
|
|
76
|
+
* Create a new `ResponseHandler` with preassigned meta.
|
|
77
|
+
*
|
|
78
|
+
* The provided meta is validated against the configured meta schema (if present).
|
|
79
|
+
*
|
|
80
|
+
* @param _meta - Partial meta that will be merged into each next response.
|
|
81
|
+
* @returns New `ResponseHandler` instance.
|
|
82
|
+
*/
|
|
83
|
+
withMeta(_meta: Partial<MetaOptions.InferedSchema<TOptions>>): ResponseHandler<TMeta, TError, TJson, TBinary, TOptions, TErrors>;
|
|
84
|
+
/**
|
|
85
|
+
* Define a named error handler.
|
|
86
|
+
*
|
|
87
|
+
* Returns a new `ResponseHandler` instance with the extended error registry.
|
|
88
|
+
*
|
|
89
|
+
* @typeParam TName - Error name.
|
|
90
|
+
* @typeParam THandlerOptions - Handler options type.
|
|
91
|
+
* @param name - Error name to register.
|
|
92
|
+
* @param handler - Error handler function or static error output.
|
|
93
|
+
* @param options - Error handler options (e.g. input schema).
|
|
94
|
+
* @returns New `ResponseHandler` instance with the new error registered.
|
|
95
|
+
*/
|
|
96
|
+
defineError<TName extends string, THandlerOptions extends ErrorHandlerOptions | undefined>(name: TName, handler: ErrorHandler<TOptions, THandlerOptions> | ErrorOptions.InferedSchema<TOptions>, options?: THandlerOptions): ResponseHandler<TMeta, TError, TJson, TBinary, TOptions, TErrors & Record<TName, ErrorDefinition<TOptions, THandlerOptions>>>;
|
|
97
|
+
mapResponse(raw: {
|
|
98
|
+
data: JsonOptions.InferedSchemaFromBase<TJson> | Binary | string | undefined;
|
|
99
|
+
error: ErrorOptions.InferedSchemaFromBase<TError> | undefined;
|
|
100
|
+
}): PromiseOr<Response>;
|
|
101
|
+
/**
|
|
102
|
+
* Returns response that mapped into `DefaultResponse`:
|
|
103
|
+
* ```
|
|
104
|
+
* export interface DefaultResponse<TData = unknown> {
|
|
105
|
+
* success: boolean;
|
|
106
|
+
* error: ErrorResponse.Base<any, any, any> | null;
|
|
107
|
+
* data: TData | null;
|
|
108
|
+
* metadata: Record<string, unknown>;
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
* @param raw
|
|
112
|
+
* @returns Response
|
|
113
|
+
*/
|
|
114
|
+
defaultMapResponse(raw: {
|
|
115
|
+
data: JsonOptions.InferedSchemaFromBase<TJson> | Binary | string | undefined;
|
|
116
|
+
error: ErrorOptions.InferedSchemaFromBase<TError> | undefined;
|
|
117
|
+
}): BaseResponse.Base<DefaultResponse> | BaseResponse.Base<Binary>;
|
|
118
|
+
/**
|
|
119
|
+
* Prepare `meta` by merging preassigned meta (from `withMeta`) with default meta (if any).
|
|
120
|
+
*
|
|
121
|
+
* @returns Resolved meta object.
|
|
122
|
+
*/
|
|
123
|
+
private prepareMeta;
|
|
124
|
+
private isBinaryData;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { AnyResponseHandler, ResolveOptionsMeta, ResponseHandler, createResponseHandler };
|
package/dist/handler.mjs
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { checkSchema } from "./schema/dist/index.mjs";
|
|
2
|
+
import { generateDefaultErrors } from "./error/default.mjs";
|
|
3
|
+
import { resolveHeaders } from "./headers.mjs";
|
|
4
|
+
import { options } from "./options/index.mjs";
|
|
5
|
+
import { BaseResponse } from "./response/base.mjs";
|
|
6
|
+
import { BinaryResponse } from "./response/binary/index.mjs";
|
|
7
|
+
import { ErrorResponse } from "./response/error/index.mjs";
|
|
8
|
+
import { JsonResponse } from "./response/json/index.mjs";
|
|
9
|
+
import { TextResponse } from "./response/text/index.mjs";
|
|
10
|
+
|
|
11
|
+
//#region src/handler.ts
|
|
12
|
+
function createResponseHandler(opts) {
|
|
13
|
+
return new ResponseHandler({ options: typeof opts === "function" ? opts(options) : opts });
|
|
14
|
+
}
|
|
15
|
+
var ResponseHandler = class ResponseHandler {
|
|
16
|
+
options;
|
|
17
|
+
errors;
|
|
18
|
+
preasignedMeta;
|
|
19
|
+
/**
|
|
20
|
+
* Create a `ResponseHandler` instance.
|
|
21
|
+
*
|
|
22
|
+
* Prefer using {@link createResponseHandler} instead of calling this directly.
|
|
23
|
+
*
|
|
24
|
+
* @param params - Constructor params.
|
|
25
|
+
* @param params.options - Handler options.
|
|
26
|
+
* @param params.errors - Optional pre-defined error registry.
|
|
27
|
+
* @param params.preasignedMeta - Optional meta merged into each response.
|
|
28
|
+
*/
|
|
29
|
+
constructor({ options: options$1, errors, preasignedMeta }) {
|
|
30
|
+
this.options = options$1;
|
|
31
|
+
this.errors = errors ?? generateDefaultErrors(options$1?.error?.mapDefaultError) ?? {};
|
|
32
|
+
this.preasignedMeta = preasignedMeta ?? {};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create an `ErrorResponse` by name.
|
|
36
|
+
*
|
|
37
|
+
* If the error has an `input` schema, the `input` is validated according to `validationType`.
|
|
38
|
+
* The resulting error response also includes prepared `meta`.
|
|
39
|
+
*
|
|
40
|
+
* @param name - Error name (registered via `defineError` or built-in default types).
|
|
41
|
+
* @param _input - Optional error payload to validate (if a schema exists).
|
|
42
|
+
* @returns Error response instance.
|
|
43
|
+
*/
|
|
44
|
+
fail(name, _input) {
|
|
45
|
+
const error = this.errors[name];
|
|
46
|
+
const errorOptions = error?.options;
|
|
47
|
+
const input = errorOptions?.input ? checkSchema(errorOptions?.input, _input, { validationType: errorOptions?.validationType ?? "parse" }) : _input;
|
|
48
|
+
const meta = this.prepareMeta();
|
|
49
|
+
const handler = error?.handler;
|
|
50
|
+
const output = typeof handler === "function" ? handler({
|
|
51
|
+
meta,
|
|
52
|
+
input
|
|
53
|
+
}) : handler;
|
|
54
|
+
const status = errorOptions?.status ?? 500;
|
|
55
|
+
const statusText = errorOptions?.statusText ?? "Unknown";
|
|
56
|
+
return new ErrorResponse.Base({
|
|
57
|
+
meta,
|
|
58
|
+
name,
|
|
59
|
+
output,
|
|
60
|
+
status,
|
|
61
|
+
statusText
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a JSON `Response`.
|
|
66
|
+
*
|
|
67
|
+
* Validates input/output using configured schemas (if present), applies `onData` transformation,
|
|
68
|
+
* and resolves/merges headers.
|
|
69
|
+
*
|
|
70
|
+
* @typeParam IInput - Inferred input type for configured JSON input schema.
|
|
71
|
+
* @param _input - JSON input value.
|
|
72
|
+
* @param options - Optional response init options.
|
|
73
|
+
* @returns JSON response instance.
|
|
74
|
+
*/
|
|
75
|
+
json(_input, options$1) {
|
|
76
|
+
const jsonOptions = this.options?.json;
|
|
77
|
+
const _output = jsonOptions?.mapData ? jsonOptions.mapData(_input) : JsonResponse.defaultOnDataOutput(_input);
|
|
78
|
+
const str = JSON.stringify(_output, null, 2);
|
|
79
|
+
const headers = {
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
...options$1?.headers ?? {},
|
|
82
|
+
...resolveHeaders(jsonOptions?.headers, { output: _output }) ?? {}
|
|
83
|
+
};
|
|
84
|
+
return new JsonResponse.Base(str, {
|
|
85
|
+
headers,
|
|
86
|
+
status: options$1?.status ?? 200,
|
|
87
|
+
statusText: options$1?.statusText,
|
|
88
|
+
output: _output
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create a plain text `Response`.
|
|
93
|
+
*
|
|
94
|
+
* @param text - Raw text response body.
|
|
95
|
+
* @param options - Optional response init options.
|
|
96
|
+
* @returns Text response instance.
|
|
97
|
+
*/
|
|
98
|
+
text(text, options$1) {
|
|
99
|
+
return new TextResponse.Base(text, { ...options$1 ?? {} });
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create a binary `Response`.
|
|
103
|
+
*
|
|
104
|
+
* Applies optional `binary.onData` transformation and resolves/merges headers.
|
|
105
|
+
*
|
|
106
|
+
* @param binary - Binary payload (Blob/ArrayBuffer/Uint8Array/ReadableStream).
|
|
107
|
+
* @param options - Optional response init options.
|
|
108
|
+
* @returns Binary response instance.
|
|
109
|
+
*/
|
|
110
|
+
binary(binary, options$1) {
|
|
111
|
+
const binaryOptions = this.options?.binary;
|
|
112
|
+
const data = binaryOptions?.mapData ? binaryOptions.mapData(binary) : binary;
|
|
113
|
+
const headers = {
|
|
114
|
+
...options$1?.headers ?? {},
|
|
115
|
+
...resolveHeaders(binaryOptions?.headers, data) ?? {}
|
|
116
|
+
};
|
|
117
|
+
return new BinaryResponse.Base(data, {
|
|
118
|
+
headers,
|
|
119
|
+
status: options$1?.status ?? 200,
|
|
120
|
+
statusText: options$1?.statusText
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create a new `ResponseHandler` with preassigned meta.
|
|
125
|
+
*
|
|
126
|
+
* The provided meta is validated against the configured meta schema (if present).
|
|
127
|
+
*
|
|
128
|
+
* @param _meta - Partial meta that will be merged into each next response.
|
|
129
|
+
* @returns New `ResponseHandler` instance.
|
|
130
|
+
*/
|
|
131
|
+
withMeta(_meta) {
|
|
132
|
+
const metaOptions = this.options.meta;
|
|
133
|
+
const meta = metaOptions?.schema ? checkSchema(metaOptions.schema.partial(), _meta, { validationType: metaOptions.validationType ?? "parse" }) : _meta;
|
|
134
|
+
return new ResponseHandler({
|
|
135
|
+
options: this.options,
|
|
136
|
+
errors: this.errors,
|
|
137
|
+
preasignedMeta: meta
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Define a named error handler.
|
|
142
|
+
*
|
|
143
|
+
* Returns a new `ResponseHandler` instance with the extended error registry.
|
|
144
|
+
*
|
|
145
|
+
* @typeParam TName - Error name.
|
|
146
|
+
* @typeParam THandlerOptions - Handler options type.
|
|
147
|
+
* @param name - Error name to register.
|
|
148
|
+
* @param handler - Error handler function or static error output.
|
|
149
|
+
* @param options - Error handler options (e.g. input schema).
|
|
150
|
+
* @returns New `ResponseHandler` instance with the new error registered.
|
|
151
|
+
*/
|
|
152
|
+
defineError(name, handler, options$1) {
|
|
153
|
+
const nextErrors = {
|
|
154
|
+
...this.errors,
|
|
155
|
+
[name]: {
|
|
156
|
+
handler,
|
|
157
|
+
options: options$1
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
return new ResponseHandler({
|
|
161
|
+
options: this.options,
|
|
162
|
+
errors: nextErrors
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
mapResponse(raw) {
|
|
166
|
+
const mapResponse = this.options.mapResponse;
|
|
167
|
+
if (this.isBinaryData(raw.data)) return this.defaultMapResponse(raw);
|
|
168
|
+
const response = this.defaultMapResponse(raw);
|
|
169
|
+
return mapResponse ? mapResponse({
|
|
170
|
+
data: raw.data,
|
|
171
|
+
error: raw.error,
|
|
172
|
+
response
|
|
173
|
+
}) : response;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns response that mapped into `DefaultResponse`:
|
|
177
|
+
* ```
|
|
178
|
+
* export interface DefaultResponse<TData = unknown> {
|
|
179
|
+
* success: boolean;
|
|
180
|
+
* error: ErrorResponse.Base<any, any, any> | null;
|
|
181
|
+
* data: TData | null;
|
|
182
|
+
* metadata: Record<string, unknown>;
|
|
183
|
+
* }
|
|
184
|
+
* ```
|
|
185
|
+
* @param raw
|
|
186
|
+
* @returns Response
|
|
187
|
+
*/
|
|
188
|
+
defaultMapResponse(raw) {
|
|
189
|
+
const options$1 = this.options;
|
|
190
|
+
const meta = this.prepareMeta();
|
|
191
|
+
const error = options$1.error?.mapError ? options$1.error?.mapError?.({
|
|
192
|
+
error: raw.error && raw.error instanceof Error ? raw.error : null,
|
|
193
|
+
meta,
|
|
194
|
+
parsedError: raw.error instanceof ErrorResponse.Base ? raw.error : null
|
|
195
|
+
}) : raw.error;
|
|
196
|
+
if (error) {
|
|
197
|
+
const status = error?.status ?? 500;
|
|
198
|
+
const statusText = error?.statusText ?? "Internal Server Error";
|
|
199
|
+
const payload$1 = {
|
|
200
|
+
error,
|
|
201
|
+
data: null,
|
|
202
|
+
success: false,
|
|
203
|
+
metadata: meta
|
|
204
|
+
};
|
|
205
|
+
const headers$1 = {
|
|
206
|
+
"Content-Type": "application/json",
|
|
207
|
+
...resolveHeaders(options$1.headers, {
|
|
208
|
+
type: "error",
|
|
209
|
+
data: error
|
|
210
|
+
}) ?? {},
|
|
211
|
+
...resolveHeaders(options$1.error?.headers, error) ?? {}
|
|
212
|
+
};
|
|
213
|
+
return new BaseResponse.Base(JSON.stringify(payload$1), {
|
|
214
|
+
status,
|
|
215
|
+
statusText,
|
|
216
|
+
headers: headers$1,
|
|
217
|
+
payload: payload$1
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (this.isBinaryData(raw.data)) {
|
|
221
|
+
const headers$1 = {
|
|
222
|
+
...resolveHeaders(options$1.headers, {
|
|
223
|
+
type: "binary",
|
|
224
|
+
data: raw.data
|
|
225
|
+
}) ?? {},
|
|
226
|
+
...resolveHeaders(options$1.binary?.headers, raw.data) ?? {}
|
|
227
|
+
};
|
|
228
|
+
return new BaseResponse.Base(raw.data, {
|
|
229
|
+
status: 200,
|
|
230
|
+
headers: headers$1,
|
|
231
|
+
payload: raw.data
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const payload = {
|
|
235
|
+
error: null,
|
|
236
|
+
data: raw.data ?? null,
|
|
237
|
+
success: true,
|
|
238
|
+
metadata: meta
|
|
239
|
+
};
|
|
240
|
+
const headers = {
|
|
241
|
+
"Content-Type": "application/json",
|
|
242
|
+
...resolveHeaders(options$1.headers, {
|
|
243
|
+
type: "json",
|
|
244
|
+
data: raw.data
|
|
245
|
+
}) ?? {},
|
|
246
|
+
...resolveHeaders(options$1.json?.headers, { output: raw.data }) ?? {}
|
|
247
|
+
};
|
|
248
|
+
return new BaseResponse.Base(JSON.stringify(payload), {
|
|
249
|
+
status: 200,
|
|
250
|
+
headers,
|
|
251
|
+
payload
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Prepare `meta` by merging preassigned meta (from `withMeta`) with default meta (if any).
|
|
256
|
+
*
|
|
257
|
+
* @returns Resolved meta object.
|
|
258
|
+
*/
|
|
259
|
+
prepareMeta() {
|
|
260
|
+
const objOrFn = this.options.meta?.default;
|
|
261
|
+
return {
|
|
262
|
+
...typeof objOrFn === "function" ? objOrFn() : objOrFn,
|
|
263
|
+
...this.preasignedMeta ?? {}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
isBinaryData(data) {
|
|
267
|
+
return data instanceof Blob || data instanceof ArrayBuffer || data instanceof Uint8Array || typeof ReadableStream !== "undefined" && data instanceof ReadableStream;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
export { ResponseHandler, createResponseHandler };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FunctionObject } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/headers.d.ts
|
|
4
|
+
type RawHeaders = Record<string, string>;
|
|
5
|
+
type Headers<T> = FunctionObject<RawHeaders, T>;
|
|
6
|
+
declare function resolveHeaders(headers: Headers<any> | undefined, input: unknown): RawHeaders | null;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { Headers, RawHeaders, resolveHeaders };
|
package/dist/headers.mjs
ADDED
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DefaultMeta } from "./response/meta/index.mjs";
|
|
2
|
+
import { AnyObject, FunctionObject, PromiseOr } from "./types.mjs";
|
|
3
|
+
import { MetaOptions, meta } from "./options/meta.mjs";
|
|
4
|
+
import { Headers, RawHeaders, resolveHeaders } from "./headers.mjs";
|
|
5
|
+
import { ErrorOptions, error } from "./options/error.mjs";
|
|
6
|
+
import { BaseResponse, ResponseTypes } from "./response/base.mjs";
|
|
7
|
+
import { JsonResponse } from "./response/json/index.mjs";
|
|
8
|
+
import { JsonOptions, json } from "./options/json.mjs";
|
|
9
|
+
import { Binary, BinaryResponse } from "./response/binary/index.mjs";
|
|
10
|
+
import { BinaryOptions, binary } from "./options/binary.mjs";
|
|
11
|
+
import { ErrorResponse } from "./response/error/index.mjs";
|
|
12
|
+
import { DefaultResponse } from "./response/default.mjs";
|
|
13
|
+
import { Options } from "./options/base.mjs";
|
|
14
|
+
import { options } from "./options/index.mjs";
|
|
15
|
+
import { generateDefaultErrors } from "./error/default.mjs";
|
|
16
|
+
import { DefaultError, DefaultErrorTypes, ErrorDefinition, ErrorHandler, ErrorHandlerOptions, ErrorRegistry } from "./error/index.mjs";
|
|
17
|
+
import { TextResponse } from "./response/text/index.mjs";
|
|
18
|
+
import { AnyResponseHandler, ResolveOptionsMeta, ResponseHandler, createResponseHandler } from "./handler.mjs";
|
|
19
|
+
import { responseSymbol } from "./symbol.mjs";
|
|
20
|
+
export { AnyObject, AnyResponseHandler, BaseResponse, Binary, BinaryOptions, BinaryResponse, DefaultError, DefaultErrorTypes, DefaultMeta, DefaultResponse, ErrorDefinition, ErrorHandler, ErrorHandlerOptions, ErrorOptions, ErrorRegistry, ErrorResponse, FunctionObject, Headers, JsonOptions, JsonResponse, MetaOptions, Options, PromiseOr, RawHeaders, ResolveOptionsMeta, ResponseHandler, ResponseTypes, TextResponse, binary, createResponseHandler, error, generateDefaultErrors, json, meta, options, resolveHeaders, responseSymbol };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { generateDefaultErrors } from "./error/default.mjs";
|
|
2
|
+
import { resolveHeaders } from "./headers.mjs";
|
|
3
|
+
import { json } from "./options/json.mjs";
|
|
4
|
+
import { meta } from "./options/meta.mjs";
|
|
5
|
+
import { error } from "./options/error.mjs";
|
|
6
|
+
import { binary } from "./options/binary.mjs";
|
|
7
|
+
import { options } from "./options/index.mjs";
|
|
8
|
+
import { BaseResponse } from "./response/base.mjs";
|
|
9
|
+
import { BinaryResponse } from "./response/binary/index.mjs";
|
|
10
|
+
import { ErrorResponse } from "./response/error/index.mjs";
|
|
11
|
+
import { JsonResponse } from "./response/json/index.mjs";
|
|
12
|
+
import { TextResponse } from "./response/text/index.mjs";
|
|
13
|
+
import { ResponseHandler, createResponseHandler } from "./handler.mjs";
|
|
14
|
+
import { responseSymbol } from "./symbol.mjs";
|
|
15
|
+
import "./response/index.mjs";
|
|
16
|
+
import "./error/index.mjs";
|
|
17
|
+
|
|
18
|
+
export { BaseResponse, BinaryResponse, ErrorResponse, JsonResponse, ResponseHandler, TextResponse, binary, createResponseHandler, error, generateDefaultErrors, json, meta, options, resolveHeaders, responseSymbol };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PromiseOr } from "../types.mjs";
|
|
2
|
+
import { MetaOptions } from "./meta.mjs";
|
|
3
|
+
import { Headers } from "../headers.mjs";
|
|
4
|
+
import { ErrorOptions } from "./error.mjs";
|
|
5
|
+
import { BaseResponse, ResponseTypes } from "../response/base.mjs";
|
|
6
|
+
import { JsonOptions } from "./json.mjs";
|
|
7
|
+
import { Binary } from "../response/binary/index.mjs";
|
|
8
|
+
import { BinaryOptions } from "./binary.mjs";
|
|
9
|
+
import { DefaultResponse } from "../response/default.mjs";
|
|
10
|
+
|
|
11
|
+
//#region src/options/base.d.ts
|
|
12
|
+
interface Options<TMeta extends MetaOptions.Base = MetaOptions.Base, TError extends ErrorOptions.Base = ErrorOptions.Base, TJson extends JsonOptions.Base = JsonOptions.Base, TBinary extends BinaryOptions.Base = BinaryOptions.Base> {
|
|
13
|
+
headers?: Headers<{
|
|
14
|
+
type: ResponseTypes;
|
|
15
|
+
data: any;
|
|
16
|
+
}>;
|
|
17
|
+
meta?: TMeta;
|
|
18
|
+
error?: TError;
|
|
19
|
+
json?: TJson;
|
|
20
|
+
binary?: TBinary;
|
|
21
|
+
mapResponse?(data: {
|
|
22
|
+
data: JsonOptions.InferedSchemaFromBase<TJson> | Binary | string;
|
|
23
|
+
error: ErrorOptions.InferedSchemaFromBase<TError>;
|
|
24
|
+
response: BaseResponse.Base<DefaultResponse>;
|
|
25
|
+
}): PromiseOr<Response>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { Options };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Headers } from "../headers.mjs";
|
|
2
|
+
import { Binary } from "../response/binary/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/options/binary.d.ts
|
|
5
|
+
declare namespace BinaryOptions {
|
|
6
|
+
interface Base {
|
|
7
|
+
headers?: Headers<Binary>;
|
|
8
|
+
mapData?: (data: Binary) => Binary;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
declare function binary<T extends BinaryOptions.Base>(opts: T): T;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { BinaryOptions, binary };
|