qualityapi 1.0.0-alpha.1 → 1.0.0-alpha.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/QualityApi.js +37 -49
- package/dist/QualityApiContentType.js +9 -9
- package/dist/QualityApiEndpointBuilder.js +10 -8
- package/dist/QualityApiMiddleware.js +0 -1
- package/dist/_internal/Logger.js +15 -0
- package/dist/_internal/Store.js +5 -5
- package/dist/_internal/globals.js +2 -0
- package/dist/_internal/util-functions.js +18 -0
- package/dist/index.js +1 -1
- package/dist/types/QualityApi.d.ts +21 -22
- package/dist/types/QualityApiBody.d.ts +1 -1
- package/dist/types/QualityApiContentType.d.ts +1 -1
- package/dist/types/QualityApiEndpointBuilder.d.ts +4 -5
- package/dist/types/QualityApiMiddleware.d.ts +1 -2
- package/dist/types/QualityApiRequest.d.ts +3 -3
- package/dist/types/_internal/Logger.d.ts +5 -0
- package/dist/types/_internal/globals.d.ts +2 -0
- package/dist/types/_internal/util-functions.d.ts +3 -0
- package/dist/types/index.d.ts +1 -2
- package/package.json +1 -1
- package/dist/QualityApiResponse.js +0 -12
- package/dist/types/QualityApiResponse.d.ts +0 -7
package/dist/QualityApi.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Store from "./_internal/Store";
|
|
2
|
-
import { QualityApiResponse as Response } from "./QualityApiResponse";
|
|
3
2
|
import { QualityApiEndpointBuilder as EndpointBuilder } from "./QualityApiEndpointBuilder";
|
|
4
3
|
import {} from "./QualityApiBody";
|
|
5
4
|
import {} from "./QualityApiConfig";
|
|
6
5
|
import {} from "./QualityApiContentType";
|
|
6
|
+
import { getBodyContentType } from "./_internal/util-functions";
|
|
7
7
|
var QualityApi;
|
|
8
8
|
(function (QualityApi) {
|
|
9
9
|
/** Starts the building process of an endpoint. Use `QualityApiEndpointBuilder`'s built-in methods (ex. `authenticate`, `body`) to build the endpoint. */
|
|
@@ -19,58 +19,46 @@ var QualityApi;
|
|
|
19
19
|
/** Contains the most commonly used HTTP response codes. Use `_` function to define your own. */
|
|
20
20
|
let Respond;
|
|
21
21
|
(function (Respond) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function ok(json) {
|
|
25
|
-
return _(200, json);
|
|
22
|
+
function generate(statusCode) {
|
|
23
|
+
return (body, contentType = getBodyContentType(body)) => _(statusCode, body, contentType);
|
|
26
24
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
function created(json) {
|
|
30
|
-
return _(201, json);
|
|
25
|
+
function generateNoBody(statusCode) {
|
|
26
|
+
return () => _(statusCode);
|
|
31
27
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Respond.badRequest =
|
|
44
|
-
/** 401
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Respond.forbidden = forbidden;
|
|
54
|
-
/** 404 - Not found */
|
|
55
|
-
function notFound(json) {
|
|
56
|
-
return _(404, json);
|
|
57
|
-
}
|
|
58
|
-
Respond.notFound = notFound;
|
|
59
|
-
/** 409 - Conflict */
|
|
60
|
-
function conflict(json) {
|
|
61
|
-
return _(409, json);
|
|
62
|
-
}
|
|
63
|
-
Respond.conflict = conflict;
|
|
64
|
-
// 5xx (Server error)
|
|
65
|
-
/** 500 - Internal server error */
|
|
66
|
-
function internalServerError(json) {
|
|
67
|
-
return _(500, json);
|
|
68
|
-
}
|
|
69
|
-
Respond.internalServerError = internalServerError;
|
|
28
|
+
// 2xx - Success
|
|
29
|
+
/** 200 OK */
|
|
30
|
+
Respond.ok = generate(200);
|
|
31
|
+
/** 201 Created */
|
|
32
|
+
Respond.created = generate(201);
|
|
33
|
+
/** 202 Accepted */
|
|
34
|
+
Respond.accepted = generate(202);
|
|
35
|
+
/** 204 No content */
|
|
36
|
+
Respond.noContent = generateNoBody(204);
|
|
37
|
+
// 4xx - Client error
|
|
38
|
+
/** 400 Bad request */
|
|
39
|
+
Respond.badRequest = generate(400);
|
|
40
|
+
/** 401 Unauthorized */
|
|
41
|
+
Respond.unauthorized = generate(401);
|
|
42
|
+
/** 403 Forbidden */
|
|
43
|
+
Respond.forbidden = generate(403);
|
|
44
|
+
/** 409 Conflict */
|
|
45
|
+
Respond.conflict = generate(400);
|
|
46
|
+
// 5xx - Client error
|
|
47
|
+
/** 500 Internal server error */
|
|
48
|
+
Respond.internalServerError = generate(500);
|
|
70
49
|
// Other
|
|
71
50
|
/** Creates a response outside of the predefined HTTP codes. */
|
|
72
|
-
function _(status,
|
|
73
|
-
|
|
51
|
+
function _(status, body, contentType = getBodyContentType(body)) {
|
|
52
|
+
const isBlob = body instanceof Blob;
|
|
53
|
+
const isString = typeof body === "string";
|
|
54
|
+
const isJson = !isBlob &&
|
|
55
|
+
!isString;
|
|
56
|
+
return new Response(isJson ? JSON.stringify(body) : body, {
|
|
57
|
+
status,
|
|
58
|
+
headers: {
|
|
59
|
+
...(contentType && { "Content-Type": contentType })
|
|
60
|
+
}
|
|
61
|
+
});
|
|
74
62
|
}
|
|
75
63
|
Respond._ = _;
|
|
76
64
|
})(Respond = QualityApi.Respond || (QualityApi.Respond = {}));
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export var
|
|
2
|
-
(function (
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
})(
|
|
1
|
+
export var QualityApiRequestContentType;
|
|
2
|
+
(function (QualityApiRequestContentType) {
|
|
3
|
+
QualityApiRequestContentType[QualityApiRequestContentType["JSON"] = 0] = "JSON";
|
|
4
|
+
QualityApiRequestContentType[QualityApiRequestContentType["Blob"] = 1] = "Blob";
|
|
5
|
+
QualityApiRequestContentType[QualityApiRequestContentType["Bytes"] = 2] = "Bytes";
|
|
6
|
+
QualityApiRequestContentType[QualityApiRequestContentType["Text"] = 3] = "Text";
|
|
7
|
+
QualityApiRequestContentType[QualityApiRequestContentType["ArrayBuffer"] = 4] = "ArrayBuffer";
|
|
8
|
+
QualityApiRequestContentType[QualityApiRequestContentType["FormData"] = 5] = "FormData";
|
|
9
|
+
})(QualityApiRequestContentType || (QualityApiRequestContentType = {}));
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import QualityApi from "./QualityApi";
|
|
2
2
|
import Store from "./_internal/./Store";
|
|
3
|
-
import { QualityApiResponse } from "./QualityApiResponse";
|
|
4
3
|
import { Continue } from "./Continue";
|
|
5
4
|
import {} from "./QualityApiMiddleware";
|
|
6
5
|
import {} from "./QualityApiBody";
|
|
7
6
|
import {} from "./QualityApiRequest";
|
|
8
7
|
import {} from "next-auth";
|
|
9
|
-
import { formatZodError, urlSearchParamsToObj } from "./_internal/util-functions";
|
|
10
|
-
import {
|
|
8
|
+
import { formatZodError, testContentHeader, urlSearchParamsToObj } from "./_internal/util-functions";
|
|
9
|
+
import { QualityApiRequestContentType as ContentType } from "./QualityApiContentType";
|
|
11
10
|
import z, { ZodObject } from "zod";
|
|
12
11
|
export class QualityApiEndpointBuilder {
|
|
13
12
|
constructor(contentType) {
|
|
@@ -137,18 +136,21 @@ export class QualityApiEndpointBuilder {
|
|
|
137
136
|
this._body = await this.parseRequestBody(nextRequest);
|
|
138
137
|
}
|
|
139
138
|
catch {
|
|
140
|
-
return QualityApi.Respond._(415)
|
|
139
|
+
return QualityApi.Respond._(415);
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
this._params = await context.params;
|
|
144
143
|
this._searchParams = urlSearchParamsToObj(new URL(nextRequest.url).searchParams);
|
|
145
144
|
for (const mw of this.middlewares) {
|
|
146
145
|
const execution = await mw(this.getRequestData(nextRequest));
|
|
147
|
-
if (
|
|
148
|
-
|
|
146
|
+
if (execution instanceof Continue)
|
|
147
|
+
continue;
|
|
148
|
+
testContentHeader(execution.headers);
|
|
149
|
+
return execution;
|
|
149
150
|
}
|
|
150
|
-
const
|
|
151
|
-
|
|
151
|
+
const fnExec = await fn(this.getRequestData(nextRequest));
|
|
152
|
+
testContentHeader(fnExec.headers);
|
|
153
|
+
return fnExec;
|
|
152
154
|
};
|
|
153
155
|
}
|
|
154
156
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export var Logger;
|
|
2
|
+
(function (Logger) {
|
|
3
|
+
function success(msg) {
|
|
4
|
+
console.log(`✅ Quality API: ${msg}`);
|
|
5
|
+
}
|
|
6
|
+
Logger.success = success;
|
|
7
|
+
function error(msg) {
|
|
8
|
+
console.error(`❌ Quality API: ${msg}`);
|
|
9
|
+
}
|
|
10
|
+
Logger.error = error;
|
|
11
|
+
function warn(msg) {
|
|
12
|
+
console.warn(`⚠️ Quality API: ${msg}`);
|
|
13
|
+
}
|
|
14
|
+
Logger.warn = warn;
|
|
15
|
+
})(Logger || (Logger = {}));
|
package/dist/_internal/Store.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { GLOBAL_THIS_NAMESPACE } from "./globals";
|
|
2
2
|
var Store;
|
|
3
3
|
(function (Store) {
|
|
4
4
|
function init() {
|
|
5
|
-
if (!(
|
|
5
|
+
if (!(GLOBAL_THIS_NAMESPACE in globalThis))
|
|
6
6
|
// @ts-ignore
|
|
7
|
-
globalThis[
|
|
7
|
+
globalThis[GLOBAL_THIS_NAMESPACE] = new Map();
|
|
8
8
|
}
|
|
9
9
|
function get(key) {
|
|
10
10
|
init();
|
|
11
11
|
// @ts-ignore
|
|
12
|
-
return globalThis[
|
|
12
|
+
return globalThis[GLOBAL_THIS_NAMESPACE].get(key);
|
|
13
13
|
}
|
|
14
14
|
Store.get = get;
|
|
15
15
|
function set(key, value) {
|
|
16
16
|
init();
|
|
17
17
|
// @ts-ignore
|
|
18
|
-
return globalThis[
|
|
18
|
+
return globalThis[GLOBAL_THIS_NAMESPACE].set(key, value);
|
|
19
19
|
}
|
|
20
20
|
Store.set = set;
|
|
21
21
|
})(Store || (Store = {}));
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BLOB_CONTENT_TYPE } from "./globals";
|
|
2
|
+
import { Logger } from "./Logger";
|
|
1
3
|
export function urlSearchParamsToObj(urlSearchParams) {
|
|
2
4
|
let result = {};
|
|
3
5
|
for (const key of urlSearchParams.keys()) {
|
|
@@ -26,3 +28,19 @@ export function formatZodError(step, error) {
|
|
|
26
28
|
return error;
|
|
27
29
|
}
|
|
28
30
|
}
|
|
31
|
+
export function getBodyContentType(body) {
|
|
32
|
+
if (body instanceof Blob)
|
|
33
|
+
return BLOB_CONTENT_TYPE;
|
|
34
|
+
else if (typeof body === "string")
|
|
35
|
+
return "text/plain";
|
|
36
|
+
else
|
|
37
|
+
return "application/json";
|
|
38
|
+
}
|
|
39
|
+
export function testContentHeader(headers) {
|
|
40
|
+
const header = headers.get("Content-Type");
|
|
41
|
+
if (!header)
|
|
42
|
+
return;
|
|
43
|
+
if (header?.split(";")[0] !== BLOB_CONTENT_TYPE)
|
|
44
|
+
return;
|
|
45
|
+
Logger.warn("Specify a \"Content-Type\" header for responses of type blob");
|
|
46
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { QualityApiResponse as Response } from "./QualityApiResponse";
|
|
2
1
|
import { QualityApiEndpointBuilder as EndpointBuilder } from "./QualityApiEndpointBuilder";
|
|
3
|
-
import { type QualityApiBody
|
|
2
|
+
import { type QualityApiBody } from "./QualityApiBody";
|
|
4
3
|
import { type QualityApiConfig as Config } from "./QualityApiConfig";
|
|
5
|
-
import { type
|
|
4
|
+
import { type QualityApiRequestContentType as ContentType } from "./QualityApiContentType";
|
|
6
5
|
type ContentTypeMap = {
|
|
7
6
|
[ContentType.JSON]: Awaited<ReturnType<Request["json"]>>;
|
|
8
7
|
[ContentType.Blob]: Awaited<ReturnType<Request["blob"]>>;
|
|
@@ -18,26 +17,26 @@ declare namespace QualityApi {
|
|
|
18
17
|
function config(options: Config): void;
|
|
19
18
|
/** Contains the most commonly used HTTP response codes. Use `_` function to define your own. */
|
|
20
19
|
namespace Respond {
|
|
21
|
-
/** 200
|
|
22
|
-
|
|
23
|
-
/** 201
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
/** 409
|
|
36
|
-
|
|
37
|
-
/** 500
|
|
38
|
-
|
|
20
|
+
/** 200 OK */
|
|
21
|
+
const ok: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
22
|
+
/** 201 Created */
|
|
23
|
+
const created: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
24
|
+
/** 202 Accepted */
|
|
25
|
+
const accepted: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
26
|
+
/** 204 No content */
|
|
27
|
+
const noContent: () => Response;
|
|
28
|
+
/** 400 Bad request */
|
|
29
|
+
const badRequest: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
30
|
+
/** 401 Unauthorized */
|
|
31
|
+
const unauthorized: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
32
|
+
/** 403 Forbidden */
|
|
33
|
+
const forbidden: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
34
|
+
/** 409 Conflict */
|
|
35
|
+
const conflict: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
36
|
+
/** 500 Internal server error */
|
|
37
|
+
const internalServerError: <Body extends QualityApiBody>(body?: Body, contentType?: string | undefined) => Response;
|
|
39
38
|
/** Creates a response outside of the predefined HTTP codes. */
|
|
40
|
-
function _<
|
|
39
|
+
function _<Body extends QualityApiBody>(status: number, body?: Body, contentType?: string | undefined): Response;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
export default QualityApi;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type QualityApiBody = {} | [
|
|
2
|
-
];
|
|
2
|
+
] | Blob | string | number;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { QualityApiResponse } from "./QualityApiResponse";
|
|
2
1
|
import { type QualityApiMiddleware as Middleware } from "./QualityApiMiddleware";
|
|
3
2
|
import { type QualityApiBody } from "./QualityApiBody";
|
|
4
3
|
import { type QualityApiRequest } from "./QualityApiRequest";
|
|
5
|
-
import {
|
|
6
|
-
import z, { ZodObject, type ZodRawShape } from "zod";
|
|
4
|
+
import { QualityApiRequestContentType as ContentType } from "./QualityApiContentType";
|
|
5
|
+
import z, { ZodObject, type ZodRawShape, type ZodType } from "zod";
|
|
7
6
|
export declare class QualityApiEndpointBuilder<Authenticated extends boolean, Body, Params, SearchParams> {
|
|
8
7
|
private middlewares;
|
|
9
8
|
private session;
|
|
@@ -19,7 +18,7 @@ export declare class QualityApiEndpointBuilder<Authenticated extends boolean, Bo
|
|
|
19
18
|
/** Adds internal middleware that verifies end user's authentication. */
|
|
20
19
|
authenticate(): QualityApiEndpointBuilder<true, Body, Params, SearchParams>;
|
|
21
20
|
/** Adds internal middleware that validates the request body. */
|
|
22
|
-
body<T extends
|
|
21
|
+
body<T extends ZodType>(schema: T): QualityApiEndpointBuilder<Authenticated, z.infer<T>, Params, SearchParams>;
|
|
23
22
|
/**
|
|
24
23
|
* Adds internal middleware that validates the request's parameters (slugs).
|
|
25
24
|
*
|
|
@@ -36,7 +35,7 @@ export declare class QualityApiEndpointBuilder<Authenticated extends boolean, Bo
|
|
|
36
35
|
* Defines the final function of the endpoint.
|
|
37
36
|
* This returns a Next.js-endpoint-compatible function with all middleware compiled.
|
|
38
37
|
*/
|
|
39
|
-
endpoint<T extends QualityApiBody>(fn: (data: QualityApiRequest<Authenticated, Body, Params, SearchParams>) =>
|
|
38
|
+
endpoint<T extends QualityApiBody>(fn: (data: QualityApiRequest<Authenticated, Body, Params, SearchParams>) => (Response | Promise<Response>)): (nextRequest: Request, context: {
|
|
40
39
|
params: Promise<{}>;
|
|
41
40
|
}) => Promise<Response>;
|
|
42
41
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { QualityApiResponse } from "./QualityApiResponse";
|
|
2
1
|
import { Continue } from "./Continue";
|
|
3
2
|
import { type QualityApiRequest } from "./QualityApiRequest";
|
|
4
|
-
export type QualityApiMiddleware<Authenticated extends boolean> = (data: QualityApiRequest<Authenticated>) =>
|
|
3
|
+
export type QualityApiMiddleware<Authenticated extends boolean> = (data: QualityApiRequest<Authenticated>) => Response | Promise<Response> | Continue;
|
|
@@ -6,11 +6,11 @@ export type QualityApiRequest<Authenticated extends boolean, Body = unknown, Par
|
|
|
6
6
|
* This can be mutated through module augmentation. See [NextAuth module augmentation](https://next-auth.js.org/getting-started/typescript#module-augmentation).
|
|
7
7
|
*/
|
|
8
8
|
session: Authenticated extends true ? Session : (Session | null);
|
|
9
|
-
/** The request body. */
|
|
9
|
+
/** The request body. Use the `.body` middleware to validate this through your Zod schema. */
|
|
10
10
|
body: Body;
|
|
11
|
-
/** The request parameters (slugs). */
|
|
11
|
+
/** The request parameters (slugs). Use the `.params` middleware to validate this through your Zod schema. */
|
|
12
12
|
params: Params;
|
|
13
|
-
/** The request search parameters (query parameters). */
|
|
13
|
+
/** The request search parameters (query parameters). Use the `.searchParams` middleware to validate this through your Zod schema. */
|
|
14
14
|
searchParams: SearchParams;
|
|
15
15
|
/** The raw Next.js request. */
|
|
16
16
|
_request: Request;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { QualityApiBody } from "../QualityApiBody";
|
|
1
2
|
export declare function urlSearchParamsToObj(urlSearchParams: URLSearchParams): {
|
|
2
3
|
[_: string]: any;
|
|
3
4
|
};
|
|
@@ -11,3 +12,5 @@ export declare function formatZodError(step: string, error: {
|
|
|
11
12
|
step: string;
|
|
12
13
|
properties: {};
|
|
13
14
|
};
|
|
15
|
+
export declare function getBodyContentType(body?: QualityApiBody): "application/octet-stream" | "text/plain" | "application/json";
|
|
16
|
+
export declare function testContentHeader(headers: Headers): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -5,6 +5,5 @@ export type { QualityApiConfig } from "./QualityApiConfig.ts";
|
|
|
5
5
|
export type { QualityApiEndpointBuilder } from "./QualityApiEndpointBuilder.ts";
|
|
6
6
|
export type { QualityApiMiddleware } from "./QualityApiMiddleware.ts";
|
|
7
7
|
export type { QualityApiRequest } from "./QualityApiRequest.ts";
|
|
8
|
-
export
|
|
9
|
-
export { QualityApiContentType } from "./QualityApiContentType";
|
|
8
|
+
export { QualityApiRequestContentType } from "./QualityApiContentType";
|
|
10
9
|
export default QualityApi;
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {} from "./QualityApiBody";
|
|
2
|
-
export class QualityApiResponse {
|
|
3
|
-
constructor(_status, _body) {
|
|
4
|
-
this.status = _status;
|
|
5
|
-
this.body = _body;
|
|
6
|
-
}
|
|
7
|
-
toNextResponse() {
|
|
8
|
-
return (this.status === 204
|
|
9
|
-
? new Response(undefined, { status: this.status })
|
|
10
|
-
: Response.json(this.body ?? {}, { status: this.status }));
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type QualityApiBody } from "./QualityApiBody";
|
|
2
|
-
export declare class QualityApiResponse<Body extends QualityApiBody> {
|
|
3
|
-
readonly status: number;
|
|
4
|
-
readonly body: Body | undefined;
|
|
5
|
-
constructor(_status: number, _body?: Body);
|
|
6
|
-
toNextResponse(): Response;
|
|
7
|
-
}
|