Skip to content

Commit

Permalink
Merge branch 'release-0.6.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
n1mmy committed May 15, 2013
2 parents bfe4b72 + 546f4e5 commit a33fcf6
Show file tree
Hide file tree
Showing 113 changed files with 2,906 additions and 1,211 deletions.
55 changes: 55 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,61 @@
## vNEXT


## v0.6.3

* Add new `check` package for ensuring that a value matches a required
type and structure. This is used to validate untrusted input from the
client. See http://docs.meteor.com/#match for details.

* Use Websockets by default on supported browsers. This reduces latency
and eliminates the constant network spinner on iOS devices.

* With `autopublish` on, publish many useful fields on `Meteor.users`.

* Files in the `client/compatibility/` subdirectory of a Meteor app do
not get wrapped in a new variable scope. This is useful for
third-party libraries which expect `var` statements at the outermost
level to be global.

* Add synthetic `tap` event for use on touch enabled devices. This is a
replacement for `click` that fires immediately.

* When using the `http` package synchronously on the server, errors
are thrown rather than passed in `result.error`

* The `manager` option to the `Meteor.Collection` constructor is now called
`connection`. The old name still works for now. #987

* The `localstorage-polyfill` smart package has been replaced by a
`localstorage` package, which defines a `Meteor._localStorage` API instead of
trying to replace the DOM `window.localStorage` facility. (Now, apps can use
the existence of `window.localStorage` to detect if the full localStorage API
is supported.) #979

* Upgrade MongoDB from 2.2.1 to 2.4.3.

* Upgrade CoffeeScript from 1.5.0 to 1.6.2. #972

* Faster reconnects when regaining connectivity. #696

* `Email.send` has a new `headers` option to set arbitrary headers. #963

* Cursor transform functions on the server no longer are required to return
objects with correct `_id` fields. #974

* Rework `observe()` callback ordering in minimongo to improve fiber
safety on the server. This makes subscriptions on server to server DDP
more usable.

* Use binary search in minimongo when updating ordered queries. #969

* Fix EJSON base64 decoding bug. #1001

* Support `appcache` on Chromium. #958

Patches contributed by GitHub users awwx, jagill, spang, and timhaines.


## v0.6.2.1

* When authenticating with GitHub, include a user agent string. This
Expand Down
2 changes: 1 addition & 1 deletion docs/.meteor/release
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.6.2.1
0.6.3
159 changes: 136 additions & 23 deletions docs/client/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ <h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>

