Файловый менеджер ⚬ 文件管理器 ⚬ File manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.2KB

  1. // https://unpkg.com/isomorphic-git@1.7.2/http/web/index.js
  2. /**
  3. * @typedef {Object} GitProgressEvent
  4. * @property {string} phase
  5. * @property {number} loaded
  6. * @property {number} total
  7. */
  8. /**
  9. * @callback ProgressCallback
  10. * @param {GitProgressEvent} progress
  11. * @returns {void | Promise<void>}
  12. */
  13. /**
  14. * @typedef {Object} GitHttpRequest
  15. * @property {string} url - The URL to request
  16. * @property {string} [method='GET'] - The HTTP method to use
  17. * @property {Object<string, string>} [headers={}] - Headers to include in the HTTP request
  18. * @property {AsyncIterableIterator<Uint8Array>} [body] - An async iterator of Uint8Arrays that make up the body of POST requests
  19. * @property {ProgressCallback} [onProgress] - Reserved for future use (emitting `GitProgressEvent`s)
  20. * @property {object} [signal] - Reserved for future use (canceling a request)
  21. */
  22. /**
  23. * @typedef {Object} GitHttpResponse
  24. * @property {string} url - The final URL that was fetched after any redirects
  25. * @property {string} [method] - The HTTP method that was used
  26. * @property {Object<string, string>} [headers] - HTTP response headers
  27. * @property {AsyncIterableIterator<Uint8Array>} [body] - An async iterator of Uint8Arrays that make up the body of the response
  28. * @property {number} statusCode - The HTTP status code
  29. * @property {string} statusMessage - The HTTP status message
  30. */
  31. /**
  32. * @callback HttpFetch
  33. * @param {GitHttpRequest} request
  34. * @returns {Promise<GitHttpResponse>}
  35. */
  36. /**
  37. * @typedef {Object} HttpClient
  38. * @property {HttpFetch} request
  39. */
  40. // Convert a value to an Async Iterator
  41. // This will be easier with async generator functions.
  42. function fromValue(value) {
  43. let queue = [value];
  44. return {
  45. next() {
  46. return Promise.resolve({ done: queue.length === 0, value: queue.pop() })
  47. },
  48. return() {
  49. queue = [];
  50. return {}
  51. },
  52. [Symbol.asyncIterator]() {
  53. return this
  54. },
  55. }
  56. }
  57. function getIterator(iterable) {
  58. if (iterable[Symbol.asyncIterator]) {
  59. return iterable[Symbol.asyncIterator]()
  60. }
  61. if (iterable[Symbol.iterator]) {
  62. return iterable[Symbol.iterator]()
  63. }
  64. if (iterable.next) {
  65. return iterable
  66. }
  67. return fromValue(iterable)
  68. }
  69. // Currently 'for await' upsets my linters.
  70. async function forAwait(iterable, cb) {
  71. const iter = getIterator(iterable);
  72. while (true) {
  73. const { value, done } = await iter.next();
  74. if (value) await cb(value);
  75. if (done) break
  76. }
  77. if (iter.return) iter.return();
  78. }
  79. async function collect(iterable) {
  80. let size = 0;
  81. const buffers = [];
  82. // This will be easier once `for await ... of` loops are available.
  83. await forAwait(iterable, value => {
  84. buffers.push(value);
  85. size += value.byteLength;
  86. });
  87. const result = new Uint8Array(size);
  88. let nextIndex = 0;
  89. for (const buffer of buffers) {
  90. result.set(buffer, nextIndex);
  91. nextIndex += buffer.byteLength;
  92. }
  93. return result
  94. }
  95. // Convert a web ReadableStream (not Node stream!) to an Async Iterator
  96. // adapted from https://jakearchibald.com/2017/async-iterators-and-generators/
  97. function fromStream(stream) {
  98. // Use native async iteration if it's available.
  99. if (stream[Symbol.asyncIterator]) return stream
  100. const reader = stream.getReader();
  101. return {
  102. next() {
  103. return reader.read()
  104. },
  105. return() {
  106. reader.releaseLock();
  107. return {}
  108. },
  109. [Symbol.asyncIterator]() {
  110. return this
  111. },
  112. }
  113. }
  114. /* eslint-env browser */
  115. /**
  116. * HttpClient
  117. *
  118. * @param {GitHttpRequest} request
  119. * @returns {Promise<GitHttpResponse>}
  120. */
  121. async function request({
  122. onProgress,
  123. url,
  124. method = 'GET',
  125. headers = {},
  126. body,
  127. }) {
  128. // streaming uploads aren't possible yet in the browser
  129. if (body) {
  130. body = await collect(body);
  131. }
  132. const res = await fetch(url, { method, headers, body });
  133. const iter =
  134. res.body && res.body.getReader
  135. ? fromStream(res.body)
  136. : [new Uint8Array(await res.arrayBuffer())];
  137. // convert Header object to ordinary JSON
  138. headers = {};
  139. for (const [key, value] of res.headers.entries()) {
  140. headers[key] = value;
  141. }
  142. return {
  143. url: res.url,
  144. method: res.method,
  145. statusCode: res.status,
  146. statusMessage: res.statusText,
  147. body: iter,
  148. headers: headers,
  149. }
  150. }
  151. var index = { request };
  152. //export default index;
  153. //export { request };