@memberjunction/core-entities 3.4.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artifact-extraction/artifact-extract-rules.js +1 -2
- package/dist/artifact-extraction/artifact-extract-rules.js.map +1 -1
- package/dist/artifact-extraction/artifact-extractor.d.ts +1 -1
- package/dist/artifact-extraction/artifact-extractor.js +1 -5
- package/dist/artifact-extraction/artifact-extractor.js.map +1 -1
- package/dist/custom/ComponentEntityExtended.d.ts +1 -1
- package/dist/custom/ComponentEntityExtended.js +8 -11
- package/dist/custom/ComponentEntityExtended.js.map +1 -1
- package/dist/custom/DashboardEntityExtended.d.ts +1 -1
- package/dist/custom/DashboardEntityExtended.js +17 -20
- package/dist/custom/DashboardEntityExtended.js.map +1 -1
- package/dist/custom/EntityEntityExtended.d.ts +1 -1
- package/dist/custom/EntityEntityExtended.js +7 -10
- package/dist/custom/EntityEntityExtended.js.map +1 -1
- package/dist/custom/EntityFieldEntityExtended.d.ts +1 -1
- package/dist/custom/EntityFieldEntityExtended.js +27 -29
- package/dist/custom/EntityFieldEntityExtended.js.map +1 -1
- package/dist/custom/EnvironmentEntityExtended.d.ts +1 -1
- package/dist/custom/EnvironmentEntityExtended.js +7 -10
- package/dist/custom/EnvironmentEntityExtended.js.map +1 -1
- package/dist/custom/ListDetailEntityExtended.d.ts +1 -1
- package/dist/custom/ListDetailEntityExtended.js +14 -17
- package/dist/custom/ListDetailEntityExtended.js.map +1 -1
- package/dist/custom/ResourcePermissions/ResourceData.js +4 -8
- package/dist/custom/ResourcePermissions/ResourceData.js.map +1 -1
- package/dist/custom/ResourcePermissions/ResourcePermissionEngine.d.ts +1 -1
- package/dist/custom/ResourcePermissions/ResourcePermissionEngine.js +6 -9
- package/dist/custom/ResourcePermissions/ResourcePermissionEngine.js.map +1 -1
- package/dist/custom/ResourcePermissions/ResourcePermissionSubclass.d.ts +1 -1
- package/dist/custom/ResourcePermissions/ResourcePermissionSubclass.js +10 -13
- package/dist/custom/ResourcePermissions/ResourcePermissionSubclass.js.map +1 -1
- package/dist/custom/ScheduledActionExtended.d.ts +1 -1
- package/dist/custom/ScheduledActionExtended.js +7 -10
- package/dist/custom/ScheduledActionExtended.js.map +1 -1
- package/dist/custom/TemplateEntityExtended.d.ts +1 -1
- package/dist/custom/TemplateEntityExtended.js +8 -11
- package/dist/custom/TemplateEntityExtended.js.map +1 -1
- package/dist/custom/UserViewEntity.d.ts +1 -1
- package/dist/custom/UserViewEntity.js +44 -75
- package/dist/custom/UserViewEntity.js.map +1 -1
- package/dist/engines/EncryptionEngineBase.d.ts +1 -6
- package/dist/engines/EncryptionEngineBase.d.ts.map +1 -1
- package/dist/engines/EncryptionEngineBase.js +8 -19
- package/dist/engines/EncryptionEngineBase.js.map +1 -1
- package/dist/engines/FileStorageEngine.d.ts +1 -1
- package/dist/engines/FileStorageEngine.js +2 -6
- package/dist/engines/FileStorageEngine.js.map +1 -1
- package/dist/engines/MCPEngine.d.ts +1 -1
- package/dist/engines/MCPEngine.js +2 -6
- package/dist/engines/MCPEngine.js.map +1 -1
- package/dist/engines/TypeTablesCache.d.ts +1 -1
- package/dist/engines/TypeTablesCache.js +2 -6
- package/dist/engines/TypeTablesCache.js.map +1 -1
- package/dist/engines/UserInfoEngine.d.ts +1 -1
- package/dist/engines/UserInfoEngine.d.ts.map +1 -1
- package/dist/engines/UserInfoEngine.js +35 -18
- package/dist/engines/UserInfoEngine.js.map +1 -1
- package/dist/engines/UserViewEngine.d.ts +1 -1
- package/dist/engines/UserViewEngine.js +4 -8
- package/dist/engines/UserViewEngine.js.map +1 -1
- package/dist/engines/artifacts.d.ts +1 -1
- package/dist/engines/artifacts.js +2 -6
- package/dist/engines/artifacts.js.map +1 -1
- package/dist/engines/component-metadata.d.ts +2 -2
- package/dist/engines/component-metadata.js +2 -6
- package/dist/engines/component-metadata.js.map +1 -1
- package/dist/engines/dashboards.d.ts +2 -2
- package/dist/engines/dashboards.js +5 -8
- package/dist/engines/dashboards.js.map +1 -1
- package/dist/generated/entity_subclasses.d.ts +1633 -56
- package/dist/generated/entity_subclasses.d.ts.map +1 -1
- package/dist/generated/entity_subclasses.js +9576 -7270
- package/dist/generated/entity_subclasses.js.map +1 -1
- package/dist/index.d.ts +24 -24
- package/dist/index.js +24 -40
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
- package/readme.md +420 -132
package/readme.md
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
# @memberjunction/core-entities
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Strongly-typed entity classes, singleton engine caches, and domain logic for every entity in MemberJunction's core metadata schema. This package is the primary data-access layer that all MJ applications -- server and client -- depend on to interact with the MJ data model in a type-safe, validated way.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The `@memberjunction/core-entities` package contains:
|
|
8
|
-
- **178+ Generated Entity Classes**: Strongly-typed TypeScript classes for all core MemberJunction entities
|
|
9
|
-
- **Extended Entity Classes**: Custom subclasses with specialized business logic
|
|
10
|
-
- **Artifact Extraction System**: Metadata-driven attribute extraction with hierarchical inheritance
|
|
11
|
-
- **Resource Permission Engine**: Comprehensive permission management system
|
|
12
|
-
- **Zod Schema Validation**: Built-in runtime validation for all entity types
|
|
13
|
-
- **Type Definitions**: Full TypeScript type definitions for enhanced IDE support
|
|
5
|
+
All entity subclasses in this package are **auto-generated by CodeGen**. Manual edits to files under `src/generated/` will be overwritten. Custom business logic is layered on top via extended classes in `src/custom/`.
|
|
14
6
|
|
|
15
7
|
## Installation
|
|
16
8
|
|
|
@@ -18,180 +10,476 @@ The `@memberjunction/core-entities` package contains:
|
|
|
18
10
|
npm install @memberjunction/core-entities
|
|
19
11
|
```
|
|
20
12
|
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
The package is structured into four layers that build on each other:
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
flowchart TD
|
|
19
|
+
subgraph Generated["Generated Layer (CodeGen)"]
|
|
20
|
+
ZOD["Zod Schemas<br/>Runtime validation"]
|
|
21
|
+
ENT["272 Entity Subclasses<br/>Typed getters/setters"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
subgraph Custom["Custom Layer (Hand-Written)"]
|
|
25
|
+
EXT["Extended Entities<br/>Business logic overrides"]
|
|
26
|
+
RPE["Resource Permissions<br/>Access control"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
subgraph Engines["Engine Layer (Singletons)"]
|
|
30
|
+
UIE["UserInfoEngine"]
|
|
31
|
+
UVE["UserViewEngine"]
|
|
32
|
+
DE["DashboardEngine"]
|
|
33
|
+
CME["ComponentMetadataEngine"]
|
|
34
|
+
AME["ArtifactMetadataEngine"]
|
|
35
|
+
FE["FileStorageEngine"]
|
|
36
|
+
EE["EncryptionEngineBase"]
|
|
37
|
+
ME["MCPEngine"]
|
|
38
|
+
TTC["TypeTablesCache"]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
subgraph Extraction["Artifact Extraction"]
|
|
42
|
+
AER["Extract Rules<br/>Type definitions"]
|
|
43
|
+
AEX["ArtifactExtractor<br/>Rule resolution + execution"]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
ENT --> EXT
|
|
47
|
+
ZOD --> ENT
|
|
48
|
+
EXT --> Engines
|
|
49
|
+
ENT --> Engines
|
|
50
|
+
AER --> AEX
|
|
51
|
+
|
|
52
|
+
style Generated fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
53
|
+
style Custom fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
54
|
+
style Engines fill:#7c5295,stroke:#563a6b,color:#fff
|
|
55
|
+
style Extraction fill:#b8762f,stroke:#8a5722,color:#fff
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Generated Entity Classes
|
|
59
|
+
|
|
60
|
+
CodeGen scans the MemberJunction database schema and produces:
|
|
61
|
+
|
|
62
|
+
- **Zod schema objects** for every entity, providing runtime validation with field-level descriptions, related-entity annotations, and value-list constraints.
|
|
63
|
+
- **Entity subclasses** extending `BaseEntity<T>` with strongly-typed getter/setter properties for every column, typed `Load()` methods, and JSDoc annotations including SQL types, defaults, and foreign key references.
|
|
64
|
+
|
|
65
|
+
There are currently **272 generated entity classes** covering approximately 78,000 lines of code in a single `entity_subclasses.ts` file.
|
|
66
|
+
|
|
67
|
+
### Extended Entity Classes
|
|
68
|
+
|
|
69
|
+
Several entities require custom business logic beyond what CodeGen can generate. Extended classes use `@RegisterClass` to override the generated base class in MJ's class factory:
|
|
70
|
+
|
|
71
|
+
| Extended Class | Entity Name | Purpose |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `UserViewEntityExtended` | User Views | Filter/column JSON parsing, WHERE clause generation, smart filter AI stub, permission checks |
|
|
74
|
+
| `DashboardEntityExtended` | Dashboards | Default config initialization, permission-based validation on save/delete |
|
|
75
|
+
| `EntityEntityExtended` | Entities | Auto-sets `AutoUpdateDescription` when description is manually changed |
|
|
76
|
+
| `EntityFieldEntityExtended` | Entity Fields | Prevents modification of database-reflected properties, auto-sets `AutoUpdateDescription` |
|
|
77
|
+
| `ComponentEntityExtended` | MJ: Components | Syncs derived fields from Specification JSON, keeps `spec` property in sync |
|
|
78
|
+
| `TemplateEntityExtended` | Templates | Content/param management, template input validation |
|
|
79
|
+
| `ScheduledActionEntityExtended` | Scheduled Actions | Auto-generates CronExpression from schedule type settings |
|
|
80
|
+
| `ListDetailEntityExtended` | List Details | Composite key handling, duplicate detection on save |
|
|
81
|
+
| `EnvironmentEntityExtended` | MJ: Environments | Exposes static `DefaultEnvironmentID` constant |
|
|
82
|
+
| `ResourcePermissionEntityExtended` | Resource Permissions | Notification workflow on permission request/approval |
|
|
83
|
+
|
|
84
|
+
### Singleton Engines
|
|
85
|
+
|
|
86
|
+
Engine classes extend `BaseEngine<T>` to provide cached, singleton access to groups of related entities. They load data once and keep it in memory, with auto-refresh when underlying data changes.
|
|
87
|
+
|
|
88
|
+
```mermaid
|
|
89
|
+
flowchart LR
|
|
90
|
+
subgraph App["Application Code"]
|
|
91
|
+
SVC["Services / Components"]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
subgraph Engines["Singleton Engines"]
|
|
95
|
+
UIE["UserInfoEngine"]
|
|
96
|
+
DE["DashboardEngine"]
|
|
97
|
+
RPE["ResourcePermissionEngine"]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
subgraph DB["Database"]
|
|
101
|
+
MJD["MJ Schema"]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
SVC -->|".Instance"| Engines
|
|
105
|
+
Engines -->|"Config() loads once"| DB
|
|
106
|
+
Engines -->|"Cached data"| SVC
|
|
107
|
+
|
|
108
|
+
style App fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
109
|
+
style Engines fill:#7c5295,stroke:#563a6b,color:#fff
|
|
110
|
+
style DB fill:#64748b,stroke:#475569,color:#fff
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Artifact Extraction System
|
|
114
|
+
|
|
115
|
+
A metadata-driven system for extracting structured attributes from artifact content using declarative JavaScript-based rules with hierarchical inheritance through parent artifact types.
|
|
116
|
+
|
|
21
117
|
## Key Features
|
|
22
118
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- **UserViewEntityExtended**: Enhanced view management with filter and column parsing
|
|
34
|
-
- **DashboardEntityExtended**: Dashboard configuration management
|
|
35
|
-
- **AIModelEntityExtended**: AI model utilities and helpers
|
|
36
|
-
- **AIPromptEntityExtended**: Prompt management functionality
|
|
37
|
-
- **ArtifactVersionExtended**: Automatic content hashing and attribute extraction
|
|
38
|
-
- **ListDetailEntityExtended**: List view enhancements
|
|
39
|
-
- **ScheduledActionExtended**: Scheduled task management
|
|
40
|
-
- **ResourcePermissionEntity**: Resource access control
|
|
41
|
-
|
|
42
|
-
### 3. Artifact Extraction System
|
|
43
|
-
A powerful metadata-driven system for extracting structured attributes from artifact content:
|
|
44
|
-
- Hierarchical extract rule inheritance
|
|
45
|
-
- Declarative JavaScript-based extractors
|
|
46
|
-
- Automatic SHA-256 content hashing
|
|
47
|
-
- Standard property mappings for UI rendering
|
|
48
|
-
- Type-safe attribute storage and retrieval
|
|
49
|
-
|
|
50
|
-
### 4. Resource Permission Engine
|
|
51
|
-
A sophisticated permission system for managing access to various resources:
|
|
52
|
-
- Role-based permissions
|
|
53
|
-
- Resource type definitions
|
|
54
|
-
- Permission inheritance
|
|
55
|
-
- Cached permission lookups
|
|
119
|
+
- **272 strongly-typed entity classes** covering all MemberJunction core schema entities
|
|
120
|
+
- **Zod runtime validation** with field-level constraints and value list enums
|
|
121
|
+
- **Extended entity classes** with permission checks, workflow logic, and JSON state parsing
|
|
122
|
+
- **9 singleton engine caches** eliminating redundant database queries
|
|
123
|
+
- **Resource permission engine** with role-based access control (View/Edit/Owner levels)
|
|
124
|
+
- **Dashboard permission engine** with owner/direct/category permission hierarchy
|
|
125
|
+
- **User view engine** with filter-to-SQL conversion and smart filter AI support
|
|
126
|
+
- **Artifact extraction** with hierarchical rule inheritance and sandboxed execution
|
|
127
|
+
- **Encryption engine base** for field-level encryption metadata caching
|
|
56
128
|
|
|
57
129
|
## Usage
|
|
58
130
|
|
|
59
|
-
###
|
|
131
|
+
### Working with Entity Objects
|
|
132
|
+
|
|
133
|
+
Always use `Metadata.GetEntityObject<T>()` to create entity instances -- never instantiate entity classes directly. This ensures the MJ class factory resolves the correct (potentially extended) subclass.
|
|
60
134
|
|
|
61
135
|
```typescript
|
|
62
136
|
import { Metadata } from '@memberjunction/core';
|
|
63
137
|
import { UserEntity, ApplicationEntity } from '@memberjunction/core-entities';
|
|
64
138
|
|
|
65
|
-
// Always use Metadata to create entity instances
|
|
66
139
|
const md = new Metadata();
|
|
67
140
|
|
|
68
|
-
// Load
|
|
141
|
+
// Load an existing record
|
|
69
142
|
const user = await md.GetEntityObject<UserEntity>('Users');
|
|
70
|
-
await user.Load('user-id
|
|
71
|
-
|
|
72
|
-
// Access strongly-typed properties
|
|
143
|
+
await user.Load('some-user-id');
|
|
73
144
|
console.log(user.Email);
|
|
74
145
|
console.log(user.FirstName);
|
|
75
146
|
|
|
76
|
-
// Create a new
|
|
147
|
+
// Create a new record
|
|
77
148
|
const app = await md.GetEntityObject<ApplicationEntity>('Applications');
|
|
78
149
|
app.NewRecord();
|
|
79
|
-
app.Name = 'My
|
|
80
|
-
app.Description = 'A
|
|
150
|
+
app.Name = 'My Application';
|
|
151
|
+
app.Description = 'A custom application';
|
|
81
152
|
await app.Save();
|
|
82
153
|
```
|
|
83
154
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{
|
|
106
|
-
"name": "subject",
|
|
107
|
-
"description": "Email subject line",
|
|
108
|
-
"type": "string",
|
|
109
|
-
"standardProperty": "name",
|
|
110
|
-
"extractor": "const parsed = JSON.parse(content); return parsed.subject || 'Untitled';"
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
"name": "recipientCount",
|
|
114
|
-
"description": "Number of recipients",
|
|
115
|
-
"type": "number",
|
|
116
|
-
"extractor": "const parsed = JSON.parse(content); return parsed.recipients?.length || 0;"
|
|
117
|
-
}
|
|
118
|
-
]
|
|
155
|
+
### Loading Collections with RunView
|
|
156
|
+
|
|
157
|
+
Use `RunView` with generics for loading collections of entity records:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { RunView } from '@memberjunction/core';
|
|
161
|
+
import { ActionEntity } from '@memberjunction/core-entities';
|
|
162
|
+
|
|
163
|
+
const rv = new RunView();
|
|
164
|
+
const result = await rv.RunView<ActionEntity>({
|
|
165
|
+
EntityName: 'Actions',
|
|
166
|
+
ExtraFilter: `Status='Active'`,
|
|
167
|
+
OrderBy: 'Name',
|
|
168
|
+
ResultType: 'entity_object'
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
if (result.Success) {
|
|
172
|
+
for (const action of result.Results) {
|
|
173
|
+
console.log(action.Name, action.Status);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
119
176
|
```
|
|
120
177
|
|
|
121
|
-
###
|
|
178
|
+
### Using the UserViewEntityExtended
|
|
122
179
|
|
|
123
|
-
|
|
124
|
-
|----------|------|-------------|
|
|
125
|
-
| `name` | string | Unique identifier for this rule |
|
|
126
|
-
| `description` | string | Human-readable description |
|
|
127
|
-
| `type` | string | TypeScript type (e.g., `'string'`, `'Array<{x: number}>'`) |
|
|
128
|
-
| `standardProperty` | string? | Maps to: `'name'`, `'description'`, `'displayMarkdown'`, `'displayHtml'` |
|
|
129
|
-
| `extractor` | string | JavaScript code that receives `content` and returns value |
|
|
180
|
+
The extended User View entity parses JSON state columns into structured objects and generates SQL WHERE clauses:
|
|
130
181
|
|
|
131
|
-
|
|
182
|
+
```typescript
|
|
183
|
+
import { Metadata } from '@memberjunction/core';
|
|
184
|
+
import { UserViewEntityExtended, ViewInfo } from '@memberjunction/core-entities';
|
|
185
|
+
|
|
186
|
+
// Load a view by name using the convenience class
|
|
187
|
+
const view = await ViewInfo.GetViewEntityByName('Active Contacts');
|
|
188
|
+
|
|
189
|
+
// Access parsed column and filter info
|
|
190
|
+
const columns = view.Columns; // ViewColumnInfo[]
|
|
191
|
+
const filters = view.Filter; // ViewFilterInfo[]
|
|
192
|
+
const sortInfo = view.ViewSortInfo; // ViewSortInfo[]
|
|
193
|
+
|
|
194
|
+
// Check user permissions
|
|
195
|
+
if (view.UserCanEdit) {
|
|
196
|
+
view.Name = 'Updated View Name';
|
|
197
|
+
await view.Save(); // Auto-regenerates WhereClause from FilterState
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Using Singleton Engines
|
|
202
|
+
|
|
203
|
+
All engines follow the same pattern: get the singleton instance, call `Config()` to load data, then access cached properties.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import {
|
|
207
|
+
UserInfoEngine,
|
|
208
|
+
DashboardEngine,
|
|
209
|
+
ResourcePermissionEngine
|
|
210
|
+
} from '@memberjunction/core-entities';
|
|
211
|
+
|
|
212
|
+
// UserInfoEngine -- notifications, favorites, settings, applications
|
|
213
|
+
const userEngine = UserInfoEngine.Instance;
|
|
214
|
+
await userEngine.Config(false, contextUser);
|
|
215
|
+
const notifications = userEngine.UnreadNotifications;
|
|
216
|
+
const favorites = userEngine.UserFavorites;
|
|
217
|
+
|
|
218
|
+
// Debounced settings (batches rapid updates)
|
|
219
|
+
userEngine.SetSettingDebounced('ui-preference/theme', 'dark');
|
|
220
|
+
|
|
221
|
+
// DashboardEngine -- dashboards, categories, permissions
|
|
222
|
+
const dashEngine = DashboardEngine.Instance;
|
|
223
|
+
await dashEngine.Config(false, contextUser);
|
|
224
|
+
const accessible = dashEngine.GetAccessibleDashboards(userId);
|
|
225
|
+
const canEdit = dashEngine.CanUserEditDashboard(dashboardId, userId);
|
|
226
|
+
|
|
227
|
+
// ResourcePermissionEngine -- role-based resource access
|
|
228
|
+
const permEngine = ResourcePermissionEngine.Instance;
|
|
229
|
+
await permEngine.Config(false, contextUser);
|
|
230
|
+
const level = permEngine.GetUserResourcePermissionLevel(resourceTypeId, recordId, user);
|
|
231
|
+
// Returns 'View' | 'Edit' | 'Owner' | null
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Artifact Extraction
|
|
235
|
+
|
|
236
|
+
Extract structured attributes from artifact content using declarative rules:
|
|
132
237
|
|
|
133
238
|
```typescript
|
|
134
239
|
import { ArtifactExtractor } from '@memberjunction/core-entities';
|
|
135
240
|
|
|
136
|
-
// Resolve extract rules with inheritance
|
|
137
|
-
const rules = ArtifactExtractor.ResolveExtractRules(
|
|
241
|
+
// Resolve extract rules with inheritance from parent types
|
|
242
|
+
const rules = ArtifactExtractor.ResolveExtractRules([
|
|
243
|
+
childArtifactType, // Most specific (overrides parent rules by name)
|
|
244
|
+
parentArtifactType // Least specific
|
|
245
|
+
]);
|
|
138
246
|
|
|
139
247
|
// Extract attributes from content
|
|
140
248
|
const result = await ArtifactExtractor.ExtractAttributes({
|
|
141
|
-
content:
|
|
249
|
+
content: '{"subject": "Q4 Campaign", "body": "..."}',
|
|
142
250
|
extractRules: rules,
|
|
143
251
|
throwOnError: false,
|
|
144
252
|
timeout: 5000
|
|
145
253
|
});
|
|
146
254
|
|
|
147
|
-
//
|
|
255
|
+
// Access extracted values
|
|
148
256
|
const name = ArtifactExtractor.GetStandardProperty(result.attributes, 'name');
|
|
149
257
|
const description = ArtifactExtractor.GetStandardProperty(result.attributes, 'description');
|
|
258
|
+
|
|
259
|
+
// Serialize for database storage
|
|
260
|
+
const serialized = ArtifactExtractor.SerializeForStorage(result.attributes);
|
|
150
261
|
```
|
|
151
262
|
|
|
152
|
-
###
|
|
263
|
+
### Encryption Metadata
|
|
264
|
+
|
|
265
|
+
The `EncryptionEngineBase` provides cached access to encryption keys, algorithms, and key sources:
|
|
153
266
|
|
|
154
267
|
```typescript
|
|
155
|
-
import {
|
|
156
|
-
import { Metadata } from '@memberjunction/core';
|
|
268
|
+
import { EncryptionEngineBase } from '@memberjunction/core-entities';
|
|
157
269
|
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
270
|
+
const engine = EncryptionEngineBase.Instance;
|
|
271
|
+
await engine.Config(false, contextUser);
|
|
272
|
+
|
|
273
|
+
// Validate a key is usable
|
|
274
|
+
const validation = engine.ValidateKey(keyId);
|
|
275
|
+
if (!validation.isValid) {
|
|
276
|
+
console.error(validation.error);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Get full key configuration (key + algorithm + source)
|
|
280
|
+
const config = engine.GetKeyConfiguration(keyId);
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## API Reference
|
|
284
|
+
|
|
285
|
+
### Generated Entity Classes
|
|
286
|
+
|
|
287
|
+
Every generated entity class provides:
|
|
288
|
+
|
|
289
|
+
| Member | Description |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `Load(ID, relationships?)` | Load a record by primary key |
|
|
292
|
+
| `Save(options?)` | Persist changes to the database |
|
|
293
|
+
| `Delete(options?)` | Delete the record |
|
|
294
|
+
| `NewRecord()` | Initialize a blank record for creation |
|
|
295
|
+
| `Validate()` | Run Zod schema validation |
|
|
296
|
+
| Typed getters/setters | One per database column, with JSDoc annotations |
|
|
297
|
+
|
|
298
|
+
### UserViewEntityExtended
|
|
299
|
+
|
|
300
|
+
| Member | Type | Description |
|
|
301
|
+
|---|---|---|
|
|
302
|
+
| `Filter` | `ViewFilterInfo[]` | Parsed filter state from JSON |
|
|
303
|
+
| `Columns` | `ViewColumnInfo[]` | Parsed column configuration from JSON |
|
|
304
|
+
| `ViewSortInfo` | `ViewSortInfo[]` | Parsed sort state |
|
|
305
|
+
| `OrderByClause` | `string` | SQL ORDER BY clause |
|
|
306
|
+
| `ViewEntityInfo` | `EntityInfo` | Metadata for the view's entity |
|
|
307
|
+
| `ParsedDisplayState` | `ViewDisplayState \| null` | View mode and display preferences |
|
|
308
|
+
| `UserCanEdit` | `boolean` | Whether current user can edit this view |
|
|
309
|
+
| `UserCanView` | `boolean` | Whether current user can view this view |
|
|
310
|
+
| `UserCanDelete` | `boolean` | Whether current user can delete this view |
|
|
311
|
+
| `SetDefaultsFromEntity(e)` | method | Initialize columns from entity metadata |
|
|
312
|
+
| `UpdateWhereClause()` | method | Regenerate WHERE clause from filter state |
|
|
313
|
+
|
|
314
|
+
### ViewInfo (Static Utility)
|
|
315
|
+
|
|
316
|
+
| Method | Description |
|
|
317
|
+
|---|---|
|
|
318
|
+
| `GetViewsForUser(entityId?, contextUser?)` | Load all views for a user |
|
|
319
|
+
| `GetViewID(viewName)` | Look up a view ID by name |
|
|
320
|
+
| `GetViewEntity(viewId, contextUser?)` | Get a cached view by ID |
|
|
321
|
+
| `GetViewEntityByName(viewName, contextUser?)` | Get a cached view by name |
|
|
322
|
+
|
|
323
|
+
### UserInfoEngine
|
|
324
|
+
|
|
325
|
+
| Member | Description |
|
|
326
|
+
|---|---|
|
|
327
|
+
| `UserNotifications` | Notifications for current user (newest first) |
|
|
328
|
+
| `UnreadNotifications` | Unread notifications only |
|
|
329
|
+
| `Workspaces` | User's workspaces |
|
|
330
|
+
| `UserApplications` | Installed applications (sorted by sequence) |
|
|
331
|
+
| `UserFavorites` | Favorited records (newest first) |
|
|
332
|
+
| `UserRecordLogs` | Recent record access history |
|
|
333
|
+
| `UserSettings` | User settings key-value pairs |
|
|
334
|
+
| `GetSetting(key)` | Get a setting value by key |
|
|
335
|
+
| `SetSetting(key, value)` | Create or update a setting |
|
|
336
|
+
| `SetSettingDebounced(key, value)` | Debounced setting update for rapid UI changes |
|
|
337
|
+
| `FlushPendingSettings()` | Force-save all debounced settings |
|
|
338
|
+
| `InstallApplication(appId)` | Install an application for the user |
|
|
339
|
+
| `DisableApplication(appId)` | Disable (but not delete) an application |
|
|
340
|
+
| `CreateDefaultApplications()` | Create records for default-for-new-user apps |
|
|
341
|
+
| `NotificationPreferences` | User's notification preferences |
|
|
342
|
+
|
|
343
|
+
### DashboardEngine
|
|
344
|
+
|
|
345
|
+
| Member | Description |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `Dashboards` | All cached dashboards |
|
|
348
|
+
| `DashboardCategories` | All dashboard categories |
|
|
349
|
+
| `DashboardPartTypes` | Dashboard widget/part types |
|
|
350
|
+
| `GetDashboardPermissions(id, userId)` | Get effective permissions (owner/direct/category) |
|
|
351
|
+
| `CanUserReadDashboard(id, userId)` | Check read access |
|
|
352
|
+
| `CanUserEditDashboard(id, userId)` | Check edit access |
|
|
353
|
+
| `CanUserDeleteDashboard(id, userId)` | Check delete access |
|
|
354
|
+
| `GetAccessibleDashboards(userId)` | All dashboards user can read |
|
|
355
|
+
| `GetSharedDashboards(userId)` | Dashboards shared with user (not owned) |
|
|
356
|
+
| `GetAccessibleCategories(userId)` | Categories user can access |
|
|
357
|
+
|
|
358
|
+
### ResourcePermissionEngine
|
|
359
|
+
|
|
360
|
+
| Member | Description |
|
|
361
|
+
|---|---|
|
|
362
|
+
| `ResourceTypes` | All resource type definitions |
|
|
363
|
+
| `Permissions` | All resource permission records |
|
|
364
|
+
| `GetResourcePermissions(typeId, recordId)` | Get all permissions for a resource |
|
|
365
|
+
| `GetUserResourcePermissionLevel(typeId, recordId, user)` | Get highest permission level (View/Edit/Owner/null) |
|
|
366
|
+
| `GetUserAvailableResources(user, typeId?)` | Get all resources a user can access |
|
|
367
|
+
|
|
368
|
+
### UserViewEngine
|
|
369
|
+
|
|
370
|
+
| Member | Description |
|
|
371
|
+
|---|---|
|
|
372
|
+
| `AllViews` | All cached views |
|
|
373
|
+
| `GetViewById(id)` | Look up view by ID |
|
|
374
|
+
| `GetViewByName(name)` | Look up view by name |
|
|
375
|
+
| `GetViewsForEntity(entityId)` | Views for a specific entity |
|
|
376
|
+
| `GetViewsForCurrentUser()` | Views owned by current user |
|
|
377
|
+
| `GetAccessibleViewsForEntity(entityId)` | Owned + shared views with permission checks |
|
|
378
|
+
| `GetDefaultViewForEntity(entityId)` | Default view for an entity |
|
|
379
|
+
|
|
380
|
+
### ArtifactExtractor
|
|
381
|
+
|
|
382
|
+
| Method | Description |
|
|
383
|
+
|---|---|
|
|
384
|
+
| `ResolveExtractRules(typeChain)` | Resolve rules with hierarchical inheritance |
|
|
385
|
+
| `ExtractAttributes(config)` | Execute extraction rules against content |
|
|
386
|
+
| `SerializeForStorage(attributes)` | Convert attributes to database-storable format |
|
|
387
|
+
| `DeserializeFromStorage(stored)` | Convert stored attributes back to runtime objects |
|
|
388
|
+
| `GetStandardProperty(attributes, prop)` | Find a standard property value (name/description/etc.) |
|
|
389
|
+
|
|
390
|
+
### Other Engines
|
|
391
|
+
|
|
392
|
+
| Engine | Purpose |
|
|
393
|
+
|---|---|
|
|
394
|
+
| `EncryptionEngineBase` | Caches encryption keys, algorithms, and key sources |
|
|
395
|
+
| `FileStorageEngine` | Caches file storage accounts and providers |
|
|
396
|
+
| `MCPEngine` | Caches MCP servers, connections, and tools |
|
|
397
|
+
| `ComponentMetadataEngine` | Caches component definitions, libraries, and registries |
|
|
398
|
+
| `ArtifactMetadataEngine` | Caches artifact type definitions |
|
|
399
|
+
| `TypeTablesCache` | Caches entity relationship display components |
|
|
400
|
+
|
|
401
|
+
## Permission Model
|
|
402
|
+
|
|
403
|
+
The package implements a layered permission model used across views, dashboards, and resources:
|
|
404
|
+
|
|
405
|
+
```mermaid
|
|
406
|
+
flowchart TD
|
|
407
|
+
subgraph Check["Permission Resolution Order"]
|
|
408
|
+
direction TB
|
|
409
|
+
OWN["1. Ownership Check<br/>Record owner gets full access"]
|
|
410
|
+
ADM["2. Admin Check<br/>System admins get full access"]
|
|
411
|
+
DIR["3. Direct Permission<br/>User-specific grants"]
|
|
412
|
+
CAT["4. Category Permission<br/>Inherited from categories"]
|
|
413
|
+
ROL["5. Role Permission<br/>Granted through user roles"]
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
OWN -->|"Not owner"| ADM
|
|
417
|
+
ADM -->|"Not admin"| DIR
|
|
418
|
+
DIR -->|"No direct grant"| CAT
|
|
419
|
+
CAT -->|"No category grant"| ROL
|
|
420
|
+
ROL -->|"No role grant"| DENY["Access Denied"]
|
|
421
|
+
|
|
422
|
+
style Check fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
423
|
+
style DENY fill:#64748b,stroke:#475569,color:#fff
|
|
172
424
|
```
|
|
173
425
|
|
|
174
|
-
|
|
426
|
+
Permission levels are hierarchical: **Owner** > **Edit** > **View**. The engine returns the highest applicable level across all sources (direct user grants and role-based grants).
|
|
427
|
+
|
|
428
|
+
## View Filter Architecture
|
|
429
|
+
|
|
430
|
+
The `UserViewEntityExtended` converts structured filter JSON into SQL WHERE clauses:
|
|
431
|
+
|
|
432
|
+
```mermaid
|
|
433
|
+
flowchart LR
|
|
434
|
+
subgraph Input["Filter State (JSON)"]
|
|
435
|
+
FS["{ logic: 'and',<br/>filters: [...] }"]
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
subgraph Process["UserViewEntityExtended"]
|
|
439
|
+
PARSE["Parse FilterState<br/>JSON column"]
|
|
440
|
+
GEN["GenerateWhereClause()<br/>Recursive group processing"]
|
|
441
|
+
SQL["SQL WHERE clause"]
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
subgraph Modes["Filter Modes"]
|
|
445
|
+
STD["Standard Filter<br/>UI-driven FilterState"]
|
|
446
|
+
SMART["Smart Filter<br/>AI-generated from prompt"]
|
|
447
|
+
CUSTOM["Custom Filter<br/>Admin-set WhereClause"]
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
FS --> PARSE --> GEN --> SQL
|
|
451
|
+
Modes --> GEN
|
|
452
|
+
|
|
453
|
+
style Input fill:#b8762f,stroke:#8a5722,color:#fff
|
|
454
|
+
style Process fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
455
|
+
style Modes fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Supported filter operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `startswith`, `endswith`, `contains`, `doesnotcontain`, `isnull`, `isempty`, `isnotnull`, `isnotempty`. Filters support arbitrary nesting with `and`/`or` logic groups.
|
|
459
|
+
|
|
460
|
+
## Important: CodeGen and This Package
|
|
175
461
|
|
|
176
|
-
|
|
462
|
+
This package's `src/generated/entity_subclasses.ts` file is **entirely auto-generated** by the MemberJunction CodeGen system. Key implications:
|
|
177
463
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
5. **Use extended classes**: When available, use extended versions for additional functionality
|
|
183
|
-
6. **Import artifacts from core-entities**: Artifact extraction utilities are in this package
|
|
464
|
+
- **Never edit generated files** -- changes will be overwritten on the next CodeGen run.
|
|
465
|
+
- **Custom logic goes in `src/custom/`** -- create an extended class with `@RegisterClass` to override the generated base.
|
|
466
|
+
- **Entity names matter** -- some entities use the `MJ: ` prefix (e.g., `MJ: Components`, `MJ: Environments`). Always verify names in the generated file's `@RegisterClass` decorators.
|
|
467
|
+
- **Zod schemas are authoritative** -- they reflect the exact database constraints including value lists, nullable fields, and default values.
|
|
184
468
|
|
|
185
469
|
## Dependencies
|
|
186
470
|
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
471
|
+
- [@memberjunction/core](../MJCore/README.md) -- Base entity classes, metadata system, RunView, BaseEngine
|
|
472
|
+
- [@memberjunction/global](../MJGlobal/README.md) -- `@RegisterClass` decorator, global utilities
|
|
473
|
+
- [@memberjunction/ai](../AI/README.md) -- AI integration types (used by some engine classes)
|
|
474
|
+
- [@memberjunction/interactive-component-types](../InteractiveComponentTypes/README.md) -- ComponentSpec type for component entity extensions
|
|
475
|
+
- [zod](https://zod.dev/) -- Runtime schema validation
|
|
190
476
|
|
|
191
|
-
##
|
|
477
|
+
## Related Packages
|
|
192
478
|
|
|
193
|
-
|
|
479
|
+
- [@memberjunction/core](../MJCore/README.md) -- Framework foundation this package builds on
|
|
480
|
+
- [@memberjunction/core-entities-server](../MJCoreEntitiesServer/README.md) -- Server-side extensions of entities defined here (e.g., smart filter AI implementation)
|
|
481
|
+
- [@memberjunction/server](../MJServer/README.md) -- Server that uses these entities for API operations
|
|
194
482
|
|
|
195
|
-
##
|
|
483
|
+
## Contributing
|
|
196
484
|
|
|
197
|
-
|
|
485
|
+
See the [MemberJunction Contributing Guide](../../CONTRIBUTING.md) for development setup and guidelines.
|