@loutrejs/loutre 0.4.1 → 0.6.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 +63 -32
- package/dist/adapters/aws-lambda.d.ts +5 -3
- package/dist/adapters/aws-lambda.js +53 -23
- package/dist/adapters/bun.d.ts +7 -4
- package/dist/adapters/bun.js +52 -42
- package/dist/adapters/cloudflare-workers.d.ts +5 -3
- package/dist/adapters/cloudflare-workers.js +23 -28
- package/dist/adapters/deno.d.ts +7 -4
- package/dist/adapters/deno.js +94 -57
- package/dist/adapters/electron.d.ts +13 -5
- package/dist/adapters/electron.js +76 -28
- package/dist/application/definition.d.ts +31 -0
- package/dist/application/definition.js +16 -0
- package/dist/application/index.d.ts +4 -63
- package/dist/application/index.js +2 -11
- package/dist/application/kernel-internal.d.ts +2 -0
- package/dist/application/kernel-internal.js +10 -0
- package/dist/application/kernel.d.ts +21 -0
- package/dist/application/kernel.js +65 -0
- package/dist/core/diagnostic.d.ts +9 -0
- package/dist/core/diagnostic.js +9 -0
- package/dist/core/extension.d.ts +107 -0
- package/dist/core/extension.js +73 -0
- package/dist/core/generic-layer.d.ts +26 -0
- package/dist/core/generic-layer.js +116 -0
- package/dist/core/index.d.ts +31 -15
- package/dist/core/index.js +15 -15
- package/dist/core/injection.d.ts +4 -13
- package/dist/core/injection.js +63 -0
- package/dist/core/model/context.d.ts +18 -0
- package/dist/core/model/context.js +34 -0
- package/dist/core/model/lifecycle.d.ts +5 -0
- package/dist/core/model/lifecycle.js +44 -0
- package/dist/core/model/modules.d.ts +2 -0
- package/dist/core/model/modules.js +101 -0
- package/dist/core/model/providers.d.ts +4 -0
- package/dist/core/model/providers.js +74 -0
- package/dist/core/model/snapshot.d.ts +6 -0
- package/dist/core/model/snapshot.js +31 -0
- package/dist/core/model/types.d.ts +78 -0
- package/dist/core/model/validation.d.ts +4 -0
- package/dist/core/model/validation.js +40 -0
- package/dist/core/model/visibility.d.ts +4 -0
- package/dist/core/model/visibility.js +20 -0
- package/dist/core/model.d.ts +10 -0
- package/dist/core/model.js +346 -0
- package/dist/core/module.d.ts +8 -13
- package/dist/core/source-location.d.ts +8 -0
- package/dist/core/source-location.js +31 -0
- package/dist/core/token-internal.d.ts +3 -0
- package/dist/core/token-internal.js +4 -0
- package/dist/core/type.d.ts +7 -0
- package/dist/core/type.js +4 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/graph/index.d.ts +2 -3
- package/dist/graph/index.js +1 -3
- package/dist/graph/model.d.ts +34 -0
- package/dist/graph/model.js +127 -0
- package/dist/http/auth.d.ts +46 -0
- package/dist/http/auth.js +96 -0
- package/dist/http/client.d.ts +28 -31
- package/dist/http/client.js +60 -41
- package/dist/http/cors-internal.d.ts +29 -0
- package/dist/http/cors-internal.js +160 -0
- package/dist/http/cors.d.ts +5 -8
- package/dist/http/cors.js +7 -165
- package/dist/http/extension.d.ts +348 -0
- package/dist/http/extension.js +947 -0
- package/dist/http/index.d.ts +9 -7
- package/dist/http/index.js +5 -7
- package/dist/{application → http}/openapi.d.ts +12 -3
- package/dist/{application → http}/openapi.js +164 -101
- package/dist/http/path.d.ts +2 -39
- package/dist/http/path.js +7 -2
- package/dist/http/runtime/request.d.ts +17 -0
- package/dist/http/runtime/request.js +109 -0
- package/dist/http/runtime/response.d.ts +18 -0
- package/dist/http/runtime/response.js +108 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/message-port/extension.d.ts +66 -0
- package/dist/message-port/extension.js +395 -0
- package/dist/message-port/index.d.ts +4 -73
- package/dist/message-port/index.js +2 -189
- package/dist/message-port/transport.d.ts +11 -0
- package/dist/message-port/transport.js +45 -0
- package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
- package/dist/runtime/async-iterator-lifecycle.js +95 -0
- package/dist/runtime/capability.d.ts +11 -11
- package/dist/runtime/capability.js +3 -3
- package/dist/runtime/di.d.ts +2 -22
- package/dist/runtime/di.js +8 -285
- package/dist/runtime/execution-tracker.d.ts +8 -0
- package/dist/runtime/execution-tracker.js +54 -0
- package/dist/runtime/index.d.ts +15 -9
- package/dist/runtime/index.js +9 -9
- package/dist/runtime/ingress-gate.d.ts +7 -0
- package/dist/runtime/ingress-gate.js +33 -0
- package/dist/runtime/kernel.d.ts +23 -0
- package/dist/runtime/kernel.js +354 -0
- package/dist/runtime/logger.d.ts +2 -0
- package/dist/runtime/logger.js +2 -0
- package/dist/runtime/node-capabilities.d.ts +1 -1
- package/dist/runtime/node-capabilities.js +1 -1
- package/dist/runtime/server-port.d.ts +2 -0
- package/dist/runtime/server-port.js +11 -0
- package/dist/tasks/extension.d.ts +144 -0
- package/dist/tasks/extension.js +499 -0
- package/dist/tasks/index.d.ts +2 -0
- package/dist/tasks/index.js +1 -0
- package/dist/tasks/runtime/cron.d.ts +6 -0
- package/dist/tasks/runtime/cron.js +89 -0
- package/dist/websocket/errors.d.ts +9 -0
- package/dist/websocket/errors.js +18 -0
- package/dist/websocket/extension.d.ts +154 -0
- package/dist/websocket/extension.js +524 -0
- package/dist/websocket/index.d.ts +3 -0
- package/dist/websocket/index.js +2 -0
- package/package.json +12 -16
- package/dist/application/binding.d.ts +0 -33
- package/dist/application/binding.js +0 -295
- package/dist/application/host.d.ts +0 -8
- package/dist/application/host.js +0 -14
- package/dist/application/queue.d.ts +0 -3
- package/dist/application/queue.js +0 -4
- package/dist/application/scheduler.d.ts +0 -2
- package/dist/application/scheduler.js +0 -45
- package/dist/core/context-key.d.ts +0 -14
- package/dist/core/context-key.js +0 -14
- package/dist/core/contract.d.ts +0 -94
- package/dist/core/contract.js +0 -79
- package/dist/core/execution.d.ts +0 -78
- package/dist/core/execution.js +0 -61
- package/dist/core/implementation.d.ts +0 -34
- package/dist/core/implementation.js +0 -30
- package/dist/core/layer.d.ts +0 -109
- package/dist/core/layer.js +0 -52
- package/dist/graph/compiler.d.ts +0 -4
- package/dist/graph/compiler.js +0 -228
- package/dist/graph/graph.d.ts +0 -17
- package/dist/graph/graph.js +0 -1103
- package/dist/graph/ir.d.ts +0 -175
- package/dist/http/application.d.ts +0 -18
- package/dist/http/application.js +0 -506
- package/dist/http/basic-auth.d.ts +0 -37
- package/dist/http/basic-auth.js +0 -67
- package/dist/http/definitions.d.ts +0 -225
- package/dist/http/definitions.js +0 -69
- package/dist/http/hosted-protocol.d.ts +0 -4
- package/dist/http/hosted-protocol.js +0 -4
- package/dist/http/params.d.ts +0 -2
- package/dist/http/params.js +0 -19
- package/dist/http/request-body.d.ts +0 -4
- package/dist/http/request-body.js +0 -6
- package/dist/http/validate.d.ts +0 -20
- package/dist/http/validate.js +0 -6
- package/dist/message-port/environment.d.ts +0 -2
- package/dist/message-port/environment.js +0 -4
- package/dist/runtime/application.d.ts +0 -38
- package/dist/runtime/application.js +0 -339
- package/dist/runtime/pipeline.d.ts +0 -11
- package/dist/runtime/pipeline.js +0 -161
- /package/dist/{graph/ir.js → core/model/types.js} +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @loutrejs/loutre
|
|
2
2
|
|
|
3
|
-
Loutreの
|
|
3
|
+
LoutreのApplication Graph Kernelです。Application Definition / Model、Module、DI、Environment、Arguments、Lifecycle、Runtime Capability、generic Layer、Kernel bootstrapを提供します。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
HTTP、Task、MessagePort、WebSocketは同じpackageのsubpathからExecution Extensionとして提供します。
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -10,53 +10,84 @@ LoutreのCore packageです。Application Definition、Contract、DI、Pipeline
|
|
|
10
10
|
npm install @loutrejs/loutre
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
新しいApplication
|
|
13
|
+
新しいApplicationはinitializerから作成できます。
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
16
|
npm create loutre@latest my-app
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
## Application
|
|
19
|
+
## Application Model
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Applicationの構成は`defineApplication()`でcanonical `Application Model`へcompileされます。
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
```ts
|
|
24
|
+
import { defineApplication, defineModule } from '@loutrejs/loutre'
|
|
25
|
+
import { http } from '@loutrejs/loutre/http'
|
|
26
|
+
import { z } from 'zod'
|
|
27
|
+
|
|
28
|
+
const HealthContract = http.contract({
|
|
29
|
+
health: {
|
|
30
|
+
method: 'GET',
|
|
31
|
+
path: '/health',
|
|
32
|
+
responses: {
|
|
33
|
+
ok: { status: 200, body: z.string() },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const HealthHttp = http.implementation({
|
|
39
|
+
name: 'HealthHttp',
|
|
40
|
+
contract: HealthContract,
|
|
41
|
+
factory: () => ({
|
|
42
|
+
health: (ctx) => ctx.response.ok({ body: 'ok' }),
|
|
43
|
+
}),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const AppModule = defineModule(() => ({
|
|
47
|
+
executions: [HealthHttp],
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
export default defineApplication({ modules: [AppModule()] })
|
|
51
|
+
```
|
|
29
52
|
|
|
30
|
-
##
|
|
53
|
+
## Kernel bootstrap
|
|
54
|
+
|
|
55
|
+
portableなApplicationはroot packageから起動できます。
|
|
31
56
|
|
|
32
57
|
```ts
|
|
33
|
-
import {
|
|
58
|
+
import { bootstrapApplication } from '@loutrejs/loutre'
|
|
59
|
+
import { bindHttpServer } from '@loutrejs/loutre/http'
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
61
|
+
const app = await bootstrapApplication({
|
|
62
|
+
application,
|
|
63
|
+
capabilities: [bindHttpServer({ runtime: 'test' })],
|
|
38
64
|
})
|
|
39
65
|
|
|
40
|
-
|
|
41
|
-
modules: [],
|
|
42
|
-
tasks: [hello],
|
|
43
|
-
})
|
|
66
|
+
const response = await app.http.fetch(new Request('http://localhost/health'))
|
|
44
67
|
```
|
|
45
68
|
|
|
69
|
+
ExtensionがApplication Modelに存在するときだけ、そのExtensionのHost APIがApplicationへ合成されます。
|
|
70
|
+
|
|
46
71
|
## Entry points
|
|
47
72
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
| `@loutrejs/loutre/
|
|
53
|
-
| `@loutrejs/loutre/
|
|
54
|
-
| `@loutrejs/loutre/
|
|
55
|
-
| `@loutrejs/loutre/
|
|
56
|
-
| `@loutrejs/loutre/
|
|
57
|
-
| `@loutrejs/loutre/openapi`
|
|
58
|
-
| `@loutrejs/loutre/presentation` | startup presentation
|
|
59
|
-
| `@loutrejs/loutre/
|
|
73
|
+
| Entry point | Role |
|
|
74
|
+
| ------------------------------- | --------------------------------------------- |
|
|
75
|
+
| `@loutrejs/loutre` | Application Graph Kernel / Kernel bootstrap |
|
|
76
|
+
| `@loutrejs/loutre/http` | HTTP Execution Extension |
|
|
77
|
+
| `@loutrejs/loutre/tasks` | Task / Trigger / Queue Execution Extension |
|
|
78
|
+
| `@loutrejs/loutre/message-port` | MessagePort Execution Extension |
|
|
79
|
+
| `@loutrejs/loutre/websocket` | WebSocket Execution Extension |
|
|
80
|
+
| `@loutrejs/loutre/graph` | Application Model graph projection |
|
|
81
|
+
| `@loutrejs/loutre/runtime` | Runtime capability / Kernel runtime primitive |
|
|
82
|
+
| `@loutrejs/loutre/http/openapi` | OpenAPI projection |
|
|
83
|
+
| `@loutrejs/loutre/presentation` | startup presentation |
|
|
84
|
+
| `@loutrejs/loutre/runtime/*` | portable Runtime adapter |
|
|
85
|
+
|
|
86
|
+
Node.js listener ownership is provided by `@loutrejs/node`.
|
|
87
|
+
|
|
88
|
+
## Architecture invariant
|
|
89
|
+
|
|
90
|
+
Core never interprets HTTP, Task, MessagePort, or WebSocket identity. Execution Extensions compile their definitions into the single Application Model and own their runtime semantics, Host API, and Graph projection.
|
|
60
91
|
|
|
61
92
|
## Documentation
|
|
62
93
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type ApplicationDefinition, type BootstrapArguments, type
|
|
2
|
-
type
|
|
3
|
-
|
|
1
|
+
import { type ApplicationDefinition, type BootstrapArguments, type RequireApplicationExtension } from '../application/index.js';
|
|
2
|
+
import type { RuntimeCapabilityBinding } from '../core/index.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
4
|
+
type HttpApplication<TDefinition extends ApplicationDefinition> = RequireApplicationExtension<TDefinition, typeof httpExecutionExtension>;
|
|
4
5
|
export type AwsLambdaBindBaseOptions<TDefinition extends ApplicationDefinition> = {
|
|
5
6
|
readonly application: HttpApplication<TDefinition>;
|
|
6
7
|
readonly environment?: unknown;
|
|
8
|
+
readonly capabilities?: readonly RuntimeCapabilityBinding[];
|
|
7
9
|
} & BootstrapArguments<TDefinition>;
|
|
8
10
|
export type AwsLambdaBindOptions<TDefinition extends ApplicationDefinition> = AwsLambdaBindBaseOptions<TDefinition> & {
|
|
9
11
|
readonly response?: 'buffered';
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createKernelApplication, } from '../application/index.js';
|
|
2
|
+
import { bindApplicationCapability } from '../application/kernel-internal.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
2
4
|
import { assertRuntimeEngine } from '../runtime/engine.js';
|
|
3
5
|
export const awsLambdaRuntime = {
|
|
4
6
|
runtime: 'aws-lambda',
|
|
@@ -14,18 +16,27 @@ export const awsLambdaRuntime = {
|
|
|
14
16
|
};
|
|
15
17
|
function bind(options) {
|
|
16
18
|
assertRuntimeEngine('aws-lambda');
|
|
17
|
-
|
|
19
|
+
if (options.application.model.extensions.get(httpExecutionExtension) ===
|
|
20
|
+
undefined) {
|
|
21
|
+
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: awsLambdaRuntime.bind() requires the HTTP Execution Extension.');
|
|
22
|
+
}
|
|
23
|
+
const application = createKernelApplication({
|
|
24
|
+
...options,
|
|
18
25
|
application: options.application,
|
|
26
|
+
capabilities: [
|
|
27
|
+
bindApplicationCapability(options.application.model, 'http.server', {
|
|
28
|
+
runtime: 'aws-lambda',
|
|
29
|
+
}),
|
|
30
|
+
...(options.capabilities ?? []),
|
|
31
|
+
],
|
|
19
32
|
environment: 'environment' in options ? options.environment : process.env,
|
|
20
|
-
...('arguments' in options ? { arguments: options.arguments } : {}),
|
|
21
33
|
});
|
|
22
|
-
const http =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
34
|
+
const http = {
|
|
35
|
+
initialize: async () => {
|
|
36
|
+
await application.init();
|
|
37
|
+
},
|
|
38
|
+
fetch: (request) => application.http.fetch(request),
|
|
39
|
+
};
|
|
29
40
|
if (options.response === 'streaming') {
|
|
30
41
|
const handler = createAwsLambdaStreamingHttpDriver(http);
|
|
31
42
|
const aws = awsLambdaGlobal();
|
|
@@ -36,9 +47,9 @@ function bind(options) {
|
|
|
36
47
|
function createAwsLambdaHttpDriver(application) {
|
|
37
48
|
let initialization;
|
|
38
49
|
return async (event) => {
|
|
39
|
-
initialization ??= application.initialize();
|
|
50
|
+
initialization ??= application.initialize?.() ?? Promise.resolve();
|
|
40
51
|
await initialization;
|
|
41
|
-
const response = await application.
|
|
52
|
+
const response = await application.fetch(toRequest(event));
|
|
42
53
|
const metadata = responseMetadata(response);
|
|
43
54
|
return {
|
|
44
55
|
statusCode: response.status,
|
|
@@ -51,9 +62,9 @@ function createAwsLambdaHttpDriver(application) {
|
|
|
51
62
|
function createAwsLambdaStreamingHttpDriver(application) {
|
|
52
63
|
let initialization;
|
|
53
64
|
return async (event, output) => {
|
|
54
|
-
initialization ??= application.initialize();
|
|
65
|
+
initialization ??= application.initialize?.() ?? Promise.resolve();
|
|
55
66
|
await initialization;
|
|
56
|
-
const response = await application.
|
|
67
|
+
const response = await application.fetch(toRequest(event));
|
|
57
68
|
const metadata = responseMetadata(response);
|
|
58
69
|
const aws = awsLambdaGlobal();
|
|
59
70
|
const outputMetadata = {
|
|
@@ -73,15 +84,34 @@ function createAwsLambdaStreamingHttpDriver(application) {
|
|
|
73
84
|
});
|
|
74
85
|
}
|
|
75
86
|
const reader = response.body?.getReader();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
let completed = false;
|
|
88
|
+
let failure;
|
|
89
|
+
try {
|
|
90
|
+
if (reader) {
|
|
91
|
+
while (true) {
|
|
92
|
+
const chunk = await reader.read();
|
|
93
|
+
if (chunk.done)
|
|
94
|
+
break;
|
|
95
|
+
if (!stream.write(chunk.value) && stream.once) {
|
|
96
|
+
await new Promise((resolve) => {
|
|
97
|
+
stream.once?.('drain', resolve);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
completed = true;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
failure = error;
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
if (reader && !completed) {
|
|
110
|
+
try {
|
|
111
|
+
await reader.cancel(failure);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// cancel失敗でresponse pumpの元errorを上書きしない。
|
|
85
115
|
}
|
|
86
116
|
}
|
|
87
117
|
}
|
package/dist/adapters/bun.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { type ApplicationDefinition, type BootstrapArguments, type
|
|
2
|
-
type
|
|
3
|
-
|
|
1
|
+
import { type ApplicationDefinition, type BootstrapArguments, type KernelHostedApplication, type RequireApplicationExtension } from '../application/index.js';
|
|
2
|
+
import type { RuntimeCapabilityBinding } from '../core/index.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
4
|
+
type HttpApplication<TDefinition extends ApplicationDefinition> = RequireApplicationExtension<TDefinition, typeof httpExecutionExtension>;
|
|
4
5
|
export type BunCreateOptions<TDefinition extends ApplicationDefinition> = {
|
|
5
6
|
readonly application: HttpApplication<TDefinition>;
|
|
6
7
|
readonly environment?: unknown;
|
|
8
|
+
readonly capabilities?: readonly RuntimeCapabilityBinding[];
|
|
9
|
+
readonly forceShutdownTimeoutMs?: number;
|
|
7
10
|
} & BootstrapArguments<TDefinition>;
|
|
8
11
|
export interface BunServeOptions {
|
|
9
12
|
readonly port?: number;
|
|
@@ -13,7 +16,7 @@ export interface BunServeOptions {
|
|
|
13
16
|
export interface BunListenerHandle {
|
|
14
17
|
readonly port: number;
|
|
15
18
|
}
|
|
16
|
-
export type BunRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> =
|
|
19
|
+
export type BunRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> = KernelHostedApplication<TDefinition> & {
|
|
17
20
|
serve(options?: BunServeOptions): Promise<BunListenerHandle>;
|
|
18
21
|
};
|
|
19
22
|
export declare const bunRuntime: {
|
package/dist/adapters/bun.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createKernelApplication, } from '../application/index.js';
|
|
2
|
+
import { bindApplicationCapability } from '../application/kernel-internal.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
2
4
|
import { LOUTRE_VERSION, detectPresentationTerminal, startStartupPresentation, } from '../presentation.js';
|
|
3
5
|
import { assertRuntimeEngine } from '../runtime/engine.js';
|
|
4
6
|
import { serverUrl } from '../runtime/server-url.js';
|
|
7
|
+
import { canRetryOnNextPort, initialServerPort, } from '../runtime/server-port.js';
|
|
5
8
|
export const bunRuntime = {
|
|
6
9
|
runtime: 'bun',
|
|
7
10
|
capabilities: new Set([
|
|
@@ -26,46 +29,64 @@ async function create(options) {
|
|
|
26
29
|
terminal: detectPresentationTerminal(process.stdout, environment),
|
|
27
30
|
write: (value) => console.log(value),
|
|
28
31
|
});
|
|
29
|
-
|
|
32
|
+
if (options.application.model.extensions.get(httpExecutionExtension) ===
|
|
33
|
+
undefined) {
|
|
34
|
+
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: bunRuntime.create() requires the HTTP Execution Extension.');
|
|
35
|
+
}
|
|
36
|
+
const hosted = createKernelApplication({
|
|
37
|
+
...options,
|
|
30
38
|
application: options.application,
|
|
39
|
+
capabilities: [
|
|
40
|
+
bindApplicationCapability(options.application.model, 'http.server', {
|
|
41
|
+
runtime: 'bun',
|
|
42
|
+
}),
|
|
43
|
+
...(options.capabilities ?? []),
|
|
44
|
+
],
|
|
31
45
|
environment: 'environment' in options ? options.environment : environment,
|
|
32
|
-
...('arguments' in options ? { arguments: options.arguments } : {}),
|
|
33
46
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
await host.application.init();
|
|
40
|
-
const application = host.application;
|
|
41
|
-
const closeApplication = host.application.close.bind(host.application);
|
|
47
|
+
await hosted.init();
|
|
48
|
+
const application = hosted;
|
|
49
|
+
const http = hosted
|
|
50
|
+
.http;
|
|
51
|
+
const closeApplication = application.close.bind(application);
|
|
42
52
|
let server;
|
|
43
53
|
let removeShutdownHooks;
|
|
44
54
|
let serving = false;
|
|
45
55
|
let closed = false;
|
|
46
|
-
|
|
56
|
+
let closingPromise;
|
|
57
|
+
const close = (signal) => {
|
|
47
58
|
if (closed)
|
|
48
|
-
return;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
return Promise.resolve();
|
|
60
|
+
if (closingPromise)
|
|
61
|
+
return closingPromise;
|
|
62
|
+
closingPromise = (async () => {
|
|
63
|
+
removeShutdownHooks?.();
|
|
64
|
+
removeShutdownHooks = undefined;
|
|
65
|
+
const errors = [];
|
|
66
|
+
if (server) {
|
|
67
|
+
try {
|
|
68
|
+
await server.stop(true);
|
|
69
|
+
server = undefined;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
errors.push(error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
54
75
|
try {
|
|
55
|
-
await
|
|
76
|
+
await closeApplication(signal);
|
|
56
77
|
}
|
|
57
78
|
catch (error) {
|
|
58
79
|
errors.push(error);
|
|
59
80
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
catch
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
if (errors.length > 0) {
|
|
82
|
+
throw new AggregateError(errors, 'Bun runtime shutdown failed');
|
|
83
|
+
}
|
|
84
|
+
closed = true;
|
|
85
|
+
})().catch((error) => {
|
|
86
|
+
closingPromise = undefined;
|
|
87
|
+
throw error;
|
|
88
|
+
});
|
|
89
|
+
return closingPromise;
|
|
69
90
|
};
|
|
70
91
|
const serve = async (serveOptions = {}) => {
|
|
71
92
|
if (closed) {
|
|
@@ -80,10 +101,8 @@ async function create(options) {
|
|
|
80
101
|
}
|
|
81
102
|
serving = true;
|
|
82
103
|
try {
|
|
83
|
-
if ('triggers' in application)
|
|
84
|
-
await application.triggers.start();
|
|
85
104
|
const requestedPort = serveOptions.port;
|
|
86
|
-
let port = requestedPort
|
|
105
|
+
let port = initialServerPort(requestedPort);
|
|
87
106
|
while (true) {
|
|
88
107
|
try {
|
|
89
108
|
server = bun.serve({
|
|
@@ -139,21 +158,12 @@ function registerBunShutdownHooks(close) {
|
|
|
139
158
|
}
|
|
140
159
|
return remove;
|
|
141
160
|
}
|
|
142
|
-
function canRetryOnNextPort(error, port) {
|
|
143
|
-
return port < 65_535 && isAddressInUseError(error);
|
|
144
|
-
}
|
|
145
|
-
function isAddressInUseError(error) {
|
|
146
|
-
return (typeof error === 'object' &&
|
|
147
|
-
error !== null &&
|
|
148
|
-
'code' in error &&
|
|
149
|
-
error.code === 'EADDRINUSE');
|
|
150
|
-
}
|
|
151
161
|
function createBunFetchDriver(application) {
|
|
152
162
|
let initialization;
|
|
153
163
|
return async (request) => {
|
|
154
|
-
initialization ??= application.initialize();
|
|
164
|
+
initialization ??= application.initialize?.() ?? Promise.resolve();
|
|
155
165
|
await initialization;
|
|
156
|
-
return application.
|
|
166
|
+
return application.fetch(request);
|
|
157
167
|
};
|
|
158
168
|
}
|
|
159
169
|
function bunGlobal() {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { type ApplicationDefinition, type BootstrapArguments, type
|
|
2
|
-
type
|
|
3
|
-
|
|
1
|
+
import { type ApplicationDefinition, type BootstrapArguments, type RequireApplicationExtension } from '../application/index.js';
|
|
2
|
+
import type { RuntimeCapabilityBinding } from '../core/index.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
4
|
+
type HttpApplication<TDefinition extends ApplicationDefinition> = RequireApplicationExtension<TDefinition, typeof httpExecutionExtension>;
|
|
4
5
|
export type CloudflareWorkersBindOptions<TDefinition extends ApplicationDefinition> = {
|
|
5
6
|
readonly application: HttpApplication<TDefinition>;
|
|
7
|
+
readonly capabilities?: readonly RuntimeCapabilityBinding[];
|
|
6
8
|
} & BootstrapArguments<TDefinition>;
|
|
7
9
|
export interface CloudflareWorkersBinding {
|
|
8
10
|
fetch(request: Request, environment?: unknown, executionContext?: unknown): Promise<Response>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createKernelApplication, } from '../application/index.js';
|
|
2
|
+
import { bindApplicationCapability } from '../application/kernel-internal.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
2
4
|
import { assertRuntimeEngine } from '../runtime/engine.js';
|
|
3
5
|
export const cloudflareWorkersRuntime = {
|
|
4
6
|
runtime: 'cloudflare-workers',
|
|
@@ -17,41 +19,34 @@ export const cloudflareWorkersRuntime = {
|
|
|
17
19
|
};
|
|
18
20
|
function bind(options) {
|
|
19
21
|
assertRuntimeEngine('cloudflare-workers');
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
if (options.application.model.extensions.get(httpExecutionExtension) ===
|
|
23
|
+
undefined) {
|
|
24
|
+
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: cloudflareWorkersRuntime.bind() requires the HTTP Execution Extension.');
|
|
25
|
+
}
|
|
26
|
+
let application;
|
|
27
|
+
let initialization;
|
|
28
|
+
const resolve = async (environment) => {
|
|
29
|
+
application ??= createKernelApplication({
|
|
30
|
+
...options,
|
|
26
31
|
application: options.application,
|
|
32
|
+
capabilities: [
|
|
33
|
+
bindApplicationCapability(options.application.model, 'http.server', {
|
|
34
|
+
runtime: 'cloudflare-workers',
|
|
35
|
+
}),
|
|
36
|
+
...(options.capabilities ?? []),
|
|
37
|
+
],
|
|
27
38
|
environment,
|
|
28
|
-
...('arguments' in options ? { arguments: options.arguments } : {}),
|
|
29
39
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (!http) {
|
|
34
|
-
void invocation.application.close();
|
|
35
|
-
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: cloudflareWorkersRuntime.bind() requires an HTTP-capable Application.');
|
|
36
|
-
}
|
|
37
|
-
fetch = createCloudflareWorkersFetchDriver(http);
|
|
38
|
-
return { invocation, fetch };
|
|
40
|
+
initialization ??= application.init();
|
|
41
|
+
await initialization;
|
|
42
|
+
return application.http;
|
|
39
43
|
};
|
|
40
44
|
return {
|
|
41
45
|
async fetch(request, environment) {
|
|
42
|
-
|
|
43
|
-
return resolved.fetch(request);
|
|
46
|
+
return (await resolve(environment)).fetch(request);
|
|
44
47
|
},
|
|
45
48
|
async close(signal) {
|
|
46
|
-
await
|
|
49
|
+
await application?.close(signal);
|
|
47
50
|
},
|
|
48
51
|
};
|
|
49
52
|
}
|
|
50
|
-
function createCloudflareWorkersFetchDriver(application) {
|
|
51
|
-
let initialization;
|
|
52
|
-
return async (request) => {
|
|
53
|
-
initialization ??= application.initialize();
|
|
54
|
-
await initialization;
|
|
55
|
-
return application.handle(request);
|
|
56
|
-
};
|
|
57
|
-
}
|
package/dist/adapters/deno.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { type ApplicationDefinition, type BootstrapArguments, type
|
|
2
|
-
type
|
|
3
|
-
|
|
1
|
+
import { type ApplicationDefinition, type BootstrapArguments, type KernelHostedApplication, type RequireApplicationExtension } from '../application/index.js';
|
|
2
|
+
import type { RuntimeCapabilityBinding } from '../core/index.js';
|
|
3
|
+
import { httpExecutionExtension } from '../http/index.js';
|
|
4
|
+
type HttpApplication<TDefinition extends ApplicationDefinition> = RequireApplicationExtension<TDefinition, typeof httpExecutionExtension>;
|
|
4
5
|
export type DenoRuntimeOptions<TDefinition extends ApplicationDefinition> = {
|
|
5
6
|
readonly application: HttpApplication<TDefinition>;
|
|
6
7
|
readonly environment?: unknown;
|
|
8
|
+
readonly capabilities?: readonly RuntimeCapabilityBinding[];
|
|
9
|
+
readonly forceShutdownTimeoutMs?: number;
|
|
7
10
|
} & BootstrapArguments<TDefinition>;
|
|
8
11
|
export type DenoCreateOptions<TDefinition extends ApplicationDefinition> = DenoRuntimeOptions<TDefinition>;
|
|
9
12
|
export interface DenoServeOptions {
|
|
@@ -18,7 +21,7 @@ export interface DenoBinding {
|
|
|
18
21
|
export interface DenoListenerHandle {
|
|
19
22
|
readonly port: number;
|
|
20
23
|
}
|
|
21
|
-
export type DenoRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> =
|
|
24
|
+
export type DenoRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> = KernelHostedApplication<TDefinition> & {
|
|
22
25
|
serve(options?: DenoServeOptions): Promise<DenoListenerHandle>;
|
|
23
26
|
};
|
|
24
27
|
export declare const denoRuntime: {
|