@camunda8/orchestration-cluster-api 1.0.0 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # [1.1.0](https://github.com/camunda/orchestration-cluster-api-js/compare/v1.0.0...v1.1.0) (2025-11-05)
2
+
3
+ ### Features
4
+
5
+ - add CamundaSupportLogger ([2562abc](https://github.com/camunda/orchestration-cluster-api-js/commit/2562abc2849161d5a306fda19776eb30c2ab56b4))
6
+ - enrich activated jobs with resolution methods ([2bbd361](https://github.com/camunda/orchestration-cluster-api-js/commit/2bbd36142abc21b34f9b9aaa16639efa6859835c))
7
+ - log telemetry at trace level ([822bf29](https://github.com/camunda/orchestration-cluster-api-js/commit/822bf29f9ef6add9f6d5668e024f8376bf2483e8))
8
+ - propagate cancel throw to caller ([c69fc0c](https://github.com/camunda/orchestration-cluster-api-js/commit/c69fc0c52881498c32b80da310a922892d92b06f))
9
+ - use injected support logger ([b46606b](https://github.com/camunda/orchestration-cluster-api-js/commit/b46606bfd49e2dcf57e5e852a15142115188a4de))
10
+
1
11
  # 1.0.0 (2025-10-23)
2
12
 
3
13
  ### Bug Fixes
package/README.md CHANGED
@@ -1,5 +1,3 @@
1
- <!-- Greenfield public README for the Camunda 8 Orchestration Cluster TypeScript SDK -->
2
-
3
1
  # Camunda 8 Orchestration Cluster TypeScript SDK (Pre‑release)
4
2
 
5
3
  Type‑safe, promise‑based client for the Camunda 8 Orchestration Cluster REST API.
@@ -15,7 +13,7 @@ Type‑safe, promise‑based client for the Camunda 8 Orchestration Cluster REST
15
13
  - Eventual consistency helper for polling endpoints
16
14
  - Immutable, deep‑frozen configuration accessible through a factory‑created client instance
17
15
  - Automatic body-level tenantId defaulting: if a request body supports an optional tenantId and you omit it, the SDK fills it from CAMUNDA_DEFAULT_TENANT_ID (path params are never auto-filled)
18
- - Automatic transient HTTP retry (429, 503, network) with exponential backoff + full jitter (configurable via CAMUNDA*SDK_HTTP_RETRY*\*). Non-retryable 500s fail fast. Pluggable strategy surface (default uses p-retry when available, internal fallback otherwise).
16
+ - Automatic transient HTTP retry (429, 503, network) with exponential backoff + full jitter (configurable via CAMUNDA_SDK_HTTP_RETRY\*). Non-retryable 500s fail fast. Pluggable strategy surface (default uses p-retry when available, internal fallback otherwise).
19
17
 
20
18
  ## Install
21
19
 
@@ -193,7 +191,6 @@ const skip = new Set([
193
191
  'withCorrelation',
194
192
  'deployResourcesFromFiles',
195
193
  ]);
196
-
197
194
  for (const key of Object.keys(client)) {
198
195
  const val: any = (client as any)[key];
199
196
  if (typeof val === 'function' && !key.startsWith('_') && !skip.has(key)) {
@@ -205,6 +202,53 @@ for (const key of Object.keys(client)) {
205
202
  // Now every public operation is wrapped.
206
203
  ```
207
204
 
205
+ ## Support Logger (Node Only)
206
+
207
+ For diagnostics during support interactions you can enable an auxiliary file logger that captures a sanitized snapshot of environment & configuration plus selected runtime events.
208
+
209
+ Enable by setting one of:
210
+
211
+ ```bash
212
+ CAMUNDA_SUPPORT_LOG_ENABLED=true # canonical
213
+ ```
214
+
215
+ Optional override for output path (default is `./camunda-support.log` in the current working directory):
216
+
217
+ ```bash
218
+ CAMUNDA_SUPPORT_LOG_FILE_PATH=/var/log/camunda-support.log
219
+ ```
220
+
221
+ Behavior:
222
+
223
+ - File is created eagerly on first client construction (one per process; if the path exists a numeric suffix is appended to avoid clobbering).
224
+ - Initial preamble includes SDK package version, timestamp, and redacted environment snapshot.
225
+ - Secrets (client secret, passwords, mTLS private key, etc.) are automatically masked or truncated.
226
+ - Designed to be low‑impact: append‑only, newline‑delimited JSON records may be added in future releases for deeper inspection (current version writes the preamble only unless additional events are wired).
227
+
228
+ Recommended usage:
229
+
230
+ ```bash
231
+ CAMUNDA_SUPPORT_LOG_ENABLED=1 CAMUNDA_SDK_LOG_LEVEL=debug node app.js
232
+ ```
233
+
234
+ Keep the file only as long as needed for troubleshooting; it may contain sensitive non‑secret operational metadata. Do not commit it to version control.
235
+
236
+ To disable, unset the env variable or set `CAMUNDA_SUPPORT_LOG_ENABLED=false`.
237
+
238
+ Refer to `./docs/CONFIG_REFERENCE.md` for the full list of related environment variables.
239
+
240
+ ## Contributing
241
+
242
+ We welcome issues and pull requests. Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) guide before opening a PR to understand:
243
+
244
+ - Deterministic builds policy (no committed timestamps) – see CONTRIBUTING
245
+ - Commit message conventions (Conventional Commits with enforced subject length)
246
+ - Release workflow & how to dry‑run semantic‑release locally
247
+ - Testing strategy (unit vs integration)
248
+ - Performance and security considerations
249
+
250
+ If you plan to help migrate to npm Trusted Publishing (OIDC), open an issue so we can coordinate workflow permission changes (`id-token: write`) and removal of the legacy `NPM_TOKEN` secret.
251
+
208
252
  ### Custom Classification Example
209
253
 
210
254
  Retry only network errors + 429/503, plus optionally 500 on safe GET endpoints you mark:
@@ -357,12 +401,11 @@ const worker = client.createJobWorker({
357
401
  outputSchema: Output, // validates variables passed to complete(...)
358
402
  validateSchemas: true, // set false for max throughput (skip Zod)
359
403
  autoStart: true, // default true; start polling immediately
360
- jobHandler: async (job) => {
404
+ jobHandler: (job) => {
361
405
  // Access typed variables
362
406
  const vars = job.variables; // inferred from Input schema
363
407
  // Do work...
364
- await job.complete({ variables: { processed: true } });
365
- // Returning the receipt is optional; completion already acknowledges the job.
408
+ return job.complete({ variables: { processed: true } });
366
409
  },
367
410
  });
368
411
 
@@ -376,12 +419,46 @@ process.on('SIGINT', () => {
376
419
 
377
420
  Your `jobHandler` must ultimately invoke exactly one of:
378
421
 
379
- - `job.complete({ variables? })`
422
+ - `job.complete({ variables? })` OR `job.complete()`
380
423
  - `job.fail({ errorMessage, retries?, retryBackoff? })`
381
- - `job.cancelWorkflow({})` / `job.cancel({})` (alias – cancels the process instance)
382
- - `job.ignore()` (marks as done locally without reporting to broker – only use for experimental flows)
424
+ - `job.cancelWorkflow({})` (cancels the process instance)
425
+ - `job.ignore()` (marks as done locally without reporting to broker – can be used for decoupled flows)
426
+
427
+ Each action returns an opaque unique symbol receipt (`JobActionReceipt`). The handler's declared return type (`Promise<JobActionReceipt>`) is intentional:
383
428
 
384
- Each action returns an opaque unique symbol receipt (`JobActionReceipt`) primarily for internal/test assertions; you do not need to use it. If the handler returns without invoking an action the worker logs a warning and internally marks the job done (no completion sent) to prevent a leak.
429
+ Why this design:
430
+
431
+ - Enforces a single terminal code path: every successful handler path should end by returning the sentinal obtained by invoking an action.
432
+ - Enables static reasoning: TypeScript can identify if your handler has a code path that does not acknowledge the job (catch unintended behavior early).
433
+ - Makes test assertions simple: e.g. `expect(await job.complete()).toBe(JobActionReceipt)`.
434
+
435
+ Acknowledgement lifecycle:
436
+
437
+ - Calling any action (`complete`, `fail`, `cancelWorkflow`, `ignore`) sets `job.acknowledged = true` internally. This surfaces multiple job resolution code paths at runtime.
438
+ - If the handler resolves (returns the symbol manually or via an action) without any acknowledgement having occurred, the worker logs `job.handler.noAction` and locally marks the job finished WITHOUT informing the broker (avoids a leak of the in-memory slot, but the broker will eventually time out and re-dispatch the job).
439
+
440
+ Recommended usage:
441
+
442
+ - Always invoke an action; if you truly mean to skip broker acknowledgement (for example: forwarding a job to another system which will complete it) use `job.ignore()`.
443
+
444
+ Example patterns:
445
+
446
+ ```ts
447
+ // GOOD: explicit completion
448
+ return job.complete({ variables: { processed: true } });
449
+
450
+ // GOOD: No-arg completion example, sentinel stored for ultimate return
451
+ const ack = await job.complete();
452
+ // ...
453
+ return ack;
454
+
455
+ // GOOD: explicit ignore
456
+ const ack = await job.ignore();
457
+ ```
458
+
459
+ ```ts
460
+ // No-arg completion example
461
+ ```
385
462
 
386
463
  ### Concurrency & Backpressure
387
464
 
@@ -397,7 +474,26 @@ If `validateSchemas` is true:
397
474
 
398
475
  ### Graceful Shutdown
399
476
 
400
- Call `worker.stop()` (or `client.stopAllWorkers()`) to cancel ongoing polling and prevent new activations. Jobs already handed to handlers can finish their HTTP completion/failure calls.
477
+ Use `await worker.stopGracefully({ waitUpToMs?, checkIntervalMs? })` to drain without force‑cancelling the current activation request.
478
+
479
+ ```ts
480
+ // Attempt graceful drain for up to 8 seconds
481
+ const { remainingJobs, timedOut } = await worker.stopGracefully({ waitUpToMs: 8000 });
482
+ if (timedOut) {
483
+ console.warn('Graceful stop timed out; remaining jobs:', remainingJobs);
484
+ }
485
+ ```
486
+
487
+ Behavior:
488
+
489
+ - Stops scheduling new polls immediately.
490
+ - Lets any in‑flight activation finish (not cancelled proactively).
491
+ - Waits for active jobs to acknowledge (complete/fail/cancelWorkflow/ignore).
492
+ - On timeout: falls back to hard stop semantics (cancels activation) and logs `worker.gracefulStop.timeout` at debug.
493
+
494
+ For immediate termination call `worker.stop()` (or `client.stopAllWorkers()`) which cancels the in‑flight activation if present.
495
+
496
+ Activation cancellations during stop are logged at debug (`activation.cancelled`) instead of error noise.
401
497
 
402
498
  ### Multiple Workers
403
499
 
@@ -427,7 +523,6 @@ For custom strategies you can still call `client.activateJobs(...)`, manage conc
427
523
  - Never increases latency for healthy clusters (no cap until first signal).
428
524
  - Cannot create fairness across multiple _processes_; it is per client instance in a single process. Scale your worker pool with that in mind.
429
525
  - Not a replacement for server‑side quotas or external rate limiters—it's a cooperative adaptive limiter.
430
- - Exempt list is minimal by design; adding more exemptions without care can reduce effectiveness.
431
526
 
432
527
  ### Opt‑Out
433
528
 
@@ -556,9 +651,21 @@ All methods return a `CancelablePromise<T>`:
556
651
  ```ts
557
652
  const p = camunda.searchProcessInstances({ filter: { processDefinitionKey: defKey } });
558
653
  setTimeout(() => p.cancel(), 100); // best‑effort cancel
559
- await p; // rejects with CancelError if aborted
654
+ try {
655
+ await p; // resolves if not cancelled
656
+ } catch (e) {
657
+ if (isSdkError(e) && e.name === 'CancelSdkError') {
658
+ console.log('Operation cancelled');
659
+ } else throw e;
660
+ }
560
661
  ```
561
662
 
663
+ Notes:
664
+
665
+ - Rejects with `CancelSdkError`.
666
+ - Cancellation classification runs first so aborted fetches are never downgraded to generic network errors.
667
+ - Abort is immediate and idempotent; underlying fetch is signalled.
668
+
562
669
  ## Functional (fp-ts style) Surface (Opt-In Subpath)
563
670
 
564
671
  The main entry stays minimal. To opt in to a TaskEither-style facade & helper combinators import from the dedicated subpath:
@@ -783,7 +890,7 @@ May throw:
783
890
  - Non‑2xx HTTP responses
784
891
  - Validation errors (strict mode)
785
892
  - `EventualConsistencyTimeoutError`
786
- - `CancelError` on cancellation
893
+ - `CancelSdkError` on cancellation
787
894
 
788
895
  ### Typed Error Handling
789
896
 
@@ -809,6 +916,9 @@ try {
809
916
  case 'AuthSdkError':
810
917
  console.error('Auth problem', e.message, e.status);
811
918
  break;
919
+ case 'CancelSdkError':
920
+ console.error('Operation cancelled', e.operationId);
921
+ break;
812
922
  case 'NetworkSdkError':
813
923
  console.error('Network layer error', e.message);
814
924
  break;
@@ -1006,29 +1116,3 @@ const client = createCamundaClient({
1006
1116
  ## License
1007
1117
 
1008
1118
  Apache 2.0
1009
-
1010
- ## Deterministic Build Mode
1011
-
1012
- To eliminate spurious publish drift caused by timestamps and formatting churn in generated artifacts, the SDK supports a deterministic build mode gated by the environment variable `CAMUNDA_SDK_DETERMINISTIC_BUILD=1`.
1013
-
1014
- When set:
1015
-
1016
- - All generation scripts use a fixed timestamp (`1970-01-01T00:00:00.000Z`) instead of `new Date().toISOString()`.
1017
- - Build info writer and doc generators produce stable content.
1018
- - Upstream spec cloning still occurs, but we exclude auto-formatting of generated files via `.prettierignore` to avoid style oscillation.
1019
-
1020
- Release workflow strategy:
1021
-
1022
- 1. Generate job runs with `CAMUNDA_SDK_DETERMINISTIC_BUILD=1`, producing canonical artifacts. If drift is detected they are committed on a temp branch and fast‑forwarded to `main`.
1023
- 2. Publish job re-runs the deterministic build and performs `git diff --exit-code` to assert zero drift before `semantic-release`.
1024
-
1025
- Local verification:
1026
-
1027
- ```bash
1028
- CAMUNDA_SDK_DETERMINISTIC_BUILD=1 npm run build
1029
- git diff --exit-code # should be clean after baseline committed
1030
- ```
1031
-
1032
- If you see persistent diff after following the above, ensure you have not manually edited generated files and that your local commit hooks (lint-staged) respect `.prettierignore`.
1033
-
1034
- Do not hand-edit files under `src/gen/`, `branding/branding-metadata.json`, `tests-integration/methods/manifest.json`, or `docs/CONFIG_REFERENCE.md`; regenerate instead.