@nanobpm/nano-sdk 1.0.0 → 1.2.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/index.d.cts CHANGED
@@ -1,10 +1,77 @@
1
1
  import { JobActionReceiptSymbol, createCamundaClient as createCamundaClient$1 } from '@camunda8/orchestration-cluster-api';
2
2
  export * from '@camunda8/orchestration-cluster-api';
3
3
 
4
+ /** A job handed to a worker handler. */
5
+ interface EmbeddedJob {
6
+ jobKey: string;
7
+ type: string;
8
+ processInstanceKey: string;
9
+ elementId: string;
10
+ retries: number;
11
+ variables: Record<string, unknown>;
12
+ }
13
+ /** The engine bridge an embedded app supplies (implemented by the app template's
14
+ * Deno host around μ-nano.wasm). Engine-core stays clock-free; the host injects now(). */
15
+ interface EmbeddedHost {
16
+ deploy(xml: string): Promise<{
17
+ processIds: string[];
18
+ }>;
19
+ createInstance(input: {
20
+ processDefinitionId?: string;
21
+ variables?: Record<string, unknown>;
22
+ }): Promise<{
23
+ processInstanceKey: string;
24
+ }>;
25
+ activateJobs(type: string, max: number, timeoutMs: number, worker: string): Promise<EmbeddedJob[]>;
26
+ completeJob(jobKey: string, variables?: Record<string, unknown>): Promise<void>;
27
+ failJob(jobKey: string, retries: number, errorMessage?: string): Promise<void>;
28
+ instanceCompleted(key: string): boolean;
29
+ instanceVariables(key: string): Record<string, unknown>;
30
+ /** Drive timers + dispatch at wall-clock now. Returns true if anything changed. */
31
+ tick(): void;
32
+ }
33
+ /** Pull-based dispatch over an in-process host. Structurally compatible with the
34
+ * FalconTransport surface used by NanoJobWorker + the client proxy. */
35
+ declare class EmbeddedTransport {
36
+ private host;
37
+ private pollMs;
38
+ private subs;
39
+ private timer;
40
+ private closed;
41
+ constructor(host: EmbeddedHost, pollMs?: number);
42
+ createInstance(input: {
43
+ processDefinitionId?: string;
44
+ variables?: Record<string, unknown>;
45
+ awaitCompletion?: boolean;
46
+ }): Promise<{
47
+ status: number;
48
+ body: unknown;
49
+ completion?: {
50
+ processCompleted: boolean;
51
+ variables: unknown;
52
+ processInstanceKey: string;
53
+ };
54
+ }>;
55
+ subscribe(sub: {
56
+ jobType: string;
57
+ worker: string;
58
+ credits: number;
59
+ timeoutMs: number;
60
+ onJob: (j: any) => void;
61
+ }): Promise<void>;
62
+ unsubscribe(jobType: string): void;
63
+ completeJob(jobKey: string, variables?: Record<string, unknown>): void;
64
+ failJob(jobKey: string, retries?: number, errorMessage?: string): void;
65
+ throwError(jobKey: string, _errorCode: string, errorMessage?: string): void;
66
+ grantCredits(jobType: string, n: number): void;
67
+ private pump;
68
+ close(): void;
69
+ }
70
+
4
71
  interface NanoInfo {
5
72
  engine: string;
6
73
  version?: string;
7
- commandStreamPath: string;
74
+ falconPath: string;
8
75
  }
