@weiliang0121/capix-invocation 0.0.0-stage → 0.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.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -2
  3. package/dist/checkpoint/children.d.ts +16 -0
  4. package/dist/checkpoint/children.js +2 -0
  5. package/dist/checkpoint/continuation.d.ts +10 -0
  6. package/dist/checkpoint/continuation.js +2 -0
  7. package/dist/checkpoint/contract.d.ts +73 -0
  8. package/dist/checkpoint/contract.js +1 -0
  9. package/dist/checkpoint/data.d.ts +5 -0
  10. package/dist/checkpoint/data.js +2 -0
  11. package/dist/checkpoint/facts.d.ts +49 -0
  12. package/dist/checkpoint/facts.js +2 -0
  13. package/dist/checkpoint/invocation.d.ts +36 -0
  14. package/dist/checkpoint/invocation.js +2 -0
  15. package/dist/checkpoint/observation.d.ts +26 -0
  16. package/dist/checkpoint/observation.js +2 -0
  17. package/dist/checkpoint/publication.d.ts +20 -0
  18. package/dist/checkpoint/publication.js +2 -0
  19. package/dist/checkpoint/restoration.d.ts +4 -0
  20. package/dist/checkpoint/restoration.js +2 -0
  21. package/dist/checkpoint/selection.d.ts +22 -0
  22. package/dist/checkpoint/selection.js +2 -0
  23. package/dist/checkpoint/target.d.ts +4 -0
  24. package/dist/checkpoint/target.js +2 -0
  25. package/dist/checkpoint/work.d.ts +27 -0
  26. package/dist/checkpoint/work.js +1 -0
  27. package/dist/clock.d.ts +4 -0
  28. package/dist/clock.js +2 -0
  29. package/dist/context/callable.d.ts +12 -0
  30. package/dist/context/callable.js +2 -0
  31. package/dist/context/context.d.ts +58 -0
  32. package/dist/context/context.js +2 -0
  33. package/dist/context/view.d.ts +34 -0
  34. package/dist/context/view.js +2 -0
  35. package/dist/events.d.ts +32 -0
  36. package/dist/events.js +2 -0
  37. package/dist/exception/contract.d.ts +11 -0
  38. package/dist/exception/contract.js +2 -0
  39. package/dist/index.d.ts +38 -0
  40. package/dist/index.js +2 -0
  41. package/dist/invocation/cancellation.d.ts +8 -0
  42. package/dist/invocation/cancellation.js +2 -0
  43. package/dist/invocation/changes.d.ts +13 -0
  44. package/dist/invocation/changes.js +2 -0
  45. package/dist/invocation/children.d.ts +72 -0
  46. package/dist/invocation/children.js +2 -0
  47. package/dist/invocation/control.d.ts +8 -0
  48. package/dist/invocation/control.js +2 -0
  49. package/dist/invocation/execution.d.ts +35 -0
  50. package/dist/invocation/execution.js +2 -0
  51. package/dist/invocation/facts.d.ts +5 -0
  52. package/dist/invocation/facts.js +2 -0
  53. package/dist/invocation/failure.d.ts +11 -0
  54. package/dist/invocation/failure.js +2 -0
  55. package/dist/invocation/invocation.d.ts +83 -0
  56. package/dist/invocation/invocation.js +2 -0
  57. package/dist/invocation/progress.d.ts +33 -0
  58. package/dist/invocation/progress.js +1 -0
  59. package/dist/invocation/provenance.d.ts +38 -0
  60. package/dist/invocation/provenance.js +2 -0
  61. package/dist/invocation/reception.d.ts +7 -0
  62. package/dist/invocation/reception.js +1 -0
  63. package/dist/invocation/relation.d.ts +93 -0
  64. package/dist/invocation/relation.js +2 -0
  65. package/dist/invocation/resource-access.d.ts +31 -0
  66. package/dist/invocation/resource-access.js +2 -0
  67. package/dist/invocation/resources.d.ts +8 -0
  68. package/dist/invocation/resources.js +2 -0
  69. package/dist/invocation/result.d.ts +12 -0
  70. package/dist/invocation/result.js +2 -0
  71. package/dist/invocation/stop.d.ts +3 -0
  72. package/dist/invocation/stop.js +2 -0
  73. package/dist/invocation/view.d.ts +30 -0
  74. package/dist/invocation/view.js +2 -0
  75. package/dist/invocation/work.d.ts +31 -0
  76. package/dist/invocation/work.js +2 -0
  77. package/dist/observation/error.d.ts +4 -0
  78. package/dist/observation/error.js +2 -0
  79. package/dist/observation/facts.d.ts +64 -0
  80. package/dist/observation/facts.js +1 -0
  81. package/dist/observation/invocation.d.ts +16 -0
  82. package/dist/observation/invocation.js +2 -0
  83. package/dist/observation/observer.d.ts +12 -0
  84. package/dist/observation/observer.js +2 -0
  85. package/dist/observation/session.d.ts +17 -0
  86. package/dist/observation/session.js +2 -0
  87. package/dist/operation/failure.d.ts +1 -0
  88. package/dist/operation/failure.js +2 -0
  89. package/dist/output/delivery.d.ts +2 -0
  90. package/dist/output/delivery.js +2 -0
  91. package/dist/output/section.d.ts +21 -0
  92. package/dist/output/section.js +2 -0
  93. package/dist/value/array.d.ts +2 -0
  94. package/dist/value/array.js +2 -0
  95. package/dist/value/object.d.ts +2 -0
  96. package/dist/value/object.js +2 -0
  97. package/dist/value/string.d.ts +2 -0
  98. package/dist/value/string.js +2 -0
  99. package/package.json +49 -3
