DocstoreClient.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import {
  2. fetchNothing,
  3. fetchJson,
  4. fetchJsonWithResponse,
  5. } from '@overleaf/fetch-utils'
  6. import settings from '@overleaf/settings'
  7. import Persistor from '../../../../app/js/PersistorManager.js'
  8. let DocstoreClient
  9. async function streamToString(stream) {
  10. const chunks = []
  11. return await new Promise((resolve, reject) => {
  12. stream.on('data', chunk => chunks.push(chunk))
  13. stream.on('error', reject)
  14. stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
  15. })
  16. }
  17. async function getStringFromPersistor(persistor, bucket, key) {
  18. const stream = await persistor.getObjectStream(bucket, key, {})
  19. stream.resume()
  20. return await streamToString(stream)
  21. }
  22. export default DocstoreClient = {
  23. async createDoc(projectId, docId, lines, version, ranges) {
  24. return await DocstoreClient.updateDoc(
  25. projectId,
  26. docId,
  27. lines,
  28. version,
  29. ranges
  30. )
  31. },
  32. async getDoc(projectId, docId, qs = {}) {
  33. const url = new URL(
  34. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`
  35. )
  36. for (const [key, value] of Object.entries(qs)) {
  37. url.searchParams.append(key, value)
  38. }
  39. return await fetchJson(url)
  40. },
  41. async peekDoc(projectId, docId, qs = {}) {
  42. const url = new URL(
  43. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/peek`
  44. )
  45. for (const [key, value] of Object.entries(qs)) {
  46. url.searchParams.append(key, value)
  47. }
  48. const { response, json } = await fetchJsonWithResponse(url)
  49. return { res: response, doc: json }
  50. },
  51. async isDocDeleted(projectId, docId) {
  52. const { response, json } = await fetchJsonWithResponse(
  53. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/deleted`
  54. )
  55. return { res: response, body: json }
  56. },
  57. async getAllDocs(projectId) {
  58. return await fetchJson(
  59. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc`
  60. )
  61. },
  62. async getAllDeletedDocs(projectId, callback) {
  63. return await fetchJson(
  64. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc-deleted`
  65. )
  66. },
  67. async getAllRanges(projectId) {
  68. return await fetchJson(
  69. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/ranges`
  70. )
  71. },
  72. async getCommentThreadIds(projectId, callback) {
  73. return await fetchJson(
  74. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/comment-thread-ids`
  75. )
  76. },
  77. async getTrackedChangesUserIds(projectId) {
  78. return await fetchJson(
  79. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/tracked-changes-user-ids`
  80. )
  81. },
  82. async updateDoc(projectId, docId, lines, version, ranges) {
  83. const res = await fetchJson(
  84. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`,
  85. {
  86. method: 'POST',
  87. json: {
  88. lines,
  89. version,
  90. ranges,
  91. },
  92. }
  93. )
  94. return res
  95. },
  96. async deleteDoc(projectId, docId) {
  97. return await DocstoreClient.deleteDocWithDateAndName(
  98. projectId,
  99. docId,
  100. new Date(),
  101. 'main.tex'
  102. )
  103. },
  104. async deleteDocWithDate(projectId, docId, date) {
  105. return await DocstoreClient.deleteDocWithDateAndName(
  106. projectId,
  107. docId,
  108. date,
  109. 'main.tex'
  110. )
  111. },
  112. async deleteDocWithName(projectId, docId, name) {
  113. return await DocstoreClient.deleteDocWithDateAndName(
  114. projectId,
  115. docId,
  116. new Date(),
  117. name
  118. )
  119. },
  120. async deleteDocWithDateAndName(projectId, docId, deletedAt, name) {
  121. return await fetchNothing(
  122. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`,
  123. { method: 'PATCH', json: { name, deleted: true, deletedAt } }
  124. )
  125. },
  126. async archiveAllDoc(projectId) {
  127. return await fetchNothing(
  128. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/archive`,
  129. { method: 'POST' }
  130. )
  131. },
  132. async archiveDoc(projectId, docId) {
  133. return await fetchNothing(
  134. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/archive`,
  135. { method: 'POST' }
  136. )
  137. },
  138. async destroyAllDoc(projectId) {
  139. await fetchNothing(
  140. `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/destroy`,
  141. { method: 'POST' }
  142. )
  143. },
  144. async healthCheck() {
  145. return await fetchNothing(
  146. `http://127.0.0.1:${settings.internal.docstore.port}/health_check`
  147. )
  148. },
  149. async getS3Doc(projectId, docId) {
  150. const data = await getStringFromPersistor(
  151. Persistor,
  152. settings.docstore.bucket,
  153. `${projectId}/${docId}`
  154. )
  155. return JSON.parse(data)
  156. },
  157. }