@zimbra/api-client 99.0.0 → 100.0.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.
Files changed (36) hide show
  1. package/.babelrc.json +1 -2
  2. package/dist/schema.graphql +10 -2
  3. package/dist/src/apollo/local-batch-link.d.ts +0 -1
  4. package/dist/src/apollo/offline-queue-link/index.d.ts +1 -4
  5. package/dist/src/batch-client/index.d.ts +4 -1
  6. package/dist/src/batch-client/types.d.ts +1 -1
  7. package/dist/src/normalize/entities.d.ts +1 -0
  8. package/dist/src/normalize/index.d.ts +1 -1
  9. package/dist/src/request/types.d.ts +0 -1
  10. package/dist/src/schema/generated-schema-types.d.ts +13 -2
  11. package/dist/src/utils/map-values-deep.d.ts +1 -0
  12. package/dist/zm-api-js-client.esm.js +201 -153
  13. package/dist/zm-api-js-client.esm.js.map +1 -1
  14. package/dist/zm-api-js-client.js +8 -8
  15. package/dist/zm-api-js-client.js.map +1 -1
  16. package/dist/zm-api-js-client.umd.js +8 -8
  17. package/dist/zm-api-js-client.umd.js.map +1 -1
  18. package/package-lock.json +339 -178
  19. package/package.json +3 -3
  20. package/rollup.config.js +1 -1
  21. package/src/apollo/offline-queue-link/util.ts +1 -2
  22. package/src/apollo/zimbra-error-link.ts +4 -3
  23. package/src/apollo/zimbra-in-memory-cache.ts +3 -3
  24. package/src/batch-client/index.ts +72 -42
  25. package/src/batch-client/types.ts +1 -1
  26. package/src/normalize/entities.ts +6 -1
  27. package/src/normalize/index.ts +42 -39
  28. package/src/request/index.ts +36 -48
  29. package/src/request/types.ts +0 -1
  30. package/src/schema/generated-schema-types.ts +15 -2
  31. package/src/schema/schema.graphql +10 -2
  32. package/src/schema/schema.ts +3 -2
  33. package/src/schema/session-handler.ts +1 -2
  34. package/src/utils/map-values-deep.ts +10 -2
  35. package/src/utils/normalize-attrs-custommetadata.ts +5 -6
  36. package/src/utils/normalize-otherAttribute-contact.ts +29 -19
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zimbra/api-client",
3
3
  "amdName": "zmApiJsClient",
4
- "version": "99.0.0",
4
+ "version": "100.0.0",
5
5
  "description": "Zimbra JS API Client and GraphQL client for making requests against the Zimbra SOAP API.",
6
6
  "main": "dist/zm-api-js-client.js",
7
7
  "source": "index.ts",
@@ -47,11 +47,11 @@
47
47
  ]
48
48
  },
49
49
  "dependencies": {
50
- "@apollo/client": "3.4.16",
50
+ "@apollo/client": "^3.14.0",
51
51
  "@graphql-tools/schema": "^10.0.25",
52
52
  "dataloader": "^2.2.2",
53
+ "es-toolkit": "^1.39.10",
53
54
  "graphql": "^16.9.0",
54
- "lodash": "^4.17.21",
55
55
  "mitt": "^3.0.0"
56
56
  },
