@nanobpm/urban 0.88.1 → 0.90.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/runtime/core/host.d.ts +149 -1
- package/dist/runtime/core/host.js +3 -0
- package/dist/runtime/core/modules/mcp.js +68 -0
- package/dist/runtime/engine/nanosdk.d.ts +32 -1
- package/dist/runtime/engine/nanosdk.js +210 -6
- package/dist/runtime/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/runtime/core/host.ts +155 -0
- package/src/runtime/core/modules/actions.test.ts +3 -0
- package/src/runtime/core/modules/agent.test.ts +3 -0
- package/src/runtime/core/modules/api.test.ts +3 -0
- package/src/runtime/core/modules/cancel.test.ts +3 -0
- package/src/runtime/core/modules/connectors.test.ts +3 -0
- package/src/runtime/core/modules/datasource.migrations.test.ts +3 -0
- package/src/runtime/core/modules/instance-tracking.test.ts +3 -0
- package/src/runtime/core/modules/mcp.test.ts +97 -0
- package/src/runtime/core/modules/mcp.ts +66 -0
- package/src/runtime/core/modules/pages.test.ts +3 -0
- package/src/runtime/core/modules/surfaces.test.ts +6 -0
- package/src/runtime/core/modules/triggers.test.ts +3 -0
- package/src/runtime/core/modules/workers.test.ts +3 -0
- package/src/runtime/core/runtime.extensions.test.ts +9 -0
- package/src/runtime/core/runtime.test.ts +9 -0
- package/src/runtime/engine/nanosdk.test.ts +136 -0
- package/src/runtime/engine/nanosdk.ts +239 -6
- package/src/runtime/index.ts +4 -0
|
@@ -198,6 +198,22 @@ export type UserTaskState = "CREATED" | "COMPLETED" | "CANCELED" | "FAILED";
|
|
|
198
198
|
export interface ProcessInstanceSnapshot {
|
|
199
199
|
readonly processInstanceKey: string;
|
|
200
200
|
readonly state: ProcessInstanceState;
|
|
201
|
+
/** The key of the deployed process definition this instance runs — the handle a caller feeds to
|
|
202
|
+
* {@link EngineClient.getProcessDefinitionXml} to fetch the deployed BPMN (the instance →
|
|
203
|
+
* `processDefinitionKey` → deployed XML path, no repo checkout). Absent when the engine omits it. */
|
|
204
|
+
readonly processDefinitionKey?: string;
|
|
205
|
+
/** The key of this instance's *immediate* parent process instance — the caller that instantiated
|
|
206
|
+
* it as a native child (a `<bpmn:callActivity>`). `undefined` for a top-level (root) instance,
|
|
207
|
+
* and absent when the engine omits it (same optional/engine-provided convention as
|
|
208
|
+
* `processDefinitionKey`). Lets a reduced-capability read path map a native child back to the
|
|
209
|
+
* subject that spawned it without a raw-REST channel. */
|
|
210
|
+
readonly parentProcessInstanceKey?: string;
|
|
211
|
+
/** The key of this instance's *root* process instance — the top-level ancestor of the
|
|
212
|
+
* call-activity hierarchy this instance belongs to (equal to `processInstanceKey` for a
|
|
213
|
+
* top-level instance). `undefined`/absent when the engine omits it (only present for hierarchies
|
|
214
|
+
* created on an engine version that reports it). Lets a reduced-capability read path correlate a
|
|
215
|
+
* deep native descendant straight back to its root subject. */
|
|
216
|
+
readonly rootProcessInstanceKey?: string;
|
|
201
217
|
}
|
|
202
218
|
/**
|
|
203
219
|
* A single open user task as {@link EngineClient.searchUserTasks} reports it. Carries the
|
|
@@ -215,6 +231,24 @@ export interface UserTaskSummary {
|
|
|
215
231
|
readonly formKey?: string;
|
|
216
232
|
/** An external form reference (a form linked outside the deployment), if any. */
|
|
217
233
|
readonly externalFormReference?: string;
|
|
234
|
+
/** The key of the process instance this task belongs to. Absent when the engine omits it (same
|
|
235
|
+
* optional/engine-provided convention as `processDefinitionKey`). For a task owned by a native
|
|
236
|
+
* child instance, this is the child's own key — the handle a reduced-capability read path feeds
|
|
237
|
+
* to {@link EngineClient.searchProcessInstances} to resolve the child's parent/root linkage. */
|
|
238
|
+
readonly processInstanceKey?: string;
|
|
239
|
+
/** The key of the *immediate* parent process instance of this task's owning instance — the caller
|
|
240
|
+
* that spawned it as a native child. Absent when the engine's user-task read model omits it (as
|
|
241
|
+
* it does today: the engine surfaces the parent linkage on {@link ProcessInstanceSnapshot}, so a
|
|
242
|
+
* caller resolves it via `processInstanceKey` → `searchProcessInstances`). Declared here for
|
|
243
|
+
* parity with the process-instance snapshot and to flow through automatically if the read model
|
|
244
|
+
* starts carrying it. */
|
|
245
|
+
readonly parentProcessInstanceKey?: string;
|
|
246
|
+
/** The key of the *root* process instance of this task's owning instance — the top-level ancestor
|
|
247
|
+
* of the call-activity hierarchy the task lives in. Absent when the engine omits it. Lets a
|
|
248
|
+
* reduced-capability read path (`pollUserTasks` and other reconcile/affordance surfaces)
|
|
249
|
+
* correlate a native-child (e.g. human-escalation grandchild) task straight back to its root
|
|
250
|
+
* subject through the typed seam, with no raw-REST fallback. */
|
|
251
|
+
readonly rootProcessInstanceKey?: string;
|
|
218
252
|
}
|
|
219
253
|
/**
|
|
220
254
|
* The lifecycle-state-agnostic selectors for a user-task search: which process instance,
|
|
@@ -226,6 +260,14 @@ export interface UserTaskFilter {
|
|
|
226
260
|
processInstanceKey?: string;
|
|
227
261
|
assignee?: string;
|
|
228
262
|
candidateGroup?: string;
|
|
263
|
+
/** Select only tasks whose owning instance has this *immediate* parent process instance. Honored
|
|
264
|
+
* server-side by the live gateway where the read model supports it; the in-process testkit
|
|
265
|
+
* applies it client-side against the row's parent linkage (absent today on the user-task read
|
|
266
|
+
* model, so it matches nothing until the engine surfaces it there). */
|
|
267
|
+
parentProcessInstanceKey?: string;
|
|
268
|
+
/** Select only tasks whose owning instance belongs to this *root* process-instance hierarchy — the
|
|
269
|
+
* selector a reduced-capability path uses to fetch every open task under one root subject. */
|
|
270
|
+
rootProcessInstanceKey?: string;
|
|
229
271
|
}
|
|
230
272
|
/**
|
|
231
273
|
* An element instance's lifecycle state, as the engine reports it on a
|
|
@@ -425,6 +467,72 @@ export interface FormSchema {
|
|
|
425
467
|
readonly version?: number;
|
|
426
468
|
readonly schema: Record<string, unknown>;
|
|
427
469
|
}
|
|
470
|
+
/**
|
|
471
|
+
* Selectors for a variable search: which process instance and/or scope to match, optionally
|
|
472
|
+
* narrowed to a single variable `name`. Used by {@link EngineClient.searchVariables}. An
|
|
473
|
+
* eventually consistent (zero-wait) read; an unset selector matches every variable in scope.
|
|
474
|
+
*/
|
|
475
|
+
export interface VariableFilter {
|
|
476
|
+
processInstanceKey?: string;
|
|
477
|
+
scopeKey?: string;
|
|
478
|
+
name?: string;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* A single process variable as {@link EngineClient.searchVariables} reports it — the read
|
|
482
|
+
* counterpart to the write-only {@link EngineClient.setVariables}. Mirrors the engine's v2
|
|
483
|
+
* `/variables/search` row: the variable's own `variableKey`, its `name`, its serialized JSON
|
|
484
|
+
* `value` (a string — an object/array value arrives JSON-encoded, so a caller `JSON.parse`s it),
|
|
485
|
+
* the `scopeKey` it is directly defined in (a process-instance key for a process-level variable,
|
|
486
|
+
* an element-instance key for a local one) and the owning `processInstanceKey`. `isTruncated` is
|
|
487
|
+
* `true` when the engine clipped a large `value` for the read model — the caller then knows the
|
|
488
|
+
* `value` is a preview, not the whole payload. This is the only way to read a parked token's
|
|
489
|
+
* business payload (`prKey`, `round`, an escalation `question`/`answer`, `resolution`,
|
|
490
|
+
* `directive`); the ADR 0065 projections carry lifecycle/position, not the payload.
|
|
491
|
+
*/
|
|
492
|
+
export interface VariableSummary {
|
|
493
|
+
readonly variableKey: string;
|
|
494
|
+
readonly name: string;
|
|
495
|
+
readonly value: string;
|
|
496
|
+
readonly scopeKey: string;
|
|
497
|
+
readonly processInstanceKey: string;
|
|
498
|
+
readonly isTruncated: boolean;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Selectors for a job search: which process instance, lifecycle `state`, job `type`, `elementId`,
|
|
502
|
+
* and/or leasing `worker` to match. Used by {@link EngineClient.searchJobs}. `state` is kept a
|
|
503
|
+
* transport-agnostic bare string (the engine's job-state enum is broad and forward-looking — e.g.
|
|
504
|
+
* `CREATED`/`COMPLETED`/`FAILED`/`TIMED_OUT`), so a new engine state flows through without having
|
|
505
|
+
* to be enumerated here. An eventually consistent (zero-wait) read; an unset selector matches
|
|
506
|
+
* every job.
|
|
507
|
+
*/
|
|
508
|
+
export interface JobFilter {
|
|
509
|
+
processInstanceKey?: string;
|
|
510
|
+
state?: string;
|
|
511
|
+
type?: string;
|
|
512
|
+
elementId?: string;
|
|
513
|
+
worker?: string;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* A single job as {@link EngineClient.searchJobs} reports it — mirrors the engine's v2
|
|
517
|
+
* `/jobs/search` row. Carries the `jobKey` a caller passes to
|
|
518
|
+
* {@link EngineClient.updateJobRetries} (the only source of a `jobKey` for a job NOT already
|
|
519
|
+
* behind a `jobNoRetries` incident, which {@link searchIncidents} surfaces), the job `type` and
|
|
520
|
+
* lifecycle `state` (a bare string — see {@link JobFilter}), the owning `processInstanceKey`, and
|
|
521
|
+
* the best-effort diagnostics `worker`/`retries`/`elementId`/`deadline`. The `worker` field is the
|
|
522
|
+
* "is it actually stuck" signal: a `CREATED` job WITH a `worker` set has been leased by an agent,
|
|
523
|
+
* while one with NONE set is merely queued — so `worker` is omitted (absent) when unset. `retries`,
|
|
524
|
+
* `elementId`, and `deadline` are likewise present when the engine reports them, omitted otherwise.
|
|
525
|
+
*/
|
|
526
|
+
export interface JobSummary {
|
|
527
|
+
readonly jobKey: string;
|
|
528
|
+
readonly type: string;
|
|
529
|
+
readonly state: string;
|
|
530
|
+
readonly processInstanceKey: string;
|
|
531
|
+
readonly worker?: string;
|
|
532
|
+
readonly retries?: number;
|
|
533
|
+
readonly elementId?: string;
|
|
534
|
+
readonly deadline?: string;
|
|
535
|
+
}
|
|
428
536
|
/**
|
|
429
537
|
* EngineClient is the seam onto a Nano engine. The SDK/REST-backed adapter implements
|
|
430
538
|
* it against a live engine; tests implement it in-memory. Core modules depend only on this.
|
|
@@ -512,6 +620,12 @@ export interface EngineClient {
|
|
|
512
620
|
searchProcessInstances(filter?: {
|
|
513
621
|
processInstanceKeys?: string[];
|
|
514
622
|
state?: ProcessInstanceState;
|
|
623
|
+
/** Select only instances whose *immediate* parent is this process instance — the reduced-path
|
|
624
|
+
* query for "the native children spawned by this subject". */
|
|
625
|
+
parentProcessInstanceKey?: string;
|
|
626
|
+
/** Select only instances belonging to this *root* process-instance hierarchy — "every instance
|
|
627
|
+
* under this root subject", the deep-descendant correlation query. */
|
|
628
|
+
rootProcessInstanceKey?: string;
|
|
515
629
|
}): Promise<ProcessInstanceSnapshot[]>;
|
|
516
630
|
/**
|
|
517
631
|
* Search element instances ("tokens") by process instance, element, and/or lifecycle state
|
|
@@ -560,6 +674,40 @@ export interface EngineClient {
|
|
|
560
674
|
* they answer "how far has this instance progressed", this answers "why is it stuck".
|
|
561
675
|
*/
|
|
562
676
|
searchIncidents(filter?: IncidentFilter): Promise<IncidentSummary[]>;
|
|
677
|
+
/**
|
|
678
|
+
* Search process variables by owning process instance and/or scope, optionally narrowed to a
|
|
679
|
+
* single `name` (`POST /v2/variables/search`). The read counterpart to the write-only
|
|
680
|
+
* {@link setVariables}: it is the only way to see a parked token's business payload (`prKey`,
|
|
681
|
+
* `round`, an escalation `question`/`answer`, `resolution`, `directive`) — the ADR 0065
|
|
682
|
+
* projections carry lifecycle/position, not the payload. An eventually consistent (zero-wait)
|
|
683
|
+
* read; each {@link VariableSummary} carries the variable's serialized JSON `value` (a string)
|
|
684
|
+
* and an `isTruncated` flag set when the engine clipped a large value for the read model.
|
|
685
|
+
*/
|
|
686
|
+
searchVariables(filter?: VariableFilter): Promise<VariableSummary[]>;
|
|
687
|
+
/**
|
|
688
|
+
* Search jobs by owning process instance, lifecycle `state`, job `type`, `elementId`, and/or
|
|
689
|
+
* leasing `worker` (`POST /v2/jobs/search`). This is the "is it actually stuck" read: a
|
|
690
|
+
* `CREATED` job WITH a `worker` set has been leased by an agent, while one with NONE set is
|
|
691
|
+
* merely queued. It is also the on-tool source of a `jobKey` for {@link updateJobRetries} when
|
|
692
|
+
* the job is NOT behind an incident — {@link searchIncidents} only surfaces a `jobKey` for a
|
|
693
|
+
* job that already faulted (a `jobNoRetries` incident), so retrying an un-incidented job would
|
|
694
|
+
* otherwise be impossible without a direct engine-API call. An eventually consistent (zero-wait)
|
|
695
|
+
* read; each {@link JobSummary} carries the `jobKey` plus best-effort `worker`/`retries`/
|
|
696
|
+
* `elementId`/`deadline` diagnostics.
|
|
697
|
+
*/
|
|
698
|
+
searchJobs(filter?: JobFilter): Promise<JobSummary[]>;
|
|
699
|
+
/**
|
|
700
|
+
* Fetch the deployed BPMN XML of a process definition by its `processDefinitionKey`
|
|
701
|
+
* (`GET /v2/process-definitions/{processDefinitionKey}/xml`), or `null` when the key is blank,
|
|
702
|
+
* unknown (a 404), or the definition carries no XML. This is the *deployed* model — the routing
|
|
703
|
+
* source of truth, including its FEEL gateway conditions — so an agent can reason about WHY an
|
|
704
|
+
* instance routed where it did without checking out `resources/processes/*.bpmn` from the app
|
|
705
|
+
* repo. An instance already carries its `processDefinitionKey` (via {@link searchProcessInstances}),
|
|
706
|
+
* so the path is instance → `processDefinitionKey` → deployed XML. A read is treated as absence
|
|
707
|
+
* (`null`) rather than propagating (mirroring {@link getForm}/{@link getElementInstance}), so a
|
|
708
|
+
* caller distinguishes "have it" from "don't" without a try/catch. A zero-wait read.
|
|
709
|
+
*/
|
|
710
|
+
getProcessDefinitionXml(processDefinitionKey: string): Promise<string | null>;
|
|
563
711
|
/**
|
|
564
712
|
* Resolve an open incident by key (`POST /v2/incidents/{incidentKey}/resolution`), unblocking
|
|
565
713
|
* the parked token: a job incident returns the job to the activatable pool (so it must have
|
|
@@ -614,4 +762,4 @@ export interface EngineClient {
|
|
|
614
762
|
* and `getForm` before it) that a purely structural `implements EngineClient` check no
|
|
615
763
|
* longer catches once the fake is published/compiled against an older `@nanobpm/urban`.
|
|
616
764
|
*/
|
|
617
|
-
export declare const ENGINE_CLIENT_METHODS: readonly ["deployResources", "createInstance", "cancelInstance", "publishMessage", "searchUserTasks", "openUserTasks", "getForm", "completeUserTask", "searchProcessInstances", "searchElementInstances", "searchElementInstanceWaitStates", "getElementInstance", "searchIncidents", "resolveIncident", "updateJobRetries", "setVariables", "registerWorker", "close"];
|
|
765
|
+
export declare const ENGINE_CLIENT_METHODS: readonly ["deployResources", "createInstance", "cancelInstance", "publishMessage", "searchUserTasks", "openUserTasks", "getForm", "completeUserTask", "searchProcessInstances", "searchElementInstances", "searchElementInstanceWaitStates", "getElementInstance", "searchIncidents", "searchVariables", "searchJobs", "getProcessDefinitionXml", "resolveIncident", "updateJobRetries", "setVariables", "registerWorker", "close"];
|
|
@@ -118,6 +118,9 @@ export const ENGINE_CLIENT_METHODS = [
|
|
|
118
118
|
"searchElementInstanceWaitStates",
|
|
119
119
|
"getElementInstance",
|
|
120
120
|
"searchIncidents",
|
|
121
|
+
"searchVariables",
|
|
122
|
+
"searchJobs",
|
|
123
|
+
"getProcessDefinitionXml",
|
|
121
124
|
"resolveIncident",
|
|
122
125
|
"updateJobRetries",
|
|
123
126
|
"setVariables",
|
|
@@ -536,6 +536,74 @@ function buildDebugTools(app) {
|
|
|
536
536
|
return app.engine.searchIncidents(filter);
|
|
537
537
|
},
|
|
538
538
|
},
|
|
539
|
+
{
|
|
540
|
+
name: `${DEBUG_PREFIX}search_variables`,
|
|
541
|
+
description: "Engine truth: search process variables by process instance and/or scope, optionally by name — the read counterpart to set_variables. Reads only, eventually consistent. This is the only way to see a parked token's business payload (prKey, round, an escalation question/answer, resolution, directive); the projections carry lifecycle/position, not the payload. Each result carries the variableKey/name/serialized-JSON value/scopeKey/processInstanceKey/isTruncated.",
|
|
542
|
+
inputSchema: {
|
|
543
|
+
type: "object",
|
|
544
|
+
properties: {
|
|
545
|
+
processInstanceKey: OPTIONAL_STRING,
|
|
546
|
+
scopeKey: OPTIONAL_STRING,
|
|
547
|
+
name: OPTIONAL_STRING,
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
run: (args) => {
|
|
551
|
+
const filter = {};
|
|
552
|
+
const pik = readPresentString(args, "processInstanceKey");
|
|
553
|
+
if (pik)
|
|
554
|
+
filter.processInstanceKey = pik;
|
|
555
|
+
const scopeKey = readPresentString(args, "scopeKey");
|
|
556
|
+
if (scopeKey)
|
|
557
|
+
filter.scopeKey = scopeKey;
|
|
558
|
+
const name = readPresentString(args, "name");
|
|
559
|
+
if (name)
|
|
560
|
+
filter.name = name;
|
|
561
|
+
return app.engine.searchVariables(filter);
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
name: `${DEBUG_PREFIX}search_jobs`,
|
|
566
|
+
description: "Engine truth: search jobs by process instance, state, and/or type/elementId/worker. Reads only, eventually consistent. The 'is it actually stuck?' test: a CREATED job WITH a worker set has been leased by an agent, one with NONE set is merely queued. This is also the on-tool source of a jobKey for retry_job (the only other source is a jobNoRetries incident via search_incidents). Each result carries jobKey/type/state/processInstanceKey and the best-effort worker/retries/elementId/deadline.",
|
|
567
|
+
inputSchema: {
|
|
568
|
+
type: "object",
|
|
569
|
+
properties: {
|
|
570
|
+
processInstanceKey: OPTIONAL_STRING,
|
|
571
|
+
state: OPTIONAL_STRING,
|
|
572
|
+
type: OPTIONAL_STRING,
|
|
573
|
+
elementId: OPTIONAL_STRING,
|
|
574
|
+
worker: OPTIONAL_STRING,
|
|
575
|
+
},
|
|
576
|
+
},
|
|
577
|
+
run: (args) => {
|
|
578
|
+
const filter = {};
|
|
579
|
+
const pik = readPresentString(args, "processInstanceKey");
|
|
580
|
+
if (pik)
|
|
581
|
+
filter.processInstanceKey = pik;
|
|
582
|
+
const state = readPresentString(args, "state");
|
|
583
|
+
if (state)
|
|
584
|
+
filter.state = state;
|
|
585
|
+
const type = readPresentString(args, "type");
|
|
586
|
+
if (type)
|
|
587
|
+
filter.type = type;
|
|
588
|
+
const elementId = readPresentString(args, "elementId");
|
|
589
|
+
if (elementId)
|
|
590
|
+
filter.elementId = elementId;
|
|
591
|
+
const worker = readPresentString(args, "worker");
|
|
592
|
+
if (worker)
|
|
593
|
+
filter.worker = worker;
|
|
594
|
+
return app.engine.searchJobs(filter);
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
name: `${DEBUG_PREFIX}get_process_definition_xml`,
|
|
599
|
+
description: "Engine truth: return the deployed BPMN XML of a process definition by key (the routing source of truth, with its FEEL gateway conditions) — reason about WHY an instance routed where it did without a repo checkout. Reads only; null when the key is unknown. An instance carries its processDefinitionKey via search_process_instances, so the path is instance → processDefinitionKey → deployed XML; pair with get_element_instance to locate the parked element.",
|
|
600
|
+
inputSchema: {
|
|
601
|
+
type: "object",
|
|
602
|
+
properties: { processDefinitionKey: OPTIONAL_STRING },
|
|
603
|
+
required: ["processDefinitionKey"],
|
|
604
|
+
},
|
|
605
|
+
run: (args) => app.engine.getProcessDefinitionXml(requireString(args, "processDefinitionKey")),
|
|
606
|
+
},
|
|
539
607
|
{
|
|
540
608
|
name: `${DEBUG_PREFIX}cancel_instance`,
|
|
541
609
|
description: "MUTATING: cancel a running process instance. Requires the shared-secret guard.",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EngineClient, ElementInstanceState, ElementInstanceSummary, ElementInstanceFilter, ElementInstanceWaitState, ElementInstanceWaitStateFilter, WaitStateType, FormSchema, IncidentFilter, IncidentState, IncidentSummary, JobHandler, ProcessInstanceSnapshot, ProcessInstanceState, UserTaskState, UserTaskSummary, UserTaskFilter, WorkerSubscription } from "../core/host.ts";
|
|
1
|
+
import type { EngineClient, ElementInstanceState, ElementInstanceSummary, ElementInstanceFilter, ElementInstanceWaitState, ElementInstanceWaitStateFilter, WaitStateType, FormSchema, IncidentFilter, IncidentState, IncidentSummary, JobFilter, JobHandler, JobSummary, ProcessInstanceSnapshot, ProcessInstanceState, UserTaskState, UserTaskSummary, UserTaskFilter, VariableFilter, VariableSummary, WorkerSubscription } from "../core/host.ts";
|
|
2
2
|
import type { EngineSdkClient } from "./sdk.ts";
|
|
3
3
|
/** Coerce an engine response's process-instance key to a non-empty string, or
|
|
4
4
|
* throw — a missing key means a malformed/partial response, not a real instance. */
|
|
@@ -40,6 +40,21 @@ export declare function mapElementInstanceWaitStateRow(row: Record<string, unkno
|
|
|
40
40
|
* `errorMessage` are best-effort diagnostics: present when the engine reports them, omitted
|
|
41
41
|
* otherwise. The single source of truth `searchIncidents` extracts through. */
|
|
42
42
|
export declare function mapIncidentRow(row: Record<string, unknown>, log: Log): IncidentSummary | undefined;
|
|
43
|
+
/** Map one engine variable row onto a {@link VariableSummary}, or `undefined` when the row is
|
|
44
|
+
* malformed (missing the `variableKey`, owning `processInstanceKey`, or `name` — the identity a
|
|
45
|
+
* caller needs). `value` is the engine's serialized JSON value (a string); a non-string value is
|
|
46
|
+
* JSON-encoded so the field is always a string a caller can `JSON.parse`. `scopeKey` falls back to
|
|
47
|
+
* the process-instance key for a process-level variable that omits it. `isTruncated` is the
|
|
48
|
+
* engine's large-value-clipped flag, defaulting to `false`. The single source of truth
|
|
49
|
+
* `searchVariables` extracts through. */
|
|
50
|
+
export declare function mapVariableRow(row: Record<string, unknown>, log: Log): VariableSummary | undefined;
|
|
51
|
+
/** Map one engine job row onto a {@link JobSummary}, or `undefined` when the row is malformed
|
|
52
|
+
* (missing the `jobKey`, `type`, or owning `processInstanceKey`). `worker`/`retries`/`elementId`/
|
|
53
|
+
* `deadline` are best-effort diagnostics: present when the engine reports them, omitted otherwise
|
|
54
|
+
* — an unset `worker` is the "queued, not leased" signal, so it must be absent rather than `""`.
|
|
55
|
+
* `state` is passed through as a bare string (the engine's job-state enum is broad). The single
|
|
56
|
+
* source of truth `searchJobs` extracts through. */
|
|
57
|
+
export declare function mapJobRow(row: Record<string, unknown>, log: Log): JobSummary | undefined;
|
|
43
58
|
/** A job as delivered to a nano-sdk job handler: the frame fields plus the
|
|
44
59
|
* acknowledgement actions the handler must call. */
|
|
45
60
|
export interface NanoSdkActivatedJob {
|
|
@@ -135,6 +150,17 @@ export interface NanoSdkClient {
|
|
|
135
150
|
filter?: Record<string, unknown>;
|
|
136
151
|
page?: Record<string, unknown>;
|
|
137
152
|
}, consistency?: unknown, options?: unknown): Promise<Record<string, unknown>>;
|
|
153
|
+
searchVariables(input: {
|
|
154
|
+
filter?: Record<string, unknown>;
|
|
155
|
+
page?: Record<string, unknown>;
|
|
156
|
+
}, consistency?: unknown, options?: unknown): Promise<Record<string, unknown>>;
|
|
157
|
+
searchJobs(input: {
|
|
158
|
+
filter?: Record<string, unknown>;
|
|
159
|
+
page?: Record<string, unknown>;
|
|
160
|
+
}, consistency?: unknown, options?: unknown): Promise<Record<string, unknown>>;
|
|
161
|
+
getProcessDefinitionXml(input: {
|
|
162
|
+
processDefinitionKey: string;
|
|
163
|
+
}, consistency?: unknown, options?: unknown): Promise<unknown>;
|
|
138
164
|
resolveIncident(input: {
|
|
139
165
|
incidentKey: string;
|
|
140
166
|
}, options?: unknown): Promise<unknown>;
|
|
@@ -210,11 +236,16 @@ export declare class SdkEngineClient implements EngineClient {
|
|
|
210
236
|
searchProcessInstances(filter?: {
|
|
211
237
|
processInstanceKeys?: string[];
|
|
212
238
|
state?: ProcessInstanceState;
|
|
239
|
+
parentProcessInstanceKey?: string;
|
|
240
|
+
rootProcessInstanceKey?: string;
|
|
213
241
|
}): Promise<ProcessInstanceSnapshot[]>;
|
|
214
242
|
searchElementInstances(filter?: ElementInstanceFilter): Promise<ElementInstanceSummary[]>;
|
|
215
243
|
searchElementInstanceWaitStates(filter?: ElementInstanceWaitStateFilter): Promise<ElementInstanceWaitState[]>;
|
|
216
244
|
getElementInstance(elementInstanceKey: string): Promise<ElementInstanceSummary | null>;
|
|
217
245
|
searchIncidents(filter?: IncidentFilter): Promise<IncidentSummary[]>;
|
|
246
|
+
searchVariables(filter?: VariableFilter): Promise<VariableSummary[]>;
|
|
247
|
+
searchJobs(filter?: JobFilter): Promise<JobSummary[]>;
|
|
248
|
+
getProcessDefinitionXml(processDefinitionKey: string): Promise<string | null>;
|
|
218
249
|
resolveIncident(input: {
|
|
219
250
|
incidentKey: string;
|
|
220
251
|
}): Promise<void>;
|
|
@@ -320,6 +320,91 @@ export function mapIncidentRow(row, log) {
|
|
|
320
320
|
state: normalizeIncidentState(row.state),
|
|
321
321
|
};
|
|
322
322
|
}
|
|
323
|
+
/** Map one engine variable row onto a {@link VariableSummary}, or `undefined` when the row is
|
|
324
|
+
* malformed (missing the `variableKey`, owning `processInstanceKey`, or `name` — the identity a
|
|
325
|
+
* caller needs). `value` is the engine's serialized JSON value (a string); a non-string value is
|
|
326
|
+
* JSON-encoded so the field is always a string a caller can `JSON.parse`. `scopeKey` falls back to
|
|
327
|
+
* the process-instance key for a process-level variable that omits it. `isTruncated` is the
|
|
328
|
+
* engine's large-value-clipped flag, defaulting to `false`. The single source of truth
|
|
329
|
+
* `searchVariables` extracts through. */
|
|
330
|
+
export function mapVariableRow(row, log) {
|
|
331
|
+
const variableKey = presentEngineKey(row.variableKey);
|
|
332
|
+
if (variableKey === undefined) {
|
|
333
|
+
log("warn", "skipping variable with no variableKey in engine response");
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
const processInstanceKey = presentEngineKey(row.processInstanceKey);
|
|
337
|
+
if (processInstanceKey === undefined) {
|
|
338
|
+
log("warn", "skipping variable with no processInstanceKey in engine response", {
|
|
339
|
+
variableKey,
|
|
340
|
+
});
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
const name = presentText(row.name);
|
|
344
|
+
if (name === undefined) {
|
|
345
|
+
log("warn", "skipping variable with no name in engine response", { variableKey });
|
|
346
|
+
return undefined;
|
|
347
|
+
}
|
|
348
|
+
// A process-level variable is scoped to the process instance itself; the engine may omit
|
|
349
|
+
// `scopeKey` for it, so fall back to the process-instance key rather than dropping the row.
|
|
350
|
+
const scopeKey = presentEngineKey(row.scopeKey) ?? processInstanceKey;
|
|
351
|
+
// The engine serializes `value` as a JSON string. Keep a string as-is; encode any other type
|
|
352
|
+
// (an object/array/number a permissive engine might inline) so the field is always a string the
|
|
353
|
+
// caller can `JSON.parse`.
|
|
354
|
+
const value = typeof row.value === "string" ? row.value : JSON.stringify(row.value ?? null);
|
|
355
|
+
return {
|
|
356
|
+
variableKey,
|
|
357
|
+
name,
|
|
358
|
+
value,
|
|
359
|
+
scopeKey,
|
|
360
|
+
processInstanceKey,
|
|
361
|
+
isTruncated: row.isTruncated === true,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
/** Map one engine job row onto a {@link JobSummary}, or `undefined` when the row is malformed
|
|
365
|
+
* (missing the `jobKey`, `type`, or owning `processInstanceKey`). `worker`/`retries`/`elementId`/
|
|
366
|
+
* `deadline` are best-effort diagnostics: present when the engine reports them, omitted otherwise
|
|
367
|
+
* — an unset `worker` is the "queued, not leased" signal, so it must be absent rather than `""`.
|
|
368
|
+
* `state` is passed through as a bare string (the engine's job-state enum is broad). The single
|
|
369
|
+
* source of truth `searchJobs` extracts through. */
|
|
370
|
+
export function mapJobRow(row, log) {
|
|
371
|
+
const jobKey = presentEngineKey(row.jobKey);
|
|
372
|
+
if (jobKey === undefined) {
|
|
373
|
+
log("warn", "skipping job with no jobKey in engine response");
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
const type = presentText(row.type);
|
|
377
|
+
if (type === undefined) {
|
|
378
|
+
log("warn", "skipping job with no type in engine response", { jobKey });
|
|
379
|
+
return undefined;
|
|
380
|
+
}
|
|
381
|
+
const processInstanceKey = presentEngineKey(row.processInstanceKey);
|
|
382
|
+
if (processInstanceKey === undefined) {
|
|
383
|
+
log("warn", "skipping job with no processInstanceKey in engine response", { jobKey });
|
|
384
|
+
return undefined;
|
|
385
|
+
}
|
|
386
|
+
const state = presentText(row.state);
|
|
387
|
+
if (state === undefined) {
|
|
388
|
+
log("warn", "skipping job with no state in engine response", { jobKey });
|
|
389
|
+
return undefined;
|
|
390
|
+
}
|
|
391
|
+
const worker = presentText(row.worker);
|
|
392
|
+
const retries = typeof row.retries === "number" && Number.isFinite(row.retries)
|
|
393
|
+
? row.retries
|
|
394
|
+
: undefined;
|
|
395
|
+
const elementId = presentText(row.elementId);
|
|
396
|
+
const deadline = presentText(row.deadline);
|
|
397
|
+
return {
|
|
398
|
+
jobKey,
|
|
399
|
+
type,
|
|
400
|
+
state,
|
|
401
|
+
processInstanceKey,
|
|
402
|
+
...(worker ? { worker } : {}),
|
|
403
|
+
...(retries !== undefined ? { retries } : {}),
|
|
404
|
+
...(elementId ? { elementId } : {}),
|
|
405
|
+
...(deadline ? { deadline } : {}),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
323
408
|
/**
|
|
324
409
|
* An `EngineClient` backed entirely by a `@nanobpm/nano-sdk` client. Deploy, create,
|
|
325
410
|
* message, and user-task calls map one-to-one onto the SDK's client methods; workers
|
|
@@ -380,7 +465,20 @@ export class SdkEngineClient {
|
|
|
380
465
|
async searchUserTasks(filter) {
|
|
381
466
|
// User tasks are an eventually consistent read; ask for zero-wait consistency so
|
|
382
467
|
// the search reflects what is currently visible without blocking.
|
|
383
|
-
|
|
468
|
+
// Normalize the process-instance key selectors through the shared presence rule so a
|
|
469
|
+
// blank/whitespace-only selector is *dropped* rather than forwarded as a present filter that
|
|
470
|
+
// silently matches nothing, and a padded key (`" 123 "`) matches the normalized keys we
|
|
471
|
+
// surface — mirroring `WasmEngineClient` (which normalizes via `presentKey`) and
|
|
472
|
+
// `searchProcessInstances` below (No Drift Surfaces).
|
|
473
|
+
const f = { ...(filter ?? {}) };
|
|
474
|
+
for (const sel of ["processInstanceKey", "parentProcessInstanceKey", "rootProcessInstanceKey"]) {
|
|
475
|
+
const normalized = presentEngineKey(filter?.[sel]);
|
|
476
|
+
if (normalized)
|
|
477
|
+
f[sel] = normalized;
|
|
478
|
+
else
|
|
479
|
+
delete f[sel];
|
|
480
|
+
}
|
|
481
|
+
const body = await this.client.searchUserTasks({ filter: f }, { consistency: { waitUpToMs: 0 } });
|
|
384
482
|
const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
|
|
385
483
|
return items.flatMap((it) => {
|
|
386
484
|
const userTaskKey = it.userTaskKey ?? it.key;
|
|
@@ -391,10 +489,16 @@ export class SdkEngineClient {
|
|
|
391
489
|
// The engine resolves a `formId="X"` linkage to the latest deployed form's key at
|
|
392
490
|
// task creation, so `formKey` (not a form id) is the linkage it reports on the task;
|
|
393
491
|
// no `resolveFormKeyByFormId` resolver is passed because the gateway already resolved it.
|
|
492
|
+
const processInstanceKey = presentEngineKey(it.processInstanceKey);
|
|
493
|
+
const parentProcessInstanceKey = presentEngineKey(it.parentProcessInstanceKey);
|
|
494
|
+
const rootProcessInstanceKey = presentEngineKey(it.rootProcessInstanceKey);
|
|
394
495
|
return [{
|
|
395
496
|
userTaskKey: String(userTaskKey),
|
|
396
497
|
elementId: typeof it.elementId === "string" ? it.elementId : undefined,
|
|
397
498
|
variables: isRecord(it.variables) ? it.variables : undefined,
|
|
499
|
+
...(processInstanceKey ? { processInstanceKey } : {}),
|
|
500
|
+
...(parentProcessInstanceKey ? { parentProcessInstanceKey } : {}),
|
|
501
|
+
...(rootProcessInstanceKey ? { rootProcessInstanceKey } : {}),
|
|
398
502
|
...pickFormLinkage(it),
|
|
399
503
|
}];
|
|
400
504
|
});
|
|
@@ -460,9 +564,24 @@ export class SdkEngineClient {
|
|
|
460
564
|
const f = {};
|
|
461
565
|
if (filter?.state)
|
|
462
566
|
f.state = filter.state;
|
|
463
|
-
|
|
567
|
+
// Normalize each requested key through the shared presence rule (drop blank/whitespace-only
|
|
568
|
+
// entries, trim padded ones like `" 123 "`) so the `$in` filter carries only present keys that
|
|
569
|
+
// match the normalized keys we surface — mirroring `WasmEngineClient` and the selector
|
|
570
|
+
// handling above (No Drift Surfaces).
|
|
571
|
+
const keys = filter?.processInstanceKeys
|
|
572
|
+
?.map((k) => presentEngineKey(k))
|
|
573
|
+
.filter((k) => k !== undefined);
|
|
464
574
|
if (keys && keys.length > 0)
|
|
465
575
|
f.processInstanceKey = { $in: keys };
|
|
576
|
+
// Parent/root selectors let the reduced path query a subject's native descendants
|
|
577
|
+
// server-side. Normalize each through the shared presence rule so a blank selector is
|
|
578
|
+
// dropped rather than sent as an empty filter that would match nothing.
|
|
579
|
+
const parentProcessInstanceKey = presentEngineKey(filter?.parentProcessInstanceKey);
|
|
580
|
+
if (parentProcessInstanceKey)
|
|
581
|
+
f.parentProcessInstanceKey = parentProcessInstanceKey;
|
|
582
|
+
const rootProcessInstanceKey = presentEngineKey(filter?.rootProcessInstanceKey);
|
|
583
|
+
if (rootProcessInstanceKey)
|
|
584
|
+
f.rootProcessInstanceKey = rootProcessInstanceKey;
|
|
466
585
|
// A process-instance search is an eventually consistent read; ask for zero-wait
|
|
467
586
|
// consistency so it reflects what is currently visible without blocking. Cap the page
|
|
468
587
|
// to the number of keys asked for (each key matches at most one instance), so a bounded
|
|
@@ -471,20 +590,33 @@ export class SdkEngineClient {
|
|
|
471
590
|
const body = await this.client.searchProcessInstances({ filter: f, ...(page ? { page } : {}) }, { consistency: { waitUpToMs: 0 } });
|
|
472
591
|
const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
|
|
473
592
|
return items.flatMap((it) => {
|
|
474
|
-
|
|
475
|
-
|
|
593
|
+
// Normalize the surfaced primary key through the shared presence rule (trim padded,
|
|
594
|
+
// drop blank/whitespace-only) so it matches the normalized parent/root linkage keys
|
|
595
|
+
// and the `searchUserTasks` mapping — the surfaced process-instance key must not drift
|
|
596
|
+
// between the two reduced-path searches (No Drift Surfaces).
|
|
597
|
+
const processInstanceKey = presentEngineKey(it.processInstanceKey);
|
|
598
|
+
if (!processInstanceKey) {
|
|
476
599
|
this.log("warn", "skipping process instance with no key in engine response");
|
|
477
600
|
return [];
|
|
478
601
|
}
|
|
479
602
|
const state = normalizeProcessInstanceState(it.state);
|
|
480
603
|
if (!state) {
|
|
481
604
|
this.log("warn", "skipping process instance with unrecognized state", {
|
|
482
|
-
processInstanceKey
|
|
605
|
+
processInstanceKey,
|
|
483
606
|
state: String(it.state),
|
|
484
607
|
});
|
|
485
608
|
return [];
|
|
486
609
|
}
|
|
487
|
-
|
|
610
|
+
const processDefinitionKey = presentEngineKey(it.processDefinitionKey);
|
|
611
|
+
const parentProcessInstanceKey = presentEngineKey(it.parentProcessInstanceKey);
|
|
612
|
+
const rootProcessInstanceKey = presentEngineKey(it.rootProcessInstanceKey);
|
|
613
|
+
return [{
|
|
614
|
+
processInstanceKey,
|
|
615
|
+
state,
|
|
616
|
+
...(processDefinitionKey ? { processDefinitionKey } : {}),
|
|
617
|
+
...(parentProcessInstanceKey ? { parentProcessInstanceKey } : {}),
|
|
618
|
+
...(rootProcessInstanceKey ? { rootProcessInstanceKey } : {}),
|
|
619
|
+
}];
|
|
488
620
|
});
|
|
489
621
|
}
|
|
490
622
|
async searchElementInstances(filter) {
|
|
@@ -575,6 +707,78 @@ export class SdkEngineClient {
|
|
|
575
707
|
return mapped ? [mapped] : [];
|
|
576
708
|
});
|
|
577
709
|
}
|
|
710
|
+
async searchVariables(filter) {
|
|
711
|
+
// Same shape as `searchIncidents`: build the engine filter from the transport-agnostic
|
|
712
|
+
// selectors, read at zero-wait consistency (a variable search is eventually consistent), and
|
|
713
|
+
// map each row through the single `mapVariableRow` gate, dropping malformed rows.
|
|
714
|
+
const f = {};
|
|
715
|
+
const processInstanceKey = presentEngineKey(filter?.processInstanceKey);
|
|
716
|
+
if (processInstanceKey)
|
|
717
|
+
f.processInstanceKey = processInstanceKey;
|
|
718
|
+
const scopeKey = presentEngineKey(filter?.scopeKey);
|
|
719
|
+
if (scopeKey)
|
|
720
|
+
f.scopeKey = scopeKey;
|
|
721
|
+
const name = filter?.name?.trim();
|
|
722
|
+
if (name)
|
|
723
|
+
f.name = name;
|
|
724
|
+
const body = await this.client.searchVariables({ filter: f }, { consistency: { waitUpToMs: 0 } });
|
|
725
|
+
const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
|
|
726
|
+
return items.flatMap((it) => {
|
|
727
|
+
const mapped = mapVariableRow(it, this.log);
|
|
728
|
+
return mapped ? [mapped] : [];
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
async searchJobs(filter) {
|
|
732
|
+
// Same shape as `searchIncidents`: build the engine filter from the transport-agnostic
|
|
733
|
+
// selectors, read at zero-wait consistency (a job search is eventually consistent), and map
|
|
734
|
+
// each row through the single `mapJobRow` gate, dropping malformed rows.
|
|
735
|
+
const f = {};
|
|
736
|
+
const processInstanceKey = presentEngineKey(filter?.processInstanceKey);
|
|
737
|
+
if (processInstanceKey)
|
|
738
|
+
f.processInstanceKey = processInstanceKey;
|
|
739
|
+
const state = filter?.state?.trim();
|
|
740
|
+
if (state)
|
|
741
|
+
f.state = state;
|
|
742
|
+
const type = filter?.type?.trim();
|
|
743
|
+
if (type)
|
|
744
|
+
f.type = type;
|
|
745
|
+
const elementId = filter?.elementId?.trim();
|
|
746
|
+
if (elementId)
|
|
747
|
+
f.elementId = elementId;
|
|
748
|
+
const worker = filter?.worker?.trim();
|
|
749
|
+
if (worker)
|
|
750
|
+
f.worker = worker;
|
|
751
|
+
const body = await this.client.searchJobs({ filter: f }, { consistency: { waitUpToMs: 0 } });
|
|
752
|
+
const items = Array.isArray(body.items) ? body.items.filter(isRecord) : [];
|
|
753
|
+
return items.flatMap((it) => {
|
|
754
|
+
const mapped = mapJobRow(it, this.log);
|
|
755
|
+
return mapped ? [mapped] : [];
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
async getProcessDefinitionXml(processDefinitionKey) {
|
|
759
|
+
// A blank key can never address a definition — short-circuit to null rather than issue a
|
|
760
|
+
// `GET /v2/process-definitions//xml` with an empty segment. Normalize a padded-but-valid key so
|
|
761
|
+
// `" 5 "` addresses the same definition, mirroring `getElementInstance`.
|
|
762
|
+
const key = presentEngineKey(processDefinitionKey);
|
|
763
|
+
if (key === undefined)
|
|
764
|
+
return null;
|
|
765
|
+
let xml;
|
|
766
|
+
try {
|
|
767
|
+
xml = await this.client.getProcessDefinitionXml({ processDefinitionKey: key }, { consistency: { waitUpToMs: 0 } });
|
|
768
|
+
}
|
|
769
|
+
catch (err) {
|
|
770
|
+
// A 404 (no such definition) is an expected "not found", not a fault — mirror `getForm`/
|
|
771
|
+
// `getElementInstance`, which treat a failed fetch as absence (null) rather than propagating.
|
|
772
|
+
this.log("warn", "getProcessDefinitionXml: engine fetch failed", {
|
|
773
|
+
processDefinitionKey: key,
|
|
774
|
+
err: err instanceof Error ? err.message : String(err),
|
|
775
|
+
});
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
// The endpoint returns the raw BPMN XML as a string (204 → empty). Treat a blank/absent body
|
|
779
|
+
// as "no XML" (null) so a caller distinguishes "have it" from "don't".
|
|
780
|
+
return typeof xml === "string" && xml.trim() !== "" ? xml : null;
|
|
781
|
+
}
|
|
578
782
|
async resolveIncident(input) {
|
|
579
783
|
await this.client.resolveIncident({
|
|
580
784
|
incidentKey: requireEngineKey(input.incidentKey, "incidentKey"),
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { bindModeToHost, expandEnv, expandEnvString, isBindMode, loadManifest, p
|
|
|
8
8
|
export type { ActionDecl, AppManifest, BindMode, ChatSurface, DataSource, DomainField, DomainType, InstanceTracking, LlmBinding, NetworkConfig, PagesSurface, Surfaces, TaskInboxSurface, Trigger, Worker, } from "./core/manifest.ts";
|
|
9
9
|
export { collectManifestIssues, ManifestValidationError, validateManifest, } from "./core/validate.ts";
|
|
10
10
|
export type { ValidationIssue } from "./core/validate.ts";
|
|
11
|
-
export type { EngineClient, ElementInstanceState, ElementInstanceSummary, ElementInstanceFilter, ElementInstanceWaitState, ElementInstanceWaitStateFilter, WaitStateType, EngineJob, FormSchema, HostContext, HttpHandler, HttpRequest, HttpResponse, HttpServer, IncidentState, EngineIncidentState, IncidentFilter, IncidentSummary, JobHandler, ProcessInstanceSnapshot, ProcessInstanceState, SqliteDb, UserTaskState, UserTaskSummary, UserTaskFilter, WatchHandle, WorkerSubscription, } from "./core/host.ts";
|
|
11
|
+
export type { EngineClient, ElementInstanceState, ElementInstanceSummary, ElementInstanceFilter, ElementInstanceWaitState, ElementInstanceWaitStateFilter, WaitStateType, EngineJob, FormSchema, HostContext, HttpHandler, HttpRequest, HttpResponse, HttpServer, IncidentState, EngineIncidentState, IncidentFilter, IncidentSummary, JobFilter, JobHandler, JobSummary, ProcessInstanceSnapshot, ProcessInstanceState, SqliteDb, UserTaskState, UserTaskSummary, UserTaskFilter, VariableFilter, VariableSummary, WatchHandle, WorkerSubscription, } from "./core/host.ts";
|
|
12
12
|
export { buildFormSchema, parseFormSchema, pickFormLinkage, presentFormIdentifier, resolveFormIdentifier, } from "./core/form-contract.ts";
|
|
13
13
|
export type { AppApi, Mounted, RuntimeContext } from "./core/context.ts";
|
|
14
14
|
export { createLogger } from "./core/logger.ts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanobpm/urban",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.0",
|
|
4
4
|
"description": "Urban: build and run code-first apps on Nano — runtime, derivation toolkit, and CLI in one. Author durable processes with @nanobpm/workflow (defineFlow), a typed datasource, forms, triggers and surfaces from a nano.app.json manifest, on Node or Deno.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|