index.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.GridFSBucket = void 0;
  4. const error_1 = require("../error");
  5. const mongo_types_1 = require("../mongo_types");
  6. const timeout_1 = require("../timeout");
  7. const utils_1 = require("../utils");
  8. const write_concern_1 = require("../write_concern");
  9. const download_1 = require("./download");
  10. const upload_1 = require("./upload");
  11. const DEFAULT_GRIDFS_BUCKET_OPTIONS = {
  12. bucketName: 'fs',
  13. chunkSizeBytes: 255 * 1024
  14. };
  15. /**
  16. * Constructor for a streaming GridFS interface
  17. * @public
  18. */
  19. class GridFSBucket extends mongo_types_1.TypedEventEmitter {
  20. constructor(db, options) {
  21. super();
  22. this.on('error', utils_1.noop);
  23. this.setMaxListeners(0);
  24. const privateOptions = (0, utils_1.resolveOptions)(db, {
  25. ...DEFAULT_GRIDFS_BUCKET_OPTIONS,
  26. ...options,
  27. writeConcern: write_concern_1.WriteConcern.fromOptions(options)
  28. });
  29. this.s = {
  30. db,
  31. options: privateOptions,
  32. _chunksCollection: db.collection(privateOptions.bucketName + '.chunks'),
  33. _filesCollection: db.collection(privateOptions.bucketName + '.files'),
  34. checkedIndexes: false,
  35. calledOpenUploadStream: false
  36. };
  37. }
  38. /**
  39. * Returns a writable stream (GridFSBucketWriteStream) for writing
  40. * buffers to GridFS. The stream's 'id' property contains the resulting
  41. * file's id.
  42. *
  43. * @param filename - The value of the 'filename' key in the files doc
  44. * @param options - Optional settings.
  45. */
  46. openUploadStream(filename, options) {
  47. return new upload_1.GridFSBucketWriteStream(this, filename, {
  48. timeoutMS: this.s.options.timeoutMS,
  49. ...options
  50. });
  51. }
  52. /**
  53. * Returns a writable stream (GridFSBucketWriteStream) for writing
  54. * buffers to GridFS for a custom file id. The stream's 'id' property contains the resulting
  55. * file's id.
  56. */
  57. openUploadStreamWithId(id, filename, options) {
  58. return new upload_1.GridFSBucketWriteStream(this, filename, {
  59. timeoutMS: this.s.options.timeoutMS,
  60. ...options,
  61. id
  62. });
  63. }
  64. /** Returns a readable stream (GridFSBucketReadStream) for streaming file data from GridFS. */
  65. openDownloadStream(id, options) {
  66. return new download_1.GridFSBucketReadStream(this.s._chunksCollection, this.s._filesCollection, this.s.options.readPreference, { _id: id }, { timeoutMS: this.s.options.timeoutMS, ...options });
  67. }
  68. /**
  69. * Deletes a file with the given id
  70. *
  71. * @param id - The id of the file doc
  72. */
  73. async delete(id, options) {
  74. const { timeoutMS } = (0, utils_1.resolveOptions)(this.s.db, options);
  75. let timeoutContext = undefined;
  76. if (timeoutMS) {
  77. timeoutContext = new timeout_1.CSOTTimeoutContext({
  78. timeoutMS,
  79. serverSelectionTimeoutMS: this.s.db.client.s.options.serverSelectionTimeoutMS
  80. });
  81. }
  82. const { deletedCount } = await this.s._filesCollection.deleteOne({ _id: id }, { timeoutMS: timeoutContext?.remainingTimeMS });
  83. const remainingTimeMS = timeoutContext?.remainingTimeMS;
  84. if (remainingTimeMS != null && remainingTimeMS <= 0)
  85. throw new error_1.MongoOperationTimeoutError(`Timed out after ${timeoutMS}ms`);
  86. // Delete orphaned chunks before returning FileNotFound
  87. await this.s._chunksCollection.deleteMany({ files_id: id }, { timeoutMS: remainingTimeMS });
  88. if (deletedCount === 0) {
  89. // TODO(NODE-3483): Replace with more appropriate error
  90. // Consider creating new error MongoGridFSFileNotFoundError
  91. throw new error_1.MongoRuntimeError(`File not found for id ${id}`);
  92. }
  93. }
  94. /** Convenience wrapper around find on the files collection */
  95. find(filter = {}, options = {}) {
  96. return this.s._filesCollection.find(filter, options);
  97. }
  98. /**
  99. * Returns a readable stream (GridFSBucketReadStream) for streaming the
  100. * file with the given name from GridFS. If there are multiple files with
  101. * the same name, this will stream the most recent file with the given name
  102. * (as determined by the `uploadDate` field). You can set the `revision`
  103. * option to change this behavior.
  104. */
  105. openDownloadStreamByName(filename, options) {
  106. let sort = { uploadDate: -1 };
  107. let skip = undefined;
  108. if (options && options.revision != null) {
  109. if (options.revision >= 0) {
  110. sort = { uploadDate: 1 };
  111. skip = options.revision;
  112. }
  113. else {
  114. skip = -options.revision - 1;
  115. }
  116. }
  117. return new download_1.GridFSBucketReadStream(this.s._chunksCollection, this.s._filesCollection, this.s.options.readPreference, { filename }, { timeoutMS: this.s.options.timeoutMS, ...options, sort, skip });
  118. }
  119. /**
  120. * Renames the file with the given _id to the given string
  121. *
  122. * @param id - the id of the file to rename
  123. * @param filename - new name for the file
  124. */
  125. async rename(id, filename, options) {
  126. const filter = { _id: id };
  127. const update = { $set: { filename } };
  128. const { matchedCount } = await this.s._filesCollection.updateOne(filter, update, options);
  129. if (matchedCount === 0) {
  130. throw new error_1.MongoRuntimeError(`File with id ${id} not found`);
  131. }
  132. }
  133. /** Removes this bucket's files collection, followed by its chunks collection. */
  134. async drop(options) {
  135. const { timeoutMS } = (0, utils_1.resolveOptions)(this.s.db, options);
  136. let timeoutContext = undefined;
  137. if (timeoutMS) {
  138. timeoutContext = new timeout_1.CSOTTimeoutContext({
  139. timeoutMS,
  140. serverSelectionTimeoutMS: this.s.db.client.s.options.serverSelectionTimeoutMS
  141. });
  142. }
  143. if (timeoutContext) {
  144. await this.s._filesCollection.drop({ timeoutMS: timeoutContext.remainingTimeMS });
  145. const remainingTimeMS = timeoutContext.getRemainingTimeMSOrThrow(`Timed out after ${timeoutMS}ms`);
  146. await this.s._chunksCollection.drop({ timeoutMS: remainingTimeMS });
  147. }
  148. else {
  149. await this.s._filesCollection.drop();
  150. await this.s._chunksCollection.drop();
  151. }
  152. }
  153. }
  154. exports.GridFSBucket = GridFSBucket;
  155. /**
  156. * When the first call to openUploadStream is made, the upload stream will
  157. * check to see if it needs to create the proper indexes on the chunks and
  158. * files collections. This event is fired either when 1) it determines that
  159. * no index creation is necessary, 2) when it successfully creates the
  160. * necessary indexes.
  161. * @event
  162. */
  163. GridFSBucket.INDEX = 'index';
  164. //# sourceMappingURL=index.js.map