57
57
  "devDependencies": {
package/rollup.config.js CHANGED
@@ -11,7 +11,7 @@ const FORMAT = process.env.FORMAT;
11
11
  const externalDeps = [
12
12
  '@apollo/client',
13
13
  'graphql',
14
- 'lodash',
14
+ 'es-toolkit',
15
15
  'mitt'
16
16
  ];
17
17
 
@@ -1,9 +1,8 @@
1
1
  import { Operation } from '@apollo/client/core';
2
- import get from 'lodash/get';
3
2
  import { OfflineOperationEntry, OperationEntry } from './types';
4
3
 
5
4
  export function hasSensitiveVariables(operation: Operation) {
6
- return !!get(operation, 'variables.password');
5
+ return !!operation?.variables?.password;
7
6
  }
8
7
 
9
8
  export function isMutationOperation({ query }: Operation) {
@@ -1,5 +1,4 @@
1
1
  import { ErrorLink } from '@apollo/client/link/error';
2
- import get from 'lodash/get';
3
2
 
4
3
  class ZimbraErrorLink extends ErrorLink {
5
4
  handlers: any[] = [];
@@ -7,8 +6,10 @@ class ZimbraErrorLink extends ErrorLink {
7
6
  constructor() {
8
7
  super(({ graphQLErrors, networkError }) => {
9
8
  graphQLErrors &&
10
- graphQLErrors.map(({ message, originalError, ...rest }) => {
11
- let errorCode = get(originalError, 'faults.0.Detail.Error.Code', '');
9
+ graphQLErrors.map((error: any) => {
10
+ const { message, ...rest } = error;
11
+ const originalError = error.originalError;
12
+ const errorCode = (originalError as any)?.faults?.[0]?.Detail?.Error?.Code || '';
12
13
 
13
14
  this.executeHandlers({
14
15
  errorCode,
@@ -1,12 +1,12 @@
1
1
  import { FieldFunctionOptions } from '@apollo/client';
2
2
  import { defaultDataIdFromObject, InMemoryCache, InMemoryCacheConfig } from '@apollo/client/core';
3
- import get from 'lodash/get';
4
- import uniqWith from 'lodash/uniqWith';
3
+ import { uniqWith } from 'es-toolkit';
4
+ import { getValueByPath } from '../utils/map-values-deep';
5
5
  import { EmailAddress } from './types';
6
6
 
7
7
  const dataIdFromPath = (result: any, path: string) => {
8
8
  if (result.__typename) {
9
- const id = get(result, path);
9
+ const id = getValueByPath(result, path);
10
10
  return id ? `${result.__typename}:${id}` : defaultDataIdFromObject(result);
11
11
  }
12
12
  };
@@ -1,8 +1,5 @@
1
1
  import DataLoader from 'dataloader';
2
- import castArray from 'lodash/castArray';
3
- import get from 'lodash/get';
4
- import isError from 'lodash/isError';
5
- import mapValues from 'lodash/mapValues';
2
+ import { mapValues } from 'es-toolkit';
6
3
  import { denormalize, normalize } from '../normalize';
7
4
  import {
8
5
  AccountRights,
@@ -35,6 +32,7 @@ import {
35
32
  GetDocumentShareURLEntity,
36
33
  GetDocumentShareURLResponseEntity,
37
34
  GetFolderRequest as GetFolderRequestEntity,
35
+ GetItem,
38
36
  GetRightsRequest,
39
37
  HabGroup,
40
38
  InviteReply,
@@ -75,6 +73,7 @@ import {
75
73
  ExternalAccountImportInput,
76
74
  ExternalAccountTestInput,
77
75
  FilterInput,
76
+ FilterMatchCondition,
78
77
  FolderActionChangeColorInput,
79
78
  FolderActionCheckCalendarInput,
80
79
  FolderView,
@@ -186,7 +185,7 @@ function normalizeMessage(
186
185
  }
187
186
 
188
187
  const hasUnreadDescendent = (folder: any): any => {
189
- const unreadDescendent = get(folder, 'unreadDescendent');
188
+ const unreadDescendent = folder?.unreadDescendent;
190
189
 
191
190
  if (
192
191
  folder[
@@ -199,7 +198,7 @@ const hasUnreadDescendent = (folder: any): any => {
199
198
  return true;
200
199
  }
201
200
 
202
- const folderArray = get(folder, 'folders') || [];
201
+ const folderArray = folder?.folders || [];
203
202
  for (let i = 0, len = folderArray.length; i < len; i++) {
204
203
  return hasUnreadDescendent(folderArray[i]);
205
204
  }
@@ -209,7 +208,7 @@ const hasUnreadDescendent = (folder: any): any => {
209
208
 
210
209
  const updateGroupName = (habGroup: any) => ({
211
210
  ...habGroup,
212
- name: get(habGroup, 'attributes.displayName')
211
+ name: habGroup?.attributes?.displayName
213
212
  });
214
213
 
215
214
  const updateGroupNameRecur = (habGroups: any) =>
@@ -220,8 +219,8 @@ const updateGroupNameRecur = (habGroups: any) =>
220
219
  });
221
220
 
222
221
  const setUnreadDescendentFlag = (folder: any) => {
223
- const folderArray = get(folder, 'folders') || [];
224
- const view = get(folder, 'view');
222
+ const folderArray = folder?.folders || [];
223
+ const view = folder?.view;
225
224
 
226
225
  // setting this flag only in message view has we dont want to show unread count in
227
226
  // other views
@@ -406,7 +405,7 @@ export class ZimbraBatchClient {
406
405
  [<string>accountType]: mapValuesDeep(accountInfo, coerceBooleanToString)
407
406
  },
408
407
  singleRequest: true
409
- }).then(res => get(res, `${accountType}.0.id`));
408
+ }).then(res => res?.[<string>accountType]?.[0]?.id);
410
409
 
411
410
  public addMessage = (message: AddMsgInput) => {
412
411
  const { folderId, content, meta } = message;
@@ -457,7 +456,7 @@ export class ZimbraBatchClient {
457
456
  }
458
457
  }
459
458
  }).then(res => {
460
- const ids = get(res, 'm[0].ids');
459
+ const ids = res?.m?.[0]?.ids;
461
460
  return ids ? ids.split(',') : [];
462
461
  });
463
462
 
@@ -532,8 +531,7 @@ export class ZimbraBatchClient {
532
531
  password,
533
532
  username,
534
533
  dryRun = false,
535
- authToken,
536
- csrfToken
534
+ authToken
537
535
  }: ChangePasswordOptions) => {
538
536
  if (authToken) {
539
537
  return this.jsonRequest({
@@ -547,8 +545,7 @@ export class ZimbraBatchClient {
547
545
  oldPassword: password,
548
546
  password: loginNewPassword,
549
547
  dryRun,
550
- authToken: { _content: authToken },
551
- csrfToken: { _content: csrfToken }
548
+ authToken: { _content: authToken }
552
549
  },
553
550
  singleRequest: true
554
551
  });
@@ -676,13 +673,11 @@ export class ZimbraBatchClient {
676
673
  identity: {
677
674
  ...rest,
678
675
  _attrs: {
679
- ...mapValues(attrs, coerceBooleanToString),
676
+ ...mapValues(attrs || {}, coerceBooleanToString),
680
677
  zimbraPrefWhenSentToAddresses: convertStringAndArrayValues(
681
- get(attrs, 'zimbraPrefWhenSentToAddresses')
678
+ attrs?.zimbraPrefWhenSentToAddresses
682
679
  ),
683
- zimbraPrefWhenInFolderIds: convertStringAndArrayValues(
684
- get(attrs, 'zimbraPrefWhenInFolderIds')
685
- )
680
+ zimbraPrefWhenInFolderIds: convertStringAndArrayValues(attrs?.zimbraPrefWhenInFolderIds)
686
681
  }
687
682
  }
688
683
  },
@@ -692,7 +687,7 @@ export class ZimbraBatchClient {
692
687
  const {
693
688
  _attrs: { zimbraPrefWhenSentToAddresses, zimbraPrefWhenInFolderIds, ...restAttr },
694
689
  ...restIdentityProps
695
- } = get(mappedResult, 'identity.0');
690
+ } = mappedResult?.identity?.[0];
696
691
 
697
692
  return {
698
693
  ...mappedResult,
@@ -942,7 +937,6 @@ export class ZimbraBatchClient {
942
937
  Header: {
943
938
  context: {
944
939
  _jsns: Namespace.All,
945
- csrfToken: this.csrfToken,
946
940
  account: {
947
941
  by: 'name',
948
942
  _content: options.accountName
@@ -1074,7 +1068,7 @@ export class ZimbraBatchClient {
1074
1068
  this.jsonRequest({
1075
1069
  name: 'GetConv',
1076
1070
  body: {
1077
- c: mapValues(options, coerceBooleanToInt)
1071
+ c: mapValues(options || {}, coerceBooleanToInt)
1078
1072
  }
1079
1073
  }).then(res => {
1080
1074
  const conversation = this.normalizeConversation(res.c[0]);
@@ -1115,7 +1109,7 @@ export class ZimbraBatchClient {
1115
1109
  this.jsonRequest({
1116
1110
  name: 'GetDeviceStatus',
1117
1111
  namespace: Namespace.Sync
1118
- }).then(res => get(res, 'device') || []);
1112
+ }).then(res => res?.device || []);
1119
1113
 
1120
1114
  public getDistributionList = (dl: String, needOwners: Boolean, needRights: String, by: String) =>
1121
1115
  this.jsonRequest({
@@ -1166,7 +1160,24 @@ export class ZimbraBatchClient {
1166
1160
  public getFilterRules = () =>
1167
1161
  this.jsonRequest({
1168
1162
  name: 'GetFilterRules'
1169
- }).then(res => normalize(Filter)(get(res, 'filterRules.0.filterRule') || []));
1163
+ }).then(res => {
1164
+ const filterRules = res?.filterRules?.[0]?.filterRule || [];
1165
+
1166
+ // Set default condition to anyof in case of null or undefined :: Classic UI approach
1167
+ for (let i = 0; i < filterRules.length; i++) {
1168
+ const rule = filterRules[i];
1169
+ if (rule?.filterTests && Array.isArray(rule.filterTests)) {
1170
+ for (let j = 0; j < rule.filterTests.length; j++) {
1171
+ const test = rule?.filterTests[j];
1172
+ if (test?.condition === null || test?.condition === undefined) {
1173
+ test.condition = FilterMatchCondition.Anyof;
1174
+ }
1175
+ }
1176
+ }
1177
+ }
1178
+
1179
+ return normalize(Filter)(filterRules);
1180
+ });
1170
1181
 
1171
1182
  public getFolder = (options: GetFolderOptions) => {
1172
1183
  return this.jsonRequest({
@@ -1174,7 +1185,7 @@ export class ZimbraBatchClient {
1174
1185
  body: denormalize(GetFolderRequestEntity)(options)
1175
1186
  }).then(res => {
1176
1187
  const foldersResponse = normalize(Folder)(res);
1177
- const folders = get(foldersResponse, 'folders.0', {});
1188
+ const folders = foldersResponse?.folders?.[0] || {};
1178
1189
 
1179
1190
  if (folders.folders) {
1180
1191
  folders.folders = folders.folders.map(setUnreadDescendentFlag);
@@ -1239,7 +1250,7 @@ export class ZimbraBatchClient {
1239
1250
  },
1240
1251
  namespace: Namespace.Account
1241
1252
  }).then(res => {
1242
- const habGroups = get(res, 'ou.0');
1253
+ const habGroups = res?.ou?.[0] || {};
1243
1254
  return {
1244
1255
  ...habGroups,
1245
1256
  habGroups: [...updateGroupNameRecur(habGroups.habGroup)]
@@ -1281,6 +1292,22 @@ export class ZimbraBatchClient {
1281
1292
  name: 'GetImportStatus'
1282
1293
  });
1283
1294
 
1295
+ public getItem = ({ id }: any) =>
1296
+ this.jsonRequest({
1297
+ name: 'GetItem',
1298
+ namespace: Namespace.Mail,
1299
+ body: {
1300
+ item: {
1301
+ id
1302
+ }
1303
+ }
1304
+ }).then(response => {
1305
+ const data = normalize(GetItem)(response);
1306
+ return {
1307
+ docs: data.documents
1308
+ };
1309
+ });
1310
+
1284
1311
  public getMailboxMetadata = ({ section }: GetMailboxMetadataOptions) =>
1285
1312
  this.jsonRequest({
1286
1313
  name: 'GetMailboxMetadata',
@@ -1346,7 +1373,12 @@ export class ZimbraBatchClient {
1346
1373
 
1347
1374
  for (const pref in prefs) {
1348
1375
  if (CASTING_PREFS.indexOf(pref) !== -1) {
1349
- prefs[pref] = typeof prefs[pref] === 'string' ? castArray(prefs[pref]) : prefs[pref];
1376
+ prefs[pref] =
1377
+ typeof prefs[pref] === 'string'
1378
+ ? prefs[pref] !== undefined
1379
+ ? [prefs[pref]]
1380
+ : []
1381
+ : prefs[pref];
1350
1382
  }
1351
1383
  }
1352
1384
  return prefs;
@@ -1607,13 +1639,11 @@ export class ZimbraBatchClient {
1607
1639
  identity: {
1608
1640
  ...rest,
1609
1641
  _attrs: {
1610
- ...mapValues(attrs, coerceBooleanToString),
1642
+ ...mapValues(attrs || {}, coerceBooleanToString),
1611
1643
  zimbraPrefWhenSentToAddresses: convertStringAndArrayValues(
1612
- get(attrs, 'zimbraPrefWhenSentToAddresses')
1644
+ attrs?.zimbraPrefWhenSentToAddresses
1613
1645
  ),
1614
- zimbraPrefWhenInFolderIds: convertStringAndArrayValues(
1615
- get(attrs, 'zimbraPrefWhenInFolderIds')
1616
- )
1646
+ zimbraPrefWhenInFolderIds: convertStringAndArrayValues(attrs?.zimbraPrefWhenInFolderIds)
1617
1647
  }
1618
1648
  }
1619
1649
  },
@@ -2037,7 +2067,7 @@ export class ZimbraBatchClient {
2037
2067
  [<string>accountType]: mapValuesDeep(accountInfo, coerceBooleanToString)
2038
2068
  },
2039
2069
  singleRequest: true
2040
- }).then(res => mapValuesDeep(get(res, `${accountType}.0`), coerceStringToBoolean));
2070
+ }).then(res => mapValuesDeep(res?.[<string>accountType]?.[0], coerceStringToBoolean));
2041
2071
 
2042
2072
  public uploadMessage = (message: string): any => {
2043
2073
  const contentDisposition = 'attachment';
@@ -2086,9 +2116,9 @@ export class ZimbraBatchClient {
2086
2116
  requests,
2087
2117
  ...this.getAdditionalRequestOptions()
2088
2118
  }).then(response => {
2089
- const sessionId = get(response, 'header.context.session.id');
2090
- const notifications = get(response, 'header.context.notify.0');
2091
- const refresh = get(response, 'header.context.refresh');
2119
+ const sessionId = response?.header?.context?.session?.id;
2120
+ const notifications = response?.header?.context?.notify?.[0];
2121
+ const refresh = response?.header?.context?.refresh;
2092
2122
 
2093
2123
  this.checkAndUpdateSessionId(sessionId);
2094
2124
 
@@ -2106,7 +2136,7 @@ export class ZimbraBatchClient {
2106
2136
  if (DEBUG) {
2107
2137
  console.log(`[Batch Client Request] ${requests[i].name}`, requests[i].body, r);
2108
2138
  }
2109
- return isError(r) ? r : r.body;
2139
+ return r instanceof Error ? r : r.body;
2110
2140
  });
2111
2141
  });
2112
2142
 
@@ -2124,9 +2154,9 @@ export class ZimbraBatchClient {
2124
2154
  // check if login request then don't add csrfToken
2125
2155
  ...this.getAdditionalRequestOptions(requests[0].name !== 'Auth')
2126
2156
  }).then(response => {
2127
- const sessionId = get(response, 'header.context.session.id');
2128
- const notifications = get(response, 'header.context.notify.0');
2129
- const refresh = get(response, 'header.context.refresh');
2157
+ const sessionId = response?.header?.context?.session?.id;
2158
+ const notifications = response?.header?.context?.notify?.[0];
2159
+ const refresh = response?.header?.context?.refresh;
2130
2160
 
2131
2161
  this.checkAndUpdateSessionId(sessionId);
2132
2162
 
@@ -2140,7 +2170,7 @@ export class ZimbraBatchClient {
2140
2170
  }
2141
2171
  }
2142
2172
 
2143
- return isError(response) ? [response] : [response.body];
2173
+ return response instanceof Error ? [response] : [response.body];
2144
2174
  });
2145
2175
 
2146
2176
  private download = ({ isSecure, url }: any) =>
@@ -178,6 +178,7 @@ export interface AppointmentOptions {
178
178
  }
179
179
 
180
180
  export interface SaveDocumentInput {
181
+ content: string;
181
182
  ct: string;
182
183
  descEnabled: Boolean;
183
184
  id: string;
@@ -234,7 +235,6 @@ export interface ShareInfoOptions {
234
235
 
235
236
  export interface ChangePasswordOptions {
236
237
  authToken: string;
237
- csrfToken: string;
238
238
  dryRun: boolean;
239
239
  loginNewPassword: string;
240
240
  password: string;
@@ -533,6 +533,10 @@ export const ListDocumentRevisions = new Entity({
533
533
  doc: ['documents', Document]
534
534
  });
535
535
 
536
+ export const GetItem = new Entity({
537
+ doc: ['documents', Document]
538
+ });
539
+
536
540
  export const MessagePartInputForDocuments = new Entity({
537
541
  id: 'messageId',
538
542
  part: 'attachmentPart'
@@ -545,7 +549,8 @@ export const SaveDocument = new Entity({
545
549
  ct: 'contentType',
546
550
  descEnabled: 'descriptionEnabled',
547
551
  m: ['messageData', MessagePartInputForDocuments],
548
- doc: ['document', Document]
552
+ doc: ['document', Document],
553
+ content: 'content'
549
554
  });
550
555
 
551
556
  export const SearchResponse = new Entity({
@@ -1,5 +1,3 @@
1
- import reduce from 'lodash/reduce';
2
-
3
1
  import { EntityMapping, EntityMappingValue, NormalizedKey } from './types';
4
2
 
5
3
  function normalizeKey(key: string, schema: Entity, inverse: Boolean = false): NormalizedKey {
@@ -19,25 +17,28 @@ function normalizeKey(key: string, schema: Entity, inverse: Boolean = false): No
19
17
  return { key };
20
18
  }
21
19
 
22
- function _normalize(data: {}, schema: Entity, inverse: Boolean = false) {
23
- return reduce(
24
- data,
25
- (result: { [key: string]: any }, v, k) => {
26
- const { key, nestedSchema } = normalizeKey(k, schema, inverse);
27
- const type = typeof v;
28
- if (Array.isArray(v)) {
29
- result[key] = (v as Array<any>).map(i =>
30
- nestedSchema ? _normalize(i, nestedSchema, inverse) : i
31
- );
32
- } else if (type === 'object' && v !== null) {
33
- result[key] = nestedSchema ? _normalize(v, nestedSchema, inverse) : v;
34
- } else {
35
- result[key] = v;
36
- }
37
- return result;
38
- },
39
- {}
40
- );
20
+ function _normalize(data: {}, schema: Entity, inverse: boolean = false) {
21
+ const result: { [key: string]: any } = {};
22
+
23
+ for (const k in data) {
24
+ if (!Object.prototype.hasOwnProperty.call(data, k)) {
25
+ continue;
26
+ }
27
+
28
+ const v = (data as any)[k];
29
+ const { key, nestedSchema } = normalizeKey(k, schema, inverse);
30
+ const type = typeof v;
31
+
32
+ if (Array.isArray(v)) {
33
+ result[key] = v.map(i => (nestedSchema ? _normalize(i, nestedSchema, inverse) : i));
34
+ } else if (type === 'object' && v !== null) {
35
+ result[key] = nestedSchema ? _normalize(v, nestedSchema, inverse) : v;
36
+ } else {
37
+ result[key] = v;
38
+ }
39
+ }
40
+
41
+ return result;
41
42
  }
42
43
 
43
44
  /**
@@ -74,24 +75,26 @@ export class Entity {
74
75
  this.inverseMapping = this.initInverseMapping(this.mapping);
75
76
  }
76
77
 
77
- initInverseMapping(mapping: EntityMapping, accumulator = {}) {
78
- return reduce(
79
- mapping,
80
- (result: EntityMapping, v: any, k) => {
81
- if (Array.isArray(v)) {
82
- result[v[0]] = [k, v[1]];
83
- } else if (typeof v === 'object' && !(v instanceof Entity)) {
84
- result[k] = this.initInverseMapping(v) as EntityMappingValue;
85
- } else if (typeof v === 'string') {
86
- result[v] = k;
87
- } else {
88
- result[k] = v;
89
- }
90
-
91
- return result;
92
- },
93
- accumulator
94
- );
78
+ initInverseMapping(mapping: EntityMapping, accumulator: EntityMapping = {}): EntityMapping {
79
+ for (const k in mapping) {
80
+ if (!Object.prototype.hasOwnProperty.call(mapping, k)) {
81
+ continue;
82
+ }
83
+
84
+ const v: any = mapping[k];
85
+
86
+ if (Array.isArray(v)) {
87
+ accumulator[v[0]] = [k, v[1]];
88
+ } else if (typeof v === 'object' && !(v instanceof Entity)) {
89
+ accumulator[k] = this.initInverseMapping(v) as EntityMappingValue;
90
+ } else if (typeof v === 'string') {
91
+ accumulator[v] = k;
92
+ } else {
93
+ accumulator[k] = v;
94
+ }
95
+ }
96
+
97
+ return accumulator;
95
98
  }
96
99
 
97
100
  public inverseKey(k: string) {
@@ -1,5 +1,3 @@
1
- import get from 'lodash/get';
2
- import reduce from 'lodash/reduce';
3
1
  import {
4
2
  BatchRequestOptions,
5
3
  BatchRequestResponse,
@@ -39,7 +37,7 @@ function parseJSON(response: Response): Promise<ParsedResponse> {
39
37
  // for the rest of the cases (as of now only 500 error), parse and return the error response so that it can
40
38
  // be handled properly by the caller
41
39
  return parseErrorJSON(response).then(parsedResponse => {
42
- const fault = get(parsedResponse.parsed, 'Body.Fault');
40
+ const fault = parsedResponse?.parsed?.Body?.Fault;
43
41
  throw faultError(parsedResponse, [fault]);
44
42
  });
45
43
  }
@@ -71,7 +69,7 @@ function networkError(response: ParsedResponse) {
71
69
 
72
70
  (error as NetworkError).message = message;
73
71
  (error as NetworkError).response = response;
74
- (error as NetworkError).parseError = response.parseError;
72
+ (error as NetworkError).parseError = response?.parseError;
75
73
 
76
74
  return error as NetworkError;
77
75
  }
@@ -80,7 +78,7 @@ function faultReasonText(faults: any = []): string {
80
78
  if (!Array.isArray(faults)) faults = [faults];
81
79
 
82
80
  return faults
83
- .map((f: any) => get(f, 'Reason.Text'))
81
+ .map((f: any) => f?.Reason?.Text)
84
82
  .filter(Boolean)
85
83
  .join(', ');
86
84
  }
@@ -88,7 +86,7 @@ function faultReasonText(faults: any = []): string {
88
86
  function faultError(response: ParsedResponse, faults: any) {
89
87
  const error = new Error(`Fault error: ${faults ? faultReasonText(faults) : 'Unknown Error'}`);
90
88
  (error as SingleBatchRequestError).response = response;
91
- (error as SingleBatchRequestError).parseError = response.parseError;
89
+ (error as SingleBatchRequestError).parseError = response?.parseError;
92
90
  (error as SingleBatchRequestError).faults = faults;
93
91
  return error as SingleBatchRequestError;
94
92
  }
@@ -98,20 +96,20 @@ function faultError(response: ParsedResponse, faults: any) {
98
96
  * containing an array of the requests for that command.
99
97
  */
100
98
  function batchBody(requests: ReadonlyArray<RequestOptions>) {
101
- return reduce(
102
- requests,
103
- (body: { [key: string]: any }, request) => {
104
- const key = `${request.name}Request`;
105
- const value = soapCommandBody(request);
106
- if (body[key]) {
107
- body[key].push(value);
108
- } else {
109
- body[key] = [value];
110
- }
111
- return body;
112
- },
113
- {}
114
- );
99
+ const body: { [key: string]: any } = {};
100
+
101
+ for (const request of requests) {
102
+ const key = `${request.name}Request`;
103
+ const value = soapCommandBody(request);
104
+
105
+ if (body[key]) {
106
+ body[key].push(value);
107
+ } else {
108
+ body[key] = [value];
109
+ }
110
+ }
111
+
112
+ return body;
115
113
  }
116
114
 
117
115
  /**
@@ -127,34 +125,26 @@ function batchResponse(requests: any, response: RequestResponse) {
127
125
  // For each request type, track which responses have been
128
126
  // pulled out of the batch request body by incrementing
129
127
  // indexes.
130
- let indexes: { [key: string]: number } = {};
128
+ const indexes: { [key: string]: number } = {};
129
+ const responses: Array<SingleBatchRequestResponse | SingleBatchRequestError> = [];
130
+
131
+ for (const request of requests) {
132
+ const batchResponses = batchBody[`${request.name}Response`];
133
+ const index = indexes[request.name] || 0;
134
+ const singleResponse = batchResponses?.[index];
135
+
136
+ if (singleResponse) {
137
+ responses.push({ body: singleResponse });
138
+ } else {
139
+ responses.push(faultError(request.originalResponse, batchBody.Fault));
140
+ }
141
+
142
+ indexes[request.name] = index + 1;
143
+ }
131
144
 
132
145
  return {
133
146
  ...res,
134
- requests: reduce(
135
- requests,
136
- (responses: Array<SingleBatchRequestResponse | SingleBatchRequestError>, request) => {
137
- const batchResponses = batchBody[`${request.name}Response`];
138
- const index = indexes[request.name];
139
- const response: any = batchResponses && batchResponses[index || 0];
140
- if (response) {
141
- responses.push({
142
- body: response
143
- });
144
- } else {
145
- responses.push(faultError(res.originalResponse, batchBody.Fault));
146
- }
147
-
148
- if (index) {
149
- indexes[request.name] += 1;
150
- } else {
151
- indexes[request.name] = 1;
152
- }
153
-
154
- return responses;
155
- },
156
- []
157
- )
147
+ requests: responses
158
148
  };
159
149
  }
160
150
 
@@ -232,8 +222,6 @@ export function jsonRequest(requestOptions: JsonRequestOptions): Promise<Request
232
222
 
233
223
  if (requestOptions.csrfToken) {
234
224
  options.headers['X-Zimbra-Csrf-Token'] = requestOptions.csrfToken;
235
-
236
- header.context.csrfToken = requestOptions.csrfToken;
237
225
  }
238
226
 
239
227
  // Allow to set Auth Token in Cookie in case `ZimbraBatchClient` is used on non-web platforms, like nodejs
@@ -267,7 +255,7 @@ export function jsonRequest(requestOptions: JsonRequestOptions): Promise<Request
267
255
  })
268
256
  .then(parseJSON)
269
257
  .then((response: any) => {
270
- const globalFault = get(response.parsed, 'Body.Fault');
258
+ const globalFault = response?.parsed?.Body?.Fault;
271
259
 
272
260
  if (globalFault) {
273
261
  throw faultError(response, globalFault);
@@ -95,7 +95,6 @@ export interface SOAPHeader {
95
95
  authTokenControl?: {
96
96
  voidOnExpired: boolean;
97
97
  };
98
- csrfToken?: string;
99
98
  jwtToken?: {
100
99
  _content: string;
101
100
  };