🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@fluojs/platform-cloudflare-workers

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fluojs/platform-cloudflare-workers - npm Package Compare versions

Comparing version
1.0.3
to
1.0.4
+8
-1
dist/adapter.d.ts

@@ -7,2 +7,3 @@ import { type Dispatcher, type HttpApplicationAdapter } from '@fluojs/http/internal';

interface FrameworkRequest {
cloudflare?: CloudflareWorkerRequestContext;
files?: UploadedFile[];

@@ -17,2 +18,7 @@ rawBody?: Uint8Array;

}
/** Worker-specific request context attached to fluo HTTP requests by the Cloudflare adapter. */
export interface CloudflareWorkerRequestContext<Env = unknown> {
readonly env: Env;
readonly executionContext?: CloudflareWorkerExecutionContext;
}
/** Message payloads accepted by Cloudflare Worker websockets. */

@@ -87,3 +93,3 @@ export type CloudflareWorkerWebSocketMessage = ArrayBuffer | ArrayBufferView | Blob | string;

configureWebSocketBinding(binding: CloudflareWorkerWebSocketBinding | undefined): void;
fetch<Env = unknown>(request: Request, _env?: Env, executionContext?: CloudflareWorkerExecutionContext): Promise<Response>;
fetch<Env = unknown>(request: Request, env?: Env, executionContext?: CloudflareWorkerExecutionContext): Promise<Response>;
listen(dispatcher: Dispatcher): Promise<void>;

@@ -93,2 +99,3 @@ private upgradeWebSocket;

private waitForInFlightRequests;
private createRequestResponseFactory;
}

@@ -95,0 +102,0 @@ /**

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}

@@ -9,2 +9,4 @@ import { createFetchStyleHttpAdapterRealtimeCapability } from '@fluojs/http/internal';

/** Worker-specific request context attached to fluo HTTP requests by the Cloudflare adapter. */
/** Message payloads accepted by Cloudflare Worker websockets. */

