@browserlessapi/inferlo 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -5
- package/dist/ai/ai-sdk.d.ts +48 -0
- package/dist/ai/ai-sdk.js +235 -0
- package/dist/ai/ai-sdk.js.map +1 -0
- package/dist/ai/index.d.ts +44 -3
- package/dist/ai/index.js +164 -9
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/public.d.ts +6 -1
- package/dist/ai/public.js +2 -0
- package/dist/ai/public.js.map +1 -1
- package/dist/ai/ui.d.ts +47 -0
- package/dist/ai/ui.js +33 -0
- package/dist/ai/ui.js.map +1 -0
- package/dist/api-version.d.ts +32 -0
- package/dist/api-version.js +45 -0
- package/dist/api-version.js.map +1 -0
- package/dist/app.d.ts +60 -6
- package/dist/app.js +310 -66
- package/dist/app.js.map +1 -1
- package/dist/astro.d.ts +60 -0
- package/dist/astro.js +68 -0
- package/dist/astro.js.map +1 -0
- package/dist/audit.d.ts +57 -0
- package/dist/audit.js +99 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +1 -0
- package/dist/auth.js.map +1 -1
- package/dist/azure.d.ts +66 -0
- package/dist/azure.js +119 -0
- package/dist/azure.js.map +1 -0
- package/dist/cache.d.ts +96 -0
- package/dist/cache.js +247 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli/main.js +28 -7
- package/dist/cli/main.js.map +1 -1
- package/dist/client-ip.d.ts +36 -1
- package/dist/client-ip.js +80 -1
- package/dist/client-ip.js.map +1 -1
- package/dist/db/memory.js +2 -1
- package/dist/db/memory.js.map +1 -1
- package/dist/db/postgres.js +4 -1
- package/dist/db/postgres.js.map +1 -1
- package/dist/db/table.d.ts +37 -5
- package/dist/db/table.js +96 -15
- package/dist/db/table.js.map +1 -1
- package/dist/db/types.d.ts +2 -0
- package/dist/describe.d.ts +54 -2
- package/dist/describe.js +34 -3
- package/dist/describe.js.map +1 -1
- package/dist/events.d.ts +134 -0
- package/dist/events.js +196 -0
- package/dist/events.js.map +1 -0
- package/dist/fastify.d.ts +10 -2
- package/dist/fastify.js +22 -4
- package/dist/fastify.js.map +1 -1
- package/dist/h3.d.ts +76 -0
- package/dist/h3.js +61 -0
- package/dist/h3.js.map +1 -0
- package/dist/hapi.d.ts +45 -0
- package/dist/hapi.js +57 -0
- package/dist/hapi.js.map +1 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +70 -10
- package/dist/jobs.js +78 -13
- package/dist/jobs.js.map +1 -1
- package/dist/koa.d.ts +51 -0
- package/dist/koa.js +45 -0
- package/dist/koa.js.map +1 -0
- package/dist/lambda.d.ts +110 -0
- package/dist/lambda.js +169 -0
- package/dist/lambda.js.map +1 -0
- package/dist/langchain.d.ts +58 -0
- package/dist/langchain.js +220 -0
- package/dist/langchain.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +7 -3
- package/dist/mcp.js.map +1 -1
- package/dist/model.d.ts +23 -6
- package/dist/model.js +35 -6
- package/dist/model.js.map +1 -1
- package/dist/module.d.ts +52 -0
- package/dist/module.js +152 -0
- package/dist/module.js.map +1 -0
- package/dist/nextjs.d.ts +35 -0
- package/dist/nextjs.js +33 -0
- package/dist/nextjs.js.map +1 -0
- package/dist/openapi.d.ts +3 -0
- package/dist/openapi.js +12 -3
- package/dist/openapi.js.map +1 -1
- package/dist/permissions.d.ts +26 -0
- package/dist/permissions.js +78 -0
- package/dist/permissions.js.map +1 -0
- package/dist/rate-limit.d.ts +5 -3
- package/dist/rate-limit.js +3 -3
- package/dist/rate-limit.js.map +1 -1
- package/dist/react-router.d.ts +41 -0
- package/dist/react-router.js +42 -0
- package/dist/react-router.js.map +1 -0
- package/dist/redis-events.d.ts +27 -0
- package/dist/redis-events.js +163 -0
- package/dist/redis-events.js.map +1 -0
- package/dist/redis-jobs.d.ts +24 -0
- package/dist/redis-jobs.js +203 -0
- package/dist/redis-jobs.js.map +1 -0
- package/dist/redis.d.ts +30 -0
- package/dist/redis.js +106 -0
- package/dist/redis.js.map +1 -0
- package/dist/request-matcher.d.ts +4 -0
- package/dist/request-matcher.js +14 -0
- package/dist/request-matcher.js.map +1 -0
- package/dist/response-body.d.ts +6 -0
- package/dist/response-body.js +7 -0
- package/dist/response-body.js.map +1 -0
- package/dist/route.d.ts +50 -2
- package/dist/route.js +24 -0
- package/dist/route.js.map +1 -1
- package/dist/schema.d.ts +2 -2
- package/dist/serve.d.ts +26 -2
- package/dist/serve.js +111 -10
- package/dist/serve.js.map +1 -1
- package/dist/service-client.d.ts +91 -0
- package/dist/service-client.js +177 -0
- package/dist/service-client.js.map +1 -0
- package/dist/sessions.d.ts +74 -0
- package/dist/sessions.js +172 -0
- package/dist/sessions.js.map +1 -0
- package/dist/sveltekit.d.ts +72 -0
- package/dist/sveltekit.js +68 -0
- package/dist/sveltekit.js.map +1 -0
- package/dist/tracing.d.ts +122 -0
- package/dist/tracing.js +210 -0
- package/dist/tracing.js.map +1 -0
- package/llms.txt +8 -3
- package/package.json +78 -4
- package/templates/app/AGENTS.md +10 -6
package/dist/route.d.ts
CHANGED
|
@@ -11,15 +11,19 @@
|
|
|
11
11
|
import type { Deprecation } from "./deprecation.ts";
|
|
12
12
|
import type { AI } from "./ai/index.ts";
|
|
13
13
|
import type { Db } from "./db/table.ts";
|
|
14
|
+
import type { Events } from "./events.ts";
|
|
14
15
|
import type { Jobs } from "./jobs.ts";
|
|
15
16
|
import type { AnyModel } from "./model.ts";
|
|
17
|
+
import type { Audit } from "./audit.ts";
|
|
18
|
+
import type { Cache, RouteCache } from "./cache.ts";
|
|
19
|
+
import type { PermissionInput, Permissions } from "./permissions.ts";
|
|
16
20
|
import type { RateLimit } from "./rate-limit.ts";
|
|
17
|
-
import type { AnySchema, Infer, ObjectSchema } from "./schema.ts";
|
|
21
|
+
import type { AnySchema, Infer, InferInput, ObjectSchema } from "./schema.ts";
|
|
18
22
|
/**
|
|
19
23
|
* Register your app's models and user type once, so every handler is fully typed:
|
|
20
24
|
*
|
|
21
25
|
* declare module "@browserlessapi/inferlo" {
|
|
22
|
-
* interface Register { models: typeof models; user: User }
|
|
26
|
+
* interface Register { models: typeof models; user: User; permissions: typeof access }
|
|
23
27
|
* }
|
|
24
28
|
*/
|
|
25
29
|
export interface Register {
|
|
@@ -33,6 +37,15 @@ export type AppUser = Registered<"user", {
|
|
|
33
37
|
roles?: string[];
|
|
34
38
|
}>;
|
|
35
39
|
export type AppDb = Db<AppModels>;
|
|
40
|
+
/**
|
|
41
|
+
* The permission names a route's `permission` option accepts. With `permissions: typeof access` in Register, only the
|
|
42
|
+
* names whose rule needs nothing but { user } (roles rules and rules of the user alone), so a typo is a type error.
|
|
43
|
+
*/
|
|
44
|
+
export type AppPermission = Registered<"permissions", undefined> extends Permissions<infer R> ? {
|
|
45
|
+
[K in keyof R & string]: {
|
|
46
|
+
user: AppUser;
|
|
47
|
+
} extends PermissionInput<R[K]> ? K : never;
|
|
48
|
+
}[keyof R & string] : string;
|
|
36
49
|
export type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
37
50
|
/** "public": anyone. "user": any signed-in user. Any other string: the user must have that role. */
|
|
38
51
|
export type Auth = "public" | "user" | (string & {});
|
|
@@ -45,6 +58,12 @@ export interface ToolOptions {
|
|
|
45
58
|
export interface RouteOptions<B extends AnySchema | undefined, Q extends ObjectSchema<any> | undefined, P extends ObjectSchema<any> | undefined> {
|
|
46
59
|
/** Who may call this route. Default "user" (signed in). */
|
|
47
60
|
auth?: Auth;
|
|
61
|
+
/**
|
|
62
|
+
* A permission from createApp({ permissions }) the signed-in user must have, checked with { user } before the
|
|
63
|
+
* handler runs (also when the route is called as an AI tool). Denied: 403 IL3004. For rules that also need a
|
|
64
|
+
* resource, call access.authorize(name, { user, ticket }) in the handler instead. Typed from Register's permissions.
|
|
65
|
+
*/
|
|
66
|
+
permission?: AppPermission;
|
|
48
67
|
/** Request body schema (JSON or form). */
|
|
49
68
|
body?: B;
|
|
50
69
|
/** Query string schema. Strings are converted to numbers and booleans automatically. */
|
|
@@ -71,6 +90,12 @@ export interface RouteOptions<B extends AnySchema | undefined, Q extends ObjectS
|
|
|
71
90
|
* Link rel="deprecation" headers on every response. Shown in OpenAPI, describe and MCP tool descriptions.
|
|
72
91
|
*/
|
|
73
92
|
deprecated?: boolean | Deprecation;
|
|
93
|
+
/**
|
|
94
|
+
* Cache this GET route's JSON responses in the app cache: { ttlMs: 60_000, by: "user", tags: ["tickets"] }.
|
|
95
|
+
* "user" (default) keeps one response per signed-in user, "public" one for every caller. Remove them early with
|
|
96
|
+
* ctx.cache.invalidate(tag). Responses carry an ETag, so clients revalidate with If-None-Match (304).
|
|
97
|
+
*/
|
|
98
|
+
cache?: RouteCache;
|
|
74
99
|
}
|
|
75
100
|
type PathParams<P extends string> = P extends `${string}:${infer Param}/${infer Rest}` ? {
|
|
76
101
|
[K in Param | keyof PathParams<`/${Rest}`>]: string;
|
|
@@ -88,6 +113,10 @@ export interface Context<Body, Query, Params, User> {
|
|
|
88
113
|
ai: AI;
|
|
89
114
|
/** Queue background jobs: await jobs.enqueue(sendEmail, { to }). */
|
|
90
115
|
jobs: Jobs;
|
|
116
|
+
/** Publish events: await events.publish(orderPaid, { orderId }) queues the jobs subscribed with on(event, job). */
|
|
117
|
+
events: Events;
|
|
118
|
+
/** The app cache: await cache.getOrSet(key, { ttlMs: 60_000, tags: ["tickets"] }, compute), cache.invalidate("tickets"). */
|
|
119
|
+
cache: Cache;
|
|
91
120
|
req: Request;
|
|
92
121
|
url: URL;
|
|
93
122
|
headers: Headers;
|
|
@@ -106,8 +135,22 @@ export interface Context<Body, Query, Params, User> {
|
|
|
106
135
|
requestId: string;
|
|
107
136
|
/** Run work after the response is sent (logging, webhooks). Errors are logged, not thrown. */
|
|
108
137
|
waitUntil(promise: Promise<unknown>): void;
|
|
138
|
+
/**
|
|
139
|
+
* Write an audit log entry with the signed-in user and this request's id (needs AuditLog in createApp({ models })):
|
|
140
|
+
* await audit("tickets.update", { model: "tickets", before: ticket, after: updated }).
|
|
141
|
+
*/
|
|
142
|
+
audit: Audit;
|
|
109
143
|
}
|
|
110
144
|
export type AnyContext = Context<any, any, any, any>;
|
|
145
|
+
/**
|
|
146
|
+
* What a caller sends to a route, before validation (defaults not yet applied): the body, query and path params.
|
|
147
|
+
* Type only ($input on the route returned by handle()), used by serviceClient for typed calls.
|
|
148
|
+
*/
|
|
149
|
+
export interface RouteInput<Path extends string, B, Q, P> {
|
|
150
|
+
body: B extends AnySchema ? InferInput<B> : undefined;
|
|
151
|
+
query: Q extends AnySchema ? InferInput<Q> : Record<string, string | undefined>;
|
|
152
|
+
params: P extends AnySchema ? InferInput<P> : PathParams<Path>;
|
|
153
|
+
}
|
|
111
154
|
export type Handler<C, R> = (ctx: C) => R | Promise<R>;
|
|
112
155
|
export interface RouteDef {
|
|
113
156
|
readonly kind: "inferlo.route";
|
|
@@ -117,6 +160,8 @@ export interface RouteDef {
|
|
|
117
160
|
readonly handler: Handler<AnyContext, unknown>;
|
|
118
161
|
/** Export name, filled in by createApp when routes are passed as modules. */
|
|
119
162
|
name?: string;
|
|
163
|
+
/** API version ("v1") when the route comes from apiVersion("v1", routes). */
|
|
164
|
+
readonly version?: string;
|
|
120
165
|
}
|
|
121
166
|
export declare class RouteBuilder<Path extends string, B extends AnySchema | undefined, Q extends ObjectSchema<any> | undefined, P extends ObjectSchema<any> | undefined, A> {
|
|
122
167
|
readonly method: Method;
|
|
@@ -126,6 +171,7 @@ export declare class RouteBuilder<Path extends string, B extends AnySchema | und
|
|
|
126
171
|
/** The request handler. Return data (sent as JSON), a Response, or nothing (204). */
|
|
127
172
|
handle<R>(handler: Handler<Context<B extends AnySchema ? Infer<B> : undefined, Q extends AnySchema ? Infer<Q> : Record<string, string | undefined>, P extends AnySchema ? Infer<P> : PathParams<Path>, UserFor<A>>, R>): RouteDef & {
|
|
128
173
|
readonly $response: Awaited<R>;
|
|
174
|
+
readonly $input: RouteInput<Path, B, Q, P>;
|
|
129
175
|
};
|
|
130
176
|
}
|
|
131
177
|
export declare const route: {
|
|
@@ -146,4 +192,6 @@ export declare const route: {
|
|
|
146
192
|
}) => RouteBuilder<Path, B, Q, P, A>;
|
|
147
193
|
};
|
|
148
194
|
export declare function isRoute(value: unknown): value is RouteDef;
|
|
195
|
+
/** The routes in route sources: routes, arrays and modules (import * as tickets), named after their exports. */
|
|
196
|
+
export declare function collectRoutes(sources: unknown): RouteDef[];
|
|
149
197
|
export {};
|
package/dist/route.js
CHANGED
|
@@ -25,4 +25,28 @@ export const route = {
|
|
|
25
25
|
export function isRoute(value) {
|
|
26
26
|
return typeof value === "object" && value !== null && value.kind === "inferlo.route";
|
|
27
27
|
}
|
|
28
|
+
/** The routes in route sources: routes, arrays and modules (import * as tickets), named after their exports. */
|
|
29
|
+
export function collectRoutes(sources) {
|
|
30
|
+
const out = [];
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
const visit = (source, name) => {
|
|
33
|
+
if (!source || typeof source !== "object" || seen.has(source))
|
|
34
|
+
return;
|
|
35
|
+
seen.add(source);
|
|
36
|
+
if (isRoute(source)) {
|
|
37
|
+
out.push(name && !source.name ? { ...source, name } : source);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(source)) {
|
|
41
|
+
for (const item of source)
|
|
42
|
+
visit(item);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
for (const [key, value] of Object.entries(source))
|
|
46
|
+
if (isRoute(value) || Array.isArray(value))
|
|
47
|
+
visit(value, key === "default" ? undefined : key);
|
|
48
|
+
};
|
|
49
|
+
visit(sources);
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
28
52
|
//# sourceMappingURL=route.js.map
|
package/dist/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AA2KA,MAAM,OAAO,YAAY;IACd,MAAM,CAAS;IACf,IAAI,CAAO;IACX,OAAO,CAAwB;IAExC,YAAY,MAAc,EAAE,IAAU,EAAE,OAA8B;QACpE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,qFAAqF;IACrF,MAAM,CACJ,OAQC;QAED,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAuC,EAG5I,CAAC;IACJ,CAAC;CACF;AAED,SAAS,OAAO,CAAC,MAAc;IAC7B,OAAO,CAOL,IAAU,EACV,UAAgD,EAAE,EAClD,EAAE,CAAC,IAAI,YAAY,CAAmB,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;IACrB,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;CAC1B,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAK,KAAkB,CAAC,IAAI,KAAK,eAAe,CAAC;AACrG,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,MAAe,EAAE,IAAa,EAAE,EAAE;QAC/C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QACtE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjB,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnJ,CAAC,CAAC;IACF,KAAK,CAAC,OAAO,CAAC,CAAC;IACf,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export interface Def {
|
|
|
26
26
|
example?: unknown;
|
|
27
27
|
unique?: boolean;
|
|
28
28
|
index?: boolean;
|
|
29
|
-
/** Filled in by the framework (id, createdAt, updatedAt). Never accepted as input. */
|
|
30
|
-
system?: "id" | "createdAt" | "updatedAt";
|
|
29
|
+
/** Filled in by the framework (id, createdAt, updatedAt, and tenantId on tenant-scoped models). Never accepted as input. */
|
|
30
|
+
system?: "id" | "createdAt" | "updatedAt" | "tenantId";
|
|
31
31
|
}
|
|
32
32
|
export interface Issue {
|
|
33
33
|
path: (string | number)[];
|
package/dist/serve.d.ts
CHANGED
|
@@ -19,8 +19,16 @@ export interface NodeRequest {
|
|
|
19
19
|
remoteAddress?: string;
|
|
20
20
|
encrypted?: boolean;
|
|
21
21
|
} | null;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* A body the host framework already read (express.json(), body-parser): a string, bytes, or a plain object or
|
|
24
|
+
* array. Used instead of the stream. Instances of other classes are ignored and the stream is read.
|
|
25
|
+
*/
|
|
23
26
|
body?: unknown;
|
|
27
|
+
/**
|
|
28
|
+
* The exact bytes of a body the host already read, as Google Cloud Run functions (the Functions Framework)
|
|
29
|
+
* and Firebase set them. Preferred over body when present, so forms and JSON reach the app unchanged.
|
|
30
|
+
*/
|
|
31
|
+
rawBody?: unknown;
|
|
24
32
|
[Symbol.asyncIterator](): AsyncIterator<unknown>;
|
|
25
33
|
}
|
|
26
34
|
/** The parts of a Node.js http.ServerResponse that Inferlo writes to. */
|
|
@@ -40,12 +48,28 @@ export interface NodeHandlerOptions {
|
|
|
40
48
|
* Leave it out when the host framework already strips the mount path (Express app.use("/ai", ...)).
|
|
41
49
|
*/
|
|
42
50
|
prefix?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Pass requests the app has no route for (by method and path, outside its OpenAPI, MCP, health and metrics
|
|
53
|
+
* endpoints) to the host framework's next() instead of answering 404 or 405. Mount the app before the host's
|
|
54
|
+
* routes with it, to move routes to Inferlo one at a time at the same URLs. Needs an app from createApp and
|
|
55
|
+
* a host that calls the handler with next (Express, NestJS, Connect). Default false.
|
|
56
|
+
*/
|
|
57
|
+
fallthrough?: boolean;
|
|
43
58
|
}
|
|
44
59
|
export interface FromNodeRequestOptions extends NodeHandlerOptions {
|
|
45
60
|
/** Aborts the request (for example when the client disconnects). */
|
|
46
61
|
signal?: AbortSignal;
|
|
47
62
|
}
|
|
48
63
|
export type NodeHandler = (req: NodeRequest, res: NodeResponse, next?: (error?: unknown) => void) => Promise<void>;
|
|
64
|
+
export declare function normalizePrefix(prefix: string | undefined): string;
|
|
65
|
+
/** The path and query of a Node request with the prefix removed, or null when it is outside the prefix. */
|
|
66
|
+
export declare function stripPrefix(rawUrl: string, prefix: string): string | null;
|
|
67
|
+
/**
|
|
68
|
+
* Whether toNodeHandler(app, { prefix, fallthrough: true }) answers a Node request itself instead of passing it
|
|
69
|
+
* on. For hosts that must decide before handing the request over, such as a Fastify onRequest hook.
|
|
70
|
+
*/
|
|
71
|
+
export declare function answersNodeRequest(app: object, req: Pick<NodeRequest, "url" | "method">, prefix?: string): boolean;
|
|
72
|
+
export declare function buildRequest(req: NodeRequest, path: string, signal?: AbortSignal): Request;
|
|
49
73
|
/**
|
|
50
74
|
* Convert a Node.js request (node:http, Express, Fastify's request.raw, NestJS) to a Web Request.
|
|
51
75
|
* With prefix, the prefix is removed from the path; a request outside it keeps its path.
|
|
@@ -59,5 +83,5 @@ export declare function writeResponse(res: NodeResponse, response: Response, met
|
|
|
59
83
|
*/
|
|
60
84
|
export declare function toNodeHandler(app: Pick<App<any>, "fetch">, options?: NodeHandlerOptions): NodeHandler;
|
|
61
85
|
export declare function serve(app: Pick<App<any>, "fetch">, options?: ServeOptions): Promise<Server>;
|
|
62
|
-
/** Closes every open connection of a
|
|
86
|
+
/** Closes every open connection of a server from serve() (Node.js, Bun and Deno), for app.close() after its timeout. */
|
|
63
87
|
export declare const forceClosers: WeakMap<Server, () => void>;
|
package/dist/serve.js
CHANGED
|
@@ -6,14 +6,17 @@
|
|
|
6
6
|
* http.createServer(toNodeHandler(app, { prefix: "/ai" })) // or strip it with prefix
|
|
7
7
|
*/
|
|
8
8
|
import { createRedactor } from "./redact.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import { appAnswers } from "./request-matcher.js";
|
|
10
|
+
import { InferloError } from "./errors.js";
|
|
11
|
+
import { clientIps, clientSignals } from "./client-ip.js";
|
|
12
|
+
import { knownBodies } from "./response-body.js";
|
|
13
|
+
export function normalizePrefix(prefix) {
|
|
11
14
|
if (!prefix || prefix === "/")
|
|
12
15
|
return "";
|
|
13
16
|
return ("/" + prefix.replace(/^\/+|\/+$/g, "")).replace(/\/+/g, "/");
|
|
14
17
|
}
|
|
15
18
|
/** The path and query of a Node request with the prefix removed, or null when it is outside the prefix. */
|
|
16
|
-
function stripPrefix(rawUrl, prefix) {
|
|
19
|
+
export function stripPrefix(rawUrl, prefix) {
|
|
17
20
|
const url = rawUrl.startsWith("/") ? rawUrl : "/" + rawUrl;
|
|
18
21
|
if (!prefix)
|
|
19
22
|
return url;
|
|
@@ -26,6 +29,25 @@ function stripPrefix(rawUrl, prefix) {
|
|
|
26
29
|
return null;
|
|
27
30
|
return rest;
|
|
28
31
|
}
|
|
32
|
+
/** Whether the app answers a method and a path (with query, prefix already removed) itself. */
|
|
33
|
+
function answersPath(app, method, path) {
|
|
34
|
+
let pathname = path.split("?")[0];
|
|
35
|
+
try {
|
|
36
|
+
pathname = new URL(pathname, "http://localhost").pathname;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Leave a path the URL parser rejects to the app, which answers it.
|
|
40
|
+
}
|
|
41
|
+
return appAnswers(app, method, pathname) === true;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether toNodeHandler(app, { prefix, fallthrough: true }) answers a Node request itself instead of passing it
|
|
45
|
+
* on. For hosts that must decide before handing the request over, such as a Fastify onRequest hook.
|
|
46
|
+
*/
|
|
47
|
+
export function answersNodeRequest(app, req, prefix) {
|
|
48
|
+
const path = stripPrefix(req.url ?? "/", normalizePrefix(prefix));
|
|
49
|
+
return path !== null && answersPath(app, req.method ?? "GET", path);
|
|
50
|
+
}
|
|
29
51
|
function bodyStream(req) {
|
|
30
52
|
const iterator = req[Symbol.asyncIterator]();
|
|
31
53
|
return new ReadableStream({
|
|
@@ -45,7 +67,20 @@ function bodyStream(req) {
|
|
|
45
67
|
},
|
|
46
68
|
});
|
|
47
69
|
}
|
|
48
|
-
|
|
70
|
+
/**
|
|
71
|
+
* True when req.body holds a body the host framework already read: a string or bytes (body-parser text and
|
|
72
|
+
* raw), or a plain object or array (express.json(), urlencoded forms). An instance of some other class is the
|
|
73
|
+
* host's own object, such as the body reader of an Encore raw request, and the stream is read instead.
|
|
74
|
+
*/
|
|
75
|
+
function isParsedBody(body) {
|
|
76
|
+
if (body === undefined)
|
|
77
|
+
return false;
|
|
78
|
+
if (body === null || typeof body !== "object" || body instanceof Uint8Array || Array.isArray(body))
|
|
79
|
+
return true;
|
|
80
|
+
const proto = Object.getPrototypeOf(body);
|
|
81
|
+
return proto === Object.prototype || proto === null;
|
|
82
|
+
}
|
|
83
|
+
export function buildRequest(req, path, signal) {
|
|
49
84
|
const host = [req.headers.host].flat()[0] ?? "localhost";
|
|
50
85
|
const url = new URL(path, `${req.socket?.encrypted ? "https" : "http"}://${host}`);
|
|
51
86
|
const headers = new Headers();
|
|
@@ -61,7 +96,12 @@ function buildRequest(req, path, signal) {
|
|
|
61
96
|
const method = (req.method ?? "GET").toUpperCase();
|
|
62
97
|
let body;
|
|
63
98
|
if (method !== "GET" && method !== "HEAD") {
|
|
64
|
-
if (req.
|
|
99
|
+
if (req.rawBody instanceof Uint8Array && isParsedBody(req.body)) {
|
|
100
|
+
// The host read the stream and kept the bytes: the app gets them unchanged, with their own content type.
|
|
101
|
+
headers.delete("content-length");
|
|
102
|
+
body = req.rawBody;
|
|
103
|
+
}
|
|
104
|
+
else if (isParsedBody(req.body)) {
|
|
65
105
|
// The host framework already read the stream: use what it parsed.
|
|
66
106
|
headers.delete("content-length");
|
|
67
107
|
if (typeof req.body === "string" || req.body instanceof Uint8Array)
|
|
@@ -95,6 +135,12 @@ export function fromNodeRequest(req, options = {}) {
|
|
|
95
135
|
const path = stripPrefix(raw, normalizePrefix(options.prefix)) ?? (raw.startsWith("/") ? raw : "/" + raw);
|
|
96
136
|
return buildRequest(req, path, options.signal);
|
|
97
137
|
}
|
|
138
|
+
const encoder = new TextEncoder();
|
|
139
|
+
/** UTF-8 length of a string, with Buffer where the runtime has it (Node.js, Bun). */
|
|
140
|
+
function byteLength(text) {
|
|
141
|
+
const B = globalThis.Buffer;
|
|
142
|
+
return B ? B.byteLength(text) : encoder.encode(text).byteLength;
|
|
143
|
+
}
|
|
98
144
|
/** Write a Web Response (status, headers with every Set-Cookie, streamed body) to a Node response. */
|
|
99
145
|
export async function writeResponse(res, response, method) {
|
|
100
146
|
const outHeaders = {};
|
|
@@ -106,6 +152,13 @@ export async function writeResponse(res, response, method) {
|
|
|
106
152
|
const cookies = response.headers.getSetCookie?.() ?? [];
|
|
107
153
|
if (cookies.length)
|
|
108
154
|
outHeaders["set-cookie"] = cookies;
|
|
155
|
+
// A JSON answer Inferlo built from a string: headers and body in one write, with its length.
|
|
156
|
+
const known = knownBodies.get(response);
|
|
157
|
+
if (known !== undefined && !response.bodyUsed && method !== "HEAD" && outHeaders["content-length"] === undefined && outHeaders["transfer-encoding"] === undefined) {
|
|
158
|
+
outHeaders["content-length"] = String(byteLength(known));
|
|
159
|
+
res.writeHead(response.status, outHeaders);
|
|
160
|
+
return void res.end(known);
|
|
161
|
+
}
|
|
109
162
|
res.writeHead(response.status, outHeaders);
|
|
110
163
|
if (!response.body || method === "HEAD")
|
|
111
164
|
return void res.end();
|
|
@@ -125,17 +178,28 @@ export async function writeResponse(res, response, method) {
|
|
|
125
178
|
*/
|
|
126
179
|
export function toNodeHandler(app, options = {}) {
|
|
127
180
|
const prefix = normalizePrefix(options.prefix);
|
|
181
|
+
if (options.fallthrough !== undefined && typeof options.fallthrough !== "boolean") {
|
|
182
|
+
throw new InferloError("IL5019", "toNodeHandler fallthrough must be true or false.", { fix: "Use toNodeHandler(app, { fallthrough: true })." });
|
|
183
|
+
}
|
|
184
|
+
if (options.fallthrough && appAnswers(app, "GET", "/") === undefined) {
|
|
185
|
+
throw new InferloError("IL5019", "toNodeHandler(app, { fallthrough: true }) needs an app from createApp.", {
|
|
186
|
+
fix: "Pass the app returned by createApp, which knows its routes; a plain fetch handler cannot tell which requests to pass on.",
|
|
187
|
+
});
|
|
188
|
+
}
|
|
128
189
|
return async (req, res, next) => {
|
|
129
190
|
const path = stripPrefix(req.url ?? "/", prefix);
|
|
130
191
|
if (path === null && next)
|
|
131
192
|
return next();
|
|
193
|
+
if (options.fallthrough && next && path !== null && !answersPath(app, req.method ?? "GET", path))
|
|
194
|
+
return next();
|
|
132
195
|
try {
|
|
133
196
|
const controller = new AbortController();
|
|
134
197
|
res.on("close", () => {
|
|
135
198
|
if (!res.writableFinished)
|
|
136
199
|
controller.abort();
|
|
137
200
|
});
|
|
138
|
-
const request = buildRequest(req, path ?? (req.url ?? "/")
|
|
201
|
+
const request = buildRequest(req, path ?? (req.url ?? "/"));
|
|
202
|
+
clientSignals.set(request, controller.signal);
|
|
139
203
|
const response = await app.fetch(request);
|
|
140
204
|
await writeResponse(res, response, request.method);
|
|
141
205
|
}
|
|
@@ -153,11 +217,48 @@ export async function serve(app, options = {}) {
|
|
|
153
217
|
const g = globalThis;
|
|
154
218
|
if (g.Bun) {
|
|
155
219
|
const server = g.Bun.serve({ port, hostname, fetch: (req, bunServer) => app.fetch(req, bunServer) });
|
|
156
|
-
|
|
220
|
+
// Wait until the open requests (and streamed answers) are done, then stop, closing the idle keep-alive
|
|
221
|
+
// connections too. Requests that arrive meanwhile get 503 IL2006 from app.close(). app.close() calls the force
|
|
222
|
+
// closer, stop(true), when its timeout is up. (stop() without true would leave keep-alive connections served on
|
|
223
|
+
// Bun 1.3, and a later stop(true) would then do nothing.)
|
|
224
|
+
let forced = false;
|
|
225
|
+
const result = {
|
|
226
|
+
port: server.port,
|
|
227
|
+
close: async () => {
|
|
228
|
+
while (server.pendingRequests > 0 && !forced)
|
|
229
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
230
|
+
await server.stop(true);
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
forceClosers.set(result, () => {
|
|
234
|
+
forced = true;
|
|
235
|
+
void server.stop(true);
|
|
236
|
+
});
|
|
237
|
+
return result;
|
|
157
238
|
}
|
|
158
239
|
if (g.Deno) {
|
|
159
|
-
|
|
160
|
-
|
|
240
|
+
// shutdown() waits for every open request and streamed answer, with no way to cut them off. So each answer
|
|
241
|
+
// with a body is passed through a stream that the force closer can abort when app.close()'s timeout is up.
|
|
242
|
+
const open = new Set();
|
|
243
|
+
const server = g.Deno.serve({ port, hostname, onListen() { } }, async (req, info) => {
|
|
244
|
+
const response = await app.fetch(req, info);
|
|
245
|
+
if (!response.body)
|
|
246
|
+
return response;
|
|
247
|
+
const abort = new AbortController();
|
|
248
|
+
const { readable, writable } = new TransformStream();
|
|
249
|
+
open.add(abort);
|
|
250
|
+
void response.body
|
|
251
|
+
.pipeTo(writable, { signal: abort.signal })
|
|
252
|
+
.catch(() => { })
|
|
253
|
+
.finally(() => open.delete(abort));
|
|
254
|
+
return new Response(readable, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
255
|
+
});
|
|
256
|
+
const result = { port: server.addr.port, close: () => server.shutdown() };
|
|
257
|
+
forceClosers.set(result, () => {
|
|
258
|
+
for (const abort of open)
|
|
259
|
+
abort.abort();
|
|
260
|
+
});
|
|
261
|
+
return result;
|
|
161
262
|
}
|
|
162
263
|
const http = await import("node:http");
|
|
163
264
|
const handler = toNodeHandler(app);
|
|
@@ -177,6 +278,6 @@ export async function serve(app, options = {}) {
|
|
|
177
278
|
forceClosers.set(result, () => server.closeAllConnections());
|
|
178
279
|
return result;
|
|
179
280
|
}
|
|
180
|
-
/** Closes every open connection of a
|
|
281
|
+
/** Closes every open connection of a server from serve() (Node.js, Bun and Deno), for app.close() after its timeout. */
|
|
181
282
|
export const forceClosers = new WeakMap();
|
|
182
283
|
//# sourceMappingURL=serve.js.map
|
package/dist/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed calls from one Inferlo service to another (microservices, part 1).
|
|
3
|
+
*
|
|
4
|
+
* import { getTicket, createTicket } from "../../tickets/src/routes/tickets.ts"; // the other service's routes
|
|
5
|
+
* const tickets = serviceClient({ baseUrl: settings.TICKETS_URL, token: settings.TICKETS_TOKEN });
|
|
6
|
+
*
|
|
7
|
+
* // in a route handler: input and answer are typed from the route
|
|
8
|
+
* const ticket = await tickets.call(getTicket, { params: { id }, ctx });
|
|
9
|
+
*
|
|
10
|
+
* The route definition gives the method, the path and the types; nothing is generated and nothing is global.
|
|
11
|
+
* Passing ctx forwards the request id (X-Request-Id) and cancels the call when the request is aborted. With
|
|
12
|
+
* tracing: { api: otel }, every attempt is a client span that sends its W3C traceparent, so the other service's
|
|
13
|
+
* spans join the caller's trace.
|
|
14
|
+
*/
|
|
15
|
+
import { InferloError } from "./errors.ts";
|
|
16
|
+
import type { RouteDef } from "./route.ts";
|
|
17
|
+
import { type TracingConfig } from "./tracing.ts";
|
|
18
|
+
export interface ServiceClientOptions {
|
|
19
|
+
/** Where the other service is reached, with any path prefix it is mounted under: "http://tickets.internal" or "https://api.example.com/v1". */
|
|
20
|
+
baseUrl: string;
|
|
21
|
+
/** Sent as Authorization: Bearer <token> on every call. */
|
|
22
|
+
token?: string;
|
|
23
|
+
/** Headers sent on every call. */
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
/** Longest wait for one attempt, in milliseconds. Default 10000. */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Extra attempts for idempotent calls (GET, PUT, DELETE) that fail with a network error, a timeout, or a 502, 503
|
|
29
|
+
* or 504 answer, waiting 100 ms, 200 ms, 400 ms... in between. POST and PATCH are never retried. Default 0.
|
|
30
|
+
*/
|
|
31
|
+
retries?: number;
|
|
32
|
+
/** The fetch to use. Default globalThis.fetch; pass otherApp.fetch to call an app in the same process (tests). */
|
|
33
|
+
fetch?: (request: Request) => Promise<Response>;
|
|
34
|
+
/**
|
|
35
|
+
* OpenTelemetry tracing: import * as otel from "@opentelemetry/api", then tracing: { api: otel }. Every attempt
|
|
36
|
+
* gets a client span ("GET /tickets/:id") under the active span and sends its trace context (traceparent), so a
|
|
37
|
+
* receiving Inferlo app with createApp({ tracing }) continues the same trace.
|
|
38
|
+
*/
|
|
39
|
+
tracing?: TracingConfig;
|
|
40
|
+
}
|
|
41
|
+
/** A route made with route.<method>(...).handle(...): carries the types of its input and answer. */
|
|
42
|
+
export type TypedRoute = RouteDef & {
|
|
43
|
+
readonly $response: unknown;
|
|
44
|
+
readonly $input: {
|
|
45
|
+
body: unknown;
|
|
46
|
+
query: unknown;
|
|
47
|
+
params: unknown;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
type ParamsInput<P> = keyof P extends never ? {
|
|
51
|
+
params?: P;
|
|
52
|
+
} : {
|
|
53
|
+
params: P;
|
|
54
|
+
};
|
|
55
|
+
type BodyInput<B> = undefined extends B ? {
|
|
56
|
+
body?: B;
|
|
57
|
+
} : {
|
|
58
|
+
body: B;
|
|
59
|
+
};
|
|
60
|
+
/** The request context to forward: pass the handler's ctx. */
|
|
61
|
+
export interface CallContext {
|
|
62
|
+
requestId: string;
|
|
63
|
+
signal: AbortSignal;
|
|
64
|
+
}
|
|
65
|
+
/** Options of one call, next to its params, query and body. */
|
|
66
|
+
export interface CallOptions {
|
|
67
|
+
/** The handler's context: forwards its request id and cancels the call when the request is aborted. */
|
|
68
|
+
ctx?: CallContext;
|
|
69
|
+
/** Cancels the call (in addition to ctx). */
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
/** Headers for this call. */
|
|
72
|
+
headers?: Record<string, string>;
|
|
73
|
+
}
|
|
74
|
+
export type CallInput<R extends TypedRoute> = ParamsInput<R["$input"]["params"]> & BodyInput<R["$input"]["body"]> & {
|
|
75
|
+
query?: Partial<R["$input"]["query"]>;
|
|
76
|
+
} & CallOptions;
|
|
77
|
+
/** The answer of a route: its JSON data, undefined for 204, or the Response itself for routes that return one (streams, files). */
|
|
78
|
+
export type CallResult<R extends TypedRoute> = R["$response"] extends Response ? Response : R["$response"] extends void | undefined ? undefined : R["$response"];
|
|
79
|
+
export interface ServiceClient {
|
|
80
|
+
/** Calls a route of the other service. Rejects with IL2008 when the call fails or answers with an error status. */
|
|
81
|
+
call<R extends TypedRoute>(route: R, ...input: {} extends CallInput<R> ? [input?: CallInput<R>] : [input: CallInput<R>]): Promise<CallResult<R>>;
|
|
82
|
+
}
|
|
83
|
+
/** Raised when a call to another service fails: remoteStatus is its HTTP status (0 when no answer came), remoteCode its error code. */
|
|
84
|
+
export declare class ServiceCallError extends InferloError {
|
|
85
|
+
readonly remoteStatus: number;
|
|
86
|
+
readonly remoteCode: string | undefined;
|
|
87
|
+
constructor(message: string, remoteStatus: number, remoteCode: string | undefined, fix: string, details: Record<string, unknown>);
|
|
88
|
+
}
|
|
89
|
+
/** A client for calls to another Inferlo service. See ServiceClientOptions. */
|
|
90
|
+
export declare function serviceClient(options: ServiceClientOptions): ServiceClient;
|
|
91
|
+
export {};
|