@memberjunction/actions-base 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -275
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
# @memberjunction/actions-base
|
|
2
2
|
|
|
3
|
-
Base classes and
|
|
3
|
+
Base classes, interfaces, and metadata engines for the MemberJunction Actions framework. This package provides the foundational layer that both server-side (`@memberjunction/actions`) and client-side action implementations build upon. It handles action metadata loading, parameter modeling, result types, and extended entity classes with lazy-loaded relationships.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The Actions framework in MemberJunction provides a flexible, metadata-driven system for executing business logic and operations. This base package contains the core classes and interfaces that enable:
|
|
8
|
-
|
|
9
|
-
- **Action Engine**: Core engine for loading, configuring, and executing actions
|
|
10
|
-
- **Entity Actions**: Actions that operate on specific entities with various invocation contexts
|
|
11
|
-
- **Code Generation**: Support for dynamically generated action code with library management
|
|
12
|
-
- **Execution Logging**: Built-in logging and result tracking for all action executions
|
|
5
|
+
For the broader Actions design philosophy -- including when to use Actions vs. direct class imports, and the "thin wrapper" principle -- see the [parent Actions CLAUDE.md](../CLAUDE.md).
|
|
13
6
|
|
|
14
7
|
## Installation
|
|
15
8
|
|
|
@@ -17,347 +10,308 @@ The Actions framework in MemberJunction provides a flexible, metadata-driven sys
|
|
|
17
10
|
npm install @memberjunction/actions-base
|
|
18
11
|
```
|
|
19
12
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
The package is organized into two parallel engine hierarchies: one for general-purpose **Actions** and one for **Entity Actions** (actions bound to a specific entity). Both engines are singletons that extend `BaseEngine` from `@memberjunction/core` and load their metadata via `Config()`.
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
graph TD
|
|
19
|
+
subgraph BasePackage["@memberjunction/actions-base"]
|
|
20
|
+
AEB["ActionEngineBase\n(singleton)"]
|
|
21
|
+
EAEB["EntityActionEngineBase\n(singleton)"]
|
|
22
|
+
AEX["ActionEntityExtended"]
|
|
23
|
+
EAEX["EntityActionEntityExtended"]
|
|
24
|
+
RAP["RunActionParams<TContext>"]
|
|
25
|
+
AR["ActionResult / ActionResultSimple"]
|
|
26
|
+
AP["ActionParam"]
|
|
27
|
+
GC["GeneratedCode"]
|
|
28
|
+
EAIP["EntityActionInvocationParams"]
|
|
29
|
+
EAR["EntityActionResult"]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
subgraph CoreDeps["Dependencies"]
|
|
33
|
+
BE["BaseEngine\n(@memberjunction/core)"]
|
|
34
|
+
CE["Entity classes\n(@memberjunction/core-entities)"]
|
|
35
|
+
RC["@RegisterClass\n(@memberjunction/global)"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
AEB -->|extends| BE
|
|
39
|
+
EAEB -->|extends| BE
|
|
40
|
+
AEX -->|extends| CE
|
|
41
|
+
EAEX -->|extends| CE
|
|
42
|
+
AEX -->|registered via| RC
|
|
43
|
+
EAEX -->|registered via| RC
|
|
44
|
+
AEB -->|manages| AEX
|
|
45
|
+
EAEB -->|manages| EAEX
|
|
46
|
+
|
|
47
|
+
style BasePackage fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
48
|
+
style CoreDeps fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
49
|
+
style AEB fill:#7c5295,stroke:#563a6b,color:#fff
|
|
50
|
+
style EAEB fill:#7c5295,stroke:#563a6b,color:#fff
|
|
51
|
+
style AEX fill:#b8762f,stroke:#8a5722,color:#fff
|
|
52
|
+
style EAEX fill:#b8762f,stroke:#8a5722,color:#fff
|
|
53
|
+
```
|
|
23
54
|
|
|
24
|
-
|
|
55
|
+
### Data Flow: Config and Execution
|
|
25
56
|
|
|
26
|
-
```
|
|
27
|
-
|
|
57
|
+
```mermaid
|
|
58
|
+
sequenceDiagram
|
|
59
|
+
participant Caller
|
|
60
|
+
participant AEB as ActionEngineBase
|
|
61
|
+
participant DB as Database (via RunView)
|
|
62
|
+
participant AEX as ActionEntityExtended
|
|
28
63
|
|
|
29
|
-
|
|
30
|
-
|
|
64
|
+
Caller->>AEB: Config(forceRefresh, contextUser)
|
|
65
|
+
AEB->>DB: RunViews (batch load 6 entity types)
|
|
66
|
+
DB-->>AEB: Actions, Categories, Filters, Params, ResultCodes, Libraries
|
|
67
|
+
AEB-->>Caller: Metadata ready
|
|
31
68
|
|
|
32
|
-
|
|
33
|
-
|
|
69
|
+
Caller->>AEB: Actions (getter)
|
|
70
|
+
AEB-->>Caller: ActionEntityExtended[]
|
|
34
71
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const actionFilters = actionEngine.ActionFilters;
|
|
72
|
+
Caller->>AEX: ResultCodes (getter, lazy)
|
|
73
|
+
AEX->>AEB: ActionResultCodes (filtered by ActionID)
|
|
74
|
+
AEB-->>AEX: ActionResultCodeEntity[]
|
|
75
|
+
AEX-->>Caller: Cached result codes
|
|
40
76
|
```
|
|
41
77
|
|
|
42
|
-
|
|
78
|
+
## Exports
|
|
43
79
|
|
|
44
|
-
|
|
80
|
+
### Engine Classes
|
|
45
81
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const entityActionEngine = EntityActionEngineBase.Instance;
|
|
82
|
+
| Export | Description |
|
|
83
|
+
|--------|-------------|
|
|
84
|
+
| `ActionEngineBase` | Singleton engine that loads and caches all action metadata (actions, categories, filters, params, result codes, libraries). Subclassed by server/client implementations. |
|
|
85
|
+
| `EntityActionEngineBase` | Singleton engine for entity-bound actions. Loads entity actions, invocation types, filters, invocations, and params. |
|
|
51
86
|
|
|
52
|
-
|
|
53
|
-
await entityActionEngine.Config(false, userInfo);
|
|
87
|
+
### Extended Entity Classes
|
|
54
88
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const viewActions = entityActionEngine.GetActionsByEntityNameAndInvocationType(
|
|
60
|
-
'Orders',
|
|
61
|
-
'View',
|
|
62
|
-
'Active'
|
|
63
|
-
);
|
|
64
|
-
```
|
|
89
|
+
| Export | Description |
|
|
90
|
+
|--------|-------------|
|
|
91
|
+
| `ActionEntityExtended` | Extends `ActionEntity` with lazy-loaded `ResultCodes`, `Params`, `Libraries`, plus computed `IsCoreAction` and `ProgrammaticName` properties. Registered as `'Actions'` in the MJ class factory. |
|
|
92
|
+
| `EntityActionEntityExtended` | Extends `EntityActionEntity` with lazy-loaded `Filters`, `Invocations`, and `Params`. Registered as `'Entity Actions'` in the MJ class factory. |
|
|
65
93
|
|
|
66
|
-
|
|
94
|
+
### Parameter and Result Types
|
|
67
95
|
|
|
68
|
-
|
|
96
|
+
| Export | Description |
|
|
97
|
+
|--------|-------------|
|
|
98
|
+
| `RunActionParams<TContext>` | Configuration object for running an action. Includes the action entity, context user, filters, parameters, and an optional generic-typed `Context` for runtime-specific data. |
|
|
99
|
+
| `ActionParam` | Key-value parameter with `Name`, `Value`, and `Type` (`'Input'` / `'Output'` / `'Both'`). |
|
|
100
|
+
| `ActionResult` | Full result from engine execution, including `Success`, `Result` (result code entity), `LogEntry`, `Message`, and output `Params`. |
|
|
101
|
+
| `ActionResultSimple` | Lightweight result returned by individual action implementations: `Success`, `ResultCode` (string), optional `Message` and `Params`. |
|
|
102
|
+
| `EntityActionInvocationParams` | Parameters for invoking an entity action, including invocation type and one of `EntityObject`, `ViewID`, or `ListID`. |
|
|
103
|
+
| `EntityActionResult` | Result from entity action execution with same structure as `ActionResult`. |
|
|
69
104
|
|
|
70
|
-
|
|
105
|
+
### Code Generation Support
|
|
71
106
|
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
| Export | Description |
|
|
108
|
+
|--------|-------------|
|
|
109
|
+
| `GeneratedCode` | Container for AI-generated action code, including `Success`, `Code`, `LibrariesUsed`, `Comments`, and `ErrorMessage`. |
|
|
110
|
+
| `ActionLibrary` | Library reference used in generated code: `LibraryName` and `ItemsUsed` (array of imported items). |
|
|
74
111
|
|
|
75
|
-
|
|
76
|
-
Name: 'CustomerID',
|
|
77
|
-
Value: '12345',
|
|
78
|
-
Type: 'Input' // 'Input' | 'Output' | 'Both'
|
|
79
|
-
};
|
|
80
|
-
```
|
|
112
|
+
## Usage
|
|
81
113
|
|
|
82
|
-
###
|
|
114
|
+
### Configuring the Action Engine
|
|
83
115
|
|
|
84
|
-
|
|
116
|
+
Both engines must be configured before use. `Config()` loads metadata from the database and caches it. Pass `forceRefresh: true` to reload after metadata changes.
|
|
85
117
|
|
|
86
118
|
```typescript
|
|
87
|
-
import {
|
|
88
|
-
|
|
89
|
-
const runParams: RunActionParams = {
|
|
90
|
-
Action: actionEntity,
|
|
91
|
-
ContextUser: userInfo,
|
|
92
|
-
SkipActionLog: false, // Optional
|
|
93
|
-
Filters: [], // Optional filters to run before action
|
|
94
|
-
Params: [
|
|
95
|
-
{ Name: 'Input1', Value: 'test', Type: 'Input' }
|
|
96
|
-
]
|
|
97
|
-
};
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
#### Type-Safe Context Support (New in v2.51.0)
|
|
119
|
+
import { ActionEngineBase } from '@memberjunction/actions-base';
|
|
120
|
+
import { UserInfo } from '@memberjunction/core';
|
|
101
121
|
|
|
102
|
-
|
|
122
|
+
async function initialize(contextUser: UserInfo) {
|
|
123
|
+
const engine = ActionEngineBase.Instance;
|
|
103
124
|
|
|
104
|
-
|
|
105
|
-
|
|
125
|
+
// Initial load -- metadata cached in GlobalObjectStore
|
|
126
|
+
await engine.Config(false, contextUser);
|
|
106
127
|
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
// Access loaded metadata
|
|
129
|
+
const allActions = engine.Actions; // ActionEntityExtended[]
|
|
130
|
+
const coreActions = engine.CoreActions; // Only core MJ actions
|
|
131
|
+
const categories = engine.ActionCategories; // ActionCategoryEntity[]
|
|
132
|
+
const params = engine.ActionParams; // ActionParamEntity[]
|
|
133
|
+
const filters = engine.ActionFilters; // ActionFilterEntity[]
|
|
134
|
+
const resultCodes = engine.ActionResultCodes;
|
|
135
|
+
const libraries = engine.ActionLibraries;
|
|
113
136
|
}
|
|
114
|
-
|
|
115
|
-
// Create typed parameters
|
|
116
|
-
const runParams = new RunActionParams<MyActionContext>();
|
|
117
|
-
runParams.Action = actionEntity;
|
|
118
|
-
runParams.ContextUser = userInfo;
|
|
119
|
-
runParams.Params = [
|
|
120
|
-
{ Name: 'customerID', Value: 'CUST123', Type: 'Input' },
|
|
121
|
-
{ Name: 'orderAmount', Value: 150.00, Type: 'Input' }
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
// Set typed context
|
|
125
|
-
runParams.Context = {
|
|
126
|
-
apiEndpoint: 'https://api.example.com',
|
|
127
|
-
apiKey: process.env.API_KEY,
|
|
128
|
-
environment: 'prod',
|
|
129
|
-
featureFlags: {
|
|
130
|
-
newFeature: true,
|
|
131
|
-
betaAccess: false
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
137
|
```
|
|
135
138
|
|
|
136
|
-
|
|
137
|
-
- **Separate from parameters**: Not stored in the database or included in logs
|
|
138
|
-
- **Runtime-specific**: For environment configuration, credentials, and session data
|
|
139
|
-
- **Type-safe**: Full TypeScript support when using generics
|
|
140
|
-
- **Propagated automatically**: Flows from agents to actions in the execution hierarchy
|
|
141
|
-
|
|
142
|
-
### ActionResult
|
|
143
|
-
|
|
144
|
-
The result object returned from action execution:
|
|
139
|
+
### Configuring the Entity Action Engine
|
|
145
140
|
|
|
146
141
|
```typescript
|
|
147
|
-
import {
|
|
148
|
-
|
|
149
|
-
// ActionResult contains:
|
|
150
|
-
// - Success: boolean indicating if action succeeded
|
|
151
|
-
// - Result: ActionResultCodeEntity with the specific result code
|
|
152
|
-
// - LogEntry: ActionExecutionLogEntity for tracking
|
|
153
|
-
// - Message: Optional message about the outcome
|
|
154
|
-
// - Params: All parameters including outputs
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### EntityActionInvocationParams
|
|
158
|
-
|
|
159
|
-
Parameters for invoking entity-specific actions:
|
|
142
|
+
import { EntityActionEngineBase } from '@memberjunction/actions-base';
|
|
160
143
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const invocationParams: EntityActionInvocationParams = {
|
|
165
|
-
EntityAction: entityActionExtended,
|
|
166
|
-
InvocationType: invocationTypeEntity,
|
|
167
|
-
ContextUser: userInfo,
|
|
168
|
-
// One of these based on invocation type:
|
|
169
|
-
EntityObject: customerEntity, // For single record
|
|
170
|
-
ViewID: 'view-123', // For view-based
|
|
171
|
-
ListID: 'list-456' // For list-based
|
|
172
|
-
};
|
|
173
|
-
```
|
|
144
|
+
async function initEntityActions(contextUser: UserInfo) {
|
|
145
|
+
const engine = EntityActionEngineBase.Instance;
|
|
146
|
+
await engine.Config(false, contextUser);
|
|
174
147
|
|
|
175
|
-
|
|
148
|
+
// All entity actions
|
|
149
|
+
const entityActions = engine.EntityActions; // EntityActionEntityExtended[]
|
|
176
150
|
|
|
177
|
-
|
|
151
|
+
// Filter by entity name and status
|
|
152
|
+
const customerActions = engine.GetActionsByEntityName('Customers', 'Active');
|
|
178
153
|
|
|
179
|
-
|
|
154
|
+
// Filter by entity name and invocation type
|
|
155
|
+
const viewActions = engine.GetActionsByEntityNameAndInvocationType(
|
|
156
|
+
'Orders',
|
|
157
|
+
'View',
|
|
158
|
+
'Active'
|
|
159
|
+
);
|
|
180
160
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// Provides additional properties:
|
|
185
|
-
const action = actionEngine.Actions[0] as ActionEntityExtended;
|
|
186
|
-
console.log(action.IsCoreAction); // true if core MJ action
|
|
187
|
-
console.log(action.ProgrammaticName); // Code-friendly name
|
|
188
|
-
console.log(action.ResultCodes); // Possible result codes
|
|
189
|
-
console.log(action.Params); // Action parameters
|
|
190
|
-
console.log(action.Libraries); // Required libraries
|
|
161
|
+
// Filter by entity ID
|
|
162
|
+
const byId = engine.GetActionsByEntityID('some-entity-uuid');
|
|
163
|
+
}
|
|
191
164
|
```
|
|
192
165
|
|
|
193
|
-
###
|
|
166
|
+
### Working with ActionEntityExtended
|
|
194
167
|
|
|
195
|
-
|
|
168
|
+
The extended entity class provides lazy-loaded related data and computed properties.
|
|
196
169
|
|
|
197
170
|
```typescript
|
|
198
|
-
import {
|
|
171
|
+
import { ActionEngineBase, ActionEntityExtended } from '@memberjunction/actions-base';
|
|
199
172
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
console.log(entityAction.Filters); // Associated filters
|
|
203
|
-
console.log(entityAction.Invocations); // Invocation configurations
|
|
204
|
-
console.log(entityAction.Params); // Action parameters
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Code Generation Support
|
|
173
|
+
const engine = ActionEngineBase.Instance;
|
|
174
|
+
await engine.Config(false, contextUser);
|
|
208
175
|
|
|
209
|
-
|
|
176
|
+
const action: ActionEntityExtended = engine.Actions[0];
|
|
210
177
|
|
|
211
|
-
|
|
212
|
-
|
|
178
|
+
// Computed properties
|
|
179
|
+
console.log(action.IsCoreAction); // boolean -- is this a core MJ action?
|
|
180
|
+
console.log(action.ProgrammaticName); // Code-safe version of action name
|
|
213
181
|
|
|
214
|
-
//
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
LibrariesUsed: [
|
|
219
|
-
{
|
|
220
|
-
LibraryName: 'lodash',
|
|
221
|
-
ItemsUsed: ['map', 'filter']
|
|
222
|
-
}
|
|
223
|
-
],
|
|
224
|
-
Comments: 'Processes customer data',
|
|
225
|
-
ErrorMessage: undefined
|
|
226
|
-
};
|
|
182
|
+
// Lazy-loaded relationships (cached after first access)
|
|
183
|
+
const resultCodes = action.ResultCodes; // ActionResultCodeEntity[]
|
|
184
|
+
const params = action.Params; // ActionParamEntity[]
|
|
185
|
+
const libraries = action.Libraries; // ActionLibraryEntity[]
|
|
227
186
|
```
|
|
228
187
|
|
|
229
|
-
|
|
188
|
+
### Building RunActionParams with Type-Safe Context
|
|
230
189
|
|
|
231
|
-
|
|
190
|
+
`RunActionParams` supports a generic `TContext` parameter for propagating runtime-specific data (API keys, environment config, feature flags) that is separate from action parameters and not persisted to logs.
|
|
232
191
|
|
|
233
192
|
```typescript
|
|
234
|
-
import {
|
|
193
|
+
import { RunActionParams, ActionParam } from '@memberjunction/actions-base';
|
|
194
|
+
import { ActionEntity } from '@memberjunction/core-entities';
|
|
235
195
|
import { UserInfo } from '@memberjunction/core';
|
|
236
196
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
197
|
+
// Define a context type for your environment
|
|
198
|
+
interface ServiceContext {
|
|
199
|
+
apiEndpoint: string;
|
|
200
|
+
apiKey: string;
|
|
201
|
+
environment: 'dev' | 'staging' | 'prod';
|
|
202
|
+
retryPolicy: {
|
|
203
|
+
maxRetries: number;
|
|
204
|
+
backoffMs: number;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function buildRunParams(
|
|
209
|
+
action: ActionEntity,
|
|
210
|
+
user: UserInfo,
|
|
211
|
+
context: ServiceContext
|
|
212
|
+
): RunActionParams<ServiceContext> {
|
|
213
|
+
const params = new RunActionParams<ServiceContext>();
|
|
214
|
+
params.Action = action;
|
|
215
|
+
params.ContextUser = user;
|
|
216
|
+
params.Params = [
|
|
217
|
+
{ Name: 'CustomerID', Value: 'CUST-123', Type: 'Input' },
|
|
218
|
+
{ Name: 'OrderTotal', Value: 250.00, Type: 'Input' }
|
|
219
|
+
];
|
|
220
|
+
params.Context = context; // Type-checked against ServiceContext
|
|
221
|
+
return params;
|
|
249
222
|
}
|
|
250
223
|
```
|
|
251
224
|
|
|
252
|
-
###
|
|
225
|
+
### Entity Action Invocation
|
|
226
|
+
|
|
227
|
+
Entity actions support three invocation modes depending on the context.
|
|
253
228
|
|
|
254
229
|
```typescript
|
|
255
|
-
import {
|
|
230
|
+
import {
|
|
231
|
+
EntityActionInvocationParams,
|
|
232
|
+
EntityActionEngineBase
|
|
233
|
+
} from '@memberjunction/actions-base';
|
|
256
234
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
235
|
+
const engine = EntityActionEngineBase.Instance;
|
|
236
|
+
await engine.Config(false, contextUser);
|
|
237
|
+
|
|
238
|
+
const entityActions = engine.GetActionsByEntityNameAndInvocationType(
|
|
239
|
+
'Customers',
|
|
240
|
+
'Single Record',
|
|
241
|
+
'Active'
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
if (entityActions.length > 0) {
|
|
245
|
+
const invocationParams: EntityActionInvocationParams = {
|
|
246
|
+
EntityAction: entityActions[0],
|
|
247
|
+
InvocationType: engine.InvocationTypes.find(
|
|
248
|
+
t => t.Name === 'Single Record'
|
|
249
|
+
)!,
|
|
250
|
+
ContextUser: contextUser,
|
|
251
|
+
EntityObject: customerRecord // BaseEntity instance
|
|
252
|
+
};
|
|
253
|
+
// Pass to your engine's run method
|
|
270
254
|
}
|
|
271
255
|
```
|
|
272
256
|
|
|
273
|
-
###
|
|
257
|
+
### Category Hierarchy Utilities
|
|
258
|
+
|
|
259
|
+
`ActionEngineBase` provides methods for navigating the action category tree.
|
|
274
260
|
|
|
275
261
|
```typescript
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
function prepareActionParams(inputs: Record<string, any>): ActionParam[] {
|
|
279
|
-
return Object.entries(inputs).map(([name, value]) => ({
|
|
280
|
-
Name: name,
|
|
281
|
-
Value: value,
|
|
282
|
-
Type: 'Input'
|
|
283
|
-
}));
|
|
284
|
-
}
|
|
262
|
+
const engine = ActionEngineBase.Instance;
|
|
285
263
|
|
|
286
|
-
//
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
264
|
+
// Check if a category is under the core actions root
|
|
265
|
+
const isCoreCategory = engine.IsCoreActionCategory(someCategoryId);
|
|
266
|
+
|
|
267
|
+
// Check if one category is a descendant of another (recursive)
|
|
268
|
+
const isChild = engine.IsChildCategoryOf(childCategoryId, parentCategoryId);
|
|
269
|
+
|
|
270
|
+
// Look up an action by name
|
|
271
|
+
const action = engine.GetActionByName('Send Email');
|
|
292
272
|
```
|
|
293
273
|
|
|
294
|
-
###
|
|
274
|
+
### Code Generation Types
|
|
295
275
|
|
|
296
|
-
|
|
276
|
+
The `GeneratedCode` and `ActionLibrary` types support the AI-powered action generation system.
|
|
297
277
|
|
|
298
278
|
```typescript
|
|
299
|
-
import {
|
|
300
|
-
|
|
301
|
-
interface ServiceContext {
|
|
302
|
-
apiEndpoint: string;
|
|
303
|
-
apiKey: string;
|
|
304
|
-
timeout: number;
|
|
305
|
-
retryPolicy: {
|
|
306
|
-
maxRetries: number;
|
|
307
|
-
backoffMs: number;
|
|
308
|
-
};
|
|
309
|
-
}
|
|
279
|
+
import { GeneratedCode, ActionLibrary } from '@memberjunction/actions-base';
|
|
310
280
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
runParams.Params = businessParams;
|
|
321
|
-
runParams.Context = context;
|
|
322
|
-
|
|
323
|
-
// The action implementation can access context via this.ContextObject
|
|
324
|
-
// This is useful for:
|
|
325
|
-
// - API configurations that vary by environment
|
|
326
|
-
// - Runtime credentials not stored in metadata
|
|
327
|
-
// - Session-specific settings
|
|
328
|
-
// - Feature flags and toggles
|
|
329
|
-
|
|
330
|
-
const result = await actionEngine.RunAction(runParams);
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
281
|
+
const generated: GeneratedCode = {
|
|
282
|
+
Success: true,
|
|
283
|
+
Code: 'async function execute(params) { /* ... */ }',
|
|
284
|
+
LibrariesUsed: [
|
|
285
|
+
{ LibraryName: 'lodash', ItemsUsed: ['map', 'filter', 'groupBy'] },
|
|
286
|
+
{ LibraryName: '@memberjunction/core', ItemsUsed: ['RunView'] }
|
|
287
|
+
],
|
|
288
|
+
Comments: 'Aggregates customer orders by region and calculates totals'
|
|
289
|
+
};
|
|
333
290
|
```
|
|
334
291
|
|
|
335
|
-
##
|
|
336
|
-
|
|
337
|
-
- `@memberjunction/global`: Global utilities and registration system
|
|
338
|
-
- `@memberjunction/core`: Core MemberJunction interfaces and base classes
|
|
339
|
-
- `@memberjunction/core-entities`: Entity definitions for MemberJunction metadata
|
|
292
|
+
## Key Design Decisions
|
|
340
293
|
|
|
341
|
-
|
|
294
|
+
**Singleton engines** -- Both `ActionEngineBase` and `EntityActionEngineBase` use the MJ `BaseEngine` singleton pattern. Always access them via the static `Instance` getter; never construct them directly.
|
|
342
295
|
|
|
343
|
-
|
|
296
|
+
**Lazy-loaded relationships** -- `ActionEntityExtended` and `EntityActionEntityExtended` fetch their related data (params, result codes, filters, invocations, libraries) lazily on first property access and cache the result. This avoids loading relationship data for actions that are never inspected.
|
|
344
297
|
|
|
345
|
-
|
|
346
|
-
- `@memberjunction/actions-client`: Client-side action execution
|
|
347
|
-
- Custom action implementations in your applications
|
|
298
|
+
**IgnoreMaxRows on Config** -- The engine overrides `LoadMultipleEntityConfigs` to set `IgnoreMaxRows: true`, ensuring all action metadata records are loaded regardless of entity-level `UserViewMaxRows` settings. Action Params in particular can exceed 1000 records.
|
|
348
299
|
|
|
349
|
-
|
|
300
|
+
**Generic context on RunActionParams** -- The `TContext` generic preserves type safety for runtime context data flowing from agents through to action implementations, without polluting the persisted parameter system.
|
|
350
301
|
|
|
351
|
-
|
|
352
|
-
2. **Use Singleton Instances**: Always use the `.Instance` property to get engine instances
|
|
353
|
-
3. **Handle Async Operations**: All configuration and many operations are asynchronous
|
|
354
|
-
4. **Check Action Status**: Filter actions by status ('Active', 'Pending', 'Disabled') when appropriate
|
|
355
|
-
5. **Validate Parameters**: Ensure all required input parameters are provided before execution
|
|
302
|
+
## Dependencies
|
|
356
303
|
|
|
357
|
-
|
|
304
|
+
| Package | Purpose |
|
|
305
|
+
|---------|---------|
|
|
306
|
+
| `@memberjunction/global` | `@RegisterClass` decorator and MJ class factory |
|
|
307
|
+
| `@memberjunction/core` | `BaseEngine`, `BaseEntity`, `UserInfo`, `RunView`, `CodeNameFromString` |
|
|
308
|
+
| `@memberjunction/core-entities` | Generated entity classes (`ActionEntity`, `EntityActionEntity`, and all related entities) |
|
|
358
309
|
|
|
359
|
-
|
|
310
|
+
## Related Packages
|
|
360
311
|
|
|
361
|
-
|
|
312
|
+
| Package | Relationship |
|
|
313
|
+
|---------|-------------|
|
|
314
|
+
| [`@memberjunction/actions`](../Engine) | Server-side engine that extends `ActionEngineBase` with execution, logging, and AI code generation |
|
|
315
|
+
| [`@memberjunction/core-actions`](../CoreActions) | 40+ pre-built action implementations using `BaseAction` from the Engine package |
|
|
316
|
+
| [`@memberjunction/scheduled-actions`](../ScheduledActions) | Cron-based scheduling engine for recurring action execution |
|
|
362
317
|
|
|
363
|
-
ISC License - see LICENSE file in the root of the repository.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/actions-base",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.2.0",
|
|
5
5
|
"description": "Base Classes for MemberJunction Actions. This library is used on both server and network nodes.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"typescript": "^5.9.3"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@memberjunction/global": "4.
|
|
24
|
-
"@memberjunction/core": "4.
|
|
25
|
-
"@memberjunction/core-entities": "4.
|
|
23
|
+
"@memberjunction/global": "4.2.0",
|
|
24
|
+
"@memberjunction/core": "4.2.0",
|
|
25
|
+
"@memberjunction/core-entities": "4.2.0"
|
|
26
26
|
},
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|