@fiduswriter/editor 0.1.49 → 0.1.50

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 (86) hide show
  1. package/dist/clipboard/copy/serializers.js.map +1 -1
  2. package/dist/collab/doc.js.map +1 -1
  3. package/dist/collab/merge/index.d.ts.map +1 -1
  4. package/dist/collab/merge/index.js +1 -1
  5. package/dist/collab/merge/index.js.map +1 -1
  6. package/dist/comments/editors/comment.d.ts.map +1 -1
  7. package/dist/comments/editors/comment.js +1 -1
  8. package/dist/comments/editors/comment.js.map +1 -1
  9. package/dist/comments/editors/notify.d.ts +2 -1
  10. package/dist/comments/editors/notify.d.ts.map +1 -1
  11. package/dist/comments/editors/notify.js +2 -3
  12. package/dist/comments/editors/notify.js.map +1 -1
  13. package/dist/comments/interactions.js +2 -2
  14. package/dist/comments/interactions.js.map +1 -1
  15. package/dist/contacts/add_dialog.d.ts +3 -1
  16. package/dist/contacts/add_dialog.d.ts.map +1 -1
  17. package/dist/contacts/add_dialog.js +11 -8
  18. package/dist/contacts/add_dialog.js.map +1 -1
  19. package/dist/databases/images.d.ts.map +1 -1
  20. package/dist/databases/images.js +8 -5
  21. package/dist/databases/images.js.map +1 -1
  22. package/dist/dialogs/citation.js +1 -1
  23. package/dist/dialogs/citation.js.map +1 -1
  24. package/dist/document_template/exporter.d.ts +8 -2
  25. package/dist/document_template/exporter.d.ts.map +1 -1
  26. package/dist/document_template/exporter.js +4 -8
  27. package/dist/document_template/exporter.js.map +1 -1
  28. package/dist/document_template/index.d.ts.map +1 -1
  29. package/dist/document_template/index.js +1 -1
  30. package/dist/document_template/index.js.map +1 -1
  31. package/dist/documents/access_rights/index.d.ts +9 -2
  32. package/dist/documents/access_rights/index.d.ts.map +1 -1
  33. package/dist/documents/access_rights/index.js +25 -12
  34. package/dist/documents/access_rights/index.js.map +1 -1
  35. package/dist/e2ee/passphrase_urls.d.ts +14 -0
  36. package/dist/e2ee/passphrase_urls.d.ts.map +1 -0
  37. package/dist/e2ee/passphrase_urls.js +27 -0
  38. package/dist/e2ee/passphrase_urls.js.map +1 -0
  39. package/dist/exporter/native/copy.d.ts +2 -1
  40. package/dist/exporter/native/copy.d.ts.map +1 -1
  41. package/dist/exporter/native/copy.js +11 -10
  42. package/dist/exporter/native/copy.js.map +1 -1
  43. package/dist/exporter/native/file.d.ts +8 -1
  44. package/dist/exporter/native/file.d.ts.map +1 -1
  45. package/dist/exporter/native/file.js +2 -2
  46. package/dist/exporter/native/file.js.map +1 -1
  47. package/dist/exporter/native/revision.js +4 -3
  48. package/dist/exporter/native/revision.js.map +1 -1
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +24 -15
  52. package/dist/index.js.map +1 -1
  53. package/dist/menus/headerbar/model.d.ts.map +1 -1
  54. package/dist/menus/headerbar/model.js +10 -8
  55. package/dist/menus/headerbar/model.js.map +1 -1
  56. package/dist/no_collab_save/index.d.ts +1 -1
  57. package/dist/no_collab_save/index.d.ts.map +1 -1
  58. package/dist/no_collab_save/index.js +13 -12
  59. package/dist/no_collab_save/index.js.map +1 -1
  60. package/dist/state_plugins/inline_reference/dropup.js.map +1 -1
  61. package/dist/state_plugins/settings.js.map +1 -1
  62. package/dist/types.d.ts +128 -3
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/package.json +9 -6
  66. package/src/clipboard/copy/serializers.ts +1 -1
  67. package/src/collab/doc.ts +1 -1
  68. package/src/collab/merge/index.ts +1 -0
  69. package/src/comments/editors/comment.ts +6 -1
  70. package/src/comments/editors/notify.ts +3 -2
  71. package/src/comments/interactions.ts +2 -2
  72. package/src/contacts/add_dialog.ts +15 -8
  73. package/src/databases/images.ts +21 -18
  74. package/src/dialogs/citation.ts +3 -3
  75. package/src/document_template/exporter.ts +10 -8
  76. package/src/document_template/index.ts +3 -2
  77. package/src/documents/access_rights/index.ts +44 -23
  78. package/src/exporter/native/copy.ts +18 -10
  79. package/src/exporter/native/file.ts +9 -1
  80. package/src/exporter/native/revision.ts +16 -16
  81. package/src/index.ts +46 -34
  82. package/src/menus/headerbar/model.ts +17 -9
  83. package/src/no_collab_save/index.ts +20 -22
  84. package/src/state_plugins/inline_reference/dropup.ts +2 -2
  85. package/src/state_plugins/settings.ts +1 -1
  86. package/src/types.ts +92 -2
