web 3d图形渲染器
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.

255 lines
6.6 KiB

  1. 'use strict'
  2. const util = require('util')
  3. const fs = require('fs')
  4. const index = require('./lib/entry-index')
  5. const memo = require('./lib/memoization')
  6. const read = require('./lib/content/read')
  7. const Minipass = require('minipass')
  8. const Collect = require('minipass-collect')
  9. const Pipeline = require('minipass-pipeline')
  10. const writeFile = util.promisify(fs.writeFile)
  11. module.exports = function get (cache, key, opts) {
  12. return getData(false, cache, key, opts)
  13. }
  14. module.exports.byDigest = function getByDigest (cache, digest, opts) {
  15. return getData(true, cache, digest, opts)
  16. }
  17. function getData (byDigest, cache, key, opts = {}) {
  18. const { integrity, memoize, size } = opts
  19. const memoized = byDigest
  20. ? memo.get.byDigest(cache, key, opts)
  21. : memo.get(cache, key, opts)
  22. if (memoized && memoize !== false) {
  23. return Promise.resolve(
  24. byDigest
  25. ? memoized
  26. : {
  27. metadata: memoized.entry.metadata,
  28. data: memoized.data,
  29. integrity: memoized.entry.integrity,
  30. size: memoized.entry.size
  31. }
  32. )
  33. }
  34. return (byDigest ? Promise.resolve(null) : index.find(cache, key, opts)).then(
  35. (entry) => {
  36. if (!entry && !byDigest) {
  37. throw new index.NotFoundError(cache, key)
  38. }
  39. return read(cache, byDigest ? key : entry.integrity, {
  40. integrity,
  41. size
  42. })
  43. .then((data) =>
  44. byDigest
  45. ? data
  46. : {
  47. data,
  48. metadata: entry.metadata,
  49. size: entry.size,
  50. integrity: entry.integrity
  51. }
  52. )
  53. .then((res) => {
  54. if (memoize && byDigest) {
  55. memo.put.byDigest(cache, key, res, opts)
  56. } else if (memoize) {
  57. memo.put(cache, entry, res.data, opts)
  58. }
  59. return res
  60. })
  61. }
  62. )
  63. }
  64. module.exports.sync = function get (cache, key, opts) {
  65. return getDataSync(false, cache, key, opts)
  66. }
  67. module.exports.sync.byDigest = function getByDigest (cache, digest, opts) {
  68. return getDataSync(true, cache, digest, opts)
  69. }
  70. function getDataSync (byDigest, cache, key, opts = {}) {
  71. const { integrity, memoize, size } = opts
  72. const memoized = byDigest
  73. ? memo.get.byDigest(cache, key, opts)
  74. : memo.get(cache, key, opts)
  75. if (memoized && memoize !== false) {
  76. return byDigest
  77. ? memoized
  78. : {
  79. metadata: memoized.entry.metadata,
  80. data: memoized.data,
  81. integrity: memoized.entry.integrity,
  82. size: memoized.entry.size
  83. }
  84. }
  85. const entry = !byDigest && index.find.sync(cache, key, opts)
  86. if (!entry && !byDigest) {
  87. throw new index.NotFoundError(cache, key)
  88. }
  89. const data = read.sync(cache, byDigest ? key : entry.integrity, {
  90. integrity: integrity,
  91. size: size
  92. })
  93. const res = byDigest
  94. ? data
  95. : {
  96. metadata: entry.metadata,
  97. data: data,
  98. size: entry.size,
  99. integrity: entry.integrity
  100. }
  101. if (memoize && byDigest) {
  102. memo.put.byDigest(cache, key, res, opts)
  103. } else if (memoize) {
  104. memo.put(cache, entry, res.data, opts)
  105. }
  106. return res
  107. }
  108. module.exports.stream = getStream
  109. const getMemoizedStream = (memoized) => {
  110. const stream = new Minipass()
  111. stream.on('newListener', function (ev, cb) {
  112. ev === 'metadata' && cb(memoized.entry.metadata)
  113. ev === 'integrity' && cb(memoized.entry.integrity)
  114. ev === 'size' && cb(memoized.entry.size)
  115. })
  116. stream.end(memoized.data)
  117. return stream
  118. }
  119. function getStream (cache, key, opts = {}) {
  120. const { memoize, size } = opts
  121. const memoized = memo.get(cache, key, opts)
  122. if (memoized && memoize !== false) {
  123. return getMemoizedStream(memoized)
  124. }
  125. const stream = new Pipeline()
  126. index
  127. .find(cache, key)
  128. .then((entry) => {
  129. if (!entry) {
  130. throw new index.NotFoundError(cache, key)
  131. }
  132. stream.emit('metadata', entry.metadata)
  133. stream.emit('integrity', entry.integrity)
  134. stream.emit('size', entry.size)
  135. stream.on('newListener', function (ev, cb) {
  136. ev === 'metadata' && cb(entry.metadata)
  137. ev === 'integrity' && cb(entry.integrity)
  138. ev === 'size' && cb(entry.size)
  139. })
  140. const src = read.readStream(
  141. cache,
  142. entry.integrity,
  143. { ...opts, size: typeof size !== 'number' ? entry.size : size }
  144. )
  145. if (memoize) {
  146. const memoStream = new Collect.PassThrough()
  147. memoStream.on('collect', data => memo.put(cache, entry, data, opts))
  148. stream.unshift(memoStream)
  149. }
  150. stream.unshift(src)
  151. })
  152. .catch((err) => stream.emit('error', err))
  153. return stream
  154. }
  155. module.exports.stream.byDigest = getStreamDigest
  156. function getStreamDigest (cache, integrity, opts = {}) {
  157. const { memoize } = opts
  158. const memoized = memo.get.byDigest(cache, integrity, opts)
  159. if (memoized && memoize !== false) {
  160. const stream = new Minipass()
  161. stream.end(memoized)
  162. return stream
  163. } else {
  164. const stream = read.readStream(cache, integrity, opts)
  165. if (!memoize) {
  166. return stream
  167. }
  168. const memoStream = new Collect.PassThrough()
  169. memoStream.on('collect', data => memo.put.byDigest(
  170. cache,
  171. integrity,
  172. data,
  173. opts
  174. ))
  175. return new Pipeline(stream, memoStream)
  176. }
  177. }
  178. module.exports.info = info
  179. function info (cache, key, opts = {}) {
  180. const { memoize } = opts
  181. const memoized = memo.get(cache, key, opts)
  182. if (memoized && memoize !== false) {
  183. return Promise.resolve(memoized.entry)
  184. } else {
  185. return index.find(cache, key)
  186. }
  187. }
  188. module.exports.hasContent = read.hasContent
  189. function cp (cache, key, dest, opts) {
  190. return copy(false, cache, key, dest, opts)
  191. }
  192. module.exports.copy = cp
  193. function cpDigest (cache, digest, dest, opts) {
  194. return copy(true, cache, digest, dest, opts)
  195. }
  196. module.exports.copy.byDigest = cpDigest
  197. function copy (byDigest, cache, key, dest, opts = {}) {
  198. if (read.copy) {
  199. return (byDigest
  200. ? Promise.resolve(null)
  201. : index.find(cache, key, opts)
  202. ).then((entry) => {
  203. if (!entry && !byDigest) {
  204. throw new index.NotFoundError(cache, key)
  205. }
  206. return read
  207. .copy(cache, byDigest ? key : entry.integrity, dest, opts)
  208. .then(() => {
  209. return byDigest
  210. ? key
  211. : {
  212. metadata: entry.metadata,
  213. size: entry.size,
  214. integrity: entry.integrity
  215. }
  216. })
  217. })
  218. }
  219. return getData(byDigest, cache, key, opts).then((res) => {
  220. return writeFile(dest, byDigest ? res : res.data).then(() => {
  221. return byDigest
  222. ? key
  223. : {
  224. metadata: res.metadata,
  225. size: res.size,
  226. integrity: res.integrity
  227. }
  228. })
  229. })
  230. }