@@ -79,3 +81,3 @@

}
async fetch(request, _env, executionContext) {
async fetch(request, env, executionContext) {
if (this.closeInFlight || this.isClosed) {

@@ -85,22 +87,30 @@ return createShutdownResponse();

const release = this.trackInFlightRequest();
const responsePromise = (async () => {
const dispatcher = this.dispatcher;
if (dispatcher && this.websocketBinding && isWebSocketUpgradeRequest(request)) {
try {
const dispatcher = this.dispatcher;
if (dispatcher && this.websocketBinding && isWebSocketUpgradeRequest(request)) {
return await this.websocketBinding.fetch(request, {
upgrade: upgradeRequest => this.upgradeWebSocket(upgradeRequest)
});
}
return await dispatchWebRequest({
dispatcher,
dispatcherNotReadyMessage: WORKER_DISPATCHER_NOT_READY_MESSAGE,
factory: this.webRequestResponseFactory,
request
const response = await this.websocketBinding.fetch(request, {
upgrade: upgradeRequest => this.upgradeWebSocket(upgradeRequest)
});
executionContext?.waitUntil(Promise.resolve());
return response;
} finally {
release();
}
}
const responsePromise = (async () => {
return await dispatchWebRequest({
dispatcher,
dispatcherNotReadyMessage: WORKER_DISPATCHER_NOT_READY_MESSAGE,
factory: this.createRequestResponseFactory(env, executionContext),
request
});
})();
executionContext?.waitUntil(responsePromise.then(() => undefined, () => undefined));
return await responsePromise;
const trackedResponsePromise = responsePromise.then(response => createLifecycleTrackedResponse(response, release), error => {
release();
throw error;
});
executionContext?.waitUntil(trackedResponsePromise.then(({
lifecycle
}) => lifecycle).then(() => undefined, () => undefined));
return (await trackedResponsePromise).response;
}

@@ -145,2 +155,16 @@ async listen(dispatcher) {

}
createRequestResponseFactory(env, executionContext) {
const baseFactory = this.webRequestResponseFactory;
return {
...baseFactory,
async createRequest(request, signal) {
const frameworkRequest = await baseFactory.createRequest(request, signal);
frameworkRequest.cloudflare = {
env,
executionContext
};
return frameworkRequest;
}
};
}
}

@@ -324,2 +348,53 @@

}
function createLifecycleTrackedResponse(response, release) {
if (!isLifecycleTrackedStreamingResponse(response)) {
release();
return {
lifecycle: Promise.resolve(),
response
};
}
const lifecycle = createDeferred();
const responseBody = response.body;
if (!responseBody) {
release();
return {
lifecycle: Promise.resolve(),
response
};
}
const reader = responseBody.getReader();
const trackedBody = new ReadableStream({
async cancel(reason) {
try {
await reader.cancel(reason);
lifecycle.resolve();
} catch (error) {
lifecycle.reject(error);
throw error;
}
},
async pull(controller) {
try {
const result = await reader.read();
if (result.done) {
controller.close();
lifecycle.resolve();
return;
}
controller.enqueue(result.value);
} catch (error) {
controller.error(error);
lifecycle.reject(error);
}
}
});
return {
lifecycle: lifecycle.promise.finally(release),
response: new Response(trackedBody, response)
};
}
function isLifecycleTrackedStreamingResponse(response) {
return response.body !== null && response.headers.get('content-type')?.toLowerCase().includes('text/event-stream') === true;
}
function waitForCloseWithTimeout(closePromise, timeoutMs) {

@@ -326,0 +401,0 @@ return new Promise((resolve, reject) => {

@@ -12,3 +12,3 @@ {

],
"version": "1.0.3",
"version": "1.0.4",
"private": false,

@@ -37,4 +37,4 @@ "license": "MIT",

"dependencies": {
"@fluojs/http": "^1.1.0",
"@fluojs/runtime": "^1.1.2"
"@fluojs/http": "^1.1.2",
"@fluojs/runtime": "^1.1.8"
},

@@ -41,0 +41,0 @@ "devDependencies": {

@@ -30,3 +30,3 @@ # @fluojs/platform-cloudflare-workers

이 어댑터는 dispatcher가 binding된 뒤 각 요청 수명주기를 `executionContext.waitUntil(...)`에 연결하고, `close()` 중에도 진행 중인 디스패치를 유지하여 Worker 종료 도중 활성 작업이 중간에 잘리지 않도록 보장합니다.
이 어댑터는 dispatcher가 binding된 뒤 각 요청 수명주기를 `executionContext.waitUntil(...)`에 연결하고, `close()` 중에도 진행 중인 디스패치와 SSE(`text/event-stream`) response body를 유지하여 Worker 종료 도중 활성 작업이 중간에 잘리지 않도록 보장합니다.

@@ -91,3 +91,3 @@ 애플리케이션 종료 중에는 즉시 새 ingress 수락을 중단하고, 활성 HTTP 핸들러가 정리될 수 있도록 최대 10초의 bounded drain window를 제공합니다. 이 시간을 넘기면 `close()`는 무기한 대기하지 않고 timeout 오류로 종료됩니다. 해당 drain이 아직 진행 중일 때 동시에 `listen()`을 호출하면 Worker를 다시 열지 않고 `Cloudflare Workers adapter cannot listen while shutdown is still draining.` 오류로 reject됩니다. 닫힌 뒤에는 어댑터가 명시적으로 다시 `listen()`될 때까지 후속 HTTP 및 WebSocket upgrade request가 동일한 JSON `503` shutdown response를 받습니다.

- `fetch()`는 `listen()` 또는 lazy entrypoint가 dispatcher를 binding한 뒤 active work를 `executionContext.waitUntil(...)`에 등록합니다. 그 lifecycle boundary 전에는 upgrade request와 HTTP dispatch가 application handler에 도달하지 않습니다.
- `fetch()`는 `listen()` 또는 lazy entrypoint가 dispatcher를 binding한 뒤 active work를 `executionContext.waitUntil(...)`에 등록합니다. SSE(`text/event-stream`) response는 body가 끝나거나 cancel될 때까지 해당 lifecycle과 close drain을 유지합니다. 그 lifecycle boundary 전에는 upgrade request와 HTTP dispatch가 application handler에 도달하지 않습니다.
- `maxBodySize` 같은 adapter option은 Worker adapter 생성 시 검증됩니다. `globalPrefix`, `cors`, `middleware`, `securityHeaders` 같은 bootstrap 전용 옵션은 `createCloudflareWorkerAdapter(...)`가 아니라 Worker bootstrap helper에 전달해야 합니다.

@@ -97,7 +97,7 @@ - WebSocket upgrade는 HTTP dispatch와 같은 listen boundary가 소유합니다. `listen()` 전의 upgrade request는 설정된 binding에 도달하지 않습니다.

- Multipart request는 `rawBody`를 보존하지 않습니다.
- Worker `env` 객체는 fetch entrypoint boundary를 통과하며, package-level config resolution은 application이 소유합니다.
- Worker `env` 객체는 각 `FrameworkRequest`에 `request.cloudflare.env`로 연결되고 Worker execution context는 `request.cloudflare.executionContext`로 제공됩니다. Package-level config resolution은 application이 소유하므로, binding은 application boundary에서 명시적 provider 또는 `@fluojs/config`로 매핑하세요.
## Conformance 커버리지
`packages/platform-cloudflare-workers/src/adapter.test.ts`는 문서화된 Worker 계약을 검증하는 package-local regression 대상입니다. 이 파일은 shared Web dispatch delegation, `executionContext.waitUntil(...)` 등록, websocket upgrade binding, listen-bound upgrade ownership, lazy entrypoint 재사용, shutdown gating, drain 중 `listen()` rejection, close 중 및 close 이후 JSON `503` response, bounded 10초 close timeout을 검증합니다.
`packages/platform-cloudflare-workers/src/adapter.test.ts`는 문서화된 Worker 계약을 검증하는 package-local regression 대상입니다. 이 파일은 shared Web dispatch delegation, Worker `env` request attachment, `executionContext.waitUntil(...)` SSE(`text/event-stream`) body tracking, websocket upgrade binding, listen-bound upgrade ownership, lazy entrypoint 재사용, shutdown gating, drain 중 `listen()` rejection, close 중 및 close 이후 JSON `503` response, bounded 10초 close timeout을 검증합니다.

@@ -115,3 +115,3 @@ 공유 edge portability suite인 `packages/testing/src/portability/web-runtime-adapter-portability.test.ts`는 Cloudflare Workers를 Bun 및 Deno와 함께 실행해 malformed cookie 보존, query decoding, JSON/text raw-body capture, multipart raw-body 제외, SSE framing을 검증합니다. 패키지 테스트의 README parity assertion은 이 edge-runtime 커버리지 문서가 한국어 mirror와 계속 동기화되도록 확인합니다.

- `CloudflareWorkerEntrypoint`: `fetch`, `ready()`, `close()` lifecycle method를 제공하는 lazy entrypoint입니다.
- Option 및 type: `CloudflareWorkerAdapterOptions`, `BootstrapCloudflareWorkerApplicationOptions`, `CloudflareWorkerExecutionContext`, `CloudflareWorkerWebSocketBinding`, Worker websocket pair/upgrade type.
- Option 및 type: `CloudflareWorkerAdapterOptions`, `BootstrapCloudflareWorkerApplicationOptions`, `CloudflareWorkerExecutionContext`, `CloudflareWorkerRequestContext`, `CloudflareWorkerWebSocketBinding`, Worker websocket pair/upgrade type.

@@ -118,0 +118,0 @@ ## 관련 패키지

@@ -30,3 +30,3 @@ # @fluojs/platform-cloudflare-workers

The adapter binds each request lifecycle to `executionContext.waitUntil(...)` after the dispatcher is bound and keeps in-flight dispatches alive during `close()` so Worker shutdown does not drop active work mid-request.
The adapter binds each request lifecycle to `executionContext.waitUntil(...)` after the dispatcher is bound and keeps in-flight dispatches and SSE (`text/event-stream`) response bodies alive during `close()` so Worker shutdown does not drop active work mid-request.

@@ -91,3 +91,3 @@ During application shutdown, the adapter stops accepting new ingress immediately and gives active HTTP handlers a bounded 10-second drain window before `close()` fails with a timeout instead of hanging indefinitely. While that drain is still in progress, a concurrent `listen()` call rejects with `Cloudflare Workers adapter cannot listen while shutdown is still draining.` instead of reopening the Worker. Once closed, follow-up HTTP and WebSocket upgrade requests receive the same JSON `503` shutdown response until the adapter is explicitly listened again.

- `fetch()` registers active work with `executionContext.waitUntil(...)` after `listen()` or the lazy entrypoint binds the dispatcher; before that lifecycle boundary, upgrade requests and HTTP dispatch do not reach application handlers.
- `fetch()` registers active work with `executionContext.waitUntil(...)` after `listen()` or the lazy entrypoint binds the dispatcher; SSE (`text/event-stream`) responses keep that lifecycle and the close drain open until the body finishes or is canceled. Before that lifecycle boundary, upgrade requests and HTTP dispatch do not reach application handlers.
- Adapter options such as `maxBodySize` are validated when the Worker adapter is created; bootstrap-only options such as `globalPrefix`, `cors`, `middleware`, and `securityHeaders` belong on Worker bootstrap helpers rather than `createCloudflareWorkerAdapter(...)`.

@@ -97,7 +97,7 @@ - WebSocket upgrades are owned by the same listen boundary as HTTP dispatch; upgrade requests before `listen()` do not reach the configured binding.

- Multipart requests do not preserve `rawBody`.
- The Worker `env` object is passed through the fetch entrypoint boundary; package-level config resolution remains application-owned.
- The Worker `env` object is attached to each `FrameworkRequest` as `request.cloudflare.env`, with the Worker execution context available as `request.cloudflare.executionContext`; package-level config resolution remains application-owned, so map bindings into explicit providers or `@fluojs/config` at the application boundary.
## Conformance Coverage
`packages/platform-cloudflare-workers/src/adapter.test.ts` is the package-local regression target for the documented Worker contract. It covers shared Web dispatch delegation, `executionContext.waitUntil(...)` registration, websocket upgrade binding, listen-bound upgrade ownership, lazy entrypoint reuse, shutdown gating, drain-time `listen()` rejection, JSON `503` responses while closing and after close, and the bounded 10-second close timeout.
`packages/platform-cloudflare-workers/src/adapter.test.ts` is the package-local regression target for the documented Worker contract. It covers shared Web dispatch delegation, Worker `env` request attachment, `executionContext.waitUntil(...)` SSE (`text/event-stream`) body tracking, websocket upgrade binding, listen-bound upgrade ownership, lazy entrypoint reuse, shutdown gating, drain-time `listen()` rejection, JSON `503` responses while closing and after close, and the bounded 10-second close timeout.

@@ -115,3 +115,3 @@ The shared edge portability suite in `packages/testing/src/portability/web-runtime-adapter-portability.test.ts` exercises Cloudflare Workers beside Bun and Deno for malformed cookie preservation, query decoding, JSON/text raw-body capture, multipart raw-body exclusion, and SSE framing. The README parity assertion in the package test keeps these documented edge-runtime coverage claims synchronized with the Korean mirror.

- `CloudflareWorkerEntrypoint`: Lazy entrypoint with `fetch`, `ready()`, and `close()` lifecycle methods.
- Options and types: `CloudflareWorkerAdapterOptions`, `BootstrapCloudflareWorkerApplicationOptions`, `CloudflareWorkerExecutionContext`, `CloudflareWorkerWebSocketBinding`, and Worker websocket pair/upgrade types.
- Options and types: `CloudflareWorkerAdapterOptions`, `BootstrapCloudflareWorkerApplicationOptions`, `CloudflareWorkerExecutionContext`, `CloudflareWorkerRequestContext`, `CloudflareWorkerWebSocketBinding`, and Worker websocket pair/upgrade types.

@@ -118,0 +118,0 @@ ## Related Packages