├── .gitignore ├── .gitmodules ├── .nvmrc ├── Contributing.md ├── README.md ├── _config.yml ├── assets ├── api-box.html └── theme-colors.less ├── conversion ├── convert-toc-to-redirects.js └── old-toc.js ├── data └── .gitkeep ├── jsdoc ├── docdata-jsdoc-template │ └── publish.js ├── jsdoc-conf.json └── jsdoc.sh ├── long-form ├── README.md ├── alternate-windows-installation.md ├── appcache.md ├── breaking-changes-1.2.md ├── build-machines.md ├── building-cross-platform-packages.md ├── editing-tools-for-windows-development.md ├── file-change-watcher-efficiency.md ├── oplog-observe-driver.md ├── package-server-api.md └── tracker-manual.md ├── netlify.toml ├── package-lock.json ├── package.json ├── renovate.json ├── scripts ├── api-box.js ├── changelog.js ├── dl.js ├── nameToId.js ├── old-redirects.js └── parseTagOptions.js └── source ├── api ├── accounts-multi.md ├── accounts.md ├── assets.md ├── blaze.md ├── check.md ├── collections.md ├── connections.md ├── core.md ├── ejson.md ├── email.md ├── http.md ├── methods.md ├── mobile-config.md ├── packagejs.md ├── passwords.md ├── pubsub.md ├── reactive-dict.md ├── reactive-var.md ├── session.md ├── templates.md ├── timers.md └── tracker.md ├── changelog.md ├── commandline.md ├── environment-variables.md ├── index.md ├── packages ├── accounts-ui.md ├── appcache.md ├── audit-argument-checks.md ├── autoupdate.md ├── browser-policy.md ├── bundle-visualizer.md ├── coffeescript.md ├── dynamic-import.md ├── ecmascript.md ├── less.md ├── markdown.md ├── modules.md ├── oauth-encryption.md ├── random.md ├── server-render.md ├── spacebars.md ├── underscore.md └── webapp.md └── windows.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | db.json 4 | *.log 5 | node_modules/ 6 | public/ 7 | .deploy*/ 8 | data/ 9 | _multiconfig.yml 10 | .idea/ 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "themes/meteor"] 2 | path = themes/meteor 3 | url = https://github.com/meteor/hexo-theme-meteor.git 4 | [submodule "code"] 5 | path = code 6 | url = https://github.com/meteor/meteor.git 7 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 8.11.2 2 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | ## Contributing to Meteor Documentation 2 | 3 | Thanks for considering contributing to Meteor documentation. We really appreciate your assistance. 4 | 5 | The simplest way to contribute to a project is to open an issue or pull request (PR) on the relevant GitHub issue tracker: 6 | 7 | - Meteor API Docs: https://github.com/meteor/docs/issues 8 | - Meteor Guide: https://github.com/meteor/guide/issues 9 | - Meteor Tutorials : https://github.com/meteor/tutorials/issues 10 | 11 | ## Issues 12 | 13 | If you see a problem with a particular piece of content, you can hit the "Edit on GitHub" button to jump straight to the file on GitHub. If you are keen, you can submit a Pull Request immediately to fix the problem; alternatively, hit the "Issues" button at the top to open an issue reporting the problem. 14 | 15 | ## Pull Requests 16 | 17 | We welcome changes both large and small. 18 | 19 | ### Small changes 20 | 21 | Smaller changes such as fixing typos and small edits for clarity will typically be merged quickly, and are very helpful! Contributions like this enable us to maintain our high quality of documentation 22 | 23 | ### Larger changes 24 | 25 | Larger changes like section rewrites, new sections, and even entirely new articles are also encouraged! In fact, some large parts of our documentation have been contributed by community members. However, more controversial larger changes may require some discussion and buy-in from the documentation maintainers before being accepted—if you are unsure, it may be sensible to open an issue discussing the changes before making them. 26 | 27 | ## Becoming a documentation maintainer 28 | 29 | If you make larger contributions to the above properties, you may be invited to become a community documentation maintainer. This is both a recognition of your contribution (thank you!) and the granting of commit rights on the above repositories. 30 | 31 | With those rights you can merge the Pull Requests of others as well as commit directly to the repository (and in some cases deploy the site). So please use your discretion and be courteous. 32 | 33 | ### Current community maintainers 34 | 35 | - [Loren Sands-Ramshaw](http://github.com/lorensr) 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Meteor API Documentation - http://docs.meteor.com 2 | 3 | This is a [hexo](https://hexo.io) static site used to generate the [Meteor API Docs](http://docs.meteor.com). 4 | 5 | ## Contributing 6 | 7 | We'd love your contributions! Please send us Pull Requests or open issues on [github](https://github.com/meteor/docs). Also, read the [contribution guidelines](https://github.com/meteor/docs/blob/master/Contributing.md). 8 | 9 | If you are making a larger contribution, you may need to run the site locally: 10 | 11 | ### Running locally 12 | 13 | #### Submodules 14 | 15 | This repo has two submodules, one the theme, the other full Meteor repository. 16 | 17 | We have the Meteor repo to generate the `data.js` file (see below). 18 | 19 | After cloning, or updating the repo, it makes sense to run 20 | 21 | ``` 22 | git submodule update --init 23 | ``` 24 | 25 | Generally you should not commit changes to the submodules, unless you know what you are doing. 26 | 27 | #### Generating `data.js` 28 | 29 | To generate the api boxes, the site uses a file `data/data.js` which is generated from the js docs in the [Meteor source code](https://github.com/meteor/meteor). This will automatically happen whenever you start your local hexo server. 30 | 31 | #### Starting hexo 32 | 33 | Ensure you've run `npm install`. Then simply `npm start`. 34 | -------------------------------------------------------------------------------- /assets/api-box.html: -------------------------------------------------------------------------------- 1 |
64 | -------------------------------------------------------------------------------- /assets/theme-colors.less: -------------------------------------------------------------------------------- 1 | // Haven't made any changes as we want the default Meteor colors 2 | -------------------------------------------------------------------------------- /conversion/convert-toc-to-redirects.js: -------------------------------------------------------------------------------- 1 | // This file was used to convert the old docs table of contents 2 | // (a slightly modified version of it in old-toc.js) 3 | // to a mapping of redirects hash -> page it lives in. 4 | // 5 | // I ran this script to generate the redirects.js file at scripts/redirects.js 6 | // 7 | // Keeping it in source control just in case we need to redo it for some reason 8 | 9 | var _ = require('underscore'); 10 | var nameToId = require('../scripts/nameToId.js'); 11 | var idToName = {}; 12 | _.each(nameToId, function(id, name) { 13 | idToName[id] = name; 14 | }); 15 | var oldToc = require('./old-toc.js'); 16 | 17 | // these point to X.html 18 | var idsToPagesWithNoHash = {}; 19 | // these point to X.html#name where name is generated from id below 20 | var idsToPages = {}; 21 | 22 | runList = (dir, as) => { 23 | _.each(as, a => { 24 | var aId; 25 | if (!_.isArray(a) && _.isObject(a)){ 26 | aId = a.id; 27 | a = a.name; 28 | } 29 | 30 | if (_.isString(a)) { 31 | var name = a.toLowerCase(); 32 | currFile = `${dir}/${name}.html`; 33 | idsToPagesWithNoHash[name] = currFile; 34 | if (aId) { 35 | idsToPagesWithNoHash[aId] = currFile; 36 | } 37 | } else { 38 | addIds = (ids) => { 39 | _.each(ids, (id) => { 40 | if (_.isArray(id)) { 41 | addIds(id); 42 | } else { 43 | if (_.isObject(id)) { 44 | if (id.type === 'spacer') { 45 | return; 46 | } 47 | id = id.id || id.name; 48 | } 49 | var ourId = (nameToId[id] || id).toLowerCase(); 50 | idsToPages[ourId] = currFile; 51 | } 52 | }); 53 | } 54 | addIds(a); 55 | } 56 | }); 57 | }; 58 | 59 | runList('api', oldToc[2]); 60 | 61 | _.each(oldToc[4][0], id => { 62 | var name = id.name || id; 63 | idsToPagesWithNoHash[name] = 'packages/' + name + '.html'; 64 | }); 65 | 66 | _.each(oldToc[6][0], id => { 67 | idsToPages[id.replace(/\s|\-|\//g, '')] = 'commandline.html'; 68 | }); 69 | 70 | _.each(_.union(_.keys(idsToPages), _.keys(idsToPagesWithNoHash)), id => { 71 | if (idsToPages[id]) { 72 | var page = idsToPages[id]; 73 | var name = idToName[id] || id; 74 | var nameId = name.replace(/[.#]/g, "-"); 75 | console.log(` /#/full/${id}: '${page}#${nameId}'`); 76 | } else { 77 | var page = idsToPagesWithNoHash[id]; 78 | console.log(` /#/full/${id}: '${page}'`); 79 | } 80 | }); 81 | -------------------------------------------------------------------------------- /data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jankapunkt/docs/478c820bc0fb4ad7d716c4358b8088ac03360ddf/data/.gitkeep -------------------------------------------------------------------------------- /jsdoc/docdata-jsdoc-template/publish.js: -------------------------------------------------------------------------------- 1 | /*global require: true */ 2 | (function () { 3 | 'use strict'; 4 | 5 | // This file receives data from JSDoc via the `publish` exported function, 6 | // and converts it into JSON that is written to a file. 7 | 8 | var fs = require('jsdoc/fs'); 9 | var helper = require('jsdoc/util/templateHelper'); 10 | 11 | var _ = require("underscore"); 12 | var stringify = require("canonical-json"); 13 | 14 | // This is the big map of name -> data that we'll write to a file. 15 | var dataContents = {}; 16 | // List of just the names, which we'll also write to a file. 17 | var names = []; 18 | 19 | /** 20 | * Get a tag dictionary from the tags field on the object, for custom fields 21 | * like package 22 | * @param {JSDocData} data The thing you get in the TaffyDB from JSDoc 23 | * @return {Object} Keys are the parameter names, values are the values. 24 | */ 25 | var getTagDict = function (data) { 26 | var tagDict = {}; 27 | 28 | if (data.tags) { 29 | _.each(data.tags, function (tag) { 30 | tagDict[tag.title] = tag.value; 31 | }); 32 | } 33 | 34 | return tagDict; 35 | }; 36 | 37 | // Fix up a JSDoc entry and add it to `dataContents`. 38 | var addToData = function (entry) { 39 | _.extend(entry, getTagDict(entry)); 40 | 41 | // strip properties we don't want 42 | entry.comment = undefined; 43 | entry.___id = undefined; 44 | entry.___s = undefined; 45 | entry.tags = undefined; 46 | 47 | // generate `.filepath` and `.lineno` from `.meta` 48 | if (entry.meta && entry.meta.path) { 49 | var packagesFolder = 'packages/'; 50 | var index = entry.meta.path.indexOf(packagesFolder); 51 | if (index != -1) { 52 | var fullFilePath = entry.meta.path.substr(index + packagesFolder.length) + '/' + entry.meta.filename; 53 | entry.filepath = fullFilePath; 54 | entry.lineno = entry.meta.lineno; 55 | } 56 | } 57 | 58 | entry.meta = undefined; 59 | 60 | if (!entry.importfrompackage && entry.filepath) { 61 | entry.module = entry.filepath.split('/')[0]; 62 | } else { 63 | entry.module = entry.importfrompackage; 64 | } 65 | 66 | names.push(entry.longname); 67 | dataContents[entry.longname] = entry; 68 | }; 69 | 70 | /** 71 | Entry point where JSDoc calls us. It passes us data in the form of 72 | a TaffyDB object (which is an in-JS database of sorts that you can 73 | query for records. 74 | 75 | @param {TAFFY} taffyData SeeMatch.Any
" %}
74 | Matches any value.
75 | {% enddtdd %}
76 |
77 | {% dtdd name:"String
, Number
, Boolean
, undefined
, null
" %}
78 | Matches a primitive of the given type.
79 | {% enddtdd %}
80 |
81 | {% dtdd name:"Match.Integer
" %}
82 | Matches a signed 32-bit integer. Doesn't match `Infinity`, `-Infinity`, or `NaN`.
83 | {% enddtdd %}
84 |
85 | {% dtdd name:"[pattern]
" %}
86 | A one-element array matches an array of elements, each of which match
87 | *pattern*. For example, `[Number]` matches a (possibly empty) array of numbers;
88 | `[Match.Any]` matches any array.
89 | {% enddtdd %}
90 |
91 | { key1: pattern1, key2: pattern2, ... }
Match.ObjectIncluding({ key1: pattern1, key2: pattern2, ... })
Object
" %}
106 | Matches any plain Object with any keys; equivalent to
107 | `Match.ObjectIncluding({})`.
108 | {% enddtdd %}
109 |
110 |
111 |
112 | {% dtdd name:"Match.Maybe(pattern)
" %}
113 |
114 | Matches either `undefined`, `null`, or _pattern_. If used in an object, matches only if the key is
115 | not set as opposed to the value being set to `undefined` or `null`. This set of conditions was
116 | chosen because `undefined` arguments to Meteor Methods are converted to `null` when sent over the
117 | wire.
118 |
119 | {% codeblock lang:js %}
120 | // In an object
121 | const pattern = { name: Match.Maybe(String) };
122 |
123 | check({ name: 'something' }, pattern); // OK
124 | check({}, pattern); // OK
125 | check({ name: undefined }, pattern); // Throws an exception
126 | check({ name: null }, pattern); // Throws an exception
127 |
128 | // Outside an object
129 | check(null, Match.Maybe(String)); // OK
130 | check(undefined, Match.Maybe(String)); // OK
131 | {% endcodeblock %}
132 | {% enddtdd %}
133 |
134 | {% dtdd name:"Match.Optional(pattern)
" %}
135 |
136 | Behaves like `Match.Maybe` except it doesn't accept `null`. If used in an object, the behavior is
137 | identical to `Match.Maybe`.
138 |
139 | {% enddtdd %}
140 |
141 | {% dtdd name:"Match.OneOf(pattern1, pattern2, ...)
" %}
142 | Matches any value that matches at least one of the provided patterns.
143 | {% enddtdd %}
144 |
145 | {% dtdd name:"Any constructor function (eg, Date
)" %}
146 | Matches any element that is an instance of that type.
147 | {% enddtdd %}
148 |
149 | {% dtdd name:"Match.Where(condition)
" %}
150 | Calls the function *condition* with the value as the argument. If *condition*
151 | returns true, this matches. If *condition* throws a `Match.Error` or returns
152 | false, this fails. If *condition* throws any other error, that error is thrown
153 | from the call to `check` or `Match.test`. Examples:
154 |
155 | {% codeblock lang:js %}
156 | check(buffer, Match.Where(EJSON.isBinary));
157 |
158 | const NonEmptyString = Match.Where((x) => {
159 | check(x, String);
160 | return x.length > 0;
161 | });
162 |
163 | check(arg, NonEmptyString);
164 | {% endcodeblock %}
165 | {% enddtdd %}
166 | null
on error.null
We've always been at war with {{theEnemy}}.
69 | 70 | 71 | ``` 72 | 73 | ```js 74 | // main.js 75 | Template.main.onCreated(function () { 76 | this.state = new ReactiveDict(); 77 | this.state.set('enemy', 'Eastasia'); 78 | }); 79 | Template.main.helpers({ 80 | theEnemy() { 81 | const inst = Template.instance(); 82 | return inst.state.get('enemy'); 83 | } 84 | }); 85 | Template.main.events({ 86 | 'click .change-enemy'(event, inst) { 87 | inst.state.set('enemy', 'Eurasia') 88 | } 89 | }); 90 | 91 | // Clicking the button will change the page to say "We've always been at war with Eurasia" 92 | ``` 93 | 94 | {% apibox "ReactiveDict#equals" %} 95 | 96 | If value is a scalar, then these two expressions do the same thing: 97 | 98 | ```js 99 | const state = new ReactiveDict() 100 | // ... 101 | state.get('key') === value 102 | state.equals('key', value) 103 | ``` 104 | 105 | However, the second is recommended, as it triggers fewer invalidations 106 | (template redraws), making your program more efficient. 107 | 108 | {% apibox "ReactiveDict#all" %} 109 | 110 | {% apibox "ReactiveDict#clear" %} 111 | 112 | {% apibox "ReactiveDict#destroy" %} 113 | -------------------------------------------------------------------------------- /source/api/reactive-var.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ReactiveVar 3 | description: Documentation of ReactiveVar, a simple reactive variable package. 4 | --- 5 | 6 | To use `ReactiveVar`, add the `reactive-var` package to your project by running 7 | in your terminal: 8 | 9 | ```bash 10 | meteor add reactive-var 11 | ``` 12 | 13 | {% apibox "ReactiveVar" %} 14 | 15 | A ReactiveVar holds a single value that can be get and set, such that calling 16 | `set` will invalidate any Computations that called `get`, according to the 17 | usual contract for reactive data sources. 18 | 19 | A ReactiveVar is similar to a Session variable, with a few differences: 20 | 21 | * ReactiveVars don't have global names, like the "foo" in `Session.get('foo')`. 22 | Instead, they may be created and used locally, for example attached to a 23 | template instance, as in: `this.foo.get()`. 24 | 25 | * ReactiveVars are not automatically migrated across hot code pushes, 26 | whereas Session state is. 27 | 28 | * ReactiveVars can hold any value, while Session variables are limited to 29 | JSON or EJSON. 30 | 31 | An important property of ReactiveVars — which is sometimes a 32 | reason for using one — is that setting the value to the same 33 | value as before has no effect; it does not trigger any invalidations. 34 | So if one autorun sets a ReactiveVar, and another autorun gets the 35 | ReactiveVar, a re-run of the first autorun won't necessarily trigger 36 | the second. By default, only primitive values are compared this way, 37 | while calling `set` on an argument that is an *object* (not a 38 | primitive) always counts as a change. You can configure this behavior 39 | using the `equalsFunc` argument. 40 | 41 | {% apibox "ReactiveVar#get" %} 42 | 43 | {% apibox "ReactiveVar#set" %} 44 | -------------------------------------------------------------------------------- /source/api/session.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Session 3 | description: Documentation of Meteor's client-side session API. 4 | --- 5 | 6 | `Session` provides a global object on the client that you can use to 7 | store an arbitrary set of key-value pairs. Use it to store things like 8 | the currently selected item in a list. 9 | 10 | What's special about `Session` is that it's reactive. If 11 | you call [`Session.get`](#session_get)`('currentList')` 12 | from inside a template, the template will automatically be rerendered 13 | whenever [`Session.set`](#session_set)`('currentList', x)` is called. 14 | 15 | To add `Session` to your application, run this command in your terminal: 16 | 17 | ```bash 18 | meteor add session 19 | ``` 20 | 21 | {% apibox "Session.set" %} 22 | 23 | Example: 24 | 25 | ```js 26 | Tracker.autorun(() => { 27 | Meteor.subscribe('chatHistory', { room: Session.get('currentRoomId') }); 28 | }); 29 | 30 | // Causes the function passed to `Tracker.autorun` to be rerun, so that the 31 | // 'chatHistory' subscription is moved to the room 'home'. 32 | Session.set('currentRoomId', 'home'); 33 | ``` 34 | 35 | `Session.set` can also be called with an object of keys and values, which is 36 | equivalent to calling `Session.set` individually on each key/value pair. 37 | 38 | ```js 39 | Session.set({ 40 | a: 'foo', 41 | b: 'bar' 42 | }); 43 | ``` 44 | 45 | {% apibox "Session.setDefault" %} 46 | 47 | This is useful in initialization code, to avoid re-initializing a session 48 | variable every time a new version of your app is loaded. 49 | 50 | {% apibox "Session.get" %} 51 | 52 | Example: 53 | 54 | ```html 55 | 56 | 57 |We've always been at war with {{theEnemy}}.
58 | 59 | ``` 60 | 61 | ```js 62 | // main.js 63 | Template.main.helpers({ 64 | theEnemy() { 65 | return Session.get('enemy'); 66 | } 67 | }); 68 | 69 | Session.set('enemy', 'Eastasia'); 70 | // Page will say "We've always been at war with Eastasia" 71 | 72 | Session.set('enemy', 'Eurasia'); 73 | // Page will change to say "We've always been at war with Eurasia" 74 | ``` 75 | 76 | 77 | {% apibox "Session.equals" %} 78 | 79 | If value is a scalar, then these two expressions do the same thing: 80 | 81 | ```js 82 | Session.get('key') === value 83 | Session.equals('key', value) 84 | ``` 85 | 86 | ...but the second one is always better. It triggers fewer invalidations 87 | (template redraws), making your program more efficient. 88 | 89 | Example: 90 | 91 | ```html 92 | 93 | {{! Show a dynamically updating list of items. Let the user click on an item 94 | to select it. The selected item is given a CSS class, so it can be 95 | rendered differently. }} 96 | 97 | {{#each posts}} 98 | {{> postItem}} 99 | {{/each}} 100 | 101 | 102 | 103 |