mongoose-gridfs
Advanced tools
Comparing version 0.3.1 to 0.3.2
'use strict'; | ||
//dependencies | ||
var path = require('path'); | ||
var storage = require(path.join(__dirname, 'lib', 'storage')); | ||
const path = require('path'); | ||
const storage = require(path.join(__dirname, 'lib', 'storage')); | ||
//export gridfs storage | ||
module.exports = storage; |
'use strict'; | ||
//dependencies | ||
var _ = require('lodash'); | ||
var mongoose = require('mongoose'); | ||
var Schema = mongoose.Schema; | ||
var Mixed = Schema.Types.Mixed; | ||
var WRITABLES = ['_id', 'filename', 'contentType', 'aliases', 'metadata']; | ||
const _ = require('lodash'); | ||
const mongoose = require('mongoose'); | ||
const Schema = mongoose.Schema; | ||
const Mixed = Schema.Types.Mixed; | ||
const WRITABLES = ['_id', 'filename', 'contentType', 'aliases', 'metadata']; | ||
@@ -15,212 +15,212 @@ /** | ||
*/ | ||
module.exports = function(gridFSStorage) { | ||
//prepare collection | ||
var collection = [gridFSStorage.options.collection, 'files'].join('.'); | ||
var model = gridFSStorage.options.model; | ||
module.exports = function (gridFSStorage) { | ||
//prepare collection | ||
const collection = [gridFSStorage.options.collection, 'files'].join('.'); | ||
const model = gridFSStorage.options.model; | ||
var GridFSSchema = new Schema({ | ||
length: { | ||
type: Number | ||
}, | ||
chunkSize: { | ||
type: Number | ||
}, | ||
uploadDate: { | ||
type: Date | ||
}, | ||
md5: { | ||
type: String | ||
}, | ||
filename: { | ||
type: String | ||
}, | ||
contentType: { | ||
type: String | ||
}, | ||
aliases: [{ | ||
type: String | ||
}], | ||
metadata: { | ||
type: Mixed | ||
}, | ||
}, { | ||
collection: collection | ||
}); | ||
const GridFSSchema = new Schema({ | ||
length: { | ||
type: Number | ||
}, | ||
chunkSize: { | ||
type: Number | ||
}, | ||
uploadDate: { | ||
type: Date | ||
}, | ||
md5: { | ||
type: String | ||
}, | ||
filename: { | ||
type: String | ||
}, | ||
contentType: { | ||
type: String | ||
}, | ||
aliases: [{ | ||
type: String | ||
}], | ||
metadata: { | ||
type: Mixed | ||
}, | ||
}, { | ||
collection: collection | ||
}); | ||
//attach GridFSStorage instance | ||
GridFSSchema.statics.gridfs = gridFSStorage; | ||
//attach GridFSStorage instance | ||
GridFSSchema.statics.gridfs = gridFSStorage; | ||
//instance methods | ||
//instance methods | ||
/** | ||
* @function | ||
* @name write | ||
* @param {stream.Readable} stream readable stream | ||
* @param {Function} [done] a callback to invoke in success or error | ||
* @private | ||
* @example | ||
* var attachment = new Attachment({filename:<filename>}); | ||
* attachment.write(<readableStream>, function(error,createdAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.methods.write = function(stream, done) { | ||
//obtain writable file details | ||
var fileDetails = _.pick(this.toObject(), WRITABLES); | ||
/** | ||
* @function | ||
* @name write | ||
* @param {stream.Readable} stream readable stream | ||
* @param {Function} [done] a callback to invoke in success or error | ||
* @private | ||
* @example | ||
* const attachment = new Attachment({filename:<filename>}); | ||
* attachment.write(<readableStream>, function(error,createdAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.methods.write = function (stream, done) { | ||
//obtain writable file details | ||
const fileDetails = _.pick(this.toObject(), WRITABLES); | ||
//grab gridfs | ||
var gridfs = mongoose.model(model).gridfs; | ||
//grab gridfs | ||
const gridfs = mongoose.model(model).gridfs; | ||
//stream file to gridfs | ||
gridfs.write(fileDetails, stream, function(error, createdFile) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
//read file details | ||
mongoose.model(model).findById(createdFile._id, done); | ||
} | ||
}); | ||
}; | ||
//stream file to gridfs | ||
gridfs.write(fileDetails, stream, function (error, createdFile) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
//read file details | ||
mongoose.model(model).findById(createdFile._id, done); | ||
} | ||
}); | ||
}; | ||
/** | ||
* @function | ||
* @name read | ||
* @param {Function} [done] a callback to invoke on success or error | ||
* @return {stream.Readable} | ||
* @private | ||
* @example | ||
* Attachment.findById(<objectid>).exec(function(error, attachment){ | ||
* attachment.read(function(error, fileContent){ | ||
* ... | ||
* }); | ||
* }); | ||
* | ||
* or for larger file size use stream | ||
* | ||
* Attachment.findById(<objectid>).exec(function(error, attachment){ | ||
* var stream = attachment.read(); | ||
* stream.on('error', fn); | ||
* stream.on('data', fn); | ||
* stream.on('close', fn); | ||
* }); | ||
*/ | ||
GridFSSchema.methods.read = function(done) { | ||
//grab gridfs | ||
var gridfs = mongoose.model(model).gridfs; | ||
/** | ||
* @function | ||
* @name read | ||
* @param {Function} [done] a callback to invoke on success or error | ||
* @return {stream.Readable} | ||
* @private | ||
* @example | ||
* Attachment.findById(<objectid>).exec(function(error, attachment){ | ||
* attachment.read(function(error, fileContent){ | ||
* ... | ||
* }); | ||
* }); | ||
* | ||
* or for larger file size use stream | ||
* | ||
* Attachment.findById(<objectid>).exec(function(error, attachment){ | ||
* const stream = attachment.read(); | ||
* stream.on('error', fn); | ||
* stream.on('data', fn); | ||
* stream.on('close', fn); | ||
* }); | ||
*/ | ||
GridFSSchema.methods.read = function (done) { | ||
//grab gridfs | ||
const gridfs = mongoose.model(model).gridfs; | ||
//stream file out of gridfs | ||
return gridfs.readById(this._id, done); | ||
}; | ||
//stream file out of gridfs | ||
return gridfs.readById(this._id, done); | ||
}; | ||
/** | ||
* @function | ||
* @name unlink | ||
* @description remove file from gridfs and file collection | ||
* @param {Function} done a callback to invoke on success or error | ||
* @private | ||
* @return {Model} mongoose model instance | ||
* @example | ||
* attachment.unlink(function(error, unlinkedAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.methods.unlink = function(done) { | ||
//grab gridfs | ||
var gridfs = mongoose.model(model).gridfs; | ||
/** | ||
* @function | ||
* @name unlink | ||
* @description remove file from gridfs and file collection | ||
* @param {Function} done a callback to invoke on success or error | ||
* @private | ||
* @return {Model} mongoose model instance | ||
* @example | ||
* attachment.unlink(function(error, unlinkedAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.methods.unlink = function (done) { | ||
//grab gridfs | ||
const gridfs = mongoose.model(model).gridfs; | ||
//obtain file details | ||
mongoose.model(model).findById(this._id, function(error, fileDetails) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
//remove file from gridfs | ||
gridfs.unlinkById(fileDetails._id, function(_error /*, id*/ ) { | ||
done(_error, fileDetails); | ||
}); | ||
} | ||
//obtain file details | ||
mongoose.model(model).findById(this._id, function (error, fileDetails) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
//remove file from gridfs | ||
gridfs.unlinkById(fileDetails._id, function (_error /*, id*/ ) { | ||
done(_error, fileDetails); | ||
}); | ||
}; | ||
} | ||
}); | ||
}; | ||
//static methods | ||
//static methods | ||
/** | ||
* @function | ||
* @name write | ||
* @param {Object} fileDetails details of the file | ||
* @param {stream.Readable} stream readable stream | ||
* @param {Function} [done] a callback to invoke in success or error | ||
* @public | ||
* @example | ||
* Attachment.write({filename:<filename>}, <readableStream>, function(error, createdAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.statics.write = function(fileDetails, stream, done) { | ||
var $new = new this(fileDetails); | ||
$new.write(stream, done); | ||
}; | ||
/** | ||
* @function | ||
* @name write | ||
* @param {Object} fileDetails details of the file | ||
* @param {stream.Readable} stream readable stream | ||
* @param {Function} [done] a callback to invoke in success or error | ||
* @public | ||
* @example | ||
* Attachment.write({filename:<filename>}, <readableStream>, function(error, createdAttachment){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.statics.write = function (fileDetails, stream, done) { | ||
const $new = new this(fileDetails); | ||
$new.write(stream, done); | ||
}; | ||
/** | ||
* @function | ||
* @name readById | ||
* @param {ObjectId} id valid object id | ||
* @param {Function} done a callback to invoke on success or error | ||
* @return {stream.Readable} | ||
* @public | ||
* @example | ||
* Attachment.readById(<objectid>,function(error, fileContent){ | ||
* ... | ||
* }); | ||
* | ||
* or for larger file size | ||
* | ||
* var stream = Attachment.readById(<id>); | ||
*/ | ||
GridFSSchema.statics.readById = function(id, done) { | ||
return this.gridfs.readById(id, done); | ||
}; | ||
/** | ||
* @function | ||
* @name readById | ||
* @param {ObjectId} id valid object id | ||
* @param {Function} done a callback to invoke on success or error | ||
* @return {stream.Readable} | ||
* @public | ||
* @example | ||
* Attachment.readById(<objectid>,function(error, fileContent){ | ||
* ... | ||
* }); | ||
* | ||
* or for larger file size | ||
* | ||
* const stream = Attachment.readById(<id>); | ||
*/ | ||
GridFSSchema.statics.readById = function (id, done) { | ||
return this.gridfs.readById(id, done); | ||
}; | ||
/** | ||
* @function | ||
* @name unlinkById | ||
* @description remove a file from gridfs using specified objectid | ||
* @param {ObjectId} id valid object id | ||
* @param {Function} done a callback to invoke on success or error | ||
* @public | ||
* @example | ||
* Attachment.unlinkById(<id>, function(error, unlinkedFileDetails){ | ||
* ... | ||
* }); | ||
* | ||
* or | ||
* | ||
* Attachment.unlink(<id>, function(error, unlinkedFileDetails){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.statics.unlinkById = | ||
GridFSSchema.statics.unlink = function(id, done) { | ||
this.findById(id).exec(function (error, foundInstance) { | ||
if (error) { | ||
return done(error); | ||
} | ||
/** | ||
* @function | ||
* @name unlinkById | ||
* @description remove a file from gridfs using specified objectid | ||
* @param {ObjectId} id valid object id | ||
* @param {Function} done a callback to invoke on success or error | ||
* @public | ||
* @example | ||
* Attachment.unlinkById(<id>, function(error, unlinkedFileDetails){ | ||
* ... | ||
* }); | ||
* | ||
* or | ||
* | ||
* Attachment.unlink(<id>, function(error, unlinkedFileDetails){ | ||
* ... | ||
* }); | ||
*/ | ||
GridFSSchema.statics.unlinkById = | ||
GridFSSchema.statics.unlink = function (id, done) { | ||
this.findById(id).exec(function (error, foundInstance) { | ||
if (error) { | ||
return done(error); | ||
} | ||
if (!foundInstance) { | ||
return done(new Error('not found')); | ||
} | ||
if (!foundInstance) { | ||
return done(new Error('not found')); | ||
} | ||
foundInstance.unlink(done); | ||
}); | ||
}; | ||
foundInstance.unlink(done); | ||
}); | ||
}; | ||
//return grifs schema | ||
return GridFSSchema; | ||
//return grifs schema | ||
return GridFSSchema; | ||
}; |
'use strict'; | ||
//dependencies | ||
var path = require('path'); | ||
var _ = require('lodash'); | ||
var mongoose = require('mongoose'); | ||
var Grid = require('gridfs-stream'); | ||
var read = require('stream-read'); | ||
const path = require('path'); | ||
const _ = require('lodash'); | ||
const mongoose = require('mongoose'); | ||
const Grid = require('gridfs-stream'); | ||
const read = require('stream-read'); | ||
Grid.mongo = mongoose.mongo; | ||
var schema = require(path.join(__dirname, 'schema')); | ||
const schema = require(path.join(__dirname, 'schema')); | ||
@@ -20,17 +20,17 @@ /** | ||
function GridFSStorage(options) { | ||
//normalize options | ||
this.options = _.merge({}, { | ||
model: 'File', | ||
collection: 'fs', | ||
mongooseConnection: null | ||
}, options); | ||
//normalize options | ||
this.options = _.merge({}, { | ||
model: 'File', | ||
collection: 'fs', | ||
mongooseConnection: null | ||
}, options); | ||
//get either option connection or mongoose connection | ||
var conn = this.options.mongooseConnection || mongoose.connection; | ||
//get either option connection or mongoose connection | ||
const conn = this.options.mongooseConnection || mongoose.connection; | ||
//Check if mongoose is connected. | ||
if(conn.readyState !== 1) { | ||
throw new Error('Mongoose is not connected'); | ||
} | ||
this.storage = new Grid(conn.db); | ||
//Check if mongoose is connected. | ||
if (conn.readyState !== 1) { | ||
throw new Error('Mongoose is not connected'); | ||
} | ||
this.storage = new Grid(conn.db); | ||
} | ||
@@ -46,5 +46,5 @@ | ||
Object.defineProperty(GridFSStorage.prototype, 'collection', { | ||
get: function() { | ||
return this.storage.collection(this.options.collection); | ||
} | ||
get: function () { | ||
return this.storage.collection(this.options.collection); | ||
} | ||
}); | ||
@@ -58,18 +58,19 @@ | ||
Object.defineProperty(GridFSStorage.prototype, 'model', { | ||
get: function() { | ||
var model; | ||
get: function () { | ||
let model; | ||
try { | ||
//obtain model if already exists | ||
model = mongoose.model(this.options.model); | ||
} catch (e) { | ||
//build schema | ||
var _schema = schema(this); | ||
//compile model otherwise | ||
model = mongoose.model(this.options.model, _schema); | ||
} | ||
try { | ||
//obtain model if already exists | ||
model = mongoose.model(this.options.model); | ||
} catch (e) { | ||
//build schema | ||
const _schema = schema(this); | ||
//export model | ||
return model; | ||
//compile model otherwise | ||
model = mongoose.model(this.options.model, _schema); | ||
} | ||
//export model | ||
return model; | ||
} | ||
}); | ||
@@ -83,9 +84,9 @@ | ||
Object.defineProperty(GridFSStorage.prototype, 'schema', { | ||
get: function() { | ||
//build schema | ||
var _schema = schema(this); | ||
get: function () { | ||
//build schema | ||
const _schema = schema(this); | ||
//export mongoose compactible schema | ||
return _schema; | ||
} | ||
//export mongoose compactible schema | ||
return _schema; | ||
} | ||
}); | ||
@@ -108,51 +109,51 @@ | ||
GridFSStorage.prototype.write = | ||
GridFSStorage.prototype.save = | ||
GridFSStorage.prototype.create = | ||
GridFSStorage.prototype.save = | ||
GridFSStorage.prototype.create = | ||
function write(fileDetails, stream, done) { | ||
//ensure filename | ||
if (!fileDetails || !fileDetails.filename) { | ||
throw new Error('Missing filename'); | ||
} | ||
function write(fileDetails, stream, done) { | ||
//ensure filename | ||
if (!fileDetails || !fileDetails.filename) { | ||
throw new Error('Missing filename'); | ||
} | ||
//obtain collection | ||
var collection = this.options.collection; | ||
//obtain collection | ||
const collection = this.options.collection; | ||
//prepare file details | ||
fileDetails = _.merge({ | ||
root: collection, //root collection to use with GridFS for storage | ||
}, fileDetails); | ||
//prepare file details | ||
fileDetails = _.merge({ | ||
root: collection, //root collection to use with GridFS for storage | ||
}, fileDetails); | ||
//normalize contentType field | ||
if (fileDetails.contentType) { | ||
// jshint camelcase:false | ||
fileDetails.content_type = fileDetails.contentType; | ||
// jshint camelcase:true | ||
delete fileDetails.contentType; | ||
} | ||
//normalize contentType field | ||
if (fileDetails.contentType) { | ||
// jshint camelcase:false | ||
fileDetails.content_type = fileDetails.contentType; | ||
// jshint camelcase:true | ||
delete fileDetails.contentType; | ||
} | ||
// initialize gridfs write stream | ||
var writestream = this.storage.createWriteStream(fileDetails); | ||
// initialize gridfs write stream | ||
const writestream = this.storage.createWriteStream(fileDetails); | ||
//stream file into mongodb GridFS | ||
stream.pipe(writestream); | ||
//stream file into mongodb GridFS | ||
stream.pipe(writestream); | ||
//work on the stream | ||
if (done && _.isFunction(done)) { | ||
//handle errors | ||
writestream.on('error', function(error) { | ||
done(error); | ||
}); | ||
//work on the stream | ||
if (done && _.isFunction(done)) { | ||
//handle errors | ||
writestream.on('error', function (error) { | ||
done(error); | ||
}); | ||
//finalize write | ||
writestream.on('close', function(file) { | ||
done(null, file); | ||
}); | ||
} | ||
//return writestream | ||
else { | ||
return writestream; | ||
} | ||
//finalize write | ||
writestream.on('close', function (file) { | ||
done(null, file); | ||
}); | ||
} | ||
//return writestream | ||
else { | ||
return writestream; | ||
} | ||
}; | ||
}; | ||
@@ -172,14 +173,14 @@ | ||
GridFSStorage.prototype.unlink = function unlink(options, done) { | ||
//obtain collection | ||
var collection = this.options.collection; | ||
//obtain collection | ||
const collection = this.options.collection; | ||
//prepare file remove options | ||
options = _.merge({ | ||
root: collection | ||
}, options); | ||
//prepare file remove options | ||
options = _.merge({ | ||
root: collection | ||
}, options); | ||
//TODO ensure filename or _id exists in options | ||
//TODO ensure filename or _id exists in options | ||
//remove file from storage | ||
this.storage.remove(options, done); | ||
//remove file from storage | ||
this.storage.remove(options, done); | ||
@@ -196,12 +197,12 @@ }; | ||
GridFSStorage.prototype.unlinkById = function unlinkById(id, done) { | ||
//remove file from storage | ||
this.unlink({ | ||
_id: id | ||
}, function(error) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
done(null, id); | ||
} | ||
}); | ||
//remove file from storage | ||
this.unlink({ | ||
_id: id | ||
}, function (error) { | ||
if (error) { | ||
done(error); | ||
} else { | ||
done(null, id); | ||
} | ||
}); | ||
}; | ||
@@ -222,13 +223,13 @@ | ||
*/ | ||
GridFSStorage.prototype.findOne = function(options, done) { | ||
//obtain collection | ||
var collection = this.options.collection; | ||
GridFSStorage.prototype.findOne = function (options, done) { | ||
//obtain collection | ||
const collection = this.options.collection; | ||
//prepare file remove options | ||
options = _.merge({ | ||
root: collection | ||
}, options); | ||
//prepare file remove options | ||
options = _.merge({ | ||
root: collection | ||
}, options); | ||
//find one existing file | ||
this.storage.findOne(options, done); | ||
//find one existing file | ||
this.storage.findOne(options, done); | ||
}; | ||
@@ -246,6 +247,6 @@ | ||
*/ | ||
GridFSStorage.prototype.findById = function(id, done) { | ||
this.findOne({ | ||
_id: id | ||
}, done); | ||
GridFSStorage.prototype.findById = function (id, done) { | ||
this.findOne({ | ||
_id: id | ||
}, done); | ||
}; | ||
@@ -267,3 +268,3 @@ | ||
* @example | ||
* var readableStream = gridfs.readById(50e03d29edfdc00d34000001); | ||
* const readableStream = gridfs.readById(50e03d29edfdc00d34000001); | ||
* | ||
@@ -274,24 +275,24 @@ * gridfs.readById(50e03d29edfdc00d34000001, function(error,content){ | ||
*/ | ||
GridFSStorage.prototype.readById = function(id, done) { | ||
//obtain collection | ||
var collection = this.options.collection; | ||
GridFSStorage.prototype.readById = function (id, done) { | ||
//obtain collection | ||
const collection = this.options.collection; | ||
//prepare file remove options | ||
var options = { | ||
_id: id, | ||
root: collection | ||
}; | ||
//prepare file remove options | ||
const options = { | ||
_id: id, | ||
root: collection | ||
}; | ||
//create a readable stream for a specific file | ||
var stream = this.storage.createReadStream(options); | ||
//create a readable stream for a specific file | ||
const stream = this.storage.createReadStream(options); | ||
//pipe the whole stream into buffer if callback provided | ||
if (done && _.isFunction(done)) { | ||
read(stream, done); | ||
} | ||
//pipe the whole stream into buffer if callback provided | ||
if (done && _.isFunction(done)) { | ||
read(stream, done); | ||
} | ||
//return stream | ||
else { | ||
return stream; | ||
} | ||
//return stream | ||
else { | ||
return stream; | ||
} | ||
@@ -311,12 +312,12 @@ }; | ||
GridFSStorage.prototype._handleFile = function _handleFile(request, file, done) { | ||
//obtain file readable stream | ||
var stream = file.stream; | ||
//obtain file readable stream | ||
const stream = file.stream; | ||
//prepare file details | ||
var fileDetails = _.merge({}, { | ||
filename: file.originalname, | ||
contentType: file.mimetype | ||
}); | ||
//prepare file details | ||
const fileDetails = _.merge({}, { | ||
filename: file.originalname, | ||
contentType: file.mimetype | ||
}); | ||
this.write(fileDetails, stream, done); | ||
this.write(fileDetails, stream, done); | ||
}; | ||
@@ -333,10 +334,10 @@ | ||
GridFSStorage.prototype._removeFile = function _removeFile(request, file, done) { | ||
//remove file | ||
if (file._id) { | ||
this.removeById(file._id, done); | ||
} | ||
//no operation | ||
else { | ||
done(null, null); | ||
} | ||
//remove file | ||
if (file._id) { | ||
this.removeById(file._id, done); | ||
} | ||
//no operation | ||
else { | ||
done(null, null); | ||
} | ||
}; | ||
@@ -346,6 +347,6 @@ | ||
//exports GridFSStorage instance | ||
module.exports = function(options) { | ||
var gridfs = new GridFSStorage(options); | ||
gridfs.GridFSStorage = GridFSStorage; | ||
return gridfs; | ||
module.exports = function (options) { | ||
const gridfs = new GridFSStorage(options); | ||
gridfs.GridFSStorage = GridFSStorage; | ||
return gridfs; | ||
}; |
{ | ||
"name": "mongoose-gridfs", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"description": "mongoose gridfs on top of gridfs-stream", | ||
@@ -22,3 +22,5 @@ "main": "index.js", | ||
"filesystem", | ||
"mongo" | ||
"mongo", | ||
"file", | ||
"storage" | ||
], | ||
@@ -36,3 +38,3 @@ "author": "lykmapipo <lallyelias87@gmail.com>", | ||
"devDependencies": { | ||
"async": "^2.5.0", | ||
"async": "^2.6.0", | ||
"chai": "^4.1.2", | ||
@@ -48,3 +50,3 @@ "grunt": "^1.0.1", | ||
"mocha": "^4.0.1", | ||
"mongoose": "^4.12.4" | ||
"mongoose": "^4.13.4" | ||
}, | ||
@@ -51,0 +53,0 @@ "engines": { |
@@ -6,3 +6,3 @@ mongoose-gridfs | ||
mongoose gridfs on top of [gridfs-stream](https://github.com/aheckmann/gridfs-stream) | ||
mongoose [gridfs](https://docs.mongodb.com/manual/core/gridfs/) on top of [gridfs-stream](https://github.com/aheckmann/gridfs-stream) | ||
@@ -9,0 +9,0 @@ *Note!: Ensure mongoose connection before use* |
20315