@ecopages/core 0.2.0-beta.29 → 0.2.0-beta.30
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/README.md +36 -7
- package/package.json +2 -2
- package/src/adapters/README.md +6 -2
- package/src/adapters/abstract/segment-path-matcher.d.ts +6 -0
- package/src/adapters/abstract/segment-path-matcher.js +149 -0
- package/src/adapters/abstract/ws-pattern-matcher.d.ts +2 -50
- package/src/adapters/abstract/ws-pattern-matcher.js +5 -36
- package/src/adapters/{shared → bun}/bun-user-websocket-lifecycle.js +1 -1
- package/src/adapters/bun/create-app.d.ts +2 -2
- package/src/adapters/bun/create-app.js +2 -2
- package/src/adapters/bun/hmr-manager.d.ts +1 -1
- package/src/adapters/bun/hmr-manager.js +1 -1
- package/src/adapters/bun/index.d.ts +1 -1
- package/src/adapters/bun/index.js +25 -2
- package/src/adapters/bun/runtime-host.d.ts +1 -1
- package/src/adapters/bun/runtime-host.js +1 -1
- package/src/adapters/bun/server-adapter.d.ts +8 -25
- package/src/adapters/bun/server-adapter.js +21 -65
- package/src/adapters/bun/static-preview-host.d.ts +1 -1
- package/src/adapters/bun/static-preview-host.js +1 -1
- package/src/adapters/index.d.ts +1 -1
- package/src/adapters/index.js +25 -2
- package/src/adapters/node/create-app.d.ts +2 -2
- package/src/adapters/node/create-app.js +2 -2
- package/src/adapters/node/node-hmr-manager.d.ts +1 -1
- package/src/adapters/node/node-hmr-manager.js +1 -1
- package/src/adapters/node/runtime-host.d.ts +1 -1
- package/src/adapters/node/runtime-host.js +1 -1
- package/src/adapters/node/server-adapter.d.ts +2 -3
- package/src/adapters/node/server-adapter.js +15 -18
- package/src/adapters/node/static-preview-host.d.ts +1 -1
- package/src/adapters/node/static-preview-host.js +1 -1
- package/src/adapters/shared/{hmr-entrypoint-registrar.d.ts → hmr/hmr-entrypoint-registrar.d.ts} +1 -1
- package/src/adapters/shared/{hmr-entrypoint-registrar.js → hmr/hmr-entrypoint-registrar.js} +1 -1
- package/src/adapters/shared/{hmr-html-response.d.ts → hmr/hmr-html-response.d.ts} +1 -1
- package/src/adapters/shared/{shared-hmr-manager.d.ts → hmr/shared-hmr-manager.d.ts} +9 -8
- package/src/adapters/shared/{shared-hmr-manager.js → hmr/shared-hmr-manager.js} +41 -15
- package/src/adapters/shared/http/api-request-pipeline.d.ts +23 -0
- package/src/adapters/shared/http/api-request-pipeline.js +129 -0
- package/src/adapters/shared/{api-response.d.ts → http/api-response.d.ts} +1 -1
- package/src/adapters/shared/{api-response.js → http/api-response.js} +6 -23
- package/src/adapters/shared/http/create-body-response.d.ts +12 -0
- package/src/adapters/shared/http/create-body-response.js +23 -0
- package/src/adapters/shared/http/define-api-handler.d.ts +90 -0
- package/src/adapters/shared/http/define-api-handler.js +63 -0
- package/src/adapters/shared/{explicit-static-render-preparation.d.ts → http/explicit-static-render-preparation.d.ts} +3 -3
- package/src/adapters/shared/{explicit-static-route-matcher.d.ts → http/explicit-static-route-matcher.d.ts} +3 -9
- package/src/adapters/shared/{explicit-static-route-matcher.js → http/explicit-static-route-matcher.js} +3 -38
- package/src/adapters/shared/{file-route-middleware-pipeline.d.ts → http/file-route-middleware-pipeline.d.ts} +2 -2
- package/src/adapters/shared/{file-route-middleware-pipeline.js → http/file-route-middleware-pipeline.js} +10 -22
- package/src/adapters/shared/{fs-server-response-factory.d.ts → http/fs-server-response-factory.d.ts} +2 -2
- package/src/adapters/shared/{fs-server-response-factory.js → http/fs-server-response-factory.js} +2 -2
- package/src/adapters/shared/{fs-server-response-matcher.d.ts → http/fs-server-response-matcher.d.ts} +5 -5
- package/src/adapters/shared/{fs-server-response-matcher.js → http/fs-server-response-matcher.js} +5 -5
- package/src/adapters/shared/http/run-middleware-chain.d.ts +5 -0
- package/src/adapters/shared/http/run-middleware-chain.js +17 -0
- package/src/adapters/shared/{application-adapter.d.ts → runtime/application-adapter.d.ts} +2 -2
- package/src/adapters/shared/{application-adapter.js → runtime/application-adapter.js} +1 -1
- package/src/adapters/shared/{render-context.d.ts → runtime/render-context.d.ts} +2 -2
- package/src/adapters/shared/{render-context.js → runtime/render-context.js} +8 -17
- package/src/adapters/shared/{runtime-app-bootstrap.d.ts → runtime/runtime-app-bootstrap.d.ts} +2 -2
- package/src/adapters/shared/{runtime-app-bootstrap.js → runtime/runtime-app-bootstrap.js} +1 -1
- package/src/adapters/shared/{runtime-server-lifecycle.d.ts → runtime/runtime-server-lifecycle.d.ts} +13 -13
- package/src/adapters/shared/{runtime-server-lifecycle.js → runtime/runtime-server-lifecycle.js} +22 -15
- package/src/adapters/shared/{server-adapter.d.ts → runtime/server-adapter.d.ts} +20 -48
- package/src/adapters/shared/runtime/server-adapter.js +226 -0
- package/src/adapters/shared/{server-route-handler.d.ts → runtime/server-route-handler.d.ts} +6 -36
- package/src/adapters/shared/{server-route-handler.js → runtime/server-route-handler.js} +6 -47
- package/src/adapters/shared/{server-static-builder.d.ts → runtime/server-static-builder.d.ts} +6 -6
- package/src/adapters/shared/{server-static-builder.js → runtime/server-static-builder.js} +8 -8
- package/src/adapters/shared/{static-preview-host.d.ts → runtime/static-preview-host.d.ts} +1 -1
- package/src/adapters/shared/{node-http-websocket-upgrades.d.ts → ws/node-http-websocket-upgrades.d.ts} +1 -1
- package/src/adapters/shared/{node-http-websocket-upgrades.js → ws/node-http-websocket-upgrades.js} +2 -2
- package/src/adapters/shared/{websocket-lifecycle.d.ts → ws/websocket-lifecycle.d.ts} +1 -1
- package/src/adapters/shared/{websocket-lifecycle.js → ws/websocket-lifecycle.js} +1 -1
- package/src/build/app-build-manifest-runtime.d.ts +4 -0
- package/src/build/app-build-manifest-runtime.js +19 -9
- package/src/index.d.ts +1 -1
- package/src/index.js +24 -1
- package/src/static-site-generator/static-site-generator.js +1 -1
- package/src/types/internal-types.d.ts +8 -2
- package/src/types/public-types.d.ts +9 -1
- package/src/adapters/shared/define-api-handler.d.ts +0 -25
- package/src/adapters/shared/define-api-handler.js +0 -15
- package/src/adapters/shared/server-adapter.js +0 -452
- /package/src/adapters/{shared → bun}/bun-user-websocket-lifecycle.d.ts +0 -0
- /package/src/adapters/shared/{hmr-html-response.js → hmr/hmr-html-response.js} +0 -0
- /package/src/adapters/shared/{explicit-static-render-preparation.js → http/explicit-static-render-preparation.js} +0 -0
- /package/src/adapters/shared/{copy-runtime-public-dir.d.ts → runtime/copy-runtime-public-dir.d.ts} +0 -0
- /package/src/adapters/shared/{copy-runtime-public-dir.js → runtime/copy-runtime-public-dir.js} +0 -0
- /package/src/adapters/shared/{port-manager.d.ts → runtime/port-manager.d.ts} +0 -0
- /package/src/adapters/shared/{port-manager.js → runtime/port-manager.js} +0 -0
- /package/src/adapters/shared/{runtime-host.d.ts → runtime/runtime-host.d.ts} +0 -0
- /package/src/adapters/shared/{runtime-host.js → runtime/runtime-host.js} +0 -0
- /package/src/adapters/shared/{static-preview-host.js → runtime/static-preview-host.js} +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { createRequire } from "../../../utils/locals-utils.js";
|
|
2
|
+
import { HttpError } from "../../../errors/http-error.js";
|
|
3
|
+
import { ApiResponseBuilder } from "./api-response.js";
|
|
4
|
+
import { runMiddlewareChain } from "./run-middleware-chain.js";
|
|
5
|
+
import { matchApiPathPattern, scoreApiPathPattern } from "../../abstract/segment-path-matcher.js";
|
|
6
|
+
import { appLogger } from "../../../global/app-logger.js";
|
|
7
|
+
class ApiRequestPipeline {
|
|
8
|
+
schemaValidator;
|
|
9
|
+
getRenderContext;
|
|
10
|
+
getCacheService;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.schemaValidator = options.schemaValidator;
|
|
13
|
+
this.getRenderContext = options.getRenderContext;
|
|
14
|
+
this.getCacheService = options.getCacheService;
|
|
15
|
+
}
|
|
16
|
+
match(request, apiHandlers) {
|
|
17
|
+
const pathname = new URL(request.url).pathname;
|
|
18
|
+
const method = request.method.toUpperCase();
|
|
19
|
+
const sortedHandlers = [...apiHandlers].sort((a, b) => {
|
|
20
|
+
return scoreApiPathPattern(b.path) - scoreApiPathPattern(a.path);
|
|
21
|
+
});
|
|
22
|
+
for (const routeConfig of sortedHandlers) {
|
|
23
|
+
const routeMethod = (routeConfig.method || "GET").toUpperCase();
|
|
24
|
+
if (routeMethod !== method) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const params = matchApiPathPattern(routeConfig.path, pathname);
|
|
28
|
+
if (params) {
|
|
29
|
+
return { routeConfig, params };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
async tryHandle(request, apiHandlers, serverInstance, errorHandler) {
|
|
35
|
+
const apiMatch = this.match(request, apiHandlers);
|
|
36
|
+
if (!apiMatch) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return await this.execute(request, apiMatch.params, apiMatch.routeConfig, serverInstance, errorHandler);
|
|
40
|
+
}
|
|
41
|
+
async execute(request, params, routeConfig, serverInstance, errorHandler) {
|
|
42
|
+
let context;
|
|
43
|
+
try {
|
|
44
|
+
context = this.createContext(request, params, serverInstance);
|
|
45
|
+
const schemaResponse = await this.applyRequestSchema(context, routeConfig.schema);
|
|
46
|
+
if (schemaResponse) {
|
|
47
|
+
return schemaResponse;
|
|
48
|
+
}
|
|
49
|
+
return await this.runMiddlewareChain(context, routeConfig);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (error instanceof Response) return error;
|
|
52
|
+
if (errorHandler) {
|
|
53
|
+
try {
|
|
54
|
+
if (!context) {
|
|
55
|
+
context = this.createContext(request, params, serverInstance);
|
|
56
|
+
}
|
|
57
|
+
return await errorHandler(error, context);
|
|
58
|
+
} catch (handlerError) {
|
|
59
|
+
appLogger.error(`[ecopages] Error in custom error handler: ${handlerError}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (error instanceof HttpError) return error.toResponse();
|
|
63
|
+
appLogger.error(`[ecopages] Error handling API request: ${error}`);
|
|
64
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
createContext(request, params, serverInstance) {
|
|
68
|
+
const locals = {};
|
|
69
|
+
const normalizedParams = this.normalizeParams(params);
|
|
70
|
+
return {
|
|
71
|
+
request,
|
|
72
|
+
params: normalizedParams,
|
|
73
|
+
response: new ApiResponseBuilder(),
|
|
74
|
+
server: serverInstance,
|
|
75
|
+
locals,
|
|
76
|
+
require: createRequire(() => locals),
|
|
77
|
+
services: {
|
|
78
|
+
cache: this.getCacheService()
|
|
79
|
+
},
|
|
80
|
+
...this.getRenderContext()
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
normalizeParams(params) {
|
|
84
|
+
return Object.fromEntries(
|
|
85
|
+
Object.entries(params).map(([key, value]) => [key, Array.isArray(value) ? value.join("/") : value])
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
async applyRequestSchema(context, schema) {
|
|
89
|
+
if (!schema) {
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
const url = new URL(context.request.url);
|
|
93
|
+
const queryParams = Object.fromEntries(url.searchParams);
|
|
94
|
+
const headers = Object.fromEntries(context.request.headers);
|
|
95
|
+
let body;
|
|
96
|
+
if (schema.body) {
|
|
97
|
+
try {
|
|
98
|
+
const contentType = context.request.headers.get("Content-Type") || "";
|
|
99
|
+
if (contentType.includes("application/json")) body = await context.request.clone().json();
|
|
100
|
+
else if (contentType.includes("text/plain")) body = await context.request.clone().text();
|
|
101
|
+
} catch {
|
|
102
|
+
return context.response.status(400).json({ error: "Invalid request body" });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const validationResult = await this.schemaValidator.validateRequest(
|
|
106
|
+
{ body, query: queryParams, headers, params: context.params },
|
|
107
|
+
schema
|
|
108
|
+
);
|
|
109
|
+
if (!validationResult.success) {
|
|
110
|
+
return context.response.status(400).json({
|
|
111
|
+
error: "Validation failed",
|
|
112
|
+
issues: validationResult.errors
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const validated = validationResult.data;
|
|
116
|
+
if (validated.body !== void 0) context.body = validated.body;
|
|
117
|
+
if (validated.query !== void 0) context.query = validated.query;
|
|
118
|
+
if (validated.headers !== void 0) context.headers = validated.headers;
|
|
119
|
+
if (validated.params !== void 0) context.params = validated.params;
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
async runMiddlewareChain(context, routeConfig) {
|
|
123
|
+
const middleware = routeConfig.middleware ?? [];
|
|
124
|
+
return runMiddlewareChain(middleware, context, async () => await routeConfig.handler(context));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
ApiRequestPipeline
|
|
129
|
+
};
|
|
@@ -21,7 +21,7 @@ export declare class ApiResponseBuilder {
|
|
|
21
21
|
* @param data - The data to serialize.
|
|
22
22
|
* @returns A Response object.
|
|
23
23
|
*/
|
|
24
|
-
json(data:
|
|
24
|
+
json(data: unknown): Response;
|
|
25
25
|
/**
|
|
26
26
|
* Creates a plain text response using the configured status and headers.
|
|
27
27
|
* @param data - The text content.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createBodyResponse } from "./create-body-response.js";
|
|
1
2
|
class ApiResponseBuilder {
|
|
2
3
|
_status = 200;
|
|
3
4
|
_headers = new Headers();
|
|
@@ -28,10 +29,7 @@ class ApiResponseBuilder {
|
|
|
28
29
|
* @returns A Response object.
|
|
29
30
|
*/
|
|
30
31
|
json(data) {
|
|
31
|
-
|
|
32
|
-
this._headers.set("Content-Type", "application/json; charset=utf-8");
|
|
33
|
-
}
|
|
34
|
-
return new Response(JSON.stringify(data), { status: this._status, headers: this._headers });
|
|
32
|
+
return createBodyResponse("json", data, { status: this._status, headers: this._headers });
|
|
35
33
|
}
|
|
36
34
|
/**
|
|
37
35
|
* Creates a plain text response using the configured status and headers.
|
|
@@ -39,10 +37,7 @@ class ApiResponseBuilder {
|
|
|
39
37
|
* @returns A Response object.
|
|
40
38
|
*/
|
|
41
39
|
text(data) {
|
|
42
|
-
|
|
43
|
-
this._headers.set("Content-Type", "text/plain; charset=utf-8");
|
|
44
|
-
}
|
|
45
|
-
return new Response(data, { status: this._status, headers: this._headers });
|
|
40
|
+
return createBodyResponse("text", data, { status: this._status, headers: this._headers });
|
|
46
41
|
}
|
|
47
42
|
/**
|
|
48
43
|
* Creates an HTML response using the configured status and headers.
|
|
@@ -50,10 +45,7 @@ class ApiResponseBuilder {
|
|
|
50
45
|
* @returns A Response object.
|
|
51
46
|
*/
|
|
52
47
|
html(data) {
|
|
53
|
-
|
|
54
|
-
this._headers.set("Content-Type", "text/html; charset=utf-8");
|
|
55
|
-
}
|
|
56
|
-
return new Response(data, { status: this._status, headers: this._headers });
|
|
48
|
+
return createBodyResponse("html", data, { status: this._status, headers: this._headers });
|
|
57
49
|
}
|
|
58
50
|
/**
|
|
59
51
|
* Creates a redirect response.
|
|
@@ -77,18 +69,9 @@ class ApiResponseBuilder {
|
|
|
77
69
|
const errorStatus = explicitStatus ?? (this._status === 200 ? 500 : this._status);
|
|
78
70
|
this.status(errorStatus);
|
|
79
71
|
if (typeof data === "object" && data !== null) {
|
|
80
|
-
|
|
81
|
-
this._headers.set("Content-Type", "application/json; charset=utf-8");
|
|
82
|
-
}
|
|
83
|
-
return new Response(JSON.stringify({ error: data }), {
|
|
84
|
-
status: this._status,
|
|
85
|
-
headers: this._headers
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
if (!this._headers.has("Content-Type")) {
|
|
89
|
-
this._headers.set("Content-Type", "text/plain; charset=utf-8");
|
|
72
|
+
return createBodyResponse("json", { error: data }, { status: this._status, headers: this._headers });
|
|
90
73
|
}
|
|
91
|
-
return
|
|
74
|
+
return createBodyResponse("text", String(data), { status: this._status, headers: this._headers });
|
|
92
75
|
}
|
|
93
76
|
}
|
|
94
77
|
export {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type BodyResponseKind = 'json' | 'html' | 'text';
|
|
2
|
+
export type CreateBodyResponseInit = {
|
|
3
|
+
status?: Response['status'];
|
|
4
|
+
headers?: HeadersInit;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Builds a typed HTTP response body for JSON, HTML, or plain text.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Sole internal emission path for adapter response helpers. Not exported from `@ecopages/core`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createBodyResponse(kind: BodyResponseKind, data: unknown, init?: CreateBodyResponseInit): Response;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function createBodyResponse(kind, data, init) {
|
|
2
|
+
const headers = new Headers(init?.headers);
|
|
3
|
+
const status = init?.status ?? 200;
|
|
4
|
+
if (kind === "json") {
|
|
5
|
+
if (!headers.has("Content-Type")) {
|
|
6
|
+
headers.set("Content-Type", "application/json; charset=utf-8");
|
|
7
|
+
}
|
|
8
|
+
return new Response(JSON.stringify(data), { status, headers });
|
|
9
|
+
}
|
|
10
|
+
if (kind === "html") {
|
|
11
|
+
if (!headers.has("Content-Type")) {
|
|
12
|
+
headers.set("Content-Type", "text/html; charset=utf-8");
|
|
13
|
+
}
|
|
14
|
+
return new Response(String(data), { status, headers });
|
|
15
|
+
}
|
|
16
|
+
if (!headers.has("Content-Type")) {
|
|
17
|
+
headers.set("Content-Type", "text/plain; charset=utf-8");
|
|
18
|
+
}
|
|
19
|
+
return new Response(String(data), { status, headers });
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
createBodyResponse
|
|
23
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { ApiHandler, ApiHandlerContext, Middleware, ResponseOptions, RouteSchema, TypedGroupHandlerContext } from '../../../types/public-types.js';
|
|
2
|
+
type UniversalContext = ApiHandlerContext<Request, unknown>;
|
|
3
|
+
type SchemaHandlerContext<TSchema extends RouteSchema | undefined, TContext extends UniversalContext> = TSchema extends RouteSchema ? TypedGroupHandlerContext<TSchema, TContext> : TContext;
|
|
4
|
+
type DefineApiHandlerInput<TPath extends string, TSchema extends RouteSchema | undefined, TContext extends UniversalContext> = Omit<ApiHandler<TPath, Request, unknown>, 'handler' | 'middleware' | 'schema' | 'method'> & {
|
|
5
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
6
|
+
middleware?: Middleware<Request, unknown, TContext>[];
|
|
7
|
+
schema?: TSchema;
|
|
8
|
+
};
|
|
9
|
+
export declare function defineApiHandler<TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: DefineApiHandlerInput<TPath, TSchema, TContext> & {
|
|
10
|
+
method: ApiHandler<TPath, Request, unknown>['method'];
|
|
11
|
+
}): ApiHandler<TPath, Request, unknown>;
|
|
12
|
+
declare const defineApiMethod: <M extends ApiHandler["method"]>(method: M) => <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: DefineApiHandlerInput<TPath, TSchema, TContext> & {
|
|
13
|
+
path: TPath;
|
|
14
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
15
|
+
export declare const defineGet: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
16
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
17
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
18
|
+
schema?: TSchema | undefined;
|
|
19
|
+
} & {
|
|
20
|
+
path: TPath;
|
|
21
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
22
|
+
export declare const definePost: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
23
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
24
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
25
|
+
schema?: TSchema | undefined;
|
|
26
|
+
} & {
|
|
27
|
+
path: TPath;
|
|
28
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
29
|
+
export declare const definePut: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
30
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
31
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
32
|
+
schema?: TSchema | undefined;
|
|
33
|
+
} & {
|
|
34
|
+
path: TPath;
|
|
35
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
36
|
+
export declare const defineDelete: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
37
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
38
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
39
|
+
schema?: TSchema | undefined;
|
|
40
|
+
} & {
|
|
41
|
+
path: TPath;
|
|
42
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
43
|
+
export declare const definePatch: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
44
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
45
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
46
|
+
schema?: TSchema | undefined;
|
|
47
|
+
} & {
|
|
48
|
+
path: TPath;
|
|
49
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
50
|
+
export declare const defineOptions: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
51
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
52
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
53
|
+
schema?: TSchema | undefined;
|
|
54
|
+
} & {
|
|
55
|
+
path: TPath;
|
|
56
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
57
|
+
export declare const defineHead: <const TPath extends string, TSchema extends RouteSchema | undefined = undefined, TContext extends UniversalContext = UniversalContext>(handler: Omit<ApiHandler<TPath, Request, unknown>, "middleware" | "method" | "schema" | "handler"> & {
|
|
58
|
+
handler: (context: SchemaHandlerContext<TSchema, TContext>) => Promise<Response> | Response;
|
|
59
|
+
middleware?: Middleware<Request, unknown, TContext>[] | undefined;
|
|
60
|
+
schema?: TSchema | undefined;
|
|
61
|
+
} & {
|
|
62
|
+
path: TPath;
|
|
63
|
+
}) => ApiHandler<TPath, Request, unknown>;
|
|
64
|
+
export declare function json(data: unknown, options?: ResponseOptions): Response;
|
|
65
|
+
export declare function html(content: string, options?: ResponseOptions): Response;
|
|
66
|
+
export declare function redirect(url: string, status?: number): Response;
|
|
67
|
+
export interface GroupHandler<TPrefix extends string = string> {
|
|
68
|
+
prefix: TPrefix;
|
|
69
|
+
middleware?: readonly Middleware<Request, unknown, any>[];
|
|
70
|
+
routes: readonly ApiHandler<string, Request, unknown>[];
|
|
71
|
+
}
|
|
72
|
+
type GroupDefineHandler<TContext extends UniversalContext> = {
|
|
73
|
+
<const TPath extends string, TSchema extends RouteSchema | undefined = undefined>(handler: DefineApiHandlerInput<TPath, TSchema, TContext> & {
|
|
74
|
+
path: TPath;
|
|
75
|
+
method: ApiHandler<TPath, Request, unknown>['method'];
|
|
76
|
+
}): ApiHandler<TPath, Request, unknown>;
|
|
77
|
+
get: ReturnType<typeof defineApiMethod<'GET'>>;
|
|
78
|
+
post: ReturnType<typeof defineApiMethod<'POST'>>;
|
|
79
|
+
put: ReturnType<typeof defineApiMethod<'PUT'>>;
|
|
80
|
+
delete: ReturnType<typeof defineApiMethod<'DELETE'>>;
|
|
81
|
+
patch: ReturnType<typeof defineApiMethod<'PATCH'>>;
|
|
82
|
+
options: ReturnType<typeof defineApiMethod<'OPTIONS'>>;
|
|
83
|
+
head: ReturnType<typeof defineApiMethod<'HEAD'>>;
|
|
84
|
+
};
|
|
85
|
+
export declare function defineGroupHandler<TPrefix extends string, TMiddleware extends readonly Middleware<Request, unknown, any>[] = [], TContext extends UniversalContext = TMiddleware extends readonly Middleware<Request, unknown, infer TGroupContext>[] ? TGroupContext : UniversalContext>(config: {
|
|
86
|
+
prefix: TPrefix;
|
|
87
|
+
middleware?: TMiddleware;
|
|
88
|
+
routes: (api: GroupDefineHandler<TContext>) => readonly ApiHandler<string, Request, unknown>[];
|
|
89
|
+
}): GroupHandler<TPrefix>;
|
|
90
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createBodyResponse } from "./create-body-response.js";
|
|
2
|
+
function defineApiHandler(handler) {
|
|
3
|
+
return handler;
|
|
4
|
+
}
|
|
5
|
+
const defineApiMethod = (method) => (handler) => defineApiHandler({ ...handler, method });
|
|
6
|
+
const defineGet = defineApiMethod("GET");
|
|
7
|
+
const definePost = defineApiMethod("POST");
|
|
8
|
+
const definePut = defineApiMethod("PUT");
|
|
9
|
+
const defineDelete = defineApiMethod("DELETE");
|
|
10
|
+
const definePatch = defineApiMethod("PATCH");
|
|
11
|
+
const defineOptions = defineApiMethod("OPTIONS");
|
|
12
|
+
const defineHead = defineApiMethod("HEAD");
|
|
13
|
+
function json(data, options) {
|
|
14
|
+
return createBodyResponse("json", data, {
|
|
15
|
+
status: options?.status,
|
|
16
|
+
headers: options?.headers
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function html(content, options) {
|
|
20
|
+
return createBodyResponse("html", content, {
|
|
21
|
+
status: options?.status,
|
|
22
|
+
headers: options?.headers
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function redirect(url, status = 302) {
|
|
26
|
+
return new Response(null, {
|
|
27
|
+
status,
|
|
28
|
+
headers: { Location: url }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function createGroupApi() {
|
|
32
|
+
const define = ((handler) => handler);
|
|
33
|
+
return Object.assign(define, {
|
|
34
|
+
get: defineApiMethod("GET"),
|
|
35
|
+
post: defineApiMethod("POST"),
|
|
36
|
+
put: defineApiMethod("PUT"),
|
|
37
|
+
delete: defineApiMethod("DELETE"),
|
|
38
|
+
patch: defineApiMethod("PATCH"),
|
|
39
|
+
options: defineApiMethod("OPTIONS"),
|
|
40
|
+
head: defineApiMethod("HEAD")
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function defineGroupHandler(config) {
|
|
44
|
+
return {
|
|
45
|
+
prefix: config.prefix,
|
|
46
|
+
middleware: config.middleware,
|
|
47
|
+
routes: config.routes(createGroupApi())
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
defineApiHandler,
|
|
52
|
+
defineDelete,
|
|
53
|
+
defineGet,
|
|
54
|
+
defineGroupHandler,
|
|
55
|
+
defineHead,
|
|
56
|
+
defineOptions,
|
|
57
|
+
definePatch,
|
|
58
|
+
definePost,
|
|
59
|
+
definePut,
|
|
60
|
+
html,
|
|
61
|
+
json,
|
|
62
|
+
redirect
|
|
63
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { EcoPagesAppConfig } from '
|
|
2
|
-
import type { EcoFunctionComponent, EcoPageComponent } from '
|
|
3
|
-
import type { ExplicitViewRenderer, ExplicitViewRendererResolver } from '
|
|
1
|
+
import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
|
|
2
|
+
import type { EcoFunctionComponent, EcoPageComponent } from '../../../types/public-types.js';
|
|
3
|
+
import type { ExplicitViewRenderer, ExplicitViewRendererResolver } from '../../../route-renderer/route-renderer.js';
|
|
4
4
|
type ExplicitStaticRenderPreparationResult = {
|
|
5
5
|
renderer: ExplicitViewRenderer;
|
|
6
6
|
props: Record<string, unknown>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { EcoPagesAppConfig } from '
|
|
2
|
-
import type { StaticRoute } from '
|
|
3
|
-
import type { ExplicitViewRendererResolver } from '
|
|
1
|
+
import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
|
|
2
|
+
import type { StaticRoute } from '../../../types/public-types.js';
|
|
3
|
+
import type { ExplicitViewRendererResolver } from '../../../route-renderer/route-renderer.js';
|
|
4
4
|
export declare const EXPLICIT_STATIC_ROUTE_MATCHER_ERRORS: {
|
|
5
5
|
readonly missingIntegration: (routePath: string) => string;
|
|
6
6
|
readonly noRendererForIntegration: (integrationName: string) => string;
|
|
@@ -27,12 +27,6 @@ export declare class ExplicitStaticRouteMatcher {
|
|
|
27
27
|
* Returns the matched route and extracted params, or null if no match.
|
|
28
28
|
*/
|
|
29
29
|
match(url: string): ExplicitRouteMatch | null;
|
|
30
|
-
/**
|
|
31
|
-
* Match a route pattern against a pathname.
|
|
32
|
-
* Supports :param and [param] syntax.
|
|
33
|
-
* Returns extracted params or null if no match.
|
|
34
|
-
*/
|
|
35
|
-
private matchRoute;
|
|
36
30
|
/**
|
|
37
31
|
* Handle a matched explicit static route.
|
|
38
32
|
* Resolves the loader and renders the view using the appropriate integration renderer.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { appLogger } from "
|
|
1
|
+
import { appLogger } from "../../../global/app-logger.js";
|
|
2
2
|
import { prepareExplicitStaticRender } from "./explicit-static-render-preparation.js";
|
|
3
|
+
import { matchExplicitStaticPathPattern } from "../../abstract/segment-path-matcher.js";
|
|
3
4
|
const EXPLICIT_STATIC_ROUTE_MATCHER_ERRORS = {
|
|
4
5
|
missingIntegration: (routePath) => `View at ${routePath} is missing __eco.integration. Ensure it's defined with eco.page() and exported as default.`,
|
|
5
6
|
noRendererForIntegration: (integrationName) => `No renderer found for integration: ${integrationName}`
|
|
@@ -20,49 +21,13 @@ class ExplicitStaticRouteMatcher {
|
|
|
20
21
|
match(url) {
|
|
21
22
|
const pathname = new URL(url).pathname;
|
|
22
23
|
for (const route of this.staticRoutes) {
|
|
23
|
-
const params =
|
|
24
|
+
const params = matchExplicitStaticPathPattern(route.path, pathname);
|
|
24
25
|
if (params !== null) {
|
|
25
26
|
return { route, params };
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
return null;
|
|
29
30
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Match a route pattern against a pathname.
|
|
32
|
-
* Supports :param and [param] syntax.
|
|
33
|
-
* Returns extracted params or null if no match.
|
|
34
|
-
*/
|
|
35
|
-
matchRoute(pattern, pathname) {
|
|
36
|
-
const patternSegments = pattern.split("/").filter(Boolean);
|
|
37
|
-
const pathSegments = pathname.split("/").filter(Boolean);
|
|
38
|
-
if (patternSegments.length !== pathSegments.length) {
|
|
39
|
-
const lastPattern = patternSegments[patternSegments.length - 1];
|
|
40
|
-
const isCatchAll = lastPattern?.startsWith("[...") || lastPattern?.startsWith(":...");
|
|
41
|
-
if (!isCatchAll) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const params = {};
|
|
46
|
-
for (let i = 0; i < patternSegments.length; i++) {
|
|
47
|
-
const patternPart = patternSegments[i];
|
|
48
|
-
const pathPart = pathSegments[i];
|
|
49
|
-
if (patternPart.startsWith(":...") || patternPart.startsWith("[...")) {
|
|
50
|
-
const paramName = patternPart.replace(/^(:\.\.\.|\[\.\.\.)/, "").replace(/\]$/, "");
|
|
51
|
-
params[paramName] = pathSegments.slice(i).join("/");
|
|
52
|
-
return params;
|
|
53
|
-
}
|
|
54
|
-
if (patternPart.startsWith(":")) {
|
|
55
|
-
const paramName = patternPart.slice(1);
|
|
56
|
-
params[paramName] = pathPart;
|
|
57
|
-
} else if (patternPart.startsWith("[") && patternPart.endsWith("]")) {
|
|
58
|
-
const paramName = patternPart.slice(1, -1);
|
|
59
|
-
params[paramName] = pathPart;
|
|
60
|
-
} else if (patternPart !== pathPart) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return params;
|
|
65
|
-
}
|
|
66
31
|
/**
|
|
67
32
|
* Handle a matched explicit static route.
|
|
68
33
|
* Resolves the loader and renders the view using the appropriate integration renderer.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FileRouteMiddleware, FileRouteMiddlewareContext, RequestLocals } from '
|
|
2
|
-
import type { PageCacheService } from '
|
|
1
|
+
import type { FileRouteMiddleware, FileRouteMiddlewareContext, RequestLocals } from '../../../types/public-types.js';
|
|
2
|
+
import type { PageCacheService } from '../../../services/cache/page-cache-service.js';
|
|
3
3
|
export declare const FILE_ROUTE_MIDDLEWARE_PIPELINE_ERRORS: {
|
|
4
4
|
readonly middlewareRequiresDynamic: (filePath: string) => string;
|
|
5
5
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createRequire } from "
|
|
1
|
+
import { createRequire } from "../../../utils/locals-utils.js";
|
|
2
2
|
import { ApiResponseBuilder } from "./api-response.js";
|
|
3
|
-
import {
|
|
3
|
+
import { runMiddlewareChain } from "./run-middleware-chain.js";
|
|
4
|
+
import { LocalsAccessError } from "../../../errors/locals-access-error.js";
|
|
4
5
|
const FILE_ROUTE_MIDDLEWARE_PIPELINE_ERRORS = {
|
|
5
6
|
middlewareRequiresDynamic: (filePath) => `[ecopages] Page middleware requires cache: 'dynamic'. Page: ${filePath}`
|
|
6
7
|
};
|
|
@@ -46,16 +47,14 @@ class FileRouteMiddlewarePipeline {
|
|
|
46
47
|
locals: input.locals,
|
|
47
48
|
require: createRequire(() => context.locals),
|
|
48
49
|
json: (data, options) => {
|
|
49
|
-
|
|
50
|
-
if (options?.
|
|
51
|
-
|
|
52
|
-
return builder.json(data);
|
|
50
|
+
if (options?.status) context.response.status(options.status);
|
|
51
|
+
if (options?.headers) context.response.headers(options.headers);
|
|
52
|
+
return context.response.json(data);
|
|
53
53
|
},
|
|
54
54
|
html: (content, options) => {
|
|
55
|
-
|
|
56
|
-
if (options?.
|
|
57
|
-
|
|
58
|
-
return builder.html(content);
|
|
55
|
+
if (options?.status) context.response.status(options.status);
|
|
56
|
+
if (options?.headers) context.response.headers(options.headers);
|
|
57
|
+
return context.response.html(content);
|
|
59
58
|
}
|
|
60
59
|
};
|
|
61
60
|
return context;
|
|
@@ -70,18 +69,7 @@ class FileRouteMiddlewarePipeline {
|
|
|
70
69
|
* @returns Response from middleware or final render stage.
|
|
71
70
|
*/
|
|
72
71
|
async run(input) {
|
|
73
|
-
|
|
74
|
-
return input.renderResponse();
|
|
75
|
-
}
|
|
76
|
-
let index = 0;
|
|
77
|
-
const executeNext = async () => {
|
|
78
|
-
if (index < input.middleware.length) {
|
|
79
|
-
const current = input.middleware[index++];
|
|
80
|
-
return current(input.context, executeNext);
|
|
81
|
-
}
|
|
82
|
-
return input.renderResponse();
|
|
83
|
-
};
|
|
84
|
-
return executeNext();
|
|
72
|
+
return runMiddlewareChain(input.middleware, input.context, input.renderResponse);
|
|
85
73
|
}
|
|
86
74
|
}
|
|
87
75
|
export {
|
package/src/adapters/shared/{fs-server-response-factory.d.ts → http/fs-server-response-factory.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FileSystemServerOptions } from '
|
|
2
|
-
import type { RouteRendererBody } from '
|
|
1
|
+
import type { FileSystemServerOptions } from '../../../types/internal-types.js';
|
|
2
|
+
import type { RouteRendererBody } from '../../../types/public-types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Builds HTTP responses for static files and shared file-system fallbacks.
|
|
5
5
|
*/
|
package/src/adapters/shared/{fs-server-response-factory.js → http/fs-server-response-factory.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { STATUS_MESSAGE } from "
|
|
2
|
-
import { appLogger } from "
|
|
1
|
+
import { STATUS_MESSAGE } from "../../../config/constants.js";
|
|
2
|
+
import { appLogger } from "../../../global/app-logger.js";
|
|
3
3
|
import { fileSystem } from "@ecopages/file-system";
|
|
4
4
|
class FileSystemServerResponseFactory {
|
|
5
5
|
options;
|
package/src/adapters/shared/{fs-server-response-matcher.d.ts → http/fs-server-response-matcher.d.ts}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { EcoPagesAppConfig, MatchResult } from '
|
|
2
|
-
import type { PageRendererResolver } from '
|
|
3
|
-
import type { RouteRegistry } from '
|
|
4
|
-
import type { PageCacheService } from '
|
|
5
|
-
import type { CacheStrategy } from '
|
|
1
|
+
import type { EcoPagesAppConfig, MatchResult } from '../../../types/internal-types.js';
|
|
2
|
+
import type { PageRendererResolver } from '../../../route-renderer/route-renderer.js';
|
|
3
|
+
import type { RouteRegistry } from '../../../router/server/route-registry.js';
|
|
4
|
+
import type { PageCacheService } from '../../../services/cache/page-cache-service.js';
|
|
5
|
+
import type { CacheStrategy } from '../../../services/cache/cache.types.js';
|
|
6
6
|
import type { FileSystemServerResponseFactory } from './fs-server-response-factory.js';
|
|
7
7
|
export interface FileSystemResponseMatcherOptions {
|
|
8
8
|
appConfig: EcoPagesAppConfig;
|
package/src/adapters/shared/{fs-server-response-matcher.js → http/fs-server-response-matcher.js}
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { appLogger } from "
|
|
3
|
-
import { PageRequestCacheCoordinator } from "
|
|
4
|
-
import { ServerUtils } from "
|
|
2
|
+
import { appLogger } from "../../../global/app-logger.js";
|
|
3
|
+
import { PageRequestCacheCoordinator } from "../../../services/cache/page-request-cache-coordinator.service.js";
|
|
4
|
+
import { ServerUtils } from "../../../utils/server-utils.module.js";
|
|
5
5
|
import { FileRouteMiddlewarePipeline } from "./file-route-middleware-pipeline.js";
|
|
6
|
-
import { LocalsAccessError } from "
|
|
7
|
-
import { isDevelopmentRuntime } from "
|
|
6
|
+
import { LocalsAccessError } from "../../../errors/locals-access-error.js";
|
|
7
|
+
import { isDevelopmentRuntime } from "../../../utils/runtime.js";
|
|
8
8
|
class FileSystemResponseMatcher {
|
|
9
9
|
appConfig;
|
|
10
10
|
assetPrefix;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type MiddlewareHandler<TContext> = (context: TContext, next: () => Promise<Response>) => Response | Promise<Response>;
|
|
2
|
+
/**
|
|
3
|
+
* Runs an onion middleware chain and invokes the terminal handler when the chain completes.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runMiddlewareChain<TContext>(middleware: readonly MiddlewareHandler<TContext>[], context: TContext, terminal: () => Promise<Response>): Promise<Response>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
async function runMiddlewareChain(middleware, context, terminal) {
|
|
2
|
+
if (middleware.length === 0) {
|
|
3
|
+
return terminal();
|
|
4
|
+
}
|
|
5
|
+
let index = 0;
|
|
6
|
+
const executeNext = async () => {
|
|
7
|
+
if (index < middleware.length) {
|
|
8
|
+
const current = middleware[index++];
|
|
9
|
+
return await current(context, executeNext);
|
|
10
|
+
}
|
|
11
|
+
return terminal();
|
|
12
|
+
};
|
|
13
|
+
return executeNext();
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
runMiddlewareChain
|
|
17
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ApiHandler, ApiHandlerContext, Middleware, RouteGroupBuilder, RouteOptions } from '
|
|
2
|
-
import { AbstractApplicationAdapter, type ApplicationAdapterOptions, type RouteGroupDefinition, type RouteHandler } from '
|
|
1
|
+
import type { ApiHandler, ApiHandlerContext, Middleware, RouteGroupBuilder, RouteOptions } from '../../../types/public-types.js';
|
|
2
|
+
import { AbstractApplicationAdapter, type ApplicationAdapterOptions, type RouteGroupDefinition, type RouteHandler } from '../../abstract/application-adapter.js';
|
|
3
3
|
export declare abstract class SharedApplicationAdapter<TOptions extends ApplicationAdapterOptions = ApplicationAdapterOptions, TServer = any, TRequest extends Request = Request> extends AbstractApplicationAdapter<TOptions, TServer, TRequest> {
|
|
4
4
|
protected register<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, method: ApiHandler['method'], handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
|
|
5
5
|
get<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AbstractApplicationAdapter
|
|
3
|
-
} from "
|
|
3
|
+
} from "../../abstract/application-adapter.js";
|
|
4
4
|
class SharedApplicationAdapter extends AbstractApplicationAdapter {
|
|
5
5
|
register(path, method, handler, options) {
|
|
6
6
|
return this.addRouteHandler(path, method, handler, options?.middleware, options?.schema);
|