@loutrejs/loutre 0.3.0 → 0.4.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/dist/adapters/bun.d.ts +11 -8
- package/dist/adapters/bun.js +72 -50
- package/dist/adapters/deno.d.ts +9 -7
- package/dist/adapters/deno.js +75 -53
- package/dist/application/binding.js +3 -0
- package/dist/application/index.d.ts +2 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/runtime/application.d.ts +2 -1
- package/dist/runtime/application.js +18 -3
- package/dist/runtime/di.d.ts +1 -0
- package/dist/runtime/di.js +31 -0
- package/package.json +1 -1
package/dist/adapters/bun.d.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { type ApplicationDefinition, type BootstrapArguments, type HasHttp, type HostBindingApplication } from '../application/index.js';
|
|
2
2
|
type IsAny<TValue> = 0 extends 1 & TValue ? true : false;
|
|
3
3
|
type HttpApplication<TDefinition extends ApplicationDefinition> = IsAny<TDefinition> extends true ? TDefinition : HasHttp<TDefinition> extends true ? TDefinition : never;
|
|
4
|
-
export type
|
|
4
|
+
export type BunCreateOptions<TDefinition extends ApplicationDefinition> = {
|
|
5
5
|
readonly application: HttpApplication<TDefinition>;
|
|
6
|
+
readonly environment?: unknown;
|
|
7
|
+
} & BootstrapArguments<TDefinition>;
|
|
8
|
+
export interface BunServeOptions {
|
|
6
9
|
readonly port?: number;
|
|
7
10
|
readonly hostname?: string;
|
|
8
11
|
readonly shutdownHooks?: boolean;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export interface BunServeHandle<TDefinition extends ApplicationDefinition = ApplicationDefinition> {
|
|
12
|
-
readonly application: HostBindingApplication<TDefinition>;
|
|
12
|
+
}
|
|
13
|
+
export interface BunListenerHandle {
|
|
13
14
|
readonly port: number;
|
|
14
|
-
close(signal?: string): Promise<void>;
|
|
15
15
|
}
|
|
16
|
+
export type BunRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> = HostBindingApplication<TDefinition> & {
|
|
17
|
+
serve(options?: BunServeOptions): Promise<BunListenerHandle>;
|
|
18
|
+
};
|
|
16
19
|
export declare const bunRuntime: {
|
|
17
20
|
readonly runtime: 'bun';
|
|
18
21
|
readonly capabilities: Set<string>;
|
|
19
|
-
readonly
|
|
22
|
+
readonly create: typeof create;
|
|
20
23
|
};
|
|
21
|
-
declare function
|
|
24
|
+
declare function create<const TDefinition extends ApplicationDefinition>(options: BunCreateOptions<TDefinition>): Promise<BunRuntimeApplication<TDefinition>>;
|
|
22
25
|
export {};
|
package/dist/adapters/bun.js
CHANGED
|
@@ -15,16 +15,13 @@ export const bunRuntime = {
|
|
|
15
15
|
'env.runtime',
|
|
16
16
|
'crypto.random',
|
|
17
17
|
]),
|
|
18
|
-
|
|
18
|
+
create,
|
|
19
19
|
};
|
|
20
|
-
async function
|
|
20
|
+
async function create(options) {
|
|
21
21
|
assertRuntimeEngine('bun');
|
|
22
22
|
const bun = bunGlobal();
|
|
23
|
-
if (!bun?.serve) {
|
|
24
|
-
throw new Error('LUTRE_BUN_UNAVAILABLE: Bun.serve() is not available.');
|
|
25
|
-
}
|
|
26
23
|
const startedAt = performance.now();
|
|
27
|
-
const environment = bun
|
|
24
|
+
const environment = bun?.env ?? {};
|
|
28
25
|
const presentation = startStartupPresentation({ version: LOUTRE_VERSION }, {
|
|
29
26
|
terminal: detectPresentationTerminal(process.stdout, environment),
|
|
30
27
|
write: (value) => console.log(value),
|
|
@@ -37,53 +34,32 @@ async function serve(options) {
|
|
|
37
34
|
const http = 'http' in host ? host.http : undefined;
|
|
38
35
|
if (!http) {
|
|
39
36
|
await host.application.close();
|
|
40
|
-
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: bunRuntime.
|
|
37
|
+
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: bunRuntime.create() requires an HTTP-capable Application.');
|
|
41
38
|
}
|
|
42
39
|
await host.application.init();
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const application = host.application;
|
|
41
|
+
const closeApplication = host.application.close.bind(host.application);
|
|
45
42
|
let server;
|
|
46
|
-
|
|
47
|
-
let
|
|
48
|
-
while (true) {
|
|
49
|
-
try {
|
|
50
|
-
server = bun.serve({
|
|
51
|
-
port,
|
|
52
|
-
...(options.hostname === undefined
|
|
53
|
-
? {}
|
|
54
|
-
: { hostname: options.hostname }),
|
|
55
|
-
fetch: createBunFetchDriver(http),
|
|
56
|
-
});
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
if (requestedPort !== undefined || !canRetryOnNextPort(error, port)) {
|
|
61
|
-
await host.application.close().catch(() => undefined);
|
|
62
|
-
throw error;
|
|
63
|
-
}
|
|
64
|
-
port += 1;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
presentation.ready({
|
|
68
|
-
server: serverUrl(options.hostname, port),
|
|
69
|
-
runtime: `Bun ${bun.version ?? 'unknown'}`,
|
|
70
|
-
environment: environment.NODE_ENV ?? 'development',
|
|
71
|
-
startupDurationMs: performance.now() - startedAt,
|
|
72
|
-
});
|
|
43
|
+
let removeShutdownHooks;
|
|
44
|
+
let serving = false;
|
|
73
45
|
let closed = false;
|
|
74
|
-
const
|
|
46
|
+
const close = async (signal) => {
|
|
75
47
|
if (closed)
|
|
76
48
|
return;
|
|
77
49
|
closed = true;
|
|
50
|
+
removeShutdownHooks?.();
|
|
51
|
+
removeShutdownHooks = undefined;
|
|
78
52
|
const errors = [];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
53
|
+
if (server) {
|
|
54
|
+
try {
|
|
55
|
+
await server.stop(true);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
errors.push(error);
|
|
59
|
+
}
|
|
84
60
|
}
|
|
85
61
|
try {
|
|
86
|
-
await
|
|
62
|
+
await closeApplication(signal);
|
|
87
63
|
}
|
|
88
64
|
catch (error) {
|
|
89
65
|
errors.push(error);
|
|
@@ -91,14 +67,60 @@ async function serve(options) {
|
|
|
91
67
|
if (errors.length > 0)
|
|
92
68
|
throw new AggregateError(errors, 'Bun runtime shutdown failed');
|
|
93
69
|
};
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
70
|
+
const serve = async (serveOptions = {}) => {
|
|
71
|
+
if (closed) {
|
|
72
|
+
throw new Error('LUTRE_APP_STOPPED: Application is stopped.');
|
|
73
|
+
}
|
|
74
|
+
if (serving) {
|
|
75
|
+
throw new Error('LUTRE_RUNTIME_ALREADY_SERVING: Bun runtime Application is already serving.');
|
|
76
|
+
}
|
|
77
|
+
if (!bun?.serve) {
|
|
78
|
+
await close().catch(() => undefined);
|
|
79
|
+
throw new Error('LUTRE_BUN_UNAVAILABLE: Bun.serve() is not available.');
|
|
80
|
+
}
|
|
81
|
+
serving = true;
|
|
82
|
+
try {
|
|
83
|
+
if ('triggers' in application)
|
|
84
|
+
await application.triggers.start();
|
|
85
|
+
const requestedPort = serveOptions.port;
|
|
86
|
+
let port = requestedPort ?? 3000;
|
|
87
|
+
while (true) {
|
|
88
|
+
try {
|
|
89
|
+
server = bun.serve({
|
|
90
|
+
port,
|
|
91
|
+
...(serveOptions.hostname === undefined
|
|
92
|
+
? {}
|
|
93
|
+
: { hostname: serveOptions.hostname }),
|
|
94
|
+
fetch: createBunFetchDriver(http),
|
|
95
|
+
});
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (requestedPort !== undefined || !canRetryOnNextPort(error, port)) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
port += 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
presentation.ready({
|
|
106
|
+
server: serverUrl(serveOptions.hostname, port),
|
|
107
|
+
runtime: `Bun ${bun.version ?? 'unknown'}`,
|
|
108
|
+
environment: environment.NODE_ENV ?? 'development',
|
|
109
|
+
startupDurationMs: performance.now() - startedAt,
|
|
110
|
+
});
|
|
111
|
+
removeShutdownHooks =
|
|
112
|
+
serveOptions.shutdownHooks === false
|
|
113
|
+
? undefined
|
|
114
|
+
: registerBunShutdownHooks(close);
|
|
115
|
+
return { port };
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
await close().catch(() => undefined);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
100
121
|
};
|
|
101
|
-
|
|
122
|
+
Object.assign(application, { serve, close });
|
|
123
|
+
return application;
|
|
102
124
|
}
|
|
103
125
|
function registerBunShutdownHooks(close) {
|
|
104
126
|
const handlers = new Map();
|
package/dist/adapters/deno.d.ts
CHANGED
|
@@ -5,26 +5,28 @@ export type DenoRuntimeOptions<TDefinition extends ApplicationDefinition> = {
|
|
|
5
5
|
readonly application: HttpApplication<TDefinition>;
|
|
6
6
|
readonly environment?: unknown;
|
|
7
7
|
} & BootstrapArguments<TDefinition>;
|
|
8
|
-
export type
|
|
8
|
+
export type DenoCreateOptions<TDefinition extends ApplicationDefinition> = DenoRuntimeOptions<TDefinition>;
|
|
9
|
+
export interface DenoServeOptions {
|
|
9
10
|
readonly port?: number;
|
|
10
11
|
readonly hostname?: string;
|
|
11
12
|
readonly shutdownHooks?: boolean;
|
|
12
|
-
}
|
|
13
|
+
}
|
|
13
14
|
export interface DenoBinding {
|
|
14
15
|
fetch(request: Request): Promise<Response>;
|
|
15
16
|
close(signal?: string): Promise<void>;
|
|
16
17
|
}
|
|
17
|
-
export interface
|
|
18
|
-
readonly application: HostBindingApplication<TDefinition>;
|
|
18
|
+
export interface DenoListenerHandle {
|
|
19
19
|
readonly port: number;
|
|
20
|
-
close(signal?: string): Promise<void>;
|
|
21
20
|
}
|
|
21
|
+
export type DenoRuntimeApplication<TDefinition extends ApplicationDefinition = ApplicationDefinition> = HostBindingApplication<TDefinition> & {
|
|
22
|
+
serve(options?: DenoServeOptions): Promise<DenoListenerHandle>;
|
|
23
|
+
};
|
|
22
24
|
export declare const denoRuntime: {
|
|
23
25
|
readonly runtime: 'deno';
|
|
24
26
|
readonly capabilities: Set<string>;
|
|
25
27
|
readonly bind: typeof bind;
|
|
26
|
-
readonly
|
|
28
|
+
readonly create: typeof create;
|
|
27
29
|
};
|
|
28
30
|
declare function bind<const TDefinition extends ApplicationDefinition>(options: DenoRuntimeOptions<TDefinition>): DenoBinding;
|
|
29
|
-
declare function
|
|
31
|
+
declare function create<const TDefinition extends ApplicationDefinition>(options: DenoCreateOptions<TDefinition>): Promise<DenoRuntimeApplication<TDefinition>>;
|
|
30
32
|
export {};
|
package/dist/adapters/deno.js
CHANGED
|
@@ -16,7 +16,7 @@ export const denoRuntime = {
|
|
|
16
16
|
'crypto.random',
|
|
17
17
|
]),
|
|
18
18
|
bind,
|
|
19
|
-
|
|
19
|
+
create,
|
|
20
20
|
};
|
|
21
21
|
function bind(options) {
|
|
22
22
|
assertRuntimeEngine('deno');
|
|
@@ -34,18 +34,15 @@ function bind(options) {
|
|
|
34
34
|
close: (signal) => invocation.application.close(signal),
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
async function
|
|
37
|
+
async function create(options) {
|
|
38
38
|
assertRuntimeEngine('deno');
|
|
39
39
|
const deno = denoGlobal();
|
|
40
|
-
if (!deno?.serve) {
|
|
41
|
-
throw new Error('LUTRE_DENO_UNAVAILABLE: Deno.serve() is not available.');
|
|
42
|
-
}
|
|
43
40
|
const startedAt = performance.now();
|
|
44
|
-
const isTTY = deno
|
|
41
|
+
const isTTY = deno?.stdout?.isTerminal?.() === true;
|
|
45
42
|
const presentation = startStartupPresentation({ version: LOUTRE_VERSION }, {
|
|
46
43
|
terminal: {
|
|
47
44
|
isTTY,
|
|
48
|
-
color: isTTY && deno
|
|
45
|
+
color: isTTY && deno?.env?.get?.('NO_COLOR') === undefined,
|
|
49
46
|
},
|
|
50
47
|
write: (value) => console.log(value),
|
|
51
48
|
});
|
|
@@ -53,55 +50,32 @@ async function serve(options) {
|
|
|
53
50
|
const http = 'http' in host ? host.http : undefined;
|
|
54
51
|
if (!http) {
|
|
55
52
|
await host.application.close();
|
|
56
|
-
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: denoRuntime.
|
|
53
|
+
throw new Error('LUTRE_RUNTIME_HTTP_REQUIRED: denoRuntime.create() requires an HTTP-capable Application.');
|
|
57
54
|
}
|
|
58
55
|
await host.application.init();
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
const application = host.application;
|
|
57
|
+
const closeApplication = host.application.close.bind(host.application);
|
|
61
58
|
let server;
|
|
62
|
-
|
|
63
|
-
let
|
|
64
|
-
while (true) {
|
|
65
|
-
try {
|
|
66
|
-
server = deno.serve({
|
|
67
|
-
port,
|
|
68
|
-
...(options.hostname === undefined
|
|
69
|
-
? {}
|
|
70
|
-
: { hostname: options.hostname }),
|
|
71
|
-
onListen: () => undefined,
|
|
72
|
-
}, createDenoFetchDriver(http));
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (requestedPort !== undefined || !canRetryOnNextPort(error, port)) {
|
|
77
|
-
await host.application.close().catch(() => undefined);
|
|
78
|
-
throw error;
|
|
79
|
-
}
|
|
80
|
-
port += 1;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
presentation.ready({
|
|
84
|
-
server: serverUrl(options.hostname, port),
|
|
85
|
-
runtime: `Deno ${deno.version?.deno ?? 'unknown'}`,
|
|
86
|
-
environment: deno.env?.get?.('DENO_ENV') ??
|
|
87
|
-
deno.env?.get?.('NODE_ENV') ??
|
|
88
|
-
'development',
|
|
89
|
-
startupDurationMs: performance.now() - startedAt,
|
|
90
|
-
});
|
|
59
|
+
let removeShutdownHooks;
|
|
60
|
+
let serving = false;
|
|
91
61
|
let closed = false;
|
|
92
|
-
const
|
|
62
|
+
const close = async (signal) => {
|
|
93
63
|
if (closed)
|
|
94
64
|
return;
|
|
95
65
|
closed = true;
|
|
66
|
+
removeShutdownHooks?.();
|
|
67
|
+
removeShutdownHooks = undefined;
|
|
96
68
|
const errors = [];
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
69
|
+
if (server) {
|
|
70
|
+
try {
|
|
71
|
+
await server.shutdown();
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
errors.push(error);
|
|
75
|
+
}
|
|
102
76
|
}
|
|
103
77
|
try {
|
|
104
|
-
await
|
|
78
|
+
await closeApplication(signal);
|
|
105
79
|
}
|
|
106
80
|
catch (error) {
|
|
107
81
|
errors.push(error);
|
|
@@ -109,14 +83,62 @@ async function serve(options) {
|
|
|
109
83
|
if (errors.length > 0)
|
|
110
84
|
throw new AggregateError(errors, 'Deno runtime shutdown failed');
|
|
111
85
|
};
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
86
|
+
const serve = async (serveOptions = {}) => {
|
|
87
|
+
if (closed) {
|
|
88
|
+
throw new Error('LUTRE_APP_STOPPED: Application is stopped.');
|
|
89
|
+
}
|
|
90
|
+
if (serving) {
|
|
91
|
+
throw new Error('LUTRE_RUNTIME_ALREADY_SERVING: Deno runtime Application is already serving.');
|
|
92
|
+
}
|
|
93
|
+
if (!deno?.serve) {
|
|
94
|
+
await close().catch(() => undefined);
|
|
95
|
+
throw new Error('LUTRE_DENO_UNAVAILABLE: Deno.serve() is not available.');
|
|
96
|
+
}
|
|
97
|
+
serving = true;
|
|
98
|
+
try {
|
|
99
|
+
if ('triggers' in application)
|
|
100
|
+
await application.triggers.start();
|
|
101
|
+
const requestedPort = serveOptions.port;
|
|
102
|
+
let port = requestedPort ?? 3000;
|
|
103
|
+
while (true) {
|
|
104
|
+
try {
|
|
105
|
+
server = deno.serve({
|
|
106
|
+
port,
|
|
107
|
+
...(serveOptions.hostname === undefined
|
|
108
|
+
? {}
|
|
109
|
+
: { hostname: serveOptions.hostname }),
|
|
110
|
+
onListen: () => undefined,
|
|
111
|
+
}, createDenoFetchDriver(http));
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (requestedPort !== undefined || !canRetryOnNextPort(error, port)) {
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
port += 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
presentation.ready({
|
|
122
|
+
server: serverUrl(serveOptions.hostname, port),
|
|
123
|
+
runtime: `Deno ${deno.version?.deno ?? 'unknown'}`,
|
|
124
|
+
environment: deno.env?.get?.('DENO_ENV') ??
|
|
125
|
+
deno.env?.get?.('NODE_ENV') ??
|
|
126
|
+
'development',
|
|
127
|
+
startupDurationMs: performance.now() - startedAt,
|
|
128
|
+
});
|
|
129
|
+
removeShutdownHooks =
|
|
130
|
+
serveOptions.shutdownHooks === false
|
|
131
|
+
? undefined
|
|
132
|
+
: registerDenoShutdownHooks(deno, close);
|
|
133
|
+
return { port };
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
await close().catch(() => undefined);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
118
139
|
};
|
|
119
|
-
|
|
140
|
+
Object.assign(application, { serve, close });
|
|
141
|
+
return application;
|
|
120
142
|
}
|
|
121
143
|
function registerDenoShutdownHooks(deno, close) {
|
|
122
144
|
if (!deno.addSignalListener || !deno.removeSignalListener) {
|
|
@@ -109,6 +109,9 @@ function createRuntimeState(options) {
|
|
|
109
109
|
function createInvocationApplication(state) {
|
|
110
110
|
const application = {
|
|
111
111
|
graph: state.graph,
|
|
112
|
+
get(token) {
|
|
113
|
+
return state.runtime.get(token);
|
|
114
|
+
},
|
|
112
115
|
async init() {
|
|
113
116
|
await state.runtime.initialize();
|
|
114
117
|
return application;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ArgsClass, ModuleProtocols, ModuleInstance, SchemaInput, TaskArguments, TaskDescriptor, TaskOutput, TriggerDescriptor } from '../core/index.js';
|
|
1
|
+
import type { ArgsClass, ModuleProtocols, ModuleInstance, SchemaInput, TaskArguments, TaskDescriptor, TaskOutput, TokenLike, TokenValue, TriggerDescriptor } from '../core/index.js';
|
|
2
2
|
import type { ApplicationGraphIR } from '../graph/index.js';
|
|
3
3
|
import type { Logger } from '../runtime/index.js';
|
|
4
4
|
export interface ApplicationDefinitionOptions<TModules extends readonly ModuleInstance[], TArguments extends ArgsClass | undefined, TTasks extends readonly TaskDescriptor<any, any>[], TTriggers extends readonly TriggerDescriptor[]> {
|
|
@@ -27,6 +27,7 @@ export type BootstrapArguments<TDefinition extends ApplicationDefinition> = TDef
|
|
|
27
27
|
};
|
|
28
28
|
export interface BaseApplication {
|
|
29
29
|
readonly graph: ApplicationGraphIR;
|
|
30
|
+
get<TToken extends TokenLike>(token: TToken): TokenValue<TToken>;
|
|
30
31
|
init(): Promise<this>;
|
|
31
32
|
close(signal?: string): Promise<void>;
|
|
32
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LOUTRE_VERSION = "0.
|
|
1
|
+
export declare const LOUTRE_VERSION = "0.4.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// package manifestとのずれを避けるため、scripts/generate-version.mjsがbuild前に更新する。
|
|
2
|
-
export const LOUTRE_VERSION = '0.
|
|
2
|
+
export const LOUTRE_VERSION = '0.4.0';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ArgsClass, type EnvClass, type ModuleInstance, type ModuleTemplate, type TaskArguments, type TaskDescriptor, type TaskOutput } from '../core/index.js';
|
|
1
|
+
import { type ArgsClass, type EnvClass, type ModuleInstance, type ModuleTemplate, type TaskArguments, type TaskDescriptor, type TaskOutput, type TokenLike } from '../core/index.js';
|
|
2
2
|
import { Container, type RuntimeModuleGraph } from './di.js';
|
|
3
3
|
import { Logger } from './logger.js';
|
|
4
4
|
export interface ApplicationRuntimeOptions {
|
|
@@ -27,6 +27,7 @@ export declare class ApplicationRuntime {
|
|
|
27
27
|
readonly container: Container;
|
|
28
28
|
constructor(roots: readonly (ModuleInstance | ModuleTemplate<void>)[], options?: ApplicationRuntimeOptions);
|
|
29
29
|
initialize(): Promise<void>;
|
|
30
|
+
get<T>(token: TokenLike<T>): T;
|
|
30
31
|
run<TTask extends TaskDescriptor<any, any>>(task: TTask, ...args: TaskArguments<TTask>): Promise<TaskOutput<TTask>>;
|
|
31
32
|
/** public run()ではTrigger専用Taskを拒否するため、Trigger Host専用経路を分ける。 */
|
|
32
33
|
runTask<TTask extends TaskDescriptor<any, any>>(task: TTask, ...args: TaskArguments<TTask>): Promise<TaskOutput<TTask>>;
|
|
@@ -164,6 +164,18 @@ export class ApplicationRuntime {
|
|
|
164
164
|
}
|
|
165
165
|
this.#prepared = true;
|
|
166
166
|
}
|
|
167
|
+
get(token) {
|
|
168
|
+
if (this.#state === 'created' || this.#state === 'initializing') {
|
|
169
|
+
throw applicationStateError('LUTRE_APP_NOT_INITIALIZED');
|
|
170
|
+
}
|
|
171
|
+
if (this.#state === 'stopping') {
|
|
172
|
+
throw applicationStateError('LUTRE_APP_STOPPING');
|
|
173
|
+
}
|
|
174
|
+
if (this.#state === 'stopped') {
|
|
175
|
+
throw applicationStateError('LUTRE_APP_STOPPED');
|
|
176
|
+
}
|
|
177
|
+
return this.container.get(token);
|
|
178
|
+
}
|
|
167
179
|
run(task, ...args) {
|
|
168
180
|
if (!this.#publicTasks.has(task)) {
|
|
169
181
|
return Promise.reject(new Error(`LUTRE_TASK_002: Task ${task.name} is not registered in Application.tasks.`));
|
|
@@ -283,9 +295,12 @@ export class ApplicationRuntime {
|
|
|
283
295
|
}
|
|
284
296
|
}
|
|
285
297
|
function applicationStateError(code) {
|
|
286
|
-
|
|
287
|
-
?
|
|
288
|
-
:
|
|
298
|
+
const message = code === 'LUTRE_APP_NOT_INITIALIZED'
|
|
299
|
+
? 'Application is not initialized.'
|
|
300
|
+
: code === 'LUTRE_APP_STOPPING'
|
|
301
|
+
? 'Application is stopping and cannot accept new executions.'
|
|
302
|
+
: 'Application is stopped and cannot accept new executions.';
|
|
303
|
+
return new Error(`${code}: ${message}`);
|
|
289
304
|
}
|
|
290
305
|
function collectApplicationPipelines(modules) {
|
|
291
306
|
const pipelines = [];
|
package/dist/runtime/di.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class Container {
|
|
|
24
24
|
bindEnvironment(environment: EnvClass, value: object): void;
|
|
25
25
|
bindArguments(argumentsContract: ArgsClass, value: object): void;
|
|
26
26
|
resolve<T>(token: TokenLike<T>): T;
|
|
27
|
+
get<T>(token: TokenLike<T>): T;
|
|
27
28
|
probeClass<T>(target: Class<T>): T;
|
|
28
29
|
prepareImplementation(implementation: ImplementationDescriptor): void;
|
|
29
30
|
implementationRuntime(implementation: ImplementationDescriptor): object;
|
package/dist/runtime/di.js
CHANGED
|
@@ -110,6 +110,37 @@ export class Container {
|
|
|
110
110
|
resolve(token) {
|
|
111
111
|
return this.#resolve(token);
|
|
112
112
|
}
|
|
113
|
+
get(token) {
|
|
114
|
+
const provider = this.#providers.get(token);
|
|
115
|
+
if (!provider) {
|
|
116
|
+
if (isEnvClass(token)) {
|
|
117
|
+
throw new DependencyResolutionError(`LUTRE_ENV_002: ${token.name} is not declared by any Module.environment.`);
|
|
118
|
+
}
|
|
119
|
+
if (isArgsClass(token)) {
|
|
120
|
+
throw new DependencyResolutionError(`LUTRE_ARGS_002: ${token.name} is not declared by Application.arguments.`);
|
|
121
|
+
}
|
|
122
|
+
throw new DependencyResolutionError(`LUTRE_DI_UNRESOLVED: Application requires ${tokenName(token)}, but no provider is declared for ${tokenName(token)}.`);
|
|
123
|
+
}
|
|
124
|
+
if (provider.scope !== 'application') {
|
|
125
|
+
throw new DependencyResolutionError(`LUTRE_DI_SCOPED_GET: ${tokenName(token)} is ${provider.scope}-scoped and cannot be retrieved with Application.get().`);
|
|
126
|
+
}
|
|
127
|
+
if (provider.kind === 'environment') {
|
|
128
|
+
if (this.#environment.has(provider.provide)) {
|
|
129
|
+
return this.#environment.get(provider.provide);
|
|
130
|
+
}
|
|
131
|
+
throw new DependencyResolutionError(`LUTRE_ENV_005: Environment ${provider.provide.name} requires a runtime Environment source before Application initialization.`);
|
|
132
|
+
}
|
|
133
|
+
if (provider.kind === 'arguments') {
|
|
134
|
+
if (this.#arguments.has(provider.provide)) {
|
|
135
|
+
return this.#arguments.get(provider.provide);
|
|
136
|
+
}
|
|
137
|
+
throw new DependencyResolutionError(`LUTRE_ARGS_005: Arguments ${provider.provide.name} requires runtime Arguments before Application initialization.`);
|
|
138
|
+
}
|
|
139
|
+
if (this.#applicationCache.has(token)) {
|
|
140
|
+
return this.#applicationCache.get(token);
|
|
141
|
+
}
|
|
142
|
+
throw new DependencyResolutionError(`LUTRE_DI_NOT_INITIALIZED: ${tokenName(token)} has not been constructed by Application initialization.`);
|
|
143
|
+
}
|
|
113
144
|
probeClass(target) {
|
|
114
145
|
try {
|
|
115
146
|
return this.#instantiate(target, [target]);
|