nvent 0.5.15 → 1.0.0-alpha.2
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/module.d.mts +181 -8
- package/dist/module.json +1 -1
- package/dist/module.mjs +1257 -1196
- package/dist/runtime/app/composables/useFunctionCall.d.ts +17 -0
- package/dist/runtime/app/composables/useFunctionCall.js +25 -0
- package/dist/runtime/app/composables/useNventStream.d.ts +23 -0
- package/dist/runtime/app/composables/useNventStream.js +58 -0
- package/dist/runtime/nitro/plugins/00.iii-lifecycle.d.ts +19 -0
- package/dist/runtime/nitro/plugins/00.iii-lifecycle.js +62 -0
- package/dist/runtime/nitro/plugins/01.iii-worker.d.ts +15 -0
- package/dist/runtime/nitro/plugins/01.iii-worker.js +91 -0
- package/dist/runtime/nitro/routes/stream-proxy.d.ts +17 -0
- package/dist/runtime/nitro/routes/stream-proxy.js +45 -0
- package/dist/runtime/nitro/utils/console.d.ts +32 -0
- package/dist/runtime/nitro/utils/console.js +95 -0
- package/dist/runtime/nitro/utils/defineFunction.d.ts +378 -3
- package/dist/runtime/nitro/utils/defineFunction.js +224 -4
- package/dist/runtime/nitro/utils/engine.d.ts +25 -0
- package/dist/runtime/nitro/utils/engine.js +130 -0
- package/dist/runtime/nitro/utils/nventDir.d.ts +1 -0
- package/dist/runtime/nitro/utils/nventDir.js +20 -0
- package/dist/runtime/nitro/utils/useIii.d.ts +23 -0
- package/dist/runtime/nitro/utils/useIii.js +14 -0
- package/dist/runtime/nitro/utils/workers/node.d.ts +24 -0
- package/dist/runtime/nitro/utils/workers/node.js +57 -0
- package/dist/runtime/nitro/utils/workers/python.d.ts +67 -0
- package/dist/runtime/nitro/utils/workers/python.js +220 -0
- package/dist/runtime/python/nvent.py +208 -0
- package/dist/runtime/python/worker_runtime.py +659 -0
- package/dist/runtime/virtual.d.ts +17 -0
- package/dist/types.d.mts +5 -1
- package/package.json +11 -14
- package/dist/runtime/adapters/base/index.d.ts +0 -6
- package/dist/runtime/adapters/base/index.js +0 -1
- package/dist/runtime/adapters/base/store-validator.d.ts +0 -48
- package/dist/runtime/adapters/base/store-validator.js +0 -147
- package/dist/runtime/adapters/builtin/file-queue.d.ts +0 -67
- package/dist/runtime/adapters/builtin/file-queue.js +0 -499
- package/dist/runtime/adapters/builtin/file-store.d.ts +0 -32
- package/dist/runtime/adapters/builtin/file-store.js +0 -206
- package/dist/runtime/adapters/builtin/file-stream.d.ts +0 -39
- package/dist/runtime/adapters/builtin/file-stream.js +0 -56
- package/dist/runtime/adapters/builtin/index.d.ts +0 -10
- package/dist/runtime/adapters/builtin/index.js +0 -5
- package/dist/runtime/adapters/builtin/memory-queue.d.ts +0 -52
- package/dist/runtime/adapters/builtin/memory-queue.js +0 -243
- package/dist/runtime/adapters/builtin/memory-store.d.ts +0 -69
- package/dist/runtime/adapters/builtin/memory-store.js +0 -357
- package/dist/runtime/adapters/builtin/memory-stream.d.ts +0 -21
- package/dist/runtime/adapters/builtin/memory-stream.js +0 -56
- package/dist/runtime/adapters/factory.d.ts +0 -31
- package/dist/runtime/adapters/factory.js +0 -135
- package/dist/runtime/adapters/index.d.ts +0 -8
- package/dist/runtime/adapters/index.js +0 -3
- package/dist/runtime/adapters/interfaces/index.d.ts +0 -11
- package/dist/runtime/adapters/interfaces/index.js +0 -3
- package/dist/runtime/adapters/interfaces/queue.d.ts +0 -155
- package/dist/runtime/adapters/interfaces/queue.js +0 -0
- package/dist/runtime/adapters/interfaces/store.d.ts +0 -299
- package/dist/runtime/adapters/interfaces/store.js +0 -0
- package/dist/runtime/adapters/interfaces/stream.d.ts +0 -62
- package/dist/runtime/adapters/interfaces/stream.js +0 -0
- package/dist/runtime/adapters/registry.d.ts +0 -85
- package/dist/runtime/adapters/registry.js +0 -161
- package/dist/runtime/config/index.d.ts +0 -23
- package/dist/runtime/config/index.js +0 -200
- package/dist/runtime/config/types.d.ts +0 -439
- package/dist/runtime/config/types.js +0 -0
- package/dist/runtime/events/eventBus.d.ts +0 -20
- package/dist/runtime/events/eventBus.js +0 -35
- package/dist/runtime/events/types.d.ts +0 -144
- package/dist/runtime/events/types.js +0 -0
- package/dist/runtime/events/utils/scheduleTrigger.d.ts +0 -8
- package/dist/runtime/events/utils/scheduleTrigger.js +0 -71
- package/dist/runtime/events/utils/stallDetector.d.ts +0 -83
- package/dist/runtime/events/utils/stallDetector.js +0 -318
- package/dist/runtime/events/utils/triggerRuntime.d.ts +0 -58
- package/dist/runtime/events/utils/triggerRuntime.js +0 -212
- package/dist/runtime/events/wiring/flowWiring.d.ts +0 -34
- package/dist/runtime/events/wiring/flowWiring.js +0 -1258
- package/dist/runtime/events/wiring/registry.d.ts +0 -19
- package/dist/runtime/events/wiring/registry.js +0 -43
- package/dist/runtime/events/wiring/stateWiring.d.ts +0 -37
- package/dist/runtime/events/wiring/stateWiring.js +0 -92
- package/dist/runtime/events/wiring/streamWiring.d.ts +0 -36
- package/dist/runtime/events/wiring/streamWiring.js +0 -156
- package/dist/runtime/events/wiring/triggerWiring.d.ts +0 -21
- package/dist/runtime/events/wiring/triggerWiring.js +0 -422
- package/dist/runtime/nitro/plugins/00.adapters.d.ts +0 -14
- package/dist/runtime/nitro/plugins/00.adapters.js +0 -73
- package/dist/runtime/nitro/plugins/01.ws-lifecycle.d.ts +0 -5
- package/dist/runtime/nitro/plugins/01.ws-lifecycle.js +0 -69
- package/dist/runtime/nitro/plugins/02.workers.d.ts +0 -2
- package/dist/runtime/nitro/plugins/02.workers.js +0 -92
- package/dist/runtime/nitro/plugins/03.triggers.d.ts +0 -12
- package/dist/runtime/nitro/plugins/03.triggers.js +0 -55
- package/dist/runtime/nitro/routes/webhook.await.d.ts +0 -23
- package/dist/runtime/nitro/routes/webhook.await.js +0 -112
- package/dist/runtime/nitro/routes/webhook.trigger.d.ts +0 -86
- package/dist/runtime/nitro/routes/webhook.trigger.js +0 -73
- package/dist/runtime/nitro/utils/adapters.d.ts +0 -66
- package/dist/runtime/nitro/utils/adapters.js +0 -51
- package/dist/runtime/nitro/utils/awaitPatterns/event.d.ts +0 -15
- package/dist/runtime/nitro/utils/awaitPatterns/event.js +0 -128
- package/dist/runtime/nitro/utils/awaitPatterns/index.d.ts +0 -28
- package/dist/runtime/nitro/utils/awaitPatterns/index.js +0 -55
- package/dist/runtime/nitro/utils/awaitPatterns/schedule.d.ts +0 -16
- package/dist/runtime/nitro/utils/awaitPatterns/schedule.js +0 -83
- package/dist/runtime/nitro/utils/awaitPatterns/time.d.ts +0 -15
- package/dist/runtime/nitro/utils/awaitPatterns/time.js +0 -71
- package/dist/runtime/nitro/utils/awaitPatterns/webhook.d.ts +0 -15
- package/dist/runtime/nitro/utils/awaitPatterns/webhook.js +0 -128
- package/dist/runtime/nitro/utils/defineFunctionConfig.d.ts +0 -378
- package/dist/runtime/nitro/utils/defineFunctionConfig.js +0 -3
- package/dist/runtime/nitro/utils/defineHooks.d.ts +0 -95
- package/dist/runtime/nitro/utils/defineHooks.js +0 -9
- package/dist/runtime/nitro/utils/registerAdapter.d.ts +0 -59
- package/dist/runtime/nitro/utils/registerAdapter.js +0 -13
- package/dist/runtime/nitro/utils/useAwait.d.ts +0 -83
- package/dist/runtime/nitro/utils/useAwait.js +0 -169
- package/dist/runtime/nitro/utils/useEventManager.d.ts +0 -15
- package/dist/runtime/nitro/utils/useEventManager.js +0 -26
- package/dist/runtime/nitro/utils/useFlow.d.ts +0 -66
- package/dist/runtime/nitro/utils/useFlow.js +0 -310
- package/dist/runtime/nitro/utils/useHookRegistry.d.ts +0 -40
- package/dist/runtime/nitro/utils/useHookRegistry.js +0 -25
- package/dist/runtime/nitro/utils/useNventLogger.d.ts +0 -42
- package/dist/runtime/nitro/utils/useNventLogger.js +0 -54
- package/dist/runtime/nitro/utils/useRunContext.d.ts +0 -6
- package/dist/runtime/nitro/utils/useRunContext.js +0 -102
- package/dist/runtime/nitro/utils/useStreamTopics.d.ts +0 -83
- package/dist/runtime/nitro/utils/useStreamTopics.js +0 -94
- package/dist/runtime/nitro/utils/useTrigger.d.ts +0 -150
- package/dist/runtime/nitro/utils/useTrigger.js +0 -311
- package/dist/runtime/nitro/utils/wsPeerManager.d.ts +0 -44
- package/dist/runtime/nitro/utils/wsPeerManager.js +0 -32
- package/dist/runtime/scheduler/index.d.ts +0 -33
- package/dist/runtime/scheduler/index.js +0 -42
- package/dist/runtime/scheduler/scheduler.d.ts +0 -132
- package/dist/runtime/scheduler/scheduler.js +0 -799
- package/dist/runtime/scheduler/types.d.ts +0 -122
- package/dist/runtime/scheduler/types.js +0 -0
- package/dist/runtime/worker/node/runner.d.ts +0 -95
- package/dist/runtime/worker/node/runner.js +0 -272
- package/dist/runtime/worker/python/get_config.py +0 -64
- package/dist/runtime/worker/system/awaitHandlers.d.ts +0 -27
- package/dist/runtime/worker/system/awaitHandlers.js +0 -230
- package/dist/runtime/worker/system/index.d.ts +0 -24
- package/dist/runtime/worker/system/index.js +0 -39
|
@@ -1,3 +1,378 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* defineFunction — the single primitive for declaring nvent functions.
|
|
3
|
+
*
|
|
4
|
+
* A function bundles config (name, description, triggers, enqueues, flows)
|
|
5
|
+
* and the handler in one call. The handler receives `(input, ctx)` where
|
|
6
|
+
* `ctx` is a `FunctionContext` with logger, state, enqueue, and match.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export default defineFunction({
|
|
10
|
+
* name: 'orders::process',
|
|
11
|
+
* description: 'Process a placed order',
|
|
12
|
+
* triggers: [
|
|
13
|
+
* { type: 'queue', config: { topic: 'order.placed' } },
|
|
14
|
+
* ],
|
|
15
|
+
* enqueues: ['order.processed'],
|
|
16
|
+
* flows: ['orders'],
|
|
17
|
+
* handler: async (input: { orderId: string }, ctx) => {
|
|
18
|
+
* ctx.logger.info('Processing order', { orderId: input.orderId })
|
|
19
|
+
* await ctx.enqueue({ topic: 'order.processed', data: input })
|
|
20
|
+
* return { processed: true }
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** Internal key used to propagate the stream channel through queue messages. */
|
|
26
|
+
export declare const NVENT_STREAM_KEY = "__nventStream";
|
|
27
|
+
interface ILogger {
|
|
28
|
+
info(msg: string, data?: unknown): void;
|
|
29
|
+
warn(msg: string, data?: unknown): void;
|
|
30
|
+
error(msg: string, data?: unknown): void;
|
|
31
|
+
debug(msg: string, data?: unknown): void;
|
|
32
|
+
trace(msg: string, data?: unknown): void;
|
|
33
|
+
}
|
|
34
|
+
interface IState {
|
|
35
|
+
get(key: string): Promise<unknown>;
|
|
36
|
+
set(key: string, value: unknown): Promise<{
|
|
37
|
+
new_value: unknown;
|
|
38
|
+
old_value: unknown;
|
|
39
|
+
}>;
|
|
40
|
+
delete(key: string): Promise<void>;
|
|
41
|
+
update(key: string, ops: unknown[]): Promise<{
|
|
42
|
+
new_value: unknown;
|
|
43
|
+
old_value: unknown;
|
|
44
|
+
}>;
|
|
45
|
+
list(): Promise<unknown[]>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Access to the iii Stream module.
|
|
49
|
+
* Data is organised as `stream_name > group_id > item_id`.
|
|
50
|
+
*
|
|
51
|
+
* **Implicit API** (recommended): `set(itemId, data)` automatically uses the
|
|
52
|
+
* function's flow name as the stream name and a UUID that is stable for the
|
|
53
|
+
* lifetime of the nvent call chain. The HTTP step activates it via
|
|
54
|
+
* `subscription()` and every subsequent `enqueue()` call carries the same
|
|
55
|
+
* channel info forward — no manual coordination needed.
|
|
56
|
+
*
|
|
57
|
+
* ```ts
|
|
58
|
+
* // HTTP step — activate the channel and tell the client where to subscribe:
|
|
59
|
+
* const { streamName, groupId } = ctx.stream.subscription()
|
|
60
|
+
* await ctx.enqueue({ topic: 'my.topic', data: { text } })
|
|
61
|
+
* return { status: 200, body: { streamName, groupId } }
|
|
62
|
+
*
|
|
63
|
+
* // Queue / Python step — just use set(), group ID is inherited automatically:
|
|
64
|
+
* await ctx.stream.set('step-1', { label: 'Tokenizing', step: 1 })
|
|
65
|
+
* await ctx.stream.send({ type: 'done' })
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* **Explicit API**: `setIn(name, group, itemId, data)` targets a specific
|
|
69
|
+
* stream and group (useful for cross-flow writes).
|
|
70
|
+
*/
|
|
71
|
+
interface IStream {
|
|
72
|
+
/**
|
|
73
|
+
* Set (create or update) an item in the **implicit** stream channel for this
|
|
74
|
+
* execution: `streamName = flow name`, `groupId = current trace ID`.
|
|
75
|
+
* All WebSocket clients subscribed to that channel receive the update.
|
|
76
|
+
*/
|
|
77
|
+
set(itemId: string, data: unknown): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Send a custom event to all subscribers of the implicit stream channel.
|
|
80
|
+
* Unlike `set`, events are not persisted — they are fire-and-forget.
|
|
81
|
+
*/
|
|
82
|
+
send(data: unknown): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Returns `{ streamName, groupId }` for the implicit stream channel.
|
|
85
|
+
* Return this from an HTTP handler so the client knows where to subscribe.
|
|
86
|
+
*
|
|
87
|
+
* ```ts
|
|
88
|
+
* return { status: 200, body: ctx.stream.subscription() }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
subscription(): {
|
|
92
|
+
streamName: string;
|
|
93
|
+
groupId: string;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Set (create or update) an item in an **explicit** stream group.
|
|
97
|
+
* Use when you need to target a specific stream name and group ID.
|
|
98
|
+
*/
|
|
99
|
+
setIn(name: string, group: string, itemId: string, data: unknown): Promise<void>;
|
|
100
|
+
/** Get a single item from a stream group. */
|
|
101
|
+
get<T = unknown>(name: string, group: string, itemId: string): Promise<T>;
|
|
102
|
+
/** Delete an item from a stream group. */
|
|
103
|
+
delete(name: string, group: string, itemId: string): Promise<void>;
|
|
104
|
+
/** List all items in a stream group. */
|
|
105
|
+
list<T = unknown>(name: string, group: string): Promise<T[]>;
|
|
106
|
+
/** Send a custom event to all subscribers of an explicit stream group. */
|
|
107
|
+
sendTo(name: string, group: string, data: unknown): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Execution context injected as the second argument to every `defineFunction` handler.
|
|
111
|
+
*
|
|
112
|
+
* ```ts
|
|
113
|
+
* export default defineFunction({
|
|
114
|
+
* id: 'greet',
|
|
115
|
+
* triggers: [{ type: 'http', config: { api_path: 'greet', http_method: 'POST' } }],
|
|
116
|
+
* handler: async (input, ctx) => {
|
|
117
|
+
* ctx.logger.info('greet called', input)
|
|
118
|
+
* const count = await ctx.state.get('greet', 'count')
|
|
119
|
+
* await ctx.enqueue({ topic: 'greeted', data: input })
|
|
120
|
+
* },
|
|
121
|
+
* })
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare class FunctionContext {
|
|
125
|
+
readonly logger: ILogger;
|
|
126
|
+
readonly state: IState;
|
|
127
|
+
readonly stream: IStream;
|
|
128
|
+
readonly triggerType: string;
|
|
129
|
+
private _streamName;
|
|
130
|
+
private _streamGroupId?;
|
|
131
|
+
constructor(triggerType: string, fnId: string, streamName: string, inheritedGroupId?: string);
|
|
132
|
+
/** Publishes a message to a queue topic.
|
|
133
|
+
* If a stream channel has been activated (via `ctx.stream.subscription()` or
|
|
134
|
+
* `ctx.stream.set()`), the channel info is automatically propagated to the
|
|
135
|
+
* downstream step so it can write to the same stream without extra wiring.
|
|
136
|
+
*/
|
|
137
|
+
enqueue({ topic, data }: {
|
|
138
|
+
topic: string;
|
|
139
|
+
data?: unknown;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Dispatches directly to a function via a named queue (requires the queue to be
|
|
143
|
+
* declared in `nvent.iii.queue.queueConfigs`). Unlike `enqueue()`, which publishes to
|
|
144
|
+
* a topic, this targets a specific function and routes the call through the named
|
|
145
|
+
* queue for FIFO ordering, concurrency control, or custom retry behaviour.
|
|
146
|
+
*
|
|
147
|
+
* Returns `{ messageReceiptId }` immediately — the function runs asynchronously.
|
|
148
|
+
*
|
|
149
|
+
* ```ts
|
|
150
|
+
* const { messageReceiptId } = await ctx.enqueueNamed({
|
|
151
|
+
* queue: 'orders',
|
|
152
|
+
* functionId: 'orders::process',
|
|
153
|
+
* data: { orderId: '123' },
|
|
154
|
+
* })
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
enqueueNamed({ queue, functionId, data }: {
|
|
158
|
+
queue: string;
|
|
159
|
+
functionId: string;
|
|
160
|
+
data?: unknown;
|
|
161
|
+
}): Promise<{
|
|
162
|
+
messageReceiptId: string;
|
|
163
|
+
}>;
|
|
164
|
+
/**
|
|
165
|
+
* Dispatch to a trigger-type-specific handler with correctly-typed input.
|
|
166
|
+
*
|
|
167
|
+
* ```ts
|
|
168
|
+
* handler: async (input, ctx) => ctx.match(input, {
|
|
169
|
+
* http: (req) => ({ status: 200, body: { hello: req.query_params.name } }),
|
|
170
|
+
* queue: (data) => process(data),
|
|
171
|
+
* cron: () => runSweep(),
|
|
172
|
+
* })
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
match<THandlers extends Partial<{
|
|
176
|
+
[K in keyof TriggerInputTypeMap]: (input: TriggerInputTypeMap[K]) => unknown;
|
|
177
|
+
} & {
|
|
178
|
+
default: (input: unknown) => unknown;
|
|
179
|
+
}>>(input: unknown, handlers: THandlers): unknown;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Input shape for http-triggered functions (Node.js).
|
|
183
|
+
* The engine uses snake_case for path/query params.
|
|
184
|
+
*/
|
|
185
|
+
export interface HttpRequest {
|
|
186
|
+
/** Parsed request body, or null for GET/HEAD */
|
|
187
|
+
body: unknown | null;
|
|
188
|
+
headers: Record<string, string>;
|
|
189
|
+
method: string;
|
|
190
|
+
/** Route path as registered (e.g. 'greet') */
|
|
191
|
+
path: string;
|
|
192
|
+
/** Path parameters extracted from the route template */
|
|
193
|
+
path_params: Record<string, string>;
|
|
194
|
+
/** Query string parameters */
|
|
195
|
+
query_params: Record<string, string>;
|
|
196
|
+
trigger: {
|
|
197
|
+
type: 'http';
|
|
198
|
+
method: string;
|
|
199
|
+
path: string;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Maps each trigger type to the input shape delivered by the engine.
|
|
204
|
+
* Used to type `ctx.match()` branches and to automatically infer the handler
|
|
205
|
+
* input type when all triggers share the same type.
|
|
206
|
+
*/
|
|
207
|
+
export type TriggerInputTypeMap = {
|
|
208
|
+
http: HttpRequest;
|
|
209
|
+
cron: undefined;
|
|
210
|
+
queue: unknown;
|
|
211
|
+
state: unknown;
|
|
212
|
+
stream: unknown;
|
|
213
|
+
'stream:join': unknown;
|
|
214
|
+
'stream:leave': unknown;
|
|
215
|
+
subscribe: unknown;
|
|
216
|
+
log: unknown;
|
|
217
|
+
};
|
|
218
|
+
export type FunctionHandler<TInput = unknown, TOutput = unknown> = (input: TInput, ctx: FunctionContext) => TOutput | Promise<TOutput>;
|
|
219
|
+
export interface HttpTriggerConfig {
|
|
220
|
+
type: 'http';
|
|
221
|
+
/** @internal injected at registration time */
|
|
222
|
+
function_id?: string;
|
|
223
|
+
config: {
|
|
224
|
+
/** URL path exposed by the engine (e.g. 'greet' or '/orders/:id') */
|
|
225
|
+
api_path: string;
|
|
226
|
+
/** HTTP method. Default: 'GET' */
|
|
227
|
+
http_method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
228
|
+
/** Loose input schema hint — maps field names to type strings */
|
|
229
|
+
input?: Record<string, string>;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export interface CronTriggerConfig {
|
|
233
|
+
type: 'cron';
|
|
234
|
+
/** @internal injected at registration time */
|
|
235
|
+
function_id?: string;
|
|
236
|
+
config: {
|
|
237
|
+
/** Cron expression (e.g. '0 9 * * *' for 9 AM daily) */
|
|
238
|
+
expression: string;
|
|
239
|
+
/** Timezone for cron evaluation. Default: UTC */
|
|
240
|
+
timezone?: string;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
export interface QueueTriggerConfig {
|
|
244
|
+
type: 'queue';
|
|
245
|
+
/** @internal injected at registration time */
|
|
246
|
+
function_id?: string;
|
|
247
|
+
config: {
|
|
248
|
+
/** Topic/queue name to consume from */
|
|
249
|
+
topic: string;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
export interface StateTriggerConfig {
|
|
253
|
+
type: 'state';
|
|
254
|
+
/** @internal injected at registration time */
|
|
255
|
+
function_id?: string;
|
|
256
|
+
config?: {
|
|
257
|
+
/** State key to watch */
|
|
258
|
+
key?: string;
|
|
259
|
+
/** State change event to react to */
|
|
260
|
+
event?: 'set' | 'delete' | 'change';
|
|
261
|
+
[key: string]: unknown;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
export interface StreamTriggerConfig {
|
|
265
|
+
type: 'stream';
|
|
266
|
+
/** @internal injected at registration time */
|
|
267
|
+
function_id?: string;
|
|
268
|
+
config: {
|
|
269
|
+
/** Stream ID to subscribe to */
|
|
270
|
+
id: string;
|
|
271
|
+
/** Optional filter criteria applied server-side */
|
|
272
|
+
filter?: Record<string, unknown>;
|
|
273
|
+
[key: string]: unknown;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
export interface StreamJoinTriggerConfig {
|
|
277
|
+
type: 'stream:join';
|
|
278
|
+
/** @internal injected at registration time */
|
|
279
|
+
function_id?: string;
|
|
280
|
+
config: {
|
|
281
|
+
/** Stream ID */
|
|
282
|
+
id: string;
|
|
283
|
+
[key: string]: unknown;
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
export interface StreamLeaveTriggerConfig {
|
|
287
|
+
type: 'stream:leave';
|
|
288
|
+
/** @internal injected at registration time */
|
|
289
|
+
function_id?: string;
|
|
290
|
+
config: {
|
|
291
|
+
/** Stream ID */
|
|
292
|
+
id: string;
|
|
293
|
+
[key: string]: unknown;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
export interface SubscribeTriggerConfig {
|
|
297
|
+
type: 'subscribe';
|
|
298
|
+
/** @internal injected at registration time */
|
|
299
|
+
function_id?: string;
|
|
300
|
+
config?: {
|
|
301
|
+
/** Topic to subscribe to */
|
|
302
|
+
topic?: string;
|
|
303
|
+
[key: string]: unknown;
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
export interface LogTriggerConfig {
|
|
307
|
+
type: 'log';
|
|
308
|
+
/** @internal injected at registration time */
|
|
309
|
+
function_id?: string;
|
|
310
|
+
config?: Record<string, unknown>;
|
|
311
|
+
}
|
|
312
|
+
export type TriggerConfig = HttpTriggerConfig | CronTriggerConfig | QueueTriggerConfig | StateTriggerConfig | StreamTriggerConfig | StreamJoinTriggerConfig | StreamLeaveTriggerConfig | SubscribeTriggerConfig | LogTriggerConfig;
|
|
313
|
+
export interface FunctionDef<TInput = unknown, TOutput = unknown> {
|
|
314
|
+
/** Step name. Auto-derived from file path if omitted. Equivalent to Motia's `name` field. */
|
|
315
|
+
name?: string;
|
|
316
|
+
description?: string;
|
|
317
|
+
triggers?: TriggerConfig[];
|
|
318
|
+
/**
|
|
319
|
+
* Topics this function can publish to via `ctx.enqueue()`.
|
|
320
|
+
* Used by the nvent console to build flow graphs.
|
|
321
|
+
*/
|
|
322
|
+
enqueues?: string[];
|
|
323
|
+
/**
|
|
324
|
+
* Flow groups this function belongs to.
|
|
325
|
+
* Functions in the same flow are visualized together in the nvent console.
|
|
326
|
+
*/
|
|
327
|
+
flows?: string[];
|
|
328
|
+
/**
|
|
329
|
+
* The stream name used by `ctx.stream.set()` and `ctx.stream.send()` (the
|
|
330
|
+
* implicit stream channel). Defaults to `flows[0]`, or the function ID
|
|
331
|
+
* prefix before `::` if no flows are declared.
|
|
332
|
+
*
|
|
333
|
+
* All steps that share this name and run in the same trace will write to
|
|
334
|
+
* the same WebSocket channel — no manual groupId coordination needed.
|
|
335
|
+
*/
|
|
336
|
+
stream?: string;
|
|
337
|
+
/** The function's business logic. Receives (input, ctx). */
|
|
338
|
+
handler: FunctionHandler<TInput, TOutput>;
|
|
339
|
+
/** @internal — runtime marker so the registry can detect defineFunction() exports */
|
|
340
|
+
readonly __nventStep: true;
|
|
341
|
+
}
|
|
342
|
+
/** @internal Infers the handler input type from the declared trigger configs. */
|
|
343
|
+
type InferHandlerInput<TTriggers extends TriggerConfig[]> = [
|
|
344
|
+
TTriggers[number]['type']
|
|
345
|
+
] extends ['http'] ? HttpRequest : unknown;
|
|
346
|
+
/**
|
|
347
|
+
* Defines a nvent function: config + handler in one call.
|
|
348
|
+
*
|
|
349
|
+
* The handler input type is inferred automatically from the trigger types:
|
|
350
|
+
* - http-only triggers → `input` is typed as `HttpRequest`
|
|
351
|
+
* - all other triggers → `input` defaults to `unknown` (annotate explicitly)
|
|
352
|
+
*
|
|
353
|
+
* ```ts
|
|
354
|
+
* // HTTP trigger — input inferred as HttpRequest
|
|
355
|
+
* export default defineFunction({
|
|
356
|
+
* triggers: [{ type: 'http', config: { api_path: 'greet' } }],
|
|
357
|
+
* handler: async (req, ctx) => {
|
|
358
|
+
* return { body: { hello: req.query_params.name } }
|
|
359
|
+
* },
|
|
360
|
+
* })
|
|
361
|
+
*
|
|
362
|
+
* // Queue trigger — annotate input type explicitly
|
|
363
|
+
* export default defineFunction({
|
|
364
|
+
* triggers: [{ type: 'queue', config: { topic: 'order.placed' } }],
|
|
365
|
+
* handler: async (input: { orderId: string }, ctx) => { ... },
|
|
366
|
+
* })
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
export declare function defineFunction<TTriggers extends TriggerConfig[], TInput = InferHandlerInput<TTriggers>, TOutput = unknown>(config: {
|
|
370
|
+
name?: string;
|
|
371
|
+
description?: string;
|
|
372
|
+
triggers?: TTriggers;
|
|
373
|
+
enqueues?: string[];
|
|
374
|
+
flows?: string[];
|
|
375
|
+
stream?: string;
|
|
376
|
+
handler: FunctionHandler<TInput, TOutput>;
|
|
377
|
+
}): FunctionDef<TInput, TOutput>;
|
|
378
|
+
export {};
|
|
@@ -1,4 +1,224 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
export
|
|
1
|
+
import { useNitroApp } from "#imports";
|
|
2
|
+
import { Logger } from "iii-sdk";
|
|
3
|
+
import { SpanStatusCode, withSpan } from "iii-sdk/telemetry";
|
|
4
|
+
export const NVENT_STREAM_KEY = "__nventStream";
|
|
5
|
+
export class FunctionContext {
|
|
6
|
+
logger;
|
|
7
|
+
state;
|
|
8
|
+
stream;
|
|
9
|
+
triggerType;
|
|
10
|
+
_streamName;
|
|
11
|
+
_streamGroupId;
|
|
12
|
+
constructor(triggerType, fnId, streamName, inheritedGroupId) {
|
|
13
|
+
this.triggerType = triggerType;
|
|
14
|
+
this._streamName = streamName;
|
|
15
|
+
this._streamGroupId = inheritedGroupId;
|
|
16
|
+
this.logger = new Logger(fnId, "nvent");
|
|
17
|
+
this.state = {
|
|
18
|
+
get: (key) => withSpan("state::get", {}, async (span) => {
|
|
19
|
+
span.setAttribute("nvent.state.scope", fnId);
|
|
20
|
+
span.setAttribute("nvent.state.key", key);
|
|
21
|
+
try {
|
|
22
|
+
return await _iii().trigger({ function_id: "state::get", payload: { scope: fnId, key } });
|
|
23
|
+
} catch (err) {
|
|
24
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
25
|
+
span.recordException(err);
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}),
|
|
29
|
+
set: (key, value) => withSpan("state::set", {}, async (span) => {
|
|
30
|
+
span.setAttribute("nvent.state.scope", fnId);
|
|
31
|
+
span.setAttribute("nvent.state.key", key);
|
|
32
|
+
try {
|
|
33
|
+
return await _iii().trigger({ function_id: "state::set", payload: { scope: fnId, key, value } });
|
|
34
|
+
} catch (err) {
|
|
35
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
36
|
+
span.recordException(err);
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
}),
|
|
40
|
+
delete: (key) => withSpan("state::delete", {}, async (span) => {
|
|
41
|
+
span.setAttribute("nvent.state.scope", fnId);
|
|
42
|
+
span.setAttribute("nvent.state.key", key);
|
|
43
|
+
try {
|
|
44
|
+
await _iii().trigger({ function_id: "state::delete", payload: { scope: fnId, key } });
|
|
45
|
+
} catch (err) {
|
|
46
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
47
|
+
span.recordException(err);
|
|
48
|
+
throw err;
|
|
49
|
+
}
|
|
50
|
+
}),
|
|
51
|
+
update: (key, ops) => withSpan("state::update", {}, async (span) => {
|
|
52
|
+
span.setAttribute("nvent.state.scope", fnId);
|
|
53
|
+
span.setAttribute("nvent.state.key", key);
|
|
54
|
+
try {
|
|
55
|
+
return await _iii().trigger({ function_id: "state::update", payload: { scope: fnId, key, ops } });
|
|
56
|
+
} catch (err) {
|
|
57
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
58
|
+
span.recordException(err);
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
}),
|
|
62
|
+
list: () => withSpan("state::list", {}, async (span) => {
|
|
63
|
+
span.setAttribute("nvent.state.scope", fnId);
|
|
64
|
+
try {
|
|
65
|
+
return await _iii().trigger({ function_id: "state::list", payload: { scope: fnId } });
|
|
66
|
+
} catch (err) {
|
|
67
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
68
|
+
span.recordException(err);
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
};
|
|
73
|
+
this.stream = {
|
|
74
|
+
subscription: () => {
|
|
75
|
+
if (!this._streamGroupId) this._streamGroupId = globalThis.crypto.randomUUID();
|
|
76
|
+
return { streamName: this._streamName, groupId: this._streamGroupId };
|
|
77
|
+
},
|
|
78
|
+
set: (itemId, data) => withSpan("stream::set", {}, async (span) => {
|
|
79
|
+
if (!this._streamGroupId) this._streamGroupId = globalThis.crypto.randomUUID();
|
|
80
|
+
span.setAttribute("nvent.stream.name", this._streamName);
|
|
81
|
+
span.setAttribute("nvent.stream.group_id", this._streamGroupId);
|
|
82
|
+
span.setAttribute("nvent.stream.item_id", itemId);
|
|
83
|
+
try {
|
|
84
|
+
await _iii().trigger({ function_id: "stream::set", payload: { stream_name: this._streamName, group_id: this._streamGroupId, item_id: itemId, data } });
|
|
85
|
+
} catch (err) {
|
|
86
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
87
|
+
span.recordException(err);
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
}),
|
|
91
|
+
send: (data) => withSpan("stream::send", {}, async (span) => {
|
|
92
|
+
if (!this._streamGroupId) this._streamGroupId = globalThis.crypto.randomUUID();
|
|
93
|
+
span.setAttribute("nvent.stream.name", this._streamName);
|
|
94
|
+
span.setAttribute("nvent.stream.group_id", this._streamGroupId);
|
|
95
|
+
try {
|
|
96
|
+
await _iii().trigger({ function_id: "stream::send", payload: { stream_name: this._streamName, group_id: this._streamGroupId, data } });
|
|
97
|
+
} catch (err) {
|
|
98
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
99
|
+
span.recordException(err);
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
// Explicit: target any stream+group
|
|
104
|
+
setIn: (name, group, itemId, data) => withSpan("stream::set", {}, async (span) => {
|
|
105
|
+
span.setAttribute("nvent.stream.name", name);
|
|
106
|
+
span.setAttribute("nvent.stream.group_id", group);
|
|
107
|
+
span.setAttribute("nvent.stream.item_id", itemId);
|
|
108
|
+
try {
|
|
109
|
+
await _iii().trigger({ function_id: "stream::set", payload: { stream_name: name, group_id: group, item_id: itemId, data } });
|
|
110
|
+
} catch (err) {
|
|
111
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
112
|
+
span.recordException(err);
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
get: (name, group, itemId) => withSpan("stream::get", {}, async (span) => {
|
|
117
|
+
span.setAttribute("nvent.stream.name", name);
|
|
118
|
+
span.setAttribute("nvent.stream.group_id", group);
|
|
119
|
+
span.setAttribute("nvent.stream.item_id", itemId);
|
|
120
|
+
try {
|
|
121
|
+
return await _iii().trigger({ function_id: "stream::get", payload: { stream_name: name, group_id: group, item_id: itemId } });
|
|
122
|
+
} catch (err) {
|
|
123
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
124
|
+
span.recordException(err);
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
}),
|
|
128
|
+
delete: (name, group, itemId) => withSpan("stream::delete", {}, async (span) => {
|
|
129
|
+
span.setAttribute("nvent.stream.name", name);
|
|
130
|
+
span.setAttribute("nvent.stream.group_id", group);
|
|
131
|
+
span.setAttribute("nvent.stream.item_id", itemId);
|
|
132
|
+
try {
|
|
133
|
+
await _iii().trigger({ function_id: "stream::delete", payload: { stream_name: name, group_id: group, item_id: itemId } });
|
|
134
|
+
} catch (err) {
|
|
135
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
136
|
+
span.recordException(err);
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
}),
|
|
140
|
+
list: (name, group) => withSpan("stream::list", {}, async (span) => {
|
|
141
|
+
span.setAttribute("nvent.stream.name", name);
|
|
142
|
+
span.setAttribute("nvent.stream.group_id", group);
|
|
143
|
+
try {
|
|
144
|
+
return await _iii().trigger({ function_id: "stream::list", payload: { stream_name: name, group_id: group } });
|
|
145
|
+
} catch (err) {
|
|
146
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
147
|
+
span.recordException(err);
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
}),
|
|
151
|
+
sendTo: (name, group, data) => withSpan("stream::send", {}, async (span) => {
|
|
152
|
+
span.setAttribute("nvent.stream.name", name);
|
|
153
|
+
span.setAttribute("nvent.stream.group_id", group);
|
|
154
|
+
try {
|
|
155
|
+
await _iii().trigger({ function_id: "stream::send", payload: { stream_name: name, group_id: group, data } });
|
|
156
|
+
} catch (err) {
|
|
157
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
158
|
+
span.recordException(err);
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/** Publishes a message to a queue topic.
|
|
165
|
+
* If a stream channel has been activated (via `ctx.stream.subscription()` or
|
|
166
|
+
* `ctx.stream.set()`), the channel info is automatically propagated to the
|
|
167
|
+
* downstream step so it can write to the same stream without extra wiring.
|
|
168
|
+
*/
|
|
169
|
+
enqueue({ topic, data }) {
|
|
170
|
+
const injectData = this._streamGroupId != null ? { ...typeof data === "object" && data !== null ? data : { data }, [NVENT_STREAM_KEY]: { name: this._streamName, groupId: this._streamGroupId } } : data;
|
|
171
|
+
return _iii().trigger({
|
|
172
|
+
function_id: "enqueue",
|
|
173
|
+
payload: { topic, data: injectData }
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Dispatches directly to a function via a named queue (requires the queue to be
|
|
178
|
+
* declared in `nvent.iii.queue.queueConfigs`). Unlike `enqueue()`, which publishes to
|
|
179
|
+
* a topic, this targets a specific function and routes the call through the named
|
|
180
|
+
* queue for FIFO ordering, concurrency control, or custom retry behaviour.
|
|
181
|
+
*
|
|
182
|
+
* Returns `{ messageReceiptId }` immediately — the function runs asynchronously.
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* const { messageReceiptId } = await ctx.enqueueNamed({
|
|
186
|
+
* queue: 'orders',
|
|
187
|
+
* functionId: 'orders::process',
|
|
188
|
+
* data: { orderId: '123' },
|
|
189
|
+
* })
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
enqueueNamed({ queue, functionId, data }) {
|
|
193
|
+
return _iii().trigger({
|
|
194
|
+
function_id: functionId,
|
|
195
|
+
payload: data,
|
|
196
|
+
action: { type: "enqueue", queue }
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Dispatch to a trigger-type-specific handler with correctly-typed input.
|
|
201
|
+
*
|
|
202
|
+
* ```ts
|
|
203
|
+
* handler: async (input, ctx) => ctx.match(input, {
|
|
204
|
+
* http: (req) => ({ status: 200, body: { hello: req.query_params.name } }),
|
|
205
|
+
* queue: (data) => process(data),
|
|
206
|
+
* cron: () => runSweep(),
|
|
207
|
+
* })
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
match(input, handlers) {
|
|
211
|
+
const fn = handlers[this.triggerType] ?? handlers.default;
|
|
212
|
+
if (!fn) throw new Error(`[nvent] ctx.match(): no handler for trigger type '${this.triggerType}'. Available: ${Object.keys(handlers).join(", ")}`);
|
|
213
|
+
return fn(input);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function _iii() {
|
|
217
|
+
const nitroApp = useNitroApp();
|
|
218
|
+
const iii = nitroApp.$iii;
|
|
219
|
+
if (!iii) throw new Error("[nvent] iii SDK not initialized");
|
|
220
|
+
return iii;
|
|
221
|
+
}
|
|
222
|
+
export function defineFunction(config) {
|
|
223
|
+
return { ...config, __nventStep: true };
|
|
224
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iii Engine Process Manager — runtime util
|
|
3
|
+
*
|
|
4
|
+
* Manages the lifecycle of the local iii engine process.
|
|
5
|
+
* Lives in src/runtime/nitro/utils/ so it is bundled into the Nitro output
|
|
6
|
+
* and can be used from the lifecycle plugin in both dev and production.
|
|
7
|
+
*/
|
|
8
|
+
export interface EngineManagerOptions {
|
|
9
|
+
binaryPath: string;
|
|
10
|
+
configPath: string;
|
|
11
|
+
httpPort?: number;
|
|
12
|
+
wsPort?: number;
|
|
13
|
+
/** Minimum log level for engine output. Default: 'warn' */
|
|
14
|
+
logLevel?: 'none' | 'error' | 'warn' | 'info';
|
|
15
|
+
}
|
|
16
|
+
export declare class EngineManager {
|
|
17
|
+
private process;
|
|
18
|
+
private readonly opts;
|
|
19
|
+
constructor(opts: EngineManagerOptions);
|
|
20
|
+
isRunning(): boolean;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
restart(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function createEngineManager(opts: EngineManagerOptions): EngineManager;
|