9
76
  /**
10
77
  * Probes a REST address once (cached) and returns the Nano engine info if the
@@ -29,7 +96,19 @@ interface Subscription {
29
96
  fetchVariables: string[] | null;
30
97
  onJob: (job: JobFrame) => void;
31
98
  }
32
- declare class CommandStreamTransport {
99
+ /**
100
+ * Thrown by {@link FalconTransport.createInstance} when the gateway does
101
+ * not acknowledge a create within `submitTimeoutMs`. On the Falcon protocol,
102
+ * admission backpressure is expressed by the server withholding submission
103
+ * credits (no `503`, no retry), so a create otherwise waits indefinitely for
104
+ * intake capacity. This turns that stall into a typed rejection — treat it as
105
+ * "the server is backpressured" and back off; do not tight-loop retry.
106
+ */
107
+ declare class SubmissionTimeoutError extends Error {
108
+ readonly timeoutMs: number;
109
+ constructor(timeoutMs: number);
110
+ }
111
+ declare class FalconTransport {
33
112
  private url;
34
113
  private ws;
35
114
  private open;
@@ -40,13 +119,29 @@ declare class CommandStreamTransport {
40
119
  private heartbeat;
41
120
  private connectPromise;
42
121
  private closed;
43
- constructor(restAddress: string, path: string);
122
+ private defaultSubmitTimeoutMs?;
123
+ /**
124
+ * Server-granted submission-credit window (seeded by `welcome`, topped up by
125
+ * `submissionCredits`). Mirrors the engine's intake metering so creates queue
126
+ * client-side under admission backpressure instead of flooding the gateway.
127
+ */
128
+ private credits;
129
+ private creditWaiters;
130
+ constructor(restAddress: string, path: string, defaultSubmitTimeoutMs?: number);
44
131
  private nextCorr;
45
132
  private send;
46
133
  connect(): Promise<void>;
47
134
  private reconnect;
48
135
  private handle;
49
136
  private sendSubscribe;
137
+ /**
138
+ * Take one submission credit, waiting for the gateway to replenish when the
139
+ * window is exhausted (admission backpressure — no 503, no retry). When
140
+ * `timeoutMs` elapses first, rejects with {@link SubmissionTimeoutError} and
141
+ * removes the queued waiter so no credit slot leaks.
142
+ */
143
+ private acquireCredit;
144
+ private releaseCreditWaiters;
50
145
  /** Create a process instance over the stream. */
51
146
  createInstance(input: {
52
147
  processDefinitionId?: string;
@@ -55,6 +150,13 @@ declare class CommandStreamTransport {
55
150
  awaitCompletion?: boolean;
56
151
  fetchVariables?: string[];
57
152
  requestTimeoutMs?: number;
153
+ /**
154
+ * Client-side bound (ms) on how long to wait for a submission credit before
155
+ * rejecting with {@link SubmissionTimeoutError}. Overrides the transport-wide
156
+ * default. Omit to wait indefinitely under backpressure. Never sent on the
157
+ * wire — the server is unaware of it.
158
+ */
159
+ submitTimeoutMs?: number;
58
160
  }): Promise<{
59
161
  status: number;
60
162
  body: unknown;
@@ -90,9 +192,9 @@ declare class NanoJobWorker {
90
192
  private stopped;
91
193
  readonly jobType: string;
92
194
  readonly name: string;
93
- constructor(transport: CommandStreamTransport, cfg: NanoJobWorkerConfig);
195
+ constructor(transport: FalconTransport, cfg: NanoJobWorkerConfig);
94
196
  /** Bind the transport after async Nano detection. */
95
- bindTransport(transport: CommandStreamTransport): void;
197
+ bindTransport(transport: FalconTransport): void;
96
198
  start(): Promise<void>;
97
199
  private enrich;
98
200
  private dispatch;
@@ -100,20 +202,29 @@ declare class NanoJobWorker {
100
202
  close(): void;
101
203
  }
102
204
 
103
- /** auto: upgrade only on Nano. command-stream: force. rest: never upgrade. */
104
- type NanoTransport = "auto" | "command-stream" | "rest";
205
+ /** auto: upgrade only on Nano. falcon: force. rest: never upgrade. embedded: in-process μ-nano. */
206
+ type NanoTransport = "auto" | "falcon" | "rest" | "embedded";
105
207
  type AnyOpts = Parameters<typeof createCamundaClient$1>[0] & {
106
208
  config?: Record<string, unknown> & {
107
209
  CAMUNDA_TRANSPORT?: NanoTransport;
108
210
  CAMUNDA_REST_ADDRESS?: string;
211
+ CAMUNDA_NANO_SUBMIT_TIMEOUT_MS?: string | number;
212
+ /**
213
+ * Force plain REST even when the gateway advertises Falcon. Useful for
214
+ * environments where WebSockets are blocked (corporate proxies etc.).
215
+ * Accepts any truthy string (`1`, `true`, `yes`, `on`).
216
+ */
217
+ CAMUNDA_FORCE_REST?: string | boolean | number;
109
218
  };
219
+ /** Embedded (ADR 0005) in-process engine host; required when transport is "embedded". */
220
+ embeddedHost?: EmbeddedHost;
110
221
  };
111
222
  /**
112
223
  * Drop-in replacement for the upstream createCamundaClient. Returns the upstream
113
224
  * client wrapped in a Proxy that upgrades createProcessInstance + createJobWorker
114
- * to the command stream when connected to a Nano server (overridable via the
115
- * CAMUNDA_TRANSPORT config: "auto" | "command-stream" | "rest").
225
+ * to the Falcon protocol when connected to a Nano server (overridable via the
226
+ * CAMUNDA_TRANSPORT config: "auto" | "falcon" | "rest").
116
227
  */
117
228
  declare function createCamundaClient(opts?: AnyOpts): ReturnType<typeof createCamundaClient$1>;
118
229
 
119
- export { CommandStreamTransport, type NanoInfo, NanoJobWorker, type NanoTransport, createCamundaClient, createCamundaClient as default, detectNano };
230
+ export { type EmbeddedHost, type EmbeddedJob, EmbeddedTransport, FalconTransport, type NanoInfo, NanoJobWorker, type NanoTransport, SubmissionTimeoutError, createCamundaClient, createCamundaClient as default, detectNano };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,77 @@
1
1
  import { JobActionReceiptSymbol, createCamundaClient as createCamundaClient$1 } from '@camunda8/orchestration-cluster-api';
2
2
  export * from '@camunda8/orchestration-cluster-api';
3
3
 
4
+ /** A job handed to a worker handler. */
5
+ interface EmbeddedJob {
6
+ jobKey: string;
7
+ type: string;
8
+ processInstanceKey: string;
9
+ elementId: string;
10
+ retries: number;
11
+ variables: Record<string, unknown>;
12
+ }
13
+ /** The engine bridge an embedded app supplies (implemented by the app template's
14
+ * Deno host around μ-nano.wasm). Engine-core stays clock-free; the host injects now(). */
15
+ interface EmbeddedHost {
16
+ deploy(xml: string): Promise<{
17
+ processIds: string[];
18
+ }>;
19
+ createInstance(input: {
20
+ processDefinitionId?: string;
21
+ variables?: Record<string, unknown>;
22
+ }): Promise<{
23
+ processInstanceKey: string;
24
+ }>;
25
+ activateJobs(type: string, max: number, timeoutMs: number, worker: string): Promise<EmbeddedJob[]>;
26
+ completeJob(jobKey: string, variables?: Record<string, unknown>): Promise<void>;
27
+ failJob(jobKey: string, retries: number, errorMessage?: string): Promise<void>;
28
+ instanceCompleted(key: string): boolean;
29
+ instanceVariables(key: string): Record<string, unknown>;
30
+ /** Drive timers + dispatch at wall-clock now. Returns true if anything changed. */
31
+ tick(): void;
32
+ }
33
+ /** Pull-based dispatch over an in-process host. Structurally compatible with the
34
+ * FalconTransport surface used by NanoJobWorker + the client proxy. */
35
+ declare class EmbeddedTransport {
36
+ private host;
37
+ private pollMs;
38
+ private subs;
39
+ private timer;
40
+ private closed;
41
+ constructor(host: EmbeddedHost, pollMs?: number);
42
+ createInstance(input: {
43
+ processDefinitionId?: string;
44
+ variables?: Record<string, unknown>;
45
+ awaitCompletion?: boolean;
46
+ }): Promise<{
47
+ status: number;
48
+ body: unknown;
49
+ completion?: {
50
+ processCompleted: boolean;
51
+ variables: unknown;
52
+ processInstanceKey: string;
53
+ };
54
+ }>;
55
+ subscribe(sub: {
56
+ jobType: string;
57
+ worker: string;
58
+ credits: number;
59
+ timeoutMs: number;
60
+ onJob: (j: any) => void;
61
+ }): Promise<void>;
62
+ unsubscribe(jobType: string): void;
63
+ completeJob(jobKey: string, variables?: Record<string, unknown>): void;
64
+ failJob(jobKey: string, retries?: number, errorMessage?: string): void;
65
+ throwError(jobKey: string, _errorCode: string, errorMessage?: string): void;
66
+ grantCredits(jobType: string, n: number): void;
67
+ private pump;
68
+ close(): void;
69
+ }
70
+
4
71
  interface NanoInfo {
5
72
  engine: string;
6
73
  version?: string;
7
- commandStreamPath: string;
74
+ falconPath: string;
8
75
  }
9
76
  /**
10
77
  * Probes a REST address once (cached) and returns the Nano engine info if the
@@ -29,7 +96,19 @@ interface Subscription {
29
96
  fetchVariables: string[] | null;
30
97
  onJob: (job: JobFrame) => void;
31
98
  }
32
- declare class CommandStreamTransport {
99
+ /**
100
+ * Thrown by {@link FalconTransport.createInstance} when the gateway does
101
+ * not acknowledge a create within `submitTimeoutMs`. On the Falcon protocol,
102
+ * admission backpressure is expressed by the server withholding submission
103
+ * credits (no `503`, no retry), so a create otherwise waits indefinitely for
104
+ * intake capacity. This turns that stall into a typed rejection — treat it as
105
+ * "the server is backpressured" and back off; do not tight-loop retry.
106
+ */
107
+ declare class SubmissionTimeoutError extends Error {
108
+ readonly timeoutMs: number;
109
+ constructor(timeoutMs: number);
110
+ }
111
+ declare class FalconTransport {
33
112
  private url;
34
113
  private ws;
35
114
  private open;
@@ -40,13 +119,29 @@ declare class CommandStreamTransport {
40
119
  private heartbeat;
41
120
  private connectPromise;
42
121
  private closed;
43
- constructor(restAddress: string, path: string);
122
+ private defaultSubmitTimeoutMs?;
123
+ /**
124
+ * Server-granted submission-credit window (seeded by `welcome`, topped up by
125
+ * `submissionCredits`). Mirrors the engine's intake metering so creates queue
126
+ * client-side under admission backpressure instead of flooding the gateway.
127
+ */
128
+ private credits;
129
+ private creditWaiters;
130
+ constructor(restAddress: string, path: string, defaultSubmitTimeoutMs?: number);
44
131
  private nextCorr;
45
132
  private send;
46
133
  connect(): Promise<void>;
47
134
  private reconnect;
48
135
  private handle;
49
136
  private sendSubscribe;
137
+ /**
138
+ * Take one submission credit, waiting for the gateway to replenish when the
139
+ * window is exhausted (admission backpressure — no 503, no retry). When
140
+ * `timeoutMs` elapses first, rejects with {@link SubmissionTimeoutError} and
141
+ * removes the queued waiter so no credit slot leaks.
142
+ */
143
+ private acquireCredit;
144
+ private releaseCreditWaiters;
50
145
  /** Create a process instance over the stream. */
51
146
  createInstance(input: {
52
147
  processDefinitionId?: string;
@@ -55,6 +150,13 @@ declare class CommandStreamTransport {
55
150
  awaitCompletion?: boolean;
56
151
  fetchVariables?: string[];
57
152
  requestTimeoutMs?: number;
153
+ /**
154
+ * Client-side bound (ms) on how long to wait for a submission credit before
155
+ * rejecting with {@link SubmissionTimeoutError}. Overrides the transport-wide
156
+ * default. Omit to wait indefinitely under backpressure. Never sent on the
157
+ * wire — the server is unaware of it.
158
+ */
159
+ submitTimeoutMs?: number;
58
160
  }): Promise<{
59
161
  status: number;
60
162
  body: unknown;
@@ -90,9 +192,9 @@ declare class NanoJobWorker {
90
192
  private stopped;
91
193
  readonly jobType: string;
92
194
  readonly name: string;
93
- constructor(transport: CommandStreamTransport, cfg: NanoJobWorkerConfig);
195
+ constructor(transport: FalconTransport, cfg: NanoJobWorkerConfig);
94
196
  /** Bind the transport after async Nano detection. */
95
- bindTransport(transport: CommandStreamTransport): void;
197
+ bindTransport(transport: FalconTransport): void;
96
198
  start(): Promise<void>;
97
199
  private enrich;
98
200
  private dispatch;
@@ -100,20 +202,29 @@ declare class NanoJobWorker {
100
202
  close(): void;
101
203
  }
102
204
 
103
- /** auto: upgrade only on Nano. command-stream: force. rest: never upgrade. */
104
- type NanoTransport = "auto" | "command-stream" | "rest";
205
+ /** auto: upgrade only on Nano. falcon: force. rest: never upgrade. embedded: in-process μ-nano. */
206
+ type NanoTransport = "auto" | "falcon" | "rest" | "embedded";
105
207
  type AnyOpts = Parameters<typeof createCamundaClient$1>[0] & {
106
208
  config?: Record<string, unknown> & {
107
209
  CAMUNDA_TRANSPORT?: NanoTransport;
108
210
  CAMUNDA_REST_ADDRESS?: string;
211
+ CAMUNDA_NANO_SUBMIT_TIMEOUT_MS?: string | number;
212
+ /**
213
+ * Force plain REST even when the gateway advertises Falcon. Useful for
214
+ * environments where WebSockets are blocked (corporate proxies etc.).
215
+ * Accepts any truthy string (`1`, `true`, `yes`, `on`).
216
+ */
217
+ CAMUNDA_FORCE_REST?: string | boolean | number;
109
218
  };
219
+ /** Embedded (ADR 0005) in-process engine host; required when transport is "embedded". */
220
+ embeddedHost?: EmbeddedHost;
110
221
  };
111
222
  /**
112
223
  * Drop-in replacement for the upstream createCamundaClient. Returns the upstream
113
224
  * client wrapped in a Proxy that upgrades createProcessInstance + createJobWorker
114
- * to the command stream when connected to a Nano server (overridable via the
115
- * CAMUNDA_TRANSPORT config: "auto" | "command-stream" | "rest").
225
+ * to the Falcon protocol when connected to a Nano server (overridable via the
226
+ * CAMUNDA_TRANSPORT config: "auto" | "falcon" | "rest").
116
227
  */
117
228
  declare function createCamundaClient(opts?: AnyOpts): ReturnType<typeof createCamundaClient$1>;
118
229
 
119
- export { CommandStreamTransport, type NanoInfo, NanoJobWorker, type NanoTransport, createCamundaClient, createCamundaClient as default, detectNano };
230
+ export { type EmbeddedHost, type EmbeddedJob, EmbeddedTransport, FalconTransport, type NanoInfo, NanoJobWorker, type NanoTransport, SubmissionTimeoutError, createCamundaClient, createCamundaClient as default, detectNano };