@zimbra/api-client 98.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 +37 -3
  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 +2 -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 +38 -2
  11. package/dist/src/utils/map-values-deep.d.ts +1 -0
  12. package/dist/zm-api-js-client.esm.js +660 -355
  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 +832 -1399
  19. package/package.json +6 -6
  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 +38 -8
  24. package/src/batch-client/index.ts +74 -44
  25. package/src/batch-client/types.ts +2 -1
  26. package/src/normalize/entities.ts +10 -3
  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 +41 -2
  31. package/src/schema/schema.graphql +37 -3
  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": "98.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,22 +47,22 @@
47
47
  ]
48
48
  },
49
49
  "dependencies": {
50
- "@apollo/client": "3.4.16",
51
- "@graphql-tools/schema": "^10.0.23",
50
+ "@apollo/client": "^3.14.0",
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": {
58
58
  "@babel/cli": "^7.17.10",
59
- "@babel/core": "^7.18.2",
59
+ "@babel/core": "^7.28.0",
60
60
  "@babel/plugin-proposal-class-properties": "^7.17.12",
61
61
  "@babel/preset-env": "^7.18.2",
62
62
  "@babel/preset-typescript": "^7.27.1",
63
63
  "@babel/register": "^7.17.7",
64
64
  "@graphql-codegen/cli": "^5.0.7",
65
- "@graphql-codegen/typescript": "^4.0.1",
65
+ "@graphql-codegen/typescript": "^4.1.6",
66
66
  "@rollup/plugin-babel": "^6.0.4",
67
67
  "@rollup/plugin-commonjs": "^28.0.5",
68
68
  "@rollup/plugin-graphql": "^1.1.0",
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,11 +1,12 @@
1
+ import { FieldFunctionOptions } from '@apollo/client';
1
2
  import { defaultDataIdFromObject, InMemoryCache, InMemoryCacheConfig } from '@apollo/client/core';
2
- import get from 'lodash/get';
3
- import uniqWith from 'lodash/uniqWith';
3
+ import { uniqWith } from 'es-toolkit';
4
+ import { getValueByPath } from '../utils/map-values-deep';
4
5
  import { EmailAddress } from './types';
5
6
 
6
7
  const dataIdFromPath = (result: any, path: string) => {
7
8
  if (result.__typename) {
8
- const id = get(result, path);
9
+ const id = getValueByPath(result, path);
9
10
  return id ? `${result.__typename}:${id}` : defaultDataIdFromObject(result);
10
11
  }
11
12
  };
@@ -58,6 +59,29 @@ function createPossibleTypes(possibleTypesFactory = Object) {
58
59
  });
59
60
  }
60
61
 
62
+ function isReference(obj: any): obj is { __ref: string } {
63
+ return obj && typeof obj === 'object' && '__ref' in obj;
64
+ }
65
+
66
+ function resolvedRefrenceAddress(
67
+ address: EmailAddress[],
68
+ readField: FieldFunctionOptions['readField']
69
+ ) {
70
+ return (address || []).map(item => {
71
+ if (isReference(item)) {
72
+ return {
73
+ __typename: readField('__typename', item),
74
+ address: readField('address', item),
75
+ type: readField('type', item),
76
+ isGroup: readField('isGroup', item),
77
+ name: readField('name', item),
78
+ displayName: readField('displayName', item)
79
+ };
80
+ }
81
+ return item;
82
+ });
83
+ }
84
+
61
85
  const typePolicies = {
62
86
  Query: {
63
87
  fields: {
@@ -95,11 +119,17 @@ const typePolicies = {
95
119
  MessageInfo: {
96
120
  fields: {
97
121
  emailAddresses: {
98
- merge(existing: EmailAddress[], incoming: EmailAddress[]) {
99
- return uniqWith(
100
- [...(existing || []), ...(incoming || [])],
101
- (a, b) => a.address === b.address && a.type === b.type
102
- );
122
+ merge(
123
+ existing: EmailAddress[] = [],
124
+ incoming: EmailAddress[] = [],
125
+ { readField }: FieldFunctionOptions
126
+ ) {
127
+ const resolvedExisting = resolvedRefrenceAddress(existing, readField);
128
+ const resolvedIncoming = resolvedRefrenceAddress(incoming, readField);
129
+ const combined = [...(resolvedIncoming || []), ...(resolvedExisting || [])];
130
+ // Prefer entries where isGroup is not null
131
+ combined.sort((a, b) => Number(b.isGroup != null) - Number(a.isGroup != null));
132
+ return uniqWith(combined, (a, b) => a.address === b.address && a.type === b.type);
103
133
  }
104
134
  }
105
135
  }
@@ -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
@@ -385,7 +384,7 @@ export class ZimbraBatchClient {
385
384
  });
386
385
 
387
386
  public action = (type: ActionType, options: ActionOptions) => {
388
- const { ids, id, ...rest } = options;
387
+ const { ids, id, isBatchOperation, ...rest } = options;
389
388
 
390
389
  return this.jsonRequest({
391
390
  name: type,
@@ -395,7 +394,7 @@ export class ZimbraBatchClient {
395
394
  ...denormalize(ActionOptionsEntity)(rest)
396
395
  }
397
396
  },
398
- singleRequest: true
397
+ singleRequest: !isBatchOperation
399
398
  }).then(Boolean);
400
399
  };
401
400
 
@@ -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;
@@ -264,6 +264,7 @@ export interface ActionOptions {
264
264
  folderId?: string;
265
265
  id?: string;
266
266
  ids?: Array<string>;
267
+ isBatchOperation?: boolean;
267
268
  isLocal?: boolean;
268
269
  name?: string;
269
270
  op: string;
@@ -87,12 +87,14 @@ const CalendarItemAttendees = new Entity({
87
87
  ptst: 'participationStatus',
88
88
  a: 'address',
89
89
  d: 'name',
90
- cutype: 'calendarUserType'
90
+ cutype: 'calendarUserType',
91
+ isGroup: 'isGroup'
91
92
  });
92
93
 
93
94
  const CalendarItemReply = new Entity({
94
95
  ptst: 'participationStatus',
95
- at: 'address'
96
+ at: 'address',
97
+ isGroup: 'isGroup'
96
98
  });
97
99
 
98
100
  const CalendarItemOrganizer = new Entity({
@@ -531,6 +533,10 @@ export const ListDocumentRevisions = new Entity({
531
533
  doc: ['documents', Document]
532
534
  });
533
535
 
536
+ export const GetItem = new Entity({
537
+ doc: ['documents', Document]
538
+ });
539
+
534
540
  export const MessagePartInputForDocuments = new Entity({
535
541
  id: 'messageId',
536
542
  part: 'attachmentPart'
@@ -543,7 +549,8 @@ export const SaveDocument = new Entity({
543
549
  ct: 'contentType',
544
550
  descEnabled: 'descriptionEnabled',
545
551
  m: ['messageData', MessagePartInputForDocuments],
546
- doc: ['document', Document]
552
+ doc: ['document', Document],
553
+ content: 'content'
547
554
  });
548
555
 
549
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) {