@memberjunction/core 2.43.0 → 2.44.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/package.json +2 -2
- package/readme.md +308 -55
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"description": "MemberJunction: Core Library including Metadata, Application, Entity Retrieval and Manipulation, and Utilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@types/debug": "^4.1.12"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@memberjunction/global": "2.
|
|
23
|
+
"@memberjunction/global": "2.44.0",
|
|
24
24
|
"rxjs": "^7.8.1",
|
|
25
25
|
"zod": "^3.23.8",
|
|
26
26
|
"debug": "^4.4.0"
|
package/readme.md
CHANGED
|
@@ -1,107 +1,360 @@
|
|
|
1
1
|
# @memberjunction/core
|
|
2
2
|
|
|
3
|
-
The `@memberjunction/core` library provides a comprehensive interface for accessing and managing metadata within MemberJunction, along with facilities for working with entities, applications, and various other aspects central to the MemberJunction ecosystem. This library
|
|
3
|
+
The `@memberjunction/core` library provides a comprehensive interface for accessing and managing metadata within MemberJunction, along with facilities for working with entities, applications, and various other aspects central to the MemberJunction ecosystem. This library serves as the foundation for all MemberJunction applications and provides essential functionality for data access, manipulation, and metadata management.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @memberjunction/core
|
|
9
|
+
```
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
11
|
+
## Overview
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The `@memberjunction/core` library is the central package in the MemberJunction ecosystem, providing:
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
- **Metadata Management**: Complete access to MemberJunction metadata including entities, fields, relationships, permissions, and more
|
|
16
|
+
- **Entity Data Access**: Base classes and utilities for loading, saving, and manipulating entity records
|
|
17
|
+
- **View Execution**: Powerful view running capabilities for both stored and dynamic views
|
|
18
|
+
- **Query & Report Execution**: Tools for running queries and reports
|
|
19
|
+
- **Security & Authorization**: User authentication, role management, and permission handling
|
|
20
|
+
- **Transaction Management**: Support for grouped database transactions
|
|
21
|
+
- **Provider Architecture**: Flexible provider model supporting different execution environments
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
## Core Components
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
### Metadata Class
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
The `Metadata` class is the primary entry point for accessing MemberJunction metadata and instantiating entity objects.
|
|
24
28
|
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
```
|
|
29
|
+
```typescript
|
|
30
|
+
import { Metadata } from '@memberjunction/core';
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
// Create metadata instance
|
|
33
|
+
const md = new Metadata();
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
// Refresh cached metadata
|
|
32
36
|
await md.Refresh();
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
#### Getting Applications, Entities, and Other Info
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
// Access various metadata collections
|
|
38
39
|
const applications = md.Applications;
|
|
39
40
|
const entities = md.Entities;
|
|
40
41
|
const currentUser = md.CurrentUser;
|
|
41
|
-
|
|
42
|
+
const roles = md.Roles;
|
|
43
|
+
const authorizations = md.Authorizations;
|
|
42
44
|
```
|
|
43
45
|
|
|
44
|
-
####
|
|
46
|
+
#### Key Metadata Properties
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
- `Applications`: Array of all applications in the system
|
|
49
|
+
- `Entities`: Array of all entity definitions
|
|
50
|
+
- `CurrentUser`: Current authenticated user (when available)
|
|
51
|
+
- `Roles`: System roles
|
|
52
|
+
- `AuditLogTypes`: Available audit log types
|
|
53
|
+
- `Authorizations`: Authorization definitions
|
|
54
|
+
- `Libraries`: Registered libraries
|
|
55
|
+
- `Queries`: Query definitions
|
|
56
|
+
- `QueryFields`: Query field metadata
|
|
57
|
+
- `QueryCategories`: Query categorization
|
|
58
|
+
- `QueryPermissions`: Query-level permissions
|
|
59
|
+
- `VisibleExplorerNavigationItems`: Navigation items visible to current user
|
|
60
|
+
- `AllExplorerNavigationItems`: All navigation items (including hidden)
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
const entityName = md.EntityNameFromID(1);
|
|
62
|
+
#### Helper Methods
|
|
52
63
|
|
|
53
|
-
|
|
64
|
+
```typescript
|
|
65
|
+
// Get entity ID from name
|
|
66
|
+
const entityId = md.EntityIDFromName('Users');
|
|
67
|
+
|
|
68
|
+
// Get entity name from ID
|
|
69
|
+
const entityName = md.EntityNameFromID('12345');
|
|
70
|
+
|
|
71
|
+
// Find entity by name (case-insensitive)
|
|
72
|
+
const userEntity = md.EntityByName('users');
|
|
73
|
+
|
|
74
|
+
// Find entity by ID
|
|
75
|
+
const entity = md.EntityByID('12345');
|
|
76
|
+
|
|
77
|
+
// Get entity object instance (IMPORTANT: Always use this pattern)
|
|
78
|
+
const user = await md.GetEntityObject<UserEntity>('Users');
|
|
54
79
|
```
|
|
55
80
|
|
|
56
|
-
|
|
81
|
+
### BaseEntity Class
|
|
82
|
+
|
|
83
|
+
The `BaseEntity` class is the foundation for all entity record manipulation in MemberJunction. All entity classes generated by the MemberJunction code generator extend this class.
|
|
57
84
|
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
|
|
85
|
+
```typescript
|
|
86
|
+
import { Metadata } from '@memberjunction/core';
|
|
87
|
+
|
|
88
|
+
// IMPORTANT: Never instantiate entity classes directly
|
|
89
|
+
// Always use Metadata.GetEntityObject() to ensure proper class registration
|
|
90
|
+
|
|
91
|
+
// ✅ Correct way to create entity instances
|
|
92
|
+
const md = new Metadata();
|
|
93
|
+
const user = await md.GetEntityObject<UserEntity>('Users');
|
|
94
|
+
|
|
95
|
+
// Load a record by ID
|
|
96
|
+
await user.Load(123);
|
|
97
|
+
|
|
98
|
+
// Create a new record
|
|
99
|
+
user.NewRecord();
|
|
100
|
+
user.FirstName = 'John';
|
|
101
|
+
user.LastName = 'Doe';
|
|
102
|
+
user.Email = 'john.doe@example.com';
|
|
103
|
+
|
|
104
|
+
// Save the record (creates new or updates existing)
|
|
105
|
+
const saveResult = await user.Save();
|
|
106
|
+
if (saveResult) {
|
|
107
|
+
console.log('User saved successfully:', user.ID);
|
|
108
|
+
} else {
|
|
109
|
+
console.log('Save failed:', user.LatestResult.Message);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Delete a record
|
|
113
|
+
const deleteResult = await user.Delete();
|
|
61
114
|
```
|
|
62
115
|
|
|
63
|
-
|
|
116
|
+
#### Entity Fields
|
|
64
117
|
|
|
65
|
-
|
|
118
|
+
Each entity field is represented by an `EntityField` object that tracks value, dirty state, and metadata:
|
|
66
119
|
|
|
67
|
-
|
|
120
|
+
```typescript
|
|
121
|
+
// Access field value
|
|
122
|
+
const firstName = user.Get('FirstName');
|
|
68
123
|
|
|
69
|
-
|
|
124
|
+
// Set field value
|
|
125
|
+
user.Set('FirstName', 'Jane');
|
|
70
126
|
|
|
71
|
-
|
|
72
|
-
|
|
127
|
+
// Check if field is dirty
|
|
128
|
+
const isDirty = user.Fields.find(f => f.Name === 'FirstName').Dirty;
|
|
129
|
+
|
|
130
|
+
// Access field metadata
|
|
131
|
+
const field = user.Fields.find(f => f.Name === 'Email');
|
|
132
|
+
console.log(field.IsUnique); // true/false
|
|
133
|
+
console.log(field.IsPrimaryKey); // true/false
|
|
134
|
+
console.log(field.ReadOnly); // true/false
|
|
73
135
|
```
|
|
74
136
|
|
|
75
|
-
|
|
137
|
+
#### Save Options
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { EntitySaveOptions } from '@memberjunction/core';
|
|
141
|
+
|
|
142
|
+
const options = new EntitySaveOptions();
|
|
143
|
+
options.IgnoreDirtyState = true; // Force save even if no changes detected
|
|
144
|
+
options.SkipEntityAIActions = true; // Skip AI-related actions
|
|
145
|
+
options.SkipEntityActions = true; // Skip entity actions
|
|
146
|
+
options.SkipOldValuesCheck = true; // Skip concurrency check (client-side only)
|
|
147
|
+
|
|
148
|
+
await entity.Save(options);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### RunView Class
|
|
152
|
+
|
|
153
|
+
The `RunView` class provides powerful view execution capabilities for both stored views and dynamic queries.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { RunView, RunViewParams } from '@memberjunction/core';
|
|
76
157
|
|
|
77
|
-
|
|
158
|
+
const rv = new RunView();
|
|
78
159
|
|
|
79
|
-
|
|
160
|
+
// Run a stored view by name
|
|
80
161
|
const params: RunViewParams = {
|
|
81
|
-
ViewName: '
|
|
82
|
-
ExtraFilter: '
|
|
83
|
-
|
|
84
|
-
Fields: ['FirstName', 'LastName'],
|
|
85
|
-
UserSearchString: 'Smith'
|
|
86
|
-
// ... other optional properties as needed
|
|
162
|
+
ViewName: 'Active Users',
|
|
163
|
+
ExtraFilter: 'CreatedDate > \'2024-01-01\'',
|
|
164
|
+
UserSearchString: 'john'
|
|
87
165
|
};
|
|
166
|
+
|
|
167
|
+
const results = await rv.RunView(params);
|
|
168
|
+
|
|
169
|
+
// Run a dynamic view with entity objects returned
|
|
170
|
+
const dynamicResults = await rv.RunView<UserEntity>({
|
|
171
|
+
EntityName: 'Users',
|
|
172
|
+
ExtraFilter: 'IsActive = 1',
|
|
173
|
+
OrderBy: 'LastName ASC, FirstName ASC',
|
|
174
|
+
Fields: ['ID', 'FirstName', 'LastName', 'Email'],
|
|
175
|
+
ResultType: 'entity_object' // Returns actual entity objects
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Access typed results
|
|
179
|
+
const users = dynamicResults.Results; // Properly typed as UserEntity[]
|
|
88
180
|
```
|
|
89
181
|
|
|
90
|
-
|
|
182
|
+
#### RunView Parameters
|
|
183
|
+
|
|
184
|
+
- `ViewID`: ID of stored view to run
|
|
185
|
+
- `ViewName`: Name of stored view to run
|
|
186
|
+
- `ViewEntity`: Pre-loaded view entity object (optimal for performance)
|
|
187
|
+
- `EntityName`: Entity name for dynamic views
|
|
188
|
+
- `ExtraFilter`: Additional SQL WHERE clause
|
|
189
|
+
- `OrderBy`: SQL ORDER BY clause (overrides stored view sorting)
|
|
190
|
+
- `Fields`: Array of field names to return
|
|
191
|
+
- `UserSearchString`: User search term
|
|
192
|
+
- `ExcludeUserViewRunID`: Exclude records from specific prior run
|
|
193
|
+
- `ExcludeDataFromAllPriorViewRuns`: Exclude all previously returned records
|
|
194
|
+
- `SaveViewResults`: Store run results for future exclusion
|
|
195
|
+
- `IgnoreMaxRows`: Bypass entity MaxRows setting
|
|
196
|
+
- `MaxRows`: Maximum rows to return
|
|
197
|
+
- `StartRow`: Row offset for pagination
|
|
198
|
+
- `ResultType`: 'simple' (default) or 'entity_object'
|
|
199
|
+
|
|
200
|
+
### RunQuery Class
|
|
201
|
+
|
|
202
|
+
Execute stored queries with parameters:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { RunQuery, RunQueryParams } from '@memberjunction/core';
|
|
206
|
+
|
|
207
|
+
const rq = new RunQuery();
|
|
208
|
+
|
|
209
|
+
const params: RunQueryParams = {
|
|
210
|
+
QueryID: '12345',
|
|
211
|
+
Parameters: {
|
|
212
|
+
StartDate: '2024-01-01',
|
|
213
|
+
EndDate: '2024-12-31',
|
|
214
|
+
Status: 'Active'
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const results = await rq.RunQuery(params);
|
|
219
|
+
```
|
|
91
220
|
|
|
92
|
-
|
|
221
|
+
### RunReport Class
|
|
93
222
|
|
|
94
|
-
|
|
223
|
+
Execute reports with various output formats:
|
|
95
224
|
|
|
96
|
-
```
|
|
97
|
-
|
|
225
|
+
```typescript
|
|
226
|
+
import { RunReport, RunReportParams } from '@memberjunction/core';
|
|
227
|
+
|
|
228
|
+
const rr = new RunReport();
|
|
229
|
+
|
|
230
|
+
const params: RunReportParams = {
|
|
231
|
+
ReportID: '12345',
|
|
232
|
+
Parameters: {
|
|
233
|
+
Year: 2024,
|
|
234
|
+
Department: 'Sales'
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const results = await rr.RunReport(params);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Transaction Management
|
|
242
|
+
|
|
243
|
+
Group multiple operations in a transaction:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { TransactionGroupBase } from '@memberjunction/core';
|
|
247
|
+
|
|
248
|
+
// Transaction management is provider-specific
|
|
249
|
+
// Consult your provider documentation for implementation details
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Entity Relationships
|
|
253
|
+
|
|
254
|
+
MemberJunction automatically handles entity relationships through the metadata system:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Load an entity with related data
|
|
258
|
+
const order = await md.GetEntityObject<OrderEntity>('Orders');
|
|
259
|
+
await order.Load(123, ['OrderDetails', 'Customer']);
|
|
260
|
+
|
|
261
|
+
// Access related entities
|
|
262
|
+
const orderDetails = order.OrderDetails; // Array of OrderDetailEntity
|
|
263
|
+
const customer = order.Customer; // CustomerEntity
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Security & Permissions
|
|
267
|
+
|
|
268
|
+
The library provides comprehensive security features:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
const md = new Metadata();
|
|
272
|
+
|
|
273
|
+
// Check current user
|
|
274
|
+
const user = md.CurrentUser;
|
|
275
|
+
console.log('Current user:', user.Email);
|
|
276
|
+
|
|
277
|
+
// Check user roles
|
|
278
|
+
const isAdmin = user.RoleName.includes('Admin');
|
|
279
|
+
|
|
280
|
+
// Entity permissions
|
|
281
|
+
const entity = md.EntityByName('Orders');
|
|
282
|
+
const canCreate = entity.CanCreate;
|
|
283
|
+
const canUpdate = entity.CanUpdate;
|
|
284
|
+
const canDelete = entity.CanDelete;
|
|
98
285
|
```
|
|
99
286
|
|
|
100
|
-
|
|
287
|
+
## Error Handling
|
|
288
|
+
|
|
289
|
+
All operations return detailed error information:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
const entity = await md.GetEntityObject('Users');
|
|
293
|
+
const result = await entity.Save();
|
|
294
|
+
|
|
295
|
+
if (!result) {
|
|
296
|
+
// Access detailed error information
|
|
297
|
+
const error = entity.LatestResult;
|
|
298
|
+
console.error('Error:', error.Message);
|
|
299
|
+
console.error('Details:', error.Details);
|
|
300
|
+
|
|
301
|
+
// Check validation errors
|
|
302
|
+
if (error.ValidationErrors && error.ValidationErrors.length > 0) {
|
|
303
|
+
error.ValidationErrors.forEach(ve => {
|
|
304
|
+
console.error(`Field ${ve.FieldName}: ${ve.Message}`);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
101
309
|
|
|
102
|
-
|
|
103
|
-
|
|
310
|
+
## Provider Architecture
|
|
311
|
+
|
|
312
|
+
MemberJunction uses a provider model to support different execution environments:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { SetProvider } from '@memberjunction/core';
|
|
316
|
+
|
|
317
|
+
// Provider setup is typically handled by your application initialization
|
|
318
|
+
// The provider determines how data is accessed (direct database, API, etc.)
|
|
319
|
+
SetProvider(myProvider);
|
|
104
320
|
```
|
|
105
321
|
|
|
106
|
-
|
|
322
|
+
## Best Practices
|
|
323
|
+
|
|
324
|
+
1. **Always use Metadata.GetEntityObject()** to create entity instances - never use `new`
|
|
325
|
+
2. **Use generic types** with RunView for type-safe results
|
|
326
|
+
3. **Handle errors properly** - check return values and LatestResult
|
|
327
|
+
4. **Use transactions** for related operations that must succeed/fail together
|
|
328
|
+
5. **Leverage metadata** for dynamic UI generation and validation
|
|
329
|
+
6. **Respect permissions** - always check CanCreate/Update/Delete before operations
|
|
330
|
+
7. **Use ExtraFilter** carefully - ensure SQL injection protection
|
|
331
|
+
8. **Cache metadata instances** when possible to improve performance
|
|
332
|
+
|
|
333
|
+
## Integration with Other MemberJunction Packages
|
|
334
|
+
|
|
335
|
+
- **@memberjunction/global**: Global utilities and constants
|
|
336
|
+
- **@memberjunction/server**: Server-side provider implementation
|
|
337
|
+
- **@memberjunction/client**: Client-side provider implementation
|
|
338
|
+
- **@memberjunction/angular**: Angular-specific components and services
|
|
339
|
+
- **@memberjunction/react**: React-specific components and hooks
|
|
340
|
+
- **@memberjunction/ai**: AI integration features
|
|
341
|
+
- **@memberjunction/communication**: Communication and messaging features
|
|
342
|
+
|
|
343
|
+
## Dependencies
|
|
344
|
+
|
|
345
|
+
- **@memberjunction/global**: Core global utilities
|
|
346
|
+
- **rxjs**: Reactive programming support
|
|
347
|
+
- **zod**: Schema validation
|
|
348
|
+
- **debug**: Debug logging
|
|
349
|
+
|
|
350
|
+
## TypeScript Support
|
|
351
|
+
|
|
352
|
+
This library is written in TypeScript and provides full type definitions. All generated entity classes include proper typing for IntelliSense support.
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
ISC License - see LICENSE file for details
|
|
357
|
+
|
|
358
|
+
## Support
|
|
107
359
|
|
|
360
|
+
For support, documentation, and examples, visit [MemberJunction.com](https://www.memberjunction.com)
|