ziex 0.1.0-dev.786 → 0.1.0-dev.787
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/aws-lambda/index.d.ts +96 -0
- package/aws-lambda/index.js +126 -0
- package/cloudflare/app.d.ts +95 -0
- package/cloudflare/index.d.ts +2 -0
- package/cloudflare/index.js +1160 -58
- package/cloudflare/kv.d.ts +8 -0
- package/cloudflare/worker.d.ts +111 -2
- package/hono/index.d.ts +92 -0
- package/hono/index.js +1515 -0
- package/index.d.ts +1 -9
- package/index.js +1496 -46
- package/package.json +16 -2
- package/vercel/index.d.ts +26 -0
- package/vercel/index.js +18 -0
- package/wasm/index.d.ts +4 -0
- package/wasm/index.js +50 -0
- package/wasm/init.js +50 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ziex adapter for AWS Lambda (API Gateway v1, v2, and ALB).
|
|
3
|
+
*
|
|
4
|
+
* Based on Hono's AWS Lambda adapter implementation.
|
|
5
|
+
*
|
|
6
|
+
* @example API Gateway v2 (HTTP API)
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { Ziex } from "ziex/cloudflare";
|
|
9
|
+
* import { handle } from "ziex/aws-lambda";
|
|
10
|
+
* import module from "./app.wasm";
|
|
11
|
+
*
|
|
12
|
+
* const app = new Ziex({ module });
|
|
13
|
+
* export const handler = handle(app);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
type ApiGwV1Event = {
|
|
17
|
+
version?: "1.0";
|
|
18
|
+
httpMethod: string;
|
|
19
|
+
path: string;
|
|
20
|
+
headers: Record<string, string> | null;
|
|
21
|
+
multiValueHeaders: Record<string, string[]> | null;
|
|
22
|
+
queryStringParameters: Record<string, string> | null;
|
|
23
|
+
multiValueQueryStringParameters: Record<string, string[]> | null;
|
|
24
|
+
body: string | null;
|
|
25
|
+
isBase64Encoded: boolean;
|
|
26
|
+
requestContext: {
|
|
27
|
+
elb?: unknown;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
type ApiGwV2Event = {
|
|
31
|
+
version: "2.0";
|
|
32
|
+
requestContext: {
|
|
33
|
+
http: {
|
|
34
|
+
method: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
rawPath: string;
|
|
38
|
+
rawQueryString: string;
|
|
39
|
+
headers: Record<string, string>;
|
|
40
|
+
body?: string;
|
|
41
|
+
isBase64Encoded: boolean;
|
|
42
|
+
};
|
|
43
|
+
type AlbEvent = {
|
|
44
|
+
httpMethod: string;
|
|
45
|
+
path: string;
|
|
46
|
+
headers: Record<string, string> | null;
|
|
47
|
+
multiValueHeaders: Record<string, string[]> | null;
|
|
48
|
+
queryStringParameters: Record<string, string> | null;
|
|
49
|
+
multiValueQueryStringParameters: Record<string, string[]> | null;
|
|
50
|
+
body: string | null;
|
|
51
|
+
isBase64Encoded: boolean;
|
|
52
|
+
requestContext: {
|
|
53
|
+
elb: unknown;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export type LambdaEvent = ApiGwV1Event | ApiGwV2Event | AlbEvent;
|
|
57
|
+
export type LambdaContext = {
|
|
58
|
+
functionName: string;
|
|
59
|
+
functionVersion: string;
|
|
60
|
+
invokedFunctionArn: string;
|
|
61
|
+
memoryLimitInMB: string;
|
|
62
|
+
awsRequestId: string;
|
|
63
|
+
logGroupName: string;
|
|
64
|
+
logStreamName: string;
|
|
65
|
+
callbackWaitsForEmptyEventLoop: boolean;
|
|
66
|
+
getRemainingTimeInMillis(): number;
|
|
67
|
+
};
|
|
68
|
+
export type LambdaResult = {
|
|
69
|
+
statusCode: number;
|
|
70
|
+
headers: Record<string, string>;
|
|
71
|
+
multiValueHeaders: Record<string, string[]>;
|
|
72
|
+
body: string;
|
|
73
|
+
isBase64Encoded: boolean;
|
|
74
|
+
cookies?: string[];
|
|
75
|
+
};
|
|
76
|
+
type FetchApp = {
|
|
77
|
+
fetch(req: Request, env?: unknown, ctx?: unknown): Promise<Response>;
|
|
78
|
+
};
|
|
79
|
+
export type HandleOptions = {
|
|
80
|
+
/**
|
|
81
|
+
* Content types to encode as base64 in the Lambda response.
|
|
82
|
+
* By default, non-text content types are base64 encoded automatically.
|
|
83
|
+
*/
|
|
84
|
+
binaryMediaTypes?: string[];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Wrap a Ziex app as an AWS Lambda handler.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* import { handle } from "ziex/aws-lambda";
|
|
92
|
+
* export const handler = handle(app);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function handle(app: FetchApp, options?: HandleOptions): (event: LambdaEvent, _context?: LambdaContext) => Promise<LambdaResult>;
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/aws-lambda/index.ts
|
|
13
|
+
function isV2(event) {
|
|
14
|
+
return "requestContext" in event && event.requestContext !== null && "http" in event.requestContext;
|
|
15
|
+
}
|
|
16
|
+
function getMethod(event) {
|
|
17
|
+
if (isV2(event))
|
|
18
|
+
return event.requestContext.http.method;
|
|
19
|
+
return event.httpMethod;
|
|
20
|
+
}
|
|
21
|
+
function getPath(event) {
|
|
22
|
+
if (isV2(event)) {
|
|
23
|
+
return event.rawPath + (event.rawQueryString ? `?${event.rawQueryString}` : "");
|
|
24
|
+
}
|
|
25
|
+
const e = event;
|
|
26
|
+
const mvqs = e.multiValueQueryStringParameters;
|
|
27
|
+
const qs = e.queryStringParameters;
|
|
28
|
+
let queryString = "";
|
|
29
|
+
if (mvqs) {
|
|
30
|
+
queryString = Object.entries(mvqs).flatMap(([k, vs]) => (vs ?? []).map((v) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)).join("&");
|
|
31
|
+
} else if (qs) {
|
|
32
|
+
queryString = new URLSearchParams(qs).toString();
|
|
33
|
+
}
|
|
34
|
+
return e.path + (queryString ? `?${queryString}` : "");
|
|
35
|
+
}
|
|
36
|
+
function getHeaders(event) {
|
|
37
|
+
const headers = new Headers;
|
|
38
|
+
if (event.headers) {
|
|
39
|
+
for (const [k, v] of Object.entries(event.headers)) {
|
|
40
|
+
if (v != null)
|
|
41
|
+
headers.set(k, v);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if ("multiValueHeaders" in event && event.multiValueHeaders) {
|
|
45
|
+
for (const [k, vs] of Object.entries(event.multiValueHeaders)) {
|
|
46
|
+
if (!vs?.length)
|
|
47
|
+
continue;
|
|
48
|
+
headers.delete(k);
|
|
49
|
+
for (const v of vs)
|
|
50
|
+
headers.append(k, v);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return headers;
|
|
54
|
+
}
|
|
55
|
+
function getBody(event) {
|
|
56
|
+
if (!event.body)
|
|
57
|
+
return null;
|
|
58
|
+
if (event.isBase64Encoded)
|
|
59
|
+
return Buffer.from(event.body, "base64");
|
|
60
|
+
return event.body;
|
|
61
|
+
}
|
|
62
|
+
function toRequest(event, headers) {
|
|
63
|
+
const method = getMethod(event);
|
|
64
|
+
const host = headers.get("host") ?? "localhost";
|
|
65
|
+
const proto = headers.get("x-forwarded-proto") ?? "https";
|
|
66
|
+
const path = getPath(event);
|
|
67
|
+
const url = `${proto}://${host}${path}`;
|
|
68
|
+
const body = ["GET", "HEAD"].includes(method) ? null : getBody(event);
|
|
69
|
+
return new Request(url, { method, headers, body });
|
|
70
|
+
}
|
|
71
|
+
var TEXT_CONTENT_TYPES = [
|
|
72
|
+
"text/",
|
|
73
|
+
"application/json",
|
|
74
|
+
"application/xml",
|
|
75
|
+
"application/javascript",
|
|
76
|
+
"application/xhtml"
|
|
77
|
+
];
|
|
78
|
+
function isBinaryContent(contentType, binaryMediaTypes) {
|
|
79
|
+
if (binaryMediaTypes.length > 0) {
|
|
80
|
+
return binaryMediaTypes.some((t) => contentType.includes(t));
|
|
81
|
+
}
|
|
82
|
+
return !TEXT_CONTENT_TYPES.some((t) => contentType.startsWith(t));
|
|
83
|
+
}
|
|
84
|
+
async function toLambdaResult(res, binaryMediaTypes) {
|
|
85
|
+
const responseHeaders = {};
|
|
86
|
+
const multiValueHeaders = {};
|
|
87
|
+
res.headers.forEach((value, key) => {
|
|
88
|
+
if (key in responseHeaders) {
|
|
89
|
+
multiValueHeaders[key] = [...multiValueHeaders[key] ?? [responseHeaders[key]], value];
|
|
90
|
+
delete responseHeaders[key];
|
|
91
|
+
} else if (key in multiValueHeaders) {
|
|
92
|
+
multiValueHeaders[key].push(value);
|
|
93
|
+
} else {
|
|
94
|
+
responseHeaders[key] = value;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
98
|
+
const binary = isBinaryContent(contentType, binaryMediaTypes);
|
|
99
|
+
let body;
|
|
100
|
+
let isBase64Encoded = false;
|
|
101
|
+
if (binary) {
|
|
102
|
+
body = Buffer.from(await res.arrayBuffer()).toString("base64");
|
|
103
|
+
isBase64Encoded = true;
|
|
104
|
+
} else {
|
|
105
|
+
body = await res.text();
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
statusCode: res.status,
|
|
109
|
+
headers: responseHeaders,
|
|
110
|
+
multiValueHeaders,
|
|
111
|
+
body,
|
|
112
|
+
isBase64Encoded
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function handle(app, options = {}) {
|
|
116
|
+
const binaryMediaTypes = options.binaryMediaTypes ?? [];
|
|
117
|
+
return async (event, _context) => {
|
|
118
|
+
const headers = getHeaders(event);
|
|
119
|
+
const req = toRequest(event, headers);
|
|
120
|
+
const res = await app.fetch(req);
|
|
121
|
+
return toLambdaResult(res, binaryMediaTypes);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
handle
|
|
126
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { KVNamespace } from "./kv";
|
|
2
|
+
type DurableObjectNamespace = {
|
|
3
|
+
idFromName(name: string): unknown;
|
|
4
|
+
get(id: unknown): {
|
|
5
|
+
fetch(req: Request): Promise<Response>;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
type WASI = {
|
|
9
|
+
wasiImport: Record<string, (...args: any[]) => unknown>;
|
|
10
|
+
start(instance: {
|
|
11
|
+
exports: {
|
|
12
|
+
memory: WebAssembly.Memory;
|
|
13
|
+
_start: () => unknown;
|
|
14
|
+
};
|
|
15
|
+
}): number;
|
|
16
|
+
initialize?(instance: {
|
|
17
|
+
exports: {
|
|
18
|
+
memory: WebAssembly.Memory;
|
|
19
|
+
_initialize?: () => unknown;
|
|
20
|
+
};
|
|
21
|
+
}): void;
|
|
22
|
+
};
|
|
23
|
+
type ZiexOptions<Env> = {
|
|
24
|
+
/** Compiled WASM module for the Ziex app. */
|
|
25
|
+
module: WebAssembly.Module;
|
|
26
|
+
/** Optional pre-configured WASI instance. */
|
|
27
|
+
wasi?: WASI;
|
|
28
|
+
/** Extra WASM import namespaces. */
|
|
29
|
+
imports?: (mem: () => WebAssembly.Memory) => Record<string, Record<string, unknown>>;
|
|
30
|
+
/**
|
|
31
|
+
* Factory that maps platform env bindings to Ziex KV namespaces.
|
|
32
|
+
* Called per-request so bindings are resolved from the live env.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* kv: (env) => ({ default: env.MY_KV })
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
kv?: (env: Env) => Record<string, KVNamespace>;
|
|
40
|
+
/**
|
|
41
|
+
* Factory that maps platform env bindings to a Durable Object namespace
|
|
42
|
+
* for WebSocket pub/sub. Requires `createWebSocketDO` export on the worker.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* websocket: (env) => env.ChatRoom
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
websocket?: (env: Env) => DurableObjectNamespace;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Main Ziex application class. Mirrors the Hono API style — construct once,
|
|
53
|
+
* export as default, and the runtime calls `fetch` for you.
|
|
54
|
+
*
|
|
55
|
+
* Works on Cloudflare Workers out of the box. For other platforms use the
|
|
56
|
+
* adapter methods (e.g. `app.vercel()`).
|
|
57
|
+
*
|
|
58
|
+
* @example Cloudflare Workers
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { Ziex } from "ziex/cloudflare";
|
|
61
|
+
* import module from "./app.wasm";
|
|
62
|
+
*
|
|
63
|
+
* const app = new Ziex<Env>({
|
|
64
|
+
* module,
|
|
65
|
+
* kv: (env) => ({ default: env.KV }),
|
|
66
|
+
* websocket: (env) => env.ChatRoom,
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* export const ChatRoom = createWebSocketDO(module);
|
|
70
|
+
* export default app;
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @example Vercel Edge
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { Ziex } from "ziex/cloudflare";
|
|
76
|
+
* import module from "./app.wasm"; // fetch at runtime on Vercel, see vercel adapter
|
|
77
|
+
*
|
|
78
|
+
* const app = new Ziex({ module });
|
|
79
|
+
* export default app.vercel();
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare class Ziex<Env = Record<string, unknown>> {
|
|
83
|
+
private readonly options;
|
|
84
|
+
constructor(options: ZiexOptions<Env>);
|
|
85
|
+
/**
|
|
86
|
+
* Cloudflare Workers fetch handler.
|
|
87
|
+
*
|
|
88
|
+
* `env` and `ctx` are injected by the CF runtime — you never call this
|
|
89
|
+
* directly. Just `export default app` and Cloudflare handles the rest.
|
|
90
|
+
*/
|
|
91
|
+
fetch(request: Request, env: Env, ctx?: {
|
|
92
|
+
waitUntil(p: Promise<unknown>): void;
|
|
93
|
+
}): Promise<Response>;
|
|
94
|
+
}
|
|
95
|
+
export {};
|
package/cloudflare/index.d.ts
CHANGED