@@ -0,0 +1,58 @@
1
+ import type { InvocationFailure } from '../invocation/failure.js';
2
+ import type { InvocationResult } from '../invocation/result.js';
3
+ import type { CheckpointContinuationFact } from '../checkpoint/continuation.js';
4
+ import { type Stable, type RuntimeErrorValue } from '@weiliang0121/capix-contracts';
5
+ export interface InvocationControls {
6
+ readonly signal?: AbortSignal;
7
+ }
8
+ export type ContextState<Output> = Readonly<{
9
+ status: 'running';
10
+ } | {
11
+ status: 'succeeded';
12
+ output: Stable<Output>;
13
+ } | {
14
+ status: 'failed';
15
+ error: unknown;
16
+ diagnostic: Stable<RuntimeErrorValue>;
17
+ failure?: InvocationFailure;
18
+ }>;
19
+ export declare class InvocationContext<Input = unknown, Output = unknown> {
20
+ #private;
21
+ get id(): string;
22
+ installIdentity(id: string): void;
23
+ installDelivery(frame: {
24
+ id: string;
25
+ round: number;
26
+ currentInput: Input | Stable<Input>;
27
+ phase: 'execute' | 'receive' | 'handling';
28
+ }, output: Output | Stable<Output>): void;
29
+ installFailure(frame: {
30
+ id: string;
31
+ round: number;
32
+ currentInput: Input | Stable<Input>;
33
+ phase: 'execute' | 'receive' | 'handling';
34
+ }, failure: InvocationFailure, diagnostic?: Stable<RuntimeErrorValue>): void;
35
+ installCheckpoint(frame: {
36
+ id: string;
37
+ round: number;
38
+ currentInput: Input | Stable<Input>;
39
+ continuation?: CheckpointContinuationFact;
40
+ }): void;
41
+ readonly input: Stable<Input>;
42
+ constructor(input: Input | Stable<Input>);
43
+ get progress(): Readonly<{
44
+ round: number;
45
+ input: Stable<Input>;
46
+ phase: "execute" | "receive" | "handling";
47
+ result?: InvocationResult<Output>;
48
+ }>;
49
+ get currentInput(): Stable<Input>;
50
+ get continuation(): CheckpointContinuationFact | undefined;
51
+ start(): void;
52
+ returned(result: InvocationResult<Output>): void;
53
+ get state(): ContextState<Output>;
54
+ get status(): ContextState<Output>['status'];
55
+ complete(output: Output | Stable<Output>): void;
56
+ fail(error: unknown, failure?: InvocationFailure, diagnostic?: Stable<RuntimeErrorValue>): void;
57
+ requireRunning(): void;
58
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{randomUUID}from"node:crypto";import{stableValue}from"@weiliang0121/capix-contracts";import{failureDiagnostic}from"../invocation/failure.js";class InvocationContext{static{__name(this,"InvocationContext")}#id=randomUUID();get id(){return this.#id}installIdentity(id){if(this.requireRunning(),this.#progress.round!==0||!id)throw new Error("Context identity can only be installed before progress");this.#id=id}installDelivery(frame,output){this.installCheckpoint(frame),this.#progress=Object.freeze({round:frame.round,input:this.currentInput,phase:frame.phase}),this.complete(output)}installFailure(frame,failure,diagnostic){this.installCheckpoint(frame),this.#progress=Object.freeze({round:frame.round,input:this.currentInput,phase:frame.phase}),this.fail(failure.error,failure,diagnostic)}installCheckpoint(frame){if(this.requireRunning(),this.#progress.round!==0||!frame.id||!Number.isInteger(frame.round)||frame.round<1||frame.round>2)throw new Error("Invalid checkpoint context installation");const input=stableValue(frame.currentInput);this.#id=frame.id,this.#progress=Object.freeze({round:frame.round,input,phase:"execute"}),this.#continuation=frame.continuation?Object.freeze({...frame.continuation}):void 0}#state=Object.freeze({status:"running"});#continuation;#progress;input;constructor(input){this.input=stableValue(input),this.#progress=Object.freeze({round:0,input:this.input,phase:"execute"})}get progress(){return this.#progress}get currentInput(){return this.#progress.input}get continuation(){return this.#continuation}start(){if(this.requireRunning(),this.#progress.round!==0)throw new Error("Invocation execution has already started");this.#progress=Object.freeze({round:1,input:this.input,phase:"execute"})}returned(result){this.requireRunning();const fixed=result.status==="succeeded"?{...result,output:stableValue(result.output)}:{...result,diagnostic:result.diagnostic?stableValue(result.diagnostic):failureDiagnostic(result.error)};this.requireRunning(),this.#progress=Object.freeze({...this.#progress,result:Object.freeze(fixed)})}get state(){return this.#state}get status(){return this.#state.status}complete(output){this.requireRunning();const fixed=stableValue(output);this.requireRunning(),this.#state=Object.freeze({status:"succeeded",output:fixed})}fail(error,failure,diagnostic){this.requireRunning();const fixed=diagnostic?stableValue(diagnostic):failureDiagnostic(error);this.requireRunning(),this.#state=Object.freeze({status:"failed",error,diagnostic:fixed,...failure?{failure}:{}})}requireRunning(){if(this.status!=="running")throw new Error("Context has already ended")}}export{InvocationContext};
@@ -0,0 +1,34 @@
1
+ import { InvocationResources } from '../invocation/resource-access.js';
2
+ import type { ContextState, InvocationContext } from './context.js';
3
+ import type { Stable } from '@weiliang0121/capix-contracts';
4
+ export interface InvocationContextView<Input = unknown, Output = unknown> {
5
+ readonly id: string;
6
+ readonly input: Stable<Input>;
7
+ readonly currentInput: Stable<Input>;
8
+ readonly progress: InvocationContext<Input, Output>['progress'];
9
+ readonly state: ContextState<Output>;
10
+ readonly status: ContextState<Output>['status'];
11
+ }
12
+ interface ResourceContextView<Input, Output, Resources extends object> extends InvocationContextView<Input, Output> {
13
+ readonly signal: AbortSignal;
14
+ readonly resources: {
15
+ readonly values: Readonly<Resources>;
16
+ };
17
+ }
18
+ export interface CallableContextView<Input = unknown, Output = unknown, Resources extends object = object> extends ResourceContextView<Input, Output, Resources> {
19
+ readonly kind: import('@weiliang0121/capix-contracts').CallableKind;
20
+ }
21
+ export type ContextViewOf<Context extends InvocationContext<any, any>> = Context extends InvocationContext<infer Input, infer Output> & {
22
+ readonly resources: InvocationResources<infer Resources>;
23
+ readonly signal: AbortSignal;
24
+ readonly kind: import('@weiliang0121/capix-contracts').CallableKind;
25
+ } ? CallableContextView<Input, Output, Resources> : Context extends InvocationContext<infer Input, infer Output> ? InvocationContextView<Input, Output> : never;
26
+ export type ContextViewResources<ContextView extends InvocationContextView<any, any>, Resources extends object> = Omit<ContextView, 'resources'> & {
27
+ readonly resources: {
28
+ readonly values: Readonly<Resources>;
29
+ };
30
+ };
31
+ export type ContextFactsOf<Context extends InvocationContext<any, any>> = Omit<ContextViewOf<Context>, 'resources'>;
32
+ export declare function invocationContextView<Context extends InvocationContext<any, any>>(context: Context): ContextFactsOf<Context>;
33
+ export declare function invocationContextView<Context extends InvocationContext<any, any>>(context: Context, values: Readonly<object>): ContextViewOf<Context>;
34
+ export {};
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import"../invocation/resource-access.js";function invocationContextView(context,values){const view={get id(){return context.id},get input(){return context.input},get currentInput(){return context.currentInput},get progress(){return context.progress},get state(){return context.state},get status(){return context.status}};return"resources"in context&&"signal"in context&&(Object.defineProperties(view,{kind:{enumerable:!0,value:"kind"in context?context.kind:void 0},signal:{enumerable:!0,value:context.signal}}),values&&Object.defineProperty(view,"resources",{enumerable:!0,value:Object.freeze({values})})),Object.freeze(view)}__name(invocationContextView,"invocationContextView");export{invocationContextView};
@@ -0,0 +1,32 @@
1
+ import type { CallableKind, InvocationFailureFact, InvocationRelationIdentity } from '@weiliang0121/capix-contracts';
2
+ export declare const invocationProcessStages: readonly ["execute", "receive", "handling", "control"];
3
+ export declare const invocationProcessActions: readonly ["start", "return", "throw", "continue", "unhandled", "stop"];
4
+ export type InvocationProcessStage = (typeof invocationProcessStages)[number];
5
+ export type InvocationProcessAction = (typeof invocationProcessActions)[number];
6
+ export type InvocationRelationPhase = 'attached' | 'returned' | 'receiving' | 'accepted' | 'handled' | 'failed';
7
+ export type InvocationEvent = Readonly<{
8
+ type: 'invocation';
9
+ contextId: string;
10
+ parentContextId?: string;
11
+ kind: CallableKind;
12
+ sequence: number;
13
+ occurredAt: string;
14
+ change: Readonly<{
15
+ kind: 'started';
16
+ }> | Readonly<{
17
+ kind: 'process';
18
+ processSequence: number;
19
+ round: number;
20
+ stage: InvocationProcessStage;
21
+ action: InvocationProcessAction;
22
+ }> | Readonly<{
23
+ kind: 'relation';
24
+ identity: InvocationRelationIdentity;
25
+ phase: InvocationRelationPhase;
26
+ status?: 'succeeded' | 'failed';
27
+ failure?: InvocationFailureFact;
28
+ }> | Readonly<{
29
+ kind: 'finished';
30
+ status: 'succeeded' | 'failed';
31
+ }>;
32
+ }>;
package/dist/events.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ const invocationProcessStages=["execute","receive","handling","control"],invocationProcessActions=["start","return","throw","continue","unhandled","stop"];export{invocationProcessActions,invocationProcessStages};
@@ -0,0 +1,11 @@
1
+ import { RuntimeError } from '@weiliang0121/capix-contracts';
2
+ export declare class ExceptionContract<F = unknown> {
3
+ readonly name: string;
4
+ constructor(name: string);
5
+ create(message: string, facts: F, options?: ErrorOptions): DeclaredException<F>;
6
+ }
7
+ export declare class DeclaredException<F = unknown> extends RuntimeError {
8
+ readonly contract: ExceptionContract<F>;
9
+ readonly facts: F;
10
+ constructor(contract: ExceptionContract<F>, message: string, facts: F, options?: ErrorOptions);
11
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{RuntimeError}from"@weiliang0121/capix-contracts";import{isNonBlankString}from"../value/string.js";class ExceptionContract{static{__name(this,"ExceptionContract")}name;constructor(name){if(this.name=name,!isNonBlankString(name))throw new Error("Exception contract needs a name");Object.freeze(this)}create(message,facts,options){return new DeclaredException(this,message,facts,options)}}class DeclaredException extends RuntimeError{static{__name(this,"DeclaredException")}contract;facts;constructor(contract,message,facts,options){super(contract.name,message,facts,options),this.contract=contract,this.facts=facts}}export{DeclaredException,ExceptionContract};
@@ -0,0 +1,38 @@
1
+ export { Invocation, type InvocationOptions, type InvocationStarted } from './invocation/invocation.js';
2
+ export { InvocationContext, type InvocationControls, type ContextState } from './context/context.js';
3
+ export { CallableContext } from './context/callable.js';
4
+ export type { InvocationWork, InvocationProcess } from './invocation/work.js';
5
+ export type { InvocationResult } from './invocation/result.js';
6
+ export { failureFact, failureDiagnostic, type InvocationFailure, type InvocationPhase } from './invocation/failure.js';
7
+ export { Clock } from './clock.js';
8
+ export { InvocationChildren, type ParentInvocation, type InvocationChildBaseline } from './invocation/children.js';
9
+ export { InvocationRelation, type InvocationRelationOptions, type InvocationTarget, type InvocationRelationReception, type InvocationRelationBaseline, type InvocationRelationOwner, type InvocationRelationSetup } from './invocation/relation.js';
10
+ export type { InvocationReceptionBinding } from './invocation/reception.js';
11
+ export { invocationContextView, type InvocationContextView, type CallableContextView, type ContextViewOf, type ContextViewResources, type ContextFactsOf } from './context/view.js';
12
+ export { invocationView, childInvocationView, type InvocationView, type ChildInvocationView, type InvocationRelationView, type InvocationViewSource } from './invocation/view.js';
13
+ export { InvocationResources, type InvocationResourceOwner } from './invocation/resource-access.js';
14
+ export { attachInvocationResources, invocationResourceFailures } from './invocation/resources.js';
15
+ export { InvocationCancelled, isInvocationCancelled, requireNotCancelled } from './invocation/cancellation.js';
16
+ export { ExceptionContract, DeclaredException } from './exception/contract.js';
17
+ export { ChildCallFailure, inspectChildCallFailure, type InvocationExceptionOrigin, type InvocationExceptionChild } from './invocation/provenance.js';
18
+ export { combineOutputReceivers } from './output/delivery.js';
19
+ export { InvocationChangeEmitter } from './invocation/changes.js';
20
+ export type { InvocationProgress } from './invocation/progress.js';
21
+ export { invocationProgress } from './invocation/facts.js';
22
+ export type { InvocationFact, InvocationChange, InvocationDescription, InvocationIdentity, InvocationRelationIdentity, InvocationRelationChange, ResourceObservation, ResourceFact, BusinessObservation, BusinessEvent } from './observation/facts.js';
23
+ export type { InvocationObserver, EventConsumer } from './observation/observer.js';
24
+ export { InvocationObservation } from './observation/invocation.js';
25
+ export { ObserverSession, publishSessions } from './observation/session.js';
26
+ export { ObservationError } from './observation/error.js';
27
+ export type { CheckpointInstallation, CheckpointRestoration, CheckpointWriter, CheckpointFact, CheckpointSaveReferences, InvocationCheckpointSelection, InvocationCheckpointOccurrence } from './checkpoint/contract.js';
28
+ export type { InvocationCheckpointWork, CheckpointBinding, CheckpointChildBinding, CheckpointReferenceSlot } from './checkpoint/work.js';
29
+ export { prepareCheckpointRestoration } from './checkpoint/restoration.js';
30
+ export { captureCheckpointContinuation, restoreCheckpointContinuation, type CheckpointContinuationFact } from './checkpoint/continuation.js';
31
+ export { checkpointChildBinding, checkpointReceptionBinding, decodeCheckpointReception, decodeCheckpointHandledReception, checkCheckpointReferences, decodeCheckpointFrame, decodeCheckpointDiagnostic, type DecodedCheckpointReception, type DecodedCheckpointHandledReception, type DecodedCheckpointChild, type DecodedCheckpointFrame } from './checkpoint/facts.js';
32
+ export { RuntimeError } from '@weiliang0121/capix-contracts';
33
+ export { PersistenceError } from '@weiliang0121/capix-diagnostics';
34
+ export { RuntimeErrorHelper } from '@weiliang0121/capix-diagnostics';
35
+ export { isNonEmptyArray, hasUniqueItems } from './value/array.js';
36
+ export { isObjectLike, isObject } from './value/object.js';
37
+ export { nonBlankStringPattern, isNonBlankString } from './value/string.js';
38
+ export { invocationProcessStages, invocationProcessActions, type InvocationEvent, type InvocationProcessStage, type InvocationProcessAction, type InvocationRelationPhase } from './events.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ import{Invocation}from"./invocation/invocation.js";import{InvocationContext}from"./context/context.js";import{CallableContext}from"./context/callable.js";import{failureFact,failureDiagnostic}from"./invocation/failure.js";import{Clock}from"./clock.js";import{InvocationChildren}from"./invocation/children.js";import{InvocationRelation}from"./invocation/relation.js";import{invocationContextView}from"./context/view.js";import{invocationView,childInvocationView}from"./invocation/view.js";import{InvocationResources}from"./invocation/resource-access.js";import{attachInvocationResources,invocationResourceFailures}from"./invocation/resources.js";import{InvocationCancelled,isInvocationCancelled,requireNotCancelled}from"./invocation/cancellation.js";import{ExceptionContract,DeclaredException}from"./exception/contract.js";import{ChildCallFailure,inspectChildCallFailure}from"./invocation/provenance.js";import{combineOutputReceivers}from"./output/delivery.js";import{InvocationChangeEmitter}from"./invocation/changes.js";import{invocationProgress}from"./invocation/facts.js";import{InvocationObservation}from"./observation/invocation.js";import{ObserverSession,publishSessions}from"./observation/session.js";import{ObservationError}from"./observation/error.js";import{prepareCheckpointRestoration}from"./checkpoint/restoration.js";import{captureCheckpointContinuation,restoreCheckpointContinuation}from"./checkpoint/continuation.js";import{checkpointChildBinding,checkpointReceptionBinding,decodeCheckpointReception,decodeCheckpointHandledReception,checkCheckpointReferences,decodeCheckpointFrame,decodeCheckpointDiagnostic}from"./checkpoint/facts.js";import{RuntimeError}from"@weiliang0121/capix-contracts";import{PersistenceError}from"@weiliang0121/capix-diagnostics";import{RuntimeErrorHelper}from"@weiliang0121/capix-diagnostics";import{isNonEmptyArray,hasUniqueItems}from"./value/array.js";import{isObjectLike,isObject}from"./value/object.js";import{nonBlankStringPattern,isNonBlankString}from"./value/string.js";import{invocationProcessStages,invocationProcessActions}from"./events.js";export{CallableContext,ChildCallFailure,Clock,DeclaredException,ExceptionContract,Invocation,InvocationCancelled,InvocationChangeEmitter,InvocationChildren,InvocationContext,InvocationObservation,InvocationRelation,InvocationResources,ObservationError,ObserverSession,PersistenceError,RuntimeError,RuntimeErrorHelper,attachInvocationResources,captureCheckpointContinuation,checkCheckpointReferences,checkpointChildBinding,checkpointReceptionBinding,childInvocationView,combineOutputReceivers,decodeCheckpointDiagnostic,decodeCheckpointFrame,decodeCheckpointHandledReception,decodeCheckpointReception,failureDiagnostic,failureFact,hasUniqueItems,inspectChildCallFailure,invocationContextView,invocationProcessActions,invocationProcessStages,invocationProgress,invocationResourceFailures,invocationView,isInvocationCancelled,isNonBlankString,isNonEmptyArray,isObject,isObjectLike,nonBlankStringPattern,prepareCheckpointRestoration,publishSessions,requireNotCancelled,restoreCheckpointContinuation};
@@ -0,0 +1,8 @@
1
+ import { InvocationStopped } from './stop.js';
2
+ export declare class InvocationCancelled extends InvocationStopped {
3
+ #private;
4
+ constructor(signal: AbortSignal, options?: ErrorOptions);
5
+ belongsTo(signal: AbortSignal): boolean;
6
+ }
7
+ export declare function isInvocationCancelled(error: unknown, signal: AbortSignal): error is InvocationCancelled;
8
+ export declare function requireNotCancelled(signal: AbortSignal): void;
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{InvocationStopped}from"./stop.js";class InvocationCancelled extends InvocationStopped{static{__name(this,"InvocationCancelled")}#signal;constructor(signal,options){if(!signal.aborted)throw new TypeError("Invocation cancellation requires an aborted signal");super("INVOCATION_CANCELLED","\u8C03\u7528\u5DF2\u53D6\u6D88\uFF0C\u4E0D\u518D\u63A8\u8FDB\u540E\u7EED\u5DE5\u4F5C\u3002",void 0,options??{cause:signal.reason}),this.#signal=signal}belongsTo(signal){return this.#signal===signal}}function isInvocationCancelled(error,signal){return error instanceof InvocationCancelled&&error.belongsTo(signal)}__name(isInvocationCancelled,"isInvocationCancelled");function requireNotCancelled(signal){if(signal.aborted)throw new InvocationCancelled(signal)}__name(requireNotCancelled,"requireNotCancelled");export{InvocationCancelled,isInvocationCancelled,requireNotCancelled};
@@ -0,0 +1,13 @@
1
+ import type { InvocationEvent } from '../events.js';
2
+ import type { ChangeCapture } from '@weiliang0121/capix-changes';
3
+ import type { InvocationIdentity } from '../observation/facts.js';
4
+ export declare class InvocationChangeEmitter {
5
+ #private;
6
+ private readonly target;
7
+ private readonly identity;
8
+ constructor(identity: InvocationIdentity, target: ChangeCapture<InvocationEvent>);
9
+ publish(change: InvocationEvent['change'], order?: {
10
+ sequence: number;
11
+ occurredAt: string;
12
+ }): void;
13
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{captureChange}from"@weiliang0121/capix-changes";class InvocationChangeEmitter{static{__name(this,"InvocationChangeEmitter")}target;#sequence=0;identity;constructor(identity,target){this.target=target,this.identity=Object.freeze({...identity})}publish(change,order){const sequence=order?.sequence??++this.#sequence;captureChange(this.target,Object.freeze({type:"invocation",...this.identity,sequence,occurredAt:order?.occurredAt??new Date().toISOString(),change:Object.freeze({...change})}))}}export{InvocationChangeEmitter};
@@ -0,0 +1,72 @@
1
+ import type { Stable } from '@weiliang0121/capix-contracts';
2
+ import type { InvocationRelationChange, InvocationRelationIdentity } from '../observation/facts.js';
3
+ import type { InvocationFailure } from './failure.js';
4
+ import type { InvocationView } from './view.js';
5
+ import type { InvocationContext } from '../context/context.js';
6
+ import { InvocationRelation, type InvocationRelationOptions, type InvocationTarget, type InvocationRelationBaseline, type InvocationRelationOwner, type InvocationRelationSetup } from './relation.js';
7
+ import type { InvocationProgress } from './progress.js';
8
+ import { DeclaredException } from '../exception/contract.js';
9
+ import { type InvocationPropagationScope, type InvocationExceptionOrigin } from './provenance.js';
10
+ export interface ParentInvocation {
11
+ readonly context: InvocationContext;
12
+ readonly children: InvocationChildren;
13
+ readonly hasProgress?: boolean;
14
+ readonly recovering?: boolean;
15
+ requireHealthy?(): void;
16
+ publishProgress?(fact: InvocationProgress): void;
17
+ }
18
+ export interface InvocationChildBaseline extends InvocationRelationSetup {
19
+ readonly state: InvocationRelationBaseline;
20
+ }
21
+ export declare class InvocationChildren implements InvocationRelationOwner {
22
+ #private;
23
+ private readonly context;
24
+ private readonly failed?;
25
+ private readonly validate?;
26
+ private readonly observe?;
27
+ private readonly classifyFailure?;
28
+ readonly view: InvocationView['children'];
29
+ constructor(context: InvocationContext, failed?: ((failure: InvocationFailure) => void) | undefined, validate?: (() => void) | undefined, observe?: ((identity: InvocationRelationIdentity, change: InvocationRelationChange) => unknown | undefined) | undefined, classifyFailure?: ((error: unknown, origin: InvocationExceptionOrigin) => InvocationFailure) | undefined);
30
+ captureDelivery(): InvocationPropagationScope;
31
+ resolveDelivery(error: unknown): Readonly<{
32
+ exception: DeclaredException;
33
+ origin: InvocationExceptionOrigin;
34
+ }> | undefined;
35
+ private origin;
36
+ deliverReturn(relation: InvocationRelation, error: unknown, failure: InvocationFailure, scope: InvocationPropagationScope): unknown;
37
+ receptionFailure(relation: InvocationRelation, error: unknown, scope: InvocationPropagationScope): {
38
+ error: unknown;
39
+ failure: InvocationFailure;
40
+ delivery: unknown;
41
+ };
42
+ get reception(): Readonly<{
43
+ parentContextId: string;
44
+ childContextId: string;
45
+ }>;
46
+ requireHealthy(): void;
47
+ reject(error: unknown): void;
48
+ fail(failure: InvocationFailure): void;
49
+ publish(relation: InvocationRelation, change: InvocationRelationChange): unknown | undefined;
50
+ private relation;
51
+ run<Value>(target: InvocationTarget<Value>, work: () => Promise<Stable<Value>>): Promise<Stable<Value>>;
52
+ accepting<Value>(work: () => Promise<Value>): Promise<Value>;
53
+ settle(): Promise<void>;
54
+ settleAcceptances(): Promise<void> | undefined;
55
+ private drainAcceptances;
56
+ private track;
57
+ receive<Value>(relation: InvocationRelation, work: () => Promise<Value>): Promise<Value>;
58
+ attach<Output>(target: InvocationTarget<Output>, options?: InvocationRelationOptions): InvocationRelation<Output>;
59
+ adopt<Output>(target: InvocationTarget<Output>): InvocationRelation<Output>;
60
+ get<Output>(target: InvocationTarget<Output>): InvocationRelation<Output>;
61
+ get nextOrder(): number;
62
+ replaceSaved(id: string, target: InvocationTarget, state: InvocationRelationBaseline): void;
63
+ install(nextOrder: number, children: readonly InvocationChildBaseline[]): void;
64
+ values(): readonly InvocationRelation[];
65
+ byContextId(contextId: string): InvocationRelation | undefined;
66
+ trackFacts(): void;
67
+ get factRevision(): number;
68
+ changedFacts(): readonly InvocationRelation[];
69
+ acknowledgeFacts(revision: number): void;
70
+ readFacts<Value>(read: () => Value): Value;
71
+ changing(): void;
72
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{AsyncLocalStorage}from"node:async_hooks";import{InvocationRelation}from"./relation.js";import{DeclaredException}from"../exception/contract.js";import{InvocationProvenance}from"./provenance.js";const receptions=new AsyncLocalStorage;class InvocationChildren{static{__name(this,"InvocationChildren")}context;failed;validate;observe;classifyFailure;#items=new Map;#installed=new Set;#nextOrder=0;#receptionOwner=Symbol();view;#provenance;#calls=new Set;#acceptances=new Set;#trackingFacts=!1;#readingFacts=!1;#factRevision=0;#changedFacts=new Map;constructor(context,failed,validate,observe,classifyFailure){this.context=context,this.failed=failed,this.validate=validate,this.observe=observe,this.classifyFailure=classifyFailure,this.#provenance=new InvocationProvenance(context),this.view=Object.freeze({get:__name(invocation=>{const relation=this.values().find(item=>item.invocation.view===invocation||item.invocation.callView===invocation);if(!relation){const error=new Error("Invocation is not a direct child");throw this.reject(error),error}return relation.view},"get"),values:__name(()=>Object.freeze(this.values().map(relation=>relation.view)),"values")})}captureDelivery(){return this.#provenance.capture()}resolveDelivery(error){return this.#provenance.resolve(error)}origin(relation,kind){return Object.freeze({kind,child:Object.freeze({parentContextId:this.context.id,childContextId:relation.invocation.context.id,parentRound:relation.round,order:relation.order})})}deliverReturn(relation,error,failure,scope){return failure.kind==="exception"&&error instanceof DeclaredException?this.#provenance.deliver(scope,error,this.origin(relation,"child-return")):error}receptionFailure(relation,error,scope){let delivered=error;try{this.#provenance.require(scope,error),this.#provenance.resolve(error)}catch(invalid){delivered=invalid}const origin=this.origin(relation,"child-reception"),failure=this.classifyFailure?.(delivered,origin)??Object.freeze({kind:"error",contextId:this.context.id,phase:this.context.progress.phase,error:delivered});if(failure.kind!=="exception"||!(failure.error instanceof DeclaredException))return{error:failure.error,failure,delivery:failure.error};const propagated=this.#provenance.resolve(delivered);return{error:failure.error,failure,delivery:propagated?delivered:this.#provenance.deliver(scope,failure.error,origin)}}get reception(){this.requireHealthy();let reception=receptions.getStore();for(;reception&&reception.owner!==this.#receptionOwner;)reception=reception.parent;if(!reception?.active)throw new Error("Fixed entity operations require an active direct-child reception");return Object.freeze({parentContextId:this.context.id,childContextId:reception.childContextId})}requireHealthy(){this.validate?.()}reject(error){this.failed?.(Object.freeze({kind:"error",phase:this.context.progress.phase,contextId:this.context.id,error}))}fail(failure){this.failed?.(failure)}publish(relation,change){this.#trackingFacts&&this.#changedFacts.set(relation.invocation.context.id,++this.#factRevision);const identity=Object.freeze({parentContextId:this.context.id,childContextId:relation.invocation.context.id,parentRound:relation.round,...relation.key?{key:relation.key}:{}});return this.observe?.(identity,change)}relation(target,round,order,key,declarationPosition,receiveFailure){return new InvocationRelation({target,round,order,key,declarationPosition,receiveFailure},this)}run(target,work){return this.get(target),this.track(this.#calls,work)}accepting(work){return this.requireHealthy(),this.track(this.#acceptances,work)}async settle(){for(;this.#calls.size||this.#acceptances.size;)await Promise.all([...this.#calls,...this.#acceptances])}settleAcceptances(){if(this.#acceptances.size)return this.drainAcceptances()}async drainAcceptances(){for(;this.#acceptances.size;)await Promise.all(this.#acceptances)}track(activities,work){let release;const settled=new Promise(resolve=>{release=resolve});activities.add(settled);const complete=__name(()=>{activities.delete(settled),release()},"complete");try{const result=work();return result.then(complete,complete),result}catch(error){throw complete(),error}}async receive(relation,work){const childContextId=relation.invocation.context.id,reception={owner:this.#receptionOwner,childContextId,active:!0,parent:receptions.getStore()};try{return await receptions.run(reception,work)}finally{reception.active=!1}}attach(target,options={}){if(this.changing(),this.context.requireRunning(),this.requireHealthy(),this.#items.has(target.context.id))throw new Error("Child invocation is already attached");const relation=this.relation(target,this.context.progress.round,this.#nextOrder++,options.key,options.declarationPosition,options.receiveFailure);return this.#items.set(target.context.id,relation),this.publish(relation,{kind:"attached"}),this.requireHealthy(),relation}adopt(target){this.changing(),this.requireHealthy();const relation=this.#items.get(target.context.id);if(!relation||!this.#installed.has(target.context.id)||relation.returned||relation.invocation.context.status!=="running")throw new Error("Restored child is not the saved waiting child");return relation.replace(target),this.#installed.delete(target.context.id),relation}get(target){const relation=this.#items.get(target.context.id);if(!relation||relation.invocation!==target)throw new Error("Invocation is not a direct child");return relation}get nextOrder(){return this.#nextOrder}replaceSaved(id,target,state){this.changing();const relation=this.#items.get(id);if(!relation||!this.#installed.has(id))throw new Error("No saved child relation");if(target.context.id!==id)throw new Error("Restored child identity changed");relation.install(target,state),this.#trackingFacts&&this.#changedFacts.set(id,++this.#factRevision)}install(nextOrder,children){if(this.changing(),this.#items.size||this.#nextOrder)throw new Error("Child baseline already installed");this.#nextOrder=nextOrder;for(const child of children){const relation=this.relation(child.target,child.round,child.order,child.key,child.declarationPosition);relation.install(child.target,child.state),this.#items.set(child.target.context.id,relation),this.#installed.add(child.target.context.id)}}values(){return Object.freeze([...this.#items.values()])}byContextId(contextId){return this.#items.get(contextId)}trackFacts(){this.#trackingFacts=!0;for(const id of this.#items.keys())this.#changedFacts.set(id,++this.#factRevision)}get factRevision(){return this.#factRevision}changedFacts(){return[...this.#changedFacts.keys()].map(id=>this.#items.get(id))}acknowledgeFacts(revision){for(const[id,changed]of this.#changedFacts)changed<=revision&&this.#changedFacts.delete(id)}readFacts(read){if(this.#readingFacts)throw new Error("Invocation fact inspection cannot reenter");this.#readingFacts=!0;try{return read()}finally{this.#readingFacts=!1}}changing(){if(!this.#readingFacts)return;const error=new Error("Invocation facts cannot change during checkpoint inspection");throw this.reject(error),error}}export{InvocationChildren};
@@ -0,0 +1,8 @@
1
+ export declare class InvocationControl {
2
+ #private;
3
+ readonly signal: AbortSignal;
4
+ constructor(signal: AbortSignal);
5
+ start(): void;
6
+ requireActive(): void;
7
+ close(): void;
8
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{requireNotCancelled}from"./cancellation.js";class InvocationControl{static{__name(this,"InvocationControl")}signal;#started=!1;#closing=!1;constructor(signal){this.signal=signal}start(){if(this.#started)throw new Error("Invocation has already started");this.#started=!0}requireActive(){if(this.#closing)throw new Error("Invocation activity window is closed");requireNotCancelled(this.signal)}close(){this.#closing=!0}}export{InvocationControl};
@@ -0,0 +1,35 @@
1
+ import type { InvocationContext } from '../context/context.js';
2
+ import type { InvocationFailure, InvocationPhase } from './failure.js';
3
+ import type { InvocationExecutionWork, InvocationProcess } from './work.js';
4
+ import type { InvocationOutputReceiver, InvocationOutputWriter, OperationOutcome } from '@weiliang0121/capix-contracts';
5
+ import { type Stable } from '@weiliang0121/capix-contracts';
6
+ export interface InvocationExecutionControls {
7
+ healthy(): void;
8
+ active(): void;
9
+ reject(error: unknown): void;
10
+ classify(error: unknown, phase: InvocationPhase, forceError?: boolean): InvocationFailure;
11
+ settleAcceptances(): Promise<void> | undefined;
12
+ }
13
+ export interface InvocationExecutionOptions<Output> {
14
+ readonly signal: AbortSignal;
15
+ readonly process: (process: InvocationProcess) => void;
16
+ readonly validate?: () => void;
17
+ readonly output?: InvocationOutputReceiver<Output>;
18
+ }
19
+ export declare class InvocationExecution<Input, Output> {
20
+ #private;
21
+ private readonly context;
22
+ private readonly work;
23
+ private readonly controls;
24
+ private readonly options;
25
+ constructor(context: InvocationContext<Input, Output>, work: InvocationExecutionWork<Output>, controls: InvocationExecutionControls, options: InvocationExecutionOptions<Output>);
26
+ get outputWriter(): InvocationOutputWriter<unknown>;
27
+ get exitFailure(): InvocationFailure | undefined;
28
+ sealOutput(): void;
29
+ discardOutput(reason: 'failed' | 'exception'): void;
30
+ completeOutput(output: Stable<Output>): void;
31
+ run(resume?: () => Output | Stable<Output> | Promise<Output | Stable<Output>>): Promise<OperationOutcome<Stable<Output>, InvocationFailure>>;
32
+ private failed;
33
+ private closeFailure;
34
+ private reportFailure;
35
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{requireNotCancelled}from"./cancellation.js";import{InvocationOutputSection}from"../output/section.js";import{ProgressChannel}from"@weiliang0121/capix-changes";import{stableValue}from"@weiliang0121/capix-contracts";class InvocationExecution{static{__name(this,"InvocationExecution")}context;work;controls;options;#outputSection;#outputDelivery;#exitFailure;constructor(context,work,controls,options){this.context=context,this.work=work,this.controls=controls,this.options=options,this.#outputDelivery=options.output?new ProgressChannel(options.output):void 0}get outputWriter(){if(!this.#outputSection)throw new Error("Invocation has no executing output segment");return this.#outputSection.writer}get exitFailure(){return this.#exitFailure}sealOutput(){this.#outputSection?.seal()}discardOutput(reason){this.#outputSection?.discard(reason)}completeOutput(output){this.#outputSection?.complete(output)}async run(resume){try{this.controls.healthy(),requireNotCancelled(this.options.signal),resume||this.context.start(),this.options.validate?.(),this.controls.healthy(),this.#outputSection=new InvocationOutputSection(this.context.id,this.context.progress.round,this.work.output,this.controls,this.#outputDelivery),this.#outputSection.start(),this.options.process({stage:"execute",type:"start",input:this.context.currentInput})}catch(error){return this.failed(this.controls.classify(error,"execute",!0))}let body,fixingFailed=!1;try{this.controls.active();const candidate=await(resume?resume():this.work.execute());try{body={status:"succeeded",value:stableValue(candidate)}}catch(failure2){fixingFailed=!0,body={status:"failed",failure:failure2}}}catch(failure2){body={status:"failed",failure:failure2}}this.sealOutput();const settling=this.controls.settleAcceptances();settling&&await settling;let failure=body.status==="failed"?this.controls.classify(body.failure,"execute",fixingFailed):void 0;const closing=this.work.close();if(closing.status==="failed"&&(failure=this.closeFailure(failure,closing.failure)),failure){this.context.returned({status:"failed",error:failure.error,failure});try{this.reportFailure(failure)}catch(error){return this.failed({...this.controls.classify(error,"execute",!0),error,kind:"error",receptionAllowed:!1})}return this.failed(failure)}if(body.status==="failed")throw new Error("Missing execution failure classification");try{let output=body.value;return this.controls.healthy(),this.context.returned({status:"succeeded",output}),this.options.process({stage:"execute",type:"return",output}),this.controls.healthy(),this.options.validate?.(),requireNotCancelled(this.options.signal),output=this.#outputSection.validateResult(output),this.controls.healthy(),requireNotCancelled(this.options.signal),{status:"succeeded",value:output}}catch(error){return this.failed(this.controls.classify(error,"execute",!0))}}failed(failure){return this.#exitFailure=failure,{status:"failed",failure}}closeFailure(body,error){const closing=this.controls.classify(error,"control",!0),primary=body??closing,delivered=body||closing.error!==error?new AggregateError([primary.error,error],"Execution and Work close both failed",{cause:primary.error}):error;return this.controls.classify(delivered,"control",!0),Object.freeze({...primary,kind:"error",error:delivered,receptionAllowed:!1})}reportFailure(failure){try{this.options.process({stage:"execute",type:"throw",error:failure.error,failure})}catch(reportingError){throw new AggregateError([failure.error,reportingError],"Failure and its process reporting both failed",{cause:failure.error})}}}export{InvocationExecution};
@@ -0,0 +1,5 @@
1
+ import type { InvocationEvent } from '../events.js';
2
+ import type { InvocationFact } from '../observation/facts.js';
3
+ import type { InvocationProgress } from './progress.js';
4
+ export declare function invocationProgress(fact: InvocationFact, signal: AbortSignal): InvocationProgress;
5
+ export declare function invocationChange(fact: InvocationFact): InvocationEvent['change'];
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{isInvocationCancelled}from"./cancellation.js";import{failureFact}from"./failure.js";function invocationProgress(fact,signal){const description={};try{if(fact.description)for(const key of["id","name","label"]){const property=Object.getOwnPropertyDescriptor(fact.description,key);property&&"value"in property&&typeof property.value=="string"&&(description[key]=property.value)}}catch{}const base={identity:Object.freeze({contextId:fact.identity.contextId,kind:fact.identity.kind,...fact.identity.parentContextId?{parentContextId:fact.identity.parentContextId}:{}}),eventSequence:fact.eventSequence,occurredAt:fact.occurredAt,...Object.keys(description).length?{description:Object.freeze(description)}:{}};if(fact.kind==="started")return Object.freeze({...base,kind:"started"});if(fact.kind==="process")return Object.freeze({...base,kind:"process",processSequence:fact.processSequence,round:fact.round,stage:fact.process.stage,action:fact.process.type});if(fact.kind==="relation"){const relation=Object.freeze({parentContextId:fact.relation.parentContextId,childContextId:fact.relation.childContextId,parentRound:fact.relation.parentRound,...fact.relation.key?{key:fact.relation.key}:{}});if(fact.change.kind!=="returned")return Object.freeze({...base,kind:"relation",relation,phase:fact.change.kind});const result=fact.change.result,status2=result.status==="succeeded"?"succeeded":isInvocationCancelled(result.error,signal)?"cancelled":"failed";return Object.freeze({...base,kind:"relation",relation,phase:"returned",status:status2})}const state=fact.state,status=state.status==="succeeded"?"succeeded":state.status==="failed"&&isInvocationCancelled(state.error,signal)?"cancelled":"failed";return Object.freeze({...base,kind:"finished",status})}__name(invocationProgress,"invocationProgress");function invocationChange(fact){return fact.kind==="process"?{kind:"process",processSequence:fact.processSequence,round:fact.round,stage:fact.process.stage,action:fact.process.type}:fact.kind==="relation"?{kind:"relation",identity:fact.relation,phase:fact.change.kind,...fact.change.kind==="returned"?{status:fact.change.result.status,...fact.change.result.status==="failed"&&fact.change.result.failure?{failure:failureFact(fact.change.result.failure)}:{}}:{}}:fact.kind==="finished"?{kind:"finished",status:fact.state.status==="succeeded"?"succeeded":"failed"}:{kind:"started"}}__name(invocationChange,"invocationChange");export{invocationChange,invocationProgress};
@@ -0,0 +1,11 @@
1
+ import { type Stable, type InvocationFailureFact, type RuntimeErrorValue } from '@weiliang0121/capix-contracts';
2
+ import type { InvocationExceptionOrigin } from './provenance.js';
3
+ export interface InvocationFailure extends InvocationFailureFact {
4
+ readonly error: unknown;
5
+ readonly origin?: InvocationExceptionOrigin;
6
+ readonly receptionAllowed?: boolean;
7
+ }
8
+ export type InvocationPhase = InvocationFailureFact['phase'];
9
+ export declare function failureFact(failure: InvocationFailure): InvocationFailureFact;
10
+ export declare function failureDiagnostic(error: unknown): Stable<RuntimeErrorValue>;
11
+ export declare function containsFailure(error: AggregateError, failure: unknown): boolean;
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{stableValue}from"@weiliang0121/capix-contracts";import{RuntimeErrorHelper}from"@weiliang0121/capix-diagnostics";function failureFact(failure){return{kind:failure.kind,phase:failure.phase,contextId:failure.contextId,...failure.contract?{contract:failure.contract}:{}}}__name(failureFact,"failureFact");function failureDiagnostic(error){try{return stableValue(RuntimeErrorHelper.format(error))}catch{return stableValue({code:"UNREADABLE_ERROR",message:"[Uninspectable thrown value]"})}}__name(failureDiagnostic,"failureDiagnostic");function containsFailure(error,failure){try{const cause=Object.getOwnPropertyDescriptor(error,"cause");if(cause&&"value"in cause&&cause.value===failure)return!0;const errors=Object.getOwnPropertyDescriptor(error,"errors");return!errors||!("value"in errors)||!Array.isArray(errors.value)?!1:Object.entries(Object.getOwnPropertyDescriptors(errors.value)).some(([key,descriptor])=>/^(0|[1-9]\d*)$/.test(key)&&"value"in descriptor&&descriptor.value===failure)}catch{return!1}}__name(containsFailure,"containsFailure");export{containsFailure,failureDiagnostic,failureFact};
@@ -0,0 +1,83 @@
1
+ import type { CheckpointInstallation, CheckpointRestoration, CheckpointWriter } from '../checkpoint/contract.js';
2
+ import type { CheckpointBinding } from '../checkpoint/work.js';
3
+ import type { InvocationTarget } from './relation.js';
4
+ import type { InvocationOutputWriter, InvocationOutputReceiver, Stable } from '@weiliang0121/capix-contracts';
5
+ import { Clock } from '../clock.js';
6
+ import type { InvocationFailure, InvocationPhase } from './failure.js';
7
+ import { type ContextFactsOf } from '../context/view.js';
8
+ import { type InvocationView, type ChildInvocationView } from './view.js';
9
+ import { InvocationChildren, type ParentInvocation } from './children.js';
10
+ import type { InvocationRelationOptions } from './relation.js';
11
+ import type { InvocationChangeEmitter } from './changes.js';
12
+ import type { InvocationContext } from '../context/context.js';
13
+ import type { InvocationObservation } from '../observation/invocation.js';
14
+ import type { InvocationIdentity, InvocationDescription, BusinessEvent } from '../observation/facts.js';
15
+ import { type InvocationWork } from './work.js';
16
+ import { type ProgressReceiver } from '@weiliang0121/capix-changes';
17
+ import type { InvocationProgress } from './progress.js';
18
+ import type { InvocationExceptionOrigin } from './provenance.js';
19
+ export type InvocationStarted<Input, Output, Context extends InvocationContext<Input, Output>> = (context: Context, invocation: Invocation<Input, Output, Context>) => undefined;
20
+ export interface InvocationOptions<Input, Output, Context extends InvocationContext<Input, Output>> {
21
+ context: Context;
22
+ construction?: object;
23
+ checkpoints?: CheckpointInstallation;
24
+ restore?: CheckpointRestoration;
25
+ clock?: Clock;
26
+ parent?: {
27
+ invocation: ParentInvocation;
28
+ } & InvocationRelationOptions;
29
+ work: InvocationWork<Input, Output, Context>;
30
+ signal: AbortSignal;
31
+ observation?: InvocationObservation;
32
+ identity?: InvocationIdentity;
33
+ description?: InvocationDescription;
34
+ started?: InvocationStarted<Input, Output, Context>;
35
+ progress?: ProgressReceiver<InvocationProgress>;
36
+ output?: InvocationOutputReceiver<Output>;
37
+ validate?: () => void;
38
+ changes?: InvocationChangeEmitter;
39
+ }
40
+ export declare class Invocation<Input = unknown, Output = unknown, Context extends InvocationContext<Input, Output> = InvocationContext<Input, Output>> {
41
+ #private;
42
+ private readonly options;
43
+ readonly hasProgress: boolean;
44
+ readonly children: InvocationChildren;
45
+ readonly origin: Readonly<{
46
+ contextId: string;
47
+ }>;
48
+ readonly view: InvocationView<Input, Output, ContextFactsOf<Context>>;
49
+ readonly callView: ChildInvocationView<Input, Output, ContextFactsOf<Context>>;
50
+ constructor(options: InvocationOptions<Input, Output, Context>);
51
+ get context(): Context;
52
+ get construction(): object | undefined;
53
+ get identity(): InvocationIdentity;
54
+ get sequence(): number;
55
+ get failure(): InvocationFailure | undefined;
56
+ get outputWriter(): InvocationOutputWriter<unknown>;
57
+ sealOutput(): void;
58
+ get checkpointBinding(): CheckpointBinding | undefined;
59
+ get checkpointWriter(): CheckpointWriter | undefined;
60
+ get restoring(): boolean;
61
+ get recovering(): boolean;
62
+ get observation(): InvocationObservation | undefined;
63
+ run(): Promise<Stable<Output>>;
64
+ private deliver;
65
+ private closeResources;
66
+ private finishDelivery;
67
+ private runWork;
68
+ private startWork;
69
+ private failWork;
70
+ private failDelivery;
71
+ requireHealthy(): void;
72
+ requireActive(): void;
73
+ reject(error: unknown, allowException?: boolean): void;
74
+ classify(error: unknown, phase: InvocationPhase, forceError?: boolean, origin?: InvocationExceptionOrigin): InvocationFailure;
75
+ private classifyFailure;
76
+ restoreChild(position: number, contextId: string, create: () => InvocationTarget): InvocationTarget;
77
+ nextResourceSequence(): number;
78
+ observeBusiness(event: BusinessEvent): void;
79
+ private nextSequence;
80
+ publishProgress(fact: InvocationProgress): void;
81
+ private publishRelation;
82
+ private publish;
83
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{InvocationCheckpoint}from"../checkpoint/invocation.js";import{isUndefined}from"es-toolkit/predicate";import{Clock}from"../clock.js";import{DeclaredException}from"../exception/contract.js";import{isProtectedOperationFailure}from"../operation/failure.js";import{InvocationStopped}from"./stop.js";import{isInvocationCancelled}from"./cancellation.js";import{InvocationControl}from"./control.js";import{containsFailure}from"./failure.js";import{invocationContextView}from"../context/view.js";import{invocationView,childInvocationView}from"./view.js";import{InvocationChildren}from"./children.js";import{combineFaults}from"@weiliang0121/capix-changes";import{invocationChange,invocationProgress}from"./facts.js";import{InvocationExecution}from"./execution.js";import{connectInvocationWork}from"./work.js";import{ProgressChannel}from"@weiliang0121/capix-changes";class Invocation{static{__name(this,"Invocation")}options;hasProgress;#checkpoint;#control;#execution;#sequence=0;#eventSequence=0;#resourceSequence=0;#businessSequence=0;#clock;#progress;#identity;#fault;#classified;#failure;children;origin;view;callView;#parentRelation;#parentDeliveryScope;constructor(options){this.options=options,this.#control=new InvocationControl(options.signal),this.#clock=options.clock??new Clock,this.#progress=options.progress?new ProgressChannel(options.progress):void 0,this.hasProgress=!this.recovering&&(!!this.#progress||!!options.parent?.invocation.hasProgress),this.#identity=Object.freeze(options.identity?{...options.identity}:{contextId:options.context.id,kind:"kind"in options.context?options.context.kind:"node",...options.parent?{parentContextId:options.parent.invocation.context.id}:{}}),this.children=new InvocationChildren(options.context,failure=>{failure.kind==="error"&&!this.#fault&&(this.#fault=failure)},()=>this.requireActive(),(relation,change)=>this.publishRelation(relation,change),(error,origin)=>this.classify(error,this.context.progress.phase,!1,origin)),this.origin=Object.freeze({contextId:options.context.id});const context=invocationContextView(options.context),invocation=this,source={origin:this.origin,get sequence(){return invocation.sequence},get failure(){return invocation.failure},children:this.children.view};if(this.view=invocationView(source,context),this.callView=childInvocationView(source,context,()=>this.run()),options.restore&&!options.checkpoints)throw new Error("Checkpoint persistence is missing");this.#execution=new InvocationExecution(options.context,connectInvocationWork(options.work,options.context,this),{active:__name(()=>this.requireActive(),"active"),healthy:__name(()=>this.requireHealthy(),"healthy"),reject:__name(error=>this.reject(error),"reject"),classify:__name((error,phase,forceError)=>this.classify(error,phase,forceError),"classify"),settleAcceptances:__name(()=>this.children.settleAcceptances(),"settleAcceptances")},{signal:options.signal,validate:options.validate,output:options.output,process:__name(process=>this.publish({kind:"process",process,processSequence:this.nextSequence(),round:options.context.progress.round}),"process")}),this.#checkpoint=options.checkpoints?new InvocationCheckpoint(this,options.checkpoints,options.work.checkpoint,options.signal,options.restore):void 0,this.#parentRelation=options.parent?options.restore?options.parent.invocation.children.adopt(this):options.parent.invocation.children.attach(this,options.parent):void 0}get context(){return this.options.context}get construction(){return this.options.construction}get identity(){return this.#identity}get sequence(){return this.#sequence}get failure(){return this.#failure}get outputWriter(){return this.#execution.outputWriter}sealOutput(){this.#execution.sealOutput()}get checkpointBinding(){return this.options.work.checkpoint}get checkpointWriter(){return this.#checkpoint?.writer()}get restoring(){return!!this.options.restore}get recovering(){return this.restoring||!!this.options.parent?.invocation.recovering}get observation(){return this.recovering?this.#checkpoint?.observation:this.options.observation}run(){try{return this.#control.start(),this.#parentDeliveryScope=this.options.parent?.invocation.children.captureDelivery(),this.options.parent?this.options.parent.invocation.children.run(this,()=>this.deliver()):this.deliver()}catch(error){return this.options.parent?.invocation.children.reject(error),Promise.reject(error)}}async deliver(){try{let outcome;try{this.#checkpoint?.begin(),outcome={status:"succeeded",value:await this.runWork()}}catch(failure){outcome={status:"failed",failure}}this.#control.close();const closing=this.closeResources();if(closing.status==="failed"){const failure=outcome.status==="failed"?new AggregateError([outcome.failure,closing.failure],"Invocation work and resource close both failed",{cause:outcome.failure}):closing.failure;this.#classified=Object.freeze({...this.classify(failure,"control",!0),kind:"error",error:failure,receptionAllowed:!1}),outcome={status:"failed",failure}}const delivery=this.finishDelivery(outcome);if(delivery.status==="failed")throw delivery.failure;return delivery.value}finally{this.#control.close(),this.#checkpoint?.release()}}closeResources(){return"resources"in this.context?this.context.resources.closeAllResult():{status:"succeeded",value:void 0}}finishDelivery(outcome){if(outcome.status==="failed")return this.failDelivery(outcome.failure);try{return this.#checkpoint?.finish({status:"succeeded",output:outcome.value}),this.#parentRelation?.returnedWith({status:"succeeded",output:outcome.value}),outcome}catch(error){return this.failDelivery(error)}}async runWork(){const context=this.context;context.requireRunning();let outcome;try{this.startWork();const execution=await this.#execution.run(this.restoring?()=>this.#checkpoint.resume():void 0);outcome=execution.status==="succeeded"?execution:{status:"failed",failure:execution.failure.error}}catch(failure){outcome={status:"failed",failure}}if(this.#control.close(),await this.children.settle(),outcome.status==="failed")return this.failWork(outcome.failure);try{this.requireHealthy()}catch(error){return this.failWork(error)}return context.complete(outcome.value),this.#execution.completeOutput(outcome.value),this.publish({kind:"finished",state:context.state}),outcome.value}startWork(){const context=this.context;this.options.parent?.invocation.children.requireHealthy(),this.options.validate?.();const registered=this.options.started?.(context,this);if(registered!==void 0)throw Promise.resolve(registered).catch(()=>{}),new TypeError("Invocation started callbacks must return undefined synchronously");this.restoring||this.publish({kind:"started",input:context.input}),"resources"in context&&context.resources.start(this.options.restore?`checkpoint:${this.options.restore.head.image.point}`:"run")}failWork(error){const context=this.context,exit=this.#execution.exitFailure,failure=this.#fault??(exit&&exit.error===error?exit:this.#classified&&this.#classified.error===error?this.#classified:this.classify(error,context.progress.round?context.progress.phase:"setup",!0));this.#classified=failure;const delivered=error instanceof AggregateError?error:failure.error;this.#execution.discardOutput(failure.kind==="exception"?"exception":"failed"),context.fail(delivered,Object.freeze({...failure,error:delivered,...error instanceof AggregateError?{kind:"error"}:{}}));try{this.publish({kind:"finished",state:context.state})}catch(observed){throw new AggregateError([delivered,observed],"Call failure and its observation both failed",{cause:delivered})}throw delivered}failDelivery(error){const classified=this.#classified&&this.#classified.error===error?this.#classified:this.classify(error,this.context.status==="succeeded"?"observation":this.context.progress.phase,!0);let delivered=error instanceof AggregateError?error:classified.error,receptionAllowed=classified.receptionAllowed===!0&&!isProtectedOperationFailure(delivered);try{this.#checkpoint?.finish({status:isInvocationCancelled(delivered,this.options.signal)?"cancelled":"failed"})}catch(checkpointError){delivered=new AggregateError([delivered,checkpointError],"Invocation failure and terminal checkpoint save failed",{cause:delivered}),receptionAllowed=!1}return this.#failure=Object.freeze({...classified,...delivered instanceof AggregateError?{kind:"error"}:{},error:delivered,receptionAllowed}),this.context.status==="running"&&this.context.fail(delivered,this.#failure),this.#parentRelation?.returnedWith({status:"failed",error:delivered,failure:this.#failure}),{status:"failed",failure:this.#parentRelation&&this.#parentDeliveryScope?this.options.parent.invocation.children.deliverReturn(this.#parentRelation,delivered,this.#failure,this.#parentDeliveryScope):delivered}}requireHealthy(){if(this.#fault)throw this.#fault.error}requireActive(){this.requireHealthy(),this.context.requireRunning(),this.#control.requireActive()}reject(error,allowException=!1){this.classify(error,this.context.progress.phase,!allowException)}classify(error,phase,forceError=!1,origin){try{return this.classifyFailure(error,phase,forceError,origin)}catch(inspection){const causes=this.#fault&&this.#fault.error!==error?[this.#fault.error,error,inspection]:[error,inspection],failure=Object.freeze({kind:"error",phase,contextId:this.context.id,error:new InvocationStopped("FAILURE_CLASSIFICATION_FAILED","\u8C03\u7528\u5931\u8D25\u5206\u7C7B\u672A\u80FD\u5B8C\u6210\u3002",void 0,{cause:new AggregateError(causes,"Invocation failure and classification both failed")}),receptionAllowed:!1});return this.#classified=failure,this.#fault=failure,failure}}classifyFailure(error,phase,forceError,origin){if(this.#fault)return(["observation","control","setup"].includes(phase)||isProtectedOperationFailure(error))&&(this.#fault=Object.freeze({...this.#fault,receptionAllowed:!1})),error instanceof AggregateError&&containsFailure(error,this.#fault.error)&&(this.#fault=Object.freeze({...this.#fault,error})),this.#fault;let propagation;try{propagation=this.children.resolveDelivery(error)}catch(invalid){error=invalid,forceError=!0}const exception=propagation?.exception??error,allowed=!forceError&&exception instanceof DeclaredException,actual=forceError&&exception instanceof DeclaredException?new InvocationStopped("INVOCATION_FAILED","\u5FC5\u8981\u673A\u5236\u629B\u51FA\u7684\u5F02\u5E38\u4E0D\u80FD\u7531\u4E1A\u52A1\u5931\u8D25\u63A5\u6536\u5668\u5904\u7406\u3002",void 0,{cause:exception}):exception,source=propagation?.origin??origin??Object.freeze({kind:"self",phase:phase==="receive"?"accept":"execute"}),failure=Object.freeze({kind:allowed?"exception":"error",phase,contextId:this.context.id,...allowed?{contract:exception.contract.name,origin:source}:{},error:actual,receptionAllowed:!forceError&&!isProtectedOperationFailure(actual)});return this.#classified=failure,failure.kind==="error"&&(this.#fault=failure),failure}restoreChild(position,contextId,create){try{if(this.requireActive(),!this.#checkpoint)throw new Error("Child continuation requires a restored parent");return this.#checkpoint.restoreChild(position,contextId,create)}catch(error){throw this.#checkpoint?.reportFailure("restore",error,contextId),this.reject(error),error}}nextResourceSequence(){return++this.#resourceSequence}observeBusiness(event){if(this.requireActive(),!event||typeof event.event!="string"||!event.event.trim())throw new TypeError("Business observation needs an event name");const fact=Object.freeze({identity:this.identity,sequence:++this.#businessSequence,occurredAt:this.#clock.now(),event:Object.freeze({...event})}),failure=this.observation?.business.publish(fact);if(failure!==void 0)throw this.classify(failure,"observation",!0),failure}nextSequence(){return++this.#sequence}publishProgress(fact){this.recovering||(this.#progress?.publish(fact),this.options.parent?.invocation.publishProgress?.(fact))}publishRelation(relation,change){try{this.publish({kind:"relation",relation,change});return}catch(error){const failure=change.kind==="returned"&&change.result.status==="failed"&&this.#fault&&this.#fault.error!==error?new AggregateError([this.#fault.error,error],"Child return and parent observation both failed",{cause:this.#fault.error}):error;return this.classify(failure,"observation",!0),failure}}publish(change){const identity=this.#identity,fact=Object.freeze({...change,identity,description:this.options.description,eventSequence:++this.#eventSequence,occurredAt:this.#clock.now(),monotonicTime:this.#clock.tick()});if(this.hasProgress){const progress=invocationProgress(fact,this.options.signal);progress&&this.publishProgress(progress)}const faults=[];try{const captured=invocationChange(fact);(this.recovering?void 0:this.options.changes)?.publish(captured,{sequence:fact.eventSequence,occurredAt:fact.occurredAt})}catch(error2){faults.push(error2)}const observed=this.observation?.publish(fact);isUndefined(observed)||faults.push(observed);const error=combineFaults(faults);if(!isUndefined(error))throw this.classify(error,"observation",!0),error}}export{Invocation};
@@ -0,0 +1,33 @@
1
+ import type { InvocationIdentity } from '@weiliang0121/capix-contracts';
2
+ import type { InvocationProcess } from './work.js';
3
+ import type { InvocationRelationIdentity, InvocationRelationChange } from '../observation/facts.js';
4
+ export type InvocationProgress = Readonly<{
5
+ identity: InvocationIdentity;
6
+ eventSequence: number;
7
+ occurredAt: string;
8
+ description?: Readonly<{
9
+ id?: string;
10
+ name?: string;
11
+ label?: string;
12
+ }>;
13
+ } & ({
14
+ kind: 'started';
15
+ } | {
16
+ kind: 'process';
17
+ processSequence: number;
18
+ round: number;
19
+ stage: InvocationProcess['stage'];
20
+ action: InvocationProcess['type'];
21
+ } | {
22
+ kind: 'relation';
23
+ relation: InvocationRelationIdentity;
24
+ phase: Exclude<InvocationRelationChange['kind'], 'returned'>;
25
+ } | {
26
+ kind: 'relation';
27
+ relation: InvocationRelationIdentity;
28
+ phase: 'returned';
29
+ status: 'succeeded' | 'failed' | 'cancelled';
30
+ } | {
31
+ kind: 'finished';
32
+ status: 'succeeded' | 'failed' | 'cancelled';
33
+ })>;
@@ -0,0 +1 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */