@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loutrejs/loutre",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -12,18 +12,6 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"import": "./dist/index.js"
|
|
14
14
|
},
|
|
15
|
-
"./host": {
|
|
16
|
-
"types": "./dist/application/host.d.ts",
|
|
17
|
-
"import": "./dist/application/host.js"
|
|
18
|
-
},
|
|
19
|
-
"./binding": {
|
|
20
|
-
"types": "./dist/application/binding.d.ts",
|
|
21
|
-
"import": "./dist/application/binding.js"
|
|
22
|
-
},
|
|
23
|
-
"./openapi": {
|
|
24
|
-
"types": "./dist/application/openapi.d.ts",
|
|
25
|
-
"import": "./dist/application/openapi.js"
|
|
26
|
-
},
|
|
27
15
|
"./presentation": {
|
|
28
16
|
"types": "./dist/presentation.d.ts",
|
|
29
17
|
"import": "./dist/presentation.js"
|
|
@@ -40,13 +28,17 @@
|
|
|
40
28
|
"types": "./dist/http/index.d.ts",
|
|
41
29
|
"import": "./dist/http/index.js"
|
|
42
30
|
},
|
|
31
|
+
"./tasks": {
|
|
32
|
+
"types": "./dist/tasks/index.d.ts",
|
|
33
|
+
"import": "./dist/tasks/index.js"
|
|
34
|
+
},
|
|
43
35
|
"./message-port": {
|
|
44
36
|
"types": "./dist/message-port/index.d.ts",
|
|
45
37
|
"import": "./dist/message-port/index.js"
|
|
46
38
|
},
|
|
47
|
-
"./
|
|
48
|
-
"types": "./dist/
|
|
49
|
-
"import": "./dist/
|
|
39
|
+
"./websocket": {
|
|
40
|
+
"types": "./dist/websocket/index.d.ts",
|
|
41
|
+
"import": "./dist/websocket/index.js"
|
|
50
42
|
},
|
|
51
43
|
"./runtime/bun": {
|
|
52
44
|
"types": "./dist/adapters/bun.d.ts",
|
|
@@ -67,6 +59,10 @@
|
|
|
67
59
|
"./runtime/electron": {
|
|
68
60
|
"types": "./dist/adapters/electron.d.ts",
|
|
69
61
|
"import": "./dist/adapters/electron.js"
|
|
62
|
+
},
|
|
63
|
+
"./http/openapi": {
|
|
64
|
+
"types": "./dist/http/openapi.d.ts",
|
|
65
|
+
"import": "./dist/http/openapi.js"
|
|
70
66
|
}
|
|
71
67
|
},
|
|
72
68
|
"sideEffects": false,
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { type ProviderDescriptor, type QueueDescriptor } from '../core/index.js';
|
|
2
|
-
import { type HttpProtocolExecution } from '../http/index.js';
|
|
3
|
-
import { type MessagePortProtocolExecution } from '../message-port/index.js';
|
|
4
|
-
import type { ApplicationDefinition, BootstrapArguments, HasHttp, HasMessagePort, HasTriggers, InvocationApplication, QueueConsumerDriver, TriggerApplicationCapability } from './index.js';
|
|
5
|
-
type IsAny<TValue> = 0 extends 1 & TValue ? true : false;
|
|
6
|
-
type ProtocolBinding<TDefinition extends ApplicationDefinition> = IsAny<TDefinition> extends true ? {
|
|
7
|
-
readonly http?: HttpProtocolExecution;
|
|
8
|
-
readonly messagePort?: MessagePortProtocolExecution;
|
|
9
|
-
} : (HasHttp<TDefinition> extends true ? {
|
|
10
|
-
readonly http: HttpProtocolExecution;
|
|
11
|
-
} : {}) & (HasMessagePort<TDefinition> extends true ? {
|
|
12
|
-
readonly messagePort: MessagePortProtocolExecution;
|
|
13
|
-
} : {});
|
|
14
|
-
export type InvocationBinding<TDefinition extends ApplicationDefinition> = {
|
|
15
|
-
readonly application: InvocationApplication<TDefinition>;
|
|
16
|
-
} & ProtocolBinding<TDefinition>;
|
|
17
|
-
export type HostBindingApplication<TDefinition extends ApplicationDefinition> = InvocationApplication<TDefinition> & (HasTriggers<TDefinition> extends true ? TriggerApplicationCapability : {});
|
|
18
|
-
export type HostBinding<TDefinition extends ApplicationDefinition> = {
|
|
19
|
-
readonly application: HostBindingApplication<TDefinition>;
|
|
20
|
-
} & ProtocolBinding<TDefinition>;
|
|
21
|
-
export interface InvocationBindingBaseOptions<TDefinition extends ApplicationDefinition> {
|
|
22
|
-
readonly application: TDefinition;
|
|
23
|
-
readonly environment?: unknown;
|
|
24
|
-
}
|
|
25
|
-
export type InvocationBindingOptions<TDefinition extends ApplicationDefinition> = InvocationBindingBaseOptions<TDefinition> & BootstrapArguments<TDefinition>;
|
|
26
|
-
interface BindingApi {
|
|
27
|
-
invocation<const TDefinition extends ApplicationDefinition>(options: InvocationBindingOptions<TDefinition>): InvocationBinding<TDefinition>;
|
|
28
|
-
host<const TDefinition extends ApplicationDefinition>(options: InvocationBindingOptions<TDefinition>): HostBinding<TDefinition>;
|
|
29
|
-
queue(descriptor: QueueDescriptor, driver: QueueConsumerDriver): ProviderDescriptor;
|
|
30
|
-
}
|
|
31
|
-
/** flatなcreateXXX/bindXXX APIを増殖させないため、外部bindingをnamespaceへ集約する。 */
|
|
32
|
-
export declare const binding: Readonly<BindingApi>;
|
|
33
|
-
export {};
|
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import { queueRuntimeToken, validateSchema, } from '../core/index.js';
|
|
2
|
-
import { assertValidCompilation, compileApplication } from '../graph/index.js';
|
|
3
|
-
import { createHttpExecution, } from '../http/index.js';
|
|
4
|
-
import { createMessagePortExecution, } from '../message-port/index.js';
|
|
5
|
-
import { ApplicationRuntime, Logger } from '../runtime/index.js';
|
|
6
|
-
import { bindQueueDriver } from './queue.js';
|
|
7
|
-
import { matchesCronTrigger } from './scheduler.js';
|
|
8
|
-
/** flatなcreateXXX/bindXXX APIを増殖させないため、外部bindingをnamespaceへ集約する。 */
|
|
9
|
-
export const binding = Object.freeze({
|
|
10
|
-
invocation: createInvocationBinding,
|
|
11
|
-
host: createHostBinding,
|
|
12
|
-
queue: bindQueueDriver,
|
|
13
|
-
});
|
|
14
|
-
function createInvocationBinding(options) {
|
|
15
|
-
const state = createRuntimeState(options);
|
|
16
|
-
const application = createInvocationApplication(state);
|
|
17
|
-
return createProtocolBinding(state, application);
|
|
18
|
-
}
|
|
19
|
-
function createHostBinding(options) {
|
|
20
|
-
const state = createRuntimeState(options);
|
|
21
|
-
const application = createInvocationApplication(state);
|
|
22
|
-
let triggersStarted = false;
|
|
23
|
-
let triggerHandles = [];
|
|
24
|
-
const stopTriggers = async () => {
|
|
25
|
-
const handles = triggerHandles;
|
|
26
|
-
triggerHandles = [];
|
|
27
|
-
triggersStarted = false;
|
|
28
|
-
const results = await Promise.allSettled(handles.toReversed().map((handle) => handle.stop()));
|
|
29
|
-
const errors = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
|
|
30
|
-
if (errors.length > 0)
|
|
31
|
-
throw new AggregateError(errors, 'Trigger stop failed');
|
|
32
|
-
};
|
|
33
|
-
Object.assign(application, {
|
|
34
|
-
async close(signal) {
|
|
35
|
-
state.runtime.stopAcceptingExecutions();
|
|
36
|
-
const errors = [];
|
|
37
|
-
try {
|
|
38
|
-
await stopTriggers();
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
errors.push(error);
|
|
42
|
-
}
|
|
43
|
-
try {
|
|
44
|
-
await state.runtime.shutdown(signal);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
errors.push(error);
|
|
48
|
-
}
|
|
49
|
-
if (errors.length > 0)
|
|
50
|
-
throw new AggregateError(errors, 'Application shutdown failed');
|
|
51
|
-
},
|
|
52
|
-
...(state.definition.triggers.length > 0
|
|
53
|
-
? {
|
|
54
|
-
triggers: {
|
|
55
|
-
async start() {
|
|
56
|
-
if (triggersStarted) {
|
|
57
|
-
throw new Error('LUTRE_TRIGGERS_ALREADY_STARTED: Trigger Engine is already started.');
|
|
58
|
-
}
|
|
59
|
-
await state.runtime.initialize();
|
|
60
|
-
triggersStarted = true;
|
|
61
|
-
const started = [];
|
|
62
|
-
try {
|
|
63
|
-
for (const trigger of state.definition.triggers) {
|
|
64
|
-
started.push(await startTrigger(trigger, state.runtime, state.logger));
|
|
65
|
-
}
|
|
66
|
-
triggerHandles = started;
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
await Promise.allSettled(started.toReversed().map((handle) => handle.stop()));
|
|
70
|
-
triggersStarted = false;
|
|
71
|
-
throw error;
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
stop: stopTriggers,
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
: {}),
|
|
78
|
-
});
|
|
79
|
-
return createProtocolBinding(state, application);
|
|
80
|
-
}
|
|
81
|
-
function createRuntimeState(options) {
|
|
82
|
-
const definition = options.application;
|
|
83
|
-
const logger = definition.logger ?? new Logger();
|
|
84
|
-
const tasks = registeredTasks(definition);
|
|
85
|
-
const graph = assertValidCompilation(compileApplication({
|
|
86
|
-
modules: definition.modules,
|
|
87
|
-
...(definition.arguments === undefined
|
|
88
|
-
? {}
|
|
89
|
-
: { arguments: definition.arguments }),
|
|
90
|
-
tasks: definition.tasks,
|
|
91
|
-
triggers: definition.triggers,
|
|
92
|
-
}));
|
|
93
|
-
const runtime = new ApplicationRuntime(definition.modules, {
|
|
94
|
-
logger,
|
|
95
|
-
tasks,
|
|
96
|
-
publicTasks: definition.tasks,
|
|
97
|
-
...(definition.arguments === undefined
|
|
98
|
-
? {}
|
|
99
|
-
: {
|
|
100
|
-
arguments: definition.arguments,
|
|
101
|
-
argumentsSource: 'arguments' in options ? options.arguments : Object.freeze({}),
|
|
102
|
-
}),
|
|
103
|
-
...('environment' in options
|
|
104
|
-
? { environmentSource: options.environment }
|
|
105
|
-
: {}),
|
|
106
|
-
});
|
|
107
|
-
return { definition, logger, runtime, graph };
|
|
108
|
-
}
|
|
109
|
-
function createInvocationApplication(state) {
|
|
110
|
-
const application = {
|
|
111
|
-
graph: state.graph,
|
|
112
|
-
get(token) {
|
|
113
|
-
return state.runtime.get(token);
|
|
114
|
-
},
|
|
115
|
-
async init() {
|
|
116
|
-
await state.runtime.initialize();
|
|
117
|
-
return application;
|
|
118
|
-
},
|
|
119
|
-
...(state.definition.tasks.length > 0
|
|
120
|
-
? {
|
|
121
|
-
run(task, ...args) {
|
|
122
|
-
return Reflect.apply(state.runtime.run, state.runtime, [
|
|
123
|
-
task,
|
|
124
|
-
...args,
|
|
125
|
-
]);
|
|
126
|
-
},
|
|
127
|
-
}
|
|
128
|
-
: {}),
|
|
129
|
-
close: (signal) => state.runtime.shutdown(signal),
|
|
130
|
-
};
|
|
131
|
-
return application;
|
|
132
|
-
}
|
|
133
|
-
function createProtocolBinding(state, application) {
|
|
134
|
-
const protocols = new Set(state.graph.pipelines.map((pipeline) => pipeline.protocol));
|
|
135
|
-
return {
|
|
136
|
-
application,
|
|
137
|
-
...(protocols.has('http')
|
|
138
|
-
? {
|
|
139
|
-
http: createHttpExecution({
|
|
140
|
-
runtime: state.runtime,
|
|
141
|
-
graph: state.graph,
|
|
142
|
-
logger: state.logger,
|
|
143
|
-
}),
|
|
144
|
-
}
|
|
145
|
-
: {}),
|
|
146
|
-
...(protocols.has('messagePort')
|
|
147
|
-
? {
|
|
148
|
-
messagePort: createMessagePortExecution({
|
|
149
|
-
runtime: state.runtime,
|
|
150
|
-
graph: state.graph,
|
|
151
|
-
logger: state.logger,
|
|
152
|
-
}),
|
|
153
|
-
}
|
|
154
|
-
: {}),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
async function startTrigger(trigger, runtime, logger) {
|
|
158
|
-
switch (trigger.trigger) {
|
|
159
|
-
case 'cron':
|
|
160
|
-
return startCronTrigger(trigger, runtime, logger);
|
|
161
|
-
case 'fixed-delay':
|
|
162
|
-
return startFixedDelayTrigger(trigger, runtime, logger);
|
|
163
|
-
case 'queue-consumer':
|
|
164
|
-
return startQueueTrigger(trigger, runtime);
|
|
165
|
-
}
|
|
166
|
-
throw new Error('LUTRE_TRIGGER_UNSUPPORTED: Unsupported trigger type.');
|
|
167
|
-
}
|
|
168
|
-
function startCronTrigger(trigger, runtime, logger) {
|
|
169
|
-
let stopped = false;
|
|
170
|
-
let lastMinute;
|
|
171
|
-
const active = new Set();
|
|
172
|
-
const tick = () => {
|
|
173
|
-
if (stopped)
|
|
174
|
-
return;
|
|
175
|
-
const now = new Date();
|
|
176
|
-
if (!matchesCronTrigger(trigger, now))
|
|
177
|
-
return;
|
|
178
|
-
const minute = cronMinuteIdentity(trigger.timezone, now);
|
|
179
|
-
if (lastMinute === minute)
|
|
180
|
-
return;
|
|
181
|
-
lastMinute = minute;
|
|
182
|
-
if (trigger.overlap === 'skip' && active.size > 0) {
|
|
183
|
-
logger.info('Cron trigger skipped overlapping execution', {
|
|
184
|
-
event: 'trigger.cron.skipped',
|
|
185
|
-
trigger: trigger.name,
|
|
186
|
-
});
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const execution = runtime.runTask(trigger.task).catch((error) => {
|
|
190
|
-
logger.error('Cron trigger execution failed', {
|
|
191
|
-
event: 'trigger.cron.execution.failed',
|
|
192
|
-
trigger: trigger.name,
|
|
193
|
-
error: error instanceof Error ? error.message : String(error),
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
active.add(execution);
|
|
197
|
-
void execution.finally(() => active.delete(execution));
|
|
198
|
-
};
|
|
199
|
-
tick();
|
|
200
|
-
const timer = setInterval(tick, 1_000);
|
|
201
|
-
return {
|
|
202
|
-
async stop() {
|
|
203
|
-
if (stopped)
|
|
204
|
-
return;
|
|
205
|
-
stopped = true;
|
|
206
|
-
clearInterval(timer);
|
|
207
|
-
await Promise.allSettled(active);
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
function startFixedDelayTrigger(trigger, runtime, logger) {
|
|
212
|
-
let stopped = false;
|
|
213
|
-
let timer;
|
|
214
|
-
let releaseSleep;
|
|
215
|
-
const sleep = () => new Promise((resolve) => {
|
|
216
|
-
releaseSleep = resolve;
|
|
217
|
-
timer = setTimeout(() => {
|
|
218
|
-
timer = undefined;
|
|
219
|
-
releaseSleep = undefined;
|
|
220
|
-
resolve();
|
|
221
|
-
}, trigger.delay);
|
|
222
|
-
});
|
|
223
|
-
const execute = async () => {
|
|
224
|
-
try {
|
|
225
|
-
await runtime.runTask(trigger.task);
|
|
226
|
-
}
|
|
227
|
-
catch (error) {
|
|
228
|
-
logger.error('Fixed-delay trigger execution failed', {
|
|
229
|
-
event: 'trigger.fixed_delay.execution.failed',
|
|
230
|
-
trigger: trigger.name,
|
|
231
|
-
error: error instanceof Error ? error.message : String(error),
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
const loop = (async () => {
|
|
236
|
-
if (!trigger.immediate)
|
|
237
|
-
await sleep();
|
|
238
|
-
while (true) {
|
|
239
|
-
if (stopped)
|
|
240
|
-
break;
|
|
241
|
-
await execute();
|
|
242
|
-
if (stopped)
|
|
243
|
-
break;
|
|
244
|
-
await sleep();
|
|
245
|
-
}
|
|
246
|
-
})();
|
|
247
|
-
return {
|
|
248
|
-
async stop() {
|
|
249
|
-
if (stopped)
|
|
250
|
-
return;
|
|
251
|
-
stopped = true;
|
|
252
|
-
if (timer)
|
|
253
|
-
clearTimeout(timer);
|
|
254
|
-
timer = undefined;
|
|
255
|
-
releaseSleep?.();
|
|
256
|
-
releaseSleep = undefined;
|
|
257
|
-
await loop;
|
|
258
|
-
},
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
async function startQueueTrigger(trigger, runtime) {
|
|
262
|
-
const driver = runtime.container.resolve(queueRuntimeToken(trigger.queue));
|
|
263
|
-
if (!driver || typeof driver.start !== 'function') {
|
|
264
|
-
throw new Error(`LUTRE_QUEUE_DRIVER_INVALID: Queue ${trigger.queue.name} driver is invalid.`);
|
|
265
|
-
}
|
|
266
|
-
const handle = await driver.start({
|
|
267
|
-
consume: async (payload) => {
|
|
268
|
-
const validated = await validateSchema(trigger.queue.payload, payload);
|
|
269
|
-
await runtime.runTask(trigger.task, validated);
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
if (!handle || typeof handle.stop !== 'function') {
|
|
273
|
-
throw new Error(`LUTRE_QUEUE_DRIVER_INVALID: Queue ${trigger.queue.name} driver returned an invalid handle.`);
|
|
274
|
-
}
|
|
275
|
-
return handle;
|
|
276
|
-
}
|
|
277
|
-
function registeredTasks(definition) {
|
|
278
|
-
return [
|
|
279
|
-
...new Set([
|
|
280
|
-
...definition.tasks,
|
|
281
|
-
...definition.triggers.map((trigger) => trigger.task),
|
|
282
|
-
]),
|
|
283
|
-
];
|
|
284
|
-
}
|
|
285
|
-
function cronMinuteIdentity(timezone, instant) {
|
|
286
|
-
return new Intl.DateTimeFormat('en-CA', {
|
|
287
|
-
timeZone: timezone,
|
|
288
|
-
year: 'numeric',
|
|
289
|
-
month: '2-digit',
|
|
290
|
-
day: '2-digit',
|
|
291
|
-
hour: '2-digit',
|
|
292
|
-
minute: '2-digit',
|
|
293
|
-
hourCycle: 'h23',
|
|
294
|
-
}).format(instant);
|
|
295
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { ApplicationDefinition, BootstrapArguments, HostedApplication } from './index.js';
|
|
2
|
-
export interface BootstrapBaseOptions<TDefinition extends ApplicationDefinition> {
|
|
3
|
-
readonly application: TDefinition;
|
|
4
|
-
readonly environment?: unknown;
|
|
5
|
-
}
|
|
6
|
-
export type BootstrapOptions<TDefinition extends ApplicationDefinition> = BootstrapBaseOptions<TDefinition> & BootstrapArguments<TDefinition>;
|
|
7
|
-
/** generic hostへruntime固有listenerを持ち込まないため、listener ownershipはruntime adapterへ委ねる。 */
|
|
8
|
-
export declare function bootstrap<const TDefinition extends ApplicationDefinition>(options: BootstrapOptions<TDefinition>): HostedApplication<TDefinition>;
|
package/dist/application/host.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { binding } from './binding.js';
|
|
2
|
-
/** generic hostへruntime固有listenerを持ち込まないため、listener ownershipはruntime adapterへ委ねる。 */
|
|
3
|
-
export function bootstrap(options) {
|
|
4
|
-
const host = binding.host(options);
|
|
5
|
-
const http = 'http' in host ? host.http : undefined;
|
|
6
|
-
if (http) {
|
|
7
|
-
Object.assign(host.application, {
|
|
8
|
-
fetch(request) {
|
|
9
|
-
return http.handle(request);
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
return host.application;
|
|
14
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export function matchesCronTrigger(trigger, instant) {
|
|
2
|
-
const [minute, hour, dayOfMonth, month, dayOfWeek] = trigger.expression
|
|
3
|
-
.trim()
|
|
4
|
-
.split(/\s+/);
|
|
5
|
-
const fields = { minute, hour, dayOfMonth, month, dayOfWeek };
|
|
6
|
-
const parts = new Intl.DateTimeFormat('en-US', {
|
|
7
|
-
timeZone: trigger.timezone,
|
|
8
|
-
minute: 'numeric',
|
|
9
|
-
hour: 'numeric',
|
|
10
|
-
day: 'numeric',
|
|
11
|
-
month: 'numeric',
|
|
12
|
-
weekday: 'short',
|
|
13
|
-
hourCycle: 'h23',
|
|
14
|
-
}).formatToParts(instant);
|
|
15
|
-
const value = (type) => parts.find((part) => part.type === type)?.value ?? '';
|
|
16
|
-
const weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].indexOf(value('weekday'));
|
|
17
|
-
return (matchesCronField(fields.minute, Number(value('minute')), 0, 59) &&
|
|
18
|
-
matchesCronField(fields.hour, Number(value('hour')), 0, 23) &&
|
|
19
|
-
matchesCronField(fields.dayOfMonth, Number(value('day')), 1, 31) &&
|
|
20
|
-
matchesCronField(fields.month, Number(value('month')), 1, 12) &&
|
|
21
|
-
matchesCronField(fields.dayOfWeek, weekday, 0, 7, true));
|
|
22
|
-
}
|
|
23
|
-
function matchesCronField(expression, value, minimum, maximum, sundayAlias = false) {
|
|
24
|
-
return expression.split(',').some((segment) => {
|
|
25
|
-
const [rangeExpression, stepExpression] = segment.split('/');
|
|
26
|
-
const step = stepExpression === undefined ? 1 : Number(stepExpression);
|
|
27
|
-
if (!Number.isInteger(step) || step <= 0 || !rangeExpression)
|
|
28
|
-
return false;
|
|
29
|
-
let start = minimum;
|
|
30
|
-
let end = maximum;
|
|
31
|
-
if (rangeExpression !== '*') {
|
|
32
|
-
const [startExpression, endExpression] = rangeExpression.split('-');
|
|
33
|
-
start = Number(startExpression);
|
|
34
|
-
end = endExpression === undefined ? start : Number(endExpression);
|
|
35
|
-
}
|
|
36
|
-
const normalized = sundayAlias && value === 0 && start === 7 ? 7 : value;
|
|
37
|
-
return (Number.isInteger(start) &&
|
|
38
|
-
Number.isInteger(end) &&
|
|
39
|
-
start >= minimum &&
|
|
40
|
-
end <= maximum &&
|
|
41
|
-
normalized >= start &&
|
|
42
|
-
normalized <= end &&
|
|
43
|
-
(normalized - start) % step === 0);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface ContextKey<TName extends string = string, TValue = unknown> {
|
|
2
|
-
readonly kind: 'context-key';
|
|
3
|
-
readonly name: TName;
|
|
4
|
-
readonly key: symbol;
|
|
5
|
-
readonly '~value'?: TValue;
|
|
6
|
-
}
|
|
7
|
-
export type ContextKeyValue<TKey> = TKey extends ContextKey<string, infer TValue> ? TValue : never;
|
|
8
|
-
export type ContextProperties<TKeys extends readonly ContextKey[]> = {
|
|
9
|
-
readonly [TKey in TKeys[number] as TKey['name']]: ContextKeyValue<TKey>;
|
|
10
|
-
};
|
|
11
|
-
export declare function contextKey<const TName extends string>(name: TName): {
|
|
12
|
-
of<TValue>(): ContextKey<TName, TValue>;
|
|
13
|
-
};
|
|
14
|
-
export declare function contextKeyName(key: ContextKey): string;
|
package/dist/core/context-key.js
DELETED
package/dist/core/contract.d.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
export interface ProtocolDescriptor<TName extends string = string, TContext = unknown, TResult = unknown, TDispatchKey extends string | null = string | null, TCapabilities extends readonly string[] = readonly string[]> {
|
|
2
|
-
readonly kind: 'protocol';
|
|
3
|
-
readonly protocol: TName;
|
|
4
|
-
readonly interaction?: InteractionMode;
|
|
5
|
-
readonly dispatchKey: TDispatchKey;
|
|
6
|
-
readonly capabilities?: TCapabilities;
|
|
7
|
-
readonly '~context'?: TContext;
|
|
8
|
-
readonly '~result'?: TResult;
|
|
9
|
-
}
|
|
10
|
-
export type InteractionMode = 'unary' | 'server-stream' | 'client-stream' | 'duplex';
|
|
11
|
-
export interface ProcedureDefinition<TProtocols extends Record<string, ProtocolDescriptor> = Record<string, ProtocolDescriptor>> {
|
|
12
|
-
readonly kind: 'procedure';
|
|
13
|
-
readonly protocols: TProtocols;
|
|
14
|
-
}
|
|
15
|
-
export interface ProtocolGroup<TName extends string = string, TProcedures extends Record<string, ProtocolDescriptor<TName>> = Record<string, ProtocolDescriptor<TName>>> {
|
|
16
|
-
readonly kind: 'protocol-group';
|
|
17
|
-
readonly protocol: TName;
|
|
18
|
-
readonly procedures: TProcedures;
|
|
19
|
-
}
|
|
20
|
-
export declare function protocolGroup<const TName extends string, const TProcedures extends Record<string, ProtocolDescriptor<TName>>>(protocol: TName, procedures: TProcedures): ProtocolGroup<TName, TProcedures>;
|
|
21
|
-
export interface ContractDefinition<TProcedures extends Record<string, ProcedureDefinition> = Record<string, ProcedureDefinition>> {
|
|
22
|
-
readonly kind: 'contract';
|
|
23
|
-
readonly procedures: TProcedures;
|
|
24
|
-
}
|
|
25
|
-
type ProcedureNamesOfGroup<TGroup> = TGroup extends ProtocolGroup<string, infer TProcedures> ? keyof TProcedures & string : never;
|
|
26
|
-
type ProcedureNamesOfGroups<TGroups extends readonly ProtocolGroup[]> = ProcedureNamesOfGroup<TGroups[number]>;
|
|
27
|
-
type ProtocolOfGroupProcedure<TGroup, TProcedure extends string> = TGroup extends ProtocolGroup<infer TProtocol, infer TProcedures> ? TProcedure extends keyof TProcedures ? {
|
|
28
|
-
readonly [K in TProtocol]: TProcedures[TProcedure];
|
|
29
|
-
} : never : never;
|
|
30
|
-
type ProceduresFromGroups<TGroups extends readonly ProtocolGroup[]> = {
|
|
31
|
-
[TProcedure in ProcedureNamesOfGroups<TGroups>]: ProcedureDefinition<UnionToIntersection<ProtocolOfGroupProcedure<TGroups[number], TProcedure>> extends infer TProtocols extends Record<string, ProtocolDescriptor> ? TProtocols : never>;
|
|
32
|
-
};
|
|
33
|
-
type NonEmptyArrayConstraint<TValues extends readonly unknown[]> = TValues extends readonly [] ? {
|
|
34
|
-
readonly __requiresAtLeastOneEntry__: never;
|
|
35
|
-
} : unknown;
|
|
36
|
-
type ProcedureProtocolKeysOfGroup<TGroup> = TGroup extends ProtocolGroup<infer TProtocol, infer TProcedures> ? `${keyof TProcedures & string}.${TProtocol}` : never;
|
|
37
|
-
type DuplicateGroupProcedureProtocolKeys<TGroups extends readonly ProtocolGroup[], TSeen extends string = never> = number extends TGroups['length'] ? never : TGroups extends readonly [
|
|
38
|
-
infer THead extends ProtocolGroup,
|
|
39
|
-
...infer TTail extends readonly ProtocolGroup[]
|
|
40
|
-
] ? Extract<ProcedureProtocolKeysOfGroup<THead>, TSeen> | DuplicateGroupProcedureProtocolKeys<TTail, TSeen | ProcedureProtocolKeysOfGroup<THead>> : never;
|
|
41
|
-
type GroupProcedureProtocolUniquenessConstraint<TGroups extends readonly ProtocolGroup[]> = [DuplicateGroupProcedureProtocolKeys<TGroups>] extends [never] ? unknown : {
|
|
42
|
-
readonly __duplicateProcedureProtocol__: DuplicateGroupProcedureProtocolKeys<TGroups>;
|
|
43
|
-
};
|
|
44
|
-
declare function defineContract<const TGroups extends readonly ProtocolGroup[]>(groups: TGroups & NonEmptyArrayConstraint<TGroups> & GroupProcedureProtocolUniquenessConstraint<TGroups> & DispatchKeyUniquenessConstraint<ProceduresFromGroups<TGroups>>): ContractDefinition<ProceduresFromGroups<TGroups>>;
|
|
45
|
-
type ProcedureNamesOfContract<TContract> = TContract extends ContractDefinition<infer TProcedures> ? keyof TProcedures & string : never;
|
|
46
|
-
type ProcedureNamesOfContracts<TContracts extends readonly ContractDefinition[]> = ProcedureNamesOfContract<TContracts[number]>;
|
|
47
|
-
type ProtocolsOfContractProcedure<TContract, TProcedure extends string> = TContract extends ContractDefinition<infer TProcedures> ? TProcedure extends keyof TProcedures ? TProcedures[TProcedure]['protocols'] : never : never;
|
|
48
|
-
type UnionToIntersection<T> = (T extends unknown ? (value: T) => void : never) extends (value: infer TIntersection) => void ? TIntersection : never;
|
|
49
|
-
type MergedProcedures<TContracts extends readonly ContractDefinition[]> = {
|
|
50
|
-
[TProcedure in ProcedureNamesOfContracts<TContracts>]: ProcedureDefinition<UnionToIntersection<ProtocolsOfContractProcedure<TContracts[number], TProcedure>> extends infer TProtocols extends Record<string, ProtocolDescriptor> ? TProtocols : never>;
|
|
51
|
-
};
|
|
52
|
-
type ProcedureProtocolKeysOfContract<TContract> = TContract extends ContractDefinition<infer TProcedures> ? {
|
|
53
|
-
[TProcedure in keyof TProcedures & string]: `${TProcedure}.${keyof TProcedures[TProcedure]['protocols'] & string}`;
|
|
54
|
-
}[keyof TProcedures & string] : never;
|
|
55
|
-
type DuplicateContractProcedureProtocolKeys<TContracts extends readonly ContractDefinition[], TSeen extends string = never> = number extends TContracts['length'] ? never : TContracts extends readonly [
|
|
56
|
-
infer THead extends ContractDefinition,
|
|
57
|
-
...infer TTail extends readonly ContractDefinition[]
|
|
58
|
-
] ? Extract<ProcedureProtocolKeysOfContract<THead>, TSeen> | DuplicateContractProcedureProtocolKeys<TTail, TSeen | ProcedureProtocolKeysOfContract<THead>> : never;
|
|
59
|
-
type ContractProcedureProtocolUniquenessConstraint<TContracts extends readonly ContractDefinition[]> = [DuplicateContractProcedureProtocolKeys<TContracts>] extends [never] ? unknown : {
|
|
60
|
-
readonly __duplicateProcedureProtocol__: DuplicateContractProcedureProtocolKeys<TContracts>;
|
|
61
|
-
};
|
|
62
|
-
declare function mergeContracts<const TContracts extends readonly ContractDefinition[]>(contracts: TContracts & NonEmptyArrayConstraint<TContracts> & ContractProcedureProtocolUniquenessConstraint<TContracts> & DispatchKeyUniquenessConstraint<MergedProcedures<TContracts>>): ContractDefinition<MergedProcedures<TContracts>>;
|
|
63
|
-
export declare const contract: typeof defineContract & {
|
|
64
|
-
merge: typeof mergeContracts;
|
|
65
|
-
};
|
|
66
|
-
type ProtocolDispatchEntries<TProcedures extends Record<string, ProcedureDefinition>> = {
|
|
67
|
-
[TProcedure in keyof TProcedures & string]: {
|
|
68
|
-
[TProtocol in keyof TProcedures[TProcedure]['protocols'] & string]: TProcedures[TProcedure]['protocols'][TProtocol] extends {
|
|
69
|
-
readonly dispatchKey: infer TDispatchKey extends string | null;
|
|
70
|
-
} ? TDispatchKey extends string ? {
|
|
71
|
-
readonly key: TDispatchKey;
|
|
72
|
-
readonly path: `${TProcedure}.${TProtocol}`;
|
|
73
|
-
} : never : never;
|
|
74
|
-
}[keyof TProcedures[TProcedure]['protocols'] & string];
|
|
75
|
-
}[keyof TProcedures & string];
|
|
76
|
-
type IsUnion<TValue, TCandidate = TValue> = TValue extends unknown ? [TCandidate] extends [TValue] ? false : true : never;
|
|
77
|
-
type DuplicateDispatchKeys<TEntries, TAllEntries = TEntries> = TEntries extends {
|
|
78
|
-
readonly key: infer TKey extends string;
|
|
79
|
-
} ? string extends TKey ? never : IsUnion<Extract<TAllEntries, {
|
|
80
|
-
readonly key: TKey;
|
|
81
|
-
}> extends {
|
|
82
|
-
readonly path: infer TPath;
|
|
83
|
-
} ? TPath : never> extends true ? TKey : never : never;
|
|
84
|
-
type DispatchKeyUniquenessConstraint<TProcedures extends Record<string, ProcedureDefinition>> = [DuplicateDispatchKeys<ProtocolDispatchEntries<TProcedures>>] extends [
|
|
85
|
-
never
|
|
86
|
-
] ? unknown : {
|
|
87
|
-
readonly __duplicateProtocolDispatchKey__: DuplicateDispatchKeys<ProtocolDispatchEntries<TProcedures>>;
|
|
88
|
-
};
|
|
89
|
-
export type ContractProcedures<TContract extends ContractDefinition> = TContract['procedures'];
|
|
90
|
-
export interface ProtocolFactory<TName extends string, TCapabilities extends readonly string[] = readonly string[]> {
|
|
91
|
-
readonly protocol: TName;
|
|
92
|
-
readonly capabilities?: TCapabilities;
|
|
93
|
-
}
|
|
94
|
-
export {};
|