// publish dependent documents and simulate joins
Meteor.publish("roomAndMessages", function (roomId) {
check(roomId, String);
return [
Rooms.find({_id: roomId}, {fields: {secretInfo: 0}}),
Messages.find({roomId: roomId})
Expand All @@ -98,6 +99,7 @@ <h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
check(roomId, String);
var count = 0;
var initializing = true;
var handle = Messages.find({roomId: roomId}).observeChanges({
Expand Down Expand Up @@ -242,6 +244,8 @@ <h2 id="methods_header"><span>Methods</span></h2>

Meteor.methods({
foo: function (arg1, arg2) {
check(arg1, String);
check(arg2, [Number]);
// .. do stuff ..
if (you want to throw an error)
throw new Meteor.Error(404, "Can't find my pants");
Expand Down Expand Up @@ -318,11 +322,14 @@ <h2 id="methods_header"><span>Methods</span></h2>

{{> api_box error}}

If you want to return an error from a method, throw an exception.
Methods can throw any kind of exception. But `Meteor.Error` is the only
kind of error that a server will send to the client. If a method
function throws a different exception, then it will be mapped to
`Meteor.Error(500, "Internal server error")` on the wire.
If you want to return an error from a method, throw an exception. Methods can
throw any kind of exception. But `Meteor.Error` is the only kind of error that
a server will send to the client. If a method function throws a different
exception, then it will be mapped to a sanitized version on the
wire. Specifically, if the `sanitizedError` field on the thrown error is set to
a `Meteor.Error`, then that error will be sent to the client. Otherwise, if no
sanitized version is available, the client gets
`Meteor.Error(500, 'Internal server error')`.

{{> api_box meteor_call}}

Expand Down Expand Up @@ -1432,13 +1439,14 @@ <h2 id="accounts_api"><span>Accounts</span></h2>
{fields: {'other': 1, 'things': 1}});
});

If the `autopublish` package is installed, the `username` and `profile` fields
for all users are published to all clients. To publish specific fields from all
users:

Meteor.publish("allUserData", function () {
return Meteor.users.find({}, {fields: {'nested.things': 1}});
});
If the autopublish package is installed, information about all users
on the system is published to all clients. This includes `username`,
`profile`, and any fields in `services` that are meant to be public
(eg `services.facebook.id`,
`services.twitter.screenName`). Additionally, when using autopublish
more information is published for the currently logged in user,
including access tokens. This allows making API calls directly from
the client for services that allow this.

Users are by default allowed to specify their own `profile` field with
[`Accounts.createUser`](#accounts_createuser) and modify it with
Expand Down Expand Up @@ -2205,6 +2213,12 @@ <h2 id="template_inst"><span>Template instances</span></h2>
catching typing in text fields, while `keydown` and `keyup` can be
used for arrow keys or modifier keys.
{{/dtdd}}

{{#dtdd "<code>tap</code>"}} Tap on an element. On touch-enabled
devices, this is a replacement to `click` that fires immediately.
These events are synthesized from `touchmove` and `touchend`.
{{/dtdd}}

</dl>

Other DOM events are available as well, but for the events above,
Expand Down Expand Up @@ -2266,6 +2280,106 @@ <h2 id="template_inst"><span>Template instances</span></h2>

{{/api_box_inline}}

<h2 id="match"><span>Match</span></h2>

Meteor methods and publish functions take arbitrary [EJSON](#ejson) types as
arguments, but most arguments are expected to be of a particular type. Meteor's
`check` package is a lightweight library for checking that arguments and other
values are of the expected type. For example:

Meteor.publish("chats-in-room", function (roomId) {
// Make sure roomId is a string, not an arbitrary mongo selector object.
check(roomId, String);
return Chats.find({room: roomId});
});

Meteor.methods({addChat: function (roomId, message) {
check(roomId, String);
check(message, {
text: String,
timestamp: Date,
// Optional, but if present must be an array of strings.
tags: Match.Optional([String])
});

// ... do something with the message ...
}});

{{> api_box check}}

If the match fails, `check` throws a `Match.Error` describing how it failed. If
this error gets sent over the wire to the client, it will appear only as
`Meteor.Error(400, "Match Failed")`; the failure details will be written to the
server logs but not revealed to the client.

{{> api_box match_test}}

{{#api_box_inline matchpatterns}}

The following patterns can be used as pattern arguments to `check` and `Match.test`:


<dl>
{{#dtdd "<code>Match.Any</code>"}}
Matches any value.
{{/dtdd}}

{{#dtdd "<code>String</code>, <code>Number</code>, <code>Boolean</code>, <code>undefined</code>, <code>null</code>"}}
Matches a primitive of the given type.
{{/dtdd}}

{{#dtdd "<code>[<em>pattern</em>]</code>"}}
A one-element array matches an array of elements, each of which match
*pattern*. For example, `[Number]` matches a (possibly empty) array of numbers;
`[Match.Any]` matches any array.
{{/dtdd}}

{{#dtdd "<code>{<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...}</code>"}}
Matches an Object with the given keys, with values matching the given patterns.
If any *pattern* is a `Match.Optional`, that key does not need to exist
in the object. The value may not contain any keys not listed in the pattern.
The value must be a plain Object with no special prototype.
{{/dtdd}}

{{#dtdd "<code>Match.ObjectIncluding({<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...})</code>"}}
Matches an Object with the given keys; the value may also have other keys
with arbitrary values.
{{/dtdd}}

{{#dtdd "<code>Object</code>"}}
Matches any plain Object with any keys; equivalent to
`Match.ObjectIncluding({})`.
{{/dtdd}}

{{#dtdd "<code>Match.Optional(<em>pattern</em>)</code>"}}
Matches either `undefined` or something that matches *pattern*.
{{/dtdd}}

{{#dtdd "<code>Match.OneOf(<em>pattern1</em>, <em>pattern2</em>, ...)</code>"}}
Matches any value that matches at least one of the provided patterns.
{{/dtdd}}

{{#dtdd "Any constructor function (eg, <code>Date</code>)"}}
Matches any element that is an instance of that type.
{{/dtdd}}

{{#dtdd "<code>Match.Where(<em>condition</em>)</code>"}}
Calls the function *condition* with the value as the argument. If *condition*
returns true, this matches. If *condition* throws a `Match.Error` or returns
false, this fails. If *condition* throws any other error, that error is thrown
from the call to `check` or `Match.test`. Examples:

check(buffer, Match.Where(EJSON.isBinary));

NonEmptyString = Match.Where(function (x) {
check(x, String);
return x.length > 0;
}
check(arg, NonEmptyString);
{{/dtdd}}
</dl>

{{/api_box_inline}}

<h2 id="timers"><span>Timers</span></h2>

Expand Down Expand Up @@ -2718,12 +2832,13 @@ <h2 id="meteor_http"><span>Meteor.http</span></h2>
or `data` option is used to specify a body, in which case the
parameters will be appended to the URL instead.

The callback receives two arguments, `error` and `result`. The `error`
argument will contain an Error if the request fails in any way,
including a network error, time-out, or an HTTP status code in the 400
or 500 range. The result object is always
defined. When run in synchronous mode, the `result` is returned from the
function, and the `error` value is a stored as a property in `result`.
The callback receives two arguments, `error` and `result`. The
`error` argument will contain an Error if the request fails in any
way, including a network error, time-out, or an HTTP status code in
the 400 or 500 range. In case of a 4xx/5xx HTTP status code, the
`response` property on `error` matches the contents of the result
object. When run in synchronous mode, either `result` is returned
from the function, or `error` is thrown.

Contents of the result object:

Expand All @@ -2745,16 +2860,12 @@ <h2 id="meteor_http"><span>Meteor.http</span></h2>
<span class="type">Object</span></dt>
<dd>A dictionary of HTTP headers from the response.</dd>

<dt><span class="name">error</span>
<span class="type">Error</span></dt>
<dd>Error object if the request failed. Matches the <code>error</code> callback parameter.</dd>


</dl>

Example server method:

Meteor.methods({checkTwitter: function (userId) {
check(userId, String);
this.unblock();
var result = Meteor.http.call("GET", "http://api.twitter.com/xyz",
{params: {user: userId}});
Expand Down Expand Up @@ -2811,6 +2922,8 @@ <h2 id="email"><span>Email</span></h2>
// In your server code: define a method that the client can call
Meteor.methods({
sendEmail: function (to, from, subject, text) {
check([to, from, subject, text], [String]);

// Let other method calls from the same client start running,
// without waiting for the email sending to complete.
this.unblock();
Expand Down
53 changes: 50 additions & 3 deletions docs/client/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ Template.api.subscription_error = {
id: "publish_error",
name: "<i>this</i>.error(error)",
locus: "Server",
descr: ["Call inside the publish function. Stops this client's subscription, triggering a call on the client to the `onError` callback passed to [`Meteor.subscribe`](#meteor_subscribe), if any. If `error` is not a [`Meteor.Error`](#meteor_error), it will be mapped to `Meteor.Error(500, \"Internal server error\")`."]
descr: ["Call inside the publish function. Stops this client's subscription, triggering a call on the client to the `onError` callback passed to [`Meteor.subscribe`](#meteor_subscribe), if any. If `error` is not a [`Meteor.Error`](#meteor_error), it will be [sanitized](#meteor_error)."]
};

Template.api.subscription_stop = {
Expand Down Expand Up @@ -472,9 +472,9 @@ Template.api.meteor_collection = {
descr: "The name of the collection. If null, creates an unmanaged (unsynchronized) local collection."}
],
options: [
{name: "manager",
{name: "connection",
type: "Object",
descr: "The Meteor connection that will manage this collection, defaults to `Meteor` if null. Unmanaged (`name` is null) collections cannot specify a manager."
descr: "The Meteor connection that will manage this collection, defaults to `Meteor` if null. Unmanaged (`name` is null) collections cannot specify a connection."
},
{name: "idGeneration",
type: "String",
Expand Down Expand Up @@ -1357,6 +1357,49 @@ Template.api.accounts_emailTemplates = {



Template.api.check = {
id: "check",
name: "check(value, pattern)",
locus: "Anywhere",
descr: ["Checks that a value matches a [pattern](#matchpatterns). If the value does not match the pattern, throws a `Match.Error`."],
args: [
{
name: "value",
type: "Any",
descr: "The value to check"
},
{
name: "pattern",
type: "Match pattern",
descr: "The [pattern](#matchpatterns) to match `value` against"
}
]
};

Template.api.match_test = {
id: "match_test",
name: "Match.test(value, pattern)",
locus: "Anywhere",
descr: ["Returns true if the value matches the [pattern](#matchpatterns)."],
args: [
{
name: "value",
type: "Any",
descr: "The value to check"
},
{
name: "pattern",
type: "Match pattern",
descr: "The [pattern](#matchpatterns) to match `value` against"
}
]
};

Template.api.matchpatterns = {
id: "matchpatterns",
name: "Match patterns"
};

Template.api.setTimeout = {
id: "meteor_settimeout",
name: "Meteor.setTimeout(func, delay)",
Expand Down Expand Up @@ -1761,6 +1804,10 @@ Template.api.email_send = {
{name: "html",
type: "String",
descr: rfc('mail body (HTML)')
},
{name: "headers",
type: "Object",
descr: rfc('custom headers (dictionary)')
}
]
};
Loading

0 comments on commit a33fcf6

Please sign in to comment.