package/src/index.ts CHANGED
@@ -7,7 +7,6 @@ import {
7
7
  addAlert,
8
8
  deactivateWait,
9
9
  ensureCSS,
10
- postJson,
11
10
  showSystemMessage,
12
11
  whenReady
13
12
  } from "fwtoolkit"
@@ -309,19 +308,21 @@ export class Editor {
309
308
  initPromises.push(this._createE2EEDocument())
310
309
  } else {
311
310
  initPromises.push(
312
- postJson("/api/document/create_doc/", {
313
- template_id: this.docInfo.templateId,
314
- path: this.docInfo.path
315
- }).then(({json}: {json: any}) => {
316
- this.docInfo.id = json.id
317
- window.history.replaceState(
318
- "",
319
- "",
320
- `/document/${this.docInfo.id}/`
321
- )
322
- delete this.docInfo.templateId
323
- return Promise.resolve()
324
- })
311
+ this.app.apiConnectors.document
312
+ .createDocument({
313
+ template_id: this.docInfo.templateId,
314
+ path: this.docInfo.path
315
+ })
316
+ .then(({json}: {json: any}) => {
317
+ this.docInfo.id = json.id
318
+ window.history.replaceState(
319
+ "",
320
+ "",
321
+ `/document/${this.docInfo.id}/`
322
+ )
323
+ delete this.docInfo.templateId
324
+ return Promise.resolve()
325
+ })
325
326
  )
326
327
  }
327
328
  }
