@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 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