@memberjunction/data-context 2.42.1 → 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 +4 -4
- package/readme.md +304 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/data-context",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"description": "This library provides a set of objects that handle run-time loading of data contexts as well as types to be able to use across application tiers for interacting with data contexts.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"typescript": "^5.4.5"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@memberjunction/global": "2.
|
|
23
|
-
"@memberjunction/core-entities": "2.
|
|
24
|
-
"@memberjunction/core": "2.
|
|
22
|
+
"@memberjunction/global": "2.44.0",
|
|
23
|
+
"@memberjunction/core-entities": "2.44.0",
|
|
24
|
+
"@memberjunction/core": "2.44.0"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/readme.md
CHANGED
|
@@ -1,3 +1,306 @@
|
|
|
1
1
|
# @memberjunction/data-context
|
|
2
2
|
|
|
3
|
-
The `@memberjunction/data-context` library provides a
|
|
3
|
+
The `@memberjunction/data-context` library provides a comprehensive framework for managing data contexts in MemberJunction applications. It enables developers to define, load, and manipulate collections of related data items across different tiers of an application.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
A Data Context in MemberJunction represents a collection of data items that can include:
|
|
8
|
+
- **Views**: Filtered and customized views of entity data
|
|
9
|
+
- **Queries**: Pre-defined SQL queries registered in the system
|
|
10
|
+
- **Full Entities**: Complete data sets from an entity
|
|
11
|
+
- **Single Records**: Individual entity records with optional related data
|
|
12
|
+
- **SQL Statements**: Direct SQL queries (server-side only)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @memberjunction/data-context
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Key Features
|
|
21
|
+
|
|
22
|
+
- **Type-safe data context management**: Full TypeScript support with proper typing
|
|
23
|
+
- **Flexible data loading**: Support for various data sources including views, queries, entities, and SQL
|
|
24
|
+
- **Metadata-driven**: Automatic loading of metadata from the MemberJunction system
|
|
25
|
+
- **Transaction support**: Save multiple data context items in a single transaction
|
|
26
|
+
- **Cross-tier compatibility**: Works across server and client tiers with appropriate implementations
|
|
27
|
+
- **Data persistence**: Optional saving of loaded data to the database
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### Basic Example
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { DataContext, DataContextItem } from '@memberjunction/data-context';
|
|
35
|
+
import { Metadata } from '@memberjunction/core';
|
|
36
|
+
|
|
37
|
+
// Create a new data context
|
|
38
|
+
const context = new DataContext();
|
|
39
|
+
|
|
40
|
+
// Load metadata and data for an existing data context
|
|
41
|
+
const dataContextID = 'your-data-context-id';
|
|
42
|
+
const loaded = await context.Load(
|
|
43
|
+
dataContextID,
|
|
44
|
+
dataSource, // Required for SQL type items (server-side only)
|
|
45
|
+
false, // forceRefresh
|
|
46
|
+
true, // loadRelatedDataOnSingleRecords
|
|
47
|
+
10, // maxRecordsPerRelationship
|
|
48
|
+
userInfo // contextUser
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (loaded) {
|
|
52
|
+
// Access the loaded data
|
|
53
|
+
context.Items.forEach(item => {
|
|
54
|
+
console.log(`Item: ${item.Description}`);
|
|
55
|
+
console.log(`Data rows: ${item.Data?.length || 0}`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Creating Data Context Items
|
|
61
|
+
|
|
62
|
+
#### From a View
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { UserViewEntityExtended } from '@memberjunction/core-entities';
|
|
66
|
+
|
|
67
|
+
// Assuming you have a view entity loaded
|
|
68
|
+
const viewEntity: UserViewEntityExtended = await md.GetEntityObject<UserViewEntityExtended>('User Views');
|
|
69
|
+
await viewEntity.Load(viewID);
|
|
70
|
+
|
|
71
|
+
const viewItem = DataContextItem.FromViewEntity(viewEntity);
|
|
72
|
+
context.Items.push(viewItem);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### From a Single Record
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { BaseEntity } from '@memberjunction/core';
|
|
79
|
+
|
|
80
|
+
// Assuming you have an entity record loaded
|
|
81
|
+
const record: BaseEntity = await md.GetEntityObject('Customers');
|
|
82
|
+
await record.Load(recordID);
|
|
83
|
+
|
|
84
|
+
const recordItem = DataContextItem.FromSingleRecord(record);
|
|
85
|
+
context.Items.push(recordItem);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### From a Query
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { QueryInfo } from '@memberjunction/core';
|
|
92
|
+
|
|
93
|
+
// Get query info from metadata
|
|
94
|
+
const queryInfo = md.Queries.find(q => q.Name === 'My Query');
|
|
95
|
+
if (queryInfo) {
|
|
96
|
+
const queryItem = DataContextItem.FromQuery(queryInfo);
|
|
97
|
+
context.Items.push(queryItem);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### From a Full Entity
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { EntityInfo } from '@memberjunction/core';
|
|
105
|
+
|
|
106
|
+
// Get entity info from metadata
|
|
107
|
+
const entityInfo = md.Entities.find(e => e.Name === 'Products');
|
|
108
|
+
if (entityInfo) {
|
|
109
|
+
const entityItem = DataContextItem.FromFullEntity(entityInfo);
|
|
110
|
+
context.Items.push(entityItem);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Loading Data for Items
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Load data for all items in the context
|
|
118
|
+
const dataLoaded = await context.LoadData(
|
|
119
|
+
dataSource, // Required for SQL type items
|
|
120
|
+
false, // forceRefresh
|
|
121
|
+
true, // loadRelatedDataOnSingleRecords
|
|
122
|
+
10 // maxRecordsPerRelationship
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// Or load data for a specific item
|
|
126
|
+
const itemLoaded = await context.Items[0].LoadData(
|
|
127
|
+
dataSource,
|
|
128
|
+
false,
|
|
129
|
+
true,
|
|
130
|
+
10
|
|
131
|
+
);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Saving Data Context Items
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// Save all items in the context to the database
|
|
138
|
+
const saved = await context.SaveItems(
|
|
139
|
+
userInfo, // contextUser
|
|
140
|
+
true // persistItemData - saves actual data, not just metadata
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
if (saved) {
|
|
144
|
+
console.log('Data context items saved successfully');
|
|
145
|
+
// Each item now has a DataContextItemID populated
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Working with Data
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Validate that all items have data loaded
|
|
153
|
+
if (context.ValidateDataExists()) {
|
|
154
|
+
// Convert to a simple object for easier manipulation
|
|
155
|
+
const simpleData = context.ConvertToSimpleObject('item_', false);
|
|
156
|
+
// Result: { item_0: [...], item_1: [...], ... }
|
|
157
|
+
|
|
158
|
+
// Get type definition for the data structure
|
|
159
|
+
const typeDef = context.CreateSimpleObjectTypeDefinition('item_');
|
|
160
|
+
console.log(typeDef);
|
|
161
|
+
// Output: {item_0: []; // View: Customer List, From Entity: Customers\n...}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Access individual item data
|
|
165
|
+
context.Items.forEach(item => {
|
|
166
|
+
if (item.DataLoaded && item.Data) {
|
|
167
|
+
console.log(`${item.Description}: ${item.Data.length} rows`);
|
|
168
|
+
|
|
169
|
+
// Process the data
|
|
170
|
+
item.Data.forEach(row => {
|
|
171
|
+
// Work with row data
|
|
172
|
+
});
|
|
173
|
+
} else if (item.DataLoadingError) {
|
|
174
|
+
console.error(`Error loading ${item.Description}: ${item.DataLoadingError}`);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Cloning Data Contexts
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Clone an existing data context
|
|
183
|
+
const clonedContext = await DataContext.Clone(
|
|
184
|
+
originalContext,
|
|
185
|
+
true, // includeData - copies the data along with metadata
|
|
186
|
+
userInfo // contextUser
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
if (clonedContext) {
|
|
190
|
+
console.log(`Cloned context ID: ${clonedContext.ID}`);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API Reference
|
|
195
|
+
|
|
196
|
+
### DataContext Class
|
|
197
|
+
|
|
198
|
+
#### Properties
|
|
199
|
+
|
|
200
|
+
- `ID: string` - The unique identifier of the data context
|
|
201
|
+
- `DataContextEntity: DataContextEntity` - The metadata entity for the data context
|
|
202
|
+
- `Items: DataContextItem[]` - Array of data context items
|
|
203
|
+
|
|
204
|
+
#### Methods
|
|
205
|
+
|
|
206
|
+
- `async LoadMetadata(DataContextID: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<boolean>`
|
|
207
|
+
- Loads only the metadata for the data context and its items
|
|
208
|
+
|
|
209
|
+
- `async LoadData(dataSource: any, forceRefresh?: boolean, loadRelatedDataOnSingleRecords?: boolean, maxRecordsPerRelationship?: number, contextUser?: UserInfo): Promise<boolean>`
|
|
210
|
+
- Loads data for all items in the context
|
|
211
|
+
|
|
212
|
+
- `async Load(DataContextID: string, dataSource: any, forceRefresh?: boolean, loadRelatedDataOnSingleRecords?: boolean, maxRecordsPerRelationship?: number, contextUser?: UserInfo): Promise<boolean>`
|
|
213
|
+
- Loads both metadata and data in one operation
|
|
214
|
+
|
|
215
|
+
- `async SaveItems(contextUser?: UserInfo, persistItemData?: boolean): Promise<boolean>`
|
|
216
|
+
- Saves all data context items to the database
|
|
217
|
+
|
|
218
|
+
- `AddDataContextItem(): DataContextItem`
|
|
219
|
+
- Creates and adds a new item to the context
|
|
220
|
+
|
|
221
|
+
- `ValidateDataExists(ignoreFailedLoadItems?: boolean): boolean`
|
|
222
|
+
- Checks if all items have data loaded
|
|
223
|
+
|
|
224
|
+
- `ConvertToSimpleObject(itemPrefix?: string, includeFailedLoadItems?: boolean): any`
|
|
225
|
+
- Converts the context to a simple object structure
|
|
226
|
+
|
|
227
|
+
- `CreateSimpleObjectTypeDefinition(itemPrefix?: string, includeFailedLoadItems?: boolean): string`
|
|
228
|
+
- Generates TypeScript type definition for the data structure
|
|
229
|
+
|
|
230
|
+
- `LoadDataFromObject(data: any[][]): boolean`
|
|
231
|
+
- Loads pre-fetched data into the context
|
|
232
|
+
|
|
233
|
+
- `static async Clone(context: DataContext, includeData?: boolean, contextUser?: UserInfo): Promise<DataContext>`
|
|
234
|
+
- Creates a deep copy of a data context
|
|
235
|
+
|
|
236
|
+
- `static async FromRawData(rawData: any): Promise<DataContext>`
|
|
237
|
+
- Creates a context from raw data object
|
|
238
|
+
|
|
239
|
+
### DataContextItem Class
|
|
240
|
+
|
|
241
|
+
#### Properties
|
|
242
|
+
|
|
243
|
+
- `Type: 'view' | 'query' | 'full_entity' | 'sql' | 'single_record'` - The type of data item
|
|
244
|
+
- `RecordID: string` - Primary key for single_record types
|
|
245
|
+
- `EntityID?: string` - Entity identifier
|
|
246
|
+
- `ViewID?: string` - View identifier
|
|
247
|
+
- `QueryID?: string` - Query identifier
|
|
248
|
+
- `RecordName: string` - Name of the view, query, or entity
|
|
249
|
+
- `SQL?: string` - SQL statement for 'sql' type
|
|
250
|
+
- `EntityName?: string` - Name of the entity
|
|
251
|
+
- `Fields: DataContextFieldInfo[]` - Field metadata
|
|
252
|
+
- `Data: any[]` - The loaded data
|
|
253
|
+
- `DataLoaded: boolean` - Indicates if data has been loaded
|
|
254
|
+
- `DataLoadingError?: string` - Error message if loading failed
|
|
255
|
+
- `Description: string` - Auto-generated description
|
|
256
|
+
- `AdditionalDescription?: string` - Optional custom description
|
|
257
|
+
|
|
258
|
+
#### Methods
|
|
259
|
+
|
|
260
|
+
- `async LoadData(dataSource: any, forceRefresh?: boolean, loadRelatedDataOnSingleRecords?: boolean, maxRecordsPerRelationship?: number, contextUser?: UserInfo): Promise<boolean>`
|
|
261
|
+
- Loads data for this specific item
|
|
262
|
+
|
|
263
|
+
- `LoadDataFromObject(data: any[]): boolean`
|
|
264
|
+
- Loads pre-fetched data into the item
|
|
265
|
+
|
|
266
|
+
- `ValidateDataExists(ignoreFailedLoad?: boolean): boolean`
|
|
267
|
+
- Validates that data has been loaded
|
|
268
|
+
|
|
269
|
+
- `static FromViewEntity(viewEntity: UserViewEntityExtended): DataContextItem`
|
|
270
|
+
- `static FromSingleRecord(singleRecord: BaseEntity): DataContextItem`
|
|
271
|
+
- `static FromQuery(query: QueryInfo): DataContextItem`
|
|
272
|
+
- `static FromFullEntity(entity: EntityInfo): DataContextItem`
|
|
273
|
+
- `static FromRawItem(rawItem: any): DataContextItem`
|
|
274
|
+
|
|
275
|
+
### DataContextFieldInfo Class
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
class DataContextFieldInfo {
|
|
279
|
+
Name: string;
|
|
280
|
+
Type: string;
|
|
281
|
+
Description?: string;
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Server-Side Considerations
|
|
286
|
+
|
|
287
|
+
For SQL type data context items, you'll need to use the server-side implementation from `@memberjunction/data-context-server` which properly handles SQL execution with appropriate security and data source management.
|
|
288
|
+
|
|
289
|
+
## Dependencies
|
|
290
|
+
|
|
291
|
+
- `@memberjunction/global`: Core global utilities and class factory
|
|
292
|
+
- `@memberjunction/core-entities`: Entity definitions for MemberJunction
|
|
293
|
+
- `@memberjunction/core`: Core MemberJunction functionality
|
|
294
|
+
|
|
295
|
+
## Best Practices
|
|
296
|
+
|
|
297
|
+
1. **Always load metadata before data**: Use `LoadMetadata()` before `LoadData()` or simply use `Load()` which does both
|
|
298
|
+
2. **Handle loading errors**: Check `DataLoaded` and `DataLoadingError` properties on items
|
|
299
|
+
3. **Use appropriate data sources**: SQL type items require server-side data sources
|
|
300
|
+
4. **Consider performance**: Use `maxRecordsPerRelationship` to limit related data loading
|
|
301
|
+
5. **Validate before use**: Call `ValidateDataExists()` before processing data
|
|
302
|
+
6. **Use transactions**: When saving multiple items, they're automatically wrapped in a transaction
|
|
303
|
+
|
|
304
|
+
## License
|
|
305
|
+
|
|
306
|
+
ISC
|