This repository has been archived by the owner on Mar 14, 2019. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 237
/
common.js
163 lines (138 loc) · 6.56 KB
/
common.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
*
* @constructor
* @param {string} name A name for the collection
* @param {Object} options
* @param {FS.StorageAdapter[]} options.stores An array of stores in which files should be saved. At least one is required.
* @param {Object} [options.filter] Filter definitions
* @param {Number} [options.chunkSize=2MB] Override the chunk size in bytes for uploads
* @param {Function} [options.uploader] A function to pass FS.File instances after inserting, which will begin uploading them. By default, `FS.HTTP.uploadQueue.uploadFile` is used if the `cfs-upload-http` package is present, or `FS.DDP.uploadQueue.uploadFile` is used if the `cfs-upload-ddp` package is present. You can override with your own, or set to `null` to prevent automatic uploading.
* @returns {undefined}
*/
FS.Collection = function(name, options) {
var self = this;
self.storesLookup = {};
self.primaryStore = {};
self.options = {
filter: null, //optional
stores: [], //required
chunkSize: null
};
// Define a default uploader based on which upload packages are present,
// preferring HTTP. You may override with your own function or
// set to null to skip automatic uploading of data after file insert/update.
if (FS.HTTP && FS.HTTP.uploadQueue) {
self.options.uploader = FS.HTTP.uploadQueue.uploadFile;
} else if (FS.DDP && FS.DDP.uploadQueue) {
self.options.uploader = FS.DDP.uploadQueue.uploadFile;
}
// Extend and overwrite options
FS.Utility.extend(self.options, options || {});
// Set the FS.Collection name
self.name = name;
// Make sure at least one store has been supplied.
// Usually the stores aren't used on the client, but we need them defined
// so that we can access their names and use the first one as the default.
if (FS.Utility.isEmpty(self.options.stores)) {
throw new Error("You must specify at least one store. Please consult the documentation.");
}
FS.Utility.each(self.options.stores, function(store, i) {
// Set the primary store
if (i === 0) {
self.primaryStore = store;
}
// Check for duplicate naming
if (typeof self.storesLookup[store.name] !== 'undefined') {
throw new Error('FS.Collection store names must be uniq, duplicate found: ' + store.name);
}
// Set the lookup
self.storesLookup[store.name] = store;
if (Meteor.isServer) {
// Emit events based on store events
store.on('stored', function (storeName, fileObj) {
// This is weird, but currently there is a bug where each store will emit the
// events for all other stores, too, so we need to make sure that this event
// is truly for this store.
if (storeName !== store.name)
return;
// When a file is successfully stored into the store, we emit a "stored" event on the FS.Collection only if the file belongs to this collection
if (fileObj.collectionName === name) {
var emitted = self.emit('stored', fileObj, store.name);
if (FS.debug && !emitted) {
console.log(fileObj.name({store: store.name}) + ' was successfully saved to the ' + store.name + ' store. You are seeing this informational message because you enabled debugging and you have not defined any listeners for the "stored" event on the ' + name + ' collection.');
}
}
fileObj.emit('stored', store.name);
});
store.on('error', function (storeName, error, fileObj) {
// This is weird, but currently there is a bug where each store will emit the
// events for all other stores, too, so we need to make sure that this event
// is truly for this store.
if (storeName !== store.name)
return;
// When a file has an error while being stored into the temp store, we emit an "error" event on the FS.Collection only if the file belongs to this collection
if (fileObj.collectionName === name) {
error = new Error('Error storing file to the ' + store.name + ' store: ' + error.message);
var emitted = self.emit('error', error, fileObj, store.name);
if (FS.debug && !emitted) {
console.log(error.message);
}
}
fileObj.emit('error', store.name);
});
}
});
var _filesOptions = {
transform: function(doc) {
// This should keep the filerecord in the file object updated in reactive
// context
var result = new FS.File(doc, true);
result.collectionName = name;
return result;
}
};
// Create the 'cfs.' ++ ".filerecord" and use fsFile
var collectionName = 'cfs.' + name + '.filerecord';
self.files = new Mongo.Collection(collectionName, _filesOptions);
// For storing custom allow/deny functions
self._validators = {
download: {allow: [], deny: []}
};
// Set up filters
// XXX Should we deprecate the filter option now that this is done with a separate pkg, or just keep it?
if (self.filters) {
self.filters(self.options.filter);
}
// Save the collection reference (we want it without the 'cfs.' prefix and '.filerecord' suffix)
FS._collections[name] = this;
// Set up observers
Meteor.isServer && FS.FileWorker && FS.FileWorker.observe(this);
// Emit "removed" event on collection
self.files.find().observe({
removed: function(fileObj) {
self.emit('removed', fileObj);
}
});
// Emit events based on TempStore events
if (FS.TempStore) {
FS.TempStore.on('stored', function (fileObj, result) {
// When a file is successfully stored into the temp store, we emit an "uploaded" event on the FS.Collection only if the file belongs to this collection
if (fileObj.collectionName === name) {
var emitted = self.emit('uploaded', fileObj);
if (FS.debug && !emitted) {
console.log(fileObj.name() + ' was successfully uploaded. You are seeing this informational message because you enabled debugging and you have not defined any listeners for the "uploaded" event on the ' + name + ' collection.');
}
}
});
FS.TempStore.on('error', function (error, fileObj) {
// When a file has an error while being stored into the temp store, we emit an "error" event on the FS.Collection only if the file belongs to this collection
if (fileObj.collectionName === name) {
self.emit('error', new Error('Error storing uploaded file to TempStore: ' + error.message), fileObj);
}
});
} else if (Meteor.isServer) {
throw new Error("FS.Collection constructor: FS.TempStore must be defined before constructing any FS.Collections.")
}
};
// An FS.Collection can emit events
FS.Collection.prototype = new EventEmitter();