@memberjunction/graphql-dataprovider 2.32.1 → 2.33.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 +295 -0
- package/dist/index.cjs +53 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +193 -1
- package/dist/index.d.mts +193 -1
- package/dist/index.mjs +56 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# MemberJunction GraphQL Data Provider
|
|
2
|
+
|
|
3
|
+
A flexible GraphQL client for MemberJunction that provides a complete data access layer for connecting applications to MemberJunction APIs.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@memberjunction/graphql-dataprovider` package is a full-featured GraphQL client implementation for MemberJunction applications. It provides a standardized way to interact with MemberJunction's GraphQL API, handling queries, mutations, subscriptions, and complex operations like transaction groups and entity relationships.
|
|
8
|
+
|
|
9
|
+
This data provider is particularly useful for frontend applications that need to communicate with a MemberJunction backend API, offering a consistent interface regardless of the underlying database technology.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @memberjunction/graphql-dataprovider
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Key Features
|
|
18
|
+
|
|
19
|
+
- **Complete Entity Operations**: CRUD operations for all MemberJunction entities
|
|
20
|
+
- **View and Report Execution**: Run database views and reports with parameters
|
|
21
|
+
- **Transaction Support**: Execute complex operations as atomic transactions
|
|
22
|
+
- **WebSocket Subscriptions**: Real-time data updates via GraphQL subscriptions
|
|
23
|
+
- **Offline Caching**: IndexedDB-based caching for offline functionality
|
|
24
|
+
- **Type Safety**: Full TypeScript support with generated types
|
|
25
|
+
- **Authentication Integration**: Works with MemberJunction's authentication system
|
|
26
|
+
- **Field Mapping**: Automatic mapping between client and server field names
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Setting up the GraphQL Client
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
34
|
+
import { RunViewOptions } from '@memberjunction/core';
|
|
35
|
+
|
|
36
|
+
// Create a data provider instance
|
|
37
|
+
const dataProvider = new GraphQLDataProvider({
|
|
38
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
39
|
+
subscriptionEndpoint: 'wss://api.example.com/graphql',
|
|
40
|
+
authToken: 'your-auth-token', // Optional, can be updated later
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Set authentication token (e.g., after user login)
|
|
44
|
+
dataProvider.setAuthToken('updated-auth-token');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Working with Entities
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
51
|
+
|
|
52
|
+
const dataProvider = new GraphQLDataProvider({
|
|
53
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Load an entity
|
|
57
|
+
async function getUserById(userId: number) {
|
|
58
|
+
const result = await dataProvider.loadEntity('User', userId);
|
|
59
|
+
return result.success ? result.entity : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Create a new entity
|
|
63
|
+
async function createUser(userData: any) {
|
|
64
|
+
const result = await dataProvider.saveEntity('User', {
|
|
65
|
+
ID: 0, // 0 indicates a new entity
|
|
66
|
+
FirstName: userData.firstName,
|
|
67
|
+
LastName: userData.lastName,
|
|
68
|
+
Email: userData.email,
|
|
69
|
+
// other fields...
|
|
70
|
+
});
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Update an existing entity
|
|
75
|
+
async function updateUser(userId: number, updatedData: any) {
|
|
76
|
+
const loadResult = await dataProvider.loadEntity('User', userId);
|
|
77
|
+
|
|
78
|
+
if (loadResult.success) {
|
|
79
|
+
const user = loadResult.entity;
|
|
80
|
+
// Update fields
|
|
81
|
+
Object.assign(user, updatedData);
|
|
82
|
+
|
|
83
|
+
// Save changes
|
|
84
|
+
const saveResult = await dataProvider.saveEntity('User', user);
|
|
85
|
+
return saveResult;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { success: false, error: 'User not found' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Delete an entity
|
|
92
|
+
async function deleteUser(userId: number) {
|
|
93
|
+
const result = await dataProvider.deleteEntity('User', userId);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Executing Views and Reports
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
102
|
+
import { RunViewOptions } from '@memberjunction/core';
|
|
103
|
+
|
|
104
|
+
const dataProvider = new GraphQLDataProvider({
|
|
105
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Execute a view
|
|
109
|
+
async function getActiveUsers() {
|
|
110
|
+
const options: RunViewOptions = {
|
|
111
|
+
EntityName: 'vwUsers',
|
|
112
|
+
ExtraFilter: "Status = 'Active'",
|
|
113
|
+
OrderBy: 'LastName, FirstName',
|
|
114
|
+
PageSize: 50,
|
|
115
|
+
PageNumber: 1
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const result = await dataProvider.runView(options);
|
|
119
|
+
return result.success ? result.Results : [];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Execute a report
|
|
123
|
+
async function getSalesReport(startDate: Date, endDate: Date) {
|
|
124
|
+
const result = await dataProvider.runReport('SalesReport', {
|
|
125
|
+
StartDate: startDate,
|
|
126
|
+
EndDate: endDate
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return result.success ? result.results : [];
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Using Transaction Groups
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
137
|
+
import { TransactionGroupBase } from '@memberjunction/core';
|
|
138
|
+
|
|
139
|
+
const dataProvider = new GraphQLDataProvider({
|
|
140
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Define a transaction group
|
|
144
|
+
class OrderTransactionGroup extends TransactionGroupBase {
|
|
145
|
+
constructor() {
|
|
146
|
+
super('CreateOrderWithItems');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Use the transaction group
|
|
151
|
+
async function createOrderWithItems(orderData: any, items: any[]) {
|
|
152
|
+
// Create transaction group
|
|
153
|
+
const transaction = new OrderTransactionGroup();
|
|
154
|
+
|
|
155
|
+
// Add order
|
|
156
|
+
transaction.addEntity('Order', {
|
|
157
|
+
ID: 0,
|
|
158
|
+
CustomerID: orderData.customerId,
|
|
159
|
+
OrderDate: new Date(),
|
|
160
|
+
Status: 'New',
|
|
161
|
+
// other fields...
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Add order items
|
|
165
|
+
for (const item of items) {
|
|
166
|
+
transaction.addEntity('OrderItem', {
|
|
167
|
+
ID: 0,
|
|
168
|
+
OrderID: '@Order.1', // Reference to the first Order entity in this transaction
|
|
169
|
+
ProductID: item.productId,
|
|
170
|
+
Quantity: item.quantity,
|
|
171
|
+
Price: item.price,
|
|
172
|
+
// other fields...
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Execute transaction
|
|
177
|
+
const result = await dataProvider.executeTransactionGroup(transaction);
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Executing Actions
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
186
|
+
|
|
187
|
+
const dataProvider = new GraphQLDataProvider({
|
|
188
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Execute an entity action
|
|
192
|
+
async function sendUserWelcomeEmail(userId: number) {
|
|
193
|
+
const result = await dataProvider.executeAction('User', 'SendWelcomeEmail', userId, {
|
|
194
|
+
templateId: 'welcome-template',
|
|
195
|
+
includeSurvey: true
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return result.success;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Execute a general action (not tied to a specific entity record)
|
|
202
|
+
async function generateReport() {
|
|
203
|
+
const result = await dataProvider.executeAction('ReportGenerator', 'GenerateMonthlyReport', null, {
|
|
204
|
+
month: new Date().getMonth(),
|
|
205
|
+
year: new Date().getFullYear(),
|
|
206
|
+
format: 'PDF'
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Field Mapping
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
217
|
+
|
|
218
|
+
const dataProvider = new GraphQLDataProvider({
|
|
219
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
220
|
+
// Configure field mapping for entities
|
|
221
|
+
fieldMappings: {
|
|
222
|
+
User: {
|
|
223
|
+
// Map client field names to server field names
|
|
224
|
+
firstName: 'FirstName',
|
|
225
|
+
lastName: 'LastName',
|
|
226
|
+
emailAddress: 'Email'
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Now you can use client field names in your code
|
|
232
|
+
async function createUser(userData: any) {
|
|
233
|
+
const result = await dataProvider.saveEntity('User', {
|
|
234
|
+
ID: 0,
|
|
235
|
+
firstName: userData.firstName, // Will be mapped to FirstName
|
|
236
|
+
lastName: userData.lastName, // Will be mapped to LastName
|
|
237
|
+
emailAddress: userData.email // Will be mapped to Email
|
|
238
|
+
});
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### WebSocket Subscriptions
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
|
|
247
|
+
|
|
248
|
+
const dataProvider = new GraphQLDataProvider({
|
|
249
|
+
graphQLEndpoint: 'https://api.example.com/graphql',
|
|
250
|
+
subscriptionEndpoint: 'wss://api.example.com/graphql'
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Subscribe to entity changes
|
|
254
|
+
function subscribeToUserChanges() {
|
|
255
|
+
const subscription = dataProvider.subscribeToEntity('User', (entity) => {
|
|
256
|
+
console.log('User entity updated:', entity);
|
|
257
|
+
// Update UI or application state
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Later, unsubscribe when no longer needed
|
|
261
|
+
subscription.unsubscribe();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Subscribe to specific entity record changes
|
|
265
|
+
function subscribeToSpecificUser(userId: number) {
|
|
266
|
+
const subscription = dataProvider.subscribeToEntityRecord('User', userId, (entity) => {
|
|
267
|
+
console.log('Specific user updated:', entity);
|
|
268
|
+
// Update UI or application state
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Later, unsubscribe when no longer needed
|
|
272
|
+
subscription.unsubscribe();
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Key Classes
|
|
277
|
+
|
|
278
|
+
| Class | Description |
|
|
279
|
+
|-------|-------------|
|
|
280
|
+
| `GraphQLDataProvider` | Main class implementing the MemberJunction data provider interface |
|
|
281
|
+
| `GraphQLClient` | Handles GraphQL operations (queries, mutations, subscriptions) |
|
|
282
|
+
| `EntityMapper` | Maps between client-side and server-side entity structures |
|
|
283
|
+
| `SubscriptionManager` | Manages WebSocket connections and GraphQL subscriptions |
|
|
284
|
+
| `OfflineCache` | Provides IndexedDB-based caching for offline operations |
|
|
285
|
+
| `EntitySerializer` | Serializes and deserializes entity data for GraphQL operations |
|
|
286
|
+
|
|
287
|
+
## Requirements
|
|
288
|
+
|
|
289
|
+
- Node.js 16+
|
|
290
|
+
- Modern browser with WebSocket support (for subscriptions)
|
|
291
|
+
- MemberJunction GraphQL API endpoint
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
ISC
|