@fluojs/platform-deno 1.0.0-beta.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.ko.md +85 -0
- package/README.md +85 -0
- package/dist/adapter.d.ts +128 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +338 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fluo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @fluojs/platform-deno
|
|
2
|
+
|
|
3
|
+
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
|
+
|
|
5
|
+
네이티브 `Deno.serve`를 기반으로 구축된 fluo 런타임용 Deno 기반 HTTP 어댑터 패키지입니다.
|
|
6
|
+
|
|
7
|
+
## 목차
|
|
8
|
+
|
|
9
|
+
- [설치](#설치)
|
|
10
|
+
- [사용 시점](#사용-시점)
|
|
11
|
+
- [빠른 시작](#빠른-시작)
|
|
12
|
+
- [주요 패턴](#주요-패턴)
|
|
13
|
+
- [공개 API 개요](#공개-api-개요)
|
|
14
|
+
- [관련 패키지](#관련-패키지)
|
|
15
|
+
- [예제 소스](#예제-소스)
|
|
16
|
+
|
|
17
|
+
## 설치
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
deno add npm:@fluojs/platform-deno npm:@fluojs/runtime npm:@fluojs/http
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
이 패키지는 Deno에서 실행하는 것을 전제로 합니다. 배포 manifest는 npm 메타데이터가 Deno 런타임 계약과 어긋나지 않도록 의도적으로 `engines.node`를 선언하지 않으며, 저장소의 Node.js 20+ 요구사항은 메인테이너용 빌드/테스트 툴체인에만 적용됩니다.
|
|
24
|
+
|
|
25
|
+
## 사용 시점
|
|
26
|
+
|
|
27
|
+
fluo 애플리케이션을 [Deno](https://deno.com/) 런타임에서 실행할 때 이 패키지를 사용합니다. 이 어댑터는 Deno의 네이티브 `fetch` 표준 `Request` 및 `Response` 객체를 활용하여 TypeScript 백엔드 개발을 위한 안전하고 고성능인 환경을 제공합니다.
|
|
28
|
+
|
|
29
|
+
애플리케이션 종료 중에는 새 유입을 중단하고, Deno 서버 수명주기가 종료되기 전에 활성 HTTP 핸들러가 bounded drain window 안에서 마무리될 수 있도록 동작합니다.
|
|
30
|
+
|
|
31
|
+
`runDenoApplication(...)`을 Deno signal API를 사용할 수 있는 환경에서 실행하면 `SIGINT`/`SIGTERM` 리스너도 등록하고, 애플리케이션이 닫히면 해당 리스너를 정리합니다.
|
|
32
|
+
|
|
33
|
+
## 빠른 시작
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { runDenoApplication } from '@fluojs/platform-deno';
|
|
37
|
+
import { AppModule } from './app.module.ts';
|
|
38
|
+
|
|
39
|
+
await runDenoApplication(AppModule, {
|
|
40
|
+
port: 3000,
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 주요 패턴
|
|
45
|
+
|
|
46
|
+
### 수동 요청 디스패칭
|
|
47
|
+
테스트나 커스텀 `Deno.serve` 구현을 위해 어댑터의 `handle` 메서드를 사용하여 네이티브 웹 요청을 수동으로 디스패치할 수 있습니다. 다만 `handle(...)`은 런타임 dispatcher가 바인딩된 뒤에만 동작하므로, 먼저 `app.listen()`(또는 `runDenoApplication(...)`)으로 부트스트랩을 완료해야 합니다.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { fluoFactory } from '@fluojs/runtime';
|
|
51
|
+
|
|
52
|
+
const adapter = createDenoAdapter({ port: 3000 });
|
|
53
|
+
const app = await fluoFactory.create(AppModule, { adapter });
|
|
54
|
+
|
|
55
|
+
await app.listen();
|
|
56
|
+
|
|
57
|
+
const response = await adapter.handle(new Request('http://localhost:3000/health'));
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Deno 네이티브 WebSocket 지원
|
|
61
|
+
어댑터는 `@fluojs/websockets/deno` 바인딩을 통해 Deno의 네이티브 `Deno.upgradeWebSocket`을 지원합니다.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Deno 어댑터가 활성화된 경우 게이트웨이는 자동으로 Deno의 네이티브 업그레이드를 사용합니다.
|
|
65
|
+
@WebSocketGateway({ path: '/ws' })
|
|
66
|
+
export class MyGateway {}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 공개 API 개요
|
|
70
|
+
|
|
71
|
+
- `createDenoAdapter(options)`: Deno HTTP 어댑터를 위한 팩토리입니다.
|
|
72
|
+
- `bootstrapDenoApplication(module, options)`: 커스텀 오케스트레이션을 위한 고급 부트스트랩입니다.
|
|
73
|
+
- `runDenoApplication(module, options)`: Deno를 위한 권장 빠른 시작 헬퍼입니다.
|
|
74
|
+
- `handle(request)`: 수동 `Request` to `Response` 디스패처입니다.
|
|
75
|
+
|
|
76
|
+
## 관련 패키지
|
|
77
|
+
|
|
78
|
+
- `@fluojs/runtime`: 핵심 런타임입니다.
|
|
79
|
+
- `@fluojs/websockets`: 전용 서브패스 `@fluojs/websockets/deno`를 포함합니다.
|
|
80
|
+
- `@fluojs/http`: HTTP 데코레이터 및 추상화 계층입니다.
|
|
81
|
+
|
|
82
|
+
## 예제 소스
|
|
83
|
+
|
|
84
|
+
- `packages/platform-deno/src/adapter.test.ts`
|
|
85
|
+
- `packages/websockets/src/deno/deno.test.ts`
|
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @fluojs/platform-deno
|
|
2
|
+
|
|
3
|
+
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
|
+
|
|
5
|
+
Deno-backed HTTP adapter for the fluo runtime, built on native `Deno.serve`.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [When to Use](#when-to-use)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Common Patterns](#common-patterns)
|
|
13
|
+
- [Public API Overview](#public-api-overview)
|
|
14
|
+
- [Related Packages](#related-packages)
|
|
15
|
+
- [Example Sources](#example-sources)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
deno add npm:@fluojs/platform-deno npm:@fluojs/runtime npm:@fluojs/http
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This package is intended to run on Deno. The published manifest intentionally does not declare `engines.node`, so npm metadata stays aligned with the Deno runtime contract; the repository's Node.js 20+ requirement only applies to the maintainer build/test toolchain.
|
|
24
|
+
|
|
25
|
+
## When to Use
|
|
26
|
+
|
|
27
|
+
Use this package when running fluo applications on the [Deno](https://deno.com/) runtime. This adapter leverages Deno's native `fetch`-standard `Request` and `Response` objects, providing a secure and high-performance environment for TypeScript backend development.
|
|
28
|
+
|
|
29
|
+
During application shutdown, the adapter stops new ingress and gives active HTTP handlers a bounded drain window before the Deno server lifecycle completes.
|
|
30
|
+
|
|
31
|
+
When `runDenoApplication(...)` runs inside Deno with signal APIs available, it also registers `SIGINT`/`SIGTERM` listeners and removes them once the application closes.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { runDenoApplication } from '@fluojs/platform-deno';
|
|
37
|
+
import { AppModule } from './app.module.ts';
|
|
38
|
+
|
|
39
|
+
await runDenoApplication(AppModule, {
|
|
40
|
+
port: 3000,
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Common Patterns
|
|
45
|
+
|
|
46
|
+
### Manual Request Dispatching
|
|
47
|
+
For testing or custom `Deno.serve` implementations, you can use the adapter's `handle` method to dispatch native web requests manually. Bind the dispatcher first via `app.listen()` (or `runDenoApplication(...)`), because `handle(...)` only works after the runtime has been bootstrapped.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { fluoFactory } from '@fluojs/runtime';
|
|
51
|
+
|
|
52
|
+
const adapter = createDenoAdapter({ port: 3000 });
|
|
53
|
+
const app = await fluoFactory.create(AppModule, { adapter });
|
|
54
|
+
|
|
55
|
+
await app.listen();
|
|
56
|
+
|
|
57
|
+
const response = await adapter.handle(new Request('http://localhost:3000/health'));
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Deno-Native WebSocket Support
|
|
61
|
+
The adapter supports Deno's native `Deno.upgradeWebSocket` through the `@fluojs/websockets/deno` binding.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Gateways automatically use Deno's native upgrade when the Deno adapter is active
|
|
65
|
+
@WebSocketGateway({ path: '/ws' })
|
|
66
|
+
export class MyGateway {}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Public API Overview
|
|
70
|
+
|
|
71
|
+
- `createDenoAdapter(options)`: Factory for the Deno HTTP adapter.
|
|
72
|
+
- `bootstrapDenoApplication(module, options)`: Advanced bootstrap for custom orchestration.
|
|
73
|
+
- `runDenoApplication(module, options)`: Recommended quick-start helper for Deno.
|
|
74
|
+
- `handle(request)`: Manual `Request` to `Response` dispatcher.
|
|
75
|
+
|
|
76
|
+
## Related Packages
|
|
77
|
+
|
|
78
|
+
- `@fluojs/runtime`: Core framework runtime.
|
|
79
|
+
- `@fluojs/websockets`: Includes specific subpath `@fluojs/websockets/deno`.
|
|
80
|
+
- `@fluojs/http`: HTTP decorators and abstractions.
|
|
81
|
+
|
|
82
|
+
## Example Sources
|
|
83
|
+
|
|
84
|
+
- `packages/platform-deno/src/adapter.test.ts`
|
|
85
|
+
- `packages/websockets/src/deno/deno.test.ts`
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { type Dispatcher, type HttpApplicationAdapter } from '@fluojs/http';
|
|
2
|
+
import type { Application, ModuleType, MultipartOptions } from '@fluojs/runtime';
|
|
3
|
+
import { type BootstrapHttpAdapterApplicationOptions, type HttpAdapterListenTarget, type RunHttpAdapterApplicationOptions } from '@fluojs/runtime/internal/http-adapter';
|
|
4
|
+
/** Listen target metadata reported by `Deno.serve(...)` callbacks. */
|
|
5
|
+
export interface DenoServeOnListenInfo {
|
|
6
|
+
hostname: string;
|
|
7
|
+
port: number;
|
|
8
|
+
}
|
|
9
|
+
/** Options forwarded to the Deno-native `serve(...)` implementation. */
|
|
10
|
+
export interface DenoServeOptions {
|
|
11
|
+
hostname?: string;
|
|
12
|
+
onListen?: (localAddr: DenoServeOnListenInfo) => void;
|
|
13
|
+
port?: number;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
/** Minimal controller contract returned by `Deno.serve(...)`. */
|
|
17
|
+
export interface DenoServeController {
|
|
18
|
+
finished: Promise<void>;
|
|
19
|
+
shutdown(): Promise<void> | void;
|
|
20
|
+
}
|
|
21
|
+
/** Deno shutdown signals supported by `runDenoApplication(...)`. */
|
|
22
|
+
export type DenoApplicationSignal = 'SIGINT' | 'SIGTERM';
|
|
23
|
+
/** Message payloads delivered through Deno server websocket bindings. */
|
|
24
|
+
export type DenoWebSocketMessage = Blob | string;
|
|
25
|
+
/** Server-side websocket shape used by the Deno platform binding seam. */
|
|
26
|
+
export interface DenoServerWebSocket extends Pick<WebSocket, 'addEventListener' | 'close' | 'removeEventListener' | 'send'> {
|
|
27
|
+
readonly readyState: number;
|
|
28
|
+
}
|
|
29
|
+
/** Result returned when the Deno runtime upgrades a request to websocket mode. */
|
|
30
|
+
export interface DenoWebSocketUpgradeResult<TSocket extends DenoServerWebSocket = DenoServerWebSocket> {
|
|
31
|
+
response: Response;
|
|
32
|
+
socket: TSocket;
|
|
33
|
+
}
|
|
34
|
+
/** Function signature for `Deno.upgradeWebSocket(...)` style adapters. */
|
|
35
|
+
export type DenoUpgradeWebSocketFunction<TSocket extends DenoServerWebSocket = DenoServerWebSocket> = (request: Request) => DenoWebSocketUpgradeResult<TSocket>;
|
|
36
|
+
/** Host wrapper that exposes websocket upgrade support to binding integrations. */
|
|
37
|
+
export interface DenoWebSocketUpgradeHost<TSocket extends DenoServerWebSocket = DenoServerWebSocket> {
|
|
38
|
+
upgrade(request: Request): DenoWebSocketUpgradeResult<TSocket>;
|
|
39
|
+
}
|
|
40
|
+
/** Official Deno websocket binding contract consumed by `@fluojs/websockets/deno`. */
|
|
41
|
+
export interface DenoWebSocketBinding<TSocket extends DenoServerWebSocket = DenoServerWebSocket> {
|
|
42
|
+
fetch(request: Request, host: DenoWebSocketUpgradeHost<TSocket>): Response | Promise<Response>;
|
|
43
|
+
}
|
|
44
|
+
/** Hook surface exposed by the Deno HTTP adapter for websocket bindings. */
|
|
45
|
+
export interface DenoWebSocketBindingHost<TSocket extends DenoServerWebSocket = DenoServerWebSocket> {
|
|
46
|
+
configureWebSocketBinding(binding: DenoWebSocketBinding<TSocket> | undefined): void;
|
|
47
|
+
}
|
|
48
|
+
/** Native request handler shape accepted by Deno's HTTP server runtime. */
|
|
49
|
+
export type DenoServeHandler = (request: Request) => Response | Promise<Response>;
|
|
50
|
+
/** Function signature for a pluggable Deno serve implementation. */
|
|
51
|
+
export type DenoServeFunction = (options: DenoServeOptions, handler: DenoServeHandler) => DenoServeController;
|
|
52
|
+
type DenoGlobalLike = {
|
|
53
|
+
addSignalListener?: (signal: DenoApplicationSignal, handler: () => void) => void;
|
|
54
|
+
removeSignalListener?: (signal: DenoApplicationSignal, handler: () => void) => void;
|
|
55
|
+
serve: DenoServeFunction;
|
|
56
|
+
upgradeWebSocket: DenoUpgradeWebSocketFunction;
|
|
57
|
+
};
|
|
58
|
+
/** Transport and parsing options for the Deno HTTP adapter factory. */
|
|
59
|
+
export interface DenoAdapterOptions {
|
|
60
|
+
hostname?: string;
|
|
61
|
+
maxBodySize?: number;
|
|
62
|
+
multipart?: MultipartOptions;
|
|
63
|
+
onListen?: (localAddr: DenoServeOnListenInfo) => void;
|
|
64
|
+
port?: number;
|
|
65
|
+
rawBody?: boolean;
|
|
66
|
+
serve?: DenoServeFunction;
|
|
67
|
+
upgradeWebSocket?: DenoUpgradeWebSocketFunction;
|
|
68
|
+
}
|
|
69
|
+
/** Bootstrap options for creating a Deno-backed app without auto-running it. */
|
|
70
|
+
export interface BootstrapDenoApplicationOptions extends BootstrapHttpAdapterApplicationOptions, DenoAdapterOptions {
|
|
71
|
+
}
|
|
72
|
+
/** Run-helper options for Deno apps, including optional signal wiring. */
|
|
73
|
+
export interface RunDenoApplicationOptions extends RunHttpAdapterApplicationOptions, DenoAdapterOptions {
|
|
74
|
+
shutdownSignals?: false | readonly DenoApplicationSignal[];
|
|
75
|
+
}
|
|
76
|
+
declare global {
|
|
77
|
+
interface GlobalThis {
|
|
78
|
+
Deno?: DenoGlobalLike;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Deno-backed HTTP adapter that preserves request draining and websocket binding seams.
|
|
83
|
+
*/
|
|
84
|
+
export declare class DenoHttpApplicationAdapter implements HttpApplicationAdapter {
|
|
85
|
+
private readonly options;
|
|
86
|
+
private abortController?;
|
|
87
|
+
private closeInFlight?;
|
|
88
|
+
private dispatcher?;
|
|
89
|
+
private inFlightDrain?;
|
|
90
|
+
private inFlightRequestCount;
|
|
91
|
+
private server?;
|
|
92
|
+
private websocketBinding?;
|
|
93
|
+
constructor(options: Required<Pick<DenoAdapterOptions, 'hostname' | 'port'>> & DenoAdapterOptions);
|
|
94
|
+
getServer(): DenoServeController | undefined;
|
|
95
|
+
getListenTarget(): HttpAdapterListenTarget;
|
|
96
|
+
getRealtimeCapability(): import("@fluojs/http").FetchStyleHttpAdapterRealtimeCapability;
|
|
97
|
+
configureWebSocketBinding<TSocket extends DenoServerWebSocket>(binding: DenoWebSocketBinding<TSocket> | undefined): void;
|
|
98
|
+
handle(request: Request): Promise<Response>;
|
|
99
|
+
listen(dispatcher: Dispatcher): Promise<void>;
|
|
100
|
+
close(): Promise<void>;
|
|
101
|
+
private trackInFlightRequest;
|
|
102
|
+
private waitForInFlightRequests;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Create the canonical Deno HTTP adapter instance.
|
|
106
|
+
*
|
|
107
|
+
* @param options Transport, parsing, and websocket-host configuration for the Deno runtime.
|
|
108
|
+
* @returns A Deno-backed `HttpApplicationAdapter`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function createDenoAdapter(options?: DenoAdapterOptions): DenoHttpApplicationAdapter;
|
|
111
|
+
/**
|
|
112
|
+
* Bootstrap a Deno-backed application shell without the quick-start run helper.
|
|
113
|
+
*
|
|
114
|
+
* @param rootModule Root module compiled by the Fluo runtime.
|
|
115
|
+
* @param options Bootstrap-time Deno adapter and runtime options.
|
|
116
|
+
* @returns An initialized application shell that can be listened to later.
|
|
117
|
+
*/
|
|
118
|
+
export declare function bootstrapDenoApplication(rootModule: ModuleType, options?: BootstrapDenoApplicationOptions): Promise<Application>;
|
|
119
|
+
/**
|
|
120
|
+
* Bootstrap and run a Deno-backed application with optional shutdown signal wiring.
|
|
121
|
+
*
|
|
122
|
+
* @param rootModule Root module compiled by the Fluo runtime.
|
|
123
|
+
* @param options Runtime, adapter, and signal-registration options for Deno.
|
|
124
|
+
* @returns A running application shell ready to receive requests.
|
|
125
|
+
*/
|
|
126
|
+
export declare function runDenoApplication(rootModule: ModuleType, options?: RunDenoApplicationOptions): Promise<Application>;
|
|
127
|
+
export {};
|
|
128
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { createFetchStyleHttpAdapterRealtimeCapability } from '@fluojs/http';
|
|
2
|
+
import { bootstrapHttpAdapterApplication, runHttpAdapterApplication } from '@fluojs/runtime/internal/http-adapter';
|
|
3
|
+
import { dispatchWebRequest } from '@fluojs/runtime/web';
|
|
4
|
+
|
|
5
|
+
/** Listen target metadata reported by `Deno.serve(...)` callbacks. */
|
|
6
|
+
|
|
7
|
+
/** Options forwarded to the Deno-native `serve(...)` implementation. */
|
|
8
|
+
|
|
9
|
+
/** Minimal controller contract returned by `Deno.serve(...)`. */
|
|
10
|
+
|
|
11
|
+
/** Deno shutdown signals supported by `runDenoApplication(...)`. */
|
|
12
|
+
|
|
13
|
+
/** Message payloads delivered through Deno server websocket bindings. */
|
|
14
|
+
|
|
15
|
+
/** Server-side websocket shape used by the Deno platform binding seam. */
|
|
16
|
+
|
|
17
|
+
/** Result returned when the Deno runtime upgrades a request to websocket mode. */
|
|
18
|
+
|
|
19
|
+
/** Function signature for `Deno.upgradeWebSocket(...)` style adapters. */
|
|
20
|
+
|
|
21
|
+
/** Host wrapper that exposes websocket upgrade support to binding integrations. */
|
|
22
|
+
|
|
23
|
+
/** Official Deno websocket binding contract consumed by `@fluojs/websockets/deno`. */
|
|
24
|
+
|
|
25
|
+
/** Hook surface exposed by the Deno HTTP adapter for websocket bindings. */
|
|
26
|
+
|
|
27
|
+
/** Native request handler shape accepted by Deno's HTTP server runtime. */
|
|
28
|
+
|
|
29
|
+
/** Function signature for a pluggable Deno serve implementation. */
|
|
30
|
+
|
|
31
|
+
/** Transport and parsing options for the Deno HTTP adapter factory. */
|
|
32
|
+
|
|
33
|
+
/** Bootstrap options for creating a Deno-backed app without auto-running it. */
|
|
34
|
+
|
|
35
|
+
/** Run-helper options for Deno apps, including optional signal wiring. */
|
|
36
|
+
|
|
37
|
+
const DEFAULT_HOSTNAME = '0.0.0.0';
|
|
38
|
+
const DEFAULT_PORT = 3000;
|
|
39
|
+
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
40
|
+
/**
|
|
41
|
+
* Deno-backed HTTP adapter that preserves request draining and websocket binding seams.
|
|
42
|
+
*/
|
|
43
|
+
export class DenoHttpApplicationAdapter {
|
|
44
|
+
abortController;
|
|
45
|
+
closeInFlight;
|
|
46
|
+
dispatcher;
|
|
47
|
+
inFlightDrain;
|
|
48
|
+
inFlightRequestCount = 0;
|
|
49
|
+
server;
|
|
50
|
+
websocketBinding;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.options = options;
|
|
53
|
+
}
|
|
54
|
+
getServer() {
|
|
55
|
+
return this.server;
|
|
56
|
+
}
|
|
57
|
+
getListenTarget() {
|
|
58
|
+
return createListenTarget(this.options.hostname, this.options.port);
|
|
59
|
+
}
|
|
60
|
+
getRealtimeCapability() {
|
|
61
|
+
return createFetchStyleHttpAdapterRealtimeCapability('Deno exposes Deno.upgradeWebSocket(request) request-upgrade hosting. Use @fluojs/websockets/deno for the official raw websocket binding.', {
|
|
62
|
+
support: 'supported'
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
configureWebSocketBinding(binding) {
|
|
66
|
+
if (this.server) {
|
|
67
|
+
throw new Error('Deno websocket binding must be configured before Deno adapter listen() starts the server.');
|
|
68
|
+
}
|
|
69
|
+
this.websocketBinding = binding;
|
|
70
|
+
}
|
|
71
|
+
async handle(request) {
|
|
72
|
+
if (this.closeInFlight) {
|
|
73
|
+
return createShutdownResponse();
|
|
74
|
+
}
|
|
75
|
+
const release = this.trackInFlightRequest();
|
|
76
|
+
try {
|
|
77
|
+
if (this.websocketBinding && isWebSocketUpgradeRequest(request)) {
|
|
78
|
+
const upgradeWebSocket = resolveUpgradeWebSocket(this.options.upgradeWebSocket);
|
|
79
|
+
return await this.websocketBinding.fetch(request, {
|
|
80
|
+
upgrade: upgradeRequest => upgradeWebSocket(upgradeRequest)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return await dispatchWebRequest({
|
|
84
|
+
dispatcher: this.dispatcher,
|
|
85
|
+
dispatcherNotReadyMessage: 'Deno adapter received a request before dispatcher binding completed.',
|
|
86
|
+
maxBodySize: this.options.maxBodySize,
|
|
87
|
+
multipart: this.options.multipart,
|
|
88
|
+
rawBody: this.options.rawBody,
|
|
89
|
+
request
|
|
90
|
+
});
|
|
91
|
+
} finally {
|
|
92
|
+
release();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async listen(dispatcher) {
|
|
96
|
+
this.dispatcher = dispatcher;
|
|
97
|
+
if (this.server) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const abortController = new AbortController();
|
|
101
|
+
const serve = resolveServe(this.options.serve);
|
|
102
|
+
this.abortController = abortController;
|
|
103
|
+
this.server = serve({
|
|
104
|
+
hostname: this.options.hostname,
|
|
105
|
+
onListen: this.options.onListen,
|
|
106
|
+
port: this.options.port,
|
|
107
|
+
signal: abortController.signal
|
|
108
|
+
}, async request => {
|
|
109
|
+
return await this.handle(request);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async close() {
|
|
113
|
+
if (this.closeInFlight) {
|
|
114
|
+
await waitForCloseWithTimeout(this.closeInFlight, DEFAULT_SHUTDOWN_TIMEOUT_MS);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const server = this.server;
|
|
118
|
+
const abortController = this.abortController;
|
|
119
|
+
if (!server) {
|
|
120
|
+
this.dispatcher = undefined;
|
|
121
|
+
this.abortController = undefined;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const closePromise = closeDenoServerWithDrain(server, abortController, () => this.waitForInFlightRequests());
|
|
125
|
+
const closeInFlight = closePromise.finally(() => {
|
|
126
|
+
if (this.server === server) {
|
|
127
|
+
this.server = undefined;
|
|
128
|
+
}
|
|
129
|
+
if (this.abortController === abortController) {
|
|
130
|
+
this.abortController = undefined;
|
|
131
|
+
}
|
|
132
|
+
this.closeInFlight = undefined;
|
|
133
|
+
this.dispatcher = undefined;
|
|
134
|
+
});
|
|
135
|
+
this.closeInFlight = closeInFlight;
|
|
136
|
+
void closeInFlight.catch(() => {});
|
|
137
|
+
await waitForCloseWithTimeout(closeInFlight, DEFAULT_SHUTDOWN_TIMEOUT_MS);
|
|
138
|
+
}
|
|
139
|
+
trackInFlightRequest() {
|
|
140
|
+
this.inFlightRequestCount += 1;
|
|
141
|
+
if (this.inFlightRequestCount === 1) {
|
|
142
|
+
this.inFlightDrain = createDeferred();
|
|
143
|
+
}
|
|
144
|
+
return () => {
|
|
145
|
+
if (this.inFlightRequestCount === 0) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
this.inFlightRequestCount -= 1;
|
|
149
|
+
if (this.inFlightRequestCount === 0) {
|
|
150
|
+
this.inFlightDrain?.resolve();
|
|
151
|
+
this.inFlightDrain = undefined;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async waitForInFlightRequests() {
|
|
156
|
+
if (this.inFlightRequestCount === 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
await this.inFlightDrain?.promise;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Create the canonical Deno HTTP adapter instance.
|
|
165
|
+
*
|
|
166
|
+
* @param options Transport, parsing, and websocket-host configuration for the Deno runtime.
|
|
167
|
+
* @returns A Deno-backed `HttpApplicationAdapter`.
|
|
168
|
+
*/
|
|
169
|
+
export function createDenoAdapter(options = {}) {
|
|
170
|
+
return new DenoHttpApplicationAdapter({
|
|
171
|
+
...options,
|
|
172
|
+
hostname: options.hostname ?? DEFAULT_HOSTNAME,
|
|
173
|
+
port: options.port ?? DEFAULT_PORT
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Bootstrap a Deno-backed application shell without the quick-start run helper.
|
|
179
|
+
*
|
|
180
|
+
* @param rootModule Root module compiled by the Fluo runtime.
|
|
181
|
+
* @param options Bootstrap-time Deno adapter and runtime options.
|
|
182
|
+
* @returns An initialized application shell that can be listened to later.
|
|
183
|
+
*/
|
|
184
|
+
export async function bootstrapDenoApplication(rootModule, options = {}) {
|
|
185
|
+
return await bootstrapHttpAdapterApplication(rootModule, options, createDenoAdapter(options));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Bootstrap and run a Deno-backed application with optional shutdown signal wiring.
|
|
190
|
+
*
|
|
191
|
+
* @param rootModule Root module compiled by the Fluo runtime.
|
|
192
|
+
* @param options Runtime, adapter, and signal-registration options for Deno.
|
|
193
|
+
* @returns A running application shell ready to receive requests.
|
|
194
|
+
*/
|
|
195
|
+
export async function runDenoApplication(rootModule, options = {}) {
|
|
196
|
+
const adapter = createDenoAdapter(options);
|
|
197
|
+
return await runHttpAdapterApplication(rootModule, {
|
|
198
|
+
...options,
|
|
199
|
+
shutdownRegistration: options.shutdownSignals === false ? undefined : createDenoShutdownSignalRegistration(options.shutdownSignals ?? defaultDenoShutdownSignals())
|
|
200
|
+
}, adapter);
|
|
201
|
+
}
|
|
202
|
+
function defaultDenoShutdownSignals() {
|
|
203
|
+
return ['SIGINT', 'SIGTERM'];
|
|
204
|
+
}
|
|
205
|
+
function createDenoShutdownSignalRegistration(signals) {
|
|
206
|
+
return (app, logger) => {
|
|
207
|
+
const denoGlobal = resolveDenoSignalGlobal();
|
|
208
|
+
if (!denoGlobal) {
|
|
209
|
+
return () => {};
|
|
210
|
+
}
|
|
211
|
+
const bindings = [];
|
|
212
|
+
const seen = new Set();
|
|
213
|
+
for (const signal of signals) {
|
|
214
|
+
if (seen.has(signal)) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
seen.add(signal);
|
|
218
|
+
const handler = () => {
|
|
219
|
+
void closeDenoApplicationFromSignal(app, logger, signal);
|
|
220
|
+
};
|
|
221
|
+
bindings.push({
|
|
222
|
+
handler,
|
|
223
|
+
signal
|
|
224
|
+
});
|
|
225
|
+
denoGlobal.addSignalListener(signal, handler);
|
|
226
|
+
}
|
|
227
|
+
return () => {
|
|
228
|
+
for (const binding of bindings) {
|
|
229
|
+
denoGlobal.removeSignalListener(binding.signal, binding.handler);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function createListenTarget(hostname, port) {
|
|
235
|
+
const isWildcard = hostname === '0.0.0.0' || hostname === '::';
|
|
236
|
+
const bindTarget = `${formatHostForAuthority(hostname)}:${String(port)}`;
|
|
237
|
+
const publicHostname = isWildcard ? 'localhost' : formatHostForAuthority(hostname);
|
|
238
|
+
return {
|
|
239
|
+
bindTarget,
|
|
240
|
+
url: `http://${publicHostname}:${String(port)}`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function formatHostForAuthority(hostname) {
|
|
244
|
+
return hostname.includes(':') && !hostname.startsWith('[') ? `[${hostname}]` : hostname;
|
|
245
|
+
}
|
|
246
|
+
function resolveServe(serve) {
|
|
247
|
+
if (serve) {
|
|
248
|
+
return serve;
|
|
249
|
+
}
|
|
250
|
+
const denoGlobal = globalThis.Deno;
|
|
251
|
+
if (denoGlobal?.serve) {
|
|
252
|
+
return denoGlobal.serve.bind(denoGlobal);
|
|
253
|
+
}
|
|
254
|
+
throw new Error('Deno.serve is not available. Pass options.serve when running outside Deno.');
|
|
255
|
+
}
|
|
256
|
+
function resolveUpgradeWebSocket(upgradeWebSocket) {
|
|
257
|
+
if (upgradeWebSocket) {
|
|
258
|
+
return upgradeWebSocket;
|
|
259
|
+
}
|
|
260
|
+
const denoGlobal = globalThis.Deno;
|
|
261
|
+
if (denoGlobal?.upgradeWebSocket) {
|
|
262
|
+
return denoGlobal.upgradeWebSocket.bind(denoGlobal);
|
|
263
|
+
}
|
|
264
|
+
throw new Error('Deno.upgradeWebSocket is not available. Pass options.upgradeWebSocket when running outside Deno.');
|
|
265
|
+
}
|
|
266
|
+
function isWebSocketUpgradeRequest(request) {
|
|
267
|
+
return request.headers.get('upgrade')?.toLowerCase() === 'websocket';
|
|
268
|
+
}
|
|
269
|
+
function closeDenoServerWithDrain(server, abortController, waitForDrain) {
|
|
270
|
+
return (async () => {
|
|
271
|
+
abortController?.abort();
|
|
272
|
+
await server.shutdown();
|
|
273
|
+
await waitForDrain();
|
|
274
|
+
await server.finished;
|
|
275
|
+
})();
|
|
276
|
+
}
|
|
277
|
+
function createDeferred() {
|
|
278
|
+
let resolve;
|
|
279
|
+
let reject;
|
|
280
|
+
const promise = new Promise((res, rej) => {
|
|
281
|
+
resolve = res;
|
|
282
|
+
reject = rej;
|
|
283
|
+
});
|
|
284
|
+
return {
|
|
285
|
+
promise,
|
|
286
|
+
reject,
|
|
287
|
+
resolve
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function createShutdownResponse() {
|
|
291
|
+
return new Response(JSON.stringify({
|
|
292
|
+
error: {
|
|
293
|
+
code: 'SERVICE_UNAVAILABLE',
|
|
294
|
+
message: 'Server is shutting down.',
|
|
295
|
+
status: 503
|
|
296
|
+
}
|
|
297
|
+
}), {
|
|
298
|
+
headers: {
|
|
299
|
+
'content-type': 'application/json'
|
|
300
|
+
},
|
|
301
|
+
status: 503
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function waitForCloseWithTimeout(closePromise, timeoutMs) {
|
|
305
|
+
return new Promise((resolve, reject) => {
|
|
306
|
+
const timeout = setTimeout(() => {
|
|
307
|
+
reject(new Error(`Deno adapter shutdown timeout exceeded ${String(timeoutMs)}ms.`));
|
|
308
|
+
}, timeoutMs);
|
|
309
|
+
void closePromise.then(() => {
|
|
310
|
+
clearTimeout(timeout);
|
|
311
|
+
resolve();
|
|
312
|
+
}, error => {
|
|
313
|
+
clearTimeout(timeout);
|
|
314
|
+
reject(error);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
function resolveDenoSignalGlobal() {
|
|
319
|
+
const denoGlobal = globalThis.Deno;
|
|
320
|
+
if (!denoGlobal?.addSignalListener || !denoGlobal.removeSignalListener) {
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
addSignalListener: denoGlobal.addSignalListener.bind(denoGlobal),
|
|
325
|
+
removeSignalListener: denoGlobal.removeSignalListener.bind(denoGlobal)
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
async function closeDenoApplicationFromSignal(app, logger, signal) {
|
|
329
|
+
if (app.state === 'closed') {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
await app.close(signal);
|
|
334
|
+
logger.log(`Application closed after receiving ${signal}.`, 'FluoFactory');
|
|
335
|
+
} catch (error) {
|
|
336
|
+
logger.error('Failed to shut down the application cleanly.', error, 'FluoFactory');
|
|
337
|
+
}
|
|
338
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './adapter.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluojs/platform-deno",
|
|
3
|
+
"description": "Deno-based HTTP adapter for the Fluo runtime.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"fluo",
|
|
6
|
+
"deno",
|
|
7
|
+
"http-adapter",
|
|
8
|
+
"platform",
|
|
9
|
+
"server"
|
|
10
|
+
],
|
|
11
|
+
"version": "1.0.0-beta.1",
|
|
12
|
+
"private": false,
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/fluojs/fluo.git",
|
|
17
|
+
"directory": "packages/platform-deno"
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@fluojs/http": "^1.0.0-beta.1",
|
|
36
|
+
"@fluojs/runtime": "^1.0.0-beta.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"vitest": "^3.2.4"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|
|
43
|
+
"build": "pnpm exec babel src --extensions .ts --ignore 'src/**/*.test.ts' --out-dir dist --config-file ../../tooling/babel/babel.config.cjs && pnpm exec tsc -p tsconfig.build.json",
|
|
44
|
+
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"test": "pnpm exec vitest run -c vitest.config.ts",
|
|
46
|
+
"test:watch": "pnpm exec vitest -c vitest.config.ts"
|
|
47
|
+
}
|
|
48
|
+
}
|