Permalink
Browse files

Make autopublish into an empty package, detected via weak deps.

  • Loading branch information...
1 parent cbcafd0 commit fa2749813989275ebe42fa323fa76cc2ca158116 @glasser glasser committed Jul 24, 2013
@@ -312,13 +312,14 @@ Meteor.publish(null, function() {
// Accounts.addAutopublishFields Notably, this isn't implemented with
// multiple publishes since DDP only merges only across top-level
// fields, not subfields (such as 'services.facebook.accessToken')
-autopublishFields = {
+var autopublishFields = {
loggedInUser: ['profile', 'username', 'emails'],
otherUsers: ['profile', 'username']
};
// Add to the list of fields or subfields to be automatically
-// published if autopublish is on
+// published if autopublish is on. Must be called from top-level
+// code (ie, before Meteor.startup hooks run).
//
// @param opts {Object} with:
// - forLoggedInUser {Array} Array of fields published to the logged-in user
@@ -330,42 +331,45 @@ Accounts.addAutopublishFields = function(opts) {
autopublishFields.otherUsers, opts.forOtherUsers);
};
-Meteor.server.onAutopublish(function () {
- // ['profile', 'username'] -> {profile: 1, username: 1}
- var toFieldSelector = function(fields) {
- return _.object(_.map(fields, function(field) {
- return [field, 1];
- }));
- };
+if (Package.autopublish) {
+ // Use Meteor.startup to give other packages a chance to call
+ // addAutopublishFields.
+ Meteor.startup(function () {
+ // ['profile', 'username'] -> {profile: 1, username: 1}
+ var toFieldSelector = function(fields) {
+ return _.object(_.map(fields, function(field) {
+ return [field, 1];
+ }));
+ };
+
+ Meteor.server.publish(null, function () {
+ if (this.userId) {
+ return Meteor.users.find(
+ {_id: this.userId},
+ {fields: toFieldSelector(autopublishFields.loggedInUser)});
+ } else {
+ return null;
+ }
+ }, /*suppress autopublish warning*/{is_auto: true});
+
+ // XXX this publish is neither dedup-able nor is it optimized by our special
+ // treatment of queries on a specific _id. Therefore this will have O(n^2)
+ // run-time performance every time a user document is changed (eg someone
+ // logging in). If this is a problem, we can instead write a manual publish
+ // function which filters out fields based on 'this.userId'.
+ Meteor.server.publish(null, function () {
+ var selector;
+ if (this.userId)
+ selector = {_id: {$ne: this.userId}};
+ else
+ selector = {};
- Meteor.server.publish(null, function () {
- if (this.userId) {
return Meteor.users.find(
- {_id: this.userId},
- {fields: toFieldSelector(autopublishFields.loggedInUser)});
- } else {
- return null;
- }
- }, /*suppress autopublish warning*/{is_auto: true});
-
- // XXX this publish is neither dedup-able nor is it optimized by our
- // special treatment of queries on a specific _id. Therefore this
- // will have O(n^2) run-time performance every time a user document
- // is changed (eg someone logging in). If this is a problem, we can
- // instead write a manual publish function which filters out fields
- // based on 'this.userId'.
- Meteor.server.publish(null, function () {
- var selector;
- if (this.userId)
- selector = {_id: {$ne: this.userId}};
- else
- selector = {};
-
- return Meteor.users.find(
- selector,
- {fields: toFieldSelector(autopublishFields.otherUsers)});
- }, /*suppress autopublish warning*/{is_auto: true});
-});
+ selector,
+ {fields: toFieldSelector(autopublishFields.otherUsers)});
+ }, /*suppress autopublish warning*/{is_auto: true});
+ });
+}
// Publish all login service configuration fields other than secret.
Meteor.publish("meteor.loginServiceConfiguration", function () {
@@ -21,6 +21,10 @@ Package.on_use(function (api) {
// {{currentUser}}. If not, no biggie.
api.use('handlebars', 'client', {weak: true});
+ // Allow us to detect 'autopublish', and publish some Meteor.users fields if
+ // it's loaded.
+ api.use('autopublish', 'server', {weak: true});
+
api.exportSymbol('Accounts');
api.add_files('accounts_common.js', ['client', 'server']);
@@ -12,7 +12,6 @@ if (Meteor.isClient) {
Facebook.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
Accounts.addAutopublishFields({
// publish all fields including access token, which can legitimately
// be used from the client (if transmitted over ssl or on
@@ -12,7 +12,6 @@ if (Meteor.isClient) {
Github.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
Accounts.addAutopublishFields({
// not sure whether the github api can be used from the browser,
// thus not sure if we should be sending access tokens; but we do it
@@ -12,7 +12,6 @@ if (Meteor.isClient) {
Google.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
Accounts.addAutopublishFields({
forLoggedInUser: _.map(
// publish access token since it can be used from the client (if
@@ -12,14 +12,11 @@ if (Meteor.isClient) {
Meetup.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
Accounts.addAutopublishFields({
// publish all fields including access token, which can legitimately
// be used from the client (if transmitted over ssl or on
// localhost). http://www.meetup.com/meetup_api/auth/#oauth2implicit
forLoggedInUser: ['services.meetup'],
forOtherUsers: ['services.meetup.id']
});
-
-
}
@@ -12,7 +12,6 @@ if (Meteor.isClient) {
Twitter.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
var autopublishedFields = _.map(
// don't send access token. https://dev.twitter.com/discussions/5025
Twitter.whitelistedFields.concat(['id', 'screenName']),
@@ -12,12 +12,10 @@ if (Meteor.isClient) {
Weibo.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
-
Accounts.addAutopublishFields({
// publish all fields including access token, which can legitimately
// be used from the client (if transmitted over ssl or on localhost)
forLoggedInUser: ['services.weibo'],
forOtherUsers: ['services.weibo.screenName']
});
-
}
@@ -1 +0,0 @@
-Meteor.server.autopublish();
@@ -2,7 +2,5 @@ Package.describe({
summary: "Automatically publish the entire database to all clients"
});
-Package.on_use(function (api) {
- api.use('livedata', 'server');
- api.add_files("autopublish.js", "server");
-});
+// This package is empty; its presence is detected by livedata and
+// accounts-base.
@@ -906,8 +906,8 @@ _.extend(Connection.prototype, {
// Mark all named subscriptions which are ready (ie, we already called the
// ready callback) as needing to be revived.
- // XXX We should also block reconnect quiescence until autopublish is done
- // re-publishing to avoid flicker!
+ // XXX We should also block reconnect quiescence until unnamed subscriptions
+ // (eg, autopublish) are done re-publishing to avoid flicker!
self._subsBeingRevived = {};
_.each(self._subscriptions, function (sub, id) {
if (sub.ready)
@@ -1024,9 +1024,6 @@ Server = function () {
self.method_handlers = {};
- self.on_autopublish = []; // array of func if AP disabled, null if enabled
- self.warned_about_autopublish = false;
-
self.sessions = {}; // map from id to session
self.stream_server = new StreamServer;
@@ -1176,7 +1173,7 @@ _.extend(Server.prototype, {
return;
}
- if (!self.on_autopublish && !options.is_auto) {
+ if (Package.autopublish && !options.is_auto) {
// They have autopublish on, yet they're trying to manually
// picking stuff to publish. They probably should turn off
// autopublish. (This check isn't perfect -- if you create a
@@ -1307,25 +1304,6 @@ _.extend(Server.prototype, {
if (exception)
throw exception;
return result;
- },
-
- // A much more elegant way to do this would be: let any autopublish
- // provider (eg, mongo-livedata) declare a weak package dependency
- // on the autopublish package, then have that package simply set a
- // flag that eg the Collection constructor checks, and autopublishes
- // if necessary.
- autopublish: function () {
- var self = this;
- _.each(self.on_autopublish || [], function (f) { f(); });
- self.on_autopublish = null;
- },
-
- onAutopublish: function (f) {
- var self = this;
- if (self.on_autopublish)
- self.on_autopublish.push(f);
- else
- f();
}
});
@@ -19,6 +19,10 @@ Package.on_use(function (api) {
// Detect whether or not the user wants us to audit argument checks.
api.use(['audit-argument-checks'], 'server', {weak: true});
+ // Allow us to detect 'autopublish', so we can print a warning if the user
+ // runs Meteor.publish while it's loaded.
+ api.use('autopublish', 'server', {weak: true});
+
api.exportSymbol('DDP');
api.exportSymbol('DDPServer', 'server');
@@ -174,12 +174,12 @@ Meteor.Collection = function (name, options) {
self._defineMutationMethods();
// autopublish
- if (!options._preventAutopublish &&
- self._connection && self._connection.onAutopublish)
- self._connection.onAutopublish(function () {
- var handler = function () { return self.find(); };
- self._connection.publish(null, handler, {is_auto: true});
- });
+ if (Package.autopublish && !options._preventAutopublish && self._connection
+ && self._connection.publish) {
+ self._connection.publish(null, function () {
+ return self.find();
+ }, {is_auto: true});
+ }
};
///
@@ -20,8 +20,12 @@ Package.on_use(function (api) {
['client', 'server']);
api.use('check', ['client', 'server']);
+ // Allow us to detect 'insecure'.
api.use('insecure', {weak: true});
+ // Allow us to detect 'autopublish', and publish collections if it's loaded.
+ api.use('autopublish', 'server', {weak: true});
+
api.exportSymbol('_MongoLivedataTest', 'server');
api.add_files('mongo_driver.js', 'server');

0 comments on commit fa27498

Please sign in to comment.