@memberjunction/actions 5.29.0 → 5.30.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/README.md +9 -6
- package/dist/generic/ActionEngine.d.ts +45 -1
- package/dist/generic/ActionEngine.d.ts.map +1 -1
- package/dist/generic/ActionEngine.js +215 -14
- package/dist/generic/ActionEngine.js.map +1 -1
- package/package.json +11 -11
- package/readme.md +0 -416
package/README.md
CHANGED
|
@@ -393,21 +393,24 @@ This package depends on:
|
|
|
393
393
|
|
|
394
394
|
- [@memberjunction/global](../../MJGlobal/README.md) — ClassFactory and `@RegisterClass` decorator
|
|
395
395
|
- [@memberjunction/core](../../MJCore/README.md) — `Metadata`, `RunView`, `BaseEntity`, logging utilities
|
|
396
|
-
- [@memberjunction/actions-base](../Base/README.md) — Shared types (`ActionEngineBase`, `RunActionParams`, `ActionResult`,
|
|
396
|
+
- [@memberjunction/actions-base](../Base/README.md) — Shared types (`ActionEngineBase`, `RunActionParams`, `ActionResult`, `RuntimeActionBridgeBuilder` abstract)
|
|
397
397
|
- [@memberjunction/core-entities](../../MJCoreEntities/README.md) — Generated entity classes (`ActionExecutionLogEntity`, `ActionFilterEntity`, etc.)
|
|
398
|
-
- [@memberjunction/
|
|
399
|
-
- [@memberjunction/
|
|
400
|
-
- [@memberjunction/
|
|
401
|
-
|
|
398
|
+
- [@memberjunction/action-runtime](../Runtime/README.md) — Sandbox executor for `Type='Runtime'` actions
|
|
399
|
+
- [@memberjunction/code-execution](../CodeExecution/README.md) — `BridgeHandlerMap` type (host-side bridge passed to the sandbox)
|
|
400
|
+
- [@memberjunction/ai](../../AI/Core/README.md) — AI model integration (shared types)
|
|
401
|
+
|
|
402
|
+
**Not a direct dependency any longer**: `@memberjunction/ai-agents`, `@memberjunction/ai-prompts`, `@memberjunction/aiengine`, `@memberjunction/ai-core-plus`. These used to be pulled in for the Runtime-action bridge; the bridge was extracted into [`@memberjunction/action-runtime-host`](../RuntimeHost/README.md) (top of the Actions stack), and this package now resolves the concrete bridge builder via `MJGlobal.ClassFactory.CreateInstance(RuntimeActionBridgeBuilder)`. See the RuntimeHost README for the cycle-breaking architecture.
|
|
402
403
|
|
|
403
404
|
## Related Packages
|
|
404
405
|
|
|
405
406
|
- [@memberjunction/actions-base](../Base/README.md) — Shared types and base classes used by both client and server
|
|
407
|
+
- [@memberjunction/action-runtime](../Runtime/README.md) — Sandboxed executor for `Type='Runtime'` actions (approval gate, input/output wiring, isolated-vm dispatch)
|
|
408
|
+
- [@memberjunction/action-runtime-host](../RuntimeHost/README.md) — Default `utilities.*` bridge (md / rv / rq / entity / actions / agents / ai) exposed to sandboxed Runtime-action code
|
|
406
409
|
- [CoreActions](../CoreActions/) — Built-in action implementations (Create Record, generated actions, etc.)
|
|
407
410
|
- [ScheduledActions](../ScheduledActions/) — Scheduled action execution support
|
|
408
411
|
- [ApolloEnrichment](../ApolloEnrichment/) — Apollo data enrichment actions
|
|
409
412
|
- [ContentAutotag](../ContentAutotag/) — Content auto-tagging actions
|
|
410
|
-
- [CodeExecution](../CodeExecution/) —
|
|
413
|
+
- [CodeExecution](../CodeExecution/) — Isolated-vm sandbox + worker pool (`CodeExecutionService` used by `action-runtime`)
|
|
411
414
|
|
|
412
415
|
For the Actions system philosophy and development guide, see the [Actions CLAUDE.md](../CLAUDE.md).
|
|
413
416
|
|
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
import { MJActionExecutionLogEntity, MJActionFilterEntity } from "@memberjunction/core-entities";
|
|
2
|
-
import { ActionEngineBase, MJActionEntityExtended, ActionParam, ActionResult, RunActionParams } from "@memberjunction/actions-base";
|
|
2
|
+
import { ActionEngineBase, MJActionEntityExtended, ActionParam, ActionResult, ActionResultSimple, RunActionParams } from "@memberjunction/actions-base";
|
|
3
3
|
/**
|
|
4
4
|
* Base class for executing actions. This class can be sub-classed if desired if you would like to modify the logic across ALL actions. To do so, sub-class this class and use the
|
|
5
5
|
* @RegisterClass decorator from the @memberjunction/global package to register your sub-class with the ClassFactory. This will cause your sub-class to be used instead of this base class when the Metadata object insantiates the ActionEngine.
|
|
6
6
|
*/
|
|
7
7
|
export declare class ActionEngineServer extends ActionEngineBase {
|
|
8
8
|
static get Instance(): ActionEngineServer;
|
|
9
|
+
/**
|
|
10
|
+
* Engine-default wall-clock timeout applied to any action whose
|
|
11
|
+
* `MaxExecutionTimeMS` is NULL. Intentionally generous (2 hours) because
|
|
12
|
+
* some integration actions do legitimately long sync work; per-action
|
|
13
|
+
* overrides should be used to tighten this for anything agent-facing.
|
|
14
|
+
* Sub-classes can override to globally change the default.
|
|
15
|
+
*/
|
|
16
|
+
protected get DefaultActionTimeoutMS(): number;
|
|
9
17
|
RunAction(params: RunActionParams): Promise<ActionResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Wraps `InternalRunAction()` with a universal wall-clock timeout
|
|
20
|
+
* (`Action.MaxExecutionTimeMS`, falling back to `DefaultActionTimeoutMS`)
|
|
21
|
+
* and an `AbortSignal` passed to the action via `params.AbortSignal`.
|
|
22
|
+
*
|
|
23
|
+
* Enforcement is cooperative: when the timeout fires we set an abort on
|
|
24
|
+
* the signal so in-flight `fetch`/`setTimeout`/custom polling logic can
|
|
25
|
+
* short-circuit, and we race the action against a rejection that surfaces
|
|
26
|
+
* a `TIMEOUT` result. If the caller already supplied an `AbortSignal`
|
|
27
|
+
* (e.g. when being run from a Runtime-action bridge that has its own
|
|
28
|
+
* abort), we chain to it so either source can trigger cancellation.
|
|
29
|
+
*/
|
|
30
|
+
protected RunActionWithTimeout(params: RunActionParams): Promise<ActionResult>;
|
|
10
31
|
protected GetActionParamsForAction(action: MJActionEntityExtended): ActionParam[];
|
|
11
32
|
/**
|
|
12
33
|
* This method handles input validation. Subclasses can override this method to provide custom input validation.
|
|
@@ -23,6 +44,29 @@ export declare class ActionEngineServer extends ActionEngineBase {
|
|
|
23
44
|
*/
|
|
24
45
|
protected RunSingleFilter(params: RunActionParams, filter: MJActionFilterEntity): Promise<boolean>;
|
|
25
46
|
protected InternalRunAction(params: RunActionParams): Promise<ActionResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Resolves and runs a Custom / Generated action via the ClassFactory.
|
|
49
|
+
* This is the pre-existing path — factored out of `InternalRunAction` so
|
|
50
|
+
* the Type dispatch is readable.
|
|
51
|
+
*/
|
|
52
|
+
protected RunClassBasedAction(params: RunActionParams): Promise<ActionResultSimple>;
|
|
53
|
+
/**
|
|
54
|
+
* Runs an `Action.Type='Runtime'` action by delegating to the sandboxed
|
|
55
|
+
* RuntimeActionExecutor. Approval / Status / Code-presence checks are
|
|
56
|
+
* enforced inside the executor; here we parse the RuntimeActionConfiguration,
|
|
57
|
+
* build the permissioned bridge-handler map, and hand it off.
|
|
58
|
+
*
|
|
59
|
+
* The bridge handlers run in-process on the host (not inside the sandbox)
|
|
60
|
+
* so they have full access to Metadata, RunView, ActionEngine, etc.
|
|
61
|
+
* Permission enforcement against `RuntimeActionConfiguration.permissions`
|
|
62
|
+
* happens inside each handler — see `RuntimeActionBridge.ts`.
|
|
63
|
+
*
|
|
64
|
+
* If the configuration is missing or malformed, we still let the action
|
|
65
|
+
* run in pure-compute mode (no bridge). The action's Code can then only
|
|
66
|
+
* use `input` + `libs`; any attempt to call `utilities.*` at runtime
|
|
67
|
+
* rejects with a "handler not registered" error from the worker pool.
|
|
68
|
+
*/
|
|
69
|
+
protected RunRuntimeAction(params: RunActionParams): Promise<ActionResultSimple>;
|
|
26
70
|
protected StartActionLog(params: RunActionParams, saveRecord?: boolean): Promise<MJActionExecutionLogEntity>;
|
|
27
71
|
protected EndActionLog(logEntity: MJActionExecutionLogEntity, params: RunActionParams, result: ActionResult): Promise<void>;
|
|
28
72
|
protected StartAndEndActionLog(params: RunActionParams, result: ActionResult): Promise<MJActionExecutionLogEntity>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionEngine.d.ts","sourceRoot":"","sources":["../../src/generic/ActionEngine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"ActionEngine.d.ts","sourceRoot":"","sources":["../../src/generic/ActionEngine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAA8C,oBAAoB,EAAiD,MAAM,+BAA+B,CAAC;AAG5L,OAAO,EACH,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,eAAe,EAGlB,MAAM,8BAA8B,CAAC;AAMtC;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,gBAAgB;IAGrD,WAAkB,QAAQ,IAAI,kBAAkB,CAE/C;IAED;;;;;;OAMG;IACH,SAAS,KAAK,sBAAsB,IAAI,MAAM,CAE7C;IAEY,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAqCtE;;;;;;;;;;;OAWG;cACa,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAgFpF,SAAS,CAAC,wBAAwB,CAAC,MAAM,EAAE,sBAAsB,GAAG,WAAW,EAAE;IAqCjF;;OAEG;cACa,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzE;;OAEG;cACa,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrE;;;;OAIG;cACa,eAAe,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;cAKxF,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAqDjF;;;;OAIG;cACa,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAYzF;;;;;;;;;;;;;;;OAeG;cACa,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;cA6FtE,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,GAAE,OAAc,GAAG,OAAO,CAAC,0BAA0B,CAAC;cAqBxG,YAAY,CAAC,SAAS,EAAE,0BAA0B,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY;cAoBjG,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,0BAA0B,CAAC;CAM1H"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { LogError, Metadata } from "@memberjunction/core";
|
|
2
2
|
import { MJGlobal, SafeJSONParse, UUIDsEqual } from "@memberjunction/global";
|
|
3
3
|
import { BaseAction } from "./BaseAction.js";
|
|
4
|
-
import { ActionEngineBase } from "@memberjunction/actions-base";
|
|
4
|
+
import { ActionEngineBase, RuntimeActionConfigurationSchema, RuntimeActionBridgeBuilder } from "@memberjunction/actions-base";
|
|
5
|
+
import { RuntimeActionExecutor } from "@memberjunction/action-runtime";
|
|
5
6
|
/**
|
|
6
7
|
* Base class for executing actions. This class can be sub-classed if desired if you would like to modify the logic across ALL actions. To do so, sub-class this class and use the
|
|
7
8
|
* @RegisterClass decorator from the @memberjunction/global package to register your sub-class with the ClassFactory. This will cause your sub-class to be used instead of this base class when the Metadata object insantiates the ActionEngine.
|
|
@@ -10,6 +11,16 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
10
11
|
static get Instance() {
|
|
11
12
|
return super.getInstance();
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Engine-default wall-clock timeout applied to any action whose
|
|
16
|
+
* `MaxExecutionTimeMS` is NULL. Intentionally generous (2 hours) because
|
|
17
|
+
* some integration actions do legitimately long sync work; per-action
|
|
18
|
+
* overrides should be used to tighten this for anything agent-facing.
|
|
19
|
+
* Sub-classes can override to globally change the default.
|
|
20
|
+
*/
|
|
21
|
+
get DefaultActionTimeoutMS() {
|
|
22
|
+
return 2 * 60 * 60 * 1000;
|
|
23
|
+
}
|
|
13
24
|
async RunAction(params) {
|
|
14
25
|
const validInputs = await this.ValidateInputs(params);
|
|
15
26
|
if (!validInputs) {
|
|
@@ -39,8 +50,90 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
39
50
|
result.LogEntry = await this.StartAndEndActionLog(params, result);
|
|
40
51
|
}
|
|
41
52
|
}
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
return await this.RunActionWithTimeout(params);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Wraps `InternalRunAction()` with a universal wall-clock timeout
|
|
57
|
+
* (`Action.MaxExecutionTimeMS`, falling back to `DefaultActionTimeoutMS`)
|
|
58
|
+
* and an `AbortSignal` passed to the action via `params.AbortSignal`.
|
|
59
|
+
*
|
|
60
|
+
* Enforcement is cooperative: when the timeout fires we set an abort on
|
|
61
|
+
* the signal so in-flight `fetch`/`setTimeout`/custom polling logic can
|
|
62
|
+
* short-circuit, and we race the action against a rejection that surfaces
|
|
63
|
+
* a `TIMEOUT` result. If the caller already supplied an `AbortSignal`
|
|
64
|
+
* (e.g. when being run from a Runtime-action bridge that has its own
|
|
65
|
+
* abort), we chain to it so either source can trigger cancellation.
|
|
66
|
+
*/
|
|
67
|
+
async RunActionWithTimeout(params) {
|
|
68
|
+
const actionTimeoutMS = params.Action.MaxExecutionTimeMS ?? this.DefaultActionTimeoutMS;
|
|
69
|
+
// Chain with any upstream AbortSignal (e.g. Runtime-action bridge).
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
const externalSignal = params.AbortSignal;
|
|
72
|
+
const relayExternalAbort = () => {
|
|
73
|
+
if (!controller.signal.aborted) {
|
|
74
|
+
controller.abort(externalSignal?.reason ?? 'upstream abort');
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
if (externalSignal) {
|
|
78
|
+
if (externalSignal.aborted) {
|
|
79
|
+
relayExternalAbort();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
externalSignal.addEventListener('abort', relayExternalAbort, { once: true });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Wall-clock timeout.
|
|
86
|
+
const timeoutId = setTimeout(() => {
|
|
87
|
+
if (!controller.signal.aborted) {
|
|
88
|
+
controller.abort(`Action '${params.Action.Name}' exceeded MaxExecutionTimeMS (${actionTimeoutMS}ms)`);
|
|
89
|
+
}
|
|
90
|
+
}, actionTimeoutMS);
|
|
91
|
+
// Assign the chained signal onto params so BaseAction subclasses can poll it.
|
|
92
|
+
const previousSignal = params.AbortSignal;
|
|
93
|
+
params.AbortSignal = controller.signal;
|
|
94
|
+
try {
|
|
95
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
96
|
+
controller.signal.addEventListener('abort', () => {
|
|
97
|
+
reject(new Error(String(controller.signal.reason ?? 'aborted')));
|
|
98
|
+
}, { once: true });
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
return await Promise.race([this.InternalRunAction(params), timeoutPromise]);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
// Timeout or upstream abort — return a standard TIMEOUT result.
|
|
105
|
+
// Result is left undefined (we don't guarantee a 'TIMEOUT' ActionResultCode
|
|
106
|
+
// exists on every action; the Success flag + Message are the canonical
|
|
107
|
+
// failure signal for timeouts).
|
|
108
|
+
if (controller.signal.aborted) {
|
|
109
|
+
const message = typeof controller.signal.reason === 'string'
|
|
110
|
+
? controller.signal.reason
|
|
111
|
+
: `Action '${params.Action.Name}' was aborted`;
|
|
112
|
+
const timeoutResult = {
|
|
113
|
+
Success: false,
|
|
114
|
+
Message: message,
|
|
115
|
+
LogEntry: null,
|
|
116
|
+
Params: params.Params,
|
|
117
|
+
RunParams: params,
|
|
118
|
+
Result: undefined
|
|
119
|
+
};
|
|
120
|
+
if (!params.SkipActionLog) {
|
|
121
|
+
timeoutResult.LogEntry = await this.StartAndEndActionLog(params, timeoutResult);
|
|
122
|
+
}
|
|
123
|
+
return timeoutResult;
|
|
124
|
+
}
|
|
125
|
+
// Real runtime error unrelated to abort — rethrow so upstream handling catches it.
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
clearTimeout(timeoutId);
|
|
131
|
+
if (externalSignal) {
|
|
132
|
+
externalSignal.removeEventListener('abort', relayExternalAbort);
|
|
133
|
+
}
|
|
134
|
+
// Restore whatever AbortSignal the caller had in place so we don't leak our own.
|
|
135
|
+
params.AbortSignal = previousSignal;
|
|
136
|
+
}
|
|
44
137
|
}
|
|
45
138
|
GetActionParamsForAction(action) {
|
|
46
139
|
const params = action.Params.map((param) => {
|
|
@@ -104,20 +197,17 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
104
197
|
// temp stub above, replace with code that will run the filter
|
|
105
198
|
}
|
|
106
199
|
async InternalRunAction(params) {
|
|
107
|
-
// this is where the actual action code will be implemented
|
|
108
|
-
// first, let's get the right BaseAction derived sub-class for this particular action
|
|
109
|
-
// using ClassFactory
|
|
110
200
|
let logEntry;
|
|
111
201
|
if (!params.SkipActionLog) {
|
|
112
202
|
logEntry = await this.StartActionLog(params);
|
|
113
203
|
}
|
|
114
204
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
205
|
+
// Branch by Action.Type. Runtime actions go through the sandboxed
|
|
206
|
+
// RuntimeActionExecutor; Custom / Generated (and legacy rows where
|
|
207
|
+
// Type may be null) flow through the existing ClassFactory path.
|
|
208
|
+
const simpleResult = params.Action.Type === 'Runtime'
|
|
209
|
+
? await this.RunRuntimeAction(params)
|
|
210
|
+
: await this.RunClassBasedAction(params);
|
|
121
211
|
const resultCodeEntity = this.ActionResultCodes.find(r => UUIDsEqual(r.ActionID, params.Action.ID) &&
|
|
122
212
|
r.ResultCode.trim().toLowerCase() === simpleResult.ResultCode.trim().toLowerCase());
|
|
123
213
|
const result = {
|
|
@@ -126,7 +216,7 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
126
216
|
Message: simpleResult.Message,
|
|
127
217
|
AIDirectives: simpleResult.AIDirectives,
|
|
128
218
|
LogEntry: logEntry,
|
|
129
|
-
Params: simpleResult.Params || params.Params,
|
|
219
|
+
Params: simpleResult.Params || params.Params,
|
|
130
220
|
Result: resultCodeEntity
|
|
131
221
|
};
|
|
132
222
|
if (logEntry) {
|
|
@@ -151,6 +241,111 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
151
241
|
return result;
|
|
152
242
|
}
|
|
153
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Resolves and runs a Custom / Generated action via the ClassFactory.
|
|
246
|
+
* This is the pre-existing path — factored out of `InternalRunAction` so
|
|
247
|
+
* the Type dispatch is readable.
|
|
248
|
+
*/
|
|
249
|
+
async RunClassBasedAction(params) {
|
|
250
|
+
const action = MJGlobal.Instance.ClassFactory.CreateInstance(BaseAction, params.Action.DriverClass || params.Action.Name, params.ContextUser);
|
|
251
|
+
if (!action || action.constructor === BaseAction) {
|
|
252
|
+
throw new Error(`Could not find a class for action ${params.Action.Name}.`);
|
|
253
|
+
}
|
|
254
|
+
return await action.Run(params);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Runs an `Action.Type='Runtime'` action by delegating to the sandboxed
|
|
258
|
+
* RuntimeActionExecutor. Approval / Status / Code-presence checks are
|
|
259
|
+
* enforced inside the executor; here we parse the RuntimeActionConfiguration,
|
|
260
|
+
* build the permissioned bridge-handler map, and hand it off.
|
|
261
|
+
*
|
|
262
|
+
* The bridge handlers run in-process on the host (not inside the sandbox)
|
|
263
|
+
* so they have full access to Metadata, RunView, ActionEngine, etc.
|
|
264
|
+
* Permission enforcement against `RuntimeActionConfiguration.permissions`
|
|
265
|
+
* happens inside each handler — see `RuntimeActionBridge.ts`.
|
|
266
|
+
*
|
|
267
|
+
* If the configuration is missing or malformed, we still let the action
|
|
268
|
+
* run in pure-compute mode (no bridge). The action's Code can then only
|
|
269
|
+
* use `input` + `libs`; any attempt to call `utilities.*` at runtime
|
|
270
|
+
* rejects with a "handler not registered" error from the worker pool.
|
|
271
|
+
*/
|
|
272
|
+
async RunRuntimeAction(params) {
|
|
273
|
+
// Extract + validate the RuntimeActionConfiguration JSON blob. Uses
|
|
274
|
+
// the strongly-typed accessor from @memberjunction/core-entities
|
|
275
|
+
// (emitted by the JSONType codegen) rather than parsing the raw string.
|
|
276
|
+
const actionEntity = params.Action;
|
|
277
|
+
const rawConfig = actionEntity.RuntimeActionConfigurationObject;
|
|
278
|
+
let bridgeHandlers;
|
|
279
|
+
let preamble = '';
|
|
280
|
+
let maxBridgeCalls;
|
|
281
|
+
if (rawConfig) {
|
|
282
|
+
const parsed = RuntimeActionConfigurationSchema.safeParse(rawConfig);
|
|
283
|
+
if (!parsed.success) {
|
|
284
|
+
return {
|
|
285
|
+
Success: false,
|
|
286
|
+
ResultCode: 'INVALID_CONFIG',
|
|
287
|
+
Message: `Runtime action '${params.Action.Name}' has a malformed ` +
|
|
288
|
+
`RuntimeActionConfiguration: ${parsed.error.message}`,
|
|
289
|
+
Params: params.Params
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
// Cast to the JSONType-emitted interface: the Zod-inferred type
|
|
293
|
+
// has optional fields due to how `z.object()` composes with this
|
|
294
|
+
// repo's non-strict TS config; the runtime validation above has
|
|
295
|
+
// already proven the shape is valid, so the narrowing cast is safe.
|
|
296
|
+
const config = parsed.data;
|
|
297
|
+
// Resolve the concrete bridge builder via MJ's ClassFactory. The
|
|
298
|
+
// implementation lives in `@memberjunction/action-runtime-host`
|
|
299
|
+
// (top of the stack — can statically import AIEngine, AgentRunner,
|
|
300
|
+
// ActionEngineServer, etc. without creating a cycle). If nothing
|
|
301
|
+
// is registered (the host package wasn't imported), we fall through
|
|
302
|
+
// to pure-compute mode: the user's Runtime action still runs, it
|
|
303
|
+
// just can't call any `utilities.*` bridge namespaces.
|
|
304
|
+
const builder = MJGlobal.Instance.ClassFactory.CreateInstance(RuntimeActionBridgeBuilder);
|
|
305
|
+
if (builder) {
|
|
306
|
+
bridgeHandlers = builder.BuildHandlers({
|
|
307
|
+
action: params.Action,
|
|
308
|
+
config,
|
|
309
|
+
contextUser: params.ContextUser,
|
|
310
|
+
abortSignal: params.AbortSignal
|
|
311
|
+
});
|
|
312
|
+
preamble = builder.GetPreamble();
|
|
313
|
+
}
|
|
314
|
+
maxBridgeCalls = config.limits?.maxBridgeCalls;
|
|
315
|
+
}
|
|
316
|
+
// If we built a preamble, inject it BEFORE the user's code so
|
|
317
|
+
// `globalThis.utilities` is available from the first line. The
|
|
318
|
+
// executor wraps everything in an async IIFE — the preamble runs
|
|
319
|
+
// inside that same IIFE.
|
|
320
|
+
const codeToRun = preamble
|
|
321
|
+
? `${preamble}\n${params.Action.Code ?? ''}`
|
|
322
|
+
: params.Action.Code ?? '';
|
|
323
|
+
// We mutate a defensive copy of the action entity so the executor sees
|
|
324
|
+
// the prepended preamble without modifying the live MJActionEntity
|
|
325
|
+
// instance (which the rest of the ActionEngine may still reference).
|
|
326
|
+
const actionForExecution = Object.create(Object.getPrototypeOf(params.Action), Object.getOwnPropertyDescriptors(params.Action));
|
|
327
|
+
// The executor checks `action.Code`; override just that getter.
|
|
328
|
+
Object.defineProperty(actionForExecution, 'Code', {
|
|
329
|
+
value: codeToRun,
|
|
330
|
+
writable: false,
|
|
331
|
+
enumerable: true,
|
|
332
|
+
configurable: true
|
|
333
|
+
});
|
|
334
|
+
const execResult = await RuntimeActionExecutor.Instance.execute({
|
|
335
|
+
action: actionForExecution,
|
|
336
|
+
params: params.Params ?? [],
|
|
337
|
+
contextUser: params.ContextUser,
|
|
338
|
+
abortSignal: params.AbortSignal,
|
|
339
|
+
bridgeHandlers,
|
|
340
|
+
maxBridgeCalls
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
Success: execResult.success,
|
|
344
|
+
ResultCode: execResult.resultCode,
|
|
345
|
+
Message: execResult.message,
|
|
346
|
+
Params: execResult.params
|
|
347
|
+
};
|
|
348
|
+
}
|
|
154
349
|
async StartActionLog(params, saveRecord = true) {
|
|
155
350
|
// this is where the log entry for the action run will be created
|
|
156
351
|
const md = new Metadata();
|
|
@@ -173,7 +368,13 @@ export class ActionEngineServer extends ActionEngineBase {
|
|
|
173
368
|
async EndActionLog(logEntity, params, result) {
|
|
174
369
|
// this is where the log entry for the action run will be created
|
|
175
370
|
logEntity.EndedAt = new Date();
|
|
176
|
-
|
|
371
|
+
// Persist the final merged param set (inputs + outputs) — Runtime actions
|
|
372
|
+
// return a fresh array from the sandbox executor that lives on
|
|
373
|
+
// `result.Params`, so logging `params.Params` would lose every new output
|
|
374
|
+
// key. Custom/Generated actions mutate `params.Params` in place, and
|
|
375
|
+
// `result.Params` falls back to that same reference, so they remain
|
|
376
|
+
// equivalent.
|
|
377
|
+
logEntity.Params = JSON.stringify(result.Params ?? params.Params);
|
|
177
378
|
logEntity.ResultCode = result.Result?.ResultCode;
|
|
178
379
|
logEntity.Message = result.Message;
|
|
179
380
|
// save a second time to record the action ending
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionEngine.js","sourceRoot":"","sources":["../../src/generic/ActionEngine.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActionEngine.js","sourceRoot":"","sources":["../../src/generic/ActionEngine.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/actions",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.30.0",
|
|
5
5
|
"description": "Main library for MemberJunction Actions. This library is only intended to be imported on the server side.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"start": "ts-node-dev src/index.ts",
|
|
13
13
|
"build": "tsc && tsc-alias -f",
|
|
14
|
-
"test": "
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest"
|
|
15
16
|
},
|
|
16
17
|
"author": "MemberJunction.com",
|
|
17
18
|
"license": "ISC",
|
|
@@ -20,15 +21,14 @@
|
|
|
20
21
|
"typescript": "^5.9.3"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"@memberjunction/
|
|
24
|
-
"@memberjunction/
|
|
25
|
-
"@memberjunction/
|
|
26
|
-
"@memberjunction/
|
|
27
|
-
"@memberjunction/
|
|
28
|
-
"@memberjunction/
|
|
29
|
-
"@memberjunction/
|
|
30
|
-
"@memberjunction/
|
|
31
|
-
"@memberjunction/doc-utils": "5.29.0"
|
|
24
|
+
"@memberjunction/action-runtime": "5.30.0",
|
|
25
|
+
"@memberjunction/actions-base": "5.30.0",
|
|
26
|
+
"@memberjunction/ai": "5.30.0",
|
|
27
|
+
"@memberjunction/code-execution": "5.30.0",
|
|
28
|
+
"@memberjunction/core": "5.30.0",
|
|
29
|
+
"@memberjunction/core-entities": "5.30.0",
|
|
30
|
+
"@memberjunction/doc-utils": "5.30.0",
|
|
31
|
+
"@memberjunction/global": "5.30.0"
|
|
32
32
|
},
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
package/readme.md
DELETED
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
# @memberjunction/actions
|
|
2
|
-
|
|
3
|
-
Server-side action execution engine for MemberJunction. This package provides the runtime infrastructure for executing actions — including input validation, filter evaluation, ClassFactory-based action dispatch, execution logging, OAuth token management, and entity-bound action invocation. It is intended for server-side use only.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @memberjunction/actions
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
The Actions Engine sits between external consumers (AI agents, workflows, APIs) and the actual action implementations registered via `@RegisterClass`. It handles the full execution lifecycle: validating inputs, running pre-execution filters, dispatching to the correct `BaseAction` subclass via ClassFactory, and logging results.
|
|
14
|
-
|
|
15
|
-
The package contains two subsystems:
|
|
16
|
-
|
|
17
|
-
- **Generic Action Engine** — Executes standalone actions with validation, filtering, and logging
|
|
18
|
-
- **Entity Action Engine** — Executes actions bound to entity records, supporting CRUD lifecycle hooks, list/view batch operations, and record validation
|
|
19
|
-
|
|
20
|
-
```mermaid
|
|
21
|
-
flowchart TD
|
|
22
|
-
subgraph Consumers["External Consumers"]
|
|
23
|
-
Agent["AI Agents"]
|
|
24
|
-
WF["Workflows"]
|
|
25
|
-
API["GraphQL API"]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
subgraph Engine["@memberjunction/actions"]
|
|
29
|
-
AES["ActionEngineServer"]
|
|
30
|
-
EAES["EntityActionEngineServer"]
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
subgraph Pipeline["Execution Pipeline"]
|
|
34
|
-
Validate["Validate Inputs"]
|
|
35
|
-
Filter["Run Filters"]
|
|
36
|
-
Dispatch["ClassFactory Dispatch"]
|
|
37
|
-
Log["Execution Logging"]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
subgraph Actions["Registered Actions"]
|
|
41
|
-
BA["BaseAction Subclasses"]
|
|
42
|
-
OAuth["BaseOAuthAction Subclasses"]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
Consumers --> Engine
|
|
46
|
-
AES --> Validate --> Filter --> Dispatch --> Log
|
|
47
|
-
Dispatch --> BA
|
|
48
|
-
Dispatch --> OAuth
|
|
49
|
-
EAES --> AES
|
|
50
|
-
|
|
51
|
-
style Consumers fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
52
|
-
style Engine fill:#7c5295,stroke:#563a6b,color:#fff
|
|
53
|
-
style Pipeline fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
54
|
-
style Actions fill:#b8762f,stroke:#8a5722,color:#fff
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Key Features
|
|
58
|
-
|
|
59
|
-
- **Action Execution Pipeline** — Validates inputs, evaluates filters, dispatches via ClassFactory, and logs all executions
|
|
60
|
-
- **ClassFactory Dispatch** — Looks up `BaseAction` subclasses by `DriverClass` or action name at runtime
|
|
61
|
-
- **Pre-Execution Filters** — `BaseActionFilter` subclasses can gate whether an action should run
|
|
62
|
-
- **Execution Logging** — Automatic start/end logging to `Action Execution Logs` entity with params and result codes
|
|
63
|
-
- **OAuth Token Management** — `BaseOAuthAction` provides token lifecycle (refresh, retry on auth failure, persistence)
|
|
64
|
-
- **OAuth2Manager** — Standalone OAuth2 client supporting authorization code, client credentials, and refresh token flows
|
|
65
|
-
- **Entity Action Invocation** — Bind actions to entity CRUD lifecycle events (BeforeCreate, AfterUpdate, etc.)
|
|
66
|
-
- **Batch Entity Actions** — Run actions against Lists or Views of records with consolidated results
|
|
67
|
-
- **Script Evaluation** — Entity action params support runtime script evaluation with entity context
|
|
68
|
-
|
|
69
|
-
## Usage
|
|
70
|
-
|
|
71
|
-
### Running a Standalone Action
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
import { ActionEngineServer } from '@memberjunction/actions';
|
|
75
|
-
|
|
76
|
-
// Configure the engine (typically done once at startup)
|
|
77
|
-
await ActionEngineServer.Instance.Config(false, contextUser);
|
|
78
|
-
|
|
79
|
-
// Find the action by name
|
|
80
|
-
const action = ActionEngineServer.Instance.Actions.find(a => a.Name === 'Send Email');
|
|
81
|
-
|
|
82
|
-
// Execute it
|
|
83
|
-
const result = await ActionEngineServer.Instance.RunAction({
|
|
84
|
-
Action: action,
|
|
85
|
-
ContextUser: contextUser,
|
|
86
|
-
Params: [
|
|
87
|
-
{ Name: 'to', Value: 'user@example.com', Type: 'Input' },
|
|
88
|
-
{ Name: 'subject', Value: 'Hello', Type: 'Input' },
|
|
89
|
-
{ Name: 'body', Value: 'Message content', Type: 'Input' }
|
|
90
|
-
],
|
|
91
|
-
Filters: []
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
if (result.Success) {
|
|
95
|
-
console.log('Action completed:', result.Message);
|
|
96
|
-
} else {
|
|
97
|
-
console.error('Action failed:', result.Message);
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Creating a Custom Action
|
|
102
|
-
|
|
103
|
-
All actions extend `BaseAction` and implement `InternalRunAction`. Register them with `@RegisterClass` so the engine can discover them via ClassFactory:
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { RegisterClass } from '@memberjunction/global';
|
|
107
|
-
import { BaseAction } from '@memberjunction/actions';
|
|
108
|
-
import { RunActionParams, ActionResultSimple } from '@memberjunction/actions-base';
|
|
109
|
-
|
|
110
|
-
@RegisterClass(BaseAction, 'My Custom Action')
|
|
111
|
-
export class MyCustomAction extends BaseAction {
|
|
112
|
-
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
113
|
-
const inputValue = params.Params.find(p => p.Name === 'input')?.Value;
|
|
114
|
-
|
|
115
|
-
// Your action logic here
|
|
116
|
-
const result = await this.doWork(inputValue);
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
Success: true,
|
|
120
|
-
ResultCode: 'SUCCESS',
|
|
121
|
-
Message: `Processed: ${result}`
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private async doWork(input: string): Promise<string> {
|
|
126
|
-
// Delegate to service classes for real logic
|
|
127
|
-
return `Done with ${input}`;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Creating an OAuth-Authenticated Action
|
|
133
|
-
|
|
134
|
-
For actions that need to call external APIs with OAuth2 credentials:
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import { RegisterClass } from '@memberjunction/global';
|
|
138
|
-
import { BaseOAuthAction } from '@memberjunction/actions';
|
|
139
|
-
import { RunActionParams, ActionResultSimple } from '@memberjunction/actions-base';
|
|
140
|
-
|
|
141
|
-
@RegisterClass(BaseAction, 'Fetch External Data')
|
|
142
|
-
export class FetchExternalDataAction extends BaseOAuthAction {
|
|
143
|
-
protected async refreshAccessToken(): Promise<void> {
|
|
144
|
-
// Platform-specific token refresh logic
|
|
145
|
-
const response = await fetch('https://api.example.com/oauth/token', {
|
|
146
|
-
method: 'POST',
|
|
147
|
-
body: new URLSearchParams({
|
|
148
|
-
grant_type: 'refresh_token',
|
|
149
|
-
refresh_token: this.getRefreshToken(),
|
|
150
|
-
})
|
|
151
|
-
});
|
|
152
|
-
const data = await response.json();
|
|
153
|
-
await this.updateStoredTokens(data.access_token, data.refresh_token, data.expires_in);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
157
|
-
const companyIntegrationId = params.Params.find(
|
|
158
|
-
p => p.Name === 'CompanyIntegrationID'
|
|
159
|
-
)?.Value as string;
|
|
160
|
-
|
|
161
|
-
// Initialize OAuth (loads tokens, refreshes if expired)
|
|
162
|
-
if (!await this.initializeOAuth(companyIntegrationId)) {
|
|
163
|
-
return this.handleOAuthError(new Error('OAuth initialization failed'));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Make authenticated request with automatic retry on 401
|
|
167
|
-
const data = await this.makeAuthenticatedRequest(async (token) => {
|
|
168
|
-
const res = await fetch('https://api.example.com/data', {
|
|
169
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
170
|
-
});
|
|
171
|
-
return res.json();
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
return { Success: true, ResultCode: 'SUCCESS', Message: JSON.stringify(data) };
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
### Using OAuth2Manager Directly
|
|
180
|
-
|
|
181
|
-
For standalone OAuth2 token management outside the action framework:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
import { OAuth2Manager } from '@memberjunction/actions';
|
|
185
|
-
|
|
186
|
-
const oauth = new OAuth2Manager({
|
|
187
|
-
clientId: 'your-client-id',
|
|
188
|
-
clientSecret: 'your-client-secret',
|
|
189
|
-
tokenEndpoint: 'https://api.example.com/oauth/token',
|
|
190
|
-
scopes: ['read', 'write'],
|
|
191
|
-
onTokenUpdate: async (tokens) => {
|
|
192
|
-
// Persist tokens to your storage
|
|
193
|
-
await saveTokens(tokens);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
// Get a valid token (auto-refreshes if expired)
|
|
198
|
-
const token = await oauth.getAccessToken();
|
|
199
|
-
|
|
200
|
-
// Or use client credentials flow
|
|
201
|
-
const tokenData = await oauth.getClientCredentialsToken();
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Architecture
|
|
205
|
-
|
|
206
|
-
### Action Execution Pipeline
|
|
207
|
-
|
|
208
|
-
The `ActionEngineServer.RunAction()` method follows this sequence:
|
|
209
|
-
|
|
210
|
-
```mermaid
|
|
211
|
-
sequenceDiagram
|
|
212
|
-
participant Caller
|
|
213
|
-
participant Engine as ActionEngineServer
|
|
214
|
-
participant Filter as BaseActionFilter
|
|
215
|
-
participant CF as ClassFactory
|
|
216
|
-
participant Action as BaseAction Subclass
|
|
217
|
-
participant Log as Execution Log
|
|
218
|
-
|
|
219
|
-
Caller->>Engine: RunAction(params)
|
|
220
|
-
Engine->>Engine: ValidateInputs(params)
|
|
221
|
-
alt Validation fails
|
|
222
|
-
Engine->>Log: StartAndEndActionLog()
|
|
223
|
-
Engine-->>Caller: {Success: false}
|
|
224
|
-
end
|
|
225
|
-
Engine->>Filter: RunFilters(params)
|
|
226
|
-
alt Filters block execution
|
|
227
|
-
Engine->>Log: StartAndEndActionLog()
|
|
228
|
-
Engine-->>Caller: {Success: true, "Filters blocked"}
|
|
229
|
-
end
|
|
230
|
-
Engine->>Log: StartActionLog()
|
|
231
|
-
Engine->>CF: CreateInstance(BaseAction, driverClass)
|
|
232
|
-
CF-->>Engine: action instance
|
|
233
|
-
Engine->>Action: Run(params)
|
|
234
|
-
Action->>Action: InternalRunAction(params)
|
|
235
|
-
Action-->>Engine: ActionResultSimple
|
|
236
|
-
Engine->>Log: EndActionLog()
|
|
237
|
-
Engine-->>Caller: ActionResult
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Entity Action Invocation
|
|
241
|
-
|
|
242
|
-
Entity actions are bound to entity lifecycle events. The `EntityActionEngineServer` delegates to invocation-type-specific handlers via ClassFactory:
|
|
243
|
-
|
|
244
|
-
```mermaid
|
|
245
|
-
classDiagram
|
|
246
|
-
class EntityActionInvocationBase {
|
|
247
|
-
<<abstract>>
|
|
248
|
-
+InvokeAction(params) EntityActionResult
|
|
249
|
-
+MapParams(params, entityActionParams, entity) ActionParam[]
|
|
250
|
-
+SafeEvalScript(id, script, entity) any
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
class SingleRecord {
|
|
254
|
-
+InvokeAction(params) EntityActionResult
|
|
255
|
-
+ValidateParams(params) boolean
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
class MultipleRecords {
|
|
259
|
-
+InvokeAction(params) EntityActionResult
|
|
260
|
-
#GetRecordList() BaseEntity[]
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
class Validate {
|
|
264
|
-
+InvokeAction(params) EntityActionResult
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
EntityActionInvocationBase <|-- SingleRecord
|
|
268
|
-
EntityActionInvocationBase <|-- MultipleRecords
|
|
269
|
-
SingleRecord <|-- Validate
|
|
270
|
-
|
|
271
|
-
note for SingleRecord "Registered for: Read, BeforeCreate,\nBeforeUpdate, BeforeDelete, AfterCreate,\nAfterUpdate, AfterDelete, SingleRecord"
|
|
272
|
-
note for MultipleRecords "Registered for: List, View"
|
|
273
|
-
note for Validate "Registered for: Validate"
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Class Hierarchy
|
|
277
|
-
|
|
278
|
-
```mermaid
|
|
279
|
-
classDiagram
|
|
280
|
-
class BaseAction {
|
|
281
|
-
<<abstract>>
|
|
282
|
-
+Run(params) ActionResultSimple
|
|
283
|
-
#InternalRunAction(params)* ActionResultSimple
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
class BaseOAuthAction {
|
|
287
|
-
<<abstract>>
|
|
288
|
-
#initializeOAuth(id) boolean
|
|
289
|
-
#getAccessToken() string
|
|
290
|
-
#makeAuthenticatedRequest(fn) T
|
|
291
|
-
#refreshAccessToken()* void
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
class BaseActionFilter {
|
|
295
|
-
<<abstract>>
|
|
296
|
-
+Run(params, filter) boolean
|
|
297
|
-
#InternalRun(params, filter)* boolean
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
class ActionEngineServer {
|
|
301
|
-
+RunAction(params) ActionResult
|
|
302
|
-
#ValidateInputs(params) boolean
|
|
303
|
-
#RunFilters(params) boolean
|
|
304
|
-
#InternalRunAction(params) ActionResult
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
class EntityActionEngineServer {
|
|
308
|
-
+RunEntityAction(params) EntityActionResult
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
class OAuth2Manager {
|
|
312
|
-
+getAccessToken() string
|
|
313
|
-
+getAuthorizationUrl() string
|
|
314
|
-
+exchangeAuthorizationCode(code) OAuth2TokenData
|
|
315
|
-
+getClientCredentialsToken() OAuth2TokenData
|
|
316
|
-
+refreshAccessToken() OAuth2TokenData
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
BaseAction <|-- BaseOAuthAction
|
|
320
|
-
ActionEngineServer --> BaseAction : dispatches to
|
|
321
|
-
ActionEngineServer --> BaseActionFilter : evaluates
|
|
322
|
-
EntityActionEngineServer --> ActionEngineServer : delegates to
|
|
323
|
-
BaseOAuthAction --> OAuth2Manager : can use
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
## API Reference
|
|
327
|
-
|
|
328
|
-
### ActionEngineServer
|
|
329
|
-
|
|
330
|
-
Singleton engine that executes actions. Access via `ActionEngineServer.Instance`.
|
|
331
|
-
|
|
332
|
-
| Method | Description |
|
|
333
|
-
|--------|-------------|
|
|
334
|
-
| `Config(forceRefresh, contextUser)` | Initialize/refresh the engine's action and filter metadata |
|
|
335
|
-
| `RunAction(params)` | Execute an action through the full pipeline (validate, filter, dispatch, log) |
|
|
336
|
-
|
|
337
|
-
### BaseAction
|
|
338
|
-
|
|
339
|
-
Abstract base class for all action implementations.
|
|
340
|
-
|
|
341
|
-
| Method | Description |
|
|
342
|
-
|--------|-------------|
|
|
343
|
-
| `Run(params)` | Public entry point — calls `InternalRunAction` |
|
|
344
|
-
| `InternalRunAction(params)` | **Abstract** — implement your action logic here |
|
|
345
|
-
|
|
346
|
-
### BaseOAuthAction
|
|
347
|
-
|
|
348
|
-
Abstract base for actions requiring OAuth authentication. Extends `BaseAction`.
|
|
349
|
-
|
|
350
|
-
| Method | Description |
|
|
351
|
-
|--------|-------------|
|
|
352
|
-
| `initializeOAuth(companyIntegrationId)` | Load integration, check/refresh tokens |
|
|
353
|
-
| `getAccessToken()` | Get the current access token |
|
|
354
|
-
| `makeAuthenticatedRequest(fn)` | Execute a request with automatic retry on 401/403 |
|
|
355
|
-
| `refreshAccessToken()` | **Abstract** — implement platform-specific token refresh |
|
|
356
|
-
| `updateStoredTokens(access, refresh?, expiresIn?)` | Persist new tokens to the Company Integration entity |
|
|
357
|
-
| `handleOAuthError(error)` | Return a standardized error result for OAuth failures |
|
|
358
|
-
|
|
359
|
-
### BaseActionFilter
|
|
360
|
-
|
|
361
|
-
Abstract base for pre-execution filters.
|
|
362
|
-
|
|
363
|
-
| Method | Description |
|
|
364
|
-
|--------|-------------|
|
|
365
|
-
| `Run(params, filter)` | Public entry point — calls `InternalRun` |
|
|
366
|
-
| `InternalRun(params, filter)` | **Abstract** — implement filter logic, return `true` to allow execution |
|
|
367
|
-
|
|
368
|
-
### EntityActionEngineServer
|
|
369
|
-
|
|
370
|
-
Singleton engine for entity-bound actions. Access via `EntityActionEngineServer.Instance`.
|
|
371
|
-
|
|
372
|
-
| Method | Description |
|
|
373
|
-
|--------|-------------|
|
|
374
|
-
| `RunEntityAction(params)` | Execute an entity action, dispatching to the correct invocation type handler |
|
|
375
|
-
|
|
376
|
-
### OAuth2Manager
|
|
377
|
-
|
|
378
|
-
Standalone OAuth2 token manager supporting multiple grant types.
|
|
379
|
-
|
|
380
|
-
| Method | Description |
|
|
381
|
-
|--------|-------------|
|
|
382
|
-
| `getAccessToken()` | Get a valid token, auto-refreshing if needed (thread-safe) |
|
|
383
|
-
| `getAuthorizationUrl(state?)` | Build the authorization URL for auth code flow |
|
|
384
|
-
| `exchangeAuthorizationCode(code)` | Exchange an auth code for tokens |
|
|
385
|
-
| `getClientCredentialsToken()` | Obtain tokens via client credentials flow |
|
|
386
|
-
| `refreshAccessToken()` | Refresh using the stored refresh token |
|
|
387
|
-
| `setTokens(access, refresh?, expiresIn?)` | Set tokens obtained externally |
|
|
388
|
-
| `isTokenValid()` | Check if current token is valid (with buffer) |
|
|
389
|
-
|
|
390
|
-
## Dependencies
|
|
391
|
-
|
|
392
|
-
This package depends on:
|
|
393
|
-
|
|
394
|
-
- [@memberjunction/global](../../MJGlobal/README.md) — ClassFactory and `@RegisterClass` decorator
|
|
395
|
-
- [@memberjunction/core](../../MJCore/README.md) — `Metadata`, `RunView`, `BaseEntity`, logging utilities
|
|
396
|
-
- [@memberjunction/actions-base](../Base/README.md) — Shared types (`ActionEngineBase`, `RunActionParams`, `ActionResult`, etc.)
|
|
397
|
-
- [@memberjunction/core-entities](../../MJCoreEntities/README.md) — Generated entity classes (`ActionExecutionLogEntity`, `ActionFilterEntity`, etc.)
|
|
398
|
-
- [@memberjunction/ai](../../AI/Core/README.md) — AI model integration
|
|
399
|
-
- [@memberjunction/ai-core-plus](../../AI/CorePlus/README.md) — Extended AI utilities
|
|
400
|
-
- [@memberjunction/aiengine](../../AI/Engine/README.md) — AI engine orchestration
|
|
401
|
-
- [@memberjunction/ai-prompts](../../AI/Prompts/README.md) — AI prompt execution
|
|
402
|
-
|
|
403
|
-
## Related Packages
|
|
404
|
-
|
|
405
|
-
- [@memberjunction/actions-base](../Base/README.md) — Shared types and base classes used by both client and server
|
|
406
|
-
- [CoreActions](../CoreActions/) — Built-in action implementations (Create Record, generated actions, etc.)
|
|
407
|
-
- [ScheduledActions](../ScheduledActions/) — Scheduled action execution support
|
|
408
|
-
- [ApolloEnrichment](../ApolloEnrichment/) — Apollo data enrichment actions
|
|
409
|
-
- [ContentAutotag](../ContentAutotag/) — Content auto-tagging actions
|
|
410
|
-
- [CodeExecution](../CodeExecution/) — Dynamic code execution actions
|
|
411
|
-
|
|
412
|
-
For the Actions system philosophy and development guide, see the [Actions CLAUDE.md](../CLAUDE.md).
|
|
413
|
-
|
|
414
|
-
## Contributing
|
|
415
|
-
|
|
416
|
-
See the [MemberJunction Contributing Guide](../../../CONTRIBUTING.md) for development setup and guidelines.
|