mp-js-api 0.0.29 → 0.0.31
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/.claude/settings.local.json +13 -0
- package/dev/Swagger UI.html +6662 -0
- package/dist/api.d.ts +24 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +62 -2
- package/dist/endpoints/communications.d.ts +122 -0
- package/dist/endpoints/communications.d.ts.map +1 -0
- package/dist/endpoints/communications.js +2 -0
- package/dist/endpoints/messages.d.ts +34 -0
- package/dist/endpoints/messages.d.ts.map +1 -0
- package/dist/endpoints/messages.js +2 -0
- package/dist/endpoints/procedures.d.ts +49 -0
- package/dist/endpoints/procedures.d.ts.map +1 -0
- package/dist/endpoints/procedures.js +2 -0
- package/dist/endpoints/texts.d.ts +18 -0
- package/dist/endpoints/texts.d.ts.map +1 -0
- package/dist/endpoints/texts.js +2 -0
- package/dist/index.d.ts +26 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/utils/converters.d.ts +27 -0
- package/dist/utils/converters.d.ts.map +1 -1
- package/dist/utils/converters.js +60 -0
- package/package.json +1 -1
- package/src/api.ts +88 -4
- package/src/endpoints/communications.ts +125 -0
- package/src/endpoints/messages.ts +34 -0
- package/src/endpoints/procedures.ts +87 -0
- package/src/endpoints/texts.ts +17 -0
- package/src/index.ts +83 -5
- package/src/utils/converters.ts +64 -0
- package/tasks/todo.md +617 -0
package/dist/utils/converters.js
CHANGED
|
@@ -9,6 +9,11 @@ exports.toCapitalSnakeCase = toCapitalSnakeCase;
|
|
|
9
9
|
exports.caseConverter = caseConverter;
|
|
10
10
|
exports.convertToCamelCase = convertToCamelCase;
|
|
11
11
|
exports.convertToSnakeCase = convertToSnakeCase;
|
|
12
|
+
exports.toPascalCase = toPascalCase;
|
|
13
|
+
exports.fromPascalCase = fromPascalCase;
|
|
14
|
+
exports.pascalCaseConverter = pascalCaseConverter;
|
|
15
|
+
exports.convertToPascalCase = convertToPascalCase;
|
|
16
|
+
exports.convertFromPascalCase = convertFromPascalCase;
|
|
12
17
|
function stringifyURLParams(mpOptions = {}) {
|
|
13
18
|
return escapeSql(Object.entries(mpOptions).reduce((acc, [key, value]) => {
|
|
14
19
|
if (!acc) {
|
|
@@ -114,3 +119,58 @@ function convertToCamelCase(obj, capitalIds = true) {
|
|
|
114
119
|
function convertToSnakeCase(obj, capitalIds = true) {
|
|
115
120
|
return caseConverter(obj, { type: 'toSnake', capitalIds });
|
|
116
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Converts a camelCase string to PascalCase.
|
|
124
|
+
* Example: "authorUserId" → "AuthorUserId"
|
|
125
|
+
*/
|
|
126
|
+
function toPascalCase(str) {
|
|
127
|
+
if (!str)
|
|
128
|
+
return str;
|
|
129
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Converts a PascalCase string to camelCase.
|
|
133
|
+
* Example: "AuthorUserId" → "authorUserId"
|
|
134
|
+
*/
|
|
135
|
+
function fromPascalCase(str) {
|
|
136
|
+
if (!str)
|
|
137
|
+
return str;
|
|
138
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Recursively converts object keys between camelCase and PascalCase.
|
|
142
|
+
* Used for /communications, /messages, /texts, /procs endpoints.
|
|
143
|
+
*/
|
|
144
|
+
function pascalCaseConverter(obj, direction) {
|
|
145
|
+
const caseFn = direction === 'toPascal' ? toPascalCase : fromPascalCase;
|
|
146
|
+
if (Array.isArray(obj)) {
|
|
147
|
+
return obj.map(val => pascalCaseConverter(val, direction));
|
|
148
|
+
}
|
|
149
|
+
if (obj !== null && typeof obj === 'object') {
|
|
150
|
+
const result = {};
|
|
151
|
+
for (const key in obj) {
|
|
152
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
153
|
+
const newKey = caseFn(key);
|
|
154
|
+
result[newKey] = pascalCaseConverter(obj[key], direction);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
return obj;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Converts camelCase object keys to PascalCase.
|
|
163
|
+
* Used for outgoing requests to /communications, /messages, /texts endpoints.
|
|
164
|
+
* Example: { authorUserId: 1 } → { AuthorUserId: 1 }
|
|
165
|
+
*/
|
|
166
|
+
function convertToPascalCase(obj) {
|
|
167
|
+
return pascalCaseConverter(obj, 'toPascal');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Converts PascalCase object keys to camelCase.
|
|
171
|
+
* Used for incoming responses from /communications, /messages, /texts, /procs endpoints.
|
|
172
|
+
* Example: { AuthorUserId: 1 } → { authorUserId: 1 }
|
|
173
|
+
*/
|
|
174
|
+
function convertFromPascalCase(obj) {
|
|
175
|
+
return pascalCaseConverter(obj, 'fromPascal');
|
|
176
|
+
}
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { URLSearchParams } from 'url';
|
|
3
|
-
import { convertToCamelCase, convertToSnakeCase, escapeApostrophes, stringifyURLParams, toCapitalSnakeCase } from './utils/converters';
|
|
3
|
+
import { convertToCamelCase, convertToSnakeCase, convertToPascalCase, convertFromPascalCase, escapeApostrophes, stringifyURLParams, toCapitalSnakeCase } from './utils/converters';
|
|
4
|
+
import { Communication, CommunicationInfo } from './endpoints/communications';
|
|
5
|
+
import { MessageInfo } from './endpoints/messages';
|
|
6
|
+
import { TextInfo } from './endpoints/texts';
|
|
7
|
+
import { ProcedureInfo } from './endpoints/procedures';
|
|
4
8
|
|
|
5
9
|
|
|
6
10
|
export type APIGetOneInstance = <T extends Record<string, any>>({ id, path, mpQuery, config }: APIGetParameter & { id: number; }) => Promise<T | undefined | { error: ErrorDetails; }>;
|
|
@@ -10,6 +14,15 @@ export type APICreateManyInstance = <T extends Record<string, any>>({ path, mpQu
|
|
|
10
14
|
export type APICreateFileInstance = <T extends Record<string, any>>({ path, mpQuery, data, config }: APICreateFileParameter) => Promise<T | { error: ErrorDetails; }>;
|
|
11
15
|
export type APIUpdateInstance = <T extends Record<string, any>>({ path, mpQuery, data, config }: APIUpdateParameter) => Promise<T[] | { error: ErrorDetails; }>;
|
|
12
16
|
|
|
17
|
+
// Communications API types
|
|
18
|
+
export type APISendCommunicationInstance = (data: CommunicationInfo, config?: AxiosRequestConfig) => Promise<Communication | { error: ErrorDetails; }>;
|
|
19
|
+
export type APISendMessageInstance = (data: MessageInfo, config?: AxiosRequestConfig) => Promise<Communication | { error: ErrorDetails; }>;
|
|
20
|
+
export type APISendTextInstance = (data: TextInfo, config?: AxiosRequestConfig) => Promise<Communication | { error: ErrorDetails; }>;
|
|
21
|
+
|
|
22
|
+
// Procedures API types
|
|
23
|
+
export type APIGetProceduresInstance = (search?: string, config?: AxiosRequestConfig) => Promise<ProcedureInfo[] | { error: ErrorDetails; }>;
|
|
24
|
+
export type APIExecuteProcedureInstance = <T = Record<string, any>>(procedureName: string, input?: Record<string, any>, config?: AxiosRequestConfig) => Promise<T[][] | { error: ErrorDetails; }>;
|
|
25
|
+
|
|
13
26
|
|
|
14
27
|
export interface MPApiBase {
|
|
15
28
|
getOne: APIGetOneInstance;
|
|
@@ -23,6 +36,13 @@ export interface MPApiBase {
|
|
|
23
36
|
post: AxiosInstance['post'];
|
|
24
37
|
put: AxiosInstance['put'];
|
|
25
38
|
getError: (error: AxiosError) => ErrorDetails;
|
|
39
|
+
// Communications API
|
|
40
|
+
sendCommunication: APISendCommunicationInstance;
|
|
41
|
+
sendMessage: APISendMessageInstance;
|
|
42
|
+
sendText: APISendTextInstance;
|
|
43
|
+
// Procedures API
|
|
44
|
+
getProcedures: APIGetProceduresInstance;
|
|
45
|
+
executeProcedure: APIExecuteProcedureInstance;
|
|
26
46
|
}
|
|
27
47
|
|
|
28
48
|
export interface ErrorDetails {
|
|
@@ -183,14 +203,14 @@ export const createApiBase = ({ auth }: { auth: { username: string; password: st
|
|
|
183
203
|
}
|
|
184
204
|
};
|
|
185
205
|
|
|
186
|
-
const createFile: APICreateFileInstance = async
|
|
206
|
+
const createFile: APICreateFileInstance = async ({ path, mpQuery, data: payload, config }: APICreateFileParameter) => {
|
|
187
207
|
const query = stringifyURLParams(mpQuery);
|
|
188
208
|
// const data = [convertToSnakeCase<Partial<T>>(payload)];
|
|
189
209
|
const data = payload;
|
|
190
210
|
const url = path + query;
|
|
191
211
|
try {
|
|
192
212
|
const res = await post(url, data, config);
|
|
193
|
-
return
|
|
213
|
+
return res.data[0];
|
|
194
214
|
}
|
|
195
215
|
catch (err) {
|
|
196
216
|
return { error: getError(err) };
|
|
@@ -226,6 +246,65 @@ export const createApiBase = ({ auth }: { auth: { username: string; password: st
|
|
|
226
246
|
};
|
|
227
247
|
};
|
|
228
248
|
|
|
249
|
+
// Communications API: POST /communications
|
|
250
|
+
const sendCommunication: APISendCommunicationInstance = async (data, config) => {
|
|
251
|
+
try {
|
|
252
|
+
const payload = convertToPascalCase(data);
|
|
253
|
+
const res = await post<Communication>('/communications', payload, config);
|
|
254
|
+
return convertFromPascalCase<Communication>(res.data);
|
|
255
|
+
} catch (err) {
|
|
256
|
+
return { error: getError(err as AxiosError) };
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// Messages API: POST /messages
|
|
261
|
+
const sendMessage: APISendMessageInstance = async (data, config) => {
|
|
262
|
+
try {
|
|
263
|
+
const payload = convertToPascalCase(data);
|
|
264
|
+
const res = await post<Communication>('/messages', payload, config);
|
|
265
|
+
return convertFromPascalCase<Communication>(res.data);
|
|
266
|
+
} catch (err) {
|
|
267
|
+
return { error: getError(err as AxiosError) };
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Texts API: POST /texts
|
|
272
|
+
const sendText: APISendTextInstance = async (data, config) => {
|
|
273
|
+
try {
|
|
274
|
+
const payload = convertToPascalCase(data);
|
|
275
|
+
const res = await post<Communication>('/texts', payload, config);
|
|
276
|
+
return convertFromPascalCase<Communication>(res.data);
|
|
277
|
+
} catch (err) {
|
|
278
|
+
return { error: getError(err as AxiosError) };
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// Procedures API: GET /procs
|
|
283
|
+
const getProcedures: APIGetProceduresInstance = async (search, config) => {
|
|
284
|
+
try {
|
|
285
|
+
const url = search ? `/procs?$search=${encodeURIComponent(search)}` : '/procs';
|
|
286
|
+
const res = await get<ProcedureInfo[]>(url, config);
|
|
287
|
+
return res.data.map(proc => convertFromPascalCase<ProcedureInfo>(proc));
|
|
288
|
+
} catch (err) {
|
|
289
|
+
return { error: getError(err as AxiosError) };
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// Procedures API: POST /procs/{procedure}
|
|
294
|
+
const executeProcedure: APIExecuteProcedureInstance = async <T = Record<string, any>>(
|
|
295
|
+
procedureName: string,
|
|
296
|
+
input?: Record<string, any>,
|
|
297
|
+
config?: AxiosRequestConfig
|
|
298
|
+
) => {
|
|
299
|
+
try {
|
|
300
|
+
const url = `/procs/${encodeURIComponent(procedureName)}`;
|
|
301
|
+
const res = await post<T[][]>(url, input, config);
|
|
302
|
+
return res.data;
|
|
303
|
+
} catch (err) {
|
|
304
|
+
return { error: getError(err as AxiosError) };
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
229
308
|
return {
|
|
230
309
|
get,
|
|
231
310
|
put,
|
|
@@ -237,7 +316,12 @@ export const createApiBase = ({ auth }: { auth: { username: string; password: st
|
|
|
237
316
|
updateMany,
|
|
238
317
|
createFile,
|
|
239
318
|
updateFile,
|
|
240
|
-
getError
|
|
319
|
+
getError,
|
|
320
|
+
sendCommunication,
|
|
321
|
+
sendMessage,
|
|
322
|
+
sendText,
|
|
323
|
+
getProcedures,
|
|
324
|
+
executeProcedure,
|
|
241
325
|
};
|
|
242
326
|
};
|
|
243
327
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Communication type enum.
|
|
3
|
+
* Determines the delivery method for the communication.
|
|
4
|
+
*/
|
|
5
|
+
export type CommunicationType = 'Unknown' | 'Email' | 'SMS' | 'RssFeed' | 'GlobalMFA';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Communication status enum.
|
|
9
|
+
* Represents the current state of a communication.
|
|
10
|
+
*/
|
|
11
|
+
export type CommunicationStatus = 'Unknown' | 'Draft' | 'InReview' | 'ReadyToSend' | 'Sent';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Texting compliance level enum.
|
|
15
|
+
* Controls how bulk opt-out messages are filtered.
|
|
16
|
+
*/
|
|
17
|
+
export type TextingComplianceLevel = 'None' | 'SingleOptIn' | 'DoubleOptIn';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* CommunicationInfo - Request payload for POST /communications.
|
|
21
|
+
* Uses camelCase internally; converted to PascalCase for API.
|
|
22
|
+
*
|
|
23
|
+
* API expects: AuthorUserId, FromContactId, CommunicationType, Contacts, etc.
|
|
24
|
+
*/
|
|
25
|
+
export interface CommunicationInfo {
|
|
26
|
+
/** User ID who authored the communication. */
|
|
27
|
+
authorUserId: number;
|
|
28
|
+
/** Subject line of email or SMS/MMS message content. */
|
|
29
|
+
subject: string;
|
|
30
|
+
/** Body content of the communication (HTML supported for email). */
|
|
31
|
+
body?: string;
|
|
32
|
+
/** Contact ID of the sender. */
|
|
33
|
+
fromContactId: number;
|
|
34
|
+
/** Contact ID for replies. */
|
|
35
|
+
replyToContactId: number;
|
|
36
|
+
/** Delivery type: 'Email' or 'SMS'. */
|
|
37
|
+
communicationType: CommunicationType;
|
|
38
|
+
/** Array of recipient Contact IDs. */
|
|
39
|
+
contacts: number[];
|
|
40
|
+
/** ISO datetime to send. Future date = scheduled. */
|
|
41
|
+
startDate?: string;
|
|
42
|
+
/** Whether this is a bulk email. */
|
|
43
|
+
isBulkEmail?: boolean;
|
|
44
|
+
/** Send to household heads instead of contacts. */
|
|
45
|
+
sendToContactParents?: boolean;
|
|
46
|
+
/** Outbound SMS phone number ID (required for SMS). */
|
|
47
|
+
textPhoneNumberId?: number;
|
|
48
|
+
/** Exclude contacts who opted out of bulk messages. */
|
|
49
|
+
excludeOptedOutOfBulkMessages?: boolean;
|
|
50
|
+
/** Texting compliance filter level (SMS only). */
|
|
51
|
+
textingComplianceLevel?: TextingComplianceLevel;
|
|
52
|
+
/** Timezone for date/time rendering in messages. */
|
|
53
|
+
timeZoneName?: string;
|
|
54
|
+
/** Locale for value formatting in messages. */
|
|
55
|
+
cultureName?: string;
|
|
56
|
+
/** Alternate email type ID. */
|
|
57
|
+
alternateEmailTypeId?: number;
|
|
58
|
+
/** Related publication ID. */
|
|
59
|
+
publicationId?: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Communication - Response model from /communications endpoints.
|
|
64
|
+
* Uses camelCase internally; API returns PascalCase.
|
|
65
|
+
*
|
|
66
|
+
* API returns: CommunicationId, AuthorUserId, AuthorName, Subject, etc.
|
|
67
|
+
*/
|
|
68
|
+
export interface Communication {
|
|
69
|
+
/** Unique identifier of the communication. */
|
|
70
|
+
communicationId: number;
|
|
71
|
+
/** User ID who authored the communication. */
|
|
72
|
+
authorUserId: number;
|
|
73
|
+
/** Display name of the author (readonly). */
|
|
74
|
+
authorName: string;
|
|
75
|
+
/** Subject line or SMS content. */
|
|
76
|
+
subject: string;
|
|
77
|
+
/** Body content. */
|
|
78
|
+
body?: string;
|
|
79
|
+
/** Start/send date. */
|
|
80
|
+
startDate: string;
|
|
81
|
+
/** Expiration date. */
|
|
82
|
+
expirationDate?: string;
|
|
83
|
+
/** Current status. */
|
|
84
|
+
status?: CommunicationStatus;
|
|
85
|
+
/** Sender contact ID. */
|
|
86
|
+
fromContactId: number;
|
|
87
|
+
/** Sender display name (readonly). */
|
|
88
|
+
fromName: string;
|
|
89
|
+
/** Sender email address (readonly). */
|
|
90
|
+
fromAddress: string;
|
|
91
|
+
/** Reply-to contact ID. */
|
|
92
|
+
replyToContactId: number;
|
|
93
|
+
/** Reply-to display name (readonly). */
|
|
94
|
+
replyToName: string;
|
|
95
|
+
/** Reply-to email address (readonly). */
|
|
96
|
+
replyToAddress: string;
|
|
97
|
+
/** Associated task ID. */
|
|
98
|
+
taskId?: number;
|
|
99
|
+
/** Selection ID for recipients. */
|
|
100
|
+
selectionId?: number;
|
|
101
|
+
/** Single recipient contact ID override. */
|
|
102
|
+
recipientContactId?: number;
|
|
103
|
+
/** Recipient display name (readonly). */
|
|
104
|
+
recipientName?: string;
|
|
105
|
+
/** Send to household heads. */
|
|
106
|
+
sendToContactParents?: boolean;
|
|
107
|
+
/** Exclude opted-out contacts. */
|
|
108
|
+
excludeOptedOutOfBulkMessages?: boolean;
|
|
109
|
+
/** Texting compliance level. */
|
|
110
|
+
textingComplianceLevel?: TextingComplianceLevel;
|
|
111
|
+
/** Timezone for rendering. */
|
|
112
|
+
timeZoneName?: string;
|
|
113
|
+
/** Locale for formatting. */
|
|
114
|
+
cultureName?: string;
|
|
115
|
+
/** Outbound SMS phone number ID. */
|
|
116
|
+
textPhoneNumberId?: number;
|
|
117
|
+
/** Outbound SMS phone number (readonly). */
|
|
118
|
+
textPhoneNumber?: string;
|
|
119
|
+
/** Communication delivery type. */
|
|
120
|
+
communicationType: CommunicationType;
|
|
121
|
+
/** Alternate email type ID. */
|
|
122
|
+
alternateEmailTypeId?: number;
|
|
123
|
+
/** Related publication ID. */
|
|
124
|
+
publicationId?: number;
|
|
125
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageAddress - Email address with display name.
|
|
3
|
+
* Used for FromAddress, ToAddresses, and ReplyToAddress.
|
|
4
|
+
*
|
|
5
|
+
* API expects/returns: DisplayName, Address (PascalCase)
|
|
6
|
+
*/
|
|
7
|
+
export interface MessageAddress {
|
|
8
|
+
/** Display name shown in email client. */
|
|
9
|
+
displayName: string;
|
|
10
|
+
/** Email address. */
|
|
11
|
+
address: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* MessageInfo - Request payload for POST /messages.
|
|
16
|
+
* Sends emails directly by email address (bypasses MP contacts).
|
|
17
|
+
* Uses camelCase internally; converted to PascalCase for API.
|
|
18
|
+
*
|
|
19
|
+
* API expects: FromAddress, ToAddresses, ReplyToAddress, Subject, Body, StartDate
|
|
20
|
+
*/
|
|
21
|
+
export interface MessageInfo {
|
|
22
|
+
/** Sender email address and display name. */
|
|
23
|
+
fromAddress: MessageAddress;
|
|
24
|
+
/** Array of recipient email addresses. */
|
|
25
|
+
toAddresses: MessageAddress[];
|
|
26
|
+
/** Reply-to email address (optional). */
|
|
27
|
+
replyToAddress?: MessageAddress;
|
|
28
|
+
/** Email subject line. */
|
|
29
|
+
subject: string;
|
|
30
|
+
/** Email body content (HTML supported). */
|
|
31
|
+
body: string;
|
|
32
|
+
/** ISO datetime to send. Future date = scheduled. */
|
|
33
|
+
startDate?: string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter direction enum.
|
|
3
|
+
* Indicates whether a parameter is input, output, or both.
|
|
4
|
+
*/
|
|
5
|
+
export type ParameterDirection = 'Input' | 'Output' | 'InputOutput' | 'ReturnValue';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parameter data type enum.
|
|
9
|
+
* All supported SQL data types for stored procedure parameters.
|
|
10
|
+
*/
|
|
11
|
+
export type ParameterDataType =
|
|
12
|
+
| 'Unknown'
|
|
13
|
+
| 'String'
|
|
14
|
+
| 'Text'
|
|
15
|
+
| 'Xml'
|
|
16
|
+
| 'Byte'
|
|
17
|
+
| 'Integer16'
|
|
18
|
+
| 'Integer32'
|
|
19
|
+
| 'Integer64'
|
|
20
|
+
| 'Decimal'
|
|
21
|
+
| 'Real'
|
|
22
|
+
| 'Boolean'
|
|
23
|
+
| 'Date'
|
|
24
|
+
| 'Time'
|
|
25
|
+
| 'DateTime'
|
|
26
|
+
| 'Timestamp'
|
|
27
|
+
| 'Binary'
|
|
28
|
+
| 'Password'
|
|
29
|
+
| 'Money'
|
|
30
|
+
| 'Guid'
|
|
31
|
+
| 'Phone'
|
|
32
|
+
| 'Email'
|
|
33
|
+
| 'Variant'
|
|
34
|
+
| 'Separator'
|
|
35
|
+
| 'Image'
|
|
36
|
+
| 'Counter'
|
|
37
|
+
| 'TableName'
|
|
38
|
+
| 'GlobalFilter'
|
|
39
|
+
| 'TimeZone'
|
|
40
|
+
| 'Locale'
|
|
41
|
+
| 'LargeString'
|
|
42
|
+
| 'Url'
|
|
43
|
+
| 'Strings'
|
|
44
|
+
| 'Integers'
|
|
45
|
+
| 'Color'
|
|
46
|
+
| 'SecretKey';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* ParameterInfo - Metadata about a stored procedure parameter.
|
|
50
|
+
* Uses camelCase internally; API returns PascalCase.
|
|
51
|
+
*
|
|
52
|
+
* API returns: Name, Direction, DataType, Size
|
|
53
|
+
*/
|
|
54
|
+
export interface ParameterInfo {
|
|
55
|
+
/** Parameter name (e.g., "@ContactId"). */
|
|
56
|
+
name: string;
|
|
57
|
+
/** Parameter direction (Input, Output, etc.). */
|
|
58
|
+
direction: ParameterDirection;
|
|
59
|
+
/** SQL data type. */
|
|
60
|
+
dataType: ParameterDataType;
|
|
61
|
+
/** Maximum length/size. */
|
|
62
|
+
size: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* ProcedureInfo - Metadata about a stored procedure.
|
|
67
|
+
* Returned from GET /procs endpoint.
|
|
68
|
+
* Uses camelCase internally; API returns PascalCase.
|
|
69
|
+
*
|
|
70
|
+
* API returns: Name, Parameters
|
|
71
|
+
*/
|
|
72
|
+
export interface ProcedureInfo {
|
|
73
|
+
/** Procedure name (e.g., "api_Custom_GetContacts"). */
|
|
74
|
+
name: string;
|
|
75
|
+
/** Array of parameter definitions. */
|
|
76
|
+
parameters: ParameterInfo[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* ProcedureInput - Input parameters for executing a stored procedure.
|
|
81
|
+
* Keys should match parameter names with @ prefix.
|
|
82
|
+
*
|
|
83
|
+
* Example: { "@SelectionID": 26918, "@StartDate": "2024-01-01" }
|
|
84
|
+
*/
|
|
85
|
+
export interface ProcedureInput {
|
|
86
|
+
[parameterName: string]: string | number | boolean | null;
|
|
87
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextInfo - Request payload for POST /texts.
|
|
3
|
+
* Sends SMS/MMS messages to phone numbers.
|
|
4
|
+
* Uses camelCase internally; converted to PascalCase for API.
|
|
5
|
+
*
|
|
6
|
+
* API expects: FromPhoneNumberId, ToPhoneNumbers, Message, StartDate
|
|
7
|
+
*/
|
|
8
|
+
export interface TextInfo {
|
|
9
|
+
/** MP phone number ID for outbound messages. */
|
|
10
|
+
fromPhoneNumberId: number;
|
|
11
|
+
/** Array of recipient phone numbers in E.164 format (e.g., "+15551234567"). */
|
|
12
|
+
toPhoneNumbers: string[];
|
|
13
|
+
/** Message content (SMS character limits apply). */
|
|
14
|
+
message: string;
|
|
15
|
+
/** ISO datetime to send. Future date = scheduled. */
|
|
16
|
+
startDate?: string;
|
|
17
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { AxiosInstance } from 'axios';
|
|
1
|
+
import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
2
2
|
import { createApiBase, MPApiBase, ErrorDetails, MPGetQuery, MPCreateQuery, MPUpdateQuery, DateTimeIsoString } from './api';
|
|
3
|
-
import { convertToCamelCase, convertToSnakeCase, escapeSql, stringifyURLParams } from './utils/converters';
|
|
3
|
+
import { convertToCamelCase, convertToSnakeCase, convertToPascalCase, convertFromPascalCase, escapeSql, stringifyURLParams } from './utils/converters';
|
|
4
4
|
import { Contact, ContactRecord } from './tables/contacts';
|
|
5
|
+
import { Communication, CommunicationInfo, CommunicationType, CommunicationStatus, TextingComplianceLevel } from './endpoints/communications';
|
|
6
|
+
import { MessageInfo, MessageAddress } from './endpoints/messages';
|
|
7
|
+
import { TextInfo } from './endpoints/texts';
|
|
8
|
+
import { ProcedureInfo, ParameterInfo, ParameterDirection, ParameterDataType, ProcedureInput } from './endpoints/procedures';
|
|
5
9
|
import { Event, EventRecord } from './tables/events';
|
|
6
10
|
import { Group, GroupRecord } from './tables/groups';
|
|
7
11
|
import { Address, AddressRecord } from './tables/addresses';
|
|
@@ -64,6 +68,20 @@ export type CreateFilePayload = WithRequired<
|
|
|
64
68
|
'Description' | 'IsDefaultImage'
|
|
65
69
|
>;
|
|
66
70
|
|
|
71
|
+
// Communications API payload types
|
|
72
|
+
export type CreateCommunicationPayload = WithRequired<
|
|
73
|
+
CommunicationInfo,
|
|
74
|
+
'authorUserId' | 'subject' | 'fromContactId' | 'replyToContactId' | 'communicationType' | 'contacts'
|
|
75
|
+
>;
|
|
76
|
+
export type CreateMessagePayload = WithRequired<
|
|
77
|
+
MessageInfo,
|
|
78
|
+
'fromAddress' | 'toAddresses' | 'subject' | 'body'
|
|
79
|
+
>;
|
|
80
|
+
export type CreateTextPayload = WithRequired<
|
|
81
|
+
TextInfo,
|
|
82
|
+
'fromPhoneNumberId' | 'toPhoneNumbers' | 'message'
|
|
83
|
+
>;
|
|
84
|
+
|
|
67
85
|
|
|
68
86
|
export interface ContactDetails extends Contact, Participant, Household {
|
|
69
87
|
householdID: number;
|
|
@@ -240,16 +258,45 @@ export type MPInstance = {
|
|
|
240
258
|
|
|
241
259
|
getFiles(table: string, recordId: number, mpQuery?: MPGetQuery)
|
|
242
260
|
: Promise<AttachedFile[] | { error: ErrorDetails; }>;
|
|
243
|
-
|
|
261
|
+
uploadFile(table: string, recordId: number, data: FormData)
|
|
244
262
|
: Promise<AttachedFile | { error: ErrorDetails; }>;
|
|
245
263
|
updateFiles(table: string, fileId: number, data: WithRequired<Partial<AttachedFile>, 'FileId'>[])
|
|
246
264
|
: Promise<AttachedFile[] | { error: ErrorDetails; }>;
|
|
265
|
+
|
|
266
|
+
// Communications API
|
|
267
|
+
sendCommunication(
|
|
268
|
+
data: CreateCommunicationPayload,
|
|
269
|
+
config?: AxiosRequestConfig
|
|
270
|
+
): Promise<Communication | { error: ErrorDetails; }>;
|
|
271
|
+
sendMessage(
|
|
272
|
+
data: CreateMessagePayload,
|
|
273
|
+
config?: AxiosRequestConfig
|
|
274
|
+
): Promise<Communication | { error: ErrorDetails; }>;
|
|
275
|
+
sendText(
|
|
276
|
+
data: CreateTextPayload,
|
|
277
|
+
config?: AxiosRequestConfig
|
|
278
|
+
): Promise<Communication | { error: ErrorDetails; }>;
|
|
279
|
+
|
|
280
|
+
// Procedures API
|
|
281
|
+
getProcedures(
|
|
282
|
+
search?: string,
|
|
283
|
+
config?: AxiosRequestConfig
|
|
284
|
+
): Promise<ProcedureInfo[] | { error: ErrorDetails; }>;
|
|
285
|
+
executeProcedure<T = Record<string, any>>(
|
|
286
|
+
procedureName: string,
|
|
287
|
+
input?: ProcedureInput,
|
|
288
|
+
config?: AxiosRequestConfig
|
|
289
|
+
): Promise<T[][] | { error: ErrorDetails; }>;
|
|
247
290
|
};
|
|
248
291
|
|
|
249
292
|
|
|
250
293
|
export const createMPInstance = ({ auth }: { auth: { username: string; password: string; }; }): MPInstance => {
|
|
251
294
|
|
|
252
|
-
const {
|
|
295
|
+
const {
|
|
296
|
+
getOne, getMany, createOne, createMany, updateMany, createFile, updateFile,
|
|
297
|
+
get, post, put,
|
|
298
|
+
sendCommunication, sendMessage, sendText, getProcedures, executeProcedure
|
|
299
|
+
} = createApiBase({ auth });
|
|
253
300
|
|
|
254
301
|
return {
|
|
255
302
|
get,
|
|
@@ -484,7 +531,7 @@ export const createMPInstance = ({ auth }: { auth: { username: string; password:
|
|
|
484
531
|
{ path: `/files/${table}/${recordId}`, mpQuery: {} }
|
|
485
532
|
);
|
|
486
533
|
},
|
|
487
|
-
async
|
|
534
|
+
async uploadFile(table, recordId, data) {
|
|
488
535
|
return createFile<AttachedFile>(
|
|
489
536
|
{ path: `/files/${table}/${recordId}`, data }
|
|
490
537
|
);
|
|
@@ -494,10 +541,20 @@ export const createMPInstance = ({ auth }: { auth: { username: string; password:
|
|
|
494
541
|
{ path: `/files/${table}/${fileId}`, data }
|
|
495
542
|
);
|
|
496
543
|
},
|
|
544
|
+
|
|
545
|
+
// Communications API
|
|
546
|
+
sendCommunication,
|
|
547
|
+
sendMessage,
|
|
548
|
+
sendText,
|
|
549
|
+
|
|
550
|
+
// Procedures API
|
|
551
|
+
getProcedures,
|
|
552
|
+
executeProcedure,
|
|
497
553
|
};
|
|
498
554
|
};
|
|
499
555
|
|
|
500
556
|
export {
|
|
557
|
+
// Tables
|
|
501
558
|
Contact,
|
|
502
559
|
Participant,
|
|
503
560
|
Event,
|
|
@@ -513,10 +570,31 @@ export {
|
|
|
513
570
|
ContactEmailAddress,
|
|
514
571
|
ContactWithEmailAddress,
|
|
515
572
|
ContactWithEmailAddresses,
|
|
573
|
+
|
|
574
|
+
// Communications endpoint types
|
|
575
|
+
Communication,
|
|
576
|
+
CommunicationInfo,
|
|
577
|
+
CommunicationType,
|
|
578
|
+
CommunicationStatus,
|
|
579
|
+
TextingComplianceLevel,
|
|
580
|
+
MessageInfo,
|
|
581
|
+
MessageAddress,
|
|
582
|
+
TextInfo,
|
|
583
|
+
|
|
584
|
+
// Procedures endpoint types
|
|
585
|
+
ProcedureInfo,
|
|
586
|
+
ParameterInfo,
|
|
587
|
+
ParameterDirection,
|
|
588
|
+
ParameterDataType,
|
|
589
|
+
ProcedureInput,
|
|
590
|
+
|
|
591
|
+
// Utilities
|
|
516
592
|
ErrorDetails,
|
|
517
593
|
DateTimeIsoString,
|
|
518
594
|
convertToCamelCase,
|
|
519
595
|
convertToSnakeCase,
|
|
596
|
+
convertToPascalCase,
|
|
597
|
+
convertFromPascalCase,
|
|
520
598
|
stringifyURLParams,
|
|
521
599
|
escapeSql
|
|
522
600
|
};
|
package/src/utils/converters.ts
CHANGED
|
@@ -114,3 +114,67 @@ export function convertToCamelCase<T extends Record<string, any> = Record<string
|
|
|
114
114
|
export function convertToSnakeCase<T extends Record<string, any> = Record<string, any>, D extends Record<string, any> = Record<string, any>>(obj: Partial<D>, capitalIds = true): T {
|
|
115
115
|
return caseConverter(obj, { type: 'toSnake', capitalIds });
|
|
116
116
|
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Converts a camelCase string to PascalCase.
|
|
120
|
+
* Example: "authorUserId" → "AuthorUserId"
|
|
121
|
+
*/
|
|
122
|
+
export function toPascalCase(str: string): string {
|
|
123
|
+
if (!str) return str;
|
|
124
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Converts a PascalCase string to camelCase.
|
|
129
|
+
* Example: "AuthorUserId" → "authorUserId"
|
|
130
|
+
*/
|
|
131
|
+
export function fromPascalCase(str: string): string {
|
|
132
|
+
if (!str) return str;
|
|
133
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Recursively converts object keys between camelCase and PascalCase.
|
|
138
|
+
* Used for /communications, /messages, /texts, /procs endpoints.
|
|
139
|
+
*/
|
|
140
|
+
export function pascalCaseConverter<T>(
|
|
141
|
+
obj: T,
|
|
142
|
+
direction: 'toPascal' | 'fromPascal'
|
|
143
|
+
): T {
|
|
144
|
+
const caseFn = direction === 'toPascal' ? toPascalCase : fromPascalCase;
|
|
145
|
+
|
|
146
|
+
if (Array.isArray(obj)) {
|
|
147
|
+
return obj.map(val => pascalCaseConverter(val, direction)) as T;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (obj !== null && typeof obj === 'object') {
|
|
151
|
+
const result: Record<string, unknown> = {};
|
|
152
|
+
for (const key in obj) {
|
|
153
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
154
|
+
const newKey = caseFn(key);
|
|
155
|
+
result[newKey] = pascalCaseConverter((obj as Record<string, unknown>)[key], direction);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return result as T;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return obj;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Converts camelCase object keys to PascalCase.
|
|
166
|
+
* Used for outgoing requests to /communications, /messages, /texts endpoints.
|
|
167
|
+
* Example: { authorUserId: 1 } → { AuthorUserId: 1 }
|
|
168
|
+
*/
|
|
169
|
+
export function convertToPascalCase<T extends Record<string, any>>(obj: T): T {
|
|
170
|
+
return pascalCaseConverter(obj, 'toPascal');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Converts PascalCase object keys to camelCase.
|
|
175
|
+
* Used for incoming responses from /communications, /messages, /texts, /procs endpoints.
|
|
176
|
+
* Example: { AuthorUserId: 1 } → { authorUserId: 1 }
|
|
177
|
+
*/
|
|
178
|
+
export function convertFromPascalCase<T extends Record<string, any>>(obj: T): T {
|
|
179
|
+
return pascalCaseConverter(obj, 'fromPascal');
|
|
180
|
+
}
|