@sx3/ultra 0.0.1
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/LICENSE +21 -0
- package/README.md +512 -0
- package/dist/auth.d.mts +56 -0
- package/dist/auth.mjs +84 -0
- package/dist/client.d.mts +27 -0
- package/dist/client.mjs +131 -0
- package/dist/context-ChCsZh7S.d.mts +17 -0
- package/dist/context.d.mts +2 -0
- package/dist/context.mjs +10 -0
- package/dist/cors.d.mts +16 -0
- package/dist/cors.mjs +58 -0
- package/dist/crypto.d.mts +7 -0
- package/dist/crypto.mjs +44 -0
- package/dist/error-CII1zMOR.mjs +45 -0
- package/dist/error.d.mts +25 -0
- package/dist/error.mjs +3 -0
- package/dist/http-BqWCMASL.d.mts +10 -0
- package/dist/http.d.mts +3 -0
- package/dist/http.mjs +1 -0
- package/dist/middleware-COKreBGP.d.mts +43 -0
- package/dist/middleware.d.mts +4 -0
- package/dist/middleware.mjs +1 -0
- package/dist/procedure-BN1rLLRX.mjs +86 -0
- package/dist/procedure.d.mts +4 -0
- package/dist/procedure.mjs +3 -0
- package/dist/response-CNhIkAYG.mjs +59 -0
- package/dist/response.d.mts +5 -0
- package/dist/response.mjs +3 -0
- package/dist/rpc-Ch2UXReT.d.mts +23 -0
- package/dist/rpc-_rBI0z-9.mjs +7 -0
- package/dist/rpc.d.mts +2 -0
- package/dist/rpc.mjs +3 -0
- package/dist/session.d.mts +115 -0
- package/dist/session.mjs +181 -0
- package/dist/types-Cn69QrjS.d.mts +11 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +1 -0
- package/dist/ultra.d.mts +69 -0
- package/dist/ultra.mjs +273 -0
- package/dist/validation-CkRfxQJ_.d.mts +57 -0
- package/dist/validation-Cop5Wvlr.mjs +12 -0
- package/dist/validation.d.mts +2 -0
- package/dist/validation.mjs +3 -0
- package/package.json +55 -0
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//#region src/client.ts
|
|
2
|
+
function proxyClient(invoke, path = []) {
|
|
3
|
+
return new Proxy(() => {}, {
|
|
4
|
+
get(_, prop) {
|
|
5
|
+
if (typeof prop === "string") return proxyClient(invoke, [...path, prop]);
|
|
6
|
+
},
|
|
7
|
+
apply(_, __, args) {
|
|
8
|
+
if (!path.length) throw new Error("Cannot call client root; select a procedure first");
|
|
9
|
+
const method = path.join("/");
|
|
10
|
+
const params = args[0];
|
|
11
|
+
const callOptions = args[1];
|
|
12
|
+
return invoke(method, params, callOptions);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function mergeHeaders(...sources) {
|
|
17
|
+
const result = new Headers();
|
|
18
|
+
for (const headersInit of sources) {
|
|
19
|
+
if (!headersInit) continue;
|
|
20
|
+
new Headers(headersInit).forEach((value, key) => result.set(key, value));
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
function createHTTPClient(clientOptions) {
|
|
25
|
+
const invoke = async (method, params, callOptions) => {
|
|
26
|
+
const options = {
|
|
27
|
+
...clientOptions,
|
|
28
|
+
...callOptions
|
|
29
|
+
};
|
|
30
|
+
const timeout = options?.timeout || 1e4;
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const httpMethod = options?.method || "POST";
|
|
33
|
+
let url = `${options.baseUrl}/${method}`;
|
|
34
|
+
const headers = mergeHeaders(clientOptions?.headers, options?.headers, callOptions?.headers);
|
|
35
|
+
let body = null;
|
|
36
|
+
const abortTimeout = setTimeout(() => controller.abort(`Timeout: ${timeout}`), timeout);
|
|
37
|
+
switch (true) {
|
|
38
|
+
case httpMethod === "GET": {
|
|
39
|
+
body = null;
|
|
40
|
+
if (!params) break;
|
|
41
|
+
if (typeof params !== "object") throw new Error("GET requests params to be an object for query string generation");
|
|
42
|
+
const entries = Object.entries(params).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => [k, String(v)]);
|
|
43
|
+
const queryString = new URLSearchParams(entries).toString();
|
|
44
|
+
if (queryString) url += `?${queryString}`;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case params instanceof FormData:
|
|
48
|
+
body = params;
|
|
49
|
+
break;
|
|
50
|
+
case typeof params === "string":
|
|
51
|
+
headers.set("Content-Type", "text/plain");
|
|
52
|
+
body = params;
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
headers.set("Content-Type", "application/json");
|
|
56
|
+
body = JSON.stringify(params);
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetch(url, {
|
|
60
|
+
method: httpMethod,
|
|
61
|
+
...body && { body },
|
|
62
|
+
...options,
|
|
63
|
+
signal: controller.signal,
|
|
64
|
+
headers
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) throw new Error(`HTTP error: ${response.statusText} ${response.status} `);
|
|
67
|
+
const type = response.headers.get("Content-Type") || "";
|
|
68
|
+
switch (true) {
|
|
69
|
+
case type.includes("application/json"): return await response.json();
|
|
70
|
+
case type.includes("text/"): return await response.text();
|
|
71
|
+
default: return await response.blob();
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error.name === "AbortError") throw new Error(`Request aborted: ${error.message}`);
|
|
75
|
+
throw error;
|
|
76
|
+
} finally {
|
|
77
|
+
clearTimeout(abortTimeout);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return proxyClient(invoke);
|
|
81
|
+
}
|
|
82
|
+
function createWebSocketClient(options) {
|
|
83
|
+
const { timeout = 1e4 } = options;
|
|
84
|
+
const makeId = () => Math.random().toString(36);
|
|
85
|
+
const invoke = (method, params, callOptions) => {
|
|
86
|
+
const socket = options.socket();
|
|
87
|
+
const readyState = socket.readyState;
|
|
88
|
+
if (typeof readyState === "number" && readyState !== WebSocket.OPEN) return Promise.reject(/* @__PURE__ */ new Error("WebSocket is not open"));
|
|
89
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
90
|
+
const mergedTimeout = callOptions?.timeout ?? timeout;
|
|
91
|
+
let rejectTimeout;
|
|
92
|
+
const requestId = makeId();
|
|
93
|
+
const listener = (event) => {
|
|
94
|
+
try {
|
|
95
|
+
const response = JSON.parse(event.data);
|
|
96
|
+
if (response.id !== requestId) return;
|
|
97
|
+
clearTimeout(rejectTimeout);
|
|
98
|
+
socket.removeEventListener("message", listener);
|
|
99
|
+
if ("error" in response) return reject(response.error);
|
|
100
|
+
return resolve(response.result);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
reject(error);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
socket.addEventListener("message", listener);
|
|
106
|
+
rejectTimeout = setTimeout(() => {
|
|
107
|
+
socket.removeEventListener("message", listener);
|
|
108
|
+
reject(`Timeout: ${mergedTimeout}`);
|
|
109
|
+
}, mergedTimeout);
|
|
110
|
+
socket.send(JSON.stringify({
|
|
111
|
+
id: requestId,
|
|
112
|
+
method,
|
|
113
|
+
params
|
|
114
|
+
}));
|
|
115
|
+
return promise;
|
|
116
|
+
};
|
|
117
|
+
return proxyClient(invoke);
|
|
118
|
+
}
|
|
119
|
+
function createSuperClient(options) {
|
|
120
|
+
const invoke = (method, params, callOptions) => {
|
|
121
|
+
const client = options.pick(method, params, callOptions);
|
|
122
|
+
const segments = method.split("/").filter(Boolean);
|
|
123
|
+
let target = client;
|
|
124
|
+
for (const segment of segments) if (target[segment]) target = target[segment];
|
|
125
|
+
return target(params, callOptions);
|
|
126
|
+
};
|
|
127
|
+
return proxyClient(invoke);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
export { createHTTPClient, createSuperClient, createWebSocketClient };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BunRequest, Server, ServerWebSocket } from "bun";
|
|
2
|
+
|
|
3
|
+
//#region src/context.d.ts
|
|
4
|
+
type DefaultSocketData = Record<string, any>;
|
|
5
|
+
interface HTTPContext {
|
|
6
|
+
server: Server<DefaultSocketData>;
|
|
7
|
+
request: BunRequest;
|
|
8
|
+
}
|
|
9
|
+
interface WSContext<SocketData> {
|
|
10
|
+
server: Server<SocketData>;
|
|
11
|
+
ws: ServerWebSocket<SocketData>;
|
|
12
|
+
}
|
|
13
|
+
type BaseContext<SocketData extends DefaultSocketData = DefaultSocketData> = HTTPContext | WSContext<SocketData>;
|
|
14
|
+
declare function isHTTP(context: BaseContext): context is HTTPContext;
|
|
15
|
+
declare function isWS<SocketData extends DefaultSocketData = DefaultSocketData>(context: BaseContext): context is WSContext<SocketData>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { isHTTP as a, WSContext as i, DefaultSocketData as n, isWS as o, HTTPContext as r, BaseContext as t };
|
package/dist/context.mjs
ADDED
package/dist/cors.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as BaseContext } from "./context-ChCsZh7S.mjs";
|
|
2
|
+
import "./http-BqWCMASL.mjs";
|
|
3
|
+
import { t as Middleware } from "./middleware-COKreBGP.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/cors.d.ts
|
|
6
|
+
interface CorsConfig {
|
|
7
|
+
origin: string[];
|
|
8
|
+
methods?: string[];
|
|
9
|
+
allowedHeaders?: string[];
|
|
10
|
+
exposedHeaders?: string[];
|
|
11
|
+
credentials?: boolean;
|
|
12
|
+
maxAge?: number;
|
|
13
|
+
}
|
|
14
|
+
declare function createCORSMiddleware(config: CorsConfig): Middleware<unknown, unknown, BaseContext>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { CorsConfig, createCORSMiddleware };
|
package/dist/cors.mjs
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { t as toHTTPResponse } from "./response-CNhIkAYG.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/cors.ts
|
|
4
|
+
const DEFAULT_HEADERS = {
|
|
5
|
+
"Access-Control-Allow-Methods": [
|
|
6
|
+
"GET",
|
|
7
|
+
"POST",
|
|
8
|
+
"PUT",
|
|
9
|
+
"PATCH",
|
|
10
|
+
"DELETE",
|
|
11
|
+
"OPTIONS"
|
|
12
|
+
].join(", "),
|
|
13
|
+
"Access-Control-Allow-Headers": [
|
|
14
|
+
"Accept-Language",
|
|
15
|
+
"Accept",
|
|
16
|
+
"Content-Type",
|
|
17
|
+
"Content-Language",
|
|
18
|
+
"Range"
|
|
19
|
+
].join(", "),
|
|
20
|
+
"Access-Control-Expose-Headers": [
|
|
21
|
+
"Cache-Control",
|
|
22
|
+
"Content-Language",
|
|
23
|
+
"Content-Type",
|
|
24
|
+
"Expires",
|
|
25
|
+
"Last-Modified",
|
|
26
|
+
"Pragma"
|
|
27
|
+
].join(", "),
|
|
28
|
+
"Access-Control-Max-Age": "3600"
|
|
29
|
+
};
|
|
30
|
+
function createCORSMiddleware(config) {
|
|
31
|
+
const cachedHeaders = {
|
|
32
|
+
...DEFAULT_HEADERS,
|
|
33
|
+
...config.methods?.length && { "Access-Control-Allow-Methods": config.methods.join(", ") },
|
|
34
|
+
...config.allowedHeaders?.length && { "Access-Control-Allow-Headers": config.allowedHeaders.join(", ") },
|
|
35
|
+
...config.exposedHeaders?.length && { "Access-Control-Expose-Headers": config.exposedHeaders.join(", ") },
|
|
36
|
+
...config.credentials && !config.origin.includes("*") && { "Access-Control-Allow-Credentials": "true" },
|
|
37
|
+
...config.maxAge && { "Access-Control-Max-Age": config.maxAge.toString() }
|
|
38
|
+
};
|
|
39
|
+
return async (options) => {
|
|
40
|
+
if (!("request" in options.context)) return options.next();
|
|
41
|
+
const origin = options.context.request.headers.get("Origin");
|
|
42
|
+
if (!origin || !config.origin.includes(origin)) return options.next();
|
|
43
|
+
if (options.context.request.method === "OPTIONS") return new Response(null, {
|
|
44
|
+
status: 204,
|
|
45
|
+
headers: {
|
|
46
|
+
"Access-Control-Allow-Origin": origin,
|
|
47
|
+
...cachedHeaders
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
const response = toHTTPResponse(await options.next());
|
|
51
|
+
response.headers.set("Access-Control-Allow-Origin", origin);
|
|
52
|
+
for (const header in cachedHeaders) response.headers.set(header, cachedHeaders[header]);
|
|
53
|
+
return response;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { createCORSMiddleware };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/crypto.d.ts
|
|
2
|
+
declare function sign(value: string, secret: string): string;
|
|
3
|
+
declare function unsign(signedValue: string, secret: string): string | null;
|
|
4
|
+
declare function encrypt(value: string, secret: string): string;
|
|
5
|
+
declare function decrypt(encrypted: string, secret: string): string | null;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { decrypt, encrypt, sign, unsign };
|
package/dist/crypto.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
//#region src/crypto.ts
|
|
4
|
+
const ALGO = "aes-256-gcm";
|
|
5
|
+
const ENCODING = "base64url";
|
|
6
|
+
const IV_LEN = 12;
|
|
7
|
+
const TAG_LEN = 16;
|
|
8
|
+
function sign(value, secret) {
|
|
9
|
+
const base64 = Buffer.from(value).toString(ENCODING);
|
|
10
|
+
return `${base64}.${createHmac("sha256", secret).update(base64).digest(ENCODING)}`;
|
|
11
|
+
}
|
|
12
|
+
function unsign(signedValue, secret) {
|
|
13
|
+
const [base64, sig] = signedValue.split(".");
|
|
14
|
+
if (!base64 || !sig) return null;
|
|
15
|
+
const expectedSig = createHmac("sha256", secret).update(base64).digest(ENCODING);
|
|
16
|
+
const a = Buffer.from(sig, ENCODING);
|
|
17
|
+
const b = Buffer.from(expectedSig, ENCODING);
|
|
18
|
+
if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
|
|
19
|
+
return Buffer.from(base64, ENCODING).toString();
|
|
20
|
+
}
|
|
21
|
+
function encrypt(value, secret) {
|
|
22
|
+
const iv = randomBytes(IV_LEN);
|
|
23
|
+
const cipher = createCipheriv(ALGO, secret, iv);
|
|
24
|
+
let enc = cipher.update(value, "utf-8", ENCODING);
|
|
25
|
+
enc += cipher.final(ENCODING);
|
|
26
|
+
return Buffer.concat([
|
|
27
|
+
iv,
|
|
28
|
+
cipher.getAuthTag(),
|
|
29
|
+
Buffer.from(enc, ENCODING)
|
|
30
|
+
]).toString(ENCODING);
|
|
31
|
+
}
|
|
32
|
+
function decrypt(encrypted, secret) {
|
|
33
|
+
const data = Buffer.from(encrypted, ENCODING);
|
|
34
|
+
if (data.length < IV_LEN + TAG_LEN) return null;
|
|
35
|
+
const iv = data.subarray(0, IV_LEN);
|
|
36
|
+
const tag = data.subarray(IV_LEN, IV_LEN + TAG_LEN);
|
|
37
|
+
const cipherText = data.subarray(IV_LEN + TAG_LEN);
|
|
38
|
+
const decipher = createDecipheriv(ALGO, secret, iv);
|
|
39
|
+
decipher.setAuthTag(tag);
|
|
40
|
+
return `${decipher.update(cipherText, void 0, "utf-8")}${decipher.final("utf-8")}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { decrypt, encrypt, sign, unsign };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/error.ts
|
|
2
|
+
var UltraError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
constructor(message, name, status) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = name;
|
|
7
|
+
this.status = status;
|
|
8
|
+
}
|
|
9
|
+
toResponse() {
|
|
10
|
+
return Response.json({ error: {
|
|
11
|
+
name: this.name,
|
|
12
|
+
message: this.message
|
|
13
|
+
} }, { status: this.status });
|
|
14
|
+
}
|
|
15
|
+
toJSON() {
|
|
16
|
+
return {
|
|
17
|
+
name: this.name,
|
|
18
|
+
message: this.message,
|
|
19
|
+
status: this.status
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var ValidationError = class extends UltraError {
|
|
24
|
+
constructor(message = "Validation failed") {
|
|
25
|
+
super(message, "ValidationError", 422);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var UnauthorizedError = class extends UltraError {
|
|
29
|
+
constructor(message = "Unauthorized") {
|
|
30
|
+
super(message, "UnauthorizedError", 401);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var NotFoundError = class extends UltraError {
|
|
34
|
+
constructor(message = "Not Found") {
|
|
35
|
+
super(message, "NotFoundError", 404);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var UnsupportedProtocolError = class extends UltraError {
|
|
39
|
+
constructor(message = "Unsupported Protocol") {
|
|
40
|
+
super(message, "UnsupportedProtocolError", 400);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ValidationError as a, UnsupportedProtocolError as i, UltraError as n, UnauthorizedError as r, NotFoundError as t };
|
package/dist/error.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/error.d.ts
|
|
2
|
+
declare class UltraError extends Error {
|
|
3
|
+
status: number;
|
|
4
|
+
constructor(message: string, name: string, status: number);
|
|
5
|
+
toResponse(): Response;
|
|
6
|
+
toJSON(): {
|
|
7
|
+
name: string;
|
|
8
|
+
message: string;
|
|
9
|
+
status: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
declare class ValidationError extends UltraError {
|
|
13
|
+
constructor(message?: string);
|
|
14
|
+
}
|
|
15
|
+
declare class UnauthorizedError extends UltraError {
|
|
16
|
+
constructor(message?: string);
|
|
17
|
+
}
|
|
18
|
+
declare class NotFoundError extends UltraError {
|
|
19
|
+
constructor(message?: string);
|
|
20
|
+
}
|
|
21
|
+
declare class UnsupportedProtocolError extends UltraError {
|
|
22
|
+
constructor(message?: string);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { NotFoundError, UltraError, UnauthorizedError, UnsupportedProtocolError, ValidationError };
|
package/dist/error.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { n as DefaultSocketData } from "./context-ChCsZh7S.mjs";
|
|
2
|
+
import { o as Promisable } from "./types-Cn69QrjS.mjs";
|
|
3
|
+
import { BunRequest, Server } from "bun";
|
|
4
|
+
|
|
5
|
+
//#region src/http.d.ts
|
|
6
|
+
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
7
|
+
type BunRouteHandler = ((request: BunRequest, server: Server<DefaultSocketData>) => Promisable<Response | undefined>) | Response;
|
|
8
|
+
type BunRoutes = Record<string, Partial<Record<HTTPMethod, BunRouteHandler>> | BunRouteHandler>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { BunRoutes as n, HTTPMethod as r, BunRouteHandler as t };
|
package/dist/http.d.mts
ADDED
package/dist/http.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { t as BaseContext } from "./context-ChCsZh7S.mjs";
|
|
2
|
+
import { o as Promisable } from "./types-Cn69QrjS.mjs";
|
|
3
|
+
import { r as HTTPMethod } from "./http-BqWCMASL.mjs";
|
|
4
|
+
import { c as StandardSchemaV1 } from "./validation-CkRfxQJ_.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/procedure.d.ts
|
|
7
|
+
interface ProcedureOptions<I, C> {
|
|
8
|
+
input: I;
|
|
9
|
+
context: C;
|
|
10
|
+
}
|
|
11
|
+
type ProcedureHandler<I, O, C extends BaseContext> = (options: ProcedureOptions<I, C>) => Promisable<O>;
|
|
12
|
+
interface HTTPOptions {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
method?: HTTPMethod;
|
|
15
|
+
}
|
|
16
|
+
declare class Procedure<I = any, O = any, C extends BaseContext = BaseContext> {
|
|
17
|
+
protected inputSchema?: StandardSchemaV1<I>;
|
|
18
|
+
protected outputSchema?: StandardSchemaV1<O>;
|
|
19
|
+
protected handlerFunction?: ProcedureHandler<I, O, C>;
|
|
20
|
+
protected middleware: Set<Middleware<I, O, C>>;
|
|
21
|
+
protected httpOptions?: HTTPOptions;
|
|
22
|
+
input<const NI>(schema?: StandardSchemaV1<NI>): Procedure<NI, O, C>;
|
|
23
|
+
output<const NO>(schema?: StandardSchemaV1<NO>): Procedure<I, NO, C>;
|
|
24
|
+
handler<const ActualOutput>(handler: ProcedureHandler<I, ActualOutput, C>): Procedure<I, ActualOutput, C>;
|
|
25
|
+
http(options?: {
|
|
26
|
+
method?: HTTPMethod;
|
|
27
|
+
}): Procedure<I, O, C>;
|
|
28
|
+
use(middleware: Middleware<I, O, C>): Procedure<I, O, C>;
|
|
29
|
+
wrap(): ProcedureHandler<I, O, C>;
|
|
30
|
+
getInfo(): {
|
|
31
|
+
http: HTTPOptions | undefined;
|
|
32
|
+
hasInput: boolean;
|
|
33
|
+
hasOutput: boolean;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/middleware.d.ts
|
|
38
|
+
interface MiddlewareOptions<I, O, C extends BaseContext = BaseContext> extends ProcedureOptions<I, C> {
|
|
39
|
+
next: () => ReturnType<ProcedureHandler<I, O, C>>;
|
|
40
|
+
}
|
|
41
|
+
type Middleware<I, O, C extends BaseContext> = (options: MiddlewareOptions<I, O, C>) => Awaited<ReturnType<ProcedureHandler<I, O, C>>>;
|
|
42
|
+
//#endregion
|
|
43
|
+
export { ProcedureHandler as a, Procedure as i, MiddlewareOptions as n, ProcedureOptions as o, HTTPOptions as r, Middleware as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { t as validate } from "./validation-Cop5Wvlr.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/procedure.ts
|
|
4
|
+
var Procedure = class {
|
|
5
|
+
inputSchema;
|
|
6
|
+
outputSchema;
|
|
7
|
+
handlerFunction;
|
|
8
|
+
middleware = /* @__PURE__ */ new Set();
|
|
9
|
+
httpOptions;
|
|
10
|
+
input(schema) {
|
|
11
|
+
if (schema) this.inputSchema = schema;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
output(schema) {
|
|
15
|
+
if (schema) this.outputSchema = schema;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
handler(handler) {
|
|
19
|
+
this.handlerFunction = handler;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
http(options) {
|
|
23
|
+
this.httpOptions = {
|
|
24
|
+
...options,
|
|
25
|
+
enabled: true
|
|
26
|
+
};
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
use(middleware) {
|
|
30
|
+
this.middleware.add(middleware);
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
wrap() {
|
|
34
|
+
if (!this.handlerFunction) throw new Error("Procedure handler is not defined");
|
|
35
|
+
if (!this.inputSchema && !this.outputSchema && !this.middleware.size) return this.handlerFunction;
|
|
36
|
+
let composed = this.handlerFunction;
|
|
37
|
+
switch (true) {
|
|
38
|
+
case !this.inputSchema && !this.outputSchema: break;
|
|
39
|
+
case !this.inputSchema: {
|
|
40
|
+
const previous = composed;
|
|
41
|
+
composed = async (options) => validate(this.outputSchema, await previous(options));
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case !this.outputSchema: {
|
|
45
|
+
const previous = composed;
|
|
46
|
+
composed = async (options) => previous({
|
|
47
|
+
...options,
|
|
48
|
+
input: await validate(this.inputSchema, options.input)
|
|
49
|
+
});
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
default: {
|
|
53
|
+
const previous = composed;
|
|
54
|
+
composed = async (options) => {
|
|
55
|
+
const result = await previous({
|
|
56
|
+
...options,
|
|
57
|
+
input: await validate(this.inputSchema, options.input)
|
|
58
|
+
});
|
|
59
|
+
return validate(this.outputSchema, result);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (this.middleware.size) {
|
|
64
|
+
const middleware = Array.from(this.middleware);
|
|
65
|
+
for (let i = middleware.length - 1; i >= 0; i--) {
|
|
66
|
+
const mw = middleware[i];
|
|
67
|
+
const previous = composed;
|
|
68
|
+
composed = (options) => mw({
|
|
69
|
+
...options,
|
|
70
|
+
next: () => previous(options)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return composed;
|
|
75
|
+
}
|
|
76
|
+
getInfo() {
|
|
77
|
+
return {
|
|
78
|
+
http: this.httpOptions,
|
|
79
|
+
hasInput: !!this.inputSchema,
|
|
80
|
+
hasOutput: !!this.outputSchema
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { Procedure as t };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { n as UltraError } from "./error-CII1zMOR.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/response.ts
|
|
4
|
+
function toHTTPResponse(data) {
|
|
5
|
+
switch (true) {
|
|
6
|
+
case data instanceof Response: return data;
|
|
7
|
+
case data instanceof UltraError: return data.toResponse();
|
|
8
|
+
case data instanceof Error: return new Response("Internal Server Error", { status: 500 });
|
|
9
|
+
case typeof data === "object": return Response.json(data);
|
|
10
|
+
case !data: return new Response(null, { status: 204 });
|
|
11
|
+
default: return new Response(String(data));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function toRPCResponse(id, data) {
|
|
15
|
+
let result;
|
|
16
|
+
switch (true) {
|
|
17
|
+
case data instanceof UltraError:
|
|
18
|
+
result = {
|
|
19
|
+
id,
|
|
20
|
+
error: {
|
|
21
|
+
code: data.status,
|
|
22
|
+
message: data.message
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
break;
|
|
26
|
+
case data instanceof Error:
|
|
27
|
+
result = {
|
|
28
|
+
id,
|
|
29
|
+
error: {
|
|
30
|
+
code: 500,
|
|
31
|
+
message: data.message
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
break;
|
|
35
|
+
case data instanceof Response:
|
|
36
|
+
result = {
|
|
37
|
+
id,
|
|
38
|
+
error: {
|
|
39
|
+
code: data.status,
|
|
40
|
+
message: data.statusText
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
break;
|
|
44
|
+
case typeof data === "object" || typeof data === "number" || typeof data === "boolean":
|
|
45
|
+
result = {
|
|
46
|
+
id,
|
|
47
|
+
result: data
|
|
48
|
+
};
|
|
49
|
+
break;
|
|
50
|
+
default: result = {
|
|
51
|
+
id,
|
|
52
|
+
result: String(data)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return JSON.stringify(result);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { toRPCResponse as n, toHTTPResponse as t };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { a as JSONValue } from "./types-Cn69QrjS.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/rpc.d.ts
|
|
4
|
+
interface ErrorResult {
|
|
5
|
+
id: string;
|
|
6
|
+
error: {
|
|
7
|
+
code: number;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
interface SuccessResult {
|
|
12
|
+
id: string;
|
|
13
|
+
result: JSONValue;
|
|
14
|
+
}
|
|
15
|
+
type Result = ErrorResult | SuccessResult;
|
|
16
|
+
interface Payload {
|
|
17
|
+
id: string;
|
|
18
|
+
method: string;
|
|
19
|
+
params?: JSONValue;
|
|
20
|
+
}
|
|
21
|
+
declare function isRPC(value: any): value is Payload;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { isRPC as a, SuccessResult as i, Payload as n, Result as r, ErrorResult as t };
|
package/dist/rpc.d.mts
ADDED
package/dist/rpc.mjs
ADDED