@@ -329,9 +330,9 @@ export class Editor {
329
330
  if (uuid4Pattern.test(this.docInfo.id)) {
330
331
  this.docInfo.token = this.docInfo.id
331
332
  initPromises.push(
332
- postJson(
333
- `/api/document/share_token/validate/${this.docInfo.token}/`
334
- ).then(({json, status}: {json: any; status: number}) => {
333
+ this.app.apiConnectors.document
334
+ .validateShareToken(this.docInfo.token as string)
335
+ .then(({json, status}: {json: any; status: number}) => {
335
336
  if (status === 200 && json.document_id) {
336
337
  this.docInfo.id = json.document_id
337
338
  this.docInfo.access_rights = json.rights
@@ -362,22 +363,22 @@ export class Editor {
362
363
  }
363
364
  const editorSaveMode = this.app.settings.EDITOR_SAVE_MODE
364
365
  const collaborativeEditing = editorSaveMode === "collaborative"
366
+ const documentApi = this.app.apiConnectors.document
365
367
  const wsBasePromise = collaborativeEditing
366
368
  ? this.docInfo.wsBase
367
369
  ? Promise.resolve({
368
370
  json: {ws_base: this.docInfo.wsBase}
369
371
  })
370
- : postJson("/api/document/get_ws_base/", {
371
- id: this.docInfo.id
372
+ : documentApi.getWebSocketBase({
373
+ id: this.docInfo.id as number,
374
+ token: this.docInfo.token
372
375
  })
373
376
  : Promise.resolve({json: {ws_base: ""}})
374
- const stylesPromise = postJson(
375
- "/api/document/get_doc_styles/",
376
- stylesPayload
377
+ const stylesPromise = documentApi.getDocumentStyles(
378
+ stylesPayload as {id: number; token?: string}
377
379
  )
378
- const docDataPromise = postJson(
379
- "/api/document/get_doc_data/",
380
- stylesPayload
380
+ const docDataPromise = documentApi.getDocumentData(
381
+ stylesPayload as {id: number; token?: string}
381
382
  )
382
383
  return Promise.all([
383
384
  wsBasePromise,
@@ -538,11 +539,13 @@ export class Editor {
538
539
  // our version (v) lets the endpoint include the
539
540
  // covering diffs as `m` so adjustDocument can
540
541
  // do a precise merge.
541
- postJson("/api/document/get_doc_data/", {
542
- id: this.docInfo.id,
543
- token: this.docInfo.token,
544
- v: this.docInfo.version
545
- }).then(({json}) => {
542
+ this.app.apiConnectors.document
543
+ .getDocumentData({
544
+ id: this.docInfo.id as number,
545
+ token: this.docInfo.token,
546
+ v: this.docInfo.version as number
547
+ })
548
+ .then(({json}) => {
546
549
  this.mod.collab.doc.receiveDocument(
547
550
  json
548
551
  )
@@ -707,6 +710,7 @@ export class Editor {
707
710
  use_current_view: true
708
711
  })
709
712
  new ExportFidusFile(
713
+ this.app,
710
714
  doc,
711
715
  this.mod.db.bibDB,
712
716
  this.mod.db.imageDB,
@@ -776,6 +780,7 @@ export class Editor {
776
780
  handleAccessRightModification(): void {
777
781
  // This function when invoked creates a copy of document in FW format and closes editor operation.
778
782
  new ExportFidusFile(
783
+ this.app,
779
784
  this.getDoc({use_current_view: true}),
780
785
  this.mod.db.bibDB,
781
786
  this.mod.db.imageDB
@@ -896,24 +901,25 @@ export class Editor {
896
901
  )
897
902
 
898
903
  // Create the document on the server with E2EE parameters
899
- const {json, status} = await postJson("/api/document/create_doc/", {
904
+ const {json, status} = await this.app.apiConnectors.document.createDocument({
900
905
  template_id: this.docInfo.templateId,
901
906
  path: this.docInfo.path,
902
907
  e2ee: true,
903
908
  e2ee_salt: saltBase64,
904
909
  e2ee_iterations: iterations
905
- }) as {json: any; status: number}
910
+ })
906
911
 
912
+ const createData = json as {id: number; error?: string}
907
913
  if (status === 403) {
908
914
  addAlert(
909
915
  "error",
910
- json.error || gettext("E2EE is not enabled on this server.")
916
+ createData.error || gettext("E2EE is not enabled on this server.")
911
917
  )
912
918
  window.location.href = "/"
913
919
  return
914
920
  }
915
921
 
916
- this.docInfo.id = json.id
922
+ this.docInfo.id = createData.id
917
923
  window.history.replaceState("", "", `/document/${this.docInfo.id}/`)
918
924
  delete this.docInfo.templateId
919
925
 
@@ -1310,3 +1316,9 @@ export class Editor {
1310
1316
  return
1311
1317
  }
1312
1318
  }
1319
+
1320
+ export type {
1321
+ EditorDocumentApi,
1322
+ EditorDocumentImportApi,
1323
+ EditorContactsApi
1324
+ } from "./types.js"
@@ -2,7 +2,6 @@ import {
2
2
  Dialog,
3
3
  addAlert,
4
4
  addProgress,
5
- postJson,
6
5
  shortFileTitle
7
6
  } from "fwtoolkit"
8
7
  import type {BibDB, ExportDoc, ImageDB} from "@fiduswriter/document"
@@ -137,10 +136,11 @@ export const headerbarModel = () => ({
137
136
  !editor.docInfo.is_owner
138
137
  ) {
139
138
  // TokenUser requesting access
140
- postJson("/api/document/request_access/", {
141
- document_id: editor.docInfo.id,
142
- rights: "write"
143
- })
139
+ editor.app.apiConnectors.document
140
+ .requestAccess({
141
+ document_id: editor.docInfo.id as number,
142
+ rights: "write"
143
+ })
144
144
  .then(({json}: {json: unknown}) => {
145
145
  const data = json as {
146
146
  success?: boolean
@@ -189,9 +189,10 @@ export const headerbarModel = () => ({
189
189
  const noPassphraseUsers: string[] = []
190
190
  for (const ar of userRecipients) {
191
191
  try {
192
+ const holderId = ar.holder?.id as number
192
193
  const hasKeys =
193
194
  await PassphraseManager.userHasEncryptionKeys(
194
- ar.holder?.id as number
195
+ holderId
195
196
  )
196
197
  if (hasKeys) {
197
198
  // Recipient has passphrase keys —
@@ -199,7 +200,7 @@ export const headerbarModel = () => ({
199
200
  await PassphraseManager.saveDocumentPassword(
200
201
  editor.docInfo.id as number,
201
202
  editor.e2ee.password,
202
- ar.holder?.id as number,
203
+ holderId,
203
204
  "user",
204
205
  false
205
206
  )
@@ -252,7 +253,9 @@ export const headerbarModel = () => ({
252
253
  editor.e2ee?.encrypted || false,
253
254
  editor.e2ee?.password || "",
254
255
  onShareSuccess,
255
- editor.app.settings
256
+ editor.app.settings,
257
+ editor.app.apiConnectors.contacts,
258
+ editor.app.apiConnectors.document
256
259
  )
257
260
  shareDialog.init()
258
261
  },
@@ -343,7 +346,10 @@ export const headerbarModel = () => ({
343
346
  getExportDoc(editor),
344
347
  db.bibDB,
345
348
  db.imageDB,
346
- editor.user
349
+ editor.user,
350
+ null,
351
+ null,
352
+ editor.app.apiConnectors.documentImport
347
353
  )
348
354
  copier
349
355
  .init()
@@ -368,6 +374,7 @@ export const headerbarModel = () => ({
368
374
  action: (editor: Editor) => {
369
375
  const db = getDB(editor)
370
376
  new ExportFidusFile(
377
+ editor.app,
371
378
  getExportDoc(editor),
372
379
  db.bibDB,
373
380
  db.imageDB,
@@ -787,6 +794,7 @@ export const headerbarModel = () => ({
787
794
  action: (editor: Editor) => {
788
795
  const db = getDB(editor)
789
796
  new ExportFidusFile(
797
+ editor.app,
790
798
  getExportDoc(editor),
791
799
  db.bibDB,
792
800
  db.imageDB,
@@ -1,4 +1,4 @@
1
- import {addAlert, postJson} from "fwtoolkit"
1
+ import {addAlert} from "fwtoolkit"
2
2
  import {receiveTransaction} from "prosemirror-collab"
3
3
  import {recreateTransform} from "../collab/merge/recreate_transform.js"
4
4
  import type {Editor} from "../types.js"
@@ -10,7 +10,7 @@ import type {Node} from "prosemirror-model"
10
10
  */
11
11
  export class NoCollabSave {
12
12
  editor: Editor
13
- saveInterval: ReturnType<typeof setInterval> | null
13
+ saveInterval: number | null
14
14
  savePromise: Promise<void> | null
15
15
  _beforeUnloadHandler: (() => void) | null
16
16
  _lastSaveTime: number
@@ -126,20 +126,19 @@ export class NoCollabSave {
126
126
  }
127
127
 
128
128
  try {
129
- const {json, status} = (await postJson(
130
- "/api/document/save/",
129
+ const {json, status} = await this.editor.app.apiConnectors.document.saveDocument(
131
130
  payload,
132
- {},
133
131
  {keepalive}
134
- )) as {json: Record<string, unknown>; status: number}
132
+ )
135
133
  if (status === 409) {
136
134
  if (!keepalive) {
137
135
  await this._handleVersionConflict()
138
136
  }
139
137
  return
140
138
  }
141
- if (json.version !== undefined) {
142
- this.editor.docInfo.version = json.version as number
139
+ const saveData = json as {version?: number}
140
+ if (saveData.version !== undefined) {
141
+ this.editor.docInfo.version = saveData.version
143
142
  }
144
143
  this.editor.docInfo.updated = new Date()
145
144
  this.editor.docInfo.confirmedDoc = this.editor.view.state.doc
@@ -167,15 +166,15 @@ export class NoCollabSave {
167
166
  payload.token = this.editor.docInfo.token
168
167
  }
169
168
  try {
170
- const {json} = (await postJson(
171
- "/api/document/get_doc_data/",
172
- payload
173
- )) as {json: Record<string, unknown>}
169
+ const {json} = await this.editor.app.apiConnectors.document.getDocumentData(
170
+ payload as {id: number; token?: string}
171
+ )
172
+ const data = json as {
173
+ doc: Record<string, unknown>
174
+ time: string
175
+ }
174
176
  const serverDoc = this.editor.schema.nodeFromJSON(
175
- (json.doc as Record<string, unknown>).content as Record<
176
- string,
177
- unknown
178
- >
177
+ (data.doc.content as Record<string, unknown>) || {}
179
178
  )
180
179
  const currentDoc = this.editor.view.state.doc
181
180
  const confirmedDoc = this.editor.docInfo.confirmedDoc as Node
@@ -203,18 +202,17 @@ export class NoCollabSave {
203
202
 
204
203
  // Update metadata from server
205
204
  ;(this.editor.mod.db?.bibDB as {setDB(value: unknown): void}).setDB(
206
- (json.doc as Record<string, unknown>).bibliography
205
+ data.doc.bibliography
207
206
  )
208
207
  ;(this.editor.mod.db?.imageDB as {setDB(value: unknown): void}).setDB(
209
- (json.doc as Record<string, unknown>).images
208
+ data.doc.images
210
209
  )
211
210
  ;(this.editor.mod.comments as any).store.loadComments(
212
- (json.doc as Record<string, unknown>).comments
211
+ data.doc.comments
213
212
  )
214
- this.editor.docInfo.version = (json.doc as Record<string, unknown>)
215
- .v as number
213
+ this.editor.docInfo.version = data.doc.v as number
216
214
  this.editor.docInfo.confirmedDoc = this.editor.view.state.doc
217
- this.editor.docInfo.updated = new Date(json.time as string)
215
+ this.editor.docInfo.updated = new Date(data.time)
218
216
  ;(this.editor.mod.footnotes as any).fnEditor.renderAllFootnotes()
219
217
 
220
218
  // Retry save with the merged document
@@ -156,8 +156,8 @@ export function buildBibliographyList(editor: Editor): BibliographyEntry[] {
156
156
  if (editor.mod?.db?.bibDB?.db) {
157
157
  addEntries(editor.mod.db.bibDB.db as Record<number, any>, "doc")
158
158
  }
159
- if ((editor.app as any).bibDB?.db) {
160
- addEntries((editor.app as any).bibDB.db as Record<number, any>, "user")
159
+ if (editor.app.bibDB?.db) {
160
+ addEntries(editor.app.bibDB.db as Record<string, any>, "user")
161
161
  }
162
162
 
163
163
  return entries
@@ -243,7 +243,7 @@ export const settingsPlugin = (options: SettingsOptions) => {
243
243
  )
244
244
  setDocTitle(
245
245
  view.state.doc.firstChild?.textContent || "",
246
- options.editor.app as any
246
+ options.editor.app
247
247
  )
248
248
  }
249
249
  }
package/src/types.ts CHANGED
@@ -14,13 +14,15 @@ import type {EditorView} from "prosemirror-view"
14
14
  import type {
15
15
  BibDB,
16
16
  BibDBEntries,
17
+ BibDBEntry,
17
18
  CommentData,
18
19
  CSL,
19
20
  ImageDB,
20
21
  ImageDBEntries
21
22
  } from "@fiduswriter/document"
23
+ import type {ImageApi} from "@fiduswriter/image-manager"
22
24
 
23
- export type {BibDB, BibDBEntries, CommentData, CSL, ImageDB, ImageDBEntries}
25
+ export type {BibDB, BibDBEntries, BibDBEntry, CommentData, CSL, ImageDB, ImageDBEntries}
24
26
 
25
27
  /** Image database interface used by the editor (document and user DBs). */
26
28
  export interface EditorImageDB extends ImageDB {
@@ -28,16 +30,104 @@ export interface EditorImageDB extends ImageDB {
28
30
  setImage(id: number, imageData: Record<string, unknown>): void
29
31
  }
30
32
 
33
+ /** Bibliography database interface used by the editor. */
34
+ export interface EditorBibDB {
35
+ db: Record<string, BibDBEntry>
36
+ }
37
+
38
+ /** API connector for document-level operations used by the editor. */
39
+ export interface EditorDocumentApi {
40
+ createDocument(
41
+ data: Record<string, unknown>
42
+ ): Promise<{json: unknown; status: number}>
43
+ getWebSocketBase(
44
+ data: {id: number; token?: string}
45
+ ): Promise<{json: unknown; status: number}>
46
+ getDocumentStyles(
47
+ data: {id: number; token?: string}
48
+ ): Promise<{json: unknown; status: number}>
49
+ getDocumentData(
50
+ data: {id: number; token?: string; v?: number}
51
+ ): Promise<{json: unknown; status: number}>
52
+ saveDocument(
53
+ data: Record<string, unknown>,
54
+ options?: {keepalive?: boolean}
55
+ ): Promise<{json: unknown; status: number}>
56
+ commentNotify(data: Record<string, unknown>): Promise<unknown>
57
+ requestAccess(
58
+ data: {document_id: number; rights: string}
59
+ ): Promise<{json: unknown; status: number}>
60
+ validateShareToken(
61
+ token: string
62
+ ): Promise<{json: unknown; status: number}>
63
+ listShareTokens(document_id: number): Promise<{json: unknown; status: number}>
64
+ createShareToken(
65
+ data: Record<string, unknown>
66
+ ): Promise<{json: unknown; status: number}>
67
+ revokeShareToken(token_id: number): Promise<{json: unknown; status: number}>
68
+ getAccessRights(
69
+ data: {document_ids: number[]}
70
+ ): Promise<{json: unknown; status: number}>
71
+ saveAccessRights(data: {
72
+ document_ids: number[]
73
+ access_rights: unknown[]
74
+ }): Promise<unknown>
75
+ saveE2EEImage(
76
+ data: Record<string, unknown>,
77
+ files?: Record<string, unknown>
78
+ ): Promise<{json: unknown; status: number}>
79
+ deleteE2EEImage(data: {doc_id: number; image_id: number}): Promise<unknown>
80
+ uploadRevision(
81
+ data: {note: string; document_id: number},
82
+ files: Record<string, unknown>
83
+ ): Promise<unknown>
84
+ getTemplateForDoc(
85
+ id: number | string,
86
+ token: string | false
87
+ ): Promise<{json: unknown; status: number}>
88
+ }
89
+
90
+ /** API connector for contact operations used by the editor. */
91
+ export interface EditorContactsApi {
92
+ add(data: {user_string: string}): Promise<{json: unknown; status: number}>
93
+ }
94
+
95
+ /** API connector for document import/copy operations used by the editor. */
96
+ export interface EditorDocumentImportApi {
97
+ createDoc(
98
+ data: Record<string, unknown>,
99
+ files?: Record<string, unknown>
100
+ ): Promise<{json: unknown; status: number}>
101
+ saveImage(
102
+ data: Record<string, unknown>,
103
+ files: Record<string, unknown>
104
+ ): Promise<{json: unknown; status: number}>
105
+ saveE2EEImage(
106
+ data: Record<string, unknown>,
107
+ files: Record<string, unknown>
108
+ ): Promise<{json: unknown; status: number}>
109
+ saveDocument(
110
+ data: Record<string, unknown>
111
+ ): Promise<{json: unknown; status: number}>
112
+ }
113
+
31
114
  /** Minimal app interface — only the fields the Editor actually uses. */
32
115
  export interface EditorApp {
33
116
  routes: Record<string, {app: string; [key: string]: unknown}>
34
117
  goTo: (url: string) => void
35
118
  settings: {APPS: string[]; [key: string]: unknown}
36
119
  menuPlugins?: Array<[string, Record<string, {new (...args: unknown[]): {init(): void}}>]>
37
- name?: string
120
+ name: string
38
121
  isOffline(): boolean
39
122
  csl: CSL
123
+ bibDB?: EditorBibDB
40
124
  imageDB: EditorImageDB
125
+ apiConnectors: {
126
+ document: EditorDocumentApi
127
+ documentImport: EditorDocumentImportApi
128
+ image: ImageApi
129
+ contacts: EditorContactsApi
130
+ }
41
131
  }
42
132
 
43
133
  /** Document access role constants. */